diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2017-12-18 16:23:39 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-12-18 16:23:39 +0800 |
commit | 8ddcbc39e617a3ce53a340303fd9ef3226ee0065 (patch) | |
tree | dfbd32b8dbd6f2471ff164256c9af084b0e60c9e | |
parent | 0b0eac1d5dc6e1cc1e9bf3682871cafdda59066d (diff) | |
download | tracifyjs-8ddcbc39e617a3ce53a340303fd9ef3226ee0065.tar.gz tracifyjs-8ddcbc39e617a3ce53a340303fd9ef3226ee0065.zip |
compress `apply()` & `call()` of `function` (#2613)
- `fn.apply(a, [ ... ])` => `fn.call(a, ...)`
- `fn.call(a, ... )` => `a, fn(...)`
where `fn` can be `function` literal or symbol reference linked through `reduce_vars`
-rw-r--r-- | lib/compress.js | 28 | ||||
-rw-r--r-- | test/compress/functions.js | 126 |
2 files changed, 154 insertions, 0 deletions
diff --git a/lib/compress.js b/lib/compress.js index 735b4d2d..af1195d4 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -3857,6 +3857,34 @@ merge(Compressor.prototype, { } } break; + case "apply": + if (self.args.length == 2 && self.args[1] instanceof AST_Array) { + var args = self.args[1].elements.slice(); + args.unshift(self.args[0]); + return make_node(AST_Call, self, { + expression: make_node(AST_Dot, exp, { + expression: exp.expression, + property: "call" + }), + args: args + }).optimize(compressor); + } + break; + case "call": + var func = exp.expression; + if (func instanceof AST_SymbolRef) { + func = func.fixed_value(); + } + if (func instanceof AST_Function && !func.contains_this()) { + return make_sequence(this, [ + self.args[0], + make_node(AST_Call, self, { + expression: exp.expression, + args: self.args.slice(1) + }) + ]).optimize(compressor); + } + break; } } if (compressor.option("unsafe_Func") diff --git a/test/compress/functions.js b/test/compress/functions.js index 5f7fba6b..23ed22df 100644 --- a/test/compress/functions.js +++ b/test/compress/functions.js @@ -923,3 +923,129 @@ issue_2604_2: { } expect_stdout: "PASS" } + +unsafe_apply_1: { + options = { + inline: true, + passes: 2, + reduce_vars: true, + side_effects: true, + unsafe: true, + unused: true, + } + input: { + (function(a, b) { + console.log(a, b); + }).apply("foo", [ "bar" ]); + (function(a, b) { + console.log(this, a, b); + }).apply("foo", [ "bar" ]); + (function(a, b) { + console.log(a, b); + }).apply("foo", [ "bar" ], "baz"); + } + expect: { + console.log("bar", void 0); + (function(a, b) { + console.log(this, a, b); + }).call("foo", "bar"); + (function(a, b) { + console.log(a, b); + }).apply("foo", [ "bar" ], "baz"); + } + expect_stdout: true +} + +unsafe_apply_2: { + options = { + reduce_vars: true, + side_effects: true, + toplevel: true, + unsafe: true, + } + input: { + function foo() { + console.log(a, b); + } + var bar = function(a, b) { + console.log(this, a, b); + } + (function() { + foo.apply("foo", [ "bar" ]); + bar.apply("foo", [ "bar" ]); + })(); + } + expect: { + function foo() { + console.log(a, b); + } + var bar = function(a, b) { + console.log(this, a, b); + } + (function() { + foo("bar"); + bar.call("foo", "bar"); + })(); + } + expect_stdout: true +} + +unsafe_call_1: { + options = { + inline: true, + passes: 2, + reduce_vars: true, + side_effects: true, + unsafe: true, + unused: true, + } + input: { + (function(a, b) { + console.log(a, b); + }).call("foo", "bar"); + (function(a, b) { + console.log(this, a, b); + }).call("foo", "bar"); + } + expect: { + console.log("bar", void 0); + (function(a, b) { + console.log(this, a, b); + }).call("foo", "bar"); + } + expect_stdout: true +} + +unsafe_call_2: { + options = { + reduce_vars: true, + side_effects: true, + toplevel: true, + unsafe: true, + } + input: { + function foo() { + console.log(a, b); + } + var bar = function(a, b) { + console.log(this, a, b); + } + (function() { + foo.call("foo", "bar"); + bar.call("foo", "bar"); + })(); + } + expect: { + function foo() { + console.log(a, b); + } + var bar = function(a, b) { + console.log(this, a, b); + } + (function() { + foo("bar"); + bar.call("foo", "bar"); + })(); + } + expect_stdout: true +} |