Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d0b00317e | ||
|
|
db49daf365 | ||
|
|
923deeff35 | ||
|
|
0b62a28b47 | ||
|
|
44116c6d2b | ||
|
|
b5bab254ce | ||
|
|
81603ecd15 | ||
|
|
e67553fa55 | ||
|
|
fcf542f262 | ||
|
|
8adfc29f91 | ||
|
|
02f47e1713 | ||
|
|
07f64d4050 | ||
|
|
6982a0554c | ||
|
|
fa3250199a | ||
|
|
06b9894c19 | ||
|
|
9f9db504d7 | ||
|
|
82ae95c334 | ||
|
|
9a5e2052c4 | ||
|
|
b1410be443 | ||
|
|
12985d86c2 | ||
|
|
49bfc6b555 | ||
|
|
d1c6bb8c7c | ||
|
|
5c169615a8 |
20
bin/uglifyjs
20
bin/uglifyjs
@@ -46,7 +46,7 @@ program.option("--name-cache <file>", "File to hold mangled name mappings.");
|
|||||||
program.option("--rename", "Force symbol expansion.");
|
program.option("--rename", "Force symbol expansion.");
|
||||||
program.option("--no-rename", "Disable symbol expansion.");
|
program.option("--no-rename", "Disable symbol expansion.");
|
||||||
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
|
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
|
||||||
program.option("--source-map [options]", "Enable source map/specify source map options.", parse_source_map());
|
program.option("--source-map [options]", "Enable source map/specify source map options.", parse_js());
|
||||||
program.option("--timings", "Display operations run time on STDERR.")
|
program.option("--timings", "Display operations run time on STDERR.")
|
||||||
program.option("--toplevel", "Compress and/or mangle variables in toplevel scope.");
|
program.option("--toplevel", "Compress and/or mangle variables in toplevel scope.");
|
||||||
program.option("--verbose", "Print diagnostic messages.");
|
program.option("--verbose", "Print diagnostic messages.");
|
||||||
@@ -176,6 +176,11 @@ function run() {
|
|||||||
UglifyJS.AST_Node.warn_function = function(msg) {
|
UglifyJS.AST_Node.warn_function = function(msg) {
|
||||||
print_error("WARN: " + msg);
|
print_error("WARN: " + msg);
|
||||||
};
|
};
|
||||||
|
var content = program.sourceMap && program.sourceMap.content;
|
||||||
|
if (content && content != "inline") {
|
||||||
|
print_error("INFO: Using input source map: " + content);
|
||||||
|
options.sourceMap.content = read_file(content, content);
|
||||||
|
}
|
||||||
if (program.timings) options.timings = true;
|
if (program.timings) options.timings = true;
|
||||||
try {
|
try {
|
||||||
if (program.parse) {
|
if (program.parse) {
|
||||||
@@ -377,19 +382,6 @@ function parse_js(flag) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parse_source_map() {
|
|
||||||
var parse = parse_js();
|
|
||||||
return function(value, options) {
|
|
||||||
var hasContent = options && "content" in options;
|
|
||||||
var settings = parse(value, options);
|
|
||||||
if (!hasContent && settings.content && settings.content != "inline") {
|
|
||||||
print_error("INFO: Using input source map: " + settings.content);
|
|
||||||
settings.content = read_file(settings.content, settings.content);
|
|
||||||
}
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function skip_key(key) {
|
function skip_key(key) {
|
||||||
return skip_keys.indexOf(key) >= 0;
|
return skip_keys.indexOf(key) >= 0;
|
||||||
}
|
}
|
||||||
|
|||||||
130
lib/compress.js
130
lib/compress.js
@@ -428,14 +428,14 @@ merge(Compressor.prototype, {
|
|||||||
var parent = tw.parent(level);
|
var parent = tw.parent(level);
|
||||||
if (value && value.is_constant()) return;
|
if (value && value.is_constant()) return;
|
||||||
if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right
|
if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right
|
||||||
|| parent instanceof AST_Call && node !== parent.expression
|
|| parent instanceof AST_Call && (node !== parent.expression || parent instanceof AST_New)
|
||||||
|| parent instanceof AST_Exit && node === parent.value && node.scope !== d.scope
|
|| parent instanceof AST_Exit && node === parent.value && node.scope !== d.scope
|
||||||
|| parent instanceof AST_VarDef && node === parent.value) {
|
|| parent instanceof AST_VarDef && node === parent.value) {
|
||||||
if (depth > 1 && !(value && value.is_constant_expression(scope))) depth = 1;
|
if (depth > 1 && !(value && value.is_constant_expression(scope))) depth = 1;
|
||||||
if (!d.escaped || d.escaped > depth) d.escaped = depth;
|
if (!d.escaped || d.escaped > depth) d.escaped = depth;
|
||||||
return;
|
return;
|
||||||
} else if (parent instanceof AST_Array
|
} else if (parent instanceof AST_Array
|
||||||
|| parent instanceof AST_Binary && lazy_op(parent.operator)
|
|| parent instanceof AST_Binary && lazy_op[parent.operator]
|
||||||
|| parent instanceof AST_Conditional && node !== parent.condition
|
|| parent instanceof AST_Conditional && node !== parent.condition
|
||||||
|| parent instanceof AST_Sequence && node === parent.tail_node()) {
|
|| parent instanceof AST_Sequence && node === parent.tail_node()) {
|
||||||
mark_escaped(tw, d, scope, parent, parent, level + 1, depth);
|
mark_escaped(tw, d, scope, parent, parent, level + 1, depth);
|
||||||
@@ -489,7 +489,7 @@ merge(Compressor.prototype, {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
def(AST_Binary, function(tw) {
|
def(AST_Binary, function(tw) {
|
||||||
if (!lazy_op(this.operator)) return;
|
if (!lazy_op[this.operator]) return;
|
||||||
this.left.walk(tw);
|
this.left.walk(tw);
|
||||||
push(tw);
|
push(tw);
|
||||||
this.right.walk(tw);
|
this.right.walk(tw);
|
||||||
@@ -530,12 +530,11 @@ merge(Compressor.prototype, {
|
|||||||
tw.safe_ids = save_ids;
|
tw.safe_ids = save_ids;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
def(AST_Do, function(tw) {
|
def(AST_DWLoop, function(tw, descend) {
|
||||||
var saved_loop = tw.in_loop;
|
var saved_loop = tw.in_loop;
|
||||||
tw.in_loop = this;
|
tw.in_loop = this;
|
||||||
push(tw);
|
push(tw);
|
||||||
this.body.walk(tw);
|
descend();
|
||||||
this.condition.walk(tw);
|
|
||||||
pop(tw);
|
pop(tw);
|
||||||
tw.in_loop = saved_loop;
|
tw.in_loop = saved_loop;
|
||||||
return true;
|
return true;
|
||||||
@@ -714,16 +713,6 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
def(AST_While, function(tw) {
|
|
||||||
var saved_loop = tw.in_loop;
|
|
||||||
tw.in_loop = this;
|
|
||||||
push(tw);
|
|
||||||
this.condition.walk(tw);
|
|
||||||
this.body.walk(tw);
|
|
||||||
pop(tw);
|
|
||||||
tw.in_loop = saved_loop;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
})(function(node, func){
|
})(function(node, func){
|
||||||
node.DEFMETHOD("reduce_vars", func);
|
node.DEFMETHOD("reduce_vars", func);
|
||||||
});
|
});
|
||||||
@@ -895,7 +884,7 @@ merge(Compressor.prototype, {
|
|||||||
var global_names = makePredicate("Array Boolean clearInterval clearTimeout console Date decodeURI decodeURIComponent encodeURI encodeURIComponent Error escape eval EvalError Function isFinite isNaN JSON Math Number parseFloat parseInt RangeError ReferenceError RegExp Object setInterval setTimeout String SyntaxError TypeError unescape URIError");
|
var global_names = makePredicate("Array Boolean clearInterval clearTimeout console Date decodeURI decodeURIComponent encodeURI encodeURIComponent Error escape eval EvalError Function isFinite isNaN JSON Math Number parseFloat parseInt RangeError ReferenceError RegExp Object setInterval setTimeout String SyntaxError TypeError unescape URIError");
|
||||||
AST_SymbolRef.DEFMETHOD("is_declared", function(compressor) {
|
AST_SymbolRef.DEFMETHOD("is_declared", function(compressor) {
|
||||||
return !this.definition().undeclared
|
return !this.definition().undeclared
|
||||||
|| compressor.option("unsafe") && global_names(this.name);
|
|| compressor.option("unsafe") && global_names[this.name];
|
||||||
});
|
});
|
||||||
|
|
||||||
var identifier_atom = makePredicate("Infinity NaN undefined");
|
var identifier_atom = makePredicate("Infinity NaN undefined");
|
||||||
@@ -988,7 +977,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
// Stop only if candidate is found within conditional branches
|
// Stop only if candidate is found within conditional branches
|
||||||
if (!stop_if_hit
|
if (!stop_if_hit
|
||||||
&& (parent instanceof AST_Binary && lazy_op(parent.operator) && parent.left !== node
|
&& (parent instanceof AST_Binary && lazy_op[parent.operator] && parent.left !== node
|
||||||
|| parent instanceof AST_Conditional && parent.condition !== node
|
|| parent instanceof AST_Conditional && parent.condition !== node
|
||||||
|| parent instanceof AST_If && parent.condition !== node)) {
|
|| parent instanceof AST_If && parent.condition !== node)) {
|
||||||
stop_if_hit = parent;
|
stop_if_hit = parent;
|
||||||
@@ -1052,6 +1041,7 @@ merge(Compressor.prototype, {
|
|||||||
&& (side_effects || node.expression.may_throw_on_access(compressor))
|
&& (side_effects || node.expression.may_throw_on_access(compressor))
|
||||||
|| node instanceof AST_SymbolRef
|
|| node instanceof AST_SymbolRef
|
||||||
&& (symbol_in_lvalues(node) || side_effects && may_modify(node))
|
&& (symbol_in_lvalues(node) || side_effects && may_modify(node))
|
||||||
|
|| node instanceof AST_This && symbol_in_lvalues(node)
|
||||||
|| node instanceof AST_VarDef && node.value
|
|| node instanceof AST_VarDef && node.value
|
||||||
&& (node.name.name in lvalues || side_effects && may_modify(node.name))
|
&& (node.name.name in lvalues || side_effects && may_modify(node.name))
|
||||||
|| (sym = is_lhs(node.left, node))
|
|| (sym = is_lhs(node.left, node))
|
||||||
@@ -1295,7 +1285,7 @@ merge(Compressor.prototype, {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (parent instanceof AST_Binary) {
|
if (parent instanceof AST_Binary) {
|
||||||
if (write_only && (!lazy_op(parent.operator) || parent.left === node)) {
|
if (write_only && (!lazy_op[parent.operator] || parent.left === node)) {
|
||||||
return find_stop(parent, level + 1, write_only);
|
return find_stop(parent, level + 1, write_only);
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
@@ -2129,15 +2119,15 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
// methods to determine whether an expression has a boolean result type
|
// methods to determine whether an expression has a boolean result type
|
||||||
(function(def){
|
(function(def){
|
||||||
var unary_bool = [ "!", "delete" ];
|
var unary_bool = makePredicate("! delete");
|
||||||
var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ];
|
var binary_bool = makePredicate("in instanceof == != === !== < <= >= >");
|
||||||
def(AST_Node, return_false);
|
def(AST_Node, return_false);
|
||||||
def(AST_UnaryPrefix, function(){
|
def(AST_UnaryPrefix, function(){
|
||||||
return member(this.operator, unary_bool);
|
return unary_bool[this.operator];
|
||||||
});
|
});
|
||||||
def(AST_Binary, function(){
|
def(AST_Binary, function(){
|
||||||
return member(this.operator, binary_bool)
|
return binary_bool[this.operator]
|
||||||
|| lazy_op(this.operator)
|
|| lazy_op[this.operator]
|
||||||
&& this.left.is_boolean()
|
&& this.left.is_boolean()
|
||||||
&& this.right.is_boolean();
|
&& this.right.is_boolean();
|
||||||
});
|
});
|
||||||
@@ -2162,16 +2152,16 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Number, return_true);
|
def(AST_Number, return_true);
|
||||||
var unary = makePredicate("+ - ~ ++ --");
|
var unary = makePredicate("+ - ~ ++ --");
|
||||||
def(AST_Unary, function(){
|
def(AST_Unary, function(){
|
||||||
return unary(this.operator);
|
return unary[this.operator];
|
||||||
});
|
});
|
||||||
var binary = makePredicate("- * / % & | ^ << >> >>>");
|
var binary = makePredicate("- * / % & | ^ << >> >>>");
|
||||||
def(AST_Binary, function(compressor){
|
def(AST_Binary, function(compressor){
|
||||||
return binary(this.operator) || this.operator == "+"
|
return binary[this.operator] || this.operator == "+"
|
||||||
&& this.left.is_number(compressor)
|
&& this.left.is_number(compressor)
|
||||||
&& this.right.is_number(compressor);
|
&& this.right.is_number(compressor);
|
||||||
});
|
});
|
||||||
def(AST_Assign, function(compressor){
|
def(AST_Assign, function(compressor){
|
||||||
return binary(this.operator.slice(0, -1))
|
return binary[this.operator.slice(0, -1)]
|
||||||
|| this.operator == "=" && this.right.is_number(compressor);
|
|| this.operator == "=" && this.right.is_number(compressor);
|
||||||
});
|
});
|
||||||
def(AST_Sequence, function(compressor){
|
def(AST_Sequence, function(compressor){
|
||||||
@@ -2212,7 +2202,7 @@ merge(Compressor.prototype, {
|
|||||||
var unary_side_effects = makePredicate("delete ++ --");
|
var unary_side_effects = makePredicate("delete ++ --");
|
||||||
|
|
||||||
function is_lhs(node, parent) {
|
function is_lhs(node, parent) {
|
||||||
if (parent instanceof AST_Unary && unary_side_effects(parent.operator)) return parent.expression;
|
if (parent instanceof AST_Unary && unary_side_effects[parent.operator]) return parent.expression;
|
||||||
if (parent instanceof AST_Assign && parent.left === node) return node;
|
if (parent instanceof AST_Assign && parent.left === node) return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2415,7 +2405,7 @@ merge(Compressor.prototype, {
|
|||||||
} else {
|
} else {
|
||||||
return this instanceof AST_UnaryPrefix
|
return this instanceof AST_UnaryPrefix
|
||||||
&& this.expression instanceof AST_Constant
|
&& this.expression instanceof AST_Constant
|
||||||
&& unaryPrefix(this.operator);
|
&& unaryPrefix[this.operator];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
def(AST_Statement, function(){
|
def(AST_Statement, function(){
|
||||||
@@ -2485,7 +2475,7 @@ merge(Compressor.prototype, {
|
|||||||
&& e.fixed_value() instanceof AST_Lambda)) {
|
&& e.fixed_value() instanceof AST_Lambda)) {
|
||||||
return typeof function(){};
|
return typeof function(){};
|
||||||
}
|
}
|
||||||
if (!non_converting_unary(this.operator)) depth++;
|
if (!non_converting_unary[this.operator]) depth++;
|
||||||
e = e._eval(compressor, cached, depth);
|
e = e._eval(compressor, cached, depth);
|
||||||
if (e === this.expression) return this;
|
if (e === this.expression) return this;
|
||||||
switch (this.operator) {
|
switch (this.operator) {
|
||||||
@@ -2504,7 +2494,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
var non_converting_binary = makePredicate("&& || === !==");
|
var non_converting_binary = makePredicate("&& || === !==");
|
||||||
def(AST_Binary, function(compressor, cached, depth) {
|
def(AST_Binary, function(compressor, cached, depth) {
|
||||||
if (!non_converting_binary(this.operator)) depth++;
|
if (!non_converting_binary[this.operator]) depth++;
|
||||||
var left = this.left._eval(compressor, cached, depth);
|
var left = this.left._eval(compressor, cached, depth);
|
||||||
if (left === this.left) return this;
|
if (left === this.left) return this;
|
||||||
var right = this.right._eval(compressor, cached, depth);
|
var right = this.right._eval(compressor, cached, depth);
|
||||||
@@ -2607,7 +2597,8 @@ merge(Compressor.prototype, {
|
|||||||
var exp = this.expression;
|
var exp = this.expression;
|
||||||
var val;
|
var val;
|
||||||
if (is_undeclared_ref(exp)) {
|
if (is_undeclared_ref(exp)) {
|
||||||
if (!(static_values[exp.name] || return_false)(key)) return this;
|
var static_value = static_values[exp.name];
|
||||||
|
if (!static_value || !static_value[key]) return this;
|
||||||
val = global_objs[exp.name];
|
val = global_objs[exp.name];
|
||||||
} else {
|
} else {
|
||||||
val = exp._eval(compressor, cached, depth + 1);
|
val = exp._eval(compressor, cached, depth + 1);
|
||||||
@@ -2636,11 +2627,14 @@ merge(Compressor.prototype, {
|
|||||||
var val;
|
var val;
|
||||||
var e = exp.expression;
|
var e = exp.expression;
|
||||||
if (is_undeclared_ref(e)) {
|
if (is_undeclared_ref(e)) {
|
||||||
if (!(static_fns[e.name] || return_false)(key)) return this;
|
var static_fn = static_fns[e.name];
|
||||||
|
if (!static_fn || !static_fn[key]) return this;
|
||||||
val = global_objs[e.name];
|
val = global_objs[e.name];
|
||||||
} else {
|
} else {
|
||||||
val = e._eval(compressor, cached, depth + 1);
|
val = e._eval(compressor, cached, depth + 1);
|
||||||
if (val === e || !(val && native_fns[val.constructor.name] || return_false)(key)) return this;
|
if (val === e || !val) return this;
|
||||||
|
var native_fn = native_fns[val.constructor.name];
|
||||||
|
if (!native_fn || !native_fn[key]) return this;
|
||||||
}
|
}
|
||||||
var args = [];
|
var args = [];
|
||||||
for (var i = 0, len = this.args.length; i < len; i++) {
|
for (var i = 0, len = this.args.length; i < len; i++) {
|
||||||
@@ -2748,11 +2742,10 @@ merge(Compressor.prototype, {
|
|||||||
AST_Call.DEFMETHOD("is_expr_pure", function(compressor) {
|
AST_Call.DEFMETHOD("is_expr_pure", function(compressor) {
|
||||||
if (compressor.option("unsafe")) {
|
if (compressor.option("unsafe")) {
|
||||||
var expr = this.expression;
|
var expr = this.expression;
|
||||||
if (is_undeclared_ref(expr) && global_pure_fns(expr.name)) return true;
|
if (is_undeclared_ref(expr) && global_pure_fns[expr.name]) return true;
|
||||||
if (expr instanceof AST_Dot
|
if (expr instanceof AST_Dot && is_undeclared_ref(expr.expression)) {
|
||||||
&& is_undeclared_ref(expr.expression)
|
var static_fn = static_fns[expr.expression.name];
|
||||||
&& (static_fns[expr.expression.name] || return_false)(expr.property)) {
|
return static_fn && static_fn[expr.property];
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.pure || !compressor.pure_funcs(this);
|
return this.pure || !compressor.pure_funcs(this);
|
||||||
@@ -2761,21 +2754,21 @@ merge(Compressor.prototype, {
|
|||||||
AST_Dot.DEFMETHOD("is_call_pure", function(compressor) {
|
AST_Dot.DEFMETHOD("is_call_pure", function(compressor) {
|
||||||
if (!compressor.option("unsafe")) return;
|
if (!compressor.option("unsafe")) return;
|
||||||
var expr = this.expression;
|
var expr = this.expression;
|
||||||
var fns = return_false;
|
var map;
|
||||||
if (expr instanceof AST_Array) {
|
if (expr instanceof AST_Array) {
|
||||||
fns = native_fns.Array;
|
map = native_fns.Array;
|
||||||
} else if (expr.is_boolean()) {
|
} else if (expr.is_boolean()) {
|
||||||
fns = native_fns.Boolean;
|
map = native_fns.Boolean;
|
||||||
} else if (expr.is_number(compressor)) {
|
} else if (expr.is_number(compressor)) {
|
||||||
fns = native_fns.Number;
|
map = native_fns.Number;
|
||||||
} else if (expr instanceof AST_RegExp) {
|
} else if (expr instanceof AST_RegExp) {
|
||||||
fns = native_fns.RegExp;
|
map = native_fns.RegExp;
|
||||||
} else if (expr.is_string(compressor)) {
|
} else if (expr.is_string(compressor)) {
|
||||||
fns = native_fns.String;
|
map = native_fns.String;
|
||||||
} else if (!this.may_throw_on_access(compressor)) {
|
} else if (!this.may_throw_on_access(compressor)) {
|
||||||
fns = native_fns.Object;
|
map = native_fns.Object;
|
||||||
}
|
}
|
||||||
return fns(this.property);
|
return map && map[this.property];
|
||||||
});
|
});
|
||||||
|
|
||||||
// determine if expression has side effects
|
// determine if expression has side effects
|
||||||
@@ -2840,7 +2833,7 @@ merge(Compressor.prototype, {
|
|||||||
|| this.alternative.has_side_effects(compressor);
|
|| this.alternative.has_side_effects(compressor);
|
||||||
});
|
});
|
||||||
def(AST_Unary, function(compressor){
|
def(AST_Unary, function(compressor){
|
||||||
return unary_side_effects(this.operator)
|
return unary_side_effects[this.operator]
|
||||||
|| this.expression.has_side_effects(compressor);
|
|| this.expression.has_side_effects(compressor);
|
||||||
});
|
});
|
||||||
def(AST_SymbolRef, function(compressor){
|
def(AST_SymbolRef, function(compressor){
|
||||||
@@ -3525,8 +3518,9 @@ merge(Compressor.prototype, {
|
|||||||
var defs = [];
|
var defs = [];
|
||||||
vars.each(function(def, name){
|
vars.each(function(def, name){
|
||||||
if (self instanceof AST_Lambda
|
if (self instanceof AST_Lambda
|
||||||
&& find_if(function(x){ return x.name == def.name.name },
|
&& !all(self.argnames, function(argname) {
|
||||||
self.argnames)) {
|
return argname.name != name;
|
||||||
|
})) {
|
||||||
vars.del(name);
|
vars.del(name);
|
||||||
} else {
|
} else {
|
||||||
def = def.clone();
|
def = def.clone();
|
||||||
@@ -3623,8 +3617,9 @@ merge(Compressor.prototype, {
|
|||||||
var sym = node.name, def, value;
|
var sym = node.name, def, value;
|
||||||
if (sym.scope === self
|
if (sym.scope === self
|
||||||
&& (def = sym.definition()).escaped != 1
|
&& (def = sym.definition()).escaped != 1
|
||||||
&& !def.single_use
|
&& !def.assignments
|
||||||
&& !def.direct_access
|
&& !def.direct_access
|
||||||
|
&& !def.single_use
|
||||||
&& !top_retain(def)
|
&& !top_retain(def)
|
||||||
&& (value = sym.fixed_value()) === node.value
|
&& (value = sym.fixed_value()) === node.value
|
||||||
&& value instanceof AST_Object) {
|
&& value instanceof AST_Object) {
|
||||||
@@ -3728,7 +3723,7 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Binary, function(compressor, first_in_statement){
|
def(AST_Binary, function(compressor, first_in_statement){
|
||||||
var right = this.right.drop_side_effect_free(compressor);
|
var right = this.right.drop_side_effect_free(compressor);
|
||||||
if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement);
|
if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement);
|
||||||
if (lazy_op(this.operator)) {
|
if (lazy_op[this.operator]) {
|
||||||
if (right === this.right) return this;
|
if (right === this.right) return this;
|
||||||
var node = this.clone();
|
var node = this.clone();
|
||||||
node.right = right;
|
node.right = right;
|
||||||
@@ -3773,7 +3768,7 @@ merge(Compressor.prototype, {
|
|||||||
return node;
|
return node;
|
||||||
});
|
});
|
||||||
def(AST_Unary, function(compressor, first_in_statement){
|
def(AST_Unary, function(compressor, first_in_statement){
|
||||||
if (unary_side_effects(this.operator)) {
|
if (unary_side_effects[this.operator]) {
|
||||||
this.write_only = !this.expression.has_side_effects(compressor);
|
this.write_only = !this.expression.has_side_effects(compressor);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -4581,7 +4576,12 @@ merge(Compressor.prototype, {
|
|||||||
if (compressor.option("inline") && stat instanceof AST_Return) {
|
if (compressor.option("inline") && stat instanceof AST_Return) {
|
||||||
var value = stat.value;
|
var value = stat.value;
|
||||||
if (!value || value.is_constant_expression()) {
|
if (!value || value.is_constant_expression()) {
|
||||||
var args = self.args.concat(value || make_node(AST_Undefined, self));
|
if (value) {
|
||||||
|
value = value.clone(true);
|
||||||
|
} else {
|
||||||
|
value = make_node(AST_Undefined, self);
|
||||||
|
}
|
||||||
|
var args = self.args.concat(value);
|
||||||
return make_sequence(self, args).optimize(compressor);
|
return make_sequence(self, args).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4676,7 +4676,7 @@ merge(Compressor.prototype, {
|
|||||||
if (arg.__unused) continue;
|
if (arg.__unused) continue;
|
||||||
if (!safe_to_inject
|
if (!safe_to_inject
|
||||||
|| catches[arg.name]
|
|| catches[arg.name]
|
||||||
|| identifier_atom(arg.name)
|
|| identifier_atom[arg.name]
|
||||||
|| scope.var_names()[arg.name]) {
|
|| scope.var_names()[arg.name]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -4694,7 +4694,7 @@ merge(Compressor.prototype, {
|
|||||||
for (var j = stat.definitions.length; --j >= 0;) {
|
for (var j = stat.definitions.length; --j >= 0;) {
|
||||||
var name = stat.definitions[j].name;
|
var name = stat.definitions[j].name;
|
||||||
if (catches[name.name]
|
if (catches[name.name]
|
||||||
|| identifier_atom(name.name)
|
|| identifier_atom[name.name]
|
||||||
|| scope.var_names()[name.name]) {
|
|| scope.var_names()[name.name]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -4773,8 +4773,10 @@ merge(Compressor.prototype, {
|
|||||||
var var_def = stat.definitions[j];
|
var var_def = stat.definitions[j];
|
||||||
var name = var_def.name;
|
var name = var_def.name;
|
||||||
append_var(decls, expressions, name, var_def.value);
|
append_var(decls, expressions, name, var_def.value);
|
||||||
if (in_loop) {
|
if (in_loop && all(fn.argnames, function(argname) {
|
||||||
var def = name.definition();
|
return argname.name != name.name;
|
||||||
|
})) {
|
||||||
|
var def = fn.variables.get(name.name);
|
||||||
var sym = make_node(AST_SymbolRef, name, name);
|
var sym = make_node(AST_SymbolRef, name, name);
|
||||||
def.references.push(sym);
|
def.references.push(sym);
|
||||||
expressions.splice(pos++, 0, make_node(AST_Assign, var_def, {
|
expressions.splice(pos++, 0, make_node(AST_Assign, var_def, {
|
||||||
@@ -5007,7 +5009,7 @@ merge(Compressor.prototype, {
|
|||||||
self.right = tmp;
|
self.right = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (commutativeOperators(self.operator)) {
|
if (commutativeOperators[self.operator]) {
|
||||||
if (self.right.is_constant()
|
if (self.right.is_constant()
|
||||||
&& !self.left.is_constant()) {
|
&& !self.left.is_constant()) {
|
||||||
// if right is a constant, whatever side effects the
|
// if right is a constant, whatever side effects the
|
||||||
@@ -5400,7 +5402,7 @@ merge(Compressor.prototype, {
|
|||||||
// "x" + (y + "z")==> "x" + y + "z"
|
// "x" + (y + "z")==> "x" + y + "z"
|
||||||
if (self.right instanceof AST_Binary
|
if (self.right instanceof AST_Binary
|
||||||
&& self.right.operator == self.operator
|
&& self.right.operator == self.operator
|
||||||
&& (lazy_op(self.operator)
|
&& (lazy_op[self.operator]
|
||||||
|| (self.operator == "+"
|
|| (self.operator == "+"
|
||||||
&& (self.right.left.is_string(compressor)
|
&& (self.right.left.is_string(compressor)
|
||||||
|| (self.left.is_string(compressor)
|
|| (self.left.is_string(compressor)
|
||||||
@@ -5651,8 +5653,8 @@ merge(Compressor.prototype, {
|
|||||||
return reachable;
|
return reachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
|
var ASSIGN_OPS = makePredicate("+ - / * % >> << >>> | ^ &");
|
||||||
var ASSIGN_OPS_COMMUTATIVE = [ '*', '|', '^', '&' ];
|
var ASSIGN_OPS_COMMUTATIVE = makePredicate("* | ^ &");
|
||||||
OPT(AST_Assign, function(self, compressor){
|
OPT(AST_Assign, function(self, compressor){
|
||||||
var def;
|
var def;
|
||||||
if (compressor.option("dead_code")
|
if (compressor.option("dead_code")
|
||||||
@@ -5681,14 +5683,14 @@ merge(Compressor.prototype, {
|
|||||||
// x = expr1 OP expr2
|
// x = expr1 OP expr2
|
||||||
if (self.right.left instanceof AST_SymbolRef
|
if (self.right.left instanceof AST_SymbolRef
|
||||||
&& self.right.left.name == self.left.name
|
&& self.right.left.name == self.left.name
|
||||||
&& member(self.right.operator, ASSIGN_OPS)) {
|
&& ASSIGN_OPS[self.right.operator]) {
|
||||||
// x = x - 2 ---> x -= 2
|
// x = x - 2 ---> x -= 2
|
||||||
self.operator = self.right.operator + "=";
|
self.operator = self.right.operator + "=";
|
||||||
self.right = self.right.right;
|
self.right = self.right.right;
|
||||||
}
|
}
|
||||||
else if (self.right.right instanceof AST_SymbolRef
|
else if (self.right.right instanceof AST_SymbolRef
|
||||||
&& self.right.right.name == self.left.name
|
&& self.right.right.name == self.left.name
|
||||||
&& member(self.right.operator, ASSIGN_OPS_COMMUTATIVE)
|
&& ASSIGN_OPS_COMMUTATIVE[self.right.operator]
|
||||||
&& !self.right.left.has_side_effects(compressor)) {
|
&& !self.right.left.has_side_effects(compressor)) {
|
||||||
// x = 2 & x ---> x &= 2
|
// x = 2 & x ---> x &= 2
|
||||||
self.operator = self.right.operator + "=";
|
self.operator = self.right.operator + "=";
|
||||||
|
|||||||
@@ -7,15 +7,23 @@ var to_base64 = typeof btoa == "undefined" ? function(str) {
|
|||||||
return new Buffer(str).toString("base64");
|
return new Buffer(str).toString("base64");
|
||||||
} : btoa;
|
} : btoa;
|
||||||
|
|
||||||
function read_source_map(code) {
|
function read_source_map(name, code) {
|
||||||
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
|
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
AST_Node.warn("inline source map not found");
|
AST_Node.warn("inline source map not found: " + name);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return to_ascii(match[2]);
|
return to_ascii(match[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parse_source_map(content) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(content);
|
||||||
|
} catch (ex) {
|
||||||
|
throw new Error("invalid input source map: " + content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function set_shorthand(name, options, keys) {
|
function set_shorthand(name, options, keys) {
|
||||||
if (options[name]) {
|
if (options[name]) {
|
||||||
keys.forEach(function(key) {
|
keys.forEach(function(key) {
|
||||||
@@ -113,7 +121,7 @@ function minify(files, options) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (timings) timings.parse = Date.now();
|
if (timings) timings.parse = Date.now();
|
||||||
var toplevel;
|
var source_maps, toplevel;
|
||||||
if (files instanceof AST_Toplevel) {
|
if (files instanceof AST_Toplevel) {
|
||||||
toplevel = files;
|
toplevel = files;
|
||||||
} else {
|
} else {
|
||||||
@@ -122,13 +130,23 @@ function minify(files, options) {
|
|||||||
}
|
}
|
||||||
options.parse = options.parse || {};
|
options.parse = options.parse || {};
|
||||||
options.parse.toplevel = null;
|
options.parse.toplevel = null;
|
||||||
|
var source_map_content = options.sourceMap && options.sourceMap.content;
|
||||||
|
if (typeof source_map_content == "string" && source_map_content != "inline") {
|
||||||
|
source_map_content = parse_source_map(source_map_content);
|
||||||
|
}
|
||||||
|
source_maps = source_map_content && Object.create(null);
|
||||||
for (var name in files) if (HOP(files, name)) {
|
for (var name in files) if (HOP(files, name)) {
|
||||||
options.parse.filename = name;
|
options.parse.filename = name;
|
||||||
options.parse.toplevel = parse(files[name], options.parse);
|
options.parse.toplevel = parse(files[name], options.parse);
|
||||||
if (options.sourceMap && options.sourceMap.content == "inline") {
|
if (source_maps) {
|
||||||
if (Object.keys(files).length > 1)
|
if (source_map_content == "inline") {
|
||||||
throw new Error("inline source map only works with singular input");
|
var inlined_content = read_source_map(name, files[name]);
|
||||||
options.sourceMap.content = read_source_map(files[name]);
|
if (inlined_content) {
|
||||||
|
source_maps[name] = parse_source_map(inlined_content);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
source_maps[name] = source_map_content;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toplevel = options.parse.toplevel;
|
toplevel = options.parse.toplevel;
|
||||||
@@ -164,12 +182,9 @@ function minify(files, options) {
|
|||||||
}
|
}
|
||||||
if (!HOP(options.output, "code") || options.output.code) {
|
if (!HOP(options.output, "code") || options.output.code) {
|
||||||
if (options.sourceMap) {
|
if (options.sourceMap) {
|
||||||
if (typeof options.sourceMap.content == "string") {
|
|
||||||
options.sourceMap.content = JSON.parse(options.sourceMap.content);
|
|
||||||
}
|
|
||||||
options.output.source_map = SourceMap({
|
options.output.source_map = SourceMap({
|
||||||
file: options.sourceMap.filename,
|
file: options.sourceMap.filename,
|
||||||
orig: options.sourceMap.content,
|
orig: source_maps,
|
||||||
root: options.sourceMap.root
|
root: options.sourceMap.root
|
||||||
});
|
});
|
||||||
if (options.sourceMap.includeSources) {
|
if (options.sourceMap.includeSources) {
|
||||||
@@ -178,6 +193,8 @@ function minify(files, options) {
|
|||||||
} else for (var name in files) if (HOP(files, name)) {
|
} else for (var name in files) if (HOP(files, name)) {
|
||||||
options.output.source_map.get().setSourceContent(name, files[name]);
|
options.output.source_map.get().setSourceContent(name, files[name]);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
options.output.source_map.get()._sourcesContents = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete options.output.ast;
|
delete options.output.ast;
|
||||||
|
|||||||
@@ -180,6 +180,17 @@
|
|||||||
end : my_end_token(M)
|
end : my_end_token(M)
|
||||||
};
|
};
|
||||||
if (val === null) return new AST_Null(args);
|
if (val === null) return new AST_Null(args);
|
||||||
|
var rx = M.regex;
|
||||||
|
if (rx && rx.pattern) {
|
||||||
|
// RegExpLiteral as per ESTree AST spec
|
||||||
|
args.value = new RegExp(rx.pattern, rx.flags);
|
||||||
|
args.value.raw_source = rx.pattern;
|
||||||
|
return new AST_RegExp(args);
|
||||||
|
} else if (rx) {
|
||||||
|
// support legacy RegExp
|
||||||
|
args.value = M.regex && M.raw ? M.raw : val;
|
||||||
|
return new AST_RegExp(args);
|
||||||
|
}
|
||||||
switch (typeof val) {
|
switch (typeof val) {
|
||||||
case "string":
|
case "string":
|
||||||
args.value = val;
|
args.value = val;
|
||||||
@@ -189,16 +200,6 @@
|
|||||||
return new AST_Number(args);
|
return new AST_Number(args);
|
||||||
case "boolean":
|
case "boolean":
|
||||||
return new (val ? AST_True : AST_False)(args);
|
return new (val ? AST_True : AST_False)(args);
|
||||||
default:
|
|
||||||
var rx = M.regex;
|
|
||||||
if (rx && rx.pattern) {
|
|
||||||
// RegExpLiteral as per ESTree AST spec
|
|
||||||
args.value = new RegExp(rx.pattern, rx.flags).toString();
|
|
||||||
} else {
|
|
||||||
// support legacy RegExp
|
|
||||||
args.value = M.regex && M.raw ? M.raw : val;
|
|
||||||
}
|
|
||||||
return new AST_RegExp(args);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Identifier: function(M) {
|
Identifier: function(M) {
|
||||||
@@ -410,14 +411,15 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
|
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
|
||||||
var value = M.value;
|
var flags = M.value.toString().match(/[gimuy]*$/)[0];
|
||||||
|
var value = "/" + M.value.raw_source + "/" + flags;
|
||||||
return {
|
return {
|
||||||
type: "Literal",
|
type: "Literal",
|
||||||
value: value,
|
value: value,
|
||||||
raw: value.toString(),
|
raw: value,
|
||||||
regex: {
|
regex: {
|
||||||
pattern: value.source,
|
pattern: M.value.raw_source,
|
||||||
flags: value.toString().match(/[gimuy]*$/)[0]
|
flags: flags
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -564,6 +566,21 @@
|
|||||||
FROM_MOZ_STACK = [];
|
FROM_MOZ_STACK = [];
|
||||||
var ast = from_moz(node);
|
var ast = from_moz(node);
|
||||||
FROM_MOZ_STACK = save_stack;
|
FROM_MOZ_STACK = save_stack;
|
||||||
|
ast.walk(new TreeWalker(function(node) {
|
||||||
|
if (node instanceof AST_LabelRef) {
|
||||||
|
for (var level = 0, parent; parent = this.parent(level); level++) {
|
||||||
|
if (parent instanceof AST_Scope) break;
|
||||||
|
if (parent instanceof AST_LabeledStatement && parent.label.name == node.name) {
|
||||||
|
node.thedef = parent.label;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!node.thedef) {
|
||||||
|
var s = node.start;
|
||||||
|
js_error("Undefined label " + node.name, s.file, s.line, s.col, s.pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
return ast;
|
return ast;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -197,6 +197,7 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
/* -----[ beautification/minification ]----- */
|
/* -----[ beautification/minification ]----- */
|
||||||
|
|
||||||
|
var has_parens = false;
|
||||||
var might_need_space = false;
|
var might_need_space = false;
|
||||||
var might_need_semicolon = false;
|
var might_need_semicolon = false;
|
||||||
var might_add_newline = 0;
|
var might_add_newline = 0;
|
||||||
@@ -280,7 +281,7 @@ function OutputStream(options) {
|
|||||||
might_need_semicolon = false;
|
might_need_semicolon = false;
|
||||||
|
|
||||||
if (prev == ":" && ch == "}" || (!ch || ";}".indexOf(ch) < 0) && prev != ";") {
|
if (prev == ":" && ch == "}" || (!ch || ";}".indexOf(ch) < 0) && prev != ";") {
|
||||||
if (options.semicolons || requireSemicolonChars(ch)) {
|
if (options.semicolons || requireSemicolonChars[ch]) {
|
||||||
OUTPUT += ";";
|
OUTPUT += ";";
|
||||||
current_col++;
|
current_col++;
|
||||||
current_pos++;
|
current_pos++;
|
||||||
@@ -340,6 +341,7 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OUTPUT += str;
|
OUTPUT += str;
|
||||||
|
has_parens = str[str.length - 1] == "(";
|
||||||
current_pos += str.length;
|
current_pos += str.length;
|
||||||
var a = str.split(/\r?\n/), n = a.length - 1;
|
var a = str.split(/\r?\n/), n = a.length - 1;
|
||||||
current_line += n;
|
current_line += n;
|
||||||
@@ -576,7 +578,7 @@ function OutputStream(options) {
|
|||||||
indentation : function() { return indentation },
|
indentation : function() { return indentation },
|
||||||
current_width : function() { return current_col - indentation },
|
current_width : function() { return current_col - indentation },
|
||||||
should_break : function() { return options.width && this.current_width() >= options.width },
|
should_break : function() { return options.width && this.current_width() >= options.width },
|
||||||
has_parens : function() { return OUTPUT.slice(-1) == "(" },
|
has_parens : function() { return has_parens },
|
||||||
newline : newline,
|
newline : newline,
|
||||||
print : print,
|
print : print,
|
||||||
space : space,
|
space : space,
|
||||||
@@ -1244,7 +1246,7 @@ function OutputStream(options) {
|
|||||||
var expr = self.expression;
|
var expr = self.expression;
|
||||||
expr.print(output);
|
expr.print(output);
|
||||||
var prop = self.property;
|
var prop = self.property;
|
||||||
if (output.option("ie8") && RESERVED_WORDS(prop)) {
|
if (output.option("ie8") && RESERVED_WORDS[prop]) {
|
||||||
output.print("[");
|
output.print("[");
|
||||||
output.add_mapping(self.end);
|
output.add_mapping(self.end);
|
||||||
output.print_string(prop);
|
output.print_string(prop);
|
||||||
@@ -1356,7 +1358,7 @@ function OutputStream(options) {
|
|||||||
output.print_string(key);
|
output.print_string(key);
|
||||||
} else if ("" + +key == key && key >= 0) {
|
} else if ("" + +key == key && key >= 0) {
|
||||||
output.print(make_num(key));
|
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")) {
|
if (quote && output.option("keep_quoted_props")) {
|
||||||
output.print_string(key, quote);
|
output.print_string(key, quote);
|
||||||
} else {
|
} else {
|
||||||
@@ -1484,47 +1486,52 @@ function OutputStream(options) {
|
|||||||
/* -----[ source map generators ]----- */
|
/* -----[ source map generators ]----- */
|
||||||
|
|
||||||
function DEFMAP(nodetype, generator) {
|
function DEFMAP(nodetype, generator) {
|
||||||
nodetype.DEFMETHOD("add_source_map", function(stream){
|
nodetype.forEach(function(nodetype) {
|
||||||
generator(this, stream);
|
nodetype.DEFMETHOD("add_source_map", generator);
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
// We could easily add info for ALL nodes, but it seems to me that
|
DEFMAP([
|
||||||
// would be quite wasteful, hence this noop in the base class.
|
// We could easily add info for ALL nodes, but it seems to me that
|
||||||
DEFMAP(AST_Node, noop);
|
// would be quite wasteful, hence this noop in the base class.
|
||||||
|
AST_Node,
|
||||||
function basic_sourcemap_gen(self, output) {
|
// since the label symbol will mark it
|
||||||
output.add_mapping(self.start);
|
AST_LabeledStatement,
|
||||||
};
|
AST_Toplevel,
|
||||||
|
], noop);
|
||||||
|
|
||||||
// XXX: I'm not exactly sure if we need it for all of these nodes,
|
// XXX: I'm not exactly sure if we need it for all of these nodes,
|
||||||
// or if we should add even more.
|
// or if we should add even more.
|
||||||
|
DEFMAP([
|
||||||
DEFMAP(AST_Directive, basic_sourcemap_gen);
|
AST_Array,
|
||||||
DEFMAP(AST_Debugger, basic_sourcemap_gen);
|
AST_BlockStatement,
|
||||||
DEFMAP(AST_Symbol, basic_sourcemap_gen);
|
AST_Catch,
|
||||||
DEFMAP(AST_Jump, basic_sourcemap_gen);
|
AST_Constant,
|
||||||
DEFMAP(AST_StatementWithBody, basic_sourcemap_gen);
|
AST_Debugger,
|
||||||
DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it
|
AST_Definitions,
|
||||||
DEFMAP(AST_Lambda, basic_sourcemap_gen);
|
AST_Directive,
|
||||||
DEFMAP(AST_Switch, basic_sourcemap_gen);
|
AST_Finally,
|
||||||
DEFMAP(AST_SwitchBranch, basic_sourcemap_gen);
|
AST_Jump,
|
||||||
DEFMAP(AST_BlockStatement, basic_sourcemap_gen);
|
AST_Lambda,
|
||||||
DEFMAP(AST_Toplevel, noop);
|
AST_New,
|
||||||
DEFMAP(AST_New, basic_sourcemap_gen);
|
AST_Object,
|
||||||
DEFMAP(AST_Try, basic_sourcemap_gen);
|
AST_StatementWithBody,
|
||||||
DEFMAP(AST_Catch, basic_sourcemap_gen);
|
AST_Symbol,
|
||||||
DEFMAP(AST_Finally, basic_sourcemap_gen);
|
AST_Switch,
|
||||||
DEFMAP(AST_Definitions, basic_sourcemap_gen);
|
AST_SwitchBranch,
|
||||||
DEFMAP(AST_Constant, basic_sourcemap_gen);
|
AST_Try,
|
||||||
DEFMAP(AST_ObjectSetter, function(self, output){
|
], function(output) {
|
||||||
output.add_mapping(self.start, self.key.name);
|
output.add_mapping(this.start);
|
||||||
});
|
|
||||||
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_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);
|
||||||
|
});
|
||||||
})();
|
})();
|
||||||
|
|||||||
46
lib/parse.js
46
lib/parse.js
@@ -165,7 +165,7 @@ function is_unicode_connector_punctuation(ch) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function is_identifier(name) {
|
function is_identifier(name) {
|
||||||
return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name);
|
return !RESERVED_WORDS[name] && /^[a-z_$][a-z0-9_$]*$/i.test(name);
|
||||||
};
|
};
|
||||||
|
|
||||||
function is_identifier_start(code) {
|
function is_identifier_start(code) {
|
||||||
@@ -245,7 +245,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
var ch = S.text.charAt(S.pos++);
|
var ch = S.text.charAt(S.pos++);
|
||||||
if (signal_eof && !ch)
|
if (signal_eof && !ch)
|
||||||
throw EX_EOF;
|
throw EX_EOF;
|
||||||
if (NEWLINE_CHARS(ch)) {
|
if (NEWLINE_CHARS[ch]) {
|
||||||
S.newline_before = S.newline_before || !in_string;
|
S.newline_before = S.newline_before || !in_string;
|
||||||
++S.line;
|
++S.line;
|
||||||
S.col = 0;
|
S.col = 0;
|
||||||
@@ -272,7 +272,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
var text = S.text;
|
var text = S.text;
|
||||||
for (var i = S.pos, n = S.text.length; i < n; ++i) {
|
for (var i = S.pos, n = S.text.length; i < n; ++i) {
|
||||||
var ch = text[i];
|
var ch = text[i];
|
||||||
if (NEWLINE_CHARS(ch))
|
if (NEWLINE_CHARS[ch])
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -292,9 +292,9 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
|
|
||||||
var prev_was_dot = false;
|
var prev_was_dot = false;
|
||||||
function token(type, value, is_comment) {
|
function token(type, value, is_comment) {
|
||||||
S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX(value)) ||
|
S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX[value]) ||
|
||||||
(type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) ||
|
(type == "keyword" && KEYWORDS_BEFORE_EXPRESSION[value]) ||
|
||||||
(type == "punc" && PUNC_BEFORE_EXPRESSION(value)));
|
(type == "punc" && PUNC_BEFORE_EXPRESSION[value]));
|
||||||
if (type == "punc" && value == ".") {
|
if (type == "punc" && value == ".") {
|
||||||
prev_was_dot = true;
|
prev_was_dot = true;
|
||||||
} else if (!is_comment) {
|
} else if (!is_comment) {
|
||||||
@@ -324,7 +324,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function skip_whitespace() {
|
function skip_whitespace() {
|
||||||
while (WHITESPACE_CHARS(peek()))
|
while (WHITESPACE_CHARS[peek()])
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -424,7 +424,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
var ch = next(true, true);
|
var ch = next(true, true);
|
||||||
if (ch == "\\") ch = read_escaped_char(true);
|
if (ch == "\\") ch = read_escaped_char(true);
|
||||||
else if (NEWLINE_CHARS(ch)) parse_error("Unterminated string constant");
|
else if (NEWLINE_CHARS[ch]) parse_error("Unterminated string constant");
|
||||||
else if (ch == quote) break;
|
else if (ch == quote) break;
|
||||||
ret += ch;
|
ret += ch;
|
||||||
}
|
}
|
||||||
@@ -476,7 +476,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
backslash = false;
|
backslash = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (KEYWORDS(name) && escaped) {
|
if (KEYWORDS[name] && escaped) {
|
||||||
hex = name.charCodeAt(0).toString(16).toUpperCase();
|
hex = name.charCodeAt(0).toString(16).toUpperCase();
|
||||||
name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
|
name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
|
||||||
}
|
}
|
||||||
@@ -485,7 +485,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
|
|
||||||
var read_regexp = with_eof_error("Unterminated regular expression", function(source) {
|
var read_regexp = with_eof_error("Unterminated regular expression", function(source) {
|
||||||
var prev_backslash = false, ch, in_class = false;
|
var prev_backslash = false, ch, in_class = false;
|
||||||
while ((ch = next(true))) if (NEWLINE_CHARS(ch)) {
|
while ((ch = next(true))) if (NEWLINE_CHARS[ch]) {
|
||||||
parse_error("Unexpected line terminator");
|
parse_error("Unexpected line terminator");
|
||||||
} else if (prev_backslash) {
|
} else if (prev_backslash) {
|
||||||
source += "\\" + ch;
|
source += "\\" + ch;
|
||||||
@@ -517,7 +517,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
function grow(op) {
|
function grow(op) {
|
||||||
if (!peek()) return op;
|
if (!peek()) return op;
|
||||||
var bigger = op + peek();
|
var bigger = op + peek();
|
||||||
if (OPERATORS(bigger)) {
|
if (OPERATORS[bigger]) {
|
||||||
next();
|
next();
|
||||||
return grow(bigger);
|
return grow(bigger);
|
||||||
} else {
|
} else {
|
||||||
@@ -550,9 +550,9 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
function read_word() {
|
function read_word() {
|
||||||
var word = read_name();
|
var word = read_name();
|
||||||
if (prev_was_dot) return token("name", word);
|
if (prev_was_dot) return token("name", word);
|
||||||
return KEYWORDS_ATOM(word) ? token("atom", word)
|
return KEYWORDS_ATOM[word] ? token("atom", word)
|
||||||
: !KEYWORDS(word) ? token("name", word)
|
: !KEYWORDS[word] ? token("name", word)
|
||||||
: OPERATORS(word) ? token("operator", word)
|
: OPERATORS[word] ? token("operator", word)
|
||||||
: token("keyword", word);
|
: token("keyword", word);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -603,8 +603,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is_digit(code)) return read_num();
|
if (is_digit(code)) return read_num();
|
||||||
if (PUNC_CHARS(ch)) return token("punc", next());
|
if (PUNC_CHARS[ch]) return token("punc", next());
|
||||||
if (OPERATOR_CHARS(ch)) return read_operator();
|
if (OPERATOR_CHARS[ch]) return read_operator();
|
||||||
if (code == 92 || is_identifier_start(code)) return read_word();
|
if (code == 92 || is_identifier_start(code)) return read_word();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -969,7 +969,9 @@ function parse($TEXT, options) {
|
|||||||
|
|
||||||
function labeled_statement() {
|
function labeled_statement() {
|
||||||
var label = as_symbol(AST_Label);
|
var label = as_symbol(AST_Label);
|
||||||
if (find_if(function(l){ return l.name == label.name }, S.labels)) {
|
if (!all(S.labels, function(l) {
|
||||||
|
return l.name != label.name;
|
||||||
|
})) {
|
||||||
// ECMA-262, 12.12: An ECMAScript program is considered
|
// ECMA-262, 12.12: An ECMAScript program is considered
|
||||||
// syntactically incorrect if it contains a
|
// syntactically incorrect if it contains a
|
||||||
// LabelledStatement that is enclosed by a
|
// LabelledStatement that is enclosed by a
|
||||||
@@ -1319,7 +1321,7 @@ function parse($TEXT, options) {
|
|||||||
func.end = prev();
|
func.end = prev();
|
||||||
return subscripts(func, allow_calls);
|
return subscripts(func, allow_calls);
|
||||||
}
|
}
|
||||||
if (ATOMIC_START_TOKEN(S.token.type)) {
|
if (ATOMIC_START_TOKEN[S.token.type]) {
|
||||||
return subscripts(as_atom_node(), allow_calls);
|
return subscripts(as_atom_node(), allow_calls);
|
||||||
}
|
}
|
||||||
unexpected();
|
unexpected();
|
||||||
@@ -1404,7 +1406,7 @@ function parse($TEXT, options) {
|
|||||||
var tmp = S.token;
|
var tmp = S.token;
|
||||||
switch (tmp.type) {
|
switch (tmp.type) {
|
||||||
case "operator":
|
case "operator":
|
||||||
if (!KEYWORDS(tmp.value)) unexpected();
|
if (!KEYWORDS[tmp.value]) unexpected();
|
||||||
case "num":
|
case "num":
|
||||||
case "string":
|
case "string":
|
||||||
case "name":
|
case "name":
|
||||||
@@ -1502,7 +1504,7 @@ function parse($TEXT, options) {
|
|||||||
|
|
||||||
var maybe_unary = function(allow_calls) {
|
var maybe_unary = function(allow_calls) {
|
||||||
var start = S.token;
|
var start = S.token;
|
||||||
if (is("operator") && UNARY_PREFIX(start.value)) {
|
if (is("operator") && UNARY_PREFIX[start.value]) {
|
||||||
next();
|
next();
|
||||||
handle_regexp();
|
handle_regexp();
|
||||||
var ex = make_unary(AST_UnaryPrefix, start, maybe_unary(allow_calls));
|
var ex = make_unary(AST_UnaryPrefix, start, maybe_unary(allow_calls));
|
||||||
@@ -1511,7 +1513,7 @@ function parse($TEXT, options) {
|
|||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
var val = expr_atom(allow_calls);
|
var val = expr_atom(allow_calls);
|
||||||
while (is("operator") && UNARY_POSTFIX(S.token.value) && !has_newline_before(S.token)) {
|
while (is("operator") && UNARY_POSTFIX[S.token.value] && !has_newline_before(S.token)) {
|
||||||
val = make_unary(AST_UnaryPostfix, S.token, val);
|
val = make_unary(AST_UnaryPostfix, S.token, val);
|
||||||
val.start = start;
|
val.start = start;
|
||||||
val.end = S.token;
|
val.end = S.token;
|
||||||
@@ -1583,7 +1585,7 @@ function parse($TEXT, options) {
|
|||||||
var maybe_assign = function(no_in) {
|
var maybe_assign = function(no_in) {
|
||||||
var start = S.token;
|
var start = S.token;
|
||||||
var left = maybe_conditional(no_in), val = S.token.value;
|
var left = maybe_conditional(no_in), val = S.token.value;
|
||||||
if (is("operator") && ASSIGNMENT(val)) {
|
if (is("operator") && ASSIGNMENT[val]) {
|
||||||
if (is_assignable(left)) {
|
if (is_assignable(left)) {
|
||||||
next();
|
next();
|
||||||
return new AST_Assign({
|
return new AST_Assign({
|
||||||
|
|||||||
@@ -150,6 +150,10 @@ function mangle_properties(ast, options) {
|
|||||||
else if (node instanceof AST_Sub) {
|
else if (node instanceof AST_Sub) {
|
||||||
addStrings(node.property, add);
|
addStrings(node.property, add);
|
||||||
}
|
}
|
||||||
|
else if (node instanceof AST_Call
|
||||||
|
&& node.expression.print_to_string() == "Object.defineProperty") {
|
||||||
|
addStrings(node.args[1], add);
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// step 2: transform the tree, renaming properties
|
// step 2: transform the tree, renaming properties
|
||||||
@@ -167,6 +171,10 @@ function mangle_properties(ast, options) {
|
|||||||
else if (!options.keep_quoted && node instanceof AST_Sub) {
|
else if (!options.keep_quoted && node instanceof AST_Sub) {
|
||||||
node.property = mangleStrings(node.property);
|
node.property = mangleStrings(node.property);
|
||||||
}
|
}
|
||||||
|
else if (node instanceof AST_Call
|
||||||
|
&& node.expression.print_to_string() == "Object.defineProperty") {
|
||||||
|
node.args[1] = mangleStrings(node.args[1]);
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// only function declarations after this line
|
// only function declarations after this line
|
||||||
|
|||||||
46
lib/scope.js
46
lib/scope.js
@@ -100,7 +100,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
// pass 1: setup scope chaining and handle definitions
|
// pass 1: setup scope chaining and handle definitions
|
||||||
var self = this;
|
var self = this;
|
||||||
var scope = self.parent_scope = null;
|
var scope = self.parent_scope = null;
|
||||||
var labels = new Dictionary();
|
|
||||||
var defun = null;
|
var defun = null;
|
||||||
var tw = new TreeWalker(function(node, descend){
|
var tw = new TreeWalker(function(node, descend){
|
||||||
if (node instanceof AST_Catch) {
|
if (node instanceof AST_Catch) {
|
||||||
@@ -115,25 +114,12 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
node.init_scope_vars(scope);
|
node.init_scope_vars(scope);
|
||||||
var save_scope = scope;
|
var save_scope = scope;
|
||||||
var save_defun = defun;
|
var save_defun = defun;
|
||||||
var save_labels = labels;
|
|
||||||
defun = scope = node;
|
defun = scope = node;
|
||||||
labels = new Dictionary();
|
|
||||||
descend();
|
descend();
|
||||||
scope = save_scope;
|
scope = save_scope;
|
||||||
defun = save_defun;
|
defun = save_defun;
|
||||||
labels = save_labels;
|
|
||||||
return true; // don't descend again in TreeWalker
|
return true; // don't descend again in TreeWalker
|
||||||
}
|
}
|
||||||
if (node instanceof AST_LabeledStatement) {
|
|
||||||
var l = node.label;
|
|
||||||
if (labels.has(l.name)) {
|
|
||||||
throw new Error(string_template("Label {name} defined twice", l));
|
|
||||||
}
|
|
||||||
labels.set(l.name, l);
|
|
||||||
descend();
|
|
||||||
labels.del(l.name);
|
|
||||||
return true; // no descend again
|
|
||||||
}
|
|
||||||
if (node instanceof AST_With) {
|
if (node instanceof AST_With) {
|
||||||
for (var s = scope; s; s = s.parent_scope)
|
for (var s = scope; s; s = s.parent_scope)
|
||||||
s.uses_with = true;
|
s.uses_with = true;
|
||||||
@@ -171,15 +157,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
else if (node instanceof AST_SymbolCatch) {
|
else if (node instanceof AST_SymbolCatch) {
|
||||||
scope.def_variable(node).defun = defun;
|
scope.def_variable(node).defun = defun;
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_LabelRef) {
|
|
||||||
var sym = labels.get(node.name);
|
|
||||||
if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", {
|
|
||||||
name: node.name,
|
|
||||||
line: node.start.line,
|
|
||||||
col: node.start.col
|
|
||||||
}));
|
|
||||||
node.thedef = sym;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
self.walk(tw);
|
self.walk(tw);
|
||||||
|
|
||||||
@@ -367,7 +344,7 @@ function next_mangled_name(scope, options, def) {
|
|||||||
}
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
name = base54(++scope.cname);
|
name = base54(++scope.cname);
|
||||||
if (in_use[name] || !is_identifier(name) || member(name, options.reserved)) continue;
|
if (in_use[name] || !is_identifier(name) || options._reserved[name]) continue;
|
||||||
if (!names[name]) break;
|
if (!names[name]) break;
|
||||||
holes.push(scope.cname);
|
holes.push(scope.cname);
|
||||||
}
|
}
|
||||||
@@ -410,6 +387,7 @@ function _default_mangler_options(options) {
|
|||||||
if (!Array.isArray(options.reserved)) options.reserved = [];
|
if (!Array.isArray(options.reserved)) options.reserved = [];
|
||||||
// Never mangle arguments
|
// Never mangle arguments
|
||||||
push_uniq(options.reserved, "arguments");
|
push_uniq(options.reserved, "arguments");
|
||||||
|
options._reserved = makePredicate(options.reserved);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,24 +435,26 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
|||||||
var redef = def.redefined();
|
var redef = def.redefined();
|
||||||
if (redef) {
|
if (redef) {
|
||||||
redefined.push(def);
|
redefined.push(def);
|
||||||
def.references.forEach(function(ref) {
|
reference(node.argname);
|
||||||
ref.thedef = redef;
|
def.references.forEach(reference);
|
||||||
ref.reference(options);
|
|
||||||
ref.thedef = def;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
descend();
|
descend();
|
||||||
if (!redef) mangle(def);
|
if (!redef) mangle(def);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function reference(sym) {
|
||||||
|
sym.thedef = redef;
|
||||||
|
sym.reference(options);
|
||||||
|
sym.thedef = def;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.walk(tw);
|
this.walk(tw);
|
||||||
redefined.forEach(mangle);
|
redefined.forEach(mangle);
|
||||||
|
|
||||||
function mangle(def) {
|
function mangle(def) {
|
||||||
if (!member(def.name, options.reserved)) {
|
if (options._reserved[def.name]) return;
|
||||||
def.mangle(options);
|
def.mangle(options);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -524,7 +504,7 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
|||||||
function rename(def) {
|
function rename(def) {
|
||||||
if (def.global && options.cache) return;
|
if (def.global && options.cache) return;
|
||||||
if (def.unmangleable(options)) return;
|
if (def.unmangleable(options)) return;
|
||||||
if (member(def.name, options.reserved)) return;
|
if (options._reserved[def.name]) return;
|
||||||
var d = def.redefined();
|
var d = def.redefined();
|
||||||
def.name = d ? d.name : next_name();
|
def.name = d ? d.name : next_name();
|
||||||
def.orig.forEach(function(sym) {
|
def.orig.forEach(function(sym) {
|
||||||
|
|||||||
@@ -57,26 +57,26 @@ function SourceMap(options) {
|
|||||||
file : options.file,
|
file : options.file,
|
||||||
sourceRoot : options.root
|
sourceRoot : options.root
|
||||||
});
|
});
|
||||||
var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
|
var maps = options.orig && Object.create(null);
|
||||||
|
if (maps) for (var source in options.orig) {
|
||||||
if (orig_map && Array.isArray(options.orig.sources)) {
|
var map = new MOZ_SourceMap.SourceMapConsumer(options.orig[source]);
|
||||||
orig_map._sources.toArray().forEach(function(source) {
|
if (Array.isArray(options.orig[source].sources)) {
|
||||||
var sourceContent = orig_map.sourceContentFor(source, true);
|
map._sources.toArray().forEach(function(source) {
|
||||||
if (sourceContent) {
|
var sourceContent = map.sourceContentFor(source, true);
|
||||||
generator.setSourceContent(source, sourceContent);
|
if (sourceContent) generator.setSourceContent(source, sourceContent);
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
|
maps[source] = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
function add(source, gen_line, gen_col, orig_line, orig_col, name) {
|
function add(source, gen_line, gen_col, orig_line, orig_col, name) {
|
||||||
if (orig_map) {
|
var map = maps && maps[source];
|
||||||
var info = orig_map.originalPositionFor({
|
if (map) {
|
||||||
|
var info = map.originalPositionFor({
|
||||||
line: orig_line,
|
line: orig_line,
|
||||||
column: orig_col
|
column: orig_col
|
||||||
});
|
});
|
||||||
if (info.source === null) {
|
if (info.source === null) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
source = info.source;
|
source = info.source;
|
||||||
orig_line = info.line;
|
orig_line = info.line;
|
||||||
orig_col = info.column;
|
orig_col = info.column;
|
||||||
|
|||||||
@@ -93,7 +93,12 @@ TreeTransformer.prototype = new TreeWalker;
|
|||||||
self.body = do_list(self.body, tw);
|
self.body = do_list(self.body, tw);
|
||||||
});
|
});
|
||||||
|
|
||||||
_(AST_DWLoop, function(self, tw){
|
_(AST_Do, function(self, tw){
|
||||||
|
self.body = self.body.transform(tw);
|
||||||
|
self.condition = self.condition.transform(tw);
|
||||||
|
});
|
||||||
|
|
||||||
|
_(AST_While, function(self, tw){
|
||||||
self.condition = self.condition.transform(tw);
|
self.condition = self.condition.transform(tw);
|
||||||
self.body = self.body.transform(tw);
|
self.body = self.body.transform(tw);
|
||||||
});
|
});
|
||||||
|
|||||||
53
lib/utils.js
53
lib/utils.js
@@ -145,7 +145,7 @@ var MAP = (function(){
|
|||||||
}
|
}
|
||||||
return is_last;
|
return is_last;
|
||||||
};
|
};
|
||||||
if (a instanceof Array) {
|
if (Array.isArray(a)) {
|
||||||
if (backwards) {
|
if (backwards) {
|
||||||
for (i = a.length; --i >= 0;) if (doit()) break;
|
for (i = a.length; --i >= 0;) if (doit()) break;
|
||||||
ret.reverse();
|
ret.reverse();
|
||||||
@@ -210,51 +210,14 @@ function mergeSort(array, cmp) {
|
|||||||
return _ms(array);
|
return _ms(array);
|
||||||
};
|
};
|
||||||
|
|
||||||
// this function is taken from Acorn [1], written by Marijn Haverbeke
|
|
||||||
// [1] https://github.com/marijnh/acorn
|
|
||||||
function makePredicate(words) {
|
function makePredicate(words) {
|
||||||
if (!(words instanceof Array)) words = words.split(" ");
|
if (!Array.isArray(words)) words = words.split(" ");
|
||||||
var f = "", cats = [];
|
var map = Object.create(null);
|
||||||
out: for (var i = 0; i < words.length; ++i) {
|
words.forEach(function(word) {
|
||||||
for (var j = 0; j < cats.length; ++j)
|
map[word] = true;
|
||||||
if (cats[j][0].length == words[i].length) {
|
});
|
||||||
cats[j].push(words[i]);
|
return map;
|
||||||
continue out;
|
}
|
||||||
}
|
|
||||||
cats.push([words[i]]);
|
|
||||||
}
|
|
||||||
function quote(word) {
|
|
||||||
return JSON.stringify(word).replace(/[\u2028\u2029]/g, function(s) {
|
|
||||||
switch (s) {
|
|
||||||
case "\u2028": return "\\u2028";
|
|
||||||
case "\u2029": return "\\u2029";
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function compareTo(arr) {
|
|
||||||
if (arr.length == 1) return f += "return str === " + quote(arr[0]) + ";";
|
|
||||||
f += "switch(str){";
|
|
||||||
for (var i = 0; i < arr.length; ++i) f += "case " + quote(arr[i]) + ":";
|
|
||||||
f += "return true}return false;";
|
|
||||||
}
|
|
||||||
// When there are more than three length categories, an outer
|
|
||||||
// switch first dispatches on the lengths, to save on comparisons.
|
|
||||||
if (cats.length > 3) {
|
|
||||||
cats.sort(function(a, b) {return b.length - a.length;});
|
|
||||||
f += "switch(str.length){";
|
|
||||||
for (var i = 0; i < cats.length; ++i) {
|
|
||||||
var cat = cats[i];
|
|
||||||
f += "case " + cat[0].length + ":";
|
|
||||||
compareTo(cat);
|
|
||||||
}
|
|
||||||
f += "}";
|
|
||||||
// Otherwise, simply generate a flat `switch` statement.
|
|
||||||
} else {
|
|
||||||
compareTo(words);
|
|
||||||
}
|
|
||||||
return new Function("str", f);
|
|
||||||
};
|
|
||||||
|
|
||||||
function all(array, predicate) {
|
function all(array, predicate) {
|
||||||
for (var i = array.length; --i >= 0;)
|
for (var i = array.length; --i >= 0;)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.3.16",
|
"version": "3.3.19",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5303,3 +5303,27 @@ issue_2974: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3032: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
pure_getters: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log({
|
||||||
|
f: function() {
|
||||||
|
this.a = 42;
|
||||||
|
return [ this.a, !1 ];
|
||||||
|
}
|
||||||
|
}.f()[0]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log({
|
||||||
|
f: function() {
|
||||||
|
this.a = 42;
|
||||||
|
return [ this.a, !1 ];
|
||||||
|
}
|
||||||
|
}.f()[0]);
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|||||||
@@ -2051,3 +2051,219 @@ drop_lone_use_strict: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3016_1: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 1;
|
||||||
|
do {
|
||||||
|
(function(a) {
|
||||||
|
return a[b];
|
||||||
|
var a;
|
||||||
|
})(3);
|
||||||
|
} while (0);
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 1;
|
||||||
|
do {
|
||||||
|
a = 3,
|
||||||
|
a[b];
|
||||||
|
} while(0);
|
||||||
|
var a;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3016_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
inline: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 1;
|
||||||
|
do {
|
||||||
|
(function(a) {
|
||||||
|
return a[b];
|
||||||
|
try {
|
||||||
|
a = 2;
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
})(3);
|
||||||
|
} while (0);
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 1;
|
||||||
|
do {
|
||||||
|
a = 3,
|
||||||
|
a[b];
|
||||||
|
} while(0);
|
||||||
|
var a;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3016_2_ie8: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
ie8: true,
|
||||||
|
inline: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 1;
|
||||||
|
do {
|
||||||
|
(function(a) {
|
||||||
|
return a[b];
|
||||||
|
try {
|
||||||
|
a = 2;
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
})(3);
|
||||||
|
} while (0);
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 1;
|
||||||
|
do {
|
||||||
|
a = 3,
|
||||||
|
a[b];
|
||||||
|
} while(0);
|
||||||
|
var a;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3016_3: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
inline: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 1;
|
||||||
|
do {
|
||||||
|
console.log(function() {
|
||||||
|
return a ? "FAIL" : a = "PASS";
|
||||||
|
try {
|
||||||
|
a = 2;
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
} while (b--);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 1;
|
||||||
|
do {
|
||||||
|
console.log((a = void 0, a ? "FAIL" : a = "PASS"));
|
||||||
|
} while(b--);
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3016_3_ie8: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
ie8: true,
|
||||||
|
inline: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 1;
|
||||||
|
do {
|
||||||
|
console.log(function() {
|
||||||
|
return a ? "FAIL" : a = "PASS";
|
||||||
|
try {
|
||||||
|
a = 2;
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
} while (b--);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 1;
|
||||||
|
do {
|
||||||
|
console.log((a = void 0, a ? "FAIL" : a = "PASS"));
|
||||||
|
} while(b--);
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3018: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 1, c = "PASS";
|
||||||
|
do {
|
||||||
|
(function() {
|
||||||
|
(function(a) {
|
||||||
|
a = 0 != (a && (c = "FAIL"));
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
} while (b--);
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 1, c = "PASS";
|
||||||
|
do {
|
||||||
|
a = void 0,
|
||||||
|
a = 0 != (a && (c = "FAIL"));
|
||||||
|
} while (b--);
|
||||||
|
var a;
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3054: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: 1,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
function f() {
|
||||||
|
return { a: true };
|
||||||
|
}
|
||||||
|
console.log(function(b) {
|
||||||
|
b = false;
|
||||||
|
return f();
|
||||||
|
}().a, f.call().a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
function f() {
|
||||||
|
return { a: !0 };
|
||||||
|
}
|
||||||
|
console.log(function(b) {
|
||||||
|
return { a: !(b = !1) };
|
||||||
|
}().a, f.call().a);
|
||||||
|
}
|
||||||
|
expect_stdout: "true true"
|
||||||
|
}
|
||||||
|
|||||||
@@ -686,3 +686,59 @@ undefined_key: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "3"
|
expect_stdout: "3"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3021: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1, b = 2;
|
||||||
|
(function() {
|
||||||
|
b = a;
|
||||||
|
if (a++ + b--)
|
||||||
|
return 1;
|
||||||
|
return;
|
||||||
|
var b = {};
|
||||||
|
})();
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1, b = 2;
|
||||||
|
(function() {
|
||||||
|
b = a;
|
||||||
|
if (a++ + b--)
|
||||||
|
return 1;
|
||||||
|
return;
|
||||||
|
var b = {};
|
||||||
|
})();
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "2 2"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3046: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
do {
|
||||||
|
var b = {
|
||||||
|
c: a++
|
||||||
|
};
|
||||||
|
} while (b.c && a);
|
||||||
|
return a;
|
||||||
|
}(0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
do {
|
||||||
|
var b_c = a++;
|
||||||
|
} while (b_c && a);
|
||||||
|
return a;
|
||||||
|
}(0));
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|||||||
@@ -464,3 +464,77 @@ issue_2976_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3035: {
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function(a) {
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
} catch (b) {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (a) {
|
||||||
|
b && (c = "PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function(o) {
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
} catch (t) {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (o) {
|
||||||
|
t && (c = "PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3035_ie8: {
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function(a) {
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
} catch (b) {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (a) {
|
||||||
|
b && (c = "PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function(t) {
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
} catch (o) {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (t) {
|
||||||
|
o && (c = "PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
@@ -1640,3 +1640,61 @@ issue_2893_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_869_1: {
|
||||||
|
mangle = {
|
||||||
|
properties: {
|
||||||
|
reserved: [ "get" ]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = { p: "FAIL" };
|
||||||
|
Object.defineProperty(o, "p", {
|
||||||
|
get: function() {
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(o.p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = { o: "FAIL" };
|
||||||
|
Object.defineProperty(o, "o", {
|
||||||
|
get: function() {
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(o.o);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_869_2: {
|
||||||
|
mangle = {
|
||||||
|
properties: {
|
||||||
|
reserved: [ "get" ]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = { p: "FAIL" };
|
||||||
|
Object.defineProperties(o, {
|
||||||
|
p: {
|
||||||
|
get: function() {
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(o.p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = { o: "FAIL" };
|
||||||
|
Object.defineProperties(o, {
|
||||||
|
o: {
|
||||||
|
get: function() {
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(o.o);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -5582,3 +5582,75 @@ issue_2992: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3042_1: {
|
||||||
|
options = {
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {}
|
||||||
|
var a = [ 1, 2 ].map(function() {
|
||||||
|
return new f();
|
||||||
|
});
|
||||||
|
console.log(a[0].constructor === a[1].constructor);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {}
|
||||||
|
var a = [ 1, 2 ].map(function() {
|
||||||
|
return new f();
|
||||||
|
});
|
||||||
|
console.log(a[0].constructor === a[1].constructor);
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3042_2: {
|
||||||
|
options = {
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function Foo() {
|
||||||
|
this.isFoo = function(o) {
|
||||||
|
return o instanceof Foo;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function FooCollection() {
|
||||||
|
this.foos = [1, 1].map(function() {
|
||||||
|
return new Foo();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var fooCollection = new FooCollection();
|
||||||
|
console.log(fooCollection.foos[0].isFoo(fooCollection.foos[0]));
|
||||||
|
console.log(fooCollection.foos[0].isFoo(fooCollection.foos[1]));
|
||||||
|
console.log(fooCollection.foos[1].isFoo(fooCollection.foos[0]));
|
||||||
|
console.log(fooCollection.foos[1].isFoo(fooCollection.foos[1]));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function Foo() {
|
||||||
|
this.isFoo = function(o) {
|
||||||
|
return o instanceof Foo;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var fooCollection = new function() {
|
||||||
|
this.foos = [1, 1].map(function() {
|
||||||
|
return new Foo();
|
||||||
|
});
|
||||||
|
}();
|
||||||
|
console.log(fooCollection.foos[0].isFoo(fooCollection.foos[0]));
|
||||||
|
console.log(fooCollection.foos[0].isFoo(fooCollection.foos[1]));
|
||||||
|
console.log(fooCollection.foos[1].isFoo(fooCollection.foos[0]));
|
||||||
|
console.log(fooCollection.foos[1].isFoo(fooCollection.foos[1]));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
2
test/input/pr-3040/expect.js
Normal file
2
test/input/pr-3040/expect.js
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
function _toConsumableArray(arr){if(Array.isArray(arr)){for(var i=0,arr2=Array(arr.length);i<arr.length;i++){arr2[i]=arr[i]}return arr2}else{return Array.from(arr)}}var _require=require("bar"),foo=_require.foo;var _require2=require("world"),hello=_require2.hello;foo.x.apply(foo,_toConsumableArray(foo.y(hello.z)));
|
||||||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0Mi5qcyJdLCJuYW1lcyI6WyJyZXF1aXJlIiwiYXJyIl0sIm1hcHBpbmdzIjoiMEpBQWNBLEtBQVFDIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3Qge2Zvb30gPSByZXF1aXJlKFwiYmFyXCIpO1xuY29uc3Qge2hlbGxvfSA9IHJlcXVpcmUoXCJ3b3JsZFwiKTtcblxuZm9vLngoLi4uZm9vLnkoaGVsbG8ueikpO1xuIl19
|
||||||
11
test/input/pr-3040/input.js
Normal file
11
test/input/pr-3040/input.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
||||||
|
|
||||||
|
var _require = require("bar"),
|
||||||
|
foo = _require.foo;
|
||||||
|
|
||||||
|
var _require2 = require("world"),
|
||||||
|
hello = _require2.hello;
|
||||||
|
|
||||||
|
foo.x.apply(foo, _toConsumableArray(foo.y(hello.z)));
|
||||||
|
|
||||||
|
//# sourceMappingURL=input.js.map
|
||||||
1
test/input/pr-3040/input.js.map
Normal file
1
test/input/pr-3040/input.js.map
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["input2.js"],"names":["require","foo","hello","x","apply","_toConsumableArray","y","z"],"mappings":"kLAAcA,QAAQ,OAAfC,aAAAA,kBACSD,QAAQ,SAAjBE,gBAAAA,MAEPD,IAAIE,EAAJC,MAAAH,IAAAI,mBAASJ,IAAIK,EAAEJ,MAAMK","sourcesContent":["const {foo} = require(\"bar\");\nconst {hello} = require(\"world\");\n\nfoo.x(...foo.y(hello.z));\n"]}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var exec = require("child_process").exec;
|
var exec = require("child_process").exec;
|
||||||
var readFileSync = require("fs").readFileSync;
|
var fs = require("fs");
|
||||||
|
|
||||||
function read(path) {
|
function read(path) {
|
||||||
return readFileSync(path, "utf8");
|
return fs.readFileSync(path, "utf8");
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("bin/uglifyjs", function () {
|
describe("bin/uglifyjs", function () {
|
||||||
@@ -56,6 +56,18 @@ describe("bin/uglifyjs", function () {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should give sensible error against invalid input source map", function(done) {
|
||||||
|
var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline";
|
||||||
|
|
||||||
|
exec(command, function (err, stdout, stderr) {
|
||||||
|
assert.ok(err);
|
||||||
|
assert.deepEqual(stderr.split(/\n/).slice(0, 2), [
|
||||||
|
"INFO: Using input source map: blah",
|
||||||
|
"ERROR: invalid input source map: blah",
|
||||||
|
]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
it("Should append source map to output when using --source-map url=inline", function (done) {
|
it("Should append source map to output when using --source-map url=inline", function (done) {
|
||||||
var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map url=inline";
|
var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map url=inline";
|
||||||
|
|
||||||
@@ -94,6 +106,36 @@ describe("bin/uglifyjs", function () {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should not load source map before finish reading from STDIN", function(done) {
|
||||||
|
var mapFile = "tmp/input.js.map";
|
||||||
|
try {
|
||||||
|
fs.mkdirSync("./tmp");
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code != "EEXIST") throw e;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(mapFile);
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code != "ENOENT") throw e;
|
||||||
|
}
|
||||||
|
var command = [
|
||||||
|
uglifyjscmd,
|
||||||
|
"--source-map", "content=" + mapFile,
|
||||||
|
"--source-map", "includeSources=true",
|
||||||
|
"--source-map", "url=inline",
|
||||||
|
].join(" ");
|
||||||
|
|
||||||
|
var child = exec(command, function(err, stdout) {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
assert.strictEqual(stdout, read("test/input/pr-3040/expect.js"));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
setTimeout(function() {
|
||||||
|
fs.writeFileSync(mapFile, read("test/input/pr-3040/input.js.map"));
|
||||||
|
child.stdin.end(read("test/input/pr-3040/input.js"));
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
it("Should work with --keep-fnames (mangle only)", function (done) {
|
it("Should work with --keep-fnames (mangle only)", function (done) {
|
||||||
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m';
|
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m';
|
||||||
|
|
||||||
@@ -175,7 +217,14 @@ describe("bin/uglifyjs", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should process inline source map", function(done) {
|
it("Should process inline source map", function(done) {
|
||||||
var command = uglifyjscmd + " test/input/issue-520/input.js -mc toplevel --source-map content=inline,url=inline";
|
var command = [
|
||||||
|
uglifyjscmd,
|
||||||
|
"test/input/issue-520/input.js",
|
||||||
|
"-mc", "toplevel",
|
||||||
|
"--source-map", "content=inline",
|
||||||
|
"--source-map", "includeSources=true",
|
||||||
|
"--source-map", "url=inline",
|
||||||
|
].join(" ");
|
||||||
|
|
||||||
exec(command, function (err, stdout) {
|
exec(command, function (err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
@@ -195,16 +244,27 @@ describe("bin/uglifyjs", function () {
|
|||||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
|
||||||
"",
|
"",
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
assert.strictEqual(stderr, "WARN: inline source map not found\n");
|
assert.strictEqual(stderr, "WARN: inline source map not found: test/input/issue-1323/sample.js\n");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should fail with multiple input and inline source map", function(done) {
|
it("Should handle multiple input and inline source map", function(done) {
|
||||||
var command = uglifyjscmd + " test/input/issue-520/input.js test/input/issue-520/output.js --source-map content=inline,url=inline";
|
var command = [
|
||||||
|
uglifyjscmd,
|
||||||
|
"test/input/issue-520/input.js",
|
||||||
|
"test/input/issue-1323/sample.js",
|
||||||
|
"--source-map", "content=inline,url=inline",
|
||||||
|
].join(" ");
|
||||||
|
|
||||||
exec(command, function (err, stdout, stderr) {
|
exec(command, function (err, stdout, stderr) {
|
||||||
assert.ok(err);
|
if (err) throw err;
|
||||||
assert.strictEqual(stderr.split(/\n/)[0], "ERROR: inline source map only works with singular input");
|
|
||||||
|
assert.strictEqual(stdout, [
|
||||||
|
"var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();",
|
||||||
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUFBLE1BQWdCQyxRQUFRQyxJQUFJLEVBQUUsSUFBTyxJQUFJRixJQ0FuRCxJQUFJRyxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
|
||||||
|
"",
|
||||||
|
].join("\n"));
|
||||||
|
assert.strictEqual(stderr, "WARN: inline source map not found: test/input/issue-1323/sample.js\n");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,66 +1,68 @@
|
|||||||
var Uglify = require('../../');
|
|
||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
|
var Uglify = require("../../");
|
||||||
var SourceMapConsumer = require("source-map").SourceMapConsumer;
|
var SourceMapConsumer = require("source-map").SourceMapConsumer;
|
||||||
|
|
||||||
|
function getMap() {
|
||||||
|
return {
|
||||||
|
"version": 3,
|
||||||
|
"sources": ["index.js"],
|
||||||
|
"names": [],
|
||||||
|
"mappings": ";;AAAA,IAAI,MAAM,SAAN,GAAM;AAAA,SAAK,SAAS,CAAd;AAAA,CAAV;AACA,QAAQ,GAAR,CAAY,IAAI,KAAJ,CAAZ",
|
||||||
|
"file": "bundle.js",
|
||||||
|
"sourcesContent": ["let foo = x => \"foo \" + x;\nconsole.log(foo(\"bar\"));"]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareMap(sourceMap) {
|
||||||
|
var code = [
|
||||||
|
'"use strict";',
|
||||||
|
"",
|
||||||
|
"var foo = function foo(x) {",
|
||||||
|
' return "foo " + x;',
|
||||||
|
"};",
|
||||||
|
'console.log(foo("bar"));',
|
||||||
|
"",
|
||||||
|
"//# sourceMappingURL=bundle.js.map",
|
||||||
|
].join("\n");
|
||||||
|
var result = Uglify.minify(code, {
|
||||||
|
sourceMap: {
|
||||||
|
content: sourceMap,
|
||||||
|
includeSources: true,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
return new SourceMapConsumer(result.map);
|
||||||
|
}
|
||||||
|
|
||||||
describe("input sourcemaps", function() {
|
describe("input sourcemaps", function() {
|
||||||
var transpilemap, map;
|
|
||||||
|
|
||||||
function getMap() {
|
|
||||||
return {
|
|
||||||
"version": 3,
|
|
||||||
"sources": ["index.js"],
|
|
||||||
"names": [],
|
|
||||||
"mappings": ";;AAAA,IAAI,MAAM,SAAN,GAAM;AAAA,SAAK,SAAS,CAAd;AAAA,CAAV;AACA,QAAQ,GAAR,CAAY,IAAI,KAAJ,CAAZ",
|
|
||||||
"file": "bundle.js",
|
|
||||||
"sourcesContent": ["let foo = x => \"foo \" + x;\nconsole.log(foo(\"bar\"));"]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepareMap(sourceMap) {
|
|
||||||
var transpiled = '"use strict";\n\n' +
|
|
||||||
'var foo = function foo(x) {\n return "foo " + x;\n};\n' +
|
|
||||||
'console.log(foo("bar"));\n\n' +
|
|
||||||
'//# sourceMappingURL=bundle.js.map';
|
|
||||||
|
|
||||||
transpilemap = sourceMap || getMap();
|
|
||||||
|
|
||||||
var result = Uglify.minify(transpiled, {
|
|
||||||
sourceMap: {
|
|
||||||
content: transpilemap
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
map = new SourceMapConsumer(result.map);
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
prepareMap();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Should copy over original sourcesContent", function() {
|
it("Should copy over original sourcesContent", function() {
|
||||||
assert.equal(map.sourceContentFor("index.js"), transpilemap.sourcesContent[0]);
|
var orig = getMap();
|
||||||
|
var map = prepareMap(orig);
|
||||||
|
assert.equal(map.sourceContentFor("index.js"), orig.sourcesContent[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should copy sourcesContent if sources are relative", function () {
|
it("Should copy sourcesContent if sources are relative", function() {
|
||||||
var relativeMap = getMap();
|
var relativeMap = getMap();
|
||||||
relativeMap.sources = ['./index.js'];
|
relativeMap.sources = ['./index.js'];
|
||||||
|
var map = prepareMap(relativeMap);
|
||||||
prepareMap(relativeMap);
|
|
||||||
assert.notEqual(map.sourcesContent, null);
|
assert.notEqual(map.sourcesContent, null);
|
||||||
assert.equal(map.sourcesContent.length, 1);
|
assert.equal(map.sourcesContent.length, 1);
|
||||||
assert.equal(map.sourceContentFor("index.js"), transpilemap.sourcesContent[0]);
|
assert.equal(map.sourceContentFor("index.js"), relativeMap.sourcesContent[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Final sourcemap should not have invalid mappings from inputSourceMap (issue #882)", function() {
|
it("Should not have invalid mappings from inputSourceMap (issue #882)", function() {
|
||||||
|
var map = prepareMap(getMap());
|
||||||
// The original source has only 2 lines, check that mappings don't have more lines
|
// The original source has only 2 lines, check that mappings don't have more lines
|
||||||
|
|
||||||
var msg = "Mapping should not have higher line number than the original file had";
|
var msg = "Mapping should not have higher line number than the original file had";
|
||||||
map.eachMapping(function(mapping) {
|
map.eachMapping(function(mapping) {
|
||||||
assert.ok(mapping.originalLine <= 2, msg)
|
assert.ok(mapping.originalLine <= 2, msg);
|
||||||
});
|
});
|
||||||
|
map.allGeneratedPositionsFor({
|
||||||
map.allGeneratedPositionsFor({source: "index.js", line: 1, column: 1}).forEach(function(pos) {
|
source: "index.js",
|
||||||
|
line: 1,
|
||||||
|
column: 1
|
||||||
|
}).forEach(function(pos) {
|
||||||
assert.ok(pos.line <= 2, msg);
|
assert.ok(pos.line <= 2, msg);
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -186,99 +186,6 @@ describe("minify", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("inSourceMap", function() {
|
|
||||||
it("Should read the given string filename correctly when sourceMapIncludeSources is enabled (#1236)", function() {
|
|
||||||
var result = Uglify.minify(read("./test/input/issue-1236/simple.js"), {
|
|
||||||
sourceMap: {
|
|
||||||
content: read("./test/input/issue-1236/simple.js.map"),
|
|
||||||
filename: "simple.min.js",
|
|
||||||
includeSources: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var map = JSON.parse(result.map);
|
|
||||||
|
|
||||||
assert.equal(map.file, 'simple.min.js');
|
|
||||||
assert.equal(map.sourcesContent.length, 1);
|
|
||||||
assert.equal(map.sourcesContent[0],
|
|
||||||
'let foo = x => "foo " + x;\nconsole.log(foo("bar"));');
|
|
||||||
});
|
|
||||||
it("Should process inline source map", function() {
|
|
||||||
var code = Uglify.minify(read("./test/input/issue-520/input.js"), {
|
|
||||||
compress: { toplevel: true },
|
|
||||||
sourceMap: {
|
|
||||||
content: "inline",
|
|
||||||
url: "inline"
|
|
||||||
}
|
|
||||||
}).code + "\n";
|
|
||||||
assert.strictEqual(code, readFileSync("test/input/issue-520/output.js", "utf8"));
|
|
||||||
});
|
|
||||||
it("Should warn for missing inline source map", function() {
|
|
||||||
var warn_function = Uglify.AST_Node.warn_function;
|
|
||||||
var warnings = [];
|
|
||||||
Uglify.AST_Node.warn_function = function(txt) {
|
|
||||||
warnings.push(txt);
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
var result = Uglify.minify(read("./test/input/issue-1323/sample.js"), {
|
|
||||||
mangle: false,
|
|
||||||
sourceMap: {
|
|
||||||
content: "inline"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
assert.strictEqual(result.code, "var bar=function(bar){return bar};");
|
|
||||||
assert.strictEqual(warnings.length, 1);
|
|
||||||
assert.strictEqual(warnings[0], "inline source map not found");
|
|
||||||
} finally {
|
|
||||||
Uglify.AST_Node.warn_function = warn_function;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
it("Should fail with multiple input and inline source map", function() {
|
|
||||||
var result = Uglify.minify([
|
|
||||||
read("./test/input/issue-520/input.js"),
|
|
||||||
read("./test/input/issue-520/output.js")
|
|
||||||
], {
|
|
||||||
sourceMap: {
|
|
||||||
content: "inline",
|
|
||||||
url: "inline"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var err = result.error;
|
|
||||||
assert.ok(err instanceof Error);
|
|
||||||
assert.strictEqual(err.stack.split(/\n/)[0], "Error: inline source map only works with singular input");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("sourceMapInline", function() {
|
|
||||||
it("should append source map to output js when sourceMapInline is enabled", function() {
|
|
||||||
var result = Uglify.minify('var a = function(foo) { return foo; };', {
|
|
||||||
sourceMap: {
|
|
||||||
url: "inline"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var code = result.code;
|
|
||||||
assert.strictEqual(code, "var a=function(n){return n};\n" +
|
|
||||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BIn0=");
|
|
||||||
});
|
|
||||||
it("should not append source map to output js when sourceMapInline is not enabled", function() {
|
|
||||||
var result = Uglify.minify('var a = function(foo) { return foo; };');
|
|
||||||
var code = result.code;
|
|
||||||
assert.strictEqual(code, "var a=function(n){return n};");
|
|
||||||
});
|
|
||||||
it("should work with max_line_len", function() {
|
|
||||||
var result = Uglify.minify(read("./test/input/issue-505/input.js"), {
|
|
||||||
output: {
|
|
||||||
max_line_len: 20
|
|
||||||
},
|
|
||||||
sourceMap: {
|
|
||||||
url: "inline"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
assert.strictEqual(result.error, undefined);
|
|
||||||
assert.strictEqual(result.code, read("./test/input/issue-505/output.js"));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("#__PURE__", function() {
|
describe("#__PURE__", function() {
|
||||||
it("should drop #__PURE__ hint after use", function() {
|
it("should drop #__PURE__ hint after use", function() {
|
||||||
var result = Uglify.minify('//@__PURE__ comment1 #__PURE__ comment2\n foo(), bar();', {
|
var result = Uglify.minify('//@__PURE__ comment1 #__PURE__ comment2\n foo(), bar();', {
|
||||||
@@ -312,6 +219,15 @@ describe("minify", function() {
|
|||||||
assert.strictEqual(err.line, 1);
|
assert.strictEqual(err.line, 1);
|
||||||
assert.strictEqual(err.col, 12);
|
assert.strictEqual(err.col, 12);
|
||||||
});
|
});
|
||||||
|
it("should reject duplicated label name", function() {
|
||||||
|
var result = Uglify.minify("L:{L:{}}");
|
||||||
|
var err = result.error;
|
||||||
|
assert.ok(err instanceof Error);
|
||||||
|
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Label L defined twice");
|
||||||
|
assert.strictEqual(err.filename, "0");
|
||||||
|
assert.strictEqual(err.line, 1);
|
||||||
|
assert.strictEqual(err.col, 4);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("global_defs", function() {
|
describe("global_defs", function() {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var uglify = require("../../");
|
var uglify = require("../../");
|
||||||
|
|
||||||
describe("New", function() {
|
describe("parentheses", function() {
|
||||||
it("Should add trailing parentheses for new expressions with zero arguments in beautify mode", function() {
|
it("Should add trailing parentheses for new expressions with zero arguments in beautify mode", function() {
|
||||||
var tests = [
|
var tests = [
|
||||||
"new x(1);",
|
"new x(1);",
|
||||||
@@ -83,4 +83,23 @@ describe("New", function() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it("Should compress leading parenthesis with reasonable performance", function() {
|
||||||
|
this.timeout(30000);
|
||||||
|
var code = [
|
||||||
|
"({}?0:1)&&x();",
|
||||||
|
"(function(){}).name;",
|
||||||
|
];
|
||||||
|
for (var i = 16; --i >= 0;) {
|
||||||
|
[].push.apply(code, code);
|
||||||
|
}
|
||||||
|
code = code.join("");
|
||||||
|
var result = uglify.minify(code, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
// Dismal performance for `assert.strictEqual()` in Node.js 6
|
||||||
|
assert.ok(result.code === code);
|
||||||
|
});
|
||||||
|
});
|
||||||
180
test/mocha/sourcemaps.js
Normal file
180
test/mocha/sourcemaps.js
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
var assert = require("assert");
|
||||||
|
var readFileSync = require("fs").readFileSync;
|
||||||
|
var Uglify = require("../../");
|
||||||
|
|
||||||
|
function read(path) {
|
||||||
|
return readFileSync(path, "utf8");
|
||||||
|
}
|
||||||
|
|
||||||
|
function source_map(code) {
|
||||||
|
return JSON.parse(Uglify.minify(code, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
sourceMap: true,
|
||||||
|
}).map);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("sourcemaps", function() {
|
||||||
|
it("Should give correct version", function() {
|
||||||
|
var map = source_map("var x = 1 + 1;");
|
||||||
|
assert.strictEqual(map.version, 3);
|
||||||
|
assert.deepEqual(map.names, [ "x" ]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should give correct names", function() {
|
||||||
|
var map = source_map([
|
||||||
|
"({",
|
||||||
|
" get enabled() {",
|
||||||
|
" return 3;",
|
||||||
|
" },",
|
||||||
|
" set enabled(x) {",
|
||||||
|
" ;",
|
||||||
|
" }",
|
||||||
|
"});",
|
||||||
|
].join("\n"));
|
||||||
|
assert.deepEqual(map.names, [ "enabled", "x" ]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should mark array/object literals", function() {
|
||||||
|
var result = Uglify.minify([
|
||||||
|
"var obj = {};",
|
||||||
|
"obj.wat([]);",
|
||||||
|
].join("\n"), {
|
||||||
|
sourceMap: true,
|
||||||
|
toplevel: true,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, "({}).wat([]);");
|
||||||
|
assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["wat"],"mappings":"CAAU,IACNA,IAAI"}');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("inSourceMap", function() {
|
||||||
|
it("Should read the given string filename correctly when sourceMapIncludeSources is enabled (#1236)", function() {
|
||||||
|
var result = Uglify.minify(read("./test/input/issue-1236/simple.js"), {
|
||||||
|
sourceMap: {
|
||||||
|
content: read("./test/input/issue-1236/simple.js.map"),
|
||||||
|
filename: "simple.min.js",
|
||||||
|
includeSources: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var map = JSON.parse(result.map);
|
||||||
|
|
||||||
|
assert.equal(map.file, 'simple.min.js');
|
||||||
|
assert.equal(map.sourcesContent.length, 1);
|
||||||
|
assert.equal(map.sourcesContent[0],
|
||||||
|
'let foo = x => "foo " + x;\nconsole.log(foo("bar"));');
|
||||||
|
});
|
||||||
|
it("Should process inline source map", function() {
|
||||||
|
var code = Uglify.minify(read("./test/input/issue-520/input.js"), {
|
||||||
|
compress: { toplevel: true },
|
||||||
|
sourceMap: {
|
||||||
|
content: "inline",
|
||||||
|
includeSources: true,
|
||||||
|
url: "inline"
|
||||||
|
}
|
||||||
|
}).code + "\n";
|
||||||
|
assert.strictEqual(code, readFileSync("test/input/issue-520/output.js", "utf8"));
|
||||||
|
});
|
||||||
|
it("Should warn for missing inline source map", function() {
|
||||||
|
var warn_function = Uglify.AST_Node.warn_function;
|
||||||
|
var warnings = [];
|
||||||
|
Uglify.AST_Node.warn_function = function(txt) {
|
||||||
|
warnings.push(txt);
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
var result = Uglify.minify(read("./test/input/issue-1323/sample.js"), {
|
||||||
|
mangle: false,
|
||||||
|
sourceMap: {
|
||||||
|
content: "inline"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assert.strictEqual(result.code, "var bar=function(bar){return bar};");
|
||||||
|
assert.strictEqual(warnings.length, 1);
|
||||||
|
assert.strictEqual(warnings[0], "inline source map not found: 0");
|
||||||
|
} finally {
|
||||||
|
Uglify.AST_Node.warn_function = warn_function;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
it("Should handle multiple input and inline source map", function() {
|
||||||
|
var warn_function = Uglify.AST_Node.warn_function;
|
||||||
|
var warnings = [];
|
||||||
|
Uglify.AST_Node.warn_function = function(txt) {
|
||||||
|
warnings.push(txt);
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
var result = Uglify.minify([
|
||||||
|
read("./test/input/issue-520/input.js"),
|
||||||
|
read("./test/input/issue-1323/sample.js"),
|
||||||
|
], {
|
||||||
|
sourceMap: {
|
||||||
|
content: "inline",
|
||||||
|
url: "inline",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"var Foo=function(){console.log(3)};new Foo;var bar=function(o){return o};",
|
||||||
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwiMSJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFdBQWdCQyxRQUFRQyxJQUFJLElBQVMsSUFBSUYsSUNBbkQsSUFBSUcsSUFDQSxTQUFjQSxHQUNWLE9BQU9BIn0=",
|
||||||
|
].join("\n"));
|
||||||
|
assert.strictEqual(warnings.length, 1);
|
||||||
|
assert.strictEqual(warnings[0], "inline source map not found: 1");
|
||||||
|
} finally {
|
||||||
|
Uglify.AST_Node.warn_function = warn_function;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
it("Should drop source contents for includeSources=false", function() {
|
||||||
|
var result = Uglify.minify(read("./test/input/issue-520/input.js"), {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
sourceMap: {
|
||||||
|
content: "inline",
|
||||||
|
includeSources: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
var map = JSON.parse(result.map);
|
||||||
|
assert.strictEqual(map.sourcesContent.length, 1);
|
||||||
|
result = Uglify.minify(result.code, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
sourceMap: {
|
||||||
|
content: result.map,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
map = JSON.parse(result.map);
|
||||||
|
assert.ok(!("sourcesContent" in map));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("sourceMapInline", function() {
|
||||||
|
it("should append source map to output js when sourceMapInline is enabled", function() {
|
||||||
|
var result = Uglify.minify('var a = function(foo) { return foo; };', {
|
||||||
|
sourceMap: {
|
||||||
|
url: "inline"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var code = result.code;
|
||||||
|
assert.strictEqual(code, "var a=function(n){return n};\n" +
|
||||||
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BIn0=");
|
||||||
|
});
|
||||||
|
it("should not append source map to output js when sourceMapInline is not enabled", function() {
|
||||||
|
var result = Uglify.minify('var a = function(foo) { return foo; };');
|
||||||
|
var code = result.code;
|
||||||
|
assert.strictEqual(code, "var a=function(n){return n};");
|
||||||
|
});
|
||||||
|
it("should work with max_line_len", function() {
|
||||||
|
var result = Uglify.minify(read("./test/input/issue-505/input.js"), {
|
||||||
|
output: {
|
||||||
|
max_line_len: 20
|
||||||
|
},
|
||||||
|
sourceMap: {
|
||||||
|
url: "inline"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assert.strictEqual(result.error, undefined);
|
||||||
|
assert.strictEqual(result.code, read("./test/input/issue-505/output.js"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -23,6 +23,15 @@ describe("spidermonkey export/import sanity test", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not add unnecessary escape slashes to regexps", function() {
|
||||||
|
var input = "/[\\\\/]/;";
|
||||||
|
var ast = uglify.parse(input).to_mozilla_ast();
|
||||||
|
assert.equal(
|
||||||
|
uglify.AST_Node.from_mozilla_ast(ast).print_to_string(),
|
||||||
|
input
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("Should judge between directives and strings correctly on import", function() {
|
it("Should judge between directives and strings correctly on import", function() {
|
||||||
var tests = [
|
var tests = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ if (failures) {
|
|||||||
var mocha_tests = require("./mocha.js");
|
var mocha_tests = require("./mocha.js");
|
||||||
mocha_tests();
|
mocha_tests();
|
||||||
|
|
||||||
var run_sourcemaps_tests = require('./sourcemaps');
|
|
||||||
run_sourcemaps_tests();
|
|
||||||
|
|
||||||
/* -----[ utils ]----- */
|
/* -----[ utils ]----- */
|
||||||
|
|
||||||
function tmpl() {
|
function tmpl() {
|
||||||
@@ -49,16 +46,9 @@ function log_test(name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function find_test_files(dir) {
|
function find_test_files(dir) {
|
||||||
var files = fs.readdirSync(dir).filter(function(name){
|
return fs.readdirSync(dir).filter(function(name) {
|
||||||
return /\.js$/i.test(name);
|
return /\.js$/i.test(name);
|
||||||
});
|
});
|
||||||
if (process.argv.length > 2) {
|
|
||||||
var x = process.argv.slice(2);
|
|
||||||
files = files.filter(function(f){
|
|
||||||
return x.indexOf(f) >= 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return files;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_directory(dir) {
|
function test_directory(dir) {
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
var UglifyJS = require("..");
|
|
||||||
var ok = require("assert");
|
|
||||||
|
|
||||||
module.exports = function () {
|
|
||||||
console.log("--- Sourcemaps tests");
|
|
||||||
|
|
||||||
var basic = source_map([
|
|
||||||
'var x = 1 + 1;'
|
|
||||||
].join('\n'));
|
|
||||||
|
|
||||||
ok.equal(basic.version, 3);
|
|
||||||
ok.deepEqual(basic.names, ['x']);
|
|
||||||
|
|
||||||
var issue836 = source_map([
|
|
||||||
"({",
|
|
||||||
" get enabled() {",
|
|
||||||
" return 3;",
|
|
||||||
" },",
|
|
||||||
" set enabled(x) {",
|
|
||||||
" ;",
|
|
||||||
" }",
|
|
||||||
"});",
|
|
||||||
].join("\n"));
|
|
||||||
|
|
||||||
ok.deepEqual(issue836.names, ['enabled', 'x']);
|
|
||||||
}
|
|
||||||
|
|
||||||
function source_map(js) {
|
|
||||||
return JSON.parse(UglifyJS.minify(js, {
|
|
||||||
compress: false,
|
|
||||||
mangle: false,
|
|
||||||
sourceMap: true
|
|
||||||
}).map);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run standalone
|
|
||||||
if (module.parent === null) {
|
|
||||||
module.exports();
|
|
||||||
}
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user