diff options
Diffstat (limited to 'remote/test/puppeteer/utils/ESTreeWalker.js')
-rw-r--r-- | remote/test/puppeteer/utils/ESTreeWalker.js | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/remote/test/puppeteer/utils/ESTreeWalker.js b/remote/test/puppeteer/utils/ESTreeWalker.js new file mode 100644 index 0000000000..1c6c6d4782 --- /dev/null +++ b/remote/test/puppeteer/utils/ESTreeWalker.js @@ -0,0 +1,135 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @unrestricted + */ +class ESTreeWalker { + /** + * @param {function(!ESTree.Node):(!Object|undefined)} beforeVisit + * @param {function(!ESTree.Node)=} afterVisit + */ + constructor(beforeVisit, afterVisit) { + this._beforeVisit = beforeVisit; + this._afterVisit = afterVisit || new Function(); + } + + /** + * @param {!ESTree.Node} ast + */ + walk(ast) { + this._innerWalk(ast, null); + } + + /** + * @param {!ESTree.Node} node + * @param {?ESTree.Node} parent + */ + _innerWalk(node, parent) { + if (!node) return; + node.parent = parent; + + if (this._beforeVisit.call(null, node) === ESTreeWalker.SkipSubtree) { + this._afterVisit.call(null, node); + return; + } + + const walkOrder = ESTreeWalker._walkOrder[node.type]; + if (!walkOrder) return; + + if (node.type === 'TemplateLiteral') { + const templateLiteral = /** @type {!ESTree.TemplateLiteralNode} */ (node); + const expressionsLength = templateLiteral.expressions.length; + for (let i = 0; i < expressionsLength; ++i) { + this._innerWalk(templateLiteral.quasis[i], templateLiteral); + this._innerWalk(templateLiteral.expressions[i], templateLiteral); + } + this._innerWalk( + templateLiteral.quasis[expressionsLength], + templateLiteral + ); + } else { + for (let i = 0; i < walkOrder.length; ++i) { + const entity = node[walkOrder[i]]; + if (Array.isArray(entity)) this._walkArray(entity, node); + else this._innerWalk(entity, node); + } + } + + this._afterVisit.call(null, node); + } + + /** + * @param {!Array.<!ESTree.Node>} nodeArray + * @param {?ESTree.Node} parentNode + */ + _walkArray(nodeArray, parentNode) { + for (let i = 0; i < nodeArray.length; ++i) + this._innerWalk(nodeArray[i], parentNode); + } +} + +/** @typedef {!Object} ESTreeWalker.SkipSubtree */ +ESTreeWalker.SkipSubtree = {}; + +/** @enum {!Array.<string>} */ +ESTreeWalker._walkOrder = { + AwaitExpression: ['argument'], + ArrayExpression: ['elements'], + ArrowFunctionExpression: ['params', 'body'], + AssignmentExpression: ['left', 'right'], + AssignmentPattern: ['left', 'right'], + BinaryExpression: ['left', 'right'], + BlockStatement: ['body'], + BreakStatement: ['label'], + CallExpression: ['callee', 'arguments'], + CatchClause: ['param', 'body'], + ClassBody: ['body'], + ClassDeclaration: ['id', 'superClass', 'body'], + ClassExpression: ['id', 'superClass', 'body'], + ConditionalExpression: ['test', 'consequent', 'alternate'], + ContinueStatement: ['label'], + DebuggerStatement: [], + DoWhileStatement: ['body', 'test'], + EmptyStatement: [], + ExpressionStatement: ['expression'], + ForInStatement: ['left', 'right', 'body'], + ForOfStatement: ['left', 'right', 'body'], + ForStatement: ['init', 'test', 'update', 'body'], + FunctionDeclaration: ['id', 'params', 'body'], + FunctionExpression: ['id', 'params', 'body'], + Identifier: [], + IfStatement: ['test', 'consequent', 'alternate'], + LabeledStatement: ['label', 'body'], + Literal: [], + LogicalExpression: ['left', 'right'], + MemberExpression: ['object', 'property'], + MethodDefinition: ['key', 'value'], + NewExpression: ['callee', 'arguments'], + ObjectExpression: ['properties'], + ObjectPattern: ['properties'], + ParenthesizedExpression: ['expression'], + Program: ['body'], + Property: ['key', 'value'], + ReturnStatement: ['argument'], + SequenceExpression: ['expressions'], + Super: [], + SwitchCase: ['test', 'consequent'], + SwitchStatement: ['discriminant', 'cases'], + TaggedTemplateExpression: ['tag', 'quasi'], + TemplateElement: [], + TemplateLiteral: ['quasis', 'expressions'], + ThisExpression: [], + ThrowStatement: ['argument'], + TryStatement: ['block', 'handler', 'finalizer'], + UnaryExpression: ['argument'], + UpdateExpression: ['argument'], + VariableDeclaration: ['declarations'], + VariableDeclarator: ['id', 'init'], + WhileStatement: ['test', 'body'], + WithStatement: ['object', 'body'], + YieldExpression: ['argument'], +}; + +module.exports = ESTreeWalker; |