Path: blob/master/node_modules/@javascript-obfuscator/escodegen/escodegen.js
1126 views
/*1Copyright (C) 2012-2014 Yusuke Suzuki <[email protected]>2Copyright (C) 2015 Ingvar Stepanyan <[email protected]>3Copyright (C) 2014 Ivan Nikulin <[email protected]>4Copyright (C) 2012-2013 Michael Ficarra <[email protected]>5Copyright (C) 2012-2013 Mathias Bynens <[email protected]>6Copyright (C) 2013 Irakli Gozalishvili <[email protected]>7Copyright (C) 2012 Robert Gust-Bardon <[email protected]>8Copyright (C) 2012 John Freeman <[email protected]>9Copyright (C) 2011-2012 Ariya Hidayat <[email protected]>10Copyright (C) 2012 Joost-Wim Boekesteijn <[email protected]>11Copyright (C) 2012 Kris Kowal <[email protected]>12Copyright (C) 2012 Arpad Borsos <[email protected]>1314Redistribution and use in source and binary forms, with or without15modification, are permitted provided that the following conditions are met:1617* Redistributions of source code must retain the above copyright18notice, this list of conditions and the following disclaimer.19* Redistributions in binary form must reproduce the above copyright20notice, this list of conditions and the following disclaimer in the21documentation and/or other materials provided with the distribution.2223THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE26ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY27DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES28(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;29LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND30ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT31(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF32THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.33*/3435/*global exports:true, require:true, global:true*/36(function () {37'use strict';3839var Syntax,40Precedence,41BinaryPrecedence,42SourceNode,43estraverse,44esutils,45base,46indent,47json,48renumber,49hexadecimal,50quotes,51escapeless,52newline,53space,54parentheses,55semicolons,56safeConcatenation,57directive,58extra,59parse,60sourceMap,61sourceCode,62preserveBlankLines,63FORMAT_MINIFY,64FORMAT_DEFAULTS;6566estraverse = require('@javascript-obfuscator/estraverse');67esutils = require('esutils');6869Syntax = estraverse.Syntax;7071// Generation is done by generateExpression.72function isExpression(node) {73return CodeGenerator.Expression.hasOwnProperty(node.type);74}7576// Generation is done by generateStatement.77function isStatement(node) {78return CodeGenerator.Statement.hasOwnProperty(node.type);79}8081Precedence = {82Sequence: 0,83Yield: 1,84Assignment: 1,85Conditional: 2,86ArrowFunction: 2,87NullishCoalescing: 3,88LogicalOR: 3,89LogicalAND: 4,90BitwiseOR: 5,91BitwiseXOR: 6,92BitwiseAND: 7,93Equality: 8,94Relational: 9,95BitwiseSHIFT: 10,96Additive: 11,97Multiplicative: 12,98Exponentiation: 13,99Await: 14,100Unary: 14,101Postfix: 15,102OptionalChaining: 16,103Call: 17,104New: 18,105TaggedTemplate: 19,106Member: 20,107Primary: 21108};109110BinaryPrecedence = {111'??': Precedence.NullishCoalescing,112'||': Precedence.LogicalOR,113'&&': Precedence.LogicalAND,114'|': Precedence.BitwiseOR,115'^': Precedence.BitwiseXOR,116'&': Precedence.BitwiseAND,117'==': Precedence.Equality,118'!=': Precedence.Equality,119'===': Precedence.Equality,120'!==': Precedence.Equality,121'is': Precedence.Equality,122'isnt': Precedence.Equality,123'<': Precedence.Relational,124'>': Precedence.Relational,125'<=': Precedence.Relational,126'>=': Precedence.Relational,127'in': Precedence.Relational,128'instanceof': Precedence.Relational,129'<<': Precedence.BitwiseSHIFT,130'>>': Precedence.BitwiseSHIFT,131'>>>': Precedence.BitwiseSHIFT,132'+': Precedence.Additive,133'-': Precedence.Additive,134'*': Precedence.Multiplicative,135'%': Precedence.Multiplicative,136'/': Precedence.Multiplicative,137'**': Precedence.Exponentiation138};139140//Flags141var F_ALLOW_IN = 1,142F_ALLOW_CALL = 1 << 1,143F_ALLOW_UNPARATH_NEW = 1 << 2,144F_FUNC_BODY = 1 << 3,145F_DIRECTIVE_CTX = 1 << 4,146F_SEMICOLON_OPT = 1 << 5;147148//Expression flag sets149//NOTE: Flag order:150// F_ALLOW_IN151// F_ALLOW_CALL152// F_ALLOW_UNPARATH_NEW153var E_FTT = F_ALLOW_CALL | F_ALLOW_UNPARATH_NEW,154E_TTF = F_ALLOW_IN | F_ALLOW_CALL,155E_TTT = F_ALLOW_IN | F_ALLOW_CALL | F_ALLOW_UNPARATH_NEW,156E_TFF = F_ALLOW_IN,157E_FFT = F_ALLOW_UNPARATH_NEW,158E_TFT = F_ALLOW_IN | F_ALLOW_UNPARATH_NEW;159160//Statement flag sets161//NOTE: Flag order:162// F_ALLOW_IN163// F_FUNC_BODY164// F_DIRECTIVE_CTX165// F_SEMICOLON_OPT166var S_TFFF = F_ALLOW_IN,167S_TFFT = F_ALLOW_IN | F_SEMICOLON_OPT,168S_FFFF = 0x00,169S_TFTF = F_ALLOW_IN | F_DIRECTIVE_CTX,170S_TTFF = F_ALLOW_IN | F_FUNC_BODY;171172function getDefaultOptions() {173// default options174return {175indent: null,176base: null,177parse: null,178comment: false,179format: {180indent: {181style: ' ',182base: 0,183adjustMultilineComment: false184},185newline: '\n',186space: ' ',187json: false,188renumber: false,189hexadecimal: false,190quotes: 'single',191escapeless: false,192compact: false,193parentheses: true,194semicolons: true,195safeConcatenation: false,196preserveBlankLines: false197},198moz: {199comprehensionExpressionStartsWithAssignment: false,200starlessGenerator: false201},202sourceMap: null,203sourceMapRoot: null,204sourceMapWithCode: false,205directive: false,206raw: true,207verbatim: null,208sourceCode: null209};210}211212function stringRepeat(str, num) {213var result = '';214215for (num |= 0; num > 0; num >>>= 1, str += str) {216if (num & 1) {217result += str;218}219}220221return result;222}223224function hasLineTerminator(str) {225return (/[\r\n]/g).test(str);226}227228function endsWithLineTerminator(str) {229var len = str.length;230return len && esutils.code.isLineTerminator(str.charCodeAt(len - 1));231}232233function merge(target, override) {234var key;235for (key in override) {236if (override.hasOwnProperty(key)) {237target[key] = override[key];238}239}240return target;241}242243function updateDeeply(target, override) {244var key, val;245246function isHashObject(target) {247return typeof target === 'object' && target instanceof Object && !(target instanceof RegExp);248}249250for (key in override) {251if (override.hasOwnProperty(key)) {252val = override[key];253if (isHashObject(val)) {254if (isHashObject(target[key])) {255updateDeeply(target[key], val);256} else {257target[key] = updateDeeply({}, val);258}259} else {260target[key] = val;261}262}263}264return target;265}266267function generateNumber(value) {268var result, point, temp, exponent, pos;269270if (value !== value) {271throw new Error('Numeric literal whose value is NaN');272}273if (value < 0 || (value === 0 && 1 / value < 0)) {274throw new Error('Numeric literal whose value is negative');275}276277if (value === 1 / 0) {278return json ? 'null' : renumber ? '1e400' : '1e+400';279}280281result = '' + value;282if (!renumber || result.length < 3) {283return result;284}285286point = result.indexOf('.');287if (!json && result.charCodeAt(0) === 0x30 /* 0 */ && point === 1) {288point = 0;289result = result.slice(1);290}291temp = result;292result = result.replace('e+', 'e');293exponent = 0;294if ((pos = temp.indexOf('e')) > 0) {295exponent = +temp.slice(pos + 1);296temp = temp.slice(0, pos);297}298if (point >= 0) {299exponent -= temp.length - point - 1;300temp = +(temp.slice(0, point) + temp.slice(point + 1)) + '';301}302pos = 0;303while (temp.charCodeAt(temp.length + pos - 1) === 0x30 /* 0 */) {304--pos;305}306if (pos !== 0) {307exponent -= pos;308temp = temp.slice(0, pos);309}310if (exponent !== 0) {311temp += 'e' + exponent;312}313if ((temp.length < result.length ||314(hexadecimal && value > 1e12 && Math.floor(value) === value && (temp = '0x' + value.toString(16)).length < result.length)) &&315+temp === value) {316result = temp;317}318319return result;320}321322// Generate valid RegExp expression.323// This function is based on https://github.com/Constellation/iv Engine324325function escapeRegExpCharacter(ch, previousIsBackslash) {326// not handling '\' and handling \u2028 or \u2029 to unicode escape sequence327if ((ch & ~1) === 0x2028) {328return (previousIsBackslash ? 'u' : '\\u') + ((ch === 0x2028) ? '2028' : '2029');329} else if (ch === 10 || ch === 13) { // \n, \r330return (previousIsBackslash ? '' : '\\') + ((ch === 10) ? 'n' : 'r');331}332return String.fromCharCode(ch);333}334335function generateRegExp(reg) {336var match, result, flags, i, iz, ch, characterInBrack, previousIsBackslash;337338result = reg.toString();339340if (reg.source) {341// extract flag from toString result342match = result.match(/\/([^/]*)$/);343if (!match) {344return result;345}346347flags = match[1];348result = '';349350characterInBrack = false;351previousIsBackslash = false;352for (i = 0, iz = reg.source.length; i < iz; ++i) {353ch = reg.source.charCodeAt(i);354355if (!previousIsBackslash) {356if (characterInBrack) {357if (ch === 93) { // ]358characterInBrack = false;359}360} else {361if (ch === 47) { // /362result += '\\';363} else if (ch === 91) { // [364characterInBrack = true;365}366}367result += escapeRegExpCharacter(ch, previousIsBackslash);368previousIsBackslash = ch === 92; // \369} else {370// if new RegExp("\\\n') is provided, create /\n/371result += escapeRegExpCharacter(ch, previousIsBackslash);372// prevent like /\\[/]/373previousIsBackslash = false;374}375}376377return '/' + result + '/' + flags;378}379380return result;381}382383function escapeAllowedCharacter(code, next) {384var hex;385386if (code === 0x08 /* \b */) {387return '\\b';388}389390if (code === 0x0C /* \f */) {391return '\\f';392}393394if (code === 0x09 /* \t */) {395return '\\t';396}397398hex = code.toString(16).toUpperCase();399if (json || code > 0xFF) {400return '\\u' + '0000'.slice(hex.length) + hex;401} else if (code === 0x0000 && !esutils.code.isDecimalDigit(next)) {402return '\\0';403} else if (code === 0x000B /* \v */) { // '\v'404return '\\x0B';405} else {406return '\\x' + '00'.slice(hex.length) + hex;407}408}409410function escapeDisallowedCharacter(code) {411if (code === 0x5C /* \ */) {412return '\\\\';413}414415if (code === 0x0A /* \n */) {416return '\\n';417}418419if (code === 0x0D /* \r */) {420return '\\r';421}422423if (code === 0x2028) {424return '\\u2028';425}426427if (code === 0x2029) {428return '\\u2029';429}430431throw new Error('Incorrectly classified character');432}433434function escapeDirective(str) {435var i, iz, code, quote;436437quote = quotes === 'double' ? '"' : '\'';438for (i = 0, iz = str.length; i < iz; ++i) {439code = str.charCodeAt(i);440if (code === 0x27 /* ' */) {441quote = '"';442break;443} else if (code === 0x22 /* " */) {444quote = '\'';445break;446} else if (code === 0x5C /* \ */) {447++i;448}449}450451return quote + str + quote;452}453454function escapeString(str) {455var result = '', i, len, code, singleQuotes = 0, doubleQuotes = 0, single, quote;456457for (i = 0, len = str.length; i < len; ++i) {458code = str.charCodeAt(i);459if (code === 0x27 /* ' */) {460++singleQuotes;461} else if (code === 0x22 /* " */) {462++doubleQuotes;463} else if (code === 0x2F /* / */ && json) {464result += '\\';465} else if (esutils.code.isLineTerminator(code) || code === 0x5C /* \ */) {466result += escapeDisallowedCharacter(code);467continue;468} else if (!esutils.code.isIdentifierPartES5(code) && (json && code < 0x20 /* SP */ || !json && !escapeless && (code < 0x20 /* SP */ || code > 0x7E /* ~ */))) {469result += escapeAllowedCharacter(code, str.charCodeAt(i + 1));470continue;471}472result += String.fromCharCode(code);473}474475single = !(quotes === 'double' || (quotes === 'auto' && doubleQuotes < singleQuotes));476quote = single ? '\'' : '"';477478if (!(single ? singleQuotes : doubleQuotes)) {479return quote + result + quote;480}481482str = result;483result = quote;484485for (i = 0, len = str.length; i < len; ++i) {486code = str.charCodeAt(i);487if ((code === 0x27 /* ' */ && single) || (code === 0x22 /* " */ && !single)) {488result += '\\';489}490result += String.fromCharCode(code);491}492493return result + quote;494}495496/**497* flatten an array to a string, where the array can contain498* either strings or nested arrays499*/500function flattenToString(arr) {501var i, iz, elem, result = '';502for (i = 0, iz = arr.length; i < iz; ++i) {503elem = arr[i];504result += Array.isArray(elem) ? flattenToString(elem) : elem;505}506return result;507}508509/**510* convert generated to a SourceNode when source maps are enabled.511*/512function toSourceNodeWhenNeeded(generated, node) {513if (!sourceMap) {514// with no source maps, generated is either an515// array or a string. if an array, flatten it.516// if a string, just return it517if (Array.isArray(generated)) {518return flattenToString(generated);519} else {520return generated;521}522}523if (node == null) {524if (generated instanceof SourceNode) {525return generated;526} else {527node = {};528}529}530if (node.loc == null) {531return new SourceNode(null, null, sourceMap, generated, node.name || null);532}533return new SourceNode(node.loc.start.line, node.loc.start.column, (sourceMap === true ? node.loc.source || null : sourceMap), generated, node.name || null);534}535536function noEmptySpace() {537return (space) ? space : ' ';538}539540function join(left, right) {541var leftSource,542rightSource,543leftCharCode,544rightCharCode;545546leftSource = toSourceNodeWhenNeeded(left).toString();547if (leftSource.length === 0) {548return [right];549}550551rightSource = toSourceNodeWhenNeeded(right).toString();552if (rightSource.length === 0) {553return [left];554}555556leftCharCode = leftSource.charCodeAt(leftSource.length - 1);557rightCharCode = rightSource.charCodeAt(0);558559if ((leftCharCode === 0x2B /* + */ || leftCharCode === 0x2D /* - */) && leftCharCode === rightCharCode ||560esutils.code.isIdentifierPartES5(leftCharCode) && esutils.code.isIdentifierPartES5(rightCharCode) ||561leftCharCode === 0x2F /* / */ && rightCharCode === 0x69 /* i */) { // infix word operators all start with `i`562return [left, noEmptySpace(), right];563} else if (esutils.code.isWhiteSpace(leftCharCode) || esutils.code.isLineTerminator(leftCharCode) ||564esutils.code.isWhiteSpace(rightCharCode) || esutils.code.isLineTerminator(rightCharCode)) {565return [left, right];566}567return [left, space, right];568}569570function addIndent(stmt) {571return [base, stmt];572}573574function withIndent(fn) {575var previousBase;576previousBase = base;577base += indent;578fn(base);579base = previousBase;580}581582function calculateSpaces(str) {583var i;584for (i = str.length - 1; i >= 0; --i) {585if (esutils.code.isLineTerminator(str.charCodeAt(i))) {586break;587}588}589return (str.length - 1) - i;590}591592function adjustMultilineComment(value, specialBase) {593var array, i, len, line, j, spaces, previousBase, sn;594595array = value.split(/\r\n|[\r\n]/);596spaces = Number.MAX_VALUE;597598// first line doesn't have indentation599for (i = 1, len = array.length; i < len; ++i) {600line = array[i];601j = 0;602while (j < line.length && esutils.code.isWhiteSpace(line.charCodeAt(j))) {603++j;604}605if (spaces > j) {606spaces = j;607}608}609610if (typeof specialBase !== 'undefined') {611// pattern like612// {613// var t = 20; /*614// * this is comment615// */616// }617previousBase = base;618if (array[1][spaces] === '*') {619specialBase += ' ';620}621base = specialBase;622} else {623if (spaces & 1) {624// /*625// *626// */627// If spaces are odd number, above pattern is considered.628// We waste 1 space.629--spaces;630}631previousBase = base;632}633634for (i = 1, len = array.length; i < len; ++i) {635sn = toSourceNodeWhenNeeded(addIndent(array[i].slice(spaces)));636array[i] = sourceMap ? sn.join('') : sn;637}638639base = previousBase;640641return array.join('\n');642}643644function generateComment(comment, specialBase) {645if (comment.type === 'Line') {646if (endsWithLineTerminator(comment.value)) {647return '//' + comment.value;648} else {649// Always use LineTerminator650var result = '//' + comment.value;651if (!preserveBlankLines) {652result += '\n';653}654return result;655}656}657if (extra.format.indent.adjustMultilineComment && /[\n\r]/.test(comment.value)) {658return adjustMultilineComment('/*' + comment.value + '*/', specialBase);659}660return '/*' + comment.value + '*/';661}662663function addComments(stmt, result) {664var i, len, comment, save, tailingToStatement, specialBase, fragment,665extRange, range, prevRange, prefix, infix, suffix, count;666667if (stmt.leadingComments && stmt.leadingComments.length > 0) {668save = result;669670if (preserveBlankLines) {671comment = stmt.leadingComments[0];672result = [];673674extRange = comment.extendedRange;675range = comment.range;676677prefix = sourceCode.substring(extRange[0], range[0]);678count = (prefix.match(/\n/g) || []).length;679if (count > 0) {680result.push(stringRepeat('\n', count));681result.push(addIndent(generateComment(comment)));682} else {683result.push(prefix);684result.push(generateComment(comment));685}686687prevRange = range;688689for (i = 1, len = stmt.leadingComments.length; i < len; i++) {690comment = stmt.leadingComments[i];691range = comment.range;692693infix = sourceCode.substring(prevRange[1], range[0]);694count = (infix.match(/\n/g) || []).length;695result.push(stringRepeat('\n', count));696result.push(addIndent(generateComment(comment)));697698prevRange = range;699}700701suffix = sourceCode.substring(range[1], extRange[1]);702count = (suffix.match(/\n/g) || []).length;703result.push(stringRepeat('\n', count));704} else {705comment = stmt.leadingComments[0];706result = [];707if (safeConcatenation && stmt.type === Syntax.Program && stmt.body.length === 0) {708result.push('\n');709}710result.push(generateComment(comment));711if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {712result.push('\n');713}714715for (i = 1, len = stmt.leadingComments.length; i < len; ++i) {716comment = stmt.leadingComments[i];717fragment = [generateComment(comment)];718if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {719fragment.push('\n');720}721result.push(addIndent(fragment));722}723}724725result.push(addIndent(save));726}727728if (stmt.trailingComments) {729730if (preserveBlankLines) {731comment = stmt.trailingComments[0];732extRange = comment.extendedRange;733range = comment.range;734735prefix = sourceCode.substring(extRange[0], range[0]);736count = (prefix.match(/\n/g) || []).length;737738if (count > 0) {739result.push(stringRepeat('\n', count));740result.push(addIndent(generateComment(comment)));741} else {742result.push(prefix);743result.push(generateComment(comment));744}745} else {746tailingToStatement = !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString());747specialBase = stringRepeat(' ', calculateSpaces(toSourceNodeWhenNeeded([base, result, indent]).toString()));748for (i = 0, len = stmt.trailingComments.length; i < len; ++i) {749comment = stmt.trailingComments[i];750if (tailingToStatement) {751// We assume target like following script752//753// var t = 20; /**754// * This is comment of t755// */756if (i === 0) {757// first case758result = [result, indent];759} else {760result = [result, specialBase];761}762result.push(generateComment(comment, specialBase));763} else {764result = [result, addIndent(generateComment(comment))];765}766if (i !== len - 1 && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {767result = [result, '\n'];768}769}770}771}772773return result;774}775776function generateBlankLines(start, end, result) {777var j, newlineCount = 0;778779for (j = start; j < end; j++) {780if (sourceCode[j] === '\n') {781newlineCount++;782}783}784785for (j = 1; j < newlineCount; j++) {786result.push(newline);787}788}789790function parenthesize(text, current, should) {791if (current < should) {792return ['(', text, ')'];793}794return text;795}796797function generateVerbatimString(string) {798var i, iz, result;799result = string.split(/\r\n|\n/);800for (i = 1, iz = result.length; i < iz; i++) {801result[i] = newline + base + result[i];802}803return result;804}805806function generateVerbatim(expr, precedence) {807var verbatim, result, prec;808verbatim = expr[extra.verbatim];809810if (typeof verbatim === 'string') {811result = parenthesize(generateVerbatimString(verbatim), Precedence.Sequence, precedence);812} else {813// verbatim is object814result = generateVerbatimString(verbatim.content);815prec = (verbatim.precedence != null) ? verbatim.precedence : Precedence.Sequence;816result = parenthesize(result, prec, precedence);817}818819return toSourceNodeWhenNeeded(result, expr);820}821822function CodeGenerator() {823}824825// Helpers.826827CodeGenerator.prototype.maybeBlock = function(stmt, flags) {828var result, noLeadingComment, that = this;829830noLeadingComment = !extra.comment || !stmt.leadingComments;831832if (stmt.type === Syntax.BlockStatement && noLeadingComment) {833return [space, this.generateStatement(stmt, flags)];834}835836if (stmt.type === Syntax.EmptyStatement && noLeadingComment) {837return ';';838}839840withIndent(function () {841result = [842newline,843addIndent(that.generateStatement(stmt, flags))844];845});846847return result;848};849850CodeGenerator.prototype.maybeBlockSuffix = function (stmt, result) {851var ends = endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString());852if (stmt.type === Syntax.BlockStatement && (!extra.comment || !stmt.leadingComments) && !ends) {853return [result, space];854}855if (ends) {856return [result, base];857}858return [result, newline, base];859};860861function generateIdentifier(node) {862var identifierName = node.name;863864if (node.type === Syntax.PrivateIdentifier) {865identifierName = '#' + identifierName;866}867868return toSourceNodeWhenNeeded(identifierName, node);869}870871function generateAsyncPrefix(node, spaceRequired) {872return node.async ? 'async' + (spaceRequired ? noEmptySpace() : space) : '';873}874875function generateStarSuffix(node) {876var isGenerator = node.generator && !extra.moz.starlessGenerator;877return isGenerator ? '*' + space : '';878}879880function generateMethodPrefix(prop) {881var func = prop.value, prefix = '';882if (func.async) {883prefix += generateAsyncPrefix(func, !prop.computed);884}885if (func.generator) {886// avoid space before method name887prefix += generateStarSuffix(func) ? '*' : '';888}889return prefix;890}891892CodeGenerator.prototype.generatePattern = function (node, precedence, flags) {893if (node.type === Syntax.Identifier) {894return generateIdentifier(node);895}896return this.generateExpression(node, precedence, flags);897};898899CodeGenerator.prototype.generateFunctionParams = function (node) {900var i, iz, result, hasDefault;901902hasDefault = false;903904if (node.type === Syntax.ArrowFunctionExpression &&905!node.rest && (!node.defaults || node.defaults.length === 0) &&906node.params.length === 1 && node.params[0].type === Syntax.Identifier) {907// arg => { } case908result = [generateAsyncPrefix(node, true), generateIdentifier(node.params[0])];909} else {910result = node.type === Syntax.ArrowFunctionExpression ? [generateAsyncPrefix(node, false)] : [];911result.push('(');912if (node.defaults) {913hasDefault = true;914}915for (i = 0, iz = node.params.length; i < iz; ++i) {916if (hasDefault && node.defaults[i]) {917// Handle default values.918result.push(this.generateAssignment(node.params[i], node.defaults[i], '=', Precedence.Assignment, E_TTT));919} else {920result.push(this.generatePattern(node.params[i], Precedence.Assignment, E_TTT));921}922if (i + 1 < iz) {923result.push(',' + space);924}925}926927if (node.rest) {928if (node.params.length) {929result.push(',' + space);930}931result.push('...');932result.push(generateIdentifier(node.rest));933}934935result.push(')');936}937938return result;939};940941CodeGenerator.prototype.generateFunctionBody = function (node) {942var result, expr;943944result = this.generateFunctionParams(node);945946if (node.type === Syntax.ArrowFunctionExpression) {947result.push(space);948result.push('=>');949}950951if (node.expression) {952result.push(space);953expr = this.generateExpression(node.body, Precedence.Assignment, E_TTT);954if (expr.toString().charAt(0) === '{') {955expr = ['(', expr, ')'];956}957result.push(expr);958} else {959result.push(this.maybeBlock(node.body, S_TTFF));960}961962return result;963};964965CodeGenerator.prototype.generateIterationForStatement = function (operator, stmt, flags) {966var result = ['for' + (stmt.await ? noEmptySpace() + 'await' : '') + space + '('], that = this;967withIndent(function () {968if (stmt.left.type === Syntax.VariableDeclaration) {969withIndent(function () {970result.push(stmt.left.kind + noEmptySpace());971result.push(that.generateStatement(stmt.left.declarations[0], S_FFFF));972});973} else {974result.push(that.generateExpression(stmt.left, Precedence.Call, E_TTT));975}976977result = join(result, operator);978result = [join(979result,980that.generateExpression(stmt.right, Precedence.Assignment, E_TTT)981), ')'];982});983result.push(this.maybeBlock(stmt.body, flags));984return result;985};986987CodeGenerator.prototype.generatePropertyKey = function (expr, computed) {988var result = [];989990if (computed) {991result.push('[');992}993994result.push(this.generateExpression(expr, Precedence.Assignment, E_TTT));995996if (computed) {997result.push(']');998}9991000return result;1001};10021003CodeGenerator.prototype.generateAssignment = function (left, right, operator, precedence, flags) {1004if (Precedence.Assignment < precedence) {1005flags |= F_ALLOW_IN;1006}10071008return parenthesize(1009[1010this.generateExpression(left, Precedence.Call, flags),1011space + operator + space,1012this.generateExpression(right, Precedence.Assignment, flags)1013],1014Precedence.Assignment,1015precedence1016);1017};10181019CodeGenerator.prototype.semicolon = function (flags) {1020if (!semicolons && flags & F_SEMICOLON_OPT) {1021return '';1022}1023return ';';1024};10251026// Statements.10271028CodeGenerator.Statement = {10291030BlockStatement: function (stmt, flags) {1031var range, content, result = ['{', newline], that = this;10321033withIndent(function () {1034// handle functions without any code1035if (stmt.body.length === 0 && preserveBlankLines) {1036range = stmt.range;1037if (range[1] - range[0] > 2) {1038content = sourceCode.substring(range[0] + 1, range[1] - 1);1039if (content[0] === '\n') {1040result = ['{'];1041}1042result.push(content);1043}1044}10451046var i, iz, fragment, bodyFlags;1047bodyFlags = S_TFFF;1048if (flags & F_FUNC_BODY) {1049bodyFlags |= F_DIRECTIVE_CTX;1050}10511052for (i = 0, iz = stmt.body.length; i < iz; ++i) {1053if (preserveBlankLines) {1054// handle spaces before the first line1055if (i === 0) {1056if (stmt.body[0].leadingComments) {1057range = stmt.body[0].leadingComments[0].extendedRange;1058content = sourceCode.substring(range[0], range[1]);1059if (content[0] === '\n') {1060result = ['{'];1061}1062}1063if (!stmt.body[0].leadingComments) {1064generateBlankLines(stmt.range[0], stmt.body[0].range[0], result);1065}1066}10671068// handle spaces between lines1069if (i > 0) {1070if (!stmt.body[i - 1].trailingComments && !stmt.body[i].leadingComments) {1071generateBlankLines(stmt.body[i - 1].range[1], stmt.body[i].range[0], result);1072}1073}1074}10751076if (i === iz - 1) {1077bodyFlags |= F_SEMICOLON_OPT;1078}10791080if (stmt.body[i].leadingComments && preserveBlankLines) {1081fragment = that.generateStatement(stmt.body[i], bodyFlags);1082} else {1083fragment = addIndent(that.generateStatement(stmt.body[i], bodyFlags));1084}10851086result.push(fragment);1087if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {1088if (preserveBlankLines && i < iz - 1) {1089// don't add a new line if there are leading coments1090// in the next statement1091if (!stmt.body[i + 1].leadingComments) {1092result.push(newline);1093}1094} else {1095result.push(newline);1096}1097}10981099if (preserveBlankLines) {1100// handle spaces after the last line1101if (i === iz - 1) {1102if (!stmt.body[i].trailingComments) {1103generateBlankLines(stmt.body[i].range[1], stmt.range[1], result);1104}1105}1106}1107}1108});11091110result.push(addIndent('}'));1111return result;1112},11131114BreakStatement: function (stmt, flags) {1115if (stmt.label) {1116return 'break ' + stmt.label.name + this.semicolon(flags);1117}1118return 'break' + this.semicolon(flags);1119},11201121ContinueStatement: function (stmt, flags) {1122if (stmt.label) {1123return 'continue ' + stmt.label.name + this.semicolon(flags);1124}1125return 'continue' + this.semicolon(flags);1126},11271128ClassBody: function (stmt, flags) {1129var result = [ '{', newline], that = this;11301131withIndent(function (indent) {1132var i, iz;11331134for (i = 0, iz = stmt.body.length; i < iz; ++i) {1135result.push(indent);1136result.push(that.generateExpression(stmt.body[i], Precedence.Sequence, E_TTT));1137if (i + 1 < iz) {1138result.push(newline);1139}1140}1141});11421143if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {1144result.push(newline);1145}1146result.push(base);1147result.push('}');1148return result;1149},11501151ClassDeclaration: function (stmt, flags) {1152var result, fragment;1153result = ['class'];1154if (stmt.id) {1155result = join(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));1156}1157if (stmt.superClass) {1158fragment = join('extends', this.generateExpression(stmt.superClass, Precedence.Unary, E_TTT));1159result = join(result, fragment);1160}1161result.push(space);1162result.push(this.generateStatement(stmt.body, S_TFFT));1163return result;1164},11651166DirectiveStatement: function (stmt, flags) {1167if (extra.raw && stmt.raw) {1168return stmt.raw + this.semicolon(flags);1169}1170return escapeDirective(stmt.directive) + this.semicolon(flags);1171},11721173DoWhileStatement: function (stmt, flags) {1174// Because `do 42 while (cond)` is Syntax Error. We need semicolon.1175var result = join('do', this.maybeBlock(stmt.body, S_TFFF));1176result = this.maybeBlockSuffix(stmt.body, result);1177return join(result, [1178'while' + space + '(',1179this.generateExpression(stmt.test, Precedence.Sequence, E_TTT),1180')' + this.semicolon(flags)1181]);1182},11831184CatchClause: function (stmt, flags) {1185var result, that = this;1186withIndent(function () {1187var guard;11881189if (stmt.param) {1190result = [1191'catch' + space + '(',1192that.generateExpression(stmt.param, Precedence.Sequence, E_TTT),1193')'1194];11951196if (stmt.guard) {1197guard = that.generateExpression(stmt.guard, Precedence.Sequence, E_TTT);1198result.splice(2, 0, ' if ', guard);1199}1200} else {1201result = ['catch'];1202}1203});1204result.push(this.maybeBlock(stmt.body, S_TFFF));1205return result;1206},12071208DebuggerStatement: function (stmt, flags) {1209return 'debugger' + this.semicolon(flags);1210},12111212EmptyStatement: function (stmt, flags) {1213return ';';1214},12151216ExportDefaultDeclaration: function (stmt, flags) {1217var result = [ 'export' ], bodyFlags;12181219bodyFlags = (flags & F_SEMICOLON_OPT) ? S_TFFT : S_TFFF;12201221// export default HoistableDeclaration[Default]1222// export default AssignmentExpression[In] ;1223result = join(result, 'default');1224if (isStatement(stmt.declaration)) {1225result = join(result, this.generateStatement(stmt.declaration, bodyFlags));1226} else {1227result = join(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));1228}1229return result;1230},12311232ExportNamedDeclaration: function (stmt, flags) {1233var result = [ 'export' ], bodyFlags, that = this;12341235bodyFlags = (flags & F_SEMICOLON_OPT) ? S_TFFT : S_TFFF;12361237// export VariableStatement1238// export Declaration[Default]1239if (stmt.declaration) {1240return join(result, this.generateStatement(stmt.declaration, bodyFlags));1241}12421243// export ExportClause[NoReference] FromClause ;1244// export ExportClause ;1245if (stmt.specifiers) {1246if (stmt.specifiers.length === 0) {1247result = join(result, '{' + space + '}');1248} else if (stmt.specifiers[0].type === Syntax.ExportBatchSpecifier) {1249result = join(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));1250} else {1251result = join(result, '{');1252withIndent(function (indent) {1253var i, iz;1254result.push(newline);1255for (i = 0, iz = stmt.specifiers.length; i < iz; ++i) {1256result.push(indent);1257result.push(that.generateExpression(stmt.specifiers[i], Precedence.Sequence, E_TTT));1258if (i + 1 < iz) {1259result.push(',' + newline);1260}1261}1262});1263if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {1264result.push(newline);1265}1266result.push(base + '}');1267}12681269if (stmt.source) {1270result = join(result, [1271'from' + space,1272// ModuleSpecifier1273this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),1274this.semicolon(flags)1275]);1276} else {1277result.push(this.semicolon(flags));1278}1279}1280return result;1281},12821283ExportAllDeclaration: function (stmt, flags) {1284// export * FromClause ;1285var result = [1286'export' + space,1287'*' + space1288];12891290if (stmt.exported) {1291result.push('as ' + stmt.exported.name + ' ');1292}12931294result = join(result, [1295'from' + space,1296// ModuleSpecifier1297this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),1298this.semicolon(flags)1299]);13001301return result;1302},13031304ExpressionStatement: function (stmt, flags) {1305var result, fragment;13061307function isClassPrefixed(fragment) {1308var code;1309if (fragment.slice(0, 5) !== 'class') {1310return false;1311}1312code = fragment.charCodeAt(5);1313return code === 0x7B /* '{' */ || esutils.code.isWhiteSpace(code) || esutils.code.isLineTerminator(code);1314}13151316function isFunctionPrefixed(fragment) {1317var code;1318if (fragment.slice(0, 8) !== 'function') {1319return false;1320}1321code = fragment.charCodeAt(8);1322return code === 0x28 /* '(' */ || esutils.code.isWhiteSpace(code) || code === 0x2A /* '*' */ || esutils.code.isLineTerminator(code);1323}13241325function isAsyncPrefixed(fragment) {1326var code, i, iz;1327if (fragment.slice(0, 5) !== 'async') {1328return false;1329}1330if (!esutils.code.isWhiteSpace(fragment.charCodeAt(5))) {1331return false;1332}1333for (i = 6, iz = fragment.length; i < iz; ++i) {1334if (!esutils.code.isWhiteSpace(fragment.charCodeAt(i))) {1335break;1336}1337}1338if (i === iz) {1339return false;1340}1341if (fragment.slice(i, i + 8) !== 'function') {1342return false;1343}1344code = fragment.charCodeAt(i + 8);1345return code === 0x28 /* '(' */ || esutils.code.isWhiteSpace(code) || code === 0x2A /* '*' */ || esutils.code.isLineTerminator(code);1346}13471348result = [this.generateExpression(stmt.expression, Precedence.Sequence, E_TTT)];1349// 12.4 '{', 'function', 'class' is not allowed in this position.1350// wrap expression with parentheses1351fragment = toSourceNodeWhenNeeded(result).toString();1352if (fragment.charCodeAt(0) === 0x7B /* '{' */ || // ObjectExpression1353isClassPrefixed(fragment) ||1354isFunctionPrefixed(fragment) ||1355isAsyncPrefixed(fragment) ||1356(directive && (flags & F_DIRECTIVE_CTX) && stmt.expression.type === Syntax.Literal && typeof stmt.expression.value === 'string')) {1357result = ['(', result, ')' + this.semicolon(flags)];1358} else {1359result.push(this.semicolon(flags));1360}1361return result;1362},13631364ImportDeclaration: function (stmt, flags) {1365// ES6: 15.2.1 valid import declarations:1366// - import ImportClause FromClause ;1367// - import ModuleSpecifier ;1368var result, cursor, that = this;13691370// If no ImportClause is present,1371// this should be `import ModuleSpecifier` so skip `from`1372// ModuleSpecifier is StringLiteral.1373if (stmt.specifiers.length === 0) {1374// import ModuleSpecifier ;1375return [1376'import',1377space,1378// ModuleSpecifier1379this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),1380this.semicolon(flags)1381];1382}13831384// import ImportClause FromClause ;1385result = [1386'import'1387];1388cursor = 0;13891390// ImportedBinding1391if (stmt.specifiers[cursor].type === Syntax.ImportDefaultSpecifier) {1392result = join(result, [1393this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)1394]);1395++cursor;1396}13971398if (stmt.specifiers[cursor]) {1399if (cursor !== 0) {1400result.push(',');1401}14021403if (stmt.specifiers[cursor].type === Syntax.ImportNamespaceSpecifier) {1404// NameSpaceImport1405result = join(result, [1406space,1407this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)1408]);1409} else {1410// NamedImports1411result.push(space + '{');14121413if ((stmt.specifiers.length - cursor) === 1) {1414// import { ... } from "...";1415result.push(space);1416result.push(this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT));1417result.push(space + '}' + space);1418} else {1419// import {1420// ...,1421// ...,1422// } from "...";1423withIndent(function (indent) {1424var i, iz;1425result.push(newline);1426for (i = cursor, iz = stmt.specifiers.length; i < iz; ++i) {1427result.push(indent);1428result.push(that.generateExpression(stmt.specifiers[i], Precedence.Sequence, E_TTT));1429if (i + 1 < iz) {1430result.push(',' + newline);1431}1432}1433});1434if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {1435result.push(newline);1436}1437result.push(base + '}' + space);1438}1439}1440}14411442result = join(result, [1443'from' + space,1444// ModuleSpecifier1445this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),1446this.semicolon(flags)1447]);1448return result;1449},14501451VariableDeclarator: function (stmt, flags) {1452var itemFlags = (flags & F_ALLOW_IN) ? E_TTT : E_FTT;1453if (stmt.init) {1454return [1455this.generateExpression(stmt.id, Precedence.Assignment, itemFlags),1456space,1457'=',1458space,1459this.generateExpression(stmt.init, Precedence.Assignment, itemFlags)1460];1461}1462return this.generatePattern(stmt.id, Precedence.Assignment, itemFlags);1463},14641465VariableDeclaration: function (stmt, flags) {1466// VariableDeclarator is typed as Statement,1467// but joined with comma (not LineTerminator).1468// So if comment is attached to target node, we should specialize.1469var result, i, iz, node, bodyFlags, that = this;14701471result = [ stmt.kind ];14721473bodyFlags = (flags & F_ALLOW_IN) ? S_TFFF : S_FFFF;14741475function block() {1476node = stmt.declarations[0];1477if (extra.comment && node.leadingComments) {1478result.push('\n');1479result.push(addIndent(that.generateStatement(node, bodyFlags)));1480} else {1481result.push(noEmptySpace());1482result.push(that.generateStatement(node, bodyFlags));1483}14841485for (i = 1, iz = stmt.declarations.length; i < iz; ++i) {1486node = stmt.declarations[i];1487if (extra.comment && node.leadingComments) {1488result.push(',' + newline);1489result.push(addIndent(that.generateStatement(node, bodyFlags)));1490} else {1491result.push(',' + space);1492result.push(that.generateStatement(node, bodyFlags));1493}1494}1495}14961497if (stmt.declarations.length > 1) {1498withIndent(block);1499} else {1500block();1501}15021503result.push(this.semicolon(flags));15041505return result;1506},15071508StaticBlock: function (stmt, flags) {1509return [1510'static' + space,1511this.BlockStatement(stmt, flags)1512];1513},15141515ThrowStatement: function (stmt, flags) {1516return [join(1517'throw',1518this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)1519), this.semicolon(flags)];1520},15211522TryStatement: function (stmt, flags) {1523var result, i, iz, guardedHandlers;15241525result = ['try', this.maybeBlock(stmt.block, S_TFFF)];1526result = this.maybeBlockSuffix(stmt.block, result);15271528if (stmt.handlers) {1529// old interface1530for (i = 0, iz = stmt.handlers.length; i < iz; ++i) {1531result = join(result, this.generateStatement(stmt.handlers[i], S_TFFF));1532if (stmt.finalizer || i + 1 !== iz) {1533result = this.maybeBlockSuffix(stmt.handlers[i].body, result);1534}1535}1536} else {1537guardedHandlers = stmt.guardedHandlers || [];15381539for (i = 0, iz = guardedHandlers.length; i < iz; ++i) {1540result = join(result, this.generateStatement(guardedHandlers[i], S_TFFF));1541if (stmt.finalizer || i + 1 !== iz) {1542result = this.maybeBlockSuffix(guardedHandlers[i].body, result);1543}1544}15451546// new interface1547if (stmt.handler) {1548if (Array.isArray(stmt.handler)) {1549for (i = 0, iz = stmt.handler.length; i < iz; ++i) {1550result = join(result, this.generateStatement(stmt.handler[i], S_TFFF));1551if (stmt.finalizer || i + 1 !== iz) {1552result = this.maybeBlockSuffix(stmt.handler[i].body, result);1553}1554}1555} else {1556result = join(result, this.generateStatement(stmt.handler, S_TFFF));1557if (stmt.finalizer) {1558result = this.maybeBlockSuffix(stmt.handler.body, result);1559}1560}1561}1562}1563if (stmt.finalizer) {1564result = join(result, ['finally', this.maybeBlock(stmt.finalizer, S_TFFF)]);1565}1566return result;1567},15681569SwitchStatement: function (stmt, flags) {1570var result, fragment, i, iz, bodyFlags, that = this;1571withIndent(function () {1572result = [1573'switch' + space + '(',1574that.generateExpression(stmt.discriminant, Precedence.Sequence, E_TTT),1575')' + space + '{' + newline1576];1577});1578if (stmt.cases) {1579bodyFlags = S_TFFF;1580for (i = 0, iz = stmt.cases.length; i < iz; ++i) {1581if (i === iz - 1) {1582bodyFlags |= F_SEMICOLON_OPT;1583}1584fragment = addIndent(this.generateStatement(stmt.cases[i], bodyFlags));1585result.push(fragment);1586if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {1587result.push(newline);1588}1589}1590}1591result.push(addIndent('}'));1592return result;1593},15941595SwitchCase: function (stmt, flags) {1596var result, fragment, i, iz, bodyFlags, that = this;1597withIndent(function () {1598if (stmt.test) {1599result = [1600join('case', that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),1601':'1602];1603} else {1604result = ['default:'];1605}16061607i = 0;1608iz = stmt.consequent.length;1609if (iz && stmt.consequent[0].type === Syntax.BlockStatement) {1610fragment = that.maybeBlock(stmt.consequent[0], S_TFFF);1611result.push(fragment);1612i = 1;1613}16141615if (i !== iz && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {1616result.push(newline);1617}16181619bodyFlags = S_TFFF;1620for (; i < iz; ++i) {1621if (i === iz - 1 && flags & F_SEMICOLON_OPT) {1622bodyFlags |= F_SEMICOLON_OPT;1623}1624fragment = addIndent(that.generateStatement(stmt.consequent[i], bodyFlags));1625result.push(fragment);1626if (i + 1 !== iz && !endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {1627result.push(newline);1628}1629}1630});1631return result;1632},16331634IfStatement: function (stmt, flags) {1635var result, bodyFlags, semicolonOptional, that = this;1636withIndent(function () {1637result = [1638'if' + space + '(',1639that.generateExpression(stmt.test, Precedence.Sequence, E_TTT),1640')'1641];1642});1643semicolonOptional = flags & F_SEMICOLON_OPT;1644bodyFlags = S_TFFF;1645if (semicolonOptional) {1646bodyFlags |= F_SEMICOLON_OPT;1647}1648if (stmt.alternate) {1649result.push(this.maybeBlock(stmt.consequent, S_TFFF));1650result = this.maybeBlockSuffix(stmt.consequent, result);1651if (stmt.alternate.type === Syntax.IfStatement) {1652result = join(result, ['else ', this.generateStatement(stmt.alternate, bodyFlags)]);1653} else {1654result = join(result, join('else', this.maybeBlock(stmt.alternate, bodyFlags)));1655}1656} else {1657result.push(this.maybeBlock(stmt.consequent, bodyFlags));1658}1659return result;1660},16611662ForStatement: function (stmt, flags) {1663var result, that = this;1664withIndent(function () {1665result = ['for' + space + '('];1666if (stmt.init) {1667if (stmt.init.type === Syntax.VariableDeclaration) {1668result.push(that.generateStatement(stmt.init, S_FFFF));1669} else {1670// F_ALLOW_IN becomes false.1671result.push(that.generateExpression(stmt.init, Precedence.Sequence, E_FTT));1672result.push(';');1673}1674} else {1675result.push(';');1676}16771678if (stmt.test) {1679result.push(space);1680result.push(that.generateExpression(stmt.test, Precedence.Sequence, E_TTT));1681result.push(';');1682} else {1683result.push(';');1684}16851686if (stmt.update) {1687result.push(space);1688result.push(that.generateExpression(stmt.update, Precedence.Sequence, E_TTT));1689result.push(')');1690} else {1691result.push(')');1692}1693});16941695result.push(this.maybeBlock(stmt.body, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF));1696return result;1697},16981699ForInStatement: function (stmt, flags) {1700return this.generateIterationForStatement('in', stmt, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF);1701},17021703ForOfStatement: function (stmt, flags) {1704return this.generateIterationForStatement('of', stmt, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF);1705},17061707LabeledStatement: function (stmt, flags) {1708return [stmt.label.name + ':', this.maybeBlock(stmt.body, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF)];1709},17101711Program: function (stmt, flags) {1712var result, fragment, i, iz, bodyFlags;1713iz = stmt.body.length;1714result = [safeConcatenation && iz > 0 ? '\n' : ''];1715bodyFlags = S_TFTF;1716for (i = 0; i < iz; ++i) {1717if (!safeConcatenation && i === iz - 1) {1718bodyFlags |= F_SEMICOLON_OPT;1719}17201721if (preserveBlankLines) {1722// handle spaces before the first line1723if (i === 0) {1724if (!stmt.body[0].leadingComments) {1725generateBlankLines(stmt.range[0], stmt.body[i].range[0], result);1726}1727}17281729// handle spaces between lines1730if (i > 0) {1731if (!stmt.body[i - 1].trailingComments && !stmt.body[i].leadingComments) {1732generateBlankLines(stmt.body[i - 1].range[1], stmt.body[i].range[0], result);1733}1734}1735}17361737fragment = addIndent(this.generateStatement(stmt.body[i], bodyFlags));1738result.push(fragment);1739if (i + 1 < iz && !endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {1740if (preserveBlankLines) {1741if (!stmt.body[i + 1].leadingComments) {1742result.push(newline);1743}1744} else {1745result.push(newline);1746}1747}17481749if (preserveBlankLines) {1750// handle spaces after the last line1751if (i === iz - 1) {1752if (!stmt.body[i].trailingComments) {1753generateBlankLines(stmt.body[i].range[1], stmt.range[1], result);1754}1755}1756}1757}1758return result;1759},17601761FunctionDeclaration: function (stmt, flags) {1762return [1763generateAsyncPrefix(stmt, true),1764'function',1765generateStarSuffix(stmt) || noEmptySpace(),1766stmt.id ? generateIdentifier(stmt.id) : '',1767this.generateFunctionBody(stmt)1768];1769},17701771ReturnStatement: function (stmt, flags) {1772if (stmt.argument) {1773return [join(1774'return',1775this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)1776), this.semicolon(flags)];1777}1778return ['return' + this.semicolon(flags)];1779},17801781WhileStatement: function (stmt, flags) {1782var result, that = this;1783withIndent(function () {1784result = [1785'while' + space + '(',1786that.generateExpression(stmt.test, Precedence.Sequence, E_TTT),1787')'1788];1789});1790result.push(this.maybeBlock(stmt.body, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF));1791return result;1792},17931794WithStatement: function (stmt, flags) {1795var result, that = this;1796withIndent(function () {1797result = [1798'with' + space + '(',1799that.generateExpression(stmt.object, Precedence.Sequence, E_TTT),1800')'1801];1802});1803result.push(this.maybeBlock(stmt.body, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF));1804return result;1805}18061807};18081809merge(CodeGenerator.prototype, CodeGenerator.Statement);18101811// Expressions.18121813CodeGenerator.Expression = {18141815SequenceExpression: function (expr, precedence, flags) {1816var result, i, iz;1817if (Precedence.Sequence < precedence) {1818flags |= F_ALLOW_IN;1819}1820result = [];1821for (i = 0, iz = expr.expressions.length; i < iz; ++i) {1822result.push(this.generateExpression(expr.expressions[i], Precedence.Assignment, flags));1823if (i + 1 < iz) {1824result.push(',' + space);1825}1826}1827return parenthesize(result, Precedence.Sequence, precedence);1828},18291830AssignmentExpression: function (expr, precedence, flags) {1831return this.generateAssignment(expr.left, expr.right, expr.operator, precedence, flags);1832},18331834ArrowFunctionExpression: function (expr, precedence, flags) {1835return parenthesize(this.generateFunctionBody(expr), Precedence.ArrowFunction, precedence);1836},18371838ConditionalExpression: function (expr, precedence, flags) {1839if (Precedence.Conditional < precedence) {1840flags |= F_ALLOW_IN;1841}1842return parenthesize(1843[1844this.generateExpression(expr.test, Precedence.LogicalOR, flags),1845space + '?' + space,1846this.generateExpression(expr.consequent, Precedence.Assignment, flags),1847space + ':' + space,1848this.generateExpression(expr.alternate, Precedence.Assignment, flags)1849],1850Precedence.Conditional,1851precedence1852);1853},18541855LogicalExpression: function (expr, precedence, flags) {1856return this.BinaryExpression(expr, precedence, flags);1857},18581859BinaryExpression: function (expr, precedence, flags) {1860var result, leftPrecedence, rightPrecedence, currentPrecedence, fragment, leftSource;1861currentPrecedence = BinaryPrecedence[expr.operator];18621863leftPrecedence = currentPrecedence;1864rightPrecedence = currentPrecedence + 1;18651866switch (expr.operator) {1867case '**':1868leftPrecedence = Precedence.Postfix;1869rightPrecedence = currentPrecedence;1870break;18711872case '??':1873if (expr.left.type === Syntax.LogicalExpression && (expr.left.operator === '||' || expr.left.operator === '&&')) {1874leftPrecedence = BinaryPrecedence[expr.left.operator] + 1;1875}18761877if (expr.right.type === Syntax.LogicalExpression && expr.right.operator === '&&') {1878rightPrecedence = BinaryPrecedence[expr.right.operator] + 1;1879}18801881break;18821883case '||':1884if (expr.left.type === Syntax.LogicalExpression && expr.left.operator === '??') {1885leftPrecedence = BinaryPrecedence[expr.left.operator] + 1;1886}18871888break;1889}18901891if (currentPrecedence < precedence) {1892flags |= F_ALLOW_IN;1893}18941895fragment = this.generateExpression(expr.left, leftPrecedence, flags);18961897leftSource = fragment.toString();18981899if (leftSource.charCodeAt(leftSource.length - 1) === 0x2F /* / */ && esutils.code.isIdentifierPartES5(expr.operator.charCodeAt(0))) {1900result = [fragment, noEmptySpace(), expr.operator];1901} else {1902result = join(fragment, expr.operator);1903}19041905fragment = this.generateExpression(expr.right, rightPrecedence, flags);19061907if (expr.operator === '/' && fragment.toString().charAt(0) === '/' ||1908expr.operator.slice(-1) === '<' && fragment.toString().slice(0, 3) === '!--') {1909// If '/' concats with '/' or `<` concats with `!--`, it is interpreted as comment start1910result.push(noEmptySpace());1911result.push(fragment);1912} else {1913result = join(result, fragment);1914}19151916if (expr.operator === 'in' && !(flags & F_ALLOW_IN)) {1917return ['(', result, ')'];1918}1919return parenthesize(result, currentPrecedence, precedence);1920},19211922CallExpression: function (expr, precedence, flags) {1923var result, i, iz, isIIFE;19241925// F_ALLOW_UNPARATH_NEW becomes false.1926result = [this.generateExpression(expr.callee, Precedence.Call, E_TTF)];19271928if (expr.optional) {1929result.push('?.');1930}19311932result.push('(');1933for (i = 0, iz = expr['arguments'].length; i < iz; ++i) {1934result.push(this.generateExpression(expr['arguments'][i], Precedence.Assignment, E_TTT));1935if (i + 1 < iz) {1936result.push(',' + space);1937}1938}1939result.push(')');19401941if (!(flags & F_ALLOW_CALL)) {1942return ['(', result, ')'];1943}19441945isIIFE = expr.callee.id === null && expr.callee.params.length === 0;19461947return isIIFE1948? parenthesize(result, precedence, Precedence.Call)1949: parenthesize(result, Precedence.Call, precedence);1950},19511952ChainExpression: function (expr, precedence, flags) {1953if (Precedence.OptionalChaining < precedence) {1954flags |= F_ALLOW_CALL;1955}19561957var result = this.generateExpression(expr.expression, Precedence.OptionalChaining, flags);19581959return parenthesize(result, Precedence.OptionalChaining, precedence);1960},19611962NewExpression: function (expr, precedence, flags) {1963var result, length, i, iz, itemFlags;1964length = expr['arguments'].length;19651966// F_ALLOW_CALL becomes false.1967// F_ALLOW_UNPARATH_NEW may become false.1968itemFlags = (flags & F_ALLOW_UNPARATH_NEW && !parentheses && length === 0) ? E_TFT : E_TFF;19691970result = join(1971'new',1972this.generateExpression(expr.callee, Precedence.New, itemFlags)1973);19741975if (!(flags & F_ALLOW_UNPARATH_NEW) || parentheses || length > 0) {1976result.push('(');1977for (i = 0, iz = length; i < iz; ++i) {1978result.push(this.generateExpression(expr['arguments'][i], Precedence.Assignment, E_TTT));1979if (i + 1 < iz) {1980result.push(',' + space);1981}1982}1983result.push(')');1984}19851986return parenthesize(result, Precedence.New, precedence);1987},19881989MemberExpression: function (expr, precedence, flags) {1990var result, fragment;19911992// F_ALLOW_UNPARATH_NEW becomes false.1993result = [this.generateExpression(expr.object, Precedence.Call, (flags & F_ALLOW_CALL) ? E_TTF : E_TFF)];19941995if (expr.computed) {1996if (expr.optional) {1997result.push('?.');1998}19992000result.push('[');2001result.push(this.generateExpression(expr.property, Precedence.Sequence, flags & F_ALLOW_CALL ? E_TTT : E_TFT));2002result.push(']');2003} else {2004if (!expr.optional && expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') {2005fragment = toSourceNodeWhenNeeded(result).toString();2006// When the following conditions are all true,2007// 1. No floating point2008// 2. Don't have exponents2009// 3. The last character is a decimal digit2010// 4. Not hexadecimal OR octal number literal2011// we should add a floating point.2012if (2013fragment.indexOf('.') < 0 &&2014!/[eExX]/.test(fragment) &&2015esutils.code.isDecimalDigit(fragment.charCodeAt(fragment.length - 1)) &&2016!(fragment.length >= 2 && fragment.charCodeAt(0) === 48) // '0'2017) {2018result.push(' ');2019}2020}2021result.push(expr.optional ? '?.' : '.');2022result.push(generateIdentifier(expr.property));2023}20242025return parenthesize(result, Precedence.Member, precedence);2026},20272028MetaProperty: function (expr, precedence, flags) {2029var result;2030result = [];2031result.push(typeof expr.meta === "string" ? expr.meta : generateIdentifier(expr.meta));2032result.push('.');2033result.push(typeof expr.property === "string" ? expr.property : generateIdentifier(expr.property));2034return parenthesize(result, Precedence.Member, precedence);2035},20362037UnaryExpression: function (expr, precedence, flags) {2038var result, fragment, rightCharCode, leftSource, leftCharCode;2039fragment = this.generateExpression(expr.argument, Precedence.Unary, E_TTT);20402041if (space === '') {2042result = join(expr.operator, fragment);2043} else {2044result = [expr.operator];2045if (expr.operator.length > 2) {2046// delete, void, typeof2047// get `typeof []`, not `typeof[]`2048result = join(result, fragment);2049} else {2050// Prevent inserting spaces between operator and argument if it is unnecessary2051// like, `!cond`2052leftSource = toSourceNodeWhenNeeded(result).toString();2053leftCharCode = leftSource.charCodeAt(leftSource.length - 1);2054rightCharCode = fragment.toString().charCodeAt(0);20552056if (((leftCharCode === 0x2B /* + */ || leftCharCode === 0x2D /* - */) && leftCharCode === rightCharCode) ||2057(esutils.code.isIdentifierPartES5(leftCharCode) && esutils.code.isIdentifierPartES5(rightCharCode))) {2058result.push(noEmptySpace());2059result.push(fragment);2060} else {2061result.push(fragment);2062}2063}2064}2065return parenthesize(result, Precedence.Unary, precedence);2066},20672068YieldExpression: function (expr, precedence, flags) {2069var result;2070if (expr.delegate) {2071result = 'yield*';2072} else {2073result = 'yield';2074}2075if (expr.argument) {2076result = join(2077result,2078this.generateExpression(expr.argument, Precedence.Yield, E_TTT)2079);2080}2081return parenthesize(result, Precedence.Yield, precedence);2082},20832084AwaitExpression: function (expr, precedence, flags) {2085var result = join(2086expr.all ? 'await*' : 'await',2087this.generateExpression(expr.argument, Precedence.Await, E_TTT)2088);2089return parenthesize(result, Precedence.Await, precedence);2090},20912092UpdateExpression: function (expr, precedence, flags) {2093if (expr.prefix) {2094return parenthesize(2095[2096expr.operator,2097this.generateExpression(expr.argument, Precedence.Unary, E_TTT)2098],2099Precedence.Unary,2100precedence2101);2102}2103return parenthesize(2104[2105this.generateExpression(expr.argument, Precedence.Postfix, E_TTT),2106expr.operator2107],2108Precedence.Postfix,2109precedence2110);2111},21122113FunctionExpression: function (expr, precedence, flags) {2114var result = [2115generateAsyncPrefix(expr, true),2116'function'2117];2118if (expr.id) {2119result.push(generateStarSuffix(expr) || noEmptySpace());2120result.push(generateIdentifier(expr.id));2121} else {2122result.push(generateStarSuffix(expr) || space);2123}2124result.push(this.generateFunctionBody(expr));2125return result;2126},21272128ArrayPattern: function (expr, precedence, flags) {2129return this.ArrayExpression(expr, precedence, flags, true);2130},21312132ArrayExpression: function (expr, precedence, flags, isPattern) {2133var result, multiline, that = this;2134if (!expr.elements.length) {2135return '[]';2136}2137multiline = isPattern ? false : expr.elements.length > 1;2138result = ['[', multiline ? newline : ''];2139withIndent(function (indent) {2140var i, iz;2141for (i = 0, iz = expr.elements.length; i < iz; ++i) {2142if (!expr.elements[i]) {2143if (multiline) {2144result.push(indent);2145}2146if (i + 1 === iz) {2147result.push(',');2148}2149} else {2150result.push(multiline ? indent : '');2151result.push(that.generateExpression(expr.elements[i], Precedence.Assignment, E_TTT));2152}2153if (i + 1 < iz) {2154result.push(',' + (multiline ? newline : space));2155}2156}2157});2158if (multiline && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {2159result.push(newline);2160}2161result.push(multiline ? base : '');2162result.push(']');2163return result;2164},21652166RestElement: function(expr, precedence, flags) {2167return '...' + this.generatePattern(expr.argument);2168},21692170ClassExpression: function (expr, precedence, flags) {2171var result, fragment;2172result = ['class'];2173if (expr.id) {2174result = join(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));2175}2176if (expr.superClass) {2177fragment = join('extends', this.generateExpression(expr.superClass, Precedence.Unary, E_TTT));2178result = join(result, fragment);2179}2180result.push(space);2181result.push(this.generateStatement(expr.body, S_TFFT));2182return result;2183},21842185MethodDefinition: function (expr, precedence, flags) {2186var result, fragment;2187if (expr['static']) {2188result = ['static' + space];2189} else {2190result = [];2191}2192if (expr.kind === 'get' || expr.kind === 'set') {2193fragment = [2194join(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),2195this.generateFunctionBody(expr.value)2196];2197} else {2198fragment = [2199generateMethodPrefix(expr),2200this.generatePropertyKey(expr.key, expr.computed),2201this.generateFunctionBody(expr.value)2202];2203}2204return join(result, fragment);2205},22062207PrivateIdentifier: function (expr, precedence, flags) {2208return generateIdentifier(expr);2209},22102211Property: function (expr, precedence, flags) {2212if (expr.kind === 'get' || expr.kind === 'set') {2213return [2214expr.kind, noEmptySpace(),2215this.generatePropertyKey(expr.key, expr.computed),2216this.generateFunctionBody(expr.value)2217];2218}22192220if (expr.shorthand) {2221if (expr.value.type === "AssignmentPattern") {2222return this.AssignmentPattern(expr.value, Precedence.Sequence, E_TTT);2223}2224return this.generatePropertyKey(expr.key, expr.computed);2225}22262227if (expr.method) {2228return [2229generateMethodPrefix(expr),2230this.generatePropertyKey(expr.key, expr.computed),2231this.generateFunctionBody(expr.value)2232];2233}22342235return [2236this.generatePropertyKey(expr.key, expr.computed),2237':' + space,2238this.generateExpression(expr.value, Precedence.Assignment, E_TTT)2239];2240},22412242PropertyDefinition: function (expr, precedence, flags) {2243var result;22442245if (expr.static) {2246result = ['static '];2247} else {2248result = [];2249}22502251result.push(this.generatePropertyKey(expr.key, expr.computed));22522253if (expr.value) {2254result.push( space + '=' + space);2255result.push(this.generateExpression(expr.value, Precedence.Assignment, E_TTT));2256}22572258result.push(this.semicolon(flags));22592260return result;2261},22622263ObjectExpression: function (expr, precedence, flags) {2264var multiline, result, fragment, that = this;22652266if (!expr.properties.length) {2267return '{}';2268}2269multiline = expr.properties.length > 1;22702271withIndent(function () {2272fragment = that.generateExpression(expr.properties[0], Precedence.Sequence, E_TTT);2273});22742275if (!multiline) {2276// issues 42277// Do not transform from2278// dejavu.Class.declare({2279// method2: function () {}2280// });2281// to2282// dejavu.Class.declare({method2: function () {2283// }});2284if (!hasLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {2285return [ '{', space, fragment, space, '}' ];2286}2287}22882289withIndent(function (indent) {2290var i, iz;2291result = [ '{', newline, indent, fragment ];22922293if (multiline) {2294result.push(',' + newline);2295for (i = 1, iz = expr.properties.length; i < iz; ++i) {2296result.push(indent);2297result.push(that.generateExpression(expr.properties[i], Precedence.Sequence, E_TTT));2298if (i + 1 < iz) {2299result.push(',' + newline);2300}2301}2302}2303});23042305if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {2306result.push(newline);2307}2308result.push(base);2309result.push('}');2310return result;2311},23122313AssignmentPattern: function(expr, precedence, flags) {2314return this.generateAssignment(expr.left, expr.right, '=', precedence, flags);2315},23162317ObjectPattern: function (expr, precedence, flags) {2318var result, i, iz, multiline, property, that = this;2319if (!expr.properties.length) {2320return '{}';2321}23222323multiline = false;2324if (expr.properties.length === 1) {2325property = expr.properties[0];2326if (2327property.type === Syntax.Property2328&& property.value.type !== Syntax.Identifier2329) {2330multiline = true;2331}2332} else {2333for (i = 0, iz = expr.properties.length; i < iz; ++i) {2334property = expr.properties[i];2335if (2336property.type === Syntax.Property2337&& !property.shorthand2338) {2339multiline = true;2340break;2341}2342}2343}2344result = ['{', multiline ? newline : '' ];23452346withIndent(function (indent) {2347var i, iz;2348for (i = 0, iz = expr.properties.length; i < iz; ++i) {2349result.push(multiline ? indent : '');2350result.push(that.generateExpression(expr.properties[i], Precedence.Sequence, E_TTT));2351if (i + 1 < iz) {2352result.push(',' + (multiline ? newline : space));2353}2354}2355});23562357if (multiline && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {2358result.push(newline);2359}2360result.push(multiline ? base : '');2361result.push('}');2362return result;2363},23642365ThisExpression: function (expr, precedence, flags) {2366return 'this';2367},23682369Super: function (expr, precedence, flags) {2370return 'super';2371},23722373Identifier: function (expr, precedence, flags) {2374return generateIdentifier(expr);2375},23762377ImportDefaultSpecifier: function (expr, precedence, flags) {2378return generateIdentifier(expr.id || expr.local);2379},23802381ImportNamespaceSpecifier: function (expr, precedence, flags) {2382var result = ['*'];2383var id = expr.id || expr.local;2384if (id) {2385result.push(space + 'as' + noEmptySpace() + generateIdentifier(id));2386}2387return result;2388},23892390ImportSpecifier: function (expr, precedence, flags) {2391var imported = expr.imported;2392var result = [ imported.name ];2393var local = expr.local;2394if (local && local.name !== imported.name) {2395result.push(noEmptySpace() + 'as' + noEmptySpace() + generateIdentifier(local));2396}2397return result;2398},23992400ExportSpecifier: function (expr, precedence, flags) {2401var local = expr.local;2402var result = [ local.name ];2403var exported = expr.exported;2404if (exported && exported.name !== local.name) {2405result.push(noEmptySpace() + 'as' + noEmptySpace() + generateIdentifier(exported));2406}2407return result;2408},24092410Literal: function (expr, precedence, flags) {2411var raw;2412if (expr.hasOwnProperty('raw') && parse && extra.raw) {2413try {2414raw = parse(expr.raw).body[0].expression;2415if (raw.type === Syntax.Literal) {2416if (raw.value === expr.value) {2417return expr.raw;2418}2419}2420} catch (e) {2421// not use raw property2422}2423}24242425if (expr.regex) {2426return '/' + expr.regex.pattern + '/' + expr.regex.flags;2427}24282429// BigInt, eg: 1n2430if (typeof expr.bigint === 'string' && expr.raw) {2431return expr.raw;2432}24332434if (expr.value === null) {2435return 'null';2436}24372438if (typeof expr.value === 'string') {2439return escapeString(expr.value);2440}24412442if (typeof expr.value === 'number') {2443// Has Numeric Separator2444if (expr.raw && expr.raw.indexOf('_') !== -1) {2445return expr.raw;2446}24472448return generateNumber(expr.value);2449}24502451if (typeof expr.value === 'boolean') {2452return expr.value ? 'true' : 'false';2453}24542455return generateRegExp(expr.value);2456},24572458GeneratorExpression: function (expr, precedence, flags) {2459return this.ComprehensionExpression(expr, precedence, flags);2460},24612462ComprehensionExpression: function (expr, precedence, flags) {2463// GeneratorExpression should be parenthesized with (...), ComprehensionExpression with [...]2464// Due to https://bugzilla.mozilla.org/show_bug.cgi?id=883468 position of expr.body can differ in Spidermonkey and ES624652466var result, i, iz, fragment, that = this;2467result = (expr.type === Syntax.GeneratorExpression) ? ['('] : ['['];24682469if (extra.moz.comprehensionExpressionStartsWithAssignment) {2470fragment = this.generateExpression(expr.body, Precedence.Assignment, E_TTT);2471result.push(fragment);2472}24732474if (expr.blocks) {2475withIndent(function () {2476for (i = 0, iz = expr.blocks.length; i < iz; ++i) {2477fragment = that.generateExpression(expr.blocks[i], Precedence.Sequence, E_TTT);2478if (i > 0 || extra.moz.comprehensionExpressionStartsWithAssignment) {2479result = join(result, fragment);2480} else {2481result.push(fragment);2482}2483}2484});2485}24862487if (expr.filter) {2488result = join(result, 'if' + space);2489fragment = this.generateExpression(expr.filter, Precedence.Sequence, E_TTT);2490result = join(result, [ '(', fragment, ')' ]);2491}24922493if (!extra.moz.comprehensionExpressionStartsWithAssignment) {2494fragment = this.generateExpression(expr.body, Precedence.Assignment, E_TTT);24952496result = join(result, fragment);2497}24982499result.push((expr.type === Syntax.GeneratorExpression) ? ')' : ']');2500return result;2501},25022503ComprehensionBlock: function (expr, precedence, flags) {2504var fragment;2505if (expr.left.type === Syntax.VariableDeclaration) {2506fragment = [2507expr.left.kind, noEmptySpace(),2508this.generateStatement(expr.left.declarations[0], S_FFFF)2509];2510} else {2511fragment = this.generateExpression(expr.left, Precedence.Call, E_TTT);2512}25132514fragment = join(fragment, expr.of ? 'of' : 'in');2515fragment = join(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));25162517return [ 'for' + space + '(', fragment, ')' ];2518},25192520SpreadElement: function (expr, precedence, flags) {2521return [2522'...',2523this.generateExpression(expr.argument, Precedence.Assignment, E_TTT)2524];2525},25262527TaggedTemplateExpression: function (expr, precedence, flags) {2528var itemFlags = E_TTF;2529if (!(flags & F_ALLOW_CALL)) {2530itemFlags = E_TFF;2531}2532var result = [2533this.generateExpression(expr.tag, Precedence.Call, itemFlags),2534this.generateExpression(expr.quasi, Precedence.Primary, E_FFT)2535];2536return parenthesize(result, Precedence.TaggedTemplate, precedence);2537},25382539TemplateElement: function (expr, precedence, flags) {2540// Don't use "cooked". Since tagged template can use raw template2541// representation. So if we do so, it breaks the script semantics.2542return expr.value.raw;2543},25442545TemplateLiteral: function (expr, precedence, flags) {2546var result, i, iz;2547result = [ '`' ];2548for (i = 0, iz = expr.quasis.length; i < iz; ++i) {2549result.push(this.generateExpression(expr.quasis[i], Precedence.Primary, E_TTT));2550if (i + 1 < iz) {2551result.push('${' + space);2552result.push(this.generateExpression(expr.expressions[i], Precedence.Sequence, E_TTT));2553result.push(space + '}');2554}2555}2556result.push('`');2557return result;2558},25592560ModuleSpecifier: function (expr, precedence, flags) {2561return this.Literal(expr, precedence, flags);2562},25632564ImportExpression: function(expr, precedence, flag) {2565return parenthesize([2566'import(',2567this.generateExpression(expr.source, Precedence.Assignment, E_TTT),2568')'2569], Precedence.Call, precedence);2570}2571};25722573merge(CodeGenerator.prototype, CodeGenerator.Expression);25742575CodeGenerator.prototype.generateExpression = function (expr, precedence, flags) {2576var result, type;25772578type = expr.type || Syntax.Property;25792580if (extra.verbatim && expr.hasOwnProperty(extra.verbatim)) {2581return generateVerbatim(expr, precedence);2582}25832584result = this[type](expr, precedence, flags);258525862587if (extra.comment) {2588result = addComments(expr, result);2589}2590return toSourceNodeWhenNeeded(result, expr);2591};25922593CodeGenerator.prototype.generateStatement = function (stmt, flags) {2594var result,2595fragment;25962597result = this[stmt.type](stmt, flags);25982599// Attach comments26002601if (extra.comment) {2602result = addComments(stmt, result);2603}26042605fragment = toSourceNodeWhenNeeded(result).toString();2606if (stmt.type === Syntax.Program && !safeConcatenation && newline === '' && fragment.charAt(fragment.length - 1) === '\n') {2607result = sourceMap ? toSourceNodeWhenNeeded(result).replaceRight(/\s+$/, '') : fragment.replace(/\s+$/, '');2608}26092610return toSourceNodeWhenNeeded(result, stmt);2611};26122613function generateInternal(node) {2614var codegen;26152616codegen = new CodeGenerator();2617if (isStatement(node)) {2618return codegen.generateStatement(node, S_TFFF);2619}26202621if (isExpression(node)) {2622return codegen.generateExpression(node, Precedence.Sequence, E_TTT);2623}26242625throw new Error('Unknown node type: ' + node.type);2626}26272628function generate(node, options) {2629var defaultOptions = getDefaultOptions(), result, pair;26302631if (options != null) {2632// Obsolete options2633//2634// `options.indent`2635// `options.base`2636//2637// Instead of them, we can use `option.format.indent`.2638if (typeof options.indent === 'string') {2639defaultOptions.format.indent.style = options.indent;2640}2641if (typeof options.base === 'number') {2642defaultOptions.format.indent.base = options.base;2643}2644options = updateDeeply(defaultOptions, options);2645indent = options.format.indent.style;2646if (typeof options.base === 'string') {2647base = options.base;2648} else {2649base = stringRepeat(indent, options.format.indent.base);2650}2651} else {2652options = defaultOptions;2653indent = options.format.indent.style;2654base = stringRepeat(indent, options.format.indent.base);2655}2656json = options.format.json;2657renumber = options.format.renumber;2658hexadecimal = json ? false : options.format.hexadecimal;2659quotes = json ? 'double' : options.format.quotes;2660escapeless = options.format.escapeless;2661newline = options.format.newline;2662space = options.format.space;2663if (options.format.compact) {2664newline = space = indent = base = '';2665}2666parentheses = options.format.parentheses;2667semicolons = options.format.semicolons;2668safeConcatenation = options.format.safeConcatenation;2669directive = options.directive;2670parse = json ? null : options.parse;2671sourceMap = options.sourceMap;2672sourceCode = options.sourceCode;2673preserveBlankLines = options.format.preserveBlankLines && sourceCode !== null;2674extra = options;26752676if (sourceMap) {2677if (!exports.browser) {2678// We assume environment is node.js2679// And prevent from including source-map by browserify2680SourceNode = require('source-map').SourceNode;2681} else {2682SourceNode = global.sourceMap.SourceNode;2683}2684}26852686result = generateInternal(node);26872688if (!sourceMap) {2689pair = {code: result.toString(), map: null};2690return options.sourceMapWithCode ? pair : pair.code;2691}269226932694pair = result.toStringWithSourceMap({2695file: options.file,2696sourceRoot: options.sourceMapRoot2697});26982699if (options.sourceContent) {2700pair.map.setSourceContent(options.sourceMap,2701options.sourceContent);2702}27032704if (options.sourceMapWithCode) {2705return pair;2706}27072708return pair.map.toString();2709}27102711FORMAT_MINIFY = {2712indent: {2713style: '',2714base: 02715},2716renumber: true,2717hexadecimal: true,2718quotes: 'auto',2719escapeless: true,2720compact: true,2721parentheses: false,2722semicolons: false2723};27242725FORMAT_DEFAULTS = getDefaultOptions().format;27262727exports.version = require('./package.json').version;2728exports.generate = generate;2729exports.attachComments = estraverse.attachComments;2730exports.Precedence = updateDeeply({}, Precedence);2731exports.browser = false;2732exports.FORMAT_MINIFY = FORMAT_MINIFY;2733exports.FORMAT_DEFAULTS = FORMAT_DEFAULTS;2734}());2735/* vim: set sw=4 ts=4 et tw=80 : */273627372738