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

View File

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

View File

@@ -1230,9 +1230,12 @@ function parse($TEXT, options) {
var is_in = is("operator", "in");
var is_of = is("name", "of");
if (is_in || is_of) {
if ((init instanceof AST_Definitions) &&
init.definitions.length > 1)
croak("Only one variable declaration allowed in for..in loop");
if (init instanceof AST_Definitions) {
if (init.definitions.length > 1)
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();
if (is_in) {
return for_in(init);

View File

@@ -450,7 +450,7 @@ AST_Function.DEFMETHOD("next_mangled", function(options, def){
AST_Symbol.DEFMETHOD("unmangleable", function(options){
var def = this.definition();
return def && def.unmangleable(options);
return !def || def.unmangleable(options);
});
// labels are always mangleable
@@ -555,113 +555,69 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
options = this._default_mangler_options(options);
var tw = new TreeWalker(function(node){
if (node instanceof AST_Constant)
base54.consider(node.print_to_string());
else if (node instanceof AST_Return)
base54.consider("return");
else if (node instanceof AST_Throw)
base54.consider("throw");
else if (node instanceof AST_Continue)
base54.consider("continue");
else if (node instanceof AST_Break)
base54.consider("break");
else if (node instanceof AST_Debugger)
base54.consider("debugger");
else if (node instanceof AST_Directive)
base54.consider(node.value);
else if (node instanceof AST_While)
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");
try {
AST_Node.prototype.print = function(stream, force_parens) {
this._print(stream, force_parens);
if (this instanceof AST_Symbol && !this.unmangleable(options)) {
base54.consider(this.name, -1);
} else if (options.properties) {
if (this instanceof AST_Dot) {
base54.consider(this.property, -1);
} else if (this instanceof AST_Sub) {
skip_string(this.property);
}
}
};
base54.consider(this.print_to_string(), 1);
} finally {
AST_Node.prototype.print = AST_Node.prototype._print;
}
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();
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 string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
var leading = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_".split("");
var digits = "0123456789".split("");
var chars, frequency;
function reset() {
frequency = Object.create(null);
chars = string.split("").map(function(ch){ return ch.charCodeAt(0) });
chars.forEach(function(ch){ frequency[ch] = 0 });
leading.forEach(function(ch) {
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;) {
var code = str.charCodeAt(i);
if (code in frequency) ++frequency[code];
frequency[str[i]] += delta;
}
};
base54.sort = function() {
chars = mergeSort(chars, function(a, b){
if (is_digit(a) && !is_digit(b)) return 1;
if (is_digit(b) && !is_digit(a)) return -1;
function compare(a, b) {
return frequency[b] - frequency[a];
});
}
base54.sort = function() {
chars = mergeSort(leading, compare).concat(mergeSort(digits, compare));
};
base54.reset = reset;
reset();
base54.get = function(){ return chars };
base54.freq = function(){ return frequency };
function base54(num) {
var ret = "", base = 54;
num++;
do {
num--;
ret += String.fromCharCode(chars[num % base]);
ret += chars[num % base];
num = Math.floor(num / base);
base = 64;
} while (num > 0);

View File

@@ -4,7 +4,7 @@
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.0.19",
"version": "3.0.20",
"engines": {
"node": ">=0.8.0"
},

View File

@@ -106,32 +106,34 @@ regression_block_scope_resolves: {
(function () {
if (1) {
let x;
const y;
const y = 1;
class Zee {};
}
if (1) {
let ex;
const why;
const why = 2;
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: {
(function () {
if (1) {
let o;
const n;
class c {};
let e;
const o = 1;
class t {};
}
if (1) {
let o;
const n;
class c {};
let e;
const o = 2;
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: {
@@ -153,25 +155,37 @@ switch_block_scope_mangler: {
console.log(cat);
}
};
fn(1);
fn(2);
fn(3);
}
expect: {
var fn = function(o) {
switch (o) {
var fn = function(e) {
switch (e) {
case 1:
let e = o + 1
let c = o + 4;
console.log(e, c);
let l = e + 1
let o = e + 4;
console.log(l, o);
break;
case 2:
let l = o + 2;
console.log(l);
let n = e + 2;
console.log(n);
break;
default:
let a = o + 3;
console.log(a);
let c = e + 3;
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: {
function test(t) {
let e = t.a || { e: 7, n: 8 };
let {t: n, e: o, n: s, s: a = 9, o: c, r: l} = e;
console.log(n, o, s, a, c, l);
let {t: n, e: o, n: s, s: l = 9, o: a, r: c} = e;
console.log(n, o, s, l, a, c);
}
test({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
test({});
@@ -462,15 +462,15 @@ mangle_destructuring_assign_toplevel_true: {
test({});
}
expect: {
function n(n) {
let t, a, c;
let l = n.a || { e: 7, n: 8 };
({t: o, e, n: s, s: t = 9, o: a, r: c} = l);
console.log(o, e, s, t, a, c);
function e(e) {
let l, s, a;
let c = e.a || { e: 7, n: 8 };
({t: n, e: o, n: t, s: l = 9, o: s, r: a} = c);
console.log(n, o, t, l, s, a);
}
let o, e, s;
n({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
n({});
let n, o, t;
e({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
e({});
}
expect_stdout: [
"1 2 3 4 5 6",
@@ -504,10 +504,10 @@ mangle_destructuring_assign_toplevel_false: {
}
expect: {
function test(o) {
let s, a, c;
let l = o.a || { e: 7, n: 8 };
({t, e, n, s = 9, o: a, r: c} = l);
console.log(t, e, n, s, a, c);
let s, l, a;
let c = o.a || { e: 7, n: 8 };
({t, e, n, s = 9, o: l, r: a} = c);
console.log(t, e, n, s, l, a);
}
let t, e, n;
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]);
}
expect: {
(({foo: o = 1, bar: n = 2}, [a = 3, b = 4]) => {
console.log(o, n, a, b);
(({foo: o = 1, bar: a = 2}, [b = 3, l = 4]) => {
console.log(o, a, b, l);
})({bar: 5}, [, 6]);
}
expect_stdout: "1 5 3 6"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -82,7 +82,7 @@ numeric_literal: {
' 42: 2,',
' "42": 3,',
' 37: 4,',
' a: 5,',
' o: 5,',
' 1e42: 6,',
' b: 7,',
' "1e+42": 8',
@@ -92,7 +92,7 @@ numeric_literal: {
'',
'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"]);',
]

View File

@@ -159,7 +159,7 @@ export_mangle_1: {
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: {
@@ -171,7 +171,7 @@ export_mangle_2: {
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: {
@@ -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: {
@@ -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: {
@@ -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: {
@@ -232,7 +232,7 @@ export_mangle_6: {
var baz = 2;
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: {

View File

@@ -8,7 +8,7 @@ compress_new_function: {
new Function("aa, bb", 'return aa;');
}
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;');
}
expect: {
Function("a", "[b]", "return a");
Function("a", "{bb:b}", "return a");
Function("[[a]]", "[{bb:b}]", 'return a');
Function("n", "[r]", "return n");
Function("n", "{bb:b}", "return n");
Function("[[n]]", "[{bb:b}]", "return n");
}
}

View File

@@ -1,37 +1,41 @@
dont_reuse_prop: {
mangle_props = {
regex: /asd/
};
}
input: {
"aaaaaaaaaabbbbb";
var obj = {};
obj.a = 123;
obj.asd = 256;
console.log(obj.a);
}
expect: {
"aaaaaaaaaabbbbb";
var obj = {};
obj.a = 123;
obj.b = 256;
console.log(obj.a);
}
expect_stdout: "123"
}
unmangleable_props_should_always_be_reserved: {
mangle_props = {
regex: /asd/
};
}
input: {
"aaaaaaaaaabbbbb";
var obj = {};
obj.asd = 256;
obj.a = 123;
console.log(obj.a);
}
expect: {
"aaaaaaaaaabbbbb";
var obj = {};
obj.b = 256;
obj.a = 123;
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: {
@@ -297,7 +297,7 @@ concise_methods_and_mangle_props: {
expect: {
function x() {
obj = {
a() { return 1; }
o() { return 1; }
}
}
}

View File

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

View File

@@ -241,3 +241,147 @@ issue_2110_2: {
}
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"
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();
});
});
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) {
var command = [
uglifyjscmd,

View File

@@ -2,29 +2,37 @@ var Uglify = require('../../');
var assert = require("assert");
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);
// Produce a lot of variables in a function and run it through mangle.
var s = '"use strict"; function foo() {';
for (var i = 0; i < 21000; ++i) {
var s = '"dddddeeeeelllllooooottttt"; function foo() {';
for (var i = 0; i < 18000; i++) {
s += "var v" + i + "=0;";
}
s += '}';
var result = Uglify.minify(s, {compress: false});
// 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);
assert.strictEqual(result.code.indexOf("var var="), -1);
[
"do",
"let",
"var",
].forEach(function(name) {
assert.strictEqual(result.code.indexOf("var " + name + "="), -1);
});
// 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.
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();
});
});

View File

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