1(function (global, factory) { 2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 3 typeof define === 'function' && define.amd ? define(['exports'], factory) : 4 (factory((global.acorn = global.acorn || {}, global.acorn.walk = global.acorn.walk || {}))); 5}(this, (function (exports) { 'use strict'; 6 7// AST walker module for Mozilla Parser API compatible trees 8 9// A simple walk is one where you simply specify callbacks to be 10// called on specific nodes. The last two arguments are optional. A 11// simple use would be 12// 13// walk.simple(myTree, { 14// Expression: function(node) { ... } 15// }); 16// 17// to do something with all expressions. All Parser API node types 18// can be used to identify node types, as well as Expression, 19// Statement, and ScopeBody, which denote categories of nodes. 20// 21// The base argument can be used to pass a custom (recursive) 22// walker, and state can be used to give this walked an initial 23// state. 24 25function simple(node, visitors, base, state, override) { 26 if (!base) base = exports.base 27 ;(function c(node, st, override) { 28 var type = override || node.type, found = visitors[type] 29 base[type](node, st, c) 30 if (found) found(node, st) 31 })(node, state, override) 32} 33 34// An ancestor walk keeps an array of ancestor nodes (including the 35// current node) and passes them to the callback as third parameter 36// (and also as state parameter when no other state is present). 37function ancestor(node, visitors, base, state) { 38 if (!base) base = exports.base 39 var ancestors = [] 40 ;(function c(node, st, override) { 41 var type = override || node.type, found = visitors[type] 42 var isNew = node != ancestors[ancestors.length - 1] 43 if (isNew) ancestors.push(node) 44 base[type](node, st, c) 45 if (found) found(node, st || ancestors, ancestors) 46 if (isNew) ancestors.pop() 47 })(node, state) 48} 49 50// A recursive walk is one where your functions override the default 51// walkers. They can modify and replace the state parameter that's 52// threaded through the walk, and can opt how and whether to walk 53// their child nodes (by calling their third argument on these 54// nodes). 55function recursive(node, state, funcs, base, override) { 56 var visitor = funcs ? exports.make(funcs, base) : base 57 ;(function c(node, st, override) { 58 visitor[override || node.type](node, st, c) 59 })(node, state, override) 60} 61 62function makeTest(test) { 63 if (typeof test == "string") 64 return function (type) { return type == test; } 65 else if (!test) 66 return function () { return true; } 67 else 68 return test 69} 70 71var Found = function Found(node, state) { this.node = node; this.state = state }; 72 73// Find a node with a given start, end, and type (all are optional, 74// null can be used as wildcard). Returns a {node, state} object, or 75// undefined when it doesn't find a matching node. 76function findNodeAt(node, start, end, test, base, state) { 77 test = makeTest(test) 78 if (!base) base = exports.base 79 try { 80 ;(function c(node, st, override) { 81 var type = override || node.type 82 if ((start == null || node.start <= start) && 83 (end == null || node.end >= end)) 84 base[type](node, st, c) 85 if ((start == null || node.start == start) && 86 (end == null || node.end == end) && 87 test(type, node)) 88 throw new Found(node, st) 89 })(node, state) 90 } catch (e) { 91 if (e instanceof Found) return e 92 throw e 93 } 94} 95 96// Find the innermost node of a given type that contains the given 97// position. Interface similar to findNodeAt. 98function findNodeAround(node, pos, test, base, state) { 99 test = makeTest(test) 100 if (!base) base = exports.base 101 try { 102 ;(function c(node, st, override) { 103 var type = override || node.type 104 if (node.start > pos || node.end < pos) return 105 base[type](node, st, c) 106 if (test(type, node)) throw new Found(node, st) 107 })(node, state) 108 } catch (e) { 109 if (e instanceof Found) return e 110 throw e 111 } 112} 113 114// Find the outermost matching node after a given position. 115function findNodeAfter(node, pos, test, base, state) { 116 test = makeTest(test) 117 if (!base) base = exports.base 118 try { 119 ;(function c(node, st, override) { 120 if (node.end < pos) return 121 var type = override || node.type 122 if (node.start >= pos && test(type, node)) throw new Found(node, st) 123 base[type](node, st, c) 124 })(node, state) 125 } catch (e) { 126 if (e instanceof Found) return e 127 throw e 128 } 129} 130 131// Find the outermost matching node before a given position. 132function findNodeBefore(node, pos, test, base, state) { 133 test = makeTest(test) 134 if (!base) base = exports.base 135 var max 136 ;(function c(node, st, override) { 137 if (node.start > pos) return 138 var type = override || node.type 139 if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node)) 140 max = new Found(node, st) 141 base[type](node, st, c) 142 })(node, state) 143 return max 144} 145 146// Fallback to an Object.create polyfill for older environments. 147var create = Object.create || function(proto) { 148 function Ctor() {} 149 Ctor.prototype = proto 150 return new Ctor 151} 152 153// Used to create a custom walker. Will fill in all missing node 154// type properties with the defaults. 155function make(funcs, base) { 156 if (!base) base = exports.base 157 var visitor = create(base) 158 for (var type in funcs) visitor[type] = funcs[type] 159 return visitor 160} 161 162function skipThrough(node, st, c) { c(node, st) } 163function ignore(_node, _st, _c) {} 164 165// Node walkers. 166 167var base = {} 168 169base.Program = base.BlockStatement = function (node, st, c) { 170 for (var i = 0; i < node.body.length; ++i) 171 c(node.body[i], st, "Statement") 172} 173base.Statement = skipThrough 174base.EmptyStatement = ignore 175base.ExpressionStatement = base.ParenthesizedExpression = 176 function (node, st, c) { return c(node.expression, st, "Expression"); } 177base.IfStatement = function (node, st, c) { 178 c(node.test, st, "Expression") 179 c(node.consequent, st, "Statement") 180 if (node.alternate) c(node.alternate, st, "Statement") 181} 182base.LabeledStatement = function (node, st, c) { return c(node.body, st, "Statement"); } 183base.BreakStatement = base.ContinueStatement = ignore 184base.WithStatement = function (node, st, c) { 185 c(node.object, st, "Expression") 186 c(node.body, st, "Statement") 187} 188base.SwitchStatement = function (node, st, c) { 189 c(node.discriminant, st, "Expression") 190 for (var i = 0; i < node.cases.length; ++i) { 191 var cs = node.cases[i] 192 if (cs.test) c(cs.test, st, "Expression") 193 for (var j = 0; j < cs.consequent.length; ++j) 194 c(cs.consequent[j], st, "Statement") 195 } 196} 197base.ReturnStatement = base.YieldExpression = base.AwaitExpression = function (node, st, c) { 198 if (node.argument) c(node.argument, st, "Expression") 199} 200base.ThrowStatement = base.SpreadElement = 201 function (node, st, c) { return c(node.argument, st, "Expression"); } 202base.TryStatement = function (node, st, c) { 203 c(node.block, st, "Statement") 204 if (node.handler) c(node.handler, st) 205 if (node.finalizer) c(node.finalizer, st, "Statement") 206} 207base.CatchClause = function (node, st, c) { 208 c(node.param, st, "Pattern") 209 c(node.body, st, "ScopeBody") 210} 211base.WhileStatement = base.DoWhileStatement = function (node, st, c) { 212 c(node.test, st, "Expression") 213 c(node.body, st, "Statement") 214} 215base.ForStatement = function (node, st, c) { 216 if (node.init) c(node.init, st, "ForInit") 217 if (node.test) c(node.test, st, "Expression") 218 if (node.update) c(node.update, st, "Expression") 219 c(node.body, st, "Statement") 220} 221base.ForInStatement = base.ForOfStatement = function (node, st, c) { 222 c(node.left, st, "ForInit") 223 c(node.right, st, "Expression") 224 c(node.body, st, "Statement") 225} 226base.ForInit = function (node, st, c) { 227 if (node.type == "VariableDeclaration") c(node, st) 228 else c(node, st, "Expression") 229} 230base.DebuggerStatement = ignore 231 232base.FunctionDeclaration = function (node, st, c) { return c(node, st, "Function"); } 233base.VariableDeclaration = function (node, st, c) { 234 for (var i = 0; i < node.declarations.length; ++i) 235 c(node.declarations[i], st) 236} 237base.VariableDeclarator = function (node, st, c) { 238 c(node.id, st, "Pattern") 239 if (node.init) c(node.init, st, "Expression") 240} 241 242base.Function = function (node, st, c) { 243 if (node.id) c(node.id, st, "Pattern") 244 for (var i = 0; i < node.params.length; i++) 245 c(node.params[i], st, "Pattern") 246 c(node.body, st, node.expression ? "ScopeExpression" : "ScopeBody") 247} 248// FIXME drop these node types in next major version 249// (They are awkward, and in ES6 every block can be a scope.) 250base.ScopeBody = function (node, st, c) { return c(node, st, "Statement"); } 251base.ScopeExpression = function (node, st, c) { return c(node, st, "Expression"); } 252 253base.Pattern = function (node, st, c) { 254 if (node.type == "Identifier") 255 c(node, st, "VariablePattern") 256 else if (node.type == "MemberExpression") 257 c(node, st, "MemberPattern") 258 else 259 c(node, st) 260} 261base.VariablePattern = ignore 262base.MemberPattern = skipThrough 263base.RestElement = function (node, st, c) { return c(node.argument, st, "Pattern"); } 264base.ArrayPattern = function (node, st, c) { 265 for (var i = 0; i < node.elements.length; ++i) { 266 var elt = node.elements[i] 267 if (elt) c(elt, st, "Pattern") 268 } 269} 270base.ObjectPattern = function (node, st, c) { 271 for (var i = 0; i < node.properties.length; ++i) 272 c(node.properties[i].value, st, "Pattern") 273} 274 275base.Expression = skipThrough 276base.ThisExpression = base.Super = base.MetaProperty = ignore 277base.ArrayExpression = function (node, st, c) { 278 for (var i = 0; i < node.elements.length; ++i) { 279 var elt = node.elements[i] 280 if (elt) c(elt, st, "Expression") 281 } 282} 283base.ObjectExpression = function (node, st, c) { 284 for (var i = 0; i < node.properties.length; ++i) 285 c(node.properties[i], st) 286} 287base.FunctionExpression = base.ArrowFunctionExpression = base.FunctionDeclaration 288base.SequenceExpression = base.TemplateLiteral = function (node, st, c) { 289 for (var i = 0; i < node.expressions.length; ++i) 290 c(node.expressions[i], st, "Expression") 291} 292base.UnaryExpression = base.UpdateExpression = function (node, st, c) { 293 c(node.argument, st, "Expression") 294} 295base.BinaryExpression = base.LogicalExpression = function (node, st, c) { 296 c(node.left, st, "Expression") 297 c(node.right, st, "Expression") 298} 299base.AssignmentExpression = base.AssignmentPattern = function (node, st, c) { 300 c(node.left, st, "Pattern") 301 c(node.right, st, "Expression") 302} 303base.ConditionalExpression = function (node, st, c) { 304 c(node.test, st, "Expression") 305 c(node.consequent, st, "Expression") 306 c(node.alternate, st, "Expression") 307} 308base.NewExpression = base.CallExpression = function (node, st, c) { 309 c(node.callee, st, "Expression") 310 if (node.arguments) for (var i = 0; i < node.arguments.length; ++i) 311 c(node.arguments[i], st, "Expression") 312} 313base.MemberExpression = function (node, st, c) { 314 c(node.object, st, "Expression") 315 if (node.computed) c(node.property, st, "Expression") 316} 317base.ExportNamedDeclaration = base.ExportDefaultDeclaration = function (node, st, c) { 318 if (node.declaration) 319 c(node.declaration, st, node.type == "ExportNamedDeclaration" || node.declaration.id ? "Statement" : "Expression") 320 if (node.source) c(node.source, st, "Expression") 321} 322base.ExportAllDeclaration = function (node, st, c) { 323 c(node.source, st, "Expression") 324} 325base.ImportDeclaration = function (node, st, c) { 326 for (var i = 0; i < node.specifiers.length; i++) 327 c(node.specifiers[i], st) 328 c(node.source, st, "Expression") 329} 330base.ImportSpecifier = base.ImportDefaultSpecifier = base.ImportNamespaceSpecifier = base.Identifier = base.Literal = ignore 331 332base.TaggedTemplateExpression = function (node, st, c) { 333 c(node.tag, st, "Expression") 334 c(node.quasi, st) 335} 336base.ClassDeclaration = base.ClassExpression = function (node, st, c) { return c(node, st, "Class"); } 337base.Class = function (node, st, c) { 338 if (node.id) c(node.id, st, "Pattern") 339 if (node.superClass) c(node.superClass, st, "Expression") 340 for (var i = 0; i < node.body.body.length; i++) 341 c(node.body.body[i], st) 342} 343base.MethodDefinition = base.Property = function (node, st, c) { 344 if (node.computed) c(node.key, st, "Expression") 345 c(node.value, st, "Expression") 346} 347 348exports.simple = simple; 349exports.ancestor = ancestor; 350exports.recursive = recursive; 351exports.findNodeAt = findNodeAt; 352exports.findNodeAround = findNodeAround; 353exports.findNodeAfter = findNodeAfter; 354exports.findNodeBefore = findNodeBefore; 355exports.make = make; 356exports.base = base; 357 358Object.defineProperty(exports, '__esModule', { value: true }); 359 360})));