mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	
		
			
	
	
		
			137 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			137 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|   | // 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; |