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