Merge branch 'master' into harmony-v3.0.20

This commit is contained in:
alexlamsl
2017-06-25 16:02:46 +08:00
25 changed files with 472 additions and 257 deletions

View File

@@ -126,15 +126,13 @@ function Compressor(options, false_by_default) {
}; };
} }
var toplevel = this.options["toplevel"]; var toplevel = this.options["toplevel"];
if (typeof toplevel == "string") { this.toplevel = typeof toplevel == "string" ? {
this.toplevel.funcs = /funcs/.test(toplevel); funcs: /funcs/.test(toplevel),
this.toplevel.vars = /vars/.test(toplevel); vars: /vars/.test(toplevel)
} else { } : {
this.toplevel = toplevel ? function(def) { funcs: toplevel,
return !def.export; vars: toplevel
} : return_false; };
this.toplevel.funcs = this.toplevel.vars = toplevel;
}
var sequences = this.options["sequences"]; var sequences = this.options["sequences"];
this.sequences_limit = sequences == 1 ? 800 : sequences | 0; this.sequences_limit = sequences == 1 ? 800 : sequences | 0;
this.warnings_produced = {}; this.warnings_produced = {};
@@ -143,12 +141,12 @@ function Compressor(options, false_by_default) {
Compressor.prototype = new TreeTransformer; Compressor.prototype = new TreeTransformer;
merge(Compressor.prototype, { merge(Compressor.prototype, {
option: function(key) { return this.options[key] }, option: function(key) { return this.options[key] },
toplevel: function(def) { exposed: function(def) {
if (def.export) return false; if (def.export) return true;
for (var i = 0, len = def.orig.length; i < len; i++) if (def.global) for (var i = 0, len = def.orig.length; i < len; i++)
if (!this.toplevel[def.orig[i] instanceof AST_SymbolDefun ? "funcs" : "vars"]) if (!this.toplevel[def.orig[i] instanceof AST_SymbolDefun ? "funcs" : "vars"])
return false; return true;
return true; return false;
}, },
compress: function(node) { compress: function(node) {
if (this.option("expression")) { if (this.option("expression")) {
@@ -284,11 +282,11 @@ merge(Compressor.prototype, {
var reduce_vars = rescan && compressor.option("reduce_vars"); var reduce_vars = rescan && compressor.option("reduce_vars");
var safe_ids = Object.create(null); var safe_ids = Object.create(null);
var suppressor = new TreeWalker(function(node) { var suppressor = new TreeWalker(function(node) {
if (node instanceof AST_Symbol) { if (!(node instanceof AST_Symbol)) return;
var d = node.definition(); var d = node.definition();
if (node instanceof AST_SymbolRef) d.references.push(node); if (!d) return;
d.fixed = false; if (node instanceof AST_SymbolRef) d.references.push(node);
} d.fixed = false;
}); });
var tw = new TreeWalker(function(node, descend) { var tw = new TreeWalker(function(node, descend) {
node._squeezed = false; node._squeezed = false;
@@ -356,7 +354,7 @@ merge(Compressor.prototype, {
} }
if (node instanceof AST_Defun) { if (node instanceof AST_Defun) {
var d = node.name.definition(); var d = node.name.definition();
if (d.global && !compressor.toplevel(d) || safe_to_read(d)) { if (compressor.exposed(d) || safe_to_read(d)) {
d.fixed = false; d.fixed = false;
} else { } else {
d.fixed = node; d.fixed = node;
@@ -531,7 +529,7 @@ merge(Compressor.prototype, {
def.escaped = false; def.escaped = false;
if (def.scope.uses_eval) { if (def.scope.uses_eval) {
def.fixed = false; def.fixed = false;
} else if (!def.global || def.orig[0] instanceof AST_SymbolConst || compressor.toplevel(def)) { } else if (def.orig[0] instanceof AST_SymbolConst || !compressor.exposed(def)) {
def.fixed = undefined; def.fixed = undefined;
} else { } else {
def.fixed = false; def.fixed = false;
@@ -561,8 +559,25 @@ merge(Compressor.prototype, {
return fixed(); return fixed();
}); });
AST_SymbolRef.DEFMETHOD("is_immutable", function() {
var orig = this.definition().orig;
return orig.length == 1 && orig[0] instanceof AST_SymbolLambda;
});
function is_lhs_read_only(lhs) { function is_lhs_read_only(lhs) {
return lhs instanceof AST_SymbolRef && lhs.definition().orig[0] instanceof AST_SymbolLambda; if (lhs instanceof AST_SymbolRef) return lhs.definition().orig[0] instanceof AST_SymbolLambda;
if (lhs instanceof AST_PropAccess) {
lhs = lhs.expression;
if (lhs instanceof AST_SymbolRef) {
if (lhs.is_immutable()) return false;
lhs = lhs.fixed_value();
}
if (!lhs) return true;
if (lhs instanceof AST_RegExp) return false;
if (lhs instanceof AST_Constant) return true;
return is_lhs_read_only(lhs);
}
return false;
} }
function is_ref_of(ref, type) { function is_ref_of(ref, type) {
@@ -783,7 +798,7 @@ merge(Compressor.prototype, {
} }
if (candidate instanceof AST_VarDef) { if (candidate instanceof AST_VarDef) {
var def = candidate.name.definition(); var def = candidate.name.definition();
if (def.references.length == 1 && (!def.global || compressor.toplevel(def))) { if (def.references.length == 1 && !compressor.exposed(def)) {
return maintain_this_binding(parent, node, candidate.value); return maintain_this_binding(parent, node, candidate.value);
} }
return make_node(AST_Assign, candidate, { return make_node(AST_Assign, candidate, {
@@ -845,7 +860,7 @@ merge(Compressor.prototype, {
if (expr instanceof AST_VarDef && expr.name instanceof AST_SymbolDeclaration) { if (expr instanceof AST_VarDef && expr.name instanceof AST_SymbolDeclaration) {
var def = expr.name.definition(); var def = expr.name.definition();
if (def.orig.length > 1 if (def.orig.length > 1
|| def.references.length == 1 && (!def.global || compressor.toplevel(def))) { || def.references.length == 1 && !compressor.exposed(def)) {
return make_node(AST_SymbolRef, expr.name, expr.name); return make_node(AST_SymbolRef, expr.name, expr.name);
} }
} else { } else {
@@ -1334,6 +1349,7 @@ merge(Compressor.prototype, {
def(AST_SymbolRef, function(pure_getters) { def(AST_SymbolRef, function(pure_getters) {
if (this.is_undefined) return true; if (this.is_undefined) return true;
if (!is_strict(pure_getters)) return false; if (!is_strict(pure_getters)) return false;
if (this.is_immutable()) return false;
var fixed = this.fixed_value(); var fixed = this.fixed_value();
return !fixed || fixed._throw_on_access(pure_getters); return !fixed || fixed._throw_on_access(pure_getters);
}); });
@@ -3270,7 +3286,9 @@ merge(Compressor.prototype, {
var comp = new Compressor(compressor.options); var comp = new Compressor(compressor.options);
ast = ast.transform(comp); ast = ast.transform(comp);
ast.figure_out_scope(mangle); ast.figure_out_scope(mangle);
ast.mangle_names(); base54.reset();
ast.compute_char_frequency(mangle);
ast.mangle_names(mangle);
var fun; var fun;
ast.walk(new TreeWalker(function(node) { ast.walk(new TreeWalker(function(node) {
if (fun) return true; if (fun) return true;
@@ -3525,6 +3543,8 @@ merge(Compressor.prototype, {
|| cdr instanceof AST_PropAccess || cdr instanceof AST_PropAccess
|| cdr instanceof AST_Unary && !unary_side_effects(cdr.operator)) { || cdr instanceof AST_Unary && !unary_side_effects(cdr.operator)) {
field = "expression"; field = "expression";
} else if (cdr instanceof AST_Conditional) {
field = "condition";
} else { } else {
expressions[++i] = expressions[j]; expressions[++i] = expressions[j];
break; break;
@@ -4059,7 +4079,7 @@ merge(Compressor.prototype, {
var d = self.definition(); var d = self.definition();
var fixed = self.fixed_value(); var fixed = self.fixed_value();
if (fixed instanceof AST_Defun) { if (fixed instanceof AST_Defun) {
d.fixed = fixed = make_node(AST_Function, fixed, fixed).clone(true); d.fixed = fixed = make_node(AST_Function, fixed, fixed);
} }
if (compressor.option("unused") if (compressor.option("unused")
&& fixed instanceof AST_Function && fixed instanceof AST_Function
@@ -4067,7 +4087,7 @@ merge(Compressor.prototype, {
&& !(d.scope.uses_arguments && d.orig[0] instanceof AST_SymbolFunarg) && !(d.scope.uses_arguments && d.orig[0] instanceof AST_SymbolFunarg)
&& !d.scope.uses_eval && !d.scope.uses_eval
&& compressor.find_parent(AST_Scope) === fixed.parent_scope) { && compressor.find_parent(AST_Scope) === fixed.parent_scope) {
return fixed; return fixed.clone(true);
} }
if (compressor.option("evaluate") && fixed) { if (compressor.option("evaluate") && fixed) {
if (d.should_replace === undefined) { if (d.should_replace === undefined) {
@@ -4090,7 +4110,7 @@ merge(Compressor.prototype, {
} }
var name_length = d.name.length; var name_length = d.name.length;
var overhead = 0; var overhead = 0;
if (compressor.option("unused") && (!d.global || compressor.toplevel(d))) { if (compressor.option("unused") && !compressor.exposed(d)) {
overhead = (name_length + 2 + value_length) / d.references.length; overhead = (name_length + 2 + value_length) / d.references.length;
} }
d.should_replace = value_length <= name_length + overhead ? fn : false; d.should_replace = value_length <= name_length + overhead ? fn : false;

View File

@@ -533,6 +533,7 @@ function OutputStream(options) {
use_asm = prev_use_asm; use_asm = prev_use_asm;
} }
}); });
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
AST_Node.DEFMETHOD("print_to_string", function(options){ AST_Node.DEFMETHOD("print_to_string", function(options){
var s = OutputStream(options); var s = OutputStream(options);

View File

@@ -1230,9 +1230,12 @@ function parse($TEXT, options) {
var is_in = is("operator", "in"); var is_in = is("operator", "in");
var is_of = is("name", "of"); var is_of = is("name", "of");
if (is_in || is_of) { if (is_in || is_of) {
if ((init instanceof AST_Definitions) && if (init instanceof AST_Definitions) {
init.definitions.length > 1) if (init.definitions.length > 1)
croak("Only one variable declaration allowed in for..in loop"); croak("Only one variable declaration allowed in for..in loop", init.start.line, init.start.col, init.start.pos);
} else if (!(is_assignable(init) || (init = to_destructuring(init)) instanceof AST_Destructuring)) {
croak("Invalid left-hand side in for..in loop", init.start.line, init.start.col, init.start.pos);
}
next(); next();
if (is_in) { if (is_in) {
return for_in(init); return for_in(init);

View File

@@ -450,7 +450,7 @@ AST_Function.DEFMETHOD("next_mangled", function(options, def){
AST_Symbol.DEFMETHOD("unmangleable", function(options){ AST_Symbol.DEFMETHOD("unmangleable", function(options){
var def = this.definition(); var def = this.definition();
return def && def.unmangleable(options); return !def || def.unmangleable(options);
}); });
// labels are always mangleable // labels are always mangleable
@@ -555,113 +555,69 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){ AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
options = this._default_mangler_options(options); options = this._default_mangler_options(options);
var tw = new TreeWalker(function(node){ try {
if (node instanceof AST_Constant) AST_Node.prototype.print = function(stream, force_parens) {
base54.consider(node.print_to_string()); this._print(stream, force_parens);
else if (node instanceof AST_Return) if (this instanceof AST_Symbol && !this.unmangleable(options)) {
base54.consider("return"); base54.consider(this.name, -1);
else if (node instanceof AST_Throw) } else if (options.properties) {
base54.consider("throw"); if (this instanceof AST_Dot) {
else if (node instanceof AST_Continue) base54.consider(this.property, -1);
base54.consider("continue"); } else if (this instanceof AST_Sub) {
else if (node instanceof AST_Break) skip_string(this.property);
base54.consider("break"); }
else if (node instanceof AST_Debugger) }
base54.consider("debugger"); };
else if (node instanceof AST_Directive) base54.consider(this.print_to_string(), 1);
base54.consider(node.value); } finally {
else if (node instanceof AST_While) AST_Node.prototype.print = AST_Node.prototype._print;
base54.consider("while"); }
else if (node instanceof AST_Do)
base54.consider("do while");
else if (node instanceof AST_If) {
base54.consider("if");
if (node.alternative) base54.consider("else");
}
else if (node instanceof AST_Var)
base54.consider("var");
else if (node instanceof AST_Const)
base54.consider("const");
else if (node instanceof AST_Lambda)
base54.consider("function");
else if (node instanceof AST_For)
base54.consider("for");
else if (node instanceof AST_ForIn)
base54.consider("for in");
else if (node instanceof AST_Switch)
base54.consider("switch");
else if (node instanceof AST_Case)
base54.consider("case");
else if (node instanceof AST_Default)
base54.consider("default");
else if (node instanceof AST_With)
base54.consider("with");
else if (node instanceof AST_ObjectSetter)
base54.consider("set" + (typeof node.key === "string" ? node.key : ""));
else if (node instanceof AST_ObjectGetter)
base54.consider("get" + (typeof node.key === "string" ? node.key : ""));
else if (node instanceof AST_ObjectKeyVal && typeof node.key === "string")
base54.consider(node.key);
else if (node instanceof AST_ConciseMethod && typeof node.key === "string")
base54.consider(node.key);
else if (node instanceof AST_New)
base54.consider("new");
else if (node instanceof AST_This)
base54.consider("this");
else if (node instanceof AST_Super)
base54.consider("super");
else if (node instanceof AST_Try)
base54.consider("try");
else if (node instanceof AST_Catch)
base54.consider("catch");
else if (node instanceof AST_Finally)
base54.consider("finally");
else if (node instanceof AST_Yield)
base54.consider("yield");
else if (node instanceof AST_Await)
base54.consider("await");
else if (node instanceof AST_Symbol && node.unmangleable(options))
base54.consider(node.name);
else if (node instanceof AST_Unary || node instanceof AST_Binary)
base54.consider(node.operator);
else if (node instanceof AST_Dot)
base54.consider(node.property);
});
this.walk(tw);
base54.sort(); base54.sort();
function skip_string(node) {
if (node instanceof AST_String) {
base54.consider(node.value, -1);
} else if (node instanceof AST_Conditional) {
skip_string(node.consequent);
skip_string(node.alternative);
} else if (node instanceof AST_Sequence) {
skip_string(node.expressions[node.expressions.length - 1]);
}
}
}); });
var base54 = (function() { var base54 = (function() {
var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; var leading = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_".split("");
var digits = "0123456789".split("");
var chars, frequency; var chars, frequency;
function reset() { function reset() {
frequency = Object.create(null); frequency = Object.create(null);
chars = string.split("").map(function(ch){ return ch.charCodeAt(0) }); leading.forEach(function(ch) {
chars.forEach(function(ch){ frequency[ch] = 0 }); frequency[ch] = 0;
});
digits.forEach(function(ch) {
frequency[ch] = 0;
});
} }
base54.consider = function(str){ base54.consider = function(str, delta) {
for (var i = str.length; --i >= 0;) { for (var i = str.length; --i >= 0;) {
var code = str.charCodeAt(i); frequency[str[i]] += delta;
if (code in frequency) ++frequency[code];
} }
}; };
function compare(a, b) {
return frequency[b] - frequency[a];
}
base54.sort = function() { base54.sort = function() {
chars = mergeSort(chars, function(a, b){ chars = mergeSort(leading, compare).concat(mergeSort(digits, compare));
if (is_digit(a) && !is_digit(b)) return 1;
if (is_digit(b) && !is_digit(a)) return -1;
return frequency[b] - frequency[a];
});
}; };
base54.reset = reset; base54.reset = reset;
reset(); reset();
base54.get = function(){ return chars };
base54.freq = function(){ return frequency };
function base54(num) { function base54(num) {
var ret = "", base = 54; var ret = "", base = 54;
num++; num++;
do { do {
num--; num--;
ret += String.fromCharCode(chars[num % base]); ret += chars[num % base];
num = Math.floor(num / base); num = Math.floor(num / base);
base = 64; base = 64;
} while (num > 0); } while (num > 0);

View File

@@ -4,7 +4,7 @@
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony", "homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
"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.0.19", "version": "3.0.20",
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=0.8.0"
}, },

View File

@@ -104,34 +104,36 @@ regression_block_scope_resolves: {
}; };
input: { input: {
(function () { (function () {
if(1) { if (1) {
let x; let x;
const y; const y = 1;
class Zee {}; class Zee {};
} }
if(1) { if (1) {
let ex; let ex;
const why; const why = 2;
class Zi {}; class Zi {};
} }
console.log(x, y, Zee, ex, why, Zi); console.log(typeof x, typeof y, typeof Zee, typeof ex, typeof why, typeof Zi);
}()); }());
} }
expect: { expect: {
(function () { (function () {
if (1) { if (1) {
let o; let e;
const n; const o = 1;
class c {}; class t {};
} }
if (1) { if (1) {
let o; let e;
const n; const o = 2;
class c {}; class t {};
} }
console.log(x, y, Zee, ex, why, Zi); console.log(typeof x, typeof y, typeof Zee, typeof ex, typeof why, typeof Zi);
}()); }());
} }
expect_stdout: "undefined undefined undefined undefined undefined undefined"
node_version: ">=6"
} }
switch_block_scope_mangler: { switch_block_scope_mangler: {
@@ -153,25 +155,37 @@ switch_block_scope_mangler: {
console.log(cat); console.log(cat);
} }
}; };
fn(1);
fn(2);
fn(3);
} }
expect: { expect: {
var fn = function(o) { var fn = function(e) {
switch (o) { switch (e) {
case 1: case 1:
let e = o + 1 let l = e + 1
let c = o + 4; let o = e + 4;
console.log(e, c); console.log(l, o);
break; break;
case 2: case 2:
let l = o + 2; let n = e + 2;
console.log(l); console.log(n);
break; break;
default: default:
let a = o + 3; let c = e + 3;
console.log(a); console.log(c);
} }
}; };
fn(1);
fn(2);
fn(3);
} }
expect_stdout: [
"2 5",
"4",
"6",
]
node_version: ">=6"
} }

View File

@@ -425,8 +425,8 @@ mangle_destructuring_decl: {
expect: { expect: {
function test(t) { function test(t) {
let e = t.a || { e: 7, n: 8 }; let e = t.a || { e: 7, n: 8 };
let {t: n, e: o, n: s, s: a = 9, o: c, r: l} = e; let {t: n, e: o, n: s, s: l = 9, o: a, r: c} = e;
console.log(n, o, s, a, c, l); console.log(n, o, s, l, a, c);
} }
test({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } }); test({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
test({}); test({});
@@ -462,15 +462,15 @@ mangle_destructuring_assign_toplevel_true: {
test({}); test({});
} }
expect: { expect: {
function n(n) { function e(e) {
let t, a, c; let l, s, a;
let l = n.a || { e: 7, n: 8 }; let c = e.a || { e: 7, n: 8 };
({t: o, e, n: s, s: t = 9, o: a, r: c} = l); ({t: n, e: o, n: t, s: l = 9, o: s, r: a} = c);
console.log(o, e, s, t, a, c); console.log(n, o, t, l, s, a);
} }
let o, e, s; let n, o, t;
n({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } }); e({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
n({}); e({});
} }
expect_stdout: [ expect_stdout: [
"1 2 3 4 5 6", "1 2 3 4 5 6",
@@ -504,10 +504,10 @@ mangle_destructuring_assign_toplevel_false: {
} }
expect: { expect: {
function test(o) { function test(o) {
let s, a, c; let s, l, a;
let l = o.a || { e: 7, n: 8 }; let c = o.a || { e: 7, n: 8 };
({t, e, n, s = 9, o: a, r: c} = l); ({t, e, n, s = 9, o: l, r: a} = c);
console.log(t, e, n, s, a, c); console.log(t, e, n, s, l, a);
} }
let t, e, n; let t, e, n;
test({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } }); test({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
@@ -588,8 +588,8 @@ arrow_func_with_destructuring_args: {
})({bar: 5 - 0}, [, 6]); })({bar: 5 - 0}, [, 6]);
} }
expect: { expect: {
(({foo: o = 1, bar: n = 2}, [a = 3, b = 4]) => { (({foo: o = 1, bar: a = 2}, [b = 3, l = 4]) => {
console.log(o, n, a, b); console.log(o, a, b, l);
})({bar: 5}, [, 6]); })({bar: 5}, [, 6]);
} }
expect_stdout: "1 5 3 6" expect_stdout: "1 5 3 6"

View File

@@ -33,10 +33,10 @@ issue_2038_2: {
export { LET, CONST, VAR }; export { LET, CONST, VAR };
} }
expect: { expect: {
let a = 1; let t = 1;
const c = 2; const e = 2;
var n = 3; var o = 3;
export { a as LET, c as CONST, n as VAR }; export { t as LET, e as CONST, o as VAR };
} }
} }
@@ -51,10 +51,10 @@ issue_2126: {
export { dog }; export { dog };
} }
expect: { expect: {
import { foo as o, cat as f } from "stuff"; import { foo as o, cat as s } from "stuff";
console.log(o, f); console.log(o, s);
export { o as qux }; export { o as qux };
export { f as dog }; export { s as dog };
} }
} }
@@ -166,9 +166,9 @@ redirection: {
export { foo as var } from "module.js"; export { foo as var } from "module.js";
} }
expect: { expect: {
let o = 1, d = 2; let e = 1, o = 2;
export { o as delete }; export { e as delete };
export { d as default }; export { o as default };
export { foo as var } from "module.js"; export { foo as var } from "module.js";
} }
} }

View File

@@ -265,7 +265,7 @@ issue_203: {
} }
expect: { expect: {
var m = {}; var m = {};
var fn = Function("a", "b", "b.exports=42"); var fn = Function("n", "o", "o.exports=42");
fn(null, m, m.exports); fn(null, m, m.exports);
console.log(m.exports); console.log(m.exports);
} }

View File

@@ -63,15 +63,15 @@ class_name_can_be_mangled: {
function x() { function x() {
class Foo { class Foo {
} }
var class1 = Foo var class1 = Foo;
var class2 = class Bar {} var class2 = class Bar {};
} }
} }
expect: { expect: {
function x() { function x() {
class a { } class a { }
var n = a var s = a;
var r = class a {} var c = class a {};
} }
} }
} }
@@ -290,12 +290,12 @@ import_statement_mangling: {
Whatever(); Whatever();
} }
expect: { expect: {
import l from "foo"; import o from "foo";
import e, {Food as o} from "lel"; import m, {Food as r} from "lel";
import {What as f} from "lel"; import {What as f} from "lel";
l();
e();
o(); o();
m();
r();
f(); f();
} }
} }
@@ -469,10 +469,10 @@ issue_1898: {
expect: { expect: {
class Foo { class Foo {
bar() { bar() {
for (const n of [ 6, 5 ]) for (const f of [ 6, 5 ])
for (let r of [ 4, 3 ]) for (let r of [ 4, 3 ])
for (var o of [ 2, 1 ]) for (var o of [ 2, 1 ])
console.log(n, r, o); console.log(f, r, o);
} }
} }
new Foo().bar(); new Foo().bar();
@@ -497,9 +497,9 @@ issue_1753: {
expect: { expect: {
class SomeClass { class SomeClass {
constructor(r) { constructor(r) {
let a = []; let s = [];
for (let s = 0; s < 6; s++) for (let a = 0; a < 6; a++)
a.push({ s.push({
mainDrawNumbers: [], mainDrawNumbers: [],
extraDrawNumbers: [] extraDrawNumbers: []
}); });
@@ -526,9 +526,9 @@ issue_1753_disable: {
expect: { expect: {
class SomeClass { class SomeClass {
constructor(r) { constructor(r) {
let a = []; let s = [];
for (let r = 0; r < 6; r++) for (let r = 0; r < 6; r++)
a.push({ s.push({
mainDrawNumbers: [], mainDrawNumbers: [],
extraDrawNumbers: [] extraDrawNumbers: []
}); });

View File

@@ -10,9 +10,9 @@ issue_1321_no_debug: {
} }
expect: { expect: {
var x = {}; var x = {};
x.b = 1; x.o = 1;
x["a"] = 2 * x.b; x["a"] = 2 * x.o;
console.log(x.b, x["a"]); console.log(x.o, x["a"]);
} }
expect_stdout: true expect_stdout: true
} }
@@ -30,9 +30,9 @@ issue_1321_debug: {
} }
expect: { expect: {
var x = {}; var x = {};
x.a = 1; x.o = 1;
x["_$foo$_"] = 2 * x.a; x["_$foo$_"] = 2 * x.o;
console.log(x.a, x["_$foo$_"]); console.log(x.o, x["_$foo$_"]);
} }
expect_stdout: true expect_stdout: true
} }
@@ -49,9 +49,9 @@ issue_1321_with_quoted: {
} }
expect: { expect: {
var x = {}; var x = {};
x.a = 1; x.o = 1;
x["b"] = 2 * x.a; x["x"] = 2 * x.o;
console.log(x.a, x["b"]); console.log(x.o, x["x"]);
} }
expect_stdout: true expect_stdout: true
} }

View File

@@ -33,8 +33,8 @@ same_variable_in_multiple_for_loop: {
console.log(o, l); console.log(o, l);
for (let o = 0; o < 2; o++) { for (let o = 0; o < 2; o++) {
console.log(o, l); console.log(o, l);
let c = 2; let e = 2;
console.log(c); console.log(e);
} }
} }
} }
@@ -114,12 +114,12 @@ same_variable_in_multiple_forIn: {
} }
expect: { expect: {
var test = [ "a", "b", "c" ]; var test = [ "a", "b", "c" ];
for (let o in test) { for (let e in test) {
console.log(o); console.log(e);
let e; let t;
e = [ "e", "f", "g" ]; t = [ "e", "f", "g" ];
for (let o in test) for (let e in test)
console.log(o); console.log(e);
} }
} }
expect_stdout: true expect_stdout: true
@@ -160,8 +160,8 @@ different_variable_in_multiple_for_loop: {
console.log(o, l); console.log(o, l);
for (let o = 0; o < 2; o++) { for (let o = 0; o < 2; o++) {
console.log(o, l); console.log(o, l);
let c = 2; let e = 2;
console.log(c); console.log(e);
} }
} }
} }
@@ -241,12 +241,12 @@ different_variable_in_multiple_forIn: {
} }
expect: { expect: {
var test = [ "a", "b", "c" ]; var test = [ "a", "b", "c" ];
for (let o in test) { for (let e in test) {
console.log(o); console.log(e);
let e; let t;
e = [ "e", "f", "g" ]; t = [ "e", "f", "g" ];
for (let o in test) for (let e in test)
console.log(o); console.log(e);
} }
} }
expect_stdout: true expect_stdout: true
@@ -281,10 +281,10 @@ more_variable_in_multiple_for: {
} }
expect: { expect: {
for (let o = 9, l = 0; l < 20; l += o) { for (let o = 9, l = 0; l < 20; l += o) {
let c = o++ + l; let e = o++ + l;
console.log(o, c, l); console.log(o, e, l);
for (let l = c, e = c * c, f = 0; f < 10; f++) for (let l = e, t = e * e, c = 0; c < 10; c++)
console.log(o, c, e, l, f); console.log(o, e, t, l, c);
} }
} }
expect_stdout: true expect_stdout: true

View File

@@ -82,7 +82,7 @@ numeric_literal: {
' 42: 2,', ' 42: 2,',
' "42": 3,', ' "42": 3,',
' 37: 4,', ' 37: 4,',
' a: 5,', ' o: 5,',
' 1e42: 6,', ' 1e42: 6,',
' b: 7,', ' b: 7,',
' "1e+42": 8', ' "1e+42": 8',
@@ -92,7 +92,7 @@ numeric_literal: {
'', '',
'console.log(obj[42], obj["42"]);', 'console.log(obj[42], obj["42"]);',
'', '',
'console.log(obj[37], obj["a"], obj[37], obj["37"]);', 'console.log(obj[37], obj["o"], obj[37], obj["37"]);',
'', '',
'console.log(obj[1e42], obj["b"], obj["1e+42"]);', 'console.log(obj[1e42], obj["b"], obj["1e+42"]);',
] ]

View File

@@ -159,7 +159,7 @@ export_mangle_1: {
return one - two; return one - two;
}; };
} }
expect_exact: "export function foo(n,o){return n-o};" expect_exact: "export function foo(o,n){return o-n};"
} }
export_mangle_2: { export_mangle_2: {
@@ -171,7 +171,7 @@ export_mangle_2: {
return one - two; return one - two;
}; };
} }
expect_exact: "export default function foo(n,o){return n-o};" expect_exact: "export default function foo(o,t){return o-t};"
} }
export_mangle_3: { export_mangle_3: {
@@ -189,7 +189,7 @@ export_mangle_3: {
} }
}; };
} }
expect_exact: "export class C{go(n,r){return n-r+n}};" expect_exact: "export class C{go(r,e){return r-e+r}};"
} }
export_mangle_4: { export_mangle_4: {
@@ -207,7 +207,7 @@ export_mangle_4: {
} }
}; };
} }
expect_exact: "export default class C{go(n,r){return n-r+n}};" expect_exact: "export default class C{go(e,r){return e-r+e}};"
} }
export_mangle_5: { export_mangle_5: {
@@ -221,7 +221,7 @@ export_mangle_5: {
} }
}; };
} }
expect_exact: "export default{prop:function(n,r){return n-r}};" expect_exact: "export default{prop:function(r,t){return r-t}};"
} }
export_mangle_6: { export_mangle_6: {
@@ -232,7 +232,7 @@ export_mangle_6: {
var baz = 2; var baz = 2;
export let foo = 1, bar = baz; export let foo = 1, bar = baz;
} }
expect_exact: "var a=2;export let foo=1,bar=a;" expect_exact: "var o=2;export let foo=1,bar=o;"
} }
export_toplevel_1: { export_toplevel_1: {

View File

@@ -8,7 +8,7 @@ compress_new_function: {
new Function("aa, bb", 'return aa;'); new Function("aa, bb", 'return aa;');
} }
expect: { expect: {
Function("a", "b", "return a"); Function("n", "r", "return n");
} }
} }
@@ -27,9 +27,9 @@ compress_new_function_with_destruct: {
new Function("[[aa]], [{bb}]", 'return aa;'); new Function("[[aa]], [{bb}]", 'return aa;');
} }
expect: { expect: {
Function("a", "[b]", "return a"); Function("n", "[r]", "return n");
Function("a", "{bb:b}", "return a"); Function("n", "{bb:b}", "return n");
Function("[[a]]", "[{bb:b}]", 'return a'); Function("[[n]]", "[{bb:b}]", "return n");
} }
} }

View File

@@ -1,37 +1,41 @@
dont_reuse_prop: { dont_reuse_prop: {
mangle_props = { mangle_props = {
regex: /asd/ regex: /asd/
}; }
input: { input: {
"aaaaaaaaaabbbbb";
var obj = {}; var obj = {};
obj.a = 123; obj.a = 123;
obj.asd = 256; obj.asd = 256;
console.log(obj.a); console.log(obj.a);
} }
expect: { expect: {
"aaaaaaaaaabbbbb";
var obj = {}; var obj = {};
obj.a = 123; obj.a = 123;
obj.b = 256; obj.b = 256;
console.log(obj.a); console.log(obj.a);
} }
expect_stdout: "123"
} }
unmangleable_props_should_always_be_reserved: { unmangleable_props_should_always_be_reserved: {
mangle_props = { mangle_props = {
regex: /asd/ regex: /asd/
}; }
input: { input: {
"aaaaaaaaaabbbbb";
var obj = {}; var obj = {};
obj.asd = 256; obj.asd = 256;
obj.a = 123; obj.a = 123;
console.log(obj.a); console.log(obj.a);
} }
expect: { expect: {
"aaaaaaaaaabbbbb";
var obj = {}; var obj = {};
obj.b = 256; obj.b = 256;
obj.a = 123; obj.a = 123;
console.log(obj.a); console.log(obj.a);
} }
expect_stdout: "123"
} }

View File

@@ -105,7 +105,7 @@ getter_setter_mangler: {
}; };
} }
} }
expect_exact: "function f(n,t){return{get:n,set:t,get g(){},set s(n){},c,a:1,m(){}}}" expect_exact: "function f(t,e){return{get:t,set:e,get g(){},set s(t){},c,a:1,m(){}}}"
} }
use_shorthand_opportunity: { use_shorthand_opportunity: {
@@ -297,7 +297,7 @@ concise_methods_and_mangle_props: {
expect: { expect: {
function x() { function x() {
obj = { obj = {
a() { return 1; } o() { return 1; }
} }
} }
} }

View File

@@ -135,11 +135,11 @@ mangle_properties: {
a['run']({color: "blue", foo: "baz"}); a['run']({color: "blue", foo: "baz"});
} }
expect: { expect: {
a["a"] = "bar"; a["o"] = "bar";
a.b = "red"; a.a = "red";
x = {c: 10}; x = {r: 10};
a.d(x.c, a.a); a.b(x.r, a.o);
a['d']({b: "blue", a: "baz"}); a['b']({a: "blue", o: "baz"});
} }
} }
@@ -178,16 +178,16 @@ mangle_unquoted_properties: {
function f1() { function f1() {
a["foo"] = "bar"; a["foo"] = "bar";
a.color = "red"; a.color = "red";
a.b = 2; a.o = 2;
x = {"bar": 10, c: 7}; x = {"bar": 10, f: 7};
a.c = 9; a.f = 9;
} }
function f2() { function f2() {
a.foo = "bar"; a.foo = "bar";
a['color'] = "red"; a['color'] = "red";
x = {bar: 10, c: 7}; x = {bar: 10, f: 7};
a.c = 9; a.f = 9;
a.b = 3; a.o = 3;
} }
} }
} }

View File

@@ -241,3 +241,147 @@ issue_2110_2: {
} }
expect_stdout: "function" expect_stdout: "function"
} }
set_immutable_1: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 1;
a.foo += "";
if (a.foo) console.log("FAIL");
else console.log("PASS");
}
expect: {
1..foo += "";
if (1..foo) console.log("FAIL");
else console.log("PASS");
}
expect_stdout: "PASS"
}
set_immutable_2: {
options = {
cascade: true,
conditionals: true,
pure_getters: "strict",
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
}
input: {
var a = 1;
a.foo += "";
if (a.foo) console.log("FAIL");
else console.log("PASS");
}
expect: {
var a = 1;
a.foo += "", a.foo ? console.log("FAIL") : console.log("PASS");
}
expect_stdout: "PASS"
}
set_immutable_3: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
var a = 1;
a.foo += "";
if (a.foo) console.log("FAIL");
else console.log("PASS");
}
expect: {
"use strict";
1..foo += "";
if (1..foo) console.log("FAIL");
else console.log("PASS");
}
expect_stdout: true
}
set_immutable_4: {
options = {
cascade: true,
conditionals: true,
pure_getters: "strict",
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
}
input: {
"use strict";
var a = 1;
a.foo += "";
if (a.foo) console.log("FAIL");
else console.log("PASS");
}
expect: {
"use strict";
var a = 1;
a.foo += "", a.foo ? console.log("FAIL") : console.log("PASS");
}
expect_stdout: true
}
set_mutable_1: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
reduce_vars: true,
unused: true,
}
input: {
!function a() {
a.foo += "";
if (a.foo) console.log("PASS");
else console.log("FAIL");
}();
}
expect: {
!function a() {
if (a.foo += "") console.log("PASS");
else console.log("FAIL");
}();
}
expect_stdout: "PASS"
}
set_mutable_2: {
options = {
cascade: true,
conditionals: true,
pure_getters: "strict",
reduce_vars: true,
sequences: true,
side_effects: true,
}
input: {
!function a() {
a.foo += "";
if (a.foo) console.log("PASS");
else console.log("FAIL");
}();
}
expect: {
!function a() {
(a.foo += "") ? console.log("PASS") : console.log("FAIL");
}();
}
expect_stdout: "PASS"
}

View File

@@ -2625,3 +2625,28 @@ issue_2090_2: {
expect_stdout: "1" expect_stdout: "1"
node_version: ">=4" node_version: ">=4"
} }
for_in_prop: {
options = {
reduce_vars: true,
}
input: {
var a = {
foo: function() {
for (this.b in [1, 2]);
}
};
a.foo();
console.log(a.b);
}
expect: {
var a = {
foo: function() {
for (this.b in [1, 2]);
}
};
a.foo();
console.log(a.b);
}
expect_stdout: "1"
}

View File

@@ -0,0 +1,4 @@
var a, b = [1, 2];
for (1, 2, a in b) {
console.log(a, b[a]);
}

View File

@@ -0,0 +1,4 @@
var c = [1, 2];
for (var a, b in c) {
console.log(a, c[a]);
}

View File

@@ -611,6 +611,36 @@ describe("bin/uglifyjs", function () {
done(); done();
}); });
}); });
it("Should throw syntax error (for-in init)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/for-in_1.js';
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/for-in_1.js:2,5",
"for (1, 2, a in b) {",
" ^",
"ERROR: Invalid left-hand side in for..in loop"
].join("\n"));
done();
});
});
it("Should throw syntax error (for-in var)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/for-in_2.js';
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/for-in_2.js:2,5",
"for (var a, b in c) {",
" ^",
"ERROR: Only one variable declaration allowed in for..in loop"
].join("\n"));
done();
});
});
it("Should handle literal string as source map input", function(done) { it("Should handle literal string as source map input", function(done) {
var command = [ var command = [
uglifyjscmd, uglifyjscmd,

View File

@@ -2,29 +2,37 @@ var Uglify = require('../../');
var assert = require("assert"); var assert = require("assert");
describe("let", function() { describe("let", function() {
it("Should not produce `let` as a variable name in mangle", function(done) { it("Should not produce reserved keywords as variable name in mangle", function(done) {
this.timeout(10000); this.timeout(10000);
// Produce a lot of variables in a function and run it through mangle. // Produce a lot of variables in a function and run it through mangle.
var s = '"use strict"; function foo() {'; var s = '"dddddeeeeelllllooooottttt"; function foo() {';
for (var i = 0; i < 21000; ++i) { for (var i = 0; i < 18000; i++) {
s += "var v" + i + "=0;"; s += "var v" + i + "=0;";
} }
s += '}'; s += '}';
var result = Uglify.minify(s, {compress: false}); var result = Uglify.minify(s, {compress: false});
// Verify that select keywords and reserved keywords not produced // Verify that select keywords and reserved keywords not produced
assert.strictEqual(result.code.indexOf("var let="), -1); [
assert.strictEqual(result.code.indexOf("var do="), -1); "do",
assert.strictEqual(result.code.indexOf("var var="), -1); "let",
"var",
].forEach(function(name) {
assert.strictEqual(result.code.indexOf("var " + name + "="), -1);
});
// Verify that the variable names that appeared immediately before // Verify that the variable names that appeared immediately before
// and after the erroneously generated `let` variable name still exist // and after the erroneously generated variable name still exist
// to show the test generated enough symbols. // to show the test generated enough symbols.
assert(result.code.indexOf("var ket=") >= 0); [
assert(result.code.indexOf("var met=") >= 0); "to", "eo",
"eet", "fet",
"rar", "oar",
].forEach(function(name) {
assert.ok(result.code.indexOf("var " + name + "=") >= 0);
});
done(); done();
}); });
}); });

View File

@@ -86,7 +86,6 @@ function run_compress_tests() {
log_start_file(file); log_start_file(file);
function test_case(test) { function test_case(test) {
log_test(test.name); log_test(test.name);
U.base54.reset();
var output_options = test.beautify || {}; var output_options = test.beautify || {};
var expect; var expect;
if (test.expect) { if (test.expect) {
@@ -101,9 +100,6 @@ function run_compress_tests() {
quote_style: 3, quote_style: 3,
keep_quoted_props: true keep_quoted_props: true
}); });
if (test.mangle_props) {
input = U.mangle_properties(input, test.mangle_props);
}
var options = U.defaults(test.options, { var options = U.defaults(test.options, {
warnings: false warnings: false
}); });
@@ -118,10 +114,16 @@ function run_compress_tests() {
var cmp = new U.Compressor(options, true); var cmp = new U.Compressor(options, true);
var output = cmp.compress(input); var output = cmp.compress(input);
output.figure_out_scope(test.mangle); output.figure_out_scope(test.mangle);
if (test.mangle) { if (test.mangle || test.mangle_props) {
U.base54.reset();
output.compute_char_frequency(test.mangle); output.compute_char_frequency(test.mangle);
}
if (test.mangle) {
output.mangle_names(test.mangle); output.mangle_names(test.mangle);
} }
if (test.mangle_props) {
output = U.mangle_properties(output, test.mangle_props);
}
output = make_code(output, output_options); output = make_code(output, output_options);
if (expect != output) { if (expect != output) {
log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", { log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", {