diff --git a/src/index-fn.js b/src/index-fn.js index 1a7f874..795fb9a 100644 --- a/src/index-fn.js +++ b/src/index-fn.js @@ -11,3 +11,4 @@ export {default as map} from "./map.js"; export {default as walk} from "./walk.js"; export {default as transform} from "./transform.js"; export {default as reduce} from "./reduce.js"; +export {default as walkUp} from "./walkUp.js"; diff --git a/src/walkUp.js b/src/walkUp.js new file mode 100644 index 0000000..ee50a89 --- /dev/null +++ b/src/walkUp.js @@ -0,0 +1,19 @@ +import { getParent } from "./parents.js"; +import { assertParentPointers } from "./util.js"; + +/** + * Walk up the tree from the given node, calling the callback on each node. + * @param {object} node + * @param {function} callback + * @returns {any} The first non-undefined value returned by the callback, otherwise undefined + */ +export default function walkUp (node, callback) { + while (node) { + const ret = callback(node); + if (ret !== undefined) { + return ret; + } + assertParentPointers.call(this, node, "Cannot walk up the tree from a node with no parent pointer."); + node = getParent.call(this, node); + } +} diff --git a/test/walkUp.js b/test/walkUp.js new file mode 100644 index 0000000..37ced0b --- /dev/null +++ b/test/walkUp.js @@ -0,0 +1,26 @@ +import walkUp from "../src/walkUp.js"; +import trees from "./utils/trees.js"; +import updateParents from "../src/updateParents.js"; +import copy from "./utils/copy.js"; + +const tree = copy(trees[0]); +updateParents(tree); + +export default { + name: "walkUp()", + run (node, cb) { + return walkUp(node, cb); + }, + tests: [ + { + name: "No callback", + args: [tree.right, () => {}], + expect: undefined + }, + { + name: "Callback returns a value", + args: [tree.right, n => n.name === "1" ? n : undefined], + expect: tree + } + ] +};