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;
 |