/* Copyright (C) 2012-2013 Yusuke Suzuki Copyright (C) 2012-2013 Michael Ficarra Copyright (C) 2012-2013 Mathias Bynens Copyright (C) 2013 Irakli Gozalishvili Copyright (C) 2012 Robert Gust-Bardon Copyright (C) 2012 John Freeman Copyright (C) 2011-2012 Ariya Hidayat Copyright (C) 2012 Joost-Wim Boekesteijn Copyright (C) 2012 Kris Kowal Copyright (C) 2012 Arpad Borsos Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /*global exports:true, generateStatement:true, generateExpression:true, require:true, global:true*/ (function () { 'use strict'; var Syntax, Precedence, BinaryPrecedence, SourceNode, estraverse, esutils, isArray, base, indent, json, renumber, hexadecimal, quotes, escapeless, newline, space, parentheses, semicolons, safeConcatenation, directive, extra, parse, sourceMap, FORMAT_MINIFY, FORMAT_DEFAULTS; estraverse = require('estraverse'); esutils = require('esutils'); Syntax = { AssignmentExpression: 'AssignmentExpression', ArrayExpression: 'ArrayExpression', ArrayPattern: 'ArrayPattern', ArrowFunctionExpression: 'ArrowFunctionExpression', BlockStatement: 'BlockStatement', BinaryExpression: 'BinaryExpression', BreakStatement: 'BreakStatement', CallExpression: 'CallExpression', CatchClause: 'CatchClause', ComprehensionBlock: 'ComprehensionBlock', ComprehensionExpression: 'ComprehensionExpression', ConditionalExpression: 'ConditionalExpression', ContinueStatement: 'ContinueStatement', DirectiveStatement: 'DirectiveStatement', DoWhileStatement: 'DoWhileStatement', DebuggerStatement: 'DebuggerStatement', EmptyStatement: 'EmptyStatement', ExportDeclaration: 'ExportDeclaration', ExpressionStatement: 'ExpressionStatement', ForStatement: 'ForStatement', ForInStatement: 'ForInStatement', ForOfStatement: 'ForOfStatement', FunctionDeclaration: 'FunctionDeclaration', FunctionExpression: 'FunctionExpression', GeneratorExpression: 'GeneratorExpression', Identifier: 'Identifier', IfStatement: 'IfStatement', Literal: 'Literal', LabeledStatement: 'LabeledStatement', LogicalExpression: 'LogicalExpression', MemberExpression: 'MemberExpression', NewExpression: 'NewExpression', ObjectExpression: 'ObjectExpression', ObjectPattern: 'ObjectPattern', Program: 'Program', Property: 'Property', ReturnStatement: 'ReturnStatement', SequenceExpression: 'SequenceExpression', SwitchStatement: 'SwitchStatement', SwitchCase: 'SwitchCase', ThisExpression: 'ThisExpression', ThrowStatement: 'ThrowStatement', TryStatement: 'TryStatement', UnaryExpression: 'UnaryExpression', UpdateExpression: 'UpdateExpression', VariableDeclaration: 'VariableDeclaration', VariableDeclarator: 'VariableDeclarator', WhileStatement: 'WhileStatement', WithStatement: 'WithStatement', YieldExpression: 'YieldExpression' }; Precedence = { Sequence: 0, Yield: 1, Assignment: 1, Conditional: 2, ArrowFunction: 2, LogicalOR: 3, LogicalAND: 4, BitwiseOR: 5, BitwiseXOR: 6, BitwiseAND: 7, Equality: 8, Relational: 9, BitwiseSHIFT: 10, Additive: 11, Multiplicative: 12, Unary: 13, Postfix: 14, Call: 15, New: 16, Member: 17, Primary: 18 }; 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 }; function getDefaultOptions() { // default options return { indent: null, base: null, parse: null, comment: false, format: { indent: { style: ' ', base: 0, adjustMultilineComment: false }, newline: '\n', space: ' ', json: false, renumber: false, hexadecimal: false, quotes: 'single', escapeless: false, compact: false, parentheses: true, semicolons: true, safeConcatenation: false }, moz: { comprehensionExpressionStartsWithAssignment: false, starlessGenerator: false, parenthesizedComprehensionBlock: false }, sourceMap: null, sourceMapRoot: null, sourceMapWithCode: false, directive: false, verbatim: null }; } 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 hasLineTerminator(str) { return (/[\r\n]/g).test(str); } function endsWithLineTerminator(str) { var len = str.length; return len && esutils.code.isLineTerminator(str.charCodeAt(len - 1)); } 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 !== value) { throw new Error('Numeric literal whose value is NaN'); } if (value < 0 || (value === 0 && 1 / value < 0)) { throw new Error('Numeric literal whose value is negative'); } 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 /* 0 */ && 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 /* 0 */) { --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; } // Generate valid RegExp expression. // This function is based on https://github.com/Constellation/iv Engine function escapeRegExpCharacter(ch, previousIsBackslash) { // not handling '\' and handling \u2028 or \u2029 to unicode escape sequence if ((ch & ~1) === 0x2028) { return (previousIsBackslash ? 'u' : '\\u') + ((ch === 0x2028) ? '2028' : '2029'); } else if (ch === 10 || ch === 13) { // \n, \r 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) { // extract flag from toString result 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 { // if new RegExp("\\\n') is provided, create /\n/ result += escapeRegExpCharacter(ch, previousIsBackslash); // prevent like /\\[/]/ previousIsBackslash = false; } } return '/' + result + '/' + flags; } return result; } function escapeAllowedCharacter(code, next) { var hex, result = '\\'; switch (code) { case 0x08 /* \b */: result += 'b'; break; case 0x0C /* \f */: result += 'f'; break; case 0x09 /* \t */: result += 't'; break; default: hex = code.toString(16).toUpperCase(); if (json || code > 0xFF) { result += 'u' + '0000'.slice(hex.length) + hex; } else if (code === 0x0000 && !esutils.code.isDecimalDigit(next)) { result += '0'; } else if (code === 0x000B /* \v */) { // '\v' 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 /* \n */: result += 'n'; break; case 0x0D /* \r */: result += 'r'; break; case 0x2028: result += 'u2028'; break; case 0x2029: result += 'u2029'; break; default: throw new Error('Incorrectly classified character'); } 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 (esutils.code.isLineTerminator(code) || code === 0x5C /* \ */) { result += escapeDisallowedCharacter(code); continue; } else if ((json && code < 0x20 /* SP */) || !(json || escapeless || (code >= 0x20 /* SP */ && 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; } /** * flatten an array to a string, where the array can contain * either strings or nested arrays */ function flattenToString(arr) { var i, iz, elem, result = ''; for (i = 0, iz = arr.length; i < iz; ++i) { elem = arr[i]; result += isArray(elem) ? flattenToString(elem) : elem; } return result; } /** * convert generated to a SourceNode when source maps are enabled. */ function toSourceNodeWhenNeeded(generated, node) { if (!sourceMap) { // with no source maps, generated is either an // array or a string. if an array, flatten it. // if a string, just return it if (isArray(generated)) { return flattenToString(generated); } else { return generated; } } if (node == null) { if (generated instanceof SourceNode) { return generated; } else { node = {}; } } if (node.loc == null) { return new SourceNode(null, null, sourceMap, generated, node.name || null); } return new SourceNode(node.loc.start.line, node.loc.start.column, (sourceMap === true ? node.loc.source || null : sourceMap), generated, node.name || null); } function noEmptySpace() { return (space) ? space : ' '; } function join(left, right) { var leftSource = toSourceNodeWhenNeeded(left).toString(), rightSource = toSourceNodeWhenNeeded(right).toString(), leftCharCode = leftSource.charCodeAt(leftSource.length - 1), rightCharCode = rightSource.charCodeAt(0); if ((leftCharCode === 0x2B /* + */ || leftCharCode === 0x2D /* - */) && leftCharCode === rightCharCode || esutils.code.isIdentifierPart(leftCharCode) && esutils.code.isIdentifierPart(rightCharCode) || leftCharCode === 0x2F /* / */ && rightCharCode === 0x69 /* i */) { // infix word operators all start with `i` return [left, noEmptySpace(), right]; } else if (esutils.code.isWhiteSpace(leftCharCode) || esutils.code.isLineTerminator(leftCharCode) || esutils.code.isWhiteSpace(rightCharCode) || esutils.code.isLineTerminator(rightCharCode)) { return [left, right]; } return [left, space, right]; } function addIndent(stmt) { return [base, stmt]; } function withIndent(fn) { var previousBase, result; previousBase = base; base += indent; result = fn.call(this, base); base = previousBase; return result; } function calculateSpaces(str) { var i; for (i = str.length - 1; i >= 0; --i) { if (esutils.code.isLineTerminator(str.charCodeAt(i))) { break; } } return (str.length - 1) - i; } function adjustMultilineComment(value, specialBase) { var array, i, len, line, j, spaces, previousBase, sn; array = value.split(/\r\n|[\r\n]/); spaces = Number.MAX_VALUE; // first line doesn't have indentation for (i = 1, len = array.length; i < len; ++i) { line = array[i]; j = 0; while (j < line.length && esutils.code.isWhiteSpace(line.charCodeAt(j))) { ++j; } if (spaces > j) { spaces = j; } } if (typeof specialBase !== 'undefined') { // pattern like // { // var t = 20; /* // * this is comment // */ // } previousBase = base; if (array[1][spaces] === '*') { specialBase += ' '; } base = specialBase; } else { if (spaces & 1) { // /* // * // */ // If spaces are odd number, above pattern is considered. // We waste 1 space. --spaces; } previousBase = base; } for (i = 1, len = array.length; i < len; ++i) { sn = toSourceNodeWhenNeeded(addIndent(array[i].slice(spaces))); array[i] = sourceMap ? sn.join('') : sn; } base = previousBase; return array.join('\n'); } function generateComment(comment, specialBase) { if (comment.type === 'Line') { if (endsWithLineTerminator(comment.value)) { return '//' + comment.value; } else { // Always use LineTerminator return '//' + comment.value + '\n'; } } if (extra.format.indent.adjustMultilineComment && /[\n\r]/.test(comment.value)) { return adjustMultilineComment('/*' + comment.value + '*/', specialBase); } return '/*' + comment.value + '*/'; } function addCommentsToStatement(stmt, result) { var i, len, comment, save, tailingToStatement, specialBase, fragment; if (stmt.leadingComments && stmt.leadingComments.length > 0) { save = result; comment = stmt.leadingComments[0]; result = []; if (safeConcatenation && stmt.type === Syntax.Program && stmt.body.length === 0) { result.push('\n'); } result.push(generateComment(comment)); if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { result.push('\n'); } for (i = 1, len = stmt.leadingComments.length; i < len; ++i) { comment = stmt.leadingComments[i]; fragment = [generateComment(comment)]; if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) { fragment.push('\n'); } result.push(addIndent(fragment)); } result.push(addIndent(save)); } if (stmt.trailingComments) { tailingToStatement = !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString()); specialBase = stringRepeat(' ', calculateSpaces(toSourceNodeWhenNeeded([base, result, indent]).toString())); for (i = 0, len = stmt.trailingComments.length; i < len; ++i) { comment = stmt.trailingComments[i]; if (tailingToStatement) { // We assume target like following script // // var t = 20; /** // * This is comment of t // */ if (i === 0) { // first case result = [result, indent]; } else { result = [result, specialBase]; } result.push(generateComment(comment, specialBase)); } else { result = [result, addIndent(generateComment(comment))]; } if (i !== len - 1 && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { result = [result, '\n']; } } } return result; } function parenthesize(text, current, should) { if (current < should) { return ['(', text, ')']; } return text; } function maybeBlock(stmt, semicolonOptional, functionBody) { var result, noLeadingComment; noLeadingComment = !extra.comment || !stmt.leadingComments; if (stmt.type === Syntax.BlockStatement && noLeadingComment) { return [space, generateStatement(stmt, { functionBody: functionBody })]; } if (stmt.type === Syntax.EmptyStatement && noLeadingComment) { return ';'; } withIndent(function () { result = [newline, addIndent(generateStatement(stmt, { semicolonOptional: semicolonOptional, functionBody: functionBody }))]; }); return result; } function maybeBlockSuffix(stmt, result) { var ends = endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString()); if (stmt.type === Syntax.BlockStatement && (!extra.comment || !stmt.leadingComments) && !ends) { return [result, space]; } if (ends) { return [result, base]; } return [result, newline, base]; } function generateVerbatim(expr, option) { var i, result; result = expr[extra.verbatim].split(/\r\n|\n/); for (i = 1; i < result.length; i++) { result[i] = newline + base + result[i]; } result = parenthesize(result, Precedence.Sequence, option.precedence); return toSourceNodeWhenNeeded(result, expr); } function generateIdentifier(node) { return toSourceNodeWhenNeeded(node.name, node); } function generatePattern(node, options) { var result; if (node.type === Syntax.Identifier) { result = generateIdentifier(node); } else { result = generateExpression(node, { precedence: options.precedence, allowIn: options.allowIn, allowCall: true }); } return result; } function generateFunctionBody(node) { var result, i, len, expr, arrow; arrow = node.type === Syntax.ArrowFunctionExpression; if (arrow && node.params.length === 1 && node.params[0].type === Syntax.Identifier) { // arg => { } case result = [generateIdentifier(node.params[0])]; } else { result = ['(']; for (i = 0, len = node.params.length; i < len; ++i) { result.push(generatePattern(node.params[i], { precedence: Precedence.Assignment, allowIn: true })); if (i + 1 < len) { result.push(',' + space); } } result.push(')'); } if (arrow) { result.push(space); result.push('=>'); } if (node.expression) { result.push(space); expr = generateExpression(node.body, { precedence: Precedence.Assignment, allowIn: true, allowCall: true }); if (expr.toString().charAt(0) === '{') { expr = ['(', expr, ')']; } result.push(expr); } else { result.push(maybeBlock(node.body, false, true)); } return result; } function generateIterationForStatement(operator, stmt, semicolonIsNotNeeded) { var result = ['for' + space + '(']; withIndent(function () { if (stmt.left.type === Syntax.VariableDeclaration) { withIndent(function () { result.push(stmt.left.kind + noEmptySpace()); result.push(generateStatement(stmt.left.declarations[0], { allowIn: false })); }); } else { result.push(generateExpression(stmt.left, { precedence: Precedence.Call, allowIn: true, allowCall: true })); } result = join(result, operator); result = [join( result, generateExpression(stmt.right, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }) ), ')']; }); result.push(maybeBlock(stmt.body, semicolonIsNotNeeded)); return result; } function generateExpression(expr, option) { var result, precedence, type, currentPrecedence, i, len, raw, fragment, multiline, leftCharCode, leftSource, rightCharCode, allowIn, allowCall, allowUnparenthesizedNew, property, isGenerator; precedence = option.precedence; allowIn = option.allowIn; allowCall = option.allowCall; type = expr.type || option.type; if (extra.verbatim && expr.hasOwnProperty(extra.verbatim)) { return generateVerbatim(expr, option); } switch (type) { case Syntax.SequenceExpression: result = []; allowIn |= (Precedence.Sequence < precedence); for (i = 0, len = expr.expressions.length; i < len; ++i) { result.push(generateExpression(expr.expressions[i], { precedence: Precedence.Assignment, allowIn: allowIn, allowCall: true })); if (i + 1 < len) { result.push(',' + space); } } result = parenthesize(result, Precedence.Sequence, precedence); break; case Syntax.AssignmentExpression: allowIn |= (Precedence.Assignment < precedence); result = parenthesize( [ generateExpression(expr.left, { precedence: Precedence.Call, allowIn: allowIn, allowCall: true }), space + expr.operator + space, generateExpression(expr.right, { precedence: Precedence.Assignment, allowIn: allowIn, allowCall: true }) ], Precedence.Assignment, precedence ); break; case Syntax.ArrowFunctionExpression: allowIn |= (Precedence.ArrowFunction < precedence); result = parenthesize(generateFunctionBody(expr), Precedence.ArrowFunction, precedence); break; case Syntax.ConditionalExpression: allowIn |= (Precedence.Conditional < precedence); result = parenthesize( [ generateExpression(expr.test, { precedence: Precedence.LogicalOR, allowIn: allowIn, allowCall: true }), space + '?' + space, generateExpression(expr.consequent, { precedence: Precedence.Assignment, allowIn: allowIn, allowCall: true }), space + ':' + space, generateExpression(expr.alternate, { precedence: Precedence.Assignment, allowIn: allowIn, allowCall: true }) ], Precedence.Conditional, precedence ); break; case Syntax.LogicalExpression: case Syntax.BinaryExpression: currentPrecedence = BinaryPrecedence[expr.operator]; allowIn |= (currentPrecedence < precedence); fragment = generateExpression(expr.left, { precedence: currentPrecedence, allowIn: allowIn, allowCall: true }); leftSource = fragment.toString(); if (leftSource.charCodeAt(leftSource.length - 1) === 0x2F /* / */ && esutils.code.isIdentifierPart(expr.operator.charCodeAt(0))) { result = [fragment, noEmptySpace(), expr.operator]; } else { result = join(fragment, expr.operator); } fragment = generateExpression(expr.right, { precedence: currentPrecedence + 1, allowIn: allowIn, allowCall: true }); if (expr.operator === '/' && fragment.toString().charAt(0) === '/' || expr.operator.slice(-1) === '<' && fragment.toString().slice(0, 3) === '!--') { // If '/' concats with '/' or `<` concats with `!--`, it is interpreted as comment start result.push(noEmptySpace()); result.push(fragment); } else { result = join(result, fragment); } if (expr.operator === 'in' && !allowIn) { result = ['(', result, ')']; } else { result = parenthesize(result, currentPrecedence, precedence); } break; case Syntax.CallExpression: result = [generateExpression(expr.callee, { precedence: Precedence.Call, allowIn: true, allowCall: true, allowUnparenthesizedNew: false })]; result.push('('); for (i = 0, len = expr['arguments'].length; i < len; ++i) { result.push(generateExpression(expr['arguments'][i], { precedence: Precedence.Assignment, allowIn: true, allowCall: true })); if (i + 1 < len) { result.push(',' + space); } } result.push(')'); if (!allowCall) { result = ['(', result, ')']; } else { result = parenthesize(result, Precedence.Call, precedence); } break; case Syntax.NewExpression: len = expr['arguments'].length; allowUnparenthesizedNew = option.allowUnparenthesizedNew === undefined || option.allowUnparenthesizedNew; result = join( 'new', generateExpression(expr.callee, { precedence: Precedence.New, allowIn: true, allowCall: false, allowUnparenthesizedNew: allowUnparenthesizedNew && !parentheses && len === 0 }) ); if (!allowUnparenthesizedNew || parentheses || len > 0) { result.push('('); for (i = 0; i < len; ++i) { result.push(generateExpression(expr['arguments'][i], { precedence: Precedence.Assignment, allowIn: true, allowCall: true })); if (i + 1 < len) { result.push(',' + space); } } result.push(')'); } result = parenthesize(result, Precedence.New, precedence); break; case Syntax.MemberExpression: result = [generateExpression(expr.object, { precedence: Precedence.Call, allowIn: true, allowCall: allowCall, allowUnparenthesizedNew: false })]; if (expr.computed) { result.push('['); result.push(generateExpression(expr.property, { precedence: Precedence.Sequence, allowIn: true, allowCall: allowCall })); result.push(']'); } else { if (expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') { fragment = toSourceNodeWhenNeeded(result).toString(); // When the following conditions are all true, // 1. No floating point // 2. Don't have exponents // 3. The last character is a decimal digit // 4. Not hexadecimal OR octal number literal // we should add a floating point. if ( fragment.indexOf('.') < 0 && !/[eExX]/.test(fragment) && esutils.code.isDecimalDigit(fragment.charCodeAt(fragment.length - 1)) && !(fragment.length >= 2 && fragment.charCodeAt(0) === 48) // '0' ) { result.push('.'); } } result.push('.'); result.push(generateIdentifier(expr.property)); } result = parenthesize(result, Precedence.Member, precedence); break; case Syntax.UnaryExpression: fragment = generateExpression(expr.argument, { precedence: Precedence.Unary, allowIn: true, allowCall: true }); if (space === '') { result = join(expr.operator, fragment); } else { result = [expr.operator]; if (expr.operator.length > 2) { // delete, void, typeof // get `typeof []`, not `typeof[]` result = join(result, fragment); } else { // Prevent inserting spaces between operator and argument if it is unnecessary // like, `!cond` leftSource = toSourceNodeWhenNeeded(result).toString(); leftCharCode = leftSource.charCodeAt(leftSource.length - 1); rightCharCode = fragment.toString().charCodeAt(0); if (((leftCharCode === 0x2B /* + */ || leftCharCode === 0x2D /* - */) && leftCharCode === rightCharCode) || (esutils.code.isIdentifierPart(leftCharCode) && esutils.code.isIdentifierPart(rightCharCode))) { result.push(noEmptySpace()); result.push(fragment); } else { result.push(fragment); } } } result = parenthesize(result, Precedence.Unary, precedence); break; case Syntax.YieldExpression: if (expr.delegate) { result = 'yield*'; } else { result = 'yield'; } if (expr.argument) { result = join( result, generateExpression(expr.argument, { precedence: Precedence.Yield, allowIn: true, allowCall: true }) ); } result = parenthesize(result, Precedence.Yield, precedence); break; case Syntax.UpdateExpression: if (expr.prefix) { result = parenthesize( [ expr.operator, generateExpression(expr.argument, { precedence: Precedence.Unary, allowIn: true, allowCall: true }) ], Precedence.Unary, precedence ); } else { result = parenthesize( [ generateExpression(expr.argument, { precedence: Precedence.Postfix, allowIn: true, allowCall: true }), expr.operator ], Precedence.Postfix, precedence ); } break; case Syntax.FunctionExpression: isGenerator = expr.generator && !extra.moz.starlessGenerator; result = isGenerator ? 'function*' : 'function'; if (expr.id) { result = [result, (isGenerator) ? space : noEmptySpace(), generateIdentifier(expr.id), generateFunctionBody(expr)]; } else { result = [result + space, generateFunctionBody(expr)]; } break; case Syntax.ArrayPattern: case Syntax.ArrayExpression: if (!expr.elements.length) { result = '[]'; break; } multiline = expr.elements.length > 1; result = ['[', multiline ? newline : '']; withIndent(function (indent) { for (i = 0, len = expr.elements.length; i < len; ++i) { if (!expr.elements[i]) { if (multiline) { result.push(indent); } if (i + 1 === len) { result.push(','); } } else { result.push(multiline ? indent : ''); result.push(generateExpression(expr.elements[i], { precedence: Precedence.Assignment, allowIn: true, allowCall: true })); } if (i + 1 < len) { result.push(',' + (multiline ? newline : space)); } } }); if (multiline && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { result.push(newline); } result.push(multiline ? base : ''); result.push(']'); break; case Syntax.Property: if (expr.kind === 'get' || expr.kind === 'set') { result = [ expr.kind, noEmptySpace(), generateExpression(expr.key, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }), generateFunctionBody(expr.value) ]; } else { if (expr.shorthand) { result = generateExpression(expr.key, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }); } else if (expr.method) { result = []; if (expr.value.generator) { result.push('*'); } result.push(generateExpression(expr.key, { precedence: Precedence.Sequence, allowIn: true, allowCall: true })); result.push(generateFunctionBody(expr.value)); } else { result = [ generateExpression(expr.key, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }), ':' + space, generateExpression(expr.value, { precedence: Precedence.Assignment, allowIn: true, allowCall: true }) ]; } } break; case Syntax.ObjectExpression: if (!expr.properties.length) { result = '{}'; break; } multiline = expr.properties.length > 1; withIndent(function () { fragment = generateExpression(expr.properties[0], { precedence: Precedence.Sequence, allowIn: true, allowCall: true, type: Syntax.Property }); }); if (!multiline) { // issues 4 // Do not transform from // dejavu.Class.declare({ // method2: function () {} // }); // to // dejavu.Class.declare({method2: function () { // }}); if (!hasLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) { result = [ '{', space, fragment, space, '}' ]; break; } } withIndent(function (indent) { result = [ '{', newline, indent, fragment ]; if (multiline) { result.push(',' + newline); for (i = 1, len = expr.properties.length; i < len; ++i) { result.push(indent); result.push(generateExpression(expr.properties[i], { precedence: Precedence.Sequence, allowIn: true, allowCall: true, type: Syntax.Property })); if (i + 1 < len) { result.push(',' + newline); } } } }); if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { result.push(newline); } result.push(base); result.push('}'); break; case Syntax.ObjectPattern: if (!expr.properties.length) { result = '{}'; break; } multiline = false; if (expr.properties.length === 1) { property = expr.properties[0]; if (property.value.type !== Syntax.Identifier) { multiline = true; } } else { for (i = 0, len = expr.properties.length; i < len; ++i) { property = expr.properties[i]; if (!property.shorthand) { multiline = true; break; } } } result = ['{', multiline ? newline : '' ]; withIndent(function (indent) { for (i = 0, len = expr.properties.length; i < len; ++i) { result.push(multiline ? indent : ''); result.push(generateExpression(expr.properties[i], { precedence: Precedence.Sequence, allowIn: true, allowCall: true })); if (i + 1 < len) { result.push(',' + (multiline ? newline : space)); } } }); if (multiline && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { result.push(newline); } result.push(multiline ? base : ''); result.push('}'); break; case Syntax.ThisExpression: result = 'this'; break; case Syntax.Identifier: result = generateIdentifier(expr); break; case Syntax.Literal: if (expr.hasOwnProperty('raw') && parse) { try { raw = parse(expr.raw).body[0].expression; if (raw.type === Syntax.Literal) { if (raw.value === expr.value) { result = expr.raw; break; } } } catch (e) { // not use raw property } } if (expr.value === null) { result = 'null'; break; } if (typeof expr.value === 'string') { result = escapeString(expr.value); break; } if (typeof expr.value === 'number') { result = generateNumber(expr.value); break; } if (typeof expr.value === 'boolean') { result = expr.value ? 'true' : 'false'; break; } result = generateRegExp(expr.value); break; case Syntax.GeneratorExpression: case Syntax.ComprehensionExpression: // GeneratorExpression should be parenthesized with (...), ComprehensionExpression with [...] // Due to https://bugzilla.mozilla.org/show_bug.cgi?id=883468 position of expr.body can differ in Spidermonkey and ES6 result = (type === Syntax.GeneratorExpression) ? ['('] : ['[']; if (extra.moz.comprehensionExpressionStartsWithAssignment) { fragment = generateExpression(expr.body, { precedence: Precedence.Assignment, allowIn: true, allowCall: true }); result.push(fragment); } if (expr.blocks) { withIndent(function () { for (i = 0, len = expr.blocks.length; i < len; ++i) { fragment = generateExpression(expr.blocks[i], { precedence: Precedence.Sequence, allowIn: true, allowCall: true }); if (i > 0 || extra.moz.comprehensionExpressionStartsWithAssignment) { result = join(result, fragment); } else { result.push(fragment); } } }); } if (expr.filter) { result = join(result, 'if' + space); fragment = generateExpression(expr.filter, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }); if (extra.moz.parenthesizedComprehensionBlock) { result = join(result, [ '(', fragment, ')' ]); } else { result = join(result, fragment); } } if (!extra.moz.comprehensionExpressionStartsWithAssignment) { fragment = generateExpression(expr.body, { precedence: Precedence.Assignment, allowIn: true, allowCall: true }); result = join(result, fragment); } result.push((type === Syntax.GeneratorExpression) ? ')' : ']'); break; case Syntax.ComprehensionBlock: if (expr.left.type === Syntax.VariableDeclaration) { fragment = [ expr.left.kind, noEmptySpace(), generateStatement(expr.left.declarations[0], { allowIn: false }) ]; } else { fragment = generateExpression(expr.left, { precedence: Precedence.Call, allowIn: true, allowCall: true }); } fragment = join(fragment, expr.of ? 'of' : 'in'); fragment = join(fragment, generateExpression(expr.right, { precedence: Precedence.Sequence, allowIn: true, allowCall: true })); if (extra.moz.parenthesizedComprehensionBlock) { result = [ 'for' + space + '(', fragment, ')' ]; } else { result = join('for' + space, fragment); } break; default: throw new Error('Unknown expression type: ' + expr.type); } return toSourceNodeWhenNeeded(result, expr); } function generateStatement(stmt, option) { var i, len, result, node, allowIn, functionBody, directiveContext, fragment, semicolon, isGenerator; allowIn = true; semicolon = ';'; functionBody = false; directiveContext = false; if (option) { allowIn = option.allowIn === undefined || option.allowIn; if (!semicolons && option.semicolonOptional === true) { semicolon = ''; } functionBody = option.functionBody; directiveContext = option.directiveContext; } switch (stmt.type) { case Syntax.BlockStatement: result = ['{', newline]; withIndent(function () { for (i = 0, len = stmt.body.length; i < len; ++i) { fragment = addIndent(generateStatement(stmt.body[i], { semicolonOptional: i === len - 1, directiveContext: functionBody })); result.push(fragment); if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) { result.push(newline); } } }); result.push(addIndent('}')); break; case Syntax.BreakStatement: if (stmt.label) { result = 'break ' + stmt.label.name + semicolon; } else { result = 'break' + semicolon; } break; case Syntax.ContinueStatement: if (stmt.label) { result = 'continue ' + stmt.label.name + semicolon; } else { result = 'continue' + semicolon; } break; case Syntax.DirectiveStatement: if (stmt.raw) { result = stmt.raw + semicolon; } else { result = escapeDirective(stmt.directive) + semicolon; } break; case Syntax.DoWhileStatement: // Because `do 42 while (cond)` is Syntax Error. We need semicolon. result = join('do', maybeBlock(stmt.body)); result = maybeBlockSuffix(stmt.body, result); result = join(result, [ 'while' + space + '(', generateExpression(stmt.test, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }), ')' + semicolon ]); break; case Syntax.CatchClause: withIndent(function () { var guard; result = [ 'catch' + space + '(', generateExpression(stmt.param, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }), ')' ]; if (stmt.guard) { guard = generateExpression(stmt.guard, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }); result.splice(2, 0, ' if ', guard); } }); result.push(maybeBlock(stmt.body)); break; case Syntax.DebuggerStatement: result = 'debugger' + semicolon; break; case Syntax.EmptyStatement: result = ';'; break; case Syntax.ExportDeclaration: result = 'export '; if (stmt.declaration) { // FunctionDeclaration or VariableDeclaration result = [result, generateStatement(stmt.declaration, { semicolonOptional: semicolon === '' })]; break; } break; case Syntax.ExpressionStatement: result = [generateExpression(stmt.expression, { precedence: Precedence.Sequence, allowIn: true, allowCall: true })]; // 12.4 '{', 'function' is not allowed in this position. // wrap expression with parentheses fragment = toSourceNodeWhenNeeded(result).toString(); if (fragment.charAt(0) === '{' || // ObjectExpression (fragment.slice(0, 8) === 'function' && '* ('.indexOf(fragment.charAt(8)) >= 0) || // function or generator (directive && directiveContext && stmt.expression.type === Syntax.Literal && typeof stmt.expression.value === 'string')) { result = ['(', result, ')' + semicolon]; } else { result.push(semicolon); } break; case Syntax.VariableDeclarator: if (stmt.init) { result = [ generateExpression(stmt.id, { precedence: Precedence.Assignment, allowIn: allowIn, allowCall: true }), space, '=', space, generateExpression(stmt.init, { precedence: Precedence.Assignment, allowIn: allowIn, allowCall: true }) ]; } else { result = generatePattern(stmt.id, { precedence: Precedence.Assignment, allowIn: allowIn }); } break; case Syntax.VariableDeclaration: result = [stmt.kind]; // special path for // var x = function () { // }; if (stmt.declarations.length === 1 && stmt.declarations[0].init && stmt.declarations[0].init.type === Syntax.FunctionExpression) { result.push(noEmptySpace()); result.push(generateStatement(stmt.declarations[0], { allowIn: allowIn })); } else { // VariableDeclarator is typed as Statement, // but joined with comma (not LineTerminator). // So if comment is attached to target node, we should specialize. withIndent(function () { node = stmt.declarations[0]; if (extra.comment && node.leadingComments) { result.push('\n'); result.push(addIndent(generateStatement(node, { allowIn: allowIn }))); } else { result.push(noEmptySpace()); result.push(generateStatement(node, { allowIn: allowIn })); } for (i = 1, len = stmt.declarations.length; i < len; ++i) { node = stmt.declarations[i]; if (extra.comment && node.leadingComments) { result.push(',' + newline); result.push(addIndent(generateStatement(node, { allowIn: allowIn }))); } else { result.push(',' + space); result.push(generateStatement(node, { allowIn: allowIn })); } } }); } result.push(semicolon); break; case Syntax.ThrowStatement: result = [join( 'throw', generateExpression(stmt.argument, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }) ), semicolon]; break; case Syntax.TryStatement: result = ['try', maybeBlock(stmt.block)]; result = maybeBlockSuffix(stmt.block, result); if (stmt.handlers) { // old interface for (i = 0, len = stmt.handlers.length; i < len; ++i) { result = join(result, generateStatement(stmt.handlers[i])); if (stmt.finalizer || i + 1 !== len) { result = maybeBlockSuffix(stmt.handlers[i].body, result); } } } else { stmt.guardedHandlers = stmt.guardedHandlers || []; for (i = 0, len = stmt.guardedHandlers.length; i < len; ++i) { result = join(result, generateStatement(stmt.guardedHandlers[i])); if (stmt.finalizer || i + 1 !== len) { result = maybeBlockSuffix(stmt.guardedHandlers[i].body, result); } } // new interface if (stmt.handler) { if (isArray(stmt.handler)) { for (i = 0, len = stmt.handler.length; i < len; ++i) { result = join(result, generateStatement(stmt.handler[i])); if (stmt.finalizer || i + 1 !== len) { result = maybeBlockSuffix(stmt.handler[i].body, result); } } } else { result = join(result, generateStatement(stmt.handler)); if (stmt.finalizer) { result = maybeBlockSuffix(stmt.handler.body, result); } } } } if (stmt.finalizer) { result = join(result, ['finally', maybeBlock(stmt.finalizer)]); } break; case Syntax.SwitchStatement: withIndent(function () { result = [ 'switch' + space + '(', generateExpression(stmt.discriminant, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }), ')' + space + '{' + newline ]; }); if (stmt.cases) { for (i = 0, len = stmt.cases.length; i < len; ++i) { fragment = addIndent(generateStatement(stmt.cases[i], {semicolonOptional: i === len - 1})); result.push(fragment); if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) { result.push(newline); } } } result.push(addIndent('}')); break; case Syntax.SwitchCase: withIndent(function () { if (stmt.test) { result = [ join('case', generateExpression(stmt.test, { precedence: Precedence.Sequence, allowIn: true, allowCall: true })), ':' ]; } else { result = ['default:']; } i = 0; len = stmt.consequent.length; if (len && stmt.consequent[0].type === Syntax.BlockStatement) { fragment = maybeBlock(stmt.consequent[0]); result.push(fragment); i = 1; } if (i !== len && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { result.push(newline); } for (; i < len; ++i) { fragment = addIndent(generateStatement(stmt.consequent[i], {semicolonOptional: i === len - 1 && semicolon === ''})); result.push(fragment); if (i + 1 !== len && !endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) { result.push(newline); } } }); break; case Syntax.IfStatement: withIndent(function () { result = [ 'if' + space + '(', generateExpression(stmt.test, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }), ')' ]; }); if (stmt.alternate) { result.push(maybeBlock(stmt.consequent)); result = maybeBlockSuffix(stmt.consequent, result); if (stmt.alternate.type === Syntax.IfStatement) { result = join(result, ['else ', generateStatement(stmt.alternate, {semicolonOptional: semicolon === ''})]); } else { result = join(result, join('else', maybeBlock(stmt.alternate, semicolon === ''))); } } else { result.push(maybeBlock(stmt.consequent, semicolon === '')); } break; case Syntax.ForStatement: withIndent(function () { result = ['for' + space + '(']; if (stmt.init) { if (stmt.init.type === Syntax.VariableDeclaration) { result.push(generateStatement(stmt.init, {allowIn: false})); } else { result.push(generateExpression(stmt.init, { precedence: Precedence.Sequence, allowIn: false, allowCall: true })); result.push(';'); } } else { result.push(';'); } if (stmt.test) { result.push(space); result.push(generateExpression(stmt.test, { precedence: Precedence.Sequence, allowIn: true, allowCall: true })); result.push(';'); } else { result.push(';'); } if (stmt.update) { result.push(space); result.push(generateExpression(stmt.update, { precedence: Precedence.Sequence, allowIn: true, allowCall: true })); result.push(')'); } else { result.push(')'); } }); result.push(maybeBlock(stmt.body, semicolon === '')); break; case Syntax.ForInStatement: result = generateIterationForStatement('in', stmt, semicolon === ''); break; case Syntax.ForOfStatement: result = generateIterationForStatement('of', stmt, semicolon === ''); break; case Syntax.LabeledStatement: result = [stmt.label.name + ':', maybeBlock(stmt.body, semicolon === '')]; break; case Syntax.Program: len = stmt.body.length; result = [safeConcatenation && len > 0 ? '\n' : '']; for (i = 0; i < len; ++i) { fragment = addIndent( generateStatement(stmt.body[i], { semicolonOptional: !safeConcatenation && i === len - 1, directiveContext: true }) ); result.push(fragment); if (i + 1 < len && !endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) { result.push(newline); } } break; case Syntax.FunctionDeclaration: isGenerator = stmt.generator && !extra.moz.starlessGenerator; result = [ (isGenerator ? 'function*' : 'function'), (isGenerator ? space : noEmptySpace()), generateIdentifier(stmt.id), generateFunctionBody(stmt) ]; break; case Syntax.ReturnStatement: if (stmt.argument) { result = [join( 'return', generateExpression(stmt.argument, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }) ), semicolon]; } else { result = ['return' + semicolon]; } break; case Syntax.WhileStatement: withIndent(function () { result = [ 'while' + space + '(', generateExpression(stmt.test, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }), ')' ]; }); result.push(maybeBlock(stmt.body, semicolon === '')); break; case Syntax.WithStatement: withIndent(function () { result = [ 'with' + space + '(', generateExpression(stmt.object, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }), ')' ]; }); result.push(maybeBlock(stmt.body, semicolon === '')); break; default: throw new Error('Unknown statement type: ' + stmt.type); } // Attach comments if (extra.comment) { result = addCommentsToStatement(stmt, result); } fragment = toSourceNodeWhenNeeded(result).toString(); if (stmt.type === Syntax.Program && !safeConcatenation && newline === '' && fragment.charAt(fragment.length - 1) === '\n') { result = sourceMap ? toSourceNodeWhenNeeded(result).replaceRight(/\s+$/, '') : fragment.replace(/\s+$/, ''); } return toSourceNodeWhenNeeded(result, stmt); } function generate(node, options) { var defaultOptions = getDefaultOptions(), result, pair; if (options != null) { // Obsolete options // // `options.indent` // `options.base` // // Instead of them, we can use `option.format.indent`. 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); indent = options.format.indent.style; if (typeof options.base === 'string') { base = options.base; } else { base = stringRepeat(indent, options.format.indent.base); } } else { options = defaultOptions; indent = options.format.indent.style; base = stringRepeat(indent, 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; space = options.format.space; if (options.format.compact) { newline = space = indent = base = ''; } parentheses = options.format.parentheses; semicolons = options.format.semicolons; safeConcatenation = options.format.safeConcatenation; directive = options.directive; parse = json ? null : options.parse; sourceMap = options.sourceMap; extra = options; if (sourceMap) { if (!exports.browser) { // We assume environment is node.js // And prevent from including source-map by browserify SourceNode = require('source-map').SourceNode; } else { SourceNode = global.sourceMap.SourceNode; } } switch (node.type) { case Syntax.BlockStatement: case Syntax.BreakStatement: case Syntax.CatchClause: case Syntax.ContinueStatement: case Syntax.DirectiveStatement: case Syntax.DoWhileStatement: case Syntax.DebuggerStatement: case Syntax.EmptyStatement: case Syntax.ExpressionStatement: case Syntax.ForStatement: case Syntax.ForInStatement: case Syntax.ForOfStatement: case Syntax.FunctionDeclaration: case Syntax.IfStatement: case Syntax.LabeledStatement: case Syntax.Program: case Syntax.ReturnStatement: case Syntax.SwitchStatement: case Syntax.SwitchCase: case Syntax.ThrowStatement: case Syntax.TryStatement: case Syntax.VariableDeclaration: case Syntax.VariableDeclarator: case Syntax.WhileStatement: case Syntax.WithStatement: result = generateStatement(node); break; case Syntax.AssignmentExpression: case Syntax.ArrayExpression: case Syntax.ArrayPattern: case Syntax.BinaryExpression: case Syntax.CallExpression: case Syntax.ConditionalExpression: case Syntax.FunctionExpression: case Syntax.Identifier: case Syntax.Literal: case Syntax.LogicalExpression: case Syntax.MemberExpression: case Syntax.NewExpression: case Syntax.ObjectExpression: case Syntax.ObjectPattern: case Syntax.Property: case Syntax.SequenceExpression: case Syntax.ThisExpression: case Syntax.UnaryExpression: case Syntax.UpdateExpression: case Syntax.YieldExpression: result = generateExpression(node, { precedence: Precedence.Sequence, allowIn: true, allowCall: true }); break; default: throw new Error('Unknown node type: ' + node.type); } if (!sourceMap) { return result.toString(); } pair = result.toStringWithSourceMap({ file: options.file, sourceRoot: options.sourceMapRoot }); if (options.sourceContent) { pair.map.setSourceContent(options.sourceMap, options.sourceContent); } if (options.sourceMapWithCode) { return pair; } return pair.map.toString(); } FORMAT_MINIFY = { indent: { style: '', base: 0 }, renumber: true, hexadecimal: true, quotes: 'auto', escapeless: true, compact: true, parentheses: false, semicolons: false }; FORMAT_DEFAULTS = getDefaultOptions().format; exports.version = require('./package.json').version; exports.generate = generate; exports.attachComments = estraverse.attachComments; exports.browser = false; exports.FORMAT_MINIFY = FORMAT_MINIFY; exports.FORMAT_DEFAULTS = FORMAT_DEFAULTS; }()); /* vim: set sw=4 ts=4 et tw=80 : */