You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2019/12/18 17:56:37 UTC
[couchdb-escodegen] 06/11: Update gh-pages
This is an automated email from the ASF dual-hosted git repository.
davisp pushed a commit to branch gh-pages
in repository https://gitbox.apache.org/repos/asf/couchdb-escodegen.git
commit b660de6b026d7d2b49092f10e0f59ed1d7fd46f7
Author: Constellation <ut...@gmail.com>
AuthorDate: Mon Jan 14 19:05:42 2013 +0900
Update gh-pages
---
escodegen.js | 1826 ++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 1272 insertions(+), 554 deletions(-)
diff --git a/escodegen.js b/escodegen.js
index 59087f6..5d8400e 100644
--- a/escodegen.js
+++ b/escodegen.js
@@ -1,12 +1,13 @@
/*
+ Copyright (C) 2012 Michael Ficarra <es...@michael.ficarra.me>
+ Copyright (C) 2012 Robert Gust-Bardon <do...@robert.gust-bardon.org>
Copyright (C) 2012 John Freeman <jf...@gmail.com>
- Copyright (C) 2012 Ariya Hidayat <ar...@gmail.com>
+ Copyright (C) 2011-2012 Ariya Hidayat <ar...@gmail.com>
Copyright (C) 2012 Mathias Bynens <ma...@qiwi.be>
Copyright (C) 2012 Joost-Wim Boekesteijn <jo...@boekesteijn.nl>
Copyright (C) 2012 Kris Kowal <kr...@cixar.com>
Copyright (C) 2012 Yusuke Suzuki <ut...@gmail.com>
Copyright (C) 2012 Arpad Borsos <ar...@googlemail.com>
- Copyright (C) 2011 Ariya Hidayat <ar...@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -30,32 +31,64 @@
*/
/*jslint bitwise:true */
-/*global escodegen:true, exports:true, generateStatement: true*/
+/*global escodegen:true, exports:true, generateStatement:true, generateExpression:true, generateFunctionBody:true, process:true, require:true, define:true*/
-(function (exports) {
+(function (factory, global) {
+ 'use strict';
+
+ // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
+ // and plain browser loading,
+ if (typeof define === 'function' && define.amd) {
+ define(['exports'], function (exports) {
+ factory(exports, global);
+ });
+ } else if (typeof exports !== 'undefined') {
+ factory(exports, global);
+ } else {
+ factory((global.escodegen = {}), global);
+ }
+}(function (exports, global) {
'use strict';
var Syntax,
Precedence,
BinaryPrecedence,
+ Regex,
VisitorKeys,
VisitorOption,
+ SourceNode,
isArray,
base,
indent,
+ json,
+ renumber,
+ hexadecimal,
+ quotes,
+ escapeless,
+ newline,
+ space,
+ parentheses,
+ semicolons,
+ safeConcatenation,
+ directive,
extra,
- parse;
+ parse,
+ sourceMap;
Syntax = {
AssignmentExpression: 'AssignmentExpression',
ArrayExpression: 'ArrayExpression',
+ ArrayPattern: 'ArrayPattern',
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',
@@ -72,6 +105,7 @@
MemberExpression: 'MemberExpression',
NewExpression: 'NewExpression',
ObjectExpression: 'ObjectExpression',
+ ObjectPattern: 'ObjectPattern',
Program: 'Program',
Property: 'Property',
ReturnStatement: 'ReturnStatement',
@@ -86,7 +120,9 @@
VariableDeclaration: 'VariableDeclaration',
VariableDeclarator: 'VariableDeclarator',
WhileStatement: 'WhileStatement',
- WithStatement: 'WithStatement'
+ WithStatement: 'WithStatement',
+ YieldExpression: 'YieldExpression',
+
};
Precedence = {
@@ -95,8 +131,8 @@
Conditional: 2,
LogicalOR: 3,
LogicalAND: 4,
- LogicalXOR: 5,
- BitwiseOR: 6,
+ BitwiseOR: 5,
+ BitwiseXOR: 6,
BitwiseAND: 7,
Equality: 8,
Relational: 9,
@@ -114,13 +150,15 @@
BinaryPrecedence = {
'||': Precedence.LogicalOR,
'&&': Precedence.LogicalAND,
- '^': Precedence.LogicalXOR,
'|': 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,
@@ -137,6 +175,10 @@
'/': Precedence.Multiplicative
};
+ Regex = {
+ NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u08 [...]
+ };
+
function getDefaultOptions() {
// default options
return {
@@ -149,20 +191,28 @@
style: ' ',
base: 0,
adjustMultilineComment: false
- }
- }
+ },
+ json: false,
+ renumber: false,
+ hexadecimal: false,
+ quotes: 'single',
+ escapeless: false,
+ compact: false,
+ parentheses: true,
+ semicolons: true,
+ safeConcatenation: false
+ },
+ moz: {
+ starlessGenerator: false,
+ parenthesizedComprehensionBlock: false
+ },
+ sourceMap: null,
+ sourceMapWithCode: false,
+ directive: false,
+ verbatim: null
};
}
- function unicodeEscape(ch) {
- var result, i;
- result = ch.charCodeAt(0).toString(16);
- for (i = result.length; i < 4; i += 1) {
- result = '0' + result;
- }
- return '\\u' + result;
- }
-
function stringToArray(str) {
var length = str.length,
result = [],
@@ -192,8 +242,73 @@
};
}
- function endsWithLineTerminator(value) {
- return (/(?:\r\n|[\n\r])$/).test(value);
+ // Fallback for the non SourceMap environment
+ function SourceNodeMock(line, column, filename, chunk) {
+ var result = [];
+
+ function flatten(input) {
+ var i, iz;
+ if (isArray(input)) {
+ for (i = 0, iz = input.length; i < iz; ++i) {
+ flatten(input[i]);
+ }
+ } else if (input instanceof SourceNodeMock) {
+ result.push(input);
+ } else if (typeof input === 'string' && input) {
+ result.push(input);
+ }
+ }
+
+ flatten(chunk);
+ this.children = result;
+ }
+
+ SourceNodeMock.prototype.toString = function toString() {
+ var res = '', i, iz, node;
+ for (i = 0, iz = this.children.length; i < iz; ++i) {
+ node = this.children[i];
+ if (node instanceof SourceNodeMock) {
+ res += node.toString();
+ } else {
+ res += node;
+ }
+ }
+ return res;
+ };
+
+ SourceNodeMock.prototype.replaceRight = function replaceRight(pattern, replacement) {
+ var last = this.children[this.children.length - 1];
+ if (last instanceof SourceNodeMock) {
+ last.replaceRight(pattern, replacement);
+ } else if (typeof last === 'string') {
+ this.children[this.children.length - 1] = last.replace(pattern, replacement);
+ } else {
+ this.children.push(''.replace(pattern, replacement));
+ }
+ return this;
+ };
+
+ SourceNodeMock.prototype.join = function join(sep) {
+ var i, iz, result;
+ result = [];
+ iz = this.children.length;
+ if (iz > 0) {
+ for (i = 0, iz -= 1; i < iz; ++i) {
+ result.push(this.children[i], sep);
+ }
+ result.push(this.children[iz]);
+ this.children = result;
+ }
+ return this;
+ };
+
+ function hasLineTerminator(str) {
+ return /[\r\n]/g.test(str);
+ }
+
+ function endsWithLineTerminator(str) {
+ var ch = str.charAt(str.length - 1);
+ return ch === '\r' || ch === '\n';
}
function shallowCopy(obj) {
@@ -245,8 +360,142 @@
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.charAt(0) === '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.charAt(temp.length + pos - 1) === '0') {
+ pos -= 1;
+ }
+ if (pos !== 0) {
+ exponent -= pos;
+ temp = temp.slice(0, pos);
+ }
+ if (exponent !== 0) {
+ temp += 'e' + exponent;
+ }
+ if ((temp.length < result.length ||
+ (hexadecimal && value > 1e12 && Math.floor(value) === value && (temp = '0x' + value.toString(16)).length < result.length)) &&
+ +temp === value) {
+ result = temp;
+ }
+
+ return result;
+ }
+
+ function escapeAllowedCharacter(ch, next) {
+ var code = ch.charCodeAt(0), hex = code.toString(16), result = '\\';
+
+ switch (ch) {
+ case '\b':
+ result += 'b';
+ break;
+ case '\f':
+ result += 'f';
+ break;
+ case '\t':
+ result += 't';
+ break;
+ default:
+ if (json || code > 0xff) {
+ result += 'u' + '0000'.slice(hex.length) + hex;
+ } else if (ch === '\u0000' && '0123456789'.indexOf(next) < 0) {
+ result += '0';
+ } else if (ch === '\v') {
+ result += 'v';
+ } else {
+ result += 'x' + '00'.slice(hex.length) + hex;
+ }
+ break;
+ }
+
+ return result;
+ }
+
+ function escapeDisallowedCharacter(ch) {
+ var result = '\\';
+ switch (ch) {
+ case '\\':
+ result += '\\';
+ break;
+ case '\n':
+ result += 'n';
+ break;
+ case '\r':
+ result += 'r';
+ break;
+ case '\u2028':
+ result += 'u2028';
+ break;
+ case '\u2029':
+ result += 'u2029';
+ break;
+ default:
+ throw new Error('Incorrectly classified character');
+ }
+
+ return result;
+ }
+
+ function escapeDirective(str) {
+ var i, iz, ch, single, buf, quote;
+
+ buf = str;
+ if (typeof buf[0] === 'undefined') {
+ buf = stringToArray(buf);
+ }
+
+ quote = quotes === 'double' ? '"' : '\'';
+ for (i = 0, iz = buf.length; i < iz; i += 1) {
+ ch = buf[i];
+ if (ch === '\'') {
+ quote = '"';
+ break;
+ } else if (ch === '"') {
+ quote = '\'';
+ break;
+ } else if (ch === '\\') {
+ i += 1;
+ }
+ }
+
+ return quote + str + quote;
+ }
+
function escapeString(str) {
- var result = '', i, len, ch;
+ var result = '', i, len, ch, next, singleQuotes = 0, doubleQuotes = 0, single;
if (typeof str[0] === 'undefined') {
str = stringToArray(str);
@@ -254,57 +503,112 @@
for (i = 0, len = str.length; i < len; i += 1) {
ch = str[i];
- if ('\'\\\b\f\n\r\t'.indexOf(ch) >= 0) {
+ if (ch === '\'') {
+ singleQuotes += 1;
+ } else if (ch === '"') {
+ doubleQuotes += 1;
+ } else if (ch === '/' && json) {
+ result += '\\';
+ } else if ('\\\n\r\u2028\u2029'.indexOf(ch) >= 0) {
+ result += escapeDisallowedCharacter(ch);
+ continue;
+ } else if ((json && ch < ' ') || !(json || escapeless || (ch >= ' ' && ch <= '~'))) {
+ result += escapeAllowedCharacter(ch, str[i + 1]);
+ continue;
+ }
+ result += ch;
+ }
+
+ single = !(quotes === 'double' || (quotes === 'auto' && doubleQuotes < singleQuotes));
+ str = result;
+ result = single ? '\'' : '"';
+
+ if (typeof str[0] === 'undefined') {
+ str = stringToArray(str);
+ }
+
+ for (i = 0, len = str.length; i < len; i += 1) {
+ ch = str[i];
+ if ((ch === '\'' && single) || (ch === '"' && !single)) {
result += '\\';
- switch (ch) {
- case '\'':
- result += '\'';
- break;
- case '\\':
- result += '\\';
- break;
- case '\b':
- result += 'b';
- break;
- case '\f':
- result += 'f';
- break;
- case '\n':
- result += 'n';
- break;
- case '\r':
- result += 'r';
- break;
- case '\t':
- result += 't';
- break;
- }
- } else if (ch < ' ' || ch.charCodeAt(0) >= 0x80) {
- result += unicodeEscape(ch);
- } else {
- result += ch;
}
+ result += ch;
}
- return '\'' + result + '\'';
+ return result + (single ? '\'' : '"');
}
function isWhiteSpace(ch) {
- return (ch === ' ') || (ch === '\u0009') || (ch === '\u000B') ||
- (ch === '\u000C') || (ch === '\u00A0') ||
- (ch.charCodeAt(0) >= 0x1680 &&
- '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(ch) >= 0);
+ return '\t\v\f \xa0'.indexOf(ch) >= 0 || (ch.charCodeAt(0) >= 0x1680 && '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\ufeff'.indexOf(ch) >= 0);
+ }
+
+ function isLineTerminator(ch) {
+ return '\n\r\u2028\u2029'.indexOf(ch) >= 0;
+ }
+
+ function isIdentifierPart(ch) {
+ return (ch === '$') || (ch === '_') || (ch === '\\') ||
+ (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
+ ((ch >= '0') && (ch <= '9')) ||
+ ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch));
+ }
+
+ function toSourceNode(generated, node) {
+ if (node == null) {
+ if (generated instanceof SourceNode) {
+ return generated;
+ } else {
+ node = {};
+ }
+ }
+ if (node.loc == null) {
+ return new SourceNode(null, null, sourceMap, generated);
+ }
+ return new SourceNode(node.loc.start.line, node.loc.start.column, (sourceMap === true ? node.loc.source || null : sourceMap), generated);
+ }
+
+ function join(left, right) {
+ var leftSource = toSourceNode(left).toString(),
+ rightSource = toSourceNode(right).toString(),
+ leftChar = leftSource.charAt(leftSource.length - 1),
+ rightChar = rightSource.charAt(0);
+
+ if (((leftChar === '+' || leftChar === '-') && leftChar === rightChar) || (isIdentifierPart(leftChar) && isIdentifierPart(rightChar))) {
+ return [left, ' ', right];
+ } else if (isWhiteSpace(leftChar) || isLineTerminator(leftChar) || isWhiteSpace(rightChar) || isLineTerminator(rightChar)) {
+ return [left, right];
+ }
+ return [left, space, right];
}
function addIndent(stmt) {
- return base + stmt;
+ return [base, stmt];
+ }
+
+ function withIndent(fn) {
+ var previousBase, result;
+ previousBase = base;
+ base += indent;
+ result = fn.call(this, base);
+ base = previousBase;
+ return result;
}
- function adjustMultilineComment(value) {
- var array, i, len, line, j, ch, spaces;
+ function calculateSpaces(str) {
+ var i;
+ for (i = str.length - 1; i >= 0; i -= 1) {
+ if (isLineTerminator(str.charAt(i))) {
+ break;
+ }
+ }
+ return (str.length - 1) - i;
+ }
+
+ function adjustMultilineComment(value, specialBase) {
+ var array, i, len, line, j, ch, spaces, previousBase;
- spaces = Number.MAX_VALUE;
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 += 1) {
@@ -318,95 +622,212 @@
}
}
- if (spaces % 2 === 1) {
- // /*
- // *
- // */
- // If spaces are odd number, above pattern is considered.
- // We waste 1 space.
- spaces -= 1;
+ 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 -= 1;
+ }
+ previousBase = base;
}
+
for (i = 1, len = array.length; i < len; i += 1) {
- array[i] = addIndent(array[i].slice(spaces));
+ array[i] = toSourceNode(addIndent(array[i].slice(spaces))).join('');
}
+
+ base = previousBase;
+
return array.join('\n');
}
- function generateComment(comment) {
+ function generateComment(comment, specialBase) {
if (comment.type === 'Line') {
- // Esprima always produce last line comment with LineTerminator
- return '//' + comment.value;
+ 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 + '*/');
+ return adjustMultilineComment('/*' + comment.value + '*/', specialBase);
}
return '/*' + comment.value + '*/';
}
+ function addCommentsToStatement(stmt, result) {
+ var i, len, comment, save, node, 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(toSourceNode(result).toString())) {
+ result.push('\n');
+ }
+
+ for (i = 1, len = stmt.leadingComments.length; i < len; i += 1) {
+ comment = stmt.leadingComments[i];
+ fragment = [generateComment(comment)];
+ if (!endsWithLineTerminator(toSourceNode(fragment).toString())) {
+ fragment.push('\n');
+ }
+ result.push(addIndent(fragment));
+ }
+
+ result.push(addIndent(save));
+ }
+
+ if (stmt.trailingComments) {
+ tailingToStatement = !endsWithLineTerminator(toSourceNode(result).toString());
+ specialBase = stringRepeat(' ', calculateSpaces(toSourceNode([base, result, indent]).toString()));
+ for (i = 0, len = stmt.trailingComments.length; i < len; i += 1) {
+ 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(toSourceNode(result).toString())) {
+ result = [result, '\n'];
+ }
+ }
+ }
+
+ return result;
+ }
+
function parenthesize(text, current, should) {
if (current < should) {
- return '(' + text + ')';
+ return ['(', text, ')'];
}
return text;
}
- function maybeBlock(stmt, suffix) {
- var previousBase, result;
+ function maybeBlock(stmt, semicolonOptional, functionBody) {
+ var result, noLeadingComment;
- if (stmt.type === Syntax.BlockStatement && (!extra.comment || !stmt.leadingComments)) {
- result = ' ' + generateStatement(stmt);
- if (suffix) {
- return result + ' ';
- }
- return result;
- }
+ noLeadingComment = !extra.comment || !stmt.leadingComments;
- if (stmt.type === Syntax.EmptyStatement && (!extra.comment || !stmt.leadingComments)) {
- result = ';';
- } else {
- previousBase = base;
- base += indent;
- result = '\n' + addIndent(generateStatement(stmt));
- base = previousBase;
+ if (stmt.type === Syntax.BlockStatement && noLeadingComment) {
+ return [space, generateStatement(stmt, { functionBody: functionBody })];
}
- if (suffix) {
- return result + '\n' + addIndent('');
+ 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(toSourceNode(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 toSourceNode(result, expr);
+ }
+
function generateFunctionBody(node) {
- var result, i, len;
- result = '(';
+ var result, i, len, expr;
+ result = ['('];
for (i = 0, len = node.params.length; i < len; i += 1) {
- result += node.params[i].name;
- if ((i + 1) < len) {
- result += ', ';
+ result.push(node.params[i].name);
+ if (i + 1 < len) {
+ result.push(',' + space);
}
}
- return result + ')' + maybeBlock(node.body);
+ 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 generateExpression(expr, option) {
- var result, precedence, currentPrecedence, previousBase, i, len, raw, allowIn, allowCall;
+ var result, precedence, currentPrecedence, i, len, raw, fragment, multiline, leftChar, leftSource, rightChar, rightSource, allowIn, allowCall, allowUnparenthesizedNew, property, key, value;
precedence = option.precedence;
allowIn = option.allowIn;
allowCall = option.allowCall;
+ if (extra.verbatim && expr.hasOwnProperty(extra.verbatim)) {
+ return generateVerbatim(expr, option);
+ }
+
switch (expr.type) {
case Syntax.SequenceExpression:
- result = '';
+ result = [];
allowIn |= (Precedence.Sequence < precedence);
for (i = 0, len = expr.expressions.length; i < len; i += 1) {
- result += generateExpression(expr.expressions[i], {
+ result.push(generateExpression(expr.expressions[i], {
precedence: Precedence.Assignment,
allowIn: allowIn,
allowCall: true
- });
- if ((i + 1) < len) {
- result += ', ';
+ }));
+ if (i + 1 < len) {
+ result.push(',' + space);
}
}
result = parenthesize(result, Precedence.Sequence, precedence);
@@ -415,16 +836,19 @@
case Syntax.AssignmentExpression:
allowIn |= (Precedence.Assignment < precedence);
result = parenthesize(
- generateExpression(expr.left, {
- precedence: Precedence.Call,
- allowIn: allowIn,
- allowCall: true
- }) + ' ' + expr.operator + ' ' +
+ [
+ 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
);
@@ -433,21 +857,25 @@
case Syntax.ConditionalExpression:
allowIn |= (Precedence.Conditional < precedence);
result = parenthesize(
- generateExpression(expr.test, {
- precedence: Precedence.LogicalOR,
- allowIn: allowIn,
- allowCall: true
- }) + ' ? ' +
+ [
+ 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
);
@@ -459,20 +887,30 @@
allowIn |= (currentPrecedence < precedence);
- result =
+ result = join(
generateExpression(expr.left, {
precedence: currentPrecedence,
allowIn: allowIn,
allowCall: true
- }) + ' ' + expr.operator + ' ' +
- generateExpression(expr.right, {
- precedence: currentPrecedence + 1,
- allowIn: allowIn,
- allowCall: true
- });
+ }),
+ expr.operator
+ );
+
+ fragment = generateExpression(expr.right, {
+ precedence: currentPrecedence + 1,
+ allowIn: allowIn,
+ allowCall: true
+ });
+
+ if (expr.operator === '/' && fragment.toString().charAt(0) === '/') {
+ // If '/' concats with '/', it is interpreted as comment start
+ result.push(' ', fragment);
+ } else {
+ result = join(result, fragment);
+ }
if (expr.operator === 'in' && !allowIn) {
- result = '(' + result + ')';
+ result = ['(', result, ')'];
} else {
result = parenthesize(result, currentPrecedence, precedence);
}
@@ -480,121 +918,167 @@
break;
case Syntax.CallExpression:
- result = generateExpression(expr.callee, {
+ result = [generateExpression(expr.callee, {
precedence: Precedence.Call,
allowIn: true,
- allowCall: true
- });
+ allowCall: true,
+ allowUnparenthesizedNew: false
+ })];
- result += '(';
+ result.push('(');
for (i = 0, len = expr['arguments'].length; i < len; i += 1) {
- result += generateExpression(expr['arguments'][i], {
+ result.push(generateExpression(expr['arguments'][i], {
precedence: Precedence.Assignment,
allowIn: true,
allowCall: true
- });
- if ((i + 1) < len) {
- result += ', ';
+ }));
+ if (i + 1 < len) {
+ result.push(',' + space);
}
}
- result += ')';
+ result.push(')');
if (!allowCall) {
- result = '(' + result + ')';
+ result = ['(', result, ')'];
} else {
result = parenthesize(result, Precedence.Call, precedence);
}
break;
case Syntax.NewExpression:
- result = 'new ' + generateExpression(expr.callee, {
- precedence: Precedence.New,
- allowIn: true,
- allowCall: false
- });
+ len = expr['arguments'].length;
+ allowUnparenthesizedNew = option.allowUnparenthesizedNew === undefined || option.allowUnparenthesizedNew;
- result += '(';
- for (i = 0, len = expr['arguments'].length; i < len; i += 1) {
- result += generateExpression(expr['arguments'][i], {
- precedence: Precedence.Assignment,
+ result = join(
+ 'new',
+ generateExpression(expr.callee, {
+ precedence: Precedence.New,
allowIn: true,
- allowCall: true
- });
- if ((i + 1) < len) {
- result += ', ';
+ allowCall: false,
+ allowUnparenthesizedNew: allowUnparenthesizedNew && !parentheses && len === 0
+ })
+ );
+
+ if (!allowUnparenthesizedNew || parentheses || len > 0) {
+ result.push('(');
+ for (i = 0; i < len; i += 1) {
+ result.push(generateExpression(expr['arguments'][i], {
+ precedence: Precedence.Assignment,
+ allowIn: true,
+ allowCall: true
+ }));
+ if (i + 1 < len) {
+ result.push(',' + space);
+ }
}
+ result.push(')');
}
- result += ')';
result = parenthesize(result, Precedence.New, precedence);
break;
case Syntax.MemberExpression:
- result = generateExpression(expr.object, {
+ result = [generateExpression(expr.object, {
precedence: Precedence.Call,
allowIn: true,
- allowCall: allowCall
- });
+ allowCall: allowCall,
+ allowUnparenthesizedNew: false
+ })];
if (expr.computed) {
- result += '[' + generateExpression(expr.property, {
+ result.push('[', generateExpression(expr.property, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: allowCall
- }) + ']';
+ }), ']');
} else {
if (expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') {
if (result.indexOf('.') < 0) {
if (!/[eExX]/.test(result) && !(result.length >= 2 && result[0] === '0')) {
- result += '.';
+ result.push('.');
}
}
}
- result += '.' + expr.property.name;
+ result.push('.' + expr.property.name);
}
result = parenthesize(result, Precedence.Member, precedence);
break;
case Syntax.UnaryExpression:
- result = expr.operator;
- if (result.length > 2) {
- result += ' ';
+ 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 = toSourceNode(result).toString();
+ leftChar = leftSource.charAt(leftSource.length - 1);
+ rightChar = fragment.toString().charAt(0);
+
+ if (((leftChar === '+' || leftChar === '-') && leftChar === rightChar) || (isIdentifierPart(leftChar) && isIdentifierPart(rightChar))) {
+ 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.Assignment,
+ allowIn: true,
+ allowCall: true
+ })
+ );
}
- result = parenthesize(
- result + generateExpression(expr.argument, {
- precedence: Precedence.Unary + (
- expr.argument.type === Syntax.UnaryExpression &&
- expr.operator.length < 3 &&
- expr.argument.operator === expr.operator ? 1 : 0
- ),
- allowIn: true,
- allowCall: true
- }),
- Precedence.Unary,
- precedence
- );
break;
case Syntax.UpdateExpression:
if (expr.prefix) {
result = parenthesize(
- expr.operator +
+ [
+ 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,
+ [
+ generateExpression(expr.argument, {
+ precedence: Precedence.Postfix,
+ allowIn: true,
+ allowCall: true
+ }),
+ expr.operator
+ ],
Precedence.Postfix,
precedence
);
@@ -602,60 +1086,94 @@
break;
case Syntax.FunctionExpression:
- result = 'function ';
+ result = 'function';
if (expr.id) {
- result += expr.id.name;
+ result += ' ' + expr.id.name;
+ } else {
+ result += space;
}
- result += generateFunctionBody(expr);
+
+ result = [result, generateFunctionBody(expr)];
break;
+ case Syntax.ArrayPattern:
case Syntax.ArrayExpression:
if (!expr.elements.length) {
result = '[]';
break;
}
- result = '[\n';
- previousBase = base;
- base += indent;
- for (i = 0, len = expr.elements.length; i < len; i += 1) {
- if (!expr.elements[i]) {
- result += addIndent('');
- if ((i + 1) === len) {
- result += ',';
+ multiline = expr.elements.length > 1;
+ result = ['[', multiline ? newline : ''];
+ withIndent(function (indent) {
+ for (i = 0, len = expr.elements.length; i < len; i += 1) {
+ if (!expr.elements[i]) {
+ if (multiline) {
+ result.push(indent);
+ }
+ if (i + 1 === len) {
+ result.push(',');
+ }
+ } else {
+ result.push(multiline ? indent : '', generateExpression(expr.elements[i], {
+ precedence: Precedence.Assignment,
+ allowIn: true,
+ allowCall: true
+ }));
+ }
+ if (i + 1 < len) {
+ result.push(',' + (multiline ? newline : space));
}
- } else {
- result += addIndent(generateExpression(expr.elements[i], {
- precedence: Precedence.Assignment,
- allowIn: true,
- allowCall: true
- }));
- }
- if ((i + 1) < len) {
- result += ',\n';
}
+ });
+ if (multiline && !endsWithLineTerminator(toSourceNode(result).toString())) {
+ result.push(newline);
}
- base = previousBase;
- result += '\n' + addIndent(']');
+ result.push(multiline ? base : '', ']');
break;
case Syntax.Property:
if (expr.kind === 'get' || expr.kind === 'set') {
- result = expr.kind + ' ' + generateExpression(expr.key, {
- precedence: Precedence.Sequence,
- allowIn: true,
- allowCall: true
- }) + generateFunctionBody(expr.value);
- } else {
- result =
+ result = [
+ expr.kind + ' ',
generateExpression(expr.key, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
- }) + ': ' + generateExpression(expr.value, {
- precedence: Precedence.Assignment,
+ }),
+ 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
+ }), 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;
@@ -664,21 +1182,95 @@
result = '{}';
break;
}
- result = '{\n';
- previousBase = base;
- base += indent;
- for (i = 0, len = expr.properties.length; i < len; i += 1) {
- result += addIndent(generateExpression(expr.properties[i], {
+ multiline = expr.properties.length > 1;
+
+ withIndent(function (indent) {
+ fragment = generateExpression(expr.properties[0], {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
- }));
- if ((i + 1) < len) {
- result += ',\n';
+ });
+ });
+
+ if (!multiline) {
+ // issues 4
+ // Do not transform from
+ // dejavu.Class.declare({
+ // method2: function () {}
+ // });
+ // to
+ // dejavu.Class.declare({method2: function () {
+ // }});
+ if (!hasLineTerminator(toSourceNode(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 += 1) {
+ result.push(indent, generateExpression(expr.properties[i], {
+ precedence: Precedence.Sequence,
+ allowIn: true,
+ allowCall: true
+ }));
+ if (i + 1 < len) {
+ result.push(',' + newline);
+ }
+ }
+ }
+ });
+
+ if (!endsWithLineTerminator(toSourceNode(result).toString())) {
+ result.push(newline);
+ }
+ result.push(base, '}');
+ 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 += 1) {
+ 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 += 1) {
+ result.push(multiline ? indent : '', generateExpression(expr.properties[i], {
+ precedence: Precedence.Sequence,
+ allowIn: true,
+ allowCall: true
+ }));
+ if (i + 1 < len) {
+ result.push(',' + (multiline ? newline : space));
+ }
}
+ });
+
+ if (multiline && !endsWithLineTerminator(toSourceNode(result).toString())) {
+ result.push(newline);
}
- base = previousBase;
- result += '\n' + addIndent('}');
+ result.push(multiline ? base : '', '}');
break;
case Syntax.ThisExpression:
@@ -709,90 +1301,185 @@
break;
}
- if (typeof expr.value === 'string') {
- result = escapeString(expr.value);
- break;
+ if (typeof expr.value === 'string') {
+ result = escapeString(expr.value);
+ break;
+ }
+
+ if (typeof expr.value === 'number') {
+ result = generateNumber(expr.value);
+ break;
+ }
+
+ result = expr.value.toString();
+ break;
+
+ case Syntax.ComprehensionExpression:
+ result = [
+ '[',
+ generateExpression(expr.body, {
+ precedence: Precedence.Assignment,
+ allowIn: true,
+ allowCall: true
+ })
+ ];
+
+ if (expr.blocks) {
+ for (i = 0, len = expr.blocks.length; i < len; i += 1) {
+ fragment = generateExpression(expr.blocks[i], {
+ precedence: Precedence.Sequence,
+ allowIn: true,
+ allowCall: true
+ });
+ result = join(result, 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);
+ }
+ }
+ result.push(']');
+ break;
+
+ case Syntax.ComprehensionBlock:
+ if (expr.left.type === Syntax.VariableDeclaration) {
+ fragment = [
+ expr.left.kind + ' ',
+ generateStatement(expr.left.declarations[0], {
+ allowIn: false
+ })
+ ];
+ } else {
+ fragment = generateExpression(expr.left, {
+ precedence: Precedence.Call,
+ allowIn: true,
+ allowCall: true
+ });
}
- if (typeof expr.value === 'number' && expr.value === Infinity) {
- // Infinity is variable
- result = '1e+1000';
- break;
- }
+ fragment = join(fragment, expr.of ? 'of' : 'in');
+ fragment = join(fragment, generateExpression(expr.right, {
+ precedence: Precedence.Sequence,
+ allowIn: true,
+ allowCall: true
+ }));
- result = expr.value.toString();
+ if (extra.moz.parenthesizedComprehensionBlock) {
+ result = [ 'for' + space + '(', fragment, ')' ];
+ } else {
+ result = join('for' + space, fragment);
+ }
break;
default:
- break;
- }
-
- if (result === undefined) {
throw new Error('Unknown expression type: ' + expr.type);
}
- return result;
+
+ return toSourceNode(result, expr);
}
function generateStatement(stmt, option) {
- var i, len, result, previousBase, comment, save, ret, node, allowIn;
+ var i, len, result, node, allowIn, functionBody, directiveContext, fragment, semicolon;
allowIn = true;
+ semicolon = ';';
+ functionBody = false;
+ directiveContext = false;
if (option) {
- allowIn = option.allowIn;
+ 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 = '{\n';
+ result = ['{', newline];
- previousBase = base;
- base += indent;
- for (i = 0, len = stmt.body.length; i < len; i += 1) {
- result += addIndent(generateStatement(stmt.body[i])) + '\n';
- }
- base = previousBase;
+ withIndent(function () {
+ for (i = 0, len = stmt.body.length; i < len; i += 1) {
+ fragment = addIndent(generateStatement(stmt.body[i], {
+ semicolonOptional: i === len - 1,
+ directiveContext: functionBody
+ }));
+ result.push(fragment);
+ if (!endsWithLineTerminator(toSourceNode(fragment).toString())) {
+ result.push(newline);
+ }
+ }
+ });
- result += addIndent('}');
+ result.push(addIndent('}'));
break;
case Syntax.BreakStatement:
if (stmt.label) {
- result = 'break ' + stmt.label.name + ';';
+ result = 'break ' + stmt.label.name + semicolon;
} else {
- result = 'break;';
+ result = 'break' + semicolon;
}
break;
case Syntax.ContinueStatement:
if (stmt.label) {
- result = 'continue ' + stmt.label.name + ';';
+ result = 'continue ' + stmt.label.name + semicolon;
+ } else {
+ result = 'continue' + semicolon;
+ }
+ break;
+
+ case Syntax.DirectiveStatement:
+ if (stmt.raw) {
+ result = stmt.raw + semicolon;
} else {
- result = 'continue;';
+ result = escapeDirective(stmt.directive) + semicolon;
}
break;
case Syntax.DoWhileStatement:
- result = 'do' + maybeBlock(stmt.body, true) + 'while (' + generateExpression(stmt.test, {
- precedence: Precedence.Sequence,
- allowIn: true,
- allowCall: true
- }) + ');';
+ // 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:
- previousBase = base;
- base += indent;
- result = ' catch (' + generateExpression(stmt.param, {
- precedence: Precedence.Sequence,
- allowIn: true,
- allowCall: true
- }) + ')';
- base = previousBase;
- result += maybeBlock(stmt.body);
+ withIndent(function () {
+ result = [
+ 'catch' + space + '(',
+ generateExpression(stmt.param, {
+ precedence: Precedence.Sequence,
+ allowIn: true,
+ allowCall: true
+ }),
+ ')'
+ ];
+ });
+ result.push(maybeBlock(stmt.body));
break;
case Syntax.DebuggerStatement:
- result = 'debugger;';
+ result = 'debugger' + semicolon;
break;
case Syntax.EmptyStatement:
@@ -800,358 +1487,356 @@
break;
case Syntax.ExpressionStatement:
- result = generateExpression(stmt.expression, {
+ result = [generateExpression(stmt.expression, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
- });
+ })];
// 12.4 '{', 'function' is not allowed in this position.
- // wrap espression with parentheses
- if (result[0] === '{' || result.indexOf('function ') === 0) {
- result = '(' + result + ');';
+ // wrap expression with parentheses
+ if (result.toString().charAt(0) === '{' || (result.toString().slice(0, 8) === 'function' && " (".indexOf(result.toString().charAt(8)) >= 0) || (directive && directiveContext && stmt.expression.type === Syntax.Literal && typeof stmt.expression.value === 'string')) {
+ result = ['(', result, ')' + semicolon];
} else {
- result += ';';
+ result.push(semicolon);
}
break;
case Syntax.VariableDeclarator:
if (stmt.init) {
- result = stmt.id.name + ' = ' + generateExpression(stmt.init, {
- precedence: Precedence.Assignment,
- allowIn: allowIn,
- allowCall: true
- });
+ 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 = stmt.id.name;
}
break;
case Syntax.VariableDeclaration:
- result = stmt.kind;
+ 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 += ' ' + generateStatement(stmt.declarations[0], {
+ 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.
- previousBase = base;
- base += indent;
-
- node = stmt.declarations[0];
- if (extra.comment && node.leadingComments) {
- result += '\n' + addIndent(generateStatement(node, {
- allowIn: allowIn
- }));
- } else {
- result += ' ' + generateStatement(node, {
- allowIn: allowIn
- });
- }
-
- for (i = 1, len = stmt.declarations.length; i < len; i += 1) {
- node = stmt.declarations[i];
+ withIndent(function () {
+ node = stmt.declarations[0];
if (extra.comment && node.leadingComments) {
- result += ',\n' + addIndent(generateStatement(node, {
+ result.push('\n', addIndent(generateStatement(node, {
allowIn: allowIn
- }));
+ })));
} else {
- result += ', ' + generateStatement(node, {
+ result.push(' ', generateStatement(node, {
allowIn: allowIn
- });
+ }));
}
- }
- base = previousBase;
+
+ for (i = 1, len = stmt.declarations.length; i < len; i += 1) {
+ node = stmt.declarations[i];
+ if (extra.comment && node.leadingComments) {
+ result.push(',' + newline, addIndent(generateStatement(node, {
+ allowIn: allowIn
+ })));
+ } else {
+ result.push(',' + space, generateStatement(node, {
+ allowIn: allowIn
+ }));
+ }
+ }
+ });
}
- result += ';';
+ result.push(semicolon);
break;
case Syntax.ThrowStatement:
- result = 'throw ' + generateExpression(stmt.argument, {
- precedence: Precedence.Sequence,
- allowIn: true,
- allowCall: true
- }) + ';';
+ result = [join(
+ 'throw',
+ generateExpression(stmt.argument, {
+ precedence: Precedence.Sequence,
+ allowIn: true,
+ allowCall: true
+ })
+ ), semicolon];
break;
case Syntax.TryStatement:
- result = 'try' + maybeBlock(stmt.block);
+ result = ['try', maybeBlock(stmt.block)];
+ result = maybeBlockSuffix(stmt.block, result);
for (i = 0, len = stmt.handlers.length; i < len; i += 1) {
- result += generateStatement(stmt.handlers[i]);
+ result = join(result, generateStatement(stmt.handlers[i]));
+ if (stmt.finalizer || i + 1 !== len) {
+ result = maybeBlockSuffix(stmt.handlers[i].body, result);
+ }
}
if (stmt.finalizer) {
- result += ' finally' + maybeBlock(stmt.finalizer);
+ result = join(result, ['finally', maybeBlock(stmt.finalizer)]);
}
break;
case Syntax.SwitchStatement:
- previousBase = base;
- base += indent;
- result = 'switch (' + generateExpression(stmt.discriminant, {
- precedence: Precedence.Sequence,
- allowIn: true,
- allowCall: true
- }) + ') {\n';
- base = previousBase;
+ 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 += 1) {
- result += addIndent(generateStatement(stmt.cases[i])) + '\n';
+ fragment = addIndent(generateStatement(stmt.cases[i], {semicolonOptional: i === len - 1}));
+ result.push(fragment);
+ if (!endsWithLineTerminator(toSourceNode(fragment).toString())) {
+ result.push(newline);
+ }
}
}
- result += addIndent('}');
+ result.push(addIndent('}'));
break;
case Syntax.SwitchCase:
- previousBase = base;
- base += indent;
- if (stmt.test) {
- result = 'case ' + generateExpression(stmt.test, {
- precedence: Precedence.Sequence,
- allowIn: true,
- allowCall: true
- }) + ':';
- } else {
- result = 'default:';
- }
+ 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) {
- result += maybeBlock(stmt.consequent[0]);
- i = 1;
- }
+ i = 0;
+ len = stmt.consequent.length;
+ if (len && stmt.consequent[0].type === Syntax.BlockStatement) {
+ fragment = maybeBlock(stmt.consequent[0]);
+ result.push(fragment);
+ i = 1;
+ }
- for (; i < len; i += 1) {
- result += '\n' + addIndent(generateStatement(stmt.consequent[i]));
- }
+ if (i !== len && !endsWithLineTerminator(toSourceNode(result).toString())) {
+ result.push(newline);
+ }
- base = previousBase;
+ for (; i < len; i += 1) {
+ fragment = addIndent(generateStatement(stmt.consequent[i], {semicolonOptional: i === len - 1 && semicolon === ''}));
+ result.push(fragment);
+ if (i + 1 !== len && !endsWithLineTerminator(toSourceNode(fragment).toString())) {
+ result.push(newline);
+ }
+ }
+ });
break;
case Syntax.IfStatement:
- if (stmt.alternate) {
- if (stmt.alternate.type === Syntax.IfStatement) {
- previousBase = base;
- base += indent;
- result = 'if (' + generateExpression(stmt.test, {
+ withIndent(function () {
+ result = [
+ 'if' + space + '(',
+ generateExpression(stmt.test, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
- }) + ')';
- base = previousBase;
- result += maybeBlock(stmt.consequent, true) + 'else ' + generateStatement(stmt.alternate);
+ }),
+ ')'
+ ];
+ });
+ 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 {
- previousBase = base;
- base += indent;
- result = 'if (' + generateExpression(stmt.test, {
- precedence: Precedence.Sequence,
- allowIn: true,
- allowCall: true
- }) + ')';
- base = previousBase;
- result += maybeBlock(stmt.consequent, true) + 'else' + maybeBlock(stmt.alternate);
+ result = join(result, join('else', maybeBlock(stmt.alternate, semicolon === '')));
}
} else {
- previousBase = base;
- base += indent;
- result = 'if (' + generateExpression(stmt.test, {
- precedence: Precedence.Sequence,
- allowIn: true,
- allowCall: true
- }) + ')';
- base = previousBase;
- result += maybeBlock(stmt.consequent);
+ result.push(maybeBlock(stmt.consequent, semicolon === ''));
}
break;
case Syntax.ForStatement:
- previousBase = base;
- base += indent;
- result = 'for (';
- if (stmt.init) {
- if (stmt.init.type === Syntax.VariableDeclaration) {
- result += generateStatement(stmt.init, {
- allowIn: false
- });
+ 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
+ }), ';');
+ }
} else {
- result += generateExpression(stmt.init, {
+ result.push(';');
+ }
+
+ if (stmt.test) {
+ result.push(space, generateExpression(stmt.test, {
precedence: Precedence.Sequence,
- allowIn: false,
+ allowIn: true,
allowCall: true
- }) + ';';
+ }), ';');
+ } else {
+ result.push(';');
}
- } else {
- result += ';';
- }
- if (stmt.test) {
- result += ' ' + generateExpression(stmt.test, {
- precedence: Precedence.Sequence,
- allowIn: true,
- allowCall: true
- }) + ';';
- } else {
- result += ';';
- }
-
- if (stmt.update) {
- result += ' ' + generateExpression(stmt.update, {
- precedence: Precedence.Sequence,
- allowIn: true,
- allowCall: true
- }) + ')';
- } else {
- result += ')';
- }
- base = previousBase;
+ if (stmt.update) {
+ result.push(space, generateExpression(stmt.update, {
+ precedence: Precedence.Sequence,
+ allowIn: true,
+ allowCall: true
+ }), ')');
+ } else {
+ result.push(')');
+ }
+ });
- result += maybeBlock(stmt.body);
+ result.push(maybeBlock(stmt.body, semicolon === ''));
break;
case Syntax.ForInStatement:
- result = 'for (';
- if (stmt.left.type === Syntax.VariableDeclaration) {
- previousBase = base;
- base += indent + indent;
- result += stmt.left.kind + ' ' + generateStatement(stmt.left.declarations[0], {
- allowIn: false
- });
- base = previousBase;
- } else {
- previousBase = base;
- base += indent;
- result += generateExpression(stmt.left, {
- precedence: Precedence.Call,
- allowIn: true,
- allowCall: true
- });
- base = previousBase;
- }
+ result = ['for' + space + '('];
+ withIndent(function () {
+ if (stmt.left.type === Syntax.VariableDeclaration) {
+ withIndent(function () {
+ result.push(stmt.left.kind + ' ', generateStatement(stmt.left.declarations[0], {
+ allowIn: false
+ }));
+ });
+ } else {
+ result.push(generateExpression(stmt.left, {
+ precedence: Precedence.Call,
+ allowIn: true,
+ allowCall: true
+ }));
+ }
- previousBase = base;
- base += indent;
- result += ' in ' + generateExpression(stmt.right, {
- precedence: Precedence.Sequence,
- allowIn: true,
- allowCall: true
- }) + ')';
- base = previousBase;
- result += maybeBlock(stmt.body);
+ result = join(result, 'in');
+ result = [join(
+ result,
+ generateExpression(stmt.right, {
+ precedence: Precedence.Sequence,
+ allowIn: true,
+ allowCall: true
+ })
+ ), ')'];
+ });
+ result.push(maybeBlock(stmt.body, semicolon === ''));
break;
case Syntax.LabeledStatement:
- result = stmt.label.name + ':' + maybeBlock(stmt.body);
+ result = [stmt.label.name + ':', maybeBlock(stmt.body, semicolon === '')];
break;
case Syntax.Program:
- result = '';
- for (i = 0, len = stmt.body.length; i < len; i += 1) {
- result += addIndent(generateStatement(stmt.body[i]));
- if ((i + 1) < len) {
- result += '\n';
+ len = stmt.body.length;
+ result = [safeConcatenation && len > 0 ? '\n' : ''];
+ for (i = 0; i < len; i += 1) {
+ fragment = addIndent(
+ generateStatement(stmt.body[i], {
+ semicolonOptional: !safeConcatenation && i === len - 1,
+ directiveContext: true
+ })
+ );
+ result.push(fragment);
+ if (i + 1 < len && !endsWithLineTerminator(toSourceNode(fragment).toString())) {
+ result.push(newline);
}
}
break;
case Syntax.FunctionDeclaration:
- result = 'function ';
- if (stmt.id) {
- result += stmt.id.name;
- }
- result += generateFunctionBody(stmt);
+ result = [(stmt.generator && !extra.moz.starlessGenerator ? 'function* ' : 'function ') + stmt.id.name, generateFunctionBody(stmt)];
break;
case Syntax.ReturnStatement:
if (stmt.argument) {
- result = 'return ' + generateExpression(stmt.argument, {
- precedence: Precedence.Sequence,
- allowIn: true,
- allowCall: true
- }) + ';';
+ result = [join(
+ 'return',
+ generateExpression(stmt.argument, {
+ precedence: Precedence.Sequence,
+ allowIn: true,
+ allowCall: true
+ })
+ ), semicolon];
} else {
- result = 'return;';
+ result = ['return' + semicolon];
}
break;
case Syntax.WhileStatement:
- previousBase = base;
- base += indent;
- result = 'while (' + generateExpression(stmt.test, {
- precedence: Precedence.Sequence,
- allowIn: true,
- allowCall: true
- }) + ')';
- base = previousBase;
- result += maybeBlock(stmt.body);
+ 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:
- previousBase = base;
- base += indent;
- result = 'with (' + generateExpression(stmt.object, {
- precedence: Precedence.Sequence,
- allowIn: true,
- allowCall: true
- }) + ')';
- base = previousBase;
- result += maybeBlock(stmt.body);
+ withIndent(function () {
+ result = [
+ 'with' + space + '(',
+ generateExpression(stmt.object, {
+ precedence: Precedence.Sequence,
+ allowIn: true,
+ allowCall: true
+ }),
+ ')'
+ ];
+ });
+ result.push(maybeBlock(stmt.body, semicolon === ''));
break;
default:
- break;
- }
-
- if (result === undefined) {
throw new Error('Unknown statement type: ' + stmt.type);
}
// Attach comments
if (extra.comment) {
- if (stmt.leadingComments) {
- save = result;
-
- comment = stmt.leadingComments[0];
- result = generateComment(comment);
- if (!endsWithLineTerminator(result)) {
- result += '\n';
- }
-
- for (i = 1, len = stmt.leadingComments.length; i < len; i += 1) {
- comment = stmt.leadingComments[i];
- ret = generateComment(comment);
- if (!endsWithLineTerminator(ret)) {
- ret += '\n';
- }
- result += addIndent(ret);
- }
-
- result += addIndent(save);
- }
+ result = addCommentsToStatement(stmt, result);
+ }
- if (stmt.trailingComments) {
- for (i = 0, len = stmt.trailingComments.length; i < len; i += 1) {
- comment = stmt.trailingComments[i];
- if (!endsWithLineTerminator(result)) {
- result += '\n';
- }
- result += addIndent(generateComment(comment));
- }
- }
+ fragment = toSourceNode(result).toString();
+ if (stmt.type === Syntax.Program && !safeConcatenation && newline === '' && fragment.charAt(fragment.length - 1) === '\n') {
+ result = toSourceNode(result).replaceRight(/\s+$/, '');
}
- return result;
+ return toSourceNode(result, stmt);
}
function generate(node, options) {
- var defaultOptions = getDefaultOptions();
+ var defaultOptions = getDefaultOptions(), result, pair;
- if (typeof options !== 'undefined') {
+ if (options != null) {
// Obsolete options
//
// `options.indent`
@@ -1161,7 +1846,9 @@
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') {
@@ -1169,20 +1856,47 @@
} else {
base = stringRepeat(indent, options.format.indent.base);
}
- parse = options.parse;
} else {
options = defaultOptions;
indent = options.format.indent.style;
base = stringRepeat(indent, options.format.indent.base);
- parse = options.parse;
}
+ json = options.format.json;
+ renumber = options.format.renumber;
+ hexadecimal = json ? false : options.format.hexadecimal;
+ quotes = json ? 'double' : options.format.quotes;
+ escapeless = options.format.escapeless;
+ if (options.format.compact) {
+ newline = space = indent = base = '';
+ } else {
+ newline = '\n';
+ space = ' ';
+ }
+ 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 (typeof process !== 'undefined') {
+ // We assume environment is node.js
+ SourceNode = require('source-map').SourceNode;
+ } else {
+ SourceNode = global.sourceMap.SourceNode;
+ }
+ } else {
+ SourceNode = SourceNodeMock;
+ }
+
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:
@@ -1202,10 +1916,12 @@
case Syntax.VariableDeclarator:
case Syntax.WhileStatement:
case Syntax.WithStatement:
- return generateStatement(node);
+ result = generateStatement(node);
+ break;
case Syntax.AssignmentExpression:
case Syntax.ArrayExpression:
+ case Syntax.ArrayPattern:
case Syntax.BinaryExpression:
case Syntax.CallExpression:
case Syntax.ConditionalExpression:
@@ -1216,21 +1932,35 @@
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:
- return generateExpression(node, {
+ case Syntax.YieldExpression:
+
+ result = generateExpression(node, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
});
+ break;
default:
- break;
+ throw new Error('Unknown node type: ' + node.type);
+ }
+
+ if (!sourceMap) {
+ return result.toString();
+ }
+
+ pair = result.toStringWithSourceMap({file: options.sourceMap});
+
+ if (options.sourceMapWithCode) {
+ return pair;
}
- throw new Error('Unknown node type: ' + node.type);
+ return pair.map.toString();
}
// simple visitor implementation
@@ -1238,6 +1968,7 @@
VisitorKeys = {
AssignmentExpression: ['left', 'right'],
ArrayExpression: ['elements'],
+ ArrayPattern: ['elements'],
BlockStatement: ['body'],
BinaryExpression: ['left', 'right'],
BreakStatement: ['label'],
@@ -1245,6 +1976,7 @@
CatchClause: ['param', 'body'],
ConditionalExpression: ['test', 'consequent', 'alternate'],
ContinueStatement: ['label'],
+ DirectiveStatement: [],
DoWhileStatement: ['body', 'test'],
DebuggerStatement: [],
EmptyStatement: [],
@@ -1261,11 +1993,12 @@
MemberExpression: ['object', 'property'],
NewExpression: ['callee', 'arguments'],
ObjectExpression: ['properties'],
+ ObjectPattern: ['properties'],
Program: ['body'],
Property: ['key', 'value'],
ReturnStatement: ['argument'],
SequenceExpression: ['expressions'],
- SwitchStatement: ['descriminant', 'cases'],
+ SwitchStatement: ['discriminant', 'cases'],
SwitchCase: ['test', 'consequent'],
ThisExpression: [],
ThrowStatement: ['argument'],
@@ -1275,7 +2008,8 @@
VariableDeclaration: ['declarations'],
VariableDeclarator: ['id', 'init'],
WhileStatement: ['test', 'body'],
- WithStatement: ['object', 'body']
+ WithStatement: ['object', 'body'],
+ YieldExpression: ['argument']
};
VisitorOption = {
@@ -1284,17 +2018,27 @@
};
function traverse(top, visitor) {
- var worklist, leavelist, node, ret, current, current2, candidates, candidate;
+ var worklist, leavelist, node, ret, current, current2, candidates, candidate, marker = {};
worklist = [ top ];
- leavelist = [];
+ leavelist = [ null ];
while (worklist.length) {
node = worklist.pop();
- if (node) {
+ if (node === marker) {
+ node = leavelist.pop();
+ if (visitor.leave) {
+ ret = visitor.leave(node, leavelist[leavelist.length - 1]);
+ } else {
+ ret = undefined;
+ }
+ if (ret === VisitorOption.Break) {
+ return;
+ }
+ } else if (node) {
if (visitor.enter) {
- ret = visitor.enter(node);
+ ret = visitor.enter(node, leavelist[leavelist.length - 1]);
} else {
ret = undefined;
}
@@ -1303,7 +2047,7 @@
return;
}
- worklist.push(null);
+ worklist.push(marker);
leavelist.push(node);
if (ret !== VisitorOption.Skip) {
@@ -1325,21 +2069,10 @@
}
}
}
- } else {
- node = leavelist.pop();
- if (visitor.leave) {
- ret = visitor.leave(node);
- } else {
- ret = undefined;
- }
- if (ret === VisitorOption.Break) {
- return;
- }
}
}
}
-
// based on LLVM libc++ upper_bound / lower_bound
// MIT License
@@ -1408,45 +2141,30 @@
function attachComments(tree, providedComments, tokens) {
// At first, we should calculate extended comment ranges.
- var comments = [], len, i;
+ var comments = [], comment, len, i;
if (!tree.range) {
throw new Error('attachComments needs range information');
}
+ // tokens array is empty, we attach comments to tree as 'leadingComments'
+ if (!tokens.length) {
+ if (providedComments.length) {
+ for (i = 0, len = providedComments.length; i < len; i += 1) {
+ comment = deepCopy(providedComments[i]);
+ comment.extendedRange = [0, tree.range[0]];
+ comments.push(comment);
+ }
+ tree.leadingComments = comments;
+ }
+ return tree;
+ }
+
for (i = 0, len = providedComments.length; i < len; i += 1) {
comments.push(extendCommentRange(deepCopy(providedComments[i]), tokens));
}
- //
- // For example,
- //
- // var i1 = 10, // test
- // i2 = 20;
- //
- // Above comment is probably trailing to i1 = 10.
- // So we specialize comma token.
- //
- // And second, comma first style example,
- //
- // var i = [
- // 10 // testing
- // , 20 // testing 2
- // ];
- //
- // 'testing' comment is trailing to 10 is proper.
- //
- // So we add some specialize path.
- //
- // 1. check comment is'nt containing LineTerminator
- // 2. check LineTerminator is not found between previous token and comment
- // 3. check LineTerminator is found between comment and next token
- //
- // If above conditions are all true,
- // we assume this comment should be attached to previous token as trailing comment.
- //
-
- // This traverse attacher is based on John Freeman's implementation.
+ // This is based on John Freeman's implementation.
traverse(tree, {
cursor: 0,
enter: function (node) {
@@ -1517,11 +2235,11 @@
}
// Sync with package.json.
- exports.version = '0.0.4';
+ exports.version = '0.0.16-dev';
exports.generate = generate;
exports.traverse = traverse;
exports.attachComments = attachComments;
-}(typeof exports === 'undefined' ? (escodegen = {}) : exports));
+}, this));
/* vim: set sw=4 ts=4 et tw=80 : */