├── .nvmrc ├── dist └── .keep ├── src ├── tests │ ├── fixtures │ │ ├── deprecated.js │ │ ├── simple.js │ │ ├── documented.js │ │ ├── commented.js │ │ └── everything.js │ ├── snapshots │ │ ├── attachComments.js.snap │ │ ├── defaultTraveler.js.snap │ │ ├── attachComments.js.md │ │ └── defaultTraveler.js.md │ ├── helpers │ │ ├── parseFixture.js │ │ └── parse.js │ ├── attachComments.js │ └── defaultTraveler.js ├── astravel.js ├── attachComments.js └── defaultTraveler.js ├── .eslintignore ├── .travis.yml ├── .gitignore ├── .npmignore ├── .eslintrc.json ├── babel.config.js ├── astravel.sublime-project ├── CHANGELOG.md ├── LICENSE ├── examples └── localVariables.js ├── package.json └── README.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 16 -------------------------------------------------------------------------------- /dist/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/tests/fixtures/deprecated.js: -------------------------------------------------------------------------------- 1 | with (object) { 2 | } 3 | -------------------------------------------------------------------------------- /src/tests/fixtures/simple.js: -------------------------------------------------------------------------------- 1 | function f() { 2 | return 1 3 | } 4 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | local/* 3 | vendor/* 4 | dist/* 5 | src/tests/fixtures/* -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 12 4 | - 14 5 | 6 | after_success: 7 | - npx codecov --file=./coverage/lcov.info 8 | -------------------------------------------------------------------------------- /src/tests/snapshots/attachComments.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidbonnet/astravel/HEAD/src/tests/snapshots/attachComments.js.snap -------------------------------------------------------------------------------- /src/tests/snapshots/defaultTraveler.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidbonnet/astravel/HEAD/src/tests/snapshots/defaultTraveler.js.snap -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | *.sublime-workspace 3 | test/_*.js 4 | .nyc_output 5 | coverage 6 | dist 7 | local 8 | node_modules 9 | npm-debug.log 10 | .nova -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.sublime-project 2 | *.sublime-workspace 3 | .babelrc 4 | .eslintignore 5 | .eslintrc.js 6 | .gitignore 7 | .travis.yml 8 | coverage/ 9 | dist/.keep 10 | local/ 11 | node_modules/ 12 | package-lock.json 13 | src/tests/ -------------------------------------------------------------------------------- /src/tests/helpers/parseFixture.js: -------------------------------------------------------------------------------- 1 | import { join } from 'path' 2 | 3 | import { parse } from './parse' 4 | 5 | const DIRNAME = join(__dirname, '../fixtures') 6 | 7 | export async function parseFixture(fileName, options) { 8 | return await parse(join(DIRNAME, fileName), options) 9 | } 10 | -------------------------------------------------------------------------------- /src/tests/attachComments.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | import { parseFixture } from './helpers/parseFixture' 4 | import { attachComments } from '../attachComments' 5 | 6 | test('Comments attachment', async (assert) => { 7 | const comments = [] 8 | const ast = await parseFixture('commented.js', { 9 | ranges: true, 10 | onComment: comments, 11 | }) 12 | assert.snapshot(comments) 13 | attachComments(ast, comments) 14 | assert.snapshot(ast) 15 | }) 16 | -------------------------------------------------------------------------------- /src/tests/fixtures/documented.js: -------------------------------------------------------------------------------- 1 | export function f(a, b) { 2 | /* 3 | Documentation for function `f` with params `a` and `b`. 4 | */ 5 | return a + b 6 | } 7 | 8 | export function privateFunction() {} 9 | 10 | export function g() { 11 | /* 12 | Documentation for function `g`. 13 | */ 14 | } 15 | 16 | export class A { 17 | /* 18 | Documentation for class A. 19 | */ 20 | 21 | m(x, y = true) { 22 | /* 23 | Document for method `m` with params `x` and `y`. 24 | */ 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/tests/fixtures/commented.js: -------------------------------------------------------------------------------- 1 | /* 2 | Module documentation. 3 | */ 4 | 5 | /* 6 | Documentation for variable `point`. 7 | */ 8 | const point = { 9 | /* This is a block comment inside an object expression */ 10 | // This comment is for the x property 11 | x: 0, 12 | // …and this one is for the y property 13 | y: 1, 14 | // Trailing comment 15 | } 16 | 17 | class A { 18 | /* 19 | Documentation for class A. 20 | */ 21 | 22 | m(x, y = true) { 23 | /* 24 | Document for method `m` with params `x` and `y`. 25 | */ 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/tests/helpers/parse.js: -------------------------------------------------------------------------------- 1 | import normalizeNewline from 'normalize-newline' 2 | import { parse as baseParse } from 'meriyah' 3 | import { readFile } from 'fs' 4 | import { promisify } from 'util' 5 | 6 | const readFileAsync = promisify(readFile) 7 | 8 | export async function parse(fileName, parserOptions = null) { 9 | const code = await readFileAsync(fileName, 'utf8') 10 | return baseParse(normalizeNewline(code), { 11 | module: true, 12 | jsx: true, 13 | specDeviation: true, 14 | next: true, 15 | ...parserOptions, 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["import"], 3 | "extends": ["eslint:recommended", "plugin:import/errors", "prettier"], 4 | "env": { 5 | "es6": true 6 | }, 7 | "parserOptions": { 8 | "ecmaVersion": 9, 9 | "sourceType": "module" 10 | }, 11 | "globals": { 12 | "__dirname": true, 13 | "__filename": true, 14 | "clearInterval": true, 15 | "clearTimeout": true, 16 | "console": true, 17 | "document": true, 18 | "global": true, 19 | "module": true, 20 | "process": true, 21 | "require": true, 22 | "window": true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/astravel.js: -------------------------------------------------------------------------------- 1 | // Astravel is tiny and fast ESTree-compliant AST walker and modifier. 2 | // 3 | // Astravel was written by David Bonnet and released under an MIT license. 4 | // 5 | // The Git repository for Astravel is available at: 6 | // https://github.com/davidbonnet/astravel.git 7 | // 8 | // Please use the GitHub bug tracker to report issues: 9 | // https://github.com/davidbonnet/astravel/issues 10 | 11 | import { defaultTraveler } from './defaultTraveler' 12 | export { attachComments } from './attachComments' 13 | 14 | export function makeTraveler(properties) { 15 | /* 16 | Returns a custom AST traveler that inherits from the `defaultTraveler` with its own provided `properties` and the property `super` that points to the parent traveler object. 17 | */ 18 | return defaultTraveler.makeChild(properties) 19 | } 20 | 21 | export { defaultTraveler } 22 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = (api) => { 2 | api.cache.never() 3 | switch (process.env.BABEL_MODE) { 4 | case 'module': 5 | return { 6 | plugins: [ 7 | [ 8 | 'module-extension-resolver', 9 | { 10 | extensionsToKeep: ['.js', '.json'], 11 | }, 12 | ], 13 | ], 14 | } 15 | default: 16 | return { 17 | plugins: [ 18 | [ 19 | '@babel/plugin-transform-runtime', 20 | { 21 | absoluteRuntime: false, 22 | corejs: false, 23 | helpers: true, 24 | regenerator: true, 25 | useESModules: false, 26 | }, 27 | ], 28 | ], 29 | presets: [ 30 | [ 31 | '@babel/preset-env', 32 | { 33 | forceAllTransforms: true, 34 | }, 35 | ], 36 | ], 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /astravel.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": ".", 5 | "folder_exclude_patterns": ["node_modules", "coverage", ".nyc_output"] 6 | } 7 | ], 8 | "settings": { 9 | "folder_exclude_patterns": [".git", "node_modules", "dist"], 10 | "tab_size": 2, 11 | "js_prettier": { 12 | "auto_format_on_save": true, 13 | "auto_format_on_save_excludes": [ 14 | "*/package.json", 15 | "*/dist/*", 16 | "*/node_modules/*", 17 | "*/.git/*" 18 | ], 19 | "allow_inline_formatting": true, 20 | "custom_file_extensions": ["sublime-project"], 21 | "additional_cli_args": { 22 | "--config": "package.json", 23 | "--config-precedence": "prefer-file" 24 | } 25 | } 26 | }, 27 | "SublimeLinter": { 28 | "linters": { 29 | "eslint": { 30 | "disable": false 31 | }, 32 | "flow": { 33 | "disable": true 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | 6 | ## [0.6.1](https://github.com/davidbonnet/astravel/compare/v0.6.0...v0.6.1) (2021-11-21) 7 | 8 | 9 | ### Bug Fixes 10 | 11 | * package and exports ([97028b6](https://github.com/davidbonnet/astravel/commit/97028b6)) 12 | 13 | 14 | 15 | 16 | # [0.6.0](https://github.com/davidbonnet/astravel/compare/v0.5.0...v0.6.0) (2021-11-21) 17 | 18 | 19 | ### Features 20 | 21 | * support es2022 ([#33](https://github.com/davidbonnet/astravel/issues/33)) ([3d5bea5](https://github.com/davidbonnet/astravel/commit/3d5bea5)) 22 | 23 | 24 | 25 | 26 | # [0.5.0](https://github.com/davidbonnet/astravel/compare/v0.4.1...v0.5.0) (2018-06-23) 27 | 28 | 29 | ### Features 30 | 31 | * **ecmascript:** add support for 2019 version ([00a2cd7](https://github.com/davidbonnet/astravel/commit/00a2cd7)) 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, David Bonnet 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /src/tests/defaultTraveler.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | import { parseFixture } from './helpers/parseFixture' 4 | import { defaultTraveler } from '../defaultTraveler' 5 | 6 | test('Default traveler', async (assert) => { 7 | const state = { 8 | tree: ['Root', []], 9 | } 10 | const ast = await parseFixture('everything.js') 11 | const customTraveler = defaultTraveler.makeChild({ 12 | go(node, state) { 13 | const { tree } = state 14 | const child = [node.type, []] 15 | tree[1].push(child) 16 | state.tree = child 17 | this[node.type](node, state) 18 | state.tree = tree 19 | }, 20 | }) 21 | customTraveler.go(ast, state) 22 | assert.snapshot(state.tree) 23 | }) 24 | 25 | test('Deprecated', async (assert) => { 26 | const ast = await parseFixture('deprecated.js', { 27 | module: false, 28 | impliedStrict: false, 29 | }) 30 | defaultTraveler.go(ast) 31 | assert.pass() 32 | }) 33 | 34 | test('Find node', async (assert) => { 35 | const ast = await parseFixture('simple.js') 36 | const type = 'ReturnStatement' 37 | const result = defaultTraveler.find((node) => node.type === type, ast) 38 | assert.truthy(result) 39 | assert.truthy(result.node) 40 | assert.is(result.node.type, type) 41 | }) 42 | 43 | test('Find node throws error', (assert) => { 44 | assert.throws(() => defaultTraveler.find(), { instanceOf: TypeError }) 45 | }) 46 | -------------------------------------------------------------------------------- /examples/localVariables.js: -------------------------------------------------------------------------------- 1 | /* 2 | This example shows how to retrieve a list of local variable names. 3 | */ 4 | 5 | var acorn = require( 'acorn' ) 6 | var astravel = require( '../dist/astravel.debug' ) 7 | 8 | var ignore = Function.prototype 9 | 10 | var traveler = astravel.makeTraveler( { 11 | FunctionDeclaration: function( node, state ) { 12 | state.names.push( node.id.name ) 13 | }, 14 | BlockStatement: function( node, state ) { 15 | if ( !state.inBlock ) { 16 | state.inBlock = true 17 | this.super.BlockStatement.call( this, node, state ) 18 | state.inBlock = false 19 | } else { 20 | this.super.BlockStatement.call( this, node, state ) 21 | } 22 | }, 23 | VariableDeclaration: function( node, state ) { 24 | if ( ( state.inBlock && node.kind === 'var' ) || !state.inBlock ) { 25 | state.inDeclaration = true 26 | this.super.VariableDeclaration.call( this, node, state ) 27 | state.inDeclaration = false 28 | } 29 | }, 30 | VariableDeclarator: function( node, state ) { 31 | this.go( node.id, state ) 32 | }, 33 | ObjectPattern: function( node, state ) { 34 | if ( state.inDeclaration ) this.super.ObjectPattern.call( this, node, state ) 35 | }, 36 | ArrayPattern: function( node, state ) { 37 | if ( state.inDeclaration ) this.super.ArrayPattern.call( this, node, state ) 38 | }, 39 | Property: function( node, state ) { 40 | if ( state.inDeclaration ) this.go( node.value, state ) 41 | }, 42 | Identifier: function( node, state ) { 43 | if ( state.inDeclaration ) state.names.push( node.name ) 44 | }, 45 | FunctionExpression: ignore, 46 | ArrowFunctionExpression: ignore 47 | }) 48 | 49 | function getLocalVariableNames( ast ) { 50 | var state = { 51 | inBlock: false, 52 | inDeclaration: false, 53 | names: [] 54 | } 55 | traveler.go( ast, state ) 56 | // Filter duplicate names 57 | return state.names.filter( function( value, index, list ) { 58 | return list.indexOf( value ) === index 59 | } ) 60 | } 61 | 62 | var code = [ 63 | "var a = 1, b = 2;", 64 | "var a = 1;", 65 | "let {x, y} = {x: 0, y: 0};", 66 | "const Y = 4", 67 | "function add(a, b) {return a + b;}", 68 | "if (a > b) {", 69 | " let c = 5;", 70 | " var [d] = someArray, {e: f} = someObject;", 71 | "}", 72 | "g = a + b;" 73 | ].join( "\n" ) + "\n" 74 | 75 | var ast = acorn.parse( code, { ecmaVersion: 6 } ) 76 | 77 | console.log( code ) 78 | console.log( 'Local variables:', getLocalVariableNames( ast ).join( ', ' ) ) 79 | 80 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "astravel", 3 | "version": "0.6.1", 4 | "description": "ESTree-compliant AST walker and modifier.", 5 | "main": "./dist/require/astravel.js", 6 | "module": "./dist/module/astravel.js", 7 | "exports": { 8 | "import": "./dist/module/astravel.js", 9 | "require": "./dist/require/astravel.js" 10 | }, 11 | "scripts": { 12 | "prepare": "rm -rf dist/*; babel --config-file ./babel.config.js --no-comments --source-maps --out-dir dist/require --ignore \"**/tests/**/*.js\" src; cross-env BABEL_MODE=module babel --config-file ./babel.config.js --no-comments --source-maps --out-dir dist/module --ignore \"**/tests/**/*.js\" src", 13 | "dev": "ava --watch", 14 | "dev:update": "ava --watch --update-snapshots", 15 | "test": "npm run eslint && npm run prettier:check && npm run test:coverage", 16 | "test:coverage": "c8 --reporter=html --reporter=text --reporter=lcov --include='src/*.js' --exclude='src/tests/**/*.js' ava", 17 | "eslint": "eslint src/", 18 | "prettier": "prettier --write \"src/*.js\" \"src/tests/*.js\" \"src/tests/helpers/*.js\"", 19 | "prettier:check": "prettier --list-different \"src/*.js\" \"src/tests/*.js\" \"src/tests/helpers/*.js\"", 20 | "prepush": "npm test", 21 | "release": "standard-version", 22 | "deploy": "git push --follow-tags origin master && npm publish", 23 | "release:deploy": "npm run release && npm run deploy" 24 | }, 25 | "keywords": [ 26 | "ast", 27 | "ast walker", 28 | "ast traveler", 29 | "ast modifier", 30 | "estree", 31 | "astring" 32 | ], 33 | "repository": { 34 | "type": "git", 35 | "url": "https://github.com/davidbonnet/astravel.git" 36 | }, 37 | "author": "David Bonnet ", 38 | "license": "MIT", 39 | "devDependencies": { 40 | "@babel/cli": "^7.11.6", 41 | "@babel/core": "^7.11.6", 42 | "@babel/plugin-transform-runtime": "^7.11.5", 43 | "@babel/preset-env": "^7.11.5", 44 | "@babel/runtime": "^7.11.2", 45 | "astring": "^1.4.3", 46 | "ava": "^3.12.1", 47 | "babel-plugin-module-extension-resolver": "^1.0.0-rc.2", 48 | "c8": "^7.3.0", 49 | "codecov": "^3.7.2", 50 | "cross-env": "^7.0.2", 51 | "eslint": "^7.9.0", 52 | "eslint-config-prettier": "^6.11.0", 53 | "eslint-plugin-import": "^2.22.0", 54 | "esm": "^3.2.25", 55 | "exorcist": "^1.0.1", 56 | "husky": "^4.3.0", 57 | "meriyah": "^2.1.1", 58 | "normalize-newline": "^3.0.0", 59 | "prettier": "^2.1.2", 60 | "standard-version": "^4.4.0" 61 | }, 62 | "prettier": { 63 | "arrowParens": "always", 64 | "bracketSpacing": true, 65 | "printWidth": 80, 66 | "semi": false, 67 | "singleQuote": true, 68 | "tabWidth": 2, 69 | "trailingComma": "all", 70 | "useTabs": false 71 | }, 72 | "ava": { 73 | "files": [ 74 | "src/**/tests/*.js" 75 | ], 76 | "require": [ 77 | "esm" 78 | ] 79 | }, 80 | "esm": "auto" 81 | } 82 | -------------------------------------------------------------------------------- /src/tests/fixtures/everything.js: -------------------------------------------------------------------------------- 1 | import a from 'a' 2 | import b, { c } from 'b' 3 | import { d as e } from 'c' 4 | import * as f from 'd' 5 | 6 | export { g } from 'd' 7 | export const h = a 8 | export * from 'e' 9 | 10 | export default class Class { 11 | constructor() { 12 | this.bound = () => {} 13 | this.otherBound = a => ({}) 14 | } 15 | static s() {} 16 | m() { 17 | new.target 18 | this.isEverything = 42 19 | } 20 | } 21 | 22 | const ClassExpression = class extends Class {} 23 | 24 | function callable(a, b, c = 42) { 25 | let d = a 26 | var e = b 27 | const f = c 28 | const { g, h, i } = e 29 | const [j, k, l] = array 30 | return c === 42 ? a : b 31 | } 32 | 33 | function* generator() { 34 | yield 35 | yield 42 36 | } 37 | 38 | async function asyncFunction() { 39 | return await answer() 40 | } 41 | 42 | async function asyncLoop() { 43 | for await (const x of generator) { 44 | } 45 | } 46 | 47 | function branches() { 48 | if (a > 0) { 49 | callable(...a) 50 | } else if (a < 0) { 51 | callable(1) 52 | } else { 53 | callable(2) 54 | } 55 | if (a == 0) { 56 | } 57 | label: switch (a) { 58 | case 1: 59 | break label 60 | default: 61 | break 62 | } 63 | return 64 | } 65 | 66 | function loops() { 67 | otherLabel: for (let i = 0; i < a.length; i++) { 68 | if (i < 10) { 69 | continue otherLabel 70 | } else { 71 | continue 72 | } 73 | } 74 | for (;;) {} 75 | for (let name in object) { 76 | } 77 | for (let name of array) { 78 | } 79 | while (i < 0) {} 80 | do {} while (i < 0) 81 | } 82 | 83 | function exceptions() { 84 | try { 85 | throw new Error() 86 | } catch (error) { 87 | callable(error) 88 | } finally { 89 | callable(42) 90 | } 91 | try { 92 | } catch (error) {} 93 | try { 94 | } catch {} 95 | } 96 | 97 | function patterns() { 98 | const { a, [b]: c, ...rest } = object 99 | const [d, e] = array 100 | } 101 | 102 | const instance = new Class() 103 | 104 | const data = { 105 | a, 106 | b: c, 107 | m() {}, 108 | ...d, 109 | } 110 | 111 | const object = { 112 | a: 42, 113 | b: '42', 114 | c: 1 + 1, 115 | d: 2 * 2, 116 | f: 2 / 2, 117 | g: 3 - 2, 118 | h: 2 % 2, 119 | i: 1.5 | 0, 120 | j: 1 ^ 2, 121 | k: 1 & 2, 122 | l: 'test' in data, 123 | m: 1 == 2, 124 | n: 1 != 2, 125 | o: 1 === 2, 126 | p: 1 !== 2, 127 | q: 1 instanceof Number, 128 | r: 1 || 2, 129 | s: 1 && 2, 130 | t: (1, 2), 131 | u: 1 > 2, 132 | v: 1 < 2, 133 | w: 1 >= 2, 134 | x: 1 <= 2, 135 | y: 42 ** 2, 136 | } 137 | 138 | object.a = 42 139 | object.a += 42 140 | object.a -= 42 141 | object.a *= 42 142 | object.a /= 42 143 | object.a %= 1 144 | object.a++ 145 | ++object.a 146 | object.a-- 147 | --object.a 148 | object.a = -object.a 149 | object.a **= 2 150 | 151 | const array = [1, 2, 3, , 4, ...a] 152 | 153 | const template = `Answer is ${42}` 154 | 155 | const formattedTemplate = format`Answer is ${a}` 156 | -------------------------------------------------------------------------------- /src/attachComments.js: -------------------------------------------------------------------------------- 1 | import { defaultTraveler } from './defaultTraveler' 2 | 3 | function attachCommentsToNode( 4 | traveler, 5 | state, 6 | parent, 7 | children, 8 | findHeadingComments, 9 | ) { 10 | let { index } = state 11 | const { comments } = state 12 | let comment = comments[index] 13 | // Hack to tackle https://github.com/babel/minify/issues/866 14 | let boundComments, trailingComments 15 | if (comment == null) { 16 | return 17 | } 18 | if (children == null || children.length === 0) { 19 | // No children, attach comments to parent 20 | boundComments = parent.comments != null ? parent.comments : [] 21 | while (comment != null && comment.end <= parent.end) { 22 | boundComments.push(comment) 23 | comment = comments[++index] 24 | } 25 | state.index = index 26 | if (boundComments.length !== 0 && parent.comments == null) { 27 | parent.comments = boundComments 28 | } 29 | return 30 | } 31 | // Look for heading block comments not immediately followed by a child 32 | if (findHeadingComments) { 33 | boundComments = parent.comments != null ? parent.comments : [] 34 | const { start } = children[0] 35 | while ( 36 | comment != null && 37 | (comment.type[0] === 'B' || comment.type[0] === 'M') && 38 | comment.end <= start 39 | ) { 40 | boundComments.push(comment) 41 | comment = comments[++index] 42 | } 43 | if (boundComments.length !== 0 && parent.comments == null) 44 | parent.comments = boundComments 45 | } 46 | // Attach comments to children 47 | for (let i = 0, { length } = children; comment != null && i < length; i++) { 48 | const child = children[i] 49 | boundComments = [] 50 | while (comment != null && comment.end <= child.start) { 51 | boundComments.push(comment) 52 | comment = comments[++index] 53 | } 54 | // Check if next comment is line comment and on the same line if location is provided 55 | if ( 56 | comment != null && 57 | comment.loc != null && 58 | (comment.type[0] === 'L' || comment.type[0] === 'S') 59 | ) { 60 | if (comment.loc.start.line === child.loc.end.line) { 61 | boundComments.push(comment) 62 | comment = comments[++index] 63 | } 64 | } 65 | if (boundComments.length !== 0) { 66 | child.comments = boundComments 67 | } 68 | // Travel through child 69 | state.index = index 70 | traveler[child.type](child, state) 71 | index = state.index 72 | comment = comments[index] 73 | } 74 | // Look for remaining comments 75 | trailingComments = [] 76 | while (comment != null && comment.end <= parent.end) { 77 | trailingComments.push(comment) 78 | comment = comments[++index] 79 | } 80 | if (trailingComments.length !== 0) { 81 | parent.trailingComments = trailingComments 82 | } 83 | state.index = index 84 | } 85 | 86 | function Block(node, state) { 87 | attachCommentsToNode(this, state, node, node.body, true) 88 | } 89 | 90 | let traveler = defaultTraveler.makeChild({ 91 | Program: Block, 92 | BlockStatement: Block, 93 | ClassBody: Block, 94 | ObjectExpression(node, state) { 95 | attachCommentsToNode(this, state, node, node.properties, true) 96 | }, 97 | ArrayExpression(node, state) { 98 | attachCommentsToNode(this, state, node, node.elements, true) 99 | }, 100 | SwitchStatement(node, state) { 101 | attachCommentsToNode(this, state, node, node.cases, false) 102 | }, 103 | SwitchCase(node, state) { 104 | attachCommentsToNode(this, state, node, node.consequent, false) 105 | }, 106 | // TODO: Consider ArrayExpression ? 107 | }) 108 | 109 | export function attachComments(node, comments) { 110 | /* 111 | Modifies in-place the AST starting at `node` by attaching the provided `comments` and returns that AST. 112 | */ 113 | traveler[node.type](node, { 114 | comments, 115 | index: 0, 116 | }) 117 | return node 118 | } 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Astravel 2 | 3 | [![NPM Version](https://img.shields.io/npm/v/astravel.svg)](https://www.npmjs.org/package/astravel) 4 | [![Build Status](https://travis-ci.org/davidbonnet/astravel.svg?branch=master)](https://travis-ci.org/davidbonnet/astravel) 5 | [![Coverage](https://codecov.io/gh/davidbonnet/astravel/branch/master/graph/badge.svg)](https://codecov.io/gh/davidbonnet/astravel) 6 | [![devDependency Status](https://david-dm.org/davidbonnet/astravel/dev-status.svg)](https://david-dm.org/davidbonnet/astravel#info=devDependencies) 7 | [![Greenkeeper](https://badges.greenkeeper.io/davidbonnet/astravel.svg)](https://greenkeeper.io/) 8 | 9 | 👟 A tiny and fast [ESTree](https://github.com/estree/estree)-compliant AST walker and modifier. 10 | 11 | ### Key features 12 | 13 | - Works on [ESTree](https://github.com/estree/estree)-compliant ASTs (JavaScript [version 13 (2022)](https://tc39.github.io/ecma262/)), such as the ones produced by [Meriyah](https://github.com/meriyah/meriyah). 14 | - Out-of-the-box functions such as source code comments insertion for [Astring](https://github.com/davidbonnet/astring). 15 | - Extensible with custom nodes. 16 | - No dependencies and small footprint. 17 | 18 | ## Installation 19 | 20 | Install with the [Node Package Manager](https://www.npmjs.com/package/astravel): 21 | 22 | ```bash 23 | npm install astravel 24 | ``` 25 | 26 | Alternatively, checkout this repository and install the development dependencies to build the module file: 27 | 28 | ```bash 29 | git clone https://github.com/davidbonnet/astravel.git 30 | cd astravel 31 | npm install 32 | ``` 33 | 34 | ## Usage 35 | 36 | The `astravel` module exports the following items: 37 | 38 | 39 | 40 | - [`defaultTraveler`](#defaulttraveler) 41 | - [`makeTraveler()`](#maketraveler) 42 | - [`attachComments()`](#attachcomments) 43 | 44 | 45 | 46 | #### `defaultTraveler` 47 | 48 | > ⬅️ `traveler` 49 | 50 | > ⚠️ Deprecated in favor of ES6 class notation. 51 | 52 | This object describes a basic AST traveler. It contains the following methods: 53 | 54 | - `go(node, state)`: Travels through the provided AST `node` with a given `state` (an object that can be of any type) by recursively calling this method. 55 | - `find(predicate, node, state) ➞ { node, state }?`: Returns `{ node, state }` for which `predicate(node, state)` returns truthy, starting at the specified AST `node` and with the provided `state`. Otherwise, returns `undefined`. 56 | - `[NodeType](node, state)`: Method handler for a specific `NodeType`. 57 | - `makeChild(properties) ➞ traveler`: Returns a custom AST traveler that inherits from `this` traveler with its own provided `properties` and the property `super` that points to `this` traveler. 58 | 59 | #### `makeTraveler()` 60 | 61 | > ➡️ `(properties)` 62 | > ⬅️ `traveler` 63 | 64 | > ⚠️ Deprecated in favor of ES6 class notation. 65 | 66 | This function is similar to `astravel.defaultTraveler.makeChild`: it returns a traveler that inherits from the `defaultTraveler` with its own provided `properties` and the property `super` that points to the `defaultTraveler` object. These properties should redefine the traveler's behavior by implementing the `go(node, state)` method and/or any node handler. 67 | 68 | When redefining the `go` method, make sure its basic functionality is kept by calling the parent's `go` method to keep traveling through the AST: 69 | 70 | ```javascript 71 | const customTraveler = makeTraveler({ 72 | go: function (node, state) { 73 | // Code before entering the node 74 | console.log('Entering ' + node.type) 75 | // Call the parent's `go` method 76 | this.super.go.call(this, node, state) 77 | // Code after leaving the node 78 | console.log('Leaving ' + node.type) 79 | }, 80 | }) 81 | ``` 82 | 83 | To skip specific node types, the most effective way is to replace the corresponding node handlers with a function that does nothing: 84 | 85 | ```javascript 86 | import { makeTraveler } from 'astravel' 87 | 88 | const ignore = Function.prototype 89 | const customTraveler = makeTraveler({ 90 | FunctionDeclaration: ignore, 91 | FunctionExpression: ignore, 92 | ArrowFunctionExpression: ignore, 93 | }) 94 | ``` 95 | 96 | #### `attachComments()` 97 | 98 | > ➡️ `(ast, comments)` 99 | > ⬅️ `ast` 100 | 101 | This function attaches a list of `comments` to the corresponding nodes of a provided `ast` and returns that same `ast`. The `ast` is modified in-place and only the nodes getting comments are augmented with a `comments` and/or a `trailingComments` array property. 102 | 103 | Each comment should be an object with the following properties: 104 | 105 | - `type`: `"Line"` or `"Block"` 106 | - `value`: Comment string value 107 | - `start`: Comment starting character offset number 108 | - `end`: Comment ending character offset number 109 | - `loc`: Location object with `start` and `end` properties containing one-based `line` number and zero-based `column` number properties. 110 | 111 | The following examples show how to obtain a proper list of `comments` of a given source `code` and how to attach them on the generated `ast`: 112 | 113 | ##### Usage with [Meriyah](https://github.com/meriyah/meriyah) 114 | 115 | ```javascript 116 | import { parse } from 'meriyah' 117 | import { attachComments } from 'astravel' 118 | 119 | const comments = [] 120 | const ast = parse(code, { 121 | // Comments are stored in this array 122 | onComment: comments, 123 | }) 124 | // Attach comments on the AST 125 | attachComments(ast, comments) 126 | ``` 127 | 128 | ##### Usage with [Acorn](https://github.com/acornjs/acorn) 129 | 130 | ```javascript 131 | import { parse } from 'acorn' 132 | import { attachComments } from 'astravel' 133 | 134 | const comments = [] 135 | const ast = parse(code, { 136 | // This ensures that the `loc` property is present on comment objects 137 | locations: true, 138 | onComment: comments, 139 | }) 140 | attachComments(ast, comments) 141 | ``` 142 | 143 | The algorithm assumes that comments are not put in exotic places, such as in-between function arguments, and proceeds as follows: 144 | 145 | - For a given statement, it stores all comments right above it and on the same line to it's right side in a `comments` property. 146 | - If a comment block is at the beginning of a code block, it is attached to that code block. 147 | - Comments not followed by any statement in a code block are attached as `trailingComments` to that code block. 148 | 149 | In this example, the comments tell to which statement they are attached: 150 | 151 | ```javascript 152 | // Attached to the variable declaration just below 153 | const point = { 154 | // Attached to the property definition just below 155 | x: 0, 156 | y: 0, // Attached to the property definition on its left 157 | } 158 | /* 159 | Attached to the function declaration just below. 160 | */ 161 | function add(a, b) { 162 | /* 163 | Attached to the function body because it is the first comment block. 164 | */ 165 | return a + b // Attached to the return statement on its left 166 | // Trailing comment attached as such to the function body 167 | } 168 | // Trailing comment attached as such to the program body 169 | ``` 170 | -------------------------------------------------------------------------------- /src/defaultTraveler.js: -------------------------------------------------------------------------------- 1 | let ForInStatement, 2 | FunctionDeclaration, 3 | RestElement, 4 | BinaryExpression, 5 | ArrayExpression, 6 | Block, 7 | MethodDefinition 8 | 9 | const ignore = Function.prototype 10 | 11 | class Found { 12 | constructor(node, state) { 13 | this.node = node 14 | this.state = state 15 | } 16 | } 17 | 18 | export const defaultTraveler = { 19 | go(node, state) { 20 | /* 21 | Starts travelling through the specified AST `node` with the provided `state`. 22 | This method is recursively called by each node handler. 23 | */ 24 | if (this[node.type]) { 25 | this[node.type](node, state) 26 | } 27 | }, 28 | find(predicate, node, state) { 29 | /* 30 | Returns { node, state } for which `predicate(node, state)` returns truthy, 31 | starting at the specified AST `node` and with the provided `state`. 32 | Otherwise, returns `undefined`. 33 | */ 34 | const finder = Object.create(this) 35 | finder.go = function (node, state) { 36 | if (predicate(node, state)) { 37 | throw new Found(node, state) 38 | } 39 | this[node.type](node, state) 40 | } 41 | try { 42 | finder.go(node, state) 43 | } catch (error) { 44 | if (error instanceof Found) { 45 | return error 46 | } else { 47 | throw error 48 | } 49 | } 50 | }, 51 | makeChild(properties = {}) { 52 | /* 53 | Returns a custom AST traveler that inherits from `this` traveler with its own provided `properties` and the property `super` that points to the parent traveler object. 54 | */ 55 | const traveler = Object.create(this) 56 | traveler.super = this 57 | for (let key in properties) { 58 | traveler[key] = properties[key] 59 | } 60 | return traveler 61 | }, 62 | Program: (Block = function (node, state) { 63 | const { body } = node 64 | if (body != null) { 65 | const { length } = body 66 | for (let i = 0; i < length; i++) { 67 | this.go(body[i], state) 68 | } 69 | } 70 | }), 71 | BlockStatement: Block, 72 | StaticBlock: Block, 73 | EmptyStatement: ignore, 74 | ExpressionStatement(node, state) { 75 | this.go(node.expression, state) 76 | }, 77 | IfStatement(node, state) { 78 | this.go(node.test, state) 79 | this.go(node.consequent, state) 80 | if (node.alternate != null) { 81 | this.go(node.alternate, state) 82 | } 83 | }, 84 | LabeledStatement(node, state) { 85 | this.go(node.label, state) 86 | this.go(node.body, state) 87 | }, 88 | BreakStatement(node, state) { 89 | if (node.label) { 90 | this.go(node.label, state) 91 | } 92 | }, 93 | ContinueStatement(node, state) { 94 | if (node.label) { 95 | this.go(node.label, state) 96 | } 97 | }, 98 | WithStatement(node, state) { 99 | this.go(node.object, state) 100 | this.go(node.body, state) 101 | }, 102 | SwitchStatement(node, state) { 103 | this.go(node.discriminant, state) 104 | const { cases } = node, 105 | { length } = cases 106 | for (let i = 0; i < length; i++) { 107 | this.go(cases[i], state) 108 | } 109 | }, 110 | SwitchCase(node, state) { 111 | if (node.test != null) { 112 | this.go(node.test, state) 113 | } 114 | const statements = node.consequent, 115 | { length } = statements 116 | for (let i = 0; i < length; i++) { 117 | this.go(statements[i], state) 118 | } 119 | }, 120 | ReturnStatement(node, state) { 121 | if (node.argument) { 122 | this.go(node.argument, state) 123 | } 124 | }, 125 | ThrowStatement(node, state) { 126 | this.go(node.argument, state) 127 | }, 128 | TryStatement(node, state) { 129 | this.go(node.block, state) 130 | if (node.handler != null) { 131 | this.go(node.handler, state) 132 | } 133 | if (node.finalizer != null) { 134 | this.go(node.finalizer, state) 135 | } 136 | }, 137 | CatchClause(node, state) { 138 | if (node.param != null) { 139 | this.go(node.param, state) 140 | } 141 | this.go(node.body, state) 142 | }, 143 | WhileStatement(node, state) { 144 | this.go(node.test, state) 145 | this.go(node.body, state) 146 | }, 147 | DoWhileStatement(node, state) { 148 | this.go(node.body, state) 149 | this.go(node.test, state) 150 | }, 151 | ForStatement(node, state) { 152 | if (node.init != null) { 153 | this.go(node.init, state) 154 | } 155 | if (node.test != null) { 156 | this.go(node.test, state) 157 | } 158 | if (node.update != null) { 159 | this.go(node.update, state) 160 | } 161 | this.go(node.body, state) 162 | }, 163 | ForInStatement: (ForInStatement = function (node, state) { 164 | this.go(node.left, state) 165 | this.go(node.right, state) 166 | this.go(node.body, state) 167 | }), 168 | DebuggerStatement: ignore, 169 | FunctionDeclaration: (FunctionDeclaration = function (node, state) { 170 | if (node.id != null) { 171 | this.go(node.id, state) 172 | } 173 | const { params } = node 174 | if (params != null) { 175 | for (let i = 0, { length } = params; i < length; i++) { 176 | this.go(params[i], state) 177 | } 178 | } 179 | this.go(node.body, state) 180 | }), 181 | VariableDeclaration(node, state) { 182 | const { declarations } = node, 183 | { length } = declarations 184 | for (let i = 0; i < length; i++) { 185 | this.go(declarations[i], state) 186 | } 187 | }, 188 | VariableDeclarator(node, state) { 189 | this.go(node.id, state) 190 | if (node.init != null) { 191 | this.go(node.init, state) 192 | } 193 | }, 194 | ArrowFunctionExpression(node, state) { 195 | const { params } = node 196 | if (params != null) { 197 | for (let i = 0, { length } = params; i < length; i++) { 198 | this.go(params[i], state) 199 | } 200 | } 201 | this.go(node.body, state) 202 | }, 203 | ThisExpression: ignore, 204 | ArrayExpression: (ArrayExpression = function (node, state) { 205 | const { elements } = node, 206 | { length } = elements 207 | for (let i = 0; i < length; i++) { 208 | let element = elements[i] 209 | if (element != null) { 210 | this.go(elements[i], state) 211 | } 212 | } 213 | }), 214 | ObjectExpression(node, state) { 215 | const { properties } = node, 216 | { length } = properties 217 | for (let i = 0; i < length; i++) { 218 | this.go(properties[i], state) 219 | } 220 | }, 221 | Property(node, state) { 222 | this.go(node.key, state) 223 | if (node.value != null) { 224 | this.go(node.value, state) 225 | } 226 | }, 227 | FunctionExpression: FunctionDeclaration, 228 | SequenceExpression(node, state) { 229 | const { expressions } = node, 230 | { length } = expressions 231 | for (let i = 0; i < length; i++) { 232 | this.go(expressions[i], state) 233 | } 234 | }, 235 | UnaryExpression(node, state) { 236 | this.go(node.argument, state) 237 | }, 238 | UpdateExpression(node, state) { 239 | this.go(node.argument, state) 240 | }, 241 | AssignmentExpression(node, state) { 242 | this.go(node.left, state) 243 | this.go(node.right, state) 244 | }, 245 | BinaryExpression: (BinaryExpression = function (node, state) { 246 | this.go(node.left, state) 247 | this.go(node.right, state) 248 | }), 249 | LogicalExpression: BinaryExpression, 250 | ConditionalExpression(node, state) { 251 | this.go(node.test, state) 252 | this.go(node.consequent, state) 253 | this.go(node.alternate, state) 254 | }, 255 | NewExpression(node, state) { 256 | this.CallExpression(node, state) 257 | }, 258 | CallExpression(node, state) { 259 | this.go(node.callee, state) 260 | const args = node['arguments'], 261 | { length } = args 262 | for (let i = 0; i < length; i++) { 263 | this.go(args[i], state) 264 | } 265 | }, 266 | MemberExpression(node, state) { 267 | this.go(node.object, state) 268 | this.go(node.property, state) 269 | }, 270 | Identifier: ignore, 271 | PrivateIdentifier: ignore, 272 | Literal: ignore, 273 | ForOfStatement: ForInStatement, 274 | ClassDeclaration(node, state) { 275 | if (node.id) { 276 | this.go(node.id, state) 277 | } 278 | if (node.superClass) { 279 | this.go(node.superClass, state) 280 | } 281 | this.go(node.body, state) 282 | }, 283 | ClassBody: Block, 284 | ImportDeclaration(node, state) { 285 | const { specifiers } = node, 286 | { length } = specifiers 287 | for (let i = 0; i < length; i++) { 288 | this.go(specifiers[i], state) 289 | } 290 | this.go(node.source, state) 291 | }, 292 | ImportNamespaceSpecifier(node, state) { 293 | this.go(node.local, state) 294 | }, 295 | ImportDefaultSpecifier(node, state) { 296 | this.go(node.local, state) 297 | }, 298 | ImportSpecifier(node, state) { 299 | this.go(node.imported, state) 300 | this.go(node.local, state) 301 | }, 302 | ExportDefaultDeclaration(node, state) { 303 | this.go(node.declaration, state) 304 | }, 305 | ExportNamedDeclaration(node, state) { 306 | if (node.declaration) { 307 | this.go(node.declaration, state) 308 | } 309 | const { specifiers } = node, 310 | { length } = specifiers 311 | for (let i = 0; i < length; i++) { 312 | this.go(specifiers[i], state) 313 | } 314 | if (node.source) { 315 | this.go(node.source, state) 316 | } 317 | }, 318 | ExportSpecifier(node, state) { 319 | this.go(node.local, state) 320 | this.go(node.exported, state) 321 | }, 322 | ExportAllDeclaration(node, state) { 323 | this.go(node.source, state) 324 | }, 325 | MethodDefinition: (MethodDefinition = function (node, state) { 326 | this.go(node.key, state) 327 | this.go(node.value, state) 328 | }), 329 | PropertyDefinition: MethodDefinition, 330 | ClassExpression(node, state) { 331 | this.ClassDeclaration(node, state) 332 | }, 333 | Super: ignore, 334 | RestElement: (RestElement = function (node, state) { 335 | this.go(node.argument, state) 336 | }), 337 | SpreadElement: RestElement, 338 | YieldExpression(node, state) { 339 | if (node.argument) { 340 | this.go(node.argument, state) 341 | } 342 | }, 343 | TaggedTemplateExpression(node, state) { 344 | this.go(node.tag, state) 345 | this.go(node.quasi, state) 346 | }, 347 | TemplateLiteral(node, state) { 348 | const { quasis, expressions } = node 349 | for (let i = 0, { length } = expressions; i < length; i++) { 350 | this.go(expressions[i], state) 351 | } 352 | for (let i = 0, { length } = quasis; i < length; i++) { 353 | this.go(quasis[i], state) 354 | } 355 | }, 356 | TemplateElement: ignore, 357 | ObjectPattern(node, state) { 358 | const { properties } = node, 359 | { length } = properties 360 | for (let i = 0; i < length; i++) { 361 | this.go(properties[i], state) 362 | } 363 | }, 364 | ArrayPattern: ArrayExpression, 365 | AssignmentPattern(node, state) { 366 | this.go(node.left, state) 367 | this.go(node.right, state) 368 | }, 369 | MetaProperty(node, state) { 370 | this.go(node.meta, state) 371 | this.go(node.property, state) 372 | }, 373 | AwaitExpression(node, state) { 374 | this.go(node.argument, state) 375 | }, 376 | } 377 | -------------------------------------------------------------------------------- /src/tests/snapshots/attachComments.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `src/tests/attachComments.js` 2 | 3 | The actual snapshot is saved in `attachComments.js.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## Comments attachment 8 | 9 | > Snapshot 1 10 | 11 | [ 12 | { 13 | end: 27, 14 | range: [ 15 | 2, 16 | 27, 17 | ], 18 | start: 2, 19 | type: 'MultiLine', 20 | value: `␊ 21 | Module documentation.␊ 22 | `, 23 | }, 24 | { 25 | end: 70, 26 | range: [ 27 | 31, 28 | 70, 29 | ], 30 | start: 31, 31 | type: 'MultiLine', 32 | value: `␊ 33 | Documentation for variable `point`.␊ 34 | `, 35 | }, 36 | { 37 | end: 146, 38 | range: [ 39 | 91, 40 | 146, 41 | ], 42 | start: 91, 43 | type: 'MultiLine', 44 | value: ' This is a block comment inside an object expression ', 45 | }, 46 | { 47 | end: 187, 48 | range: [ 49 | 151, 50 | 187, 51 | ], 52 | start: 151, 53 | type: 'SingleLine', 54 | value: ` This comment is for the x property␊ 55 | `, 56 | }, 57 | { 58 | end: 236, 59 | range: [ 60 | 199, 61 | 236, 62 | ], 63 | start: 199, 64 | type: 'SingleLine', 65 | value: ` …and this one is for the y property␊ 66 | `, 67 | }, 68 | { 69 | end: 266, 70 | range: [ 71 | 248, 72 | 266, 73 | ], 74 | start: 248, 75 | type: 'SingleLine', 76 | value: ` Trailing comment␊ 77 | `, 78 | }, 79 | { 80 | end: 315, 81 | range: [ 82 | 283, 83 | 315, 84 | ], 85 | start: 283, 86 | type: 'MultiLine', 87 | value: `␊ 88 | Documentation for class A.␊ 89 | `, 90 | }, 91 | { 92 | end: 398, 93 | range: [ 94 | 342, 95 | 398, 96 | ], 97 | start: 342, 98 | type: 'MultiLine', 99 | value: `␊ 100 | Document for method `m` with params `x` and `y`.␊ 101 | `, 102 | }, 103 | ] 104 | 105 | > Snapshot 2 106 | 107 | { 108 | body: [ 109 | { 110 | declarations: [ 111 | { 112 | end: 267, 113 | id: { 114 | end: 82, 115 | name: 'point', 116 | range: [ 117 | 77, 118 | 82, 119 | ], 120 | start: 77, 121 | type: 'Identifier', 122 | }, 123 | init: { 124 | comments: [ 125 | { 126 | end: 146, 127 | range: [ 128 | 91, 129 | 146, 130 | ], 131 | start: 91, 132 | type: 'MultiLine', 133 | value: ' This is a block comment inside an object expression ', 134 | }, 135 | ], 136 | end: 267, 137 | properties: [ 138 | { 139 | comments: [ 140 | { 141 | end: 187, 142 | range: [ 143 | 151, 144 | 187, 145 | ], 146 | start: 151, 147 | type: 'SingleLine', 148 | value: ` This comment is for the x property␊ 149 | `, 150 | }, 151 | ], 152 | computed: false, 153 | end: 193, 154 | key: { 155 | end: 190, 156 | name: 'x', 157 | range: [ 158 | 189, 159 | 190, 160 | ], 161 | start: 189, 162 | type: 'Identifier', 163 | }, 164 | kind: 'init', 165 | method: false, 166 | range: [ 167 | 189, 168 | 193, 169 | ], 170 | shorthand: false, 171 | start: 189, 172 | type: 'Property', 173 | value: { 174 | end: 193, 175 | range: [ 176 | 192, 177 | 193, 178 | ], 179 | start: 192, 180 | type: 'Literal', 181 | value: 0, 182 | }, 183 | }, 184 | { 185 | comments: [ 186 | { 187 | end: 236, 188 | range: [ 189 | 199, 190 | 236, 191 | ], 192 | start: 199, 193 | type: 'SingleLine', 194 | value: ` …and this one is for the y property␊ 195 | `, 196 | }, 197 | ], 198 | computed: false, 199 | end: 242, 200 | key: { 201 | end: 239, 202 | name: 'y', 203 | range: [ 204 | 238, 205 | 239, 206 | ], 207 | start: 238, 208 | type: 'Identifier', 209 | }, 210 | kind: 'init', 211 | method: false, 212 | range: [ 213 | 238, 214 | 242, 215 | ], 216 | shorthand: false, 217 | start: 238, 218 | type: 'Property', 219 | value: { 220 | end: 242, 221 | range: [ 222 | 241, 223 | 242, 224 | ], 225 | start: 241, 226 | type: 'Literal', 227 | value: 1, 228 | }, 229 | }, 230 | ], 231 | range: [ 232 | 85, 233 | 267, 234 | ], 235 | start: 85, 236 | trailingComments: [ 237 | { 238 | end: 266, 239 | range: [ 240 | 248, 241 | 266, 242 | ], 243 | start: 248, 244 | type: 'SingleLine', 245 | value: ` Trailing comment␊ 246 | `, 247 | }, 248 | ], 249 | type: 'ObjectExpression', 250 | }, 251 | range: [ 252 | 77, 253 | 267, 254 | ], 255 | start: 77, 256 | type: 'VariableDeclarator', 257 | }, 258 | ], 259 | end: 267, 260 | kind: 'const', 261 | range: [ 262 | 71, 263 | 267, 264 | ], 265 | start: 71, 266 | type: 'VariableDeclaration', 267 | }, 268 | { 269 | body: { 270 | body: [ 271 | { 272 | computed: false, 273 | decorators: [], 274 | end: 402, 275 | key: { 276 | end: 320, 277 | name: 'm', 278 | range: [ 279 | 319, 280 | 320, 281 | ], 282 | start: 319, 283 | type: 'Identifier', 284 | }, 285 | kind: 'method', 286 | range: [ 287 | 319, 288 | 402, 289 | ], 290 | start: 319, 291 | static: false, 292 | type: 'MethodDefinition', 293 | value: { 294 | async: false, 295 | body: { 296 | body: [], 297 | comments: [ 298 | { 299 | end: 398, 300 | range: [ 301 | 342, 302 | 398, 303 | ], 304 | start: 342, 305 | type: 'MultiLine', 306 | value: `␊ 307 | Document for method `m` with params `x` and `y`.␊ 308 | `, 309 | }, 310 | ], 311 | end: 402, 312 | range: [ 313 | 334, 314 | 402, 315 | ], 316 | start: 334, 317 | type: 'BlockStatement', 318 | }, 319 | end: 402, 320 | generator: false, 321 | id: null, 322 | params: [ 323 | { 324 | end: 322, 325 | name: 'x', 326 | range: [ 327 | 321, 328 | 322, 329 | ], 330 | start: 321, 331 | type: 'Identifier', 332 | }, 333 | { 334 | end: 332, 335 | left: { 336 | end: 325, 337 | name: 'y', 338 | range: [ 339 | 324, 340 | 325, 341 | ], 342 | start: 324, 343 | type: 'Identifier', 344 | }, 345 | range: [ 346 | 324, 347 | 332, 348 | ], 349 | right: { 350 | end: 332, 351 | range: [ 352 | 328, 353 | 332, 354 | ], 355 | start: 328, 356 | type: 'Literal', 357 | value: true, 358 | }, 359 | start: 324, 360 | type: 'AssignmentPattern', 361 | }, 362 | ], 363 | range: [ 364 | 320, 365 | 402, 366 | ], 367 | start: 320, 368 | type: 'FunctionExpression', 369 | }, 370 | }, 371 | ], 372 | comments: [ 373 | { 374 | end: 315, 375 | range: [ 376 | 283, 377 | 315, 378 | ], 379 | start: 283, 380 | type: 'MultiLine', 381 | value: `␊ 382 | Documentation for class A.␊ 383 | `, 384 | }, 385 | ], 386 | end: 404, 387 | range: [ 388 | 277, 389 | 404, 390 | ], 391 | start: 277, 392 | type: 'ClassBody', 393 | }, 394 | decorators: [], 395 | end: 404, 396 | id: { 397 | end: 276, 398 | name: 'A', 399 | range: [ 400 | 275, 401 | 276, 402 | ], 403 | start: 275, 404 | type: 'Identifier', 405 | }, 406 | range: [ 407 | 269, 408 | 404, 409 | ], 410 | start: 269, 411 | superClass: null, 412 | type: 'ClassDeclaration', 413 | }, 414 | ], 415 | comments: [ 416 | { 417 | end: 27, 418 | range: [ 419 | 2, 420 | 27, 421 | ], 422 | start: 2, 423 | type: 'MultiLine', 424 | value: `␊ 425 | Module documentation.␊ 426 | `, 427 | }, 428 | { 429 | end: 70, 430 | range: [ 431 | 31, 432 | 70, 433 | ], 434 | start: 31, 435 | type: 'MultiLine', 436 | value: `␊ 437 | Documentation for variable `point`.␊ 438 | `, 439 | }, 440 | ], 441 | end: 405, 442 | range: [ 443 | 0, 444 | 405, 445 | ], 446 | sourceType: 'module', 447 | start: 0, 448 | type: 'Program', 449 | } 450 | -------------------------------------------------------------------------------- /src/tests/snapshots/defaultTraveler.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `src/tests/defaultTraveler.js` 2 | 3 | The actual snapshot is saved in `defaultTraveler.js.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## Default traveler 8 | 9 | > Snapshot 1 10 | 11 | [ 12 | 'Root', 13 | [ 14 | [ 15 | 'Program', 16 | [ 17 | [ 18 | 'ImportDeclaration', 19 | [ 20 | [ 21 | 'ImportDefaultSpecifier', 22 | [ 23 | [ 24 | 'Identifier', 25 | [], 26 | ], 27 | ], 28 | ], 29 | [ 30 | 'Literal', 31 | [], 32 | ], 33 | ], 34 | ], 35 | [ 36 | 'ImportDeclaration', 37 | [ 38 | [ 39 | 'ImportDefaultSpecifier', 40 | [ 41 | [ 42 | 'Identifier', 43 | [], 44 | ], 45 | ], 46 | ], 47 | [ 48 | 'ImportSpecifier', 49 | [ 50 | [ 51 | 'Identifier', 52 | [], 53 | ], 54 | [ 55 | 'Identifier', 56 | [], 57 | ], 58 | ], 59 | ], 60 | [ 61 | 'Literal', 62 | [], 63 | ], 64 | ], 65 | ], 66 | [ 67 | 'ImportDeclaration', 68 | [ 69 | [ 70 | 'ImportSpecifier', 71 | [ 72 | [ 73 | 'Identifier', 74 | [], 75 | ], 76 | [ 77 | 'Identifier', 78 | [], 79 | ], 80 | ], 81 | ], 82 | [ 83 | 'Literal', 84 | [], 85 | ], 86 | ], 87 | ], 88 | [ 89 | 'ImportDeclaration', 90 | [ 91 | [ 92 | 'ImportNamespaceSpecifier', 93 | [ 94 | [ 95 | 'Identifier', 96 | [], 97 | ], 98 | ], 99 | ], 100 | [ 101 | 'Literal', 102 | [], 103 | ], 104 | ], 105 | ], 106 | [ 107 | 'ExportNamedDeclaration', 108 | [ 109 | [ 110 | 'ExportSpecifier', 111 | [ 112 | [ 113 | 'Identifier', 114 | [], 115 | ], 116 | [ 117 | 'Identifier', 118 | [], 119 | ], 120 | ], 121 | ], 122 | [ 123 | 'Literal', 124 | [], 125 | ], 126 | ], 127 | ], 128 | [ 129 | 'ExportNamedDeclaration', 130 | [ 131 | [ 132 | 'VariableDeclaration', 133 | [ 134 | [ 135 | 'VariableDeclarator', 136 | [ 137 | [ 138 | 'Identifier', 139 | [], 140 | ], 141 | [ 142 | 'Identifier', 143 | [], 144 | ], 145 | ], 146 | ], 147 | ], 148 | ], 149 | ], 150 | ], 151 | [ 152 | 'ExportAllDeclaration', 153 | [ 154 | [ 155 | 'Literal', 156 | [], 157 | ], 158 | ], 159 | ], 160 | [ 161 | 'ExportDefaultDeclaration', 162 | [ 163 | [ 164 | 'ClassDeclaration', 165 | [ 166 | [ 167 | 'Identifier', 168 | [], 169 | ], 170 | [ 171 | 'ClassBody', 172 | [ 173 | [ 174 | 'MethodDefinition', 175 | [ 176 | [ 177 | 'Identifier', 178 | [], 179 | ], 180 | [ 181 | 'FunctionExpression', 182 | [ 183 | [ 184 | 'BlockStatement', 185 | [ 186 | [ 187 | 'ExpressionStatement', 188 | [ 189 | [ 190 | 'AssignmentExpression', 191 | [ 192 | [ 193 | 'MemberExpression', 194 | [ 195 | [ 196 | 'ThisExpression', 197 | [], 198 | ], 199 | [ 200 | 'Identifier', 201 | [], 202 | ], 203 | ], 204 | ], 205 | [ 206 | 'ArrowFunctionExpression', 207 | [ 208 | [ 209 | 'BlockStatement', 210 | [], 211 | ], 212 | ], 213 | ], 214 | ], 215 | ], 216 | ], 217 | ], 218 | [ 219 | 'ExpressionStatement', 220 | [ 221 | [ 222 | 'AssignmentExpression', 223 | [ 224 | [ 225 | 'MemberExpression', 226 | [ 227 | [ 228 | 'ThisExpression', 229 | [], 230 | ], 231 | [ 232 | 'Identifier', 233 | [], 234 | ], 235 | ], 236 | ], 237 | [ 238 | 'ArrowFunctionExpression', 239 | [ 240 | [ 241 | 'Identifier', 242 | [], 243 | ], 244 | [ 245 | 'ObjectExpression', 246 | [], 247 | ], 248 | ], 249 | ], 250 | ], 251 | ], 252 | ], 253 | ], 254 | ], 255 | ], 256 | ], 257 | ], 258 | ], 259 | ], 260 | [ 261 | 'MethodDefinition', 262 | [ 263 | [ 264 | 'Identifier', 265 | [], 266 | ], 267 | [ 268 | 'FunctionExpression', 269 | [ 270 | [ 271 | 'BlockStatement', 272 | [], 273 | ], 274 | ], 275 | ], 276 | ], 277 | ], 278 | [ 279 | 'MethodDefinition', 280 | [ 281 | [ 282 | 'Identifier', 283 | [], 284 | ], 285 | [ 286 | 'FunctionExpression', 287 | [ 288 | [ 289 | 'BlockStatement', 290 | [ 291 | [ 292 | 'ExpressionStatement', 293 | [ 294 | [ 295 | 'MetaProperty', 296 | [ 297 | [ 298 | 'Identifier', 299 | [], 300 | ], 301 | [ 302 | 'Identifier', 303 | [], 304 | ], 305 | ], 306 | ], 307 | ], 308 | ], 309 | [ 310 | 'ExpressionStatement', 311 | [ 312 | [ 313 | 'AssignmentExpression', 314 | [ 315 | [ 316 | 'MemberExpression', 317 | [ 318 | [ 319 | 'ThisExpression', 320 | [], 321 | ], 322 | [ 323 | 'Identifier', 324 | [], 325 | ], 326 | ], 327 | ], 328 | [ 329 | 'Literal', 330 | [], 331 | ], 332 | ], 333 | ], 334 | ], 335 | ], 336 | ], 337 | ], 338 | ], 339 | ], 340 | ], 341 | ], 342 | ], 343 | ], 344 | ], 345 | ], 346 | ], 347 | ], 348 | [ 349 | 'VariableDeclaration', 350 | [ 351 | [ 352 | 'VariableDeclarator', 353 | [ 354 | [ 355 | 'Identifier', 356 | [], 357 | ], 358 | [ 359 | 'ClassExpression', 360 | [ 361 | [ 362 | 'Identifier', 363 | [], 364 | ], 365 | [ 366 | 'ClassBody', 367 | [], 368 | ], 369 | ], 370 | ], 371 | ], 372 | ], 373 | ], 374 | ], 375 | [ 376 | 'FunctionDeclaration', 377 | [ 378 | [ 379 | 'Identifier', 380 | [], 381 | ], 382 | [ 383 | 'Identifier', 384 | [], 385 | ], 386 | [ 387 | 'Identifier', 388 | [], 389 | ], 390 | [ 391 | 'AssignmentPattern', 392 | [ 393 | [ 394 | 'Identifier', 395 | [], 396 | ], 397 | [ 398 | 'Literal', 399 | [], 400 | ], 401 | ], 402 | ], 403 | [ 404 | 'BlockStatement', 405 | [ 406 | [ 407 | 'VariableDeclaration', 408 | [ 409 | [ 410 | 'VariableDeclarator', 411 | [ 412 | [ 413 | 'Identifier', 414 | [], 415 | ], 416 | [ 417 | 'Identifier', 418 | [], 419 | ], 420 | ], 421 | ], 422 | ], 423 | ], 424 | [ 425 | 'VariableDeclaration', 426 | [ 427 | [ 428 | 'VariableDeclarator', 429 | [ 430 | [ 431 | 'Identifier', 432 | [], 433 | ], 434 | [ 435 | 'Identifier', 436 | [], 437 | ], 438 | ], 439 | ], 440 | ], 441 | ], 442 | [ 443 | 'VariableDeclaration', 444 | [ 445 | [ 446 | 'VariableDeclarator', 447 | [ 448 | [ 449 | 'Identifier', 450 | [], 451 | ], 452 | [ 453 | 'Identifier', 454 | [], 455 | ], 456 | ], 457 | ], 458 | ], 459 | ], 460 | [ 461 | 'VariableDeclaration', 462 | [ 463 | [ 464 | 'VariableDeclarator', 465 | [ 466 | [ 467 | 'ObjectPattern', 468 | [ 469 | [ 470 | 'Property', 471 | [ 472 | [ 473 | 'Identifier', 474 | [], 475 | ], 476 | [ 477 | 'Identifier', 478 | [], 479 | ], 480 | ], 481 | ], 482 | [ 483 | 'Property', 484 | [ 485 | [ 486 | 'Identifier', 487 | [], 488 | ], 489 | [ 490 | 'Identifier', 491 | [], 492 | ], 493 | ], 494 | ], 495 | [ 496 | 'Property', 497 | [ 498 | [ 499 | 'Identifier', 500 | [], 501 | ], 502 | [ 503 | 'Identifier', 504 | [], 505 | ], 506 | ], 507 | ], 508 | ], 509 | ], 510 | [ 511 | 'Identifier', 512 | [], 513 | ], 514 | ], 515 | ], 516 | ], 517 | ], 518 | [ 519 | 'VariableDeclaration', 520 | [ 521 | [ 522 | 'VariableDeclarator', 523 | [ 524 | [ 525 | 'ArrayPattern', 526 | [ 527 | [ 528 | 'Identifier', 529 | [], 530 | ], 531 | [ 532 | 'Identifier', 533 | [], 534 | ], 535 | [ 536 | 'Identifier', 537 | [], 538 | ], 539 | ], 540 | ], 541 | [ 542 | 'Identifier', 543 | [], 544 | ], 545 | ], 546 | ], 547 | ], 548 | ], 549 | [ 550 | 'ReturnStatement', 551 | [ 552 | [ 553 | 'ConditionalExpression', 554 | [ 555 | [ 556 | 'BinaryExpression', 557 | [ 558 | [ 559 | 'Identifier', 560 | [], 561 | ], 562 | [ 563 | 'Literal', 564 | [], 565 | ], 566 | ], 567 | ], 568 | [ 569 | 'Identifier', 570 | [], 571 | ], 572 | [ 573 | 'Identifier', 574 | [], 575 | ], 576 | ], 577 | ], 578 | ], 579 | ], 580 | ], 581 | ], 582 | ], 583 | ], 584 | [ 585 | 'FunctionDeclaration', 586 | [ 587 | [ 588 | 'Identifier', 589 | [], 590 | ], 591 | [ 592 | 'BlockStatement', 593 | [ 594 | [ 595 | 'ExpressionStatement', 596 | [ 597 | [ 598 | 'YieldExpression', 599 | [], 600 | ], 601 | ], 602 | ], 603 | [ 604 | 'ExpressionStatement', 605 | [ 606 | [ 607 | 'YieldExpression', 608 | [ 609 | [ 610 | 'Literal', 611 | [], 612 | ], 613 | ], 614 | ], 615 | ], 616 | ], 617 | ], 618 | ], 619 | ], 620 | ], 621 | [ 622 | 'FunctionDeclaration', 623 | [ 624 | [ 625 | 'Identifier', 626 | [], 627 | ], 628 | [ 629 | 'BlockStatement', 630 | [ 631 | [ 632 | 'ReturnStatement', 633 | [ 634 | [ 635 | 'AwaitExpression', 636 | [ 637 | [ 638 | 'CallExpression', 639 | [ 640 | [ 641 | 'Identifier', 642 | [], 643 | ], 644 | ], 645 | ], 646 | ], 647 | ], 648 | ], 649 | ], 650 | ], 651 | ], 652 | ], 653 | ], 654 | [ 655 | 'FunctionDeclaration', 656 | [ 657 | [ 658 | 'Identifier', 659 | [], 660 | ], 661 | [ 662 | 'BlockStatement', 663 | [ 664 | [ 665 | 'ForOfStatement', 666 | [ 667 | [ 668 | 'VariableDeclaration', 669 | [ 670 | [ 671 | 'VariableDeclarator', 672 | [ 673 | [ 674 | 'Identifier', 675 | [], 676 | ], 677 | ], 678 | ], 679 | ], 680 | ], 681 | [ 682 | 'Identifier', 683 | [], 684 | ], 685 | [ 686 | 'BlockStatement', 687 | [], 688 | ], 689 | ], 690 | ], 691 | ], 692 | ], 693 | ], 694 | ], 695 | [ 696 | 'FunctionDeclaration', 697 | [ 698 | [ 699 | 'Identifier', 700 | [], 701 | ], 702 | [ 703 | 'BlockStatement', 704 | [ 705 | [ 706 | 'IfStatement', 707 | [ 708 | [ 709 | 'BinaryExpression', 710 | [ 711 | [ 712 | 'Identifier', 713 | [], 714 | ], 715 | [ 716 | 'Literal', 717 | [], 718 | ], 719 | ], 720 | ], 721 | [ 722 | 'BlockStatement', 723 | [ 724 | [ 725 | 'ExpressionStatement', 726 | [ 727 | [ 728 | 'CallExpression', 729 | [ 730 | [ 731 | 'Identifier', 732 | [], 733 | ], 734 | [ 735 | 'SpreadElement', 736 | [ 737 | [ 738 | 'Identifier', 739 | [], 740 | ], 741 | ], 742 | ], 743 | ], 744 | ], 745 | ], 746 | ], 747 | ], 748 | ], 749 | [ 750 | 'IfStatement', 751 | [ 752 | [ 753 | 'BinaryExpression', 754 | [ 755 | [ 756 | 'Identifier', 757 | [], 758 | ], 759 | [ 760 | 'Literal', 761 | [], 762 | ], 763 | ], 764 | ], 765 | [ 766 | 'BlockStatement', 767 | [ 768 | [ 769 | 'ExpressionStatement', 770 | [ 771 | [ 772 | 'CallExpression', 773 | [ 774 | [ 775 | 'Identifier', 776 | [], 777 | ], 778 | [ 779 | 'Literal', 780 | [], 781 | ], 782 | ], 783 | ], 784 | ], 785 | ], 786 | ], 787 | ], 788 | [ 789 | 'BlockStatement', 790 | [ 791 | [ 792 | 'ExpressionStatement', 793 | [ 794 | [ 795 | 'CallExpression', 796 | [ 797 | [ 798 | 'Identifier', 799 | [], 800 | ], 801 | [ 802 | 'Literal', 803 | [], 804 | ], 805 | ], 806 | ], 807 | ], 808 | ], 809 | ], 810 | ], 811 | ], 812 | ], 813 | ], 814 | ], 815 | [ 816 | 'IfStatement', 817 | [ 818 | [ 819 | 'BinaryExpression', 820 | [ 821 | [ 822 | 'Identifier', 823 | [], 824 | ], 825 | [ 826 | 'Literal', 827 | [], 828 | ], 829 | ], 830 | ], 831 | [ 832 | 'BlockStatement', 833 | [], 834 | ], 835 | ], 836 | ], 837 | [ 838 | 'LabeledStatement', 839 | [ 840 | [ 841 | 'Identifier', 842 | [], 843 | ], 844 | [ 845 | 'SwitchStatement', 846 | [ 847 | [ 848 | 'Identifier', 849 | [], 850 | ], 851 | [ 852 | 'SwitchCase', 853 | [ 854 | [ 855 | 'Literal', 856 | [], 857 | ], 858 | [ 859 | 'BreakStatement', 860 | [ 861 | [ 862 | 'Identifier', 863 | [], 864 | ], 865 | ], 866 | ], 867 | ], 868 | ], 869 | [ 870 | 'SwitchCase', 871 | [ 872 | [ 873 | 'BreakStatement', 874 | [], 875 | ], 876 | ], 877 | ], 878 | ], 879 | ], 880 | ], 881 | ], 882 | [ 883 | 'ReturnStatement', 884 | [], 885 | ], 886 | ], 887 | ], 888 | ], 889 | ], 890 | [ 891 | 'FunctionDeclaration', 892 | [ 893 | [ 894 | 'Identifier', 895 | [], 896 | ], 897 | [ 898 | 'BlockStatement', 899 | [ 900 | [ 901 | 'LabeledStatement', 902 | [ 903 | [ 904 | 'Identifier', 905 | [], 906 | ], 907 | [ 908 | 'ForStatement', 909 | [ 910 | [ 911 | 'VariableDeclaration', 912 | [ 913 | [ 914 | 'VariableDeclarator', 915 | [ 916 | [ 917 | 'Identifier', 918 | [], 919 | ], 920 | [ 921 | 'Literal', 922 | [], 923 | ], 924 | ], 925 | ], 926 | ], 927 | ], 928 | [ 929 | 'BinaryExpression', 930 | [ 931 | [ 932 | 'Identifier', 933 | [], 934 | ], 935 | [ 936 | 'MemberExpression', 937 | [ 938 | [ 939 | 'Identifier', 940 | [], 941 | ], 942 | [ 943 | 'Identifier', 944 | [], 945 | ], 946 | ], 947 | ], 948 | ], 949 | ], 950 | [ 951 | 'UpdateExpression', 952 | [ 953 | [ 954 | 'Identifier', 955 | [], 956 | ], 957 | ], 958 | ], 959 | [ 960 | 'BlockStatement', 961 | [ 962 | [ 963 | 'IfStatement', 964 | [ 965 | [ 966 | 'BinaryExpression', 967 | [ 968 | [ 969 | 'Identifier', 970 | [], 971 | ], 972 | [ 973 | 'Literal', 974 | [], 975 | ], 976 | ], 977 | ], 978 | [ 979 | 'BlockStatement', 980 | [ 981 | [ 982 | 'ContinueStatement', 983 | [ 984 | [ 985 | 'Identifier', 986 | [], 987 | ], 988 | ], 989 | ], 990 | ], 991 | ], 992 | [ 993 | 'BlockStatement', 994 | [ 995 | [ 996 | 'ContinueStatement', 997 | [], 998 | ], 999 | ], 1000 | ], 1001 | ], 1002 | ], 1003 | ], 1004 | ], 1005 | ], 1006 | ], 1007 | ], 1008 | ], 1009 | [ 1010 | 'ForStatement', 1011 | [ 1012 | [ 1013 | 'BlockStatement', 1014 | [], 1015 | ], 1016 | ], 1017 | ], 1018 | [ 1019 | 'ForInStatement', 1020 | [ 1021 | [ 1022 | 'VariableDeclaration', 1023 | [ 1024 | [ 1025 | 'VariableDeclarator', 1026 | [ 1027 | [ 1028 | 'Identifier', 1029 | [], 1030 | ], 1031 | ], 1032 | ], 1033 | ], 1034 | ], 1035 | [ 1036 | 'Identifier', 1037 | [], 1038 | ], 1039 | [ 1040 | 'BlockStatement', 1041 | [], 1042 | ], 1043 | ], 1044 | ], 1045 | [ 1046 | 'ForOfStatement', 1047 | [ 1048 | [ 1049 | 'VariableDeclaration', 1050 | [ 1051 | [ 1052 | 'VariableDeclarator', 1053 | [ 1054 | [ 1055 | 'Identifier', 1056 | [], 1057 | ], 1058 | ], 1059 | ], 1060 | ], 1061 | ], 1062 | [ 1063 | 'Identifier', 1064 | [], 1065 | ], 1066 | [ 1067 | 'BlockStatement', 1068 | [], 1069 | ], 1070 | ], 1071 | ], 1072 | [ 1073 | 'WhileStatement', 1074 | [ 1075 | [ 1076 | 'BinaryExpression', 1077 | [ 1078 | [ 1079 | 'Identifier', 1080 | [], 1081 | ], 1082 | [ 1083 | 'Literal', 1084 | [], 1085 | ], 1086 | ], 1087 | ], 1088 | [ 1089 | 'BlockStatement', 1090 | [], 1091 | ], 1092 | ], 1093 | ], 1094 | [ 1095 | 'DoWhileStatement', 1096 | [ 1097 | [ 1098 | 'BlockStatement', 1099 | [], 1100 | ], 1101 | [ 1102 | 'BinaryExpression', 1103 | [ 1104 | [ 1105 | 'Identifier', 1106 | [], 1107 | ], 1108 | [ 1109 | 'Literal', 1110 | [], 1111 | ], 1112 | ], 1113 | ], 1114 | ], 1115 | ], 1116 | ], 1117 | ], 1118 | ], 1119 | ], 1120 | [ 1121 | 'FunctionDeclaration', 1122 | [ 1123 | [ 1124 | 'Identifier', 1125 | [], 1126 | ], 1127 | [ 1128 | 'BlockStatement', 1129 | [ 1130 | [ 1131 | 'TryStatement', 1132 | [ 1133 | [ 1134 | 'BlockStatement', 1135 | [ 1136 | [ 1137 | 'ThrowStatement', 1138 | [ 1139 | [ 1140 | 'NewExpression', 1141 | [ 1142 | [ 1143 | 'Identifier', 1144 | [], 1145 | ], 1146 | ], 1147 | ], 1148 | ], 1149 | ], 1150 | ], 1151 | ], 1152 | [ 1153 | 'CatchClause', 1154 | [ 1155 | [ 1156 | 'Identifier', 1157 | [], 1158 | ], 1159 | [ 1160 | 'BlockStatement', 1161 | [ 1162 | [ 1163 | 'ExpressionStatement', 1164 | [ 1165 | [ 1166 | 'CallExpression', 1167 | [ 1168 | [ 1169 | 'Identifier', 1170 | [], 1171 | ], 1172 | [ 1173 | 'Identifier', 1174 | [], 1175 | ], 1176 | ], 1177 | ], 1178 | ], 1179 | ], 1180 | ], 1181 | ], 1182 | ], 1183 | ], 1184 | [ 1185 | 'BlockStatement', 1186 | [ 1187 | [ 1188 | 'ExpressionStatement', 1189 | [ 1190 | [ 1191 | 'CallExpression', 1192 | [ 1193 | [ 1194 | 'Identifier', 1195 | [], 1196 | ], 1197 | [ 1198 | 'Literal', 1199 | [], 1200 | ], 1201 | ], 1202 | ], 1203 | ], 1204 | ], 1205 | ], 1206 | ], 1207 | ], 1208 | ], 1209 | [ 1210 | 'TryStatement', 1211 | [ 1212 | [ 1213 | 'BlockStatement', 1214 | [], 1215 | ], 1216 | [ 1217 | 'CatchClause', 1218 | [ 1219 | [ 1220 | 'Identifier', 1221 | [], 1222 | ], 1223 | [ 1224 | 'BlockStatement', 1225 | [], 1226 | ], 1227 | ], 1228 | ], 1229 | ], 1230 | ], 1231 | [ 1232 | 'TryStatement', 1233 | [ 1234 | [ 1235 | 'BlockStatement', 1236 | [], 1237 | ], 1238 | [ 1239 | 'CatchClause', 1240 | [ 1241 | [ 1242 | 'BlockStatement', 1243 | [], 1244 | ], 1245 | ], 1246 | ], 1247 | ], 1248 | ], 1249 | ], 1250 | ], 1251 | ], 1252 | ], 1253 | [ 1254 | 'FunctionDeclaration', 1255 | [ 1256 | [ 1257 | 'Identifier', 1258 | [], 1259 | ], 1260 | [ 1261 | 'BlockStatement', 1262 | [ 1263 | [ 1264 | 'VariableDeclaration', 1265 | [ 1266 | [ 1267 | 'VariableDeclarator', 1268 | [ 1269 | [ 1270 | 'ObjectPattern', 1271 | [ 1272 | [ 1273 | 'Property', 1274 | [ 1275 | [ 1276 | 'Identifier', 1277 | [], 1278 | ], 1279 | [ 1280 | 'Identifier', 1281 | [], 1282 | ], 1283 | ], 1284 | ], 1285 | [ 1286 | 'Property', 1287 | [ 1288 | [ 1289 | 'Identifier', 1290 | [], 1291 | ], 1292 | [ 1293 | 'Identifier', 1294 | [], 1295 | ], 1296 | ], 1297 | ], 1298 | [ 1299 | 'RestElement', 1300 | [ 1301 | [ 1302 | 'Identifier', 1303 | [], 1304 | ], 1305 | ], 1306 | ], 1307 | ], 1308 | ], 1309 | [ 1310 | 'Identifier', 1311 | [], 1312 | ], 1313 | ], 1314 | ], 1315 | ], 1316 | ], 1317 | [ 1318 | 'VariableDeclaration', 1319 | [ 1320 | [ 1321 | 'VariableDeclarator', 1322 | [ 1323 | [ 1324 | 'ArrayPattern', 1325 | [ 1326 | [ 1327 | 'Identifier', 1328 | [], 1329 | ], 1330 | [ 1331 | 'Identifier', 1332 | [], 1333 | ], 1334 | ], 1335 | ], 1336 | [ 1337 | 'Identifier', 1338 | [], 1339 | ], 1340 | ], 1341 | ], 1342 | ], 1343 | ], 1344 | ], 1345 | ], 1346 | ], 1347 | ], 1348 | [ 1349 | 'VariableDeclaration', 1350 | [ 1351 | [ 1352 | 'VariableDeclarator', 1353 | [ 1354 | [ 1355 | 'Identifier', 1356 | [], 1357 | ], 1358 | [ 1359 | 'NewExpression', 1360 | [ 1361 | [ 1362 | 'Identifier', 1363 | [], 1364 | ], 1365 | ], 1366 | ], 1367 | ], 1368 | ], 1369 | ], 1370 | ], 1371 | [ 1372 | 'VariableDeclaration', 1373 | [ 1374 | [ 1375 | 'VariableDeclarator', 1376 | [ 1377 | [ 1378 | 'Identifier', 1379 | [], 1380 | ], 1381 | [ 1382 | 'ObjectExpression', 1383 | [ 1384 | [ 1385 | 'Property', 1386 | [ 1387 | [ 1388 | 'Identifier', 1389 | [], 1390 | ], 1391 | [ 1392 | 'Identifier', 1393 | [], 1394 | ], 1395 | ], 1396 | ], 1397 | [ 1398 | 'Property', 1399 | [ 1400 | [ 1401 | 'Identifier', 1402 | [], 1403 | ], 1404 | [ 1405 | 'Identifier', 1406 | [], 1407 | ], 1408 | ], 1409 | ], 1410 | [ 1411 | 'Property', 1412 | [ 1413 | [ 1414 | 'Identifier', 1415 | [], 1416 | ], 1417 | [ 1418 | 'FunctionExpression', 1419 | [ 1420 | [ 1421 | 'BlockStatement', 1422 | [], 1423 | ], 1424 | ], 1425 | ], 1426 | ], 1427 | ], 1428 | [ 1429 | 'SpreadElement', 1430 | [ 1431 | [ 1432 | 'Identifier', 1433 | [], 1434 | ], 1435 | ], 1436 | ], 1437 | ], 1438 | ], 1439 | ], 1440 | ], 1441 | ], 1442 | ], 1443 | [ 1444 | 'VariableDeclaration', 1445 | [ 1446 | [ 1447 | 'VariableDeclarator', 1448 | [ 1449 | [ 1450 | 'Identifier', 1451 | [], 1452 | ], 1453 | [ 1454 | 'ObjectExpression', 1455 | [ 1456 | [ 1457 | 'Property', 1458 | [ 1459 | [ 1460 | 'Identifier', 1461 | [], 1462 | ], 1463 | [ 1464 | 'Literal', 1465 | [], 1466 | ], 1467 | ], 1468 | ], 1469 | [ 1470 | 'Property', 1471 | [ 1472 | [ 1473 | 'Identifier', 1474 | [], 1475 | ], 1476 | [ 1477 | 'Literal', 1478 | [], 1479 | ], 1480 | ], 1481 | ], 1482 | [ 1483 | 'Property', 1484 | [ 1485 | [ 1486 | 'Identifier', 1487 | [], 1488 | ], 1489 | [ 1490 | 'BinaryExpression', 1491 | [ 1492 | [ 1493 | 'Literal', 1494 | [], 1495 | ], 1496 | [ 1497 | 'Literal', 1498 | [], 1499 | ], 1500 | ], 1501 | ], 1502 | ], 1503 | ], 1504 | [ 1505 | 'Property', 1506 | [ 1507 | [ 1508 | 'Identifier', 1509 | [], 1510 | ], 1511 | [ 1512 | 'BinaryExpression', 1513 | [ 1514 | [ 1515 | 'Literal', 1516 | [], 1517 | ], 1518 | [ 1519 | 'Literal', 1520 | [], 1521 | ], 1522 | ], 1523 | ], 1524 | ], 1525 | ], 1526 | [ 1527 | 'Property', 1528 | [ 1529 | [ 1530 | 'Identifier', 1531 | [], 1532 | ], 1533 | [ 1534 | 'BinaryExpression', 1535 | [ 1536 | [ 1537 | 'Literal', 1538 | [], 1539 | ], 1540 | [ 1541 | 'Literal', 1542 | [], 1543 | ], 1544 | ], 1545 | ], 1546 | ], 1547 | ], 1548 | [ 1549 | 'Property', 1550 | [ 1551 | [ 1552 | 'Identifier', 1553 | [], 1554 | ], 1555 | [ 1556 | 'BinaryExpression', 1557 | [ 1558 | [ 1559 | 'Literal', 1560 | [], 1561 | ], 1562 | [ 1563 | 'Literal', 1564 | [], 1565 | ], 1566 | ], 1567 | ], 1568 | ], 1569 | ], 1570 | [ 1571 | 'Property', 1572 | [ 1573 | [ 1574 | 'Identifier', 1575 | [], 1576 | ], 1577 | [ 1578 | 'BinaryExpression', 1579 | [ 1580 | [ 1581 | 'Literal', 1582 | [], 1583 | ], 1584 | [ 1585 | 'Literal', 1586 | [], 1587 | ], 1588 | ], 1589 | ], 1590 | ], 1591 | ], 1592 | [ 1593 | 'Property', 1594 | [ 1595 | [ 1596 | 'Identifier', 1597 | [], 1598 | ], 1599 | [ 1600 | 'BinaryExpression', 1601 | [ 1602 | [ 1603 | 'Literal', 1604 | [], 1605 | ], 1606 | [ 1607 | 'Literal', 1608 | [], 1609 | ], 1610 | ], 1611 | ], 1612 | ], 1613 | ], 1614 | [ 1615 | 'Property', 1616 | [ 1617 | [ 1618 | 'Identifier', 1619 | [], 1620 | ], 1621 | [ 1622 | 'BinaryExpression', 1623 | [ 1624 | [ 1625 | 'Literal', 1626 | [], 1627 | ], 1628 | [ 1629 | 'Literal', 1630 | [], 1631 | ], 1632 | ], 1633 | ], 1634 | ], 1635 | ], 1636 | [ 1637 | 'Property', 1638 | [ 1639 | [ 1640 | 'Identifier', 1641 | [], 1642 | ], 1643 | [ 1644 | 'BinaryExpression', 1645 | [ 1646 | [ 1647 | 'Literal', 1648 | [], 1649 | ], 1650 | [ 1651 | 'Literal', 1652 | [], 1653 | ], 1654 | ], 1655 | ], 1656 | ], 1657 | ], 1658 | [ 1659 | 'Property', 1660 | [ 1661 | [ 1662 | 'Identifier', 1663 | [], 1664 | ], 1665 | [ 1666 | 'BinaryExpression', 1667 | [ 1668 | [ 1669 | 'Literal', 1670 | [], 1671 | ], 1672 | [ 1673 | 'Identifier', 1674 | [], 1675 | ], 1676 | ], 1677 | ], 1678 | ], 1679 | ], 1680 | [ 1681 | 'Property', 1682 | [ 1683 | [ 1684 | 'Identifier', 1685 | [], 1686 | ], 1687 | [ 1688 | 'BinaryExpression', 1689 | [ 1690 | [ 1691 | 'Literal', 1692 | [], 1693 | ], 1694 | [ 1695 | 'Literal', 1696 | [], 1697 | ], 1698 | ], 1699 | ], 1700 | ], 1701 | ], 1702 | [ 1703 | 'Property', 1704 | [ 1705 | [ 1706 | 'Identifier', 1707 | [], 1708 | ], 1709 | [ 1710 | 'BinaryExpression', 1711 | [ 1712 | [ 1713 | 'Literal', 1714 | [], 1715 | ], 1716 | [ 1717 | 'Literal', 1718 | [], 1719 | ], 1720 | ], 1721 | ], 1722 | ], 1723 | ], 1724 | [ 1725 | 'Property', 1726 | [ 1727 | [ 1728 | 'Identifier', 1729 | [], 1730 | ], 1731 | [ 1732 | 'BinaryExpression', 1733 | [ 1734 | [ 1735 | 'Literal', 1736 | [], 1737 | ], 1738 | [ 1739 | 'Literal', 1740 | [], 1741 | ], 1742 | ], 1743 | ], 1744 | ], 1745 | ], 1746 | [ 1747 | 'Property', 1748 | [ 1749 | [ 1750 | 'Identifier', 1751 | [], 1752 | ], 1753 | [ 1754 | 'BinaryExpression', 1755 | [ 1756 | [ 1757 | 'Literal', 1758 | [], 1759 | ], 1760 | [ 1761 | 'Literal', 1762 | [], 1763 | ], 1764 | ], 1765 | ], 1766 | ], 1767 | ], 1768 | [ 1769 | 'Property', 1770 | [ 1771 | [ 1772 | 'Identifier', 1773 | [], 1774 | ], 1775 | [ 1776 | 'BinaryExpression', 1777 | [ 1778 | [ 1779 | 'Literal', 1780 | [], 1781 | ], 1782 | [ 1783 | 'Identifier', 1784 | [], 1785 | ], 1786 | ], 1787 | ], 1788 | ], 1789 | ], 1790 | [ 1791 | 'Property', 1792 | [ 1793 | [ 1794 | 'Identifier', 1795 | [], 1796 | ], 1797 | [ 1798 | 'LogicalExpression', 1799 | [ 1800 | [ 1801 | 'Literal', 1802 | [], 1803 | ], 1804 | [ 1805 | 'Literal', 1806 | [], 1807 | ], 1808 | ], 1809 | ], 1810 | ], 1811 | ], 1812 | [ 1813 | 'Property', 1814 | [ 1815 | [ 1816 | 'Identifier', 1817 | [], 1818 | ], 1819 | [ 1820 | 'LogicalExpression', 1821 | [ 1822 | [ 1823 | 'Literal', 1824 | [], 1825 | ], 1826 | [ 1827 | 'Literal', 1828 | [], 1829 | ], 1830 | ], 1831 | ], 1832 | ], 1833 | ], 1834 | [ 1835 | 'Property', 1836 | [ 1837 | [ 1838 | 'Identifier', 1839 | [], 1840 | ], 1841 | [ 1842 | 'SequenceExpression', 1843 | [ 1844 | [ 1845 | 'Literal', 1846 | [], 1847 | ], 1848 | [ 1849 | 'Literal', 1850 | [], 1851 | ], 1852 | ], 1853 | ], 1854 | ], 1855 | ], 1856 | [ 1857 | 'Property', 1858 | [ 1859 | [ 1860 | 'Identifier', 1861 | [], 1862 | ], 1863 | [ 1864 | 'BinaryExpression', 1865 | [ 1866 | [ 1867 | 'Literal', 1868 | [], 1869 | ], 1870 | [ 1871 | 'Literal', 1872 | [], 1873 | ], 1874 | ], 1875 | ], 1876 | ], 1877 | ], 1878 | [ 1879 | 'Property', 1880 | [ 1881 | [ 1882 | 'Identifier', 1883 | [], 1884 | ], 1885 | [ 1886 | 'BinaryExpression', 1887 | [ 1888 | [ 1889 | 'Literal', 1890 | [], 1891 | ], 1892 | [ 1893 | 'Literal', 1894 | [], 1895 | ], 1896 | ], 1897 | ], 1898 | ], 1899 | ], 1900 | [ 1901 | 'Property', 1902 | [ 1903 | [ 1904 | 'Identifier', 1905 | [], 1906 | ], 1907 | [ 1908 | 'BinaryExpression', 1909 | [ 1910 | [ 1911 | 'Literal', 1912 | [], 1913 | ], 1914 | [ 1915 | 'Literal', 1916 | [], 1917 | ], 1918 | ], 1919 | ], 1920 | ], 1921 | ], 1922 | [ 1923 | 'Property', 1924 | [ 1925 | [ 1926 | 'Identifier', 1927 | [], 1928 | ], 1929 | [ 1930 | 'BinaryExpression', 1931 | [ 1932 | [ 1933 | 'Literal', 1934 | [], 1935 | ], 1936 | [ 1937 | 'Literal', 1938 | [], 1939 | ], 1940 | ], 1941 | ], 1942 | ], 1943 | ], 1944 | [ 1945 | 'Property', 1946 | [ 1947 | [ 1948 | 'Identifier', 1949 | [], 1950 | ], 1951 | [ 1952 | 'BinaryExpression', 1953 | [ 1954 | [ 1955 | 'Literal', 1956 | [], 1957 | ], 1958 | [ 1959 | 'Literal', 1960 | [], 1961 | ], 1962 | ], 1963 | ], 1964 | ], 1965 | ], 1966 | ], 1967 | ], 1968 | ], 1969 | ], 1970 | ], 1971 | ], 1972 | [ 1973 | 'ExpressionStatement', 1974 | [ 1975 | [ 1976 | 'AssignmentExpression', 1977 | [ 1978 | [ 1979 | 'MemberExpression', 1980 | [ 1981 | [ 1982 | 'Identifier', 1983 | [], 1984 | ], 1985 | [ 1986 | 'Identifier', 1987 | [], 1988 | ], 1989 | ], 1990 | ], 1991 | [ 1992 | 'Literal', 1993 | [], 1994 | ], 1995 | ], 1996 | ], 1997 | ], 1998 | ], 1999 | [ 2000 | 'ExpressionStatement', 2001 | [ 2002 | [ 2003 | 'AssignmentExpression', 2004 | [ 2005 | [ 2006 | 'MemberExpression', 2007 | [ 2008 | [ 2009 | 'Identifier', 2010 | [], 2011 | ], 2012 | [ 2013 | 'Identifier', 2014 | [], 2015 | ], 2016 | ], 2017 | ], 2018 | [ 2019 | 'Literal', 2020 | [], 2021 | ], 2022 | ], 2023 | ], 2024 | ], 2025 | ], 2026 | [ 2027 | 'ExpressionStatement', 2028 | [ 2029 | [ 2030 | 'AssignmentExpression', 2031 | [ 2032 | [ 2033 | 'MemberExpression', 2034 | [ 2035 | [ 2036 | 'Identifier', 2037 | [], 2038 | ], 2039 | [ 2040 | 'Identifier', 2041 | [], 2042 | ], 2043 | ], 2044 | ], 2045 | [ 2046 | 'Literal', 2047 | [], 2048 | ], 2049 | ], 2050 | ], 2051 | ], 2052 | ], 2053 | [ 2054 | 'ExpressionStatement', 2055 | [ 2056 | [ 2057 | 'AssignmentExpression', 2058 | [ 2059 | [ 2060 | 'MemberExpression', 2061 | [ 2062 | [ 2063 | 'Identifier', 2064 | [], 2065 | ], 2066 | [ 2067 | 'Identifier', 2068 | [], 2069 | ], 2070 | ], 2071 | ], 2072 | [ 2073 | 'Literal', 2074 | [], 2075 | ], 2076 | ], 2077 | ], 2078 | ], 2079 | ], 2080 | [ 2081 | 'ExpressionStatement', 2082 | [ 2083 | [ 2084 | 'AssignmentExpression', 2085 | [ 2086 | [ 2087 | 'MemberExpression', 2088 | [ 2089 | [ 2090 | 'Identifier', 2091 | [], 2092 | ], 2093 | [ 2094 | 'Identifier', 2095 | [], 2096 | ], 2097 | ], 2098 | ], 2099 | [ 2100 | 'Literal', 2101 | [], 2102 | ], 2103 | ], 2104 | ], 2105 | ], 2106 | ], 2107 | [ 2108 | 'ExpressionStatement', 2109 | [ 2110 | [ 2111 | 'AssignmentExpression', 2112 | [ 2113 | [ 2114 | 'MemberExpression', 2115 | [ 2116 | [ 2117 | 'Identifier', 2118 | [], 2119 | ], 2120 | [ 2121 | 'Identifier', 2122 | [], 2123 | ], 2124 | ], 2125 | ], 2126 | [ 2127 | 'Literal', 2128 | [], 2129 | ], 2130 | ], 2131 | ], 2132 | ], 2133 | ], 2134 | [ 2135 | 'ExpressionStatement', 2136 | [ 2137 | [ 2138 | 'UpdateExpression', 2139 | [ 2140 | [ 2141 | 'MemberExpression', 2142 | [ 2143 | [ 2144 | 'Identifier', 2145 | [], 2146 | ], 2147 | [ 2148 | 'Identifier', 2149 | [], 2150 | ], 2151 | ], 2152 | ], 2153 | ], 2154 | ], 2155 | ], 2156 | ], 2157 | [ 2158 | 'ExpressionStatement', 2159 | [ 2160 | [ 2161 | 'UpdateExpression', 2162 | [ 2163 | [ 2164 | 'MemberExpression', 2165 | [ 2166 | [ 2167 | 'Identifier', 2168 | [], 2169 | ], 2170 | [ 2171 | 'Identifier', 2172 | [], 2173 | ], 2174 | ], 2175 | ], 2176 | ], 2177 | ], 2178 | ], 2179 | ], 2180 | [ 2181 | 'ExpressionStatement', 2182 | [ 2183 | [ 2184 | 'UpdateExpression', 2185 | [ 2186 | [ 2187 | 'MemberExpression', 2188 | [ 2189 | [ 2190 | 'Identifier', 2191 | [], 2192 | ], 2193 | [ 2194 | 'Identifier', 2195 | [], 2196 | ], 2197 | ], 2198 | ], 2199 | ], 2200 | ], 2201 | ], 2202 | ], 2203 | [ 2204 | 'ExpressionStatement', 2205 | [ 2206 | [ 2207 | 'UpdateExpression', 2208 | [ 2209 | [ 2210 | 'MemberExpression', 2211 | [ 2212 | [ 2213 | 'Identifier', 2214 | [], 2215 | ], 2216 | [ 2217 | 'Identifier', 2218 | [], 2219 | ], 2220 | ], 2221 | ], 2222 | ], 2223 | ], 2224 | ], 2225 | ], 2226 | [ 2227 | 'ExpressionStatement', 2228 | [ 2229 | [ 2230 | 'AssignmentExpression', 2231 | [ 2232 | [ 2233 | 'MemberExpression', 2234 | [ 2235 | [ 2236 | 'Identifier', 2237 | [], 2238 | ], 2239 | [ 2240 | 'Identifier', 2241 | [], 2242 | ], 2243 | ], 2244 | ], 2245 | [ 2246 | 'UnaryExpression', 2247 | [ 2248 | [ 2249 | 'MemberExpression', 2250 | [ 2251 | [ 2252 | 'Identifier', 2253 | [], 2254 | ], 2255 | [ 2256 | 'Identifier', 2257 | [], 2258 | ], 2259 | ], 2260 | ], 2261 | ], 2262 | ], 2263 | ], 2264 | ], 2265 | ], 2266 | ], 2267 | [ 2268 | 'ExpressionStatement', 2269 | [ 2270 | [ 2271 | 'AssignmentExpression', 2272 | [ 2273 | [ 2274 | 'MemberExpression', 2275 | [ 2276 | [ 2277 | 'Identifier', 2278 | [], 2279 | ], 2280 | [ 2281 | 'Identifier', 2282 | [], 2283 | ], 2284 | ], 2285 | ], 2286 | [ 2287 | 'Literal', 2288 | [], 2289 | ], 2290 | ], 2291 | ], 2292 | ], 2293 | ], 2294 | [ 2295 | 'VariableDeclaration', 2296 | [ 2297 | [ 2298 | 'VariableDeclarator', 2299 | [ 2300 | [ 2301 | 'Identifier', 2302 | [], 2303 | ], 2304 | [ 2305 | 'ArrayExpression', 2306 | [ 2307 | [ 2308 | 'Literal', 2309 | [], 2310 | ], 2311 | [ 2312 | 'Literal', 2313 | [], 2314 | ], 2315 | [ 2316 | 'Literal', 2317 | [], 2318 | ], 2319 | [ 2320 | 'Literal', 2321 | [], 2322 | ], 2323 | [ 2324 | 'SpreadElement', 2325 | [ 2326 | [ 2327 | 'Identifier', 2328 | [], 2329 | ], 2330 | ], 2331 | ], 2332 | ], 2333 | ], 2334 | ], 2335 | ], 2336 | ], 2337 | ], 2338 | [ 2339 | 'VariableDeclaration', 2340 | [ 2341 | [ 2342 | 'VariableDeclarator', 2343 | [ 2344 | [ 2345 | 'Identifier', 2346 | [], 2347 | ], 2348 | [ 2349 | 'TemplateLiteral', 2350 | [ 2351 | [ 2352 | 'Literal', 2353 | [], 2354 | ], 2355 | [ 2356 | 'TemplateElement', 2357 | [], 2358 | ], 2359 | [ 2360 | 'TemplateElement', 2361 | [], 2362 | ], 2363 | ], 2364 | ], 2365 | ], 2366 | ], 2367 | ], 2368 | ], 2369 | [ 2370 | 'VariableDeclaration', 2371 | [ 2372 | [ 2373 | 'VariableDeclarator', 2374 | [ 2375 | [ 2376 | 'Identifier', 2377 | [], 2378 | ], 2379 | [ 2380 | 'TaggedTemplateExpression', 2381 | [ 2382 | [ 2383 | 'Identifier', 2384 | [], 2385 | ], 2386 | [ 2387 | 'TemplateLiteral', 2388 | [ 2389 | [ 2390 | 'Identifier', 2391 | [], 2392 | ], 2393 | [ 2394 | 'TemplateElement', 2395 | [], 2396 | ], 2397 | [ 2398 | 'TemplateElement', 2399 | [], 2400 | ], 2401 | ], 2402 | ], 2403 | ], 2404 | ], 2405 | ], 2406 | ], 2407 | ], 2408 | ], 2409 | ], 2410 | ], 2411 | ], 2412 | ] 2413 | --------------------------------------------------------------------------------