Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/third_party/terser/terser.js
6162 views
1
(function (global, factory) {
2
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
(global = global || self, factory(global.Terser = {}));
5
}(this, (function (exports) { 'use strict';
6
7
/***********************************************************************
8
9
A JavaScript tokenizer / parser / beautifier / compressor.
10
https://github.com/mishoo/UglifyJS2
11
12
-------------------------------- (C) ---------------------------------
13
14
Author: Mihai Bazon
15
<[email protected]>
16
http://mihai.bazon.net/blog
17
18
Distributed under the BSD license:
19
20
Copyright 2012 (c) Mihai Bazon <[email protected]>
21
22
Redistribution and use in source and binary forms, with or without
23
modification, are permitted provided that the following conditions
24
are met:
25
26
* Redistributions of source code must retain the above
27
copyright notice, this list of conditions and the following
28
disclaimer.
29
30
* Redistributions in binary form must reproduce the above
31
copyright notice, this list of conditions and the following
32
disclaimer in the documentation and/or other materials
33
provided with the distribution.
34
35
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
36
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
39
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
40
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
41
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
45
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46
SUCH DAMAGE.
47
48
***********************************************************************/
49
50
function characters(str) {
51
return str.split("");
52
}
53
54
class DefaultsError extends Error {
55
constructor(msg, defs) {
56
super();
57
58
this.name = "DefaultsError";
59
this.message = msg;
60
this.defs = defs;
61
}
62
}
63
64
function defaults(args, defs, croak) {
65
if (args === true) {
66
args = {};
67
} else if (args != null && typeof args === "object") {
68
args = {...args};
69
}
70
71
const ret = args || {};
72
73
if (croak) for (const i in ret) if (HOP(ret, i) && !HOP(defs, i)) {
74
throw new DefaultsError("`" + i + "` is not a supported option", defs);
75
}
76
77
for (const i in defs) if (HOP(defs, i)) {
78
if (!args || !HOP(args, i)) {
79
ret[i] = defs[i];
80
} else if (i === "ecma") {
81
let ecma = args[i] | 0;
82
if (ecma > 5 && ecma < 2015) ecma += 2009;
83
ret[i] = ecma;
84
} else {
85
ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
86
}
87
}
88
89
return ret;
90
}
91
92
function noop() {}
93
function return_false() { return false; }
94
function return_true() { return true; }
95
function return_this() { return this; }
96
97
var MAP = (function() {
98
function MAP(a, tw, allow_splicing = true) {
99
const new_a = [];
100
101
for (let i = 0; i < a.length; ++i) {
102
let item = a[i];
103
let ret = item.transform(tw, allow_splicing);
104
105
if (ret instanceof AST_Node) {
106
new_a.push(ret);
107
} else if (ret instanceof Splice) {
108
new_a.push(...ret.v);
109
}
110
}
111
112
return new_a;
113
}
114
115
MAP.splice = function(val) { return new Splice(val); };
116
MAP.skip = {};
117
function Splice(val) { this.v = val; }
118
return MAP;
119
})();
120
121
function make_node(ctor, orig, props) {
122
if (!props) props = {};
123
if (orig) {
124
if (!props.start) props.start = orig.start;
125
if (!props.end) props.end = orig.end;
126
}
127
return new ctor(props);
128
}
129
130
function push_uniq(array, el) {
131
if (!array.includes(el))
132
array.push(el);
133
}
134
135
function string_template(text, props) {
136
return text.replace(/{(.+?)}/g, function(str, p) {
137
return props && props[p];
138
});
139
}
140
141
function mergeSort(array, cmp) {
142
if (array.length < 2) return array.slice();
143
function merge(a, b) {
144
var r = [], ai = 0, bi = 0, i = 0;
145
while (ai < a.length && bi < b.length) {
146
cmp(a[ai], b[bi]) <= 0
147
? r[i++] = a[ai++]
148
: r[i++] = b[bi++];
149
}
150
if (ai < a.length) r.push.apply(r, a.slice(ai));
151
if (bi < b.length) r.push.apply(r, b.slice(bi));
152
return r;
153
}
154
function _ms(a) {
155
if (a.length <= 1)
156
return a;
157
var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
158
left = _ms(left);
159
right = _ms(right);
160
return merge(left, right);
161
}
162
return _ms(array);
163
}
164
165
function makePredicate(words) {
166
if (!Array.isArray(words)) words = words.split(" ");
167
168
return new Set(words.sort());
169
}
170
171
function HOP(obj, prop) {
172
return Object.prototype.hasOwnProperty.call(obj, prop);
173
}
174
175
function keep_name(keep_setting, name) {
176
return keep_setting === true
177
|| (keep_setting instanceof RegExp && keep_setting.test(name));
178
}
179
180
var lineTerminatorEscape = {
181
"\0": "0",
182
"\n": "n",
183
"\r": "r",
184
"\u2028": "u2028",
185
"\u2029": "u2029",
186
};
187
function regexp_source_fix(source) {
188
// V8 does not escape line terminators in regexp patterns in node 12
189
// We'll also remove literal \0
190
return source.replace(/[\0\n\r\u2028\u2029]/g, function (match, offset) {
191
var escaped = source[offset - 1] == "\\"
192
&& (source[offset - 2] != "\\"
193
|| /(?:^|[^\\])(?:\\{2})*$/.test(source.slice(0, offset - 1)));
194
return (escaped ? "" : "\\") + lineTerminatorEscape[match];
195
});
196
}
197
198
const all_flags = "dgimsuyv";
199
function sort_regexp_flags(flags) {
200
const existing_flags = new Set(flags.split(""));
201
let out = "";
202
for (const flag of all_flags) {
203
if (existing_flags.has(flag)) {
204
out += flag;
205
existing_flags.delete(flag);
206
}
207
}
208
if (existing_flags.size) {
209
// Flags Terser doesn't know about
210
existing_flags.forEach(flag => { out += flag; });
211
}
212
return out;
213
}
214
215
function set_annotation(node, annotation) {
216
node._annotations |= annotation;
217
}
218
219
/***********************************************************************
220
221
A JavaScript tokenizer / parser / beautifier / compressor.
222
https://github.com/mishoo/UglifyJS2
223
224
-------------------------------- (C) ---------------------------------
225
226
Author: Mihai Bazon
227
<[email protected]>
228
http://mihai.bazon.net/blog
229
230
Distributed under the BSD license:
231
232
Copyright 2012 (c) Mihai Bazon <[email protected]>
233
Parser based on parse-js (http://marijn.haverbeke.nl/parse-js/).
234
235
Redistribution and use in source and binary forms, with or without
236
modification, are permitted provided that the following conditions
237
are met:
238
239
* Redistributions of source code must retain the above
240
copyright notice, this list of conditions and the following
241
disclaimer.
242
243
* Redistributions in binary form must reproduce the above
244
copyright notice, this list of conditions and the following
245
disclaimer in the documentation and/or other materials
246
provided with the distribution.
247
248
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
249
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
250
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
251
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
252
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
253
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
254
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
255
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
256
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
257
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
258
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
259
SUCH DAMAGE.
260
261
***********************************************************************/
262
263
var LATEST_RAW = ""; // Only used for numbers and template strings
264
var TEMPLATE_RAWS = new Map(); // Raw template strings
265
266
var KEYWORDS = "break case catch class const continue debugger default delete do else export extends finally for function if in instanceof let new return switch throw try typeof var void while with";
267
var KEYWORDS_ATOM = "false null true";
268
var RESERVED_WORDS = "enum import super this " + KEYWORDS_ATOM + " " + KEYWORDS;
269
var ALL_RESERVED_WORDS = "implements interface package private protected public static " + RESERVED_WORDS;
270
var KEYWORDS_BEFORE_EXPRESSION = "return new delete throw else case yield await";
271
272
KEYWORDS = makePredicate(KEYWORDS);
273
RESERVED_WORDS = makePredicate(RESERVED_WORDS);
274
KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION);
275
KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM);
276
ALL_RESERVED_WORDS = makePredicate(ALL_RESERVED_WORDS);
277
278
var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
279
280
var RE_NUM_LITERAL = /[0-9a-f]/i;
281
var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
282
var RE_OCT_NUMBER = /^0[0-7]+$/;
283
var RE_ES6_OCT_NUMBER = /^0o[0-7]+$/i;
284
var RE_BIN_NUMBER = /^0b[01]+$/i;
285
var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
286
var RE_BIG_INT = /^(0[xob])?[0-9a-f]+n$/i;
287
288
var OPERATORS = makePredicate([
289
"in",
290
"instanceof",
291
"typeof",
292
"new",
293
"void",
294
"delete",
295
"++",
296
"--",
297
"+",
298
"-",
299
"!",
300
"~",
301
"&",
302
"|",
303
"^",
304
"*",
305
"**",
306
"/",
307
"%",
308
">>",
309
"<<",
310
">>>",
311
"<",
312
">",
313
"<=",
314
">=",
315
"==",
316
"===",
317
"!=",
318
"!==",
319
"?",
320
"=",
321
"+=",
322
"-=",
323
"||=",
324
"&&=",
325
"??=",
326
"/=",
327
"*=",
328
"**=",
329
"%=",
330
">>=",
331
"<<=",
332
">>>=",
333
"|=",
334
"^=",
335
"&=",
336
"&&",
337
"??",
338
"||",
339
]);
340
341
var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\uFEFF"));
342
343
var NEWLINE_CHARS = makePredicate(characters("\n\r\u2028\u2029"));
344
345
var PUNC_AFTER_EXPRESSION = makePredicate(characters(";]),:"));
346
347
var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,;:"));
348
349
var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
350
351
/* -----[ Tokenizer ]----- */
352
353
// surrogate safe regexps adapted from https://github.com/mathiasbynens/unicode-8.0.0/tree/89b412d8a71ecca9ed593d9e9fa073ab64acfebe/Binary_Property
354
var UNICODE = {
355
ID_Start: /[$A-Z_a-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]/,
356
ID_Continue: /(?:[$0-9A-Z_a-z\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B4\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF])+/,
357
};
358
359
try {
360
UNICODE = {
361
// https://262.ecma-international.org/13.0/#prod-IdentifierStartChar
362
// $, _, ID_Start
363
ID_Start: new RegExp("[_$\\p{ID_Start}]", "u"),
364
// https://262.ecma-international.org/13.0/#prod-IdentifierPartChar
365
// $, zero-width-joiner, zero-width-non-joiner, ID_Continue
366
ID_Continue: new RegExp("[$\\u200C\\u200D\\p{ID_Continue}]+", "u"),
367
};
368
} catch(e) {
369
// Could not use modern JS \p{...}. UNICODE is already defined above so let's continue
370
}
371
372
function get_full_char(str, pos) {
373
if (is_surrogate_pair_head(str.charCodeAt(pos))) {
374
if (is_surrogate_pair_tail(str.charCodeAt(pos + 1))) {
375
return str.charAt(pos) + str.charAt(pos + 1);
376
}
377
} else if (is_surrogate_pair_tail(str.charCodeAt(pos))) {
378
if (is_surrogate_pair_head(str.charCodeAt(pos - 1))) {
379
return str.charAt(pos - 1) + str.charAt(pos);
380
}
381
}
382
return str.charAt(pos);
383
}
384
385
function get_full_char_code(str, pos) {
386
// https://en.wikipedia.org/wiki/Universal_Character_Set_characters#Surrogates
387
if (is_surrogate_pair_head(str.charCodeAt(pos))) {
388
return 0x10000 + (str.charCodeAt(pos) - 0xd800 << 10) + str.charCodeAt(pos + 1) - 0xdc00;
389
}
390
return str.charCodeAt(pos);
391
}
392
393
function get_full_char_length(str) {
394
var surrogates = 0;
395
396
for (var i = 0; i < str.length; i++) {
397
if (is_surrogate_pair_head(str.charCodeAt(i)) && is_surrogate_pair_tail(str.charCodeAt(i + 1))) {
398
surrogates++;
399
i++;
400
}
401
}
402
403
return str.length - surrogates;
404
}
405
406
function from_char_code(code) {
407
// Based on https://github.com/mathiasbynens/String.fromCodePoint/blob/master/fromcodepoint.js
408
if (code > 0xFFFF) {
409
code -= 0x10000;
410
return (String.fromCharCode((code >> 10) + 0xD800) +
411
String.fromCharCode((code % 0x400) + 0xDC00));
412
}
413
return String.fromCharCode(code);
414
}
415
416
function is_surrogate_pair_head(code) {
417
return code >= 0xd800 && code <= 0xdbff;
418
}
419
420
function is_surrogate_pair_tail(code) {
421
return code >= 0xdc00 && code <= 0xdfff;
422
}
423
424
function is_digit(code) {
425
return code >= 48 && code <= 57;
426
}
427
428
function is_identifier_start(ch) {
429
return UNICODE.ID_Start.test(ch);
430
}
431
432
function is_identifier_char(ch) {
433
return UNICODE.ID_Continue.test(ch);
434
}
435
436
const BASIC_IDENT = /^[a-z_$][a-z0-9_$]*$/i;
437
438
function is_basic_identifier_string(str) {
439
return BASIC_IDENT.test(str);
440
}
441
442
function is_identifier_string(str, allow_surrogates) {
443
if (BASIC_IDENT.test(str)) {
444
return true;
445
}
446
if (!allow_surrogates && /[\ud800-\udfff]/.test(str)) {
447
return false;
448
}
449
var match = UNICODE.ID_Start.exec(str);
450
if (!match || match.index !== 0) {
451
return false;
452
}
453
454
str = str.slice(match[0].length);
455
if (!str) {
456
return true;
457
}
458
459
match = UNICODE.ID_Continue.exec(str);
460
return !!match && match[0].length === str.length;
461
}
462
463
function parse_js_number(num, allow_e = true) {
464
if (!allow_e && num.includes("e")) {
465
return NaN;
466
}
467
if (RE_HEX_NUMBER.test(num)) {
468
return parseInt(num.substr(2), 16);
469
} else if (RE_OCT_NUMBER.test(num)) {
470
return parseInt(num.substr(1), 8);
471
} else if (RE_ES6_OCT_NUMBER.test(num)) {
472
return parseInt(num.substr(2), 8);
473
} else if (RE_BIN_NUMBER.test(num)) {
474
return parseInt(num.substr(2), 2);
475
} else if (RE_DEC_NUMBER.test(num)) {
476
return parseFloat(num);
477
} else {
478
var val = parseFloat(num);
479
if (val == num) return val;
480
}
481
}
482
483
class JS_Parse_Error extends Error {
484
constructor(message, filename, line, col, pos) {
485
super();
486
487
this.name = "SyntaxError";
488
this.message = message;
489
this.filename = filename;
490
this.line = line;
491
this.col = col;
492
this.pos = pos;
493
}
494
}
495
496
function js_error(message, filename, line, col, pos) {
497
throw new JS_Parse_Error(message, filename, line, col, pos);
498
}
499
500
function is_token(token, type, val) {
501
return token.type == type && (val == null || token.value == val);
502
}
503
504
var EX_EOF = {};
505
506
function tokenizer($TEXT, filename, html5_comments, shebang) {
507
var S = {
508
text : $TEXT,
509
filename : filename,
510
pos : 0,
511
tokpos : 0,
512
line : 1,
513
tokline : 0,
514
col : 0,
515
tokcol : 0,
516
newline_before : false,
517
regex_allowed : false,
518
brace_counter : 0,
519
template_braces : [],
520
comments_before : [],
521
directives : {},
522
directive_stack : []
523
};
524
525
function peek() { return get_full_char(S.text, S.pos); }
526
527
// Used because parsing ?. involves a lookahead for a digit
528
function is_option_chain_op() {
529
const must_be_dot = S.text.charCodeAt(S.pos + 1) === 46;
530
if (!must_be_dot) return false;
531
532
const cannot_be_digit = S.text.charCodeAt(S.pos + 2);
533
return cannot_be_digit < 48 || cannot_be_digit > 57;
534
}
535
536
function next(signal_eof, in_string) {
537
var ch = get_full_char(S.text, S.pos++);
538
if (signal_eof && !ch)
539
throw EX_EOF;
540
if (NEWLINE_CHARS.has(ch)) {
541
S.newline_before = S.newline_before || !in_string;
542
++S.line;
543
S.col = 0;
544
if (ch == "\r" && peek() == "\n") {
545
// treat a \r\n sequence as a single \n
546
++S.pos;
547
ch = "\n";
548
}
549
} else {
550
if (ch.length > 1) {
551
++S.pos;
552
++S.col;
553
}
554
++S.col;
555
}
556
return ch;
557
}
558
559
function forward(i) {
560
while (i--) next();
561
}
562
563
function looking_at(str) {
564
return S.text.substr(S.pos, str.length) == str;
565
}
566
567
function find_eol() {
568
var text = S.text;
569
for (var i = S.pos, n = S.text.length; i < n; ++i) {
570
var ch = text[i];
571
if (NEWLINE_CHARS.has(ch))
572
return i;
573
}
574
return -1;
575
}
576
577
function find(what, signal_eof) {
578
var pos = S.text.indexOf(what, S.pos);
579
if (signal_eof && pos == -1) throw EX_EOF;
580
return pos;
581
}
582
583
function start_token() {
584
S.tokline = S.line;
585
S.tokcol = S.col;
586
S.tokpos = S.pos;
587
}
588
589
var prev_was_dot = false;
590
var previous_token = null;
591
function token(type, value, is_comment) {
592
S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX.has(value)) ||
593
(type == "keyword" && KEYWORDS_BEFORE_EXPRESSION.has(value)) ||
594
(type == "punc" && PUNC_BEFORE_EXPRESSION.has(value))) ||
595
(type == "arrow");
596
if (type == "punc" && (value == "." || value == "?.")) {
597
prev_was_dot = true;
598
} else if (!is_comment) {
599
prev_was_dot = false;
600
}
601
const line = S.tokline;
602
const col = S.tokcol;
603
const pos = S.tokpos;
604
const nlb = S.newline_before;
605
const file = filename;
606
let comments_before = [];
607
let comments_after = [];
608
609
if (!is_comment) {
610
comments_before = S.comments_before;
611
comments_after = S.comments_before = [];
612
}
613
S.newline_before = false;
614
const tok = new AST_Token(type, value, line, col, pos, nlb, comments_before, comments_after, file);
615
616
if (!is_comment) previous_token = tok;
617
return tok;
618
}
619
620
function skip_whitespace() {
621
while (WHITESPACE_CHARS.has(peek()))
622
next();
623
}
624
625
function read_while(pred) {
626
var ret = "", ch, i = 0;
627
while ((ch = peek()) && pred(ch, i++))
628
ret += next();
629
return ret;
630
}
631
632
function parse_error(err) {
633
js_error(err, filename, S.tokline, S.tokcol, S.tokpos);
634
}
635
636
function read_num(prefix) {
637
var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".", is_big_int = false, numeric_separator = false;
638
var num = read_while(function(ch, i) {
639
if (is_big_int) return false;
640
641
var code = ch.charCodeAt(0);
642
switch (code) {
643
case 95: // _
644
return (numeric_separator = true);
645
case 98: case 66: // bB
646
return (has_x = true); // Can occur in hex sequence, don't return false yet
647
case 111: case 79: // oO
648
case 120: case 88: // xX
649
return has_x ? false : (has_x = true);
650
case 101: case 69: // eE
651
return has_x ? true : has_e ? false : (has_e = after_e = true);
652
case 45: // -
653
return after_e || (i == 0 && !prefix);
654
case 43: // +
655
return after_e;
656
case (after_e = false, 46): // .
657
return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false;
658
}
659
660
if (ch === "n") {
661
is_big_int = true;
662
663
return true;
664
}
665
666
return RE_NUM_LITERAL.test(ch);
667
});
668
if (prefix) num = prefix + num;
669
670
LATEST_RAW = num;
671
672
if (RE_OCT_NUMBER.test(num) && next_token.has_directive("use strict")) {
673
parse_error("Legacy octal literals are not allowed in strict mode");
674
}
675
if (numeric_separator) {
676
if (num.endsWith("_")) {
677
parse_error("Numeric separators are not allowed at the end of numeric literals");
678
} else if (num.includes("__")) {
679
parse_error("Only one underscore is allowed as numeric separator");
680
}
681
num = num.replace(/_/g, "");
682
}
683
if (num.endsWith("n")) {
684
const without_n = num.slice(0, -1);
685
const allow_e = RE_HEX_NUMBER.test(without_n);
686
const valid = parse_js_number(without_n, allow_e);
687
if (!has_dot && RE_BIG_INT.test(num) && !isNaN(valid))
688
return token("big_int", without_n);
689
parse_error("Invalid or unexpected token");
690
}
691
var valid = parse_js_number(num);
692
if (!isNaN(valid)) {
693
return token("num", valid);
694
} else {
695
parse_error("Invalid syntax: " + num);
696
}
697
}
698
699
function is_octal(ch) {
700
return ch >= "0" && ch <= "7";
701
}
702
703
function read_escaped_char(in_string, strict_hex, template_string) {
704
var ch = next(true, in_string);
705
switch (ch.charCodeAt(0)) {
706
case 110 : return "\n";
707
case 114 : return "\r";
708
case 116 : return "\t";
709
case 98 : return "\b";
710
case 118 : return "\u000b"; // \v
711
case 102 : return "\f";
712
case 120 : return String.fromCharCode(hex_bytes(2, strict_hex)); // \x
713
case 117 : // \u
714
if (peek() == "{") {
715
next(true);
716
if (peek() === "}")
717
parse_error("Expecting hex-character between {}");
718
while (peek() == "0") next(true); // No significance
719
var result, length = find("}", true) - S.pos;
720
// Avoid 32 bit integer overflow (1 << 32 === 1)
721
// We know first character isn't 0 and thus out of range anyway
722
if (length > 6 || (result = hex_bytes(length, strict_hex)) > 0x10FFFF) {
723
parse_error("Unicode reference out of bounds");
724
}
725
next(true);
726
return from_char_code(result);
727
}
728
return String.fromCharCode(hex_bytes(4, strict_hex));
729
case 10 : return ""; // newline
730
case 13 : // \r
731
if (peek() == "\n") { // DOS newline
732
next(true, in_string);
733
return "";
734
}
735
}
736
if (is_octal(ch)) {
737
if (template_string && strict_hex) {
738
const represents_null_character = ch === "0" && !is_octal(peek());
739
if (!represents_null_character) {
740
parse_error("Octal escape sequences are not allowed in template strings");
741
}
742
}
743
return read_octal_escape_sequence(ch, strict_hex);
744
}
745
return ch;
746
}
747
748
function read_octal_escape_sequence(ch, strict_octal) {
749
// Read
750
var p = peek();
751
if (p >= "0" && p <= "7") {
752
ch += next(true);
753
if (ch[0] <= "3" && (p = peek()) >= "0" && p <= "7")
754
ch += next(true);
755
}
756
757
// Parse
758
if (ch === "0") return "\0";
759
if (ch.length > 0 && next_token.has_directive("use strict") && strict_octal)
760
parse_error("Legacy octal escape sequences are not allowed in strict mode");
761
return String.fromCharCode(parseInt(ch, 8));
762
}
763
764
function hex_bytes(n, strict_hex) {
765
var num = 0;
766
for (; n > 0; --n) {
767
if (!strict_hex && isNaN(parseInt(peek(), 16))) {
768
return parseInt(num, 16) || "";
769
}
770
var digit = next(true);
771
if (isNaN(parseInt(digit, 16)))
772
parse_error("Invalid hex-character pattern in string");
773
num += digit;
774
}
775
return parseInt(num, 16);
776
}
777
778
var read_string = with_eof_error("Unterminated string constant", function() {
779
const start_pos = S.pos;
780
var quote = next(), ret = [];
781
for (;;) {
782
var ch = next(true, true);
783
if (ch == "\\") ch = read_escaped_char(true, true);
784
else if (ch == "\r" || ch == "\n") parse_error("Unterminated string constant");
785
else if (ch == quote) break;
786
ret.push(ch);
787
}
788
var tok = token("string", ret.join(""));
789
LATEST_RAW = S.text.slice(start_pos, S.pos);
790
tok.quote = quote;
791
return tok;
792
});
793
794
var read_template_characters = with_eof_error("Unterminated template", function(begin) {
795
if (begin) {
796
S.template_braces.push(S.brace_counter);
797
}
798
var content = "", raw = "", ch, tok;
799
next(true, true);
800
while ((ch = next(true, true)) != "`") {
801
if (ch == "\r") {
802
if (peek() == "\n") ++S.pos;
803
ch = "\n";
804
} else if (ch == "$" && peek() == "{") {
805
next(true, true);
806
S.brace_counter++;
807
tok = token(begin ? "template_head" : "template_substitution", content);
808
TEMPLATE_RAWS.set(tok, raw);
809
tok.template_end = false;
810
return tok;
811
}
812
813
raw += ch;
814
if (ch == "\\") {
815
var tmp = S.pos;
816
var prev_is_tag = previous_token && (previous_token.type === "name" || previous_token.type === "punc" && (previous_token.value === ")" || previous_token.value === "]"));
817
ch = read_escaped_char(true, !prev_is_tag, true);
818
raw += S.text.substr(tmp, S.pos - tmp);
819
}
820
821
content += ch;
822
}
823
S.template_braces.pop();
824
tok = token(begin ? "template_head" : "template_substitution", content);
825
TEMPLATE_RAWS.set(tok, raw);
826
tok.template_end = true;
827
return tok;
828
});
829
830
function skip_line_comment(type) {
831
var regex_allowed = S.regex_allowed;
832
var i = find_eol(), ret;
833
if (i == -1) {
834
ret = S.text.substr(S.pos);
835
S.pos = S.text.length;
836
} else {
837
ret = S.text.substring(S.pos, i);
838
S.pos = i;
839
}
840
S.col = S.tokcol + (S.pos - S.tokpos);
841
S.comments_before.push(token(type, ret, true));
842
S.regex_allowed = regex_allowed;
843
return next_token;
844
}
845
846
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function() {
847
var regex_allowed = S.regex_allowed;
848
var i = find("*/", true);
849
var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, "\n");
850
// update stream position
851
forward(get_full_char_length(text) /* text length doesn't count \r\n as 2 char while S.pos - i does */ + 2);
852
S.comments_before.push(token("comment2", text, true));
853
S.newline_before = S.newline_before || text.includes("\n");
854
S.regex_allowed = regex_allowed;
855
return next_token;
856
});
857
858
var read_name = with_eof_error("Unterminated identifier name", function() {
859
var name = [], ch, escaped = false;
860
var read_escaped_identifier_char = function() {
861
escaped = true;
862
next();
863
if (peek() !== "u") {
864
parse_error("Expecting UnicodeEscapeSequence -- uXXXX or u{XXXX}");
865
}
866
return read_escaped_char(false, true);
867
};
868
869
// Read first character (ID_Start)
870
if ((ch = peek()) === "\\") {
871
ch = read_escaped_identifier_char();
872
if (!is_identifier_start(ch)) {
873
parse_error("First identifier char is an invalid identifier char");
874
}
875
} else if (is_identifier_start(ch)) {
876
next();
877
} else {
878
return "";
879
}
880
881
name.push(ch);
882
883
// Read ID_Continue
884
while ((ch = peek()) != null) {
885
if ((ch = peek()) === "\\") {
886
ch = read_escaped_identifier_char();
887
if (!is_identifier_char(ch)) {
888
parse_error("Invalid escaped identifier char");
889
}
890
} else {
891
if (!is_identifier_char(ch)) {
892
break;
893
}
894
next();
895
}
896
name.push(ch);
897
}
898
const name_str = name.join("");
899
if (RESERVED_WORDS.has(name_str) && escaped) {
900
parse_error("Escaped characters are not allowed in keywords");
901
}
902
return name_str;
903
});
904
905
var read_regexp = with_eof_error("Unterminated regular expression", function(source) {
906
var prev_backslash = false, ch, in_class = false;
907
while ((ch = next(true))) if (NEWLINE_CHARS.has(ch)) {
908
parse_error("Unexpected line terminator");
909
} else if (prev_backslash) {
910
source += "\\" + ch;
911
prev_backslash = false;
912
} else if (ch == "[") {
913
in_class = true;
914
source += ch;
915
} else if (ch == "]" && in_class) {
916
in_class = false;
917
source += ch;
918
} else if (ch == "/" && !in_class) {
919
break;
920
} else if (ch == "\\") {
921
prev_backslash = true;
922
} else {
923
source += ch;
924
}
925
const flags = read_name();
926
return token("regexp", "/" + source + "/" + flags);
927
});
928
929
function read_operator(prefix) {
930
function grow(op) {
931
if (!peek()) return op;
932
var bigger = op + peek();
933
if (OPERATORS.has(bigger)) {
934
next();
935
return grow(bigger);
936
} else {
937
return op;
938
}
939
}
940
return token("operator", grow(prefix || next()));
941
}
942
943
function handle_slash() {
944
next();
945
switch (peek()) {
946
case "/":
947
next();
948
return skip_line_comment("comment1");
949
case "*":
950
next();
951
return skip_multiline_comment();
952
}
953
return S.regex_allowed ? read_regexp("") : read_operator("/");
954
}
955
956
function handle_eq_sign() {
957
next();
958
if (peek() === ">") {
959
next();
960
return token("arrow", "=>");
961
} else {
962
return read_operator("=");
963
}
964
}
965
966
function handle_dot() {
967
next();
968
if (is_digit(peek().charCodeAt(0))) {
969
return read_num(".");
970
}
971
if (peek() === ".") {
972
next(); // Consume second dot
973
next(); // Consume third dot
974
return token("expand", "...");
975
}
976
977
return token("punc", ".");
978
}
979
980
function read_word() {
981
var word = read_name();
982
if (prev_was_dot) return token("name", word);
983
return KEYWORDS_ATOM.has(word) ? token("atom", word)
984
: !KEYWORDS.has(word) ? token("name", word)
985
: OPERATORS.has(word) ? token("operator", word)
986
: token("keyword", word);
987
}
988
989
function read_private_word() {
990
next();
991
return token("privatename", read_name());
992
}
993
994
function with_eof_error(eof_error, cont) {
995
return function(x) {
996
try {
997
return cont(x);
998
} catch(ex) {
999
if (ex === EX_EOF) parse_error(eof_error);
1000
else throw ex;
1001
}
1002
};
1003
}
1004
1005
function next_token(force_regexp) {
1006
if (force_regexp != null)
1007
return read_regexp(force_regexp);
1008
if (shebang && S.pos == 0 && looking_at("#!")) {
1009
start_token();
1010
forward(2);
1011
skip_line_comment("comment5");
1012
}
1013
for (;;) {
1014
skip_whitespace();
1015
start_token();
1016
if (html5_comments) {
1017
if (looking_at("<!--")) {
1018
forward(4);
1019
skip_line_comment("comment3");
1020
continue;
1021
}
1022
if (looking_at("-->") && S.newline_before) {
1023
forward(3);
1024
skip_line_comment("comment4");
1025
continue;
1026
}
1027
}
1028
var ch = peek();
1029
if (!ch) return token("eof");
1030
var code = ch.charCodeAt(0);
1031
switch (code) {
1032
case 34: case 39: return read_string();
1033
case 46: return handle_dot();
1034
case 47: {
1035
var tok = handle_slash();
1036
if (tok === next_token) continue;
1037
return tok;
1038
}
1039
case 61: return handle_eq_sign();
1040
case 63: {
1041
if (!is_option_chain_op()) break; // Handled below
1042
1043
next(); // ?
1044
next(); // .
1045
1046
return token("punc", "?.");
1047
}
1048
case 96: return read_template_characters(true);
1049
case 123:
1050
S.brace_counter++;
1051
break;
1052
case 125:
1053
S.brace_counter--;
1054
if (S.template_braces.length > 0
1055
&& S.template_braces[S.template_braces.length - 1] === S.brace_counter)
1056
return read_template_characters(false);
1057
break;
1058
}
1059
if (is_digit(code)) return read_num();
1060
if (PUNC_CHARS.has(ch)) return token("punc", next());
1061
if (OPERATOR_CHARS.has(ch)) return read_operator();
1062
if (code == 92 || is_identifier_start(ch)) return read_word();
1063
if (code == 35) return read_private_word();
1064
break;
1065
}
1066
parse_error("Unexpected character '" + ch + "'");
1067
}
1068
1069
next_token.next = next;
1070
next_token.peek = peek;
1071
1072
next_token.context = function(nc) {
1073
if (nc) S = nc;
1074
return S;
1075
};
1076
1077
next_token.add_directive = function(directive) {
1078
S.directive_stack[S.directive_stack.length - 1].push(directive);
1079
1080
if (S.directives[directive] === undefined) {
1081
S.directives[directive] = 1;
1082
} else {
1083
S.directives[directive]++;
1084
}
1085
};
1086
1087
next_token.push_directives_stack = function() {
1088
S.directive_stack.push([]);
1089
};
1090
1091
next_token.pop_directives_stack = function() {
1092
var directives = S.directive_stack[S.directive_stack.length - 1];
1093
1094
for (var i = 0; i < directives.length; i++) {
1095
S.directives[directives[i]]--;
1096
}
1097
1098
S.directive_stack.pop();
1099
};
1100
1101
next_token.has_directive = function(directive) {
1102
return S.directives[directive] > 0;
1103
};
1104
1105
return next_token;
1106
1107
}
1108
1109
/* -----[ Parser (constants) ]----- */
1110
1111
var UNARY_PREFIX = makePredicate([
1112
"typeof",
1113
"void",
1114
"delete",
1115
"--",
1116
"++",
1117
"!",
1118
"~",
1119
"-",
1120
"+"
1121
]);
1122
1123
var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
1124
1125
var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "??=", "&&=", "||=", "/=", "*=", "**=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
1126
1127
var LOGICAL_ASSIGNMENT = makePredicate([ "??=", "&&=", "||=" ]);
1128
1129
var PRECEDENCE = (function(a, ret) {
1130
for (var i = 0; i < a.length; ++i) {
1131
var b = a[i];
1132
for (var j = 0; j < b.length; ++j) {
1133
ret[b[j]] = i + 1;
1134
}
1135
}
1136
return ret;
1137
})(
1138
[
1139
["||"],
1140
["??"],
1141
["&&"],
1142
["|"],
1143
["^"],
1144
["&"],
1145
["==", "===", "!=", "!=="],
1146
["<", ">", "<=", ">=", "in", "instanceof"],
1147
[">>", "<<", ">>>"],
1148
["+", "-"],
1149
["*", "/", "%"],
1150
["**"]
1151
],
1152
{}
1153
);
1154
1155
var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "big_int", "string", "regexp", "name"]);
1156
1157
/* -----[ Parser ]----- */
1158
1159
function parse($TEXT, options) {
1160
// maps start tokens to count of comments found outside of their parens
1161
// Example: /* I count */ ( /* I don't */ foo() )
1162
// Useful because comments_before property of call with parens outside
1163
// contains both comments inside and outside these parens. Used to find the
1164
// right #__PURE__ comments for an expression
1165
const outer_comments_before_counts = new WeakMap();
1166
1167
options = defaults(options, {
1168
bare_returns : false,
1169
ecma : null, // Legacy
1170
expression : false,
1171
filename : null,
1172
html5_comments : true,
1173
module : false,
1174
shebang : true,
1175
strict : false,
1176
toplevel : null,
1177
}, true);
1178
1179
var S = {
1180
input : (typeof $TEXT == "string"
1181
? tokenizer($TEXT, options.filename,
1182
options.html5_comments, options.shebang)
1183
: $TEXT),
1184
token : null,
1185
prev : null,
1186
peeked : null,
1187
in_function : 0,
1188
in_async : -1,
1189
in_generator : -1,
1190
in_directives : true,
1191
in_loop : 0,
1192
labels : []
1193
};
1194
1195
S.token = next();
1196
1197
function is(type, value) {
1198
return is_token(S.token, type, value);
1199
}
1200
1201
function peek() { return S.peeked || (S.peeked = S.input()); }
1202
1203
function next() {
1204
S.prev = S.token;
1205
1206
if (!S.peeked) peek();
1207
S.token = S.peeked;
1208
S.peeked = null;
1209
S.in_directives = S.in_directives && (
1210
S.token.type == "string" || is("punc", ";")
1211
);
1212
return S.token;
1213
}
1214
1215
function prev() {
1216
return S.prev;
1217
}
1218
1219
function croak(msg, line, col, pos) {
1220
var ctx = S.input.context();
1221
js_error(msg,
1222
ctx.filename,
1223
line != null ? line : ctx.tokline,
1224
col != null ? col : ctx.tokcol,
1225
pos != null ? pos : ctx.tokpos);
1226
}
1227
1228
function token_error(token, msg) {
1229
croak(msg, token.line, token.col);
1230
}
1231
1232
function unexpected(token) {
1233
if (token == null)
1234
token = S.token;
1235
token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
1236
}
1237
1238
function expect_token(type, val) {
1239
if (is(type, val)) {
1240
return next();
1241
}
1242
token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
1243
}
1244
1245
function expect(punc) { return expect_token("punc", punc); }
1246
1247
function has_newline_before(token) {
1248
return token.nlb || !token.comments_before.every((comment) => !comment.nlb);
1249
}
1250
1251
function can_insert_semicolon() {
1252
return !options.strict
1253
&& (is("eof") || is("punc", "}") || has_newline_before(S.token));
1254
}
1255
1256
function is_in_generator() {
1257
return S.in_generator === S.in_function;
1258
}
1259
1260
function is_in_async() {
1261
return S.in_async === S.in_function;
1262
}
1263
1264
function can_await() {
1265
return (
1266
S.in_async === S.in_function
1267
|| S.in_function === 0 && S.input.has_directive("use strict")
1268
);
1269
}
1270
1271
function semicolon(optional) {
1272
if (is("punc", ";")) next();
1273
else if (!optional && !can_insert_semicolon()) unexpected();
1274
}
1275
1276
function parenthesised() {
1277
expect("(");
1278
var exp = expression(true);
1279
expect(")");
1280
return exp;
1281
}
1282
1283
function embed_tokens(parser) {
1284
return function _embed_tokens_wrapper(...args) {
1285
const start = S.token;
1286
const expr = parser(...args);
1287
expr.start = start;
1288
expr.end = prev();
1289
return expr;
1290
};
1291
}
1292
1293
function handle_regexp() {
1294
if (is("operator", "/") || is("operator", "/=")) {
1295
S.peeked = null;
1296
S.token = S.input(S.token.value.substr(1)); // force regexp
1297
}
1298
}
1299
1300
var statement = embed_tokens(function statement(is_export_default, is_for_body, is_if_body) {
1301
handle_regexp();
1302
switch (S.token.type) {
1303
case "string":
1304
if (S.in_directives) {
1305
var token = peek();
1306
if (!LATEST_RAW.includes("\\")
1307
&& (is_token(token, "punc", ";")
1308
|| is_token(token, "punc", "}")
1309
|| has_newline_before(token)
1310
|| is_token(token, "eof"))) {
1311
S.input.add_directive(S.token.value);
1312
} else {
1313
S.in_directives = false;
1314
}
1315
}
1316
var dir = S.in_directives, stat = simple_statement();
1317
return dir && stat.body instanceof AST_String ? new AST_Directive(stat.body) : stat;
1318
case "template_head":
1319
case "num":
1320
case "big_int":
1321
case "regexp":
1322
case "operator":
1323
case "atom":
1324
return simple_statement();
1325
1326
case "name":
1327
case "privatename":
1328
if(is("privatename") && !S.in_class)
1329
croak("Private field must be used in an enclosing class");
1330
1331
if (S.token.value == "async" && is_token(peek(), "keyword", "function")) {
1332
next();
1333
next();
1334
if (is_for_body) {
1335
croak("functions are not allowed as the body of a loop");
1336
}
1337
return function_(AST_Defun, false, true, is_export_default);
1338
}
1339
if (S.token.value == "import" && !is_token(peek(), "punc", "(") && !is_token(peek(), "punc", ".")) {
1340
next();
1341
var node = import_statement();
1342
semicolon();
1343
return node;
1344
}
1345
return is_token(peek(), "punc", ":")
1346
? labeled_statement()
1347
: simple_statement();
1348
1349
case "punc":
1350
switch (S.token.value) {
1351
case "{":
1352
return new AST_BlockStatement({
1353
start : S.token,
1354
body : block_(),
1355
end : prev()
1356
});
1357
case "[":
1358
case "(":
1359
return simple_statement();
1360
case ";":
1361
S.in_directives = false;
1362
next();
1363
return new AST_EmptyStatement();
1364
default:
1365
unexpected();
1366
}
1367
1368
case "keyword":
1369
switch (S.token.value) {
1370
case "break":
1371
next();
1372
return break_cont(AST_Break);
1373
1374
case "continue":
1375
next();
1376
return break_cont(AST_Continue);
1377
1378
case "debugger":
1379
next();
1380
semicolon();
1381
return new AST_Debugger();
1382
1383
case "do":
1384
next();
1385
var body = in_loop(statement);
1386
expect_token("keyword", "while");
1387
var condition = parenthesised();
1388
semicolon(true);
1389
return new AST_Do({
1390
body : body,
1391
condition : condition
1392
});
1393
1394
case "while":
1395
next();
1396
return new AST_While({
1397
condition : parenthesised(),
1398
body : in_loop(function() { return statement(false, true); })
1399
});
1400
1401
case "for":
1402
next();
1403
return for_();
1404
1405
case "class":
1406
next();
1407
if (is_for_body) {
1408
croak("classes are not allowed as the body of a loop");
1409
}
1410
if (is_if_body) {
1411
croak("classes are not allowed as the body of an if");
1412
}
1413
return class_(AST_DefClass, is_export_default);
1414
1415
case "function":
1416
next();
1417
if (is_for_body) {
1418
croak("functions are not allowed as the body of a loop");
1419
}
1420
return function_(AST_Defun, false, false, is_export_default);
1421
1422
case "if":
1423
next();
1424
return if_();
1425
1426
case "return":
1427
if (S.in_function == 0 && !options.bare_returns)
1428
croak("'return' outside of function");
1429
next();
1430
var value = null;
1431
if (is("punc", ";")) {
1432
next();
1433
} else if (!can_insert_semicolon()) {
1434
value = expression(true);
1435
semicolon();
1436
}
1437
return new AST_Return({
1438
value: value
1439
});
1440
1441
case "switch":
1442
next();
1443
return new AST_Switch({
1444
expression : parenthesised(),
1445
body : in_loop(switch_body_)
1446
});
1447
1448
case "throw":
1449
next();
1450
if (has_newline_before(S.token))
1451
croak("Illegal newline after 'throw'");
1452
var value = expression(true);
1453
semicolon();
1454
return new AST_Throw({
1455
value: value
1456
});
1457
1458
case "try":
1459
next();
1460
return try_();
1461
1462
case "var":
1463
next();
1464
var node = var_();
1465
semicolon();
1466
return node;
1467
1468
case "let":
1469
next();
1470
var node = let_();
1471
semicolon();
1472
return node;
1473
1474
case "const":
1475
next();
1476
var node = const_();
1477
semicolon();
1478
return node;
1479
1480
case "with":
1481
if (S.input.has_directive("use strict")) {
1482
croak("Strict mode may not include a with statement");
1483
}
1484
next();
1485
return new AST_With({
1486
expression : parenthesised(),
1487
body : statement()
1488
});
1489
1490
case "export":
1491
if (!is_token(peek(), "punc", "(")) {
1492
next();
1493
var node = export_statement();
1494
if (is("punc", ";")) semicolon();
1495
return node;
1496
}
1497
}
1498
}
1499
unexpected();
1500
});
1501
1502
function labeled_statement() {
1503
var label = as_symbol(AST_Label);
1504
if (label.name === "await" && is_in_async()) {
1505
token_error(S.prev, "await cannot be used as label inside async function");
1506
}
1507
if (S.labels.some((l) => l.name === label.name)) {
1508
// ECMA-262, 12.12: An ECMAScript program is considered
1509
// syntactically incorrect if it contains a
1510
// LabelledStatement that is enclosed by a
1511
// LabelledStatement with the same Identifier as label.
1512
croak("Label " + label.name + " defined twice");
1513
}
1514
expect(":");
1515
S.labels.push(label);
1516
var stat = statement();
1517
S.labels.pop();
1518
if (!(stat instanceof AST_IterationStatement)) {
1519
// check for `continue` that refers to this label.
1520
// those should be reported as syntax errors.
1521
// https://github.com/mishoo/UglifyJS2/issues/287
1522
label.references.forEach(function(ref) {
1523
if (ref instanceof AST_Continue) {
1524
ref = ref.label.start;
1525
croak("Continue label `" + label.name + "` refers to non-IterationStatement.",
1526
ref.line, ref.col, ref.pos);
1527
}
1528
});
1529
}
1530
return new AST_LabeledStatement({ body: stat, label: label });
1531
}
1532
1533
function simple_statement(tmp) {
1534
return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) });
1535
}
1536
1537
function break_cont(type) {
1538
var label = null, ldef;
1539
if (!can_insert_semicolon()) {
1540
label = as_symbol(AST_LabelRef, true);
1541
}
1542
if (label != null) {
1543
ldef = S.labels.find((l) => l.name === label.name);
1544
if (!ldef)
1545
croak("Undefined label " + label.name);
1546
label.thedef = ldef;
1547
} else if (S.in_loop == 0)
1548
croak(type.TYPE + " not inside a loop or switch");
1549
semicolon();
1550
var stat = new type({ label: label });
1551
if (ldef) ldef.references.push(stat);
1552
return stat;
1553
}
1554
1555
function for_() {
1556
var for_await_error = "`for await` invalid in this context";
1557
var await_tok = S.token;
1558
if (await_tok.type == "name" && await_tok.value == "await") {
1559
if (!can_await()) {
1560
token_error(await_tok, for_await_error);
1561
}
1562
next();
1563
} else {
1564
await_tok = false;
1565
}
1566
expect("(");
1567
var init = null;
1568
if (!is("punc", ";")) {
1569
init =
1570
is("keyword", "var") ? (next(), var_(true)) :
1571
is("keyword", "let") ? (next(), let_(true)) :
1572
is("keyword", "const") ? (next(), const_(true)) :
1573
expression(true, true);
1574
var is_in = is("operator", "in");
1575
var is_of = is("name", "of");
1576
if (await_tok && !is_of) {
1577
token_error(await_tok, for_await_error);
1578
}
1579
if (is_in || is_of) {
1580
if (init instanceof AST_Definitions) {
1581
if (init.definitions.length > 1)
1582
token_error(init.start, "Only one variable declaration allowed in for..in loop");
1583
} else if (!(is_assignable(init) || (init = to_destructuring(init)) instanceof AST_Destructuring)) {
1584
token_error(init.start, "Invalid left-hand side in for..in loop");
1585
}
1586
next();
1587
if (is_in) {
1588
return for_in(init);
1589
} else {
1590
return for_of(init, !!await_tok);
1591
}
1592
}
1593
} else if (await_tok) {
1594
token_error(await_tok, for_await_error);
1595
}
1596
return regular_for(init);
1597
}
1598
1599
function regular_for(init) {
1600
expect(";");
1601
var test = is("punc", ";") ? null : expression(true);
1602
expect(";");
1603
var step = is("punc", ")") ? null : expression(true);
1604
expect(")");
1605
return new AST_For({
1606
init : init,
1607
condition : test,
1608
step : step,
1609
body : in_loop(function() { return statement(false, true); })
1610
});
1611
}
1612
1613
function for_of(init, is_await) {
1614
var lhs = init instanceof AST_Definitions ? init.definitions[0].name : null;
1615
var obj = expression(true);
1616
expect(")");
1617
return new AST_ForOf({
1618
await : is_await,
1619
init : init,
1620
name : lhs,
1621
object : obj,
1622
body : in_loop(function() { return statement(false, true); })
1623
});
1624
}
1625
1626
function for_in(init) {
1627
var obj = expression(true);
1628
expect(")");
1629
return new AST_ForIn({
1630
init : init,
1631
object : obj,
1632
body : in_loop(function() { return statement(false, true); })
1633
});
1634
}
1635
1636
var arrow_function = function(start, argnames, is_async) {
1637
if (has_newline_before(S.token)) {
1638
croak("Unexpected newline before arrow (=>)");
1639
}
1640
1641
expect_token("arrow", "=>");
1642
1643
var body = _function_body(is("punc", "{"), false, is_async);
1644
1645
var end =
1646
body instanceof Array && body.length ? body[body.length - 1].end :
1647
body instanceof Array ? start :
1648
body.end;
1649
1650
return new AST_Arrow({
1651
start : start,
1652
end : end,
1653
async : is_async,
1654
argnames : argnames,
1655
body : body
1656
});
1657
};
1658
1659
var function_ = function(ctor, is_generator_property, is_async, is_export_default) {
1660
var in_statement = ctor === AST_Defun;
1661
var is_generator = is("operator", "*");
1662
if (is_generator) {
1663
next();
1664
}
1665
1666
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
1667
if (in_statement && !name) {
1668
if (is_export_default) {
1669
ctor = AST_Function;
1670
} else {
1671
unexpected();
1672
}
1673
}
1674
1675
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
1676
unexpected(prev());
1677
1678
var args = [];
1679
var body = _function_body(true, is_generator || is_generator_property, is_async, name, args);
1680
return new ctor({
1681
start : args.start,
1682
end : body.end,
1683
is_generator: is_generator,
1684
async : is_async,
1685
name : name,
1686
argnames: args,
1687
body : body
1688
});
1689
};
1690
1691
class UsedParametersTracker {
1692
constructor(is_parameter, strict, duplicates_ok = false) {
1693
this.is_parameter = is_parameter;
1694
this.duplicates_ok = duplicates_ok;
1695
this.parameters = new Set();
1696
this.duplicate = null;
1697
this.default_assignment = false;
1698
this.spread = false;
1699
this.strict_mode = !!strict;
1700
}
1701
add_parameter(token) {
1702
if (this.parameters.has(token.value)) {
1703
if (this.duplicate === null) {
1704
this.duplicate = token;
1705
}
1706
this.check_strict();
1707
} else {
1708
this.parameters.add(token.value);
1709
if (this.is_parameter) {
1710
switch (token.value) {
1711
case "arguments":
1712
case "eval":
1713
case "yield":
1714
if (this.strict_mode) {
1715
token_error(token, "Unexpected " + token.value + " identifier as parameter inside strict mode");
1716
}
1717
break;
1718
default:
1719
if (RESERVED_WORDS.has(token.value)) {
1720
unexpected();
1721
}
1722
}
1723
}
1724
}
1725
}
1726
mark_default_assignment(token) {
1727
if (this.default_assignment === false) {
1728
this.default_assignment = token;
1729
}
1730
}
1731
mark_spread(token) {
1732
if (this.spread === false) {
1733
this.spread = token;
1734
}
1735
}
1736
mark_strict_mode() {
1737
this.strict_mode = true;
1738
}
1739
is_strict() {
1740
return this.default_assignment !== false || this.spread !== false || this.strict_mode;
1741
}
1742
check_strict() {
1743
if (this.is_strict() && this.duplicate !== null && !this.duplicates_ok) {
1744
token_error(this.duplicate, "Parameter " + this.duplicate.value + " was used already");
1745
}
1746
}
1747
}
1748
1749
function parameters(params) {
1750
var used_parameters = new UsedParametersTracker(true, S.input.has_directive("use strict"));
1751
1752
expect("(");
1753
1754
while (!is("punc", ")")) {
1755
var param = parameter(used_parameters);
1756
params.push(param);
1757
1758
if (!is("punc", ")")) {
1759
expect(",");
1760
}
1761
1762
if (param instanceof AST_Expansion) {
1763
break;
1764
}
1765
}
1766
1767
next();
1768
}
1769
1770
function parameter(used_parameters, symbol_type) {
1771
var param;
1772
var expand = false;
1773
if (used_parameters === undefined) {
1774
used_parameters = new UsedParametersTracker(true, S.input.has_directive("use strict"));
1775
}
1776
if (is("expand", "...")) {
1777
expand = S.token;
1778
used_parameters.mark_spread(S.token);
1779
next();
1780
}
1781
param = binding_element(used_parameters, symbol_type);
1782
1783
if (is("operator", "=") && expand === false) {
1784
used_parameters.mark_default_assignment(S.token);
1785
next();
1786
param = new AST_DefaultAssign({
1787
start: param.start,
1788
left: param,
1789
operator: "=",
1790
right: expression(false),
1791
end: S.token
1792
});
1793
}
1794
1795
if (expand !== false) {
1796
if (!is("punc", ")")) {
1797
unexpected();
1798
}
1799
param = new AST_Expansion({
1800
start: expand,
1801
expression: param,
1802
end: expand
1803
});
1804
}
1805
used_parameters.check_strict();
1806
1807
return param;
1808
}
1809
1810
function binding_element(used_parameters, symbol_type) {
1811
var elements = [];
1812
var first = true;
1813
var is_expand = false;
1814
var expand_token;
1815
var first_token = S.token;
1816
if (used_parameters === undefined) {
1817
const strict = S.input.has_directive("use strict");
1818
const duplicates_ok = symbol_type === AST_SymbolVar;
1819
used_parameters = new UsedParametersTracker(false, strict, duplicates_ok);
1820
}
1821
symbol_type = symbol_type === undefined ? AST_SymbolFunarg : symbol_type;
1822
if (is("punc", "[")) {
1823
next();
1824
while (!is("punc", "]")) {
1825
if (first) {
1826
first = false;
1827
} else {
1828
expect(",");
1829
}
1830
1831
if (is("expand", "...")) {
1832
is_expand = true;
1833
expand_token = S.token;
1834
used_parameters.mark_spread(S.token);
1835
next();
1836
}
1837
if (is("punc")) {
1838
switch (S.token.value) {
1839
case ",":
1840
elements.push(new AST_Hole({
1841
start: S.token,
1842
end: S.token
1843
}));
1844
continue;
1845
case "]": // Trailing comma after last element
1846
break;
1847
case "[":
1848
case "{":
1849
elements.push(binding_element(used_parameters, symbol_type));
1850
break;
1851
default:
1852
unexpected();
1853
}
1854
} else if (is("name")) {
1855
used_parameters.add_parameter(S.token);
1856
elements.push(as_symbol(symbol_type));
1857
} else {
1858
croak("Invalid function parameter");
1859
}
1860
if (is("operator", "=") && is_expand === false) {
1861
used_parameters.mark_default_assignment(S.token);
1862
next();
1863
elements[elements.length - 1] = new AST_DefaultAssign({
1864
start: elements[elements.length - 1].start,
1865
left: elements[elements.length - 1],
1866
operator: "=",
1867
right: expression(false),
1868
end: S.token
1869
});
1870
}
1871
if (is_expand) {
1872
if (!is("punc", "]")) {
1873
croak("Rest element must be last element");
1874
}
1875
elements[elements.length - 1] = new AST_Expansion({
1876
start: expand_token,
1877
expression: elements[elements.length - 1],
1878
end: expand_token
1879
});
1880
}
1881
}
1882
expect("]");
1883
used_parameters.check_strict();
1884
return new AST_Destructuring({
1885
start: first_token,
1886
names: elements,
1887
is_array: true,
1888
end: prev()
1889
});
1890
} else if (is("punc", "{")) {
1891
next();
1892
while (!is("punc", "}")) {
1893
if (first) {
1894
first = false;
1895
} else {
1896
expect(",");
1897
}
1898
if (is("expand", "...")) {
1899
is_expand = true;
1900
expand_token = S.token;
1901
used_parameters.mark_spread(S.token);
1902
next();
1903
}
1904
if (is("name") && (is_token(peek(), "punc") || is_token(peek(), "operator")) && [",", "}", "="].includes(peek().value)) {
1905
used_parameters.add_parameter(S.token);
1906
var start = prev();
1907
var value = as_symbol(symbol_type);
1908
if (is_expand) {
1909
elements.push(new AST_Expansion({
1910
start: expand_token,
1911
expression: value,
1912
end: value.end,
1913
}));
1914
} else {
1915
elements.push(new AST_ObjectKeyVal({
1916
start: start,
1917
key: value.name,
1918
value: value,
1919
end: value.end,
1920
}));
1921
}
1922
} else if (is("punc", "}")) {
1923
continue; // Allow trailing hole
1924
} else {
1925
var property_token = S.token;
1926
var property = as_property_name();
1927
if (property === null) {
1928
unexpected(prev());
1929
} else if (prev().type === "name" && !is("punc", ":")) {
1930
elements.push(new AST_ObjectKeyVal({
1931
start: prev(),
1932
key: property,
1933
value: new symbol_type({
1934
start: prev(),
1935
name: property,
1936
end: prev()
1937
}),
1938
end: prev()
1939
}));
1940
} else {
1941
expect(":");
1942
elements.push(new AST_ObjectKeyVal({
1943
start: property_token,
1944
quote: property_token.quote,
1945
key: property,
1946
value: binding_element(used_parameters, symbol_type),
1947
end: prev()
1948
}));
1949
}
1950
}
1951
if (is_expand) {
1952
if (!is("punc", "}")) {
1953
croak("Rest element must be last element");
1954
}
1955
} else if (is("operator", "=")) {
1956
used_parameters.mark_default_assignment(S.token);
1957
next();
1958
elements[elements.length - 1].value = new AST_DefaultAssign({
1959
start: elements[elements.length - 1].value.start,
1960
left: elements[elements.length - 1].value,
1961
operator: "=",
1962
right: expression(false),
1963
end: S.token
1964
});
1965
}
1966
}
1967
expect("}");
1968
used_parameters.check_strict();
1969
return new AST_Destructuring({
1970
start: first_token,
1971
names: elements,
1972
is_array: false,
1973
end: prev()
1974
});
1975
} else if (is("name")) {
1976
used_parameters.add_parameter(S.token);
1977
return as_symbol(symbol_type);
1978
} else {
1979
croak("Invalid function parameter");
1980
}
1981
}
1982
1983
function params_or_seq_(allow_arrows, maybe_sequence) {
1984
var spread_token;
1985
var invalid_sequence;
1986
var trailing_comma;
1987
var a = [];
1988
expect("(");
1989
while (!is("punc", ")")) {
1990
if (spread_token) unexpected(spread_token);
1991
if (is("expand", "...")) {
1992
spread_token = S.token;
1993
if (maybe_sequence) invalid_sequence = S.token;
1994
next();
1995
a.push(new AST_Expansion({
1996
start: prev(),
1997
expression: expression(),
1998
end: S.token,
1999
}));
2000
} else {
2001
a.push(expression());
2002
}
2003
if (!is("punc", ")")) {
2004
expect(",");
2005
if (is("punc", ")")) {
2006
trailing_comma = prev();
2007
if (maybe_sequence) invalid_sequence = trailing_comma;
2008
}
2009
}
2010
}
2011
expect(")");
2012
if (allow_arrows && is("arrow", "=>")) {
2013
if (spread_token && trailing_comma) unexpected(trailing_comma);
2014
} else if (invalid_sequence) {
2015
unexpected(invalid_sequence);
2016
}
2017
return a;
2018
}
2019
2020
function _function_body(block, generator, is_async, name, args) {
2021
var loop = S.in_loop;
2022
var labels = S.labels;
2023
var current_generator = S.in_generator;
2024
var current_async = S.in_async;
2025
++S.in_function;
2026
if (generator)
2027
S.in_generator = S.in_function;
2028
if (is_async)
2029
S.in_async = S.in_function;
2030
if (args) parameters(args);
2031
if (block)
2032
S.in_directives = true;
2033
S.in_loop = 0;
2034
S.labels = [];
2035
if (block) {
2036
S.input.push_directives_stack();
2037
var a = block_();
2038
if (name) _verify_symbol(name);
2039
if (args) args.forEach(_verify_symbol);
2040
S.input.pop_directives_stack();
2041
} else {
2042
var a = [new AST_Return({
2043
start: S.token,
2044
value: expression(false),
2045
end: S.token
2046
})];
2047
}
2048
--S.in_function;
2049
S.in_loop = loop;
2050
S.labels = labels;
2051
S.in_generator = current_generator;
2052
S.in_async = current_async;
2053
return a;
2054
}
2055
2056
function _await_expression() {
2057
// Previous token must be "await" and not be interpreted as an identifier
2058
if (!can_await()) {
2059
croak("Unexpected await expression outside async function",
2060
S.prev.line, S.prev.col, S.prev.pos);
2061
}
2062
// the await expression is parsed as a unary expression in Babel
2063
return new AST_Await({
2064
start: prev(),
2065
end: S.token,
2066
expression : maybe_unary(true),
2067
});
2068
}
2069
2070
function _yield_expression() {
2071
// Previous token must be keyword yield and not be interpret as an identifier
2072
if (!is_in_generator()) {
2073
croak("Unexpected yield expression outside generator function",
2074
S.prev.line, S.prev.col, S.prev.pos);
2075
}
2076
var start = S.token;
2077
var star = false;
2078
var has_expression = true;
2079
2080
// Attempt to get expression or star (and then the mandatory expression)
2081
// behind yield on the same line.
2082
//
2083
// If nothing follows on the same line of the yieldExpression,
2084
// it should default to the value `undefined` for yield to return.
2085
// In that case, the `undefined` stored as `null` in ast.
2086
//
2087
// Note 1: It isn't allowed for yield* to close without an expression
2088
// Note 2: If there is a nlb between yield and star, it is interpret as
2089
// yield <explicit undefined> <inserted automatic semicolon> *
2090
if (can_insert_semicolon() ||
2091
(is("punc") && PUNC_AFTER_EXPRESSION.has(S.token.value))) {
2092
has_expression = false;
2093
2094
} else if (is("operator", "*")) {
2095
star = true;
2096
next();
2097
}
2098
2099
return new AST_Yield({
2100
start : start,
2101
is_star : star,
2102
expression : has_expression ? expression() : null,
2103
end : prev()
2104
});
2105
}
2106
2107
function if_() {
2108
var cond = parenthesised(), body = statement(false, false, true), belse = null;
2109
if (is("keyword", "else")) {
2110
next();
2111
belse = statement(false, false, true);
2112
}
2113
return new AST_If({
2114
condition : cond,
2115
body : body,
2116
alternative : belse
2117
});
2118
}
2119
2120
function block_() {
2121
expect("{");
2122
var a = [];
2123
while (!is("punc", "}")) {
2124
if (is("eof")) unexpected();
2125
a.push(statement());
2126
}
2127
next();
2128
return a;
2129
}
2130
2131
function switch_body_() {
2132
expect("{");
2133
var a = [], cur = null, branch = null, tmp;
2134
while (!is("punc", "}")) {
2135
if (is("eof")) unexpected();
2136
if (is("keyword", "case")) {
2137
if (branch) branch.end = prev();
2138
cur = [];
2139
branch = new AST_Case({
2140
start : (tmp = S.token, next(), tmp),
2141
expression : expression(true),
2142
body : cur
2143
});
2144
a.push(branch);
2145
expect(":");
2146
} else if (is("keyword", "default")) {
2147
if (branch) branch.end = prev();
2148
cur = [];
2149
branch = new AST_Default({
2150
start : (tmp = S.token, next(), expect(":"), tmp),
2151
body : cur
2152
});
2153
a.push(branch);
2154
} else {
2155
if (!cur) unexpected();
2156
cur.push(statement());
2157
}
2158
}
2159
if (branch) branch.end = prev();
2160
next();
2161
return a;
2162
}
2163
2164
function try_() {
2165
var body, bcatch = null, bfinally = null;
2166
body = new AST_TryBlock({
2167
start : S.token,
2168
body : block_(),
2169
end : prev(),
2170
});
2171
if (is("keyword", "catch")) {
2172
var start = S.token;
2173
next();
2174
if (is("punc", "{")) {
2175
var name = null;
2176
} else {
2177
expect("(");
2178
var name = parameter(undefined, AST_SymbolCatch);
2179
expect(")");
2180
}
2181
bcatch = new AST_Catch({
2182
start : start,
2183
argname : name,
2184
body : block_(),
2185
end : prev()
2186
});
2187
}
2188
if (is("keyword", "finally")) {
2189
var start = S.token;
2190
next();
2191
bfinally = new AST_Finally({
2192
start : start,
2193
body : block_(),
2194
end : prev()
2195
});
2196
}
2197
if (!bcatch && !bfinally)
2198
croak("Missing catch/finally blocks");
2199
return new AST_Try({
2200
body : body,
2201
bcatch : bcatch,
2202
bfinally : bfinally
2203
});
2204
}
2205
2206
/**
2207
* var
2208
* vardef1 = 2,
2209
* vardef2 = 3;
2210
*/
2211
function vardefs(no_in, kind) {
2212
var var_defs = [];
2213
var def;
2214
for (;;) {
2215
var sym_type =
2216
kind === "var" ? AST_SymbolVar :
2217
kind === "const" ? AST_SymbolConst :
2218
kind === "let" ? AST_SymbolLet : null;
2219
// var { a } = b
2220
if (is("punc", "{") || is("punc", "[")) {
2221
def = new AST_VarDef({
2222
start: S.token,
2223
name: binding_element(undefined, sym_type),
2224
value: is("operator", "=") ? (expect_token("operator", "="), expression(false, no_in)) : null,
2225
end: prev()
2226
});
2227
} else {
2228
def = new AST_VarDef({
2229
start : S.token,
2230
name : as_symbol(sym_type),
2231
value : is("operator", "=")
2232
? (next(), expression(false, no_in))
2233
: !no_in && kind === "const"
2234
? croak("Missing initializer in const declaration") : null,
2235
end : prev()
2236
});
2237
if (def.name.name == "import") croak("Unexpected token: import");
2238
}
2239
var_defs.push(def);
2240
if (!is("punc", ","))
2241
break;
2242
next();
2243
}
2244
return var_defs;
2245
}
2246
2247
var var_ = function(no_in) {
2248
return new AST_Var({
2249
start : prev(),
2250
definitions : vardefs(no_in, "var"),
2251
end : prev()
2252
});
2253
};
2254
2255
var let_ = function(no_in) {
2256
return new AST_Let({
2257
start : prev(),
2258
definitions : vardefs(no_in, "let"),
2259
end : prev()
2260
});
2261
};
2262
2263
var const_ = function(no_in) {
2264
return new AST_Const({
2265
start : prev(),
2266
definitions : vardefs(no_in, "const"),
2267
end : prev()
2268
});
2269
};
2270
2271
var new_ = function(allow_calls) {
2272
var start = S.token;
2273
expect_token("operator", "new");
2274
if (is("punc", ".")) {
2275
next();
2276
expect_token("name", "target");
2277
return subscripts(new AST_NewTarget({
2278
start : start,
2279
end : prev()
2280
}), allow_calls);
2281
}
2282
var newexp = expr_atom(false), args;
2283
if (is("punc", "(")) {
2284
next();
2285
args = expr_list(")", true);
2286
} else {
2287
args = [];
2288
}
2289
var call = new AST_New({
2290
start : start,
2291
expression : newexp,
2292
args : args,
2293
end : prev()
2294
});
2295
annotate(call);
2296
return subscripts(call, allow_calls);
2297
};
2298
2299
function as_atom_node() {
2300
var tok = S.token, ret;
2301
switch (tok.type) {
2302
case "name":
2303
ret = _make_symbol(AST_SymbolRef);
2304
break;
2305
case "num":
2306
ret = new AST_Number({
2307
start: tok,
2308
end: tok,
2309
value: tok.value,
2310
raw: LATEST_RAW
2311
});
2312
break;
2313
case "big_int":
2314
ret = new AST_BigInt({ start: tok, end: tok, value: tok.value });
2315
break;
2316
case "string":
2317
ret = new AST_String({
2318
start : tok,
2319
end : tok,
2320
value : tok.value,
2321
quote : tok.quote
2322
});
2323
annotate(ret);
2324
break;
2325
case "regexp":
2326
const [_, source, flags] = tok.value.match(/^\/(.*)\/(\w*)$/);
2327
2328
ret = new AST_RegExp({ start: tok, end: tok, value: { source, flags } });
2329
break;
2330
case "atom":
2331
switch (tok.value) {
2332
case "false":
2333
ret = new AST_False({ start: tok, end: tok });
2334
break;
2335
case "true":
2336
ret = new AST_True({ start: tok, end: tok });
2337
break;
2338
case "null":
2339
ret = new AST_Null({ start: tok, end: tok });
2340
break;
2341
}
2342
break;
2343
}
2344
next();
2345
return ret;
2346
}
2347
2348
function to_fun_args(ex, default_seen_above) {
2349
var insert_default = function(ex, default_value) {
2350
if (default_value) {
2351
return new AST_DefaultAssign({
2352
start: ex.start,
2353
left: ex,
2354
operator: "=",
2355
right: default_value,
2356
end: default_value.end
2357
});
2358
}
2359
return ex;
2360
};
2361
if (ex instanceof AST_Object) {
2362
return insert_default(new AST_Destructuring({
2363
start: ex.start,
2364
end: ex.end,
2365
is_array: false,
2366
names: ex.properties.map(prop => to_fun_args(prop))
2367
}), default_seen_above);
2368
} else if (ex instanceof AST_ObjectKeyVal) {
2369
ex.value = to_fun_args(ex.value);
2370
return insert_default(ex, default_seen_above);
2371
} else if (ex instanceof AST_Hole) {
2372
return ex;
2373
} else if (ex instanceof AST_Destructuring) {
2374
ex.names = ex.names.map(name => to_fun_args(name));
2375
return insert_default(ex, default_seen_above);
2376
} else if (ex instanceof AST_SymbolRef) {
2377
return insert_default(new AST_SymbolFunarg({
2378
name: ex.name,
2379
start: ex.start,
2380
end: ex.end
2381
}), default_seen_above);
2382
} else if (ex instanceof AST_Expansion) {
2383
ex.expression = to_fun_args(ex.expression);
2384
return insert_default(ex, default_seen_above);
2385
} else if (ex instanceof AST_Array) {
2386
return insert_default(new AST_Destructuring({
2387
start: ex.start,
2388
end: ex.end,
2389
is_array: true,
2390
names: ex.elements.map(elm => to_fun_args(elm))
2391
}), default_seen_above);
2392
} else if (ex instanceof AST_Assign) {
2393
return insert_default(to_fun_args(ex.left, ex.right), default_seen_above);
2394
} else if (ex instanceof AST_DefaultAssign) {
2395
ex.left = to_fun_args(ex.left);
2396
return ex;
2397
} else {
2398
croak("Invalid function parameter", ex.start.line, ex.start.col);
2399
}
2400
}
2401
2402
var expr_atom = function(allow_calls, allow_arrows) {
2403
if (is("operator", "new")) {
2404
return new_(allow_calls);
2405
}
2406
if (is("name", "import") && is_token(peek(), "punc", ".")) {
2407
return import_meta(allow_calls);
2408
}
2409
var start = S.token;
2410
var peeked;
2411
var async = is("name", "async")
2412
&& (peeked = peek()).value != "["
2413
&& peeked.type != "arrow"
2414
&& as_atom_node();
2415
if (is("punc")) {
2416
switch (S.token.value) {
2417
case "(":
2418
if (async && !allow_calls) break;
2419
var exprs = params_or_seq_(allow_arrows, !async);
2420
if (allow_arrows && is("arrow", "=>")) {
2421
return arrow_function(start, exprs.map(e => to_fun_args(e)), !!async);
2422
}
2423
var ex = async ? new AST_Call({
2424
expression: async,
2425
args: exprs
2426
}) : exprs.length == 1 ? exprs[0] : new AST_Sequence({
2427
expressions: exprs
2428
});
2429
if (ex.start) {
2430
const outer_comments_before = start.comments_before.length;
2431
outer_comments_before_counts.set(start, outer_comments_before);
2432
ex.start.comments_before.unshift(...start.comments_before);
2433
start.comments_before = ex.start.comments_before;
2434
if (outer_comments_before == 0 && start.comments_before.length > 0) {
2435
var comment = start.comments_before[0];
2436
if (!comment.nlb) {
2437
comment.nlb = start.nlb;
2438
start.nlb = false;
2439
}
2440
}
2441
start.comments_after = ex.start.comments_after;
2442
}
2443
ex.start = start;
2444
var end = prev();
2445
if (ex.end) {
2446
end.comments_before = ex.end.comments_before;
2447
ex.end.comments_after.push(...end.comments_after);
2448
end.comments_after = ex.end.comments_after;
2449
}
2450
ex.end = end;
2451
if (ex instanceof AST_Call) annotate(ex);
2452
return subscripts(ex, allow_calls);
2453
case "[":
2454
return subscripts(array_(), allow_calls);
2455
case "{":
2456
return subscripts(object_or_destructuring_(), allow_calls);
2457
}
2458
if (!async) unexpected();
2459
}
2460
if (allow_arrows && is("name") && is_token(peek(), "arrow")) {
2461
var param = new AST_SymbolFunarg({
2462
name: S.token.value,
2463
start: start,
2464
end: start,
2465
});
2466
next();
2467
return arrow_function(start, [param], !!async);
2468
}
2469
if (is("keyword", "function")) {
2470
next();
2471
var func = function_(AST_Function, false, !!async);
2472
func.start = start;
2473
func.end = prev();
2474
return subscripts(func, allow_calls);
2475
}
2476
if (async) return subscripts(async, allow_calls);
2477
if (is("keyword", "class")) {
2478
next();
2479
var cls = class_(AST_ClassExpression);
2480
cls.start = start;
2481
cls.end = prev();
2482
return subscripts(cls, allow_calls);
2483
}
2484
if (is("template_head")) {
2485
return subscripts(template_string(), allow_calls);
2486
}
2487
if (is("privatename")) {
2488
if(!S.in_class) {
2489
croak("Private field must be used in an enclosing class");
2490
}
2491
2492
const start = S.token;
2493
const key = new AST_SymbolPrivateProperty({
2494
start,
2495
name: start.value,
2496
end: start
2497
});
2498
next();
2499
expect_token("operator", "in");
2500
2501
const private_in = new AST_PrivateIn({
2502
start,
2503
key,
2504
value: subscripts(as_atom_node(), allow_calls),
2505
end: prev()
2506
});
2507
2508
return subscripts(private_in, allow_calls);
2509
}
2510
if (ATOMIC_START_TOKEN.has(S.token.type)) {
2511
return subscripts(as_atom_node(), allow_calls);
2512
}
2513
unexpected();
2514
};
2515
2516
function template_string() {
2517
var segments = [], start = S.token;
2518
2519
segments.push(new AST_TemplateSegment({
2520
start: S.token,
2521
raw: TEMPLATE_RAWS.get(S.token),
2522
value: S.token.value,
2523
end: S.token
2524
}));
2525
2526
while (!S.token.template_end) {
2527
next();
2528
handle_regexp();
2529
segments.push(expression(true));
2530
2531
segments.push(new AST_TemplateSegment({
2532
start: S.token,
2533
raw: TEMPLATE_RAWS.get(S.token),
2534
value: S.token.value,
2535
end: S.token
2536
}));
2537
}
2538
next();
2539
2540
return new AST_TemplateString({
2541
start: start,
2542
segments: segments,
2543
end: S.token
2544
});
2545
}
2546
2547
function expr_list(closing, allow_trailing_comma, allow_empty) {
2548
var first = true, a = [];
2549
while (!is("punc", closing)) {
2550
if (first) first = false; else expect(",");
2551
if (allow_trailing_comma && is("punc", closing)) break;
2552
if (is("punc", ",") && allow_empty) {
2553
a.push(new AST_Hole({ start: S.token, end: S.token }));
2554
} else if (is("expand", "...")) {
2555
next();
2556
a.push(new AST_Expansion({start: prev(), expression: expression(),end: S.token}));
2557
} else {
2558
a.push(expression(false));
2559
}
2560
}
2561
next();
2562
return a;
2563
}
2564
2565
var array_ = embed_tokens(function() {
2566
expect("[");
2567
return new AST_Array({
2568
elements: expr_list("]", !options.strict, true)
2569
});
2570
});
2571
2572
var create_accessor = embed_tokens((is_generator, is_async) => {
2573
return function_(AST_Accessor, is_generator, is_async);
2574
});
2575
2576
var object_or_destructuring_ = embed_tokens(function object_or_destructuring_() {
2577
var start = S.token, first = true, a = [];
2578
expect("{");
2579
while (!is("punc", "}")) {
2580
if (first) first = false; else expect(",");
2581
if (!options.strict && is("punc", "}"))
2582
// allow trailing comma
2583
break;
2584
2585
start = S.token;
2586
if (start.type == "expand") {
2587
next();
2588
a.push(new AST_Expansion({
2589
start: start,
2590
expression: expression(false),
2591
end: prev(),
2592
}));
2593
continue;
2594
}
2595
if(is("privatename")) {
2596
croak("private fields are not allowed in an object");
2597
}
2598
var name = as_property_name();
2599
var value;
2600
2601
// Check property and fetch value
2602
if (!is("punc", ":")) {
2603
var concise = concise_method_or_getset(name, start);
2604
if (concise) {
2605
a.push(concise);
2606
continue;
2607
}
2608
2609
value = new AST_SymbolRef({
2610
start: prev(),
2611
name: name,
2612
end: prev()
2613
});
2614
} else if (name === null) {
2615
unexpected(prev());
2616
} else {
2617
next(); // `:` - see first condition
2618
value = expression(false);
2619
}
2620
2621
// Check for default value and alter value accordingly if necessary
2622
if (is("operator", "=")) {
2623
next();
2624
value = new AST_Assign({
2625
start: start,
2626
left: value,
2627
operator: "=",
2628
right: expression(false),
2629
logical: false,
2630
end: prev()
2631
});
2632
}
2633
2634
// Create property
2635
const kv = new AST_ObjectKeyVal({
2636
start: start,
2637
quote: start.quote,
2638
key: name instanceof AST_Node ? name : "" + name,
2639
value: value,
2640
end: prev()
2641
});
2642
a.push(annotate(kv));
2643
}
2644
next();
2645
return new AST_Object({ properties: a });
2646
});
2647
2648
function class_(KindOfClass, is_export_default) {
2649
var start, method, class_name, extends_, a = [];
2650
2651
S.input.push_directives_stack(); // Push directive stack, but not scope stack
2652
S.input.add_directive("use strict");
2653
2654
if (S.token.type == "name" && S.token.value != "extends") {
2655
class_name = as_symbol(KindOfClass === AST_DefClass ? AST_SymbolDefClass : AST_SymbolClass);
2656
}
2657
2658
if (KindOfClass === AST_DefClass && !class_name) {
2659
if (is_export_default) {
2660
KindOfClass = AST_ClassExpression;
2661
} else {
2662
unexpected();
2663
}
2664
}
2665
2666
if (S.token.value == "extends") {
2667
next();
2668
extends_ = expression(true);
2669
}
2670
2671
expect("{");
2672
// mark in class feild,
2673
const save_in_class = S.in_class;
2674
S.in_class = true;
2675
while (is("punc", ";")) { next(); } // Leading semicolons are okay in class bodies.
2676
while (!is("punc", "}")) {
2677
start = S.token;
2678
method = concise_method_or_getset(as_property_name(), start, true);
2679
if (!method) { unexpected(); }
2680
a.push(method);
2681
while (is("punc", ";")) { next(); }
2682
}
2683
// mark in class feild,
2684
S.in_class = save_in_class;
2685
2686
S.input.pop_directives_stack();
2687
2688
next();
2689
2690
return new KindOfClass({
2691
start: start,
2692
name: class_name,
2693
extends: extends_,
2694
properties: a,
2695
end: prev(),
2696
});
2697
}
2698
2699
function concise_method_or_getset(name, start, is_class) {
2700
const get_symbol_ast = (name, SymbolClass = AST_SymbolMethod) => {
2701
if (typeof name === "string" || typeof name === "number") {
2702
return new SymbolClass({
2703
start,
2704
name: "" + name,
2705
end: prev()
2706
});
2707
} else if (name === null) {
2708
unexpected();
2709
}
2710
return name;
2711
};
2712
2713
const is_not_method_start = () =>
2714
!is("punc", "(") && !is("punc", ",") && !is("punc", "}") && !is("punc", ";") && !is("operator", "=");
2715
2716
var is_async = false;
2717
var is_static = false;
2718
var is_generator = false;
2719
var is_private = false;
2720
var accessor_type = null;
2721
2722
if (is_class && name === "static" && is_not_method_start()) {
2723
const static_block = class_static_block();
2724
if (static_block != null) {
2725
return static_block;
2726
}
2727
is_static = true;
2728
name = as_property_name();
2729
}
2730
if (name === "async" && is_not_method_start()) {
2731
is_async = true;
2732
name = as_property_name();
2733
}
2734
if (prev().type === "operator" && prev().value === "*") {
2735
is_generator = true;
2736
name = as_property_name();
2737
}
2738
if ((name === "get" || name === "set") && is_not_method_start()) {
2739
accessor_type = name;
2740
name = as_property_name();
2741
}
2742
if (prev().type === "privatename") {
2743
is_private = true;
2744
}
2745
2746
const property_token = prev();
2747
2748
if (accessor_type != null) {
2749
if (!is_private) {
2750
const AccessorClass = accessor_type === "get"
2751
? AST_ObjectGetter
2752
: AST_ObjectSetter;
2753
2754
name = get_symbol_ast(name);
2755
return annotate(new AccessorClass({
2756
start,
2757
static: is_static,
2758
key: name,
2759
quote: name instanceof AST_SymbolMethod ? property_token.quote : undefined,
2760
value: create_accessor(),
2761
end: prev()
2762
}));
2763
} else {
2764
const AccessorClass = accessor_type === "get"
2765
? AST_PrivateGetter
2766
: AST_PrivateSetter;
2767
2768
return annotate(new AccessorClass({
2769
start,
2770
static: is_static,
2771
key: get_symbol_ast(name),
2772
value: create_accessor(),
2773
end: prev(),
2774
}));
2775
}
2776
}
2777
2778
if (is("punc", "(")) {
2779
name = get_symbol_ast(name);
2780
const AST_MethodVariant = is_private
2781
? AST_PrivateMethod
2782
: AST_ConciseMethod;
2783
var node = new AST_MethodVariant({
2784
start : start,
2785
static : is_static,
2786
is_generator: is_generator,
2787
async : is_async,
2788
key : name,
2789
quote : name instanceof AST_SymbolMethod ?
2790
property_token.quote : undefined,
2791
value : create_accessor(is_generator, is_async),
2792
end : prev()
2793
});
2794
return annotate(node);
2795
}
2796
2797
if (is_class) {
2798
const key = get_symbol_ast(name, AST_SymbolClassProperty);
2799
const quote = key instanceof AST_SymbolClassProperty
2800
? property_token.quote
2801
: undefined;
2802
const AST_ClassPropertyVariant = is_private
2803
? AST_ClassPrivateProperty
2804
: AST_ClassProperty;
2805
if (is("operator", "=")) {
2806
next();
2807
return annotate(
2808
new AST_ClassPropertyVariant({
2809
start,
2810
static: is_static,
2811
quote,
2812
key,
2813
value: expression(false),
2814
end: prev()
2815
})
2816
);
2817
} else if (
2818
is("name")
2819
|| is("privatename")
2820
|| is("operator", "*")
2821
|| is("punc", ";")
2822
|| is("punc", "}")
2823
) {
2824
return annotate(
2825
new AST_ClassPropertyVariant({
2826
start,
2827
static: is_static,
2828
quote,
2829
key,
2830
end: prev()
2831
})
2832
);
2833
}
2834
}
2835
}
2836
2837
function class_static_block() {
2838
if (!is("punc", "{")) {
2839
return null;
2840
}
2841
2842
const start = S.token;
2843
const body = [];
2844
2845
next();
2846
2847
while (!is("punc", "}")) {
2848
body.push(statement());
2849
}
2850
2851
next();
2852
2853
return new AST_ClassStaticBlock({ start, body, end: prev() });
2854
}
2855
2856
function maybe_import_assertion() {
2857
if (is("name", "assert") && !has_newline_before(S.token)) {
2858
next();
2859
return object_or_destructuring_();
2860
}
2861
return null;
2862
}
2863
2864
function import_statement() {
2865
var start = prev();
2866
2867
var imported_name;
2868
var imported_names;
2869
if (is("name")) {
2870
imported_name = as_symbol(AST_SymbolImport);
2871
}
2872
2873
if (is("punc", ",")) {
2874
next();
2875
}
2876
2877
imported_names = map_names(true);
2878
2879
if (imported_names || imported_name) {
2880
expect_token("name", "from");
2881
}
2882
var mod_str = S.token;
2883
if (mod_str.type !== "string") {
2884
unexpected();
2885
}
2886
next();
2887
2888
const assert_clause = maybe_import_assertion();
2889
2890
return new AST_Import({
2891
start,
2892
imported_name,
2893
imported_names,
2894
module_name: new AST_String({
2895
start: mod_str,
2896
value: mod_str.value,
2897
quote: mod_str.quote,
2898
end: mod_str,
2899
}),
2900
assert_clause,
2901
end: S.token,
2902
});
2903
}
2904
2905
function import_meta(allow_calls) {
2906
var start = S.token;
2907
expect_token("name", "import");
2908
expect_token("punc", ".");
2909
expect_token("name", "meta");
2910
return subscripts(new AST_ImportMeta({
2911
start: start,
2912
end: prev()
2913
}), allow_calls);
2914
}
2915
2916
function map_name(is_import) {
2917
function make_symbol(type, quote) {
2918
return new type({
2919
name: as_property_name(),
2920
quote: quote || undefined,
2921
start: prev(),
2922
end: prev()
2923
});
2924
}
2925
2926
var foreign_type = is_import ? AST_SymbolImportForeign : AST_SymbolExportForeign;
2927
var type = is_import ? AST_SymbolImport : AST_SymbolExport;
2928
var start = S.token;
2929
var foreign_name;
2930
var name;
2931
2932
if (is_import) {
2933
foreign_name = make_symbol(foreign_type, start.quote);
2934
} else {
2935
name = make_symbol(type, start.quote);
2936
}
2937
if (is("name", "as")) {
2938
next(); // The "as" word
2939
if (is_import) {
2940
name = make_symbol(type);
2941
} else {
2942
foreign_name = make_symbol(foreign_type, S.token.quote);
2943
}
2944
} else if (is_import) {
2945
name = new type(foreign_name);
2946
} else {
2947
foreign_name = new foreign_type(name);
2948
}
2949
2950
return new AST_NameMapping({
2951
start: start,
2952
foreign_name: foreign_name,
2953
name: name,
2954
end: prev(),
2955
});
2956
}
2957
2958
function map_nameAsterisk(is_import, import_or_export_foreign_name) {
2959
var foreign_type = is_import ? AST_SymbolImportForeign : AST_SymbolExportForeign;
2960
var type = is_import ? AST_SymbolImport : AST_SymbolExport;
2961
var start = S.token;
2962
var name, foreign_name;
2963
var end = prev();
2964
2965
if (is_import) {
2966
name = import_or_export_foreign_name;
2967
} else {
2968
foreign_name = import_or_export_foreign_name;
2969
}
2970
2971
name = name || new type({
2972
start: start,
2973
name: "*",
2974
end: end,
2975
});
2976
2977
foreign_name = foreign_name || new foreign_type({
2978
start: start,
2979
name: "*",
2980
end: end,
2981
});
2982
2983
return new AST_NameMapping({
2984
start: start,
2985
foreign_name: foreign_name,
2986
name: name,
2987
end: end,
2988
});
2989
}
2990
2991
function map_names(is_import) {
2992
var names;
2993
if (is("punc", "{")) {
2994
next();
2995
names = [];
2996
while (!is("punc", "}")) {
2997
names.push(map_name(is_import));
2998
if (is("punc", ",")) {
2999
next();
3000
}
3001
}
3002
next();
3003
} else if (is("operator", "*")) {
3004
var name;
3005
next();
3006
if (is("name", "as")) {
3007
next(); // The "as" word
3008
name = is_import ? as_symbol(AST_SymbolImport) : as_symbol_or_string(AST_SymbolExportForeign);
3009
}
3010
names = [map_nameAsterisk(is_import, name)];
3011
}
3012
return names;
3013
}
3014
3015
function export_statement() {
3016
var start = S.token;
3017
var is_default;
3018
var exported_names;
3019
3020
if (is("keyword", "default")) {
3021
is_default = true;
3022
next();
3023
} else if (exported_names = map_names(false)) {
3024
if (is("name", "from")) {
3025
next();
3026
3027
var mod_str = S.token;
3028
if (mod_str.type !== "string") {
3029
unexpected();
3030
}
3031
next();
3032
3033
const assert_clause = maybe_import_assertion();
3034
3035
return new AST_Export({
3036
start: start,
3037
is_default: is_default,
3038
exported_names: exported_names,
3039
module_name: new AST_String({
3040
start: mod_str,
3041
value: mod_str.value,
3042
quote: mod_str.quote,
3043
end: mod_str,
3044
}),
3045
end: prev(),
3046
assert_clause
3047
});
3048
} else {
3049
return new AST_Export({
3050
start: start,
3051
is_default: is_default,
3052
exported_names: exported_names,
3053
end: prev(),
3054
});
3055
}
3056
}
3057
3058
var node;
3059
var exported_value;
3060
var exported_definition;
3061
if (is("punc", "{")
3062
|| is_default
3063
&& (is("keyword", "class") || is("keyword", "function"))
3064
&& is_token(peek(), "punc")) {
3065
exported_value = expression(false);
3066
semicolon();
3067
} else if ((node = statement(is_default)) instanceof AST_Definitions && is_default) {
3068
unexpected(node.start);
3069
} else if (
3070
node instanceof AST_Definitions
3071
|| node instanceof AST_Defun
3072
|| node instanceof AST_DefClass
3073
) {
3074
exported_definition = node;
3075
} else if (
3076
node instanceof AST_ClassExpression
3077
|| node instanceof AST_Function
3078
) {
3079
exported_value = node;
3080
} else if (node instanceof AST_SimpleStatement) {
3081
exported_value = node.body;
3082
} else {
3083
unexpected(node.start);
3084
}
3085
3086
return new AST_Export({
3087
start: start,
3088
is_default: is_default,
3089
exported_value: exported_value,
3090
exported_definition: exported_definition,
3091
end: prev(),
3092
assert_clause: null
3093
});
3094
}
3095
3096
function as_property_name() {
3097
var tmp = S.token;
3098
switch (tmp.type) {
3099
case "punc":
3100
if (tmp.value === "[") {
3101
next();
3102
var ex = expression(false);
3103
expect("]");
3104
return ex;
3105
} else unexpected(tmp);
3106
case "operator":
3107
if (tmp.value === "*") {
3108
next();
3109
return null;
3110
}
3111
if (!["delete", "in", "instanceof", "new", "typeof", "void"].includes(tmp.value)) {
3112
unexpected(tmp);
3113
}
3114
/* falls through */
3115
case "name":
3116
case "privatename":
3117
case "string":
3118
case "num":
3119
case "big_int":
3120
case "keyword":
3121
case "atom":
3122
next();
3123
return tmp.value;
3124
default:
3125
unexpected(tmp);
3126
}
3127
}
3128
3129
function as_name() {
3130
var tmp = S.token;
3131
if (tmp.type != "name" && tmp.type != "privatename") unexpected();
3132
next();
3133
return tmp.value;
3134
}
3135
3136
function _make_symbol(type) {
3137
var name = S.token.value;
3138
return new (name == "this" ? AST_This :
3139
name == "super" ? AST_Super :
3140
type)({
3141
name : String(name),
3142
start : S.token,
3143
end : S.token
3144
});
3145
}
3146
3147
function _verify_symbol(sym) {
3148
var name = sym.name;
3149
if (is_in_generator() && name == "yield") {
3150
token_error(sym.start, "Yield cannot be used as identifier inside generators");
3151
}
3152
if (S.input.has_directive("use strict")) {
3153
if (name == "yield") {
3154
token_error(sym.start, "Unexpected yield identifier inside strict mode");
3155
}
3156
if (sym instanceof AST_SymbolDeclaration && (name == "arguments" || name == "eval")) {
3157
token_error(sym.start, "Unexpected " + name + " in strict mode");
3158
}
3159
}
3160
}
3161
3162
function as_symbol(type, noerror) {
3163
if (!is("name")) {
3164
if (!noerror) croak("Name expected");
3165
return null;
3166
}
3167
var sym = _make_symbol(type);
3168
_verify_symbol(sym);
3169
next();
3170
return sym;
3171
}
3172
3173
function as_symbol_or_string(type) {
3174
if (!is("name")) {
3175
if (!is("string")) {
3176
croak("Name or string expected");
3177
}
3178
var tok = S.token;
3179
var ret = new type({
3180
start : tok,
3181
end : tok,
3182
name : tok.value,
3183
quote : tok.quote
3184
});
3185
next();
3186
return ret;
3187
}
3188
var sym = _make_symbol(type);
3189
_verify_symbol(sym);
3190
next();
3191
return sym;
3192
}
3193
3194
// Annotate AST_Call, AST_Lambda or AST_New with the special comments
3195
function annotate(node, before_token = node.start) {
3196
var comments = before_token.comments_before;
3197
const comments_outside_parens = outer_comments_before_counts.get(before_token);
3198
var i = comments_outside_parens != null ? comments_outside_parens : comments.length;
3199
while (--i >= 0) {
3200
var comment = comments[i];
3201
if (/[@#]__/.test(comment.value)) {
3202
if (/[@#]__PURE__/.test(comment.value)) {
3203
set_annotation(node, _PURE);
3204
break;
3205
}
3206
if (/[@#]__INLINE__/.test(comment.value)) {
3207
set_annotation(node, _INLINE);
3208
break;
3209
}
3210
if (/[@#]__NOINLINE__/.test(comment.value)) {
3211
set_annotation(node, _NOINLINE);
3212
break;
3213
}
3214
if (/[@#]__KEY__/.test(comment.value)) {
3215
set_annotation(node, _KEY);
3216
break;
3217
}
3218
if (/[@#]__MANGLE_PROP__/.test(comment.value)) {
3219
set_annotation(node, _MANGLEPROP);
3220
break;
3221
}
3222
}
3223
}
3224
return node;
3225
}
3226
3227
var subscripts = function(expr, allow_calls, is_chain) {
3228
var start = expr.start;
3229
if (is("punc", ".")) {
3230
next();
3231
if(is("privatename") && !S.in_class)
3232
croak("Private field must be used in an enclosing class");
3233
const AST_DotVariant = is("privatename") ? AST_DotHash : AST_Dot;
3234
return subscripts(new AST_DotVariant({
3235
start : start,
3236
expression : expr,
3237
optional : false,
3238
property : as_name(),
3239
end : prev()
3240
}), allow_calls, is_chain);
3241
}
3242
if (is("punc", "[")) {
3243
next();
3244
var prop = expression(true);
3245
expect("]");
3246
return subscripts(new AST_Sub({
3247
start : start,
3248
expression : expr,
3249
optional : false,
3250
property : prop,
3251
end : prev()
3252
}), allow_calls, is_chain);
3253
}
3254
if (allow_calls && is("punc", "(")) {
3255
next();
3256
var call = new AST_Call({
3257
start : start,
3258
expression : expr,
3259
optional : false,
3260
args : call_args(),
3261
end : prev()
3262
});
3263
annotate(call);
3264
return subscripts(call, true, is_chain);
3265
}
3266
3267
if (is("punc", "?.")) {
3268
next();
3269
3270
let chain_contents;
3271
3272
if (allow_calls && is("punc", "(")) {
3273
next();
3274
3275
const call = new AST_Call({
3276
start,
3277
optional: true,
3278
expression: expr,
3279
args: call_args(),
3280
end: prev()
3281
});
3282
annotate(call);
3283
3284
chain_contents = subscripts(call, true, true);
3285
} else if (is("name") || is("privatename")) {
3286
if(is("privatename") && !S.in_class)
3287
croak("Private field must be used in an enclosing class");
3288
const AST_DotVariant = is("privatename") ? AST_DotHash : AST_Dot;
3289
chain_contents = subscripts(new AST_DotVariant({
3290
start,
3291
expression: expr,
3292
optional: true,
3293
property: as_name(),
3294
end: prev()
3295
}), allow_calls, true);
3296
} else if (is("punc", "[")) {
3297
next();
3298
const property = expression(true);
3299
expect("]");
3300
chain_contents = subscripts(new AST_Sub({
3301
start,
3302
expression: expr,
3303
optional: true,
3304
property,
3305
end: prev()
3306
}), allow_calls, true);
3307
}
3308
3309
if (!chain_contents) unexpected();
3310
3311
if (chain_contents instanceof AST_Chain) return chain_contents;
3312
3313
return new AST_Chain({
3314
start,
3315
expression: chain_contents,
3316
end: prev()
3317
});
3318
}
3319
3320
if (is("template_head")) {
3321
if (is_chain) {
3322
// a?.b`c` is a syntax error
3323
unexpected();
3324
}
3325
3326
return subscripts(new AST_PrefixedTemplateString({
3327
start: start,
3328
prefix: expr,
3329
template_string: template_string(),
3330
end: prev()
3331
}), allow_calls);
3332
}
3333
return expr;
3334
};
3335
3336
function call_args() {
3337
var args = [];
3338
while (!is("punc", ")")) {
3339
if (is("expand", "...")) {
3340
next();
3341
args.push(new AST_Expansion({
3342
start: prev(),
3343
expression: expression(false),
3344
end: prev()
3345
}));
3346
} else {
3347
args.push(expression(false));
3348
}
3349
if (!is("punc", ")")) {
3350
expect(",");
3351
}
3352
}
3353
next();
3354
return args;
3355
}
3356
3357
var maybe_unary = function(allow_calls, allow_arrows) {
3358
var start = S.token;
3359
if (start.type == "name" && start.value == "await" && can_await()) {
3360
next();
3361
return _await_expression();
3362
}
3363
if (is("operator") && UNARY_PREFIX.has(start.value)) {
3364
next();
3365
handle_regexp();
3366
var ex = make_unary(AST_UnaryPrefix, start, maybe_unary(allow_calls));
3367
ex.start = start;
3368
ex.end = prev();
3369
return ex;
3370
}
3371
var val = expr_atom(allow_calls, allow_arrows);
3372
while (is("operator") && UNARY_POSTFIX.has(S.token.value) && !has_newline_before(S.token)) {
3373
if (val instanceof AST_Arrow) unexpected();
3374
val = make_unary(AST_UnaryPostfix, S.token, val);
3375
val.start = start;
3376
val.end = S.token;
3377
next();
3378
}
3379
return val;
3380
};
3381
3382
function make_unary(ctor, token, expr) {
3383
var op = token.value;
3384
switch (op) {
3385
case "++":
3386
case "--":
3387
if (!is_assignable(expr))
3388
croak("Invalid use of " + op + " operator", token.line, token.col, token.pos);
3389
break;
3390
case "delete":
3391
if (expr instanceof AST_SymbolRef && S.input.has_directive("use strict"))
3392
croak("Calling delete on expression not allowed in strict mode", expr.start.line, expr.start.col, expr.start.pos);
3393
break;
3394
}
3395
return new ctor({ operator: op, expression: expr });
3396
}
3397
3398
var expr_op = function(left, min_prec, no_in) {
3399
var op = is("operator") ? S.token.value : null;
3400
if (op == "in" && no_in) op = null;
3401
if (op == "**" && left instanceof AST_UnaryPrefix
3402
/* unary token in front not allowed - parenthesis required */
3403
&& !is_token(left.start, "punc", "(")
3404
&& left.operator !== "--" && left.operator !== "++")
3405
unexpected(left.start);
3406
var prec = op != null ? PRECEDENCE[op] : null;
3407
if (prec != null && (prec > min_prec || (op === "**" && min_prec === prec))) {
3408
next();
3409
var right = expr_op(maybe_unary(true), prec, no_in);
3410
return expr_op(new AST_Binary({
3411
start : left.start,
3412
left : left,
3413
operator : op,
3414
right : right,
3415
end : right.end
3416
}), min_prec, no_in);
3417
}
3418
return left;
3419
};
3420
3421
function expr_ops(no_in) {
3422
return expr_op(maybe_unary(true, true), 0, no_in);
3423
}
3424
3425
var maybe_conditional = function(no_in) {
3426
var start = S.token;
3427
var expr = expr_ops(no_in);
3428
if (is("operator", "?")) {
3429
next();
3430
var yes = expression(false);
3431
expect(":");
3432
return new AST_Conditional({
3433
start : start,
3434
condition : expr,
3435
consequent : yes,
3436
alternative : expression(false, no_in),
3437
end : prev()
3438
});
3439
}
3440
return expr;
3441
};
3442
3443
function is_assignable(expr) {
3444
return expr instanceof AST_PropAccess || expr instanceof AST_SymbolRef;
3445
}
3446
3447
function to_destructuring(node) {
3448
if (node instanceof AST_Object) {
3449
node = new AST_Destructuring({
3450
start: node.start,
3451
names: node.properties.map(to_destructuring),
3452
is_array: false,
3453
end: node.end
3454
});
3455
} else if (node instanceof AST_Array) {
3456
var names = [];
3457
3458
for (var i = 0; i < node.elements.length; i++) {
3459
// Only allow expansion as last element
3460
if (node.elements[i] instanceof AST_Expansion) {
3461
if (i + 1 !== node.elements.length) {
3462
token_error(node.elements[i].start, "Spread must the be last element in destructuring array");
3463
}
3464
node.elements[i].expression = to_destructuring(node.elements[i].expression);
3465
}
3466
3467
names.push(to_destructuring(node.elements[i]));
3468
}
3469
3470
node = new AST_Destructuring({
3471
start: node.start,
3472
names: names,
3473
is_array: true,
3474
end: node.end
3475
});
3476
} else if (node instanceof AST_ObjectProperty) {
3477
node.value = to_destructuring(node.value);
3478
} else if (node instanceof AST_Assign) {
3479
node = new AST_DefaultAssign({
3480
start: node.start,
3481
left: node.left,
3482
operator: "=",
3483
right: node.right,
3484
end: node.end
3485
});
3486
}
3487
return node;
3488
}
3489
3490
// In ES6, AssignmentExpression can also be an ArrowFunction
3491
var maybe_assign = function(no_in) {
3492
handle_regexp();
3493
var start = S.token;
3494
3495
if (start.type == "name" && start.value == "yield") {
3496
if (is_in_generator()) {
3497
next();
3498
return _yield_expression();
3499
} else if (S.input.has_directive("use strict")) {
3500
token_error(S.token, "Unexpected yield identifier inside strict mode");
3501
}
3502
}
3503
3504
var left = maybe_conditional(no_in);
3505
var val = S.token.value;
3506
3507
if (is("operator") && ASSIGNMENT.has(val)) {
3508
if (is_assignable(left) || (left = to_destructuring(left)) instanceof AST_Destructuring) {
3509
next();
3510
3511
return new AST_Assign({
3512
start : start,
3513
left : left,
3514
operator : val,
3515
right : maybe_assign(no_in),
3516
logical : LOGICAL_ASSIGNMENT.has(val),
3517
end : prev()
3518
});
3519
}
3520
croak("Invalid assignment");
3521
}
3522
return left;
3523
};
3524
3525
var expression = function(commas, no_in) {
3526
var start = S.token;
3527
var exprs = [];
3528
while (true) {
3529
exprs.push(maybe_assign(no_in));
3530
if (!commas || !is("punc", ",")) break;
3531
next();
3532
commas = true;
3533
}
3534
return exprs.length == 1 ? exprs[0] : new AST_Sequence({
3535
start : start,
3536
expressions : exprs,
3537
end : peek()
3538
});
3539
};
3540
3541
function in_loop(cont) {
3542
++S.in_loop;
3543
var ret = cont();
3544
--S.in_loop;
3545
return ret;
3546
}
3547
3548
if (options.expression) {
3549
return expression(true);
3550
}
3551
3552
return (function parse_toplevel() {
3553
var start = S.token;
3554
var body = [];
3555
S.input.push_directives_stack();
3556
if (options.module) S.input.add_directive("use strict");
3557
while (!is("eof")) {
3558
body.push(statement());
3559
}
3560
S.input.pop_directives_stack();
3561
var end = prev();
3562
var toplevel = options.toplevel;
3563
if (toplevel) {
3564
toplevel.body = toplevel.body.concat(body);
3565
toplevel.end = end;
3566
} else {
3567
toplevel = new AST_Toplevel({ start: start, body: body, end: end });
3568
}
3569
TEMPLATE_RAWS = new Map();
3570
return toplevel;
3571
})();
3572
3573
}
3574
3575
/***********************************************************************
3576
3577
A JavaScript tokenizer / parser / beautifier / compressor.
3578
https://github.com/mishoo/UglifyJS2
3579
3580
-------------------------------- (C) ---------------------------------
3581
3582
Author: Mihai Bazon
3583
<[email protected]>
3584
http://mihai.bazon.net/blog
3585
3586
Distributed under the BSD license:
3587
3588
Copyright 2012 (c) Mihai Bazon <[email protected]>
3589
3590
Redistribution and use in source and binary forms, with or without
3591
modification, are permitted provided that the following conditions
3592
are met:
3593
3594
* Redistributions of source code must retain the above
3595
copyright notice, this list of conditions and the following
3596
disclaimer.
3597
3598
* Redistributions in binary form must reproduce the above
3599
copyright notice, this list of conditions and the following
3600
disclaimer in the documentation and/or other materials
3601
provided with the distribution.
3602
3603
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
3604
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3605
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
3606
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
3607
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
3608
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
3609
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3610
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3611
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
3612
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
3613
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3614
SUCH DAMAGE.
3615
3616
***********************************************************************/
3617
3618
function DEFNODE(type, props, ctor, methods, base = AST_Node) {
3619
if (!props) props = [];
3620
else props = props.split(/\s+/);
3621
var self_props = props;
3622
if (base && base.PROPS)
3623
props = props.concat(base.PROPS);
3624
const proto = base && Object.create(base.prototype);
3625
if (proto) {
3626
ctor.prototype = proto;
3627
ctor.BASE = base;
3628
}
3629
if (base) base.SUBCLASSES.push(ctor);
3630
ctor.prototype.CTOR = ctor;
3631
ctor.prototype.constructor = ctor;
3632
ctor.PROPS = props || null;
3633
ctor.SELF_PROPS = self_props;
3634
ctor.SUBCLASSES = [];
3635
if (type) {
3636
ctor.prototype.TYPE = ctor.TYPE = type;
3637
}
3638
if (methods) for (let i in methods) if (HOP(methods, i)) {
3639
if (i[0] === "$") {
3640
ctor[i.substr(1)] = methods[i];
3641
} else {
3642
ctor.prototype[i] = methods[i];
3643
}
3644
}
3645
ctor.DEFMETHOD = function(name, method) {
3646
this.prototype[name] = method;
3647
};
3648
return ctor;
3649
}
3650
3651
const has_tok_flag = (tok, flag) => Boolean(tok.flags & flag);
3652
const set_tok_flag = (tok, flag, truth) => {
3653
if (truth) {
3654
tok.flags |= flag;
3655
} else {
3656
tok.flags &= ~flag;
3657
}
3658
};
3659
3660
const TOK_FLAG_NLB = 0b0001;
3661
const TOK_FLAG_QUOTE_SINGLE = 0b0010;
3662
const TOK_FLAG_QUOTE_EXISTS = 0b0100;
3663
const TOK_FLAG_TEMPLATE_END = 0b1000;
3664
3665
class AST_Token {
3666
constructor(type, value, line, col, pos, nlb, comments_before, comments_after, file) {
3667
this.flags = (nlb ? 1 : 0);
3668
3669
this.type = type;
3670
this.value = value;
3671
this.line = line;
3672
this.col = col;
3673
this.pos = pos;
3674
this.comments_before = comments_before;
3675
this.comments_after = comments_after;
3676
this.file = file;
3677
3678
Object.seal(this);
3679
}
3680
3681
// Return a string summary of the token for node.js console.log
3682
[Symbol.for("nodejs.util.inspect.custom")](_depth, options) {
3683
const special = str => options.stylize(str, "special");
3684
const quote = typeof this.value === "string" && this.value.includes("`") ? "'" : "`";
3685
const value = `${quote}${this.value}${quote}`;
3686
return `${special("[AST_Token")} ${value} at ${this.line}:${this.col}${special("]")}`;
3687
}
3688
3689
get nlb() {
3690
return has_tok_flag(this, TOK_FLAG_NLB);
3691
}
3692
3693
set nlb(new_nlb) {
3694
set_tok_flag(this, TOK_FLAG_NLB, new_nlb);
3695
}
3696
3697
get quote() {
3698
return !has_tok_flag(this, TOK_FLAG_QUOTE_EXISTS)
3699
? ""
3700
: (has_tok_flag(this, TOK_FLAG_QUOTE_SINGLE) ? "'" : '"');
3701
}
3702
3703
set quote(quote_type) {
3704
set_tok_flag(this, TOK_FLAG_QUOTE_SINGLE, quote_type === "'");
3705
set_tok_flag(this, TOK_FLAG_QUOTE_EXISTS, !!quote_type);
3706
}
3707
3708
get template_end() {
3709
return has_tok_flag(this, TOK_FLAG_TEMPLATE_END);
3710
}
3711
3712
set template_end(new_template_end) {
3713
set_tok_flag(this, TOK_FLAG_TEMPLATE_END, new_template_end);
3714
}
3715
}
3716
3717
var AST_Node = DEFNODE("Node", "start end", function AST_Node(props) {
3718
if (props) {
3719
this.start = props.start;
3720
this.end = props.end;
3721
}
3722
3723
this.flags = 0;
3724
}, {
3725
_clone: function(deep) {
3726
if (deep) {
3727
var self = this.clone();
3728
return self.transform(new TreeTransformer(function(node) {
3729
if (node !== self) {
3730
return node.clone(true);
3731
}
3732
}));
3733
}
3734
return new this.CTOR(this);
3735
},
3736
clone: function(deep) {
3737
return this._clone(deep);
3738
},
3739
$documentation: "Base class of all AST nodes",
3740
$propdoc: {
3741
start: "[AST_Token] The first token of this node",
3742
end: "[AST_Token] The last token of this node"
3743
},
3744
_walk: function(visitor) {
3745
return visitor._visit(this);
3746
},
3747
walk: function(visitor) {
3748
return this._walk(visitor); // not sure the indirection will be any help
3749
},
3750
_children_backwards: () => {}
3751
}, null);
3752
3753
/* -----[ statements ]----- */
3754
3755
var AST_Statement = DEFNODE("Statement", null, function AST_Statement(props) {
3756
if (props) {
3757
this.start = props.start;
3758
this.end = props.end;
3759
}
3760
3761
this.flags = 0;
3762
}, {
3763
$documentation: "Base class of all statements",
3764
});
3765
3766
var AST_Debugger = DEFNODE("Debugger", null, function AST_Debugger(props) {
3767
if (props) {
3768
this.start = props.start;
3769
this.end = props.end;
3770
}
3771
3772
this.flags = 0;
3773
}, {
3774
$documentation: "Represents a debugger statement",
3775
}, AST_Statement);
3776
3777
var AST_Directive = DEFNODE("Directive", "value quote", function AST_Directive(props) {
3778
if (props) {
3779
this.value = props.value;
3780
this.quote = props.quote;
3781
this.start = props.start;
3782
this.end = props.end;
3783
}
3784
3785
this.flags = 0;
3786
}, {
3787
$documentation: "Represents a directive, like \"use strict\";",
3788
$propdoc: {
3789
value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
3790
quote: "[string] the original quote character"
3791
},
3792
}, AST_Statement);
3793
3794
var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", function AST_SimpleStatement(props) {
3795
if (props) {
3796
this.body = props.body;
3797
this.start = props.start;
3798
this.end = props.end;
3799
}
3800
3801
this.flags = 0;
3802
}, {
3803
$documentation: "A statement consisting of an expression, i.e. a = 1 + 2",
3804
$propdoc: {
3805
body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
3806
},
3807
_walk: function(visitor) {
3808
return visitor._visit(this, function() {
3809
this.body._walk(visitor);
3810
});
3811
},
3812
_children_backwards(push) {
3813
push(this.body);
3814
}
3815
}, AST_Statement);
3816
3817
// XXX Emscripten localmod: Add a node type for a parenthesized expression so that we can retain
3818
// Closure annotations that need a form "/**annotation*/(expression)"
3819
var AST_ParenthesizedExpression = DEFNODE("ParenthesizedExpression", "body", function AST_ParenthesizedExpression(props) {
3820
if (props) {
3821
this.body = props.body;
3822
this.start = props.start;
3823
this.end = props.end;
3824
}
3825
3826
this.flags = 0;
3827
}, {
3828
$documentation: "An explicitly parenthesized expression, i.e. a = (1 + 2)",
3829
$propdoc: {
3830
body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
3831
},
3832
_walk: function(visitor) {
3833
return visitor._visit(this, function() {
3834
this.body._walk(visitor);
3835
});
3836
}
3837
}, AST_Statement);
3838
// XXX End of Emscripten localmod
3839
3840
function walk_body(node, visitor) {
3841
const body = node.body;
3842
for (var i = 0, len = body.length; i < len; i++) {
3843
body[i]._walk(visitor);
3844
}
3845
}
3846
3847
function clone_block_scope(deep) {
3848
var clone = this._clone(deep);
3849
if (this.block_scope) {
3850
clone.block_scope = this.block_scope.clone();
3851
}
3852
return clone;
3853
}
3854
3855
var AST_Block = DEFNODE("Block", "body block_scope", function AST_Block(props) {
3856
if (props) {
3857
this.body = props.body;
3858
this.block_scope = props.block_scope;
3859
this.start = props.start;
3860
this.end = props.end;
3861
}
3862
3863
this.flags = 0;
3864
}, {
3865
$documentation: "A body of statements (usually braced)",
3866
$propdoc: {
3867
body: "[AST_Statement*] an array of statements",
3868
block_scope: "[AST_Scope] the block scope"
3869
},
3870
_walk: function(visitor) {
3871
return visitor._visit(this, function() {
3872
walk_body(this, visitor);
3873
});
3874
},
3875
_children_backwards(push) {
3876
let i = this.body.length;
3877
while (i--) push(this.body[i]);
3878
},
3879
clone: clone_block_scope
3880
}, AST_Statement);
3881
3882
var AST_BlockStatement = DEFNODE("BlockStatement", null, function AST_BlockStatement(props) {
3883
if (props) {
3884
this.body = props.body;
3885
this.block_scope = props.block_scope;
3886
this.start = props.start;
3887
this.end = props.end;
3888
}
3889
3890
this.flags = 0;
3891
}, {
3892
$documentation: "A block statement",
3893
}, AST_Block);
3894
3895
var AST_EmptyStatement = DEFNODE("EmptyStatement", null, function AST_EmptyStatement(props) {
3896
if (props) {
3897
this.start = props.start;
3898
this.end = props.end;
3899
}
3900
3901
this.flags = 0;
3902
}, {
3903
$documentation: "The empty statement (empty block or simply a semicolon)"
3904
}, AST_Statement);
3905
3906
var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", function AST_StatementWithBody(props) {
3907
if (props) {
3908
this.body = props.body;
3909
this.start = props.start;
3910
this.end = props.end;
3911
}
3912
3913
this.flags = 0;
3914
}, {
3915
$documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",
3916
$propdoc: {
3917
body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
3918
}
3919
}, AST_Statement);
3920
3921
var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", function AST_LabeledStatement(props) {
3922
if (props) {
3923
this.label = props.label;
3924
this.body = props.body;
3925
this.start = props.start;
3926
this.end = props.end;
3927
}
3928
3929
this.flags = 0;
3930
}, {
3931
$documentation: "Statement with a label",
3932
$propdoc: {
3933
label: "[AST_Label] a label definition"
3934
},
3935
_walk: function(visitor) {
3936
return visitor._visit(this, function() {
3937
this.label._walk(visitor);
3938
this.body._walk(visitor);
3939
});
3940
},
3941
_children_backwards(push) {
3942
push(this.body);
3943
push(this.label);
3944
},
3945
clone: function(deep) {
3946
var node = this._clone(deep);
3947
if (deep) {
3948
var label = node.label;
3949
var def = this.label;
3950
node.walk(new TreeWalker(function(node) {
3951
if (node instanceof AST_LoopControl
3952
&& node.label && node.label.thedef === def) {
3953
node.label.thedef = label;
3954
label.references.push(node);
3955
}
3956
}));
3957
}
3958
return node;
3959
}
3960
}, AST_StatementWithBody);
3961
3962
var AST_IterationStatement = DEFNODE(
3963
"IterationStatement",
3964
"block_scope",
3965
function AST_IterationStatement(props) {
3966
if (props) {
3967
this.block_scope = props.block_scope;
3968
this.body = props.body;
3969
this.start = props.start;
3970
this.end = props.end;
3971
}
3972
3973
this.flags = 0;
3974
},
3975
{
3976
$documentation: "Internal class. All loops inherit from it.",
3977
$propdoc: {
3978
block_scope: "[AST_Scope] the block scope for this iteration statement."
3979
},
3980
clone: clone_block_scope
3981
},
3982
AST_StatementWithBody
3983
);
3984
3985
var AST_DWLoop = DEFNODE("DWLoop", "condition", function AST_DWLoop(props) {
3986
if (props) {
3987
this.condition = props.condition;
3988
this.block_scope = props.block_scope;
3989
this.body = props.body;
3990
this.start = props.start;
3991
this.end = props.end;
3992
}
3993
3994
this.flags = 0;
3995
}, {
3996
$documentation: "Base class for do/while statements",
3997
$propdoc: {
3998
condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement"
3999
}
4000
}, AST_IterationStatement);
4001
4002
var AST_Do = DEFNODE("Do", null, function AST_Do(props) {
4003
if (props) {
4004
this.condition = props.condition;
4005
this.block_scope = props.block_scope;
4006
this.body = props.body;
4007
this.start = props.start;
4008
this.end = props.end;
4009
}
4010
4011
this.flags = 0;
4012
}, {
4013
$documentation: "A `do` statement",
4014
_walk: function(visitor) {
4015
return visitor._visit(this, function() {
4016
this.body._walk(visitor);
4017
this.condition._walk(visitor);
4018
});
4019
},
4020
_children_backwards(push) {
4021
push(this.condition);
4022
push(this.body);
4023
}
4024
}, AST_DWLoop);
4025
4026
var AST_While = DEFNODE("While", null, function AST_While(props) {
4027
if (props) {
4028
this.condition = props.condition;
4029
this.block_scope = props.block_scope;
4030
this.body = props.body;
4031
this.start = props.start;
4032
this.end = props.end;
4033
}
4034
4035
this.flags = 0;
4036
}, {
4037
$documentation: "A `while` statement",
4038
_walk: function(visitor) {
4039
return visitor._visit(this, function() {
4040
this.condition._walk(visitor);
4041
this.body._walk(visitor);
4042
});
4043
},
4044
_children_backwards(push) {
4045
push(this.body);
4046
push(this.condition);
4047
},
4048
}, AST_DWLoop);
4049
4050
var AST_For = DEFNODE("For", "init condition step", function AST_For(props) {
4051
if (props) {
4052
this.init = props.init;
4053
this.condition = props.condition;
4054
this.step = props.step;
4055
this.block_scope = props.block_scope;
4056
this.body = props.body;
4057
this.start = props.start;
4058
this.end = props.end;
4059
}
4060
4061
this.flags = 0;
4062
}, {
4063
$documentation: "A `for` statement",
4064
$propdoc: {
4065
init: "[AST_Node?] the `for` initialization code, or null if empty",
4066
condition: "[AST_Node?] the `for` termination clause, or null if empty",
4067
step: "[AST_Node?] the `for` update clause, or null if empty"
4068
},
4069
_walk: function(visitor) {
4070
return visitor._visit(this, function() {
4071
if (this.init) this.init._walk(visitor);
4072
if (this.condition) this.condition._walk(visitor);
4073
if (this.step) this.step._walk(visitor);
4074
this.body._walk(visitor);
4075
});
4076
},
4077
_children_backwards(push) {
4078
push(this.body);
4079
if (this.step) push(this.step);
4080
if (this.condition) push(this.condition);
4081
if (this.init) push(this.init);
4082
},
4083
}, AST_IterationStatement);
4084
4085
var AST_ForIn = DEFNODE("ForIn", "init object", function AST_ForIn(props) {
4086
if (props) {
4087
this.init = props.init;
4088
this.object = props.object;
4089
this.block_scope = props.block_scope;
4090
this.body = props.body;
4091
this.start = props.start;
4092
this.end = props.end;
4093
}
4094
4095
this.flags = 0;
4096
}, {
4097
$documentation: "A `for ... in` statement",
4098
$propdoc: {
4099
init: "[AST_Node] the `for/in` initialization code",
4100
object: "[AST_Node] the object that we're looping through"
4101
},
4102
_walk: function(visitor) {
4103
return visitor._visit(this, function() {
4104
this.init._walk(visitor);
4105
this.object._walk(visitor);
4106
this.body._walk(visitor);
4107
});
4108
},
4109
_children_backwards(push) {
4110
push(this.body);
4111
if (this.object) push(this.object);
4112
if (this.init) push(this.init);
4113
},
4114
}, AST_IterationStatement);
4115
4116
var AST_ForOf = DEFNODE("ForOf", "await", function AST_ForOf(props) {
4117
if (props) {
4118
this.await = props.await;
4119
this.init = props.init;
4120
this.object = props.object;
4121
this.block_scope = props.block_scope;
4122
this.body = props.body;
4123
this.start = props.start;
4124
this.end = props.end;
4125
}
4126
4127
this.flags = 0;
4128
}, {
4129
$documentation: "A `for ... of` statement",
4130
}, AST_ForIn);
4131
4132
var AST_With = DEFNODE("With", "expression", function AST_With(props) {
4133
if (props) {
4134
this.expression = props.expression;
4135
this.body = props.body;
4136
this.start = props.start;
4137
this.end = props.end;
4138
}
4139
4140
this.flags = 0;
4141
}, {
4142
$documentation: "A `with` statement",
4143
$propdoc: {
4144
expression: "[AST_Node] the `with` expression"
4145
},
4146
_walk: function(visitor) {
4147
return visitor._visit(this, function() {
4148
this.expression._walk(visitor);
4149
this.body._walk(visitor);
4150
});
4151
},
4152
_children_backwards(push) {
4153
push(this.body);
4154
push(this.expression);
4155
},
4156
}, AST_StatementWithBody);
4157
4158
/* -----[ scope and functions ]----- */
4159
4160
var AST_Scope = DEFNODE(
4161
"Scope",
4162
"variables uses_with uses_eval parent_scope enclosed cname",
4163
function AST_Scope(props) {
4164
if (props) {
4165
this.variables = props.variables;
4166
this.uses_with = props.uses_with;
4167
this.uses_eval = props.uses_eval;
4168
this.parent_scope = props.parent_scope;
4169
this.enclosed = props.enclosed;
4170
this.cname = props.cname;
4171
this.body = props.body;
4172
this.block_scope = props.block_scope;
4173
this.start = props.start;
4174
this.end = props.end;
4175
}
4176
4177
this.flags = 0;
4178
},
4179
{
4180
$documentation: "Base class for all statements introducing a lexical scope",
4181
$propdoc: {
4182
variables: "[Map/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
4183
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
4184
uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
4185
parent_scope: "[AST_Scope?/S] link to the parent scope",
4186
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
4187
cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
4188
},
4189
get_defun_scope: function() {
4190
var self = this;
4191
while (self.is_block_scope()) {
4192
self = self.parent_scope;
4193
}
4194
return self;
4195
},
4196
clone: function(deep, toplevel) {
4197
var node = this._clone(deep);
4198
if (deep && this.variables && toplevel && !this._block_scope) {
4199
node.figure_out_scope({}, {
4200
toplevel: toplevel,
4201
parent_scope: this.parent_scope
4202
});
4203
} else {
4204
if (this.variables) node.variables = new Map(this.variables);
4205
if (this.enclosed) node.enclosed = this.enclosed.slice();
4206
if (this._block_scope) node._block_scope = this._block_scope;
4207
}
4208
return node;
4209
},
4210
pinned: function() {
4211
return this.uses_eval || this.uses_with;
4212
}
4213
},
4214
AST_Block
4215
);
4216
4217
var AST_Toplevel = DEFNODE("Toplevel", "globals", function AST_Toplevel(props) {
4218
if (props) {
4219
this.globals = props.globals;
4220
this.variables = props.variables;
4221
this.uses_with = props.uses_with;
4222
this.uses_eval = props.uses_eval;
4223
this.parent_scope = props.parent_scope;
4224
this.enclosed = props.enclosed;
4225
this.cname = props.cname;
4226
this.body = props.body;
4227
this.block_scope = props.block_scope;
4228
this.start = props.start;
4229
this.end = props.end;
4230
}
4231
4232
this.flags = 0;
4233
}, {
4234
$documentation: "The toplevel scope",
4235
$propdoc: {
4236
globals: "[Map/S] a map of name -> SymbolDef for all undeclared names",
4237
},
4238
wrap_commonjs: function(name) {
4239
var body = this.body;
4240
var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");";
4241
wrapped_tl = parse(wrapped_tl);
4242
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function(node) {
4243
if (node instanceof AST_Directive && node.value == "$ORIG") {
4244
return MAP.splice(body);
4245
}
4246
}));
4247
return wrapped_tl;
4248
},
4249
wrap_enclose: function(args_values) {
4250
if (typeof args_values != "string") args_values = "";
4251
var index = args_values.indexOf(":");
4252
if (index < 0) index = args_values.length;
4253
var body = this.body;
4254
return parse([
4255
"(function(",
4256
args_values.slice(0, index),
4257
'){"$ORIG"})(',
4258
args_values.slice(index + 1),
4259
")"
4260
].join("")).transform(new TreeTransformer(function(node) {
4261
if (node instanceof AST_Directive && node.value == "$ORIG") {
4262
return MAP.splice(body);
4263
}
4264
}));
4265
}
4266
}, AST_Scope);
4267
4268
var AST_Expansion = DEFNODE("Expansion", "expression", function AST_Expansion(props) {
4269
if (props) {
4270
this.expression = props.expression;
4271
this.start = props.start;
4272
this.end = props.end;
4273
}
4274
4275
this.flags = 0;
4276
}, {
4277
$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",
4278
$propdoc: {
4279
expression: "[AST_Node] the thing to be expanded"
4280
},
4281
_walk: function(visitor) {
4282
return visitor._visit(this, function() {
4283
this.expression.walk(visitor);
4284
});
4285
},
4286
_children_backwards(push) {
4287
push(this.expression);
4288
},
4289
});
4290
4291
var AST_Lambda = DEFNODE(
4292
"Lambda",
4293
"name argnames uses_arguments is_generator async",
4294
function AST_Lambda(props) {
4295
if (props) {
4296
this.name = props.name;
4297
this.argnames = props.argnames;
4298
this.uses_arguments = props.uses_arguments;
4299
this.is_generator = props.is_generator;
4300
this.async = props.async;
4301
this.variables = props.variables;
4302
this.uses_with = props.uses_with;
4303
this.uses_eval = props.uses_eval;
4304
this.parent_scope = props.parent_scope;
4305
this.enclosed = props.enclosed;
4306
this.cname = props.cname;
4307
this.body = props.body;
4308
this.block_scope = props.block_scope;
4309
this.start = props.start;
4310
this.end = props.end;
4311
}
4312
4313
this.flags = 0;
4314
},
4315
{
4316
$documentation: "Base class for functions",
4317
$propdoc: {
4318
name: "[AST_SymbolDeclaration?] the name of this function",
4319
argnames: "[AST_SymbolFunarg|AST_Destructuring|AST_Expansion|AST_DefaultAssign*] array of function arguments, destructurings, or expanding arguments",
4320
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array",
4321
is_generator: "[boolean] is this a generator method",
4322
async: "[boolean] is this method async",
4323
},
4324
args_as_names: function () {
4325
var out = [];
4326
for (var i = 0; i < this.argnames.length; i++) {
4327
if (this.argnames[i] instanceof AST_Destructuring) {
4328
out.push(...this.argnames[i].all_symbols());
4329
} else {
4330
out.push(this.argnames[i]);
4331
}
4332
}
4333
return out;
4334
},
4335
_walk: function(visitor) {
4336
return visitor._visit(this, function() {
4337
if (this.name) this.name._walk(visitor);
4338
var argnames = this.argnames;
4339
for (var i = 0, len = argnames.length; i < len; i++) {
4340
argnames[i]._walk(visitor);
4341
}
4342
walk_body(this, visitor);
4343
});
4344
},
4345
_children_backwards(push) {
4346
let i = this.body.length;
4347
while (i--) push(this.body[i]);
4348
4349
i = this.argnames.length;
4350
while (i--) push(this.argnames[i]);
4351
4352
if (this.name) push(this.name);
4353
},
4354
is_braceless() {
4355
return this.body[0] instanceof AST_Return && this.body[0].value;
4356
},
4357
// Default args and expansion don't count, so .argnames.length doesn't cut it
4358
length_property() {
4359
let length = 0;
4360
4361
for (const arg of this.argnames) {
4362
if (arg instanceof AST_SymbolFunarg || arg instanceof AST_Destructuring) {
4363
length++;
4364
}
4365
}
4366
4367
return length;
4368
}
4369
},
4370
AST_Scope
4371
);
4372
4373
var AST_Accessor = DEFNODE("Accessor", null, function AST_Accessor(props) {
4374
if (props) {
4375
this.name = props.name;
4376
this.argnames = props.argnames;
4377
this.uses_arguments = props.uses_arguments;
4378
this.is_generator = props.is_generator;
4379
this.async = props.async;
4380
this.variables = props.variables;
4381
this.uses_with = props.uses_with;
4382
this.uses_eval = props.uses_eval;
4383
this.parent_scope = props.parent_scope;
4384
this.enclosed = props.enclosed;
4385
this.cname = props.cname;
4386
this.body = props.body;
4387
this.block_scope = props.block_scope;
4388
this.start = props.start;
4389
this.end = props.end;
4390
}
4391
4392
this.flags = 0;
4393
}, {
4394
$documentation: "A setter/getter function. The `name` property is always null."
4395
}, AST_Lambda);
4396
4397
var AST_Function = DEFNODE("Function", null, function AST_Function(props) {
4398
if (props) {
4399
this.name = props.name;
4400
this.argnames = props.argnames;
4401
this.uses_arguments = props.uses_arguments;
4402
this.is_generator = props.is_generator;
4403
this.async = props.async;
4404
this.variables = props.variables;
4405
this.uses_with = props.uses_with;
4406
this.uses_eval = props.uses_eval;
4407
this.parent_scope = props.parent_scope;
4408
this.enclosed = props.enclosed;
4409
this.cname = props.cname;
4410
this.body = props.body;
4411
this.block_scope = props.block_scope;
4412
this.start = props.start;
4413
this.end = props.end;
4414
}
4415
4416
this.flags = 0;
4417
}, {
4418
$documentation: "A function expression"
4419
}, AST_Lambda);
4420
4421
var AST_Arrow = DEFNODE("Arrow", null, function AST_Arrow(props) {
4422
if (props) {
4423
this.name = props.name;
4424
this.argnames = props.argnames;
4425
this.uses_arguments = props.uses_arguments;
4426
this.is_generator = props.is_generator;
4427
this.async = props.async;
4428
this.variables = props.variables;
4429
this.uses_with = props.uses_with;
4430
this.uses_eval = props.uses_eval;
4431
this.parent_scope = props.parent_scope;
4432
this.enclosed = props.enclosed;
4433
this.cname = props.cname;
4434
this.body = props.body;
4435
this.block_scope = props.block_scope;
4436
this.start = props.start;
4437
this.end = props.end;
4438
}
4439
4440
this.flags = 0;
4441
}, {
4442
$documentation: "An ES6 Arrow function ((a) => b)"
4443
}, AST_Lambda);
4444
4445
var AST_Defun = DEFNODE("Defun", null, function AST_Defun(props) {
4446
if (props) {
4447
this.name = props.name;
4448
this.argnames = props.argnames;
4449
this.uses_arguments = props.uses_arguments;
4450
this.is_generator = props.is_generator;
4451
this.async = props.async;
4452
this.variables = props.variables;
4453
this.uses_with = props.uses_with;
4454
this.uses_eval = props.uses_eval;
4455
this.parent_scope = props.parent_scope;
4456
this.enclosed = props.enclosed;
4457
this.cname = props.cname;
4458
this.body = props.body;
4459
this.block_scope = props.block_scope;
4460
this.start = props.start;
4461
this.end = props.end;
4462
}
4463
4464
this.flags = 0;
4465
}, {
4466
$documentation: "A function definition"
4467
}, AST_Lambda);
4468
4469
/* -----[ DESTRUCTURING ]----- */
4470
var AST_Destructuring = DEFNODE("Destructuring", "names is_array", function AST_Destructuring(props) {
4471
if (props) {
4472
this.names = props.names;
4473
this.is_array = props.is_array;
4474
this.start = props.start;
4475
this.end = props.end;
4476
}
4477
4478
this.flags = 0;
4479
}, {
4480
$documentation: "A destructuring of several names. Used in destructuring assignment and with destructuring function argument names",
4481
$propdoc: {
4482
"names": "[AST_Node*] Array of properties or elements",
4483
"is_array": "[Boolean] Whether the destructuring represents an object or array"
4484
},
4485
_walk: function(visitor) {
4486
return visitor._visit(this, function() {
4487
this.names.forEach(function(name) {
4488
name._walk(visitor);
4489
});
4490
});
4491
},
4492
_children_backwards(push) {
4493
let i = this.names.length;
4494
while (i--) push(this.names[i]);
4495
},
4496
all_symbols: function() {
4497
var out = [];
4498
walk(this, node => {
4499
if (node instanceof AST_SymbolDeclaration) {
4500
out.push(node);
4501
}
4502
if (node instanceof AST_Lambda) {
4503
return true;
4504
}
4505
});
4506
return out;
4507
}
4508
});
4509
4510
var AST_PrefixedTemplateString = DEFNODE(
4511
"PrefixedTemplateString",
4512
"template_string prefix",
4513
function AST_PrefixedTemplateString(props) {
4514
if (props) {
4515
this.template_string = props.template_string;
4516
this.prefix = props.prefix;
4517
this.start = props.start;
4518
this.end = props.end;
4519
}
4520
4521
this.flags = 0;
4522
},
4523
{
4524
$documentation: "A templatestring with a prefix, such as String.raw`foobarbaz`",
4525
$propdoc: {
4526
template_string: "[AST_TemplateString] The template string",
4527
prefix: "[AST_Node] The prefix, which will get called."
4528
},
4529
_walk: function(visitor) {
4530
return visitor._visit(this, function () {
4531
this.prefix._walk(visitor);
4532
this.template_string._walk(visitor);
4533
});
4534
},
4535
_children_backwards(push) {
4536
push(this.template_string);
4537
push(this.prefix);
4538
},
4539
}
4540
);
4541
4542
var AST_TemplateString = DEFNODE("TemplateString", "segments", function AST_TemplateString(props) {
4543
if (props) {
4544
this.segments = props.segments;
4545
this.start = props.start;
4546
this.end = props.end;
4547
}
4548
4549
this.flags = 0;
4550
}, {
4551
$documentation: "A template string literal",
4552
$propdoc: {
4553
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."
4554
},
4555
_walk: function(visitor) {
4556
return visitor._visit(this, function() {
4557
this.segments.forEach(function(seg) {
4558
seg._walk(visitor);
4559
});
4560
});
4561
},
4562
_children_backwards(push) {
4563
let i = this.segments.length;
4564
while (i--) push(this.segments[i]);
4565
}
4566
});
4567
4568
var AST_TemplateSegment = DEFNODE("TemplateSegment", "value raw", function AST_TemplateSegment(props) {
4569
if (props) {
4570
this.value = props.value;
4571
this.raw = props.raw;
4572
this.start = props.start;
4573
this.end = props.end;
4574
}
4575
4576
this.flags = 0;
4577
}, {
4578
$documentation: "A segment of a template string literal",
4579
$propdoc: {
4580
value: "Content of the segment",
4581
raw: "Raw source of the segment",
4582
}
4583
});
4584
4585
/* -----[ JUMPS ]----- */
4586
4587
var AST_Jump = DEFNODE("Jump", null, function AST_Jump(props) {
4588
if (props) {
4589
this.start = props.start;
4590
this.end = props.end;
4591
}
4592
4593
this.flags = 0;
4594
}, {
4595
$documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"
4596
}, AST_Statement);
4597
4598
/** Base class for “exits” (`return` and `throw`) */
4599
var AST_Exit = DEFNODE("Exit", "value", function AST_Exit(props) {
4600
if (props) {
4601
this.value = props.value;
4602
this.start = props.start;
4603
this.end = props.end;
4604
}
4605
4606
this.flags = 0;
4607
}, {
4608
$documentation: "Base class for “exits” (`return` and `throw`)",
4609
$propdoc: {
4610
value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
4611
},
4612
_walk: function(visitor) {
4613
return visitor._visit(this, this.value && function() {
4614
this.value._walk(visitor);
4615
});
4616
},
4617
_children_backwards(push) {
4618
if (this.value) push(this.value);
4619
},
4620
}, AST_Jump);
4621
4622
var AST_Return = DEFNODE("Return", null, function AST_Return(props) {
4623
if (props) {
4624
this.value = props.value;
4625
this.start = props.start;
4626
this.end = props.end;
4627
}
4628
4629
this.flags = 0;
4630
}, {
4631
$documentation: "A `return` statement"
4632
}, AST_Exit);
4633
4634
var AST_Throw = DEFNODE("Throw", null, function AST_Throw(props) {
4635
if (props) {
4636
this.value = props.value;
4637
this.start = props.start;
4638
this.end = props.end;
4639
}
4640
4641
this.flags = 0;
4642
}, {
4643
$documentation: "A `throw` statement"
4644
}, AST_Exit);
4645
4646
var AST_LoopControl = DEFNODE("LoopControl", "label", function AST_LoopControl(props) {
4647
if (props) {
4648
this.label = props.label;
4649
this.start = props.start;
4650
this.end = props.end;
4651
}
4652
4653
this.flags = 0;
4654
}, {
4655
$documentation: "Base class for loop control statements (`break` and `continue`)",
4656
$propdoc: {
4657
label: "[AST_LabelRef?] the label, or null if none",
4658
},
4659
_walk: function(visitor) {
4660
return visitor._visit(this, this.label && function() {
4661
this.label._walk(visitor);
4662
});
4663
},
4664
_children_backwards(push) {
4665
if (this.label) push(this.label);
4666
},
4667
}, AST_Jump);
4668
4669
var AST_Break = DEFNODE("Break", null, function AST_Break(props) {
4670
if (props) {
4671
this.label = props.label;
4672
this.start = props.start;
4673
this.end = props.end;
4674
}
4675
4676
this.flags = 0;
4677
}, {
4678
$documentation: "A `break` statement"
4679
}, AST_LoopControl);
4680
4681
var AST_Continue = DEFNODE("Continue", null, function AST_Continue(props) {
4682
if (props) {
4683
this.label = props.label;
4684
this.start = props.start;
4685
this.end = props.end;
4686
}
4687
4688
this.flags = 0;
4689
}, {
4690
$documentation: "A `continue` statement"
4691
}, AST_LoopControl);
4692
4693
var AST_Await = DEFNODE("Await", "expression", function AST_Await(props) {
4694
if (props) {
4695
this.expression = props.expression;
4696
this.start = props.start;
4697
this.end = props.end;
4698
}
4699
4700
this.flags = 0;
4701
}, {
4702
$documentation: "An `await` statement",
4703
$propdoc: {
4704
expression: "[AST_Node] the mandatory expression being awaited",
4705
},
4706
_walk: function(visitor) {
4707
return visitor._visit(this, function() {
4708
this.expression._walk(visitor);
4709
});
4710
},
4711
_children_backwards(push) {
4712
push(this.expression);
4713
},
4714
});
4715
4716
var AST_Yield = DEFNODE("Yield", "expression is_star", function AST_Yield(props) {
4717
if (props) {
4718
this.expression = props.expression;
4719
this.is_star = props.is_star;
4720
this.start = props.start;
4721
this.end = props.end;
4722
}
4723
4724
this.flags = 0;
4725
}, {
4726
$documentation: "A `yield` statement",
4727
$propdoc: {
4728
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",
4729
is_star: "[Boolean] Whether this is a yield or yield* statement"
4730
},
4731
_walk: function(visitor) {
4732
return visitor._visit(this, this.expression && function() {
4733
this.expression._walk(visitor);
4734
});
4735
},
4736
_children_backwards(push) {
4737
if (this.expression) push(this.expression);
4738
}
4739
});
4740
4741
/* -----[ IF ]----- */
4742
4743
var AST_If = DEFNODE("If", "condition alternative", function AST_If(props) {
4744
if (props) {
4745
this.condition = props.condition;
4746
this.alternative = props.alternative;
4747
this.body = props.body;
4748
this.start = props.start;
4749
this.end = props.end;
4750
}
4751
4752
this.flags = 0;
4753
}, {
4754
$documentation: "A `if` statement",
4755
$propdoc: {
4756
condition: "[AST_Node] the `if` condition",
4757
alternative: "[AST_Statement?] the `else` part, or null if not present"
4758
},
4759
_walk: function(visitor) {
4760
return visitor._visit(this, function() {
4761
this.condition._walk(visitor);
4762
this.body._walk(visitor);
4763
if (this.alternative) this.alternative._walk(visitor);
4764
});
4765
},
4766
_children_backwards(push) {
4767
if (this.alternative) {
4768
push(this.alternative);
4769
}
4770
push(this.body);
4771
push(this.condition);
4772
}
4773
}, AST_StatementWithBody);
4774
4775
/* -----[ SWITCH ]----- */
4776
4777
var AST_Switch = DEFNODE("Switch", "expression", function AST_Switch(props) {
4778
if (props) {
4779
this.expression = props.expression;
4780
this.body = props.body;
4781
this.block_scope = props.block_scope;
4782
this.start = props.start;
4783
this.end = props.end;
4784
}
4785
4786
this.flags = 0;
4787
}, {
4788
$documentation: "A `switch` statement",
4789
$propdoc: {
4790
expression: "[AST_Node] the `switch` “discriminant”"
4791
},
4792
_walk: function(visitor) {
4793
return visitor._visit(this, function() {
4794
this.expression._walk(visitor);
4795
walk_body(this, visitor);
4796
});
4797
},
4798
_children_backwards(push) {
4799
let i = this.body.length;
4800
while (i--) push(this.body[i]);
4801
push(this.expression);
4802
}
4803
}, AST_Block);
4804
4805
var AST_SwitchBranch = DEFNODE("SwitchBranch", null, function AST_SwitchBranch(props) {
4806
if (props) {
4807
this.body = props.body;
4808
this.block_scope = props.block_scope;
4809
this.start = props.start;
4810
this.end = props.end;
4811
}
4812
4813
this.flags = 0;
4814
}, {
4815
$documentation: "Base class for `switch` branches",
4816
}, AST_Block);
4817
4818
var AST_Default = DEFNODE("Default", null, function AST_Default(props) {
4819
if (props) {
4820
this.body = props.body;
4821
this.block_scope = props.block_scope;
4822
this.start = props.start;
4823
this.end = props.end;
4824
}
4825
4826
this.flags = 0;
4827
}, {
4828
$documentation: "A `default` switch branch",
4829
}, AST_SwitchBranch);
4830
4831
var AST_Case = DEFNODE("Case", "expression", function AST_Case(props) {
4832
if (props) {
4833
this.expression = props.expression;
4834
this.body = props.body;
4835
this.block_scope = props.block_scope;
4836
this.start = props.start;
4837
this.end = props.end;
4838
}
4839
4840
this.flags = 0;
4841
}, {
4842
$documentation: "A `case` switch branch",
4843
$propdoc: {
4844
expression: "[AST_Node] the `case` expression"
4845
},
4846
_walk: function(visitor) {
4847
return visitor._visit(this, function() {
4848
this.expression._walk(visitor);
4849
walk_body(this, visitor);
4850
});
4851
},
4852
_children_backwards(push) {
4853
let i = this.body.length;
4854
while (i--) push(this.body[i]);
4855
push(this.expression);
4856
},
4857
}, AST_SwitchBranch);
4858
4859
/* -----[ EXCEPTIONS ]----- */
4860
4861
var AST_Try = DEFNODE("Try", "body bcatch bfinally", function AST_Try(props) {
4862
if (props) {
4863
this.body = props.body;
4864
this.bcatch = props.bcatch;
4865
this.bfinally = props.bfinally;
4866
this.start = props.start;
4867
this.end = props.end;
4868
}
4869
4870
this.flags = 0;
4871
}, {
4872
$documentation: "A `try` statement",
4873
$propdoc: {
4874
body: "[AST_TryBlock] the try block",
4875
bcatch: "[AST_Catch?] the catch block, or null if not present",
4876
bfinally: "[AST_Finally?] the finally block, or null if not present"
4877
},
4878
_walk: function(visitor) {
4879
return visitor._visit(this, function() {
4880
this.body._walk(visitor);
4881
if (this.bcatch) this.bcatch._walk(visitor);
4882
if (this.bfinally) this.bfinally._walk(visitor);
4883
});
4884
},
4885
_children_backwards(push) {
4886
if (this.bfinally) push(this.bfinally);
4887
if (this.bcatch) push(this.bcatch);
4888
push(this.body);
4889
},
4890
}, AST_Statement);
4891
4892
var AST_TryBlock = DEFNODE("TryBlock", null, function AST_TryBlock(props) {
4893
if (props) {
4894
this.body = props.body;
4895
this.block_scope = props.block_scope;
4896
this.start = props.start;
4897
this.end = props.end;
4898
}
4899
4900
this.flags = 0;
4901
}, {
4902
$documentation: "The `try` block of a try statement"
4903
}, AST_Block);
4904
4905
var AST_Catch = DEFNODE("Catch", "argname", function AST_Catch(props) {
4906
if (props) {
4907
this.argname = props.argname;
4908
this.body = props.body;
4909
this.block_scope = props.block_scope;
4910
this.start = props.start;
4911
this.end = props.end;
4912
}
4913
4914
this.flags = 0;
4915
}, {
4916
$documentation: "A `catch` node; only makes sense as part of a `try` statement",
4917
$propdoc: {
4918
argname: "[AST_SymbolCatch|AST_Destructuring|AST_Expansion|AST_DefaultAssign] symbol for the exception"
4919
},
4920
_walk: function(visitor) {
4921
return visitor._visit(this, function() {
4922
if (this.argname) this.argname._walk(visitor);
4923
walk_body(this, visitor);
4924
});
4925
},
4926
_children_backwards(push) {
4927
let i = this.body.length;
4928
while (i--) push(this.body[i]);
4929
if (this.argname) push(this.argname);
4930
},
4931
}, AST_Block);
4932
4933
var AST_Finally = DEFNODE("Finally", null, function AST_Finally(props) {
4934
if (props) {
4935
this.body = props.body;
4936
this.block_scope = props.block_scope;
4937
this.start = props.start;
4938
this.end = props.end;
4939
}
4940
4941
this.flags = 0;
4942
}, {
4943
$documentation: "A `finally` node; only makes sense as part of a `try` statement"
4944
}, AST_Block);
4945
4946
/* -----[ VAR/CONST ]----- */
4947
4948
var AST_Definitions = DEFNODE("Definitions", "definitions", function AST_Definitions(props) {
4949
if (props) {
4950
this.definitions = props.definitions;
4951
this.start = props.start;
4952
this.end = props.end;
4953
}
4954
4955
this.flags = 0;
4956
}, {
4957
$documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
4958
$propdoc: {
4959
definitions: "[AST_VarDef*] array of variable definitions"
4960
},
4961
_walk: function(visitor) {
4962
return visitor._visit(this, function() {
4963
var definitions = this.definitions;
4964
for (var i = 0, len = definitions.length; i < len; i++) {
4965
definitions[i]._walk(visitor);
4966
}
4967
});
4968
},
4969
_children_backwards(push) {
4970
let i = this.definitions.length;
4971
while (i--) push(this.definitions[i]);
4972
},
4973
}, AST_Statement);
4974
4975
var AST_Var = DEFNODE("Var", null, function AST_Var(props) {
4976
if (props) {
4977
this.definitions = props.definitions;
4978
this.start = props.start;
4979
this.end = props.end;
4980
}
4981
4982
this.flags = 0;
4983
}, {
4984
$documentation: "A `var` statement"
4985
}, AST_Definitions);
4986
4987
var AST_Let = DEFNODE("Let", null, function AST_Let(props) {
4988
if (props) {
4989
this.definitions = props.definitions;
4990
this.start = props.start;
4991
this.end = props.end;
4992
}
4993
4994
this.flags = 0;
4995
}, {
4996
$documentation: "A `let` statement"
4997
}, AST_Definitions);
4998
4999
var AST_Const = DEFNODE("Const", null, function AST_Const(props) {
5000
if (props) {
5001
this.definitions = props.definitions;
5002
this.start = props.start;
5003
this.end = props.end;
5004
}
5005
5006
this.flags = 0;
5007
}, {
5008
$documentation: "A `const` statement"
5009
}, AST_Definitions);
5010
5011
var AST_VarDef = DEFNODE("VarDef", "name value", function AST_VarDef(props) {
5012
if (props) {
5013
this.name = props.name;
5014
this.value = props.value;
5015
this.start = props.start;
5016
this.end = props.end;
5017
}
5018
5019
this.flags = 0;
5020
}, {
5021
$documentation: "A variable declaration; only appears in a AST_Definitions node",
5022
$propdoc: {
5023
name: "[AST_Destructuring|AST_SymbolConst|AST_SymbolLet|AST_SymbolVar] name of the variable",
5024
value: "[AST_Node?] initializer, or null of there's no initializer"
5025
},
5026
_walk: function(visitor) {
5027
return visitor._visit(this, function() {
5028
this.name._walk(visitor);
5029
if (this.value) this.value._walk(visitor);
5030
});
5031
},
5032
_children_backwards(push) {
5033
if (this.value) push(this.value);
5034
push(this.name);
5035
},
5036
declarations_as_names() {
5037
if (this.name instanceof AST_SymbolDeclaration) {
5038
return [this];
5039
} else {
5040
return this.name.all_symbols();
5041
}
5042
}
5043
});
5044
5045
var AST_NameMapping = DEFNODE("NameMapping", "foreign_name name", function AST_NameMapping(props) {
5046
if (props) {
5047
this.foreign_name = props.foreign_name;
5048
this.name = props.name;
5049
this.start = props.start;
5050
this.end = props.end;
5051
}
5052
5053
this.flags = 0;
5054
}, {
5055
$documentation: "The part of the export/import statement that declare names from a module.",
5056
$propdoc: {
5057
foreign_name: "[AST_SymbolExportForeign|AST_SymbolImportForeign] The name being exported/imported (as specified in the module)",
5058
name: "[AST_SymbolExport|AST_SymbolImport] The name as it is visible to this module."
5059
},
5060
_walk: function (visitor) {
5061
return visitor._visit(this, function() {
5062
this.foreign_name._walk(visitor);
5063
this.name._walk(visitor);
5064
});
5065
},
5066
_children_backwards(push) {
5067
push(this.name);
5068
push(this.foreign_name);
5069
},
5070
});
5071
5072
var AST_Import = DEFNODE(
5073
"Import",
5074
"imported_name imported_names module_name assert_clause",
5075
function AST_Import(props) {
5076
if (props) {
5077
this.imported_name = props.imported_name;
5078
this.imported_names = props.imported_names;
5079
this.module_name = props.module_name;
5080
this.assert_clause = props.assert_clause;
5081
this.start = props.start;
5082
this.end = props.end;
5083
}
5084
5085
this.flags = 0;
5086
},
5087
{
5088
$documentation: "An `import` statement",
5089
$propdoc: {
5090
imported_name: "[AST_SymbolImport] The name of the variable holding the module's default export.",
5091
imported_names: "[AST_NameMapping*] The names of non-default imported variables",
5092
module_name: "[AST_String] String literal describing where this module came from",
5093
assert_clause: "[AST_Object?] The import assertion"
5094
},
5095
_walk: function(visitor) {
5096
return visitor._visit(this, function() {
5097
if (this.imported_name) {
5098
this.imported_name._walk(visitor);
5099
}
5100
if (this.imported_names) {
5101
this.imported_names.forEach(function(name_import) {
5102
name_import._walk(visitor);
5103
});
5104
}
5105
this.module_name._walk(visitor);
5106
});
5107
},
5108
_children_backwards(push) {
5109
push(this.module_name);
5110
if (this.imported_names) {
5111
let i = this.imported_names.length;
5112
while (i--) push(this.imported_names[i]);
5113
}
5114
if (this.imported_name) push(this.imported_name);
5115
},
5116
}
5117
);
5118
5119
var AST_ImportMeta = DEFNODE("ImportMeta", null, function AST_ImportMeta(props) {
5120
if (props) {
5121
this.start = props.start;
5122
this.end = props.end;
5123
}
5124
5125
this.flags = 0;
5126
}, {
5127
$documentation: "A reference to import.meta",
5128
});
5129
5130
var AST_Export = DEFNODE(
5131
"Export",
5132
"exported_definition exported_value is_default exported_names module_name assert_clause",
5133
function AST_Export(props) {
5134
if (props) {
5135
this.exported_definition = props.exported_definition;
5136
this.exported_value = props.exported_value;
5137
this.is_default = props.is_default;
5138
this.exported_names = props.exported_names;
5139
this.module_name = props.module_name;
5140
this.assert_clause = props.assert_clause;
5141
this.start = props.start;
5142
this.end = props.end;
5143
}
5144
5145
this.flags = 0;
5146
},
5147
{
5148
$documentation: "An `export` statement",
5149
$propdoc: {
5150
exported_definition: "[AST_Defun|AST_Definitions|AST_DefClass?] An exported definition",
5151
exported_value: "[AST_Node?] An exported value",
5152
exported_names: "[AST_NameMapping*?] List of exported names",
5153
module_name: "[AST_String?] Name of the file to load exports from",
5154
is_default: "[Boolean] Whether this is the default exported value of this module",
5155
assert_clause: "[AST_Object?] The import assertion"
5156
},
5157
_walk: function (visitor) {
5158
return visitor._visit(this, function () {
5159
if (this.exported_definition) {
5160
this.exported_definition._walk(visitor);
5161
}
5162
if (this.exported_value) {
5163
this.exported_value._walk(visitor);
5164
}
5165
if (this.exported_names) {
5166
this.exported_names.forEach(function(name_export) {
5167
name_export._walk(visitor);
5168
});
5169
}
5170
if (this.module_name) {
5171
this.module_name._walk(visitor);
5172
}
5173
});
5174
},
5175
_children_backwards(push) {
5176
if (this.module_name) push(this.module_name);
5177
if (this.exported_names) {
5178
let i = this.exported_names.length;
5179
while (i--) push(this.exported_names[i]);
5180
}
5181
if (this.exported_value) push(this.exported_value);
5182
if (this.exported_definition) push(this.exported_definition);
5183
}
5184
},
5185
AST_Statement
5186
);
5187
5188
/* -----[ OTHER ]----- */
5189
5190
var AST_Call = DEFNODE(
5191
"Call",
5192
"expression args optional _annotations",
5193
function AST_Call(props) {
5194
if (props) {
5195
this.expression = props.expression;
5196
this.args = props.args;
5197
this.optional = props.optional;
5198
this._annotations = props._annotations;
5199
this.start = props.start;
5200
this.end = props.end;
5201
this.initialize();
5202
}
5203
5204
this.flags = 0;
5205
},
5206
{
5207
$documentation: "A function call expression",
5208
$propdoc: {
5209
expression: "[AST_Node] expression to invoke as function",
5210
args: "[AST_Node*] array of arguments",
5211
optional: "[boolean] whether this is an optional call (IE ?.() )",
5212
_annotations: "[number] bitfield containing information about the call"
5213
},
5214
initialize() {
5215
if (this._annotations == null) this._annotations = 0;
5216
},
5217
_walk(visitor) {
5218
return visitor._visit(this, function() {
5219
var args = this.args;
5220
for (var i = 0, len = args.length; i < len; i++) {
5221
args[i]._walk(visitor);
5222
}
5223
this.expression._walk(visitor); // TODO why do we need to crawl this last?
5224
});
5225
},
5226
_children_backwards(push) {
5227
let i = this.args.length;
5228
while (i--) push(this.args[i]);
5229
push(this.expression);
5230
},
5231
}
5232
);
5233
5234
var AST_New = DEFNODE("New", null, function AST_New(props) {
5235
if (props) {
5236
this.expression = props.expression;
5237
this.args = props.args;
5238
this.optional = props.optional;
5239
this._annotations = props._annotations;
5240
this.start = props.start;
5241
this.end = props.end;
5242
this.initialize();
5243
}
5244
5245
this.flags = 0;
5246
}, {
5247
$documentation: "An object instantiation. Derives from a function call since it has exactly the same properties"
5248
}, AST_Call);
5249
5250
var AST_Sequence = DEFNODE("Sequence", "expressions", function AST_Sequence(props) {
5251
if (props) {
5252
this.expressions = props.expressions;
5253
this.start = props.start;
5254
this.end = props.end;
5255
}
5256
5257
this.flags = 0;
5258
}, {
5259
$documentation: "A sequence expression (comma-separated expressions)",
5260
$propdoc: {
5261
expressions: "[AST_Node*] array of expressions (at least two)"
5262
},
5263
_walk: function(visitor) {
5264
return visitor._visit(this, function() {
5265
this.expressions.forEach(function(node) {
5266
node._walk(visitor);
5267
});
5268
});
5269
},
5270
_children_backwards(push) {
5271
let i = this.expressions.length;
5272
while (i--) push(this.expressions[i]);
5273
},
5274
});
5275
5276
var AST_PropAccess = DEFNODE(
5277
"PropAccess",
5278
"expression property optional",
5279
function AST_PropAccess(props) {
5280
if (props) {
5281
this.expression = props.expression;
5282
this.property = props.property;
5283
this.optional = props.optional;
5284
this.start = props.start;
5285
this.end = props.end;
5286
}
5287
5288
this.flags = 0;
5289
},
5290
{
5291
$documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`",
5292
$propdoc: {
5293
expression: "[AST_Node] the “container” expression",
5294
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",
5295
5296
optional: "[boolean] whether this is an optional property access (IE ?.)"
5297
}
5298
}
5299
);
5300
5301
var AST_Dot = DEFNODE("Dot", "quote", function AST_Dot(props) {
5302
if (props) {
5303
this.quote = props.quote;
5304
this.expression = props.expression;
5305
this.property = props.property;
5306
this.optional = props.optional;
5307
this.start = props.start;
5308
this.end = props.end;
5309
}
5310
5311
this.flags = 0;
5312
}, {
5313
$documentation: "A dotted property access expression",
5314
$propdoc: {
5315
quote: "[string] the original quote character when transformed from AST_Sub",
5316
},
5317
_walk: function(visitor) {
5318
return visitor._visit(this, function() {
5319
this.expression._walk(visitor);
5320
});
5321
},
5322
_children_backwards(push) {
5323
push(this.expression);
5324
},
5325
}, AST_PropAccess);
5326
5327
var AST_DotHash = DEFNODE("DotHash", "", function AST_DotHash(props) {
5328
if (props) {
5329
this.expression = props.expression;
5330
this.property = props.property;
5331
this.optional = props.optional;
5332
this.start = props.start;
5333
this.end = props.end;
5334
}
5335
5336
this.flags = 0;
5337
}, {
5338
$documentation: "A dotted property access to a private property",
5339
_walk: function(visitor) {
5340
return visitor._visit(this, function() {
5341
this.expression._walk(visitor);
5342
});
5343
},
5344
_children_backwards(push) {
5345
push(this.expression);
5346
},
5347
}, AST_PropAccess);
5348
5349
var AST_Sub = DEFNODE("Sub", null, function AST_Sub(props) {
5350
if (props) {
5351
this.expression = props.expression;
5352
this.property = props.property;
5353
this.optional = props.optional;
5354
this.start = props.start;
5355
this.end = props.end;
5356
}
5357
5358
this.flags = 0;
5359
}, {
5360
$documentation: "Index-style property access, i.e. `a[\"foo\"]`",
5361
_walk: function(visitor) {
5362
return visitor._visit(this, function() {
5363
this.expression._walk(visitor);
5364
this.property._walk(visitor);
5365
});
5366
},
5367
_children_backwards(push) {
5368
push(this.property);
5369
push(this.expression);
5370
},
5371
}, AST_PropAccess);
5372
5373
var AST_Chain = DEFNODE("Chain", "expression", function AST_Chain(props) {
5374
if (props) {
5375
this.expression = props.expression;
5376
this.start = props.start;
5377
this.end = props.end;
5378
}
5379
5380
this.flags = 0;
5381
}, {
5382
$documentation: "A chain expression like a?.b?.(c)?.[d]",
5383
$propdoc: {
5384
expression: "[AST_Call|AST_Dot|AST_DotHash|AST_Sub] chain element."
5385
},
5386
_walk: function (visitor) {
5387
return visitor._visit(this, function() {
5388
this.expression._walk(visitor);
5389
});
5390
},
5391
_children_backwards(push) {
5392
push(this.expression);
5393
},
5394
});
5395
5396
var AST_Unary = DEFNODE("Unary", "operator expression", function AST_Unary(props) {
5397
if (props) {
5398
this.operator = props.operator;
5399
this.expression = props.expression;
5400
this.start = props.start;
5401
this.end = props.end;
5402
}
5403
5404
this.flags = 0;
5405
}, {
5406
$documentation: "Base class for unary expressions",
5407
$propdoc: {
5408
operator: "[string] the operator",
5409
expression: "[AST_Node] expression that this unary operator applies to"
5410
},
5411
_walk: function(visitor) {
5412
return visitor._visit(this, function() {
5413
this.expression._walk(visitor);
5414
});
5415
},
5416
_children_backwards(push) {
5417
push(this.expression);
5418
},
5419
});
5420
5421
var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, function AST_UnaryPrefix(props) {
5422
if (props) {
5423
this.operator = props.operator;
5424
this.expression = props.expression;
5425
this.start = props.start;
5426
this.end = props.end;
5427
}
5428
5429
this.flags = 0;
5430
}, {
5431
$documentation: "Unary prefix expression, i.e. `typeof i` or `++i`"
5432
}, AST_Unary);
5433
5434
var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, function AST_UnaryPostfix(props) {
5435
if (props) {
5436
this.operator = props.operator;
5437
this.expression = props.expression;
5438
this.start = props.start;
5439
this.end = props.end;
5440
}
5441
5442
this.flags = 0;
5443
}, {
5444
$documentation: "Unary postfix expression, i.e. `i++`"
5445
}, AST_Unary);
5446
5447
var AST_Binary = DEFNODE("Binary", "operator left right", function AST_Binary(props) {
5448
if (props) {
5449
this.operator = props.operator;
5450
this.left = props.left;
5451
this.right = props.right;
5452
this.start = props.start;
5453
this.end = props.end;
5454
}
5455
5456
this.flags = 0;
5457
}, {
5458
$documentation: "Binary expression, i.e. `a + b`",
5459
$propdoc: {
5460
left: "[AST_Node] left-hand side expression",
5461
operator: "[string] the operator",
5462
right: "[AST_Node] right-hand side expression"
5463
},
5464
_walk: function(visitor) {
5465
return visitor._visit(this, function() {
5466
this.left._walk(visitor);
5467
this.right._walk(visitor);
5468
});
5469
},
5470
_children_backwards(push) {
5471
push(this.right);
5472
push(this.left);
5473
},
5474
});
5475
5476
var AST_Conditional = DEFNODE(
5477
"Conditional",
5478
"condition consequent alternative",
5479
function AST_Conditional(props) {
5480
if (props) {
5481
this.condition = props.condition;
5482
this.consequent = props.consequent;
5483
this.alternative = props.alternative;
5484
this.start = props.start;
5485
this.end = props.end;
5486
}
5487
5488
this.flags = 0;
5489
},
5490
{
5491
$documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`",
5492
$propdoc: {
5493
condition: "[AST_Node]",
5494
consequent: "[AST_Node]",
5495
alternative: "[AST_Node]"
5496
},
5497
_walk: function(visitor) {
5498
return visitor._visit(this, function() {
5499
this.condition._walk(visitor);
5500
this.consequent._walk(visitor);
5501
this.alternative._walk(visitor);
5502
});
5503
},
5504
_children_backwards(push) {
5505
push(this.alternative);
5506
push(this.consequent);
5507
push(this.condition);
5508
},
5509
}
5510
);
5511
5512
var AST_Assign = DEFNODE("Assign", "logical", function AST_Assign(props) {
5513
if (props) {
5514
this.logical = props.logical;
5515
this.operator = props.operator;
5516
this.left = props.left;
5517
this.right = props.right;
5518
this.start = props.start;
5519
this.end = props.end;
5520
}
5521
5522
this.flags = 0;
5523
}, {
5524
$documentation: "An assignment expression — `a = b + 5`",
5525
$propdoc: {
5526
logical: "Whether it's a logical assignment"
5527
}
5528
}, AST_Binary);
5529
5530
var AST_DefaultAssign = DEFNODE("DefaultAssign", null, function AST_DefaultAssign(props) {
5531
if (props) {
5532
this.operator = props.operator;
5533
this.left = props.left;
5534
this.right = props.right;
5535
this.start = props.start;
5536
this.end = props.end;
5537
}
5538
5539
this.flags = 0;
5540
}, {
5541
$documentation: "A default assignment expression like in `(a = 3) => a`"
5542
}, AST_Binary);
5543
5544
/* -----[ LITERALS ]----- */
5545
5546
var AST_Array = DEFNODE("Array", "elements", function AST_Array(props) {
5547
if (props) {
5548
this.elements = props.elements;
5549
this.start = props.start;
5550
this.end = props.end;
5551
}
5552
5553
this.flags = 0;
5554
}, {
5555
$documentation: "An array literal",
5556
$propdoc: {
5557
elements: "[AST_Node*] array of elements"
5558
},
5559
_walk: function(visitor) {
5560
return visitor._visit(this, function() {
5561
var elements = this.elements;
5562
for (var i = 0, len = elements.length; i < len; i++) {
5563
elements[i]._walk(visitor);
5564
}
5565
});
5566
},
5567
_children_backwards(push) {
5568
let i = this.elements.length;
5569
while (i--) push(this.elements[i]);
5570
},
5571
});
5572
5573
var AST_Object = DEFNODE("Object", "properties", function AST_Object(props) {
5574
if (props) {
5575
this.properties = props.properties;
5576
this.start = props.start;
5577
this.end = props.end;
5578
}
5579
5580
this.flags = 0;
5581
}, {
5582
$documentation: "An object literal",
5583
$propdoc: {
5584
properties: "[AST_ObjectProperty*] array of properties"
5585
},
5586
_walk: function(visitor) {
5587
return visitor._visit(this, function() {
5588
var properties = this.properties;
5589
for (var i = 0, len = properties.length; i < len; i++) {
5590
properties[i]._walk(visitor);
5591
}
5592
});
5593
},
5594
_children_backwards(push) {
5595
let i = this.properties.length;
5596
while (i--) push(this.properties[i]);
5597
},
5598
});
5599
5600
var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", function AST_ObjectProperty(props) {
5601
if (props) {
5602
this.key = props.key;
5603
this.value = props.value;
5604
this.start = props.start;
5605
this.end = props.end;
5606
this._annotations = props._annotations;
5607
}
5608
5609
this.flags = 0;
5610
}, {
5611
$documentation: "Base class for literal object properties",
5612
$propdoc: {
5613
key: "[string|AST_Node] property name. For ObjectKeyVal this is a string. For getters, setters and computed property this is an AST_Node.",
5614
value: "[AST_Node] property value. For getters and setters this is an AST_Accessor."
5615
},
5616
_walk: function(visitor) {
5617
return visitor._visit(this, function() {
5618
if (this.key instanceof AST_Node)
5619
this.key._walk(visitor);
5620
this.value._walk(visitor);
5621
});
5622
},
5623
_children_backwards(push) {
5624
push(this.value);
5625
if (this.key instanceof AST_Node) push(this.key);
5626
}
5627
});
5628
5629
var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote", function AST_ObjectKeyVal(props) {
5630
if (props) {
5631
this.quote = props.quote;
5632
this.key = props.key;
5633
this.value = props.value;
5634
this.start = props.start;
5635
this.end = props.end;
5636
this._annotations = props._annotations;
5637
}
5638
5639
this.flags = 0;
5640
}, {
5641
$documentation: "A key: value object property",
5642
$propdoc: {
5643
quote: "[string] the original quote character"
5644
},
5645
computed_key() {
5646
return this.key instanceof AST_Node;
5647
}
5648
}, AST_ObjectProperty);
5649
5650
var AST_PrivateSetter = DEFNODE("PrivateSetter", "static", function AST_PrivateSetter(props) {
5651
if (props) {
5652
this.static = props.static;
5653
this.key = props.key;
5654
this.value = props.value;
5655
this.start = props.start;
5656
this.end = props.end;
5657
}
5658
5659
this.flags = 0;
5660
}, {
5661
$propdoc: {
5662
static: "[boolean] whether this is a static private setter"
5663
},
5664
$documentation: "A private setter property",
5665
computed_key() {
5666
return false;
5667
}
5668
}, AST_ObjectProperty);
5669
5670
var AST_PrivateGetter = DEFNODE("PrivateGetter", "static", function AST_PrivateGetter(props) {
5671
if (props) {
5672
this.static = props.static;
5673
this.key = props.key;
5674
this.value = props.value;
5675
this.start = props.start;
5676
this.end = props.end;
5677
}
5678
5679
this.flags = 0;
5680
}, {
5681
$propdoc: {
5682
static: "[boolean] whether this is a static private getter"
5683
},
5684
$documentation: "A private getter property",
5685
computed_key() {
5686
return false;
5687
}
5688
}, AST_ObjectProperty);
5689
5690
var AST_ObjectSetter = DEFNODE("ObjectSetter", "quote static", function AST_ObjectSetter(props) {
5691
if (props) {
5692
this.quote = props.quote;
5693
this.static = props.static;
5694
this.key = props.key;
5695
this.value = props.value;
5696
this.start = props.start;
5697
this.end = props.end;
5698
this._annotations = props._annotations;
5699
}
5700
5701
this.flags = 0;
5702
}, {
5703
$propdoc: {
5704
quote: "[string|undefined] the original quote character, if any",
5705
static: "[boolean] whether this is a static setter (classes only)"
5706
},
5707
$documentation: "An object setter property",
5708
computed_key() {
5709
return !(this.key instanceof AST_SymbolMethod);
5710
}
5711
}, AST_ObjectProperty);
5712
5713
var AST_ObjectGetter = DEFNODE("ObjectGetter", "quote static", function AST_ObjectGetter(props) {
5714
if (props) {
5715
this.quote = props.quote;
5716
this.static = props.static;
5717
this.key = props.key;
5718
this.value = props.value;
5719
this.start = props.start;
5720
this.end = props.end;
5721
this._annotations = props._annotations;
5722
}
5723
5724
this.flags = 0;
5725
}, {
5726
$propdoc: {
5727
quote: "[string|undefined] the original quote character, if any",
5728
static: "[boolean] whether this is a static getter (classes only)"
5729
},
5730
$documentation: "An object getter property",
5731
computed_key() {
5732
return !(this.key instanceof AST_SymbolMethod);
5733
}
5734
}, AST_ObjectProperty);
5735
5736
var AST_ConciseMethod = DEFNODE(
5737
"ConciseMethod",
5738
"quote static is_generator async",
5739
function AST_ConciseMethod(props) {
5740
if (props) {
5741
this.quote = props.quote;
5742
this.static = props.static;
5743
this.is_generator = props.is_generator;
5744
this.async = props.async;
5745
this.key = props.key;
5746
this.value = props.value;
5747
this.start = props.start;
5748
this.end = props.end;
5749
this._annotations = props._annotations;
5750
}
5751
5752
this.flags = 0;
5753
},
5754
{
5755
$propdoc: {
5756
quote: "[string|undefined] the original quote character, if any",
5757
static: "[boolean] is this method static (classes only)",
5758
is_generator: "[boolean] is this a generator method",
5759
async: "[boolean] is this method async",
5760
},
5761
$documentation: "An ES6 concise method inside an object or class",
5762
computed_key() {
5763
return !(this.key instanceof AST_SymbolMethod);
5764
}
5765
},
5766
AST_ObjectProperty
5767
);
5768
5769
var AST_PrivateMethod = DEFNODE("PrivateMethod", "", function AST_PrivateMethod(props) {
5770
if (props) {
5771
this.quote = props.quote;
5772
this.static = props.static;
5773
this.is_generator = props.is_generator;
5774
this.async = props.async;
5775
this.key = props.key;
5776
this.value = props.value;
5777
this.start = props.start;
5778
this.end = props.end;
5779
}
5780
5781
this.flags = 0;
5782
}, {
5783
$documentation: "A private class method inside a class",
5784
}, AST_ConciseMethod);
5785
5786
var AST_Class = DEFNODE("Class", "name extends properties", function AST_Class(props) {
5787
if (props) {
5788
this.name = props.name;
5789
this.extends = props.extends;
5790
this.properties = props.properties;
5791
this.variables = props.variables;
5792
this.uses_with = props.uses_with;
5793
this.uses_eval = props.uses_eval;
5794
this.parent_scope = props.parent_scope;
5795
this.enclosed = props.enclosed;
5796
this.cname = props.cname;
5797
this.body = props.body;
5798
this.block_scope = props.block_scope;
5799
this.start = props.start;
5800
this.end = props.end;
5801
}
5802
5803
this.flags = 0;
5804
}, {
5805
$propdoc: {
5806
name: "[AST_SymbolClass|AST_SymbolDefClass?] optional class name.",
5807
extends: "[AST_Node]? optional parent class",
5808
properties: "[AST_ObjectProperty*] array of properties"
5809
},
5810
$documentation: "An ES6 class",
5811
_walk: function(visitor) {
5812
return visitor._visit(this, function() {
5813
if (this.name) {
5814
this.name._walk(visitor);
5815
}
5816
if (this.extends) {
5817
this.extends._walk(visitor);
5818
}
5819
this.properties.forEach((prop) => prop._walk(visitor));
5820
});
5821
},
5822
_children_backwards(push) {
5823
let i = this.properties.length;
5824
while (i--) push(this.properties[i]);
5825
if (this.extends) push(this.extends);
5826
if (this.name) push(this.name);
5827
},
5828
/** go through the bits that are executed instantly, not when the class is `new`'d. Doesn't walk the name. */
5829
visit_nondeferred_class_parts(visitor) {
5830
if (this.extends) {
5831
this.extends._walk(visitor);
5832
}
5833
this.properties.forEach((prop) => {
5834
if (prop instanceof AST_ClassStaticBlock) {
5835
prop._walk(visitor);
5836
return;
5837
}
5838
if (prop.computed_key()) {
5839
visitor.push(prop);
5840
prop.key._walk(visitor);
5841
visitor.pop();
5842
}
5843
if ((prop instanceof AST_ClassPrivateProperty || prop instanceof AST_ClassProperty) && prop.static && prop.value) {
5844
visitor.push(prop);
5845
prop.value._walk(visitor);
5846
visitor.pop();
5847
}
5848
});
5849
},
5850
/** go through the bits that are executed later, when the class is `new`'d or a static method is called */
5851
visit_deferred_class_parts(visitor) {
5852
this.properties.forEach((prop) => {
5853
if (prop instanceof AST_ConciseMethod) {
5854
prop.walk(visitor);
5855
} else if (prop instanceof AST_ClassProperty && !prop.static && prop.value) {
5856
visitor.push(prop);
5857
prop.value._walk(visitor);
5858
visitor.pop();
5859
}
5860
});
5861
},
5862
}, AST_Scope /* TODO a class might have a scope but it's not a scope */);
5863
5864
var AST_ClassProperty = DEFNODE("ClassProperty", "static quote", function AST_ClassProperty(props) {
5865
if (props) {
5866
this.static = props.static;
5867
this.quote = props.quote;
5868
this.key = props.key;
5869
this.value = props.value;
5870
this.start = props.start;
5871
this.end = props.end;
5872
this._annotations = props._annotations;
5873
}
5874
5875
this.flags = 0;
5876
}, {
5877
$documentation: "A class property",
5878
$propdoc: {
5879
static: "[boolean] whether this is a static key",
5880
quote: "[string] which quote is being used"
5881
},
5882
_walk: function(visitor) {
5883
return visitor._visit(this, function() {
5884
if (this.key instanceof AST_Node)
5885
this.key._walk(visitor);
5886
if (this.value instanceof AST_Node)
5887
this.value._walk(visitor);
5888
});
5889
},
5890
_children_backwards(push) {
5891
if (this.value instanceof AST_Node) push(this.value);
5892
if (this.key instanceof AST_Node) push(this.key);
5893
},
5894
computed_key() {
5895
return !(this.key instanceof AST_SymbolClassProperty);
5896
}
5897
}, AST_ObjectProperty);
5898
5899
var AST_ClassPrivateProperty = DEFNODE("ClassPrivateProperty", "", function AST_ClassPrivateProperty(props) {
5900
if (props) {
5901
this.static = props.static;
5902
this.quote = props.quote;
5903
this.key = props.key;
5904
this.value = props.value;
5905
this.start = props.start;
5906
this.end = props.end;
5907
}
5908
5909
this.flags = 0;
5910
}, {
5911
$documentation: "A class property for a private property",
5912
}, AST_ClassProperty);
5913
5914
var AST_PrivateIn = DEFNODE("PrivateIn", "key value", function AST_PrivateIn(props) {
5915
if (props) {
5916
this.key = props.key;
5917
this.value = props.value;
5918
this.start = props.start;
5919
this.end = props.end;
5920
}
5921
5922
this.flags = 0;
5923
}, {
5924
$documentation: "An `in` binop when the key is private, eg #x in this",
5925
_walk: function(visitor) {
5926
return visitor._visit(this, function() {
5927
this.key._walk(visitor);
5928
this.value._walk(visitor);
5929
});
5930
},
5931
_children_backwards(push) {
5932
push(this.value);
5933
push(this.key);
5934
},
5935
});
5936
5937
var AST_DefClass = DEFNODE("DefClass", null, function AST_DefClass(props) {
5938
if (props) {
5939
this.name = props.name;
5940
this.extends = props.extends;
5941
this.properties = props.properties;
5942
this.variables = props.variables;
5943
this.uses_with = props.uses_with;
5944
this.uses_eval = props.uses_eval;
5945
this.parent_scope = props.parent_scope;
5946
this.enclosed = props.enclosed;
5947
this.cname = props.cname;
5948
this.body = props.body;
5949
this.block_scope = props.block_scope;
5950
this.start = props.start;
5951
this.end = props.end;
5952
}
5953
5954
this.flags = 0;
5955
}, {
5956
$documentation: "A class definition",
5957
}, AST_Class);
5958
5959
var AST_ClassStaticBlock = DEFNODE("ClassStaticBlock", "body block_scope", function AST_ClassStaticBlock (props) {
5960
this.body = props.body;
5961
this.block_scope = props.block_scope;
5962
this.start = props.start;
5963
this.end = props.end;
5964
}, {
5965
$documentation: "A block containing statements to be executed in the context of the class",
5966
$propdoc: {
5967
body: "[AST_Statement*] an array of statements",
5968
},
5969
_walk: function(visitor) {
5970
return visitor._visit(this, function() {
5971
walk_body(this, visitor);
5972
});
5973
},
5974
_children_backwards(push) {
5975
let i = this.body.length;
5976
while (i--) push(this.body[i]);
5977
},
5978
clone: clone_block_scope,
5979
computed_key: () => false
5980
}, AST_Scope);
5981
5982
var AST_ClassExpression = DEFNODE("ClassExpression", null, function AST_ClassExpression(props) {
5983
if (props) {
5984
this.name = props.name;
5985
this.extends = props.extends;
5986
this.properties = props.properties;
5987
this.variables = props.variables;
5988
this.uses_with = props.uses_with;
5989
this.uses_eval = props.uses_eval;
5990
this.parent_scope = props.parent_scope;
5991
this.enclosed = props.enclosed;
5992
this.cname = props.cname;
5993
this.body = props.body;
5994
this.block_scope = props.block_scope;
5995
this.start = props.start;
5996
this.end = props.end;
5997
}
5998
5999
this.flags = 0;
6000
}, {
6001
$documentation: "A class expression."
6002
}, AST_Class);
6003
6004
var AST_Symbol = DEFNODE("Symbol", "scope name thedef", function AST_Symbol(props) {
6005
if (props) {
6006
this.scope = props.scope;
6007
this.name = props.name;
6008
this.thedef = props.thedef;
6009
this.start = props.start;
6010
this.end = props.end;
6011
}
6012
6013
this.flags = 0;
6014
}, {
6015
$propdoc: {
6016
name: "[string] name of this symbol",
6017
scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
6018
thedef: "[SymbolDef/S] the definition of this symbol"
6019
},
6020
$documentation: "Base class for all symbols"
6021
});
6022
6023
var AST_NewTarget = DEFNODE("NewTarget", null, function AST_NewTarget(props) {
6024
if (props) {
6025
this.start = props.start;
6026
this.end = props.end;
6027
}
6028
6029
this.flags = 0;
6030
}, {
6031
$documentation: "A reference to new.target"
6032
});
6033
6034
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", function AST_SymbolDeclaration(props) {
6035
if (props) {
6036
this.init = props.init;
6037
this.scope = props.scope;
6038
this.name = props.name;
6039
this.thedef = props.thedef;
6040
this.start = props.start;
6041
this.end = props.end;
6042
}
6043
6044
this.flags = 0;
6045
}, {
6046
$documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
6047
}, AST_Symbol);
6048
6049
var AST_SymbolVar = DEFNODE("SymbolVar", null, function AST_SymbolVar(props) {
6050
if (props) {
6051
this.init = props.init;
6052
this.scope = props.scope;
6053
this.name = props.name;
6054
this.thedef = props.thedef;
6055
this.start = props.start;
6056
this.end = props.end;
6057
}
6058
6059
this.flags = 0;
6060
}, {
6061
$documentation: "Symbol defining a variable",
6062
}, AST_SymbolDeclaration);
6063
6064
var AST_SymbolBlockDeclaration = DEFNODE(
6065
"SymbolBlockDeclaration",
6066
null,
6067
function AST_SymbolBlockDeclaration(props) {
6068
if (props) {
6069
this.init = props.init;
6070
this.scope = props.scope;
6071
this.name = props.name;
6072
this.thedef = props.thedef;
6073
this.start = props.start;
6074
this.end = props.end;
6075
}
6076
6077
this.flags = 0;
6078
},
6079
{
6080
$documentation: "Base class for block-scoped declaration symbols"
6081
},
6082
AST_SymbolDeclaration
6083
);
6084
6085
var AST_SymbolConst = DEFNODE("SymbolConst", null, function AST_SymbolConst(props) {
6086
if (props) {
6087
this.init = props.init;
6088
this.scope = props.scope;
6089
this.name = props.name;
6090
this.thedef = props.thedef;
6091
this.start = props.start;
6092
this.end = props.end;
6093
}
6094
6095
this.flags = 0;
6096
}, {
6097
$documentation: "A constant declaration"
6098
}, AST_SymbolBlockDeclaration);
6099
6100
var AST_SymbolLet = DEFNODE("SymbolLet", null, function AST_SymbolLet(props) {
6101
if (props) {
6102
this.init = props.init;
6103
this.scope = props.scope;
6104
this.name = props.name;
6105
this.thedef = props.thedef;
6106
this.start = props.start;
6107
this.end = props.end;
6108
}
6109
6110
this.flags = 0;
6111
}, {
6112
$documentation: "A block-scoped `let` declaration"
6113
}, AST_SymbolBlockDeclaration);
6114
6115
var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, function AST_SymbolFunarg(props) {
6116
if (props) {
6117
this.init = props.init;
6118
this.scope = props.scope;
6119
this.name = props.name;
6120
this.thedef = props.thedef;
6121
this.start = props.start;
6122
this.end = props.end;
6123
}
6124
6125
this.flags = 0;
6126
}, {
6127
$documentation: "Symbol naming a function argument",
6128
}, AST_SymbolVar);
6129
6130
var AST_SymbolDefun = DEFNODE("SymbolDefun", null, function AST_SymbolDefun(props) {
6131
if (props) {
6132
this.init = props.init;
6133
this.scope = props.scope;
6134
this.name = props.name;
6135
this.thedef = props.thedef;
6136
this.start = props.start;
6137
this.end = props.end;
6138
}
6139
6140
this.flags = 0;
6141
}, {
6142
$documentation: "Symbol defining a function",
6143
}, AST_SymbolDeclaration);
6144
6145
var AST_SymbolMethod = DEFNODE("SymbolMethod", null, function AST_SymbolMethod(props) {
6146
if (props) {
6147
this.scope = props.scope;
6148
this.name = props.name;
6149
this.thedef = props.thedef;
6150
this.start = props.start;
6151
this.end = props.end;
6152
}
6153
6154
this.flags = 0;
6155
}, {
6156
$documentation: "Symbol in an object defining a method",
6157
}, AST_Symbol);
6158
6159
var AST_SymbolClassProperty = DEFNODE("SymbolClassProperty", null, function AST_SymbolClassProperty(props) {
6160
if (props) {
6161
this.scope = props.scope;
6162
this.name = props.name;
6163
this.thedef = props.thedef;
6164
this.start = props.start;
6165
this.end = props.end;
6166
}
6167
6168
this.flags = 0;
6169
}, {
6170
$documentation: "Symbol for a class property",
6171
}, AST_Symbol);
6172
6173
var AST_SymbolLambda = DEFNODE("SymbolLambda", null, function AST_SymbolLambda(props) {
6174
if (props) {
6175
this.init = props.init;
6176
this.scope = props.scope;
6177
this.name = props.name;
6178
this.thedef = props.thedef;
6179
this.start = props.start;
6180
this.end = props.end;
6181
}
6182
6183
this.flags = 0;
6184
}, {
6185
$documentation: "Symbol naming a function expression",
6186
}, AST_SymbolDeclaration);
6187
6188
var AST_SymbolDefClass = DEFNODE("SymbolDefClass", null, function AST_SymbolDefClass(props) {
6189
if (props) {
6190
this.init = props.init;
6191
this.scope = props.scope;
6192
this.name = props.name;
6193
this.thedef = props.thedef;
6194
this.start = props.start;
6195
this.end = props.end;
6196
}
6197
6198
this.flags = 0;
6199
}, {
6200
$documentation: "Symbol naming a class's name in a class declaration. Lexically scoped to its containing scope, and accessible within the class."
6201
}, AST_SymbolBlockDeclaration);
6202
6203
var AST_SymbolClass = DEFNODE("SymbolClass", null, function AST_SymbolClass(props) {
6204
if (props) {
6205
this.init = props.init;
6206
this.scope = props.scope;
6207
this.name = props.name;
6208
this.thedef = props.thedef;
6209
this.start = props.start;
6210
this.end = props.end;
6211
}
6212
6213
this.flags = 0;
6214
}, {
6215
$documentation: "Symbol naming a class's name. Lexically scoped to the class."
6216
}, AST_SymbolDeclaration);
6217
6218
var AST_SymbolCatch = DEFNODE("SymbolCatch", null, function AST_SymbolCatch(props) {
6219
if (props) {
6220
this.init = props.init;
6221
this.scope = props.scope;
6222
this.name = props.name;
6223
this.thedef = props.thedef;
6224
this.start = props.start;
6225
this.end = props.end;
6226
}
6227
6228
this.flags = 0;
6229
}, {
6230
$documentation: "Symbol naming the exception in catch",
6231
}, AST_SymbolBlockDeclaration);
6232
6233
var AST_SymbolImport = DEFNODE("SymbolImport", null, function AST_SymbolImport(props) {
6234
if (props) {
6235
this.init = props.init;
6236
this.scope = props.scope;
6237
this.name = props.name;
6238
this.thedef = props.thedef;
6239
this.start = props.start;
6240
this.end = props.end;
6241
}
6242
6243
this.flags = 0;
6244
}, {
6245
$documentation: "Symbol referring to an imported name",
6246
}, AST_SymbolBlockDeclaration);
6247
6248
var AST_SymbolImportForeign = DEFNODE("SymbolImportForeign", null, function AST_SymbolImportForeign(props) {
6249
if (props) {
6250
this.scope = props.scope;
6251
this.name = props.name;
6252
this.thedef = props.thedef;
6253
this.quote = props.quote;
6254
this.start = props.start;
6255
this.end = props.end;
6256
}
6257
6258
this.flags = 0;
6259
}, {
6260
$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",
6261
}, AST_Symbol);
6262
6263
var AST_Label = DEFNODE("Label", "references", function AST_Label(props) {
6264
if (props) {
6265
this.references = props.references;
6266
this.scope = props.scope;
6267
this.name = props.name;
6268
this.thedef = props.thedef;
6269
this.start = props.start;
6270
this.end = props.end;
6271
this.initialize();
6272
}
6273
6274
this.flags = 0;
6275
}, {
6276
$documentation: "Symbol naming a label (declaration)",
6277
$propdoc: {
6278
references: "[AST_LoopControl*] a list of nodes referring to this label"
6279
},
6280
initialize: function() {
6281
this.references = [];
6282
this.thedef = this;
6283
}
6284
}, AST_Symbol);
6285
6286
var AST_SymbolRef = DEFNODE("SymbolRef", null, function AST_SymbolRef(props) {
6287
if (props) {
6288
this.scope = props.scope;
6289
this.name = props.name;
6290
this.thedef = props.thedef;
6291
this.start = props.start;
6292
this.end = props.end;
6293
}
6294
6295
this.flags = 0;
6296
}, {
6297
$documentation: "Reference to some symbol (not definition/declaration)",
6298
}, AST_Symbol);
6299
6300
var AST_SymbolExport = DEFNODE("SymbolExport", null, function AST_SymbolExport(props) {
6301
if (props) {
6302
this.scope = props.scope;
6303
this.name = props.name;
6304
this.thedef = props.thedef;
6305
this.quote = props.quote;
6306
this.start = props.start;
6307
this.end = props.end;
6308
}
6309
6310
this.flags = 0;
6311
}, {
6312
$documentation: "Symbol referring to a name to export",
6313
}, AST_SymbolRef);
6314
6315
var AST_SymbolExportForeign = DEFNODE("SymbolExportForeign", null, function AST_SymbolExportForeign(props) {
6316
if (props) {
6317
this.scope = props.scope;
6318
this.name = props.name;
6319
this.thedef = props.thedef;
6320
this.quote = props.quote;
6321
this.start = props.start;
6322
this.end = props.end;
6323
}
6324
6325
this.flags = 0;
6326
}, {
6327
$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",
6328
}, AST_Symbol);
6329
6330
var AST_LabelRef = DEFNODE("LabelRef", null, function AST_LabelRef(props) {
6331
if (props) {
6332
this.scope = props.scope;
6333
this.name = props.name;
6334
this.thedef = props.thedef;
6335
this.start = props.start;
6336
this.end = props.end;
6337
}
6338
6339
this.flags = 0;
6340
}, {
6341
$documentation: "Reference to a label symbol",
6342
}, AST_Symbol);
6343
6344
var AST_SymbolPrivateProperty = DEFNODE("SymbolPrivateProperty", null, function AST_SymbolPrivateProperty(props) {
6345
if (props) {
6346
this.scope = props.scope;
6347
this.name = props.name;
6348
this.thedef = props.thedef;
6349
this.start = props.start;
6350
this.end = props.end;
6351
}
6352
6353
this.flags = 0;
6354
}, {
6355
$documentation: "A symbol that refers to a private property",
6356
}, AST_Symbol);
6357
6358
var AST_This = DEFNODE("This", null, function AST_This(props) {
6359
if (props) {
6360
this.scope = props.scope;
6361
this.name = props.name;
6362
this.thedef = props.thedef;
6363
this.start = props.start;
6364
this.end = props.end;
6365
}
6366
6367
this.flags = 0;
6368
}, {
6369
$documentation: "The `this` symbol",
6370
}, AST_Symbol);
6371
6372
var AST_Super = DEFNODE("Super", null, function AST_Super(props) {
6373
if (props) {
6374
this.scope = props.scope;
6375
this.name = props.name;
6376
this.thedef = props.thedef;
6377
this.start = props.start;
6378
this.end = props.end;
6379
}
6380
6381
this.flags = 0;
6382
}, {
6383
$documentation: "The `super` symbol",
6384
}, AST_This);
6385
6386
var AST_Constant = DEFNODE("Constant", null, function AST_Constant(props) {
6387
if (props) {
6388
this.start = props.start;
6389
this.end = props.end;
6390
}
6391
6392
this.flags = 0;
6393
}, {
6394
$documentation: "Base class for all constants",
6395
getValue: function() {
6396
return this.value;
6397
}
6398
});
6399
6400
var AST_String = DEFNODE("String", "value quote", function AST_String(props) {
6401
if (props) {
6402
this.value = props.value;
6403
this.quote = props.quote;
6404
this.start = props.start;
6405
this.end = props.end;
6406
this._annotations = props._annotations;
6407
}
6408
6409
this.flags = 0;
6410
}, {
6411
$documentation: "A string literal",
6412
$propdoc: {
6413
value: "[string] the contents of this string",
6414
quote: "[string] the original quote character"
6415
}
6416
}, AST_Constant);
6417
6418
var AST_Number = DEFNODE("Number", "value raw", function AST_Number(props) {
6419
if (props) {
6420
this.value = props.value;
6421
this.raw = props.raw;
6422
this.start = props.start;
6423
this.end = props.end;
6424
}
6425
6426
this.flags = 0;
6427
}, {
6428
$documentation: "A number literal",
6429
$propdoc: {
6430
value: "[number] the numeric value",
6431
raw: "[string] numeric value as string"
6432
}
6433
}, AST_Constant);
6434
6435
var AST_BigInt = DEFNODE("BigInt", "value", function AST_BigInt(props) {
6436
if (props) {
6437
this.value = props.value;
6438
this.start = props.start;
6439
this.end = props.end;
6440
}
6441
6442
this.flags = 0;
6443
}, {
6444
$documentation: "A big int literal",
6445
$propdoc: {
6446
value: "[string] big int value"
6447
}
6448
}, AST_Constant);
6449
6450
var AST_RegExp = DEFNODE("RegExp", "value", function AST_RegExp(props) {
6451
if (props) {
6452
this.value = props.value;
6453
this.start = props.start;
6454
this.end = props.end;
6455
}
6456
6457
this.flags = 0;
6458
}, {
6459
$documentation: "A regexp literal",
6460
$propdoc: {
6461
value: "[RegExp] the actual regexp",
6462
}
6463
}, AST_Constant);
6464
6465
var AST_Atom = DEFNODE("Atom", null, function AST_Atom(props) {
6466
if (props) {
6467
this.start = props.start;
6468
this.end = props.end;
6469
}
6470
6471
this.flags = 0;
6472
}, {
6473
$documentation: "Base class for atoms",
6474
}, AST_Constant);
6475
6476
var AST_Null = DEFNODE("Null", null, function AST_Null(props) {
6477
if (props) {
6478
this.start = props.start;
6479
this.end = props.end;
6480
}
6481
6482
this.flags = 0;
6483
}, {
6484
$documentation: "The `null` atom",
6485
value: null
6486
}, AST_Atom);
6487
6488
var AST_NaN = DEFNODE("NaN", null, function AST_NaN(props) {
6489
if (props) {
6490
this.start = props.start;
6491
this.end = props.end;
6492
}
6493
6494
this.flags = 0;
6495
}, {
6496
$documentation: "The impossible value",
6497
value: 0/0
6498
}, AST_Atom);
6499
6500
var AST_Undefined = DEFNODE("Undefined", null, function AST_Undefined(props) {
6501
if (props) {
6502
this.start = props.start;
6503
this.end = props.end;
6504
}
6505
6506
this.flags = 0;
6507
}, {
6508
$documentation: "The `undefined` value",
6509
value: (function() {}())
6510
}, AST_Atom);
6511
6512
var AST_Hole = DEFNODE("Hole", null, function AST_Hole(props) {
6513
if (props) {
6514
this.start = props.start;
6515
this.end = props.end;
6516
}
6517
6518
this.flags = 0;
6519
}, {
6520
$documentation: "A hole in an array",
6521
value: (function() {}())
6522
}, AST_Atom);
6523
6524
var AST_Infinity = DEFNODE("Infinity", null, function AST_Infinity(props) {
6525
if (props) {
6526
this.start = props.start;
6527
this.end = props.end;
6528
}
6529
6530
this.flags = 0;
6531
}, {
6532
$documentation: "The `Infinity` value",
6533
value: 1/0
6534
}, AST_Atom);
6535
6536
var AST_Boolean = DEFNODE("Boolean", null, function AST_Boolean(props) {
6537
if (props) {
6538
this.start = props.start;
6539
this.end = props.end;
6540
}
6541
6542
this.flags = 0;
6543
}, {
6544
$documentation: "Base class for booleans",
6545
}, AST_Atom);
6546
6547
var AST_False = DEFNODE("False", null, function AST_False(props) {
6548
if (props) {
6549
this.start = props.start;
6550
this.end = props.end;
6551
}
6552
6553
this.flags = 0;
6554
}, {
6555
$documentation: "The `false` atom",
6556
value: false
6557
}, AST_Boolean);
6558
6559
var AST_True = DEFNODE("True", null, function AST_True(props) {
6560
if (props) {
6561
this.start = props.start;
6562
this.end = props.end;
6563
}
6564
6565
this.flags = 0;
6566
}, {
6567
$documentation: "The `true` atom",
6568
value: true
6569
}, AST_Boolean);
6570
6571
/* -----[ Walk function ]---- */
6572
6573
/**
6574
* Walk nodes in depth-first search fashion.
6575
* Callback can return `walk_abort` symbol to stop iteration.
6576
* It can also return `true` to stop iteration just for child nodes.
6577
* Iteration can be stopped and continued by passing the `to_visit` argument,
6578
* which is given to the callback in the second argument.
6579
**/
6580
function walk(node, cb, to_visit = [node]) {
6581
const push = to_visit.push.bind(to_visit);
6582
while (to_visit.length) {
6583
const node = to_visit.pop();
6584
const ret = cb(node, to_visit);
6585
6586
if (ret) {
6587
if (ret === walk_abort) return true;
6588
continue;
6589
}
6590
6591
node._children_backwards(push);
6592
}
6593
return false;
6594
}
6595
6596
const walk_abort = Symbol("abort walk");
6597
6598
/* -----[ TreeWalker ]----- */
6599
6600
class TreeWalker {
6601
constructor(callback) {
6602
this.visit = callback;
6603
this.stack = [];
6604
this.directives = Object.create(null);
6605
}
6606
6607
_visit(node, descend) {
6608
this.push(node);
6609
var ret = this.visit(node, descend ? function() {
6610
descend.call(node);
6611
} : noop);
6612
if (!ret && descend) {
6613
descend.call(node);
6614
}
6615
this.pop();
6616
return ret;
6617
}
6618
6619
parent(n) {
6620
return this.stack[this.stack.length - 2 - (n || 0)];
6621
}
6622
6623
push(node) {
6624
if (node instanceof AST_Lambda) {
6625
this.directives = Object.create(this.directives);
6626
} else if (node instanceof AST_Directive && !this.directives[node.value]) {
6627
this.directives[node.value] = node;
6628
} else if (node instanceof AST_Class) {
6629
this.directives = Object.create(this.directives);
6630
if (!this.directives["use strict"]) {
6631
this.directives["use strict"] = node;
6632
}
6633
}
6634
this.stack.push(node);
6635
}
6636
6637
pop() {
6638
var node = this.stack.pop();
6639
if (node instanceof AST_Lambda || node instanceof AST_Class) {
6640
this.directives = Object.getPrototypeOf(this.directives);
6641
}
6642
}
6643
6644
self() {
6645
return this.stack[this.stack.length - 1];
6646
}
6647
6648
find_parent(type) {
6649
var stack = this.stack;
6650
for (var i = stack.length; --i >= 0;) {
6651
var x = stack[i];
6652
if (x instanceof type) return x;
6653
}
6654
}
6655
6656
find_scope() {
6657
var stack = this.stack;
6658
for (var i = stack.length; --i >= 0;) {
6659
const p = stack[i];
6660
if (p instanceof AST_Toplevel) return p;
6661
if (p instanceof AST_Lambda) return p;
6662
if (p.block_scope) return p.block_scope;
6663
}
6664
}
6665
6666
has_directive(type) {
6667
var dir = this.directives[type];
6668
if (dir) return dir;
6669
var node = this.stack[this.stack.length - 1];
6670
if (node instanceof AST_Scope && node.body) {
6671
for (var i = 0; i < node.body.length; ++i) {
6672
var st = node.body[i];
6673
if (!(st instanceof AST_Directive)) break;
6674
if (st.value == type) return st;
6675
}
6676
}
6677
}
6678
6679
loopcontrol_target(node) {
6680
var stack = this.stack;
6681
if (node.label) for (var i = stack.length; --i >= 0;) {
6682
var x = stack[i];
6683
if (x instanceof AST_LabeledStatement && x.label.name == node.label.name)
6684
return x.body;
6685
} else for (var i = stack.length; --i >= 0;) {
6686
var x = stack[i];
6687
if (x instanceof AST_IterationStatement
6688
|| node instanceof AST_Break && x instanceof AST_Switch)
6689
return x;
6690
}
6691
}
6692
}
6693
6694
// Tree transformer helpers.
6695
class TreeTransformer extends TreeWalker {
6696
constructor(before, after) {
6697
super();
6698
this.before = before;
6699
this.after = after;
6700
}
6701
}
6702
6703
const _PURE = 0b00000001;
6704
const _INLINE = 0b00000010;
6705
const _NOINLINE = 0b00000100;
6706
const _KEY = 0b00001000;
6707
const _MANGLEPROP = 0b00010000;
6708
6709
// XXX Emscripten: export TreeWalker for walking through AST in acorn-optimizer.mjs.
6710
exports.TreeWalker = TreeWalker;
6711
6712
/***********************************************************************
6713
6714
A JavaScript tokenizer / parser / beautifier / compressor.
6715
https://github.com/mishoo/UglifyJS2
6716
6717
-------------------------------- (C) ---------------------------------
6718
6719
Author: Mihai Bazon
6720
<[email protected]>
6721
http://mihai.bazon.net/blog
6722
6723
Distributed under the BSD license:
6724
6725
Copyright 2012 (c) Mihai Bazon <[email protected]>
6726
6727
Redistribution and use in source and binary forms, with or without
6728
modification, are permitted provided that the following conditions
6729
are met:
6730
6731
* Redistributions of source code must retain the above
6732
copyright notice, this list of conditions and the following
6733
disclaimer.
6734
6735
* Redistributions in binary form must reproduce the above
6736
copyright notice, this list of conditions and the following
6737
disclaimer in the documentation and/or other materials
6738
provided with the distribution.
6739
6740
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
6741
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6742
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
6743
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
6744
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
6745
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
6746
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
6747
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
6748
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
6749
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
6750
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6751
SUCH DAMAGE.
6752
6753
***********************************************************************/
6754
6755
function def_transform(node, descend) {
6756
node.DEFMETHOD("transform", function(tw, in_list) {
6757
let transformed = undefined;
6758
tw.push(this);
6759
if (tw.before) transformed = tw.before(this, descend, in_list);
6760
if (transformed === undefined) {
6761
transformed = this;
6762
descend(transformed, tw);
6763
if (tw.after) {
6764
const after_ret = tw.after(transformed, in_list);
6765
if (after_ret !== undefined) transformed = after_ret;
6766
}
6767
}
6768
tw.pop();
6769
return transformed;
6770
});
6771
}
6772
6773
def_transform(AST_Node, noop);
6774
6775
def_transform(AST_LabeledStatement, function(self, tw) {
6776
self.label = self.label.transform(tw);
6777
self.body = self.body.transform(tw);
6778
});
6779
6780
def_transform(AST_SimpleStatement, function(self, tw) {
6781
self.body = self.body.transform(tw);
6782
});
6783
6784
def_transform(AST_Block, function(self, tw) {
6785
self.body = MAP(self.body, tw);
6786
});
6787
6788
def_transform(AST_Do, function(self, tw) {
6789
self.body = self.body.transform(tw);
6790
self.condition = self.condition.transform(tw);
6791
});
6792
6793
def_transform(AST_While, function(self, tw) {
6794
self.condition = self.condition.transform(tw);
6795
self.body = self.body.transform(tw);
6796
});
6797
6798
def_transform(AST_For, function(self, tw) {
6799
if (self.init) self.init = self.init.transform(tw);
6800
if (self.condition) self.condition = self.condition.transform(tw);
6801
if (self.step) self.step = self.step.transform(tw);
6802
self.body = self.body.transform(tw);
6803
});
6804
6805
def_transform(AST_ForIn, function(self, tw) {
6806
self.init = self.init.transform(tw);
6807
self.object = self.object.transform(tw);
6808
self.body = self.body.transform(tw);
6809
});
6810
6811
def_transform(AST_With, function(self, tw) {
6812
self.expression = self.expression.transform(tw);
6813
self.body = self.body.transform(tw);
6814
});
6815
6816
def_transform(AST_Exit, function(self, tw) {
6817
if (self.value) self.value = self.value.transform(tw);
6818
});
6819
6820
def_transform(AST_LoopControl, function(self, tw) {
6821
if (self.label) self.label = self.label.transform(tw);
6822
});
6823
6824
def_transform(AST_If, function(self, tw) {
6825
self.condition = self.condition.transform(tw);
6826
self.body = self.body.transform(tw);
6827
if (self.alternative) self.alternative = self.alternative.transform(tw);
6828
});
6829
6830
def_transform(AST_Switch, function(self, tw) {
6831
self.expression = self.expression.transform(tw);
6832
self.body = MAP(self.body, tw);
6833
});
6834
6835
def_transform(AST_Case, function(self, tw) {
6836
self.expression = self.expression.transform(tw);
6837
self.body = MAP(self.body, tw);
6838
});
6839
6840
def_transform(AST_Try, function(self, tw) {
6841
self.body = self.body.transform(tw);
6842
if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
6843
if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
6844
});
6845
6846
def_transform(AST_Catch, function(self, tw) {
6847
if (self.argname) self.argname = self.argname.transform(tw);
6848
self.body = MAP(self.body, tw);
6849
});
6850
6851
def_transform(AST_Definitions, function(self, tw) {
6852
self.definitions = MAP(self.definitions, tw);
6853
});
6854
6855
def_transform(AST_VarDef, function(self, tw) {
6856
self.name = self.name.transform(tw);
6857
if (self.value) self.value = self.value.transform(tw);
6858
});
6859
6860
def_transform(AST_Destructuring, function(self, tw) {
6861
self.names = MAP(self.names, tw);
6862
});
6863
6864
def_transform(AST_Lambda, function(self, tw) {
6865
if (self.name) self.name = self.name.transform(tw);
6866
self.argnames = MAP(self.argnames, tw, /* allow_splicing */ false);
6867
if (self.body instanceof AST_Node) {
6868
self.body = self.body.transform(tw);
6869
} else {
6870
self.body = MAP(self.body, tw);
6871
}
6872
});
6873
6874
def_transform(AST_Call, function(self, tw) {
6875
self.expression = self.expression.transform(tw);
6876
self.args = MAP(self.args, tw, /* allow_splicing */ false);
6877
});
6878
6879
def_transform(AST_Sequence, function(self, tw) {
6880
const result = MAP(self.expressions, tw);
6881
self.expressions = result.length
6882
? result
6883
: [new AST_Number({ value: 0 })];
6884
});
6885
6886
def_transform(AST_PropAccess, function(self, tw) {
6887
self.expression = self.expression.transform(tw);
6888
});
6889
6890
def_transform(AST_Sub, function(self, tw) {
6891
self.expression = self.expression.transform(tw);
6892
self.property = self.property.transform(tw);
6893
});
6894
6895
def_transform(AST_Chain, function(self, tw) {
6896
self.expression = self.expression.transform(tw);
6897
});
6898
6899
def_transform(AST_Yield, function(self, tw) {
6900
if (self.expression) self.expression = self.expression.transform(tw);
6901
});
6902
6903
def_transform(AST_Await, function(self, tw) {
6904
self.expression = self.expression.transform(tw);
6905
});
6906
6907
def_transform(AST_Unary, function(self, tw) {
6908
self.expression = self.expression.transform(tw);
6909
});
6910
6911
def_transform(AST_Binary, function(self, tw) {
6912
self.left = self.left.transform(tw);
6913
self.right = self.right.transform(tw);
6914
});
6915
6916
def_transform(AST_PrivateIn, function(self, tw) {
6917
self.key = self.key.transform(tw);
6918
self.value = self.value.transform(tw);
6919
});
6920
6921
def_transform(AST_Conditional, function(self, tw) {
6922
self.condition = self.condition.transform(tw);
6923
self.consequent = self.consequent.transform(tw);
6924
self.alternative = self.alternative.transform(tw);
6925
});
6926
6927
def_transform(AST_Array, function(self, tw) {
6928
self.elements = MAP(self.elements, tw);
6929
});
6930
6931
def_transform(AST_Object, function(self, tw) {
6932
self.properties = MAP(self.properties, tw);
6933
});
6934
6935
def_transform(AST_ObjectProperty, function(self, tw) {
6936
if (self.key instanceof AST_Node) {
6937
self.key = self.key.transform(tw);
6938
}
6939
if (self.value) self.value = self.value.transform(tw);
6940
});
6941
6942
def_transform(AST_Class, function(self, tw) {
6943
if (self.name) self.name = self.name.transform(tw);
6944
if (self.extends) self.extends = self.extends.transform(tw);
6945
self.properties = MAP(self.properties, tw);
6946
});
6947
6948
def_transform(AST_ClassStaticBlock, function(self, tw) {
6949
self.body = MAP(self.body, tw);
6950
});
6951
6952
def_transform(AST_Expansion, function(self, tw) {
6953
self.expression = self.expression.transform(tw);
6954
});
6955
6956
def_transform(AST_NameMapping, function(self, tw) {
6957
self.foreign_name = self.foreign_name.transform(tw);
6958
self.name = self.name.transform(tw);
6959
});
6960
6961
def_transform(AST_Import, function(self, tw) {
6962
if (self.imported_name) self.imported_name = self.imported_name.transform(tw);
6963
if (self.imported_names) MAP(self.imported_names, tw);
6964
self.module_name = self.module_name.transform(tw);
6965
});
6966
6967
def_transform(AST_Export, function(self, tw) {
6968
if (self.exported_definition) self.exported_definition = self.exported_definition.transform(tw);
6969
if (self.exported_value) self.exported_value = self.exported_value.transform(tw);
6970
if (self.exported_names) MAP(self.exported_names, tw);
6971
if (self.module_name) self.module_name = self.module_name.transform(tw);
6972
});
6973
6974
def_transform(AST_TemplateString, function(self, tw) {
6975
self.segments = MAP(self.segments, tw);
6976
});
6977
6978
def_transform(AST_PrefixedTemplateString, function(self, tw) {
6979
self.prefix = self.prefix.transform(tw);
6980
self.template_string = self.template_string.transform(tw);
6981
});
6982
6983
/***********************************************************************
6984
6985
A JavaScript tokenizer / parser / beautifier / compressor.
6986
https://github.com/mishoo/UglifyJS2
6987
6988
-------------------------------- (C) ---------------------------------
6989
6990
Author: Mihai Bazon
6991
<[email protected]>
6992
http://mihai.bazon.net/blog
6993
6994
Distributed under the BSD license:
6995
6996
Copyright 2012 (c) Mihai Bazon <[email protected]>
6997
6998
Redistribution and use in source and binary forms, with or without
6999
modification, are permitted provided that the following conditions
7000
are met:
7001
7002
* Redistributions of source code must retain the above
7003
copyright notice, this list of conditions and the following
7004
disclaimer.
7005
7006
* Redistributions in binary form must reproduce the above
7007
copyright notice, this list of conditions and the following
7008
disclaimer in the documentation and/or other materials
7009
provided with the distribution.
7010
7011
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
7012
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7013
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
7014
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
7015
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
7016
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
7017
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
7018
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
7019
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
7020
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
7021
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7022
SUCH DAMAGE.
7023
7024
***********************************************************************/
7025
7026
(function() {
7027
7028
var normalize_directives = function(body) {
7029
var in_directive = true;
7030
7031
for (var i = 0; i < body.length; i++) {
7032
if (in_directive && body[i] instanceof AST_Statement && body[i].body instanceof AST_String) {
7033
body[i] = new AST_Directive({
7034
start: body[i].start,
7035
end: body[i].end,
7036
value: body[i].body.value
7037
});
7038
} else if (in_directive && !(body[i] instanceof AST_Statement && body[i].body instanceof AST_String)) {
7039
in_directive = false;
7040
}
7041
}
7042
7043
return body;
7044
};
7045
7046
const assert_clause_from_moz = (assertions) => {
7047
if (assertions && assertions.length > 0) {
7048
return new AST_Object({
7049
start: my_start_token(assertions),
7050
end: my_end_token(assertions),
7051
properties: assertions.map((assertion_kv) =>
7052
new AST_ObjectKeyVal({
7053
start: my_start_token(assertion_kv),
7054
end: my_end_token(assertion_kv),
7055
key: assertion_kv.key.name || assertion_kv.key.value,
7056
value: from_moz(assertion_kv.value)
7057
})
7058
)
7059
});
7060
}
7061
return null;
7062
};
7063
7064
var MOZ_TO_ME = {
7065
Program: function(M) {
7066
return new AST_Toplevel({
7067
start: my_start_token(M),
7068
end: my_end_token(M),
7069
body: normalize_directives(M.body.map(from_moz))
7070
});
7071
},
7072
7073
ArrayPattern: function(M) {
7074
return new AST_Destructuring({
7075
start: my_start_token(M),
7076
end: my_end_token(M),
7077
names: M.elements.map(function(elm) {
7078
if (elm === null) {
7079
return new AST_Hole();
7080
}
7081
return from_moz(elm);
7082
}),
7083
is_array: true
7084
});
7085
},
7086
7087
ObjectPattern: function(M) {
7088
return new AST_Destructuring({
7089
start: my_start_token(M),
7090
end: my_end_token(M),
7091
names: M.properties.map(from_moz),
7092
is_array: false
7093
});
7094
},
7095
7096
AssignmentPattern: function(M) {
7097
return new AST_DefaultAssign({
7098
start: my_start_token(M),
7099
end: my_end_token(M),
7100
left: from_moz(M.left),
7101
operator: "=",
7102
right: from_moz(M.right)
7103
});
7104
},
7105
7106
SpreadElement: function(M) {
7107
return new AST_Expansion({
7108
start: my_start_token(M),
7109
end: my_end_token(M),
7110
expression: from_moz(M.argument)
7111
});
7112
},
7113
7114
RestElement: function(M) {
7115
return new AST_Expansion({
7116
start: my_start_token(M),
7117
end: my_end_token(M),
7118
expression: from_moz(M.argument)
7119
});
7120
},
7121
7122
TemplateElement: function(M) {
7123
return new AST_TemplateSegment({
7124
start: my_start_token(M),
7125
end: my_end_token(M),
7126
value: M.value.cooked,
7127
raw: M.value.raw
7128
});
7129
},
7130
7131
TemplateLiteral: function(M) {
7132
var segments = [];
7133
for (var i = 0; i < M.quasis.length; i++) {
7134
segments.push(from_moz(M.quasis[i]));
7135
if (M.expressions[i]) {
7136
segments.push(from_moz(M.expressions[i]));
7137
}
7138
}
7139
return new AST_TemplateString({
7140
start: my_start_token(M),
7141
end: my_end_token(M),
7142
segments: segments
7143
});
7144
},
7145
7146
TaggedTemplateExpression: function(M) {
7147
return new AST_PrefixedTemplateString({
7148
start: my_start_token(M),
7149
end: my_end_token(M),
7150
template_string: from_moz(M.quasi),
7151
prefix: from_moz(M.tag)
7152
});
7153
},
7154
7155
FunctionDeclaration: function(M) {
7156
return new AST_Defun({
7157
start: my_start_token(M),
7158
end: my_end_token(M),
7159
name: from_moz(M.id),
7160
argnames: M.params.map(from_moz),
7161
is_generator: M.generator,
7162
async: M.async,
7163
body: normalize_directives(from_moz(M.body).body)
7164
});
7165
},
7166
7167
FunctionExpression: function(M) {
7168
return new AST_Function({
7169
start: my_start_token(M),
7170
end: my_end_token(M),
7171
name: from_moz(M.id),
7172
argnames: M.params.map(from_moz),
7173
is_generator: M.generator,
7174
async: M.async,
7175
body: normalize_directives(from_moz(M.body).body)
7176
});
7177
},
7178
7179
ArrowFunctionExpression: function(M) {
7180
const body = M.body.type === "BlockStatement"
7181
? from_moz(M.body).body
7182
: [make_node(AST_Return, {}, { value: from_moz(M.body) })];
7183
return new AST_Arrow({
7184
start: my_start_token(M),
7185
end: my_end_token(M),
7186
argnames: M.params.map(from_moz),
7187
body,
7188
async: M.async,
7189
});
7190
},
7191
7192
ExpressionStatement: function(M) {
7193
return new AST_SimpleStatement({
7194
start: my_start_token(M),
7195
end: my_end_token(M),
7196
body: from_moz(M.expression)
7197
});
7198
},
7199
7200
// XXX Emscripten localmod: Add a node type for a parenthesized expression so that we can retain
7201
// Closure annotations that need a form "/**annotation*/(expression)"
7202
ParenthesizedExpression: function(M) {
7203
return new AST_ParenthesizedExpression({
7204
start: my_start_token(M),
7205
end: my_end_token(M),
7206
body: from_moz(M.expression)
7207
});
7208
},
7209
// XXX End Emscripten localmod
7210
7211
TryStatement: function(M) {
7212
var handlers = M.handlers || [M.handler];
7213
if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) {
7214
throw new Error("Multiple catch clauses are not supported.");
7215
}
7216
return new AST_Try({
7217
start : my_start_token(M),
7218
end : my_end_token(M),
7219
body : new AST_TryBlock(from_moz(M.block)),
7220
bcatch : from_moz(handlers[0]),
7221
bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
7222
});
7223
},
7224
7225
Property: function(M) {
7226
var key = M.key;
7227
var args = {
7228
start : my_start_token(key || M.value),
7229
end : my_end_token(M.value),
7230
key : key.type == "Identifier" ? key.name : key.value,
7231
value : from_moz(M.value)
7232
};
7233
if (M.computed) {
7234
args.key = from_moz(M.key);
7235
}
7236
if (M.method) {
7237
args.is_generator = M.value.generator;
7238
args.async = M.value.async;
7239
if (!M.computed) {
7240
args.key = new AST_SymbolMethod({ name: args.key });
7241
} else {
7242
args.key = from_moz(M.key);
7243
}
7244
return new AST_ConciseMethod(args);
7245
}
7246
if (M.kind == "init") {
7247
if (key.type != "Identifier" && key.type != "Literal") {
7248
args.key = from_moz(key);
7249
}
7250
return new AST_ObjectKeyVal(args);
7251
}
7252
if (typeof args.key === "string" || typeof args.key === "number") {
7253
args.key = new AST_SymbolMethod({
7254
name: args.key
7255
});
7256
}
7257
args.value = new AST_Accessor(args.value);
7258
if (M.kind == "get") return new AST_ObjectGetter(args);
7259
if (M.kind == "set") return new AST_ObjectSetter(args);
7260
if (M.kind == "method") {
7261
args.async = M.value.async;
7262
args.is_generator = M.value.generator;
7263
args.quote = M.computed ? "\"" : null;
7264
return new AST_ConciseMethod(args);
7265
}
7266
},
7267
7268
MethodDefinition: function(M) {
7269
const is_private = M.key.type === "PrivateIdentifier";
7270
const key = M.computed ? from_moz(M.key) : new AST_SymbolMethod({ name: M.key.name || M.key.value });
7271
7272
var args = {
7273
start : my_start_token(M),
7274
end : my_end_token(M),
7275
key,
7276
value : from_moz(M.value),
7277
static : M.static,
7278
};
7279
if (M.kind == "get") {
7280
return new (is_private ? AST_PrivateGetter : AST_ObjectGetter)(args);
7281
}
7282
if (M.kind == "set") {
7283
return new (is_private ? AST_PrivateSetter : AST_ObjectSetter)(args);
7284
}
7285
args.is_generator = M.value.generator;
7286
args.async = M.value.async;
7287
return new (is_private ? AST_PrivateMethod : AST_ConciseMethod)(args);
7288
},
7289
7290
FieldDefinition: function(M) {
7291
let key;
7292
if (M.computed) {
7293
key = from_moz(M.key);
7294
} else {
7295
if (M.key.type !== "Identifier") throw new Error("Non-Identifier key in FieldDefinition");
7296
key = from_moz(M.key);
7297
}
7298
return new AST_ClassProperty({
7299
start : my_start_token(M),
7300
end : my_end_token(M),
7301
key,
7302
value : from_moz(M.value),
7303
static : M.static,
7304
});
7305
},
7306
7307
PropertyDefinition: function(M) {
7308
let key;
7309
if (M.computed) {
7310
key = from_moz(M.key);
7311
} else if (M.key.type === "PrivateIdentifier") {
7312
return new AST_ClassPrivateProperty({
7313
start : my_start_token(M),
7314
end : my_end_token(M),
7315
key : from_moz(M.key),
7316
value : from_moz(M.value),
7317
static : M.static,
7318
});
7319
} else {
7320
if (M.key.type !== "Identifier") {
7321
throw new Error("Non-Identifier key in PropertyDefinition");
7322
}
7323
key = from_moz(M.key);
7324
}
7325
7326
return new AST_ClassProperty({
7327
start : my_start_token(M),
7328
end : my_end_token(M),
7329
key,
7330
value : from_moz(M.value),
7331
static : M.static,
7332
});
7333
},
7334
7335
PrivateIdentifier: function (M) {
7336
return new AST_SymbolPrivateProperty({
7337
start: my_start_token(M),
7338
end: my_end_token(M),
7339
name: M.name
7340
});
7341
},
7342
7343
StaticBlock: function(M) {
7344
return new AST_ClassStaticBlock({
7345
start : my_start_token(M),
7346
end : my_end_token(M),
7347
body : M.body.map(from_moz),
7348
});
7349
},
7350
7351
ArrayExpression: function(M) {
7352
return new AST_Array({
7353
start : my_start_token(M),
7354
end : my_end_token(M),
7355
elements : M.elements.map(function(elem) {
7356
return elem === null ? new AST_Hole() : from_moz(elem);
7357
})
7358
});
7359
},
7360
7361
ObjectExpression: function(M) {
7362
return new AST_Object({
7363
start : my_start_token(M),
7364
end : my_end_token(M),
7365
properties : M.properties.map(function(prop) {
7366
if (prop.type === "SpreadElement") {
7367
return from_moz(prop);
7368
}
7369
prop.type = "Property";
7370
// XXX EMSCRIPTEN preserve quoted properties
7371
// https://github.com/mishoo/UglifyJS2/pull/3323
7372
var ret = from_moz(prop);
7373
if (prop.key.type === "Literal" &&
7374
(prop.key.raw[0] === '"' || prop.key.raw[0] === "'")) {
7375
ret.quote = true;
7376
}
7377
return ret;
7378
})
7379
});
7380
},
7381
7382
SequenceExpression: function(M) {
7383
return new AST_Sequence({
7384
start : my_start_token(M),
7385
end : my_end_token(M),
7386
expressions: M.expressions.map(from_moz)
7387
});
7388
},
7389
7390
MemberExpression: function(M) {
7391
if (M.property.type === "PrivateIdentifier") {
7392
return new AST_DotHash({
7393
start : my_start_token(M),
7394
end : my_end_token(M),
7395
property : M.property.name,
7396
expression : from_moz(M.object),
7397
optional : M.optional || false
7398
});
7399
}
7400
return new (M.computed ? AST_Sub : AST_Dot)({
7401
start : my_start_token(M),
7402
end : my_end_token(M),
7403
property : M.computed ? from_moz(M.property) : M.property.name,
7404
expression : from_moz(M.object),
7405
optional : M.optional || false
7406
});
7407
},
7408
7409
ChainExpression: function(M) {
7410
return new AST_Chain({
7411
start : my_start_token(M),
7412
end : my_end_token(M),
7413
expression : from_moz(M.expression)
7414
});
7415
},
7416
7417
SwitchCase: function(M) {
7418
return new (M.test ? AST_Case : AST_Default)({
7419
start : my_start_token(M),
7420
end : my_end_token(M),
7421
expression : from_moz(M.test),
7422
body : M.consequent.map(from_moz)
7423
});
7424
},
7425
7426
VariableDeclaration: function(M) {
7427
return new (M.kind === "const" ? AST_Const :
7428
M.kind === "let" ? AST_Let : AST_Var)({
7429
start : my_start_token(M),
7430
end : my_end_token(M),
7431
definitions : M.declarations.map(from_moz)
7432
});
7433
},
7434
7435
ImportDeclaration: function(M) {
7436
var imported_name = null;
7437
var imported_names = null;
7438
M.specifiers.forEach(function (specifier) {
7439
if (specifier.type === "ImportSpecifier" || specifier.type === "ImportNamespaceSpecifier") {
7440
if (!imported_names) { imported_names = []; }
7441
imported_names.push(from_moz(specifier));
7442
} else if (specifier.type === "ImportDefaultSpecifier") {
7443
imported_name = from_moz(specifier);
7444
}
7445
});
7446
return new AST_Import({
7447
start : my_start_token(M),
7448
end : my_end_token(M),
7449
imported_name: imported_name,
7450
imported_names : imported_names,
7451
module_name : from_moz(M.source),
7452
assert_clause: assert_clause_from_moz(M.assertions)
7453
});
7454
},
7455
7456
ImportSpecifier: function(M) {
7457
return new AST_NameMapping({
7458
start: my_start_token(M),
7459
end: my_end_token(M),
7460
foreign_name: from_moz(M.imported),
7461
name: from_moz(M.local)
7462
});
7463
},
7464
7465
ImportDefaultSpecifier: function(M) {
7466
return from_moz(M.local);
7467
},
7468
7469
ImportNamespaceSpecifier: function(M) {
7470
return new AST_NameMapping({
7471
start: my_start_token(M),
7472
end: my_end_token(M),
7473
foreign_name: new AST_SymbolImportForeign({ name: "*" }),
7474
name: from_moz(M.local)
7475
});
7476
},
7477
7478
ExportAllDeclaration: function(M) {
7479
var foreign_name = M.exported == null ?
7480
new AST_SymbolExportForeign({ name: "*" }) :
7481
from_moz(M.exported);
7482
return new AST_Export({
7483
start: my_start_token(M),
7484
end: my_end_token(M),
7485
exported_names: [
7486
new AST_NameMapping({
7487
name: new AST_SymbolExportForeign({ name: "*" }),
7488
foreign_name: foreign_name
7489
})
7490
],
7491
module_name: from_moz(M.source),
7492
assert_clause: assert_clause_from_moz(M.assertions)
7493
});
7494
},
7495
7496
ExportNamedDeclaration: function(M) {
7497
return new AST_Export({
7498
start: my_start_token(M),
7499
end: my_end_token(M),
7500
exported_definition: from_moz(M.declaration),
7501
exported_names: M.specifiers && M.specifiers.length ? M.specifiers.map(function (specifier) {
7502
return from_moz(specifier);
7503
}) : null,
7504
module_name: from_moz(M.source),
7505
assert_clause: assert_clause_from_moz(M.assertions)
7506
});
7507
},
7508
7509
ExportDefaultDeclaration: function(M) {
7510
return new AST_Export({
7511
start: my_start_token(M),
7512
end: my_end_token(M),
7513
exported_value: from_moz(M.declaration),
7514
is_default: true
7515
});
7516
},
7517
7518
ExportSpecifier: function(M) {
7519
return new AST_NameMapping({
7520
foreign_name: from_moz(M.exported),
7521
name: from_moz(M.local)
7522
});
7523
},
7524
7525
Literal: function(M) {
7526
var val = M.value, args = {
7527
start : my_start_token(M),
7528
end : my_end_token(M)
7529
};
7530
var rx = M.regex;
7531
if (rx && rx.pattern) {
7532
// RegExpLiteral as per ESTree AST spec
7533
args.value = {
7534
source: rx.pattern,
7535
flags: rx.flags
7536
};
7537
return new AST_RegExp(args);
7538
} else if (rx) {
7539
// support legacy RegExp
7540
const rx_source = M.raw || val;
7541
const match = rx_source.match(/^\/(.*)\/(\w*)$/);
7542
if (!match) throw new Error("Invalid regex source " + rx_source);
7543
const [_, source, flags] = match;
7544
args.value = { source, flags };
7545
return new AST_RegExp(args);
7546
}
7547
if (val === null) return new AST_Null(args);
7548
switch (typeof val) {
7549
case "string":
7550
args.quote = "\"";
7551
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
7552
if (p.type == "ImportSpecifier") {
7553
args.name = val;
7554
return new AST_SymbolImportForeign(args);
7555
} else if (p.type == "ExportSpecifier") {
7556
args.name = val;
7557
if (M == p.exported) {
7558
return new AST_SymbolExportForeign(args);
7559
} else {
7560
return new AST_SymbolExport(args);
7561
}
7562
} else if (p.type == "ExportAllDeclaration" && M == p.exported) {
7563
args.name = val;
7564
return new AST_SymbolExportForeign(args);
7565
}
7566
args.value = val;
7567
return new AST_String(args);
7568
case "number":
7569
args.value = val;
7570
args.raw = M.raw || val.toString();
7571
return new AST_Number(args);
7572
case "boolean":
7573
return new (val ? AST_True : AST_False)(args);
7574
case "bigint":
7575
args.value = val;
7576
return new AST_BigInt(args);
7577
case "undefined":
7578
return undefined;
7579
default:
7580
throw new Error("Unhandled value type: " + typeof val);
7581
}
7582
},
7583
7584
MetaProperty: function(M) {
7585
if (M.meta.name === "new" && M.property.name === "target") {
7586
return new AST_NewTarget({
7587
start: my_start_token(M),
7588
end: my_end_token(M)
7589
});
7590
} else if (M.meta.name === "import" && M.property.name === "meta") {
7591
return new AST_ImportMeta({
7592
start: my_start_token(M),
7593
end: my_end_token(M)
7594
});
7595
}
7596
},
7597
7598
Identifier: function(M) {
7599
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
7600
return new ( p.type == "LabeledStatement" ? AST_Label
7601
: p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : p.kind == "let" ? AST_SymbolLet : AST_SymbolVar)
7602
: /Import.*Specifier/.test(p.type) ? (p.local === M ? AST_SymbolImport : AST_SymbolImportForeign)
7603
: p.type == "ExportSpecifier" ? (p.local === M ? AST_SymbolExport : AST_SymbolExportForeign)
7604
: p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
7605
: p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
7606
: p.type == "ArrowFunctionExpression" ? (p.params.includes(M)) ? AST_SymbolFunarg : AST_SymbolRef
7607
: p.type == "ClassExpression" ? (p.id === M ? AST_SymbolClass : AST_SymbolRef)
7608
: p.type == "Property" ? (p.key === M && p.computed || p.value === M ? AST_SymbolRef : AST_SymbolMethod)
7609
: p.type == "PropertyDefinition" || p.type === "FieldDefinition" ? (p.key === M && p.computed || p.value === M ? AST_SymbolRef : AST_SymbolClassProperty)
7610
: p.type == "ClassDeclaration" ? (p.id === M ? AST_SymbolDefClass : AST_SymbolRef)
7611
: p.type == "MethodDefinition" ? (p.computed ? AST_SymbolRef : AST_SymbolMethod)
7612
: p.type == "CatchClause" ? AST_SymbolCatch
7613
: p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef
7614
: AST_SymbolRef)({
7615
start : my_start_token(M),
7616
end : my_end_token(M),
7617
name : M.name
7618
});
7619
},
7620
7621
BigIntLiteral(M) {
7622
return new AST_BigInt({
7623
start : my_start_token(M),
7624
end : my_end_token(M),
7625
value : M.value
7626
});
7627
},
7628
7629
EmptyStatement: function(M) {
7630
return new AST_EmptyStatement({
7631
start: my_start_token(M),
7632
end: my_end_token(M)
7633
});
7634
},
7635
7636
BlockStatement: function(M) {
7637
return new AST_BlockStatement({
7638
start: my_start_token(M),
7639
end: my_end_token(M),
7640
body: M.body.map(from_moz)
7641
});
7642
},
7643
7644
IfStatement: function(M) {
7645
return new AST_If({
7646
start: my_start_token(M),
7647
end: my_end_token(M),
7648
condition: from_moz(M.test),
7649
body: from_moz(M.consequent),
7650
alternative: from_moz(M.alternate)
7651
});
7652
},
7653
7654
LabeledStatement: function(M) {
7655
return new AST_LabeledStatement({
7656
start: my_start_token(M),
7657
end: my_end_token(M),
7658
label: from_moz(M.label),
7659
body: from_moz(M.body)
7660
});
7661
},
7662
7663
BreakStatement: function(M) {
7664
return new AST_Break({
7665
start: my_start_token(M),
7666
end: my_end_token(M),
7667
label: from_moz(M.label)
7668
});
7669
},
7670
7671
ContinueStatement: function(M) {
7672
return new AST_Continue({
7673
start: my_start_token(M),
7674
end: my_end_token(M),
7675
label: from_moz(M.label)
7676
});
7677
},
7678
7679
WithStatement: function(M) {
7680
return new AST_With({
7681
start: my_start_token(M),
7682
end: my_end_token(M),
7683
expression: from_moz(M.object),
7684
body: from_moz(M.body)
7685
});
7686
},
7687
7688
SwitchStatement: function(M) {
7689
return new AST_Switch({
7690
start: my_start_token(M),
7691
end: my_end_token(M),
7692
expression: from_moz(M.discriminant),
7693
body: M.cases.map(from_moz)
7694
});
7695
},
7696
7697
ReturnStatement: function(M) {
7698
return new AST_Return({
7699
start: my_start_token(M),
7700
end: my_end_token(M),
7701
value: from_moz(M.argument)
7702
});
7703
},
7704
7705
ThrowStatement: function(M) {
7706
return new AST_Throw({
7707
start: my_start_token(M),
7708
end: my_end_token(M),
7709
value: from_moz(M.argument)
7710
});
7711
},
7712
7713
WhileStatement: function(M) {
7714
return new AST_While({
7715
start: my_start_token(M),
7716
end: my_end_token(M),
7717
condition: from_moz(M.test),
7718
body: from_moz(M.body)
7719
});
7720
},
7721
7722
DoWhileStatement: function(M) {
7723
return new AST_Do({
7724
start: my_start_token(M),
7725
end: my_end_token(M),
7726
condition: from_moz(M.test),
7727
body: from_moz(M.body)
7728
});
7729
},
7730
7731
ForStatement: function(M) {
7732
return new AST_For({
7733
start: my_start_token(M),
7734
end: my_end_token(M),
7735
init: from_moz(M.init),
7736
condition: from_moz(M.test),
7737
step: from_moz(M.update),
7738
body: from_moz(M.body)
7739
});
7740
},
7741
7742
ForInStatement: function(M) {
7743
return new AST_ForIn({
7744
start: my_start_token(M),
7745
end: my_end_token(M),
7746
init: from_moz(M.left),
7747
object: from_moz(M.right),
7748
body: from_moz(M.body)
7749
});
7750
},
7751
7752
ForOfStatement: function(M) {
7753
return new AST_ForOf({
7754
start: my_start_token(M),
7755
end: my_end_token(M),
7756
init: from_moz(M.left),
7757
object: from_moz(M.right),
7758
body: from_moz(M.body),
7759
await: M.await
7760
});
7761
},
7762
7763
AwaitExpression: function(M) {
7764
return new AST_Await({
7765
start: my_start_token(M),
7766
end: my_end_token(M),
7767
expression: from_moz(M.argument)
7768
});
7769
},
7770
7771
YieldExpression: function(M) {
7772
return new AST_Yield({
7773
start: my_start_token(M),
7774
end: my_end_token(M),
7775
expression: from_moz(M.argument),
7776
is_star: M.delegate
7777
});
7778
},
7779
7780
DebuggerStatement: function(M) {
7781
return new AST_Debugger({
7782
start: my_start_token(M),
7783
end: my_end_token(M)
7784
});
7785
},
7786
7787
VariableDeclarator: function(M) {
7788
return new AST_VarDef({
7789
start: my_start_token(M),
7790
end: my_end_token(M),
7791
name: from_moz(M.id),
7792
value: from_moz(M.init)
7793
});
7794
},
7795
7796
CatchClause: function(M) {
7797
return new AST_Catch({
7798
start: my_start_token(M),
7799
end: my_end_token(M),
7800
argname: from_moz(M.param),
7801
body: from_moz(M.body).body
7802
});
7803
},
7804
7805
ThisExpression: function(M) {
7806
return new AST_This({
7807
start: my_start_token(M),
7808
end: my_end_token(M)
7809
});
7810
},
7811
7812
Super: function(M) {
7813
return new AST_Super({
7814
start: my_start_token(M),
7815
end: my_end_token(M)
7816
});
7817
},
7818
7819
BinaryExpression: function(M) {
7820
if (M.left.type === "PrivateIdentifier") {
7821
return new AST_PrivateIn({
7822
start: my_start_token(M),
7823
end: my_end_token(M),
7824
key: new AST_SymbolPrivateProperty({
7825
start: my_start_token(M.left),
7826
end: my_end_token(M.left),
7827
name: M.left.name
7828
}),
7829
value: from_moz(M.right),
7830
});
7831
}
7832
return new AST_Binary({
7833
start: my_start_token(M),
7834
end: my_end_token(M),
7835
operator: M.operator,
7836
left: from_moz(M.left),
7837
right: from_moz(M.right)
7838
});
7839
},
7840
7841
LogicalExpression: function(M) {
7842
return new AST_Binary({
7843
start: my_start_token(M),
7844
end: my_end_token(M),
7845
operator: M.operator,
7846
left: from_moz(M.left),
7847
right: from_moz(M.right)
7848
});
7849
},
7850
7851
AssignmentExpression: function(M) {
7852
return new AST_Assign({
7853
start: my_start_token(M),
7854
end: my_end_token(M),
7855
operator: M.operator,
7856
left: from_moz(M.left),
7857
right: from_moz(M.right)
7858
});
7859
},
7860
7861
ConditionalExpression: function(M) {
7862
return new AST_Conditional({
7863
start: my_start_token(M),
7864
end: my_end_token(M),
7865
condition: from_moz(M.test),
7866
consequent: from_moz(M.consequent),
7867
alternative: from_moz(M.alternate)
7868
});
7869
},
7870
7871
NewExpression: function(M) {
7872
return new AST_New({
7873
start: my_start_token(M),
7874
end: my_end_token(M),
7875
expression: from_moz(M.callee),
7876
args: M.arguments.map(from_moz)
7877
});
7878
},
7879
7880
CallExpression: function(M) {
7881
return new AST_Call({
7882
start: my_start_token(M),
7883
end: my_end_token(M),
7884
expression: from_moz(M.callee),
7885
optional: M.optional,
7886
args: M.arguments.map(from_moz)
7887
});
7888
},
7889
7890
ImportExpression: function(M) {
7891
let import_token = my_start_token(M);
7892
return new AST_Call({
7893
start : import_token,
7894
end : my_end_token(M),
7895
expression : new AST_SymbolRef({
7896
start : import_token,
7897
end : import_token,
7898
name : "import"
7899
}),
7900
args : [from_moz(M.source)]
7901
});
7902
}
7903
};
7904
7905
MOZ_TO_ME.UpdateExpression =
7906
MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) {
7907
var prefix = "prefix" in M ? M.prefix
7908
: M.type == "UnaryExpression" ? true : false;
7909
return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
7910
start : my_start_token(M),
7911
end : my_end_token(M),
7912
operator : M.operator,
7913
expression : from_moz(M.argument)
7914
});
7915
};
7916
7917
MOZ_TO_ME.ClassDeclaration =
7918
MOZ_TO_ME.ClassExpression = function From_Moz_Class(M) {
7919
return new (M.type === "ClassDeclaration" ? AST_DefClass : AST_ClassExpression)({
7920
start : my_start_token(M),
7921
end : my_end_token(M),
7922
name : from_moz(M.id),
7923
extends : from_moz(M.superClass),
7924
properties: M.body.body.map(from_moz)
7925
});
7926
};
7927
7928
def_to_moz(AST_EmptyStatement, function To_Moz_EmptyStatement() {
7929
return {
7930
type: "EmptyStatement"
7931
};
7932
});
7933
def_to_moz(AST_BlockStatement, function To_Moz_BlockStatement(M) {
7934
return {
7935
type: "BlockStatement",
7936
body: M.body.map(to_moz)
7937
};
7938
});
7939
def_to_moz(AST_If, function To_Moz_IfStatement(M) {
7940
return {
7941
type: "IfStatement",
7942
test: to_moz(M.condition),
7943
consequent: to_moz(M.body),
7944
alternate: to_moz(M.alternative)
7945
};
7946
});
7947
def_to_moz(AST_LabeledStatement, function To_Moz_LabeledStatement(M) {
7948
return {
7949
type: "LabeledStatement",
7950
label: to_moz(M.label),
7951
body: to_moz(M.body)
7952
};
7953
});
7954
def_to_moz(AST_Break, function To_Moz_BreakStatement(M) {
7955
return {
7956
type: "BreakStatement",
7957
label: to_moz(M.label)
7958
};
7959
});
7960
def_to_moz(AST_Continue, function To_Moz_ContinueStatement(M) {
7961
return {
7962
type: "ContinueStatement",
7963
label: to_moz(M.label)
7964
};
7965
});
7966
def_to_moz(AST_With, function To_Moz_WithStatement(M) {
7967
return {
7968
type: "WithStatement",
7969
object: to_moz(M.expression),
7970
body: to_moz(M.body)
7971
};
7972
});
7973
def_to_moz(AST_Switch, function To_Moz_SwitchStatement(M) {
7974
return {
7975
type: "SwitchStatement",
7976
discriminant: to_moz(M.expression),
7977
cases: M.body.map(to_moz)
7978
};
7979
});
7980
def_to_moz(AST_Return, function To_Moz_ReturnStatement(M) {
7981
return {
7982
type: "ReturnStatement",
7983
argument: to_moz(M.value)
7984
};
7985
});
7986
def_to_moz(AST_Throw, function To_Moz_ThrowStatement(M) {
7987
return {
7988
type: "ThrowStatement",
7989
argument: to_moz(M.value)
7990
};
7991
});
7992
def_to_moz(AST_While, function To_Moz_WhileStatement(M) {
7993
return {
7994
type: "WhileStatement",
7995
test: to_moz(M.condition),
7996
body: to_moz(M.body)
7997
};
7998
});
7999
def_to_moz(AST_Do, function To_Moz_DoWhileStatement(M) {
8000
return {
8001
type: "DoWhileStatement",
8002
test: to_moz(M.condition),
8003
body: to_moz(M.body)
8004
};
8005
});
8006
def_to_moz(AST_For, function To_Moz_ForStatement(M) {
8007
return {
8008
type: "ForStatement",
8009
init: to_moz(M.init),
8010
test: to_moz(M.condition),
8011
update: to_moz(M.step),
8012
body: to_moz(M.body)
8013
};
8014
});
8015
def_to_moz(AST_ForIn, function To_Moz_ForInStatement(M) {
8016
return {
8017
type: "ForInStatement",
8018
left: to_moz(M.init),
8019
right: to_moz(M.object),
8020
body: to_moz(M.body)
8021
};
8022
});
8023
def_to_moz(AST_ForOf, function To_Moz_ForOfStatement(M) {
8024
return {
8025
type: "ForOfStatement",
8026
left: to_moz(M.init),
8027
right: to_moz(M.object),
8028
body: to_moz(M.body),
8029
await: M.await
8030
};
8031
});
8032
def_to_moz(AST_Await, function To_Moz_AwaitExpression(M) {
8033
return {
8034
type: "AwaitExpression",
8035
argument: to_moz(M.expression)
8036
};
8037
});
8038
def_to_moz(AST_Yield, function To_Moz_YieldExpression(M) {
8039
return {
8040
type: "YieldExpression",
8041
argument: to_moz(M.expression),
8042
delegate: M.is_star
8043
};
8044
});
8045
def_to_moz(AST_Debugger, function To_Moz_DebuggerStatement() {
8046
return {
8047
type: "DebuggerStatement"
8048
};
8049
});
8050
def_to_moz(AST_VarDef, function To_Moz_VariableDeclarator(M) {
8051
return {
8052
type: "VariableDeclarator",
8053
id: to_moz(M.name),
8054
init: to_moz(M.value)
8055
};
8056
});
8057
def_to_moz(AST_Catch, function To_Moz_CatchClause(M) {
8058
return {
8059
type: "CatchClause",
8060
param: to_moz(M.argname),
8061
body: to_moz_block(M)
8062
};
8063
});
8064
8065
def_to_moz(AST_This, function To_Moz_ThisExpression() {
8066
return {
8067
type: "ThisExpression"
8068
};
8069
});
8070
def_to_moz(AST_Super, function To_Moz_Super() {
8071
return {
8072
type: "Super"
8073
};
8074
});
8075
def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {
8076
return {
8077
type: "BinaryExpression",
8078
operator: M.operator,
8079
left: to_moz(M.left),
8080
right: to_moz(M.right)
8081
};
8082
});
8083
def_to_moz(AST_Binary, function To_Moz_LogicalExpression(M) {
8084
return {
8085
type: "LogicalExpression",
8086
operator: M.operator,
8087
left: to_moz(M.left),
8088
right: to_moz(M.right)
8089
};
8090
});
8091
def_to_moz(AST_Assign, function To_Moz_AssignmentExpression(M) {
8092
return {
8093
type: "AssignmentExpression",
8094
operator: M.operator,
8095
left: to_moz(M.left),
8096
right: to_moz(M.right)
8097
};
8098
});
8099
def_to_moz(AST_Conditional, function To_Moz_ConditionalExpression(M) {
8100
return {
8101
type: "ConditionalExpression",
8102
test: to_moz(M.condition),
8103
consequent: to_moz(M.consequent),
8104
alternate: to_moz(M.alternative)
8105
};
8106
});
8107
def_to_moz(AST_New, function To_Moz_NewExpression(M) {
8108
return {
8109
type: "NewExpression",
8110
callee: to_moz(M.expression),
8111
arguments: M.args.map(to_moz)
8112
};
8113
});
8114
def_to_moz(AST_Call, function To_Moz_CallExpression(M) {
8115
return {
8116
type: "CallExpression",
8117
callee: to_moz(M.expression),
8118
optional: M.optional,
8119
arguments: M.args.map(to_moz)
8120
};
8121
});
8122
8123
def_to_moz(AST_Toplevel, function To_Moz_Program(M) {
8124
return to_moz_scope("Program", M);
8125
});
8126
8127
def_to_moz(AST_Expansion, function To_Moz_Spread(M) {
8128
return {
8129
type: to_moz_in_destructuring() ? "RestElement" : "SpreadElement",
8130
argument: to_moz(M.expression)
8131
};
8132
});
8133
8134
def_to_moz(AST_PrefixedTemplateString, function To_Moz_TaggedTemplateExpression(M) {
8135
return {
8136
type: "TaggedTemplateExpression",
8137
tag: to_moz(M.prefix),
8138
quasi: to_moz(M.template_string)
8139
};
8140
});
8141
8142
def_to_moz(AST_TemplateString, function To_Moz_TemplateLiteral(M) {
8143
var quasis = [];
8144
var expressions = [];
8145
for (var i = 0; i < M.segments.length; i++) {
8146
if (i % 2 !== 0) {
8147
expressions.push(to_moz(M.segments[i]));
8148
} else {
8149
quasis.push({
8150
type: "TemplateElement",
8151
value: {
8152
raw: M.segments[i].raw,
8153
cooked: M.segments[i].value
8154
},
8155
tail: i === M.segments.length - 1
8156
});
8157
}
8158
}
8159
return {
8160
type: "TemplateLiteral",
8161
quasis: quasis,
8162
expressions: expressions
8163
};
8164
});
8165
8166
def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) {
8167
return {
8168
type: "FunctionDeclaration",
8169
id: to_moz(M.name),
8170
params: M.argnames.map(to_moz),
8171
generator: M.is_generator,
8172
async: M.async,
8173
body: to_moz_scope("BlockStatement", M)
8174
};
8175
});
8176
8177
def_to_moz(AST_Function, function To_Moz_FunctionExpression(M, parent) {
8178
var is_generator = parent.is_generator !== undefined ?
8179
parent.is_generator : M.is_generator;
8180
return {
8181
type: "FunctionExpression",
8182
id: to_moz(M.name),
8183
params: M.argnames.map(to_moz),
8184
generator: is_generator,
8185
async: M.async,
8186
body: to_moz_scope("BlockStatement", M)
8187
};
8188
});
8189
8190
def_to_moz(AST_Arrow, function To_Moz_ArrowFunctionExpression(M) {
8191
var body = {
8192
type: "BlockStatement",
8193
body: M.body.map(to_moz)
8194
};
8195
return {
8196
type: "ArrowFunctionExpression",
8197
params: M.argnames.map(to_moz),
8198
async: M.async,
8199
body: body
8200
};
8201
});
8202
8203
def_to_moz(AST_Destructuring, function To_Moz_ObjectPattern(M) {
8204
if (M.is_array) {
8205
return {
8206
type: "ArrayPattern",
8207
elements: M.names.map(to_moz)
8208
};
8209
}
8210
return {
8211
type: "ObjectPattern",
8212
properties: M.names.map(to_moz)
8213
};
8214
});
8215
8216
def_to_moz(AST_Directive, function To_Moz_Directive(M) {
8217
return {
8218
type: "ExpressionStatement",
8219
expression: {
8220
type: "Literal",
8221
value: M.value,
8222
raw: M.print_to_string()
8223
},
8224
directive: M.value
8225
};
8226
});
8227
8228
def_to_moz(AST_SimpleStatement, function To_Moz_ExpressionStatement(M) {
8229
return {
8230
type: "ExpressionStatement",
8231
expression: to_moz(M.body)
8232
};
8233
});
8234
8235
def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) {
8236
return {
8237
type: "SwitchCase",
8238
test: to_moz(M.expression),
8239
consequent: M.body.map(to_moz)
8240
};
8241
});
8242
8243
def_to_moz(AST_Try, function To_Moz_TryStatement(M) {
8244
return {
8245
type: "TryStatement",
8246
block: to_moz_block(M.body),
8247
handler: to_moz(M.bcatch),
8248
guardedHandlers: [],
8249
finalizer: to_moz(M.bfinally)
8250
};
8251
});
8252
8253
def_to_moz(AST_Catch, function To_Moz_CatchClause(M) {
8254
return {
8255
type: "CatchClause",
8256
param: to_moz(M.argname),
8257
guard: null,
8258
body: to_moz_block(M)
8259
};
8260
});
8261
8262
def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
8263
return {
8264
type: "VariableDeclaration",
8265
kind:
8266
M instanceof AST_Const ? "const" :
8267
M instanceof AST_Let ? "let" : "var",
8268
declarations: M.definitions.map(to_moz)
8269
};
8270
});
8271
8272
const assert_clause_to_moz = assert_clause => {
8273
const assertions = [];
8274
if (assert_clause) {
8275
for (const { key, value } of assert_clause.properties) {
8276
const key_moz = is_basic_identifier_string(key)
8277
? { type: "Identifier", name: key }
8278
: { type: "Literal", value: key, raw: JSON.stringify(key) };
8279
assertions.push({
8280
type: "ImportAttribute",
8281
key: key_moz,
8282
value: to_moz(value)
8283
});
8284
}
8285
}
8286
return assertions;
8287
};
8288
8289
def_to_moz(AST_Export, function To_Moz_ExportDeclaration(M) {
8290
if (M.exported_names) {
8291
var first_exported = M.exported_names[0];
8292
var first_exported_name = first_exported.name;
8293
if (first_exported_name.name === "*" && !first_exported_name.quote) {
8294
var foreign_name = first_exported.foreign_name;
8295
var exported = foreign_name.name === "*" && !foreign_name.quote
8296
? null
8297
: to_moz(foreign_name);
8298
return {
8299
type: "ExportAllDeclaration",
8300
source: to_moz(M.module_name),
8301
exported: exported,
8302
assertions: assert_clause_to_moz(M.assert_clause)
8303
};
8304
}
8305
return {
8306
type: "ExportNamedDeclaration",
8307
specifiers: M.exported_names.map(function (name_mapping) {
8308
return {
8309
type: "ExportSpecifier",
8310
exported: to_moz(name_mapping.foreign_name),
8311
local: to_moz(name_mapping.name)
8312
};
8313
}),
8314
declaration: to_moz(M.exported_definition),
8315
source: to_moz(M.module_name),
8316
assertions: assert_clause_to_moz(M.assert_clause)
8317
};
8318
}
8319
return {
8320
type: M.is_default ? "ExportDefaultDeclaration" : "ExportNamedDeclaration",
8321
declaration: to_moz(M.exported_value || M.exported_definition)
8322
};
8323
});
8324
8325
def_to_moz(AST_Import, function To_Moz_ImportDeclaration(M) {
8326
var specifiers = [];
8327
if (M.imported_name) {
8328
specifiers.push({
8329
type: "ImportDefaultSpecifier",
8330
local: to_moz(M.imported_name)
8331
});
8332
}
8333
if (M.imported_names) {
8334
var first_imported_foreign_name = M.imported_names[0].foreign_name;
8335
if (first_imported_foreign_name.name === "*" && !first_imported_foreign_name.quote) {
8336
specifiers.push({
8337
type: "ImportNamespaceSpecifier",
8338
local: to_moz(M.imported_names[0].name)
8339
});
8340
} else {
8341
M.imported_names.forEach(function(name_mapping) {
8342
specifiers.push({
8343
type: "ImportSpecifier",
8344
local: to_moz(name_mapping.name),
8345
imported: to_moz(name_mapping.foreign_name)
8346
});
8347
});
8348
}
8349
}
8350
return {
8351
type: "ImportDeclaration",
8352
specifiers: specifiers,
8353
source: to_moz(M.module_name),
8354
assertions: assert_clause_to_moz(M.assert_clause)
8355
};
8356
});
8357
8358
def_to_moz(AST_ImportMeta, function To_Moz_MetaProperty() {
8359
return {
8360
type: "MetaProperty",
8361
meta: {
8362
type: "Identifier",
8363
name: "import"
8364
},
8365
property: {
8366
type: "Identifier",
8367
name: "meta"
8368
}
8369
};
8370
});
8371
8372
def_to_moz(AST_Sequence, function To_Moz_SequenceExpression(M) {
8373
return {
8374
type: "SequenceExpression",
8375
expressions: M.expressions.map(to_moz)
8376
};
8377
});
8378
8379
def_to_moz(AST_DotHash, function To_Moz_PrivateMemberExpression(M) {
8380
return {
8381
type: "MemberExpression",
8382
object: to_moz(M.expression),
8383
computed: false,
8384
property: {
8385
type: "PrivateIdentifier",
8386
name: M.property
8387
},
8388
optional: M.optional
8389
};
8390
});
8391
8392
def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) {
8393
var isComputed = M instanceof AST_Sub;
8394
return {
8395
type: "MemberExpression",
8396
object: to_moz(M.expression),
8397
computed: isComputed,
8398
property: isComputed ? to_moz(M.property) : {type: "Identifier", name: M.property},
8399
optional: M.optional
8400
};
8401
});
8402
8403
def_to_moz(AST_Chain, function To_Moz_ChainExpression(M) {
8404
return {
8405
type: "ChainExpression",
8406
expression: to_moz(M.expression)
8407
};
8408
});
8409
8410
def_to_moz(AST_Unary, function To_Moz_Unary(M) {
8411
return {
8412
type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression",
8413
operator: M.operator,
8414
prefix: M instanceof AST_UnaryPrefix,
8415
argument: to_moz(M.expression)
8416
};
8417
});
8418
8419
def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {
8420
if (M.operator == "=" && to_moz_in_destructuring()) {
8421
return {
8422
type: "AssignmentPattern",
8423
left: to_moz(M.left),
8424
right: to_moz(M.right)
8425
};
8426
}
8427
8428
const type = M.operator == "&&" || M.operator == "||" || M.operator === "??"
8429
? "LogicalExpression"
8430
: "BinaryExpression";
8431
8432
return {
8433
type,
8434
left: to_moz(M.left),
8435
operator: M.operator,
8436
right: to_moz(M.right)
8437
};
8438
});
8439
8440
def_to_moz(AST_PrivateIn, function To_Moz_BinaryExpression_PrivateIn(M) {
8441
return {
8442
type: "BinaryExpression",
8443
left: { type: "PrivateIdentifier", name: M.key.name },
8444
operator: "in",
8445
right: to_moz(M.value),
8446
};
8447
});
8448
8449
def_to_moz(AST_Array, function To_Moz_ArrayExpression(M) {
8450
return {
8451
type: "ArrayExpression",
8452
elements: M.elements.map(to_moz)
8453
};
8454
});
8455
8456
def_to_moz(AST_Object, function To_Moz_ObjectExpression(M) {
8457
return {
8458
type: "ObjectExpression",
8459
properties: M.properties.map(to_moz)
8460
};
8461
});
8462
8463
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M, parent) {
8464
var key = M.key instanceof AST_Node ? to_moz(M.key) : {
8465
type: "Identifier",
8466
value: M.key
8467
};
8468
if (typeof M.key === "number") {
8469
key = {
8470
type: "Literal",
8471
value: Number(M.key)
8472
};
8473
}
8474
if (typeof M.key === "string") {
8475
key = {
8476
type: "Identifier",
8477
name: M.key
8478
};
8479
}
8480
var kind;
8481
var string_or_num = typeof M.key === "string" || typeof M.key === "number";
8482
var computed = string_or_num ? false : !(M.key instanceof AST_Symbol) || M.key instanceof AST_SymbolRef;
8483
if (M instanceof AST_ObjectKeyVal) {
8484
kind = "init";
8485
computed = !string_or_num;
8486
} else
8487
if (M instanceof AST_ObjectGetter) {
8488
kind = "get";
8489
} else
8490
if (M instanceof AST_ObjectSetter) {
8491
kind = "set";
8492
}
8493
if (M instanceof AST_PrivateGetter || M instanceof AST_PrivateSetter) {
8494
const kind = M instanceof AST_PrivateGetter ? "get" : "set";
8495
return {
8496
type: "MethodDefinition",
8497
computed: false,
8498
kind: kind,
8499
static: M.static,
8500
key: {
8501
type: "PrivateIdentifier",
8502
name: M.key.name
8503
},
8504
value: to_moz(M.value)
8505
};
8506
}
8507
if (M instanceof AST_ClassPrivateProperty) {
8508
return {
8509
type: "PropertyDefinition",
8510
key: {
8511
type: "PrivateIdentifier",
8512
name: M.key.name
8513
},
8514
value: to_moz(M.value),
8515
computed: false,
8516
static: M.static
8517
};
8518
}
8519
if (M instanceof AST_ClassProperty) {
8520
return {
8521
type: "PropertyDefinition",
8522
key,
8523
value: to_moz(M.value),
8524
computed,
8525
static: M.static
8526
};
8527
}
8528
if (parent instanceof AST_Class) {
8529
return {
8530
type: "MethodDefinition",
8531
computed: computed,
8532
kind: kind,
8533
static: M.static,
8534
key: to_moz(M.key),
8535
value: to_moz(M.value)
8536
};
8537
}
8538
return {
8539
type: "Property",
8540
computed: computed,
8541
kind: kind,
8542
key: key,
8543
value: to_moz(M.value)
8544
};
8545
});
8546
8547
def_to_moz(AST_ConciseMethod, function To_Moz_MethodDefinition(M, parent) {
8548
if (parent instanceof AST_Object) {
8549
return {
8550
type: "Property",
8551
computed: !(M.key instanceof AST_Symbol) || M.key instanceof AST_SymbolRef,
8552
kind: "init",
8553
method: true,
8554
shorthand: false,
8555
key: to_moz(M.key),
8556
value: to_moz(M.value)
8557
};
8558
}
8559
8560
const key = M instanceof AST_PrivateMethod
8561
? {
8562
type: "PrivateIdentifier",
8563
name: M.key.name
8564
}
8565
: to_moz(M.key);
8566
8567
return {
8568
type: "MethodDefinition",
8569
kind: M.key === "constructor" ? "constructor" : "method",
8570
key,
8571
value: to_moz(M.value),
8572
computed: !(M.key instanceof AST_Symbol) || M.key instanceof AST_SymbolRef,
8573
static: M.static,
8574
};
8575
});
8576
8577
def_to_moz(AST_Class, function To_Moz_Class(M) {
8578
var type = M instanceof AST_ClassExpression ? "ClassExpression" : "ClassDeclaration";
8579
return {
8580
type: type,
8581
superClass: to_moz(M.extends),
8582
id: M.name ? to_moz(M.name) : null,
8583
body: {
8584
type: "ClassBody",
8585
body: M.properties.map(to_moz)
8586
}
8587
};
8588
});
8589
8590
def_to_moz(AST_ClassStaticBlock, function To_Moz_StaticBlock(M) {
8591
return {
8592
type: "StaticBlock",
8593
body: M.body.map(to_moz),
8594
};
8595
});
8596
8597
def_to_moz(AST_NewTarget, function To_Moz_MetaProperty() {
8598
return {
8599
type: "MetaProperty",
8600
meta: {
8601
type: "Identifier",
8602
name: "new"
8603
},
8604
property: {
8605
type: "Identifier",
8606
name: "target"
8607
}
8608
};
8609
});
8610
8611
def_to_moz(AST_Symbol, function To_Moz_Identifier(M, parent) {
8612
if (
8613
(M instanceof AST_SymbolMethod && parent.quote) ||
8614
((
8615
M instanceof AST_SymbolImportForeign ||
8616
M instanceof AST_SymbolExportForeign ||
8617
M instanceof AST_SymbolExport
8618
) && M.quote)
8619
) {
8620
return {
8621
type: "Literal",
8622
value: M.name
8623
};
8624
}
8625
var def = M.definition();
8626
return {
8627
type: "Identifier",
8628
name: def ? def.mangled_name || def.name : M.name
8629
};
8630
});
8631
8632
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
8633
const pattern = M.value.source;
8634
const flags = M.value.flags;
8635
return {
8636
type: "Literal",
8637
value: null,
8638
raw: M.print_to_string(),
8639
regex: { pattern, flags }
8640
};
8641
});
8642
8643
def_to_moz(AST_Constant, function To_Moz_Literal(M) {
8644
var value = M.value;
8645
return {
8646
type: "Literal",
8647
value: value,
8648
raw: M.raw || M.print_to_string()
8649
};
8650
});
8651
8652
def_to_moz(AST_Atom, function To_Moz_Atom(M) {
8653
return {
8654
type: "Identifier",
8655
name: String(M.value)
8656
};
8657
});
8658
8659
def_to_moz(AST_BigInt, M => ({
8660
type: "BigIntLiteral",
8661
value: M.value
8662
}));
8663
8664
AST_Boolean.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
8665
AST_Null.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
8666
AST_Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() { return null; });
8667
8668
AST_Block.DEFMETHOD("to_mozilla_ast", AST_BlockStatement.prototype.to_mozilla_ast);
8669
AST_Lambda.DEFMETHOD("to_mozilla_ast", AST_Function.prototype.to_mozilla_ast);
8670
8671
/* -----[ tools ]----- */
8672
8673
function my_start_token(moznode) {
8674
var loc = moznode.loc, start = loc && loc.start;
8675
var range = moznode.range;
8676
return new AST_Token(
8677
"",
8678
"",
8679
start && start.line || 0,
8680
start && start.column || 0,
8681
range ? range [0] : moznode.start,
8682
false,
8683
[],
8684
[],
8685
loc && loc.source,
8686
);
8687
}
8688
8689
function my_end_token(moznode) {
8690
var loc = moznode.loc, end = loc && loc.end;
8691
var range = moznode.range;
8692
return new AST_Token(
8693
"",
8694
"",
8695
end && end.line || 0,
8696
end && end.column || 0,
8697
range ? range [0] : moznode.end,
8698
false,
8699
[],
8700
[],
8701
loc && loc.source,
8702
);
8703
}
8704
8705
var FROM_MOZ_STACK = null;
8706
8707
function from_moz(node) {
8708
FROM_MOZ_STACK.push(node);
8709
var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
8710
FROM_MOZ_STACK.pop();
8711
return ret;
8712
}
8713
8714
AST_Node.from_mozilla_ast = function(node) {
8715
var save_stack = FROM_MOZ_STACK;
8716
FROM_MOZ_STACK = [];
8717
var ast = from_moz(node);
8718
FROM_MOZ_STACK = save_stack;
8719
return ast;
8720
};
8721
8722
function set_moz_loc(mynode, moznode) {
8723
var start = mynode.start;
8724
var end = mynode.end;
8725
if (!(start && end)) {
8726
return moznode;
8727
}
8728
if (start.pos != null && end.endpos != null) {
8729
moznode.range = [start.pos, end.endpos];
8730
}
8731
if (start.line) {
8732
moznode.loc = {
8733
start: {line: start.line, column: start.col},
8734
end: end.endline ? {line: end.endline, column: end.endcol} : null
8735
};
8736
if (start.file) {
8737
moznode.loc.source = start.file;
8738
}
8739
}
8740
return moznode;
8741
}
8742
8743
function def_to_moz(mytype, handler) {
8744
mytype.DEFMETHOD("to_mozilla_ast", function(parent) {
8745
return set_moz_loc(this, handler(this, parent));
8746
});
8747
}
8748
8749
var TO_MOZ_STACK = null;
8750
8751
function to_moz(node) {
8752
if (TO_MOZ_STACK === null) { TO_MOZ_STACK = []; }
8753
TO_MOZ_STACK.push(node);
8754
var ast = node != null ? node.to_mozilla_ast(TO_MOZ_STACK[TO_MOZ_STACK.length - 2]) : null;
8755
TO_MOZ_STACK.pop();
8756
if (TO_MOZ_STACK.length === 0) { TO_MOZ_STACK = null; }
8757
return ast;
8758
}
8759
8760
function to_moz_in_destructuring() {
8761
var i = TO_MOZ_STACK.length;
8762
while (i--) {
8763
if (TO_MOZ_STACK[i] instanceof AST_Destructuring) {
8764
return true;
8765
}
8766
}
8767
return false;
8768
}
8769
8770
function to_moz_block(node) {
8771
return {
8772
type: "BlockStatement",
8773
body: node.body.map(to_moz)
8774
};
8775
}
8776
8777
function to_moz_scope(type, node) {
8778
var body = node.body.map(to_moz);
8779
if (node.body[0] instanceof AST_SimpleStatement && node.body[0].body instanceof AST_String) {
8780
body.unshift(to_moz(new AST_EmptyStatement(node.body[0])));
8781
}
8782
return {
8783
type: type,
8784
body: body
8785
};
8786
}
8787
})();
8788
8789
// return true if the node at the top of the stack (that means the
8790
// innermost node in the current output) is lexically the first in
8791
// a statement.
8792
function first_in_statement(stack) {
8793
let node = stack.parent(-1);
8794
for (let i = 0, p; p = stack.parent(i); i++) {
8795
if (p instanceof AST_Statement && p.body === node)
8796
return true;
8797
if ((p instanceof AST_Sequence && p.expressions[0] === node) ||
8798
(p.TYPE === "Call" && p.expression === node) ||
8799
(p instanceof AST_PrefixedTemplateString && p.prefix === node) ||
8800
(p instanceof AST_Dot && p.expression === node) ||
8801
(p instanceof AST_Sub && p.expression === node) ||
8802
(p instanceof AST_Chain && p.expression === node) ||
8803
(p instanceof AST_Conditional && p.condition === node) ||
8804
(p instanceof AST_Binary && p.left === node) ||
8805
(p instanceof AST_UnaryPostfix && p.expression === node)
8806
) {
8807
node = p;
8808
} else {
8809
return false;
8810
}
8811
}
8812
}
8813
8814
// Returns whether the leftmost item in the expression is an object
8815
function left_is_object(node) {
8816
if (node instanceof AST_Object) return true;
8817
if (node instanceof AST_Sequence) return left_is_object(node.expressions[0]);
8818
if (node.TYPE === "Call") return left_is_object(node.expression);
8819
if (node instanceof AST_PrefixedTemplateString) return left_is_object(node.prefix);
8820
if (node instanceof AST_Dot || node instanceof AST_Sub) return left_is_object(node.expression);
8821
if (node instanceof AST_Chain) return left_is_object(node.expression);
8822
if (node instanceof AST_Conditional) return left_is_object(node.condition);
8823
if (node instanceof AST_Binary) return left_is_object(node.left);
8824
if (node instanceof AST_UnaryPostfix) return left_is_object(node.expression);
8825
return false;
8826
}
8827
8828
/***********************************************************************
8829
8830
A JavaScript tokenizer / parser / beautifier / compressor.
8831
https://github.com/mishoo/UglifyJS2
8832
8833
-------------------------------- (C) ---------------------------------
8834
8835
Author: Mihai Bazon
8836
<[email protected]>
8837
http://mihai.bazon.net/blog
8838
8839
Distributed under the BSD license:
8840
8841
Copyright 2012 (c) Mihai Bazon <[email protected]>
8842
8843
Redistribution and use in source and binary forms, with or without
8844
modification, are permitted provided that the following conditions
8845
are met:
8846
8847
* Redistributions of source code must retain the above
8848
copyright notice, this list of conditions and the following
8849
disclaimer.
8850
8851
* Redistributions in binary form must reproduce the above
8852
copyright notice, this list of conditions and the following
8853
disclaimer in the documentation and/or other materials
8854
provided with the distribution.
8855
8856
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
8857
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8858
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
8859
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
8860
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
8861
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
8862
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
8863
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
8864
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
8865
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
8866
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8867
SUCH DAMAGE.
8868
8869
***********************************************************************/
8870
8871
const EXPECT_DIRECTIVE = /^$|[;{][\s\n]*$/;
8872
const CODE_LINE_BREAK = 10;
8873
const CODE_SPACE = 32;
8874
8875
const r_annotation = /[@#]__(PURE|INLINE|NOINLINE)__/g;
8876
8877
function is_some_comments(comment) {
8878
// multiline comment
8879
return (
8880
(comment.type === "comment2" || comment.type === "comment1")
8881
&& /@preserve|@copyright|@lic|@cc_on|^\**!/i.test(comment.value)
8882
);
8883
}
8884
8885
class Rope {
8886
constructor() {
8887
this.committed = "";
8888
this.current = "";
8889
}
8890
8891
append(str) {
8892
this.current += str;
8893
}
8894
8895
insertAt(char, index) {
8896
const { committed, current } = this;
8897
if (index < committed.length) {
8898
this.committed = committed.slice(0, index) + char + committed.slice(index);
8899
} else if (index === committed.length) {
8900
this.committed += char;
8901
} else {
8902
index -= committed.length;
8903
this.committed += current.slice(0, index) + char;
8904
this.current = current.slice(index);
8905
}
8906
}
8907
8908
charAt(index) {
8909
const { committed } = this;
8910
if (index < committed.length) return committed[index];
8911
return this.current[index - committed.length];
8912
}
8913
8914
curLength() {
8915
return this.current.length;
8916
}
8917
8918
length() {
8919
return this.committed.length + this.current.length;
8920
}
8921
8922
toString() {
8923
return this.committed + this.current;
8924
}
8925
}
8926
8927
function OutputStream(options) {
8928
8929
var readonly = !options;
8930
options = defaults(options, {
8931
ascii_only : false,
8932
beautify : false,
8933
braces : false,
8934
comments : "some",
8935
ecma : 5,
8936
ie8 : false,
8937
indent_level : 4,
8938
indent_start : 0,
8939
inline_script : true,
8940
keep_numbers : false,
8941
keep_quoted_props : false,
8942
max_line_len : false,
8943
preamble : null,
8944
preserve_annotations : false,
8945
quote_keys : false,
8946
quote_style : 0,
8947
safari10 : false,
8948
semicolons : true,
8949
shebang : true,
8950
shorthand : undefined,
8951
source_map : null,
8952
webkit : false,
8953
width : 80,
8954
wrap_iife : false,
8955
wrap_func_args : true,
8956
8957
_destroy_ast : false
8958
}, true);
8959
8960
if (options.shorthand === undefined)
8961
options.shorthand = options.ecma > 5;
8962
8963
// Convert comment option to RegExp if necessary and set up comments filter
8964
var comment_filter = return_false; // Default case, throw all comments away
8965
if (options.comments) {
8966
let comments = options.comments;
8967
if (typeof options.comments === "string" && /^\/.*\/[a-zA-Z]*$/.test(options.comments)) {
8968
var regex_pos = options.comments.lastIndexOf("/");
8969
comments = new RegExp(
8970
options.comments.substr(1, regex_pos - 1),
8971
options.comments.substr(regex_pos + 1)
8972
);
8973
}
8974
if (comments instanceof RegExp) {
8975
comment_filter = function(comment) {
8976
return comment.type != "comment5" && comments.test(comment.value);
8977
};
8978
} else if (typeof comments === "function") {
8979
comment_filter = function(comment) {
8980
return comment.type != "comment5" && comments(this, comment);
8981
};
8982
} else if (comments === "some") {
8983
comment_filter = is_some_comments;
8984
} else { // NOTE includes "all" option
8985
comment_filter = return_true;
8986
}
8987
}
8988
8989
var indentation = 0;
8990
var current_col = 0;
8991
var current_line = 1;
8992
var current_pos = 0;
8993
var OUTPUT = new Rope();
8994
let printed_comments = new Set();
8995
8996
var to_utf8 = options.ascii_only ? function(str, identifier = false, regexp = false) {
8997
if (options.ecma >= 2015 && !options.safari10 && !regexp) {
8998
str = str.replace(/[\ud800-\udbff][\udc00-\udfff]/g, function(ch) {
8999
var code = get_full_char_code(ch, 0).toString(16);
9000
return "\\u{" + code + "}";
9001
});
9002
}
9003
return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
9004
var code = ch.charCodeAt(0).toString(16);
9005
if (code.length <= 2 && !identifier) {
9006
while (code.length < 2) code = "0" + code;
9007
return "\\x" + code;
9008
} else {
9009
while (code.length < 4) code = "0" + code;
9010
return "\\u" + code;
9011
}
9012
});
9013
} : function(str) {
9014
return str.replace(/[\ud800-\udbff][\udc00-\udfff]|([\ud800-\udbff]|[\udc00-\udfff])/g, function(match, lone) {
9015
if (lone) {
9016
return "\\u" + lone.charCodeAt(0).toString(16);
9017
}
9018
return match;
9019
});
9020
};
9021
9022
function make_string(str, quote) {
9023
var dq = 0, sq = 0;
9024
str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g,
9025
function(s, i) {
9026
switch (s) {
9027
case '"': ++dq; return '"';
9028
case "'": ++sq; return "'";
9029
case "\\": return "\\\\";
9030
case "\n": return "\\n";
9031
case "\r": return "\\r";
9032
case "\t": return "\\t";
9033
case "\b": return "\\b";
9034
case "\f": return "\\f";
9035
case "\x0B": return options.ie8 ? "\\x0B" : "\\v";
9036
case "\u2028": return "\\u2028";
9037
case "\u2029": return "\\u2029";
9038
case "\ufeff": return "\\ufeff";
9039
case "\0":
9040
return /[0-9]/.test(get_full_char(str, i+1)) ? "\\x00" : "\\0";
9041
}
9042
return s;
9043
});
9044
function quote_single() {
9045
return "'" + str.replace(/\x27/g, "\\'") + "'";
9046
}
9047
function quote_double() {
9048
return '"' + str.replace(/\x22/g, '\\"') + '"';
9049
}
9050
function quote_template() {
9051
return "`" + str.replace(/`/g, "\\`") + "`";
9052
}
9053
str = to_utf8(str);
9054
if (quote === "`") return quote_template();
9055
switch (options.quote_style) {
9056
case 1:
9057
return quote_single();
9058
case 2:
9059
return quote_double();
9060
case 3:
9061
return quote == "'" ? quote_single() : quote_double();
9062
default:
9063
return dq > sq ? quote_single() : quote_double();
9064
}
9065
}
9066
9067
function encode_string(str, quote) {
9068
var ret = make_string(str, quote);
9069
if (options.inline_script) {
9070
ret = ret.replace(/<\x2f(script)([>\/\t\n\f\r ])/gi, "<\\/$1$2");
9071
ret = ret.replace(/\x3c!--/g, "\\x3c!--");
9072
ret = ret.replace(/--\x3e/g, "--\\x3e");
9073
}
9074
return ret;
9075
}
9076
9077
function make_name(name) {
9078
name = name.toString();
9079
name = to_utf8(name, true);
9080
return name;
9081
}
9082
9083
function make_indent(back) {
9084
return " ".repeat(options.indent_start + indentation - back * options.indent_level);
9085
}
9086
9087
/* -----[ beautification/minification ]----- */
9088
9089
var has_parens = false;
9090
var might_need_space = false;
9091
var might_need_semicolon = false;
9092
var might_add_newline = 0;
9093
var need_newline_indented = false;
9094
var need_space = false;
9095
var newline_insert = -1;
9096
var last = "";
9097
var mapping_token, mapping_name, mappings = options.source_map && [];
9098
9099
var do_add_mapping = mappings ? function() {
9100
mappings.forEach(function(mapping) {
9101
try {
9102
let { name, token } = mapping;
9103
if (token.type == "name" || token.type === "privatename") {
9104
name = token.value;
9105
} else if (name instanceof AST_Symbol) {
9106
name = token.type === "string" ? token.value : name.name;
9107
}
9108
options.source_map.add(
9109
mapping.token.file,
9110
mapping.line, mapping.col,
9111
mapping.token.line, mapping.token.col,
9112
is_basic_identifier_string(name) ? name : undefined
9113
);
9114
} catch(ex) {
9115
// Ignore bad mapping
9116
}
9117
});
9118
mappings = [];
9119
} : noop;
9120
9121
var ensure_line_len = options.max_line_len ? function() {
9122
if (current_col > options.max_line_len) {
9123
if (might_add_newline) {
9124
OUTPUT.insertAt("\n", might_add_newline);
9125
const curLength = OUTPUT.curLength();
9126
if (mappings) {
9127
var delta = curLength - current_col;
9128
mappings.forEach(function(mapping) {
9129
mapping.line++;
9130
mapping.col += delta;
9131
});
9132
}
9133
current_line++;
9134
current_pos++;
9135
current_col = curLength;
9136
}
9137
}
9138
if (might_add_newline) {
9139
might_add_newline = 0;
9140
do_add_mapping();
9141
}
9142
} : noop;
9143
9144
var requireSemicolonChars = makePredicate("( [ + * / - , . `");
9145
9146
function print(str) {
9147
str = String(str);
9148
var ch = get_full_char(str, 0);
9149
if (need_newline_indented && ch) {
9150
need_newline_indented = false;
9151
if (ch !== "\n") {
9152
print("\n");
9153
indent();
9154
}
9155
}
9156
if (need_space && ch) {
9157
need_space = false;
9158
if (!/[\s;})]/.test(ch)) {
9159
space();
9160
}
9161
}
9162
newline_insert = -1;
9163
var prev = last.charAt(last.length - 1);
9164
if (might_need_semicolon) {
9165
might_need_semicolon = false;
9166
9167
if (prev === ":" && ch === "}" || (!ch || !";}".includes(ch)) && prev !== ";") {
9168
if (options.semicolons || requireSemicolonChars.has(ch)) {
9169
OUTPUT.append(";");
9170
current_col++;
9171
current_pos++;
9172
} else {
9173
ensure_line_len();
9174
if (current_col > 0) {
9175
OUTPUT.append("\n");
9176
current_pos++;
9177
current_line++;
9178
current_col = 0;
9179
}
9180
9181
if (/^\s+$/.test(str)) {
9182
// reset the semicolon flag, since we didn't print one
9183
// now and might still have to later
9184
might_need_semicolon = true;
9185
}
9186
}
9187
9188
if (!options.beautify)
9189
might_need_space = false;
9190
}
9191
}
9192
9193
if (might_need_space) {
9194
if ((is_identifier_char(prev)
9195
&& (is_identifier_char(ch) || ch == "\\"))
9196
|| (ch == "/" && ch == prev)
9197
|| ((ch == "+" || ch == "-") && ch == last)
9198
) {
9199
OUTPUT.append(" ");
9200
current_col++;
9201
current_pos++;
9202
}
9203
might_need_space = false;
9204
}
9205
9206
if (mapping_token) {
9207
mappings.push({
9208
token: mapping_token,
9209
name: mapping_name,
9210
line: current_line,
9211
col: current_col
9212
});
9213
mapping_token = false;
9214
if (!might_add_newline) do_add_mapping();
9215
}
9216
9217
OUTPUT.append(str);
9218
has_parens = str[str.length - 1] == "(";
9219
current_pos += str.length;
9220
var a = str.split(/\r?\n/), n = a.length - 1;
9221
current_line += n;
9222
current_col += a[0].length;
9223
if (n > 0) {
9224
ensure_line_len();
9225
current_col = a[n].length;
9226
}
9227
last = str;
9228
}
9229
9230
var star = function() {
9231
print("*");
9232
};
9233
9234
var space = options.beautify ? function() {
9235
print(" ");
9236
} : function() {
9237
might_need_space = true;
9238
};
9239
9240
var indent = options.beautify ? function(half) {
9241
if (options.beautify) {
9242
print(make_indent(half ? 0.5 : 0));
9243
}
9244
} : noop;
9245
9246
var with_indent = options.beautify ? function(col, cont) {
9247
if (col === true) col = next_indent();
9248
var save_indentation = indentation;
9249
indentation = col;
9250
var ret = cont();
9251
indentation = save_indentation;
9252
return ret;
9253
} : function(col, cont) { return cont(); };
9254
9255
var newline = options.beautify ? function() {
9256
if (newline_insert < 0) return print("\n");
9257
if (OUTPUT.charAt(newline_insert) != "\n") {
9258
OUTPUT.insertAt("\n", newline_insert);
9259
current_pos++;
9260
current_line++;
9261
}
9262
newline_insert++;
9263
} : options.max_line_len ? function() {
9264
ensure_line_len();
9265
might_add_newline = OUTPUT.length();
9266
} : noop;
9267
9268
var semicolon = options.beautify ? function() {
9269
print(";");
9270
} : function() {
9271
might_need_semicolon = true;
9272
};
9273
9274
function force_semicolon() {
9275
might_need_semicolon = false;
9276
print(";");
9277
}
9278
9279
function next_indent() {
9280
return indentation + options.indent_level;
9281
}
9282
9283
function with_block(cont) {
9284
var ret;
9285
print("{");
9286
newline();
9287
with_indent(next_indent(), function() {
9288
ret = cont();
9289
});
9290
indent();
9291
print("}");
9292
return ret;
9293
}
9294
9295
function with_parens(cont) {
9296
print("(");
9297
//XXX: still nice to have that for argument lists
9298
//var ret = with_indent(current_col, cont);
9299
var ret = cont();
9300
print(")");
9301
return ret;
9302
}
9303
9304
function with_square(cont) {
9305
print("[");
9306
//var ret = with_indent(current_col, cont);
9307
var ret = cont();
9308
print("]");
9309
return ret;
9310
}
9311
9312
function comma() {
9313
print(",");
9314
space();
9315
}
9316
9317
function colon() {
9318
print(":");
9319
space();
9320
}
9321
9322
var add_mapping = mappings ? function(token, name) {
9323
mapping_token = token;
9324
mapping_name = name;
9325
} : noop;
9326
9327
function get() {
9328
if (might_add_newline) {
9329
ensure_line_len();
9330
}
9331
return OUTPUT.toString();
9332
}
9333
9334
function has_nlb() {
9335
const output = OUTPUT.toString();
9336
let n = output.length - 1;
9337
while (n >= 0) {
9338
const code = output.charCodeAt(n);
9339
if (code === CODE_LINE_BREAK) {
9340
return true;
9341
}
9342
9343
if (code !== CODE_SPACE) {
9344
return false;
9345
}
9346
n--;
9347
}
9348
return true;
9349
}
9350
9351
function filter_comment(comment) {
9352
if (!options.preserve_annotations) {
9353
comment = comment.replace(r_annotation, " ");
9354
}
9355
if (/^\s*$/.test(comment)) {
9356
return "";
9357
}
9358
return comment.replace(/(<\s*\/\s*)(script)/i, "<\\/$2");
9359
}
9360
9361
function prepend_comments(node) {
9362
var self = this;
9363
var start = node.start;
9364
if (!start) return;
9365
var printed_comments = self.printed_comments;
9366
9367
// There cannot be a newline between return/yield and its value.
9368
const keyword_with_value =
9369
node instanceof AST_Exit && node.value
9370
|| (node instanceof AST_Await || node instanceof AST_Yield)
9371
&& node.expression;
9372
9373
if (
9374
start.comments_before
9375
&& printed_comments.has(start.comments_before)
9376
) {
9377
if (keyword_with_value) {
9378
start.comments_before = [];
9379
} else {
9380
return;
9381
}
9382
}
9383
9384
var comments = start.comments_before;
9385
if (!comments) {
9386
comments = start.comments_before = [];
9387
}
9388
printed_comments.add(comments);
9389
9390
if (keyword_with_value) {
9391
var tw = new TreeWalker(function(node) {
9392
var parent = tw.parent();
9393
if (parent instanceof AST_Exit
9394
|| parent instanceof AST_Await
9395
|| parent instanceof AST_Yield
9396
|| parent instanceof AST_Binary && parent.left === node
9397
|| parent.TYPE == "Call" && parent.expression === node
9398
|| parent instanceof AST_Conditional && parent.condition === node
9399
|| parent instanceof AST_Dot && parent.expression === node
9400
|| parent instanceof AST_Sequence && parent.expressions[0] === node
9401
|| parent instanceof AST_Sub && parent.expression === node
9402
|| parent instanceof AST_UnaryPostfix) {
9403
if (!node.start) return;
9404
var text = node.start.comments_before;
9405
if (text && !printed_comments.has(text)) {
9406
printed_comments.add(text);
9407
comments = comments.concat(text);
9408
}
9409
} else {
9410
return true;
9411
}
9412
});
9413
tw.push(node);
9414
keyword_with_value.walk(tw);
9415
}
9416
9417
if (current_pos == 0) {
9418
if (comments.length > 0 && options.shebang && comments[0].type === "comment5"
9419
&& !printed_comments.has(comments[0])) {
9420
print("#!" + comments.shift().value + "\n");
9421
indent();
9422
}
9423
var preamble = options.preamble;
9424
if (preamble) {
9425
print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
9426
}
9427
}
9428
9429
comments = comments.filter(comment_filter, node).filter(c => !printed_comments.has(c));
9430
if (comments.length == 0) return;
9431
var last_nlb = has_nlb();
9432
comments.forEach(function(c, i) {
9433
printed_comments.add(c);
9434
if (!last_nlb) {
9435
if (c.nlb) {
9436
print("\n");
9437
indent();
9438
last_nlb = true;
9439
} else if (i > 0) {
9440
space();
9441
}
9442
}
9443
9444
if (/comment[134]/.test(c.type)) {
9445
var value = filter_comment(c.value);
9446
if (value) {
9447
print("//" + value + "\n");
9448
indent();
9449
}
9450
last_nlb = true;
9451
} else if (c.type == "comment2") {
9452
var value = filter_comment(c.value);
9453
if (value) {
9454
print("/*" + value + "*/");
9455
}
9456
last_nlb = false;
9457
}
9458
});
9459
if (!last_nlb) {
9460
if (start.nlb) {
9461
print("\n");
9462
indent();
9463
} else {
9464
space();
9465
}
9466
}
9467
}
9468
9469
function append_comments(node, tail) {
9470
var self = this;
9471
var token = node.end;
9472
if (!token) return;
9473
var printed_comments = self.printed_comments;
9474
var comments = token[tail ? "comments_before" : "comments_after"];
9475
if (!comments || printed_comments.has(comments)) return;
9476
if (!(node instanceof AST_Statement || comments.every((c) =>
9477
!/comment[134]/.test(c.type)
9478
))) return;
9479
printed_comments.add(comments);
9480
var insert = OUTPUT.length();
9481
comments.filter(comment_filter, node).forEach(function(c, i) {
9482
if (printed_comments.has(c)) return;
9483
printed_comments.add(c);
9484
need_space = false;
9485
if (need_newline_indented) {
9486
print("\n");
9487
indent();
9488
need_newline_indented = false;
9489
} else if (c.nlb && (i > 0 || !has_nlb())) {
9490
print("\n");
9491
indent();
9492
} else if (i > 0 || !tail) {
9493
space();
9494
}
9495
if (/comment[134]/.test(c.type)) {
9496
const value = filter_comment(c.value);
9497
if (value) {
9498
print("//" + value);
9499
}
9500
need_newline_indented = true;
9501
} else if (c.type == "comment2") {
9502
const value = filter_comment(c.value);
9503
if (value) {
9504
print("/*" + value + "*/");
9505
}
9506
need_space = true;
9507
}
9508
});
9509
if (OUTPUT.length() > insert) newline_insert = insert;
9510
}
9511
9512
/**
9513
* When output.option("_destroy_ast") is enabled, destroy the function.
9514
* Call this after printing it.
9515
*/
9516
const gc_scope =
9517
options["_destroy_ast"]
9518
? function gc_scope(scope) {
9519
scope.body.length = 0;
9520
scope.argnames.length = 0;
9521
}
9522
: noop;
9523
9524
var stack = [];
9525
return {
9526
get : get,
9527
toString : get,
9528
indent : indent,
9529
in_directive : false,
9530
use_asm : null,
9531
active_scope : null,
9532
indentation : function() { return indentation; },
9533
current_width : function() { return current_col - indentation; },
9534
should_break : function() { return options.width && this.current_width() >= options.width; },
9535
has_parens : function() { return has_parens; },
9536
newline : newline,
9537
print : print,
9538
star : star,
9539
space : space,
9540
comma : comma,
9541
colon : colon,
9542
last : function() { return last; },
9543
semicolon : semicolon,
9544
force_semicolon : force_semicolon,
9545
to_utf8 : to_utf8,
9546
print_name : function(name) { print(make_name(name)); },
9547
print_string : function(str, quote, escape_directive) {
9548
var encoded = encode_string(str, quote);
9549
if (escape_directive === true && !encoded.includes("\\")) {
9550
// Insert semicolons to break directive prologue
9551
if (!EXPECT_DIRECTIVE.test(OUTPUT.toString())) {
9552
force_semicolon();
9553
}
9554
force_semicolon();
9555
}
9556
print(encoded);
9557
},
9558
print_template_string_chars: function(str) {
9559
var encoded = encode_string(str, "`").replace(/\${/g, "\\${");
9560
return print(encoded.substr(1, encoded.length - 2));
9561
},
9562
encode_string : encode_string,
9563
next_indent : next_indent,
9564
with_indent : with_indent,
9565
with_block : with_block,
9566
with_parens : with_parens,
9567
with_square : with_square,
9568
add_mapping : add_mapping,
9569
option : function(opt) { return options[opt]; },
9570
gc_scope,
9571
printed_comments: printed_comments,
9572
prepend_comments: readonly ? noop : prepend_comments,
9573
append_comments : readonly || comment_filter === return_false ? noop : append_comments,
9574
line : function() { return current_line; },
9575
col : function() { return current_col; },
9576
pos : function() { return current_pos; },
9577
push_node : function(node) { stack.push(node); },
9578
pop_node : function() { return stack.pop(); },
9579
parent : function(n) {
9580
return stack[stack.length - 2 - (n || 0)];
9581
}
9582
};
9583
9584
}
9585
9586
/* -----[ code generators ]----- */
9587
9588
(function() {
9589
9590
/* -----[ utils ]----- */
9591
9592
function DEFPRINT(nodetype, generator) {
9593
nodetype.DEFMETHOD("_codegen", generator);
9594
}
9595
9596
AST_Node.DEFMETHOD("print", function(output, force_parens) {
9597
var self = this, generator = self._codegen;
9598
if (self instanceof AST_Scope) {
9599
output.active_scope = self;
9600
} else if (!output.use_asm && self instanceof AST_Directive && self.value == "use asm") {
9601
output.use_asm = output.active_scope;
9602
}
9603
function doit() {
9604
output.prepend_comments(self);
9605
self.add_source_map(output);
9606
generator(self, output);
9607
output.append_comments(self);
9608
}
9609
output.push_node(self);
9610
if (force_parens || self.needs_parens(output)) {
9611
output.with_parens(doit);
9612
} else {
9613
doit();
9614
}
9615
output.pop_node();
9616
if (self === output.use_asm) {
9617
output.use_asm = null;
9618
}
9619
});
9620
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
9621
9622
AST_Node.DEFMETHOD("print_to_string", function(options) {
9623
var output = OutputStream(options);
9624
this.print(output);
9625
return output.get();
9626
});
9627
9628
/* -----[ PARENTHESES ]----- */
9629
9630
function PARENS(nodetype, func) {
9631
if (Array.isArray(nodetype)) {
9632
nodetype.forEach(function(nodetype) {
9633
PARENS(nodetype, func);
9634
});
9635
} else {
9636
nodetype.DEFMETHOD("needs_parens", func);
9637
}
9638
}
9639
9640
PARENS(AST_Node, return_false);
9641
9642
// a function expression needs parens around it when it's provably
9643
// the first token to appear in a statement.
9644
PARENS(AST_Function, function(output) {
9645
if (!output.has_parens() && first_in_statement(output)) {
9646
return true;
9647
}
9648
9649
if (output.option("webkit")) {
9650
var p = output.parent();
9651
if (p instanceof AST_PropAccess && p.expression === this) {
9652
return true;
9653
}
9654
}
9655
9656
if (output.option("wrap_iife")) {
9657
var p = output.parent();
9658
if (p instanceof AST_Call && p.expression === this) {
9659
return true;
9660
}
9661
}
9662
9663
if (output.option("wrap_func_args")) {
9664
var p = output.parent();
9665
if (p instanceof AST_Call && p.args.includes(this)) {
9666
return true;
9667
}
9668
}
9669
9670
return false;
9671
});
9672
9673
PARENS(AST_Arrow, function(output) {
9674
var p = output.parent();
9675
9676
if (
9677
output.option("wrap_func_args")
9678
&& p instanceof AST_Call
9679
&& p.args.includes(this)
9680
) {
9681
return true;
9682
}
9683
return p instanceof AST_PropAccess && p.expression === this;
9684
});
9685
9686
// same goes for an object literal (as in AST_Function), because
9687
// otherwise {...} would be interpreted as a block of code.
9688
PARENS(AST_Object, function(output) {
9689
return !output.has_parens() && first_in_statement(output);
9690
});
9691
9692
PARENS(AST_ClassExpression, first_in_statement);
9693
9694
PARENS(AST_Unary, function(output) {
9695
var p = output.parent();
9696
return p instanceof AST_PropAccess && p.expression === this
9697
|| p instanceof AST_Call && p.expression === this
9698
|| p instanceof AST_Binary
9699
&& p.operator === "**"
9700
&& this instanceof AST_UnaryPrefix
9701
&& p.left === this
9702
&& this.operator !== "++"
9703
&& this.operator !== "--";
9704
});
9705
9706
PARENS(AST_Await, function(output) {
9707
var p = output.parent();
9708
return p instanceof AST_PropAccess && p.expression === this
9709
|| p instanceof AST_Call && p.expression === this
9710
|| p instanceof AST_Binary && p.operator === "**" && p.left === this
9711
|| output.option("safari10") && p instanceof AST_UnaryPrefix;
9712
});
9713
9714
PARENS(AST_Sequence, function(output) {
9715
var p = output.parent();
9716
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
9717
|| p instanceof AST_Unary // !(foo, bar, baz)
9718
|| p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8
9719
|| p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4
9720
|| p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
9721
|| p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
9722
|| p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2
9723
|| p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)
9724
* ==> 20 (side effect, set a := 10 and b := 20) */
9725
|| p instanceof AST_Arrow // x => (x, x)
9726
|| p instanceof AST_DefaultAssign // x => (x = (0, function(){}))
9727
|| p instanceof AST_Expansion // [...(a, b)]
9728
|| p instanceof AST_ForOf && this === p.object // for (e of (foo, bar)) {}
9729
|| p instanceof AST_Yield // yield (foo, bar)
9730
|| p instanceof AST_Export // export default (foo, bar)
9731
;
9732
});
9733
9734
PARENS(AST_Binary, function(output) {
9735
var p = output.parent();
9736
// (foo && bar)()
9737
if (p instanceof AST_Call && p.expression === this)
9738
return true;
9739
// typeof (foo && bar)
9740
if (p instanceof AST_Unary)
9741
return true;
9742
// (foo && bar)["prop"], (foo && bar).prop
9743
if (p instanceof AST_PropAccess && p.expression === this)
9744
return true;
9745
// this deals with precedence: 3 * (2 + 1)
9746
if (p instanceof AST_Binary) {
9747
const po = p.operator;
9748
const so = this.operator;
9749
9750
if (so === "??" && (po === "||" || po === "&&")) {
9751
return true;
9752
}
9753
9754
if (po === "??" && (so === "||" || so === "&&")) {
9755
return true;
9756
}
9757
9758
const pp = PRECEDENCE[po];
9759
const sp = PRECEDENCE[so];
9760
if (pp > sp
9761
|| (pp == sp
9762
&& (this === p.right || po == "**"))) {
9763
return true;
9764
}
9765
}
9766
});
9767
9768
PARENS(AST_Yield, function(output) {
9769
var p = output.parent();
9770
// (yield 1) + (yield 2)
9771
// a = yield 3
9772
if (p instanceof AST_Binary && p.operator !== "=")
9773
return true;
9774
// (yield 1)()
9775
// new (yield 1)()
9776
if (p instanceof AST_Call && p.expression === this)
9777
return true;
9778
// (yield 1) ? yield 2 : yield 3
9779
if (p instanceof AST_Conditional && p.condition === this)
9780
return true;
9781
// -(yield 4)
9782
if (p instanceof AST_Unary)
9783
return true;
9784
// (yield x).foo
9785
// (yield x)['foo']
9786
if (p instanceof AST_PropAccess && p.expression === this)
9787
return true;
9788
});
9789
9790
PARENS(AST_Chain, function(output) {
9791
var p = output.parent();
9792
if (!(p instanceof AST_Call || p instanceof AST_PropAccess)) return false;
9793
return p.expression === this;
9794
});
9795
9796
PARENS(AST_PropAccess, function(output) {
9797
var p = output.parent();
9798
if (p instanceof AST_New && p.expression === this) {
9799
// i.e. new (foo.bar().baz)
9800
//
9801
// if there's one call into this subtree, then we need
9802
// parens around it too, otherwise the call will be
9803
// interpreted as passing the arguments to the upper New
9804
// expression.
9805
return walk(this, node => {
9806
if (node instanceof AST_Scope) return true;
9807
if (node instanceof AST_Call) {
9808
return walk_abort; // makes walk() return true.
9809
}
9810
});
9811
}
9812
});
9813
9814
PARENS(AST_Call, function(output) {
9815
var p = output.parent(), p1;
9816
if (p instanceof AST_New && p.expression === this
9817
|| p instanceof AST_Export && p.is_default && this.expression instanceof AST_Function)
9818
return true;
9819
9820
// workaround for Safari bug.
9821
// https://bugs.webkit.org/show_bug.cgi?id=123506
9822
return this.expression instanceof AST_Function
9823
&& p instanceof AST_PropAccess
9824
&& p.expression === this
9825
&& (p1 = output.parent(1)) instanceof AST_Assign
9826
&& p1.left === p;
9827
});
9828
9829
PARENS(AST_New, function(output) {
9830
var p = output.parent();
9831
if (this.args.length === 0
9832
&& (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]()
9833
|| p instanceof AST_Call && p.expression === this
9834
|| p instanceof AST_PrefixedTemplateString && p.prefix === this)) // (new foo)(bar)
9835
return true;
9836
});
9837
9838
PARENS(AST_Number, function(output) {
9839
var p = output.parent();
9840
if (p instanceof AST_PropAccess && p.expression === this) {
9841
var value = this.getValue();
9842
if (value < 0 || /^0/.test(make_num(value))) {
9843
return true;
9844
}
9845
}
9846
});
9847
9848
PARENS(AST_BigInt, function(output) {
9849
var p = output.parent();
9850
if (p instanceof AST_PropAccess && p.expression === this) {
9851
var value = this.getValue();
9852
if (value.startsWith("-")) {
9853
return true;
9854
}
9855
}
9856
});
9857
9858
PARENS([ AST_Assign, AST_Conditional ], function(output) {
9859
var p = output.parent();
9860
// !(a = false) → true
9861
if (p instanceof AST_Unary)
9862
return true;
9863
// 1 + (a = 2) + 3 → 6, side effect setting a = 2
9864
if (p instanceof AST_Binary && !(p instanceof AST_Assign))
9865
return true;
9866
// (a = func)() —or— new (a = Object)()
9867
if (p instanceof AST_Call && p.expression === this)
9868
return true;
9869
// (a = foo) ? bar : baz
9870
if (p instanceof AST_Conditional && p.condition === this)
9871
return true;
9872
// (a = foo)["prop"] —or— (a = foo).prop
9873
if (p instanceof AST_PropAccess && p.expression === this)
9874
return true;
9875
// ({a, b} = {a: 1, b: 2}), a destructuring assignment
9876
if (this instanceof AST_Assign && this.left instanceof AST_Destructuring && this.left.is_array === false)
9877
return true;
9878
});
9879
9880
/* -----[ PRINTERS ]----- */
9881
9882
DEFPRINT(AST_Directive, function(self, output) {
9883
output.print_string(self.value, self.quote);
9884
output.semicolon();
9885
});
9886
9887
DEFPRINT(AST_Expansion, function (self, output) {
9888
output.print("...");
9889
self.expression.print(output);
9890
});
9891
9892
DEFPRINT(AST_Destructuring, function (self, output) {
9893
output.print(self.is_array ? "[" : "{");
9894
var len = self.names.length;
9895
self.names.forEach(function (name, i) {
9896
if (i > 0) output.comma();
9897
name.print(output);
9898
// If the final element is a hole, we need to make sure it
9899
// doesn't look like a trailing comma, by inserting an actual
9900
// trailing comma.
9901
if (i == len - 1 && name instanceof AST_Hole) output.comma();
9902
});
9903
output.print(self.is_array ? "]" : "}");
9904
});
9905
9906
DEFPRINT(AST_Debugger, function(self, output) {
9907
output.print("debugger");
9908
output.semicolon();
9909
});
9910
9911
/* -----[ statements ]----- */
9912
9913
function display_body(body, is_toplevel, output, allow_directives) {
9914
var last = body.length - 1;
9915
output.in_directive = allow_directives;
9916
body.forEach(function(stmt, i) {
9917
if (output.in_directive === true && !(stmt instanceof AST_Directive ||
9918
stmt instanceof AST_EmptyStatement ||
9919
(stmt instanceof AST_SimpleStatement && stmt.body instanceof AST_String)
9920
)) {
9921
output.in_directive = false;
9922
}
9923
if (!(stmt instanceof AST_EmptyStatement)) {
9924
output.indent();
9925
stmt.print(output);
9926
if (!(i == last && is_toplevel)) {
9927
output.newline();
9928
if (is_toplevel) output.newline();
9929
}
9930
}
9931
if (output.in_directive === true &&
9932
stmt instanceof AST_SimpleStatement &&
9933
stmt.body instanceof AST_String
9934
) {
9935
output.in_directive = false;
9936
}
9937
});
9938
output.in_directive = false;
9939
}
9940
9941
AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
9942
print_maybe_braced_body(this.body, output);
9943
});
9944
9945
DEFPRINT(AST_Statement, function(self, output) {
9946
self.body.print(output);
9947
output.semicolon();
9948
});
9949
DEFPRINT(AST_Toplevel, function(self, output) {
9950
display_body(self.body, true, output, true);
9951
output.print("");
9952
});
9953
DEFPRINT(AST_LabeledStatement, function(self, output) {
9954
self.label.print(output);
9955
output.colon();
9956
self.body.print(output);
9957
});
9958
DEFPRINT(AST_SimpleStatement, function(self, output) {
9959
self.body.print(output);
9960
output.semicolon();
9961
});
9962
// XXX Emscripten localmod: Add a node type for a parenthesized expression so that we can retain
9963
// Closure annotations that need a form "/**annotation*/(expression)"
9964
DEFPRINT(AST_ParenthesizedExpression, function(self, output) {
9965
output.print('(');
9966
self.body.print(output);
9967
output.print(')');
9968
});
9969
// XXX End Emscripten localmod
9970
function print_braced_empty(self, output) {
9971
output.print("{");
9972
output.with_indent(output.next_indent(), function() {
9973
output.append_comments(self, true);
9974
});
9975
output.add_mapping(self.end);
9976
output.print("}");
9977
}
9978
function print_braced(self, output, allow_directives) {
9979
if (self.body.length > 0) {
9980
output.with_block(function() {
9981
display_body(self.body, false, output, allow_directives);
9982
output.add_mapping(self.end);
9983
});
9984
} else print_braced_empty(self, output);
9985
}
9986
DEFPRINT(AST_BlockStatement, function(self, output) {
9987
print_braced(self, output);
9988
});
9989
DEFPRINT(AST_EmptyStatement, function(self, output) {
9990
output.semicolon();
9991
});
9992
DEFPRINT(AST_Do, function(self, output) {
9993
output.print("do");
9994
output.space();
9995
make_block(self.body, output);
9996
output.space();
9997
output.print("while");
9998
output.space();
9999
output.with_parens(function() {
10000
self.condition.print(output);
10001
});
10002
output.semicolon();
10003
});
10004
DEFPRINT(AST_While, function(self, output) {
10005
output.print("while");
10006
output.space();
10007
output.with_parens(function() {
10008
self.condition.print(output);
10009
});
10010
output.space();
10011
self._do_print_body(output);
10012
});
10013
DEFPRINT(AST_For, function(self, output) {
10014
output.print("for");
10015
output.space();
10016
output.with_parens(function() {
10017
if (self.init) {
10018
if (self.init instanceof AST_Definitions) {
10019
self.init.print(output);
10020
} else {
10021
parenthesize_for_noin(self.init, output, true);
10022
}
10023
output.print(";");
10024
output.space();
10025
} else {
10026
output.print(";");
10027
}
10028
if (self.condition) {
10029
self.condition.print(output);
10030
output.print(";");
10031
output.space();
10032
} else {
10033
output.print(";");
10034
}
10035
if (self.step) {
10036
self.step.print(output);
10037
}
10038
});
10039
output.space();
10040
self._do_print_body(output);
10041
});
10042
DEFPRINT(AST_ForIn, function(self, output) {
10043
output.print("for");
10044
if (self.await) {
10045
output.space();
10046
output.print("await");
10047
}
10048
output.space();
10049
output.with_parens(function() {
10050
self.init.print(output);
10051
output.space();
10052
output.print(self instanceof AST_ForOf ? "of" : "in");
10053
output.space();
10054
self.object.print(output);
10055
});
10056
output.space();
10057
self._do_print_body(output);
10058
});
10059
DEFPRINT(AST_With, function(self, output) {
10060
output.print("with");
10061
output.space();
10062
output.with_parens(function() {
10063
self.expression.print(output);
10064
});
10065
output.space();
10066
self._do_print_body(output);
10067
});
10068
10069
/* -----[ functions ]----- */
10070
AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword) {
10071
var self = this;
10072
if (!nokeyword) {
10073
if (self.async) {
10074
output.print("async");
10075
output.space();
10076
}
10077
output.print("function");
10078
if (self.is_generator) {
10079
output.star();
10080
}
10081
if (self.name) {
10082
output.space();
10083
}
10084
}
10085
if (self.name instanceof AST_Symbol) {
10086
self.name.print(output);
10087
} else if (nokeyword && self.name instanceof AST_Node) {
10088
output.with_square(function() {
10089
self.name.print(output); // Computed method name
10090
});
10091
}
10092
output.with_parens(function() {
10093
self.argnames.forEach(function(arg, i) {
10094
if (i) output.comma();
10095
arg.print(output);
10096
});
10097
});
10098
output.space();
10099
print_braced(self, output, true);
10100
});
10101
DEFPRINT(AST_Lambda, function(self, output) {
10102
self._do_print(output);
10103
output.gc_scope(self);
10104
});
10105
10106
DEFPRINT(AST_PrefixedTemplateString, function(self, output) {
10107
var tag = self.prefix;
10108
var parenthesize_tag = tag instanceof AST_Lambda
10109
|| tag instanceof AST_Binary
10110
|| tag instanceof AST_Conditional
10111
|| tag instanceof AST_Sequence
10112
|| tag instanceof AST_Unary
10113
|| tag instanceof AST_Dot && tag.expression instanceof AST_Object;
10114
if (parenthesize_tag) output.print("(");
10115
self.prefix.print(output);
10116
if (parenthesize_tag) output.print(")");
10117
self.template_string.print(output);
10118
});
10119
DEFPRINT(AST_TemplateString, function(self, output) {
10120
var is_tagged = output.parent() instanceof AST_PrefixedTemplateString;
10121
10122
output.print("`");
10123
for (var i = 0; i < self.segments.length; i++) {
10124
if (!(self.segments[i] instanceof AST_TemplateSegment)) {
10125
output.print("${");
10126
self.segments[i].print(output);
10127
output.print("}");
10128
} else if (is_tagged) {
10129
output.print(self.segments[i].raw);
10130
} else {
10131
output.print_template_string_chars(self.segments[i].value);
10132
}
10133
}
10134
output.print("`");
10135
});
10136
DEFPRINT(AST_TemplateSegment, function(self, output) {
10137
output.print_template_string_chars(self.value);
10138
});
10139
10140
AST_Arrow.DEFMETHOD("_do_print", function(output) {
10141
var self = this;
10142
var parent = output.parent();
10143
var needs_parens = (parent instanceof AST_Binary && !(parent instanceof AST_Assign)) ||
10144
parent instanceof AST_Unary ||
10145
(parent instanceof AST_Call && self === parent.expression);
10146
if (needs_parens) { output.print("("); }
10147
if (self.async) {
10148
output.print("async");
10149
output.space();
10150
}
10151
if (self.argnames.length === 1 && self.argnames[0] instanceof AST_Symbol) {
10152
self.argnames[0].print(output);
10153
} else {
10154
output.with_parens(function() {
10155
self.argnames.forEach(function(arg, i) {
10156
if (i) output.comma();
10157
arg.print(output);
10158
});
10159
});
10160
}
10161
output.space();
10162
output.print("=>");
10163
output.space();
10164
const first_statement = self.body[0];
10165
if (
10166
self.body.length === 1
10167
&& first_statement instanceof AST_Return
10168
) {
10169
const returned = first_statement.value;
10170
if (!returned) {
10171
output.print("{}");
10172
} else if (left_is_object(returned)) {
10173
output.print("(");
10174
returned.print(output);
10175
output.print(")");
10176
} else {
10177
returned.print(output);
10178
}
10179
} else {
10180
print_braced(self, output);
10181
}
10182
if (needs_parens) { output.print(")"); }
10183
output.gc_scope(self);
10184
});
10185
10186
/* -----[ exits ]----- */
10187
AST_Exit.DEFMETHOD("_do_print", function(output, kind) {
10188
output.print(kind);
10189
if (this.value) {
10190
output.space();
10191
const comments = this.value.start.comments_before;
10192
if (comments && comments.length && !output.printed_comments.has(comments)) {
10193
output.print("(");
10194
this.value.print(output);
10195
output.print(")");
10196
} else {
10197
this.value.print(output);
10198
}
10199
}
10200
output.semicolon();
10201
});
10202
DEFPRINT(AST_Return, function(self, output) {
10203
self._do_print(output, "return");
10204
});
10205
DEFPRINT(AST_Throw, function(self, output) {
10206
self._do_print(output, "throw");
10207
});
10208
10209
/* -----[ yield ]----- */
10210
10211
DEFPRINT(AST_Yield, function(self, output) {
10212
var star = self.is_star ? "*" : "";
10213
output.print("yield" + star);
10214
if (self.expression) {
10215
output.space();
10216
self.expression.print(output);
10217
}
10218
});
10219
10220
DEFPRINT(AST_Await, function(self, output) {
10221
output.print("await");
10222
output.space();
10223
var e = self.expression;
10224
var parens = !(
10225
e instanceof AST_Call
10226
|| e instanceof AST_SymbolRef
10227
|| e instanceof AST_PropAccess
10228
|| e instanceof AST_Unary
10229
|| e instanceof AST_Constant
10230
|| e instanceof AST_Await
10231
|| e instanceof AST_Object
10232
);
10233
if (parens) output.print("(");
10234
self.expression.print(output);
10235
if (parens) output.print(")");
10236
});
10237
10238
/* -----[ loop control ]----- */
10239
AST_LoopControl.DEFMETHOD("_do_print", function(output, kind) {
10240
output.print(kind);
10241
if (this.label) {
10242
output.space();
10243
this.label.print(output);
10244
}
10245
output.semicolon();
10246
});
10247
DEFPRINT(AST_Break, function(self, output) {
10248
self._do_print(output, "break");
10249
});
10250
DEFPRINT(AST_Continue, function(self, output) {
10251
self._do_print(output, "continue");
10252
});
10253
10254
/* -----[ if ]----- */
10255
function make_then(self, output) {
10256
var b = self.body;
10257
if (output.option("braces")
10258
|| output.option("ie8") && b instanceof AST_Do)
10259
return make_block(b, output);
10260
// The squeezer replaces "block"-s that contain only a single
10261
// statement with the statement itself; technically, the AST
10262
// is correct, but this can create problems when we output an
10263
// IF having an ELSE clause where the THEN clause ends in an
10264
// IF *without* an ELSE block (then the outer ELSE would refer
10265
// to the inner IF). This function checks for this case and
10266
// adds the block braces if needed.
10267
if (!b) return output.force_semicolon();
10268
while (true) {
10269
if (b instanceof AST_If) {
10270
if (!b.alternative) {
10271
make_block(self.body, output);
10272
return;
10273
}
10274
b = b.alternative;
10275
} else if (b instanceof AST_StatementWithBody) {
10276
b = b.body;
10277
} else break;
10278
}
10279
print_maybe_braced_body(self.body, output);
10280
}
10281
DEFPRINT(AST_If, function(self, output) {
10282
output.print("if");
10283
output.space();
10284
output.with_parens(function() {
10285
self.condition.print(output);
10286
});
10287
output.space();
10288
if (self.alternative) {
10289
make_then(self, output);
10290
output.space();
10291
output.print("else");
10292
output.space();
10293
if (self.alternative instanceof AST_If)
10294
self.alternative.print(output);
10295
else
10296
print_maybe_braced_body(self.alternative, output);
10297
} else {
10298
self._do_print_body(output);
10299
}
10300
});
10301
10302
/* -----[ switch ]----- */
10303
DEFPRINT(AST_Switch, function(self, output) {
10304
output.print("switch");
10305
output.space();
10306
output.with_parens(function() {
10307
self.expression.print(output);
10308
});
10309
output.space();
10310
var last = self.body.length - 1;
10311
if (last < 0) print_braced_empty(self, output);
10312
else output.with_block(function() {
10313
self.body.forEach(function(branch, i) {
10314
output.indent(true);
10315
branch.print(output);
10316
if (i < last && branch.body.length > 0)
10317
output.newline();
10318
});
10319
});
10320
});
10321
AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output) {
10322
output.newline();
10323
this.body.forEach(function(stmt) {
10324
output.indent();
10325
stmt.print(output);
10326
output.newline();
10327
});
10328
});
10329
DEFPRINT(AST_Default, function(self, output) {
10330
output.print("default:");
10331
self._do_print_body(output);
10332
});
10333
DEFPRINT(AST_Case, function(self, output) {
10334
output.print("case");
10335
output.space();
10336
self.expression.print(output);
10337
output.print(":");
10338
self._do_print_body(output);
10339
});
10340
10341
/* -----[ exceptions ]----- */
10342
DEFPRINT(AST_Try, function(self, output) {
10343
output.print("try");
10344
output.space();
10345
self.body.print(output);
10346
if (self.bcatch) {
10347
output.space();
10348
self.bcatch.print(output);
10349
}
10350
if (self.bfinally) {
10351
output.space();
10352
self.bfinally.print(output);
10353
}
10354
});
10355
DEFPRINT(AST_TryBlock, function(self, output) {
10356
print_braced(self, output);
10357
});
10358
DEFPRINT(AST_Catch, function(self, output) {
10359
output.print("catch");
10360
if (self.argname) {
10361
output.space();
10362
output.with_parens(function() {
10363
self.argname.print(output);
10364
});
10365
}
10366
output.space();
10367
print_braced(self, output);
10368
});
10369
DEFPRINT(AST_Finally, function(self, output) {
10370
output.print("finally");
10371
output.space();
10372
print_braced(self, output);
10373
});
10374
10375
/* -----[ var/const ]----- */
10376
AST_Definitions.DEFMETHOD("_do_print", function(output, kind) {
10377
output.print(kind);
10378
output.space();
10379
this.definitions.forEach(function(def, i) {
10380
if (i) output.comma();
10381
def.print(output);
10382
});
10383
var p = output.parent();
10384
var in_for = p instanceof AST_For || p instanceof AST_ForIn;
10385
var output_semicolon = !in_for || p && p.init !== this;
10386
if (output_semicolon)
10387
output.semicolon();
10388
});
10389
DEFPRINT(AST_Let, function(self, output) {
10390
self._do_print(output, "let");
10391
});
10392
DEFPRINT(AST_Var, function(self, output) {
10393
self._do_print(output, "var");
10394
});
10395
DEFPRINT(AST_Const, function(self, output) {
10396
self._do_print(output, "const");
10397
});
10398
DEFPRINT(AST_Import, function(self, output) {
10399
output.print("import");
10400
output.space();
10401
if (self.imported_name) {
10402
self.imported_name.print(output);
10403
}
10404
if (self.imported_name && self.imported_names) {
10405
output.print(",");
10406
output.space();
10407
}
10408
if (self.imported_names) {
10409
if (self.imported_names.length === 1 &&
10410
self.imported_names[0].foreign_name.name === "*" &&
10411
!self.imported_names[0].foreign_name.quote) {
10412
self.imported_names[0].print(output);
10413
} else {
10414
output.print("{");
10415
self.imported_names.forEach(function (name_import, i) {
10416
output.space();
10417
name_import.print(output);
10418
if (i < self.imported_names.length - 1) {
10419
output.print(",");
10420
}
10421
});
10422
output.space();
10423
output.print("}");
10424
}
10425
}
10426
if (self.imported_name || self.imported_names) {
10427
output.space();
10428
output.print("from");
10429
output.space();
10430
}
10431
self.module_name.print(output);
10432
if (self.assert_clause) {
10433
output.print("assert");
10434
self.assert_clause.print(output);
10435
}
10436
output.semicolon();
10437
});
10438
DEFPRINT(AST_ImportMeta, function(self, output) {
10439
output.print("import.meta");
10440
});
10441
10442
DEFPRINT(AST_NameMapping, function(self, output) {
10443
var is_import = output.parent() instanceof AST_Import;
10444
var definition = self.name.definition();
10445
var foreign_name = self.foreign_name;
10446
var names_are_different =
10447
(definition && definition.mangled_name || self.name.name) !==
10448
foreign_name.name;
10449
if (!names_are_different &&
10450
foreign_name.name === "*" &&
10451
foreign_name.quote != self.name.quote) {
10452
// export * as "*"
10453
names_are_different = true;
10454
}
10455
var foreign_name_is_name = foreign_name.quote == null;
10456
if (names_are_different) {
10457
if (is_import) {
10458
if (foreign_name_is_name) {
10459
output.print(foreign_name.name);
10460
} else {
10461
output.print_string(foreign_name.name, foreign_name.quote);
10462
}
10463
} else {
10464
if (self.name.quote == null) {
10465
self.name.print(output);
10466
} else {
10467
output.print_string(self.name.name, self.name.quote);
10468
}
10469
10470
}
10471
output.space();
10472
output.print("as");
10473
output.space();
10474
if (is_import) {
10475
self.name.print(output);
10476
} else {
10477
if (foreign_name_is_name) {
10478
output.print(foreign_name.name);
10479
} else {
10480
output.print_string(foreign_name.name, foreign_name.quote);
10481
}
10482
}
10483
} else {
10484
if (self.name.quote == null) {
10485
self.name.print(output);
10486
} else {
10487
output.print_string(self.name.name, self.name.quote);
10488
}
10489
}
10490
});
10491
10492
DEFPRINT(AST_Export, function(self, output) {
10493
output.print("export");
10494
output.space();
10495
if (self.is_default) {
10496
output.print("default");
10497
output.space();
10498
}
10499
if (self.exported_names) {
10500
if (self.exported_names.length === 1 &&
10501
self.exported_names[0].name.name === "*" &&
10502
!self.exported_names[0].name.quote) {
10503
self.exported_names[0].print(output);
10504
} else {
10505
output.print("{");
10506
self.exported_names.forEach(function(name_export, i) {
10507
output.space();
10508
name_export.print(output);
10509
if (i < self.exported_names.length - 1) {
10510
output.print(",");
10511
}
10512
});
10513
output.space();
10514
output.print("}");
10515
}
10516
} else if (self.exported_value) {
10517
self.exported_value.print(output);
10518
} else if (self.exported_definition) {
10519
self.exported_definition.print(output);
10520
if (self.exported_definition instanceof AST_Definitions) return;
10521
}
10522
if (self.module_name) {
10523
output.space();
10524
output.print("from");
10525
output.space();
10526
self.module_name.print(output);
10527
}
10528
if (self.assert_clause) {
10529
output.print("assert");
10530
self.assert_clause.print(output);
10531
}
10532
if (self.exported_value
10533
&& !(self.exported_value instanceof AST_Defun ||
10534
self.exported_value instanceof AST_Function ||
10535
self.exported_value instanceof AST_Class)
10536
|| self.module_name
10537
|| self.exported_names
10538
) {
10539
output.semicolon();
10540
}
10541
});
10542
10543
function parenthesize_for_noin(node, output, noin) {
10544
var parens = false;
10545
// need to take some precautions here:
10546
// https://github.com/mishoo/UglifyJS2/issues/60
10547
if (noin) {
10548
parens = walk(node, node => {
10549
// Don't go into scopes -- except arrow functions:
10550
// https://github.com/terser/terser/issues/1019#issuecomment-877642607
10551
if (node instanceof AST_Scope && !(node instanceof AST_Arrow)) {
10552
return true;
10553
}
10554
if (
10555
node instanceof AST_Binary && node.operator == "in"
10556
|| node instanceof AST_PrivateIn
10557
) {
10558
return walk_abort; // makes walk() return true
10559
}
10560
});
10561
}
10562
node.print(output, parens);
10563
}
10564
10565
DEFPRINT(AST_VarDef, function(self, output) {
10566
self.name.print(output);
10567
if (self.value) {
10568
output.space();
10569
output.print("=");
10570
output.space();
10571
var p = output.parent(1);
10572
var noin = p instanceof AST_For || p instanceof AST_ForIn;
10573
parenthesize_for_noin(self.value, output, noin);
10574
}
10575
});
10576
10577
/* -----[ other expressions ]----- */
10578
DEFPRINT(AST_Call, function(self, output) {
10579
self.expression.print(output);
10580
if (self instanceof AST_New && self.args.length === 0)
10581
return;
10582
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
10583
output.add_mapping(self.start);
10584
}
10585
if (self.optional) output.print("?.");
10586
output.with_parens(function() {
10587
self.args.forEach(function(expr, i) {
10588
if (i) output.comma();
10589
expr.print(output);
10590
});
10591
});
10592
});
10593
DEFPRINT(AST_New, function(self, output) {
10594
output.print("new");
10595
output.space();
10596
AST_Call.prototype._codegen(self, output);
10597
});
10598
10599
AST_Sequence.DEFMETHOD("_do_print", function(output) {
10600
this.expressions.forEach(function(node, index) {
10601
if (index > 0) {
10602
output.comma();
10603
if (output.should_break()) {
10604
output.newline();
10605
output.indent();
10606
}
10607
}
10608
node.print(output);
10609
});
10610
});
10611
DEFPRINT(AST_Sequence, function(self, output) {
10612
self._do_print(output);
10613
// var p = output.parent();
10614
// if (p instanceof AST_Statement) {
10615
// output.with_indent(output.next_indent(), function(){
10616
// self._do_print(output);
10617
// });
10618
// } else {
10619
// self._do_print(output);
10620
// }
10621
});
10622
DEFPRINT(AST_Dot, function(self, output) {
10623
var expr = self.expression;
10624
expr.print(output);
10625
var prop = self.property;
10626
var print_computed = ALL_RESERVED_WORDS.has(prop)
10627
? output.option("ie8")
10628
: !is_identifier_string(
10629
prop,
10630
output.option("ecma") >= 2015 && !output.option("safari10")
10631
);
10632
10633
if (self.optional) output.print("?.");
10634
10635
if (print_computed) {
10636
output.print("[");
10637
output.add_mapping(self.end);
10638
output.print_string(prop);
10639
output.print("]");
10640
} else {
10641
if (expr instanceof AST_Number && expr.getValue() >= 0) {
10642
if (!/[xa-f.)]/i.test(output.last())) {
10643
output.print(".");
10644
}
10645
}
10646
if (!self.optional) output.print(".");
10647
// the name after dot would be mapped about here.
10648
output.add_mapping(self.end);
10649
output.print_name(prop);
10650
}
10651
});
10652
DEFPRINT(AST_DotHash, function(self, output) {
10653
var expr = self.expression;
10654
expr.print(output);
10655
var prop = self.property;
10656
10657
if (self.optional) output.print("?");
10658
output.print(".#");
10659
output.add_mapping(self.end);
10660
output.print_name(prop);
10661
});
10662
DEFPRINT(AST_Sub, function(self, output) {
10663
self.expression.print(output);
10664
if (self.optional) output.print("?.");
10665
output.print("[");
10666
self.property.print(output);
10667
output.print("]");
10668
});
10669
DEFPRINT(AST_Chain, function(self, output) {
10670
self.expression.print(output);
10671
});
10672
DEFPRINT(AST_UnaryPrefix, function(self, output) {
10673
var op = self.operator;
10674
output.print(op);
10675
if (/^[a-z]/i.test(op)
10676
|| (/[+-]$/.test(op)
10677
&& self.expression instanceof AST_UnaryPrefix
10678
&& /^[+-]/.test(self.expression.operator))) {
10679
output.space();
10680
}
10681
self.expression.print(output);
10682
});
10683
DEFPRINT(AST_UnaryPostfix, function(self, output) {
10684
self.expression.print(output);
10685
output.print(self.operator);
10686
});
10687
DEFPRINT(AST_Binary, function(self, output) {
10688
var op = self.operator;
10689
self.left.print(output);
10690
if (op[0] == ">" /* ">>" ">>>" ">" ">=" */
10691
&& self.left instanceof AST_UnaryPostfix
10692
&& self.left.operator == "--") {
10693
// space is mandatory to avoid outputting -->
10694
output.print(" ");
10695
} else {
10696
// the space is optional depending on "beautify"
10697
output.space();
10698
}
10699
output.print(op);
10700
if ((op == "<" || op == "<<")
10701
&& self.right instanceof AST_UnaryPrefix
10702
&& self.right.operator == "!"
10703
&& self.right.expression instanceof AST_UnaryPrefix
10704
&& self.right.expression.operator == "--") {
10705
// space is mandatory to avoid outputting <!--
10706
output.print(" ");
10707
} else {
10708
// the space is optional depending on "beautify"
10709
output.space();
10710
}
10711
self.right.print(output);
10712
});
10713
DEFPRINT(AST_Conditional, function(self, output) {
10714
self.condition.print(output);
10715
output.space();
10716
output.print("?");
10717
output.space();
10718
self.consequent.print(output);
10719
output.space();
10720
output.colon();
10721
self.alternative.print(output);
10722
});
10723
10724
/* -----[ literals ]----- */
10725
DEFPRINT(AST_Array, function(self, output) {
10726
output.with_square(function() {
10727
var a = self.elements, len = a.length;
10728
if (len > 0) output.space();
10729
a.forEach(function(exp, i) {
10730
if (i) output.comma();
10731
exp.print(output);
10732
// If the final element is a hole, we need to make sure it
10733
// doesn't look like a trailing comma, by inserting an actual
10734
// trailing comma.
10735
if (i === len - 1 && exp instanceof AST_Hole)
10736
output.comma();
10737
});
10738
if (len > 0) output.space();
10739
});
10740
});
10741
DEFPRINT(AST_Object, function(self, output) {
10742
if (self.properties.length > 0) output.with_block(function() {
10743
self.properties.forEach(function(prop, i) {
10744
if (i) {
10745
output.print(",");
10746
output.newline();
10747
}
10748
output.indent();
10749
prop.print(output);
10750
});
10751
output.newline();
10752
});
10753
else print_braced_empty(self, output);
10754
});
10755
DEFPRINT(AST_Class, function(self, output) {
10756
output.print("class");
10757
output.space();
10758
if (self.name) {
10759
self.name.print(output);
10760
output.space();
10761
}
10762
if (self.extends) {
10763
var parens = (
10764
!(self.extends instanceof AST_SymbolRef)
10765
&& !(self.extends instanceof AST_PropAccess)
10766
&& !(self.extends instanceof AST_ClassExpression)
10767
&& !(self.extends instanceof AST_Function)
10768
);
10769
output.print("extends");
10770
if (parens) {
10771
output.print("(");
10772
} else {
10773
output.space();
10774
}
10775
self.extends.print(output);
10776
if (parens) {
10777
output.print(")");
10778
} else {
10779
output.space();
10780
}
10781
}
10782
if (self.properties.length > 0) output.with_block(function() {
10783
self.properties.forEach(function(prop, i) {
10784
if (i) {
10785
output.newline();
10786
}
10787
output.indent();
10788
prop.print(output);
10789
});
10790
output.newline();
10791
});
10792
else output.print("{}");
10793
});
10794
DEFPRINT(AST_NewTarget, function(self, output) {
10795
output.print("new.target");
10796
});
10797
10798
/** Prints a prop name. Returns whether it can be used as a shorthand. */
10799
function print_property_name(key, quote, output) {
10800
if (output.option("quote_keys")) {
10801
output.print_string(key);
10802
return false;
10803
}
10804
if ("" + +key == key && key >= 0) {
10805
if (output.option("keep_numbers")) {
10806
output.print(key);
10807
return false;
10808
}
10809
output.print(make_num(key));
10810
return false;
10811
}
10812
var print_string = ALL_RESERVED_WORDS.has(key)
10813
? output.option("ie8")
10814
: (
10815
output.option("ecma") < 2015 || output.option("safari10")
10816
? !is_basic_identifier_string(key)
10817
: !is_identifier_string(key, true)
10818
);
10819
if (print_string || (quote && output.option("keep_quoted_props"))) {
10820
output.print_string(key, quote);
10821
return false;
10822
}
10823
output.print_name(key);
10824
return true;
10825
}
10826
10827
DEFPRINT(AST_ObjectKeyVal, function(self, output) {
10828
function get_name(self) {
10829
var def = self.definition();
10830
return def ? def.mangled_name || def.name : self.name;
10831
}
10832
10833
const try_shorthand = output.option("shorthand") && !(self.key instanceof AST_Node);
10834
if (
10835
try_shorthand
10836
&& self.value instanceof AST_Symbol
10837
&& get_name(self.value) === self.key
10838
&& !ALL_RESERVED_WORDS.has(self.key)
10839
) {
10840
const was_shorthand = print_property_name(self.key, self.quote, output);
10841
if (!was_shorthand) {
10842
output.colon();
10843
self.value.print(output);
10844
}
10845
} else if (
10846
try_shorthand
10847
&& self.value instanceof AST_DefaultAssign
10848
&& self.value.left instanceof AST_Symbol
10849
&& get_name(self.value.left) === self.key
10850
) {
10851
const was_shorthand = print_property_name(self.key, self.quote, output);
10852
if (!was_shorthand) {
10853
output.colon();
10854
self.value.left.print(output);
10855
}
10856
output.space();
10857
output.print("=");
10858
output.space();
10859
self.value.right.print(output);
10860
} else {
10861
if (!(self.key instanceof AST_Node)) {
10862
print_property_name(self.key, self.quote, output);
10863
} else {
10864
output.with_square(function() {
10865
self.key.print(output);
10866
});
10867
}
10868
output.colon();
10869
self.value.print(output);
10870
}
10871
});
10872
DEFPRINT(AST_ClassPrivateProperty, (self, output) => {
10873
if (self.static) {
10874
output.print("static");
10875
output.space();
10876
}
10877
10878
output.print("#");
10879
10880
print_property_name(self.key.name, self.quote, output);
10881
10882
if (self.value) {
10883
output.print("=");
10884
self.value.print(output);
10885
}
10886
10887
output.semicolon();
10888
});
10889
DEFPRINT(AST_ClassProperty, (self, output) => {
10890
if (self.static) {
10891
output.print("static");
10892
output.space();
10893
}
10894
10895
if (self.key instanceof AST_SymbolClassProperty) {
10896
print_property_name(self.key.name, self.quote, output);
10897
} else {
10898
output.print("[");
10899
self.key.print(output);
10900
output.print("]");
10901
}
10902
10903
if (self.value) {
10904
output.print("=");
10905
self.value.print(output);
10906
}
10907
10908
output.semicolon();
10909
});
10910
AST_ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, is_private, output) {
10911
var self = this;
10912
if (self.static) {
10913
output.print("static");
10914
output.space();
10915
}
10916
if (type) {
10917
output.print(type);
10918
output.space();
10919
}
10920
if (self.key instanceof AST_SymbolMethod) {
10921
if (is_private) output.print("#");
10922
print_property_name(self.key.name, self.quote, output);
10923
} else {
10924
output.with_square(function() {
10925
self.key.print(output);
10926
});
10927
}
10928
self.value._do_print(output, true);
10929
});
10930
DEFPRINT(AST_ObjectSetter, function(self, output) {
10931
self._print_getter_setter("set", false, output);
10932
});
10933
DEFPRINT(AST_ObjectGetter, function(self, output) {
10934
self._print_getter_setter("get", false, output);
10935
});
10936
DEFPRINT(AST_PrivateSetter, function(self, output) {
10937
self._print_getter_setter("set", true, output);
10938
});
10939
DEFPRINT(AST_PrivateGetter, function(self, output) {
10940
self._print_getter_setter("get", true, output);
10941
});
10942
DEFPRINT(AST_PrivateMethod, function(self, output) {
10943
var type;
10944
if (self.is_generator && self.async) {
10945
type = "async*";
10946
} else if (self.is_generator) {
10947
type = "*";
10948
} else if (self.async) {
10949
type = "async";
10950
}
10951
self._print_getter_setter(type, true, output);
10952
});
10953
DEFPRINT(AST_PrivateIn, function(self, output) {
10954
self.key.print(output);
10955
output.space();
10956
output.print("in");
10957
output.space();
10958
self.value.print(output);
10959
});
10960
DEFPRINT(AST_SymbolPrivateProperty, function(self, output) {
10961
output.print("#" + self.name);
10962
});
10963
DEFPRINT(AST_ConciseMethod, function(self, output) {
10964
var type;
10965
if (self.is_generator && self.async) {
10966
type = "async*";
10967
} else if (self.is_generator) {
10968
type = "*";
10969
} else if (self.async) {
10970
type = "async";
10971
}
10972
self._print_getter_setter(type, false, output);
10973
});
10974
DEFPRINT(AST_ClassStaticBlock, function (self, output) {
10975
output.print("static");
10976
output.space();
10977
print_braced(self, output);
10978
});
10979
AST_Symbol.DEFMETHOD("_do_print", function(output) {
10980
var def = this.definition();
10981
output.print_name(def ? def.mangled_name || def.name : this.name);
10982
});
10983
DEFPRINT(AST_Symbol, function (self, output) {
10984
self._do_print(output);
10985
});
10986
DEFPRINT(AST_Hole, noop);
10987
DEFPRINT(AST_This, function(self, output) {
10988
output.print("this");
10989
});
10990
DEFPRINT(AST_Super, function(self, output) {
10991
output.print("super");
10992
});
10993
DEFPRINT(AST_Constant, function(self, output) {
10994
output.print(self.getValue());
10995
});
10996
DEFPRINT(AST_String, function(self, output) {
10997
output.print_string(self.getValue(), self.quote, output.in_directive);
10998
});
10999
DEFPRINT(AST_Number, function(self, output) {
11000
if ((output.option("keep_numbers") || output.use_asm) && self.raw) {
11001
output.print(self.raw);
11002
} else {
11003
output.print(make_num(self.getValue()));
11004
}
11005
});
11006
DEFPRINT(AST_BigInt, function(self, output) {
11007
output.print(self.getValue() + "n");
11008
});
11009
11010
const r_slash_script = /(<\s*\/\s*script)/i;
11011
const slash_script_replace = (_, $1) => $1.replace("/", "\\/");
11012
DEFPRINT(AST_RegExp, function(self, output) {
11013
let { source, flags } = self.getValue();
11014
source = regexp_source_fix(source);
11015
flags = flags ? sort_regexp_flags(flags) : "";
11016
source = source.replace(r_slash_script, slash_script_replace);
11017
11018
output.print(output.to_utf8(`/${source}/${flags}`, false, true));
11019
11020
const parent = output.parent();
11021
if (
11022
parent instanceof AST_Binary
11023
&& /^\w/.test(parent.operator)
11024
&& parent.left === self
11025
) {
11026
output.print(" ");
11027
}
11028
});
11029
11030
/** if, for, while, may or may not have braces surrounding its body */
11031
function print_maybe_braced_body(stat, output) {
11032
if (output.option("braces")) {
11033
make_block(stat, output);
11034
} else {
11035
if (!stat || stat instanceof AST_EmptyStatement)
11036
output.force_semicolon();
11037
else if (stat instanceof AST_Let || stat instanceof AST_Const || stat instanceof AST_Class)
11038
make_block(stat, output);
11039
else
11040
stat.print(output);
11041
}
11042
}
11043
11044
function best_of(a) {
11045
var best = a[0], len = best.length;
11046
for (var i = 1; i < a.length; ++i) {
11047
if (a[i].length < len) {
11048
best = a[i];
11049
len = best.length;
11050
}
11051
}
11052
return best;
11053
}
11054
11055
function make_num(num) {
11056
var str = num.toString(10).replace(/^0\./, ".").replace("e+", "e");
11057
var candidates = [ str ];
11058
if (Math.floor(num) === num) {
11059
if (num < 0) {
11060
candidates.push("-0x" + (-num).toString(16).toLowerCase());
11061
} else {
11062
candidates.push("0x" + num.toString(16).toLowerCase());
11063
}
11064
}
11065
var match, len, digits;
11066
if (match = /^\.0+/.exec(str)) {
11067
len = match[0].length;
11068
digits = str.slice(len);
11069
candidates.push(digits + "e-" + (digits.length + len - 1));
11070
} else if (match = /0+$/.exec(str)) {
11071
len = match[0].length;
11072
candidates.push(str.slice(0, -len) + "e" + len);
11073
} else if (match = /^(\d)\.(\d+)e(-?\d+)$/.exec(str)) {
11074
candidates.push(match[1] + match[2] + "e" + (match[3] - match[2].length));
11075
}
11076
return best_of(candidates);
11077
}
11078
11079
function make_block(stmt, output) {
11080
if (!stmt || stmt instanceof AST_EmptyStatement)
11081
output.print("{}");
11082
else if (stmt instanceof AST_BlockStatement)
11083
stmt.print(output);
11084
else output.with_block(function() {
11085
output.indent();
11086
stmt.print(output);
11087
output.newline();
11088
});
11089
}
11090
11091
/* -----[ source map generators ]----- */
11092
11093
function DEFMAP(nodetype, generator) {
11094
nodetype.forEach(function(nodetype) {
11095
nodetype.DEFMETHOD("add_source_map", generator);
11096
});
11097
}
11098
11099
DEFMAP([
11100
// We could easily add info for ALL nodes, but it seems to me that
11101
// would be quite wasteful, hence this noop in the base class.
11102
AST_Node,
11103
// since the label symbol will mark it
11104
AST_LabeledStatement,
11105
AST_Toplevel,
11106
], noop);
11107
11108
// XXX: I'm not exactly sure if we need it for all of these nodes,
11109
// or if we should add even more.
11110
DEFMAP([
11111
AST_Array,
11112
AST_BlockStatement,
11113
AST_Catch,
11114
AST_Class,
11115
AST_Constant,
11116
AST_Debugger,
11117
AST_Definitions,
11118
AST_Directive,
11119
AST_Finally,
11120
AST_Jump,
11121
AST_Lambda,
11122
AST_New,
11123
AST_Object,
11124
AST_StatementWithBody,
11125
AST_Symbol,
11126
AST_Switch,
11127
AST_SwitchBranch,
11128
AST_TemplateString,
11129
AST_TemplateSegment,
11130
AST_Try,
11131
], function(output) {
11132
output.add_mapping(this.start);
11133
});
11134
11135
DEFMAP([
11136
AST_ObjectGetter,
11137
AST_ObjectSetter,
11138
AST_PrivateGetter,
11139
AST_PrivateSetter,
11140
], function(output) {
11141
output.add_mapping(this.key.end, this.key.name);
11142
});
11143
11144
DEFMAP([ AST_ObjectProperty ], function(output) {
11145
output.add_mapping(this.start, this.key);
11146
});
11147
})();
11148
11149
/***********************************************************************
11150
11151
A JavaScript tokenizer / parser / beautifier / compressor.
11152
https://github.com/mishoo/UglifyJS2
11153
11154
-------------------------------- (C) ---------------------------------
11155
11156
Author: Mihai Bazon
11157
<[email protected]>
11158
http://mihai.bazon.net/blog
11159
11160
Distributed under the BSD license:
11161
11162
Copyright 2012 (c) Mihai Bazon <[email protected]>
11163
11164
Redistribution and use in source and binary forms, with or without
11165
modification, are permitted provided that the following conditions
11166
are met:
11167
11168
* Redistributions of source code must retain the above
11169
copyright notice, this list of conditions and the following
11170
disclaimer.
11171
11172
* Redistributions in binary form must reproduce the above
11173
copyright notice, this list of conditions and the following
11174
disclaimer in the documentation and/or other materials
11175
provided with the distribution.
11176
11177
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
11178
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
11179
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
11180
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
11181
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
11182
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
11183
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
11184
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11185
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
11186
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
11187
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
11188
SUCH DAMAGE.
11189
11190
***********************************************************************/
11191
11192
const MASK_EXPORT_DONT_MANGLE = 1 << 0;
11193
const MASK_EXPORT_WANT_MANGLE = 1 << 1;
11194
11195
let function_defs = null;
11196
let unmangleable_names = null;
11197
/**
11198
* When defined, there is a function declaration somewhere that's inside of a block.
11199
* See https://tc39.es/ecma262/multipage/additional-ecmascript-features-for-web-browsers.html#sec-block-level-function-declarations-web-legacy-compatibility-semantics
11200
*/
11201
let scopes_with_block_defuns = null;
11202
11203
class SymbolDef {
11204
constructor(scope, orig, init) {
11205
this.name = orig.name;
11206
this.orig = [ orig ];
11207
this.init = init;
11208
this.eliminated = 0;
11209
this.assignments = 0;
11210
this.scope = scope;
11211
this.replaced = 0;
11212
this.global = false;
11213
this.export = 0;
11214
this.mangled_name = null;
11215
this.undeclared = false;
11216
this.id = SymbolDef.next_id++;
11217
this.chained = false;
11218
this.direct_access = false;
11219
this.escaped = 0;
11220
this.recursive_refs = 0;
11221
this.references = [];
11222
this.should_replace = undefined;
11223
this.single_use = false;
11224
this.fixed = false;
11225
Object.seal(this);
11226
}
11227
fixed_value() {
11228
if (!this.fixed || this.fixed instanceof AST_Node) return this.fixed;
11229
return this.fixed();
11230
}
11231
unmangleable(options) {
11232
if (!options) options = {};
11233
11234
if (
11235
function_defs &&
11236
function_defs.has(this.id) &&
11237
keep_name(options.keep_fnames, this.orig[0].name)
11238
) return true;
11239
11240
return this.global && !options.toplevel
11241
|| (this.export & MASK_EXPORT_DONT_MANGLE)
11242
|| this.undeclared
11243
|| !options.eval && this.scope.pinned()
11244
|| (this.orig[0] instanceof AST_SymbolLambda
11245
|| this.orig[0] instanceof AST_SymbolDefun) && keep_name(options.keep_fnames, this.orig[0].name)
11246
|| this.orig[0] instanceof AST_SymbolMethod
11247
|| (this.orig[0] instanceof AST_SymbolClass
11248
|| this.orig[0] instanceof AST_SymbolDefClass) && keep_name(options.keep_classnames, this.orig[0].name);
11249
}
11250
mangle(options) {
11251
const cache = options.cache && options.cache.props;
11252
if (this.global && cache && cache.has(this.name)) {
11253
this.mangled_name = cache.get(this.name);
11254
} else if (!this.mangled_name && !this.unmangleable(options)) {
11255
var s = this.scope;
11256
var sym = this.orig[0];
11257
if (options.ie8 && sym instanceof AST_SymbolLambda)
11258
s = s.parent_scope;
11259
const redefinition = redefined_catch_def(this);
11260
this.mangled_name = redefinition
11261
? redefinition.mangled_name || redefinition.name
11262
: s.next_mangled(options, this);
11263
if (this.global && cache) {
11264
cache.set(this.name, this.mangled_name);
11265
}
11266
}
11267
}
11268
}
11269
11270
SymbolDef.next_id = 1;
11271
11272
function redefined_catch_def(def) {
11273
if (def.orig[0] instanceof AST_SymbolCatch
11274
&& def.scope.is_block_scope()
11275
) {
11276
return def.scope.get_defun_scope().variables.get(def.name);
11277
}
11278
}
11279
11280
AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = null, toplevel = this } = {}) {
11281
options = defaults(options, {
11282
cache: null,
11283
ie8: false,
11284
safari10: false,
11285
});
11286
11287
if (!(toplevel instanceof AST_Toplevel)) {
11288
throw new Error("Invalid toplevel scope");
11289
}
11290
11291
// pass 1: setup scope chaining and handle definitions
11292
var scope = this.parent_scope = parent_scope;
11293
var labels = new Map();
11294
var defun = null;
11295
var in_destructuring = null;
11296
var for_scopes = [];
11297
var tw = new TreeWalker((node, descend) => {
11298
if (node.is_block_scope()) {
11299
const save_scope = scope;
11300
node.block_scope = scope = new AST_Scope(node);
11301
scope._block_scope = true;
11302
scope.init_scope_vars(save_scope);
11303
scope.uses_with = save_scope.uses_with;
11304
scope.uses_eval = save_scope.uses_eval;
11305
11306
if (options.safari10) {
11307
if (node instanceof AST_For || node instanceof AST_ForIn || node instanceof AST_ForOf) {
11308
for_scopes.push(scope);
11309
}
11310
}
11311
11312
if (node instanceof AST_Switch) {
11313
// XXX: HACK! Ensure the switch expression gets the correct scope (the parent scope) and the body gets the contained scope
11314
// AST_Switch has a scope within the body, but it itself "is a block scope"
11315
// This means the switched expression has to belong to the outer scope
11316
// while the body inside belongs to the switch itself.
11317
// This is pretty nasty and warrants an AST change
11318
const the_block_scope = scope;
11319
scope = save_scope;
11320
node.expression.walk(tw);
11321
scope = the_block_scope;
11322
for (let i = 0; i < node.body.length; i++) {
11323
node.body[i].walk(tw);
11324
}
11325
} else {
11326
descend();
11327
}
11328
scope = save_scope;
11329
return true;
11330
}
11331
if (node instanceof AST_Destructuring) {
11332
const save_destructuring = in_destructuring;
11333
in_destructuring = node;
11334
descend();
11335
in_destructuring = save_destructuring;
11336
return true;
11337
}
11338
if (node instanceof AST_Scope) {
11339
node.init_scope_vars(scope);
11340
var save_scope = scope;
11341
var save_defun = defun;
11342
var save_labels = labels;
11343
defun = scope = node;
11344
labels = new Map();
11345
descend();
11346
scope = save_scope;
11347
defun = save_defun;
11348
labels = save_labels;
11349
return true; // don't descend again in TreeWalker
11350
}
11351
if (node instanceof AST_LabeledStatement) {
11352
var l = node.label;
11353
if (labels.has(l.name)) {
11354
throw new Error(string_template("Label {name} defined twice", l));
11355
}
11356
labels.set(l.name, l);
11357
descend();
11358
labels.delete(l.name);
11359
return true; // no descend again
11360
}
11361
if (node instanceof AST_With) {
11362
for (var s = scope; s; s = s.parent_scope)
11363
s.uses_with = true;
11364
return;
11365
}
11366
if (node instanceof AST_Symbol) {
11367
node.scope = scope;
11368
}
11369
if (node instanceof AST_Label) {
11370
node.thedef = node;
11371
node.references = [];
11372
}
11373
if (node instanceof AST_SymbolLambda) {
11374
defun.def_function(node, node.name == "arguments" ? undefined : defun);
11375
} else if (node instanceof AST_SymbolDefun) {
11376
// Careful here, the scope where this should be defined is
11377
// the parent scope. The reason is that we enter a new
11378
// scope when we encounter the AST_Defun node (which is
11379
// instanceof AST_Scope) but we get to the symbol a bit
11380
// later.
11381
const closest_scope = defun.parent_scope;
11382
11383
// In strict mode, function definitions are block-scoped
11384
node.scope = tw.directives["use strict"]
11385
? closest_scope
11386
: closest_scope.get_defun_scope();
11387
11388
mark_export(node.scope.def_function(node, defun), 1);
11389
} else if (node instanceof AST_SymbolClass) {
11390
mark_export(defun.def_variable(node, defun), 1);
11391
} else if (node instanceof AST_SymbolImport) {
11392
scope.def_variable(node);
11393
} else if (node instanceof AST_SymbolDefClass) {
11394
// This deals with the name of the class being available
11395
// inside the class.
11396
mark_export((node.scope = defun.parent_scope).def_function(node, defun), 1);
11397
} else if (
11398
node instanceof AST_SymbolVar
11399
|| node instanceof AST_SymbolLet
11400
|| node instanceof AST_SymbolConst
11401
|| node instanceof AST_SymbolCatch
11402
) {
11403
var def;
11404
if (node instanceof AST_SymbolBlockDeclaration) {
11405
def = scope.def_variable(node, null);
11406
} else {
11407
def = defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
11408
}
11409
if (!def.orig.every((sym) => {
11410
if (sym === node) return true;
11411
if (node instanceof AST_SymbolBlockDeclaration) {
11412
return sym instanceof AST_SymbolLambda;
11413
}
11414
return !(sym instanceof AST_SymbolLet || sym instanceof AST_SymbolConst);
11415
})) {
11416
js_error(
11417
`"${node.name}" is redeclared`,
11418
node.start.file,
11419
node.start.line,
11420
node.start.col,
11421
node.start.pos
11422
);
11423
}
11424
if (!(node instanceof AST_SymbolFunarg)) mark_export(def, 2);
11425
if (defun !== scope) {
11426
node.mark_enclosed();
11427
var def = scope.find_variable(node);
11428
if (node.thedef !== def) {
11429
node.thedef = def;
11430
node.reference();
11431
}
11432
}
11433
} else if (node instanceof AST_LabelRef) {
11434
var sym = labels.get(node.name);
11435
if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", {
11436
name: node.name,
11437
line: node.start.line,
11438
col: node.start.col
11439
}));
11440
node.thedef = sym;
11441
}
11442
if (!(scope instanceof AST_Toplevel) && (node instanceof AST_Export || node instanceof AST_Import)) {
11443
js_error(
11444
`"${node.TYPE}" statement may only appear at the top level`,
11445
node.start.file,
11446
node.start.line,
11447
node.start.col,
11448
node.start.pos
11449
);
11450
}
11451
});
11452
this.walk(tw);
11453
11454
function mark_export(def, level) {
11455
if (in_destructuring) {
11456
var i = 0;
11457
do {
11458
level++;
11459
} while (tw.parent(i++) !== in_destructuring);
11460
}
11461
var node = tw.parent(level);
11462
if (def.export = node instanceof AST_Export ? MASK_EXPORT_DONT_MANGLE : 0) {
11463
var exported = node.exported_definition;
11464
if ((exported instanceof AST_Defun || exported instanceof AST_DefClass) && node.is_default) {
11465
def.export = MASK_EXPORT_WANT_MANGLE;
11466
}
11467
}
11468
}
11469
11470
// pass 2: find back references and eval
11471
const is_toplevel = this instanceof AST_Toplevel;
11472
if (is_toplevel) {
11473
this.globals = new Map();
11474
}
11475
11476
var tw = new TreeWalker(node => {
11477
if (node instanceof AST_LoopControl && node.label) {
11478
node.label.thedef.references.push(node);
11479
return true;
11480
}
11481
if (node instanceof AST_SymbolRef) {
11482
var name = node.name;
11483
if (name == "eval" && tw.parent() instanceof AST_Call) {
11484
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
11485
s.uses_eval = true;
11486
}
11487
}
11488
var sym;
11489
if (tw.parent() instanceof AST_NameMapping && tw.parent(1).module_name
11490
|| !(sym = node.scope.find_variable(name))) {
11491
11492
sym = toplevel.def_global(node);
11493
if (node instanceof AST_SymbolExport) sym.export = MASK_EXPORT_DONT_MANGLE;
11494
} else if (sym.scope instanceof AST_Lambda && name == "arguments") {
11495
sym.scope.get_defun_scope().uses_arguments = true;
11496
}
11497
node.thedef = sym;
11498
node.reference();
11499
if (node.scope.is_block_scope()
11500
&& !(sym.orig[0] instanceof AST_SymbolBlockDeclaration)) {
11501
node.scope = node.scope.get_defun_scope();
11502
}
11503
return true;
11504
}
11505
// ensure mangling works if catch reuses a scope variable
11506
var def;
11507
if (node instanceof AST_SymbolCatch && (def = redefined_catch_def(node.definition()))) {
11508
var s = node.scope;
11509
while (s) {
11510
push_uniq(s.enclosed, def);
11511
if (s === def.scope) break;
11512
s = s.parent_scope;
11513
}
11514
}
11515
});
11516
this.walk(tw);
11517
11518
// pass 3: work around IE8 and Safari catch scope bugs
11519
if (options.ie8 || options.safari10) {
11520
walk(this, node => {
11521
if (node instanceof AST_SymbolCatch) {
11522
var name = node.name;
11523
var refs = node.thedef.references;
11524
var scope = node.scope.get_defun_scope();
11525
var def = scope.find_variable(name)
11526
|| toplevel.globals.get(name)
11527
|| scope.def_variable(node);
11528
refs.forEach(function(ref) {
11529
ref.thedef = def;
11530
ref.reference();
11531
});
11532
node.thedef = def;
11533
node.reference();
11534
return true;
11535
}
11536
});
11537
}
11538
11539
// pass 4: add symbol definitions to loop scopes
11540
// Safari/Webkit bug workaround - loop init let variable shadowing argument.
11541
// https://github.com/mishoo/UglifyJS2/issues/1753
11542
// https://bugs.webkit.org/show_bug.cgi?id=171041
11543
if (options.safari10) {
11544
for (const scope of for_scopes) {
11545
scope.parent_scope.variables.forEach(function(def) {
11546
push_uniq(scope.enclosed, def);
11547
});
11548
}
11549
}
11550
});
11551
11552
AST_Toplevel.DEFMETHOD("def_global", function(node) {
11553
var globals = this.globals, name = node.name;
11554
if (globals.has(name)) {
11555
return globals.get(name);
11556
} else {
11557
var g = new SymbolDef(this, node);
11558
g.undeclared = true;
11559
g.global = true;
11560
globals.set(name, g);
11561
return g;
11562
}
11563
});
11564
11565
AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) {
11566
this.variables = new Map(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
11567
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
11568
this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
11569
this.parent_scope = parent_scope; // the parent scope
11570
this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
11571
this.cname = -1; // the current index for mangling functions/variables
11572
});
11573
11574
AST_Scope.DEFMETHOD("conflicting_def", function (name) {
11575
return (
11576
this.enclosed.find(def => def.name === name)
11577
|| this.variables.has(name)
11578
|| (this.parent_scope && this.parent_scope.conflicting_def(name))
11579
);
11580
});
11581
11582
AST_Scope.DEFMETHOD("conflicting_def_shallow", function (name) {
11583
return (
11584
this.enclosed.find(def => def.name === name)
11585
|| this.variables.has(name)
11586
);
11587
});
11588
11589
AST_Scope.DEFMETHOD("add_child_scope", function (scope) {
11590
// `scope` is going to be moved into `this` right now.
11591
// Update the required scopes' information
11592
11593
if (scope.parent_scope === this) return;
11594
11595
scope.parent_scope = this;
11596
11597
// Propagate to this.uses_arguments from arrow functions
11598
if ((scope instanceof AST_Arrow) && !this.uses_arguments) {
11599
this.uses_arguments = walk(scope, node => {
11600
if (
11601
node instanceof AST_SymbolRef
11602
&& node.scope instanceof AST_Lambda
11603
&& node.name === "arguments"
11604
) {
11605
return walk_abort;
11606
}
11607
11608
if (node instanceof AST_Lambda && !(node instanceof AST_Arrow)) {
11609
return true;
11610
}
11611
});
11612
}
11613
11614
this.uses_with = this.uses_with || scope.uses_with;
11615
this.uses_eval = this.uses_eval || scope.uses_eval;
11616
11617
const scope_ancestry = (() => {
11618
const ancestry = [];
11619
let cur = this;
11620
do {
11621
ancestry.push(cur);
11622
} while ((cur = cur.parent_scope));
11623
ancestry.reverse();
11624
return ancestry;
11625
})();
11626
11627
const new_scope_enclosed_set = new Set(scope.enclosed);
11628
const to_enclose = [];
11629
for (const scope_topdown of scope_ancestry) {
11630
to_enclose.forEach(e => push_uniq(scope_topdown.enclosed, e));
11631
for (const def of scope_topdown.variables.values()) {
11632
if (new_scope_enclosed_set.has(def)) {
11633
push_uniq(to_enclose, def);
11634
push_uniq(scope_topdown.enclosed, def);
11635
}
11636
}
11637
}
11638
});
11639
11640
function find_scopes_visible_from(scopes) {
11641
const found_scopes = new Set();
11642
11643
for (const scope of new Set(scopes)) {
11644
(function bubble_up(scope) {
11645
if (scope == null || found_scopes.has(scope)) return;
11646
11647
found_scopes.add(scope);
11648
11649
bubble_up(scope.parent_scope);
11650
})(scope);
11651
}
11652
11653
return [...found_scopes];
11654
}
11655
11656
// Creates a symbol during compression
11657
AST_Scope.DEFMETHOD("create_symbol", function(SymClass, {
11658
source,
11659
tentative_name,
11660
scope,
11661
conflict_scopes = [scope],
11662
init = null
11663
} = {}) {
11664
let symbol_name;
11665
11666
conflict_scopes = find_scopes_visible_from(conflict_scopes);
11667
11668
if (tentative_name) {
11669
// Implement hygiene (no new names are conflicting with existing names)
11670
tentative_name =
11671
symbol_name =
11672
tentative_name.replace(/(?:^[^a-z_$]|[^a-z0-9_$])/ig, "_");
11673
11674
let i = 0;
11675
while (conflict_scopes.find(s => s.conflicting_def_shallow(symbol_name))) {
11676
symbol_name = tentative_name + "$" + i++;
11677
}
11678
}
11679
11680
if (!symbol_name) {
11681
throw new Error("No symbol name could be generated in create_symbol()");
11682
}
11683
11684
const symbol = make_node(SymClass, source, {
11685
name: symbol_name,
11686
scope
11687
});
11688
11689
this.def_variable(symbol, init || null);
11690
11691
symbol.mark_enclosed();
11692
11693
return symbol;
11694
});
11695
11696
11697
AST_Node.DEFMETHOD("is_block_scope", return_false);
11698
AST_Class.DEFMETHOD("is_block_scope", return_false);
11699
AST_Lambda.DEFMETHOD("is_block_scope", return_false);
11700
AST_Toplevel.DEFMETHOD("is_block_scope", return_false);
11701
AST_SwitchBranch.DEFMETHOD("is_block_scope", return_false);
11702
AST_Block.DEFMETHOD("is_block_scope", return_true);
11703
AST_Scope.DEFMETHOD("is_block_scope", function () {
11704
return this._block_scope || false;
11705
});
11706
AST_IterationStatement.DEFMETHOD("is_block_scope", return_true);
11707
11708
AST_Lambda.DEFMETHOD("init_scope_vars", function() {
11709
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
11710
this.uses_arguments = false;
11711
this.def_variable(new AST_SymbolFunarg({
11712
name: "arguments",
11713
start: this.start,
11714
end: this.end
11715
}));
11716
});
11717
11718
AST_Arrow.DEFMETHOD("init_scope_vars", function() {
11719
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
11720
this.uses_arguments = false;
11721
});
11722
11723
AST_Symbol.DEFMETHOD("mark_enclosed", function() {
11724
var def = this.definition();
11725
var s = this.scope;
11726
while (s) {
11727
push_uniq(s.enclosed, def);
11728
if (s === def.scope) break;
11729
s = s.parent_scope;
11730
}
11731
});
11732
11733
AST_Symbol.DEFMETHOD("reference", function() {
11734
this.definition().references.push(this);
11735
this.mark_enclosed();
11736
});
11737
11738
AST_Scope.DEFMETHOD("find_variable", function(name) {
11739
if (name instanceof AST_Symbol) name = name.name;
11740
return this.variables.get(name)
11741
|| (this.parent_scope && this.parent_scope.find_variable(name));
11742
});
11743
11744
AST_Scope.DEFMETHOD("def_function", function(symbol, init) {
11745
var def = this.def_variable(symbol, init);
11746
if (!def.init || def.init instanceof AST_Defun) def.init = init;
11747
return def;
11748
});
11749
11750
AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
11751
var def = this.variables.get(symbol.name);
11752
if (def) {
11753
def.orig.push(symbol);
11754
if (def.init && (def.scope !== symbol.scope || def.init instanceof AST_Function)) {
11755
def.init = init;
11756
}
11757
} else {
11758
def = new SymbolDef(this, symbol, init);
11759
this.variables.set(symbol.name, def);
11760
def.global = !this.parent_scope;
11761
}
11762
return symbol.thedef = def;
11763
});
11764
11765
function next_mangled(scope, options) {
11766
let defun_scope;
11767
if (
11768
scopes_with_block_defuns
11769
&& (defun_scope = scope.get_defun_scope())
11770
&& scopes_with_block_defuns.has(defun_scope)
11771
) {
11772
scope = defun_scope;
11773
}
11774
11775
var ext = scope.enclosed;
11776
var nth_identifier = options.nth_identifier;
11777
out: while (true) {
11778
var m = nth_identifier.get(++scope.cname);
11779
if (ALL_RESERVED_WORDS.has(m)) continue; // skip over "do"
11780
11781
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not
11782
// shadow a name reserved from mangling.
11783
if (options.reserved.has(m)) continue;
11784
11785
// Functions with short names might collide with base54 output
11786
// and therefore cause collisions when keep_fnames is true.
11787
if (unmangleable_names && unmangleable_names.has(m)) continue out;
11788
11789
// we must ensure that the mangled name does not shadow a name
11790
// from some parent scope that is referenced in this or in
11791
// inner scopes.
11792
for (let i = ext.length; --i >= 0;) {
11793
const def = ext[i];
11794
const name = def.mangled_name || (def.unmangleable(options) && def.name);
11795
if (m == name) continue out;
11796
}
11797
return m;
11798
}
11799
}
11800
11801
AST_Scope.DEFMETHOD("next_mangled", function(options) {
11802
return next_mangled(this, options);
11803
});
11804
11805
AST_Toplevel.DEFMETHOD("next_mangled", function(options) {
11806
let name;
11807
const mangled_names = this.mangled_names;
11808
do {
11809
name = next_mangled(this, options);
11810
} while (mangled_names.has(name));
11811
return name;
11812
});
11813
11814
AST_Function.DEFMETHOD("next_mangled", function(options, def) {
11815
// #179, #326
11816
// in Safari strict mode, something like (function x(x){...}) is a syntax error;
11817
// a function expression's argument cannot shadow the function expression's name
11818
11819
var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition();
11820
11821
// the function's mangled_name is null when keep_fnames is true
11822
var tricky_name = tricky_def ? tricky_def.mangled_name || tricky_def.name : null;
11823
11824
while (true) {
11825
var name = next_mangled(this, options);
11826
if (!tricky_name || tricky_name != name)
11827
return name;
11828
}
11829
});
11830
11831
AST_Symbol.DEFMETHOD("unmangleable", function(options) {
11832
var def = this.definition();
11833
return !def || def.unmangleable(options);
11834
});
11835
11836
// labels are always mangleable
11837
AST_Label.DEFMETHOD("unmangleable", return_false);
11838
11839
AST_Symbol.DEFMETHOD("unreferenced", function() {
11840
return !this.definition().references.length && !this.scope.pinned();
11841
});
11842
11843
AST_Symbol.DEFMETHOD("definition", function() {
11844
return this.thedef;
11845
});
11846
11847
AST_Symbol.DEFMETHOD("global", function() {
11848
return this.thedef.global;
11849
});
11850
11851
/**
11852
* Format the mangler options (if any) into their appropriate types
11853
*/
11854
function format_mangler_options(options) {
11855
options = defaults(options, {
11856
eval : false,
11857
nth_identifier : base54,
11858
ie8 : false,
11859
keep_classnames: false,
11860
keep_fnames : false,
11861
module : false,
11862
reserved : [],
11863
toplevel : false,
11864
});
11865
if (options.module) options.toplevel = true;
11866
if (!Array.isArray(options.reserved)
11867
&& !(options.reserved instanceof Set)
11868
) {
11869
options.reserved = [];
11870
}
11871
options.reserved = new Set(options.reserved);
11872
// Never mangle arguments
11873
options.reserved.add("arguments");
11874
return options;
11875
}
11876
11877
AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
11878
options = format_mangler_options(options);
11879
var nth_identifier = options.nth_identifier;
11880
11881
// We only need to mangle declaration nodes. Special logic wired
11882
// into the code generator will display the mangled name if it's
11883
// present (and for AST_SymbolRef-s it'll use the mangled name of
11884
// the AST_SymbolDeclaration that it points to).
11885
var lname = -1;
11886
var to_mangle = [];
11887
11888
if (options.keep_fnames) {
11889
function_defs = new Set();
11890
}
11891
11892
const mangled_names = this.mangled_names = new Set();
11893
unmangleable_names = new Set();
11894
11895
if (options.cache) {
11896
this.globals.forEach(collect);
11897
if (options.cache.props) {
11898
options.cache.props.forEach(function(mangled_name) {
11899
mangled_names.add(mangled_name);
11900
});
11901
}
11902
}
11903
11904
var tw = new TreeWalker(function(node, descend) {
11905
if (node instanceof AST_LabeledStatement) {
11906
// lname is incremented when we get to the AST_Label
11907
var save_nesting = lname;
11908
descend();
11909
lname = save_nesting;
11910
return true; // don't descend again in TreeWalker
11911
}
11912
if (
11913
node instanceof AST_Defun
11914
&& !(tw.parent() instanceof AST_Scope)
11915
) {
11916
scopes_with_block_defuns = scopes_with_block_defuns || new Set();
11917
scopes_with_block_defuns.add(node.parent_scope.get_defun_scope());
11918
}
11919
if (node instanceof AST_Scope) {
11920
node.variables.forEach(collect);
11921
return;
11922
}
11923
if (node.is_block_scope()) {
11924
node.block_scope.variables.forEach(collect);
11925
return;
11926
}
11927
if (
11928
function_defs
11929
&& node instanceof AST_VarDef
11930
&& node.value instanceof AST_Lambda
11931
&& !node.value.name
11932
&& keep_name(options.keep_fnames, node.name.name)
11933
) {
11934
function_defs.add(node.name.definition().id);
11935
return;
11936
}
11937
if (node instanceof AST_Label) {
11938
let name;
11939
do {
11940
name = nth_identifier.get(++lname);
11941
} while (ALL_RESERVED_WORDS.has(name));
11942
node.mangled_name = name;
11943
return true;
11944
}
11945
if (!(options.ie8 || options.safari10) && node instanceof AST_SymbolCatch) {
11946
to_mangle.push(node.definition());
11947
return;
11948
}
11949
});
11950
11951
this.walk(tw);
11952
11953
if (options.keep_fnames || options.keep_classnames) {
11954
// Collect a set of short names which are unmangleable,
11955
// for use in avoiding collisions in next_mangled.
11956
to_mangle.forEach(def => {
11957
if (def.name.length < 6 && def.unmangleable(options)) {
11958
unmangleable_names.add(def.name);
11959
}
11960
});
11961
}
11962
11963
to_mangle.forEach(def => { def.mangle(options); });
11964
11965
function_defs = null;
11966
unmangleable_names = null;
11967
scopes_with_block_defuns = null;
11968
11969
function collect(symbol) {
11970
if (symbol.export & MASK_EXPORT_DONT_MANGLE) {
11971
unmangleable_names.add(symbol.name);
11972
} else if (!options.reserved.has(symbol.name)) {
11973
to_mangle.push(symbol);
11974
}
11975
}
11976
});
11977
11978
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
11979
const cache = options.cache && options.cache.props;
11980
const avoid = new Set();
11981
options.reserved.forEach(to_avoid);
11982
this.globals.forEach(add_def);
11983
this.walk(new TreeWalker(function(node) {
11984
if (node instanceof AST_Scope) node.variables.forEach(add_def);
11985
if (node instanceof AST_SymbolCatch) add_def(node.definition());
11986
}));
11987
return avoid;
11988
11989
function to_avoid(name) {
11990
avoid.add(name);
11991
}
11992
11993
function add_def(def) {
11994
var name = def.name;
11995
if (def.global && cache && cache.has(name)) name = cache.get(name);
11996
else if (!def.unmangleable(options)) return;
11997
to_avoid(name);
11998
}
11999
});
12000
12001
AST_Toplevel.DEFMETHOD("expand_names", function(options) {
12002
options = format_mangler_options(options);
12003
var nth_identifier = options.nth_identifier;
12004
if (nth_identifier.reset && nth_identifier.sort) {
12005
nth_identifier.reset();
12006
nth_identifier.sort();
12007
}
12008
var avoid = this.find_colliding_names(options);
12009
var cname = 0;
12010
this.globals.forEach(rename);
12011
this.walk(new TreeWalker(function(node) {
12012
if (node instanceof AST_Scope) node.variables.forEach(rename);
12013
if (node instanceof AST_SymbolCatch) rename(node.definition());
12014
}));
12015
12016
function next_name() {
12017
var name;
12018
do {
12019
name = nth_identifier.get(cname++);
12020
} while (avoid.has(name) || ALL_RESERVED_WORDS.has(name));
12021
return name;
12022
}
12023
12024
function rename(def) {
12025
if (def.global && options.cache) return;
12026
if (def.unmangleable(options)) return;
12027
if (options.reserved.has(def.name)) return;
12028
const redefinition = redefined_catch_def(def);
12029
const name = def.name = redefinition ? redefinition.name : next_name();
12030
def.orig.forEach(function(sym) {
12031
sym.name = name;
12032
});
12033
def.references.forEach(function(sym) {
12034
sym.name = name;
12035
});
12036
}
12037
});
12038
12039
AST_Node.DEFMETHOD("tail_node", return_this);
12040
AST_Sequence.DEFMETHOD("tail_node", function() {
12041
return this.expressions[this.expressions.length - 1];
12042
});
12043
12044
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
12045
options = format_mangler_options(options);
12046
var nth_identifier = options.nth_identifier;
12047
if (!nth_identifier.reset || !nth_identifier.consider || !nth_identifier.sort) {
12048
// If the identifier mangler is invariant, skip computing character frequency.
12049
return;
12050
}
12051
nth_identifier.reset();
12052
12053
try {
12054
AST_Node.prototype.print = function(stream, force_parens) {
12055
this._print(stream, force_parens);
12056
if (this instanceof AST_Symbol && !this.unmangleable(options)) {
12057
nth_identifier.consider(this.name, -1);
12058
} else if (options.properties) {
12059
if (this instanceof AST_DotHash) {
12060
nth_identifier.consider("#" + this.property, -1);
12061
} else if (this instanceof AST_Dot) {
12062
nth_identifier.consider(this.property, -1);
12063
} else if (this instanceof AST_Sub) {
12064
skip_string(this.property);
12065
}
12066
}
12067
};
12068
nth_identifier.consider(this.print_to_string(), 1);
12069
} finally {
12070
AST_Node.prototype.print = AST_Node.prototype._print;
12071
}
12072
nth_identifier.sort();
12073
12074
function skip_string(node) {
12075
if (node instanceof AST_String) {
12076
nth_identifier.consider(node.value, -1);
12077
} else if (node instanceof AST_Conditional) {
12078
skip_string(node.consequent);
12079
skip_string(node.alternative);
12080
} else if (node instanceof AST_Sequence) {
12081
skip_string(node.tail_node());
12082
}
12083
}
12084
});
12085
12086
const base54 = (() => {
12087
const leading = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_".split("");
12088
const digits = "0123456789".split("");
12089
let chars;
12090
let frequency;
12091
function reset() {
12092
frequency = new Map();
12093
leading.forEach(function(ch) {
12094
frequency.set(ch, 0);
12095
});
12096
digits.forEach(function(ch) {
12097
frequency.set(ch, 0);
12098
});
12099
}
12100
function consider(str, delta) {
12101
for (var i = str.length; --i >= 0;) {
12102
frequency.set(str[i], frequency.get(str[i]) + delta);
12103
}
12104
}
12105
function compare(a, b) {
12106
return frequency.get(b) - frequency.get(a);
12107
}
12108
function sort() {
12109
chars = mergeSort(leading, compare).concat(mergeSort(digits, compare));
12110
}
12111
// Ensure this is in a usable initial state.
12112
reset();
12113
sort();
12114
function base54(num) {
12115
var ret = "", base = 54;
12116
num++;
12117
do {
12118
num--;
12119
ret += chars[num % base];
12120
num = Math.floor(num / base);
12121
base = 64;
12122
} while (num > 0);
12123
return ret;
12124
}
12125
12126
return {
12127
get: base54,
12128
consider,
12129
reset,
12130
sort
12131
};
12132
})();
12133
12134
exports.AST_Node = AST_Node;
12135
exports.AST_Token = AST_Token;
12136
12137
})));
12138
12139