@@ -324,7 +324,6 @@ merge(Compressor.prototype, {
|
||||
|| value.is_constant_expression(node.scope);
|
||||
} else {
|
||||
d.single_use = d.scope === node.scope
|
||||
&& loop_ids[d.id] === in_loop
|
||||
&& value.is_constant_expression();
|
||||
}
|
||||
} else {
|
||||
@@ -384,6 +383,7 @@ merge(Compressor.prototype, {
|
||||
d.fixed = false;
|
||||
} else {
|
||||
d.fixed = node;
|
||||
loop_ids[d.id] = in_loop;
|
||||
mark(d, true);
|
||||
if (ref_once(d)) {
|
||||
d.single_use = d.scope === d.references[0].scope
|
||||
@@ -577,7 +577,11 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
|
||||
function ref_once(def) {
|
||||
return unused && !def.scope.uses_eval && !def.scope.uses_with && def.references.length == 1;
|
||||
return unused
|
||||
&& !def.scope.uses_eval
|
||||
&& !def.scope.uses_with
|
||||
&& def.references.length == 1
|
||||
&& loop_ids[def.id] === in_loop;
|
||||
}
|
||||
|
||||
function is_immutable(value) {
|
||||
@@ -623,7 +627,8 @@ merge(Compressor.prototype, {
|
||||
|
||||
function mark_escaped(d, node, value, level) {
|
||||
var parent = tw.parent(level);
|
||||
if (value instanceof AST_Constant || value instanceof AST_Function) return;
|
||||
if (value instanceof AST_Constant) return;
|
||||
if (level > 0 && value instanceof AST_Function) return;
|
||||
if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right
|
||||
|| parent instanceof AST_Call && node !== parent.expression
|
||||
|| parent instanceof AST_Return && node === parent.value && node.scope !== d.scope
|
||||
@@ -4216,6 +4221,17 @@ merge(Compressor.prototype, {
|
||||
return self;
|
||||
});
|
||||
|
||||
function recursive_ref(compressor, def) {
|
||||
var node;
|
||||
for (var i = 0; node = compressor.parent(i); i++) {
|
||||
if (node instanceof AST_Lambda) {
|
||||
var name = node.name;
|
||||
if (name && name.definition() === def) break;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
OPT(AST_SymbolRef, function(self, compressor){
|
||||
var def = self.resolve_defines(compressor);
|
||||
if (def) {
|
||||
@@ -4241,21 +4257,14 @@ merge(Compressor.prototype, {
|
||||
if (fixed instanceof AST_Defun) {
|
||||
d.fixed = fixed = make_node(AST_Function, fixed, fixed);
|
||||
}
|
||||
if (fixed && d.single_use) {
|
||||
var recurse;
|
||||
if (fixed instanceof AST_Function) {
|
||||
for (var i = 0; recurse = compressor.parent(i); i++) {
|
||||
if (recurse instanceof AST_Lambda) {
|
||||
var name = recurse.name;
|
||||
if (name && name.definition() === d) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!recurse) {
|
||||
if (fixed
|
||||
&& d.single_use
|
||||
&& !(fixed instanceof AST_Function
|
||||
&& (d.escaped && d.scope !== self.scope
|
||||
|| recursive_ref(compressor, d)))) {
|
||||
var value = fixed.optimize(compressor);
|
||||
return value === fixed ? fixed.clone(true) : value;
|
||||
}
|
||||
}
|
||||
if (fixed && d.should_replace === undefined) {
|
||||
var init;
|
||||
if (fixed instanceof AST_This) {
|
||||
|
||||
@@ -1123,11 +1123,12 @@ toplevel_on_loops_1: {
|
||||
while (x);
|
||||
}
|
||||
expect: {
|
||||
function bar() {
|
||||
console.log("bar:", --x);
|
||||
}
|
||||
var x = 3;
|
||||
do
|
||||
(function() {
|
||||
console.log("bar:", --x);
|
||||
})();
|
||||
bar();
|
||||
while (x);
|
||||
}
|
||||
expect_stdout: true
|
||||
@@ -1180,9 +1181,10 @@ toplevel_on_loops_2: {
|
||||
while (x);
|
||||
}
|
||||
expect: {
|
||||
for (;;) (function() {
|
||||
function bar() {
|
||||
console.log("bar:");
|
||||
})();
|
||||
}
|
||||
for (;;) bar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3845,3 +3847,145 @@ recursive_inlining_5: {
|
||||
"foo 0",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2450_1: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {}
|
||||
function g() {
|
||||
return f;
|
||||
}
|
||||
console.log(g() === g());
|
||||
}
|
||||
expect: {
|
||||
function f() {}
|
||||
function g() {
|
||||
return f;
|
||||
}
|
||||
console.log(g() === g());
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
issue_2450_2: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function g() {
|
||||
function f() {}
|
||||
return f;
|
||||
}
|
||||
console.log(g() === g());
|
||||
}
|
||||
expect: {
|
||||
function g() {
|
||||
return function() {};
|
||||
}
|
||||
console.log(g() === g());
|
||||
}
|
||||
expect_stdout: "false"
|
||||
}
|
||||
|
||||
issue_2450_3: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var x = (function() {
|
||||
function test() {
|
||||
return "foo";
|
||||
}
|
||||
return function b() {
|
||||
return [1, test];
|
||||
}
|
||||
})();
|
||||
console.log(x()[1] === x()[1]);
|
||||
}
|
||||
expect: {
|
||||
var x = (function() {
|
||||
function test() {
|
||||
return "foo";
|
||||
}
|
||||
return function() {
|
||||
return [1, test];
|
||||
}
|
||||
})();
|
||||
console.log(x()[1] === x()[1]);
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
issue_2450_4: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
function f(b) {
|
||||
console.log(a === b);
|
||||
a = b;
|
||||
}
|
||||
function g() {}
|
||||
for (var i = 3; --i >= 0;)
|
||||
f(g);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
function f(b) {
|
||||
console.log(a === b);
|
||||
a = b;
|
||||
}
|
||||
function g() {}
|
||||
for (var i = 3; --i >= 0;)
|
||||
f(g);
|
||||
}
|
||||
expect_stdout: [
|
||||
"false",
|
||||
"true",
|
||||
"true",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2450_5: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
function f(b) {
|
||||
console.log(a === b);
|
||||
a = b;
|
||||
}
|
||||
function g() {}
|
||||
[1, 2, 3].forEach(function() {
|
||||
f(g);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
function g() {}
|
||||
[1, 2, 3].forEach(function() {
|
||||
(function(b) {
|
||||
console.log(a === b);
|
||||
a = b;
|
||||
})(g);
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"false",
|
||||
"true",
|
||||
"true",
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user