diff --git a/.babelrc b/.babelrc deleted file mode 100644 index a0765e1..0000000 --- a/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["es2015"] -} diff --git a/.babelrc.json b/.babelrc.json new file mode 100644 index 0000000..69fe715 --- /dev/null +++ b/.babelrc.json @@ -0,0 +1,3 @@ +{ + "presets": ["@babel/preset-env"] +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..d83d722 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +# This file is for unifying the coding style for different editors and IDEs +# editorconfig.org + +root = true + +[*] +end_of_line = lf +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 + +[*.json] +indent_size = 2 + +[*.yml] +indent_size = 2 diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..42b0b2a --- /dev/null +++ b/.eslintignore @@ -0,0 +1,5 @@ +node_modules +dist + +!.eslintrc.js +coverage diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..1507be3 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,48 @@ +'use strict'; +module.exports = { + env: { + browser: true, + commonjs: true, + es6: true, + node: true + }, + extends: 'eslint:recommended', + globals: { + Atomics: 'readonly', + SharedArrayBuffer: 'readonly' + }, + overrides: [{ + files: '.eslintrc.js', + parserOptions: { + sourceType: 'script' + }, + rules: { + strict: 'error' + } + }, { + files: 'test/**', + globals: { + expect: true + }, + env: { + mocha: true + } + }], + parserOptions: { + sourceType: 'module', + ecmaVersion: 2018 + }, + rules: { + semi: ['error'], + indent: ['error', 4, { SwitchCase: 1 }], + 'prefer-const': ['error'], + 'no-var': ['error'], + 'prefer-destructuring': ['error'], + 'object-shorthand': ['error'], + 'object-curly-spacing': ['error', 'always'], + quotes: ['error', 'single'], + 'quote-props': ['error', 'as-needed'], + 'brace-style': ['error', '1tbs', { allowSingleLine: true }], + 'prefer-template': ['error'] + } +}; diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 2711a8f..0000000 --- a/.npmignore +++ /dev/null @@ -1,16 +0,0 @@ -npm-debug.log -.DS_Store -.vimrc.local -t.js -.travis.yml -.npmignore -/tmp/ -/.git/ -/node_modules/ -/tools/ -/test/ -/build/ -/cover_html/ -/coverage/ -/.coverage_data/ -package-lock.json diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..c1ca392 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock = false diff --git a/.travis.yml b/.travis.yml index c60f507..6a408a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ sudo: false language: node_js node_js: - - "6" - - "8" - - "10" + - 10 + - 12 + - 14 diff --git a/LICENSE.BSD b/LICENSE.BSD new file mode 100644 index 0000000..3e580c3 --- /dev/null +++ b/LICENSE.BSD @@ -0,0 +1,19 @@ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index ffea6b4..56d5e85 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The following code will output all variables declared at the root of a file. ```javascript esrecurse.visit(ast, { - XXXStatement: function (node) { + XXXStatement (node) { this.visit(node.left); // do something... this.visit(node.right); @@ -21,8 +21,8 @@ esrecurse.visit(ast, { We can use `Visitor` instance. ```javascript -var visitor = new esrecurse.Visitor({ - XXXStatement: function (node) { +const visitor = new esrecurse.Visitor({ + XXXStatement (node) { this.visit(node.left); // do something... this.visit(node.right); @@ -36,8 +36,7 @@ We can inherit `Visitor` instance easily. ```javascript class Derived extends esrecurse.Visitor { - constructor() - { + constructor() { super(null); } @@ -76,7 +75,7 @@ We can use user-defined node types. ```javascript // This tree contains a user-defined `TestExpression` node. -var tree = { +const tree = { type: 'TestExpression', // This 'argument' is the property containing the other **node**. @@ -91,7 +90,7 @@ var tree = { esrecurse.visit( ast, { - Literal: function (node) { + Literal (node) { // do something... } }, @@ -113,7 +112,7 @@ Please note circular references cause the stack overflow. AST might have circula esrecurse.visit( ast, { - Literal: function (node) { + Literal (node) { // do something... } }, @@ -130,13 +129,13 @@ Please note circular references cause the stack overflow. AST might have circula esrecurse.visit( ast, { - Literal: function (node) { + Literal (node) { // do something... } }, { - fallback: function (node) { - return Object.keys(node).filter(function(key) { + fallback (node) { + return Object.keys(node).filter((key) => { return key !== 'argument' }); } diff --git a/esrecurse.js b/esrecurse.js index 15d57df..6e36262 100644 --- a/esrecurse.js +++ b/esrecurse.js @@ -1,3 +1,5 @@ +// Todo: Remove eslint disable directive once have a Babel routine +/* eslint-disable no-var, prefer-template */ /* Copyright (C) 2014 Yusuke Suzuki @@ -27,6 +29,7 @@ var estraverse = require('estraverse'); function isNode(node) { + // istanbul ignore if -- Is currently always truthy if (node == null) { return false; } diff --git a/gulpfile.babel.js b/gulpfile.babel.js deleted file mode 100644 index aa881c9..0000000 --- a/gulpfile.babel.js +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (C) 2014 Yusuke Suzuki -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import gulp from 'gulp'; -import mocha from 'gulp-mocha'; -import eslint from 'gulp-eslint'; -import minimist from 'minimist'; -import git from 'gulp-git'; -import bump from 'gulp-bump'; -import filter from 'gulp-filter'; -import tagVersion from 'gulp-tag-version'; -import 'babel-register'; - -const SOURCE = [ - '*.js' -]; - -let ESLINT_OPTION = { - parser: 'babel-eslint', - parserOptions: { - 'sourceType': 'module' - }, - rules: { - 'quotes': 0, - 'eqeqeq': 0, - 'no-use-before-define': 0, - 'no-shadow': 0, - 'no-new': 0, - 'no-underscore-dangle': 0, - 'no-multi-spaces': 0, - 'no-native-reassign': 0, - 'no-loop-func': 0 - }, - env: { - 'node': true - } -}; - -gulp.task('test', function() { - let options = minimist(process.argv.slice(2), { - string: 'test', - default: { - test: 'test/*.js' - } - } - ); - return gulp.src(options.test).pipe(mocha({reporter: 'spec'})); -}); - -gulp.task('lint', () => - gulp.src(SOURCE) - .pipe(eslint(ESLINT_OPTION)) - .pipe(eslint.formatEach('stylish', process.stderr)) - .pipe(eslint.failOnError()) -); - -let inc = importance => - gulp.src(['./package.json']) - .pipe(bump({type: importance})) - .pipe(gulp.dest('./')) - .pipe(git.commit('Bumps package version')) - .pipe(filter('package.json')) - .pipe(tagVersion({ - prefix: '' - })) -; - -gulp.task('travis', [ 'lint', 'test' ]); -gulp.task('default', [ 'travis' ]); - -gulp.task('patch', [ ], () => inc('patch')); -gulp.task('minor', [ ], () => inc('minor')); -gulp.task('major', [ ], () => inc('major')); diff --git a/package.json b/package.json index dec5b1b..a0e7717 100755 --- a/package.json +++ b/package.json @@ -2,51 +2,62 @@ "name": "esrecurse", "description": "ECMAScript AST recursive visitor", "homepage": "https://github.com/estools/esrecurse", + "bugs": "https://github.com/estools/esrecurse/issues", "main": "esrecurse.js", "version": "4.3.0", "engines": { "node": ">=4.0" }, - "maintainers": [ - { - "name": "Yusuke Suzuki", - "email": "utatane.tea@gmail.com", - "web": "https://github.com/Constellation" - } + "files": [ + "esrecurse.js", + "LICENSE.BSD", + "README.md" + ], + "author": { + "name": "Yusuke Suzuki", + "email": "utatane.tea@gmail.com", + "web": "https://github.com/Constellation" + }, + "contributors": [ + "Brett Zamir" ], "repository": { "type": "git", "url": "https://github.com/estools/esrecurse.git" }, + "keywords": [ + "recursion" + ], "dependencies": { - "estraverse": "^5.2.0" + "estraverse": "^5.3.0" }, "devDependencies": { - "babel-cli": "^6.24.1", - "babel-eslint": "^7.2.3", - "babel-preset-es2015": "^6.24.1", - "babel-register": "^6.24.1", - "chai": "^4.0.2", - "esprima": "^4.0.0", - "gulp": "^3.9.0", - "gulp-bump": "^2.7.0", - "gulp-eslint": "^4.0.0", - "gulp-filter": "^5.0.0", - "gulp-git": "^2.4.1", - "gulp-mocha": "^4.3.1", - "gulp-tag-version": "^1.2.1", - "jsdoc": "^3.3.0-alpha10", - "minimist": "^1.1.0" + "@babel/core": "^7.17.5", + "@babel/preset-env": "^7.16.11", + "@babel/register": "^7.17.0", + "chai": "^4.3.6", + "eslint": "^8.11.0", + "esprima": "^4.0.1", + "mocha": "^9.2.2", + "nyc": "^15.1.0" }, "license": "BSD-2-Clause", - "scripts": { - "test": "gulp travis", - "unit-test": "gulp test", - "lint": "gulp lint" - }, - "babel": { - "presets": [ - "es2015" + "nyc": { + "branches": 100, + "lines": 100, + "functions": 100, + "statements": 100, + "reporter": [ + "html", + "text" + ], + "exclude": [ + "test" ] + }, + "scripts": { + "test": "npm run lint && npm run unit-test", + "unit-test": "nyc mocha --require chai/register-expect.js --require @babel/register test", + "lint": "eslint ." } } diff --git a/test/traverse.js b/test/traverse.js index 285edaa..24f7d64 100644 --- a/test/traverse.js +++ b/test/traverse.js @@ -1,31 +1,32 @@ -// Copyright (C) 2013 Yusuke Suzuki -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -var expect = require('chai').expect; -var esrecurse = require('..'); - -describe('object expression', () => +/* +Copyright (C) 2013 Yusuke Suzuki + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import esrecurse from '../'; + +describe('object expression', () => { it('properties', function() { - let tree = { + const tree = { type: 'ObjectExpression', properties: [{ type: 'Property', @@ -40,7 +41,7 @@ describe('object expression', () => }] }; - let log = []; + const log = []; esrecurse.visit(tree, { Identifier(node) { return log.push(node.name); @@ -48,14 +49,36 @@ describe('object expression', () => } ); + expect(log).to.deep.equal(['a', 'b']); + }); - return expect(log).to.deep.equal(['a', 'b']); - }) -); + it('silently recover when AST missing visitor keys', function() { + const tree = { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'a' + } + }] + }; + + const log = []; + esrecurse.visit(tree, { + Identifier(node) { + return log.push(node.name); + } + } + ); + + expect(log).to.deep.equal(['a']); + }); +}); describe('chain expression', () => it('expressions', function() { - let tree = { + const tree = { type: 'ChainExpression', expression: [{ type: 'MemberExpression', @@ -72,22 +95,20 @@ describe('chain expression', () => }] }; - let log = []; + const log = []; esrecurse.visit(tree, { - Identifier(node) { - return log.push(node.name); - } + Identifier(node) { + return log.push(node.name); } - ); - + }); return expect(log).to.deep.equal(['a', 'b']); }) ); -describe('non listed keys throw an error', () => +describe('non listed keys throw an error', () => { it('traverse', function() { - let tree = { + const tree = { type: 'TestStatement', id: { type: 'Identifier', @@ -111,8 +132,8 @@ describe('non listed keys throw an error', () => } }; - return expect(function() { - let log = []; + expect(function() { + const log = []; return esrecurse.visit( tree, { @@ -122,14 +143,13 @@ describe('non listed keys throw an error', () => } ); }).to.throw('Unknown node type TestStatement.'); - }) -); - + }); +}); -describe('no listed keys fallback if "fallback" option was given', () => +describe('no listed keys fallback if "fallback" option was given', () => { it('traverse', function() { - let tree = { + const tree = { type: 'TestStatement', id: { type: 'Identifier', @@ -153,7 +173,7 @@ describe('no listed keys fallback if "fallback" option was given', () => } }; - let log = []; + const log = []; esrecurse.visit( tree, { @@ -166,13 +186,13 @@ describe('no listed keys fallback if "fallback" option was given', () => } ); - return expect(log).to.deep.equal([ 20 ]); -}) -); + expect(log).to.deep.equal([ 20 ]); + }); +}); -describe('no listed keys fallback if "fallback" option is a function', () => +describe('no listed keys fallback if "fallback" option is a function', () => { it('traverse', function() { - let tree = { + const tree = { type: 'TestStatement', id: { type: 'Identifier', @@ -211,14 +231,14 @@ describe('no listed keys fallback if "fallback" option is a function', () => } ); - return expect(result).to.equal(2); - }) -); + expect(result).to.equal(2); + }); +}); describe('inherit Visitor', function() { it('log names', function() { - let tree = { + const tree = { type: 'TestStatement', id: { type: 'Identifier', @@ -244,7 +264,7 @@ describe('inherit Visitor', function() { class Derived extends esrecurse.Visitor { constructor() { - super(null, {fallback: 'iteration'}); + super(null, { fallback: 'iteration' }); this.log = []; } @@ -253,14 +273,165 @@ describe('inherit Visitor', function() { } } - let visitor = new Derived; + const visitor = new Derived(); visitor.visit(tree); - return expect(visitor.log).to.deep.equal([ 'decl', 'a', 'rest' ]); -}); + expect(visitor.log).to.deep.equal([ 'decl', 'a', 'rest' ]); + }); + + it('`visit` handles `null`', function () { + class Derived extends esrecurse.Visitor { + constructor() { + super(null, { fallback: 'iteration' }); + this.log = []; + } + + Identifier(node) { + return this.log.push(node.name); + } + } + + const visitor = new Derived(); + visitor.visit(null); + + expect(visitor.log).to.be.empty; + }); + + it('`visit` defaults to Property type', function () { + class Derived extends esrecurse.Visitor { + constructor() { + super(null, { fallback: 'iteration' }); + this.log = []; + } + + key(node) { + return this.log.push(node.name); + } + value(node) { + return this.log.push(node.name); + } + } + + const visitor = new Derived(); + visitor.visit({ + key: { + name: 'myKey', + type: 'key' + }, + value: { + name: 'myValue', + type: 'value' + } + }); + + expect(visitor.log).to.deep.equal(['myKey', 'myValue']); + }); - return it('customize behavior', function() { - let tree = { + // `null` should not get to `visitChildren` through `visit` + it('`visitChildren` handles `null`', function () { + class Derived extends esrecurse.Visitor { + constructor() { + super(null, { fallback: 'iteration' }); + this.log = []; + } + + Identifier(node) { + return this.log.push(node.name); + } + } + + const visitor = new Derived(); + visitor.visitChildren(null); + + expect(visitor.log).to.be.empty; + }); + + it('`visitChildren` ignores non-Node children', function () { + class Derived extends esrecurse.Visitor { + constructor() { + super(null, { fallback: 'iteration' }); + this.log = []; + } + + FunctionDeclaration(node) { + return this.log.push(node.name); + } + + Identifier(node) { + return this.log.push(node.name); + } + } + + const visitor = new Derived(); + visitor.visitChildren({ + type: 'FunctionDeclaration', + params: [null, {}] + }); + + expect(visitor.log).to.be.empty; + }); + + it('`visitChildren` defaults to Property type', function () { + class Derived extends esrecurse.Visitor { + constructor() { + super(null, { fallback: 'iteration' }); + this.log = []; + } + + key(node) { + return this.log.push(node.name); + } + value(node) { + return this.log.push(node.name); + } + } + + const visitor = new Derived(); + visitor.visitChildren({ + key: { + name: 'myKey', + type: 'key' + }, + value: { + name: 'myValue', + type: 'value' + } + }); + + expect(visitor.log).to.deep.equal(['myKey', 'myValue']); + }); + + it('`visitChildren` visits non-Node `ObjectExpression`/`ObjectPattern` property keys', function () { + class Derived extends esrecurse.Visitor { + constructor() { + super(null, { fallback: 'iteration' }); + this.log = []; + } + + Property(node) { + return this.log.push(node.name); + } + } + + const visitor = new Derived(); + visitor.visitChildren({ + type: 'ObjectExpression', + properties: [{ + name: 'myExpression' + }] + }); + visitor.visitChildren({ + type: 'ObjectPattern', + properties: [{ + name: 'myPattern' + }] + }); + + expect(visitor.log).to.deep.equal(['myExpression', 'myPattern']); + }); + + it('customize behavior', function() { + const tree = { type: 'TestStatement', id: { type: 'Identifier', @@ -289,27 +460,27 @@ describe('inherit Visitor', function() { class Derived extends esrecurse.Visitor { constructor() { - super(null, {fallback: 'iteration'}); + super(null, { fallback: 'iteration' }); this.log = []; } - BlockStatement(node) {} + BlockStatement(/* node */) {} Identifier(node) { return this.log.push(node.name); } } - let visitor = new Derived; + const visitor = new Derived(); visitor.visit(tree); - return expect(visitor.log).to.deep.equal([ 'decl', 'a', 'rest' ]); -}); + expect(visitor.log).to.deep.equal([ 'decl', 'a', 'rest' ]); + }); }); describe('bidirectional relationship at non visitor keys.', function() { it('ExpressionStatement <-> Identifier', function() { - let tree = { + const tree = { type: 'ExpressionStatement', expression: { type: 'Identifier', @@ -318,20 +489,18 @@ describe('bidirectional relationship at non visitor keys.', function() { }; tree.expression.parent = tree; - let log = []; + const log = []; esrecurse.visit(tree, { Identifier(node) { return log.push(node.name); } - } - ); + }); + expect(log).to.deep.equal(['foo']); + }); - return expect(log).to.deep.equal(['foo']); -}); - - return it('ExpressionStatement <-> UnknownNode with the childVisitorKeys option', function() { - let tree = { + it('ExpressionStatement <-> UnknownNode with the childVisitorKeys option', function() { + const tree = { type: 'ExpressionStatement', expression: { type: 'UnknownNode', @@ -344,7 +513,7 @@ describe('bidirectional relationship at non visitor keys.', function() { tree.expression.parent = tree; tree.expression.argument.parent = tree.expression; - let log = []; + const log = []; esrecurse.visit( tree, { @@ -359,7 +528,6 @@ describe('bidirectional relationship at non visitor keys.', function() { } ); - - return expect(log).to.deep.equal(['foo']); -}); + expect(log).to.deep.equal(['foo']); + }); });