source: imaps-frontend/node_modules/terser/lib/ast.js@ 79a0317

main
Last change on this file since 79a0317 was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 3 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 96.2 KB
RevLine 
[79a0317]1/***********************************************************************
2
3 A JavaScript tokenizer / parser / beautifier / compressor.
4 https://github.com/mishoo/UglifyJS2
5
6 -------------------------------- (C) ---------------------------------
7
8 Author: Mihai Bazon
9 <mihai.bazon@gmail.com>
10 http://mihai.bazon.net/blog
11
12 Distributed under the BSD license:
13
14 Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
15
16 Redistribution and use in source and binary forms, with or without
17 modification, are permitted provided that the following conditions
18 are met:
19
20 * Redistributions of source code must retain the above
21 copyright notice, this list of conditions and the following
22 disclaimer.
23
24 * Redistributions in binary form must reproduce the above
25 copyright notice, this list of conditions and the following
26 disclaimer in the documentation and/or other materials
27 provided with the distribution.
28
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
30 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
33 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
34 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
35 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
38 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
39 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 SUCH DAMAGE.
41
42 ***********************************************************************/
43
44import {
45 HOP,
46 MAP,
47 noop
48} from "./utils/index.js";
49import { parse } from "./parse.js";
50
51function DEFNODE(type, props, ctor, methods, base = AST_Node) {
52 if (!props) props = [];
53 else props = props.split(/\s+/);
54 var self_props = props;
55 if (base && base.PROPS)
56 props = props.concat(base.PROPS);
57 const proto = base && Object.create(base.prototype);
58 if (proto) {
59 ctor.prototype = proto;
60 ctor.BASE = base;
61 }
62 if (base) base.SUBCLASSES.push(ctor);
63 ctor.prototype.CTOR = ctor;
64 ctor.prototype.constructor = ctor;
65 ctor.PROPS = props || null;
66 ctor.SELF_PROPS = self_props;
67 ctor.SUBCLASSES = [];
68 if (type) {
69 ctor.prototype.TYPE = ctor.TYPE = type;
70 }
71 if (methods) for (let i in methods) if (HOP(methods, i)) {
72 if (i[0] === "$") {
73 ctor[i.substr(1)] = methods[i];
74 } else {
75 ctor.prototype[i] = methods[i];
76 }
77 }
78 ctor.DEFMETHOD = function(name, method) {
79 this.prototype[name] = method;
80 };
81 return ctor;
82}
83
84const has_tok_flag = (tok, flag) => Boolean(tok.flags & flag);
85const set_tok_flag = (tok, flag, truth) => {
86 if (truth) {
87 tok.flags |= flag;
88 } else {
89 tok.flags &= ~flag;
90 }
91};
92
93const TOK_FLAG_NLB = 0b0001;
94const TOK_FLAG_QUOTE_SINGLE = 0b0010;
95const TOK_FLAG_QUOTE_EXISTS = 0b0100;
96const TOK_FLAG_TEMPLATE_END = 0b1000;
97
98class AST_Token {
99 constructor(type, value, line, col, pos, nlb, comments_before, comments_after, file) {
100 this.flags = (nlb ? 1 : 0);
101
102 this.type = type;
103 this.value = value;
104 this.line = line;
105 this.col = col;
106 this.pos = pos;
107 this.comments_before = comments_before;
108 this.comments_after = comments_after;
109 this.file = file;
110
111 Object.seal(this);
112 }
113
114 // Return a string summary of the token for node.js console.log
115 [Symbol.for("nodejs.util.inspect.custom")](_depth, options) {
116 const special = str => options.stylize(str, "special");
117 const quote = typeof this.value === "string" && this.value.includes("`") ? "'" : "`";
118 const value = `${quote}${this.value}${quote}`;
119 return `${special("[AST_Token")} ${value} at ${this.line}:${this.col}${special("]")}`;
120 }
121
122 get nlb() {
123 return has_tok_flag(this, TOK_FLAG_NLB);
124 }
125
126 set nlb(new_nlb) {
127 set_tok_flag(this, TOK_FLAG_NLB, new_nlb);
128 }
129
130 get quote() {
131 return !has_tok_flag(this, TOK_FLAG_QUOTE_EXISTS)
132 ? ""
133 : (has_tok_flag(this, TOK_FLAG_QUOTE_SINGLE) ? "'" : '"');
134 }
135
136 set quote(quote_type) {
137 set_tok_flag(this, TOK_FLAG_QUOTE_SINGLE, quote_type === "'");
138 set_tok_flag(this, TOK_FLAG_QUOTE_EXISTS, !!quote_type);
139 }
140
141 get template_end() {
142 return has_tok_flag(this, TOK_FLAG_TEMPLATE_END);
143 }
144
145 set template_end(new_template_end) {
146 set_tok_flag(this, TOK_FLAG_TEMPLATE_END, new_template_end);
147 }
148}
149
150var AST_Node = DEFNODE("Node", "start end", function AST_Node(props) {
151 if (props) {
152 this.start = props.start;
153 this.end = props.end;
154 }
155
156 this.flags = 0;
157}, {
158 _clone: function(deep) {
159 if (deep) {
160 var self = this.clone();
161 return self.transform(new TreeTransformer(function(node) {
162 if (node !== self) {
163 return node.clone(true);
164 }
165 }));
166 }
167 return new this.CTOR(this);
168 },
169 clone: function(deep) {
170 return this._clone(deep);
171 },
172 $documentation: "Base class of all AST nodes",
173 $propdoc: {
174 start: "[AST_Token] The first token of this node",
175 end: "[AST_Token] The last token of this node"
176 },
177 _walk: function(visitor) {
178 return visitor._visit(this);
179 },
180 walk: function(visitor) {
181 return this._walk(visitor); // not sure the indirection will be any help
182 },
183 _children_backwards: () => {}
184}, null);
185
186/* -----[ statements ]----- */
187
188var AST_Statement = DEFNODE("Statement", null, function AST_Statement(props) {
189 if (props) {
190 this.start = props.start;
191 this.end = props.end;
192 }
193
194 this.flags = 0;
195}, {
196 $documentation: "Base class of all statements",
197});
198
199var AST_Debugger = DEFNODE("Debugger", null, function AST_Debugger(props) {
200 if (props) {
201 this.start = props.start;
202 this.end = props.end;
203 }
204
205 this.flags = 0;
206}, {
207 $documentation: "Represents a debugger statement",
208}, AST_Statement);
209
210var AST_Directive = DEFNODE("Directive", "value quote", function AST_Directive(props) {
211 if (props) {
212 this.value = props.value;
213 this.quote = props.quote;
214 this.start = props.start;
215 this.end = props.end;
216 }
217
218 this.flags = 0;
219}, {
220 $documentation: "Represents a directive, like \"use strict\";",
221 $propdoc: {
222 value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
223 quote: "[string] the original quote character"
224 },
225}, AST_Statement);
226
227var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", function AST_SimpleStatement(props) {
228 if (props) {
229 this.body = props.body;
230 this.start = props.start;
231 this.end = props.end;
232 }
233
234 this.flags = 0;
235}, {
236 $documentation: "A statement consisting of an expression, i.e. a = 1 + 2",
237 $propdoc: {
238 body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
239 },
240 _walk: function(visitor) {
241 return visitor._visit(this, function() {
242 this.body._walk(visitor);
243 });
244 },
245 _children_backwards(push) {
246 push(this.body);
247 }
248}, AST_Statement);
249
250function walk_body(node, visitor) {
251 const body = node.body;
252 for (var i = 0, len = body.length; i < len; i++) {
253 body[i]._walk(visitor);
254 }
255}
256
257function clone_block_scope(deep) {
258 var clone = this._clone(deep);
259 if (this.block_scope) {
260 clone.block_scope = this.block_scope.clone();
261 }
262 return clone;
263}
264
265var AST_Block = DEFNODE("Block", "body block_scope", function AST_Block(props) {
266 if (props) {
267 this.body = props.body;
268 this.block_scope = props.block_scope;
269 this.start = props.start;
270 this.end = props.end;
271 }
272
273 this.flags = 0;
274}, {
275 $documentation: "A body of statements (usually braced)",
276 $propdoc: {
277 body: "[AST_Statement*] an array of statements",
278 block_scope: "[AST_Scope] the block scope"
279 },
280 _walk: function(visitor) {
281 return visitor._visit(this, function() {
282 walk_body(this, visitor);
283 });
284 },
285 _children_backwards(push) {
286 let i = this.body.length;
287 while (i--) push(this.body[i]);
288 },
289 clone: clone_block_scope
290}, AST_Statement);
291
292var AST_BlockStatement = DEFNODE("BlockStatement", null, function AST_BlockStatement(props) {
293 if (props) {
294 this.body = props.body;
295 this.block_scope = props.block_scope;
296 this.start = props.start;
297 this.end = props.end;
298 }
299
300 this.flags = 0;
301}, {
302 $documentation: "A block statement",
303}, AST_Block);
304
305var AST_EmptyStatement = DEFNODE("EmptyStatement", null, function AST_EmptyStatement(props) {
306 if (props) {
307 this.start = props.start;
308 this.end = props.end;
309 }
310
311 this.flags = 0;
312}, {
313 $documentation: "The empty statement (empty block or simply a semicolon)"
314}, AST_Statement);
315
316var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", function AST_StatementWithBody(props) {
317 if (props) {
318 this.body = props.body;
319 this.start = props.start;
320 this.end = props.end;
321 }
322
323 this.flags = 0;
324}, {
325 $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",
326 $propdoc: {
327 body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
328 }
329}, AST_Statement);
330
331var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", function AST_LabeledStatement(props) {
332 if (props) {
333 this.label = props.label;
334 this.body = props.body;
335 this.start = props.start;
336 this.end = props.end;
337 }
338
339 this.flags = 0;
340}, {
341 $documentation: "Statement with a label",
342 $propdoc: {
343 label: "[AST_Label] a label definition"
344 },
345 _walk: function(visitor) {
346 return visitor._visit(this, function() {
347 this.label._walk(visitor);
348 this.body._walk(visitor);
349 });
350 },
351 _children_backwards(push) {
352 push(this.body);
353 push(this.label);
354 },
355 clone: function(deep) {
356 var node = this._clone(deep);
357 if (deep) {
358 var label = node.label;
359 var def = this.label;
360 node.walk(new TreeWalker(function(node) {
361 if (node instanceof AST_LoopControl
362 && node.label && node.label.thedef === def) {
363 node.label.thedef = label;
364 label.references.push(node);
365 }
366 }));
367 }
368 return node;
369 }
370}, AST_StatementWithBody);
371
372var AST_IterationStatement = DEFNODE(
373 "IterationStatement",
374 "block_scope",
375 function AST_IterationStatement(props) {
376 if (props) {
377 this.block_scope = props.block_scope;
378 this.body = props.body;
379 this.start = props.start;
380 this.end = props.end;
381 }
382
383 this.flags = 0;
384 },
385 {
386 $documentation: "Internal class. All loops inherit from it.",
387 $propdoc: {
388 block_scope: "[AST_Scope] the block scope for this iteration statement."
389 },
390 clone: clone_block_scope
391 },
392 AST_StatementWithBody
393);
394
395var AST_DWLoop = DEFNODE("DWLoop", "condition", function AST_DWLoop(props) {
396 if (props) {
397 this.condition = props.condition;
398 this.block_scope = props.block_scope;
399 this.body = props.body;
400 this.start = props.start;
401 this.end = props.end;
402 }
403
404 this.flags = 0;
405}, {
406 $documentation: "Base class for do/while statements",
407 $propdoc: {
408 condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement"
409 }
410}, AST_IterationStatement);
411
412var AST_Do = DEFNODE("Do", null, function AST_Do(props) {
413 if (props) {
414 this.condition = props.condition;
415 this.block_scope = props.block_scope;
416 this.body = props.body;
417 this.start = props.start;
418 this.end = props.end;
419 }
420
421 this.flags = 0;
422}, {
423 $documentation: "A `do` statement",
424 _walk: function(visitor) {
425 return visitor._visit(this, function() {
426 this.body._walk(visitor);
427 this.condition._walk(visitor);
428 });
429 },
430 _children_backwards(push) {
431 push(this.condition);
432 push(this.body);
433 }
434}, AST_DWLoop);
435
436var AST_While = DEFNODE("While", null, function AST_While(props) {
437 if (props) {
438 this.condition = props.condition;
439 this.block_scope = props.block_scope;
440 this.body = props.body;
441 this.start = props.start;
442 this.end = props.end;
443 }
444
445 this.flags = 0;
446}, {
447 $documentation: "A `while` statement",
448 _walk: function(visitor) {
449 return visitor._visit(this, function() {
450 this.condition._walk(visitor);
451 this.body._walk(visitor);
452 });
453 },
454 _children_backwards(push) {
455 push(this.body);
456 push(this.condition);
457 },
458}, AST_DWLoop);
459
460var AST_For = DEFNODE("For", "init condition step", function AST_For(props) {
461 if (props) {
462 this.init = props.init;
463 this.condition = props.condition;
464 this.step = props.step;
465 this.block_scope = props.block_scope;
466 this.body = props.body;
467 this.start = props.start;
468 this.end = props.end;
469 }
470
471 this.flags = 0;
472}, {
473 $documentation: "A `for` statement",
474 $propdoc: {
475 init: "[AST_Node?] the `for` initialization code, or null if empty",
476 condition: "[AST_Node?] the `for` termination clause, or null if empty",
477 step: "[AST_Node?] the `for` update clause, or null if empty"
478 },
479 _walk: function(visitor) {
480 return visitor._visit(this, function() {
481 if (this.init) this.init._walk(visitor);
482 if (this.condition) this.condition._walk(visitor);
483 if (this.step) this.step._walk(visitor);
484 this.body._walk(visitor);
485 });
486 },
487 _children_backwards(push) {
488 push(this.body);
489 if (this.step) push(this.step);
490 if (this.condition) push(this.condition);
491 if (this.init) push(this.init);
492 },
493}, AST_IterationStatement);
494
495var AST_ForIn = DEFNODE("ForIn", "init object", function AST_ForIn(props) {
496 if (props) {
497 this.init = props.init;
498 this.object = props.object;
499 this.block_scope = props.block_scope;
500 this.body = props.body;
501 this.start = props.start;
502 this.end = props.end;
503 }
504
505 this.flags = 0;
506}, {
507 $documentation: "A `for ... in` statement",
508 $propdoc: {
509 init: "[AST_Node] the `for/in` initialization code",
510 object: "[AST_Node] the object that we're looping through"
511 },
512 _walk: function(visitor) {
513 return visitor._visit(this, function() {
514 this.init._walk(visitor);
515 this.object._walk(visitor);
516 this.body._walk(visitor);
517 });
518 },
519 _children_backwards(push) {
520 push(this.body);
521 if (this.object) push(this.object);
522 if (this.init) push(this.init);
523 },
524}, AST_IterationStatement);
525
526var AST_ForOf = DEFNODE("ForOf", "await", function AST_ForOf(props) {
527 if (props) {
528 this.await = props.await;
529 this.init = props.init;
530 this.object = props.object;
531 this.block_scope = props.block_scope;
532 this.body = props.body;
533 this.start = props.start;
534 this.end = props.end;
535 }
536
537 this.flags = 0;
538}, {
539 $documentation: "A `for ... of` statement",
540}, AST_ForIn);
541
542var AST_With = DEFNODE("With", "expression", function AST_With(props) {
543 if (props) {
544 this.expression = props.expression;
545 this.body = props.body;
546 this.start = props.start;
547 this.end = props.end;
548 }
549
550 this.flags = 0;
551}, {
552 $documentation: "A `with` statement",
553 $propdoc: {
554 expression: "[AST_Node] the `with` expression"
555 },
556 _walk: function(visitor) {
557 return visitor._visit(this, function() {
558 this.expression._walk(visitor);
559 this.body._walk(visitor);
560 });
561 },
562 _children_backwards(push) {
563 push(this.body);
564 push(this.expression);
565 },
566}, AST_StatementWithBody);
567
568/* -----[ scope and functions ]----- */
569
570var AST_Scope = DEFNODE(
571 "Scope",
572 "variables uses_with uses_eval parent_scope enclosed cname",
573 function AST_Scope(props) {
574 if (props) {
575 this.variables = props.variables;
576 this.uses_with = props.uses_with;
577 this.uses_eval = props.uses_eval;
578 this.parent_scope = props.parent_scope;
579 this.enclosed = props.enclosed;
580 this.cname = props.cname;
581 this.body = props.body;
582 this.block_scope = props.block_scope;
583 this.start = props.start;
584 this.end = props.end;
585 }
586
587 this.flags = 0;
588 },
589 {
590 $documentation: "Base class for all statements introducing a lexical scope",
591 $propdoc: {
592 variables: "[Map/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
593 uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
594 uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
595 parent_scope: "[AST_Scope?/S] link to the parent scope",
596 enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
597 cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
598 },
599 get_defun_scope: function() {
600 var self = this;
601 while (self.is_block_scope()) {
602 self = self.parent_scope;
603 }
604 return self;
605 },
606 clone: function(deep, toplevel) {
607 var node = this._clone(deep);
608 if (deep && this.variables && toplevel && !this._block_scope) {
609 node.figure_out_scope({}, {
610 toplevel: toplevel,
611 parent_scope: this.parent_scope
612 });
613 } else {
614 if (this.variables) node.variables = new Map(this.variables);
615 if (this.enclosed) node.enclosed = this.enclosed.slice();
616 if (this._block_scope) node._block_scope = this._block_scope;
617 }
618 return node;
619 },
620 pinned: function() {
621 return this.uses_eval || this.uses_with;
622 }
623 },
624 AST_Block
625);
626
627var AST_Toplevel = DEFNODE("Toplevel", "globals", function AST_Toplevel(props) {
628 if (props) {
629 this.globals = props.globals;
630 this.variables = props.variables;
631 this.uses_with = props.uses_with;
632 this.uses_eval = props.uses_eval;
633 this.parent_scope = props.parent_scope;
634 this.enclosed = props.enclosed;
635 this.cname = props.cname;
636 this.body = props.body;
637 this.block_scope = props.block_scope;
638 this.start = props.start;
639 this.end = props.end;
640 }
641
642 this.flags = 0;
643}, {
644 $documentation: "The toplevel scope",
645 $propdoc: {
646 globals: "[Map/S] a map of name -> SymbolDef for all undeclared names",
647 },
648 wrap_commonjs: function(name) {
649 var body = this.body;
650 var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");";
651 wrapped_tl = parse(wrapped_tl);
652 wrapped_tl = wrapped_tl.transform(new TreeTransformer(function(node) {
653 if (node instanceof AST_Directive && node.value == "$ORIG") {
654 return MAP.splice(body);
655 }
656 }));
657 return wrapped_tl;
658 },
659 wrap_enclose: function(args_values) {
660 if (typeof args_values != "string") args_values = "";
661 var index = args_values.indexOf(":");
662 if (index < 0) index = args_values.length;
663 var body = this.body;
664 return parse([
665 "(function(",
666 args_values.slice(0, index),
667 '){"$ORIG"})(',
668 args_values.slice(index + 1),
669 ")"
670 ].join("")).transform(new TreeTransformer(function(node) {
671 if (node instanceof AST_Directive && node.value == "$ORIG") {
672 return MAP.splice(body);
673 }
674 }));
675 }
676}, AST_Scope);
677
678var AST_Expansion = DEFNODE("Expansion", "expression", function AST_Expansion(props) {
679 if (props) {
680 this.expression = props.expression;
681 this.start = props.start;
682 this.end = props.end;
683 }
684
685 this.flags = 0;
686}, {
687 $documentation: "An expandible argument, such as ...rest, a splat, such as [1,2,...all], or an expansion in a variable declaration, such as var [first, ...rest] = list",
688 $propdoc: {
689 expression: "[AST_Node] the thing to be expanded"
690 },
691 _walk: function(visitor) {
692 return visitor._visit(this, function() {
693 this.expression.walk(visitor);
694 });
695 },
696 _children_backwards(push) {
697 push(this.expression);
698 },
699});
700
701var AST_Lambda = DEFNODE(
702 "Lambda",
703 "name argnames uses_arguments is_generator async",
704 function AST_Lambda(props) {
705 if (props) {
706 this.name = props.name;
707 this.argnames = props.argnames;
708 this.uses_arguments = props.uses_arguments;
709 this.is_generator = props.is_generator;
710 this.async = props.async;
711 this.variables = props.variables;
712 this.uses_with = props.uses_with;
713 this.uses_eval = props.uses_eval;
714 this.parent_scope = props.parent_scope;
715 this.enclosed = props.enclosed;
716 this.cname = props.cname;
717 this.body = props.body;
718 this.block_scope = props.block_scope;
719 this.start = props.start;
720 this.end = props.end;
721 }
722
723 this.flags = 0;
724 },
725 {
726 $documentation: "Base class for functions",
727 $propdoc: {
728 name: "[AST_SymbolDeclaration?] the name of this function",
729 argnames: "[AST_SymbolFunarg|AST_Destructuring|AST_Expansion|AST_DefaultAssign*] array of function arguments, destructurings, or expanding arguments",
730 uses_arguments: "[boolean/S] tells whether this function accesses the arguments array",
731 is_generator: "[boolean] is this a generator method",
732 async: "[boolean] is this method async",
733 },
734 args_as_names: function () {
735 var out = [];
736 for (var i = 0; i < this.argnames.length; i++) {
737 if (this.argnames[i] instanceof AST_Destructuring) {
738 out.push(...this.argnames[i].all_symbols());
739 } else {
740 out.push(this.argnames[i]);
741 }
742 }
743 return out;
744 },
745 _walk: function(visitor) {
746 return visitor._visit(this, function() {
747 if (this.name) this.name._walk(visitor);
748 var argnames = this.argnames;
749 for (var i = 0, len = argnames.length; i < len; i++) {
750 argnames[i]._walk(visitor);
751 }
752 walk_body(this, visitor);
753 });
754 },
755 _children_backwards(push) {
756 let i = this.body.length;
757 while (i--) push(this.body[i]);
758
759 i = this.argnames.length;
760 while (i--) push(this.argnames[i]);
761
762 if (this.name) push(this.name);
763 },
764 is_braceless() {
765 return this.body[0] instanceof AST_Return && this.body[0].value;
766 },
767 // Default args and expansion don't count, so .argnames.length doesn't cut it
768 length_property() {
769 let length = 0;
770
771 for (const arg of this.argnames) {
772 if (arg instanceof AST_SymbolFunarg || arg instanceof AST_Destructuring) {
773 length++;
774 }
775 }
776
777 return length;
778 }
779 },
780 AST_Scope
781);
782
783var AST_Accessor = DEFNODE("Accessor", null, function AST_Accessor(props) {
784 if (props) {
785 this.name = props.name;
786 this.argnames = props.argnames;
787 this.uses_arguments = props.uses_arguments;
788 this.is_generator = props.is_generator;
789 this.async = props.async;
790 this.variables = props.variables;
791 this.uses_with = props.uses_with;
792 this.uses_eval = props.uses_eval;
793 this.parent_scope = props.parent_scope;
794 this.enclosed = props.enclosed;
795 this.cname = props.cname;
796 this.body = props.body;
797 this.block_scope = props.block_scope;
798 this.start = props.start;
799 this.end = props.end;
800 }
801
802 this.flags = 0;
803}, {
804 $documentation: "A setter/getter function. The `name` property is always null."
805}, AST_Lambda);
806
807var AST_Function = DEFNODE("Function", null, function AST_Function(props) {
808 if (props) {
809 this.name = props.name;
810 this.argnames = props.argnames;
811 this.uses_arguments = props.uses_arguments;
812 this.is_generator = props.is_generator;
813 this.async = props.async;
814 this.variables = props.variables;
815 this.uses_with = props.uses_with;
816 this.uses_eval = props.uses_eval;
817 this.parent_scope = props.parent_scope;
818 this.enclosed = props.enclosed;
819 this.cname = props.cname;
820 this.body = props.body;
821 this.block_scope = props.block_scope;
822 this.start = props.start;
823 this.end = props.end;
824 }
825
826 this.flags = 0;
827}, {
828 $documentation: "A function expression"
829}, AST_Lambda);
830
831var AST_Arrow = DEFNODE("Arrow", null, function AST_Arrow(props) {
832 if (props) {
833 this.name = props.name;
834 this.argnames = props.argnames;
835 this.uses_arguments = props.uses_arguments;
836 this.is_generator = props.is_generator;
837 this.async = props.async;
838 this.variables = props.variables;
839 this.uses_with = props.uses_with;
840 this.uses_eval = props.uses_eval;
841 this.parent_scope = props.parent_scope;
842 this.enclosed = props.enclosed;
843 this.cname = props.cname;
844 this.body = props.body;
845 this.block_scope = props.block_scope;
846 this.start = props.start;
847 this.end = props.end;
848 }
849
850 this.flags = 0;
851}, {
852 $documentation: "An ES6 Arrow function ((a) => b)"
853}, AST_Lambda);
854
855var AST_Defun = DEFNODE("Defun", null, function AST_Defun(props) {
856 if (props) {
857 this.name = props.name;
858 this.argnames = props.argnames;
859 this.uses_arguments = props.uses_arguments;
860 this.is_generator = props.is_generator;
861 this.async = props.async;
862 this.variables = props.variables;
863 this.uses_with = props.uses_with;
864 this.uses_eval = props.uses_eval;
865 this.parent_scope = props.parent_scope;
866 this.enclosed = props.enclosed;
867 this.cname = props.cname;
868 this.body = props.body;
869 this.block_scope = props.block_scope;
870 this.start = props.start;
871 this.end = props.end;
872 }
873
874 this.flags = 0;
875}, {
876 $documentation: "A function definition"
877}, AST_Lambda);
878
879/* -----[ DESTRUCTURING ]----- */
880var AST_Destructuring = DEFNODE("Destructuring", "names is_array", function AST_Destructuring(props) {
881 if (props) {
882 this.names = props.names;
883 this.is_array = props.is_array;
884 this.start = props.start;
885 this.end = props.end;
886 }
887
888 this.flags = 0;
889}, {
890 $documentation: "A destructuring of several names. Used in destructuring assignment and with destructuring function argument names",
891 $propdoc: {
892 "names": "[AST_Node*] Array of properties or elements",
893 "is_array": "[Boolean] Whether the destructuring represents an object or array"
894 },
895 _walk: function(visitor) {
896 return visitor._visit(this, function() {
897 this.names.forEach(function(name) {
898 name._walk(visitor);
899 });
900 });
901 },
902 _children_backwards(push) {
903 let i = this.names.length;
904 while (i--) push(this.names[i]);
905 },
906 all_symbols: function() {
907 var out = [];
908 walk(this, node => {
909 if (node instanceof AST_SymbolDeclaration) {
910 out.push(node);
911 }
912 if (node instanceof AST_Lambda) {
913 return true;
914 }
915 });
916 return out;
917 }
918});
919
920var AST_PrefixedTemplateString = DEFNODE(
921 "PrefixedTemplateString",
922 "template_string prefix",
923 function AST_PrefixedTemplateString(props) {
924 if (props) {
925 this.template_string = props.template_string;
926 this.prefix = props.prefix;
927 this.start = props.start;
928 this.end = props.end;
929 }
930
931 this.flags = 0;
932 },
933 {
934 $documentation: "A templatestring with a prefix, such as String.raw`foobarbaz`",
935 $propdoc: {
936 template_string: "[AST_TemplateString] The template string",
937 prefix: "[AST_Node] The prefix, which will get called."
938 },
939 _walk: function(visitor) {
940 return visitor._visit(this, function () {
941 this.prefix._walk(visitor);
942 this.template_string._walk(visitor);
943 });
944 },
945 _children_backwards(push) {
946 push(this.template_string);
947 push(this.prefix);
948 },
949 }
950);
951
952var AST_TemplateString = DEFNODE("TemplateString", "segments", function AST_TemplateString(props) {
953 if (props) {
954 this.segments = props.segments;
955 this.start = props.start;
956 this.end = props.end;
957 }
958
959 this.flags = 0;
960}, {
961 $documentation: "A template string literal",
962 $propdoc: {
963 segments: "[AST_Node*] One or more segments, starting with AST_TemplateSegment. AST_Node may follow AST_TemplateSegment, but each AST_Node must be followed by AST_TemplateSegment."
964 },
965 _walk: function(visitor) {
966 return visitor._visit(this, function() {
967 this.segments.forEach(function(seg) {
968 seg._walk(visitor);
969 });
970 });
971 },
972 _children_backwards(push) {
973 let i = this.segments.length;
974 while (i--) push(this.segments[i]);
975 }
976});
977
978var AST_TemplateSegment = DEFNODE("TemplateSegment", "value raw", function AST_TemplateSegment(props) {
979 if (props) {
980 this.value = props.value;
981 this.raw = props.raw;
982 this.start = props.start;
983 this.end = props.end;
984 }
985
986 this.flags = 0;
987}, {
988 $documentation: "A segment of a template string literal",
989 $propdoc: {
990 value: "Content of the segment",
991 raw: "Raw source of the segment",
992 }
993});
994
995/* -----[ JUMPS ]----- */
996
997var AST_Jump = DEFNODE("Jump", null, function AST_Jump(props) {
998 if (props) {
999 this.start = props.start;
1000 this.end = props.end;
1001 }
1002
1003 this.flags = 0;
1004}, {
1005 $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"
1006}, AST_Statement);
1007
1008/** Base class for “exits” (`return` and `throw`) */
1009var AST_Exit = DEFNODE("Exit", "value", function AST_Exit(props) {
1010 if (props) {
1011 this.value = props.value;
1012 this.start = props.start;
1013 this.end = props.end;
1014 }
1015
1016 this.flags = 0;
1017}, {
1018 $documentation: "Base class for “exits” (`return` and `throw`)",
1019 $propdoc: {
1020 value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
1021 },
1022 _walk: function(visitor) {
1023 return visitor._visit(this, this.value && function() {
1024 this.value._walk(visitor);
1025 });
1026 },
1027 _children_backwards(push) {
1028 if (this.value) push(this.value);
1029 },
1030}, AST_Jump);
1031
1032var AST_Return = DEFNODE("Return", null, function AST_Return(props) {
1033 if (props) {
1034 this.value = props.value;
1035 this.start = props.start;
1036 this.end = props.end;
1037 }
1038
1039 this.flags = 0;
1040}, {
1041 $documentation: "A `return` statement"
1042}, AST_Exit);
1043
1044var AST_Throw = DEFNODE("Throw", null, function AST_Throw(props) {
1045 if (props) {
1046 this.value = props.value;
1047 this.start = props.start;
1048 this.end = props.end;
1049 }
1050
1051 this.flags = 0;
1052}, {
1053 $documentation: "A `throw` statement"
1054}, AST_Exit);
1055
1056var AST_LoopControl = DEFNODE("LoopControl", "label", function AST_LoopControl(props) {
1057 if (props) {
1058 this.label = props.label;
1059 this.start = props.start;
1060 this.end = props.end;
1061 }
1062
1063 this.flags = 0;
1064}, {
1065 $documentation: "Base class for loop control statements (`break` and `continue`)",
1066 $propdoc: {
1067 label: "[AST_LabelRef?] the label, or null if none",
1068 },
1069 _walk: function(visitor) {
1070 return visitor._visit(this, this.label && function() {
1071 this.label._walk(visitor);
1072 });
1073 },
1074 _children_backwards(push) {
1075 if (this.label) push(this.label);
1076 },
1077}, AST_Jump);
1078
1079var AST_Break = DEFNODE("Break", null, function AST_Break(props) {
1080 if (props) {
1081 this.label = props.label;
1082 this.start = props.start;
1083 this.end = props.end;
1084 }
1085
1086 this.flags = 0;
1087}, {
1088 $documentation: "A `break` statement"
1089}, AST_LoopControl);
1090
1091var AST_Continue = DEFNODE("Continue", null, function AST_Continue(props) {
1092 if (props) {
1093 this.label = props.label;
1094 this.start = props.start;
1095 this.end = props.end;
1096 }
1097
1098 this.flags = 0;
1099}, {
1100 $documentation: "A `continue` statement"
1101}, AST_LoopControl);
1102
1103var AST_Await = DEFNODE("Await", "expression", function AST_Await(props) {
1104 if (props) {
1105 this.expression = props.expression;
1106 this.start = props.start;
1107 this.end = props.end;
1108 }
1109
1110 this.flags = 0;
1111}, {
1112 $documentation: "An `await` statement",
1113 $propdoc: {
1114 expression: "[AST_Node] the mandatory expression being awaited",
1115 },
1116 _walk: function(visitor) {
1117 return visitor._visit(this, function() {
1118 this.expression._walk(visitor);
1119 });
1120 },
1121 _children_backwards(push) {
1122 push(this.expression);
1123 },
1124});
1125
1126var AST_Yield = DEFNODE("Yield", "expression is_star", function AST_Yield(props) {
1127 if (props) {
1128 this.expression = props.expression;
1129 this.is_star = props.is_star;
1130 this.start = props.start;
1131 this.end = props.end;
1132 }
1133
1134 this.flags = 0;
1135}, {
1136 $documentation: "A `yield` statement",
1137 $propdoc: {
1138 expression: "[AST_Node?] the value returned or thrown by this statement; could be null (representing undefined) but only when is_star is set to false",
1139 is_star: "[Boolean] Whether this is a yield or yield* statement"
1140 },
1141 _walk: function(visitor) {
1142 return visitor._visit(this, this.expression && function() {
1143 this.expression._walk(visitor);
1144 });
1145 },
1146 _children_backwards(push) {
1147 if (this.expression) push(this.expression);
1148 }
1149});
1150
1151/* -----[ IF ]----- */
1152
1153var AST_If = DEFNODE("If", "condition alternative", function AST_If(props) {
1154 if (props) {
1155 this.condition = props.condition;
1156 this.alternative = props.alternative;
1157 this.body = props.body;
1158 this.start = props.start;
1159 this.end = props.end;
1160 }
1161
1162 this.flags = 0;
1163}, {
1164 $documentation: "A `if` statement",
1165 $propdoc: {
1166 condition: "[AST_Node] the `if` condition",
1167 alternative: "[AST_Statement?] the `else` part, or null if not present"
1168 },
1169 _walk: function(visitor) {
1170 return visitor._visit(this, function() {
1171 this.condition._walk(visitor);
1172 this.body._walk(visitor);
1173 if (this.alternative) this.alternative._walk(visitor);
1174 });
1175 },
1176 _children_backwards(push) {
1177 if (this.alternative) {
1178 push(this.alternative);
1179 }
1180 push(this.body);
1181 push(this.condition);
1182 }
1183}, AST_StatementWithBody);
1184
1185/* -----[ SWITCH ]----- */
1186
1187var AST_Switch = DEFNODE("Switch", "expression", function AST_Switch(props) {
1188 if (props) {
1189 this.expression = props.expression;
1190 this.body = props.body;
1191 this.block_scope = props.block_scope;
1192 this.start = props.start;
1193 this.end = props.end;
1194 }
1195
1196 this.flags = 0;
1197}, {
1198 $documentation: "A `switch` statement",
1199 $propdoc: {
1200 expression: "[AST_Node] the `switch` “discriminant”"
1201 },
1202 _walk: function(visitor) {
1203 return visitor._visit(this, function() {
1204 this.expression._walk(visitor);
1205 walk_body(this, visitor);
1206 });
1207 },
1208 _children_backwards(push) {
1209 let i = this.body.length;
1210 while (i--) push(this.body[i]);
1211 push(this.expression);
1212 }
1213}, AST_Block);
1214
1215var AST_SwitchBranch = DEFNODE("SwitchBranch", null, function AST_SwitchBranch(props) {
1216 if (props) {
1217 this.body = props.body;
1218 this.block_scope = props.block_scope;
1219 this.start = props.start;
1220 this.end = props.end;
1221 }
1222
1223 this.flags = 0;
1224}, {
1225 $documentation: "Base class for `switch` branches",
1226}, AST_Block);
1227
1228var AST_Default = DEFNODE("Default", null, function AST_Default(props) {
1229 if (props) {
1230 this.body = props.body;
1231 this.block_scope = props.block_scope;
1232 this.start = props.start;
1233 this.end = props.end;
1234 }
1235
1236 this.flags = 0;
1237}, {
1238 $documentation: "A `default` switch branch",
1239}, AST_SwitchBranch);
1240
1241var AST_Case = DEFNODE("Case", "expression", function AST_Case(props) {
1242 if (props) {
1243 this.expression = props.expression;
1244 this.body = props.body;
1245 this.block_scope = props.block_scope;
1246 this.start = props.start;
1247 this.end = props.end;
1248 }
1249
1250 this.flags = 0;
1251}, {
1252 $documentation: "A `case` switch branch",
1253 $propdoc: {
1254 expression: "[AST_Node] the `case` expression"
1255 },
1256 _walk: function(visitor) {
1257 return visitor._visit(this, function() {
1258 this.expression._walk(visitor);
1259 walk_body(this, visitor);
1260 });
1261 },
1262 _children_backwards(push) {
1263 let i = this.body.length;
1264 while (i--) push(this.body[i]);
1265 push(this.expression);
1266 },
1267}, AST_SwitchBranch);
1268
1269/* -----[ EXCEPTIONS ]----- */
1270
1271var AST_Try = DEFNODE("Try", "body bcatch bfinally", function AST_Try(props) {
1272 if (props) {
1273 this.body = props.body;
1274 this.bcatch = props.bcatch;
1275 this.bfinally = props.bfinally;
1276 this.start = props.start;
1277 this.end = props.end;
1278 }
1279
1280 this.flags = 0;
1281}, {
1282 $documentation: "A `try` statement",
1283 $propdoc: {
1284 body: "[AST_TryBlock] the try block",
1285 bcatch: "[AST_Catch?] the catch block, or null if not present",
1286 bfinally: "[AST_Finally?] the finally block, or null if not present"
1287 },
1288 _walk: function(visitor) {
1289 return visitor._visit(this, function() {
1290 this.body._walk(visitor);
1291 if (this.bcatch) this.bcatch._walk(visitor);
1292 if (this.bfinally) this.bfinally._walk(visitor);
1293 });
1294 },
1295 _children_backwards(push) {
1296 if (this.bfinally) push(this.bfinally);
1297 if (this.bcatch) push(this.bcatch);
1298 push(this.body);
1299 },
1300}, AST_Statement);
1301
1302var AST_TryBlock = DEFNODE("TryBlock", null, function AST_TryBlock(props) {
1303 if (props) {
1304 this.body = props.body;
1305 this.block_scope = props.block_scope;
1306 this.start = props.start;
1307 this.end = props.end;
1308 }
1309
1310 this.flags = 0;
1311}, {
1312 $documentation: "The `try` block of a try statement"
1313}, AST_Block);
1314
1315var AST_Catch = DEFNODE("Catch", "argname", function AST_Catch(props) {
1316 if (props) {
1317 this.argname = props.argname;
1318 this.body = props.body;
1319 this.block_scope = props.block_scope;
1320 this.start = props.start;
1321 this.end = props.end;
1322 }
1323
1324 this.flags = 0;
1325}, {
1326 $documentation: "A `catch` node; only makes sense as part of a `try` statement",
1327 $propdoc: {
1328 argname: "[AST_SymbolCatch|AST_Destructuring|AST_Expansion|AST_DefaultAssign] symbol for the exception"
1329 },
1330 _walk: function(visitor) {
1331 return visitor._visit(this, function() {
1332 if (this.argname) this.argname._walk(visitor);
1333 walk_body(this, visitor);
1334 });
1335 },
1336 _children_backwards(push) {
1337 let i = this.body.length;
1338 while (i--) push(this.body[i]);
1339 if (this.argname) push(this.argname);
1340 },
1341}, AST_Block);
1342
1343var AST_Finally = DEFNODE("Finally", null, function AST_Finally(props) {
1344 if (props) {
1345 this.body = props.body;
1346 this.block_scope = props.block_scope;
1347 this.start = props.start;
1348 this.end = props.end;
1349 }
1350
1351 this.flags = 0;
1352}, {
1353 $documentation: "A `finally` node; only makes sense as part of a `try` statement"
1354}, AST_Block);
1355
1356/* -----[ VAR/CONST ]----- */
1357
1358var AST_Definitions = DEFNODE("Definitions", "definitions", function AST_Definitions(props) {
1359 if (props) {
1360 this.definitions = props.definitions;
1361 this.start = props.start;
1362 this.end = props.end;
1363 }
1364
1365 this.flags = 0;
1366}, {
1367 $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
1368 $propdoc: {
1369 definitions: "[AST_VarDef*] array of variable definitions"
1370 },
1371 _walk: function(visitor) {
1372 return visitor._visit(this, function() {
1373 var definitions = this.definitions;
1374 for (var i = 0, len = definitions.length; i < len; i++) {
1375 definitions[i]._walk(visitor);
1376 }
1377 });
1378 },
1379 _children_backwards(push) {
1380 let i = this.definitions.length;
1381 while (i--) push(this.definitions[i]);
1382 },
1383}, AST_Statement);
1384
1385var AST_Var = DEFNODE("Var", null, function AST_Var(props) {
1386 if (props) {
1387 this.definitions = props.definitions;
1388 this.start = props.start;
1389 this.end = props.end;
1390 }
1391
1392 this.flags = 0;
1393}, {
1394 $documentation: "A `var` statement"
1395}, AST_Definitions);
1396
1397var AST_Let = DEFNODE("Let", null, function AST_Let(props) {
1398 if (props) {
1399 this.definitions = props.definitions;
1400 this.start = props.start;
1401 this.end = props.end;
1402 }
1403
1404 this.flags = 0;
1405}, {
1406 $documentation: "A `let` statement"
1407}, AST_Definitions);
1408
1409var AST_Const = DEFNODE("Const", null, function AST_Const(props) {
1410 if (props) {
1411 this.definitions = props.definitions;
1412 this.start = props.start;
1413 this.end = props.end;
1414 }
1415
1416 this.flags = 0;
1417}, {
1418 $documentation: "A `const` statement"
1419}, AST_Definitions);
1420
1421var AST_VarDef = DEFNODE("VarDef", "name value", function AST_VarDef(props) {
1422 if (props) {
1423 this.name = props.name;
1424 this.value = props.value;
1425 this.start = props.start;
1426 this.end = props.end;
1427 }
1428
1429 this.flags = 0;
1430}, {
1431 $documentation: "A variable declaration; only appears in a AST_Definitions node",
1432 $propdoc: {
1433 name: "[AST_Destructuring|AST_SymbolConst|AST_SymbolLet|AST_SymbolVar] name of the variable",
1434 value: "[AST_Node?] initializer, or null of there's no initializer"
1435 },
1436 _walk: function(visitor) {
1437 return visitor._visit(this, function() {
1438 this.name._walk(visitor);
1439 if (this.value) this.value._walk(visitor);
1440 });
1441 },
1442 _children_backwards(push) {
1443 if (this.value) push(this.value);
1444 push(this.name);
1445 },
1446 declarations_as_names() {
1447 if (this.name instanceof AST_SymbolDeclaration) {
1448 return [this];
1449 } else {
1450 return this.name.all_symbols();
1451 }
1452 }
1453});
1454
1455var AST_NameMapping = DEFNODE("NameMapping", "foreign_name name", function AST_NameMapping(props) {
1456 if (props) {
1457 this.foreign_name = props.foreign_name;
1458 this.name = props.name;
1459 this.start = props.start;
1460 this.end = props.end;
1461 }
1462
1463 this.flags = 0;
1464}, {
1465 $documentation: "The part of the export/import statement that declare names from a module.",
1466 $propdoc: {
1467 foreign_name: "[AST_SymbolExportForeign|AST_SymbolImportForeign] The name being exported/imported (as specified in the module)",
1468 name: "[AST_SymbolExport|AST_SymbolImport] The name as it is visible to this module."
1469 },
1470 _walk: function (visitor) {
1471 return visitor._visit(this, function() {
1472 this.foreign_name._walk(visitor);
1473 this.name._walk(visitor);
1474 });
1475 },
1476 _children_backwards(push) {
1477 push(this.name);
1478 push(this.foreign_name);
1479 },
1480});
1481
1482var AST_Import = DEFNODE(
1483 "Import",
1484 "imported_name imported_names module_name attributes",
1485 function AST_Import(props) {
1486 if (props) {
1487 this.imported_name = props.imported_name;
1488 this.imported_names = props.imported_names;
1489 this.module_name = props.module_name;
1490 this.attributes = props.attributes;
1491 this.start = props.start;
1492 this.end = props.end;
1493 }
1494
1495 this.flags = 0;
1496 },
1497 {
1498 $documentation: "An `import` statement",
1499 $propdoc: {
1500 imported_name: "[AST_SymbolImport] The name of the variable holding the module's default export.",
1501 imported_names: "[AST_NameMapping*] The names of non-default imported variables",
1502 module_name: "[AST_String] String literal describing where this module came from",
1503 attributes: "[AST_Object?] The import attributes (with {...})"
1504 },
1505 _walk: function(visitor) {
1506 return visitor._visit(this, function() {
1507 if (this.imported_name) {
1508 this.imported_name._walk(visitor);
1509 }
1510 if (this.imported_names) {
1511 this.imported_names.forEach(function(name_import) {
1512 name_import._walk(visitor);
1513 });
1514 }
1515 this.module_name._walk(visitor);
1516 });
1517 },
1518 _children_backwards(push) {
1519 push(this.module_name);
1520 if (this.imported_names) {
1521 let i = this.imported_names.length;
1522 while (i--) push(this.imported_names[i]);
1523 }
1524 if (this.imported_name) push(this.imported_name);
1525 },
1526 }
1527);
1528
1529var AST_ImportMeta = DEFNODE("ImportMeta", null, function AST_ImportMeta(props) {
1530 if (props) {
1531 this.start = props.start;
1532 this.end = props.end;
1533 }
1534
1535 this.flags = 0;
1536}, {
1537 $documentation: "A reference to import.meta",
1538});
1539
1540var AST_Export = DEFNODE(
1541 "Export",
1542 "exported_definition exported_value is_default exported_names module_name attributes",
1543 function AST_Export(props) {
1544 if (props) {
1545 this.exported_definition = props.exported_definition;
1546 this.exported_value = props.exported_value;
1547 this.is_default = props.is_default;
1548 this.exported_names = props.exported_names;
1549 this.module_name = props.module_name;
1550 this.attributes = props.attributes;
1551 this.start = props.start;
1552 this.end = props.end;
1553 }
1554
1555 this.flags = 0;
1556 },
1557 {
1558 $documentation: "An `export` statement",
1559 $propdoc: {
1560 exported_definition: "[AST_Defun|AST_Definitions|AST_DefClass?] An exported definition",
1561 exported_value: "[AST_Node?] An exported value",
1562 exported_names: "[AST_NameMapping*?] List of exported names",
1563 module_name: "[AST_String?] Name of the file to load exports from",
1564 is_default: "[Boolean] Whether this is the default exported value of this module",
1565 attributes: "[AST_Object?] The import attributes"
1566 },
1567 _walk: function (visitor) {
1568 return visitor._visit(this, function () {
1569 if (this.exported_definition) {
1570 this.exported_definition._walk(visitor);
1571 }
1572 if (this.exported_value) {
1573 this.exported_value._walk(visitor);
1574 }
1575 if (this.exported_names) {
1576 this.exported_names.forEach(function(name_export) {
1577 name_export._walk(visitor);
1578 });
1579 }
1580 if (this.module_name) {
1581 this.module_name._walk(visitor);
1582 }
1583 });
1584 },
1585 _children_backwards(push) {
1586 if (this.module_name) push(this.module_name);
1587 if (this.exported_names) {
1588 let i = this.exported_names.length;
1589 while (i--) push(this.exported_names[i]);
1590 }
1591 if (this.exported_value) push(this.exported_value);
1592 if (this.exported_definition) push(this.exported_definition);
1593 }
1594 },
1595 AST_Statement
1596);
1597
1598/* -----[ OTHER ]----- */
1599
1600var AST_Call = DEFNODE(
1601 "Call",
1602 "expression args optional _annotations",
1603 function AST_Call(props) {
1604 if (props) {
1605 this.expression = props.expression;
1606 this.args = props.args;
1607 this.optional = props.optional;
1608 this._annotations = props._annotations;
1609 this.start = props.start;
1610 this.end = props.end;
1611 this.initialize();
1612 }
1613
1614 this.flags = 0;
1615 },
1616 {
1617 $documentation: "A function call expression",
1618 $propdoc: {
1619 expression: "[AST_Node] expression to invoke as function",
1620 args: "[AST_Node*] array of arguments",
1621 optional: "[boolean] whether this is an optional call (IE ?.() )",
1622 _annotations: "[number] bitfield containing information about the call"
1623 },
1624 initialize() {
1625 if (this._annotations == null) this._annotations = 0;
1626 },
1627 _walk(visitor) {
1628 return visitor._visit(this, function() {
1629 var args = this.args;
1630 for (var i = 0, len = args.length; i < len; i++) {
1631 args[i]._walk(visitor);
1632 }
1633 this.expression._walk(visitor); // TODO why do we need to crawl this last?
1634 });
1635 },
1636 _children_backwards(push) {
1637 let i = this.args.length;
1638 while (i--) push(this.args[i]);
1639 push(this.expression);
1640 },
1641 }
1642);
1643
1644var AST_New = DEFNODE("New", null, function AST_New(props) {
1645 if (props) {
1646 this.expression = props.expression;
1647 this.args = props.args;
1648 this.optional = props.optional;
1649 this._annotations = props._annotations;
1650 this.start = props.start;
1651 this.end = props.end;
1652 this.initialize();
1653 }
1654
1655 this.flags = 0;
1656}, {
1657 $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties"
1658}, AST_Call);
1659
1660var AST_Sequence = DEFNODE("Sequence", "expressions", function AST_Sequence(props) {
1661 if (props) {
1662 this.expressions = props.expressions;
1663 this.start = props.start;
1664 this.end = props.end;
1665 }
1666
1667 this.flags = 0;
1668}, {
1669 $documentation: "A sequence expression (comma-separated expressions)",
1670 $propdoc: {
1671 expressions: "[AST_Node*] array of expressions (at least two)"
1672 },
1673 _walk: function(visitor) {
1674 return visitor._visit(this, function() {
1675 this.expressions.forEach(function(node) {
1676 node._walk(visitor);
1677 });
1678 });
1679 },
1680 _children_backwards(push) {
1681 let i = this.expressions.length;
1682 while (i--) push(this.expressions[i]);
1683 },
1684});
1685
1686var AST_PropAccess = DEFNODE(
1687 "PropAccess",
1688 "expression property optional",
1689 function AST_PropAccess(props) {
1690 if (props) {
1691 this.expression = props.expression;
1692 this.property = props.property;
1693 this.optional = props.optional;
1694 this.start = props.start;
1695 this.end = props.end;
1696 }
1697
1698 this.flags = 0;
1699 },
1700 {
1701 $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`",
1702 $propdoc: {
1703 expression: "[AST_Node] the “container” expression",
1704 property: "[AST_Node|string] the property to access. For AST_Dot & AST_DotHash this is always a plain string, while for AST_Sub it's an arbitrary AST_Node",
1705
1706 optional: "[boolean] whether this is an optional property access (IE ?.)"
1707 }
1708 }
1709);
1710
1711var AST_Dot = DEFNODE("Dot", "quote", function AST_Dot(props) {
1712 if (props) {
1713 this.quote = props.quote;
1714 this.expression = props.expression;
1715 this.property = props.property;
1716 this.optional = props.optional;
1717 this._annotations = props._annotations;
1718 this.start = props.start;
1719 this.end = props.end;
1720 }
1721
1722 this.flags = 0;
1723}, {
1724 $documentation: "A dotted property access expression",
1725 $propdoc: {
1726 quote: "[string] the original quote character when transformed from AST_Sub",
1727 },
1728 _walk: function(visitor) {
1729 return visitor._visit(this, function() {
1730 this.expression._walk(visitor);
1731 });
1732 },
1733 _children_backwards(push) {
1734 push(this.expression);
1735 },
1736}, AST_PropAccess);
1737
1738var AST_DotHash = DEFNODE("DotHash", "", function AST_DotHash(props) {
1739 if (props) {
1740 this.expression = props.expression;
1741 this.property = props.property;
1742 this.optional = props.optional;
1743 this.start = props.start;
1744 this.end = props.end;
1745 }
1746
1747 this.flags = 0;
1748}, {
1749 $documentation: "A dotted property access to a private property",
1750 _walk: function(visitor) {
1751 return visitor._visit(this, function() {
1752 this.expression._walk(visitor);
1753 });
1754 },
1755 _children_backwards(push) {
1756 push(this.expression);
1757 },
1758}, AST_PropAccess);
1759
1760var AST_Sub = DEFNODE("Sub", null, function AST_Sub(props) {
1761 if (props) {
1762 this.expression = props.expression;
1763 this.property = props.property;
1764 this.optional = props.optional;
1765 this._annotations = props._annotations;
1766 this.start = props.start;
1767 this.end = props.end;
1768 }
1769
1770 this.flags = 0;
1771}, {
1772 $documentation: "Index-style property access, i.e. `a[\"foo\"]`",
1773 _walk: function(visitor) {
1774 return visitor._visit(this, function() {
1775 this.expression._walk(visitor);
1776 this.property._walk(visitor);
1777 });
1778 },
1779 _children_backwards(push) {
1780 push(this.property);
1781 push(this.expression);
1782 },
1783}, AST_PropAccess);
1784
1785var AST_Chain = DEFNODE("Chain", "expression", function AST_Chain(props) {
1786 if (props) {
1787 this.expression = props.expression;
1788 this.start = props.start;
1789 this.end = props.end;
1790 }
1791
1792 this.flags = 0;
1793}, {
1794 $documentation: "A chain expression like a?.b?.(c)?.[d]",
1795 $propdoc: {
1796 expression: "[AST_Call|AST_Dot|AST_DotHash|AST_Sub] chain element."
1797 },
1798 _walk: function (visitor) {
1799 return visitor._visit(this, function() {
1800 this.expression._walk(visitor);
1801 });
1802 },
1803 _children_backwards(push) {
1804 push(this.expression);
1805 },
1806});
1807
1808var AST_Unary = DEFNODE("Unary", "operator expression", function AST_Unary(props) {
1809 if (props) {
1810 this.operator = props.operator;
1811 this.expression = props.expression;
1812 this.start = props.start;
1813 this.end = props.end;
1814 }
1815
1816 this.flags = 0;
1817}, {
1818 $documentation: "Base class for unary expressions",
1819 $propdoc: {
1820 operator: "[string] the operator",
1821 expression: "[AST_Node] expression that this unary operator applies to"
1822 },
1823 _walk: function(visitor) {
1824 return visitor._visit(this, function() {
1825 this.expression._walk(visitor);
1826 });
1827 },
1828 _children_backwards(push) {
1829 push(this.expression);
1830 },
1831});
1832
1833var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, function AST_UnaryPrefix(props) {
1834 if (props) {
1835 this.operator = props.operator;
1836 this.expression = props.expression;
1837 this.start = props.start;
1838 this.end = props.end;
1839 }
1840
1841 this.flags = 0;
1842}, {
1843 $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`"
1844}, AST_Unary);
1845
1846var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, function AST_UnaryPostfix(props) {
1847 if (props) {
1848 this.operator = props.operator;
1849 this.expression = props.expression;
1850 this.start = props.start;
1851 this.end = props.end;
1852 }
1853
1854 this.flags = 0;
1855}, {
1856 $documentation: "Unary postfix expression, i.e. `i++`"
1857}, AST_Unary);
1858
1859var AST_Binary = DEFNODE("Binary", "operator left right", function AST_Binary(props) {
1860 if (props) {
1861 this.operator = props.operator;
1862 this.left = props.left;
1863 this.right = props.right;
1864 this.start = props.start;
1865 this.end = props.end;
1866 }
1867
1868 this.flags = 0;
1869}, {
1870 $documentation: "Binary expression, i.e. `a + b`",
1871 $propdoc: {
1872 left: "[AST_Node] left-hand side expression",
1873 operator: "[string] the operator",
1874 right: "[AST_Node] right-hand side expression"
1875 },
1876 _walk: function(visitor) {
1877 return visitor._visit(this, function() {
1878 this.left._walk(visitor);
1879 this.right._walk(visitor);
1880 });
1881 },
1882 _children_backwards(push) {
1883 push(this.right);
1884 push(this.left);
1885 },
1886});
1887
1888var AST_Conditional = DEFNODE(
1889 "Conditional",
1890 "condition consequent alternative",
1891 function AST_Conditional(props) {
1892 if (props) {
1893 this.condition = props.condition;
1894 this.consequent = props.consequent;
1895 this.alternative = props.alternative;
1896 this.start = props.start;
1897 this.end = props.end;
1898 }
1899
1900 this.flags = 0;
1901 },
1902 {
1903 $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`",
1904 $propdoc: {
1905 condition: "[AST_Node]",
1906 consequent: "[AST_Node]",
1907 alternative: "[AST_Node]"
1908 },
1909 _walk: function(visitor) {
1910 return visitor._visit(this, function() {
1911 this.condition._walk(visitor);
1912 this.consequent._walk(visitor);
1913 this.alternative._walk(visitor);
1914 });
1915 },
1916 _children_backwards(push) {
1917 push(this.alternative);
1918 push(this.consequent);
1919 push(this.condition);
1920 },
1921 }
1922);
1923
1924var AST_Assign = DEFNODE("Assign", "logical", function AST_Assign(props) {
1925 if (props) {
1926 this.logical = props.logical;
1927 this.operator = props.operator;
1928 this.left = props.left;
1929 this.right = props.right;
1930 this.start = props.start;
1931 this.end = props.end;
1932 }
1933
1934 this.flags = 0;
1935}, {
1936 $documentation: "An assignment expression — `a = b + 5`",
1937 $propdoc: {
1938 logical: "Whether it's a logical assignment"
1939 }
1940}, AST_Binary);
1941
1942var AST_DefaultAssign = DEFNODE("DefaultAssign", null, function AST_DefaultAssign(props) {
1943 if (props) {
1944 this.operator = props.operator;
1945 this.left = props.left;
1946 this.right = props.right;
1947 this.start = props.start;
1948 this.end = props.end;
1949 }
1950
1951 this.flags = 0;
1952}, {
1953 $documentation: "A default assignment expression like in `(a = 3) => a`"
1954}, AST_Binary);
1955
1956/* -----[ LITERALS ]----- */
1957
1958var AST_Array = DEFNODE("Array", "elements", function AST_Array(props) {
1959 if (props) {
1960 this.elements = props.elements;
1961 this.start = props.start;
1962 this.end = props.end;
1963 }
1964
1965 this.flags = 0;
1966}, {
1967 $documentation: "An array literal",
1968 $propdoc: {
1969 elements: "[AST_Node*] array of elements"
1970 },
1971 _walk: function(visitor) {
1972 return visitor._visit(this, function() {
1973 var elements = this.elements;
1974 for (var i = 0, len = elements.length; i < len; i++) {
1975 elements[i]._walk(visitor);
1976 }
1977 });
1978 },
1979 _children_backwards(push) {
1980 let i = this.elements.length;
1981 while (i--) push(this.elements[i]);
1982 },
1983});
1984
1985var AST_Object = DEFNODE("Object", "properties", function AST_Object(props) {
1986 if (props) {
1987 this.properties = props.properties;
1988 this.start = props.start;
1989 this.end = props.end;
1990 }
1991
1992 this.flags = 0;
1993}, {
1994 $documentation: "An object literal",
1995 $propdoc: {
1996 properties: "[AST_ObjectProperty*] array of properties"
1997 },
1998 _walk: function(visitor) {
1999 return visitor._visit(this, function() {
2000 var properties = this.properties;
2001 for (var i = 0, len = properties.length; i < len; i++) {
2002 properties[i]._walk(visitor);
2003 }
2004 });
2005 },
2006 _children_backwards(push) {
2007 let i = this.properties.length;
2008 while (i--) push(this.properties[i]);
2009 },
2010});
2011
2012var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", function AST_ObjectProperty(props) {
2013 if (props) {
2014 this.key = props.key;
2015 this.value = props.value;
2016 this.start = props.start;
2017 this.end = props.end;
2018 this._annotations = props._annotations;
2019 }
2020
2021 this.flags = 0;
2022}, {
2023 $documentation: "Base class for literal object properties",
2024 $propdoc: {
2025 key: "[string|AST_Node] property name. For ObjectKeyVal this is a string. For getters, setters and computed property this is an AST_Node.",
2026 value: "[AST_Node] property value. For getters and setters this is an AST_Accessor."
2027 },
2028 _walk: function(visitor) {
2029 return visitor._visit(this, function() {
2030 if (this.key instanceof AST_Node)
2031 this.key._walk(visitor);
2032 this.value._walk(visitor);
2033 });
2034 },
2035 _children_backwards(push) {
2036 push(this.value);
2037 if (this.key instanceof AST_Node) push(this.key);
2038 }
2039});
2040
2041var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote", function AST_ObjectKeyVal(props) {
2042 if (props) {
2043 this.quote = props.quote;
2044 this.key = props.key;
2045 this.value = props.value;
2046 this.start = props.start;
2047 this.end = props.end;
2048 this._annotations = props._annotations;
2049 }
2050
2051 this.flags = 0;
2052}, {
2053 $documentation: "A key: value object property",
2054 $propdoc: {
2055 quote: "[string] the original quote character"
2056 },
2057 computed_key() {
2058 return this.key instanceof AST_Node;
2059 }
2060}, AST_ObjectProperty);
2061
2062var AST_PrivateSetter = DEFNODE("PrivateSetter", "static", function AST_PrivateSetter(props) {
2063 if (props) {
2064 this.static = props.static;
2065 this.key = props.key;
2066 this.value = props.value;
2067 this.start = props.start;
2068 this.end = props.end;
2069 }
2070
2071 this.flags = 0;
2072}, {
2073 $propdoc: {
2074 static: "[boolean] whether this is a static private setter"
2075 },
2076 $documentation: "A private setter property",
2077 computed_key() {
2078 return false;
2079 }
2080}, AST_ObjectProperty);
2081
2082var AST_PrivateGetter = DEFNODE("PrivateGetter", "static", function AST_PrivateGetter(props) {
2083 if (props) {
2084 this.static = props.static;
2085 this.key = props.key;
2086 this.value = props.value;
2087 this.start = props.start;
2088 this.end = props.end;
2089 }
2090
2091 this.flags = 0;
2092}, {
2093 $propdoc: {
2094 static: "[boolean] whether this is a static private getter"
2095 },
2096 $documentation: "A private getter property",
2097 computed_key() {
2098 return false;
2099 }
2100}, AST_ObjectProperty);
2101
2102var AST_ObjectSetter = DEFNODE("ObjectSetter", "quote static", function AST_ObjectSetter(props) {
2103 if (props) {
2104 this.quote = props.quote;
2105 this.static = props.static;
2106 this.key = props.key;
2107 this.value = props.value;
2108 this.start = props.start;
2109 this.end = props.end;
2110 this._annotations = props._annotations;
2111 }
2112
2113 this.flags = 0;
2114}, {
2115 $propdoc: {
2116 quote: "[string|undefined] the original quote character, if any",
2117 static: "[boolean] whether this is a static setter (classes only)"
2118 },
2119 $documentation: "An object setter property",
2120 computed_key() {
2121 return !(this.key instanceof AST_SymbolMethod);
2122 }
2123}, AST_ObjectProperty);
2124
2125var AST_ObjectGetter = DEFNODE("ObjectGetter", "quote static", function AST_ObjectGetter(props) {
2126 if (props) {
2127 this.quote = props.quote;
2128 this.static = props.static;
2129 this.key = props.key;
2130 this.value = props.value;
2131 this.start = props.start;
2132 this.end = props.end;
2133 this._annotations = props._annotations;
2134 }
2135
2136 this.flags = 0;
2137}, {
2138 $propdoc: {
2139 quote: "[string|undefined] the original quote character, if any",
2140 static: "[boolean] whether this is a static getter (classes only)"
2141 },
2142 $documentation: "An object getter property",
2143 computed_key() {
2144 return !(this.key instanceof AST_SymbolMethod);
2145 }
2146}, AST_ObjectProperty);
2147
2148var AST_ConciseMethod = DEFNODE(
2149 "ConciseMethod",
2150 "quote static is_generator async",
2151 function AST_ConciseMethod(props) {
2152 if (props) {
2153 this.quote = props.quote;
2154 this.static = props.static;
2155 this.is_generator = props.is_generator;
2156 this.async = props.async;
2157 this.key = props.key;
2158 this.value = props.value;
2159 this.start = props.start;
2160 this.end = props.end;
2161 this._annotations = props._annotations;
2162 }
2163
2164 this.flags = 0;
2165 },
2166 {
2167 $propdoc: {
2168 quote: "[string|undefined] the original quote character, if any",
2169 static: "[boolean] is this method static (classes only)",
2170 is_generator: "[boolean] is this a generator method",
2171 async: "[boolean] is this method async",
2172 },
2173 $documentation: "An ES6 concise method inside an object or class",
2174 computed_key() {
2175 return !(this.key instanceof AST_SymbolMethod);
2176 }
2177 },
2178 AST_ObjectProperty
2179);
2180
2181var AST_PrivateMethod = DEFNODE("PrivateMethod", "", function AST_PrivateMethod(props) {
2182 if (props) {
2183 this.quote = props.quote;
2184 this.static = props.static;
2185 this.is_generator = props.is_generator;
2186 this.async = props.async;
2187 this.key = props.key;
2188 this.value = props.value;
2189 this.start = props.start;
2190 this.end = props.end;
2191 }
2192
2193 this.flags = 0;
2194}, {
2195 $documentation: "A private class method inside a class",
2196}, AST_ConciseMethod);
2197
2198var AST_Class = DEFNODE("Class", "name extends properties", function AST_Class(props) {
2199 if (props) {
2200 this.name = props.name;
2201 this.extends = props.extends;
2202 this.properties = props.properties;
2203 this.variables = props.variables;
2204 this.uses_with = props.uses_with;
2205 this.uses_eval = props.uses_eval;
2206 this.parent_scope = props.parent_scope;
2207 this.enclosed = props.enclosed;
2208 this.cname = props.cname;
2209 this.body = props.body;
2210 this.block_scope = props.block_scope;
2211 this.start = props.start;
2212 this.end = props.end;
2213 }
2214
2215 this.flags = 0;
2216}, {
2217 $propdoc: {
2218 name: "[AST_SymbolClass|AST_SymbolDefClass?] optional class name.",
2219 extends: "[AST_Node]? optional parent class",
2220 properties: "[AST_ObjectProperty*] array of properties"
2221 },
2222 $documentation: "An ES6 class",
2223 _walk: function(visitor) {
2224 return visitor._visit(this, function() {
2225 if (this.name) {
2226 this.name._walk(visitor);
2227 }
2228 if (this.extends) {
2229 this.extends._walk(visitor);
2230 }
2231 this.properties.forEach((prop) => prop._walk(visitor));
2232 });
2233 },
2234 _children_backwards(push) {
2235 let i = this.properties.length;
2236 while (i--) push(this.properties[i]);
2237 if (this.extends) push(this.extends);
2238 if (this.name) push(this.name);
2239 },
2240 /** go through the bits that are executed instantly, not when the class is `new`'d. Doesn't walk the name. */
2241 visit_nondeferred_class_parts(visitor) {
2242 if (this.extends) {
2243 this.extends._walk(visitor);
2244 }
2245 this.properties.forEach((prop) => {
2246 if (prop instanceof AST_ClassStaticBlock) {
2247 prop._walk(visitor);
2248 return;
2249 }
2250 if (prop.computed_key()) {
2251 visitor.push(prop);
2252 prop.key._walk(visitor);
2253 visitor.pop();
2254 }
2255 if ((prop instanceof AST_ClassPrivateProperty || prop instanceof AST_ClassProperty) && prop.static && prop.value) {
2256 visitor.push(prop);
2257 prop.value._walk(visitor);
2258 visitor.pop();
2259 }
2260 });
2261 },
2262 /** go through the bits that are executed later, when the class is `new`'d or a static method is called */
2263 visit_deferred_class_parts(visitor) {
2264 this.properties.forEach((prop) => {
2265 if (prop instanceof AST_ConciseMethod) {
2266 prop.walk(visitor);
2267 } else if (prop instanceof AST_ClassProperty && !prop.static && prop.value) {
2268 visitor.push(prop);
2269 prop.value._walk(visitor);
2270 visitor.pop();
2271 }
2272 });
2273 },
2274 is_self_referential: function() {
2275 const this_id = this.name && this.name.definition().id;
2276 let found = false;
2277 let class_this = true;
2278 this.visit_nondeferred_class_parts(new TreeWalker((node, descend) => {
2279 if (found) return true;
2280 if (node instanceof AST_This) return (found = class_this);
2281 if (node instanceof AST_SymbolRef) return (found = node.definition().id === this_id);
2282 if (node instanceof AST_Lambda && !(node instanceof AST_Arrow)) {
2283 const class_this_save = class_this;
2284 class_this = false;
2285 descend();
2286 class_this = class_this_save;
2287 return true;
2288 }
2289 }));
2290 return found;
2291 },
2292}, AST_Scope /* TODO a class might have a scope but it's not a scope */);
2293
2294var AST_ClassProperty = DEFNODE("ClassProperty", "static quote", function AST_ClassProperty(props) {
2295 if (props) {
2296 this.static = props.static;
2297 this.quote = props.quote;
2298 this.key = props.key;
2299 this.value = props.value;
2300 this.start = props.start;
2301 this.end = props.end;
2302 this._annotations = props._annotations;
2303 }
2304
2305 this.flags = 0;
2306}, {
2307 $documentation: "A class property",
2308 $propdoc: {
2309 static: "[boolean] whether this is a static key",
2310 quote: "[string] which quote is being used"
2311 },
2312 _walk: function(visitor) {
2313 return visitor._visit(this, function() {
2314 if (this.key instanceof AST_Node)
2315 this.key._walk(visitor);
2316 if (this.value instanceof AST_Node)
2317 this.value._walk(visitor);
2318 });
2319 },
2320 _children_backwards(push) {
2321 if (this.value instanceof AST_Node) push(this.value);
2322 if (this.key instanceof AST_Node) push(this.key);
2323 },
2324 computed_key() {
2325 return !(this.key instanceof AST_SymbolClassProperty);
2326 }
2327}, AST_ObjectProperty);
2328
2329var AST_ClassPrivateProperty = DEFNODE("ClassPrivateProperty", "", function AST_ClassPrivateProperty(props) {
2330 if (props) {
2331 this.static = props.static;
2332 this.quote = props.quote;
2333 this.key = props.key;
2334 this.value = props.value;
2335 this.start = props.start;
2336 this.end = props.end;
2337 }
2338
2339 this.flags = 0;
2340}, {
2341 $documentation: "A class property for a private property",
2342}, AST_ClassProperty);
2343
2344var AST_PrivateIn = DEFNODE("PrivateIn", "key value", function AST_PrivateIn(props) {
2345 if (props) {
2346 this.key = props.key;
2347 this.value = props.value;
2348 this.start = props.start;
2349 this.end = props.end;
2350 }
2351
2352 this.flags = 0;
2353}, {
2354 $documentation: "An `in` binop when the key is private, eg #x in this",
2355 _walk: function(visitor) {
2356 return visitor._visit(this, function() {
2357 this.key._walk(visitor);
2358 this.value._walk(visitor);
2359 });
2360 },
2361 _children_backwards(push) {
2362 push(this.value);
2363 push(this.key);
2364 },
2365});
2366
2367var AST_DefClass = DEFNODE("DefClass", null, function AST_DefClass(props) {
2368 if (props) {
2369 this.name = props.name;
2370 this.extends = props.extends;
2371 this.properties = props.properties;
2372 this.variables = props.variables;
2373 this.uses_with = props.uses_with;
2374 this.uses_eval = props.uses_eval;
2375 this.parent_scope = props.parent_scope;
2376 this.enclosed = props.enclosed;
2377 this.cname = props.cname;
2378 this.body = props.body;
2379 this.block_scope = props.block_scope;
2380 this.start = props.start;
2381 this.end = props.end;
2382 }
2383
2384 this.flags = 0;
2385}, {
2386 $documentation: "A class definition",
2387}, AST_Class);
2388
2389var AST_ClassStaticBlock = DEFNODE("ClassStaticBlock", "body block_scope", function AST_ClassStaticBlock (props) {
2390 this.body = props.body;
2391 this.block_scope = props.block_scope;
2392 this.start = props.start;
2393 this.end = props.end;
2394}, {
2395 $documentation: "A block containing statements to be executed in the context of the class",
2396 $propdoc: {
2397 body: "[AST_Statement*] an array of statements",
2398 },
2399 _walk: function(visitor) {
2400 return visitor._visit(this, function() {
2401 walk_body(this, visitor);
2402 });
2403 },
2404 _children_backwards(push) {
2405 let i = this.body.length;
2406 while (i--) push(this.body[i]);
2407 },
2408 clone: clone_block_scope,
2409 computed_key: () => false
2410}, AST_Scope);
2411
2412var AST_ClassExpression = DEFNODE("ClassExpression", null, function AST_ClassExpression(props) {
2413 if (props) {
2414 this.name = props.name;
2415 this.extends = props.extends;
2416 this.properties = props.properties;
2417 this.variables = props.variables;
2418 this.uses_with = props.uses_with;
2419 this.uses_eval = props.uses_eval;
2420 this.parent_scope = props.parent_scope;
2421 this.enclosed = props.enclosed;
2422 this.cname = props.cname;
2423 this.body = props.body;
2424 this.block_scope = props.block_scope;
2425 this.start = props.start;
2426 this.end = props.end;
2427 }
2428
2429 this.flags = 0;
2430}, {
2431 $documentation: "A class expression."
2432}, AST_Class);
2433
2434var AST_Symbol = DEFNODE("Symbol", "scope name thedef", function AST_Symbol(props) {
2435 if (props) {
2436 this.scope = props.scope;
2437 this.name = props.name;
2438 this.thedef = props.thedef;
2439 this.start = props.start;
2440 this.end = props.end;
2441 }
2442
2443 this.flags = 0;
2444}, {
2445 $propdoc: {
2446 name: "[string] name of this symbol",
2447 scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
2448 thedef: "[SymbolDef/S] the definition of this symbol"
2449 },
2450 $documentation: "Base class for all symbols"
2451});
2452
2453var AST_NewTarget = DEFNODE("NewTarget", null, function AST_NewTarget(props) {
2454 if (props) {
2455 this.start = props.start;
2456 this.end = props.end;
2457 }
2458
2459 this.flags = 0;
2460}, {
2461 $documentation: "A reference to new.target"
2462});
2463
2464var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", function AST_SymbolDeclaration(props) {
2465 if (props) {
2466 this.init = props.init;
2467 this.scope = props.scope;
2468 this.name = props.name;
2469 this.thedef = props.thedef;
2470 this.start = props.start;
2471 this.end = props.end;
2472 }
2473
2474 this.flags = 0;
2475}, {
2476 $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
2477}, AST_Symbol);
2478
2479var AST_SymbolVar = DEFNODE("SymbolVar", null, function AST_SymbolVar(props) {
2480 if (props) {
2481 this.init = props.init;
2482 this.scope = props.scope;
2483 this.name = props.name;
2484 this.thedef = props.thedef;
2485 this.start = props.start;
2486 this.end = props.end;
2487 }
2488
2489 this.flags = 0;
2490}, {
2491 $documentation: "Symbol defining a variable",
2492}, AST_SymbolDeclaration);
2493
2494var AST_SymbolBlockDeclaration = DEFNODE(
2495 "SymbolBlockDeclaration",
2496 null,
2497 function AST_SymbolBlockDeclaration(props) {
2498 if (props) {
2499 this.init = props.init;
2500 this.scope = props.scope;
2501 this.name = props.name;
2502 this.thedef = props.thedef;
2503 this.start = props.start;
2504 this.end = props.end;
2505 }
2506
2507 this.flags = 0;
2508 },
2509 {
2510 $documentation: "Base class for block-scoped declaration symbols"
2511 },
2512 AST_SymbolDeclaration
2513);
2514
2515var AST_SymbolConst = DEFNODE("SymbolConst", null, function AST_SymbolConst(props) {
2516 if (props) {
2517 this.init = props.init;
2518 this.scope = props.scope;
2519 this.name = props.name;
2520 this.thedef = props.thedef;
2521 this.start = props.start;
2522 this.end = props.end;
2523 }
2524
2525 this.flags = 0;
2526}, {
2527 $documentation: "A constant declaration"
2528}, AST_SymbolBlockDeclaration);
2529
2530var AST_SymbolLet = DEFNODE("SymbolLet", null, function AST_SymbolLet(props) {
2531 if (props) {
2532 this.init = props.init;
2533 this.scope = props.scope;
2534 this.name = props.name;
2535 this.thedef = props.thedef;
2536 this.start = props.start;
2537 this.end = props.end;
2538 }
2539
2540 this.flags = 0;
2541}, {
2542 $documentation: "A block-scoped `let` declaration"
2543}, AST_SymbolBlockDeclaration);
2544
2545var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, function AST_SymbolFunarg(props) {
2546 if (props) {
2547 this.init = props.init;
2548 this.scope = props.scope;
2549 this.name = props.name;
2550 this.thedef = props.thedef;
2551 this.start = props.start;
2552 this.end = props.end;
2553 }
2554
2555 this.flags = 0;
2556}, {
2557 $documentation: "Symbol naming a function argument",
2558}, AST_SymbolVar);
2559
2560var AST_SymbolDefun = DEFNODE("SymbolDefun", null, function AST_SymbolDefun(props) {
2561 if (props) {
2562 this.init = props.init;
2563 this.scope = props.scope;
2564 this.name = props.name;
2565 this.thedef = props.thedef;
2566 this.start = props.start;
2567 this.end = props.end;
2568 }
2569
2570 this.flags = 0;
2571}, {
2572 $documentation: "Symbol defining a function",
2573}, AST_SymbolDeclaration);
2574
2575var AST_SymbolMethod = DEFNODE("SymbolMethod", null, function AST_SymbolMethod(props) {
2576 if (props) {
2577 this.scope = props.scope;
2578 this.name = props.name;
2579 this.thedef = props.thedef;
2580 this.start = props.start;
2581 this.end = props.end;
2582 }
2583
2584 this.flags = 0;
2585}, {
2586 $documentation: "Symbol in an object defining a method",
2587}, AST_Symbol);
2588
2589var AST_SymbolClassProperty = DEFNODE("SymbolClassProperty", null, function AST_SymbolClassProperty(props) {
2590 if (props) {
2591 this.scope = props.scope;
2592 this.name = props.name;
2593 this.thedef = props.thedef;
2594 this.start = props.start;
2595 this.end = props.end;
2596 }
2597
2598 this.flags = 0;
2599}, {
2600 $documentation: "Symbol for a class property",
2601}, AST_Symbol);
2602
2603var AST_SymbolLambda = DEFNODE("SymbolLambda", null, function AST_SymbolLambda(props) {
2604 if (props) {
2605 this.init = props.init;
2606 this.scope = props.scope;
2607 this.name = props.name;
2608 this.thedef = props.thedef;
2609 this.start = props.start;
2610 this.end = props.end;
2611 }
2612
2613 this.flags = 0;
2614}, {
2615 $documentation: "Symbol naming a function expression",
2616}, AST_SymbolDeclaration);
2617
2618var AST_SymbolDefClass = DEFNODE("SymbolDefClass", null, function AST_SymbolDefClass(props) {
2619 if (props) {
2620 this.init = props.init;
2621 this.scope = props.scope;
2622 this.name = props.name;
2623 this.thedef = props.thedef;
2624 this.start = props.start;
2625 this.end = props.end;
2626 }
2627
2628 this.flags = 0;
2629}, {
2630 $documentation: "Symbol naming a class's name in a class declaration. Lexically scoped to its containing scope, and accessible within the class."
2631}, AST_SymbolBlockDeclaration);
2632
2633var AST_SymbolClass = DEFNODE("SymbolClass", null, function AST_SymbolClass(props) {
2634 if (props) {
2635 this.init = props.init;
2636 this.scope = props.scope;
2637 this.name = props.name;
2638 this.thedef = props.thedef;
2639 this.start = props.start;
2640 this.end = props.end;
2641 }
2642
2643 this.flags = 0;
2644}, {
2645 $documentation: "Symbol naming a class's name. Lexically scoped to the class."
2646}, AST_SymbolDeclaration);
2647
2648var AST_SymbolCatch = DEFNODE("SymbolCatch", null, function AST_SymbolCatch(props) {
2649 if (props) {
2650 this.init = props.init;
2651 this.scope = props.scope;
2652 this.name = props.name;
2653 this.thedef = props.thedef;
2654 this.start = props.start;
2655 this.end = props.end;
2656 }
2657
2658 this.flags = 0;
2659}, {
2660 $documentation: "Symbol naming the exception in catch",
2661}, AST_SymbolBlockDeclaration);
2662
2663var AST_SymbolImport = DEFNODE("SymbolImport", null, function AST_SymbolImport(props) {
2664 if (props) {
2665 this.init = props.init;
2666 this.scope = props.scope;
2667 this.name = props.name;
2668 this.thedef = props.thedef;
2669 this.start = props.start;
2670 this.end = props.end;
2671 }
2672
2673 this.flags = 0;
2674}, {
2675 $documentation: "Symbol referring to an imported name",
2676}, AST_SymbolBlockDeclaration);
2677
2678var AST_SymbolImportForeign = DEFNODE("SymbolImportForeign", null, function AST_SymbolImportForeign(props) {
2679 if (props) {
2680 this.scope = props.scope;
2681 this.name = props.name;
2682 this.thedef = props.thedef;
2683 this.quote = props.quote;
2684 this.start = props.start;
2685 this.end = props.end;
2686 }
2687
2688 this.flags = 0;
2689}, {
2690 $documentation: "A symbol imported from a module, but it is defined in the other module, and its real name is irrelevant for this module's purposes",
2691}, AST_Symbol);
2692
2693var AST_Label = DEFNODE("Label", "references", function AST_Label(props) {
2694 if (props) {
2695 this.references = props.references;
2696 this.scope = props.scope;
2697 this.name = props.name;
2698 this.thedef = props.thedef;
2699 this.start = props.start;
2700 this.end = props.end;
2701 this.initialize();
2702 }
2703
2704 this.flags = 0;
2705}, {
2706 $documentation: "Symbol naming a label (declaration)",
2707 $propdoc: {
2708 references: "[AST_LoopControl*] a list of nodes referring to this label"
2709 },
2710 initialize: function() {
2711 this.references = [];
2712 this.thedef = this;
2713 }
2714}, AST_Symbol);
2715
2716var AST_SymbolRef = DEFNODE("SymbolRef", null, function AST_SymbolRef(props) {
2717 if (props) {
2718 this.scope = props.scope;
2719 this.name = props.name;
2720 this.thedef = props.thedef;
2721 this.start = props.start;
2722 this.end = props.end;
2723 }
2724
2725 this.flags = 0;
2726}, {
2727 $documentation: "Reference to some symbol (not definition/declaration)",
2728}, AST_Symbol);
2729
2730var AST_SymbolExport = DEFNODE("SymbolExport", null, function AST_SymbolExport(props) {
2731 if (props) {
2732 this.scope = props.scope;
2733 this.name = props.name;
2734 this.thedef = props.thedef;
2735 this.quote = props.quote;
2736 this.start = props.start;
2737 this.end = props.end;
2738 }
2739
2740 this.flags = 0;
2741}, {
2742 $documentation: "Symbol referring to a name to export",
2743}, AST_SymbolRef);
2744
2745var AST_SymbolExportForeign = DEFNODE("SymbolExportForeign", null, function AST_SymbolExportForeign(props) {
2746 if (props) {
2747 this.scope = props.scope;
2748 this.name = props.name;
2749 this.thedef = props.thedef;
2750 this.quote = props.quote;
2751 this.start = props.start;
2752 this.end = props.end;
2753 }
2754
2755 this.flags = 0;
2756}, {
2757 $documentation: "A symbol exported from this module, but it is used in the other module, and its real name is irrelevant for this module's purposes",
2758}, AST_Symbol);
2759
2760var AST_LabelRef = DEFNODE("LabelRef", null, function AST_LabelRef(props) {
2761 if (props) {
2762 this.scope = props.scope;
2763 this.name = props.name;
2764 this.thedef = props.thedef;
2765 this.start = props.start;
2766 this.end = props.end;
2767 }
2768
2769 this.flags = 0;
2770}, {
2771 $documentation: "Reference to a label symbol",
2772}, AST_Symbol);
2773
2774var AST_SymbolPrivateProperty = DEFNODE("SymbolPrivateProperty", null, function AST_SymbolPrivateProperty(props) {
2775 if (props) {
2776 this.scope = props.scope;
2777 this.name = props.name;
2778 this.thedef = props.thedef;
2779 this.start = props.start;
2780 this.end = props.end;
2781 }
2782
2783 this.flags = 0;
2784}, {
2785 $documentation: "A symbol that refers to a private property",
2786}, AST_Symbol);
2787
2788var AST_This = DEFNODE("This", null, function AST_This(props) {
2789 if (props) {
2790 this.scope = props.scope;
2791 this.name = props.name;
2792 this.thedef = props.thedef;
2793 this.start = props.start;
2794 this.end = props.end;
2795 }
2796
2797 this.flags = 0;
2798}, {
2799 $documentation: "The `this` symbol",
2800}, AST_Symbol);
2801
2802var AST_Super = DEFNODE("Super", null, function AST_Super(props) {
2803 if (props) {
2804 this.scope = props.scope;
2805 this.name = props.name;
2806 this.thedef = props.thedef;
2807 this.start = props.start;
2808 this.end = props.end;
2809 }
2810
2811 this.flags = 0;
2812}, {
2813 $documentation: "The `super` symbol",
2814}, AST_This);
2815
2816var AST_Constant = DEFNODE("Constant", null, function AST_Constant(props) {
2817 if (props) {
2818 this.start = props.start;
2819 this.end = props.end;
2820 }
2821
2822 this.flags = 0;
2823}, {
2824 $documentation: "Base class for all constants",
2825 getValue: function() {
2826 return this.value;
2827 }
2828});
2829
2830var AST_String = DEFNODE("String", "value quote", function AST_String(props) {
2831 if (props) {
2832 this.value = props.value;
2833 this.quote = props.quote;
2834 this.start = props.start;
2835 this.end = props.end;
2836 this._annotations = props._annotations;
2837 }
2838
2839 this.flags = 0;
2840}, {
2841 $documentation: "A string literal",
2842 $propdoc: {
2843 value: "[string] the contents of this string",
2844 quote: "[string] the original quote character"
2845 }
2846}, AST_Constant);
2847
2848var AST_Number = DEFNODE("Number", "value raw", function AST_Number(props) {
2849 if (props) {
2850 this.value = props.value;
2851 this.raw = props.raw;
2852 this.start = props.start;
2853 this.end = props.end;
2854 }
2855
2856 this.flags = 0;
2857}, {
2858 $documentation: "A number literal",
2859 $propdoc: {
2860 value: "[number] the numeric value",
2861 raw: "[string] numeric value as string"
2862 }
2863}, AST_Constant);
2864
2865var AST_BigInt = DEFNODE("BigInt", "value", function AST_BigInt(props) {
2866 if (props) {
2867 this.value = props.value;
2868 this.start = props.start;
2869 this.end = props.end;
2870 }
2871
2872 this.flags = 0;
2873}, {
2874 $documentation: "A big int literal",
2875 $propdoc: {
2876 value: "[string] big int value"
2877 }
2878}, AST_Constant);
2879
2880var AST_RegExp = DEFNODE("RegExp", "value", function AST_RegExp(props) {
2881 if (props) {
2882 this.value = props.value;
2883 this.start = props.start;
2884 this.end = props.end;
2885 }
2886
2887 this.flags = 0;
2888}, {
2889 $documentation: "A regexp literal",
2890 $propdoc: {
2891 value: "[RegExp] the actual regexp",
2892 }
2893}, AST_Constant);
2894
2895var AST_Atom = DEFNODE("Atom", null, function AST_Atom(props) {
2896 if (props) {
2897 this.start = props.start;
2898 this.end = props.end;
2899 }
2900
2901 this.flags = 0;
2902}, {
2903 $documentation: "Base class for atoms",
2904}, AST_Constant);
2905
2906var AST_Null = DEFNODE("Null", null, function AST_Null(props) {
2907 if (props) {
2908 this.start = props.start;
2909 this.end = props.end;
2910 }
2911
2912 this.flags = 0;
2913}, {
2914 $documentation: "The `null` atom",
2915 value: null
2916}, AST_Atom);
2917
2918var AST_NaN = DEFNODE("NaN", null, function AST_NaN(props) {
2919 if (props) {
2920 this.start = props.start;
2921 this.end = props.end;
2922 }
2923
2924 this.flags = 0;
2925}, {
2926 $documentation: "The impossible value",
2927 value: 0/0
2928}, AST_Atom);
2929
2930var AST_Undefined = DEFNODE("Undefined", null, function AST_Undefined(props) {
2931 if (props) {
2932 this.start = props.start;
2933 this.end = props.end;
2934 }
2935
2936 this.flags = 0;
2937}, {
2938 $documentation: "The `undefined` value",
2939 value: (function() {}())
2940}, AST_Atom);
2941
2942var AST_Hole = DEFNODE("Hole", null, function AST_Hole(props) {
2943 if (props) {
2944 this.start = props.start;
2945 this.end = props.end;
2946 }
2947
2948 this.flags = 0;
2949}, {
2950 $documentation: "A hole in an array",
2951 value: (function() {}())
2952}, AST_Atom);
2953
2954var AST_Infinity = DEFNODE("Infinity", null, function AST_Infinity(props) {
2955 if (props) {
2956 this.start = props.start;
2957 this.end = props.end;
2958 }
2959
2960 this.flags = 0;
2961}, {
2962 $documentation: "The `Infinity` value",
2963 value: 1/0
2964}, AST_Atom);
2965
2966var AST_Boolean = DEFNODE("Boolean", null, function AST_Boolean(props) {
2967 if (props) {
2968 this.start = props.start;
2969 this.end = props.end;
2970 }
2971
2972 this.flags = 0;
2973}, {
2974 $documentation: "Base class for booleans",
2975}, AST_Atom);
2976
2977var AST_False = DEFNODE("False", null, function AST_False(props) {
2978 if (props) {
2979 this.start = props.start;
2980 this.end = props.end;
2981 }
2982
2983 this.flags = 0;
2984}, {
2985 $documentation: "The `false` atom",
2986 value: false
2987}, AST_Boolean);
2988
2989var AST_True = DEFNODE("True", null, function AST_True(props) {
2990 if (props) {
2991 this.start = props.start;
2992 this.end = props.end;
2993 }
2994
2995 this.flags = 0;
2996}, {
2997 $documentation: "The `true` atom",
2998 value: true
2999}, AST_Boolean);
3000
3001/* -----[ Walk function ]---- */
3002
3003/**
3004 * Walk nodes in depth-first search fashion.
3005 * Callback can return `walk_abort` symbol to stop iteration.
3006 * It can also return `true` to stop iteration just for child nodes.
3007 * Iteration can be stopped and continued by passing the `to_visit` argument,
3008 * which is given to the callback in the second argument.
3009 **/
3010function walk(node, cb, to_visit = [node]) {
3011 const push = to_visit.push.bind(to_visit);
3012 while (to_visit.length) {
3013 const node = to_visit.pop();
3014 const ret = cb(node, to_visit);
3015
3016 if (ret) {
3017 if (ret === walk_abort) return true;
3018 continue;
3019 }
3020
3021 node._children_backwards(push);
3022 }
3023 return false;
3024}
3025
3026/**
3027 * Walks an AST node and its children.
3028 *
3029 * {cb} can return `walk_abort` to interrupt the walk.
3030 *
3031 * @param node
3032 * @param cb {(node, info: { parent: (nth) => any }) => (boolean | undefined)}
3033 *
3034 * @returns {boolean} whether the walk was aborted
3035 *
3036 * @example
3037 * const found_some_cond = walk_parent(my_ast_node, (node, { parent }) => {
3038 * if (some_cond(node, parent())) return walk_abort
3039 * });
3040 */
3041function walk_parent(node, cb, initial_stack) {
3042 const to_visit = [node];
3043 const push = to_visit.push.bind(to_visit);
3044 const stack = initial_stack ? initial_stack.slice() : [];
3045 const parent_pop_indices = [];
3046
3047 let current;
3048
3049 const info = {
3050 parent: (n = 0) => {
3051 if (n === -1) {
3052 return current;
3053 }
3054
3055 // [ p1 p0 ] [ 1 0 ]
3056 if (initial_stack && n >= stack.length) {
3057 n -= stack.length;
3058 return initial_stack[
3059 initial_stack.length - (n + 1)
3060 ];
3061 }
3062
3063 return stack[stack.length - (1 + n)];
3064 },
3065 };
3066
3067 while (to_visit.length) {
3068 current = to_visit.pop();
3069
3070 while (
3071 parent_pop_indices.length &&
3072 to_visit.length == parent_pop_indices[parent_pop_indices.length - 1]
3073 ) {
3074 stack.pop();
3075 parent_pop_indices.pop();
3076 }
3077
3078 const ret = cb(current, info);
3079
3080 if (ret) {
3081 if (ret === walk_abort) return true;
3082 continue;
3083 }
3084
3085 const visit_length = to_visit.length;
3086
3087 current._children_backwards(push);
3088
3089 // Push only if we're going to traverse the children
3090 if (to_visit.length > visit_length) {
3091 stack.push(current);
3092 parent_pop_indices.push(visit_length - 1);
3093 }
3094 }
3095
3096 return false;
3097}
3098
3099const walk_abort = Symbol("abort walk");
3100
3101/* -----[ TreeWalker ]----- */
3102
3103class TreeWalker {
3104 constructor(callback) {
3105 this.visit = callback;
3106 this.stack = [];
3107 this.directives = Object.create(null);
3108 }
3109
3110 _visit(node, descend) {
3111 this.push(node);
3112 var ret = this.visit(node, descend ? function() {
3113 descend.call(node);
3114 } : noop);
3115 if (!ret && descend) {
3116 descend.call(node);
3117 }
3118 this.pop();
3119 return ret;
3120 }
3121
3122 parent(n) {
3123 return this.stack[this.stack.length - 2 - (n || 0)];
3124 }
3125
3126 push(node) {
3127 if (node instanceof AST_Lambda) {
3128 this.directives = Object.create(this.directives);
3129 } else if (node instanceof AST_Directive && !this.directives[node.value]) {
3130 this.directives[node.value] = node;
3131 } else if (node instanceof AST_Class) {
3132 this.directives = Object.create(this.directives);
3133 if (!this.directives["use strict"]) {
3134 this.directives["use strict"] = node;
3135 }
3136 }
3137 this.stack.push(node);
3138 }
3139
3140 pop() {
3141 var node = this.stack.pop();
3142 if (node instanceof AST_Lambda || node instanceof AST_Class) {
3143 this.directives = Object.getPrototypeOf(this.directives);
3144 }
3145 }
3146
3147 self() {
3148 return this.stack[this.stack.length - 1];
3149 }
3150
3151 find_parent(type) {
3152 var stack = this.stack;
3153 for (var i = stack.length; --i >= 0;) {
3154 var x = stack[i];
3155 if (x instanceof type) return x;
3156 }
3157 }
3158
3159 find_scope() {
3160 var stack = this.stack;
3161 for (var i = stack.length; --i >= 0;) {
3162 const p = stack[i];
3163 if (p instanceof AST_Toplevel) return p;
3164 if (p instanceof AST_Lambda) return p;
3165 if (p.block_scope) return p.block_scope;
3166 }
3167 }
3168
3169 has_directive(type) {
3170 var dir = this.directives[type];
3171 if (dir) return dir;
3172 var node = this.stack[this.stack.length - 1];
3173 if (node instanceof AST_Scope && node.body) {
3174 for (var i = 0; i < node.body.length; ++i) {
3175 var st = node.body[i];
3176 if (!(st instanceof AST_Directive)) break;
3177 if (st.value == type) return st;
3178 }
3179 }
3180 }
3181
3182 loopcontrol_target(node) {
3183 var stack = this.stack;
3184 if (node.label) for (var i = stack.length; --i >= 0;) {
3185 var x = stack[i];
3186 if (x instanceof AST_LabeledStatement && x.label.name == node.label.name)
3187 return x.body;
3188 } else for (var i = stack.length; --i >= 0;) {
3189 var x = stack[i];
3190 if (x instanceof AST_IterationStatement
3191 || node instanceof AST_Break && x instanceof AST_Switch)
3192 return x;
3193 }
3194 }
3195}
3196
3197// Tree transformer helpers.
3198class TreeTransformer extends TreeWalker {
3199 constructor(before, after) {
3200 super();
3201 this.before = before;
3202 this.after = after;
3203 }
3204}
3205
3206const _PURE = 0b00000001;
3207const _INLINE = 0b00000010;
3208const _NOINLINE = 0b00000100;
3209const _KEY = 0b00001000;
3210const _MANGLEPROP = 0b00010000;
3211
3212export {
3213 AST_Accessor,
3214 AST_Array,
3215 AST_Arrow,
3216 AST_Assign,
3217 AST_Atom,
3218 AST_Await,
3219 AST_BigInt,
3220 AST_Binary,
3221 AST_Block,
3222 AST_BlockStatement,
3223 AST_Boolean,
3224 AST_Break,
3225 AST_Call,
3226 AST_Case,
3227 AST_Catch,
3228 AST_Chain,
3229 AST_Class,
3230 AST_ClassExpression,
3231 AST_ClassPrivateProperty,
3232 AST_PrivateIn,
3233 AST_ClassProperty,
3234 AST_ClassStaticBlock,
3235 AST_ConciseMethod,
3236 AST_Conditional,
3237 AST_Const,
3238 AST_Constant,
3239 AST_Continue,
3240 AST_Debugger,
3241 AST_Default,
3242 AST_DefaultAssign,
3243 AST_DefClass,
3244 AST_Definitions,
3245 AST_Defun,
3246 AST_Destructuring,
3247 AST_Directive,
3248 AST_Do,
3249 AST_Dot,
3250 AST_DotHash,
3251 AST_DWLoop,
3252 AST_EmptyStatement,
3253 AST_Exit,
3254 AST_Expansion,
3255 AST_Export,
3256 AST_False,
3257 AST_Finally,
3258 AST_For,
3259 AST_ForIn,
3260 AST_ForOf,
3261 AST_Function,
3262 AST_Hole,
3263 AST_If,
3264 AST_Import,
3265 AST_ImportMeta,
3266 AST_Infinity,
3267 AST_IterationStatement,
3268 AST_Jump,
3269 AST_Label,
3270 AST_LabeledStatement,
3271 AST_LabelRef,
3272 AST_Lambda,
3273 AST_Let,
3274 AST_LoopControl,
3275 AST_NameMapping,
3276 AST_NaN,
3277 AST_New,
3278 AST_NewTarget,
3279 AST_Node,
3280 AST_Null,
3281 AST_Number,
3282 AST_Object,
3283 AST_ObjectGetter,
3284 AST_ObjectKeyVal,
3285 AST_ObjectProperty,
3286 AST_ObjectSetter,
3287 AST_PrefixedTemplateString,
3288 AST_PrivateGetter,
3289 AST_PrivateMethod,
3290 AST_PrivateSetter,
3291 AST_PropAccess,
3292 AST_RegExp,
3293 AST_Return,
3294 AST_Scope,
3295 AST_Sequence,
3296 AST_SimpleStatement,
3297 AST_Statement,
3298 AST_StatementWithBody,
3299 AST_String,
3300 AST_Sub,
3301 AST_Super,
3302 AST_Switch,
3303 AST_SwitchBranch,
3304 AST_Symbol,
3305 AST_SymbolBlockDeclaration,
3306 AST_SymbolCatch,
3307 AST_SymbolClass,
3308 AST_SymbolClassProperty,
3309 AST_SymbolConst,
3310 AST_SymbolDeclaration,
3311 AST_SymbolDefClass,
3312 AST_SymbolDefun,
3313 AST_SymbolExport,
3314 AST_SymbolExportForeign,
3315 AST_SymbolFunarg,
3316 AST_SymbolImport,
3317 AST_SymbolImportForeign,
3318 AST_SymbolLambda,
3319 AST_SymbolLet,
3320 AST_SymbolMethod,
3321 AST_SymbolRef,
3322 AST_SymbolVar,
3323 AST_TemplateSegment,
3324 AST_TemplateString,
3325 AST_SymbolPrivateProperty,
3326 AST_This,
3327 AST_Throw,
3328 AST_Token,
3329 AST_Toplevel,
3330 AST_True,
3331 AST_Try,
3332 AST_TryBlock,
3333 AST_Unary,
3334 AST_UnaryPostfix,
3335 AST_UnaryPrefix,
3336 AST_Undefined,
3337 AST_Var,
3338 AST_VarDef,
3339 AST_While,
3340 AST_With,
3341 AST_Yield,
3342
3343 // Walkers
3344 TreeTransformer,
3345 TreeWalker,
3346 walk,
3347 walk_abort,
3348 walk_body,
3349 walk_parent,
3350
3351 // annotations
3352 _INLINE,
3353 _NOINLINE,
3354 _PURE,
3355 _KEY,
3356 _MANGLEPROP,
3357};
Note: See TracBrowser for help on using the repository browser.