aboutsummaryrefslogtreecommitdiff
path: root/node_modules/uglify-js/lib/output.js
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2018-09-20 02:56:13 +0200
committerFlorian Dold <florian.dold@gmail.com>2018-09-20 02:56:13 +0200
commitbbff7403fbf46f9ad92240ac213df8d30ef31b64 (patch)
treec58400ec5124da1c7d56b01aea83309f80a56c3b /node_modules/uglify-js/lib/output.js
parent003fb34971cf63466184351b4db5f7c67df4f444 (diff)
update packages
Diffstat (limited to 'node_modules/uglify-js/lib/output.js')
-rw-r--r--node_modules/uglify-js/lib/output.js818
1 files changed, 443 insertions, 375 deletions
diff --git a/node_modules/uglify-js/lib/output.js b/node_modules/uglify-js/lib/output.js
index 1aa634501..7f7e74df5 100644
--- a/node_modules/uglify-js/lib/output.js
+++ b/node_modules/uglify-js/lib/output.js
@@ -52,10 +52,11 @@ function is_some_comments(comment) {
function OutputStream(options) {
+ var readonly = !options;
options = defaults(options, {
ascii_only : false,
beautify : false,
- bracketize : false,
+ braces : false,
comments : false,
ie8 : false,
indent_level : 4,
@@ -121,17 +122,22 @@ function OutputStream(options) {
}
});
} : function(str) {
- return str.replace(/[\ud800-\udbff](?![\udc00-\udfff])/g, function(ch) {
- return "\\u" + ch.charCodeAt(0).toString(16);
- }).replace(/(^|[^\ud800-\udbff])([\udc00-\udfff])/g, function(match, prefix, ch) {
- return prefix + "\\u" + ch.charCodeAt(0).toString(16);
- });
+ var s = "";
+ for (var i = 0, len = str.length; i < len; i++) {
+ if (is_surrogate_pair_head(str[i]) && !is_surrogate_pair_tail(str[i + 1])
+ || is_surrogate_pair_tail(str[i]) && !is_surrogate_pair_head(str[i - 1])) {
+ s += "\\u" + str.charCodeAt(i).toString(16);
+ } else {
+ s += str[i];
+ }
+ }
+ return s;
};
function make_string(str, quote) {
var dq = 0, sq = 0;
str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g,
- function(s, i){
+ function(s, i) {
switch (s) {
case '"': ++dq; return '"';
case "'": ++sq; return "'";
@@ -167,37 +173,49 @@ function OutputStream(options) {
default:
return dq > sq ? quote_single() : quote_double();
}
- };
+ }
function encode_string(str, quote) {
var ret = make_string(str, quote);
if (options.inline_script) {
- ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
+ ret = ret.replace(/<\x2f(script)([>\/\t\n\f\r ])/gi, "<\\/$1$2");
ret = ret.replace(/\x3c!--/g, "\\x3c!--");
ret = ret.replace(/--\x3e/g, "--\\x3e");
}
return ret;
- };
+ }
function make_name(name) {
name = name.toString();
name = to_utf8(name, true);
return name;
- };
+ }
function make_indent(back) {
return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
- };
+ }
/* -----[ beautification/minification ]----- */
+ var has_parens = false;
+ var line_end = 0;
+ var line_fixed = true;
var might_need_space = false;
var might_need_semicolon = false;
- var might_add_newline = 0;
+ var need_newline_indented = false;
+ var need_space = false;
+ var newline_insert = -1;
var last = "";
var mapping_token, mapping_name, mappings = options.source_map && [];
- var do_add_mapping = mappings ? function() {
+ var adjust_mappings = mappings ? function(line, col) {
+ mappings.forEach(function(mapping) {
+ mapping.line += line;
+ mapping.col += col;
+ });
+ } : noop;
+
+ var flush_mappings = mappings ? function() {
mappings.forEach(function(mapping) {
try {
options.source_map.add(
@@ -220,31 +238,30 @@ function OutputStream(options) {
mappings = [];
} : noop;
- var ensure_line_len = options.max_line_len ? function() {
- if (current_col > options.max_line_len) {
- if (might_add_newline) {
- var left = OUTPUT.slice(0, might_add_newline);
- var right = OUTPUT.slice(might_add_newline);
- if (mappings) {
- var delta = right.length - current_col;
- mappings.forEach(function(mapping) {
- mapping.line++;
- mapping.col += delta;
- });
- }
- OUTPUT = left + "\n" + right;
- current_line++;
- current_pos++;
- current_col = right.length;
- }
+ function insert_newlines(count) {
+ var index = OUTPUT.lastIndexOf("\n");
+ if (line_end < index) line_end = index;
+ var left = OUTPUT.slice(0, line_end);
+ var right = OUTPUT.slice(line_end);
+ adjust_mappings(count, right.length - current_col);
+ current_line += count;
+ current_pos += count;
+ current_col = right.length;
+ OUTPUT = left;
+ while (count--) OUTPUT += "\n";
+ OUTPUT += right;
+ }
+
+ var fix_line = options.max_line_len ? function() {
+ if (line_fixed) {
if (current_col > options.max_line_len) {
AST_Node.warn("Output exceeds {max_line_len} characters", options);
}
+ return;
}
- if (might_add_newline) {
- might_add_newline = 0;
- do_add_mapping();
- }
+ if (current_col > options.max_line_len) insert_newlines(1);
+ line_fixed = true;
+ flush_mappings();
} : noop;
var requireSemicolonChars = makePredicate("( [ + * / - , .");
@@ -252,17 +269,31 @@ function OutputStream(options) {
function print(str) {
str = String(str);
var ch = str.charAt(0);
+ if (need_newline_indented && ch) {
+ need_newline_indented = false;
+ if (ch != "\n") {
+ print("\n");
+ indent();
+ }
+ }
+ if (need_space && ch) {
+ need_space = false;
+ if (!/[\s;})]/.test(ch)) {
+ space();
+ }
+ }
+ newline_insert = -1;
var prev = last.charAt(last.length - 1);
if (might_need_semicolon) {
might_need_semicolon = false;
if (prev == ":" && ch == "}" || (!ch || ";}".indexOf(ch) < 0) && prev != ";") {
- if (options.semicolons || requireSemicolonChars(ch)) {
+ if (options.semicolons || requireSemicolonChars[ch]) {
OUTPUT += ";";
current_col++;
current_pos++;
} else {
- ensure_line_len();
+ fix_line();
OUTPUT += "\n";
current_pos++;
current_line++;
@@ -280,18 +311,6 @@ function OutputStream(options) {
}
}
- if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
- var target_line = stack[stack.length - 1].start.line;
- while (current_line < target_line) {
- ensure_line_len();
- OUTPUT += "\n";
- current_pos++;
- current_line++;
- current_col = 0;
- might_need_space = false;
- }
- }
-
if (might_need_space) {
if ((is_identifier_char(prev)
&& (is_identifier_char(ch) || ch == "\\"))
@@ -313,20 +332,21 @@ function OutputStream(options) {
col: current_col
});
mapping_token = false;
- if (!might_add_newline) do_add_mapping();
+ if (line_fixed) flush_mappings();
}
OUTPUT += str;
+ has_parens = str[str.length - 1] == "(";
current_pos += str.length;
var a = str.split(/\r?\n/), n = a.length - 1;
current_line += n;
current_col += a[0].length;
if (n > 0) {
- ensure_line_len();
+ fix_line();
current_col = a[n].length;
}
last = str;
- };
+ }
var space = options.beautify ? function() {
print(" ");
@@ -349,13 +369,22 @@ function OutputStream(options) {
return ret;
} : function(col, cont) { return cont() };
- var newline = options.beautify ? function() {
- print("\n");
- } : options.max_line_len ? function() {
- ensure_line_len();
- might_add_newline = OUTPUT.length;
+ var may_add_newline = options.max_line_len || options.preserve_line ? function() {
+ fix_line();
+ line_end = OUTPUT.length;
+ line_fixed = false;
} : noop;
+ var newline = options.beautify ? function() {
+ if (newline_insert < 0) return print("\n");
+ if (OUTPUT[newline_insert] != "\n") {
+ OUTPUT = OUTPUT.slice(0, newline_insert) + "\n" + OUTPUT.slice(newline_insert);
+ current_pos++;
+ current_line++;
+ }
+ newline_insert++;
+ } : may_add_newline;
+
var semicolon = options.beautify ? function() {
print(";");
} : function() {
@@ -365,50 +394,56 @@ function OutputStream(options) {
function force_semicolon() {
might_need_semicolon = false;
print(";");
- };
+ }
function next_indent() {
return indentation + options.indent_level;
- };
+ }
function with_block(cont) {
var ret;
print("{");
newline();
- with_indent(next_indent(), function(){
+ with_indent(next_indent(), function() {
ret = cont();
});
indent();
print("}");
return ret;
- };
+ }
function with_parens(cont) {
print("(");
+ may_add_newline();
//XXX: still nice to have that for argument lists
//var ret = with_indent(current_col, cont);
var ret = cont();
+ may_add_newline();
print(")");
return ret;
- };
+ }
function with_square(cont) {
print("[");
+ may_add_newline();
//var ret = with_indent(current_col, cont);
var ret = cont();
+ may_add_newline();
print("]");
return ret;
- };
+ }
function comma() {
+ may_add_newline();
print(",");
+ may_add_newline();
space();
- };
+ }
function colon() {
print(":");
space();
- };
+ }
var add_mapping = mappings ? function(token, name) {
mapping_token = token;
@@ -416,11 +451,126 @@ function OutputStream(options) {
} : noop;
function get() {
- if (might_add_newline) {
- ensure_line_len();
- }
+ if (!line_fixed) fix_line();
return OUTPUT;
- };
+ }
+
+ function has_nlb() {
+ var index = OUTPUT.lastIndexOf("\n");
+ return /^ *$/.test(OUTPUT.slice(index + 1));
+ }
+
+ function prepend_comments(node) {
+ var self = this;
+ var start = node.start;
+ if (!start) return;
+ if (start.comments_before && start.comments_before._dumped === self) return;
+ var comments = start.comments_before;
+ if (!comments) {
+ comments = start.comments_before = [];
+ }
+ comments._dumped = self;
+
+ if (node instanceof AST_Exit && node.value) {
+ var tw = new TreeWalker(function(node) {
+ var parent = tw.parent();
+ if (parent instanceof AST_Exit
+ || parent instanceof AST_Binary && parent.left === node
+ || parent.TYPE == "Call" && parent.expression === node
+ || parent instanceof AST_Conditional && parent.condition === node
+ || parent instanceof AST_Dot && parent.expression === node
+ || parent instanceof AST_Sequence && parent.expressions[0] === node
+ || parent instanceof AST_Sub && parent.expression === node
+ || parent instanceof AST_UnaryPostfix) {
+ var text = node.start.comments_before;
+ if (text && text._dumped !== self) {
+ text._dumped = self;
+ comments = comments.concat(text);
+ }
+ } else {
+ return true;
+ }
+ });
+ tw.push(node);
+ node.value.walk(tw);
+ }
+
+ if (current_pos == 0) {
+ if (comments.length > 0 && options.shebang && comments[0].type == "comment5") {
+ print("#!" + comments.shift().value + "\n");
+ indent();
+ }
+ var preamble = options.preamble;
+ if (preamble) {
+ print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
+ }
+ }
+
+ comments = comments.filter(comment_filter, node);
+ if (comments.length == 0) return;
+ var last_nlb = has_nlb();
+ comments.forEach(function(c, i) {
+ if (!last_nlb) {
+ if (c.nlb) {
+ print("\n");
+ indent();
+ last_nlb = true;
+ } else if (i > 0) {
+ space();
+ }
+ }
+ if (/comment[134]/.test(c.type)) {
+ print("//" + c.value.replace(/[@#]__PURE__/g, ' ') + "\n");
+ indent();
+ last_nlb = true;
+ } else if (c.type == "comment2") {
+ print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
+ last_nlb = false;
+ }
+ });
+ if (!last_nlb) {
+ if (start.nlb) {
+ print("\n");
+ indent();
+ } else {
+ space();
+ }
+ }
+ }
+
+ function append_comments(node, tail) {
+ var self = this;
+ var token = node.end;
+ if (!token) return;
+ var comments = token[tail ? "comments_before" : "comments_after"];
+ if (!comments || comments._dumped === self) return;
+ if (!(node instanceof AST_Statement || all(comments, function(c) {
+ return !/comment[134]/.test(c.type);
+ }))) return;
+ comments._dumped = self;
+ var insert = OUTPUT.length;
+ comments.filter(comment_filter, node).forEach(function(c, i) {
+ need_space = false;
+ if (need_newline_indented) {
+ print("\n");
+ indent();
+ need_newline_indented = false;
+ } else if (c.nlb && (i > 0 || !has_nlb())) {
+ print("\n");
+ indent();
+ } else if (i > 0 || !tail) {
+ space();
+ }
+ if (/comment[134]/.test(c.type)) {
+ print("//" + c.value.replace(/[@#]__PURE__/g, ' '));
+ need_newline_indented = true;
+ } else if (c.type == "comment2") {
+ print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
+ need_space = true;
+ }
+ });
+ if (OUTPUT.length > insert) newline_insert = insert;
+ }
var stack = [];
return {
@@ -430,6 +580,7 @@ function OutputStream(options) {
indentation : function() { return indentation },
current_width : function() { return current_col - indentation },
should_break : function() { return options.width && this.current_width() >= options.width },
+ has_parens : function() { return has_parens },
newline : newline,
print : print,
space : space,
@@ -459,34 +610,41 @@ function OutputStream(options) {
with_square : with_square,
add_mapping : add_mapping,
option : function(opt) { return options[opt] },
- comment_filter : comment_filter,
+ prepend_comments: readonly ? noop : prepend_comments,
+ append_comments : readonly || comment_filter === return_false ? noop : append_comments,
line : function() { return current_line },
col : function() { return current_col },
pos : function() { return current_pos },
push_node : function(node) { stack.push(node) },
- pop_node : function() { return stack.pop() },
+ pop_node : options.preserve_line ? function() {
+ var node = stack.pop();
+ if (node.start && node.start.line > current_line) {
+ insert_newlines(node.start.line - current_line);
+ }
+ } : function() {
+ stack.pop();
+ },
parent : function(n) {
return stack[stack.length - 2 - (n || 0)];
}
};
-
-};
+}
/* -----[ code generators ]----- */
-(function(){
+(function() {
/* -----[ utils ]----- */
function DEFPRINT(nodetype, generator) {
nodetype.DEFMETHOD("_codegen", generator);
- };
+ }
var in_directive = false;
var active_scope = null;
var use_asm = null;
- AST_Node.DEFMETHOD("print", function(stream, force_parens){
+ AST_Node.DEFMETHOD("print", function(stream, force_parens) {
var self = this, generator = self._codegen;
if (self instanceof AST_Scope) {
active_scope = self;
@@ -495,9 +653,10 @@ function OutputStream(options) {
use_asm = active_scope;
}
function doit() {
- self.add_comments(stream);
+ stream.prepend_comments(self);
self.add_source_map(stream);
generator(self, stream);
+ stream.append_comments(self);
}
stream.push_node(self);
if (force_parens || self.needs_parens(stream)) {
@@ -512,130 +671,53 @@ function OutputStream(options) {
});
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
- AST_Node.DEFMETHOD("print_to_string", function(options){
+ AST_Node.DEFMETHOD("print_to_string", function(options) {
var s = OutputStream(options);
- if (!options) s._readonly = true;
this.print(s);
return s.get();
});
- /* -----[ comments ]----- */
-
- AST_Node.DEFMETHOD("add_comments", function(output){
- if (output._readonly) return;
- var self = this;
- var start = self.start;
- if (start && !start._comments_dumped) {
- start._comments_dumped = true;
- var comments = start.comments_before || [];
-
- // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112
- // and https://github.com/mishoo/UglifyJS2/issues/372
- if (self instanceof AST_Exit && self.value) {
- self.value.walk(new TreeWalker(function(node){
- if (node.start && node.start.comments_before) {
- comments = comments.concat(node.start.comments_before);
- node.start.comments_before = [];
- }
- if (node instanceof AST_Function ||
- node instanceof AST_Array ||
- node instanceof AST_Object)
- {
- return true; // don't go inside.
- }
- }));
- }
-
- if (output.pos() == 0) {
- if (comments.length > 0 && output.option("shebang") && comments[0].type == "comment5") {
- output.print("#!" + comments.shift().value + "\n");
- output.indent();
- }
- var preamble = output.option("preamble");
- if (preamble) {
- output.print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
- }
- }
-
- comments = comments.filter(output.comment_filter, self);
-
- // Keep single line comments after nlb, after nlb
- if (!output.option("beautify") && comments.length > 0 &&
- /comment[134]/.test(comments[0].type) &&
- output.col() !== 0 && comments[0].nlb)
- {
- output.print("\n");
- }
-
- comments.forEach(function(c){
- if (/comment[134]/.test(c.type)) {
- output.print("//" + c.value + "\n");
- output.indent();
- }
- else if (c.type == "comment2") {
- output.print("/*" + c.value + "*/");
- if (start.nlb) {
- output.print("\n");
- output.indent();
- } else {
- output.space();
- }
- }
- });
- }
- });
-
/* -----[ PARENTHESES ]----- */
function PARENS(nodetype, func) {
if (Array.isArray(nodetype)) {
- nodetype.forEach(function(nodetype){
+ nodetype.forEach(function(nodetype) {
PARENS(nodetype, func);
});
} else {
nodetype.DEFMETHOD("needs_parens", func);
}
- };
+ }
- PARENS(AST_Node, function(){
- return false;
- });
+ PARENS(AST_Node, return_false);
// a function expression needs parens around it when it's provably
// the first token to appear in a statement.
- PARENS(AST_Function, function(output){
- if (first_in_statement(output)) {
- return true;
- }
-
+ PARENS(AST_Function, function(output) {
+ if (!output.has_parens() && first_in_statement(output)) return true;
if (output.option('webkit')) {
var p = output.parent();
- if (p instanceof AST_PropAccess && p.expression === this) {
- return true;
- }
+ if (p instanceof AST_PropAccess && p.expression === this) return true;
}
-
if (output.option('wrap_iife')) {
var p = output.parent();
- return p instanceof AST_Call && p.expression === this;
+ if (p instanceof AST_Call && p.expression === this) return true;
}
-
- return false;
});
// same goes for an object literal, because otherwise it would be
// interpreted as a block of code.
- PARENS(AST_Object, function(output){
- return first_in_statement(output);
+ PARENS(AST_Object, function(output) {
+ return !output.has_parens() && first_in_statement(output);
});
- PARENS(AST_Unary, function(output){
+ PARENS(AST_Unary, function(output) {
var p = output.parent();
return p instanceof AST_PropAccess && p.expression === this
|| p instanceof AST_Call && p.expression === this;
});
- PARENS(AST_Sequence, function(output){
+ PARENS(AST_Sequence, function(output) {
var p = output.parent();
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
|| p instanceof AST_Unary // !(foo, bar, baz)
@@ -649,7 +731,7 @@ function OutputStream(options) {
;
});
- PARENS(AST_Binary, function(output){
+ PARENS(AST_Binary, function(output) {
var p = output.parent();
// (foo && bar)()
if (p instanceof AST_Call && p.expression === this)
@@ -672,7 +754,7 @@ function OutputStream(options) {
}
});
- PARENS(AST_PropAccess, function(output){
+ PARENS(AST_PropAccess, function(output) {
var p = output.parent();
if (p instanceof AST_New && p.expression === this) {
// i.e. new (foo.bar().baz)
@@ -693,21 +775,21 @@ function OutputStream(options) {
}
});
- PARENS(AST_Call, function(output){
- var p = output.parent(), p1;
- if (p instanceof AST_New && p.expression === this)
- return true;
-
- // workaround for Safari bug.
+ PARENS(AST_Call, function(output) {
+ var p = output.parent();
+ if (p instanceof AST_New && p.expression === this) return true;
// https://bugs.webkit.org/show_bug.cgi?id=123506
- return this.expression instanceof AST_Function
- && p instanceof AST_PropAccess
- && p.expression === this
- && (p1 = output.parent(1)) instanceof AST_Assign
- && p1.left === p;
+ if (output.option('webkit')) {
+ var g = output.parent(1);
+ return this.expression instanceof AST_Function
+ && p instanceof AST_PropAccess
+ && p.expression === this
+ && g instanceof AST_Assign
+ && g.left === p;
+ }
});
- PARENS(AST_New, function(output){
+ PARENS(AST_New, function(output) {
var p = output.parent();
if (!need_constructor_parens(this, output)
&& (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]()
@@ -715,7 +797,7 @@ function OutputStream(options) {
return true;
});
- PARENS(AST_Number, function(output){
+ PARENS(AST_Number, function(output) {
var p = output.parent();
if (p instanceof AST_PropAccess && p.expression === this) {
var value = this.getValue();
@@ -725,7 +807,7 @@ function OutputStream(options) {
}
});
- PARENS([ AST_Assign, AST_Conditional ], function(output){
+ PARENS([ AST_Assign, AST_Conditional ], function(output) {
var p = output.parent();
// !(a = false) → true
if (p instanceof AST_Unary)
@@ -746,11 +828,11 @@ function OutputStream(options) {
/* -----[ PRINTERS ]----- */
- DEFPRINT(AST_Directive, function(self, output){
+ DEFPRINT(AST_Directive, function(self, output) {
output.print_string(self.value, self.quote);
output.semicolon();
});
- DEFPRINT(AST_Debugger, function(self, output){
+ DEFPRINT(AST_Debugger, function(self, output) {
output.print("debugger");
output.semicolon();
});
@@ -760,7 +842,7 @@ function OutputStream(options) {
function display_body(body, is_toplevel, output, allow_directives) {
var last = body.length - 1;
in_directive = allow_directives;
- body.forEach(function(stmt, i){
+ body.forEach(function(stmt, i) {
if (in_directive === true && !(stmt instanceof AST_Directive ||
stmt instanceof AST_EmptyStatement ||
(stmt instanceof AST_SimpleStatement && stmt.body instanceof AST_String)
@@ -783,66 +865,74 @@ function OutputStream(options) {
}
});
in_directive = false;
- };
+ }
- AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){
+ AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
force_statement(this.body, output);
});
- DEFPRINT(AST_Statement, function(self, output){
+ DEFPRINT(AST_Statement, function(self, output) {
self.body.print(output);
output.semicolon();
});
- DEFPRINT(AST_Toplevel, function(self, output){
+ DEFPRINT(AST_Toplevel, function(self, output) {
display_body(self.body, true, output, true);
output.print("");
});
- DEFPRINT(AST_LabeledStatement, function(self, output){
+ DEFPRINT(AST_LabeledStatement, function(self, output) {
self.label.print(output);
output.colon();
self.body.print(output);
});
- DEFPRINT(AST_SimpleStatement, function(self, output){
+ DEFPRINT(AST_SimpleStatement, function(self, output) {
self.body.print(output);
output.semicolon();
});
- function print_bracketed(body, output, allow_directives) {
- if (body.length > 0) output.with_block(function(){
- display_body(body, false, output, allow_directives);
+ function print_braced_empty(self, output) {
+ output.print("{");
+ output.with_indent(output.next_indent(), function() {
+ output.append_comments(self, true);
});
- else output.print("{}");
- };
- DEFPRINT(AST_BlockStatement, function(self, output){
- print_bracketed(self.body, output);
+ output.print("}");
+ }
+ function print_braced(self, output, allow_directives) {
+ if (self.body.length > 0) {
+ output.with_block(function() {
+ display_body(self.body, false, output, allow_directives);
+ });
+ } else print_braced_empty(self, output);
+ }
+ DEFPRINT(AST_BlockStatement, function(self, output) {
+ print_braced(self, output);
});
- DEFPRINT(AST_EmptyStatement, function(self, output){
+ DEFPRINT(AST_EmptyStatement, function(self, output) {
output.semicolon();
});
- DEFPRINT(AST_Do, function(self, output){
+ DEFPRINT(AST_Do, function(self, output) {
output.print("do");
output.space();
make_block(self.body, output);
output.space();
output.print("while");
output.space();
- output.with_parens(function(){
+ output.with_parens(function() {
self.condition.print(output);
});
output.semicolon();
});
- DEFPRINT(AST_While, function(self, output){
+ DEFPRINT(AST_While, function(self, output) {
output.print("while");
output.space();
- output.with_parens(function(){
+ output.with_parens(function() {
self.condition.print(output);
});
output.space();
self._do_print_body(output);
});
- DEFPRINT(AST_For, function(self, output){
+ DEFPRINT(AST_For, function(self, output) {
output.print("for");
output.space();
- output.with_parens(function(){
+ output.with_parens(function() {
if (self.init) {
if (self.init instanceof AST_Definitions) {
self.init.print(output);
@@ -868,10 +958,10 @@ function OutputStream(options) {
output.space();
self._do_print_body(output);
});
- DEFPRINT(AST_ForIn, function(self, output){
+ DEFPRINT(AST_ForIn, function(self, output) {
output.print("for");
output.space();
- output.with_parens(function(){
+ output.with_parens(function() {
self.init.print(output);
output.space();
output.print("in");
@@ -881,10 +971,10 @@ function OutputStream(options) {
output.space();
self._do_print_body(output);
});
- DEFPRINT(AST_With, function(self, output){
+ DEFPRINT(AST_With, function(self, output) {
output.print("with");
output.space();
- output.with_parens(function(){
+ output.with_parens(function() {
self.expression.print(output);
});
output.space();
@@ -892,7 +982,7 @@ function OutputStream(options) {
});
/* -----[ functions ]----- */
- AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){
+ AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword) {
var self = this;
if (!nokeyword) {
output.print("function");
@@ -901,55 +991,46 @@ function OutputStream(options) {
output.space();
self.name.print(output);
}
- output.with_parens(function(){
- self.argnames.forEach(function(arg, i){
+ output.with_parens(function() {
+ self.argnames.forEach(function(arg, i) {
if (i) output.comma();
arg.print(output);
});
});
output.space();
- print_bracketed(self.body, output, true);
+ print_braced(self, output, true);
});
- DEFPRINT(AST_Lambda, function(self, output){
+ DEFPRINT(AST_Lambda, function(self, output) {
self._do_print(output);
});
- /* -----[ exits ]----- */
- AST_Exit.DEFMETHOD("_do_print", function(output, kind){
+ /* -----[ jumps ]----- */
+ function print_jump(output, kind, target) {
output.print(kind);
- if (this.value) {
+ if (target) {
output.space();
- this.value.print(output);
+ target.print(output);
}
output.semicolon();
- });
- DEFPRINT(AST_Return, function(self, output){
- self._do_print(output, "return");
- });
- DEFPRINT(AST_Throw, function(self, output){
- self._do_print(output, "throw");
- });
+ }
- /* -----[ loop control ]----- */
- AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){
- output.print(kind);
- if (this.label) {
- output.space();
- this.label.print(output);
- }
- output.semicolon();
+ DEFPRINT(AST_Return, function(self, output) {
+ print_jump(output, "return", self.value);
+ });
+ DEFPRINT(AST_Throw, function(self, output) {
+ print_jump(output, "throw", self.value);
});
- DEFPRINT(AST_Break, function(self, output){
- self._do_print(output, "break");
+ DEFPRINT(AST_Break, function(self, output) {
+ print_jump(output, "break", self.label);
});
- DEFPRINT(AST_Continue, function(self, output){
- self._do_print(output, "continue");
+ DEFPRINT(AST_Continue, function(self, output) {
+ print_jump(output, "continue", self.label);
});
/* -----[ if ]----- */
function make_then(self, output) {
var b = self.body;
- if (output.option("bracketize")
+ if (output.option("braces")
|| output.option("ie8") && b instanceof AST_Do)
return make_block(b, output);
// The squeezer replaces "block"-s that contain only a single
@@ -958,7 +1039,7 @@ function OutputStream(options) {
// IF having an ELSE clause where the THEN clause ends in an
// IF *without* an ELSE block (then the outer ELSE would refer
// to the inner IF). This function checks for this case and
- // adds the block brackets if needed.
+ // adds the block braces if needed.
if (!b) return output.force_semicolon();
while (true) {
if (b instanceof AST_If) {
@@ -974,11 +1055,11 @@ function OutputStream(options) {
else break;
}
force_statement(self.body, output);
- };
- DEFPRINT(AST_If, function(self, output){
+ }
+ DEFPRINT(AST_If, function(self, output) {
output.print("if");
output.space();
- output.with_parens(function(){
+ output.with_parens(function() {
self.condition.print(output);
});
output.space();
@@ -997,17 +1078,17 @@ function OutputStream(options) {
});
/* -----[ switch ]----- */
- DEFPRINT(AST_Switch, function(self, output){
+ DEFPRINT(AST_Switch, function(self, output) {
output.print("switch");
output.space();
- output.with_parens(function(){
+ output.with_parens(function() {
self.expression.print(output);
});
output.space();
var last = self.body.length - 1;
- if (last < 0) output.print("{}");
- else output.with_block(function(){
- self.body.forEach(function(branch, i){
+ if (last < 0) print_braced_empty(self, output);
+ else output.with_block(function() {
+ self.body.forEach(function(branch, i) {
output.indent(true);
branch.print(output);
if (i < last && branch.body.length > 0)
@@ -1015,19 +1096,19 @@ function OutputStream(options) {
});
});
});
- AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){
+ AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output) {
output.newline();
- this.body.forEach(function(stmt){
+ this.body.forEach(function(stmt) {
output.indent();
stmt.print(output);
output.newline();
});
});
- DEFPRINT(AST_Default, function(self, output){
+ DEFPRINT(AST_Default, function(self, output) {
output.print("default:");
self._do_print_body(output);
});
- DEFPRINT(AST_Case, function(self, output){
+ DEFPRINT(AST_Case, function(self, output) {
output.print("case");
output.space();
self.expression.print(output);
@@ -1036,10 +1117,10 @@ function OutputStream(options) {
});
/* -----[ exceptions ]----- */
- DEFPRINT(AST_Try, function(self, output){
+ DEFPRINT(AST_Try, function(self, output) {
output.print("try");
output.space();
- print_bracketed(self.body, output);
+ print_braced(self, output);
if (self.bcatch) {
output.space();
self.bcatch.print(output);
@@ -1049,37 +1130,30 @@ function OutputStream(options) {
self.bfinally.print(output);
}
});
- DEFPRINT(AST_Catch, function(self, output){
+ DEFPRINT(AST_Catch, function(self, output) {
output.print("catch");
output.space();
- output.with_parens(function(){
+ output.with_parens(function() {
self.argname.print(output);
});
output.space();
- print_bracketed(self.body, output);
+ print_braced(self, output);
});
- DEFPRINT(AST_Finally, function(self, output){
+ DEFPRINT(AST_Finally, function(self, output) {
output.print("finally");
output.space();
- print_bracketed(self.body, output);
+ print_braced(self, output);
});
- /* -----[ var/const ]----- */
- AST_Definitions.DEFMETHOD("_do_print", function(output, kind){
- output.print(kind);
+ DEFPRINT(AST_Var, function(self, output) {
+ output.print("var");
output.space();
- this.definitions.forEach(function(def, i){
+ self.definitions.forEach(function(def, i) {
if (i) output.comma();
def.print(output);
});
var p = output.parent();
- var in_for = p instanceof AST_For || p instanceof AST_ForIn;
- var avoid_semicolon = in_for && p.init === this;
- if (!avoid_semicolon)
- output.semicolon();
- });
- DEFPRINT(AST_Var, function(self, output){
- self._do_print(output, "var");
+ if (p && p.init !== self || !(p instanceof AST_For || p instanceof AST_ForIn)) output.semicolon();
});
function parenthesize_for_noin(node, output, noin) {
@@ -1094,9 +1168,9 @@ function OutputStream(options) {
}
}));
node.print(output, parens);
- };
+ }
- DEFPRINT(AST_VarDef, function(self, output){
+ DEFPRINT(AST_VarDef, function(self, output) {
self.name.print(output);
if (self.value) {
output.space();
@@ -1109,28 +1183,27 @@ function OutputStream(options) {
});
/* -----[ other expressions ]----- */
- DEFPRINT(AST_Call, function(self, output){
+ DEFPRINT(AST_Call, function(self, output) {
self.expression.print(output);
if (self instanceof AST_New && !need_constructor_parens(self, output))
return;
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
output.add_mapping(self.start);
}
- output.with_parens(function(){
- self.args.forEach(function(expr, i){
+ output.with_parens(function() {
+ self.args.forEach(function(expr, i) {
if (i) output.comma();
expr.print(output);
});
});
});
- DEFPRINT(AST_New, function(self, output){
+ DEFPRINT(AST_New, function(self, output) {
output.print("new");
output.space();
AST_Call.prototype._codegen(self, output);
});
-
- AST_Sequence.DEFMETHOD("_do_print", function(output){
- this.expressions.forEach(function(node, index) {
+ DEFPRINT(AST_Sequence, function(self, output) {
+ self.expressions.forEach(function(node, index) {
if (index > 0) {
output.comma();
if (output.should_break()) {
@@ -1141,22 +1214,11 @@ function OutputStream(options) {
node.print(output);
});
});
- DEFPRINT(AST_Sequence, function(self, output){
- self._do_print(output);
- // var p = output.parent();
- // if (p instanceof AST_Statement) {
- // output.with_indent(output.next_indent(), function(){
- // self._do_print(output);
- // });
- // } else {
- // self._do_print(output);
- // }
- });
- DEFPRINT(AST_Dot, function(self, output){
+ DEFPRINT(AST_Dot, function(self, output) {
var expr = self.expression;
expr.print(output);
var prop = self.property;
- if (output.option("ie8") && RESERVED_WORDS(prop)) {
+ if (output.option("ie8") && RESERVED_WORDS[prop]) {
output.print("[");
output.add_mapping(self.end);
output.print_string(prop);
@@ -1173,13 +1235,13 @@ function OutputStream(options) {
output.print_name(prop);
}
});
- DEFPRINT(AST_Sub, function(self, output){
+ DEFPRINT(AST_Sub, function(self, output) {
self.expression.print(output);
output.print("[");
self.property.print(output);
output.print("]");
});
- DEFPRINT(AST_UnaryPrefix, function(self, output){
+ DEFPRINT(AST_UnaryPrefix, function(self, output) {
var op = self.operator;
output.print(op);
if (/^[a-z]/i.test(op)
@@ -1190,11 +1252,11 @@ function OutputStream(options) {
}
self.expression.print(output);
});
- DEFPRINT(AST_UnaryPostfix, function(self, output){
+ DEFPRINT(AST_UnaryPostfix, function(self, output) {
self.expression.print(output);
output.print(self.operator);
});
- DEFPRINT(AST_Binary, function(self, output){
+ DEFPRINT(AST_Binary, function(self, output) {
var op = self.operator;
self.left.print(output);
if (op[0] == ">" /* ">>" ">>>" ">" ">=" */
@@ -1220,7 +1282,7 @@ function OutputStream(options) {
}
self.right.print(output);
});
- DEFPRINT(AST_Conditional, function(self, output){
+ DEFPRINT(AST_Conditional, function(self, output) {
self.condition.print(output);
output.space();
output.print("?");
@@ -1232,11 +1294,11 @@ function OutputStream(options) {
});
/* -----[ literals ]----- */
- DEFPRINT(AST_Array, function(self, output){
- output.with_square(function(){
+ DEFPRINT(AST_Array, function(self, output) {
+ output.with_square(function() {
var a = self.elements, len = a.length;
if (len > 0) output.space();
- a.forEach(function(exp, i){
+ a.forEach(function(exp, i) {
if (i) output.comma();
exp.print(output);
// If the final element is a hole, we need to make sure it
@@ -1248,9 +1310,9 @@ function OutputStream(options) {
if (len > 0) output.space();
});
});
- DEFPRINT(AST_Object, function(self, output){
- if (self.properties.length > 0) output.with_block(function(){
- self.properties.forEach(function(prop, i){
+ DEFPRINT(AST_Object, function(self, output) {
+ if (self.properties.length > 0) output.with_block(function() {
+ self.properties.forEach(function(prop, i) {
if (i) {
output.print(",");
output.newline();
@@ -1260,18 +1322,15 @@ function OutputStream(options) {
});
output.newline();
});
- else output.print("{}");
+ else print_braced_empty(self, output);
});
function print_property_name(key, quote, output) {
if (output.option("quote_keys")) {
- output.print_string(key + "");
- } else if ((typeof key == "number"
- || !output.option("beautify")
- && +key + "" == key)
- && parseFloat(key) >= 0) {
+ output.print_string(key);
+ } else if ("" + +key == key && key >= 0) {
output.print(make_num(key));
- } else if (RESERVED_WORDS(key) ? !output.option("ie8") : is_identifier_string(key)) {
+ } else if (RESERVED_WORDS[key] ? !output.option("ie8") : is_identifier_string(key)) {
if (quote && output.option("keep_quoted_props")) {
output.print_string(key, quote);
} else {
@@ -1282,7 +1341,7 @@ function OutputStream(options) {
}
}
- DEFPRINT(AST_ObjectKeyVal, function(self, output){
+ DEFPRINT(AST_ObjectKeyVal, function(self, output) {
print_property_name(self.key, self.quote, output);
output.colon();
self.value.print(output);
@@ -1293,27 +1352,27 @@ function OutputStream(options) {
print_property_name(this.key.name, this.quote, output);
this.value._do_print(output, true);
});
- DEFPRINT(AST_ObjectSetter, function(self, output){
+ DEFPRINT(AST_ObjectSetter, function(self, output) {
self._print_getter_setter("set", output);
});
- DEFPRINT(AST_ObjectGetter, function(self, output){
+ DEFPRINT(AST_ObjectGetter, function(self, output) {
self._print_getter_setter("get", output);
});
- DEFPRINT(AST_Symbol, function(self, output){
+ DEFPRINT(AST_Symbol, function(self, output) {
var def = self.definition();
output.print_name(def ? def.mangled_name || def.name : self.name);
});
DEFPRINT(AST_Hole, noop);
- DEFPRINT(AST_This, function(self, output){
+ DEFPRINT(AST_This, function(self, output) {
output.print("this");
});
- DEFPRINT(AST_Constant, function(self, output){
+ DEFPRINT(AST_Constant, function(self, output) {
output.print(self.getValue());
});
- DEFPRINT(AST_String, function(self, output){
+ DEFPRINT(AST_String, function(self, output) {
output.print_string(self.getValue(), self.quote, in_directive);
});
- DEFPRINT(AST_Number, function(self, output){
+ DEFPRINT(AST_Number, function(self, output) {
if (use_asm && self.start && self.start.raw != null) {
output.print(self.start.raw);
} else {
@@ -1321,7 +1380,7 @@ function OutputStream(options) {
}
});
- DEFPRINT(AST_RegExp, function(self, output){
+ DEFPRINT(AST_RegExp, function(self, output) {
var regexp = self.getValue();
var str = regexp.toString();
if (regexp.raw_source) {
@@ -1335,7 +1394,7 @@ function OutputStream(options) {
});
function force_statement(stat, output) {
- if (output.option("bracketize")) {
+ if (output.option("braces")) {
make_block(stat, output);
} else {
if (!stat || stat instanceof AST_EmptyStatement)
@@ -1343,7 +1402,7 @@ function OutputStream(options) {
else
stat.print(output);
}
- };
+ }
// self should be AST_New. decide if we want to show parens or not.
function need_constructor_parens(self, output) {
@@ -1351,7 +1410,7 @@ function OutputStream(options) {
if (self.args.length > 0) return true;
return output.option("beautify");
- };
+ }
function best_of(a) {
var best = a[0], len = best.length;
@@ -1362,84 +1421,93 @@ function OutputStream(options) {
}
}
return best;
- };
+ }
function make_num(num) {
- var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m;
+ var str = num.toString(10).replace(/^0\./, ".").replace("e+", "e");
+ var candidates = [ str ];
if (Math.floor(num) === num) {
- if (num >= 0) {
- a.push("0x" + num.toString(16).toLowerCase(), // probably pointless
- "0" + num.toString(8)); // same.
+ if (num < 0) {
+ candidates.push("-0x" + (-num).toString(16).toLowerCase());
} else {
- a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless
- "-0" + (-num).toString(8)); // same.
+ candidates.push("0x" + num.toString(16).toLowerCase());
}
- if ((m = /^(.*?)(0+)$/.exec(num))) {
- a.push(m[1] + "e" + m[2].length);
- }
- } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {
- a.push(m[2] + "e-" + (m[1].length + m[2].length),
- str.substr(str.indexOf(".")));
}
- return best_of(a);
- };
+ var match, len, digits;
+ if (match = /^\.0+/.exec(str)) {
+ len = match[0].length;
+ digits = str.slice(len);
+ candidates.push(digits + "e-" + (digits.length + len - 1));
+ } else if (match = /0+$/.exec(str)) {
+ len = match[0].length;
+ candidates.push(str.slice(0, -len) + "e" + len);
+ } else if (match = /^(\d)\.(\d+)e(-?\d+)$/.exec(str)) {
+ candidates.push(match[1] + match[2] + "e" + (match[3] - match[2].length));
+ }
+ return best_of(candidates);
+ }
function make_block(stmt, output) {
if (!stmt || stmt instanceof AST_EmptyStatement)
output.print("{}");
else if (stmt instanceof AST_BlockStatement)
stmt.print(output);
- else output.with_block(function(){
+ else output.with_block(function() {
output.indent();
stmt.print(output);
output.newline();
});
- };
+ }
/* -----[ source map generators ]----- */
function DEFMAP(nodetype, generator) {
- nodetype.DEFMETHOD("add_source_map", function(stream){
- generator(this, stream);
+ nodetype.forEach(function(nodetype) {
+ nodetype.DEFMETHOD("add_source_map", generator);
});
- };
-
- // We could easily add info for ALL nodes, but it seems to me that
- // would be quite wasteful, hence this noop in the base class.
- DEFMAP(AST_Node, noop);
+ }
- function basic_sourcemap_gen(self, output) {
- output.add_mapping(self.start);
- };
+ DEFMAP([
+ // We could easily add info for ALL nodes, but it seems to me that
+ // would be quite wasteful, hence this noop in the base class.
+ AST_Node,
+ // since the label symbol will mark it
+ AST_LabeledStatement,
+ AST_Toplevel,
+ ], noop);
// XXX: I'm not exactly sure if we need it for all of these nodes,
// or if we should add even more.
-
- DEFMAP(AST_Directive, basic_sourcemap_gen);
- DEFMAP(AST_Debugger, basic_sourcemap_gen);
- DEFMAP(AST_Symbol, basic_sourcemap_gen);
- DEFMAP(AST_Jump, basic_sourcemap_gen);
- DEFMAP(AST_StatementWithBody, basic_sourcemap_gen);
- DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it
- DEFMAP(AST_Lambda, basic_sourcemap_gen);
- DEFMAP(AST_Switch, basic_sourcemap_gen);
- DEFMAP(AST_SwitchBranch, basic_sourcemap_gen);
- DEFMAP(AST_BlockStatement, basic_sourcemap_gen);
- DEFMAP(AST_Toplevel, noop);
- DEFMAP(AST_New, basic_sourcemap_gen);
- DEFMAP(AST_Try, basic_sourcemap_gen);
- DEFMAP(AST_Catch, basic_sourcemap_gen);
- DEFMAP(AST_Finally, basic_sourcemap_gen);
- DEFMAP(AST_Definitions, basic_sourcemap_gen);
- DEFMAP(AST_Constant, basic_sourcemap_gen);
- DEFMAP(AST_ObjectSetter, function(self, output){
- output.add_mapping(self.start, self.key.name);
- });
- DEFMAP(AST_ObjectGetter, function(self, output){
- output.add_mapping(self.start, self.key.name);
- });
- DEFMAP(AST_ObjectProperty, function(self, output){
- output.add_mapping(self.start, self.key);
+ DEFMAP([
+ AST_Array,
+ AST_BlockStatement,
+ AST_Catch,
+ AST_Constant,
+ AST_Debugger,
+ AST_Definitions,
+ AST_Directive,
+ AST_Finally,
+ AST_Jump,
+ AST_Lambda,
+ AST_New,
+ AST_Object,
+ AST_StatementWithBody,
+ AST_Symbol,
+ AST_Switch,
+ AST_SwitchBranch,
+ AST_Try,
+ ], function(output) {
+ output.add_mapping(this.start);
+ });
+
+ DEFMAP([
+ AST_ObjectGetter,
+ AST_ObjectSetter,
+ ], function(output) {
+ output.add_mapping(this.start, this.key.name);
+ });
+
+ DEFMAP([ AST_ObjectProperty ], function(output) {
+ output.add_mapping(this.start, this.key);
});
-
})();