aboutsummaryrefslogtreecommitdiff
path: root/node_modules/uglify-js/lib/output.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/uglify-js/lib/output.js')
-rw-r--r--node_modules/uglify-js/lib/output.js267
1 files changed, 144 insertions, 123 deletions
diff --git a/node_modules/uglify-js/lib/output.js b/node_modules/uglify-js/lib/output.js
index 0731fb492..4c873f10d 100644
--- a/node_modules/uglify-js/lib/output.js
+++ b/node_modules/uglify-js/lib/output.js
@@ -57,6 +57,7 @@ function OutputStream(options) {
beautify : false,
bracketize : false,
comments : false,
+ ie8 : false,
indent_level : 4,
indent_start : 0,
inline_script : true,
@@ -66,12 +67,10 @@ function OutputStream(options) {
preserve_line : false,
quote_keys : false,
quote_style : 0,
- screw_ie8 : true,
semicolons : true,
shebang : true,
source_map : null,
- space_colon : true,
- unescape_regexps : false,
+ webkit : false,
width : 80,
wrap_iife : false,
}, true);
@@ -110,7 +109,7 @@ function OutputStream(options) {
var current_pos = 0;
var OUTPUT = "";
- function to_ascii(str, identifier) {
+ var to_utf8 = options.ascii_only ? function(str, identifier) {
return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
var code = ch.charCodeAt(0).toString(16);
if (code.length <= 2 && !identifier) {
@@ -121,6 +120,12 @@ function OutputStream(options) {
return "\\u" + code;
}
});
+ } : 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);
+ });
};
function make_string(str, quote) {
@@ -136,7 +141,7 @@ function OutputStream(options) {
case "\t": return "\\t";
case "\b": return "\\b";
case "\f": return "\\f";
- case "\x0B": return options.screw_ie8 ? "\\v" : "\\x0B";
+ case "\x0B": return options.ie8 ? "\\x0B" : "\\v";
case "\u2028": return "\\u2028";
case "\u2029": return "\\u2029";
case "\ufeff": return "\\ufeff";
@@ -151,7 +156,7 @@ function OutputStream(options) {
function quote_double() {
return '"' + str.replace(/\x22/g, '\\"') + '"';
}
- if (options.ascii_only) str = to_ascii(str);
+ str = to_utf8(str);
switch (options.quote_style) {
case 1:
return quote_single();
@@ -176,8 +181,7 @@ function OutputStream(options) {
function make_name(name) {
name = name.toString();
- if (options.ascii_only)
- name = to_ascii(name, true);
+ name = to_utf8(name, true);
return name;
};
@@ -191,12 +195,43 @@ function OutputStream(options) {
var might_need_semicolon = false;
var might_add_newline = 0;
var last = "";
+ var mapping_token, mapping_name, mappings = options.source_map && [];
+
+ var do_add_mapping = mappings ? function() {
+ mappings.forEach(function(mapping) {
+ try {
+ options.source_map.add(
+ mapping.token.file,
+ mapping.line, mapping.col,
+ mapping.token.line, mapping.token.col,
+ !mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name
+ );
+ } catch(ex) {
+ AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
+ file: mapping.token.file,
+ line: mapping.token.line,
+ col: mapping.token.col,
+ cline: mapping.line,
+ ccol: mapping.col,
+ name: mapping.name || ""
+ })
+ }
+ });
+ 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++;
@@ -206,7 +241,10 @@ function OutputStream(options) {
AST_Node.warn("Output exceeds {max_line_len} characters", options);
}
}
- might_add_newline = 0;
+ if (might_add_newline) {
+ might_add_newline = 0;
+ do_add_mapping();
+ }
} : noop;
var requireSemicolonChars = makePredicate("( [ + * / - , .");
@@ -266,6 +304,18 @@ function OutputStream(options) {
}
might_need_space = false;
}
+
+ if (mapping_token) {
+ mappings.push({
+ token: mapping_token,
+ name: mapping_name,
+ line: current_line,
+ col: current_col
+ });
+ mapping_token = false;
+ if (!might_add_newline) do_add_mapping();
+ }
+
OUTPUT += str;
current_pos += str.length;
var a = str.split(/\r?\n/), n = a.length - 1;
@@ -357,27 +407,12 @@ function OutputStream(options) {
function colon() {
print(":");
- if (options.space_colon) space();
+ space();
};
- var add_mapping = options.source_map ? function(token, name) {
- try {
- if (token) options.source_map.add(
- token.file || "?",
- current_line, current_col,
- token.line, token.col,
- (!name && token.type == "name") ? token.value : name
- );
- } catch(ex) {
- AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
- file: token.file,
- line: token.line,
- col: token.col,
- cline: current_line,
- ccol: current_col,
- name: name || ""
- })
- }
+ var add_mapping = mappings ? function(token, name) {
+ mapping_token = token;
+ mapping_name = name;
} : noop;
function get() {
@@ -403,7 +438,7 @@ function OutputStream(options) {
last : function() { return last },
semicolon : semicolon,
force_semicolon : force_semicolon,
- to_ascii : to_ascii,
+ to_utf8 : to_utf8,
print_name : function(name) { print(make_name(name)) },
print_string : function(str, quote, escape_directive) {
var encoded = encode_string(str, quote);
@@ -471,6 +506,7 @@ function OutputStream(options) {
use_asm = prev_use_asm;
}
});
+ AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
AST_Node.DEFMETHOD("print_to_string", function(options){
var s = OutputStream(options);
@@ -568,6 +604,13 @@ function OutputStream(options) {
return true;
}
+ if (output.option('webkit')) {
+ var p = output.parent();
+ 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;
@@ -588,7 +631,7 @@ function OutputStream(options) {
|| p instanceof AST_Call && p.expression === this;
});
- PARENS(AST_Seq, 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)
@@ -634,14 +677,15 @@ function OutputStream(options) {
// parens around it too, otherwise the call will be
// interpreted as passing the arguments to the upper New
// expression.
- try {
- this.walk(new TreeWalker(function(node){
- if (node instanceof AST_Call) throw p;
- }));
- } catch(ex) {
- if (ex !== p) throw ex;
- return true;
- }
+ var parens = false;
+ this.walk(new TreeWalker(function(node) {
+ if (parens || node instanceof AST_Scope) return true;
+ if (node instanceof AST_Call) {
+ parens = true;
+ return true;
+ }
+ }));
+ return parens;
}
});
@@ -677,7 +721,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)
@@ -902,7 +946,7 @@ function OutputStream(options) {
function make_then(self, output) {
var b = self.body;
if (output.option("bracketize")
- || !output.option("screw_ie8") && b instanceof AST_Do)
+ || output.option("ie8") && b instanceof AST_Do)
return make_block(b, output);
// The squeezer replaces "block"-s that contain only a single
// statement with the statement itself; technically, the AST
@@ -1033,24 +1077,19 @@ function OutputStream(options) {
DEFPRINT(AST_Var, function(self, output){
self._do_print(output, "var");
});
- DEFPRINT(AST_Const, function(self, output){
- self._do_print(output, "const");
- });
function parenthesize_for_noin(node, output, noin) {
- if (!noin) node.print(output);
- else try {
- // need to take some precautions here:
- // https://github.com/mishoo/UglifyJS2/issues/60
- node.walk(new TreeWalker(function(node){
- if (node instanceof AST_Binary && node.operator == "in")
- throw output;
- }));
- node.print(output);
- } catch(ex) {
- if (ex !== output) throw ex;
- node.print(output, true);
- }
+ var parens = false;
+ // need to take some precautions here:
+ // https://github.com/mishoo/UglifyJS2/issues/60
+ if (noin) node.walk(new TreeWalker(function(node) {
+ if (parens || node instanceof AST_Scope) return true;
+ if (node instanceof AST_Binary && node.operator == "in") {
+ parens = true;
+ return true;
+ }
+ }));
+ node.print(output, parens);
};
DEFPRINT(AST_VarDef, function(self, output){
@@ -1070,6 +1109,9 @@ function OutputStream(options) {
self.expression.print(output);
if (self instanceof AST_New && !need_constructor_parens(self, output))
return;
+ if (self.expression instanceof AST_Lambda) {
+ output.add_mapping(self.start);
+ }
output.with_parens(function(){
self.args.forEach(function(expr, i){
if (i) output.comma();
@@ -1083,18 +1125,19 @@ function OutputStream(options) {
AST_Call.prototype._codegen(self, output);
});
- AST_Seq.DEFMETHOD("_do_print", function(output){
- this.car.print(output);
- if (this.cdr) {
- output.comma();
- if (output.should_break()) {
- output.newline();
- output.indent();
+ AST_Sequence.DEFMETHOD("_do_print", function(output){
+ this.expressions.forEach(function(node, index) {
+ if (index > 0) {
+ output.comma();
+ if (output.should_break()) {
+ output.newline();
+ output.indent();
+ }
}
- this.cdr.print(output);
- }
+ node.print(output);
+ });
});
- DEFPRINT(AST_Seq, function(self, output){
+ DEFPRINT(AST_Sequence, function(self, output){
self._do_print(output);
// var p = output.parent();
// if (p instanceof AST_Statement) {
@@ -1108,15 +1151,23 @@ function OutputStream(options) {
DEFPRINT(AST_Dot, function(self, output){
var expr = self.expression;
expr.print(output);
- if (expr instanceof AST_Number && expr.getValue() >= 0) {
- if (!/[xa-f.)]/i.test(output.last())) {
- output.print(".");
+ var prop = self.property;
+ if (output.option("ie8") && RESERVED_WORDS(prop)) {
+ output.print("[");
+ output.add_mapping(self.end);
+ output.print_string(prop);
+ output.print("]");
+ } else {
+ if (expr instanceof AST_Number && expr.getValue() >= 0) {
+ if (!/[xa-f.)]/i.test(output.last())) {
+ output.print(".");
+ }
}
+ output.print(".");
+ // the name after dot would be mapped about here.
+ output.add_mapping(self.end);
+ output.print_name(prop);
}
- output.print(".");
- // the name after dot would be mapped about here.
- output.add_mapping(self.end);
- output.print_name(self.property);
});
DEFPRINT(AST_Sub, function(self, output){
self.expression.print(output);
@@ -1207,9 +1258,8 @@ function OutputStream(options) {
});
else output.print("{}");
});
- DEFPRINT(AST_ObjectKeyVal, function(self, output){
- var key = self.key;
- var quote = self.quote;
+
+ function print_property_name(key, quote, output) {
if (output.option("quote_keys")) {
output.print_string(key + "");
} else if ((typeof key == "number"
@@ -1217,7 +1267,7 @@ function OutputStream(options) {
&& +key + "" == key)
&& parseFloat(key) >= 0) {
output.print(make_num(key));
- } else if (RESERVED_WORDS(key) ? output.option("screw_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 {
@@ -1226,20 +1276,24 @@ function OutputStream(options) {
} else {
output.print_string(key, quote);
}
+ }
+
+ DEFPRINT(AST_ObjectKeyVal, function(self, output){
+ print_property_name(self.key, self.quote, output);
output.colon();
self.value.print(output);
});
- DEFPRINT(AST_ObjectSetter, function(self, output){
- output.print("set");
+ AST_ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, output) {
+ output.print(type);
output.space();
- self.key.print(output);
- self.value._do_print(output, true);
+ print_property_name(this.key.name, this.quote, output);
+ this.value._do_print(output, true);
+ });
+ DEFPRINT(AST_ObjectSetter, function(self, output){
+ self._print_getter_setter("set", output);
});
DEFPRINT(AST_ObjectGetter, function(self, output){
- output.print("get");
- output.space();
- self.key.print(output);
- self.value._do_print(output, true);
+ self._print_getter_setter("get", output);
});
DEFPRINT(AST_Symbol, function(self, output){
var def = self.definition();
@@ -1263,46 +1317,13 @@ function OutputStream(options) {
}
});
- function regexp_safe_literal(code) {
- return [
- 0x5c , // \
- 0x2f , // /
- 0x2e , // .
- 0x2b , // +
- 0x2a , // *
- 0x3f , // ?
- 0x28 , // (
- 0x29 , // )
- 0x5b , // [
- 0x5d , // ]
- 0x7b , // {
- 0x7d , // }
- 0x24 , // $
- 0x5e , // ^
- 0x3a , // :
- 0x7c , // |
- 0x21 , // !
- 0x0a , // \n
- 0x0d , // \r
- 0x00 , // \0
- 0xfeff , // Unicode BOM
- 0x2028 , // unicode "line separator"
- 0x2029 , // unicode "paragraph separator"
- ].indexOf(code) < 0;
- };
-
DEFPRINT(AST_RegExp, function(self, output){
- var str = self.getValue().toString();
- if (output.option("ascii_only")) {
- str = output.to_ascii(str);
- } else if (output.option("unescape_regexps")) {
- str = str.split("\\\\").map(function(str){
- return str.replace(/\\u[0-9a-fA-F]{4}|\\x[0-9a-fA-F]{2}/g, function(s){
- var code = parseInt(s.substr(2), 16);
- return regexp_safe_literal(code) ? String.fromCharCode(code) : s;
- });
- }).join("\\\\");
+ var regexp = self.getValue();
+ var str = regexp.toString();
+ if (regexp.raw_source) {
+ str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
}
+ str = output.to_utf8(str);
output.print(str);
var p = output.parent();
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)