From 182a47bfb1d49a99a561253edc05e70a6dc5b8e8 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Fri, 15 Sep 2017 12:46:48 +0800 Subject: [PATCH 1/4] improve source mapping (#2312) fixes #2310 --- lib/output.js | 2 +- test/input/issue-2310/input.js | 10 ++++++++++ test/mocha/cli.js | 19 +++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 test/input/issue-2310/input.js diff --git a/lib/output.js b/lib/output.js index 6f7b18db..315bfafd 100644 --- a/lib/output.js +++ b/lib/output.js @@ -1109,7 +1109,7 @@ function OutputStream(options) { self.expression.print(output); if (self instanceof AST_New && !need_constructor_parens(self, output)) return; - if (self.expression instanceof AST_Lambda) { + if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) { output.add_mapping(self.start); } output.with_parens(function(){ diff --git a/test/input/issue-2310/input.js b/test/input/issue-2310/input.js new file mode 100644 index 00000000..ea7c1f33 --- /dev/null +++ b/test/input/issue-2310/input.js @@ -0,0 +1,10 @@ +function foo() { + return function() { + console.log("PASS"); + }; +} + +(function() { + var f = foo(); + f(); +})(); diff --git a/test/mocha/cli.js b/test/mocha/cli.js index 1d847dc9..85b2e8c9 100644 --- a/test/mocha/cli.js +++ b/test/mocha/cli.js @@ -573,6 +573,25 @@ describe("bin/uglifyjs", function () { return JSON.stringify(map).replace(/"/g, '\\"'); } }); + it("Should include function calls in source map", function(done) { + var command = [ + uglifyjscmd, + "test/input/issue-2310/input.js", + "-c", + "--source-map", "url=inline", + ].join(" "); + + exec(command, function(err, stdout, stderr) { + if (err) throw err; + + assert.strictEqual(stdout, [ + 'function foo(){return function(){console.log("PASS")}}foo()();', + "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMjMxMC9pbnB1dC5qcyJdLCJuYW1lcyI6WyJmb28iLCJjb25zb2xlIiwibG9nIiwiZiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsTUFDTCxPQUFPLFdBQ0hDLFFBQVFDLElBQUksU0FLUkYsS0FDUkcifQ==", + "" + ].join("\n")); + done(); + }); + }); it("Should dump AST as JSON", function(done) { var command = uglifyjscmd + " test/input/global_defs/simple.js -mco ast"; exec(command, function (err, stdout) { From 4f0953f7e9bc4d1bb704369e0e20771f7c19caaf Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sat, 16 Sep 2017 11:45:19 +0800 Subject: [PATCH 2/4] handle LHS side-effects on `cascade` & `collapse_vars` (#2314) fixes #2313 --- lib/compress.js | 5 +- test/compress/collapse_vars.js | 67 +++++++++++ test/compress/pure_getters.js | 214 +++++++++++++++++++++++++++++++++ test/compress/sequences.js | 41 +++++++ 4 files changed, 325 insertions(+), 2 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index da68dbc7..3164c5a0 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -561,6 +561,7 @@ merge(Compressor.prototype, { }); function is_lhs_read_only(lhs) { + if (lhs instanceof AST_This) return true; if (lhs instanceof AST_SymbolRef) return lhs.definition().orig[0] instanceof AST_SymbolLambda; if (lhs instanceof AST_PropAccess) { lhs = lhs.expression; @@ -745,7 +746,7 @@ merge(Compressor.prototype, { while (candidates.length > 0) { var candidate = candidates.pop(); var lhs = get_lhs(candidate); - if (!lhs || is_lhs_read_only(lhs)) continue; + if (!lhs || is_lhs_read_only(lhs) || lhs.has_side_effects(compressor)) continue; // Locate symbols which may execute code outside of scanning range var lvalues = get_lvalues(candidate); if (lhs instanceof AST_SymbolRef) lvalues[lhs.name] = false; @@ -3496,7 +3497,7 @@ merge(Compressor.prototype, { && (left.operator == "++" || left.operator == "--")) { left = left.expression; } else left = null; - if (!left || is_lhs_read_only(left)) { + if (!left || is_lhs_read_only(left) || left.has_side_effects(compressor)) { expressions[++i] = cdr; continue; } diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js index 72123d4b..5e7e982e 100644 --- a/test/compress/collapse_vars.js +++ b/test/compress/collapse_vars.js @@ -2384,3 +2384,70 @@ issue_2298: { } expect_stdout: "PASS" } + +issue_2313_1: { + options = { + collapse_vars: true, + conditionals: true, + } + input: { + var a = 0, b = 0; + var foo = { + get c() { + a++; + return 42; + }, + set c(c) { + b++; + }, + d: function() { + this.c++; + if (this.c) console.log(a, b); + } + } + foo.d(); + } + expect: { + var a = 0, b = 0; + var foo = { + get c() { + a++; + return 42; + }, + set c(c) { + b++; + }, + d: function() { + this.c++; + this.c && console.log(a, b); + } + } + foo.d(); + } + expect_stdout: "2 1" +} + +issue_2313_2: { + options = { + collapse_vars: true, + } + input: { + var c = 0; + !function a() { + a && c++; + var a = 0; + a && c++; + }(); + console.log(c); + } + expect: { + var c = 0; + !function a() { + a && c++; + var a = 0; + a && c++; + }(); + console.log(c); + } + expect_stdout: "0" +} diff --git a/test/compress/pure_getters.js b/test/compress/pure_getters.js index dc56e19d..22441d98 100644 --- a/test/compress/pure_getters.js +++ b/test/compress/pure_getters.js @@ -385,3 +385,217 @@ set_mutable_2: { } expect_stdout: "PASS" } + +issue_2313_1: { + options = { + cascade: true, + conditionals: true, + pure_getters: "strict", + sequences: true, + side_effects: true, + } + input: { + function x() { + console.log(1); + return { + y: function() { + console.log(2); + return { + z: 0 + }; + } + }; + } + x().y().z++; + if (x().y().z) { + console.log(3); + } + } + expect: { + function x() { + return console.log(1), { + y: function() { + return console.log(2), { + z: 0 + }; + } + }; + } + x().y().z++, + x().y().z && console.log(3); + } + expect_stdout: [ + "1", + "2", + "1", + "2", + ] +} + +issue_2313_2: { + options = { + cascade: true, + conditionals: true, + pure_getters: true, + sequences: true, + side_effects: true, + } + input: { + function x() { + console.log(1); + return { + y: function() { + console.log(2); + return { + z: 0 + }; + } + }; + } + x().y().z++; + if (x().y().z) { + console.log(3); + } + } + expect: { + function x() { + return console.log(1), { + y: function() { + return console.log(2), { + z: 0 + }; + } + }; + } + x().y().z++, + x().y().z && console.log(3); + } + expect_stdout: [ + "1", + "2", + "1", + "2", + ] +} + +issue_2313_3: { + options = { + collapse_vars: true, + conditionals: true, + pure_getters: "strict", + } + input: { + function x() { + console.log(1); + return { + y: function() { + console.log(2); + return { + z: 0 + }; + } + }; + } + x().y().z++; + if (x().y().z) { + console.log(3); + } + } + expect: { + function x() { + console.log(1); + return { + y: function() { + console.log(2); + return { + z: 0 + }; + } + }; + } + x().y().z++; + x().y().z && console.log(3); + } + expect_stdout: [ + "1", + "2", + "1", + "2", + ] +} + +issue_2313_4: { + options = { + collapse_vars: true, + conditionals: true, + pure_getters: true, + } + input: { + function x() { + console.log(1); + return { + y: function() { + console.log(2); + return { + z: 0 + }; + } + }; + } + x().y().z++; + if (x().y().z) { + console.log(3); + } + } + expect: { + function x() { + console.log(1); + return { + y: function() { + console.log(2); + return { + z: 0 + }; + } + }; + } + x().y().z++; + x().y().z && console.log(3); + } + expect_stdout: [ + "1", + "2", + "1", + "2", + ] +} + +issue_2313_5: { + options = { + pure_getters: "strict", + side_effects: true, + } + input: { + x().y++; + x().y; + } + expect: { + x().y++; + x().y; + } +} + +issue_2313_6: { + options = { + pure_getters: true, + side_effects: true, + } + input: { + x().y++; + x().y; + } + expect: { + x().y++; + x(); + } +} diff --git a/test/compress/sequences.js b/test/compress/sequences.js index 5ce24ac0..def62781 100644 --- a/test/compress/sequences.js +++ b/test/compress/sequences.js @@ -739,3 +739,44 @@ issue_2062: { } expect_stdout: "1" } + +issue_2313: { + options = { + cascade: true, + sequences: true, + side_effects: true, + } + input: { + var a = 0, b = 0; + var foo = { + get c() { + a++; + return 42; + }, + set c(c) { + b++; + }, + d: function() { + this.c++; + if (this.c) console.log(a, b); + } + } + foo.d(); + } + expect: { + var a = 0, b = 0; + var foo = { + get c() { + return a++, 42; + }, + set c(c) { + b++; + }, + d: function() { + if (this.c++, this.c) console.log(a, b); + } + } + foo.d(); + } + expect_stdout: "2 1" +} From aceb0af36b8c89ae76b18c63a32b600156e4766e Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sun, 17 Sep 2017 04:36:27 +0800 Subject: [PATCH 3/4] v3.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 15ef15f0..2b298d3b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "homepage": "http://lisperator.net/uglifyjs", "author": "Mihai Bazon (http://lisperator.net/)", "license": "BSD-2-Clause", - "version": "3.1.0", + "version": "3.1.1", "engines": { "node": ">=0.8.0" }, From 3b0b4d6abf075845ce3a7cdb4762848e4706a1d1 Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Sun, 17 Sep 2017 05:00:58 +0800 Subject: [PATCH 4/4] handle `AST_Super` in `collapse_vars` & `side_effects` --- lib/compress.js | 3 +++ test/compress/pure_getters.js | 48 +++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/lib/compress.js b/lib/compress.js index 4bf3006d..8eb20048 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -579,6 +579,7 @@ merge(Compressor.prototype, { } function is_lhs_read_only(lhs) { + if (lhs instanceof AST_Super) return true; if (lhs instanceof AST_This) return true; if (lhs instanceof AST_SymbolRef) return lhs.definition().orig[0] instanceof AST_SymbolLambda; if (lhs instanceof AST_PropAccess) { @@ -2109,6 +2110,7 @@ merge(Compressor.prototype, { def(AST_EmptyStatement, return_false); def(AST_Constant, return_false); + def(AST_Super, return_false); def(AST_This, return_false); def(AST_Call, function(compressor){ @@ -2787,6 +2789,7 @@ merge(Compressor.prototype, { def(AST_Node, return_this); def(AST_Constant, return_null); + def(AST_Super, return_null); def(AST_This, return_null); def(AST_Call, function(compressor, first_in_statement){ if (!this.is_expr_pure(compressor)) { diff --git a/test/compress/pure_getters.js b/test/compress/pure_getters.js index b6d3880b..cef66309 100644 --- a/test/compress/pure_getters.js +++ b/test/compress/pure_getters.js @@ -672,3 +672,51 @@ issue_2313_6: { x(); } } + +issue_2313_7: { + options = { + collapse_vars: true, + conditionals: true, + pure_getters: true, + } + input: { + var a = 0, b = 0; + class foo { + get c() { + a++; + return 42; + } + set c(c) { + b++; + } + } + class bar extends foo { + d() { + super.c++; + if (super.c) console.log(a, b); + } + } + new bar().d(); + } + expect: { + var a = 0, b = 0; + class foo { + get c() { + a++; + return 42; + } + set c(c) { + b++; + } + } + class bar extends foo { + d() { + super.c++; + super.c && console.log(a, b); + } + } + new bar().d(); + } + expect_stdout: "2 1" + node_version: ">=6" +}