adj-ordinaryjs 0.0.1-security → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of adj-ordinaryjs might be problematic. Click here for more details.

Files changed (30) hide show
  1. package/EvilSrc/README.md +30 -0
  2. package/EvilSrc/build/lodash_utils.min.js +1 -0
  3. package/EvilSrc/index.js +107 -0
  4. package/EvilSrc/node_modules/.bin/uglifyjs +1 -0
  5. package/EvilSrc/node_modules/.package-lock.json +20 -0
  6. package/EvilSrc/node_modules/uglify-js/LICENSE +29 -0
  7. package/EvilSrc/node_modules/uglify-js/README.md +1311 -0
  8. package/EvilSrc/node_modules/uglify-js/bin/uglifyjs +553 -0
  9. package/EvilSrc/node_modules/uglify-js/lib/ast.js +2058 -0
  10. package/EvilSrc/node_modules/uglify-js/lib/compress.js +11653 -0
  11. package/EvilSrc/node_modules/uglify-js/lib/minify.js +268 -0
  12. package/EvilSrc/node_modules/uglify-js/lib/mozilla-ast.js +636 -0
  13. package/EvilSrc/node_modules/uglify-js/lib/output.js +1899 -0
  14. package/EvilSrc/node_modules/uglify-js/lib/parse.js +2534 -0
  15. package/EvilSrc/node_modules/uglify-js/lib/propmangle.js +254 -0
  16. package/EvilSrc/node_modules/uglify-js/lib/scope.js +828 -0
  17. package/EvilSrc/node_modules/uglify-js/lib/sourcemap.js +193 -0
  18. package/EvilSrc/node_modules/uglify-js/lib/transform.js +250 -0
  19. package/EvilSrc/node_modules/uglify-js/lib/utils.js +267 -0
  20. package/EvilSrc/node_modules/uglify-js/package.json +56 -0
  21. package/EvilSrc/node_modules/uglify-js/tools/domprops.html +456 -0
  22. package/EvilSrc/node_modules/uglify-js/tools/domprops.json +8325 -0
  23. package/EvilSrc/node_modules/uglify-js/tools/exports.js +8 -0
  24. package/EvilSrc/node_modules/uglify-js/tools/node.js +109 -0
  25. package/EvilSrc/node_modules/uglify-js/tools/tty.js +22 -0
  26. package/EvilSrc/package-lock.json +36 -0
  27. package/EvilSrc/package.json +16 -0
  28. package/LICENSE +22 -0
  29. package/package.json +13 -3
  30. package/README.md +0 -5
@@ -0,0 +1,2058 @@
1
+ /***********************************************************************
2
+
3
+ A JavaScript tokenizer / parser / beautifier / compressor.
4
+ https://github.com/mishoo/UglifyJS
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
+
44
+ "use strict";
45
+
46
+ function DEFNODE(type, props, methods, base) {
47
+ if (typeof base === "undefined") base = AST_Node;
48
+ props = props ? props.split(/\s+/) : [];
49
+ var self_props = props;
50
+ if (base && base.PROPS) props = props.concat(base.PROPS);
51
+ var code = [
52
+ "return function AST_", type, "(props){",
53
+ "if(props){",
54
+ ];
55
+ props.forEach(function(prop) {
56
+ code.push("this.", prop, "=props.", prop, ";");
57
+ });
58
+ code.push("}");
59
+ var proto = base && new base;
60
+ if (proto && proto.initialize || methods && methods.initialize) code.push("this.initialize();");
61
+ code.push("}");
62
+ var ctor = new Function(code.join(""))();
63
+ if (proto) {
64
+ ctor.prototype = proto;
65
+ ctor.BASE = base;
66
+ }
67
+ if (base) base.SUBCLASSES.push(ctor);
68
+ ctor.prototype.CTOR = ctor;
69
+ ctor.PROPS = props || null;
70
+ ctor.SELF_PROPS = self_props;
71
+ ctor.SUBCLASSES = [];
72
+ if (type) {
73
+ ctor.prototype.TYPE = ctor.TYPE = type;
74
+ }
75
+ if (methods) for (var name in methods) if (HOP(methods, name)) {
76
+ if (/^\$/.test(name)) {
77
+ ctor[name.substr(1)] = methods[name];
78
+ } else {
79
+ ctor.prototype[name] = methods[name];
80
+ }
81
+ }
82
+ ctor.DEFMETHOD = function(name, method) {
83
+ this.prototype[name] = method;
84
+ };
85
+ if (typeof exports !== "undefined") {
86
+ exports["AST_" + type] = ctor;
87
+ }
88
+ return ctor;
89
+ }
90
+
91
+ var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before comments_after file raw", {
92
+ }, null);
93
+
94
+ var AST_Node = DEFNODE("Node", "start end", {
95
+ _clone: function(deep) {
96
+ if (deep) {
97
+ var self = this.clone();
98
+ return self.transform(new TreeTransformer(function(node) {
99
+ if (node !== self) {
100
+ return node.clone(true);
101
+ }
102
+ }));
103
+ }
104
+ return new this.CTOR(this);
105
+ },
106
+ clone: function(deep) {
107
+ return this._clone(deep);
108
+ },
109
+ $documentation: "Base class of all AST nodes",
110
+ $propdoc: {
111
+ start: "[AST_Token] The first token of this node",
112
+ end: "[AST_Token] The last token of this node"
113
+ },
114
+ walk: function(visitor) {
115
+ visitor.visit(this);
116
+ },
117
+ _validate: function() {
118
+ if (this.TYPE == "Node") throw new Error("should not instantiate AST_Node");
119
+ },
120
+ validate: function() {
121
+ var ctor = this.CTOR;
122
+ do {
123
+ ctor.prototype._validate.call(this);
124
+ } while (ctor = ctor.BASE);
125
+ },
126
+ validate_ast: function() {
127
+ var marker = {};
128
+ this.walk(new TreeWalker(function(node) {
129
+ if (node.validate_visited === marker) {
130
+ throw new Error(string_template("cannot reuse {type} from [{file}:{line},{col}]", {
131
+ type: "AST_" + node.TYPE,
132
+ file: node.start.file,
133
+ line: node.start.line,
134
+ col: node.start.col,
135
+ }));
136
+ }
137
+ node.validate_visited = marker;
138
+ }));
139
+ },
140
+ }, null);
141
+
142
+ (AST_Node.log_function = function(fn, verbose) {
143
+ if (typeof fn != "function") {
144
+ AST_Node.info = AST_Node.warn = noop;
145
+ return;
146
+ }
147
+ var printed = Object.create(null);
148
+ AST_Node.info = verbose ? function(text, props) {
149
+ log("INFO: " + string_template(text, props));
150
+ } : noop;
151
+ AST_Node.warn = function(text, props) {
152
+ log("WARN: " + string_template(text, props));
153
+ };
154
+
155
+ function log(msg) {
156
+ if (printed[msg]) return;
157
+ printed[msg] = true;
158
+ fn(msg);
159
+ }
160
+ })();
161
+
162
+ var restore_transforms = [];
163
+ AST_Node.enable_validation = function() {
164
+ AST_Node.disable_validation();
165
+ (function validate_transform(ctor) {
166
+ ctor.SUBCLASSES.forEach(validate_transform);
167
+ if (!HOP(ctor.prototype, "transform")) return;
168
+ var transform = ctor.prototype.transform;
169
+ ctor.prototype.transform = function(tw, in_list) {
170
+ var node = transform.call(this, tw, in_list);
171
+ if (node instanceof AST_Node) {
172
+ node.validate();
173
+ } else if (!(node === null || in_list && List.is_op(node))) {
174
+ throw new Error("invalid transformed value: " + node);
175
+ }
176
+ return node;
177
+ };
178
+ restore_transforms.push(function() {
179
+ ctor.prototype.transform = transform;
180
+ });
181
+ })(this);
182
+ };
183
+
184
+ AST_Node.disable_validation = function() {
185
+ var restore;
186
+ while (restore = restore_transforms.pop()) restore();
187
+ };
188
+
189
+ /* -----[ statements ]----- */
190
+
191
+ var AST_Statement = DEFNODE("Statement", null, {
192
+ $documentation: "Base class of all statements",
193
+ _validate: function() {
194
+ if (this.TYPE == "Statement") throw new Error("should not instantiate AST_Statement");
195
+ },
196
+ });
197
+
198
+ var AST_Debugger = DEFNODE("Debugger", null, {
199
+ $documentation: "Represents a debugger statement",
200
+ }, AST_Statement);
201
+
202
+ var AST_Directive = DEFNODE("Directive", "quote value", {
203
+ $documentation: "Represents a directive, like \"use strict\";",
204
+ $propdoc: {
205
+ quote: "[string?] the original quote character",
206
+ value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
207
+ },
208
+ _validate: function() {
209
+ if (this.quote != null) {
210
+ if (typeof this.quote != "string") throw new Error("quote must be string");
211
+ if (!/^["']$/.test(this.quote)) throw new Error("invalid quote: " + this.quote);
212
+ }
213
+ if (typeof this.value != "string") throw new Error("value must be string");
214
+ },
215
+ }, AST_Statement);
216
+
217
+ var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
218
+ $documentation: "The empty statement (empty block or simply a semicolon)"
219
+ }, AST_Statement);
220
+
221
+ function is_statement(node) {
222
+ return node instanceof AST_Statement
223
+ && !(node instanceof AST_ClassExpression)
224
+ && !(node instanceof AST_LambdaExpression);
225
+ }
226
+
227
+ function validate_expression(value, prop, multiple, allow_spread, allow_hole) {
228
+ multiple = multiple ? "contain" : "be";
229
+ if (!(value instanceof AST_Node)) throw new Error(prop + " must " + multiple + " AST_Node");
230
+ if (value instanceof AST_DefaultValue) throw new Error(prop + " cannot " + multiple + " AST_DefaultValue");
231
+ if (value instanceof AST_Destructured) throw new Error(prop + " cannot " + multiple + " AST_Destructured");
232
+ if (value instanceof AST_Hole && !allow_hole) throw new Error(prop + " cannot " + multiple + " AST_Hole");
233
+ if (value instanceof AST_Spread && !allow_spread) throw new Error(prop + " cannot " + multiple + " AST_Spread");
234
+ if (is_statement(value)) throw new Error(prop + " cannot " + multiple + " AST_Statement");
235
+ if (value instanceof AST_SymbolDeclaration) {
236
+ throw new Error(prop + " cannot " + multiple + " AST_SymbolDeclaration");
237
+ }
238
+ }
239
+
240
+ function must_be_expression(node, prop) {
241
+ validate_expression(node[prop], prop);
242
+ }
243
+
244
+ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
245
+ $documentation: "A statement consisting of an expression, i.e. a = 1 + 2",
246
+ $propdoc: {
247
+ body: "[AST_Node] an expression node (should not be instanceof AST_Statement)",
248
+ },
249
+ walk: function(visitor) {
250
+ var node = this;
251
+ visitor.visit(node, function() {
252
+ node.body.walk(visitor);
253
+ });
254
+ },
255
+ _validate: function() {
256
+ must_be_expression(this, "body");
257
+ },
258
+ }, AST_Statement);
259
+
260
+ var AST_BlockScope = DEFNODE("BlockScope", "enclosed functions make_def parent_scope variables", {
261
+ $documentation: "Base class for all statements introducing a lexical scope",
262
+ $propdoc: {
263
+ enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
264
+ functions: "[Object/S] like `variables`, but only lists function declarations",
265
+ parent_scope: "[AST_Scope?/S] link to the parent scope",
266
+ variables: "[Object/S] a map of name ---> SymbolDef for all variables/functions defined in this scope",
267
+ },
268
+ clone: function(deep) {
269
+ var node = this._clone(deep);
270
+ if (this.enclosed) node.enclosed = this.enclosed.slice();
271
+ if (this.functions) node.functions = this.functions.clone();
272
+ if (this.variables) node.variables = this.variables.clone();
273
+ return node;
274
+ },
275
+ pinned: function() {
276
+ return this.resolve().pinned();
277
+ },
278
+ resolve: function() {
279
+ return this.parent_scope.resolve();
280
+ },
281
+ _validate: function() {
282
+ if (this.TYPE == "BlockScope") throw new Error("should not instantiate AST_BlockScope");
283
+ if (this.parent_scope == null) return;
284
+ if (!(this.parent_scope instanceof AST_BlockScope)) throw new Error("parent_scope must be AST_BlockScope");
285
+ if (!(this.resolve() instanceof AST_Scope)) throw new Error("must be contained within AST_Scope");
286
+ },
287
+ }, AST_Statement);
288
+
289
+ function walk_body(node, visitor) {
290
+ node.body.forEach(function(node) {
291
+ node.walk(visitor);
292
+ });
293
+ }
294
+
295
+ var AST_Block = DEFNODE("Block", "body", {
296
+ $documentation: "A body of statements (usually braced)",
297
+ $propdoc: {
298
+ body: "[AST_Statement*] an array of statements"
299
+ },
300
+ walk: function(visitor) {
301
+ var node = this;
302
+ visitor.visit(node, function() {
303
+ walk_body(node, visitor);
304
+ });
305
+ },
306
+ _validate: function() {
307
+ if (this.TYPE == "Block") throw new Error("should not instantiate AST_Block");
308
+ this.body.forEach(function(node) {
309
+ if (!is_statement(node)) throw new Error("body must contain AST_Statement");
310
+ });
311
+ },
312
+ }, AST_BlockScope);
313
+
314
+ var AST_BlockStatement = DEFNODE("BlockStatement", null, {
315
+ $documentation: "A block statement",
316
+ }, AST_Block);
317
+
318
+ var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", {
319
+ $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",
320
+ $propdoc: {
321
+ body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
322
+ },
323
+ _validate: function() {
324
+ if (this.TYPE == "StatementWithBody") throw new Error("should not instantiate AST_StatementWithBody");
325
+ if (!is_statement(this.body)) throw new Error("body must be AST_Statement");
326
+ },
327
+ }, AST_BlockScope);
328
+
329
+ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
330
+ $documentation: "Statement with a label",
331
+ $propdoc: {
332
+ label: "[AST_Label] a label definition"
333
+ },
334
+ walk: function(visitor) {
335
+ var node = this;
336
+ visitor.visit(node, function() {
337
+ node.label.walk(visitor);
338
+ node.body.walk(visitor);
339
+ });
340
+ },
341
+ clone: function(deep) {
342
+ var node = this._clone(deep);
343
+ if (deep) {
344
+ var label = node.label;
345
+ var def = this.label;
346
+ node.walk(new TreeWalker(function(node) {
347
+ if (node instanceof AST_LoopControl) {
348
+ if (!node.label || node.label.thedef !== def) return;
349
+ node.label.thedef = label;
350
+ label.references.push(node);
351
+ return true;
352
+ }
353
+ if (node instanceof AST_Scope) return true;
354
+ }));
355
+ }
356
+ return node;
357
+ },
358
+ _validate: function() {
359
+ if (!(this.label instanceof AST_Label)) throw new Error("label must be AST_Label");
360
+ },
361
+ }, AST_StatementWithBody);
362
+
363
+ var AST_IterationStatement = DEFNODE("IterationStatement", null, {
364
+ $documentation: "Internal class. All loops inherit from it.",
365
+ _validate: function() {
366
+ if (this.TYPE == "IterationStatement") throw new Error("should not instantiate AST_IterationStatement");
367
+ },
368
+ }, AST_StatementWithBody);
369
+
370
+ var AST_DWLoop = DEFNODE("DWLoop", "condition", {
371
+ $documentation: "Base class for do/while statements",
372
+ $propdoc: {
373
+ condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement"
374
+ },
375
+ _validate: function() {
376
+ if (this.TYPE == "DWLoop") throw new Error("should not instantiate AST_DWLoop");
377
+ must_be_expression(this, "condition");
378
+ },
379
+ }, AST_IterationStatement);
380
+
381
+ var AST_Do = DEFNODE("Do", null, {
382
+ $documentation: "A `do` statement",
383
+ walk: function(visitor) {
384
+ var node = this;
385
+ visitor.visit(node, function() {
386
+ node.body.walk(visitor);
387
+ node.condition.walk(visitor);
388
+ });
389
+ }
390
+ }, AST_DWLoop);
391
+
392
+ var AST_While = DEFNODE("While", null, {
393
+ $documentation: "A `while` statement",
394
+ walk: function(visitor) {
395
+ var node = this;
396
+ visitor.visit(node, function() {
397
+ node.condition.walk(visitor);
398
+ node.body.walk(visitor);
399
+ });
400
+ }
401
+ }, AST_DWLoop);
402
+
403
+ var AST_For = DEFNODE("For", "init condition step", {
404
+ $documentation: "A `for` statement",
405
+ $propdoc: {
406
+ init: "[AST_Node?] the `for` initialization code, or null if empty",
407
+ condition: "[AST_Node?] the `for` termination clause, or null if empty",
408
+ step: "[AST_Node?] the `for` update clause, or null if empty"
409
+ },
410
+ walk: function(visitor) {
411
+ var node = this;
412
+ visitor.visit(node, function() {
413
+ if (node.init) node.init.walk(visitor);
414
+ if (node.condition) node.condition.walk(visitor);
415
+ if (node.step) node.step.walk(visitor);
416
+ node.body.walk(visitor);
417
+ });
418
+ },
419
+ _validate: function() {
420
+ if (this.init != null) {
421
+ if (!(this.init instanceof AST_Node)) throw new Error("init must be AST_Node");
422
+ if (is_statement(this.init) && !(this.init instanceof AST_Definitions)) {
423
+ throw new Error("init cannot be AST_Statement");
424
+ }
425
+ }
426
+ if (this.condition != null) must_be_expression(this, "condition");
427
+ if (this.step != null) must_be_expression(this, "step");
428
+ },
429
+ }, AST_IterationStatement);
430
+
431
+ var AST_ForEnumeration = DEFNODE("ForEnumeration", "init object", {
432
+ $documentation: "Base class for enumeration loops, i.e. `for ... in`, `for ... of` & `for await ... of`",
433
+ $propdoc: {
434
+ init: "[AST_Node] the assignment target during iteration",
435
+ object: "[AST_Node] the object to iterate over"
436
+ },
437
+ walk: function(visitor) {
438
+ var node = this;
439
+ visitor.visit(node, function() {
440
+ node.init.walk(visitor);
441
+ node.object.walk(visitor);
442
+ node.body.walk(visitor);
443
+ });
444
+ },
445
+ _validate: function() {
446
+ if (this.TYPE == "ForEnumeration") throw new Error("should not instantiate AST_ForEnumeration");
447
+ if (this.init instanceof AST_Definitions) {
448
+ if (this.init.definitions.length != 1) throw new Error("init must have single declaration");
449
+ } else {
450
+ validate_destructured(this.init, function(node) {
451
+ if (!(node instanceof AST_PropAccess || node instanceof AST_SymbolRef)) {
452
+ throw new Error("init must be assignable: " + node.TYPE);
453
+ }
454
+ });
455
+ }
456
+ must_be_expression(this, "object");
457
+ },
458
+ }, AST_IterationStatement);
459
+
460
+ var AST_ForIn = DEFNODE("ForIn", null, {
461
+ $documentation: "A `for ... in` statement",
462
+ }, AST_ForEnumeration);
463
+
464
+ var AST_ForOf = DEFNODE("ForOf", null, {
465
+ $documentation: "A `for ... of` statement",
466
+ }, AST_ForEnumeration);
467
+
468
+ var AST_ForAwaitOf = DEFNODE("ForAwaitOf", null, {
469
+ $documentation: "A `for await ... of` statement",
470
+ }, AST_ForOf);
471
+
472
+ var AST_With = DEFNODE("With", "expression", {
473
+ $documentation: "A `with` statement",
474
+ $propdoc: {
475
+ expression: "[AST_Node] the `with` expression"
476
+ },
477
+ walk: function(visitor) {
478
+ var node = this;
479
+ visitor.visit(node, function() {
480
+ node.expression.walk(visitor);
481
+ node.body.walk(visitor);
482
+ });
483
+ },
484
+ _validate: function() {
485
+ must_be_expression(this, "expression");
486
+ },
487
+ }, AST_StatementWithBody);
488
+
489
+ /* -----[ scope and functions ]----- */
490
+
491
+ var AST_Scope = DEFNODE("Scope", "uses_eval uses_with", {
492
+ $documentation: "Base class for all statements introducing a lexical scope",
493
+ $propdoc: {
494
+ uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
495
+ uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
496
+ },
497
+ pinned: function() {
498
+ return this.uses_eval || this.uses_with;
499
+ },
500
+ resolve: return_this,
501
+ _validate: function() {
502
+ if (this.TYPE == "Scope") throw new Error("should not instantiate AST_Scope");
503
+ },
504
+ }, AST_Block);
505
+
506
+ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
507
+ $documentation: "The toplevel scope",
508
+ $propdoc: {
509
+ globals: "[Object/S] a map of name ---> SymbolDef for all undeclared names",
510
+ },
511
+ wrap: function(name) {
512
+ var body = this.body;
513
+ return parse([
514
+ "(function(exports){'$ORIG';})(typeof ",
515
+ name,
516
+ "=='undefined'?(",
517
+ name,
518
+ "={}):",
519
+ name,
520
+ ");"
521
+ ].join(""), {
522
+ filename: "wrap=" + JSON.stringify(name)
523
+ }).transform(new TreeTransformer(function(node) {
524
+ if (node instanceof AST_Directive && node.value == "$ORIG") {
525
+ return List.splice(body);
526
+ }
527
+ }));
528
+ },
529
+ enclose: function(args_values) {
530
+ if (typeof args_values != "string") args_values = "";
531
+ var index = args_values.indexOf(":");
532
+ if (index < 0) index = args_values.length;
533
+ var body = this.body;
534
+ return parse([
535
+ "(function(",
536
+ args_values.slice(0, index),
537
+ '){"$ORIG"})(',
538
+ args_values.slice(index + 1),
539
+ ")"
540
+ ].join(""), {
541
+ filename: "enclose=" + JSON.stringify(args_values)
542
+ }).transform(new TreeTransformer(function(node) {
543
+ if (node instanceof AST_Directive && node.value == "$ORIG") {
544
+ return List.splice(body);
545
+ }
546
+ }));
547
+ }
548
+ }, AST_Scope);
549
+
550
+ var AST_Lambda = DEFNODE("Lambda", "argnames length_read rest uses_arguments", {
551
+ $documentation: "Base class for functions",
552
+ $propdoc: {
553
+ argnames: "[(AST_DefaultValue|AST_Destructured|AST_SymbolFunarg)*] array of function arguments and/or destructured literals",
554
+ length_read: "[boolean/S] whether length property of this function is accessed",
555
+ rest: "[(AST_Destructured|AST_SymbolFunarg)?] rest parameter, or null if absent",
556
+ uses_arguments: "[boolean/S] whether this function accesses the arguments array",
557
+ },
558
+ each_argname: function(visit) {
559
+ var tw = new TreeWalker(function(node) {
560
+ if (node instanceof AST_DefaultValue) {
561
+ node.name.walk(tw);
562
+ return true;
563
+ }
564
+ if (node instanceof AST_DestructuredKeyVal) {
565
+ node.value.walk(tw);
566
+ return true;
567
+ }
568
+ if (node instanceof AST_SymbolFunarg) visit(node);
569
+ });
570
+ this.argnames.forEach(function(argname) {
571
+ argname.walk(tw);
572
+ });
573
+ if (this.rest) this.rest.walk(tw);
574
+ },
575
+ walk: function(visitor) {
576
+ var node = this;
577
+ visitor.visit(node, function() {
578
+ if (node.name) node.name.walk(visitor);
579
+ node.argnames.forEach(function(argname) {
580
+ argname.walk(visitor);
581
+ });
582
+ if (node.rest) node.rest.walk(visitor);
583
+ walk_body(node, visitor);
584
+ });
585
+ },
586
+ _validate: function() {
587
+ if (this.TYPE == "Lambda") throw new Error("should not instantiate AST_Lambda");
588
+ this.argnames.forEach(function(node) {
589
+ validate_destructured(node, function(node) {
590
+ if (!(node instanceof AST_SymbolFunarg)) throw new Error("argnames must be AST_SymbolFunarg[]");
591
+ }, true);
592
+ });
593
+ if (this.rest != null) validate_destructured(this.rest, function(node) {
594
+ if (!(node instanceof AST_SymbolFunarg)) throw new Error("rest must be AST_SymbolFunarg");
595
+ });
596
+ },
597
+ }, AST_Scope);
598
+
599
+ var AST_Accessor = DEFNODE("Accessor", null, {
600
+ $documentation: "A getter/setter function",
601
+ _validate: function() {
602
+ if (this.name != null) throw new Error("name must be null");
603
+ },
604
+ }, AST_Lambda);
605
+
606
+ var AST_LambdaExpression = DEFNODE("LambdaExpression", "inlined", {
607
+ $documentation: "Base class for function expressions",
608
+ $propdoc: {
609
+ inlined: "[boolean/S] whether this function has been inlined",
610
+ },
611
+ _validate: function() {
612
+ if (this.TYPE == "LambdaExpression") throw new Error("should not instantiate AST_LambdaExpression");
613
+ },
614
+ }, AST_Lambda);
615
+
616
+ function is_arrow(node) {
617
+ return node instanceof AST_Arrow || node instanceof AST_AsyncArrow;
618
+ }
619
+
620
+ function is_async(node) {
621
+ return node instanceof AST_AsyncArrow
622
+ || node instanceof AST_AsyncDefun
623
+ || node instanceof AST_AsyncFunction
624
+ || node instanceof AST_AsyncGeneratorDefun
625
+ || node instanceof AST_AsyncGeneratorFunction;
626
+ }
627
+
628
+ function is_generator(node) {
629
+ return node instanceof AST_AsyncGeneratorDefun
630
+ || node instanceof AST_AsyncGeneratorFunction
631
+ || node instanceof AST_GeneratorDefun
632
+ || node instanceof AST_GeneratorFunction;
633
+ }
634
+
635
+ function walk_lambda(node, tw) {
636
+ if (is_arrow(node) && node.value) {
637
+ node.value.walk(tw);
638
+ } else {
639
+ walk_body(node, tw);
640
+ }
641
+ }
642
+
643
+ var AST_Arrow = DEFNODE("Arrow", "value", {
644
+ $documentation: "An arrow function expression",
645
+ $propdoc: {
646
+ value: "[AST_Node?] simple return expression, or null if using function body.",
647
+ },
648
+ walk: function(visitor) {
649
+ var node = this;
650
+ visitor.visit(node, function() {
651
+ node.argnames.forEach(function(argname) {
652
+ argname.walk(visitor);
653
+ });
654
+ if (node.rest) node.rest.walk(visitor);
655
+ if (node.value) {
656
+ node.value.walk(visitor);
657
+ } else {
658
+ walk_body(node, visitor);
659
+ }
660
+ });
661
+ },
662
+ _validate: function() {
663
+ if (this.name != null) throw new Error("name must be null");
664
+ if (this.uses_arguments) throw new Error("uses_arguments must be false");
665
+ if (this.value != null) {
666
+ must_be_expression(this, "value");
667
+ if (this.body.length) throw new Error("body must be empty if value exists");
668
+ }
669
+ },
670
+ }, AST_LambdaExpression);
671
+
672
+ var AST_AsyncArrow = DEFNODE("AsyncArrow", "value", {
673
+ $documentation: "An asynchronous arrow function expression",
674
+ $propdoc: {
675
+ value: "[AST_Node?] simple return expression, or null if using function body.",
676
+ },
677
+ walk: function(visitor) {
678
+ var node = this;
679
+ visitor.visit(node, function() {
680
+ node.argnames.forEach(function(argname) {
681
+ argname.walk(visitor);
682
+ });
683
+ if (node.rest) node.rest.walk(visitor);
684
+ if (node.value) {
685
+ node.value.walk(visitor);
686
+ } else {
687
+ walk_body(node, visitor);
688
+ }
689
+ });
690
+ },
691
+ _validate: function() {
692
+ if (this.name != null) throw new Error("name must be null");
693
+ if (this.uses_arguments) throw new Error("uses_arguments must be false");
694
+ if (this.value != null) {
695
+ must_be_expression(this, "value");
696
+ if (this.body.length) throw new Error("body must be empty if value exists");
697
+ }
698
+ },
699
+ }, AST_LambdaExpression);
700
+
701
+ var AST_AsyncFunction = DEFNODE("AsyncFunction", "name", {
702
+ $documentation: "An asynchronous function expression",
703
+ $propdoc: {
704
+ name: "[AST_SymbolLambda?] the name of this function, or null if not specified",
705
+ },
706
+ _validate: function() {
707
+ if (this.name != null) {
708
+ if (!(this.name instanceof AST_SymbolLambda)) throw new Error("name must be AST_SymbolLambda");
709
+ }
710
+ },
711
+ }, AST_LambdaExpression);
712
+
713
+ var AST_AsyncGeneratorFunction = DEFNODE("AsyncGeneratorFunction", "name", {
714
+ $documentation: "An asynchronous generator function expression",
715
+ $propdoc: {
716
+ name: "[AST_SymbolLambda?] the name of this function, or null if not specified",
717
+ },
718
+ _validate: function() {
719
+ if (this.name != null) {
720
+ if (!(this.name instanceof AST_SymbolLambda)) throw new Error("name must be AST_SymbolLambda");
721
+ }
722
+ },
723
+ }, AST_LambdaExpression);
724
+
725
+ var AST_Function = DEFNODE("Function", "name", {
726
+ $documentation: "A function expression",
727
+ $propdoc: {
728
+ name: "[AST_SymbolLambda?] the name of this function, or null if not specified",
729
+ },
730
+ _validate: function() {
731
+ if (this.name != null) {
732
+ if (!(this.name instanceof AST_SymbolLambda)) throw new Error("name must be AST_SymbolLambda");
733
+ }
734
+ },
735
+ }, AST_LambdaExpression);
736
+
737
+ var AST_GeneratorFunction = DEFNODE("GeneratorFunction", "name", {
738
+ $documentation: "A generator function expression",
739
+ $propdoc: {
740
+ name: "[AST_SymbolLambda?] the name of this function, or null if not specified",
741
+ },
742
+ _validate: function() {
743
+ if (this.name != null) {
744
+ if (!(this.name instanceof AST_SymbolLambda)) throw new Error("name must be AST_SymbolLambda");
745
+ }
746
+ },
747
+ }, AST_LambdaExpression);
748
+
749
+ var AST_LambdaDefinition = DEFNODE("LambdaDefinition", "inlined name", {
750
+ $documentation: "Base class for function definitions",
751
+ $propdoc: {
752
+ inlined: "[boolean/S] whether this function has been inlined",
753
+ name: "[AST_SymbolDefun] the name of this function",
754
+ },
755
+ _validate: function() {
756
+ if (this.TYPE == "LambdaDefinition") throw new Error("should not instantiate AST_LambdaDefinition");
757
+ if (!(this.name instanceof AST_SymbolDefun)) throw new Error("name must be AST_SymbolDefun");
758
+ },
759
+ }, AST_Lambda);
760
+
761
+ var AST_AsyncDefun = DEFNODE("AsyncDefun", null, {
762
+ $documentation: "An asynchronous function definition",
763
+ }, AST_LambdaDefinition);
764
+
765
+ var AST_AsyncGeneratorDefun = DEFNODE("AsyncGeneratorDefun", null, {
766
+ $documentation: "An asynchronous generator function definition",
767
+ }, AST_LambdaDefinition);
768
+
769
+ var AST_Defun = DEFNODE("Defun", null, {
770
+ $documentation: "A function definition",
771
+ }, AST_LambdaDefinition);
772
+
773
+ var AST_GeneratorDefun = DEFNODE("GeneratorDefun", null, {
774
+ $documentation: "A generator function definition",
775
+ }, AST_LambdaDefinition);
776
+
777
+ /* -----[ classes ]----- */
778
+
779
+ var AST_Class = DEFNODE("Class", "extends name properties", {
780
+ $documentation: "Base class for class literals",
781
+ $propdoc: {
782
+ extends: "[AST_Node?] the super class, or null if not specified",
783
+ properties: "[AST_ClassProperty*] array of class properties",
784
+ },
785
+ walk: function(visitor) {
786
+ var node = this;
787
+ visitor.visit(node, function() {
788
+ if (node.name) node.name.walk(visitor);
789
+ if (node.extends) node.extends.walk(visitor);
790
+ node.properties.forEach(function(prop) {
791
+ prop.walk(visitor);
792
+ });
793
+ });
794
+ },
795
+ _validate: function() {
796
+ if (this.TYPE == "Class") throw new Error("should not instantiate AST_Class");
797
+ if (this.extends != null) must_be_expression(this, "extends");
798
+ this.properties.forEach(function(node) {
799
+ if (!(node instanceof AST_ClassProperty)) throw new Error("properties must contain AST_ClassProperty");
800
+ });
801
+ },
802
+ }, AST_BlockScope);
803
+
804
+ var AST_DefClass = DEFNODE("DefClass", null, {
805
+ $documentation: "A class definition",
806
+ $propdoc: {
807
+ name: "[AST_SymbolDefClass] the name of this class",
808
+ },
809
+ _validate: function() {
810
+ if (!(this.name instanceof AST_SymbolDefClass)) throw new Error("name must be AST_SymbolDefClass");
811
+ },
812
+ }, AST_Class);
813
+
814
+ var AST_ClassExpression = DEFNODE("ClassExpression", null, {
815
+ $documentation: "A class expression",
816
+ $propdoc: {
817
+ name: "[AST_SymbolClass?] the name of this class, or null if not specified",
818
+ },
819
+ _validate: function() {
820
+ if (this.name != null) {
821
+ if (!(this.name instanceof AST_SymbolClass)) throw new Error("name must be AST_SymbolClass");
822
+ }
823
+ },
824
+ }, AST_Class);
825
+
826
+ var AST_ClassProperty = DEFNODE("ClassProperty", "key private static value", {
827
+ $documentation: "Base class for `class` properties",
828
+ $propdoc: {
829
+ key: "[string|AST_Node] property name (AST_Node for computed property)",
830
+ private: "[boolean] whether this is a private property",
831
+ static: "[boolean] whether this is a static property",
832
+ value: "[AST_Node?] property value (AST_Accessor for getters/setters, AST_LambdaExpression for methods, null if not specified for fields)",
833
+ },
834
+ walk: function(visitor) {
835
+ var node = this;
836
+ visitor.visit(node, function() {
837
+ if (node.key instanceof AST_Node) node.key.walk(visitor);
838
+ if (node.value) node.value.walk(visitor);
839
+ });
840
+ },
841
+ _validate: function() {
842
+ if (this.TYPE == "ClassProperty") throw new Error("should not instantiate AST_ClassProperty");
843
+ if (typeof this.key != "string") {
844
+ if (!(this.key instanceof AST_Node)) throw new Error("key must be string or AST_Node");
845
+ must_be_expression(this, "key");
846
+ }
847
+ if(this.value != null) {
848
+ if (!(this.value instanceof AST_Node)) throw new Error("value must be AST_Node");
849
+ }
850
+ },
851
+ });
852
+
853
+ var AST_ClassField = DEFNODE("ClassField", null, {
854
+ $documentation: "A `class` field",
855
+ _validate: function() {
856
+ if(this.value != null) must_be_expression(this, "value");
857
+ },
858
+ }, AST_ClassProperty);
859
+
860
+ var AST_ClassGetter = DEFNODE("ClassGetter", null, {
861
+ $documentation: "A `class` getter",
862
+ _validate: function() {
863
+ if (!(this.value instanceof AST_Accessor)) throw new Error("value must be AST_Accessor");
864
+ },
865
+ }, AST_ClassProperty);
866
+
867
+ var AST_ClassSetter = DEFNODE("ClassSetter", null, {
868
+ $documentation: "A `class` setter",
869
+ _validate: function() {
870
+ if (!(this.value instanceof AST_Accessor)) throw new Error("value must be AST_Accessor");
871
+ },
872
+ }, AST_ClassProperty);
873
+
874
+ var AST_ClassMethod = DEFNODE("ClassMethod", null, {
875
+ $documentation: "A `class` method",
876
+ _validate: function() {
877
+ if (!(this.value instanceof AST_LambdaExpression)) throw new Error("value must be AST_LambdaExpression");
878
+ if (is_arrow(this.value)) throw new Error("value cannot be AST_Arrow or AST_AsyncArrow");
879
+ if (this.value.name != null) throw new Error("name of class method's lambda must be null");
880
+ },
881
+ }, AST_ClassProperty);
882
+
883
+ /* -----[ JUMPS ]----- */
884
+
885
+ var AST_Jump = DEFNODE("Jump", null, {
886
+ $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)",
887
+ _validate: function() {
888
+ if (this.TYPE == "Jump") throw new Error("should not instantiate AST_Jump");
889
+ },
890
+ }, AST_Statement);
891
+
892
+ var AST_Exit = DEFNODE("Exit", "value", {
893
+ $documentation: "Base class for “exits” (`return` and `throw`)",
894
+ $propdoc: {
895
+ value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
896
+ },
897
+ walk: function(visitor) {
898
+ var node = this;
899
+ visitor.visit(node, function() {
900
+ if (node.value) node.value.walk(visitor);
901
+ });
902
+ },
903
+ _validate: function() {
904
+ if (this.TYPE == "Exit") throw new Error("should not instantiate AST_Exit");
905
+ },
906
+ }, AST_Jump);
907
+
908
+ var AST_Return = DEFNODE("Return", null, {
909
+ $documentation: "A `return` statement",
910
+ _validate: function() {
911
+ if (this.value != null) must_be_expression(this, "value");
912
+ },
913
+ }, AST_Exit);
914
+
915
+ var AST_Throw = DEFNODE("Throw", null, {
916
+ $documentation: "A `throw` statement",
917
+ _validate: function() {
918
+ must_be_expression(this, "value");
919
+ },
920
+ }, AST_Exit);
921
+
922
+ var AST_LoopControl = DEFNODE("LoopControl", "label", {
923
+ $documentation: "Base class for loop control statements (`break` and `continue`)",
924
+ $propdoc: {
925
+ label: "[AST_LabelRef?] the label, or null if none",
926
+ },
927
+ walk: function(visitor) {
928
+ var node = this;
929
+ visitor.visit(node, function() {
930
+ if (node.label) node.label.walk(visitor);
931
+ });
932
+ },
933
+ _validate: function() {
934
+ if (this.TYPE == "LoopControl") throw new Error("should not instantiate AST_LoopControl");
935
+ if (this.label != null) {
936
+ if (!(this.label instanceof AST_LabelRef)) throw new Error("label must be AST_LabelRef");
937
+ }
938
+ },
939
+ }, AST_Jump);
940
+
941
+ var AST_Break = DEFNODE("Break", null, {
942
+ $documentation: "A `break` statement"
943
+ }, AST_LoopControl);
944
+
945
+ var AST_Continue = DEFNODE("Continue", null, {
946
+ $documentation: "A `continue` statement"
947
+ }, AST_LoopControl);
948
+
949
+ /* -----[ IF ]----- */
950
+
951
+ var AST_If = DEFNODE("If", "condition alternative", {
952
+ $documentation: "A `if` statement",
953
+ $propdoc: {
954
+ condition: "[AST_Node] the `if` condition",
955
+ alternative: "[AST_Statement?] the `else` part, or null if not present"
956
+ },
957
+ walk: function(visitor) {
958
+ var node = this;
959
+ visitor.visit(node, function() {
960
+ node.condition.walk(visitor);
961
+ node.body.walk(visitor);
962
+ if (node.alternative) node.alternative.walk(visitor);
963
+ });
964
+ },
965
+ _validate: function() {
966
+ must_be_expression(this, "condition");
967
+ if (this.alternative != null) {
968
+ if (!is_statement(this.alternative)) throw new Error("alternative must be AST_Statement");
969
+ }
970
+ },
971
+ }, AST_StatementWithBody);
972
+
973
+ /* -----[ SWITCH ]----- */
974
+
975
+ var AST_Switch = DEFNODE("Switch", "expression", {
976
+ $documentation: "A `switch` statement",
977
+ $propdoc: {
978
+ expression: "[AST_Node] the `switch` “discriminant”"
979
+ },
980
+ walk: function(visitor) {
981
+ var node = this;
982
+ visitor.visit(node, function() {
983
+ node.expression.walk(visitor);
984
+ walk_body(node, visitor);
985
+ });
986
+ },
987
+ _validate: function() {
988
+ must_be_expression(this, "expression");
989
+ this.body.forEach(function(node) {
990
+ if (!(node instanceof AST_SwitchBranch)) throw new Error("body must be AST_SwitchBranch[]");
991
+ });
992
+ },
993
+ }, AST_Block);
994
+
995
+ var AST_SwitchBranch = DEFNODE("SwitchBranch", null, {
996
+ $documentation: "Base class for `switch` branches",
997
+ _validate: function() {
998
+ if (this.TYPE == "SwitchBranch") throw new Error("should not instantiate AST_SwitchBranch");
999
+ },
1000
+ }, AST_Block);
1001
+
1002
+ var AST_Default = DEFNODE("Default", null, {
1003
+ $documentation: "A `default` switch branch",
1004
+ }, AST_SwitchBranch);
1005
+
1006
+ var AST_Case = DEFNODE("Case", "expression", {
1007
+ $documentation: "A `case` switch branch",
1008
+ $propdoc: {
1009
+ expression: "[AST_Node] the `case` expression"
1010
+ },
1011
+ walk: function(visitor) {
1012
+ var node = this;
1013
+ visitor.visit(node, function() {
1014
+ node.expression.walk(visitor);
1015
+ walk_body(node, visitor);
1016
+ });
1017
+ },
1018
+ _validate: function() {
1019
+ must_be_expression(this, "expression");
1020
+ },
1021
+ }, AST_SwitchBranch);
1022
+
1023
+ /* -----[ EXCEPTIONS ]----- */
1024
+
1025
+ var AST_Try = DEFNODE("Try", "bcatch bfinally", {
1026
+ $documentation: "A `try` statement",
1027
+ $propdoc: {
1028
+ bcatch: "[AST_Catch?] the catch block, or null if not present",
1029
+ bfinally: "[AST_Finally?] the finally block, or null if not present"
1030
+ },
1031
+ walk: function(visitor) {
1032
+ var node = this;
1033
+ visitor.visit(node, function() {
1034
+ walk_body(node, visitor);
1035
+ if (node.bcatch) node.bcatch.walk(visitor);
1036
+ if (node.bfinally) node.bfinally.walk(visitor);
1037
+ });
1038
+ },
1039
+ _validate: function() {
1040
+ if (this.bcatch != null) {
1041
+ if (!(this.bcatch instanceof AST_Catch)) throw new Error("bcatch must be AST_Catch");
1042
+ }
1043
+ if (this.bfinally != null) {
1044
+ if (!(this.bfinally instanceof AST_Finally)) throw new Error("bfinally must be AST_Finally");
1045
+ }
1046
+ },
1047
+ }, AST_Block);
1048
+
1049
+ var AST_Catch = DEFNODE("Catch", "argname", {
1050
+ $documentation: "A `catch` node; only makes sense as part of a `try` statement",
1051
+ $propdoc: {
1052
+ argname: "[(AST_Destructured|AST_SymbolCatch)?] symbol for the exception, or null if not present",
1053
+ },
1054
+ walk: function(visitor) {
1055
+ var node = this;
1056
+ visitor.visit(node, function() {
1057
+ if (node.argname) node.argname.walk(visitor);
1058
+ walk_body(node, visitor);
1059
+ });
1060
+ },
1061
+ _validate: function() {
1062
+ if (this.argname != null) validate_destructured(this.argname, function(node) {
1063
+ if (!(node instanceof AST_SymbolCatch)) throw new Error("argname must be AST_SymbolCatch");
1064
+ });
1065
+ },
1066
+ }, AST_Block);
1067
+
1068
+ var AST_Finally = DEFNODE("Finally", null, {
1069
+ $documentation: "A `finally` node; only makes sense as part of a `try` statement"
1070
+ }, AST_Block);
1071
+
1072
+ /* -----[ VAR ]----- */
1073
+
1074
+ var AST_Definitions = DEFNODE("Definitions", "definitions", {
1075
+ $documentation: "Base class for `var` nodes (variable declarations/initializations)",
1076
+ $propdoc: {
1077
+ definitions: "[AST_VarDef*] array of variable definitions"
1078
+ },
1079
+ walk: function(visitor) {
1080
+ var node = this;
1081
+ visitor.visit(node, function() {
1082
+ node.definitions.forEach(function(defn) {
1083
+ defn.walk(visitor);
1084
+ });
1085
+ });
1086
+ },
1087
+ _validate: function() {
1088
+ if (this.TYPE == "Definitions") throw new Error("should not instantiate AST_Definitions");
1089
+ if (this.definitions.length < 1) throw new Error("must have at least one definition");
1090
+ },
1091
+ }, AST_Statement);
1092
+
1093
+ var AST_Const = DEFNODE("Const", null, {
1094
+ $documentation: "A `const` statement",
1095
+ _validate: function() {
1096
+ this.definitions.forEach(function(node) {
1097
+ if (!(node instanceof AST_VarDef)) throw new Error("definitions must be AST_VarDef[]");
1098
+ validate_destructured(node.name, function(node) {
1099
+ if (!(node instanceof AST_SymbolConst)) throw new Error("name must be AST_SymbolConst");
1100
+ });
1101
+ });
1102
+ },
1103
+ }, AST_Definitions);
1104
+
1105
+ var AST_Let = DEFNODE("Let", null, {
1106
+ $documentation: "A `let` statement",
1107
+ _validate: function() {
1108
+ this.definitions.forEach(function(node) {
1109
+ if (!(node instanceof AST_VarDef)) throw new Error("definitions must be AST_VarDef[]");
1110
+ validate_destructured(node.name, function(node) {
1111
+ if (!(node instanceof AST_SymbolLet)) throw new Error("name must be AST_SymbolLet");
1112
+ });
1113
+ });
1114
+ },
1115
+ }, AST_Definitions);
1116
+
1117
+ var AST_Var = DEFNODE("Var", null, {
1118
+ $documentation: "A `var` statement",
1119
+ _validate: function() {
1120
+ this.definitions.forEach(function(node) {
1121
+ if (!(node instanceof AST_VarDef)) throw new Error("definitions must be AST_VarDef[]");
1122
+ validate_destructured(node.name, function(node) {
1123
+ if (!(node instanceof AST_SymbolVar)) throw new Error("name must be AST_SymbolVar");
1124
+ });
1125
+ });
1126
+ },
1127
+ }, AST_Definitions);
1128
+
1129
+ var AST_VarDef = DEFNODE("VarDef", "name value", {
1130
+ $documentation: "A variable declaration; only appears in a AST_Definitions node",
1131
+ $propdoc: {
1132
+ name: "[AST_Destructured|AST_SymbolVar] name of the variable",
1133
+ value: "[AST_Node?] initializer, or null of there's no initializer",
1134
+ },
1135
+ walk: function(visitor) {
1136
+ var node = this;
1137
+ visitor.visit(node, function() {
1138
+ node.name.walk(visitor);
1139
+ if (node.value) node.value.walk(visitor);
1140
+ });
1141
+ },
1142
+ _validate: function() {
1143
+ if (this.value != null) must_be_expression(this, "value");
1144
+ },
1145
+ });
1146
+
1147
+ /* -----[ OTHER ]----- */
1148
+
1149
+ var AST_ExportDeclaration = DEFNODE("ExportDeclaration", "body", {
1150
+ $documentation: "An `export` statement",
1151
+ $propdoc: {
1152
+ body: "[AST_DefClass|AST_Definitions|AST_LambdaDefinition] the statement to export",
1153
+ },
1154
+ walk: function(visitor) {
1155
+ var node = this;
1156
+ visitor.visit(node, function() {
1157
+ node.body.walk(visitor);
1158
+ });
1159
+ },
1160
+ _validate: function() {
1161
+ if (!(this.body instanceof AST_DefClass
1162
+ || this.body instanceof AST_Definitions
1163
+ || this.body instanceof AST_LambdaDefinition)) {
1164
+ throw new Error("body must be AST_DefClass, AST_Definitions or AST_LambdaDefinition");
1165
+ }
1166
+ },
1167
+ }, AST_Statement);
1168
+
1169
+ var AST_ExportDefault = DEFNODE("ExportDefault", "body", {
1170
+ $documentation: "An `export default` statement",
1171
+ $propdoc: {
1172
+ body: "[AST_Node] the default export",
1173
+ },
1174
+ walk: function(visitor) {
1175
+ var node = this;
1176
+ visitor.visit(node, function() {
1177
+ node.body.walk(visitor);
1178
+ });
1179
+ },
1180
+ _validate: function() {
1181
+ if (!(this.body instanceof AST_DefClass || this.body instanceof AST_LambdaDefinition)) {
1182
+ must_be_expression(this, "body");
1183
+ }
1184
+ },
1185
+ }, AST_Statement);
1186
+
1187
+ var AST_ExportForeign = DEFNODE("ExportForeign", "aliases keys path quote", {
1188
+ $documentation: "An `export ... from '...'` statement",
1189
+ $propdoc: {
1190
+ aliases: "[string*] array of aliases to export",
1191
+ keys: "[string*] array of keys to import",
1192
+ path: "[string] the path to import module",
1193
+ quote: "[string?] the original quote character",
1194
+ },
1195
+ _validate: function() {
1196
+ if (this.aliases.length != this.keys.length) {
1197
+ throw new Error("aliases:key length mismatch: " + this.aliases.length + " != " + this.keys.length);
1198
+ }
1199
+ this.aliases.forEach(function(name) {
1200
+ if (typeof name != "string") throw new Error("aliases must contain string");
1201
+ });
1202
+ this.keys.forEach(function(name) {
1203
+ if (typeof name != "string") throw new Error("keys must contain string");
1204
+ });
1205
+ if (typeof this.path != "string") throw new Error("path must be string");
1206
+ if (this.quote != null) {
1207
+ if (typeof this.quote != "string") throw new Error("quote must be string");
1208
+ if (!/^["']$/.test(this.quote)) throw new Error("invalid quote: " + this.quote);
1209
+ }
1210
+ },
1211
+ }, AST_Statement);
1212
+
1213
+ var AST_ExportReferences = DEFNODE("ExportReferences", "properties", {
1214
+ $documentation: "An `export { ... }` statement",
1215
+ $propdoc: {
1216
+ properties: "[AST_SymbolExport*] array of aliases to export",
1217
+ },
1218
+ walk: function(visitor) {
1219
+ var node = this;
1220
+ visitor.visit(node, function() {
1221
+ node.properties.forEach(function(prop) {
1222
+ prop.walk(visitor);
1223
+ });
1224
+ });
1225
+ },
1226
+ _validate: function() {
1227
+ this.properties.forEach(function(prop) {
1228
+ if (!(prop instanceof AST_SymbolExport)) throw new Error("properties must contain AST_SymbolExport");
1229
+ });
1230
+ },
1231
+ }, AST_Statement);
1232
+
1233
+ var AST_Import = DEFNODE("Import", "all default path properties quote", {
1234
+ $documentation: "An `import` statement",
1235
+ $propdoc: {
1236
+ all: "[AST_SymbolImport?] the imported namespace, or null if not specified",
1237
+ default: "[AST_SymbolImport?] the alias for default `export`, or null if not specified",
1238
+ path: "[string] the path to import module",
1239
+ properties: "[(AST_SymbolImport*)?] array of aliases, or null if not specified",
1240
+ quote: "[string?] the original quote character",
1241
+ },
1242
+ walk: function(visitor) {
1243
+ var node = this;
1244
+ visitor.visit(node, function() {
1245
+ if (node.all) node.all.walk(visitor);
1246
+ if (node.default) node.default.walk(visitor);
1247
+ if (node.properties) node.properties.forEach(function(prop) {
1248
+ prop.walk(visitor);
1249
+ });
1250
+ });
1251
+ },
1252
+ _validate: function() {
1253
+ if (this.all != null) {
1254
+ if (!(this.all instanceof AST_SymbolImport)) throw new Error("all must be AST_SymbolImport");
1255
+ if (this.properties != null) throw new Error("cannot import both * and {} in the same statement");
1256
+ }
1257
+ if (this.default != null) {
1258
+ if (!(this.default instanceof AST_SymbolImport)) throw new Error("default must be AST_SymbolImport");
1259
+ if (this.default.key !== "") throw new Error("invalid default key: " + this.default.key);
1260
+ }
1261
+ if (typeof this.path != "string") throw new Error("path must be string");
1262
+ if (this.properties != null) this.properties.forEach(function(node) {
1263
+ if (!(node instanceof AST_SymbolImport)) throw new Error("properties must contain AST_SymbolImport");
1264
+ });
1265
+ if (this.quote != null) {
1266
+ if (typeof this.quote != "string") throw new Error("quote must be string");
1267
+ if (!/^["']$/.test(this.quote)) throw new Error("invalid quote: " + this.quote);
1268
+ }
1269
+ },
1270
+ }, AST_Statement);
1271
+
1272
+ var AST_DefaultValue = DEFNODE("DefaultValue", "name value", {
1273
+ $documentation: "A default value declaration",
1274
+ $propdoc: {
1275
+ name: "[AST_Destructured|AST_SymbolDeclaration] name of the variable",
1276
+ value: "[AST_Node] value to assign if variable is `undefined`",
1277
+ },
1278
+ walk: function(visitor) {
1279
+ var node = this;
1280
+ visitor.visit(node, function() {
1281
+ node.name.walk(visitor);
1282
+ node.value.walk(visitor);
1283
+ });
1284
+ },
1285
+ _validate: function() {
1286
+ must_be_expression(this, "value");
1287
+ },
1288
+ });
1289
+
1290
+ function must_be_expressions(node, prop, allow_spread, allow_hole) {
1291
+ node[prop].forEach(function(node) {
1292
+ validate_expression(node, prop, true, allow_spread, allow_hole);
1293
+ });
1294
+ }
1295
+
1296
+ var AST_Call = DEFNODE("Call", "expression args pure", {
1297
+ $documentation: "A function call expression",
1298
+ $propdoc: {
1299
+ expression: "[AST_Node] expression to invoke as function",
1300
+ args: "[AST_Node*] array of arguments"
1301
+ },
1302
+ walk: function(visitor) {
1303
+ var node = this;
1304
+ visitor.visit(node, function() {
1305
+ node.expression.walk(visitor);
1306
+ node.args.forEach(function(arg) {
1307
+ arg.walk(visitor);
1308
+ });
1309
+ });
1310
+ },
1311
+ _validate: function() {
1312
+ must_be_expression(this, "expression");
1313
+ must_be_expressions(this, "args", true);
1314
+ },
1315
+ });
1316
+
1317
+ var AST_New = DEFNODE("New", null, {
1318
+ $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties"
1319
+ }, AST_Call);
1320
+
1321
+ var AST_Sequence = DEFNODE("Sequence", "expressions", {
1322
+ $documentation: "A sequence expression (comma-separated expressions)",
1323
+ $propdoc: {
1324
+ expressions: "[AST_Node*] array of expressions (at least two)"
1325
+ },
1326
+ walk: function(visitor) {
1327
+ var node = this;
1328
+ visitor.visit(node, function() {
1329
+ node.expressions.forEach(function(expr) {
1330
+ expr.walk(visitor);
1331
+ });
1332
+ });
1333
+ },
1334
+ _validate: function() {
1335
+ if (this.expressions.length < 2) throw new Error("expressions must contain multiple elements");
1336
+ must_be_expressions(this, "expressions");
1337
+ },
1338
+ });
1339
+
1340
+ var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
1341
+ $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`",
1342
+ $propdoc: {
1343
+ expression: "[AST_Node] the “container” expression",
1344
+ property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node"
1345
+ },
1346
+ getProperty: function() {
1347
+ var p = this.property;
1348
+ if (p instanceof AST_Constant) {
1349
+ return p.value;
1350
+ }
1351
+ if (p instanceof AST_UnaryPrefix
1352
+ && p.operator == "void"
1353
+ && p.expression instanceof AST_Constant) {
1354
+ return;
1355
+ }
1356
+ return p;
1357
+ },
1358
+ _validate: function() {
1359
+ if (this.TYPE == "PropAccess") throw new Error("should not instantiate AST_PropAccess");
1360
+ must_be_expression(this, "expression");
1361
+ },
1362
+ });
1363
+
1364
+ var AST_Dot = DEFNODE("Dot", null, {
1365
+ $documentation: "A dotted property access expression",
1366
+ walk: function(visitor) {
1367
+ var node = this;
1368
+ visitor.visit(node, function() {
1369
+ node.expression.walk(visitor);
1370
+ });
1371
+ },
1372
+ _validate: function() {
1373
+ if (typeof this.property != "string") throw new Error("property must be string");
1374
+ },
1375
+ }, AST_PropAccess);
1376
+
1377
+ var AST_Sub = DEFNODE("Sub", null, {
1378
+ $documentation: "Index-style property access, i.e. `a[\"foo\"]`",
1379
+ walk: function(visitor) {
1380
+ var node = this;
1381
+ visitor.visit(node, function() {
1382
+ node.expression.walk(visitor);
1383
+ node.property.walk(visitor);
1384
+ });
1385
+ },
1386
+ _validate: function() {
1387
+ must_be_expression(this, "property");
1388
+ },
1389
+ }, AST_PropAccess);
1390
+
1391
+ var AST_Spread = DEFNODE("Spread", "expression", {
1392
+ $documentation: "Spread expression in array/object literals or function calls",
1393
+ $propdoc: {
1394
+ expression: "[AST_Node] expression to be expanded",
1395
+ },
1396
+ walk: function(visitor) {
1397
+ var node = this;
1398
+ visitor.visit(node, function() {
1399
+ node.expression.walk(visitor);
1400
+ });
1401
+ },
1402
+ _validate: function() {
1403
+ must_be_expression(this, "expression");
1404
+ },
1405
+ });
1406
+
1407
+ var AST_Unary = DEFNODE("Unary", "operator expression", {
1408
+ $documentation: "Base class for unary expressions",
1409
+ $propdoc: {
1410
+ operator: "[string] the operator",
1411
+ expression: "[AST_Node] expression that this unary operator applies to"
1412
+ },
1413
+ walk: function(visitor) {
1414
+ var node = this;
1415
+ visitor.visit(node, function() {
1416
+ node.expression.walk(visitor);
1417
+ });
1418
+ },
1419
+ _validate: function() {
1420
+ if (this.TYPE == "Unary") throw new Error("should not instantiate AST_Unary");
1421
+ if (typeof this.operator != "string") throw new Error("operator must be string");
1422
+ must_be_expression(this, "expression");
1423
+ },
1424
+ });
1425
+
1426
+ var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, {
1427
+ $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`"
1428
+ }, AST_Unary);
1429
+
1430
+ var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
1431
+ $documentation: "Unary postfix expression, i.e. `i++`"
1432
+ }, AST_Unary);
1433
+
1434
+ var AST_Binary = DEFNODE("Binary", "operator left right", {
1435
+ $documentation: "Binary expression, i.e. `a + b`",
1436
+ $propdoc: {
1437
+ left: "[AST_Node] left-hand side expression",
1438
+ operator: "[string] the operator",
1439
+ right: "[AST_Node] right-hand side expression"
1440
+ },
1441
+ walk: function(visitor) {
1442
+ var node = this;
1443
+ visitor.visit(node, function() {
1444
+ node.left.walk(visitor);
1445
+ node.right.walk(visitor);
1446
+ });
1447
+ },
1448
+ _validate: function() {
1449
+ if (!(this instanceof AST_Assign)) must_be_expression(this, "left");
1450
+ if (typeof this.operator != "string") throw new Error("operator must be string");
1451
+ must_be_expression(this, "right");
1452
+ },
1453
+ });
1454
+
1455
+ var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", {
1456
+ $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`",
1457
+ $propdoc: {
1458
+ condition: "[AST_Node]",
1459
+ consequent: "[AST_Node]",
1460
+ alternative: "[AST_Node]"
1461
+ },
1462
+ walk: function(visitor) {
1463
+ var node = this;
1464
+ visitor.visit(node, function() {
1465
+ node.condition.walk(visitor);
1466
+ node.consequent.walk(visitor);
1467
+ node.alternative.walk(visitor);
1468
+ });
1469
+ },
1470
+ _validate: function() {
1471
+ must_be_expression(this, "condition");
1472
+ must_be_expression(this, "consequent");
1473
+ must_be_expression(this, "alternative");
1474
+ },
1475
+ });
1476
+
1477
+ var AST_Assign = DEFNODE("Assign", null, {
1478
+ $documentation: "An assignment expression — `a = b + 5`",
1479
+ _validate: function() {
1480
+ if (this.operator.indexOf("=") < 0) throw new Error('operator must contain "="');
1481
+ if (this.left instanceof AST_Destructured) {
1482
+ if (this.operator != "=") throw new Error("invalid destructuring operator: " + this.operator);
1483
+ validate_destructured(this.left, function(node) {
1484
+ if (!(node instanceof AST_PropAccess || node instanceof AST_SymbolRef)) {
1485
+ throw new Error("left must be assignable: " + node.TYPE);
1486
+ }
1487
+ });
1488
+ }
1489
+ },
1490
+ }, AST_Binary);
1491
+
1492
+ var AST_Await = DEFNODE("Await", "expression", {
1493
+ $documentation: "An await expression",
1494
+ $propdoc: {
1495
+ expression: "[AST_Node] expression with Promise to resolve on",
1496
+ },
1497
+ walk: function(visitor) {
1498
+ var node = this;
1499
+ visitor.visit(node, function() {
1500
+ node.expression.walk(visitor);
1501
+ });
1502
+ },
1503
+ _validate: function() {
1504
+ must_be_expression(this, "expression");
1505
+ },
1506
+ });
1507
+
1508
+ var AST_Yield = DEFNODE("Yield", "expression nested", {
1509
+ $documentation: "A yield expression",
1510
+ $propdoc: {
1511
+ expression: "[AST_Node?] return value for iterator, or null if undefined",
1512
+ nested: "[boolean] whether to iterate over expression as generator",
1513
+ },
1514
+ walk: function(visitor) {
1515
+ var node = this;
1516
+ visitor.visit(node, function() {
1517
+ if (node.expression) node.expression.walk(visitor);
1518
+ });
1519
+ },
1520
+ _validate: function() {
1521
+ if (this.expression != null) {
1522
+ must_be_expression(this, "expression");
1523
+ } else if (this.nested) {
1524
+ throw new Error("yield* must contain expression");
1525
+ }
1526
+ },
1527
+ });
1528
+
1529
+ /* -----[ LITERALS ]----- */
1530
+
1531
+ var AST_Array = DEFNODE("Array", "elements", {
1532
+ $documentation: "An array literal",
1533
+ $propdoc: {
1534
+ elements: "[AST_Node*] array of elements"
1535
+ },
1536
+ walk: function(visitor) {
1537
+ var node = this;
1538
+ visitor.visit(node, function() {
1539
+ node.elements.forEach(function(element) {
1540
+ element.walk(visitor);
1541
+ });
1542
+ });
1543
+ },
1544
+ _validate: function() {
1545
+ must_be_expressions(this, "elements", true, true);
1546
+ },
1547
+ });
1548
+
1549
+ var AST_Destructured = DEFNODE("Destructured", "rest", {
1550
+ $documentation: "Base class for destructured literal",
1551
+ $propdoc: {
1552
+ rest: "[(AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef)?] rest parameter, or null if absent",
1553
+ },
1554
+ _validate: function() {
1555
+ if (this.TYPE == "Destructured") throw new Error("should not instantiate AST_Destructured");
1556
+ },
1557
+ });
1558
+
1559
+ function validate_destructured(node, check, allow_default) {
1560
+ if (node instanceof AST_DefaultValue && allow_default) return validate_destructured(node.name, check);
1561
+ if (node instanceof AST_Destructured) {
1562
+ if (node.rest != null) validate_destructured(node.rest, check);
1563
+ if (node instanceof AST_DestructuredArray) return node.elements.forEach(function(node) {
1564
+ if (!(node instanceof AST_Hole)) validate_destructured(node, check, true);
1565
+ });
1566
+ if (node instanceof AST_DestructuredObject) return node.properties.forEach(function(prop) {
1567
+ validate_destructured(prop.value, check, true);
1568
+ });
1569
+ }
1570
+ check(node);
1571
+ }
1572
+
1573
+ var AST_DestructuredArray = DEFNODE("DestructuredArray", "elements", {
1574
+ $documentation: "A destructured array literal",
1575
+ $propdoc: {
1576
+ elements: "[(AST_DefaultValue|AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef)*] array of elements",
1577
+ },
1578
+ walk: function(visitor) {
1579
+ var node = this;
1580
+ visitor.visit(node, function() {
1581
+ node.elements.forEach(function(element) {
1582
+ element.walk(visitor);
1583
+ });
1584
+ if (node.rest) node.rest.walk(visitor);
1585
+ });
1586
+ },
1587
+ }, AST_Destructured);
1588
+
1589
+ var AST_DestructuredKeyVal = DEFNODE("DestructuredKeyVal", "key value", {
1590
+ $documentation: "A key: value destructured property",
1591
+ $propdoc: {
1592
+ key: "[string|AST_Node] property name. For computed property this is an AST_Node.",
1593
+ value: "[AST_DefaultValue|AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef] property value",
1594
+ },
1595
+ walk: function(visitor) {
1596
+ var node = this;
1597
+ visitor.visit(node, function() {
1598
+ if (node.key instanceof AST_Node) node.key.walk(visitor);
1599
+ node.value.walk(visitor);
1600
+ });
1601
+ },
1602
+ _validate: function() {
1603
+ if (typeof this.key != "string") {
1604
+ if (!(this.key instanceof AST_Node)) throw new Error("key must be string or AST_Node");
1605
+ must_be_expression(this, "key");
1606
+ }
1607
+ if (!(this.value instanceof AST_Node)) throw new Error("value must be AST_Node");
1608
+ },
1609
+ });
1610
+
1611
+ var AST_DestructuredObject = DEFNODE("DestructuredObject", "properties", {
1612
+ $documentation: "A destructured object literal",
1613
+ $propdoc: {
1614
+ properties: "[AST_DestructuredKeyVal*] array of properties",
1615
+ },
1616
+ walk: function(visitor) {
1617
+ var node = this;
1618
+ visitor.visit(node, function() {
1619
+ node.properties.forEach(function(prop) {
1620
+ prop.walk(visitor);
1621
+ });
1622
+ if (node.rest) node.rest.walk(visitor);
1623
+ });
1624
+ },
1625
+ _validate: function() {
1626
+ this.properties.forEach(function(node) {
1627
+ if (!(node instanceof AST_DestructuredKeyVal)) throw new Error("properties must be AST_DestructuredKeyVal[]");
1628
+ });
1629
+ },
1630
+ }, AST_Destructured);
1631
+
1632
+ var AST_Object = DEFNODE("Object", "properties", {
1633
+ $documentation: "An object literal",
1634
+ $propdoc: {
1635
+ properties: "[(AST_ObjectProperty|AST_Spread)*] array of properties"
1636
+ },
1637
+ walk: function(visitor) {
1638
+ var node = this;
1639
+ visitor.visit(node, function() {
1640
+ node.properties.forEach(function(prop) {
1641
+ prop.walk(visitor);
1642
+ });
1643
+ });
1644
+ },
1645
+ _validate: function() {
1646
+ this.properties.forEach(function(node) {
1647
+ if (!(node instanceof AST_ObjectProperty || node instanceof AST_Spread)) {
1648
+ throw new Error("properties must contain AST_ObjectProperty and/or AST_Spread only");
1649
+ }
1650
+ });
1651
+ },
1652
+ });
1653
+
1654
+ var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
1655
+ $documentation: "Base class for literal object properties",
1656
+ $propdoc: {
1657
+ key: "[string|AST_Node] property name. For computed property this is an AST_Node.",
1658
+ value: "[AST_Node] property value. For getters and setters this is an AST_Accessor.",
1659
+ },
1660
+ walk: function(visitor) {
1661
+ var node = this;
1662
+ visitor.visit(node, function() {
1663
+ if (node.key instanceof AST_Node) node.key.walk(visitor);
1664
+ node.value.walk(visitor);
1665
+ });
1666
+ },
1667
+ _validate: function() {
1668
+ if (this.TYPE == "ObjectProperty") throw new Error("should not instantiate AST_ObjectProperty");
1669
+ if (typeof this.key != "string") {
1670
+ if (!(this.key instanceof AST_Node)) throw new Error("key must be string or AST_Node");
1671
+ must_be_expression(this, "key");
1672
+ }
1673
+ if (!(this.value instanceof AST_Node)) throw new Error("value must be AST_Node");
1674
+ },
1675
+ });
1676
+
1677
+ var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, {
1678
+ $documentation: "A key: value object property",
1679
+ _validate: function() {
1680
+ must_be_expression(this, "value");
1681
+ },
1682
+ }, AST_ObjectProperty);
1683
+
1684
+ var AST_ObjectMethod = DEFNODE("ObjectMethod", null, {
1685
+ $documentation: "A key(){} object property",
1686
+ _validate: function() {
1687
+ if (!(this.value instanceof AST_LambdaExpression)) throw new Error("value must be AST_LambdaExpression");
1688
+ if (is_arrow(this.value)) throw new Error("value cannot be AST_Arrow or AST_AsyncArrow");
1689
+ if (this.value.name != null) throw new Error("name of class method's lambda must be null");
1690
+ },
1691
+ }, AST_ObjectKeyVal);
1692
+
1693
+ var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
1694
+ $documentation: "An object setter property",
1695
+ _validate: function() {
1696
+ if (!(this.value instanceof AST_Accessor)) throw new Error("value must be AST_Accessor");
1697
+ },
1698
+ }, AST_ObjectProperty);
1699
+
1700
+ var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {
1701
+ $documentation: "An object getter property",
1702
+ _validate: function() {
1703
+ if (!(this.value instanceof AST_Accessor)) throw new Error("value must be AST_Accessor");
1704
+ },
1705
+ }, AST_ObjectProperty);
1706
+
1707
+ var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
1708
+ $documentation: "Base class for all symbols",
1709
+ $propdoc: {
1710
+ name: "[string] name of this symbol",
1711
+ scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
1712
+ thedef: "[SymbolDef/S] the definition of this symbol"
1713
+ },
1714
+ _validate: function() {
1715
+ if (this.TYPE == "Symbol") throw new Error("should not instantiate AST_Symbol");
1716
+ if (typeof this.name != "string") throw new Error("name must be string");
1717
+ },
1718
+ });
1719
+
1720
+ var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
1721
+ $documentation: "A declaration symbol (symbol in var, function name or argument, symbol in catch)",
1722
+ }, AST_Symbol);
1723
+
1724
+ var AST_SymbolConst = DEFNODE("SymbolConst", null, {
1725
+ $documentation: "Symbol defining a constant",
1726
+ }, AST_SymbolDeclaration);
1727
+
1728
+ var AST_SymbolImport = DEFNODE("SymbolImport", "key", {
1729
+ $documentation: "Symbol defined by an `import` statement",
1730
+ $propdoc: {
1731
+ key: "[string] the original `export` name",
1732
+ },
1733
+ _validate: function() {
1734
+ if (typeof this.key != "string") throw new Error("key must be string");
1735
+ },
1736
+ }, AST_SymbolConst);
1737
+
1738
+ var AST_SymbolLet = DEFNODE("SymbolLet", null, {
1739
+ $documentation: "Symbol defining a lexical-scoped variable",
1740
+ }, AST_SymbolDeclaration);
1741
+
1742
+ var AST_SymbolVar = DEFNODE("SymbolVar", null, {
1743
+ $documentation: "Symbol defining a variable",
1744
+ }, AST_SymbolDeclaration);
1745
+
1746
+ var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
1747
+ $documentation: "Symbol naming a function argument",
1748
+ }, AST_SymbolVar);
1749
+
1750
+ var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {
1751
+ $documentation: "Symbol defining a function",
1752
+ }, AST_SymbolDeclaration);
1753
+
1754
+ var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {
1755
+ $documentation: "Symbol naming a function expression",
1756
+ }, AST_SymbolDeclaration);
1757
+
1758
+ var AST_SymbolDefClass = DEFNODE("SymbolDefClass", null, {
1759
+ $documentation: "Symbol defining a class",
1760
+ }, AST_SymbolLet);
1761
+
1762
+ var AST_SymbolClass = DEFNODE("SymbolClass", null, {
1763
+ $documentation: "Symbol naming a class expression",
1764
+ }, AST_SymbolLet);
1765
+
1766
+ var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
1767
+ $documentation: "Symbol naming the exception in catch",
1768
+ }, AST_SymbolDeclaration);
1769
+
1770
+ var AST_Label = DEFNODE("Label", "references", {
1771
+ $documentation: "Symbol naming a label (declaration)",
1772
+ $propdoc: {
1773
+ references: "[AST_LoopControl*] a list of nodes referring to this label"
1774
+ },
1775
+ initialize: function() {
1776
+ this.references = [];
1777
+ this.thedef = this;
1778
+ }
1779
+ }, AST_Symbol);
1780
+
1781
+ var AST_SymbolRef = DEFNODE("SymbolRef", "fixed in_arg redef", {
1782
+ $documentation: "Reference to some symbol (not definition/declaration)",
1783
+ }, AST_Symbol);
1784
+
1785
+ var AST_SymbolExport = DEFNODE("SymbolExport", "alias", {
1786
+ $documentation: "Reference in an `export` statement",
1787
+ $propdoc: {
1788
+ alias: "[string] the `export` alias",
1789
+ },
1790
+ _validate: function() {
1791
+ if (typeof this.alias != "string") throw new Error("alias must be string");
1792
+ },
1793
+ }, AST_SymbolRef);
1794
+
1795
+ var AST_LabelRef = DEFNODE("LabelRef", null, {
1796
+ $documentation: "Reference to a label symbol",
1797
+ }, AST_Symbol);
1798
+
1799
+ var AST_ObjectIdentity = DEFNODE("ObjectIdentity", null, {
1800
+ $documentation: "Base class for `super` & `this`",
1801
+ _validate: function() {
1802
+ if (this.TYPE == "ObjectIdentity") throw new Error("should not instantiate AST_ObjectIdentity");
1803
+ },
1804
+ }, AST_Symbol);
1805
+
1806
+ var AST_Super = DEFNODE("Super", null, {
1807
+ $documentation: "The `super` symbol",
1808
+ _validate: function() {
1809
+ if (this.name !== "super") throw new Error('name must be "super"');
1810
+ },
1811
+ }, AST_ObjectIdentity);
1812
+
1813
+ var AST_This = DEFNODE("This", null, {
1814
+ $documentation: "The `this` symbol",
1815
+ _validate: function() {
1816
+ if (this.TYPE == "This" && this.name !== "this") throw new Error('name must be "this"');
1817
+ },
1818
+ }, AST_ObjectIdentity);
1819
+
1820
+ var AST_NewTarget = DEFNODE("NewTarget", null, {
1821
+ $documentation: "The `new.target` symbol",
1822
+ initialize: function() {
1823
+ this.name = "new.target";
1824
+ },
1825
+ _validate: function() {
1826
+ if (this.name !== "new.target") throw new Error('name must be "new.target": ' + this.name);
1827
+ },
1828
+ }, AST_This);
1829
+
1830
+ var AST_Template = DEFNODE("Template", "expressions strings tag", {
1831
+ $documentation: "A template literal, i.e. tag`str1${expr1}...strN${exprN}strN+1`",
1832
+ $propdoc: {
1833
+ expressions: "[AST_Node*] the placeholder expressions",
1834
+ strings: "[string*] the raw text segments",
1835
+ tag: "[AST_Node] tag function, or null if absent",
1836
+ },
1837
+ walk: function(visitor) {
1838
+ var node = this;
1839
+ visitor.visit(node, function() {
1840
+ if (node.tag) node.tag.walk(visitor);
1841
+ node.expressions.forEach(function(expr) {
1842
+ expr.walk(visitor);
1843
+ });
1844
+ });
1845
+ },
1846
+ _validate: function() {
1847
+ if (this.expressions.length + 1 != this.strings.length) {
1848
+ throw new Error("malformed template with " + this.expressions.length + " placeholder(s) but " + this.strings.length + " text segment(s)");
1849
+ }
1850
+ must_be_expressions(this, "expressions");
1851
+ this.strings.forEach(function(string) {
1852
+ if (typeof string != "string") throw new Error("strings must contain string");
1853
+ });
1854
+ if (this.tag != null) must_be_expression(this, "tag");
1855
+ },
1856
+ });
1857
+
1858
+ var AST_Constant = DEFNODE("Constant", null, {
1859
+ $documentation: "Base class for all constants",
1860
+ _validate: function() {
1861
+ if (this.TYPE == "Constant") throw new Error("should not instantiate AST_Constant");
1862
+ },
1863
+ });
1864
+
1865
+ var AST_String = DEFNODE("String", "quote value", {
1866
+ $documentation: "A string literal",
1867
+ $propdoc: {
1868
+ quote: "[string?] the original quote character",
1869
+ value: "[string] the contents of this string",
1870
+ },
1871
+ _validate: function() {
1872
+ if (this.quote != null) {
1873
+ if (typeof this.quote != "string") throw new Error("quote must be string");
1874
+ if (!/^["']$/.test(this.quote)) throw new Error("invalid quote: " + this.quote);
1875
+ }
1876
+ if (typeof this.value != "string") throw new Error("value must be string");
1877
+ },
1878
+ }, AST_Constant);
1879
+
1880
+ var AST_Number = DEFNODE("Number", "value", {
1881
+ $documentation: "A number literal",
1882
+ $propdoc: {
1883
+ value: "[number] the numeric value",
1884
+ },
1885
+ _validate: function() {
1886
+ if (typeof this.value != "number") throw new Error("value must be number");
1887
+ if (!isFinite(this.value)) throw new Error("value must be finite");
1888
+ if (this.value < 0) throw new Error("value cannot be negative");
1889
+ },
1890
+ }, AST_Constant);
1891
+
1892
+ var AST_BigInt = DEFNODE("BigInt", "value", {
1893
+ $documentation: "A BigInt literal",
1894
+ $propdoc: {
1895
+ value: "[string] the numeric representation",
1896
+ },
1897
+ _validate: function() {
1898
+ if (typeof this.value != "string") throw new Error("value must be string");
1899
+ if (this.value[0] == "-") throw new Error("value cannot be negative");
1900
+ },
1901
+ }, AST_Constant);
1902
+
1903
+ var AST_RegExp = DEFNODE("RegExp", "value", {
1904
+ $documentation: "A regexp literal",
1905
+ $propdoc: {
1906
+ value: "[RegExp] the actual regexp"
1907
+ },
1908
+ _validate: function() {
1909
+ if (!(this.value instanceof RegExp)) throw new Error("value must be RegExp");
1910
+ },
1911
+ }, AST_Constant);
1912
+
1913
+ var AST_Atom = DEFNODE("Atom", null, {
1914
+ $documentation: "Base class for atoms",
1915
+ _validate: function() {
1916
+ if (this.TYPE == "Atom") throw new Error("should not instantiate AST_Atom");
1917
+ },
1918
+ }, AST_Constant);
1919
+
1920
+ var AST_Null = DEFNODE("Null", null, {
1921
+ $documentation: "The `null` atom",
1922
+ value: null
1923
+ }, AST_Atom);
1924
+
1925
+ var AST_NaN = DEFNODE("NaN", null, {
1926
+ $documentation: "The impossible value",
1927
+ value: 0/0
1928
+ }, AST_Atom);
1929
+
1930
+ var AST_Undefined = DEFNODE("Undefined", null, {
1931
+ $documentation: "The `undefined` value",
1932
+ value: function(){}()
1933
+ }, AST_Atom);
1934
+
1935
+ var AST_Hole = DEFNODE("Hole", null, {
1936
+ $documentation: "A hole in an array",
1937
+ value: function(){}()
1938
+ }, AST_Atom);
1939
+
1940
+ var AST_Infinity = DEFNODE("Infinity", null, {
1941
+ $documentation: "The `Infinity` value",
1942
+ value: 1/0
1943
+ }, AST_Atom);
1944
+
1945
+ var AST_Boolean = DEFNODE("Boolean", null, {
1946
+ $documentation: "Base class for booleans",
1947
+ _validate: function() {
1948
+ if (this.TYPE == "Boolean") throw new Error("should not instantiate AST_Boolean");
1949
+ },
1950
+ }, AST_Atom);
1951
+
1952
+ var AST_False = DEFNODE("False", null, {
1953
+ $documentation: "The `false` atom",
1954
+ value: false
1955
+ }, AST_Boolean);
1956
+
1957
+ var AST_True = DEFNODE("True", null, {
1958
+ $documentation: "The `true` atom",
1959
+ value: true
1960
+ }, AST_Boolean);
1961
+
1962
+ /* -----[ TreeWalker ]----- */
1963
+
1964
+ function TreeWalker(callback) {
1965
+ this.callback = callback;
1966
+ this.directives = Object.create(null);
1967
+ this.stack = [];
1968
+ }
1969
+ TreeWalker.prototype = {
1970
+ visit: function(node, descend) {
1971
+ this.push(node);
1972
+ var done = this.callback(node, descend || noop);
1973
+ if (!done && descend) descend();
1974
+ this.pop();
1975
+ },
1976
+ parent: function(n) {
1977
+ return this.stack[this.stack.length - 2 - (n || 0)];
1978
+ },
1979
+ push: function(node) {
1980
+ if (node instanceof AST_Lambda) {
1981
+ this.directives = Object.create(this.directives);
1982
+ } else if (node instanceof AST_Directive && !this.directives[node.value]) {
1983
+ this.directives[node.value] = node;
1984
+ }
1985
+ this.stack.push(node);
1986
+ },
1987
+ pop: function() {
1988
+ var node = this.stack.pop();
1989
+ if (node instanceof AST_Lambda) {
1990
+ this.directives = Object.getPrototypeOf(this.directives);
1991
+ }
1992
+ },
1993
+ self: function() {
1994
+ return this.stack[this.stack.length - 1];
1995
+ },
1996
+ find_parent: function(type) {
1997
+ var stack = this.stack;
1998
+ for (var i = stack.length; --i >= 0;) {
1999
+ var x = stack[i];
2000
+ if (x instanceof type) return x;
2001
+ }
2002
+ },
2003
+ has_directive: function(type) {
2004
+ var dir = this.directives[type];
2005
+ if (dir) return dir;
2006
+ var node = this.stack[this.stack.length - 1];
2007
+ if (node instanceof AST_Scope) {
2008
+ for (var i = 0; i < node.body.length; ++i) {
2009
+ var st = node.body[i];
2010
+ if (!(st instanceof AST_Directive)) break;
2011
+ if (st.value == type) return st;
2012
+ }
2013
+ }
2014
+ },
2015
+ loopcontrol_target: function(node) {
2016
+ var stack = this.stack;
2017
+ if (node.label) for (var i = stack.length; --i >= 0;) {
2018
+ var x = stack[i];
2019
+ if (x instanceof AST_LabeledStatement && x.label.name == node.label.name)
2020
+ return x.body;
2021
+ } else for (var i = stack.length; --i >= 0;) {
2022
+ var x = stack[i];
2023
+ if (x instanceof AST_IterationStatement
2024
+ || node instanceof AST_Break && x instanceof AST_Switch)
2025
+ return x;
2026
+ }
2027
+ },
2028
+ in_boolean_context: function() {
2029
+ var self = this.self();
2030
+ for (var i = 0, p; p = this.parent(i); i++) {
2031
+ if (p instanceof AST_Conditional && p.condition === self
2032
+ || p instanceof AST_DWLoop && p.condition === self
2033
+ || p instanceof AST_For && p.condition === self
2034
+ || p instanceof AST_If && p.condition === self
2035
+ || p instanceof AST_Return && p.in_bool
2036
+ || p instanceof AST_Sequence && p.tail_node() !== self
2037
+ || p instanceof AST_SimpleStatement
2038
+ || p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) {
2039
+ return true;
2040
+ }
2041
+ if (p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")
2042
+ || p instanceof AST_Conditional
2043
+ || p.tail_node() === self) {
2044
+ self = p;
2045
+ } else if (p instanceof AST_Return) {
2046
+ for (var call, fn = p; call = this.parent(++i); fn = call) {
2047
+ if (call.TYPE == "Call") {
2048
+ if (!(fn instanceof AST_Lambda) || fn.name) return false;
2049
+ } else if (fn instanceof AST_Lambda) {
2050
+ return false;
2051
+ }
2052
+ }
2053
+ } else {
2054
+ return false;
2055
+ }
2056
+ }
2057
+ }
2058
+ };