aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-04-05 03:42:23 +0100
committerGitHub <noreply@github.com>2020-04-05 10:42:23 +0800
commit1b07f640573494d1f8625f8926868caeaeaaaa9e (patch)
treeb2f77fdafe1a05439bad270a9b561eb437db5916
parent80d9c44b22fd8d479d0cf86b1037568ea3f94cd7 (diff)
downloadtracifyjs-1b07f640573494d1f8625f8926868caeaeaaaa9e.tar.gz
tracifyjs-1b07f640573494d1f8625f8926868caeaeaaaa9e.zip
enhance `inline` (#3760)
-rw-r--r--lib/compress.js27
-rw-r--r--test/compress/functions.js130
-rw-r--r--test/input/rename/input.js2
-rw-r--r--test/mocha/cli.js8
-rw-r--r--test/ufuzz/index.js1
5 files changed, 151 insertions, 17 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 72690fef..f03e0eef 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -5813,12 +5813,24 @@ merge(Compressor.prototype, {
var is_func = fn instanceof AST_Lambda;
var stat = is_func && fn.first_statement();
var can_inline = compressor.option("inline") && !self.is_expr_pure(compressor);
- if (exp === fn && can_inline && stat instanceof AST_Return) {
+ if (can_inline && stat instanceof AST_Return) {
var value = stat.value;
- if (!value || value.is_constant_expression()) {
+ if (exp === fn && (!value || value.is_constant_expression())) {
var args = self.args.concat(value || make_node(AST_Undefined, self));
return make_sequence(self, args).optimize(compressor);
}
+ var funarg, pos;
+ if (value instanceof AST_SymbolRef
+ && (funarg = resolve_funarg(value.definition().orig))
+ && (pos = fn.argnames.indexOf(funarg)) >= 0
+ && (pos >= self.args.length - 1 || all(self.args.slice(pos), function(funarg) {
+ return !funarg.has_side_effects(compressor);
+ }))) {
+ var args = self.args.slice();
+ args.push(args.splice(pos, 1)[0] || make_node(AST_Undefined, self));
+ var node = make_sequence(self, args).optimize(compressor);
+ return maintain_this_binding(compressor, compressor.parent(), compressor.self(), node);
+ }
}
if (is_func) {
var def, value, scope, in_loop, level = -1;
@@ -5837,7 +5849,8 @@ merge(Compressor.prototype, {
&& can_inject_symbols()) {
fn._squeezed = true;
if (exp !== fn) fn.parent_scope = exp.scope;
- return make_sequence(self, flatten_fn()).optimize(compressor);
+ var node = make_sequence(self, flatten_fn()).optimize(compressor);
+ return maintain_this_binding(compressor, compressor.parent(), compressor.self(), node);
}
if (compressor.option("side_effects")
&& all(fn.body, is_empty)
@@ -5864,6 +5877,14 @@ merge(Compressor.prototype, {
}
return try_evaluate(compressor, self);
+ function resolve_funarg(orig) {
+ var funarg;
+ for (var i = 0; orig[i] instanceof AST_SymbolFunarg; i++) {
+ funarg = orig[i];
+ }
+ return funarg;
+ }
+
function return_value(stat) {
if (!stat) return make_node(AST_Undefined, self);
if (stat instanceof AST_Return) {
diff --git a/test/compress/functions.js b/test/compress/functions.js
index 0cf01792..b1a44ffa 100644
--- a/test/compress/functions.js
+++ b/test/compress/functions.js
@@ -342,11 +342,7 @@ inner_ref: {
}(2));
}
expect: {
- console.log(function(a) {
- return a;
- }(1), function(a) {
- return a;
- }());
+ console.log(1, void 0);
}
expect_stdout: "1 undefined"
}
@@ -1577,7 +1573,23 @@ issue_2663_3: {
]
}
-duplicate_argnames: {
+duplicate_argnames_1: {
+ options = {
+ inline: true,
+ side_effects: true,
+ }
+ input: {
+ console.log(function(a, a, a) {
+ return a;
+ }("FAIL", 42, "PASS"));
+ }
+ expect: {
+ console.log("PASS");
+ }
+ expect_stdout: "PASS"
+}
+
+duplicate_argnames_2: {
options = {
inline: true,
reduce_vars: true,
@@ -1857,10 +1869,9 @@ use_before_init_in_loop: {
expect_stdout: "PASS"
}
-duplicate_arg_var: {
+duplicate_arg_var_1: {
options = {
inline: true,
- toplevel: true,
}
input: {
console.log(function(b) {
@@ -1869,7 +1880,24 @@ duplicate_arg_var: {
}("PASS"));
}
expect: {
- console.log((b = "PASS", b));
+ console.log("PASS");
+ }
+ expect_stdout: "PASS"
+}
+
+duplicate_arg_var_2: {
+ options = {
+ inline: true,
+ toplevel: true,
+ }
+ input: {
+ console.log(function(b) {
+ return b + "SS";
+ var b;
+ }("PA"));
+ }
+ expect: {
+ console.log((b = "PA", b + "SS"));
var b;
}
expect_stdout: "PASS"
@@ -3785,3 +3813,87 @@ issue_3679_3: {
}
expect_stdout: "PASS"
}
+
+preceding_side_effects: {
+ options = {
+ inline: true,
+ }
+ input: {
+ console.log(function(a, b, c) {
+ return b;
+ }(console, "PASS", 42));
+ }
+ expect: {
+ console.log((console, 42, "PASS"));
+ }
+ expect_stdout: "PASS"
+}
+
+trailing_side_effects: {
+ options = {
+ inline: true,
+ }
+ input: {
+ console.log(function(a, b, c) {
+ return b;
+ }(42, "PASS", console));
+ }
+ expect: {
+ console.log(function(a, b, c) {
+ return b;
+ }(42, "PASS", console));
+ }
+ expect_stdout: "PASS"
+}
+
+preserve_binding_1: {
+ options = {
+ inline: true,
+ }
+ input: {
+ var o = {
+ f: function() {
+ return this === o ? "FAIL" : "PASS";
+ },
+ };
+ console.log(function(a) {
+ return a;
+ }(o.f)());
+ }
+ expect: {
+ var o = {
+ f: function() {
+ return this === o ? "FAIL" : "PASS";
+ },
+ };
+ console.log((0, o.f)());
+ }
+ expect_stdout: "PASS"
+}
+
+preserve_binding_2: {
+ options = {
+ collapse_vars: true,
+ inline: true,
+ unused: true,
+ }
+ input: {
+ var o = {
+ f: function() {
+ return this === o ? "FAIL" : "PASS";
+ },
+ };
+ console.log(function(a) {
+ return a;
+ }(o.f)());
+ }
+ expect: {
+ var o = {
+ f: function() {
+ return this === o ? "FAIL" : "PASS";
+ },
+ };
+ console.log((0, o.f)());
+ }
+ expect_stdout: "PASS"
+}
diff --git a/test/input/rename/input.js b/test/input/rename/input.js
index ef6daed2..3008433a 100644
--- a/test/input/rename/input.js
+++ b/test/input/rename/input.js
@@ -1,6 +1,6 @@
function f(x) {
return g(x);
function g(x) {
- return x;
+ return x + 1;
}
}
diff --git a/test/mocha/cli.js b/test/mocha/cli.js
index 0347797e..2e68fbf3 100644
--- a/test/mocha/cli.js
+++ b/test/mocha/cli.js
@@ -674,7 +674,7 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/rename/input.js --rename";
exec(command, function(err, stdout, stderr) {
if (err) throw err;
- assert.strictEqual(stdout, "function f(a){return b(a);function b(c){return c}}\n");
+ assert.strictEqual(stdout, "function f(a){return b(a);function b(c){return c+1}}\n");
done();
});
});
@@ -682,7 +682,7 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2 --no-rename";
exec(command, function(err, stdout, stderr) {
if (err) throw err;
- assert.strictEqual(stdout, "function f(n){return function(n){return n}(n)}\n");
+ assert.strictEqual(stdout, "function f(n){return function(n){return n+1}(n)}\n");
done();
});
});
@@ -690,7 +690,7 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2";
exec(command, function(err, stdout, stderr) {
if (err) throw err;
- assert.strictEqual(stdout, "function f(n){return n}\n");
+ assert.strictEqual(stdout, "function f(n){return n+1}\n");
done();
});
});
@@ -698,7 +698,7 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/rename/input.js -c passes=2";
exec(command, function(err, stdout, stderr) {
if (err) throw err;
- assert.strictEqual(stdout, "function f(x){return function(x){return x}(x)}\n");
+ assert.strictEqual(stdout, "function f(x){return function(x){return x+1}(x)}\n");
done();
});
});
diff --git a/test/ufuzz/index.js b/test/ufuzz/index.js
index f1fce6a1..76a782ef 100644
--- a/test/ufuzz/index.js
+++ b/test/ufuzz/index.js
@@ -704,6 +704,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
break;
}
VAR_NAMES.length = nameLenBefore;
+ if (canThrow && rng(8) == 0 && !/^new /.test(s[0])) s[s.length - 1] += "()";
return filterDirective(s).join("\n");
case p++:
case p++: