'use strict';
var isArray,
json,
renumber,
hexadecimal,
quotes,
escapeless,
parentheses,
semicolons,
safeConcatenation,
directive,
extra,
parse;
var Syntax = {
AssignmentExpression: 'AssignmentExpression',
AssignmentPattern: 'AssignmentPattern',
ArrayExpression: 'ArrayExpression',
ArrayPattern: 'ArrayPattern',
ArrowFunctionExpression: 'ArrowFunctionExpression',
AwaitExpression: 'AwaitExpression',
BlockStatement: 'BlockStatement',
BinaryExpression: 'BinaryExpression',
BreakStatement: 'BreakStatement',
CallExpression: 'CallExpression',
CatchClause: 'CatchClause',
ClassBody: 'ClassBody',
ClassDeclaration: 'ClassDeclaration',
ClassExpression: 'ClassExpression',
ComprehensionBlock: 'ComprehensionBlock',
ComprehensionExpression: 'ComprehensionExpression',
ConditionalExpression: 'ConditionalExpression',
ContinueStatement: 'ContinueStatement',
DirectiveStatement: 'DirectiveStatement',
DoWhileStatement: 'DoWhileStatement',
DebuggerStatement: 'DebuggerStatement',
EmptyStatement: 'EmptyStatement',
ExportAllDeclaration: 'ExportAllDeclaration',
ExportBatchSpecifier: 'ExportBatchSpecifier',
ExportDeclaration: 'ExportDeclaration',
ExportNamedDeclaration: 'ExportNamedDeclaration',
ExportSpecifier: 'ExportSpecifier',
ExpressionStatement: 'ExpressionStatement',
ForStatement: 'ForStatement',
ForInStatement: 'ForInStatement',
ForOfStatement: 'ForOfStatement',
FunctionDeclaration: 'FunctionDeclaration',
FunctionExpression: 'FunctionExpression',
GeneratorExpression: 'GeneratorExpression',
Identifier: 'Identifier',
IfStatement: 'IfStatement',
ImportExpression: 'ImportExpression',
ImportSpecifier: 'ImportSpecifier',
ImportDeclaration: 'ImportDeclaration',
ChainExpression: 'ChainExpression',
Literal: 'Literal',
LabeledStatement: 'LabeledStatement',
LogicalExpression: 'LogicalExpression',
MemberExpression: 'MemberExpression',
MetaProperty: 'MetaProperty',
MethodDefinition: 'MethodDefinition',
ModuleDeclaration: 'ModuleDeclaration',
NewExpression: 'NewExpression',
ObjectExpression: 'ObjectExpression',
ObjectPattern: 'ObjectPattern',
Program: 'Program',
Property: 'Property',
RestElement: 'RestElement',
ReturnStatement: 'ReturnStatement',
SequenceExpression: 'SequenceExpression',
SpreadElement: 'SpreadElement',
Super: 'Super',
SwitchStatement: 'SwitchStatement',
SwitchCase: 'SwitchCase',
TaggedTemplateExpression: 'TaggedTemplateExpression',
TemplateElement: 'TemplateElement',
TemplateLiteral: 'TemplateLiteral',
ThisExpression: 'ThisExpression',
ThrowStatement: 'ThrowStatement',
TryStatement: 'TryStatement',
UnaryExpression: 'UnaryExpression',
UpdateExpression: 'UpdateExpression',
VariableDeclaration: 'VariableDeclaration',
VariableDeclarator: 'VariableDeclarator',
WhileStatement: 'WhileStatement',
WithStatement: 'WithStatement',
YieldExpression: 'YieldExpression'
};
exports.Syntax = Syntax;
var Precedence = {
Sequence: 0,
Yield: 1,
Assignment: 1,
Conditional: 2,
ArrowFunction: 2,
Coalesce: 3,
LogicalOR: 3,
LogicalAND: 4,
BitwiseOR: 5,
BitwiseXOR: 6,
BitwiseAND: 7,
Equality: 8,
Relational: 9,
BitwiseSHIFT: 10,
Additive: 11,
Multiplicative: 12,
Unary: 13,
Exponentiation: 14,
Postfix: 14,
Await: 14,
Call: 15,
New: 16,
TaggedTemplate: 17,
OptionalChaining: 17,
Member: 18,
Primary: 19
};
var BinaryPrecedence = {
'||': Precedence.LogicalOR,
'&&': Precedence.LogicalAND,
'|': Precedence.BitwiseOR,
'^': Precedence.BitwiseXOR,
'&': Precedence.BitwiseAND,
'==': Precedence.Equality,
'!=': Precedence.Equality,
'===': Precedence.Equality,
'!==': Precedence.Equality,
'is': Precedence.Equality,
'isnt': Precedence.Equality,
'<': Precedence.Relational,
'>': Precedence.Relational,
'<=': Precedence.Relational,
'>=': Precedence.Relational,
'in': Precedence.Relational,
'instanceof': Precedence.Relational,
'<<': Precedence.BitwiseSHIFT,
'>>': Precedence.BitwiseSHIFT,
'>>>': Precedence.BitwiseSHIFT,
'+': Precedence.Additive,
'-': Precedence.Additive,
'*': Precedence.Multiplicative,
'%': Precedence.Multiplicative,
'/': Precedence.Multiplicative,
'??': Precedence.Coalesce,
'**': Precedence.Exponentiation
};
function getDefaultOptions () {
return {
indent: null,
base: null,
parse: null,
format: {
indent: {
style: ' ',
base: 0
},
newline: '\n',
space: ' ',
json: false,
renumber: false,
hexadecimal: false,
quotes: 'single',
escapeless: false,
compact: false,
parentheses: true,
semicolons: true,
safeConcatenation: false
},
directive: false,
raw: true,
verbatim: null
};
}
var NON_ASCII_WHITESPACES = [
0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005,
0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000,
0xFEFF
];
var NON_ASCII_IDENTIFIER_CHARACTERS_REGEXP = new RegExp(
'[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376' +
'\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-' +
'\u0527\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\u08A2-\u08AC\u08E4-\u08FE\u0900-' +
'\u0963\u0966-\u096F\u0971-\u0977\u0979-\u097F\u0981-\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\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\u0C01-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D-\u0C44\u0C46-' +
'\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C82\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\u0D02\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44' +
'\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-' +
'\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\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\u1380-' +
'\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\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-\u191C\u1920-\u192B' +
'\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E' +
'\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-' +
'\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1D00-\u1DE6\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' +
'\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\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\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A' +
'\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5' +
'\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA697' +
'\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA827\uA840-\uA873' +
'\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-' +
'\uA9D9\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7B\uAA80-\uAAC2\uAADB-\uAADD\uAAE0-' +
'\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\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-\uFE26\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]'
);
function isIdentifierCh (cp) {
if (cp < 0x80) {
return cp >= 97 && cp <= 122 ||
cp >= 65 && cp <= 90 ||
cp >= 48 && cp <= 57 ||
cp === 36 || cp === 95 ||
cp === 92;
}
var ch = String.fromCharCode(cp);
return NON_ASCII_IDENTIFIER_CHARACTERS_REGEXP.test(ch);
}
function isLineTerminator (cp) {
return cp === 0x0A || cp === 0x0D || cp === 0x2028 || cp === 0x2029;
}
function isWhitespace (cp) {
return cp === 0x20 || cp === 0x09 || isLineTerminator(cp) || cp === 0x0B || cp === 0x0C || cp === 0xA0 ||
(cp >= 0x1680 && NON_ASCII_WHITESPACES.indexOf(cp) >= 0);
}
function isDecimalDigit (cp) {
return cp >= 48 && cp <= 57;
}
function stringRepeat (str, num) {
var result = '';
for (num |= 0; num > 0; num >>>= 1, str += str) {
if (num & 1) {
result += str;
}
}
return result;
}
isArray = Array.isArray;
if (!isArray) {
isArray = function isArray (array) {
return Object.prototype.toString.call(array) === '[object Array]';
};
}
function updateDeeply (target, override) {
var key, val;
function isHashObject (target) {
return typeof target === 'object' && target instanceof Object && !(target instanceof RegExp);
}
for (key in override) {
if (override.hasOwnProperty(key)) {
val = override[key];
if (isHashObject(val)) {
if (isHashObject(target[key])) {
updateDeeply(target[key], val);
}
else {
target[key] = updateDeeply({}, val);
}
}
else {
target[key] = val;
}
}
}
return target;
}
function generateNumber (value) {
var result, point, temp, exponent, pos;
if (value === 1 / 0) {
return json ? 'null' : renumber ? '1e400' : '1e+400';
}
result = '' + value;
if (!renumber || result.length < 3) {
return result;
}
point = result.indexOf('.');
if (!json && result.charCodeAt(0) === 0x30 && point === 1) {
point = 0;
result = result.slice(1);
}
temp = result;
result = result.replace('e+', 'e');
exponent = 0;
if ((pos = temp.indexOf('e')) > 0) {
exponent = +temp.slice(pos + 1);
temp = temp.slice(0, pos);
}
if (point >= 0) {
exponent -= temp.length - point - 1;
temp = +(temp.slice(0, point) + temp.slice(point + 1)) + '';
}
pos = 0;
while (temp.charCodeAt(temp.length + pos - 1) === 0x30) {
--pos;
}
if (pos !== 0) {
exponent -= pos;
temp = temp.slice(0, pos);
}
if (exponent !== 0) {
temp += 'e' + exponent;
}
if ((temp.length < result.length ||
(hexadecimal && value > 1e12 && Math.floor(value) === value &&
(temp = '0x' + value.toString(16)).length
< result.length)) &&
+temp === value) {
result = temp;
}
return result;
}
function escapeRegExpCharacter (ch, previousIsBackslash) {
if ((ch & ~1) === 0x2028) {
return (previousIsBackslash ? 'u' : '\\u') + ((ch === 0x2028) ? '2028' : '2029');
}
else if (ch === 10 || ch === 13) {
return (previousIsBackslash ? '' : '\\') + ((ch === 10) ? 'n' : 'r');
}
return String.fromCharCode(ch);
}
function generateRegExp (reg) {
var match, result, flags, i, iz, ch, characterInBrack, previousIsBackslash;
result = reg.toString();
if (reg.source) {
match = result.match(/\/([^/]*)$/);
if (!match) {
return result;
}
flags = match[1];
result = '';
characterInBrack = false;
previousIsBackslash = false;
for (i = 0, iz = reg.source.length; i < iz; ++i) {
ch = reg.source.charCodeAt(i);
if (!previousIsBackslash) {
if (characterInBrack) {
if (ch === 93) {
characterInBrack = false;
}
}
else {
if (ch === 47) {
result += '\\';
}
else if (ch === 91) {
characterInBrack = true;
}
}
result += escapeRegExpCharacter(ch, previousIsBackslash);
previousIsBackslash = ch === 92;
}
else {
result += escapeRegExpCharacter(ch, previousIsBackslash);
previousIsBackslash = false;
}
}
return '/' + result + '/' + flags;
}
return result;
}
function escapeAllowedCharacter (code, next) {
var hex, result = '\\';
switch (code) {
case 0x08:
result += 'b';
break;
case 0x0C:
result += 'f';
break;
case 0x09:
result += 't';
break;
default:
hex = code.toString(16).toUpperCase();
if (json || code > 0xFF) {
result += 'u' + '0000'.slice(hex.length) + hex;
}
else if (code === 0x0000 && !isDecimalDigit(next)) {
result += '0';
}
else if (code === 0x000B) {
result += 'x0B';
}
else {
result += 'x' + '00'.slice(hex.length) + hex;
}
break;
}
return result;
}
function escapeDisallowedCharacter (code) {
var result = '\\';
switch (code) {
case 0x5C
:
result += '\\';
break;
case 0x0A
:
result += 'n';
break;
case 0x0D
:
result += 'r';
break;
case 0x2028:
result += 'u2028';
break;
case 0x2029:
result += 'u2029';
break;
}
return result;
}
function escapeDirective (str) {
var i, iz, code, quote;
quote = quotes === 'double' ? '"' : '\'';
for (i = 0, iz = str.length; i < iz; ++i) {
code = str.charCodeAt(i);
if (code === 0x27) {
quote = '"';
break;
}
else if (code === 0x22) {
quote = '\'';
break;
}
else if (code === 0x5C) {
++i;
}
}
return quote + str + quote;
}
function escapeString (str) {
var result = '', i, len, code, singleQuotes = 0, doubleQuotes = 0, single, quote;
for (i = 0, len = str.length; i < len; ++i) {
code = str.charCodeAt(i);
if (code === 0x27) {
++singleQuotes;
}
else if (code === 0x22) {
++doubleQuotes;
}
else if (code === 0x2F && json) {
result += '\\';
}
else if (isLineTerminator(code) || code === 0x5C) {
result += escapeDisallowedCharacter(code);
continue;
}
else if ((json && code < 0x20) ||
!(json || escapeless || (code >= 0x20 && code <= 0x7E))) {
result += escapeAllowedCharacter(code, str.charCodeAt(i + 1));
continue;
}
result += String.fromCharCode(code);
}
single = !(quotes === 'double' || (quotes === 'auto' && doubleQuotes < singleQuotes));
quote = single ? '\'' : '"';
if (!(single ? singleQuotes : doubleQuotes)) {
return quote + result + quote;
}
str = result;
result = quote;
for (i = 0, len = str.length; i < len; ++i) {
code = str.charCodeAt(i);
if ((code === 0x27 && single) || (code === 0x22 && !single)) {
result += '\\';
}
result += String.fromCharCode(code);
}
return result + quote;
}
function join (l, r) {
if (!l.length)
return r;
if (!r.length)
return l;
var lCp = l.charCodeAt(l.length - 1),
rCp = r.charCodeAt(0);
if (isIdentifierCh(lCp) && isIdentifierCh(rCp) ||
lCp === rCp && (lCp === 0x2B || lCp === 0x2D) ||
lCp === 0x2F && rCp === 0x69) {
return l + _.space + r;
}
else if (isWhitespace(lCp) || isWhitespace(rCp))
return l + r;
return l + _.optSpace + r;
}
function shiftIndent () {
var prevIndent = _.indent;
_.indent += _.indentUnit;
return prevIndent;
}
function adoptionPrefix ($stmt) {
if ($stmt.type === Syntax.BlockStatement)
return _.optSpace;
if ($stmt.type === Syntax.EmptyStatement)
return '';
return _.newline + _.indent + _.indentUnit;
}
function adoptionSuffix ($stmt) {
if ($stmt.type === Syntax.BlockStatement)
return _.optSpace;
return _.newline + _.indent;
}
function generateVerbatim ($expr, settings) {
var verbatim = $expr[extra.verbatim],
strVerbatim = typeof verbatim === 'string',
precedence = !strVerbatim &&
verbatim.precedence !== void 0 ? verbatim.precedence : Precedence.Sequence,
parenthesize = precedence < settings.precedence,
content = strVerbatim ? verbatim : verbatim.content,
chunks = content.split(/\r\n|\n/),
chunkCount = chunks.length;
if (parenthesize)
_.js += '(';
_.js += chunks[0];
for (var i = 1; i < chunkCount; i++)
_.js += _.newline + _.indent + chunks[i];
if (parenthesize)
_.js += ')';
}
function generateFunctionParams ($node) {
var $params = $node.params,
paramCount = $params.length,
lastParamIdx = paramCount - 1,
arrowFuncWithoutParentheses = $node.type === Syntax.ArrowFunctionExpression && paramCount === 1 &&
$params[0].type === Syntax.Identifier;
if (arrowFuncWithoutParentheses)
_.js += $params[0].name;
else {
_.js += '(';
for (var i = 0; i < paramCount; ++i) {
var $param = $params[i];
if ($params[i].type === Syntax.Identifier)
_.js += $param.name;
else
ExprGen[$param.type]($param, Preset.e4);
if (i !== lastParamIdx)
_.js += ',' + _.optSpace;
}
_.js += ')';
}
}
function generateFunctionBody ($node) {
var $body = $node.body;
generateFunctionParams($node);
if ($node.type === Syntax.ArrowFunctionExpression)
_.js += _.optSpace + '=>';
if ($node.expression) {
_.js += _.optSpace;
var exprJs = exprToJs($body, Preset.e4);
if (exprJs.charAt(0) === '{')
exprJs = '(' + exprJs + ')';
_.js += exprJs;
}
else {
_.js += adoptionPrefix($body);
StmtGen[$body.type]($body, Preset.s8);
}
}
var Preset = {
e1: function (allowIn) {
return {
precedence: Precedence.Assignment,
allowIn: allowIn,
allowCall: true,
allowUnparenthesizedNew: true
};
},
e2: function (allowIn) {
return {
precedence: Precedence.LogicalOR,
allowIn: allowIn,
allowCall: true,
allowUnparenthesizedNew: true
};
},
e3: {
precedence: Precedence.Call,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: false
},
e4: {
precedence: Precedence.Assignment,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: true
},
e5: {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: true
},
e6: function (allowUnparenthesizedNew) {
return {
precedence: Precedence.New,
allowIn: true,
allowCall: false,
allowUnparenthesizedNew: allowUnparenthesizedNew
};
},
e7: {
precedence: Precedence.Unary,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: true
},
e8: {
precedence: Precedence.Postfix,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: true
},
e9: {
precedence: void 0,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: true
},
e10: {
precedence: Precedence.Call,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: true
},
e11: function (allowCall) {
return {
precedence: Precedence.Call,
allowIn: true,
allowCall: allowCall,
allowUnparenthesizedNew: false
};
},
e12: {
precedence: Precedence.Primary,
allowIn: false,
allowCall: false,
allowUnparenthesizedNew: true
},
e13: {
precedence: Precedence.Primary,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: true
},
e14: {
precedence: Precedence.Sequence,
allowIn: false,
allowCall: true,
allowUnparenthesizedNew: true
},
e15: function (allowCall) {
return {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: allowCall,
allowUnparenthesizedNew: true
};
},
e16: function (precedence, allowIn) {
return {
precedence: precedence,
allowIn: allowIn,
allowCall: true,
allowUnparenthesizedNew: true
};
},
e17: function (allowIn) {
return {
precedence: Precedence.Call,
allowIn: allowIn,
allowCall: true,
allowUnparenthesizedNew: true
}
},
e18: function (allowIn) {
return {
precedence: Precedence.Assignment,
allowIn: allowIn,
allowCall: true,
allowUnparenthesizedNew: true
}
},
e19: {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true,
semicolonOptional: false
},
e20: {
precedence: Precedence.Await,
allowCall: true
},
s1: function (functionBody, semicolonOptional) {
return {
allowIn: true,
functionBody: false,
directiveContext: functionBody,
semicolonOptional: semicolonOptional
};
},
s2: {
allowIn: true,
functionBody: false,
directiveContext: false,
semicolonOptional: true
},
s3: function (allowIn) {
return {
allowIn: allowIn,
functionBody: false,
directiveContext: false,
semicolonOptional: false
};
},
s4: function (semicolonOptional) {
return {
allowIn: true,
functionBody: false,
directiveContext: false,
semicolonOptional: semicolonOptional
};
},
s5: function (semicolonOptional) {
return {
allowIn: true,
functionBody: false,
directiveContext: true,
semicolonOptional: semicolonOptional,
};
},
s6: {
allowIn: false,
functionBody: false,
directiveContext: false,
semicolonOptional: false
},
s7: {
allowIn: true,
functionBody: false,
directiveContext: false,
semicolonOptional: false
},
s8: {
allowIn: true,
functionBody: true,
directiveContext: false,
semicolonOptional: false
}
};
var FLOATING_OR_OCTAL_REGEXP = /[.eExX]|^0[0-9]+/,
LAST_DECIMAL_DIGIT_REGEXP = /[0-9]$/;
function generateLogicalOrBinaryExpression ($expr, settings) {
var op = $expr.operator,
precedence = BinaryPrecedence[$expr.operator],
parenthesize = precedence < settings.precedence,
allowIn = settings.allowIn || parenthesize,
operandGenSettings = Preset.e16(precedence, allowIn),
exprJs = exprToJs($expr.left, operandGenSettings);
parenthesize |= op === 'in' && !allowIn;
if (parenthesize)
_.js += '(';
if (exprJs.charCodeAt(exprJs.length - 1) === 0x2F && isIdentifierCh(op.charCodeAt(0)))
exprJs = exprJs + _.space + op;
else
exprJs = join(exprJs, op);
operandGenSettings.precedence++;
var rightJs = exprToJs($expr.right, operandGenSettings);
if (op === '/' && rightJs.charAt(0) === '/' || op.slice(-1) === '<' && rightJs.slice(0, 3) === '!--')
exprJs += _.space + rightJs;
else
exprJs = join(exprJs, rightJs);
_.js += exprJs;
if (parenthesize)
_.js += ')';
}
function generateArrayPatternOrExpression ($expr) {
var $elems = $expr.elements,
elemCount = $elems.length;
if (elemCount) {
var lastElemIdx = elemCount - 1,
multiline = elemCount > 1,
prevIndent = shiftIndent(),
itemPrefix = _.newline + _.indent;
_.js += '[';
for (var i = 0; i < elemCount; i++) {
var $elem = $elems[i];
if (multiline)
_.js += itemPrefix;
if ($elem)
ExprGen[$elem.type]($elem, Preset.e4);
if (i !== lastElemIdx || !$elem)
_.js += ',';
}
_.indent = prevIndent;
if (multiline)
_.js += _.newline + _.indent;
_.js += ']';
}
else
_.js += '[]';
}
function generateGeneratorOrComprehensionExpression ($expr) {
var $blocks = $expr.blocks,
$filter = $expr.filter,
isGenerator = $expr.type === Syntax.GeneratorExpression,
exprJs = isGenerator ? '(' : '[',
bodyJs = exprToJs($expr.body, Preset.e4);
if ($blocks) {
var prevIndent = shiftIndent(),
blockCount = $blocks.length;
for (var i = 0; i < blockCount; ++i) {
var blockJs = exprToJs($blocks[i], Preset.e5);
exprJs = i > 0 ? join(exprJs, blockJs) : (exprJs + blockJs);
}
_.indent = prevIndent;
}
if ($filter) {
var filterJs = exprToJs($filter, Preset.e5);
exprJs = join(exprJs, 'if' + _.optSpace);
exprJs = join(exprJs, '(' + filterJs + ')');
}
exprJs = join(exprJs, bodyJs);
exprJs += isGenerator ? ')' : ']';
_.js += exprJs;
}
var ExprRawGen = {
SequenceExpression: function generateSequenceExpression ($expr, settings) {
var $children = $expr.expressions,
childrenCount = $children.length,
lastChildIdx = childrenCount - 1,
parenthesize = Precedence.Sequence < settings.precedence,
exprGenSettings = Preset.e1(settings.allowIn || parenthesize);
if (parenthesize)
_.js += '(';
for (var i = 0; i < childrenCount; i++) {
var $child = $children[i];
ExprGen[$child.type]($child, exprGenSettings);
if (i !== lastChildIdx)
_.js += ',' + _.optSpace;
}
if (parenthesize)
_.js += ')';
},
AssignmentExpression: function generateAssignmentExpression ($expr, settings) {
var $left = $expr.left,
$right = $expr.right,
parenthesize = Precedence.Assignment < settings.precedence,
allowIn = settings.allowIn || parenthesize;
if (parenthesize)
_.js += '(';
ExprGen[$left.type]($left, Preset.e17(allowIn));
_.js += _.optSpace + $expr.operator + _.optSpace;
ExprGen[$right.type]($right, Preset.e18(allowIn));
if (parenthesize)
_.js += ')';
},
AssignmentPattern: function generateAssignmentPattern ($node) {
var $fakeAssign = {
left: $node.left,
right: $node.right,
operator: '='
};
ExprGen.AssignmentExpression($fakeAssign, Preset.e4);
},
ArrowFunctionExpression: function generateArrowFunctionExpression ($expr, settings) {
var parenthesize = Precedence.ArrowFunction < settings.precedence;
if (parenthesize)
_.js += '(';
if ($expr.async)
_.js += 'async ';
generateFunctionBody($expr);
if (parenthesize)
_.js += ')';
},
AwaitExpression: function generateAwaitExpression ($expr, settings) {
var parenthesize = Precedence.Await < settings.precedence;
if (parenthesize)
_.js += '(';
_.js += $expr.all ? 'await* ' : 'await ';
ExprGen[$expr.argument.type]($expr.argument, Preset.e20);
if (parenthesize)
_.js += ')';
},
ConditionalExpression: function generateConditionalExpression ($expr, settings) {
var $test = $expr.test,
$conseq = $expr.consequent,
$alt = $expr.alternate,
parenthesize = Precedence.Conditional < settings.precedence,
allowIn = settings.allowIn || parenthesize,
testGenSettings = Preset.e2(allowIn),
branchGenSettings = Preset.e1(allowIn);
if (parenthesize)
_.js += '(';
ExprGen[$test.type]($test, testGenSettings);
_.js += _.optSpace + '?' + _.optSpace;
ExprGen[$conseq.type]($conseq, branchGenSettings);
_.js += _.optSpace + ':' + _.optSpace;
ExprGen[$alt.type]($alt, branchGenSettings);
if (parenthesize)
_.js += ')';
},
LogicalExpression: generateLogicalOrBinaryExpression,
BinaryExpression: generateLogicalOrBinaryExpression,
CallExpression: function generateCallExpression ($expr, settings) {
var $callee = $expr.callee,
$args = $expr['arguments'],
argCount = $args.length,
lastArgIdx = argCount - 1,
parenthesize = !settings.allowCall || Precedence.Call < settings.precedence;
if (parenthesize)
_.js += '(';
ExprGen[$callee.type]($callee, Preset.e3);
if ($expr.optional)
_.js += '?.';
_.js += '(';
for (var i = 0; i < argCount; ++i) {
var $arg = $args[i];
ExprGen[$arg.type]($arg, Preset.e4);
if (i !== lastArgIdx)
_.js += ',' + _.optSpace;
}
_.js += ')';
if (parenthesize)
_.js += ')';
},
NewExpression: function generateNewExpression ($expr, settings) {
var $args = $expr['arguments'],
parenthesize = Precedence.New < settings.precedence,
argCount = $args.length,
lastArgIdx = argCount - 1,
withCall = !settings.allowUnparenthesizedNew || parentheses || argCount > 0,
calleeJs = exprToJs($expr.callee, Preset.e6(!withCall));
if (parenthesize)
_.js += '(';
_.js += join('new', calleeJs);
if (withCall) {
_.js += '(';
for (var i = 0; i < argCount; ++i) {
var $arg = $args[i];
ExprGen[$arg.type]($arg, Preset.e4);
if (i !== lastArgIdx)
_.js += ',' + _.optSpace;
}
_.js += ')';
}
if (parenthesize)
_.js += ')';
},
MemberExpression: function generateMemberExpression ($expr, settings) {
var $obj = $expr.object,
$prop = $expr.property,
parenthesize = Precedence.Member < settings.precedence,
isNumObj = !$expr.computed && $obj.type === Syntax.Literal && typeof $obj.value === 'number';
if (parenthesize)
_.js += '(';
if (isNumObj) {
var numJs = exprToJs($obj, Preset.e11(settings.allowCall)),
withPoint = LAST_DECIMAL_DIGIT_REGEXP.test(numJs) && !FLOATING_OR_OCTAL_REGEXP.test(numJs);
_.js += withPoint ? (numJs + '.') : numJs;
}
else
ExprGen[$obj.type]($obj, Preset.e11(settings.allowCall));
if ($expr.computed) {
if ($expr.optional)
_.js += '?.';
_.js += '[';
ExprGen[$prop.type]($prop, Preset.e15(settings.allowCall));
_.js += ']';
}
else
_.js += ($expr.optional ? '?.' : '.') + $prop.name;
if (parenthesize)
_.js += ')';
},
UnaryExpression: function generateUnaryExpression ($expr, settings) {
var parenthesize = Precedence.Unary < settings.precedence,
op = $expr.operator,
argJs = exprToJs($expr.argument, Preset.e7);
if (parenthesize)
_.js += '(';
if (_.optSpace === '' || op.length > 2)
_.js += join(op, argJs);
else {
_.js += op;
var leftCp = op.charCodeAt(op.length - 1),
rightCp = argJs.charCodeAt(0);
if (leftCp === rightCp && (leftCp === 0x2B || leftCp === 0x2D) ||
isIdentifierCh(leftCp) && isIdentifierCh(rightCp)) {
_.js += _.space;
}
_.js += argJs;
}
if (parenthesize)
_.js += ')';
},
YieldExpression: function generateYieldExpression ($expr, settings) {
var $arg = $expr.argument,
js = $expr.delegate ? 'yield*' : 'yield',
parenthesize = Precedence.Yield < settings.precedence;
if (parenthesize)
_.js += '(';
if ($arg) {
var argJs = exprToJs($arg, Preset.e4);
js = join(js, argJs);
}
_.js += js;
if (parenthesize)
_.js += ')';
},
UpdateExpression: function generateUpdateExpression ($expr, settings) {
var $arg = $expr.argument,
$op = $expr.operator,
prefix = $expr.prefix,
precedence = prefix ? Precedence.Unary : Precedence.Postfix,
parenthesize = precedence < settings.precedence;
if (parenthesize)
_.js += '(';
if (prefix) {
_.js += $op;
ExprGen[$arg.type]($arg, Preset.e8);
}
else {
ExprGen[$arg.type]($arg, Preset.e8);
_.js += $op;
}
if (parenthesize)
_.js += ')';
},
FunctionExpression: function generateFunctionExpression ($expr) {
var isGenerator = !!$expr.generator;
if ($expr.async)
_.js += 'async ';
_.js += isGenerator ? 'function*' : 'function';
if ($expr.id) {
_.js += isGenerator ? _.optSpace : _.space;
_.js += $expr.id.name;
}
else
_.js += _.optSpace;
generateFunctionBody($expr);
},
ExportBatchSpecifier: function generateExportBatchSpecifier () {
_.js += '*';
},
ArrayPattern: generateArrayPatternOrExpression,
ArrayExpression: generateArrayPatternOrExpression,
ClassExpression: function generateClassExpression ($expr) {
var $id = $expr.id,
$super = $expr.superClass,
$body = $expr.body,
exprJs = 'class';
if ($id) {
var idJs = exprToJs($id, Preset.e9);
exprJs = join(exprJs, idJs);
}
if ($super) {
var superJs = exprToJs($super, Preset.e4);
superJs = join('extends', superJs);
exprJs = join(exprJs, superJs);
}
_.js += exprJs + _.optSpace;
StmtGen[$body.type]($body, Preset.s2);
},
MetaProperty: function generateMetaProperty ($expr, settings) {
var $meta = $expr.meta,
$property = $expr.property,
parenthesize = Precedence.Member < settings.precedence;
if (parenthesize)
_.js += '(';
_.js += (typeof $meta === "string" ? $meta : $meta.name) +
'.' + (typeof $property === "string" ? $property : $property.name);
if (parenthesize)
_.js += ')';
},
MethodDefinition: function generateMethodDefinition ($expr) {
var exprJs = $expr['static'] ? 'static' + _.optSpace : '',
keyJs = exprToJs($expr.key, Preset.e5);
if ($expr.computed)
keyJs = '[' + keyJs + ']';
if ($expr.kind === 'get' || $expr.kind === 'set') {
keyJs = join($expr.kind, keyJs);
_.js += join(exprJs, keyJs);
}
else {
if ($expr.value.generator)
_.js += exprJs + '*' + keyJs;
else if ($expr.value.async)
_.js += exprJs + 'async ' + keyJs;
else
_.js += join(exprJs, keyJs);
}
generateFunctionBody($expr.value);
},
Property: function generateProperty ($expr) {
var $val = $expr.value,
$kind = $expr.kind,
keyJs = exprToJs($expr.key, Preset.e4);
if ($expr.computed)
keyJs = '[' + keyJs + ']';
if ($kind === 'get' || $kind === 'set') {
_.js += $kind + _.space + keyJs;
generateFunctionBody($val);
}
else {
if ($expr.shorthand)
_.js += keyJs;
else if ($expr.method) {
if ($val.generator)
keyJs = '*' + keyJs;
else if ($val.async)
keyJs = 'async ' + keyJs;
_.js += keyJs;
generateFunctionBody($val)
}
else {
_.js += keyJs + ':' + _.optSpace;
ExprGen[$val.type]($val, Preset.e4);
}
}
},
ObjectExpression: function generateObjectExpression ($expr) {
var $props = $expr.properties,
propCount = $props.length;
if (propCount) {
var lastPropIdx = propCount - 1,
prevIndent = shiftIndent();
_.js += '{';
for (var i = 0; i < propCount; i++) {
var $prop = $props[i],
propType = $prop.type || Syntax.Property;
_.js += _.newline + _.indent;
ExprGen[propType]($prop, Preset.e5);
if (i !== lastPropIdx)
_.js += ',';
}
_.indent = prevIndent;
_.js += _.newline + _.indent + '}';
}
else
_.js += '{}';
},
ObjectPattern: function generateObjectPattern ($expr) {
var $props = $expr.properties,
propCount = $props.length;
if (propCount) {
var lastPropIdx = propCount - 1,
multiline = false;
if (propCount === 1 && $props[0].value)
multiline = $props[0].value.type !== Syntax.Identifier;
else {
for (var i = 0; i < propCount; i++) {
if (!$props[i].shorthand) {
multiline = true;
break;
}
}
}
_.js += multiline ? ('{' + _.newline) : '{';
var prevIndent = shiftIndent(),
propSuffix = ',' + (multiline ? _.newline : _.optSpace);
for (var i = 0; i < propCount; i++) {
var $prop = $props[i];
if (multiline)
_.js += _.indent;
ExprGen[$prop.type]($prop, Preset.e5);
if (i !== lastPropIdx)
_.js += propSuffix;
}
_.indent = prevIndent;
_.js += multiline ? (_.newline + _.indent + '}') : '}';
}
else
_.js += '{}';
},
ThisExpression: function generateThisExpression () {
_.js += 'this';
},
Identifier: function generateIdentifier ($expr, precedence, flag) {
_.js += $expr.name;
},
ImportExpression: function generateImportExpression ($expr, settings) {
var parenthesize = Precedence.Call < settings.precedence;
var $source = $expr.source;
if (parenthesize)
_.js += '(';
_.js += 'import(';
ExprGen[$source.type]($source, Preset.e4);
_.js += ')';
if (parenthesize)
_.js += ')';
},
ImportSpecifier: function generateImportSpecifier ($expr) {
_.js += $expr.imported.name;
if ($expr.local)
_.js += _.space + 'as' + _.space + $expr.local.name;
},
ExportSpecifier: function generateImportOrExportSpecifier ($expr) {
_.js += $expr.local.name;
if ($expr.exported)
_.js += _.space + 'as' + _.space + $expr.exported.name;
},
ChainExpression: function generateChainExpression ($expr, settings) {
var parenthesize = Precedence.OptionalChaining < settings.precedence;
var $expression = $expr.expression;
settings = settings || {};
var newSettings = {
precedence: Precedence.OptionalChaining,
allowIn: settings.allowIn ,
allowCall: settings.allowCall,
allowUnparenthesizedNew: settings.allowUnparenthesizedNew
}
if (parenthesize) {
newSettings.allowCall = true;
_.js += '(';
}
ExprGen[$expression.type]($expression, newSettings);
if (parenthesize)
_.js += ')';
},
Literal: function generateLiteral ($expr) {
if (extra.raw && $expr.raw !== void 0)
_.js += $expr.raw;
else if ($expr.value === null)
_.js += 'null';
else {
var valueType = typeof $expr.value;
if (valueType === 'string')
_.js += escapeString($expr.value);
else if (valueType === 'number')
_.js += generateNumber($expr.value);
else if (valueType === 'boolean')
_.js += $expr.value ? 'true' : 'false';
else
_.js += generateRegExp($expr.value);
}
},
GeneratorExpression: generateGeneratorOrComprehensionExpression,
ComprehensionExpression: generateGeneratorOrComprehensionExpression,
ComprehensionBlock: function generateComprehensionBlock ($expr) {
var $left = $expr.left,
leftJs = void 0,
rightJs = exprToJs($expr.right, Preset.e5);
if ($left.type === Syntax.VariableDeclaration)
leftJs = $left.kind + _.space + stmtToJs($left.declarations[0], Preset.s6);
else
leftJs = exprToJs($left, Preset.e10);
leftJs = join(leftJs, $expr.of ? 'of' : 'in');
_.js += 'for' + _.optSpace + '(' + join(leftJs, rightJs) + ')';
},
RestElement: function generateRestElement ($node) {
_.js += '...' + $node.argument.name;
},
SpreadElement: function generateSpreadElement ($expr) {
var $arg = $expr.argument;
_.js += '...';
ExprGen[$arg.type]($arg, Preset.e4);
},
TaggedTemplateExpression: function generateTaggedTemplateExpression ($expr, settings) {
var $tag = $expr.tag,
$quasi = $expr.quasi,
parenthesize = Precedence.TaggedTemplate < settings.precedence;
if (parenthesize)
_.js += '(';
ExprGen[$tag.type]($tag, Preset.e11(settings.allowCall));
ExprGen[$quasi.type]($quasi, Preset.e12);
if (parenthesize)
_.js += ')';
},
TemplateElement: function generateTemplateElement ($expr) {
_.js += $expr.value.raw;
},
TemplateLiteral: function generateTemplateLiteral ($expr) {
var $quasis = $expr.quasis,
$childExprs = $expr.expressions,
quasiCount = $quasis.length,
lastQuasiIdx = quasiCount - 1;
_.js += '`';
for (var i = 0; i < quasiCount; ++i) {
var $quasi = $quasis[i];
ExprGen[$quasi.type]($quasi, Preset.e13);
if (i !== lastQuasiIdx) {
var $childExpr = $childExprs[i];
_.js += '${' + _.optSpace;
ExprGen[$childExpr.type]($childExpr, Preset.e5);
_.js += _.optSpace + '}';
}
}
_.js += '`';
},
Super: function generateSuper () {
_.js += 'super';
}
};
var EXPR_STMT_UNALLOWED_EXPR_REGEXP = /^{|^class(?:\s|{)|^(async )?function(?:\s|\*|\()/;
function generateTryStatementHandlers (stmtJs, $finalizer, handlers) {
var handlerCount = handlers.length,
lastHandlerIdx = handlerCount - 1;
for (var i = 0; i < handlerCount; ++i) {
var handlerJs = stmtToJs(handlers[i], Preset.s7);
stmtJs = join(stmtJs, handlerJs);
if ($finalizer || i !== lastHandlerIdx)
stmtJs += adoptionSuffix(handlers[i].body);
}
return stmtJs;
}
function generateForStatementIterator ($op, $stmt, settings) {
var $body = $stmt.body,
$left = $stmt.left,
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
prevIndent1 = shiftIndent(),
awaitStr = $stmt.await ? ' await' : '',
stmtJs = 'for' + awaitStr + _.optSpace + '(';
if ($left.type === Syntax.VariableDeclaration) {
var prevIndent2 = shiftIndent();
stmtJs += $left.kind + _.space + stmtToJs($left.declarations[0], Preset.s6);
_.indent = prevIndent2;
}
else
stmtJs += exprToJs($left, Preset.e10);
stmtJs = join(stmtJs, $op);
var rightJs = exprToJs($stmt.right, Preset.e4);
stmtJs = join(stmtJs, rightJs) + ')';
_.indent = prevIndent1;
_.js += stmtJs + adoptionPrefix($body);
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
}
var StmtRawGen = {
BlockStatement: function generateBlockStatement ($stmt, settings) {
var $body = $stmt.body,
len = $body.length,
lastIdx = len - 1,
prevIndent = shiftIndent();
_.js += '{' + _.newline;
for (var i = 0; i < len; i++) {
var $item = $body[i];
_.js += _.indent;
StmtGen[$item.type]($item, Preset.s1(settings.functionBody, i === lastIdx));
_.js += _.newline;
}
_.indent = prevIndent;
_.js += _.indent + '}';
},
BreakStatement: function generateBreakStatement ($stmt, settings) {
if ($stmt.label)
_.js += 'break ' + $stmt.label.name;
else
_.js += 'break';
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
ContinueStatement: function generateContinueStatement ($stmt, settings) {
if ($stmt.label)
_.js += 'continue ' + $stmt.label.name;
else
_.js += 'continue';
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
ClassBody: function generateClassBody ($stmt) {
var $body = $stmt.body,
itemCount = $body.length,
lastItemIdx = itemCount - 1,
prevIndent = shiftIndent();
_.js += '{' + _.newline;
for (var i = 0; i < itemCount; i++) {
var $item = $body[i],
itemType = $item.type || Syntax.Property;
_.js += _.indent;
ExprGen[itemType]($item, Preset.e5);
if (i !== lastItemIdx)
_.js += _.newline;
}
_.indent = prevIndent;
_.js += _.newline + _.indent + '}';
},
ClassDeclaration: function generateClassDeclaration ($stmt) {
var $body = $stmt.body,
$super = $stmt.superClass,
js = 'class ' + $stmt.id.name;
if ($super) {
var superJs = exprToJs($super, Preset.e4);
js += _.space + join('extends', superJs);
}
_.js += js + _.optSpace;
StmtGen[$body.type]($body, Preset.s2);
},
DirectiveStatement: function generateDirectiveStatement ($stmt, settings) {
if (extra.raw && $stmt.raw)
_.js += $stmt.raw;
else
_.js += escapeDirective($stmt.directive);
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
DoWhileStatement: function generateDoWhileStatement ($stmt, settings) {
var $body = $stmt.body,
$test = $stmt.test,
bodyJs = adoptionPrefix($body) +
stmtToJs($body, Preset.s7) +
adoptionSuffix($body);
var stmtJs = join('do', bodyJs);
_.js += join(stmtJs, 'while' + _.optSpace + '(');
ExprGen[$test.type]($test, Preset.e5);
_.js += ')';
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
CatchClause: function generateCatchClause ($stmt) {
var $param = $stmt.param,
$guard = $stmt.guard,
$body = $stmt.body,
prevIndent = shiftIndent();
_.js += 'catch' + _.optSpace;
if ($param) {
_.js += '(';
ExprGen[$param.type]($param, Preset.e5);
}
if ($guard) {
_.js += ' if ';
ExprGen[$guard.type]($guard, Preset.e5);
}
_.indent = prevIndent;
if ($param) {
_.js += ')';
}
_.js += adoptionPrefix($body);
StmtGen[$body.type]($body, Preset.s7);
},
DebuggerStatement: function generateDebuggerStatement ($stmt, settings) {
_.js += 'debugger';
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
EmptyStatement: function generateEmptyStatement () {
_.js += ';';
},
ExportAllDeclaration: function ($stmt, settings) {
StmtRawGen.ExportDeclaration($stmt, settings, true);
},
ExportDeclaration: function generateExportDeclaration ($stmt, settings, exportAll) {
var $specs = $stmt.specifiers,
$decl = $stmt.declaration,
withSemicolon = semicolons || !settings.semicolonOptional;
if ($stmt['default']) {
var declJs = exprToJs($decl, Preset.e4);
_.js += join('export default', declJs);
if (withSemicolon)
_.js += ';';
}
else if ($specs || exportAll) {
var stmtJs = 'export';
if (exportAll)
stmtJs += _.optSpace + '*';
else if ($specs.length === 0)
stmtJs += _.optSpace + '{' + _.optSpace + '}';
else if ($specs[0].type === Syntax.ExportBatchSpecifier) {
var specJs = exprToJs($specs[0], Preset.e5);
stmtJs = join(stmtJs, specJs);
}
else {
var prevIndent = shiftIndent(),
specCount = $specs.length,
lastSpecIdx = specCount - 1;
stmtJs += _.optSpace + '{';
for (var i = 0; i < specCount; ++i) {
stmtJs += _.newline + _.indent;
stmtJs += exprToJs($specs[i], Preset.e5);
if (i !== lastSpecIdx)
stmtJs += ',';
}
_.indent = prevIndent;
stmtJs += _.newline + _.indent + '}';
}
if ($stmt.source) {
_.js += join(stmtJs, 'from' + _.optSpace);
ExprGen.Literal($stmt.source);
}
else
_.js += stmtJs;
if (withSemicolon)
_.js += ';';
}
else if ($decl) {
var declJs = stmtToJs($decl, Preset.s4(!withSemicolon));
_.js += join('export', declJs);
}
},
ExportNamedDeclaration: function ($stmt, settings) {
StmtRawGen.ExportDeclaration($stmt, settings);
},
ExpressionStatement: function generateExpressionStatement ($stmt, settings) {
var exprJs = exprToJs($stmt.expression, Preset.e5),
parenthesize = EXPR_STMT_UNALLOWED_EXPR_REGEXP.test(exprJs) ||
(directive &&
settings.directiveContext &&
$stmt.expression.type === Syntax.Literal &&
typeof $stmt.expression.value === 'string');
if (parenthesize)
_.js += '(' + exprJs + ')';
else
_.js += exprJs;
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
ImportDeclaration: function generateImportDeclaration ($stmt, settings) {
var $specs = $stmt.specifiers,
stmtJs = 'import',
specCount = $specs.length;
if (specCount) {
var hasBinding = !!$specs[0]['default'],
firstNamedIdx = hasBinding ? 1 : 0,
lastSpecIdx = specCount - 1;
if (hasBinding)
stmtJs = join(stmtJs, $specs[0].id.name);
if (firstNamedIdx < specCount) {
if (hasBinding)
stmtJs += ',';
stmtJs += _.optSpace + '{';
if (firstNamedIdx === lastSpecIdx)
stmtJs += _.optSpace + exprToJs($specs[firstNamedIdx], Preset.e5) + _.optSpace;
else {
var prevIndent = shiftIndent();
for (var i = firstNamedIdx; i < specCount; i++) {
stmtJs += _.newline + _.indent + exprToJs($specs[i], Preset.e5);
if (i !== lastSpecIdx)
stmtJs += ',';
}
_.indent = prevIndent;
stmtJs += _.newline + _.indent;
}
stmtJs += '}' + _.optSpace;
}
stmtJs = join(stmtJs, 'from')
}
_.js += stmtJs + _.optSpace;
ExprGen.Literal($stmt.source);
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
VariableDeclarator: function generateVariableDeclarator ($stmt, settings) {
var $id = $stmt.id,
$init = $stmt.init,
genSettings = Preset.e1(settings.allowIn);
if ($init) {
ExprGen[$id.type]($id, genSettings);
_.js += _.optSpace + '=' + _.optSpace;
ExprGen[$init.type]($init, genSettings);
}
else {
if ($id.type === Syntax.Identifier)
_.js += $id.name;
else
ExprGen[$id.type]($id, genSettings);
}
},
VariableDeclaration: function generateVariableDeclaration ($stmt, settings) {
var $decls = $stmt.declarations,
len = $decls.length,
prevIndent = len > 1 ? shiftIndent() : _.indent,
declGenSettings = Preset.s3(settings.allowIn);
_.js += $stmt.kind;
for (var i = 0; i < len; i++) {
var $decl = $decls[i];
_.js += i === 0 ? _.space : (',' + _.optSpace);
StmtGen[$decl.type]($decl, declGenSettings);
}
if (semicolons || !settings.semicolonOptional)
_.js += ';';
_.indent = prevIndent;
},
ThrowStatement: function generateThrowStatement ($stmt, settings) {
var argJs = exprToJs($stmt.argument, Preset.e5);
_.js += join('throw', argJs);
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
TryStatement: function generateTryStatement ($stmt) {
var $block = $stmt.block,
$finalizer = $stmt.finalizer,
stmtJs = 'try' +
adoptionPrefix($block) +
stmtToJs($block, Preset.s7) +
adoptionSuffix($block);
var $handlers = $stmt.handlers || $stmt.guardedHandlers;
if ($handlers)
stmtJs = generateTryStatementHandlers(stmtJs, $finalizer, $handlers);
if ($stmt.handler) {
$handlers = isArray($stmt.handler) ? $stmt.handler : [$stmt.handler];
stmtJs = generateTryStatementHandlers(stmtJs, $finalizer, $handlers);
}
if ($finalizer) {
stmtJs = join(stmtJs, 'finally' + adoptionPrefix($finalizer));
stmtJs += stmtToJs($finalizer, Preset.s7);
}
_.js += stmtJs;
},
SwitchStatement: function generateSwitchStatement ($stmt) {
var $cases = $stmt.cases,
$discr = $stmt.discriminant,
prevIndent = shiftIndent();
_.js += 'switch' + _.optSpace + '(';
ExprGen[$discr.type]($discr, Preset.e5);
_.js += ')' + _.optSpace + '{' + _.newline;
_.indent = prevIndent;
if ($cases) {
var caseCount = $cases.length,
lastCaseIdx = caseCount - 1;
for (var i = 0; i < caseCount; i++) {
var $case = $cases[i];
_.js += _.indent;
StmtGen[$case.type]($case, Preset.s4(i === lastCaseIdx));
_.js += _.newline;
}
}
_.js += _.indent + '}';
},
SwitchCase: function generateSwitchCase ($stmt, settings) {
var $conseqs = $stmt.consequent,
$firstConseq = $conseqs[0],
$test = $stmt.test,
i = 0,
conseqSemicolonOptional = !semicolons && settings.semicolonOptional,
conseqCount = $conseqs.length,
lastConseqIdx = conseqCount - 1,
prevIndent = shiftIndent();
if ($test) {
var testJs = exprToJs($test, Preset.e5);
_.js += join('case', testJs) + ':';
}
else
_.js += 'default:';
if (conseqCount && $firstConseq.type === Syntax.BlockStatement) {
i++;
_.js += adoptionPrefix($firstConseq);
StmtGen[$firstConseq.type]($firstConseq, Preset.s7);
}
for (; i < conseqCount; i++) {
var $conseq = $conseqs[i],
semicolonOptional = i === lastConseqIdx && conseqSemicolonOptional;
_.js += _.newline + _.indent;
StmtGen[$conseq.type]($conseq, Preset.s4(semicolonOptional));
}
_.indent = prevIndent;
},
IfStatement: function generateIfStatement ($stmt, settings) {
var $conseq = $stmt.consequent,
$test = $stmt.test,
prevIndent = shiftIndent(),
semicolonOptional = !semicolons && settings.semicolonOptional;
_.js += 'if' + _.optSpace + '(';
ExprGen[$test.type]($test, Preset.e5);
_.js += ')';
_.indent = prevIndent;
_.js += adoptionPrefix($conseq);
if ($stmt.alternate) {
var conseq = stmtToJs($conseq, Preset.s7) + adoptionSuffix($conseq),
alt = stmtToJs($stmt.alternate, Preset.s4(semicolonOptional));
if ($stmt.alternate.type === Syntax.IfStatement)
alt = 'else ' + alt;
else
alt = join('else', adoptionPrefix($stmt.alternate) + alt);
_.js += join(conseq, alt);
}
else
StmtGen[$conseq.type]($conseq, Preset.s4(semicolonOptional));
},
ForStatement: function generateForStatement ($stmt, settings) {
var $init = $stmt.init,
$test = $stmt.test,
$body = $stmt.body,
$update = $stmt.update,
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
prevIndent = shiftIndent();
_.js += 'for' + _.optSpace + '(';
if ($init) {
if ($init.type === Syntax.VariableDeclaration)
StmtGen[$init.type]($init, Preset.s6);
else {
ExprGen[$init.type]($init, Preset.e14);
_.js += ';';
}
}
else
_.js += ';';
if ($test) {
_.js += _.optSpace;
ExprGen[$test.type]($test, Preset.e5);
}
_.js += ';';
if ($update) {
_.js += _.optSpace;
ExprGen[$update.type]($update, Preset.e5);
}
_.js += ')';
_.indent = prevIndent;
_.js += adoptionPrefix($body);
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
},
ForInStatement: function generateForInStatement ($stmt, settings) {
generateForStatementIterator('in', $stmt, settings);
},
ForOfStatement: function generateForOfStatement ($stmt, settings) {
generateForStatementIterator('of', $stmt, settings);
},
LabeledStatement: function generateLabeledStatement ($stmt, settings) {
var $body = $stmt.body,
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
prevIndent = _.indent;
_.js += $stmt.label.name + ':' + adoptionPrefix($body);
if ($body.type !== Syntax.BlockStatement)
prevIndent = shiftIndent();
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
_.indent = prevIndent;
},
ModuleDeclaration: function generateModuleDeclaration ($stmt, settings) {
_.js += 'module' + _.space + $stmt.id.name + _.space + 'from' + _.optSpace;
ExprGen.Literal($stmt.source);
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
Program: function generateProgram ($stmt) {
var $body = $stmt.body,
len = $body.length,
lastIdx = len - 1;
if (safeConcatenation && len > 0)
_.js += '\n';
for (var i = 0; i < len; i++) {
var $item = $body[i];
_.js += _.indent;
StmtGen[$item.type]($item, Preset.s5(!safeConcatenation && i === lastIdx));
if (i !== lastIdx)
_.js += _.newline;
}
},
FunctionDeclaration: function generateFunctionDeclaration ($stmt) {
var isGenerator = !!$stmt.generator;
if ($stmt.async)
_.js += 'async ';
_.js += isGenerator ? ('function*' + _.optSpace) : ('function' + _.space );
_.js += $stmt.id.name;
generateFunctionBody($stmt);
},
ReturnStatement: function generateReturnStatement ($stmt, settings) {
var $arg = $stmt.argument;
if ($arg) {
var argJs = exprToJs($arg, Preset.e5);
_.js += join('return', argJs);
}
else
_.js += 'return';
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
WhileStatement: function generateWhileStatement ($stmt, settings) {
var $body = $stmt.body,
$test = $stmt.test,
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
prevIndent = shiftIndent();
_.js += 'while' + _.optSpace + '(';
ExprGen[$test.type]($test, Preset.e5);
_.js += ')';
_.indent = prevIndent;
_.js += adoptionPrefix($body);
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
},
WithStatement: function generateWithStatement ($stmt, settings) {
var $body = $stmt.body,
$obj = $stmt.object,
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
prevIndent = shiftIndent();
_.js += 'with' + _.optSpace + '(';
ExprGen[$obj.type]($obj, Preset.e5);
_.js += ')';
_.indent = prevIndent;
_.js += adoptionPrefix($body);
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
}
};
function generateStatement ($stmt, option) {
StmtGen[$stmt.type]($stmt, option);
}
function exprToJs ($expr, settings) {
var savedJs = _.js;
_.js = '';
if (typeof ExprGen[$expr.type] == 'function') ExprGen[$expr.type]($expr, settings);
var src = _.js;
_.js = savedJs;
return src;
}
function stmtToJs ($stmt, settings) {
var savedJs = _.js;
_.js = '';
StmtGen[$stmt.type]($stmt, settings);
var src = _.js;
_.js = savedJs;
return src;
}
function run ($node) {
_.js = '';
if (StmtGen[$node.type])
StmtGen[$node.type]($node, Preset.s7);
else
ExprGen[$node.type]($node, Preset.e19);
return _.js;
}
function wrapExprGen (gen) {
return function ($expr, settings) {
if (extra.verbatim && $expr.hasOwnProperty(extra.verbatim))
generateVerbatim($expr, settings);
else
gen($expr, settings);
}
}
function createExprGenWithExtras () {
var gens = {};
for (var key in ExprRawGen) {
if (ExprRawGen.hasOwnProperty(key))
gens[key] = wrapExprGen(ExprRawGen[key]);
}
return gens;
}
var _ = {
js: '',
newline: '\n',
optSpace: ' ',
space: ' ',
indentUnit: ' ',
indent: ''
};
var ExprGen = void 0,
StmtGen = StmtRawGen;
exports.generate = function ($node, options) {
var defaultOptions = getDefaultOptions(), result, pair;
if (options != null) {
if (typeof options.indent === 'string') {
defaultOptions.format.indent.style = options.indent;
}
if (typeof options.base === 'number') {
defaultOptions.format.indent.base = options.base;
}
options = updateDeeply(defaultOptions, options);
_.indentUnit = options.format.indent.style;
if (typeof options.base === 'string') {
_.indent = options.base;
}
else {
_.indent = stringRepeat(_.indentUnit, options.format.indent.base);
}
}
else {
options = defaultOptions;
_.indentUnit = options.format.indent.style;
_.indent = stringRepeat(_.indentUnit, options.format.indent.base);
}
json = options.format.json;
renumber = options.format.renumber;
hexadecimal = json ? false : options.format.hexadecimal;
quotes = json ? 'double' : options.format.quotes;
escapeless = options.format.escapeless;
_.newline = options.format.newline;
_.optSpace = options.format.space;
if (options.format.compact)
_.newline = _.optSpace = _.indentUnit = _.indent = '';
_.space = _.optSpace ? _.optSpace : ' ';
parentheses = options.format.parentheses;
semicolons = options.format.semicolons;
safeConcatenation = options.format.safeConcatenation;
directive = options.directive;
parse = json ? null : options.parse;
extra = options;
if (extra.verbatim)
ExprGen = createExprGenWithExtras();
else
ExprGen = ExprRawGen;
return run($node);
};