fix corner case in ie8 & rename (#3223)
This commit is contained in:
@@ -118,10 +118,8 @@ var AST_Node = DEFNODE("Node", "start end", {
|
|||||||
}
|
}
|
||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
AST_Node.warn_function = null;
|
|
||||||
AST_Node.warn = function(txt, props) {
|
AST_Node.warn = function(txt, props) {
|
||||||
if (AST_Node.warn_function)
|
if (AST_Node.warn_function) AST_Node.warn_function(string_template(txt, props));
|
||||||
AST_Node.warn_function(string_template(txt, props));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* -----[ statements ]----- */
|
/* -----[ statements ]----- */
|
||||||
@@ -207,8 +205,7 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
|
|||||||
var label = node.label;
|
var label = node.label;
|
||||||
var def = this.label;
|
var def = this.label;
|
||||||
node.walk(new TreeWalker(function(node) {
|
node.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_LoopControl
|
if (node instanceof AST_LoopControl && node.label && node.label.thedef === def) {
|
||||||
&& node.label && node.label.thedef === def) {
|
|
||||||
node.label.thedef = label;
|
node.label.thedef = label;
|
||||||
label.references.push(node);
|
label.references.push(node);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,25 +53,30 @@ function find_builtins(reserved) {
|
|||||||
"-Infinity",
|
"-Infinity",
|
||||||
"undefined",
|
"undefined",
|
||||||
].forEach(add);
|
].forEach(add);
|
||||||
[ Object, Array, Function, Number,
|
[
|
||||||
String, Boolean, Error, Math,
|
Array,
|
||||||
Date, RegExp
|
Boolean,
|
||||||
|
Date,
|
||||||
|
Error,
|
||||||
|
Function,
|
||||||
|
Math,
|
||||||
|
Number,
|
||||||
|
Object,
|
||||||
|
RegExp,
|
||||||
|
String,
|
||||||
].forEach(function(ctor) {
|
].forEach(function(ctor) {
|
||||||
Object.getOwnPropertyNames(ctor).map(add);
|
Object.getOwnPropertyNames(ctor).map(add);
|
||||||
if (ctor.prototype) {
|
if (ctor.prototype) {
|
||||||
Object.getOwnPropertyNames(ctor.prototype).map(add);
|
Object.getOwnPropertyNames(ctor.prototype).map(add);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function add(name) {
|
function add(name) {
|
||||||
push_uniq(reserved, name);
|
push_uniq(reserved, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function reserve_quoted_keys(ast, reserved) {
|
function reserve_quoted_keys(ast, reserved) {
|
||||||
function add(name) {
|
|
||||||
push_uniq(reserved, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
ast.walk(new TreeWalker(function(node) {
|
ast.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_ObjectKeyVal && node.quote) {
|
if (node instanceof AST_ObjectKeyVal && node.quote) {
|
||||||
add(node.key);
|
add(node.key);
|
||||||
@@ -79,6 +84,10 @@ function reserve_quoted_keys(ast, reserved) {
|
|||||||
addStrings(node.property, add);
|
addStrings(node.property, add);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
function add(name) {
|
||||||
|
push_uniq(reserved, name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addStrings(node, add) {
|
function addStrings(node, add) {
|
||||||
@@ -127,10 +136,8 @@ function mangle_properties(ast, options) {
|
|||||||
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
|
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
|
||||||
// the same as passing an empty string.
|
// the same as passing an empty string.
|
||||||
var debug = options.debug !== false;
|
var debug = options.debug !== false;
|
||||||
var debug_name_suffix;
|
var debug_suffix;
|
||||||
if (debug) {
|
if (debug) debug_suffix = options.debug === true ? "" : options.debug;
|
||||||
debug_name_suffix = (options.debug === true ? "" : options.debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
var names_to_mangle = [];
|
var names_to_mangle = [];
|
||||||
var unmangleable = [];
|
var unmangleable = [];
|
||||||
@@ -139,18 +146,14 @@ function mangle_properties(ast, options) {
|
|||||||
ast.walk(new TreeWalker(function(node) {
|
ast.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_ObjectKeyVal) {
|
if (node instanceof AST_ObjectKeyVal) {
|
||||||
add(node.key);
|
add(node.key);
|
||||||
}
|
} else if (node instanceof AST_ObjectProperty) {
|
||||||
else if (node instanceof AST_ObjectProperty) {
|
|
||||||
// setter or getter, since KeyVal is handled above
|
// setter or getter, since KeyVal is handled above
|
||||||
add(node.key.name);
|
add(node.key.name);
|
||||||
}
|
} else if (node instanceof AST_Dot) {
|
||||||
else if (node instanceof AST_Dot) {
|
|
||||||
add(node.property);
|
add(node.property);
|
||||||
}
|
} 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
|
||||||
else if (node instanceof AST_Call
|
|
||||||
&& node.expression.print_to_string() == "Object.defineProperty") {
|
&& node.expression.print_to_string() == "Object.defineProperty") {
|
||||||
addStrings(node.args[1], add);
|
addStrings(node.args[1], add);
|
||||||
}
|
}
|
||||||
@@ -160,18 +163,14 @@ function mangle_properties(ast, options) {
|
|||||||
return ast.transform(new TreeTransformer(function(node) {
|
return ast.transform(new TreeTransformer(function(node) {
|
||||||
if (node instanceof AST_ObjectKeyVal) {
|
if (node instanceof AST_ObjectKeyVal) {
|
||||||
node.key = mangle(node.key);
|
node.key = mangle(node.key);
|
||||||
}
|
} else if (node instanceof AST_ObjectProperty) {
|
||||||
else if (node instanceof AST_ObjectProperty) {
|
|
||||||
// setter or getter
|
// setter or getter
|
||||||
node.key.name = mangle(node.key.name);
|
node.key.name = mangle(node.key.name);
|
||||||
}
|
} else if (node instanceof AST_Dot) {
|
||||||
else if (node instanceof AST_Dot) {
|
|
||||||
node.property = mangle(node.property);
|
node.property = mangle(node.property);
|
||||||
}
|
} 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
|
||||||
else if (node instanceof AST_Call
|
|
||||||
&& node.expression.print_to_string() == "Object.defineProperty") {
|
&& node.expression.print_to_string() == "Object.defineProperty") {
|
||||||
node.args[1] = mangleStrings(node.args[1]);
|
node.args[1] = mangleStrings(node.args[1]);
|
||||||
}
|
}
|
||||||
@@ -182,9 +181,7 @@ function mangle_properties(ast, options) {
|
|||||||
function can_mangle(name) {
|
function can_mangle(name) {
|
||||||
if (unmangleable.indexOf(name) >= 0) return false;
|
if (unmangleable.indexOf(name) >= 0) return false;
|
||||||
if (reserved.indexOf(name) >= 0) return false;
|
if (reserved.indexOf(name) >= 0) return false;
|
||||||
if (options.only_cache) {
|
if (options.only_cache) return cache.has(name);
|
||||||
return cache.has(name);
|
|
||||||
}
|
|
||||||
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
|
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -192,42 +189,29 @@ function mangle_properties(ast, options) {
|
|||||||
function should_mangle(name) {
|
function should_mangle(name) {
|
||||||
if (regex && !regex.test(name)) return false;
|
if (regex && !regex.test(name)) return false;
|
||||||
if (reserved.indexOf(name) >= 0) return false;
|
if (reserved.indexOf(name) >= 0) return false;
|
||||||
return cache.has(name)
|
return cache.has(name) || names_to_mangle.indexOf(name) >= 0;
|
||||||
|| names_to_mangle.indexOf(name) >= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function add(name) {
|
function add(name) {
|
||||||
if (can_mangle(name))
|
if (can_mangle(name)) push_uniq(names_to_mangle, name);
|
||||||
push_uniq(names_to_mangle, name);
|
if (!should_mangle(name)) push_uniq(unmangleable, name);
|
||||||
|
|
||||||
if (!should_mangle(name)) {
|
|
||||||
push_uniq(unmangleable, name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mangle(name) {
|
function mangle(name) {
|
||||||
if (!should_mangle(name)) {
|
if (!should_mangle(name)) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mangled = cache.get(name);
|
var mangled = cache.get(name);
|
||||||
if (!mangled) {
|
if (!mangled) {
|
||||||
if (debug) {
|
if (debug) {
|
||||||
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
|
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
|
||||||
var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
|
var debug_mangled = "_$" + name + "$" + debug_suffix + "_";
|
||||||
|
if (can_mangle(debug_mangled)) mangled = debug_mangled;
|
||||||
if (can_mangle(debug_mangled)) {
|
|
||||||
mangled = debug_mangled;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// either debug mode is off, or it is on and we could not use the mangled name
|
// either debug mode is off, or it is on and we could not use the mangled name
|
||||||
if (!mangled) {
|
if (!mangled) do {
|
||||||
do {
|
|
||||||
mangled = base54(++cname);
|
mangled = base54(++cname);
|
||||||
} while (!can_mangle(mangled));
|
} while (!can_mangle(mangled));
|
||||||
}
|
|
||||||
|
|
||||||
cache.set(name, mangled);
|
cache.set(name, mangled);
|
||||||
}
|
}
|
||||||
return mangled;
|
return mangled;
|
||||||
@@ -238,11 +222,9 @@ function mangle_properties(ast, options) {
|
|||||||
if (node instanceof AST_Sequence) {
|
if (node instanceof AST_Sequence) {
|
||||||
var last = node.expressions.length - 1;
|
var last = node.expressions.length - 1;
|
||||||
node.expressions[last] = mangleStrings(node.expressions[last]);
|
node.expressions[last] = mangleStrings(node.expressions[last]);
|
||||||
}
|
} else if (node instanceof AST_String) {
|
||||||
else if (node instanceof AST_String) {
|
|
||||||
node.value = mangle(node.value);
|
node.value = mangle(node.value);
|
||||||
}
|
} else if (node instanceof AST_Conditional) {
|
||||||
else if (node instanceof AST_Conditional) {
|
|
||||||
node.consequent = mangleStrings(node.consequent);
|
node.consequent = mangleStrings(node.consequent);
|
||||||
node.alternative = mangleStrings(node.alternative);
|
node.alternative = mangleStrings(node.alternative);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,7 +136,8 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
// AST_Defun node before getting to its AST_Symbol.
|
// AST_Defun node before getting to its AST_Symbol.
|
||||||
(node.scope = defun.parent_scope.resolve()).def_function(node, defun);
|
(node.scope = defun.parent_scope.resolve()).def_function(node, defun);
|
||||||
} else if (node instanceof AST_SymbolLambda) {
|
} else if (node instanceof AST_SymbolLambda) {
|
||||||
defun.def_function(node, node.name == "arguments" ? undefined : defun);
|
var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
|
||||||
|
if (options.ie8) def.defun = defun.parent_scope.resolve();
|
||||||
} else if (node instanceof AST_SymbolVar) {
|
} else if (node instanceof AST_SymbolVar) {
|
||||||
defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
|
defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
|
||||||
if (defun !== scope) {
|
if (defun !== scope) {
|
||||||
|
|||||||
@@ -458,8 +458,8 @@ issue_2976_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function f() {
|
console.log(function f() {
|
||||||
var o;
|
var n;
|
||||||
return o === f ? "FAIL" : "PASS";
|
return n === f ? "FAIL" : "PASS";
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
@@ -477,9 +477,9 @@ issue_2976_3: {
|
|||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function r() {
|
console.log(function o() {
|
||||||
var o;
|
var n;
|
||||||
return o === r ? "FAIL" : "PASS";
|
return n === o ? "FAIL" : "PASS";
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
@@ -772,17 +772,17 @@ issue_3215_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function foo() {
|
console.log(function foo() {
|
||||||
var r = function r(o) {
|
var o = function o(n) {
|
||||||
return "PASS";
|
return "PASS";
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
"moo";
|
"moo";
|
||||||
} catch (o) {
|
} catch (n) {
|
||||||
r = function r(o) {
|
o = function o(n) {
|
||||||
return "FAIL";
|
return "FAIL";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return r;
|
return o;
|
||||||
}()());
|
}()());
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
@@ -846,17 +846,17 @@ issue_3215_4: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function foo() {
|
console.log(function foo() {
|
||||||
var r = function r(o) {
|
var o = function o(n) {
|
||||||
return "FAIL";
|
return "FAIL";
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
moo;
|
moo;
|
||||||
} catch (o) {
|
} catch (n) {
|
||||||
r = function r(o) {
|
o = function o(n) {
|
||||||
return "PASS";
|
return "PASS";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return r;
|
return o;
|
||||||
}()());
|
}()());
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
|
|||||||
@@ -534,3 +534,80 @@ function_catch_catch_ie8: {
|
|||||||
"undefined",
|
"undefined",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function_do_catch_ie8: {
|
||||||
|
rename = true
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1, b = 1, c = 0;
|
||||||
|
function d(e) {
|
||||||
|
var f, g, h, i;
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
var j = function q(){}();
|
||||||
|
} catch (r) {
|
||||||
|
--a && w("ddddddddeeeeeeegggggggggiiiiilllllllnnnnntuuuuuuuuyyyyyyy");
|
||||||
|
var k, l, m, n, o;
|
||||||
|
--m;
|
||||||
|
--n;
|
||||||
|
--o;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
i[1];
|
||||||
|
} catch (s) {
|
||||||
|
var p;
|
||||||
|
switch (function t() {
|
||||||
|
c++;
|
||||||
|
}()) {
|
||||||
|
case j + --p:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (u) {}
|
||||||
|
} while (--i);
|
||||||
|
b--;
|
||||||
|
}
|
||||||
|
d();
|
||||||
|
console.log(b, c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var t = 1, u = 1, y = 0;
|
||||||
|
function c(c) {
|
||||||
|
var d;
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
var e = void 0;
|
||||||
|
} catch (i) {
|
||||||
|
--t && w("ddddddddeeeeeeegggggggggiiiiilllllllnnnnntuuuuuuuuyyyyyyy");
|
||||||
|
0;
|
||||||
|
0;
|
||||||
|
0;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
d[1];
|
||||||
|
} catch (l) {
|
||||||
|
var g;
|
||||||
|
switch(function x() {
|
||||||
|
y++;
|
||||||
|
}()) {
|
||||||
|
case e + --g:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (n) {}
|
||||||
|
} while (--d);
|
||||||
|
u--;
|
||||||
|
}
|
||||||
|
c();
|
||||||
|
console.log(u, y);
|
||||||
|
}
|
||||||
|
expect_stdout: "0 1"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user