Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
FogNetwork
GitHub Repository: FogNetwork/Tsunami
Path: blob/main/lib/esotope.js
1034 views
1
// -------------------------------------------------------------
2
// WARNING: this file is used by both the client and the server.
3
// Do not use any browser or node-specific API!
4
// -------------------------------------------------------------
5
6
/*
7
Copyright (C) 2014 Ivan Nikulin <[email protected]>
8
Copyright (C) 2012-2014 Yusuke Suzuki <[email protected]>
9
Copyright (C) 2012-2013 Michael Ficarra <[email protected]>
10
Copyright (C) 2012-2013 Mathias Bynens <[email protected]>
11
Copyright (C) 2013 Irakli Gozalishvili <[email protected]>
12
Copyright (C) 2012 Robert Gust-Bardon <[email protected]>
13
Copyright (C) 2012 John Freeman <[email protected]>
14
Copyright (C) 2011-2012 Ariya Hidayat <[email protected]>
15
Copyright (C) 2012 Joost-Wim Boekesteijn <[email protected]>
16
Copyright (C) 2012 Kris Kowal <[email protected]>
17
Copyright (C) 2012 Arpad Borsos <[email protected]>
18
19
Redistribution and use in source and binary forms, with or without
20
modification, are permitted provided that the following conditions are met:
21
22
* Redistributions of source code must retain the above copyright
23
notice, this list of conditions and the following disclaimer.
24
* Redistributions in binary form must reproduce the above copyright
25
notice, this list of conditions and the following disclaimer in the
26
documentation and/or other materials provided with the distribution.
27
28
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
32
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
37
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
*/
39
40
'use strict';
41
42
var isArray,
43
json,
44
renumber,
45
hexadecimal,
46
quotes,
47
escapeless,
48
parentheses,
49
semicolons,
50
safeConcatenation,
51
directive,
52
extra,
53
parse;
54
55
var Syntax = {
56
AssignmentExpression: 'AssignmentExpression',
57
AssignmentPattern: 'AssignmentPattern',
58
ArrayExpression: 'ArrayExpression',
59
ArrayPattern: 'ArrayPattern',
60
ArrowFunctionExpression: 'ArrowFunctionExpression',
61
AwaitExpression: 'AwaitExpression',
62
BlockStatement: 'BlockStatement',
63
BinaryExpression: 'BinaryExpression',
64
BreakStatement: 'BreakStatement',
65
CallExpression: 'CallExpression',
66
CatchClause: 'CatchClause',
67
ClassBody: 'ClassBody',
68
ClassDeclaration: 'ClassDeclaration',
69
ClassExpression: 'ClassExpression',
70
ComprehensionBlock: 'ComprehensionBlock',
71
ComprehensionExpression: 'ComprehensionExpression',
72
ConditionalExpression: 'ConditionalExpression',
73
ContinueStatement: 'ContinueStatement',
74
DirectiveStatement: 'DirectiveStatement',
75
DoWhileStatement: 'DoWhileStatement',
76
DebuggerStatement: 'DebuggerStatement',
77
EmptyStatement: 'EmptyStatement',
78
ExportAllDeclaration: 'ExportAllDeclaration',
79
ExportBatchSpecifier: 'ExportBatchSpecifier',
80
ExportDeclaration: 'ExportDeclaration',
81
ExportNamedDeclaration: 'ExportNamedDeclaration',
82
ExportSpecifier: 'ExportSpecifier',
83
ExpressionStatement: 'ExpressionStatement',
84
ForStatement: 'ForStatement',
85
ForInStatement: 'ForInStatement',
86
ForOfStatement: 'ForOfStatement',
87
FunctionDeclaration: 'FunctionDeclaration',
88
FunctionExpression: 'FunctionExpression',
89
GeneratorExpression: 'GeneratorExpression',
90
Identifier: 'Identifier',
91
IfStatement: 'IfStatement',
92
ImportExpression: 'ImportExpression',
93
ImportSpecifier: 'ImportSpecifier',
94
ImportDeclaration: 'ImportDeclaration',
95
ChainExpression: 'ChainExpression',
96
Literal: 'Literal',
97
LabeledStatement: 'LabeledStatement',
98
LogicalExpression: 'LogicalExpression',
99
MemberExpression: 'MemberExpression',
100
MetaProperty: 'MetaProperty',
101
MethodDefinition: 'MethodDefinition',
102
ModuleDeclaration: 'ModuleDeclaration',
103
NewExpression: 'NewExpression',
104
ObjectExpression: 'ObjectExpression',
105
ObjectPattern: 'ObjectPattern',
106
Program: 'Program',
107
Property: 'Property',
108
RestElement: 'RestElement',
109
ReturnStatement: 'ReturnStatement',
110
SequenceExpression: 'SequenceExpression',
111
SpreadElement: 'SpreadElement',
112
Super: 'Super',
113
SwitchStatement: 'SwitchStatement',
114
SwitchCase: 'SwitchCase',
115
TaggedTemplateExpression: 'TaggedTemplateExpression',
116
TemplateElement: 'TemplateElement',
117
TemplateLiteral: 'TemplateLiteral',
118
ThisExpression: 'ThisExpression',
119
ThrowStatement: 'ThrowStatement',
120
TryStatement: 'TryStatement',
121
UnaryExpression: 'UnaryExpression',
122
UpdateExpression: 'UpdateExpression',
123
VariableDeclaration: 'VariableDeclaration',
124
VariableDeclarator: 'VariableDeclarator',
125
WhileStatement: 'WhileStatement',
126
WithStatement: 'WithStatement',
127
YieldExpression: 'YieldExpression'
128
};
129
130
exports.Syntax = Syntax;
131
132
var Precedence = {
133
Sequence: 0,
134
Yield: 1,
135
Assignment: 1,
136
Conditional: 2,
137
ArrowFunction: 2,
138
Coalesce: 3,
139
LogicalOR: 3,
140
LogicalAND: 4,
141
BitwiseOR: 5,
142
BitwiseXOR: 6,
143
BitwiseAND: 7,
144
Equality: 8,
145
Relational: 9,
146
BitwiseSHIFT: 10,
147
Additive: 11,
148
Multiplicative: 12,
149
Unary: 13,
150
Exponentiation: 14,
151
Postfix: 14,
152
Await: 14,
153
Call: 15,
154
New: 16,
155
TaggedTemplate: 17,
156
OptionalChaining: 17,
157
Member: 18,
158
Primary: 19
159
};
160
161
var BinaryPrecedence = {
162
'||': Precedence.LogicalOR,
163
'&&': Precedence.LogicalAND,
164
'|': Precedence.BitwiseOR,
165
'^': Precedence.BitwiseXOR,
166
'&': Precedence.BitwiseAND,
167
'==': Precedence.Equality,
168
'!=': Precedence.Equality,
169
'===': Precedence.Equality,
170
'!==': Precedence.Equality,
171
'is': Precedence.Equality,
172
'isnt': Precedence.Equality,
173
'<': Precedence.Relational,
174
'>': Precedence.Relational,
175
'<=': Precedence.Relational,
176
'>=': Precedence.Relational,
177
'in': Precedence.Relational,
178
'instanceof': Precedence.Relational,
179
'<<': Precedence.BitwiseSHIFT,
180
'>>': Precedence.BitwiseSHIFT,
181
'>>>': Precedence.BitwiseSHIFT,
182
'+': Precedence.Additive,
183
'-': Precedence.Additive,
184
'*': Precedence.Multiplicative,
185
'%': Precedence.Multiplicative,
186
'/': Precedence.Multiplicative,
187
'??': Precedence.Coalesce,
188
'**': Precedence.Exponentiation
189
};
190
191
function getDefaultOptions () {
192
// default options
193
return {
194
indent: null,
195
base: null,
196
parse: null,
197
format: {
198
indent: {
199
style: ' ',
200
base: 0
201
},
202
newline: '\n',
203
space: ' ',
204
json: false,
205
renumber: false,
206
hexadecimal: false,
207
quotes: 'single',
208
escapeless: false,
209
compact: false,
210
parentheses: true,
211
semicolons: true,
212
safeConcatenation: false
213
},
214
directive: false,
215
raw: true,
216
verbatim: null
217
};
218
}
219
220
//-------------------------------------------------===------------------------------------------------------
221
// Lexical utils
222
//-------------------------------------------------===------------------------------------------------------
223
224
//Const
225
var NON_ASCII_WHITESPACES = [
226
0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005,
227
0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000,
228
0xFEFF
229
];
230
231
//Regular expressions
232
var NON_ASCII_IDENTIFIER_CHARACTERS_REGEXP = new RegExp(
233
'[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376' +
234
'\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-' +
235
'\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA' +
236
'\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-' +
237
'\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0\u08A2-\u08AC\u08E4-\u08FE\u0900-' +
238
'\u0963\u0966-\u096F\u0971-\u0977\u0979-\u097F\u0981-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-' +
239
'\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-' +
240
'\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38' +
241
'\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83' +
242
'\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9' +
243
'\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-' +
244
'\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-' +
245
'\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E' +
246
'\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-' +
247
'\u0BEF\u0C01-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D-\u0C44\u0C46-' +
248
'\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C82\u0C83\u0C85-\u0C8C\u0C8E-' +
249
'\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE' +
250
'\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D02\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44' +
251
'\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-' +
252
'\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E01-\u0E3A' +
253
'\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-' +
254
'\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9' +
255
'\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84' +
256
'\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-' +
257
'\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5' +
258
'\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-' +
259
'\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-' +
260
'\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD' +
261
'\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191C\u1920-\u192B' +
262
'\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E' +
263
'\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-' +
264
'\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1D00-\u1DE6\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-' +
265
'\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-' +
266
'\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F' +
267
'\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115' +
268
'\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188' +
269
'\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-' +
270
'\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-' +
271
'\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A' +
272
'\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5' +
273
'\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA697' +
274
'\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA827\uA840-\uA873' +
275
'\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-' +
276
'\uA9D9\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7B\uAA80-\uAAC2\uAADB-\uAADD\uAAE0-' +
277
'\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABEA\uABEC' +
278
'\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-' +
279
'\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D' +
280
'\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE26\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74' +
281
'\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-' +
282
'\uFFD7\uFFDA-\uFFDC]'
283
);
284
285
286
//Methods
287
function isIdentifierCh (cp) {
288
if (cp < 0x80) {
289
return cp >= 97 && cp <= 122 || // a..z
290
cp >= 65 && cp <= 90 || // A..Z
291
cp >= 48 && cp <= 57 || // 0..9
292
cp === 36 || cp === 95 || // $ (dollar) and _ (underscore)
293
cp === 92; // \ (backslash)
294
}
295
296
var ch = String.fromCharCode(cp);
297
298
return NON_ASCII_IDENTIFIER_CHARACTERS_REGEXP.test(ch);
299
}
300
301
function isLineTerminator (cp) {
302
return cp === 0x0A || cp === 0x0D || cp === 0x2028 || cp === 0x2029;
303
}
304
305
function isWhitespace (cp) {
306
return cp === 0x20 || cp === 0x09 || isLineTerminator(cp) || cp === 0x0B || cp === 0x0C || cp === 0xA0 ||
307
(cp >= 0x1680 && NON_ASCII_WHITESPACES.indexOf(cp) >= 0);
308
}
309
310
function isDecimalDigit (cp) {
311
return cp >= 48 && cp <= 57;
312
}
313
314
function stringRepeat (str, num) {
315
var result = '';
316
317
for (num |= 0; num > 0; num >>>= 1, str += str) {
318
if (num & 1) {
319
result += str;
320
}
321
}
322
323
return result;
324
}
325
326
isArray = Array.isArray;
327
if (!isArray) {
328
isArray = function isArray (array) {
329
return Object.prototype.toString.call(array) === '[object Array]';
330
};
331
}
332
333
334
function updateDeeply (target, override) {
335
var key, val;
336
337
function isHashObject (target) {
338
return typeof target === 'object' && target instanceof Object && !(target instanceof RegExp);
339
}
340
341
for (key in override) {
342
if (override.hasOwnProperty(key)) {
343
val = override[key];
344
if (isHashObject(val)) {
345
if (isHashObject(target[key])) {
346
updateDeeply(target[key], val);
347
}
348
else {
349
target[key] = updateDeeply({}, val);
350
}
351
}
352
else {
353
target[key] = val;
354
}
355
}
356
}
357
return target;
358
}
359
360
function generateNumber (value) {
361
var result, point, temp, exponent, pos;
362
363
if (value === 1 / 0) {
364
return json ? 'null' : renumber ? '1e400' : '1e+400';
365
}
366
367
result = '' + value;
368
if (!renumber || result.length < 3) {
369
return result;
370
}
371
372
point = result.indexOf('.');
373
//NOTE: 0x30 == '0'
374
if (!json && result.charCodeAt(0) === 0x30 && point === 1) {
375
point = 0;
376
result = result.slice(1);
377
}
378
temp = result;
379
result = result.replace('e+', 'e');
380
exponent = 0;
381
if ((pos = temp.indexOf('e')) > 0) {
382
exponent = +temp.slice(pos + 1);
383
temp = temp.slice(0, pos);
384
}
385
if (point >= 0) {
386
exponent -= temp.length - point - 1;
387
temp = +(temp.slice(0, point) + temp.slice(point + 1)) + '';
388
}
389
pos = 0;
390
391
//NOTE: 0x30 == '0'
392
while (temp.charCodeAt(temp.length + pos - 1) === 0x30) {
393
--pos;
394
}
395
if (pos !== 0) {
396
exponent -= pos;
397
temp = temp.slice(0, pos);
398
}
399
if (exponent !== 0) {
400
temp += 'e' + exponent;
401
}
402
if ((temp.length < result.length ||
403
(hexadecimal && value > 1e12 && Math.floor(value) === value &&
404
(temp = '0x' + value.toString(16)).length
405
< result.length)) &&
406
+temp === value) {
407
result = temp;
408
}
409
410
return result;
411
}
412
413
// Generate valid RegExp expression.
414
// This function is based on https://github.com/Constellation/iv Engine
415
416
function escapeRegExpCharacter (ch, previousIsBackslash) {
417
// not handling '\' and handling \u2028 or \u2029 to unicode escape sequence
418
if ((ch & ~1) === 0x2028) {
419
return (previousIsBackslash ? 'u' : '\\u') + ((ch === 0x2028) ? '2028' : '2029');
420
}
421
else if (ch === 10 || ch === 13) { // \n, \r
422
return (previousIsBackslash ? '' : '\\') + ((ch === 10) ? 'n' : 'r');
423
}
424
return String.fromCharCode(ch);
425
}
426
427
function generateRegExp (reg) {
428
var match, result, flags, i, iz, ch, characterInBrack, previousIsBackslash;
429
430
result = reg.toString();
431
432
if (reg.source) {
433
// extract flag from toString result
434
match = result.match(/\/([^/]*)$/);
435
if (!match) {
436
return result;
437
}
438
439
flags = match[1];
440
result = '';
441
442
characterInBrack = false;
443
previousIsBackslash = false;
444
for (i = 0, iz = reg.source.length; i < iz; ++i) {
445
ch = reg.source.charCodeAt(i);
446
447
if (!previousIsBackslash) {
448
if (characterInBrack) {
449
if (ch === 93) { // ]
450
characterInBrack = false;
451
}
452
}
453
else {
454
if (ch === 47) { // /
455
result += '\\';
456
}
457
else if (ch === 91) { // [
458
characterInBrack = true;
459
}
460
}
461
result += escapeRegExpCharacter(ch, previousIsBackslash);
462
previousIsBackslash = ch === 92; // \
463
}
464
else {
465
// if new RegExp("\\\n') is provided, create /\n/
466
result += escapeRegExpCharacter(ch, previousIsBackslash);
467
// prevent like /\\[/]/
468
previousIsBackslash = false;
469
}
470
}
471
472
return '/' + result + '/' + flags;
473
}
474
475
return result;
476
}
477
478
function escapeAllowedCharacter (code, next) {
479
var hex, result = '\\';
480
481
switch (code) {
482
case 0x08: // \b
483
result += 'b';
484
break;
485
case 0x0C: // \f
486
result += 'f';
487
break;
488
case 0x09: // \t
489
result += 't';
490
break;
491
default:
492
hex = code.toString(16).toUpperCase();
493
if (json || code > 0xFF) {
494
result += 'u' + '0000'.slice(hex.length) + hex;
495
}
496
497
else if (code === 0x0000 && !isDecimalDigit(next)) {
498
result += '0';
499
}
500
501
else if (code === 0x000B) { // \v
502
result += 'x0B';
503
}
504
505
else {
506
result += 'x' + '00'.slice(hex.length) + hex;
507
}
508
break;
509
}
510
511
return result;
512
}
513
514
function escapeDisallowedCharacter (code) {
515
var result = '\\';
516
switch (code) {
517
case 0x5C // \
518
:
519
result += '\\';
520
break;
521
case 0x0A // \n
522
:
523
result += 'n';
524
break;
525
case 0x0D // \r
526
:
527
result += 'r';
528
break;
529
case 0x2028:
530
result += 'u2028';
531
break;
532
case 0x2029:
533
result += 'u2029';
534
break;
535
}
536
537
return result;
538
}
539
540
function escapeDirective (str) {
541
var i, iz, code, quote;
542
543
quote = quotes === 'double' ? '"' : '\'';
544
for (i = 0, iz = str.length; i < iz; ++i) {
545
code = str.charCodeAt(i);
546
if (code === 0x27) { // '
547
quote = '"';
548
break;
549
}
550
else if (code === 0x22) { // "
551
quote = '\'';
552
break;
553
}
554
else if (code === 0x5C) { // \
555
++i;
556
}
557
}
558
559
return quote + str + quote;
560
}
561
562
function escapeString (str) {
563
var result = '', i, len, code, singleQuotes = 0, doubleQuotes = 0, single, quote;
564
//TODO http://jsperf.com/character-counting/8
565
for (i = 0, len = str.length; i < len; ++i) {
566
code = str.charCodeAt(i);
567
if (code === 0x27) { // '
568
++singleQuotes;
569
}
570
else if (code === 0x22) { // "
571
++doubleQuotes;
572
}
573
else if (code === 0x2F && json) { // /
574
result += '\\';
575
}
576
else if (isLineTerminator(code) || code === 0x5C) { // \
577
result += escapeDisallowedCharacter(code);
578
continue;
579
}
580
else if ((json && code < 0x20) || // SP
581
!(json || escapeless || (code >= 0x20 && code <= 0x7E))) { // SP, ~
582
result += escapeAllowedCharacter(code, str.charCodeAt(i + 1));
583
continue;
584
}
585
result += String.fromCharCode(code);
586
}
587
588
single = !(quotes === 'double' || (quotes === 'auto' && doubleQuotes < singleQuotes));
589
quote = single ? '\'' : '"';
590
591
if (!(single ? singleQuotes : doubleQuotes)) {
592
return quote + result + quote;
593
}
594
595
str = result;
596
result = quote;
597
598
for (i = 0, len = str.length; i < len; ++i) {
599
code = str.charCodeAt(i);
600
if ((code === 0x27 && single) || (code === 0x22 && !single)) { // ', "
601
result += '\\';
602
}
603
result += String.fromCharCode(code);
604
}
605
606
return result + quote;
607
}
608
609
610
function join (l, r) {
611
if (!l.length)
612
return r;
613
614
if (!r.length)
615
return l;
616
617
var lCp = l.charCodeAt(l.length - 1),
618
rCp = r.charCodeAt(0);
619
620
if (isIdentifierCh(lCp) && isIdentifierCh(rCp) ||
621
lCp === rCp && (lCp === 0x2B || lCp === 0x2D) || // + +, - -
622
lCp === 0x2F && rCp === 0x69) { // /re/ instanceof foo
623
return l + _.space + r;
624
}
625
626
else if (isWhitespace(lCp) || isWhitespace(rCp))
627
return l + r;
628
629
return l + _.optSpace + r;
630
}
631
632
function shiftIndent () {
633
var prevIndent = _.indent;
634
635
_.indent += _.indentUnit;
636
return prevIndent;
637
}
638
639
function adoptionPrefix ($stmt) {
640
if ($stmt.type === Syntax.BlockStatement)
641
return _.optSpace;
642
643
if ($stmt.type === Syntax.EmptyStatement)
644
return '';
645
646
return _.newline + _.indent + _.indentUnit;
647
}
648
649
function adoptionSuffix ($stmt) {
650
if ($stmt.type === Syntax.BlockStatement)
651
return _.optSpace;
652
653
return _.newline + _.indent;
654
}
655
656
//Subentities generators
657
function generateVerbatim ($expr, settings) {
658
var verbatim = $expr[extra.verbatim],
659
strVerbatim = typeof verbatim === 'string',
660
precedence = !strVerbatim &&
661
verbatim.precedence !== void 0 ? verbatim.precedence : Precedence.Sequence,
662
parenthesize = precedence < settings.precedence,
663
content = strVerbatim ? verbatim : verbatim.content,
664
chunks = content.split(/\r\n|\n/),
665
chunkCount = chunks.length;
666
667
if (parenthesize)
668
_.js += '(';
669
670
_.js += chunks[0];
671
672
for (var i = 1; i < chunkCount; i++)
673
_.js += _.newline + _.indent + chunks[i];
674
675
if (parenthesize)
676
_.js += ')';
677
}
678
679
function generateFunctionParams ($node) {
680
var $params = $node.params,
681
paramCount = $params.length,
682
lastParamIdx = paramCount - 1,
683
arrowFuncWithoutParentheses = $node.type === Syntax.ArrowFunctionExpression && paramCount === 1 &&
684
$params[0].type === Syntax.Identifier;
685
686
//NOTE: arg => { } case
687
if (arrowFuncWithoutParentheses)
688
_.js += $params[0].name;
689
690
else {
691
_.js += '(';
692
693
for (var i = 0; i < paramCount; ++i) {
694
var $param = $params[i];
695
696
if ($params[i].type === Syntax.Identifier)
697
_.js += $param.name;
698
699
else
700
ExprGen[$param.type]($param, Preset.e4);
701
702
if (i !== lastParamIdx)
703
_.js += ',' + _.optSpace;
704
}
705
706
_.js += ')';
707
}
708
}
709
710
function generateFunctionBody ($node) {
711
var $body = $node.body;
712
713
generateFunctionParams($node);
714
715
if ($node.type === Syntax.ArrowFunctionExpression)
716
_.js += _.optSpace + '=>';
717
718
if ($node.expression) {
719
_.js += _.optSpace;
720
721
var exprJs = exprToJs($body, Preset.e4);
722
723
if (exprJs.charAt(0) === '{')
724
exprJs = '(' + exprJs + ')';
725
726
_.js += exprJs;
727
}
728
729
else {
730
_.js += adoptionPrefix($body);
731
StmtGen[$body.type]($body, Preset.s8);
732
}
733
}
734
735
736
//-------------------------------------------------===------------------------------------------------------
737
// Syntactic entities generation presets
738
//-------------------------------------------------===------------------------------------------------------
739
740
var Preset = {
741
e1: function (allowIn) {
742
return {
743
precedence: Precedence.Assignment,
744
allowIn: allowIn,
745
allowCall: true,
746
allowUnparenthesizedNew: true
747
};
748
},
749
750
e2: function (allowIn) {
751
return {
752
precedence: Precedence.LogicalOR,
753
allowIn: allowIn,
754
allowCall: true,
755
allowUnparenthesizedNew: true
756
};
757
},
758
759
e3: {
760
precedence: Precedence.Call,
761
allowIn: true,
762
allowCall: true,
763
allowUnparenthesizedNew: false
764
},
765
766
e4: {
767
precedence: Precedence.Assignment,
768
allowIn: true,
769
allowCall: true,
770
allowUnparenthesizedNew: true
771
},
772
773
e5: {
774
precedence: Precedence.Sequence,
775
allowIn: true,
776
allowCall: true,
777
allowUnparenthesizedNew: true
778
},
779
780
e6: function (allowUnparenthesizedNew) {
781
return {
782
precedence: Precedence.New,
783
allowIn: true,
784
allowCall: false,
785
allowUnparenthesizedNew: allowUnparenthesizedNew
786
};
787
},
788
789
e7: {
790
precedence: Precedence.Unary,
791
allowIn: true,
792
allowCall: true,
793
allowUnparenthesizedNew: true
794
},
795
796
e8: {
797
precedence: Precedence.Postfix,
798
allowIn: true,
799
allowCall: true,
800
allowUnparenthesizedNew: true
801
},
802
803
e9: {
804
precedence: void 0,
805
allowIn: true,
806
allowCall: true,
807
allowUnparenthesizedNew: true
808
},
809
810
e10: {
811
precedence: Precedence.Call,
812
allowIn: true,
813
allowCall: true,
814
allowUnparenthesizedNew: true
815
},
816
817
e11: function (allowCall) {
818
return {
819
precedence: Precedence.Call,
820
allowIn: true,
821
allowCall: allowCall,
822
allowUnparenthesizedNew: false
823
};
824
},
825
826
e12: {
827
precedence: Precedence.Primary,
828
allowIn: false,
829
allowCall: false,
830
allowUnparenthesizedNew: true
831
},
832
833
e13: {
834
precedence: Precedence.Primary,
835
allowIn: true,
836
allowCall: true,
837
allowUnparenthesizedNew: true
838
},
839
840
841
e14: {
842
precedence: Precedence.Sequence,
843
allowIn: false,
844
allowCall: true,
845
allowUnparenthesizedNew: true
846
},
847
848
849
e15: function (allowCall) {
850
return {
851
precedence: Precedence.Sequence,
852
allowIn: true,
853
allowCall: allowCall,
854
allowUnparenthesizedNew: true
855
};
856
},
857
858
e16: function (precedence, allowIn) {
859
return {
860
precedence: precedence,
861
allowIn: allowIn,
862
allowCall: true,
863
allowUnparenthesizedNew: true
864
};
865
},
866
867
e17: function (allowIn) {
868
return {
869
precedence: Precedence.Call,
870
allowIn: allowIn,
871
allowCall: true,
872
allowUnparenthesizedNew: true
873
}
874
},
875
876
e18: function (allowIn) {
877
return {
878
precedence: Precedence.Assignment,
879
allowIn: allowIn,
880
allowCall: true,
881
allowUnparenthesizedNew: true
882
}
883
},
884
885
e19: {
886
precedence: Precedence.Sequence,
887
allowIn: true,
888
allowCall: true,
889
semicolonOptional: false
890
},
891
892
e20: {
893
precedence: Precedence.Await,
894
allowCall: true
895
},
896
897
s1: function (functionBody, semicolonOptional) {
898
return {
899
allowIn: true,
900
functionBody: false,
901
directiveContext: functionBody,
902
semicolonOptional: semicolonOptional
903
};
904
},
905
906
s2: {
907
allowIn: true,
908
functionBody: false,
909
directiveContext: false,
910
semicolonOptional: true
911
},
912
913
s3: function (allowIn) {
914
return {
915
allowIn: allowIn,
916
functionBody: false,
917
directiveContext: false,
918
semicolonOptional: false
919
};
920
},
921
922
s4: function (semicolonOptional) {
923
return {
924
allowIn: true,
925
functionBody: false,
926
directiveContext: false,
927
semicolonOptional: semicolonOptional
928
};
929
},
930
931
s5: function (semicolonOptional) {
932
return {
933
allowIn: true,
934
functionBody: false,
935
directiveContext: true,
936
semicolonOptional: semicolonOptional,
937
};
938
},
939
940
s6: {
941
allowIn: false,
942
functionBody: false,
943
directiveContext: false,
944
semicolonOptional: false
945
},
946
947
s7: {
948
allowIn: true,
949
functionBody: false,
950
directiveContext: false,
951
semicolonOptional: false
952
},
953
954
s8: {
955
allowIn: true,
956
functionBody: true,
957
directiveContext: false,
958
semicolonOptional: false
959
}
960
};
961
962
963
//-------------------------------------------------===-------------------------------------------------------
964
// Expressions
965
//-------------------------------------------------===-------------------------------------------------------
966
967
//Regular expressions
968
var FLOATING_OR_OCTAL_REGEXP = /[.eExX]|^0[0-9]+/,
969
LAST_DECIMAL_DIGIT_REGEXP = /[0-9]$/;
970
971
972
//Common expression generators
973
function generateLogicalOrBinaryExpression ($expr, settings) {
974
var op = $expr.operator,
975
precedence = BinaryPrecedence[$expr.operator],
976
parenthesize = precedence < settings.precedence,
977
allowIn = settings.allowIn || parenthesize,
978
operandGenSettings = Preset.e16(precedence, allowIn),
979
exprJs = exprToJs($expr.left, operandGenSettings);
980
981
parenthesize |= op === 'in' && !allowIn;
982
983
if (parenthesize)
984
_.js += '(';
985
986
// 0x2F = '/'
987
if (exprJs.charCodeAt(exprJs.length - 1) === 0x2F && isIdentifierCh(op.charCodeAt(0)))
988
exprJs = exprJs + _.space + op;
989
990
else
991
exprJs = join(exprJs, op);
992
993
operandGenSettings.precedence++;
994
995
var rightJs = exprToJs($expr.right, operandGenSettings);
996
997
//NOTE: If '/' concats with '/' or `<` concats with `!--`, it is interpreted as comment start
998
if (op === '/' && rightJs.charAt(0) === '/' || op.slice(-1) === '<' && rightJs.slice(0, 3) === '!--')
999
exprJs += _.space + rightJs;
1000
1001
else
1002
exprJs = join(exprJs, rightJs);
1003
1004
_.js += exprJs;
1005
1006
if (parenthesize)
1007
_.js += ')';
1008
}
1009
1010
function generateArrayPatternOrExpression ($expr) {
1011
var $elems = $expr.elements,
1012
elemCount = $elems.length;
1013
1014
if (elemCount) {
1015
var lastElemIdx = elemCount - 1,
1016
multiline = elemCount > 1,
1017
prevIndent = shiftIndent(),
1018
itemPrefix = _.newline + _.indent;
1019
1020
_.js += '[';
1021
1022
for (var i = 0; i < elemCount; i++) {
1023
var $elem = $elems[i];
1024
1025
if (multiline)
1026
_.js += itemPrefix;
1027
1028
if ($elem)
1029
ExprGen[$elem.type]($elem, Preset.e4);
1030
1031
if (i !== lastElemIdx || !$elem)
1032
_.js += ',';
1033
}
1034
1035
_.indent = prevIndent;
1036
1037
if (multiline)
1038
_.js += _.newline + _.indent;
1039
1040
_.js += ']';
1041
}
1042
1043
else
1044
_.js += '[]';
1045
}
1046
1047
function generateGeneratorOrComprehensionExpression ($expr) {
1048
//NOTE: GeneratorExpression should be parenthesized with (...), ComprehensionExpression with [...]
1049
var $blocks = $expr.blocks,
1050
$filter = $expr.filter,
1051
isGenerator = $expr.type === Syntax.GeneratorExpression,
1052
exprJs = isGenerator ? '(' : '[',
1053
bodyJs = exprToJs($expr.body, Preset.e4);
1054
1055
if ($blocks) {
1056
var prevIndent = shiftIndent(),
1057
blockCount = $blocks.length;
1058
1059
for (var i = 0; i < blockCount; ++i) {
1060
var blockJs = exprToJs($blocks[i], Preset.e5);
1061
1062
exprJs = i > 0 ? join(exprJs, blockJs) : (exprJs + blockJs);
1063
}
1064
1065
_.indent = prevIndent;
1066
}
1067
1068
if ($filter) {
1069
var filterJs = exprToJs($filter, Preset.e5);
1070
1071
exprJs = join(exprJs, 'if' + _.optSpace);
1072
exprJs = join(exprJs, '(' + filterJs + ')');
1073
}
1074
1075
exprJs = join(exprJs, bodyJs);
1076
exprJs += isGenerator ? ')' : ']';
1077
1078
_.js += exprJs;
1079
}
1080
1081
1082
//Expression raw generator dictionary
1083
var ExprRawGen = {
1084
SequenceExpression: function generateSequenceExpression ($expr, settings) {
1085
var $children = $expr.expressions,
1086
childrenCount = $children.length,
1087
lastChildIdx = childrenCount - 1,
1088
parenthesize = Precedence.Sequence < settings.precedence,
1089
exprGenSettings = Preset.e1(settings.allowIn || parenthesize);
1090
1091
if (parenthesize)
1092
_.js += '(';
1093
1094
for (var i = 0; i < childrenCount; i++) {
1095
var $child = $children[i];
1096
1097
ExprGen[$child.type]($child, exprGenSettings);
1098
1099
if (i !== lastChildIdx)
1100
_.js += ',' + _.optSpace;
1101
}
1102
1103
if (parenthesize)
1104
_.js += ')';
1105
},
1106
1107
AssignmentExpression: function generateAssignmentExpression ($expr, settings) {
1108
var $left = $expr.left,
1109
$right = $expr.right,
1110
parenthesize = Precedence.Assignment < settings.precedence,
1111
allowIn = settings.allowIn || parenthesize;
1112
1113
if (parenthesize)
1114
_.js += '(';
1115
1116
ExprGen[$left.type]($left, Preset.e17(allowIn));
1117
_.js += _.optSpace + $expr.operator + _.optSpace;
1118
ExprGen[$right.type]($right, Preset.e18(allowIn));
1119
1120
if (parenthesize)
1121
_.js += ')';
1122
},
1123
1124
AssignmentPattern: function generateAssignmentPattern ($node) {
1125
var $fakeAssign = {
1126
left: $node.left,
1127
right: $node.right,
1128
operator: '='
1129
};
1130
1131
ExprGen.AssignmentExpression($fakeAssign, Preset.e4);
1132
},
1133
1134
ArrowFunctionExpression: function generateArrowFunctionExpression ($expr, settings) {
1135
var parenthesize = Precedence.ArrowFunction < settings.precedence;
1136
1137
if (parenthesize)
1138
_.js += '(';
1139
1140
if ($expr.async)
1141
_.js += 'async ';
1142
1143
generateFunctionBody($expr);
1144
1145
if (parenthesize)
1146
_.js += ')';
1147
},
1148
1149
AwaitExpression: function generateAwaitExpression ($expr, settings) {
1150
var parenthesize = Precedence.Await < settings.precedence;
1151
1152
if (parenthesize)
1153
_.js += '(';
1154
1155
_.js += $expr.all ? 'await* ' : 'await ';
1156
1157
ExprGen[$expr.argument.type]($expr.argument, Preset.e20);
1158
1159
if (parenthesize)
1160
_.js += ')';
1161
},
1162
1163
ConditionalExpression: function generateConditionalExpression ($expr, settings) {
1164
var $test = $expr.test,
1165
$conseq = $expr.consequent,
1166
$alt = $expr.alternate,
1167
parenthesize = Precedence.Conditional < settings.precedence,
1168
allowIn = settings.allowIn || parenthesize,
1169
testGenSettings = Preset.e2(allowIn),
1170
branchGenSettings = Preset.e1(allowIn);
1171
1172
if (parenthesize)
1173
_.js += '(';
1174
1175
ExprGen[$test.type]($test, testGenSettings);
1176
_.js += _.optSpace + '?' + _.optSpace;
1177
ExprGen[$conseq.type]($conseq, branchGenSettings);
1178
_.js += _.optSpace + ':' + _.optSpace;
1179
ExprGen[$alt.type]($alt, branchGenSettings);
1180
1181
if (parenthesize)
1182
_.js += ')';
1183
},
1184
1185
LogicalExpression: generateLogicalOrBinaryExpression,
1186
1187
BinaryExpression: generateLogicalOrBinaryExpression,
1188
1189
CallExpression: function generateCallExpression ($expr, settings) {
1190
var $callee = $expr.callee,
1191
$args = $expr['arguments'],
1192
argCount = $args.length,
1193
lastArgIdx = argCount - 1,
1194
parenthesize = !settings.allowCall || Precedence.Call < settings.precedence;
1195
1196
if (parenthesize)
1197
_.js += '(';
1198
1199
ExprGen[$callee.type]($callee, Preset.e3);
1200
1201
if ($expr.optional)
1202
_.js += '?.';
1203
1204
_.js += '(';
1205
1206
for (var i = 0; i < argCount; ++i) {
1207
var $arg = $args[i];
1208
1209
ExprGen[$arg.type]($arg, Preset.e4);
1210
1211
if (i !== lastArgIdx)
1212
_.js += ',' + _.optSpace;
1213
}
1214
1215
_.js += ')';
1216
1217
if (parenthesize)
1218
_.js += ')';
1219
},
1220
1221
NewExpression: function generateNewExpression ($expr, settings) {
1222
var $args = $expr['arguments'],
1223
parenthesize = Precedence.New < settings.precedence,
1224
argCount = $args.length,
1225
lastArgIdx = argCount - 1,
1226
withCall = !settings.allowUnparenthesizedNew || parentheses || argCount > 0,
1227
calleeJs = exprToJs($expr.callee, Preset.e6(!withCall));
1228
1229
if (parenthesize)
1230
_.js += '(';
1231
1232
_.js += join('new', calleeJs);
1233
1234
if (withCall) {
1235
_.js += '(';
1236
1237
for (var i = 0; i < argCount; ++i) {
1238
var $arg = $args[i];
1239
1240
ExprGen[$arg.type]($arg, Preset.e4);
1241
1242
if (i !== lastArgIdx)
1243
_.js += ',' + _.optSpace;
1244
}
1245
1246
_.js += ')';
1247
}
1248
1249
if (parenthesize)
1250
_.js += ')';
1251
},
1252
1253
MemberExpression: function generateMemberExpression ($expr, settings) {
1254
var $obj = $expr.object,
1255
$prop = $expr.property,
1256
parenthesize = Precedence.Member < settings.precedence,
1257
isNumObj = !$expr.computed && $obj.type === Syntax.Literal && typeof $obj.value === 'number';
1258
1259
if (parenthesize)
1260
_.js += '(';
1261
1262
if (isNumObj) {
1263
1264
//NOTE: When the following conditions are all true:
1265
// 1. No floating point
1266
// 2. Don't have exponents
1267
// 3. The last character is a decimal digit
1268
// 4. Not hexadecimal OR octal number literal
1269
// then we should add a floating point.
1270
1271
var numJs = exprToJs($obj, Preset.e11(settings.allowCall)),
1272
withPoint = LAST_DECIMAL_DIGIT_REGEXP.test(numJs) && !FLOATING_OR_OCTAL_REGEXP.test(numJs);
1273
1274
_.js += withPoint ? (numJs + '.') : numJs;
1275
}
1276
1277
else
1278
ExprGen[$obj.type]($obj, Preset.e11(settings.allowCall));
1279
1280
if ($expr.computed) {
1281
if ($expr.optional)
1282
_.js += '?.';
1283
1284
_.js += '[';
1285
ExprGen[$prop.type]($prop, Preset.e15(settings.allowCall));
1286
_.js += ']';
1287
}
1288
1289
else
1290
_.js += ($expr.optional ? '?.' : '.') + $prop.name;
1291
1292
if (parenthesize)
1293
_.js += ')';
1294
},
1295
1296
UnaryExpression: function generateUnaryExpression ($expr, settings) {
1297
var parenthesize = Precedence.Unary < settings.precedence,
1298
op = $expr.operator,
1299
argJs = exprToJs($expr.argument, Preset.e7);
1300
1301
if (parenthesize)
1302
_.js += '(';
1303
1304
//NOTE: delete, void, typeof
1305
// get `typeof []`, not `typeof[]`
1306
if (_.optSpace === '' || op.length > 2)
1307
_.js += join(op, argJs);
1308
1309
else {
1310
_.js += op;
1311
1312
//NOTE: Prevent inserting spaces between operator and argument if it is unnecessary
1313
// like, `!cond`
1314
var leftCp = op.charCodeAt(op.length - 1),
1315
rightCp = argJs.charCodeAt(0);
1316
1317
// 0x2B = '+', 0x2D = '-'
1318
if (leftCp === rightCp && (leftCp === 0x2B || leftCp === 0x2D) ||
1319
isIdentifierCh(leftCp) && isIdentifierCh(rightCp)) {
1320
_.js += _.space;
1321
}
1322
1323
_.js += argJs;
1324
}
1325
1326
if (parenthesize)
1327
_.js += ')';
1328
},
1329
1330
YieldExpression: function generateYieldExpression ($expr, settings) {
1331
var $arg = $expr.argument,
1332
js = $expr.delegate ? 'yield*' : 'yield',
1333
parenthesize = Precedence.Yield < settings.precedence;
1334
1335
if (parenthesize)
1336
_.js += '(';
1337
1338
if ($arg) {
1339
var argJs = exprToJs($arg, Preset.e4);
1340
1341
js = join(js, argJs);
1342
}
1343
1344
_.js += js;
1345
1346
if (parenthesize)
1347
_.js += ')';
1348
},
1349
1350
UpdateExpression: function generateUpdateExpression ($expr, settings) {
1351
var $arg = $expr.argument,
1352
$op = $expr.operator,
1353
prefix = $expr.prefix,
1354
precedence = prefix ? Precedence.Unary : Precedence.Postfix,
1355
parenthesize = precedence < settings.precedence;
1356
1357
if (parenthesize)
1358
_.js += '(';
1359
1360
if (prefix) {
1361
_.js += $op;
1362
ExprGen[$arg.type]($arg, Preset.e8);
1363
1364
}
1365
1366
else {
1367
ExprGen[$arg.type]($arg, Preset.e8);
1368
_.js += $op;
1369
}
1370
1371
if (parenthesize)
1372
_.js += ')';
1373
},
1374
1375
FunctionExpression: function generateFunctionExpression ($expr) {
1376
var isGenerator = !!$expr.generator;
1377
1378
if ($expr.async)
1379
_.js += 'async ';
1380
1381
_.js += isGenerator ? 'function*' : 'function';
1382
1383
if ($expr.id) {
1384
_.js += isGenerator ? _.optSpace : _.space;
1385
_.js += $expr.id.name;
1386
}
1387
else
1388
_.js += _.optSpace;
1389
1390
generateFunctionBody($expr);
1391
},
1392
1393
ExportBatchSpecifier: function generateExportBatchSpecifier () {
1394
_.js += '*';
1395
},
1396
1397
ArrayPattern: generateArrayPatternOrExpression,
1398
1399
ArrayExpression: generateArrayPatternOrExpression,
1400
1401
ClassExpression: function generateClassExpression ($expr) {
1402
var $id = $expr.id,
1403
$super = $expr.superClass,
1404
$body = $expr.body,
1405
exprJs = 'class';
1406
1407
if ($id) {
1408
var idJs = exprToJs($id, Preset.e9);
1409
1410
exprJs = join(exprJs, idJs);
1411
}
1412
1413
if ($super) {
1414
var superJs = exprToJs($super, Preset.e4);
1415
1416
superJs = join('extends', superJs);
1417
exprJs = join(exprJs, superJs);
1418
}
1419
1420
_.js += exprJs + _.optSpace;
1421
StmtGen[$body.type]($body, Preset.s2);
1422
},
1423
1424
MetaProperty: function generateMetaProperty ($expr, settings) {
1425
var $meta = $expr.meta,
1426
$property = $expr.property,
1427
parenthesize = Precedence.Member < settings.precedence;
1428
1429
if (parenthesize)
1430
_.js += '(';
1431
1432
_.js += (typeof $meta === "string" ? $meta : $meta.name) +
1433
'.' + (typeof $property === "string" ? $property : $property.name);
1434
1435
if (parenthesize)
1436
_.js += ')';
1437
},
1438
1439
MethodDefinition: function generateMethodDefinition ($expr) {
1440
var exprJs = $expr['static'] ? 'static' + _.optSpace : '',
1441
keyJs = exprToJs($expr.key, Preset.e5);
1442
1443
if ($expr.computed)
1444
keyJs = '[' + keyJs + ']';
1445
1446
if ($expr.kind === 'get' || $expr.kind === 'set') {
1447
keyJs = join($expr.kind, keyJs);
1448
_.js += join(exprJs, keyJs);
1449
}
1450
1451
else {
1452
if ($expr.value.generator)
1453
_.js += exprJs + '*' + keyJs;
1454
else if ($expr.value.async)
1455
_.js += exprJs + 'async ' + keyJs;
1456
else
1457
_.js += join(exprJs, keyJs);
1458
}
1459
1460
generateFunctionBody($expr.value);
1461
},
1462
1463
Property: function generateProperty ($expr) {
1464
var $val = $expr.value,
1465
$kind = $expr.kind,
1466
keyJs = exprToJs($expr.key, Preset.e4);
1467
1468
if ($expr.computed)
1469
keyJs = '[' + keyJs + ']';
1470
1471
if ($kind === 'get' || $kind === 'set') {
1472
_.js += $kind + _.space + keyJs;
1473
generateFunctionBody($val);
1474
}
1475
1476
else {
1477
if ($expr.shorthand)
1478
_.js += keyJs;
1479
1480
else if ($expr.method) {
1481
if ($val.generator)
1482
keyJs = '*' + keyJs;
1483
else if ($val.async)
1484
keyJs = 'async ' + keyJs;
1485
1486
_.js += keyJs;
1487
generateFunctionBody($val)
1488
}
1489
1490
else {
1491
_.js += keyJs + ':' + _.optSpace;
1492
ExprGen[$val.type]($val, Preset.e4);
1493
}
1494
}
1495
},
1496
1497
ObjectExpression: function generateObjectExpression ($expr) {
1498
var $props = $expr.properties,
1499
propCount = $props.length;
1500
1501
if (propCount) {
1502
var lastPropIdx = propCount - 1,
1503
prevIndent = shiftIndent();
1504
1505
_.js += '{';
1506
1507
for (var i = 0; i < propCount; i++) {
1508
var $prop = $props[i],
1509
propType = $prop.type || Syntax.Property;
1510
1511
_.js += _.newline + _.indent;
1512
ExprGen[propType]($prop, Preset.e5);
1513
1514
if (i !== lastPropIdx)
1515
_.js += ',';
1516
}
1517
1518
_.indent = prevIndent;
1519
_.js += _.newline + _.indent + '}';
1520
}
1521
1522
else
1523
_.js += '{}';
1524
},
1525
1526
ObjectPattern: function generateObjectPattern ($expr) {
1527
var $props = $expr.properties,
1528
propCount = $props.length;
1529
1530
if (propCount) {
1531
var lastPropIdx = propCount - 1,
1532
multiline = false;
1533
1534
if (propCount === 1 && $props[0].value)
1535
multiline = $props[0].value.type !== Syntax.Identifier;
1536
1537
else {
1538
for (var i = 0; i < propCount; i++) {
1539
if (!$props[i].shorthand) {
1540
multiline = true;
1541
break;
1542
}
1543
}
1544
}
1545
1546
_.js += multiline ? ('{' + _.newline) : '{';
1547
1548
var prevIndent = shiftIndent(),
1549
propSuffix = ',' + (multiline ? _.newline : _.optSpace);
1550
1551
for (var i = 0; i < propCount; i++) {
1552
var $prop = $props[i];
1553
1554
if (multiline)
1555
_.js += _.indent;
1556
1557
ExprGen[$prop.type]($prop, Preset.e5);
1558
1559
if (i !== lastPropIdx)
1560
_.js += propSuffix;
1561
}
1562
1563
_.indent = prevIndent;
1564
_.js += multiline ? (_.newline + _.indent + '}') : '}';
1565
}
1566
else
1567
_.js += '{}';
1568
},
1569
1570
ThisExpression: function generateThisExpression () {
1571
_.js += 'this';
1572
},
1573
1574
Identifier: function generateIdentifier ($expr, precedence, flag) {
1575
_.js += $expr.name;
1576
},
1577
1578
ImportExpression: function generateImportExpression ($expr, settings) {
1579
var parenthesize = Precedence.Call < settings.precedence;
1580
var $source = $expr.source;
1581
1582
if (parenthesize)
1583
_.js += '(';
1584
1585
_.js += 'import(';
1586
1587
ExprGen[$source.type]($source, Preset.e4);
1588
1589
_.js += ')';
1590
1591
if (parenthesize)
1592
_.js += ')';
1593
},
1594
1595
ImportSpecifier: function generateImportSpecifier ($expr) {
1596
_.js += $expr.imported.name;
1597
1598
if ($expr.local)
1599
_.js += _.space + 'as' + _.space + $expr.local.name;
1600
},
1601
1602
ExportSpecifier: function generateImportOrExportSpecifier ($expr) {
1603
_.js += $expr.local.name;
1604
1605
if ($expr.exported)
1606
_.js += _.space + 'as' + _.space + $expr.exported.name;
1607
},
1608
1609
ChainExpression: function generateChainExpression ($expr, settings) {
1610
var parenthesize = Precedence.OptionalChaining < settings.precedence;
1611
var $expression = $expr.expression;
1612
1613
settings = settings || {};
1614
1615
var newSettings = {
1616
precedence: Precedence.OptionalChaining,
1617
allowIn: settings.allowIn ,
1618
allowCall: settings.allowCall,
1619
1620
allowUnparenthesizedNew: settings.allowUnparenthesizedNew
1621
}
1622
1623
if (parenthesize) {
1624
newSettings.allowCall = true;
1625
_.js += '(';
1626
}
1627
1628
ExprGen[$expression.type]($expression, newSettings);
1629
1630
if (parenthesize)
1631
_.js += ')';
1632
},
1633
1634
Literal: function generateLiteral ($expr) {
1635
if (extra.raw && $expr.raw !== void 0)
1636
_.js += $expr.raw;
1637
1638
else if ($expr.value === null)
1639
_.js += 'null';
1640
1641
else {
1642
var valueType = typeof $expr.value;
1643
1644
if (valueType === 'string')
1645
_.js += escapeString($expr.value);
1646
1647
else if (valueType === 'number')
1648
_.js += generateNumber($expr.value);
1649
1650
else if (valueType === 'boolean')
1651
_.js += $expr.value ? 'true' : 'false';
1652
1653
else
1654
_.js += generateRegExp($expr.value);
1655
}
1656
},
1657
1658
GeneratorExpression: generateGeneratorOrComprehensionExpression,
1659
1660
ComprehensionExpression: generateGeneratorOrComprehensionExpression,
1661
1662
ComprehensionBlock: function generateComprehensionBlock ($expr) {
1663
var $left = $expr.left,
1664
leftJs = void 0,
1665
rightJs = exprToJs($expr.right, Preset.e5);
1666
1667
if ($left.type === Syntax.VariableDeclaration)
1668
leftJs = $left.kind + _.space + stmtToJs($left.declarations[0], Preset.s6);
1669
1670
else
1671
leftJs = exprToJs($left, Preset.e10);
1672
1673
leftJs = join(leftJs, $expr.of ? 'of' : 'in');
1674
1675
_.js += 'for' + _.optSpace + '(' + join(leftJs, rightJs) + ')';
1676
},
1677
1678
RestElement: function generateRestElement ($node) {
1679
_.js += '...' + $node.argument.name;
1680
},
1681
1682
SpreadElement: function generateSpreadElement ($expr) {
1683
var $arg = $expr.argument;
1684
1685
_.js += '...';
1686
ExprGen[$arg.type]($arg, Preset.e4);
1687
},
1688
1689
TaggedTemplateExpression: function generateTaggedTemplateExpression ($expr, settings) {
1690
var $tag = $expr.tag,
1691
$quasi = $expr.quasi,
1692
parenthesize = Precedence.TaggedTemplate < settings.precedence;
1693
1694
if (parenthesize)
1695
_.js += '(';
1696
1697
ExprGen[$tag.type]($tag, Preset.e11(settings.allowCall));
1698
ExprGen[$quasi.type]($quasi, Preset.e12);
1699
1700
if (parenthesize)
1701
_.js += ')';
1702
},
1703
1704
TemplateElement: function generateTemplateElement ($expr) {
1705
//NOTE: Don't use "cooked". Since tagged template can use raw template
1706
// representation. So if we do so, it breaks the script semantics.
1707
_.js += $expr.value.raw;
1708
},
1709
1710
TemplateLiteral: function generateTemplateLiteral ($expr) {
1711
var $quasis = $expr.quasis,
1712
$childExprs = $expr.expressions,
1713
quasiCount = $quasis.length,
1714
lastQuasiIdx = quasiCount - 1;
1715
1716
_.js += '`';
1717
1718
for (var i = 0; i < quasiCount; ++i) {
1719
var $quasi = $quasis[i];
1720
1721
ExprGen[$quasi.type]($quasi, Preset.e13);
1722
1723
if (i !== lastQuasiIdx) {
1724
var $childExpr = $childExprs[i];
1725
1726
_.js += '${' + _.optSpace;
1727
ExprGen[$childExpr.type]($childExpr, Preset.e5);
1728
_.js += _.optSpace + '}';
1729
}
1730
}
1731
1732
_.js += '`';
1733
},
1734
1735
Super: function generateSuper () {
1736
_.js += 'super';
1737
}
1738
};
1739
1740
1741
//-------------------------------------------------===------------------------------------------------------
1742
// Statements
1743
//-------------------------------------------------===------------------------------------------------------
1744
1745
1746
//Regular expressions
1747
var EXPR_STMT_UNALLOWED_EXPR_REGEXP = /^{|^class(?:\s|{)|^(async )?function(?:\s|\*|\()/;
1748
1749
1750
//Common statement generators
1751
function generateTryStatementHandlers (stmtJs, $finalizer, handlers) {
1752
var handlerCount = handlers.length,
1753
lastHandlerIdx = handlerCount - 1;
1754
1755
for (var i = 0; i < handlerCount; ++i) {
1756
var handlerJs = stmtToJs(handlers[i], Preset.s7);
1757
1758
stmtJs = join(stmtJs, handlerJs);
1759
1760
if ($finalizer || i !== lastHandlerIdx)
1761
stmtJs += adoptionSuffix(handlers[i].body);
1762
}
1763
1764
return stmtJs;
1765
}
1766
1767
function generateForStatementIterator ($op, $stmt, settings) {
1768
var $body = $stmt.body,
1769
$left = $stmt.left,
1770
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
1771
prevIndent1 = shiftIndent(),
1772
awaitStr = $stmt.await ? ' await' : '',
1773
stmtJs = 'for' + awaitStr + _.optSpace + '(';
1774
1775
if ($left.type === Syntax.VariableDeclaration) {
1776
var prevIndent2 = shiftIndent();
1777
1778
stmtJs += $left.kind + _.space + stmtToJs($left.declarations[0], Preset.s6);
1779
_.indent = prevIndent2;
1780
}
1781
1782
else
1783
stmtJs += exprToJs($left, Preset.e10);
1784
1785
stmtJs = join(stmtJs, $op);
1786
1787
var rightJs = exprToJs($stmt.right, Preset.e4);
1788
1789
stmtJs = join(stmtJs, rightJs) + ')';
1790
1791
_.indent = prevIndent1;
1792
1793
_.js += stmtJs + adoptionPrefix($body);
1794
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
1795
}
1796
1797
1798
//Statement generator dictionary
1799
var StmtRawGen = {
1800
BlockStatement: function generateBlockStatement ($stmt, settings) {
1801
var $body = $stmt.body,
1802
len = $body.length,
1803
lastIdx = len - 1,
1804
prevIndent = shiftIndent();
1805
1806
_.js += '{' + _.newline;
1807
1808
for (var i = 0; i < len; i++) {
1809
var $item = $body[i];
1810
1811
_.js += _.indent;
1812
StmtGen[$item.type]($item, Preset.s1(settings.functionBody, i === lastIdx));
1813
_.js += _.newline;
1814
}
1815
1816
_.indent = prevIndent;
1817
_.js += _.indent + '}';
1818
},
1819
1820
BreakStatement: function generateBreakStatement ($stmt, settings) {
1821
if ($stmt.label)
1822
_.js += 'break ' + $stmt.label.name;
1823
1824
else
1825
_.js += 'break';
1826
1827
if (semicolons || !settings.semicolonOptional)
1828
_.js += ';';
1829
},
1830
1831
ContinueStatement: function generateContinueStatement ($stmt, settings) {
1832
if ($stmt.label)
1833
_.js += 'continue ' + $stmt.label.name;
1834
1835
else
1836
_.js += 'continue';
1837
1838
if (semicolons || !settings.semicolonOptional)
1839
_.js += ';';
1840
},
1841
1842
ClassBody: function generateClassBody ($stmt) {
1843
var $body = $stmt.body,
1844
itemCount = $body.length,
1845
lastItemIdx = itemCount - 1,
1846
prevIndent = shiftIndent();
1847
1848
_.js += '{' + _.newline;
1849
1850
for (var i = 0; i < itemCount; i++) {
1851
var $item = $body[i],
1852
itemType = $item.type || Syntax.Property;
1853
1854
_.js += _.indent;
1855
ExprGen[itemType]($item, Preset.e5);
1856
1857
if (i !== lastItemIdx)
1858
_.js += _.newline;
1859
}
1860
1861
_.indent = prevIndent;
1862
_.js += _.newline + _.indent + '}';
1863
},
1864
1865
ClassDeclaration: function generateClassDeclaration ($stmt) {
1866
var $body = $stmt.body,
1867
$super = $stmt.superClass,
1868
js = 'class ' + $stmt.id.name;
1869
1870
if ($super) {
1871
var superJs = exprToJs($super, Preset.e4);
1872
1873
js += _.space + join('extends', superJs);
1874
}
1875
1876
_.js += js + _.optSpace;
1877
StmtGen[$body.type]($body, Preset.s2);
1878
},
1879
1880
DirectiveStatement: function generateDirectiveStatement ($stmt, settings) {
1881
if (extra.raw && $stmt.raw)
1882
_.js += $stmt.raw;
1883
1884
else
1885
_.js += escapeDirective($stmt.directive);
1886
1887
if (semicolons || !settings.semicolonOptional)
1888
_.js += ';';
1889
},
1890
1891
DoWhileStatement: function generateDoWhileStatement ($stmt, settings) {
1892
var $body = $stmt.body,
1893
$test = $stmt.test,
1894
bodyJs = adoptionPrefix($body) +
1895
stmtToJs($body, Preset.s7) +
1896
adoptionSuffix($body);
1897
1898
//NOTE: Because `do 42 while (cond)` is Syntax Error. We need semicolon.
1899
var stmtJs = join('do', bodyJs);
1900
1901
_.js += join(stmtJs, 'while' + _.optSpace + '(');
1902
ExprGen[$test.type]($test, Preset.e5);
1903
_.js += ')';
1904
1905
if (semicolons || !settings.semicolonOptional)
1906
_.js += ';';
1907
},
1908
1909
CatchClause: function generateCatchClause ($stmt) {
1910
var $param = $stmt.param,
1911
$guard = $stmt.guard,
1912
$body = $stmt.body,
1913
prevIndent = shiftIndent();
1914
1915
_.js += 'catch' + _.optSpace;
1916
1917
if ($param) {
1918
_.js += '(';
1919
ExprGen[$param.type]($param, Preset.e5);
1920
}
1921
1922
if ($guard) {
1923
_.js += ' if ';
1924
ExprGen[$guard.type]($guard, Preset.e5);
1925
}
1926
1927
_.indent = prevIndent;
1928
if ($param) {
1929
_.js += ')';
1930
}
1931
1932
_.js += adoptionPrefix($body);
1933
StmtGen[$body.type]($body, Preset.s7);
1934
},
1935
1936
DebuggerStatement: function generateDebuggerStatement ($stmt, settings) {
1937
_.js += 'debugger';
1938
1939
if (semicolons || !settings.semicolonOptional)
1940
_.js += ';';
1941
},
1942
1943
EmptyStatement: function generateEmptyStatement () {
1944
_.js += ';';
1945
},
1946
1947
ExportAllDeclaration: function ($stmt, settings) {
1948
StmtRawGen.ExportDeclaration($stmt, settings, true);
1949
},
1950
1951
ExportDeclaration: function generateExportDeclaration ($stmt, settings, exportAll) {
1952
var $specs = $stmt.specifiers,
1953
$decl = $stmt.declaration,
1954
withSemicolon = semicolons || !settings.semicolonOptional;
1955
1956
// export default AssignmentExpression[In] ;
1957
if ($stmt['default']) {
1958
var declJs = exprToJs($decl, Preset.e4);
1959
1960
_.js += join('export default', declJs);
1961
1962
if (withSemicolon)
1963
_.js += ';';
1964
}
1965
1966
// export * FromClause ;
1967
// export ExportClause[NoReference] FromClause ;
1968
// export ExportClause ;
1969
else if ($specs || exportAll) {
1970
var stmtJs = 'export';
1971
1972
if (exportAll)
1973
stmtJs += _.optSpace + '*';
1974
1975
else if ($specs.length === 0)
1976
stmtJs += _.optSpace + '{' + _.optSpace + '}';
1977
1978
else if ($specs[0].type === Syntax.ExportBatchSpecifier) {
1979
var specJs = exprToJs($specs[0], Preset.e5);
1980
1981
stmtJs = join(stmtJs, specJs);
1982
}
1983
1984
else {
1985
var prevIndent = shiftIndent(),
1986
specCount = $specs.length,
1987
lastSpecIdx = specCount - 1;
1988
1989
stmtJs += _.optSpace + '{';
1990
1991
for (var i = 0; i < specCount; ++i) {
1992
stmtJs += _.newline + _.indent;
1993
stmtJs += exprToJs($specs[i], Preset.e5);
1994
1995
if (i !== lastSpecIdx)
1996
stmtJs += ',';
1997
}
1998
1999
_.indent = prevIndent;
2000
stmtJs += _.newline + _.indent + '}';
2001
}
2002
2003
if ($stmt.source) {
2004
_.js += join(stmtJs, 'from' + _.optSpace);
2005
ExprGen.Literal($stmt.source);
2006
}
2007
2008
else
2009
_.js += stmtJs;
2010
2011
if (withSemicolon)
2012
_.js += ';';
2013
}
2014
2015
// export VariableStatement
2016
// export Declaration[Default]
2017
else if ($decl) {
2018
var declJs = stmtToJs($decl, Preset.s4(!withSemicolon));
2019
2020
_.js += join('export', declJs);
2021
}
2022
},
2023
2024
ExportNamedDeclaration: function ($stmt, settings) {
2025
StmtRawGen.ExportDeclaration($stmt, settings);
2026
},
2027
2028
ExpressionStatement: function generateExpressionStatement ($stmt, settings) {
2029
var exprJs = exprToJs($stmt.expression, Preset.e5),
2030
parenthesize = EXPR_STMT_UNALLOWED_EXPR_REGEXP.test(exprJs) ||
2031
(directive &&
2032
settings.directiveContext &&
2033
$stmt.expression.type === Syntax.Literal &&
2034
typeof $stmt.expression.value === 'string');
2035
2036
//NOTE: '{', 'function', 'class' are not allowed in expression statement.
2037
// Therefore, they should be parenthesized.
2038
if (parenthesize)
2039
_.js += '(' + exprJs + ')';
2040
2041
else
2042
_.js += exprJs;
2043
2044
if (semicolons || !settings.semicolonOptional)
2045
_.js += ';';
2046
},
2047
2048
ImportDeclaration: function generateImportDeclaration ($stmt, settings) {
2049
var $specs = $stmt.specifiers,
2050
stmtJs = 'import',
2051
specCount = $specs.length;
2052
2053
//NOTE: If no ImportClause is present,
2054
// this should be `import ModuleSpecifier` so skip `from`
2055
// ModuleSpecifier is StringLiteral.
2056
if (specCount) {
2057
var hasBinding = !!$specs[0]['default'],
2058
firstNamedIdx = hasBinding ? 1 : 0,
2059
lastSpecIdx = specCount - 1;
2060
2061
// ImportedBinding
2062
if (hasBinding)
2063
stmtJs = join(stmtJs, $specs[0].id.name);
2064
2065
// NamedImports
2066
if (firstNamedIdx < specCount) {
2067
if (hasBinding)
2068
stmtJs += ',';
2069
2070
stmtJs += _.optSpace + '{';
2071
2072
// import { ... } from "...";
2073
if (firstNamedIdx === lastSpecIdx)
2074
stmtJs += _.optSpace + exprToJs($specs[firstNamedIdx], Preset.e5) + _.optSpace;
2075
2076
else {
2077
var prevIndent = shiftIndent();
2078
2079
// import {
2080
// ...,
2081
// ...,
2082
// } from "...";
2083
for (var i = firstNamedIdx; i < specCount; i++) {
2084
stmtJs += _.newline + _.indent + exprToJs($specs[i], Preset.e5);
2085
2086
if (i !== lastSpecIdx)
2087
stmtJs += ',';
2088
}
2089
2090
_.indent = prevIndent;
2091
stmtJs += _.newline + _.indent;
2092
}
2093
2094
stmtJs += '}' + _.optSpace;
2095
}
2096
2097
stmtJs = join(stmtJs, 'from')
2098
}
2099
2100
_.js += stmtJs + _.optSpace;
2101
ExprGen.Literal($stmt.source);
2102
2103
if (semicolons || !settings.semicolonOptional)
2104
_.js += ';';
2105
},
2106
2107
VariableDeclarator: function generateVariableDeclarator ($stmt, settings) {
2108
var $id = $stmt.id,
2109
$init = $stmt.init,
2110
genSettings = Preset.e1(settings.allowIn);
2111
2112
if ($init) {
2113
ExprGen[$id.type]($id, genSettings);
2114
_.js += _.optSpace + '=' + _.optSpace;
2115
ExprGen[$init.type]($init, genSettings);
2116
}
2117
2118
else {
2119
if ($id.type === Syntax.Identifier)
2120
_.js += $id.name;
2121
2122
else
2123
ExprGen[$id.type]($id, genSettings);
2124
}
2125
},
2126
2127
VariableDeclaration: function generateVariableDeclaration ($stmt, settings) {
2128
var $decls = $stmt.declarations,
2129
len = $decls.length,
2130
prevIndent = len > 1 ? shiftIndent() : _.indent,
2131
declGenSettings = Preset.s3(settings.allowIn);
2132
2133
_.js += $stmt.kind;
2134
2135
for (var i = 0; i < len; i++) {
2136
var $decl = $decls[i];
2137
2138
_.js += i === 0 ? _.space : (',' + _.optSpace);
2139
StmtGen[$decl.type]($decl, declGenSettings);
2140
}
2141
2142
if (semicolons || !settings.semicolonOptional)
2143
_.js += ';';
2144
2145
_.indent = prevIndent;
2146
},
2147
2148
ThrowStatement: function generateThrowStatement ($stmt, settings) {
2149
var argJs = exprToJs($stmt.argument, Preset.e5);
2150
2151
_.js += join('throw', argJs);
2152
2153
if (semicolons || !settings.semicolonOptional)
2154
_.js += ';';
2155
},
2156
2157
TryStatement: function generateTryStatement ($stmt) {
2158
var $block = $stmt.block,
2159
$finalizer = $stmt.finalizer,
2160
stmtJs = 'try' +
2161
adoptionPrefix($block) +
2162
stmtToJs($block, Preset.s7) +
2163
adoptionSuffix($block);
2164
2165
var $handlers = $stmt.handlers || $stmt.guardedHandlers;
2166
2167
if ($handlers)
2168
stmtJs = generateTryStatementHandlers(stmtJs, $finalizer, $handlers);
2169
2170
if ($stmt.handler) {
2171
$handlers = isArray($stmt.handler) ? $stmt.handler : [$stmt.handler];
2172
stmtJs = generateTryStatementHandlers(stmtJs, $finalizer, $handlers);
2173
}
2174
2175
if ($finalizer) {
2176
stmtJs = join(stmtJs, 'finally' + adoptionPrefix($finalizer));
2177
stmtJs += stmtToJs($finalizer, Preset.s7);
2178
}
2179
2180
_.js += stmtJs;
2181
},
2182
2183
SwitchStatement: function generateSwitchStatement ($stmt) {
2184
var $cases = $stmt.cases,
2185
$discr = $stmt.discriminant,
2186
prevIndent = shiftIndent();
2187
2188
_.js += 'switch' + _.optSpace + '(';
2189
ExprGen[$discr.type]($discr, Preset.e5);
2190
_.js += ')' + _.optSpace + '{' + _.newline;
2191
_.indent = prevIndent;
2192
2193
if ($cases) {
2194
var caseCount = $cases.length,
2195
lastCaseIdx = caseCount - 1;
2196
2197
for (var i = 0; i < caseCount; i++) {
2198
var $case = $cases[i];
2199
2200
_.js += _.indent;
2201
StmtGen[$case.type]($case, Preset.s4(i === lastCaseIdx));
2202
_.js += _.newline;
2203
}
2204
}
2205
2206
_.js += _.indent + '}';
2207
},
2208
2209
SwitchCase: function generateSwitchCase ($stmt, settings) {
2210
var $conseqs = $stmt.consequent,
2211
$firstConseq = $conseqs[0],
2212
$test = $stmt.test,
2213
i = 0,
2214
conseqSemicolonOptional = !semicolons && settings.semicolonOptional,
2215
conseqCount = $conseqs.length,
2216
lastConseqIdx = conseqCount - 1,
2217
prevIndent = shiftIndent();
2218
2219
if ($test) {
2220
var testJs = exprToJs($test, Preset.e5);
2221
2222
_.js += join('case', testJs) + ':';
2223
}
2224
2225
else
2226
_.js += 'default:';
2227
2228
2229
if (conseqCount && $firstConseq.type === Syntax.BlockStatement) {
2230
i++;
2231
_.js += adoptionPrefix($firstConseq);
2232
StmtGen[$firstConseq.type]($firstConseq, Preset.s7);
2233
}
2234
2235
for (; i < conseqCount; i++) {
2236
var $conseq = $conseqs[i],
2237
semicolonOptional = i === lastConseqIdx && conseqSemicolonOptional;
2238
2239
_.js += _.newline + _.indent;
2240
StmtGen[$conseq.type]($conseq, Preset.s4(semicolonOptional));
2241
}
2242
2243
_.indent = prevIndent;
2244
},
2245
2246
IfStatement: function generateIfStatement ($stmt, settings) {
2247
var $conseq = $stmt.consequent,
2248
$test = $stmt.test,
2249
prevIndent = shiftIndent(),
2250
semicolonOptional = !semicolons && settings.semicolonOptional;
2251
2252
_.js += 'if' + _.optSpace + '(';
2253
ExprGen[$test.type]($test, Preset.e5);
2254
_.js += ')';
2255
_.indent = prevIndent;
2256
_.js += adoptionPrefix($conseq);
2257
2258
if ($stmt.alternate) {
2259
var conseq = stmtToJs($conseq, Preset.s7) + adoptionSuffix($conseq),
2260
alt = stmtToJs($stmt.alternate, Preset.s4(semicolonOptional));
2261
2262
if ($stmt.alternate.type === Syntax.IfStatement)
2263
alt = 'else ' + alt;
2264
2265
else
2266
alt = join('else', adoptionPrefix($stmt.alternate) + alt);
2267
2268
_.js += join(conseq, alt);
2269
}
2270
2271
else
2272
StmtGen[$conseq.type]($conseq, Preset.s4(semicolonOptional));
2273
},
2274
2275
ForStatement: function generateForStatement ($stmt, settings) {
2276
var $init = $stmt.init,
2277
$test = $stmt.test,
2278
$body = $stmt.body,
2279
$update = $stmt.update,
2280
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
2281
prevIndent = shiftIndent();
2282
2283
_.js += 'for' + _.optSpace + '(';
2284
2285
if ($init) {
2286
if ($init.type === Syntax.VariableDeclaration)
2287
StmtGen[$init.type]($init, Preset.s6);
2288
2289
else {
2290
ExprGen[$init.type]($init, Preset.e14);
2291
_.js += ';';
2292
}
2293
}
2294
2295
else
2296
_.js += ';';
2297
2298
if ($test) {
2299
_.js += _.optSpace;
2300
ExprGen[$test.type]($test, Preset.e5);
2301
}
2302
2303
_.js += ';';
2304
2305
if ($update) {
2306
_.js += _.optSpace;
2307
ExprGen[$update.type]($update, Preset.e5);
2308
}
2309
2310
_.js += ')';
2311
_.indent = prevIndent;
2312
_.js += adoptionPrefix($body);
2313
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
2314
},
2315
2316
ForInStatement: function generateForInStatement ($stmt, settings) {
2317
generateForStatementIterator('in', $stmt, settings);
2318
},
2319
2320
ForOfStatement: function generateForOfStatement ($stmt, settings) {
2321
generateForStatementIterator('of', $stmt, settings);
2322
},
2323
2324
LabeledStatement: function generateLabeledStatement ($stmt, settings) {
2325
var $body = $stmt.body,
2326
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
2327
prevIndent = _.indent;
2328
2329
_.js += $stmt.label.name + ':' + adoptionPrefix($body);
2330
2331
if ($body.type !== Syntax.BlockStatement)
2332
prevIndent = shiftIndent();
2333
2334
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
2335
_.indent = prevIndent;
2336
},
2337
2338
ModuleDeclaration: function generateModuleDeclaration ($stmt, settings) {
2339
_.js += 'module' + _.space + $stmt.id.name + _.space + 'from' + _.optSpace;
2340
2341
ExprGen.Literal($stmt.source);
2342
2343
if (semicolons || !settings.semicolonOptional)
2344
_.js += ';';
2345
},
2346
2347
Program: function generateProgram ($stmt) {
2348
var $body = $stmt.body,
2349
len = $body.length,
2350
lastIdx = len - 1;
2351
2352
if (safeConcatenation && len > 0)
2353
_.js += '\n';
2354
2355
for (var i = 0; i < len; i++) {
2356
var $item = $body[i];
2357
2358
_.js += _.indent;
2359
StmtGen[$item.type]($item, Preset.s5(!safeConcatenation && i === lastIdx));
2360
2361
if (i !== lastIdx)
2362
_.js += _.newline;
2363
}
2364
},
2365
2366
FunctionDeclaration: function generateFunctionDeclaration ($stmt) {
2367
var isGenerator = !!$stmt.generator;
2368
2369
if ($stmt.async)
2370
_.js += 'async ';
2371
2372
_.js += isGenerator ? ('function*' + _.optSpace) : ('function' + _.space );
2373
_.js += $stmt.id.name;
2374
generateFunctionBody($stmt);
2375
},
2376
2377
ReturnStatement: function generateReturnStatement ($stmt, settings) {
2378
var $arg = $stmt.argument;
2379
2380
if ($arg) {
2381
var argJs = exprToJs($arg, Preset.e5);
2382
2383
_.js += join('return', argJs);
2384
}
2385
2386
else
2387
_.js += 'return';
2388
2389
if (semicolons || !settings.semicolonOptional)
2390
_.js += ';';
2391
},
2392
2393
WhileStatement: function generateWhileStatement ($stmt, settings) {
2394
var $body = $stmt.body,
2395
$test = $stmt.test,
2396
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
2397
prevIndent = shiftIndent();
2398
2399
_.js += 'while' + _.optSpace + '(';
2400
ExprGen[$test.type]($test, Preset.e5);
2401
_.js += ')';
2402
_.indent = prevIndent;
2403
2404
_.js += adoptionPrefix($body);
2405
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
2406
},
2407
2408
WithStatement: function generateWithStatement ($stmt, settings) {
2409
var $body = $stmt.body,
2410
$obj = $stmt.object,
2411
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
2412
prevIndent = shiftIndent();
2413
2414
_.js += 'with' + _.optSpace + '(';
2415
ExprGen[$obj.type]($obj, Preset.e5);
2416
_.js += ')';
2417
_.indent = prevIndent;
2418
_.js += adoptionPrefix($body);
2419
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
2420
}
2421
};
2422
2423
function generateStatement ($stmt, option) {
2424
StmtGen[$stmt.type]($stmt, option);
2425
}
2426
2427
//CodeGen
2428
//-----------------------------------------------------------------------------------
2429
function exprToJs ($expr, settings) {
2430
var savedJs = _.js;
2431
_.js = '';
2432
2433
// ExprGen[$expr.type]($expr, settings);
2434
// Modified for Corrosion
2435
if (typeof ExprGen[$expr.type] == 'function') ExprGen[$expr.type]($expr, settings);
2436
2437
var src = _.js;
2438
_.js = savedJs;
2439
2440
return src;
2441
}
2442
2443
function stmtToJs ($stmt, settings) {
2444
var savedJs = _.js;
2445
_.js = '';
2446
2447
StmtGen[$stmt.type]($stmt, settings);
2448
2449
var src = _.js;
2450
_.js = savedJs;
2451
2452
return src;
2453
}
2454
2455
function run ($node) {
2456
_.js = '';
2457
2458
if (StmtGen[$node.type])
2459
StmtGen[$node.type]($node, Preset.s7);
2460
2461
else
2462
ExprGen[$node.type]($node, Preset.e19);
2463
2464
return _.js;
2465
}
2466
2467
function wrapExprGen (gen) {
2468
return function ($expr, settings) {
2469
if (extra.verbatim && $expr.hasOwnProperty(extra.verbatim))
2470
generateVerbatim($expr, settings);
2471
2472
else
2473
gen($expr, settings);
2474
}
2475
}
2476
2477
function createExprGenWithExtras () {
2478
var gens = {};
2479
2480
for (var key in ExprRawGen) {
2481
if (ExprRawGen.hasOwnProperty(key))
2482
gens[key] = wrapExprGen(ExprRawGen[key]);
2483
}
2484
2485
return gens;
2486
}
2487
2488
2489
//Strings
2490
var _ = {
2491
js: '',
2492
newline: '\n',
2493
optSpace: ' ',
2494
space: ' ',
2495
indentUnit: ' ',
2496
indent: ''
2497
};
2498
2499
2500
//Generators
2501
var ExprGen = void 0,
2502
StmtGen = StmtRawGen;
2503
2504
2505
exports.generate = function ($node, options) {
2506
var defaultOptions = getDefaultOptions(), result, pair;
2507
2508
if (options != null) {
2509
//NOTE: Obsolete options
2510
//
2511
// `options.indent`
2512
// `options.base`
2513
//
2514
// Instead of them, we can use `option.format.indent`.
2515
if (typeof options.indent === 'string') {
2516
defaultOptions.format.indent.style = options.indent;
2517
}
2518
if (typeof options.base === 'number') {
2519
defaultOptions.format.indent.base = options.base;
2520
}
2521
options = updateDeeply(defaultOptions, options);
2522
_.indentUnit = options.format.indent.style;
2523
if (typeof options.base === 'string') {
2524
_.indent = options.base;
2525
}
2526
else {
2527
_.indent = stringRepeat(_.indentUnit, options.format.indent.base);
2528
}
2529
}
2530
else {
2531
options = defaultOptions;
2532
_.indentUnit = options.format.indent.style;
2533
_.indent = stringRepeat(_.indentUnit, options.format.indent.base);
2534
}
2535
json = options.format.json;
2536
renumber = options.format.renumber;
2537
hexadecimal = json ? false : options.format.hexadecimal;
2538
quotes = json ? 'double' : options.format.quotes;
2539
escapeless = options.format.escapeless;
2540
2541
_.newline = options.format.newline;
2542
_.optSpace = options.format.space;
2543
2544
if (options.format.compact)
2545
_.newline = _.optSpace = _.indentUnit = _.indent = '';
2546
2547
_.space = _.optSpace ? _.optSpace : ' ';
2548
parentheses = options.format.parentheses;
2549
semicolons = options.format.semicolons;
2550
safeConcatenation = options.format.safeConcatenation;
2551
directive = options.directive;
2552
parse = json ? null : options.parse;
2553
extra = options;
2554
2555
if (extra.verbatim)
2556
ExprGen = createExprGenWithExtras();
2557
2558
else
2559
ExprGen = ExprRawGen;
2560
2561
return run($node);
2562
};
2563