diff --git a/.eslintrc b/.eslintrc index 4bd2fba..a045e9b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,71 +1,61 @@ { - "root": true, + "root": true, - "extends": "@ljharb/eslint-config/node/0.4", + "extends": "@ljharb/eslint-config/node/0.4", - "rules": { - "array-bracket-newline": 0, - "array-bracket-spacing": 1, - "array-callback-return": 1, - "array-element-newline": 0, - "brace-style": 1, - "camelcase": 1, - "comma-dangle": 1, - "comma-spacing": 1, - "complexity": 0, - "consistent-return": 1, - "curly": 1, - "dot-notation": 1, - "eqeqeq": 1, - "func-style": 1, - "function-call-argument-newline": 1, - "function-paren-newline": 1, - "global-require": 1, - "indent": [1, 4], - "key-spacing": 1, - "max-lines-per-function": 1, - "max-statements-per-line": 1, - "multiline-comment-style": 0, - "new-parens": 1, - "no-else-return": 1, - "no-extra-bind": 1, - "no-extra-parens": 1, - "no-extra-semi": 1, - "no-multi-assign": 1, - "no-new-wrappers": 1, - "no-param-reassign": 1, - "no-plusplus": 1, - "no-proto": 1, - "no-restricted-syntax": 1, - "no-shadow": 1, - "no-sparse-arrays": 1, - "no-trailing-spaces": 1, - "no-undef": 1, - "no-underscore-dangle": 1, - "no-unused-vars": 1, - "no-use-before-define": 1, - "no-useless-concat": 1, - "object-curly-newline": 1, - "one-var-declaration-per-line": 1, - "operator-linebreak": 1, - "quote-props": 1, - "quotes": 1, - "semi-style": 1, - "semi": 1, - "sort-keys": 0, - "space-before-function-paren": 1, - "space-unary-ops": 1, - "spaced-comment": 1, - "strict": 1, - "wrap-iife": 1, - }, + "rules": { + "array-bracket-newline": 0, + "array-callback-return": 1, + "array-element-newline": 0, + "brace-style": 1, + "camelcase": 1, + "comma-dangle": 1, + "complexity": 0, + "consistent-return": 1, + "curly": 0, + "dot-notation": 1, + "eqeqeq": 1, + "func-style": 1, + "global-require": 1, + "max-lines-per-function": 1, + "max-statements-per-line": 1, + "multiline-comment-style": 0, + "new-parens": 1, + "no-else-return": 1, + "no-extra-bind": 1, + "no-extra-parens": 1, + "no-extra-semi": 1, + "no-multi-assign": 1, + "no-new-wrappers": 1, + "no-param-reassign": 1, + "no-plusplus": 1, + "no-proto": 1, + "no-restricted-syntax": 1, + "no-shadow": 1, + "no-sparse-arrays": 1, + "no-undef": 1, + "no-underscore-dangle": 1, + "no-unused-vars": 1, + "no-use-before-define": 1, + "no-useless-concat": 1, + "object-curly-newline": 0, + "one-var-declaration-per-line": 1, + "operator-linebreak": 1, + "quote-props": 1, + "quotes": 1, + "semi-style": 1, + "semi": 1, + "sort-keys": 0, + "strict": 1, + "wrap-iife": 1, + }, - "overrides": [ - { - "files": "examples/**", - "rules": { - "no-console": 0, - }, - }, - ], + "overrides": [ + { + "files": "examples/**", + "rules": { + "no-console": 0, + }, + }, + ], } diff --git a/examples/json.js b/examples/json.js index 50d612e..78e0748 100755 --- a/examples/json.js +++ b/examples/json.js @@ -2,14 +2,14 @@ var traverse = require('traverse'); var id = 54; var callbacks = {}; -var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; +var obj = { moo: function () {}, foo: [2, 3, 4, function () {}] }; var scrubbed = traverse(obj).map(function (x) { - if (typeof x === 'function') { - callbacks[id] = { id : id, f : x, path : this.path }; - this.update('[Function]'); - id++; - } + if (typeof x === 'function') { + callbacks[id] = { id: id, f: x, path: this.path }; + this.update('[Function]'); + id++; + } }); console.dir(scrubbed); diff --git a/examples/leaves.js b/examples/leaves.js index c1b310b..43a1f70 100755 --- a/examples/leaves.js +++ b/examples/leaves.js @@ -1,15 +1,15 @@ var traverse = require('traverse'); var obj = { - a : [1,2,3], - b : 4, - c : [5,6], - d : { e : [7,8], f : 9 }, + a: [1, 2, 3], + b: 4, + c: [5, 6], + d: { e: [7, 8], f: 9 }, }; var leaves = traverse(obj).reduce(function (acc, x) { - if (this.isLeaf) acc.push(x); - return acc; + if (this.isLeaf) acc.push(x); + return acc; }, []); console.dir(leaves); diff --git a/examples/negative.js b/examples/negative.js index 78608a0..93ee684 100755 --- a/examples/negative.js +++ b/examples/negative.js @@ -1,8 +1,8 @@ var traverse = require('traverse'); -var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; +var obj = [5, 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }]; traverse(obj).forEach(function (x) { - if (x < 0) this.update(x + 128); + if (x < 0) this.update(x + 128); }); console.dir(obj); diff --git a/examples/scrub.js b/examples/scrub.js index 5d15b91..07227b4 100755 --- a/examples/scrub.js +++ b/examples/scrub.js @@ -1,10 +1,10 @@ // scrub out circular references var traverse = require('traverse'); -var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +var obj = { a: 1, b: 2, c: [3, 4] }; obj.c.push(obj); var scrubbed = traverse(obj).map(function (x) { - if (this.circular) this.remove() + if (this.circular) this.remove() }); console.dir(scrubbed); diff --git a/examples/stringify.js b/examples/stringify.js index 167b68b..7d44c73 100755 --- a/examples/stringify.js +++ b/examples/stringify.js @@ -1,37 +1,37 @@ #!/usr/bin/env node var traverse = require('traverse'); -var obj = [ 'five', 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; +var obj = ['five', 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }]; var s = ''; -traverse(obj).forEach(function to_s (node) { - if (Array.isArray(node)) { - this.before(function () { s += '[' }); - this.post(function (child) { - if (!child.isLast) s += ','; - }); - this.after(function () { s += ']' }); - } - else if (typeof node == 'object') { - this.before(function () { s += '{' }); - this.pre(function (x, key) { - to_s(key); - s += ':'; - }); - this.post(function (child) { - if (!child.isLast) s += ','; - }); - this.after(function () { s += '}' }); - } - else if (typeof node == 'string') { - s += '"' + node.toString().replace(/"/g, '\\"') + '"'; - } - else if (typeof node == 'function') { - s += 'null'; - } - else { - s += node.toString(); - } +traverse(obj).forEach(function to_s(node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + to_s(key); + s += ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'string') { + s += '"' + node.toString().replace(/"/g, '\\"') + '"'; + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } }); console.log('JSON.stringify: ' + JSON.stringify(obj)); diff --git a/index.js b/index.js index 2f2cf67..31dc1c0 100644 --- a/index.js +++ b/index.js @@ -1,314 +1,314 @@ var traverse = module.exports = function (obj) { - return new Traverse(obj); + return new Traverse(obj); }; -function Traverse (obj) { - this.value = obj; +function Traverse(obj) { + this.value = obj; } Traverse.prototype.get = function (ps) { - var node = this.value; - for (var i = 0; i < ps.length; i ++) { - var key = ps[i]; - if (!node || !hasOwnProperty.call(node, key)) { - node = undefined; - break; - } - node = node[key]; - } - return node; + var node = this.value; + for (var i = 0; i < ps.length; i++) { + var key = ps[i]; + if (!node || !hasOwnProperty.call(node, key)) { + node = undefined; + break; + } + node = node[key]; + } + return node; }; Traverse.prototype.has = function (ps) { - var node = this.value; - for (var i = 0; i < ps.length; i ++) { - var key = ps[i]; - if (!node || !hasOwnProperty.call(node, key)) { - return false; - } - node = node[key]; - } - return true; + var node = this.value; + for (var i = 0; i < ps.length; i++) { + var key = ps[i]; + if (!node || !hasOwnProperty.call(node, key)) { + return false; + } + node = node[key]; + } + return true; }; Traverse.prototype.set = function (ps, value) { - var node = this.value; - for (var i = 0; i < ps.length - 1; i ++) { - var key = ps[i]; - if (!hasOwnProperty.call(node, key)) node[key] = {}; - node = node[key]; - } - node[ps[i]] = value; - return value; + var node = this.value; + for (var i = 0; i < ps.length - 1; i++) { + var key = ps[i]; + if (!hasOwnProperty.call(node, key)) node[key] = {}; + node = node[key]; + } + node[ps[i]] = value; + return value; }; Traverse.prototype.map = function (cb) { - return walk(this.value, cb, true); + return walk(this.value, cb, true); }; Traverse.prototype.forEach = function (cb) { - this.value = walk(this.value, cb, false); - return this.value; + this.value = walk(this.value, cb, false); + return this.value; }; Traverse.prototype.reduce = function (cb, init) { - var skip = arguments.length === 1; - var acc = skip ? this.value : init; - this.forEach(function (x) { - if (!this.isRoot || !skip) { - acc = cb.call(this, acc, x); - } - }); - return acc; + var skip = arguments.length === 1; + var acc = skip ? this.value : init; + this.forEach(function (x) { + if (!this.isRoot || !skip) { + acc = cb.call(this, acc, x); + } + }); + return acc; }; Traverse.prototype.paths = function () { - var acc = []; - this.forEach(function (x) { - acc.push(this.path); - }); - return acc; + var acc = []; + this.forEach(function (x) { + acc.push(this.path); + }); + return acc; }; Traverse.prototype.nodes = function () { - var acc = []; - this.forEach(function (x) { - acc.push(this.node); - }); - return acc; + var acc = []; + this.forEach(function (x) { + acc.push(this.node); + }); + return acc; }; Traverse.prototype.clone = function () { - var parents = [], nodes = []; - - return (function clone (src) { - for (var i = 0; i < parents.length; i++) { - if (parents[i] === src) { - return nodes[i]; - } - } - - if (typeof src === 'object' && src !== null) { - var dst = copy(src); - - parents.push(src); - nodes.push(dst); - - forEach(objectKeys(src), function (key) { - dst[key] = clone(src[key]); - }); - - parents.pop(); - nodes.pop(); - return dst; - } - else { - return src; - } - })(this.value); + var parents = [], nodes = []; + + return (function clone(src) { + for (var i = 0; i < parents.length; i++) { + if (parents[i] === src) { + return nodes[i]; + } + } + + if (typeof src === 'object' && src !== null) { + var dst = copy(src); + + parents.push(src); + nodes.push(dst); + + forEach(objectKeys(src), function (key) { + dst[key] = clone(src[key]); + }); + + parents.pop(); + nodes.pop(); + return dst; + } + else { + return src; + } + })(this.value); }; -function walk (root, cb, immutable) { - var path = []; - var parents = []; - var alive = true; - - return (function walker (node_) { - var node = immutable ? copy(node_) : node_; - var modifiers = {}; - - var keepGoing = true; - - var state = { - node : node, - node_ : node_, - path : [].concat(path), - parent : parents[parents.length - 1], - parents : parents, - key : path.slice(-1)[0], - isRoot : path.length === 0, - level : path.length, - circular : null, - update : function (x, stopHere) { - if (!state.isRoot) { - state.parent.node[state.key] = x; - } - state.node = x; - if (stopHere) keepGoing = false; - }, - 'delete' : function (stopHere) { - delete state.parent.node[state.key]; - if (stopHere) keepGoing = false; - }, - remove : function (stopHere) { - if (isArray(state.parent.node)) { - state.parent.node.splice(state.key, 1); - } - else { - delete state.parent.node[state.key]; - } - if (stopHere) keepGoing = false; - }, - keys : null, - before : function (f) { modifiers.before = f }, - after : function (f) { modifiers.after = f }, - pre : function (f) { modifiers.pre = f }, - post : function (f) { modifiers.post = f }, - stop : function () { alive = false }, - block : function () { keepGoing = false } - }; - - if (!alive) return state; - - function updateState() { - if (typeof state.node === 'object' && state.node !== null) { - if (!state.keys || state.node_ !== state.node) { - state.keys = objectKeys(state.node) - } - - state.isLeaf = state.keys.length == 0; - - for (var i = 0; i < parents.length; i++) { - if (parents[i].node_ === node_) { - state.circular = parents[i]; - break; - } - } - } - else { - state.isLeaf = true; - state.keys = null; - } - - state.notLeaf = !state.isLeaf; - state.notRoot = !state.isRoot; - } - - updateState(); - - // use return values to update if defined - var ret = cb.call(state, state.node); - if (ret !== undefined && state.update) state.update(ret); - - if (modifiers.before) modifiers.before.call(state, state.node); - - if (!keepGoing) return state; - - if (typeof state.node == 'object' +function walk(root, cb, immutable) { + var path = []; + var parents = []; + var alive = true; + + return (function walker(node_) { + var node = immutable ? copy(node_) : node_; + var modifiers = {}; + + var keepGoing = true; + + var state = { + node: node, + node_: node_, + path: [].concat(path), + parent: parents[parents.length - 1], + parents: parents, + key: path.slice(-1)[0], + isRoot: path.length === 0, + level: path.length, + circular: null, + update: function (x, stopHere) { + if (!state.isRoot) { + state.parent.node[state.key] = x; + } + state.node = x; + if (stopHere) keepGoing = false; + }, + 'delete': function (stopHere) { + delete state.parent.node[state.key]; + if (stopHere) keepGoing = false; + }, + remove: function (stopHere) { + if (isArray(state.parent.node)) { + state.parent.node.splice(state.key, 1); + } + else { + delete state.parent.node[state.key]; + } + if (stopHere) keepGoing = false; + }, + keys: null, + before: function (f) { modifiers.before = f }, + after: function (f) { modifiers.after = f }, + pre: function (f) { modifiers.pre = f }, + post: function (f) { modifiers.post = f }, + stop: function () { alive = false }, + block: function () { keepGoing = false } + }; + + if (!alive) return state; + + function updateState() { + if (typeof state.node === 'object' && state.node !== null) { + if (!state.keys || state.node_ !== state.node) { + state.keys = objectKeys(state.node) + } + + state.isLeaf = state.keys.length == 0; + + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; + } + } + } + else { + state.isLeaf = true; + state.keys = null; + } + + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; + } + + updateState(); + + // use return values to update if defined + var ret = cb.call(state, state.node); + if (ret !== undefined && state.update) state.update(ret); + + if (modifiers.before) modifiers.before.call(state, state.node); + + if (!keepGoing) return state; + + if (typeof state.node == 'object' && state.node !== null && !state.circular) { - parents.push(state); - - updateState(); - - forEach(state.keys, function (key, i) { - path.push(key); - - if (modifiers.pre) modifiers.pre.call(state, state.node[key], key); - - var child = walker(state.node[key]); - if (immutable && hasOwnProperty.call(state.node, key)) { - state.node[key] = child.node; - } - - child.isLast = i == state.keys.length - 1; - child.isFirst = i == 0; - - if (modifiers.post) modifiers.post.call(state, child); - - path.pop(); - }); - parents.pop(); - } - - if (modifiers.after) modifiers.after.call(state, state.node); - - return state; - })(root).node; + parents.push(state); + + updateState(); + + forEach(state.keys, function (key, i) { + path.push(key); + + if (modifiers.pre) modifiers.pre.call(state, state.node[key], key); + + var child = walker(state.node[key]); + if (immutable && hasOwnProperty.call(state.node, key)) { + state.node[key] = child.node; + } + + child.isLast = i == state.keys.length - 1; + child.isFirst = i == 0; + + if (modifiers.post) modifiers.post.call(state, child); + + path.pop(); + }); + parents.pop(); + } + + if (modifiers.after) modifiers.after.call(state, state.node); + + return state; + })(root).node; } -function copy (src) { - if (typeof src === 'object' && src !== null) { - var dst; - - if (isArray(src)) { - dst = []; - } - else if (isDate(src)) { - dst = new Date(src.getTime ? src.getTime() : src); - } - else if (isRegExp(src)) { - dst = new RegExp(src); - } - else if (isError(src)) { - dst = { message: src.message }; - } - else if (isBoolean(src)) { - dst = new Boolean(src); - } - else if (isNumber(src)) { - dst = new Number(src); - } - else if (isString(src)) { - dst = new String(src); - } - else if (Object.create && Object.getPrototypeOf) { - dst = Object.create(Object.getPrototypeOf(src)); - } - else if (src.constructor === Object) { - dst = {}; - } - else { - var proto = +function copy(src) { + if (typeof src === 'object' && src !== null) { + var dst; + + if (isArray(src)) { + dst = []; + } + else if (isDate(src)) { + dst = new Date(src.getTime ? src.getTime() : src); + } + else if (isRegExp(src)) { + dst = new RegExp(src); + } + else if (isError(src)) { + dst = { message: src.message }; + } + else if (isBoolean(src)) { + dst = new Boolean(src); + } + else if (isNumber(src)) { + dst = new Number(src); + } + else if (isString(src)) { + dst = new String(src); + } + else if (Object.create && Object.getPrototypeOf) { + dst = Object.create(Object.getPrototypeOf(src)); + } + else if (src.constructor === Object) { + dst = {}; + } + else { + var proto = (src.constructor && src.constructor.prototype) || src.__proto__ || {} ; - var T = function () {}; - T.prototype = proto; - dst = new T; - } - - forEach(objectKeys(src), function (key) { - dst[key] = src[key]; - }); - return dst; - } - else return src; + var T = function () {}; + T.prototype = proto; + dst = new T; + } + + forEach(objectKeys(src), function (key) { + dst[key] = src[key]; + }); + return dst; + } + else return src; } -var objectKeys = Object.keys || function keys (obj) { - var res = []; - for (var key in obj) res.push(key) - return res; +var objectKeys = Object.keys || function keys(obj) { + var res = []; + for (var key in obj) res.push(key) + return res; }; -function toS (obj) { return Object.prototype.toString.call(obj) } -function isDate (obj) { return toS(obj) === '[object Date]' } -function isRegExp (obj) { return toS(obj) === '[object RegExp]' } -function isError (obj) { return toS(obj) === '[object Error]' } -function isBoolean (obj) { return toS(obj) === '[object Boolean]' } -function isNumber (obj) { return toS(obj) === '[object Number]' } -function isString (obj) { return toS(obj) === '[object String]' } +function toS(obj) { return Object.prototype.toString.call(obj) } +function isDate(obj) { return toS(obj) === '[object Date]' } +function isRegExp(obj) { return toS(obj) === '[object RegExp]' } +function isError(obj) { return toS(obj) === '[object Error]' } +function isBoolean(obj) { return toS(obj) === '[object Boolean]' } +function isNumber(obj) { return toS(obj) === '[object Number]' } +function isString(obj) { return toS(obj) === '[object String]' } -var isArray = Array.isArray || function isArray (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; +var isArray = Array.isArray || function isArray(xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; }; var forEach = function (xs, fn) { - if (xs.forEach) return xs.forEach(fn) - else for (var i = 0; i < xs.length; i++) { - fn(xs[i], i, xs); - } + if (xs.forEach) return xs.forEach(fn) + else for (var i = 0; i < xs.length; i++) { + fn(xs[i], i, xs); + } }; forEach(objectKeys(Traverse.prototype), function (key) { - traverse[key] = function (obj) { - var args = [].slice.call(arguments, 1); - var t = new Traverse(obj); - return t[key].apply(t, args); - }; + traverse[key] = function (obj) { + var args = [].slice.call(arguments, 1); + var t = new Traverse(obj); + return t[key].apply(t, args); + }; }); var hasOwnProperty = Object.hasOwnProperty || function (obj, key) { - return key in obj; + return key in obj; }; diff --git a/package.json b/package.json index 3e4be9e..07091ba 100644 --- a/package.json +++ b/package.json @@ -1,68 +1,68 @@ { - "name": "traverse", - "version": "0.6.6", - "description": "traverse and transform objects by visiting every node on a recursive walk", - "main": "index.js", - "directories": { - "example": "example", - "test": "test" - }, - "devDependencies": { - "@ljharb/eslint-config": "^21.0.0", - "aud": "^2.0.1", - "eslint": "=8.8.0", - "tape": "^5.6.1" - }, - "scripts": { - "lint": "eslint --ext=js,mjs .", - "pretest": "npm run lint", - "tests-only": "tape 'test/**/*.js'", - "test": "npm run tests-only", - "posttest": "aud --production" - }, - "testling": { - "files": "test/*.js", - "browsers": { - "iexplore": [ - "6.0", - "7.0", - "8.0", - "9.0" - ], - "chrome": [ - "10.0", - "20.0" - ], - "firefox": [ - "10.0", - "15.0" - ], - "safari": [ - "5.1" - ], - "opera": [ - "12.0" - ] - } - }, - "repository": { - "type": "git", - "url": "git://github.com/ljharb/js-traverse.git" - }, - "homepage": "https://github.com/ljharb/js-traverse", - "keywords": [ - "traverse", - "walk", - "recursive", - "map", - "forEach", - "deep", - "clone" - ], - "author": { - "name": "James Halliday", - "email": "mail@substack.net", - "url": "http://substack.net" - }, - "license": "MIT" + "name": "traverse", + "version": "0.6.6", + "description": "traverse and transform objects by visiting every node on a recursive walk", + "main": "index.js", + "directories": { + "example": "example", + "test": "test" + }, + "devDependencies": { + "@ljharb/eslint-config": "^21.0.0", + "aud": "^2.0.1", + "eslint": "=8.8.0", + "tape": "^5.6.1" + }, + "scripts": { + "lint": "eslint --ext=js,mjs .", + "pretest": "npm run lint", + "tests-only": "tape 'test/**/*.js'", + "test": "npm run tests-only", + "posttest": "aud --production" + }, + "testling": { + "files": "test/*.js", + "browsers": { + "iexplore": [ + "6.0", + "7.0", + "8.0", + "9.0" + ], + "chrome": [ + "10.0", + "20.0" + ], + "firefox": [ + "10.0", + "15.0" + ], + "safari": [ + "5.1" + ], + "opera": [ + "12.0" + ] + } + }, + "repository": { + "type": "git", + "url": "git://github.com/ljharb/js-traverse.git" + }, + "homepage": "https://github.com/ljharb/js-traverse", + "keywords": [ + "traverse", + "walk", + "recursive", + "map", + "forEach", + "deep", + "clone" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "license": "MIT" } diff --git a/test/circular.js b/test/circular.js index 9cffed7..14f6f8d 100644 --- a/test/circular.js +++ b/test/circular.js @@ -4,114 +4,114 @@ var deepEqual = require('./lib/deep_equal'); var util = require('util'); test('circular', function (t) { - t.plan(1); - - var obj = { x : 3 }; - obj.y = obj; - traverse(obj).forEach(function (x) { - if (this.path.join('') == 'y') { - t.equal( - util.inspect(this.circular.node), - util.inspect(obj) - ); - } - }); + t.plan(1); + + var obj = { x: 3 }; + obj.y = obj; + traverse(obj).forEach(function (x) { + if (this.path.join('') == 'y') { + t.equal( + util.inspect(this.circular.node), + util.inspect(obj) + ); + } + }); }); test('deepCirc', function (t) { - t.plan(2); - var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; - obj.y[2] = obj; - - var times = 0; - traverse(obj).forEach(function (x) { - if (this.circular) { - t.deepEqual(this.circular.path, []); - t.deepEqual(this.path, [ 'y', '2' ]); - } - }); + t.plan(2); + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + + var times = 0; + traverse(obj).forEach(function (x) { + if (this.circular) { + t.deepEqual(this.circular.path, []); + t.deepEqual(this.path, ['y', '2']); + } + }); }); test('doubleCirc', function (t) { - var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; - obj.y[2] = obj; - obj.x.push(obj.y); - - var circs = []; - traverse(obj).forEach(function (x) { - if (this.circular) { - circs.push({ circ : this.circular, self : this, node : x }); - } - }); - - t.deepEqual(circs[0].self.path, [ 'x', '3', '2' ]); - t.deepEqual(circs[0].circ.path, []); - - t.deepEqual(circs[1].self.path, [ 'y', '2' ]); - t.deepEqual(circs[1].circ.path, []); - - t.deepEqual(circs.length, 2); - t.end(); + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var circs = []; + traverse(obj).forEach(function (x) { + if (this.circular) { + circs.push({ circ: this.circular, self: this, node: x }); + } + }); + + t.deepEqual(circs[0].self.path, ['x', '3', '2']); + t.deepEqual(circs[0].circ.path, []); + + t.deepEqual(circs[1].self.path, ['y', '2']); + t.deepEqual(circs[1].circ.path, []); + + t.deepEqual(circs.length, 2); + t.end(); }); test('circDubForEach', function (t) { - var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; - obj.y[2] = obj; - obj.x.push(obj.y); - - traverse(obj).forEach(function (x) { - if (this.circular) this.update('...'); - }); - - t.same(obj, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); - t.end(); + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + traverse(obj).forEach(function (x) { + if (this.circular) this.update('...'); + }); + + t.same(obj, { x: [1, 2, 3, [4, 5, '...']], y: [4, 5, '...'] }); + t.end(); }); test('circDubMap', function (t) { - var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; - obj.y[2] = obj; - obj.x.push(obj.y); - - var c = traverse(obj).map(function (x) { - if (this.circular) { - this.update('...'); - } - }); - - t.same(c, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); - t.end(); + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var c = traverse(obj).map(function (x) { + if (this.circular) { + this.update('...'); + } + }); + + t.same(c, { x: [1, 2, 3, [4, 5, '...']], y: [4, 5, '...'] }); + t.end(); }); test('circClone', function (t) { - var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; - obj.y[2] = obj; - obj.x.push(obj.y); - - var clone = traverse.clone(obj); - t.ok(obj !== clone); - - t.ok(clone.y[2] === clone); - t.ok(clone.y[2] !== obj); - t.ok(clone.x[3][2] === clone); - t.ok(clone.x[3][2] !== obj); - t.same(clone.x.slice(0,3), [1,2,3]); - t.same(clone.y.slice(0,2), [4,5]); - t.end(); + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var clone = traverse.clone(obj); + t.ok(obj !== clone); + + t.ok(clone.y[2] === clone); + t.ok(clone.y[2] !== obj); + t.ok(clone.x[3][2] === clone); + t.ok(clone.x[3][2] !== obj); + t.same(clone.x.slice(0, 3), [1, 2, 3]); + t.same(clone.y.slice(0, 2), [4, 5]); + t.end(); }); test('circMapScrub', function (t) { - var obj = { a : 1, b : 2 }; - obj.c = obj; - - var scrubbed = traverse(obj).map(function (node) { - if (this.circular) this.remove(); - }); - t.same( - Object.keys(scrubbed).sort(), - [ 'a', 'b' ] - ); - t.ok(deepEqual(scrubbed, { a : 1, b : 2 })); - - t.equal(obj.c, obj); - t.end(); + var obj = { a: 1, b: 2 }; + obj.c = obj; + + var scrubbed = traverse(obj).map(function (node) { + if (this.circular) this.remove(); + }); + t.same( + Object.keys(scrubbed).sort(), + ['a', 'b'] + ); + t.ok(deepEqual(scrubbed, { a: 1, b: 2 })); + + t.equal(obj.c, obj); + t.end(); }); diff --git a/test/date.js b/test/date.js index 54db4b0..cfc4102 100644 --- a/test/date.js +++ b/test/date.js @@ -2,36 +2,36 @@ var test = require('tape'); var traverse = require('../'); test('dateEach', function (t) { - var obj = { x : new Date, y : 10, z : 5 }; - - var counts = {}; - - traverse(obj).forEach(function (node) { - var t = (node instanceof Date && 'Date') || typeof node; - counts[t] = (counts[t] || 0) + 1; - }); - - t.same(counts, { - object : 1, - Date : 1, - number : 2, - }); - t.end(); + var obj = { x: new Date, y: 10, z: 5 }; + + var counts = {}; + + traverse(obj).forEach(function (node) { + var t = (node instanceof Date && 'Date') || typeof node; + counts[t] = (counts[t] || 0) + 1; + }); + + t.same(counts, { + object: 1, + Date: 1, + number: 2, + }); + t.end(); }); test('dateMap', function (t) { - var obj = { x : new Date, y : 10, z : 5 }; - - var res = traverse(obj).map(function (node) { - if (typeof node === 'number') this.update(node + 100); - }); - - t.ok(obj.x !== res.x); - t.same(res, { - x : obj.x, - y : 110, - z : 105, - }); - t.end(); + var obj = { x: new Date, y: 10, z: 5 }; + + var res = traverse(obj).map(function (node) { + if (typeof node === 'number') this.update(node + 100); + }); + + t.ok(obj.x !== res.x); + t.same(res, { + x: obj.x, + y: 110, + z: 105, + }); + t.end(); }); diff --git a/test/equal.js b/test/equal.js index fd0463c..ee5efce 100644 --- a/test/equal.js +++ b/test/equal.js @@ -3,238 +3,236 @@ var traverse = require('../'); var deepEqual = require('./lib/deep_equal'); test('deepDates', function (t) { - t.plan(2); - - t.ok( - deepEqual( - { d : new Date, x : [ 1, 2, 3 ] }, - { d : new Date, x : [ 1, 2, 3 ] } - ), - 'dates should be equal' - ); - - var d0 = new Date; - setTimeout(function () { - t.ok( - !deepEqual( - { d : d0, x : [ 1, 2, 3 ], }, - { d : new Date, x : [ 1, 2, 3 ] } - ), - 'microseconds should count in date equality' - ); - }, 5); + t.plan(2); + + t.ok( + deepEqual( + { d: new Date, x: [1, 2, 3] }, + { d: new Date, x: [1, 2, 3] } + ), + 'dates should be equal' + ); + + var d0 = new Date; + setTimeout(function () { + t.ok( + !deepEqual( + { d: d0, x: [1, 2, 3], }, + { d: new Date, x: [1, 2, 3] } + ), + 'microseconds should count in date equality' + ); + }, 5); }); test('deepCircular', function (t) { - var a = [1]; - a.push(a); // a = [ 1, *a ] - - var b = [1]; - b.push(a); // b = [ 1, [ 1, *a ] ] - - t.ok( - !deepEqual(a, b), - 'circular ref mount points count towards equality' - ); - - var c = [1]; - c.push(c); // c = [ 1, *c ] - t.ok( - deepEqual(a, c), - 'circular refs are structurally the same here' - ); - - var d = [1]; - d.push(a); // c = [ 1, [ 1, *d ] ] - t.ok( - deepEqual(b, d), - 'non-root circular ref structural comparison' - ); - - t.end(); + var a = [1]; + a.push(a); // a = [ 1, *a ] + + var b = [1]; + b.push(a); // b = [ 1, [ 1, *a ] ] + + t.ok( + !deepEqual(a, b), + 'circular ref mount points count towards equality' + ); + + var c = [1]; + c.push(c); // c = [ 1, *c ] + t.ok( + deepEqual(a, c), + 'circular refs are structurally the same here' + ); + + var d = [1]; + d.push(a); // c = [ 1, [ 1, *d ] ] + t.ok( + deepEqual(b, d), + 'non-root circular ref structural comparison' + ); + + t.end(); }); test('deepInstances', function (t) { - t.ok( - !deepEqual([ new Boolean(false) ], [ false ]), - 'boolean instances are not real booleans' - ); - - t.ok( - !deepEqual([ new String('x') ], [ 'x' ]), - 'string instances are not real strings' - ); - - t.ok( - !deepEqual([ new Number(4) ], [ 4 ]), - 'number instances are not real numbers' - ); - - t.ok( - deepEqual([ new RegExp('x') ], [ /x/ ]), - 'regexp instances are real regexps' - ); - - t.ok( - !deepEqual([ new RegExp(/./) ], [ /../ ]), - 'these regexps aren\'t the same' - ); - - t.ok( - !deepEqual( - [ function (x) { return x * 2 } ], - [ function (x) { return x * 2 } ] - ), - 'functions with the same .toString() aren\'t necessarily the same' - ); - - var f = function (x) { return x * 2 }; - t.ok( - deepEqual([ f ], [ f ]), - 'these functions are actually equal' - ); - - t.end(); + t.ok( + !deepEqual([new Boolean(false)], [false]), + 'boolean instances are not real booleans' + ); + + t.ok( + !deepEqual([new String('x')], ['x']), + 'string instances are not real strings' + ); + + t.ok( + !deepEqual([new Number(4)], [4]), + 'number instances are not real numbers' + ); + + t.ok( + deepEqual([new RegExp('x')], [/x/]), + 'regexp instances are real regexps' + ); + + t.ok( + !deepEqual([new RegExp(/./)], [/../]), + 'these regexps aren\'t the same' + ); + + t.ok( + !deepEqual( + [function (x) { return x * 2 }], + [function (x) { return x * 2 }] + ), + 'functions with the same .toString() aren\'t necessarily the same' + ); + + var f = function (x) { return x * 2 }; + t.ok( + deepEqual([f], [f]), + 'these functions are actually equal' + ); + + t.end(); }); test('deepEqual', function (t) { - t.ok( - !deepEqual([ 1, 2, 3 ], { 0 : 1, 1 : 2, 2 : 3 }), - 'arrays are not objects' - ); - t.end(); + t.ok( + !deepEqual([1, 2, 3], { 0: 1, 1: 2, 2: 3 }), + 'arrays are not objects' + ); + t.end(); }); test('falsy', function (t) { - t.ok( - !deepEqual([ undefined ], [ null ]), - 'null is not undefined!' - ); - - t.ok( - !deepEqual([ null ], [ undefined ]), - 'undefined is not null!' - ); - - t.ok( - !deepEqual( - { a : 1, b : 2, c : [ 3, undefined, 5 ] }, - { a : 1, b : 2, c : [ 3, null, 5 ] } - ), - 'undefined is not null, however deeply!' - ); - - t.ok( - !deepEqual( - { a : 1, b : 2, c : [ 3, undefined, 5 ] }, - { a : 1, b : 2, c : [ 3, null, 5 ] } - ), - 'null is not undefined, however deeply!' - ); - - t.ok( - !deepEqual( - { a : 1, b : 2, c : [ 3, undefined, 5 ] }, - { a : 1, b : 2, c : [ 3, null, 5 ] } - ), - 'null is not undefined, however deeply!' - ); - - t.end(); + t.ok( + !deepEqual([undefined], [null]), + 'null is not undefined!' + ); + + t.ok( + !deepEqual([null], [undefined]), + 'undefined is not null!' + ); + + t.ok( + !deepEqual( + { a: 1, b: 2, c: [3, undefined, 5] }, + { a: 1, b: 2, c: [3, null, 5] } + ), + 'undefined is not null, however deeply!' + ); + + t.ok( + !deepEqual( + { a: 1, b: 2, c: [3, undefined, 5] }, + { a: 1, b: 2, c: [3, null, 5] } + ), + 'null is not undefined, however deeply!' + ); + + t.ok( + !deepEqual( + { a: 1, b: 2, c: [3, undefined, 5] }, + { a: 1, b: 2, c: [3, null, 5] } + ), + 'null is not undefined, however deeply!' + ); + + t.end(); }); test('deletedArrayEqual', function (t) { - var xs = [ 1, 2, 3, 4 ]; - delete xs[2]; - - var ys = Object.create(Array.prototype); - ys[0] = 1; - ys[1] = 2; - ys[3] = 4; - - t.ok( - deepEqual(xs, ys), - 'arrays with deleted elements are only equal to' + var xs = [1, 2, 3, 4]; + delete xs[2]; + + var ys = Object.create(Array.prototype); + ys[0] = 1; + ys[1] = 2; + ys[3] = 4; + + t.ok( + deepEqual(xs, ys), + 'arrays with deleted elements are only equal to' + ' arrays with similarly deleted elements' - ); - - t.ok( - !deepEqual(xs, [ 1, 2, undefined, 4 ]), - 'deleted array elements cannot be undefined' - ); - - t.ok( - !deepEqual(xs, [ 1, 2, null, 4 ]), - 'deleted array elements cannot be null' - ); - - t.end(); + ); + + t.ok( + !deepEqual(xs, [1, 2, undefined, 4]), + 'deleted array elements cannot be undefined' + ); + + t.ok( + !deepEqual(xs, [1, 2, null, 4]), + 'deleted array elements cannot be null' + ); + + t.end(); }); test('deletedObjectEqual', function (t) { - var obj = { a : 1, b : 2, c : 3 }; - delete obj.c; - - t.ok( - deepEqual(obj, { a : 1, b : 2 }), - 'deleted object elements should not show up' - ); - - t.ok( - !deepEqual(obj, { a : 1, b : 2, c : undefined }), - 'deleted object elements are not undefined' - ); - - t.ok( - !deepEqual(obj, { a : 1, b : 2, c : null }), - 'deleted object elements are not null' - ); - - t.end(); + var obj = { a: 1, b: 2, c: 3 }; + delete obj.c; + + t.ok( + deepEqual(obj, { a: 1, b: 2 }), + 'deleted object elements should not show up' + ); + + t.ok( + !deepEqual(obj, { a: 1, b: 2, c: undefined }), + 'deleted object elements are not undefined' + ); + + t.ok( + !deepEqual(obj, { a: 1, b: 2, c: null }), + 'deleted object elements are not null' + ); + + t.end(); }); test('emptyKeyEqual', function (t) { - t.ok(!deepEqual( - { a : 1 }, { a : 1, '' : 55 } - )); - - t.end(); + t.ok(!deepEqual({ a: 1 }, { a: 1, '': 55 })); + + t.end(); }); test('deepArguments', function (t) { - t.ok( - !deepEqual( - [ 4, 5, 6 ], - (function () { return arguments })(4, 5, 6) - ), - 'arguments are not arrays' - ); - - t.ok( - deepEqual( - (function () { return arguments })(4, 5, 6), - (function () { return arguments })(4, 5, 6) - ), - 'arguments should equal' - ); - - t.end(); + t.ok( + !deepEqual( + [4, 5, 6], + (function () { return arguments })(4, 5, 6) + ), + 'arguments are not arrays' + ); + + t.ok( + deepEqual( + (function () { return arguments })(4, 5, 6), + (function () { return arguments })(4, 5, 6) + ), + 'arguments should equal' + ); + + t.end(); }); test('deepUn', function (t) { - t.ok(!deepEqual({ a : 1, b : 2 }, undefined)); - t.ok(!deepEqual({ a : 1, b : 2 }, {})); - t.ok(!deepEqual(undefined, { a : 1, b : 2 })); - t.ok(!deepEqual({}, { a : 1, b : 2 })); - t.ok(deepEqual(undefined, undefined)); - t.ok(deepEqual(null, null)); - t.ok(!deepEqual(undefined, null)); - - t.end(); + t.ok(!deepEqual({ a: 1, b: 2 }, undefined)); + t.ok(!deepEqual({ a: 1, b: 2 }, {})); + t.ok(!deepEqual(undefined, { a: 1, b: 2 })); + t.ok(!deepEqual({}, { a: 1, b: 2 })); + t.ok(deepEqual(undefined, undefined)); + t.ok(deepEqual(null, null)); + t.ok(!deepEqual(undefined, null)); + + t.end(); }); test('deepLevels', function (t) { - var xs = [ 1, 2, [ 3, 4, [ 5, 6 ] ] ]; - t.ok(!deepEqual(xs, [])); - t.end(); + var xs = [1, 2, [3, 4, [5, 6]]]; + t.ok(!deepEqual(xs, [])); + t.end(); }); diff --git a/test/error.js b/test/error.js index 447c725..13d191d 100644 --- a/test/error.js +++ b/test/error.js @@ -2,10 +2,10 @@ var test = require('tape'); var traverse = require('../'); test('traverse an Error', function (t) { - var obj = new Error("test"); - var results = traverse(obj).map(function (node) {}); - t.same(results, { message: 'test' }); - - t.end(); + var obj = new Error("test"); + var results = traverse(obj).map(function (node) {}); + t.same(results, { message: 'test' }); + + t.end(); }); diff --git a/test/has.js b/test/has.js index 94a50c6..f30e18d 100644 --- a/test/has.js +++ b/test/has.js @@ -2,14 +2,14 @@ var test = require('tape'); var traverse = require('../'); test('has', function (t) { - var obj = { a : 2, b : [ 4, 5, { c : 6 } ] }; - - t.equal(traverse(obj).has([ 'b', 2, 'c' ]), true) - t.equal(traverse(obj).has([ 'b', 2, 'c', 0 ]), false) - t.equal(traverse(obj).has([ 'b', 2, 'd' ]), false) - t.equal(traverse(obj).has([]), true) - t.equal(traverse(obj).has([ 'a' ]), true) - t.equal(traverse(obj).has([ 'a', 2 ]), false) - - t.end(); + var obj = { a: 2, b: [4, 5, { c: 6 }] }; + + t.equal(traverse(obj).has(['b', 2, 'c']), true) + t.equal(traverse(obj).has(['b', 2, 'c', 0]), false) + t.equal(traverse(obj).has(['b', 2, 'd']), false) + t.equal(traverse(obj).has([]), true) + t.equal(traverse(obj).has(['a']), true) + t.equal(traverse(obj).has(['a', 2]), false) + + t.end(); }); diff --git a/test/instance.js b/test/instance.js index 112f477..98d54f9 100644 --- a/test/instance.js +++ b/test/instance.js @@ -3,15 +3,15 @@ var traverse = require('../'); var EventEmitter = require('events').EventEmitter; test('check instanceof on node elems', function (t) { - var counts = { emitter : 0 }; - - traverse([ new EventEmitter, 3, 4, { ev : new EventEmitter }]) - .forEach(function (node) { - if (node instanceof EventEmitter) counts.emitter ++; - }) - ; - - t.equal(counts.emitter, 2); - - t.end(); + var counts = { emitter: 0 }; + + traverse([new EventEmitter, 3, 4, { ev: new EventEmitter }]) + .forEach(function (node) { + if (node instanceof EventEmitter) counts.emitter++; + }) + ; + + t.equal(counts.emitter, 2); + + t.end(); }); diff --git a/test/interface.js b/test/interface.js index f454c27..d526bf5 100644 --- a/test/interface.js +++ b/test/interface.js @@ -2,42 +2,42 @@ var test = require('tape'); var traverse = require('../'); test('interface map', function (t) { - var obj = { a : [ 5,6,7 ], b : { c : [8] } }; - - t.same( - traverse.paths(obj) - .sort() - .map(function (path) { return path.join('/') }) - .slice(1) - .join(' ') - , - 'a a/0 a/1 a/2 b b/c b/c/0' - ); - - t.same( - traverse.nodes(obj), - [ - { a: [ 5, 6, 7 ], b: { c: [ 8 ] } }, - [ 5, 6, 7 ], 5, 6, 7, - { c: [ 8 ] }, [ 8 ], 8 - ] - ); - - t.same( - traverse.map(obj, function (node) { - if (typeof node == 'number') { - return node + 1000; - } - else if (Array.isArray(node)) { - return node.join(' '); - } - }), - { a: '5 6 7', b: { c: '8' } } - ); - - var nodes = 0; - traverse.forEach(obj, function (node) { nodes ++ }); - t.same(nodes, 8); - - t.end(); + var obj = { a: [5, 6, 7], b: { c: [8] } }; + + t.same( + traverse.paths(obj) + .sort() + .map(function (path) { return path.join('/') }) + .slice(1) + .join(' ') + , + 'a a/0 a/1 a/2 b b/c b/c/0' + ); + + t.same( + traverse.nodes(obj), + [ + { a: [5, 6, 7], b: { c: [8] } }, + [5, 6, 7], 5, 6, 7, + { c: [8] }, [8], 8 + ] + ); + + t.same( + traverse.map(obj, function (node) { + if (typeof node == 'number') { + return node + 1000; + } + else if (Array.isArray(node)) { + return node.join(' '); + } + }), + { a: '5 6 7', b: { c: '8' } } + ); + + var nodes = 0; + traverse.forEach(obj, function (node) { nodes++ }); + t.same(nodes, 8); + + t.end(); }); diff --git a/test/json.js b/test/json.js index 46d55e6..71dd995 100644 --- a/test/json.js +++ b/test/json.js @@ -2,48 +2,52 @@ var test = require('tape'); var traverse = require('../'); test('json test', function (t) { - var id = 54; - var callbacks = {}; - var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; - - var scrubbed = traverse(obj).map(function (x) { - if (typeof x === 'function') { - callbacks[id] = { id : id, f : x, path : this.path }; - this.update('[Function]'); - id++; - } - }); - - t.equal( - scrubbed.moo, '[Function]', - 'obj.moo replaced with "[Function]"' - ); - - t.equal( - scrubbed.foo[3], '[Function]', - 'obj.foo[3] replaced with "[Function]"' - ); - - t.same(scrubbed, { - moo : '[Function]', - foo : [ 2, 3, 4, "[Function]" ] - }, 'Full JSON string matches'); - - t.same( - typeof obj.moo, 'function', - 'Original obj.moo still a function' - ); - - t.same( - typeof obj.foo[3], 'function', - 'Original obj.foo[3] still a function' - ); - - t.same(callbacks, { - 54: { id: 54, f : obj.moo, path: [ 'moo' ] }, - 55: { id: 55, f : obj.foo[3], path: [ 'foo', '3' ] }, - }, 'Check the generated callbacks list'); - - t.end(); + var id = 54; + var callbacks = {}; + var obj = { moo: function () {}, foo: [2, 3, 4, function () {}] }; + + var scrubbed = traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id: id, f: x, path: this.path }; + this.update('[Function]'); + id++; + } + }); + + t.equal( + scrubbed.moo, + '[Function]', + 'obj.moo replaced with "[Function]"' + ); + + t.equal( + scrubbed.foo[3], + '[Function]', + 'obj.foo[3] replaced with "[Function]"' + ); + + t.same(scrubbed, { + moo: '[Function]', + foo: [2, 3, 4, '[Function]'], + }, 'Full JSON string matches'); + + t.same( + typeof obj.moo, + 'function', + 'Original obj.moo still a function' + ); + + t.same( + typeof obj.foo[3], + 'function', + 'Original obj.foo[3] still a function' + ); + + t.same(callbacks, { + 54: { id: 54, f: obj.moo, path: ['moo'] }, + 55: { id: 55, f: obj.foo[3], path: ['foo', '3'] }, + }, 'Check the generated callbacks list'); + + t.end(); }); diff --git a/test/keys.js b/test/keys.js index 9661140..e720bf9 100644 --- a/test/keys.js +++ b/test/keys.js @@ -2,30 +2,30 @@ var test = require('tape'); var traverse = require('../'); test('sort test', function (t) { - var acc = []; - traverse({ - a: 30, - b: 22, - id: 9 - }).forEach(function (node) { - if ((! Array.isArray(node)) && typeof node === 'object') { - this.before(function(node) { - this.keys = Object.keys(node); - this.keys.sort(function(a, b) { - a = [a === "id" ? 0 : 1, a]; - b = [b === "id" ? 0 : 1, b]; - return a < b ? -1 : a > b ? 1 : 0; - }); - }); - } - if (this.isLeaf) acc.push(node); - }); - - t.equal( - acc.join(' '), - '9 30 22', - 'Traversal in a custom order' - ); - - t.end(); + var acc = []; + traverse({ + a: 30, + b: 22, + id: 9 + }).forEach(function (node) { + if ((!Array.isArray(node)) && typeof node === 'object') { + this.before(function (node) { + this.keys = Object.keys(node); + this.keys.sort(function (a, b) { + a = [a === "id" ? 0 : 1, a]; + b = [b === "id" ? 0 : 1, b]; + return a < b ? -1 : a > b ? 1 : 0; + }); + }); + } + if (this.isLeaf) acc.push(node); + }); + + t.equal( + acc.join(' '), + '9 30 22', + 'Traversal in a custom order' + ); + + t.end(); }); diff --git a/test/leaves.js b/test/leaves.js index c04ad5f..fb825b3 100644 --- a/test/leaves.js +++ b/test/leaves.js @@ -2,21 +2,21 @@ var test = require('tape'); var traverse = require('../'); test('leaves test', function (t) { - var acc = []; - traverse({ - a : [1,2,3], - b : 4, - c : [5,6], - d : { e : [7,8], f : 9 } - }).forEach(function (x) { - if (this.isLeaf) acc.push(x); - }); - - t.equal( - acc.join(' '), - '1 2 3 4 5 6 7 8 9', - 'Traversal in the right(?) order' - ); - - t.end(); + var acc = []; + traverse({ + a: [1, 2, 3], + b: 4, + c: [5, 6], + d: { e: [7, 8], f: 9 } + }).forEach(function (x) { + if (this.isLeaf) acc.push(x); + }); + + t.equal( + acc.join(' '), + '1 2 3 4 5 6 7 8 9', + 'Traversal in the right(?) order' + ); + + t.end(); }); diff --git a/test/lib/deep_equal.js b/test/lib/deep_equal.js index c75b04c..5865daf 100644 --- a/test/lib/deep_equal.js +++ b/test/lib/deep_equal.js @@ -1,96 +1,94 @@ var traverse = require('../../'); module.exports = function (a, b) { - if (arguments.length !== 2) { - throw new Error( - 'deepEqual requires exactly two objects to compare against' - ); - } - - var equal = true; - var node = b; - - traverse(a).forEach(function (y) { - var notEqual = (function () { - equal = false; - //this.stop(); - return undefined; - }).bind(this); - - //if (node === undefined || node === null) return notEqual(); - - if (!this.isRoot) { - /* + if (arguments.length !== 2) { + throw new Error('deepEqual requires exactly two objects to compare against'); + } + + var equal = true; + var node = b; + + traverse(a).forEach(function (y) { + var notEqual = (function () { + equal = false; + // this.stop(); + return undefined; + }).bind(this); + + // if (node === undefined || node === null) return notEqual(); + + if (!this.isRoot) { + /* if (!Object.hasOwnProperty.call(node, this.key)) { return notEqual(); } */ - if (typeof node !== 'object') return notEqual(); - node = node[this.key]; - } - - var x = node; - - this.post(function () { - node = x; - }); - - var toS = function (o) { - return Object.prototype.toString.call(o); - }; - - if (this.circular) { - if (traverse(b).get(this.circular.path) !== x) notEqual(); - } - else if (typeof x !== typeof y) { - notEqual(); - } - else if (x === null || y === null || x === undefined || y === undefined) { - if (x !== y) notEqual(); - } - else if (x.__proto__ !== y.__proto__) { - notEqual(); - } - else if (x === y) { - // nop - } - else if (typeof x === 'function') { - if (x instanceof RegExp) { - // both regexps on account of the __proto__ check - if (x.toString() != y.toString()) notEqual(); - } - else if (x !== y) notEqual(); - } - else if (typeof x === 'object') { - if (toS(y) === '[object Arguments]' + if (typeof node !== 'object') return notEqual(); + node = node[this.key]; + } + + var x = node; + + this.post(function () { + node = x; + }); + + var toS = function (o) { + return Object.prototype.toString.call(o); + }; + + if (this.circular) { + if (traverse(b).get(this.circular.path) !== x) notEqual(); + } + else if (typeof x !== typeof y) { + notEqual(); + } + else if (x === null || y === null || x === undefined || y === undefined) { + if (x !== y) notEqual(); + } + else if (x.__proto__ !== y.__proto__) { + notEqual(); + } + else if (x === y) { + // nop + } + else if (typeof x === 'function') { + if (x instanceof RegExp) { + // both regexps on account of the __proto__ check + if (x.toString() != y.toString()) notEqual(); + } + else if (x !== y) notEqual(); + } + else if (typeof x === 'object') { + if (toS(y) === '[object Arguments]' || toS(x) === '[object Arguments]') { - if (toS(x) !== toS(y)) { - notEqual(); - } - } - else if (toS(y) === '[object RegExp]' + if (toS(x) !== toS(y)) { + notEqual(); + } + } + else if (toS(y) === '[object RegExp]' || toS(x) === '[object RegExp]') { - if (!x || !y || x.toString() !== y.toString()) notEqual(); - } - else if (x instanceof Date || y instanceof Date) { - if (!(x instanceof Date) || !(y instanceof Date) + if (!x || !y || x.toString() !== y.toString()) notEqual(); + } + else if (x instanceof Date || y instanceof Date) { + if (!(x instanceof Date) || !(y instanceof Date) || x.getTime() !== y.getTime()) { - notEqual(); - } - } - else { - var kx = Object.keys(x); - var ky = Object.keys(y); - if (kx.length !== ky.length) return notEqual(); - for (var i = 0; i < kx.length; i++) { - var k = kx[i]; - if (!Object.hasOwnProperty.call(y, k)) { - notEqual(); - } - } - } - } - }); - - return equal; + notEqual(); + } + } + else { + var kx = Object.keys(x); + var ky = Object.keys(y); + if (kx.length !== ky.length) return notEqual(); + for (var i = 0; i < kx.length; i++) { + var k = kx[i]; + if (!Object.hasOwnProperty.call(y, k)) { + notEqual(); + } + } + } + } + }); + + return equal; }; diff --git a/test/mutability.js b/test/mutability.js index 3ab90da..36c7485 100644 --- a/test/mutability.js +++ b/test/mutability.js @@ -3,298 +3,272 @@ var traverse = require('../'); var deepEqual = require('./lib/deep_equal'); test('mutate', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4 ] }; - var res = traverse(obj).forEach(function (x) { - if (typeof x === 'number' && x % 2 === 0) { - this.update(x * 10); - } - }); - t.same(obj, res); - t.same(obj, { a : 1, b : 20, c : [ 3, 40 ] }); - t.end(); + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, res); + t.same(obj, { a: 1, b: 20, c: [3, 40] }); + t.end(); }); test('mutateT', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4 ] }; - var res = traverse.forEach(obj, function (x) { - if (typeof x === 'number' && x % 2 === 0) { - this.update(x * 10); - } - }); - t.same(obj, res); - t.same(obj, { a : 1, b : 20, c : [ 3, 40 ] }); - t.end(); + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse.forEach(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, res); + t.same(obj, { a: 1, b: 20, c: [3, 40] }); + t.end(); }); test('map', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4 ] }; - var res = traverse(obj).map(function (x) { - if (typeof x === 'number' && x % 2 === 0) { - this.update(x * 10); - } - }); - t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); - t.same(res, { a : 1, b : 20, c : [ 3, 40 ] }); - t.end(); + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).map(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, { a: 1, b: 20, c: [3, 40] }); + t.end(); }); test('mapT', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4 ] }; - var res = traverse.map(obj, function (x) { - if (typeof x === 'number' && x % 2 === 0) { - this.update(x * 10); - } - }); - t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); - t.same(res, { a : 1, b : 20, c : [ 3, 40 ] }); - t.end(); + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse.map(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, { a: 1, b: 20, c: [3, 40] }); + t.end(); }); test('clone', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4 ] }; - var res = traverse(obj).clone(); - t.same(obj, res); - t.ok(obj !== res); - obj.a ++; - t.same(res.a, 1); - obj.c.push(5); - t.same(res.c, [ 3, 4 ]); - t.end(); + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).clone(); + t.same(obj, res); + t.ok(obj !== res); + obj.a++; + t.same(res.a, 1); + obj.c.push(5); + t.same(res.c, [3, 4]); + t.end(); }); test('cloneT', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4 ] }; - var res = traverse.clone(obj); - t.same(obj, res); - t.ok(obj !== res); - obj.a ++; - t.same(res.a, 1); - obj.c.push(5); - t.same(res.c, [ 3, 4 ]); - t.end(); + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse.clone(obj); + t.same(obj, res); + t.ok(obj !== res); + obj.a++; + t.same(res.a, 1); + obj.c.push(5); + t.same(res.c, [3, 4]); + t.end(); }); test('reduce', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4 ] }; - var res = traverse(obj).reduce(function (acc, x) { - if (this.isLeaf) acc.push(x); - return acc; - }, []); - t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); - t.same(res, [ 1, 2, 3, 4 ]); - t.end(); + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; + }, []); + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, [1, 2, 3, 4]); + t.end(); }); test('reduceInit', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4 ] }; - var res = traverse(obj).reduce(function (acc, x) { - if (this.isRoot) assert.fail('got root'); - return acc; - }); - t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); - t.same(res, obj); - t.end(); + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).reduce(function (acc, x) { + if (this.isRoot) assert.fail('got root'); + return acc; + }); + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, obj); + t.end(); }); test('remove', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4 ] }; - traverse(obj).forEach(function (x) { - if (this.isLeaf && x % 2 == 0) this.remove(); - }); - - t.same(obj, { a : 1, c : [ 3 ] }); - t.end(); + var obj = { a: 1, b: 2, c: [3, 4] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + t.same(obj, { a: 1, c: [3] }); + t.end(); }); -exports.removeNoStop = function() { - var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 }; - - var keys = []; - traverse(obj).forEach(function (x) { - keys.push(this.key) - if (this.key == 'c') this.remove(); - }); - - t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e', 'f']) - t.end(); +exports.removeNoStop = function () { + var obj = { a: 1, b: 2, c: { d: 3, e: 4 }, f: 5 }; + + var keys = []; + traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.remove(); + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e', 'f']) + t.end(); } -exports.removeStop = function() { - var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 }; - - var keys = []; - traverse(obj).forEach(function (x) { - keys.push(this.key) - if (this.key == 'c') this.remove(true); - }); - - t.same(keys, [undefined, 'a', 'b', 'c', 'f']) - t.end(); +exports.removeStop = function () { + var obj = { a: 1, b: 2, c: { d: 3, e: 4 }, f: 5 }; + + var keys = []; + traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.remove(true); + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'f']) + t.end(); } test('removeMap', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4 ] }; - var res = traverse(obj).map(function (x) { - if (this.isLeaf && x % 2 == 0) this.remove(); - }); - - t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); - t.same(res, { a : 1, c : [ 3 ] }); - t.end(); + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, { a: 1, c: [3] }); + t.end(); }); test('delete', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4 ] }; - traverse(obj).forEach(function (x) { - if (this.isLeaf && x % 2 == 0) this.delete(); - }); - - t.ok(!deepEqual( - obj, { a : 1, c : [ 3, undefined ] } - )); - - t.ok(deepEqual( - obj, { a : 1, c : [ 3 ] } - )); - - t.ok(!deepEqual( - obj, { a : 1, c : [ 3, null ] } - )); - t.end(); + var obj = { a: 1, b: 2, c: [3, 4] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + t.ok(!deepEqual(obj, { a: 1, c: [3, undefined] })); + + t.ok(deepEqual(obj, { a: 1, c: [3] })); + + t.ok(!deepEqual(obj, { a: 1, c: [3, null] })); + t.end(); }); test('deleteNoStop', function (t) { - var obj = { a : 1, b : 2, c : { d: 3, e: 4 } }; - - var keys = []; - traverse(obj).forEach(function (x) { - keys.push(this.key) - if (this.key == 'c') this.delete(); - }); - - t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e']) - t.end(); + var obj = { a: 1, b: 2, c: { d: 3, e: 4 } }; + + var keys = []; + traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.delete(); + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e']) + t.end(); }); test('deleteStop', function (t) { - var obj = { a : 1, b : 2, c : { d: 3, e: 4 } }; - - var keys = []; - traverse(obj).forEach(function (x) { - keys.push(this.key) - if (this.key == 'c') this.delete(true); - }); - - t.same(keys, [undefined, 'a', 'b', 'c']) - t.end(); + var obj = { a: 1, b: 2, c: { d: 3, e: 4 } }; + + var keys = []; + traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.delete(true); + }); + + t.same(keys, [undefined, 'a', 'b', 'c']) + t.end(); }); test('deleteRedux', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; - traverse(obj).forEach(function (x) { - if (this.isLeaf && x % 2 == 0) this.delete(); - }); - - t.ok(!deepEqual( - obj, { a : 1, c : [ 3, undefined, 5 ] } - )); - - t.ok(deepEqual( - obj, { a : 1, c : [ 3 ,, 5 ] } - )); - - t.ok(!deepEqual( - obj, { a : 1, c : [ 3, null, 5 ] } - )); - - t.ok(!deepEqual( - obj, { a : 1, c : [ 3, 5 ] } - )); - - t.end(); + var obj = { a: 1, b: 2, c: [3, 4, 5] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + t.ok(!deepEqual(obj, { a: 1, c: [3, undefined, 5] })); + + t.ok(deepEqual(obj, { a: 1, c: [3,, 5] })); + + t.ok(!deepEqual(obj, { a: 1, c: [3, null, 5] })); + + t.ok(!deepEqual(obj, { a: 1, c: [3, 5] })); + + t.end(); }); test('deleteMap', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4 ] }; - var res = traverse(obj).map(function (x) { - if (this.isLeaf && x % 2 == 0) this.delete(); - }); - - t.ok(deepEqual( - obj, - { a : 1, b : 2, c : [ 3, 4 ] } - )); - - var xs = [ 3, 4 ]; - delete xs[1]; - - t.ok(deepEqual( - res, { a : 1, c : xs } - )); - - t.ok(deepEqual( - res, { a : 1, c : [ 3, ] } - )); - - t.ok(deepEqual( - res, { a : 1, c : [ 3 ] } - )); - - t.end(); + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + t.ok(deepEqual( + obj, + { a: 1, b: 2, c: [3, 4] } + )); + + var xs = [3, 4]; + delete xs[1]; + + t.ok(deepEqual(res, { a: 1, c: xs })); + + t.ok(deepEqual(res, { a: 1, c: [3,,] })); // eslint-disable-line comma-spacing + + t.ok(deepEqual(res, { a: 1, c: [3] })); + + t.end(); }); test('deleteMapRedux', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; - var res = traverse(obj).map(function (x) { - if (this.isLeaf && x % 2 == 0) this.delete(); - }); - - t.ok(deepEqual( - obj, - { a : 1, b : 2, c : [ 3, 4, 5 ] } - )); - - var xs = [ 3, 4, 5 ]; - delete xs[1]; - - t.ok(deepEqual( - res, { a : 1, c : xs } - )); - - t.ok(!deepEqual( - res, { a : 1, c : [ 3, 5 ] } - )); - - t.ok(deepEqual( - res, { a : 1, c : [ 3 ,, 5 ] } - )); - - t.end(); + var obj = { a: 1, b: 2, c: [3, 4, 5] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + t.ok(deepEqual( + obj, + { a: 1, b: 2, c: [3, 4, 5] } + )); + + var xs = [3, 4, 5]; + delete xs[1]; + + t.ok(deepEqual(res, { a: 1, c: xs })); + + t.ok(!deepEqual(res, { a: 1, c: [3, 5] })); + + t.ok(deepEqual(res, { a: 1, c: [3,, 5] })); + + t.end(); }); test('objectToString', function (t) { - var obj = { a : 1, b : 2, c : [ 3, 4 ] }; - var res = traverse(obj).forEach(function (x) { - if (typeof x === 'object' && !this.isRoot) { - this.update(JSON.stringify(x)); - } - }); - t.same(obj, res); - t.same(obj, { a : 1, b : 2, c : "[3,4]" }); - t.end(); + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'object' && !this.isRoot) { + this.update(JSON.stringify(x)); + } + }); + t.same(obj, res); + t.same(obj, { a: 1, b: 2, c: "[3,4]" }); + t.end(); }); test('stringToObject', function (t) { - var obj = { a : 1, b : 2, c : "[3,4]" }; - var res = traverse(obj).forEach(function (x) { - if (typeof x === 'string') { - this.update(JSON.parse(x)); - } - else if (typeof x === 'number' && x % 2 === 0) { - this.update(x * 10); - } - }); - t.deepEqual(obj, res); - t.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] }); - t.end(); + var obj = { a: 1, b: 2, c: "[3,4]" }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'string') { + this.update(JSON.parse(x)); + } + else if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.deepEqual(obj, res); + t.deepEqual(obj, { a: 1, b: 20, c: [3, 40] }); + t.end(); }); diff --git a/test/negative.js b/test/negative.js index 91566c8..135a91a 100644 --- a/test/negative.js +++ b/test/negative.js @@ -2,20 +2,22 @@ var traverse = require('../'); var test = require('tape'); test('negative update test', function (t) { - var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; - var fixed = traverse.map(obj, function (x) { - if (x < 0) this.update(x + 128); - }); - - t.same(fixed, - [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ], - 'Negative values += 128' - ); - - t.same(obj, - [ 5, 6, -3, [ 7, 8, -2, 1 ], { f: 10, g: -13 } ], - 'Original references not modified' - ); - - t.end(); + var obj = [5, 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }]; + var fixed = traverse.map(obj, function (x) { + if (x < 0) this.update(x + 128); + }); + + t.same( + fixed, + [5, 6, 125, [7, 8, 126, 1], { f: 10, g: 115 }], + 'Negative values += 128' + ); + + t.same( + obj, + [5, 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }], + 'Original references not modified' + ); + + t.end(); }); diff --git a/test/obj.js b/test/obj.js index 8bcf58a..fffb08d 100644 --- a/test/obj.js +++ b/test/obj.js @@ -2,10 +2,10 @@ var test = require('tape'); var traverse = require('../'); test('traverse an object with nested functions', function (t) { - t.plan(1); - - function Cons (x) { - t.equal(x, 10) - }; - traverse(new Cons(10)); + t.plan(1); + + function Cons(x) { + t.equal(x, 10) + }; + traverse(new Cons(10)); }); diff --git a/test/siblings.js b/test/siblings.js index c59e557..33dc228 100644 --- a/test/siblings.js +++ b/test/siblings.js @@ -2,36 +2,36 @@ var test = require('tape'); var traverse = require('../'); test('siblings', function (t) { - var obj = { a : 1, b : 2, c : [ 4, 5, 6 ] }; - - var res = traverse(obj).reduce(function (acc, x) { - var p = '/' + this.path.join('/'); - if (this.parent) { - acc[p] = { - siblings : this.parent.keys, - key : this.key, - index : this.parent.keys.indexOf(this.key) - }; - } - else { - acc[p] = { - siblings : [], - key : this.key, - index : -1 - } - } - return acc; - }, {}); - - t.same(res, { - '/' : { siblings : [], key : undefined, index : -1 }, - '/a' : { siblings : [ 'a', 'b', 'c' ], key : 'a', index : 0 }, - '/b' : { siblings : [ 'a', 'b', 'c' ], key : 'b', index : 1 }, - '/c' : { siblings : [ 'a', 'b', 'c' ], key : 'c', index : 2 }, - '/c/0' : { siblings : [ '0', '1', '2' ], key : '0', index : 0 }, - '/c/1' : { siblings : [ '0', '1', '2' ], key : '1', index : 1 }, - '/c/2' : { siblings : [ '0', '1', '2' ], key : '2', index : 2 } - }); - - t.end(); + var obj = { a: 1, b: 2, c: [4, 5, 6] }; + + var res = traverse(obj).reduce(function (acc, x) { + var p = '/' + this.path.join('/'); + if (this.parent) { + acc[p] = { + siblings: this.parent.keys, + key: this.key, + index: this.parent.keys.indexOf(this.key) + }; + } + else { + acc[p] = { + siblings: [], + key: this.key, + index: -1 + } + } + return acc; + }, {}); + + t.same(res, { + '/': { siblings: [], key: undefined, index: -1 }, + '/a': { siblings: ['a', 'b', 'c'], key: 'a', index: 0 }, + '/b': { siblings: ['a', 'b', 'c'], key: 'b', index: 1 }, + '/c': { siblings: ['a', 'b', 'c'], key: 'c', index: 2 }, + '/c/0': { siblings: ['0', '1', '2'], key: '0', index: 0 }, + '/c/1': { siblings: ['0', '1', '2'], key: '1', index: 1 }, + '/c/2': { siblings: ['0', '1', '2'], key: '2', index: 2 } + }); + + t.end(); }); diff --git a/test/stop.js b/test/stop.js index 9ce15b0..cdf6b56 100644 --- a/test/stop.js +++ b/test/stop.js @@ -2,43 +2,43 @@ var test = require('tape'); var traverse = require('../'); test('stop', function (t) { - var visits = 0; - traverse('abcdefghij'.split('')).forEach(function (node) { - if (typeof node === 'string') { - visits ++; - if (node === 'e') this.stop() - } - }); - - t.equal(visits, 5); - t.end(); + var visits = 0; + traverse('abcdefghij'.split('')).forEach(function (node) { + if (typeof node === 'string') { + visits++; + if (node === 'e') this.stop() + } + }); + + t.equal(visits, 5); + t.end(); }); test('stopMap', function (t) { - var s = traverse('abcdefghij'.split('')).map(function (node) { - if (typeof node === 'string') { - if (node === 'e') this.stop() - return node.toUpperCase(); - } - }).join(''); - - t.equal(s, 'ABCDEfghij'); - t.end(); + var s = traverse('abcdefghij'.split('')).map(function (node) { + if (typeof node === 'string') { + if (node === 'e') this.stop() + return node.toUpperCase(); + } + }).join(''); + + t.equal(s, 'ABCDEfghij'); + t.end(); }); test('stopReduce', function (t) { - var obj = { - a : [ 4, 5 ], - b : [ 6, [ 7, 8, 9 ] ] - }; - var xs = traverse(obj).reduce(function (acc, node) { - if (this.isLeaf) { - if (node === 7) this.stop(); - else acc.push(node) - } - return acc; - }, []); - - t.same(xs, [ 4, 5, 6 ]); - t.end(); + var obj = { + a: [4, 5], + b: [6, [7, 8, 9]] + }; + var xs = traverse(obj).reduce(function (acc, node) { + if (this.isLeaf) { + if (node === 7) this.stop(); + else acc.push(node) + } + return acc; + }, []); + + t.same(xs, [4, 5, 6]); + t.end(); }); diff --git a/test/stringify.js b/test/stringify.js index f1680d8..95c712d 100644 --- a/test/stringify.js +++ b/test/stringify.js @@ -2,35 +2,35 @@ var test = require('tape'); var traverse = require('../'); test('stringify', function (t) { - var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; - - var s = ''; - traverse(obj).forEach(function (node) { - if (Array.isArray(node)) { - this.before(function () { s += '[' }); - this.post(function (child) { - if (!child.isLast) s += ','; - }); - this.after(function () { s += ']' }); - } - else if (typeof node == 'object') { - this.before(function () { s += '{' }); - this.pre(function (x, key) { - s += '"' + key + '"' + ':'; - }); - this.post(function (child) { - if (!child.isLast) s += ','; - }); - this.after(function () { s += '}' }); - } - else if (typeof node == 'function') { - s += 'null'; - } - else { - s += node.toString(); - } - }); - - t.equal(s, JSON.stringify(obj)); - t.end(); + var obj = [5, 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }]; + + var s = ''; + traverse(obj).forEach(function (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + s += '"' + key + '"' + ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } + }); + + t.equal(s, JSON.stringify(obj)); + t.end(); }); diff --git a/test/subexpr.js b/test/subexpr.js index 7682608..34edeb4 100644 --- a/test/subexpr.js +++ b/test/subexpr.js @@ -2,35 +2,35 @@ var traverse = require('../'); var test = require('tape'); test('subexpr', function (t) { - var obj = [ 'a', 4, 'b', 5, 'c', 6 ]; - var r = traverse(obj).map(function (x) { - if (typeof x === 'number') { - this.update([ x - 0.1, x, x + 0.1 ], true); - } - }); - - t.same(obj, [ 'a', 4, 'b', 5, 'c', 6 ]); - t.same(r, [ - 'a', [ 3.9, 4, 4.1 ], - 'b', [ 4.9, 5, 5.1 ], - 'c', [ 5.9, 6, 6.1 ], - ]); - t.end(); + var obj = ['a', 4, 'b', 5, 'c', 6]; + var r = traverse(obj).map(function (x) { + if (typeof x === 'number') { + this.update([x - 0.1, x, x + 0.1], true); + } + }); + + t.same(obj, ['a', 4, 'b', 5, 'c', 6]); + t.same(r, [ + 'a', [3.9, 4, 4.1], + 'b', [4.9, 5, 5.1], + 'c', [5.9, 6, 6.1], + ]); + t.end(); }); test('block', function (t) { - var obj = [ [ 1 ], [ 2 ], [ 3 ] ]; - var r = traverse(obj).map(function (x) { - if (Array.isArray(x) && !this.isRoot) { - if (x[0] === 5) this.block() - else this.update([ [ x[0] + 1 ] ]) - } - }); - - t.same(r, [ - [ [ [ [ [ 5 ] ] ] ] ], - [ [ [ [ 5 ] ] ] ], - [ [ [ 5 ] ] ], - ]); - t.end(); + var obj = [[1], [2], [3]]; + var r = traverse(obj).map(function (x) { + if (Array.isArray(x) && !this.isRoot) { + if (x[0] === 5) this.block() + else this.update([[x[0] + 1]]) + } + }); + + t.same(r, [ + [[[[[5]]]]], + [[[[5]]]], + [[[5]]], + ]); + t.end(); }); diff --git a/test/super_deep.js b/test/super_deep.js index 1eb9e26..18b17cd 100644 --- a/test/super_deep.js +++ b/test/super_deep.js @@ -3,54 +3,54 @@ var traverse = require('../'); var deepEqual = require('./lib/deep_equal'); test('super_deep', function (t) { - var util = require('util'); - var a0 = make(); - var a1 = make(); - t.ok(deepEqual(a0, a1)); - - a0.c.d.moo = true; - t.ok(!deepEqual(a0, a1)); - - a1.c.d.moo = true; - t.ok(deepEqual(a0, a1)); - - // TODO: this one - //a0.c.a = a1; - //t.ok(!deepEqual(a0, a1)); - t.end(); + var util = require('util'); + var a0 = make(); + var a1 = make(); + t.ok(deepEqual(a0, a1)); + + a0.c.d.moo = true; + t.ok(!deepEqual(a0, a1)); + + a1.c.d.moo = true; + t.ok(deepEqual(a0, a1)); + + // TODO: this one + // a0.c.a = a1; + // t.ok(!deepEqual(a0, a1)); + t.end(); }); -function make () { - var a = { self : 'a' }; - var b = { self : 'b' }; - var c = { self : 'c' }; - var d = { self : 'd' }; - var e = { self : 'e' }; - - a.a = a; - a.b = b; - a.c = c; - - b.a = a; - b.b = b; - b.c = c; - - c.a = a; - c.b = b; - c.c = c; - c.d = d; - - d.a = a; - d.b = b; - d.c = c; - d.d = d; - d.e = e; - - e.a = a; - e.b = b; - e.c = c; - e.d = d; - e.e = e; - - return a; +function make() { + var a = { self: 'a' }; + var b = { self: 'b' }; + var c = { self: 'c' }; + var d = { self: 'd' }; + var e = { self: 'e' }; + + a.a = a; + a.b = b; + a.c = c; + + b.a = a; + b.b = b; + b.c = c; + + c.a = a; + c.b = b; + c.c = c; + c.d = d; + + d.a = a; + d.b = b; + d.c = c; + d.d = d; + d.e = e; + + e.a = a; + e.b = b; + e.c = c; + e.d = d; + e.e = e; + + return a; }