From f01f580d6c2312ba556a37144f6fef227bd89f77 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Fri, 14 Feb 2020 02:47:20 +0000 Subject: improve `--reduce-test` (#3719) - cover missing cases when eliminating unreferenced labels - format multi-line outputs correctly --- test/input/reduce/input.js | 18 --------- test/input/reduce/label.js | 9 +++++ test/input/reduce/label.reduced.js | 16 ++++++++ test/input/reduce/output.js | 15 ------- test/input/reduce/unsafe_math.js | 18 +++++++++ test/input/reduce/unsafe_math.reduced.js | 22 +++++++++++ test/mocha/reduce.js | 67 +++++++++++++++++++++++++++++--- test/reduce.js | 31 ++++++++------- 8 files changed, 144 insertions(+), 52 deletions(-) delete mode 100644 test/input/reduce/input.js create mode 100644 test/input/reduce/label.js create mode 100644 test/input/reduce/label.reduced.js delete mode 100644 test/input/reduce/output.js create mode 100644 test/input/reduce/unsafe_math.js create mode 100644 test/input/reduce/unsafe_math.reduced.js diff --git a/test/input/reduce/input.js b/test/input/reduce/input.js deleted file mode 100644 index b99ffd0e..00000000 --- a/test/input/reduce/input.js +++ /dev/null @@ -1,18 +0,0 @@ -var _calls_ = 10, a = 100, b = 10, c = 0; - -function f0(b_1, a, undefined_2) { - a++ + ++b; - { - var expr2 = (b + 1 - .1 - .1 - .1 || a || 3).toString(); - L20778: for (var key2 in expr2) { - (c = c + 1) + [ --b + b_1, typeof f0 == "function" && --_calls_ >= 0 && f0(--b + typeof (undefined_2 = 1 === 1 ? a : b), --b + { - c: (c = c + 1) + null - }, a++ + (typeof f0 == "function" && --_calls_ >= 0 && f0(typeof (c = 1 + c, 3 / "a" * ("c" >>> 23..toString()) >= (b_1 && (b_1[(c = c + 1) + a--] = (- -0, - true + {})))), 3, 25))), 1 === 1 ? a : b ]; - } - } -} - -var a_1 = f0([ , 0 ].length === 2); - -console.log(null, a, b, c, Infinity, NaN, undefined); diff --git a/test/input/reduce/label.js b/test/input/reduce/label.js new file mode 100644 index 00000000..aee57a40 --- /dev/null +++ b/test/input/reduce/label.js @@ -0,0 +1,9 @@ +var o = this; + +for (var k in o) L17060: { + a++; +} + +var a; + +console.log(k); diff --git a/test/input/reduce/label.reduced.js b/test/input/reduce/label.reduced.js new file mode 100644 index 00000000..faaa206d --- /dev/null +++ b/test/input/reduce/label.reduced.js @@ -0,0 +1,16 @@ +var o = this; + +for (var k in o) { + 0; +} + +var a; + +console.log(k); +// output: a +// +// minify: k +// +// options: { +// "mangle": false +// } \ No newline at end of file diff --git a/test/input/reduce/output.js b/test/input/reduce/output.js deleted file mode 100644 index 25ea7fec..00000000 --- a/test/input/reduce/output.js +++ /dev/null @@ -1,15 +0,0 @@ -var b = 0; - -function f0() { - var expr2 = (0 - 1 - .1 - .1).toString(); - for (var key2 in expr2) { - --b; - } -} - -var a_1 = f0(); - -console.log(b); -// output: -19 -// minify: -4 -// options: {"compress":{"unsafe_math":true},"mangle":false} \ No newline at end of file diff --git a/test/input/reduce/unsafe_math.js b/test/input/reduce/unsafe_math.js new file mode 100644 index 00000000..b99ffd0e --- /dev/null +++ b/test/input/reduce/unsafe_math.js @@ -0,0 +1,18 @@ +var _calls_ = 10, a = 100, b = 10, c = 0; + +function f0(b_1, a, undefined_2) { + a++ + ++b; + { + var expr2 = (b + 1 - .1 - .1 - .1 || a || 3).toString(); + L20778: for (var key2 in expr2) { + (c = c + 1) + [ --b + b_1, typeof f0 == "function" && --_calls_ >= 0 && f0(--b + typeof (undefined_2 = 1 === 1 ? a : b), --b + { + c: (c = c + 1) + null + }, a++ + (typeof f0 == "function" && --_calls_ >= 0 && f0(typeof (c = 1 + c, 3 / "a" * ("c" >>> 23..toString()) >= (b_1 && (b_1[(c = c + 1) + a--] = (- -0, + true + {})))), 3, 25))), 1 === 1 ? a : b ]; + } + } +} + +var a_1 = f0([ , 0 ].length === 2); + +console.log(null, a, b, c, Infinity, NaN, undefined); diff --git a/test/input/reduce/unsafe_math.reduced.js b/test/input/reduce/unsafe_math.reduced.js new file mode 100644 index 00000000..ac2f1890 --- /dev/null +++ b/test/input/reduce/unsafe_math.reduced.js @@ -0,0 +1,22 @@ +var b = 0; + +function f0() { + var expr2 = (0 - 1 - .1 - .1).toString(); + for (var key2 in expr2) { + --b; + } +} + +var a_1 = f0(); + +console.log(b); +// output: -19 +// +// minify: -4 +// +// options: { +// "compress": { +// "unsafe_math": true +// }, +// "mangle": false +// } \ No newline at end of file diff --git a/test/mocha/reduce.js b/test/mocha/reduce.js index 0e21666c..f55c278d 100644 --- a/test/mocha/reduce.js +++ b/test/mocha/reduce.js @@ -8,9 +8,9 @@ function read(path) { } describe("test/reduce.js", function() { + this.timeout(60000); it("Should reduce test case", function() { - this.timeout(60000); - var result = reduce_test(read("test/input/reduce/input.js"), { + var result = reduce_test(read("test/input/reduce/unsafe_math.js"), { compress: { unsafe_math: true, }, @@ -19,7 +19,16 @@ describe("test/reduce.js", function() { verbose: false, }); if (result.error) throw result.error; - assert.strictEqual(result.code, read("test/input/reduce/output.js")); + assert.strictEqual(result.code, read("test/input/reduce/unsafe_math.reduced.js")); + }); + it("Should eliminate unreferenced labels", function() { + var result = reduce_test(read("test/input/reduce/label.js"), { + mangle: false, + }, { + verbose: false, + }); + if (result.error) throw result.error; + assert.strictEqual(result.code, read("test/input/reduce/label.reduced.js")); }); it("Should handle test cases with --toplevel", function() { var result = reduce_test([ @@ -31,7 +40,9 @@ describe("test/reduce.js", function() { if (result.error) throw result.error; assert.strictEqual(result.code, [ "// Can't reproduce test failure with minify options provided:", - '// {"toplevel":true}', + "// {", + '// "toplevel": true', + "// }", "", ].join("\n")); }); @@ -40,7 +51,10 @@ describe("test/reduce.js", function() { if (result.error) throw result.error; assert.strictEqual(result.code, [ "// Can't reproduce test failure with minify options provided:", - '// {"compress":{},"mangle":false}', + "// {", + '// "compress": {},', + '// "mangle": false', + "// }", "", ].join("\n")); }); @@ -61,8 +75,15 @@ describe("test/reduce.js", function() { " return f.length;", "}());", "// output: 1", + "// ", "// minify: 0", - '// options: {"compress":{"keep_fargs":false},"mangle":false}', + "// ", + "// options: {", + '// "compress": {', + '// "keep_fargs": false', + "// },", + '// "mangle": false', + "// }", ].join("\n")); }); it("Should fail when invalid option is supplied", function() { @@ -81,4 +102,38 @@ describe("test/reduce.js", function() { assert.ok(err instanceof Error); assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Name expected"); }); + it("Should format multi-line output correctly", function() { + var code = [ + "var a = 0;", + "", + "for (var b in [ 1, 2, 3 ]) {", + " a = +a + 1 - .2;", + " console.log(a);", + "}", + ].join("\n"); + var result = reduce_test(code, { + compress: { + unsafe_math: true, + }, + mangle: false, + }); + if (result.error) throw result.error; + assert.strictEqual(result.code, [ + code, + "// output: 0.8", + "// 1.6", + "// 2.4", + "// ", + "// minify: 0.8", + "// 1.6", + "// 2.4000000000000004", + "// ", + "// options: {", + '// "compress": {', + '// "unsafe_math": true', + "// },", + '// "mangle": false', + "// }", + ].join("\n")); + }); }); diff --git a/test/reduce.js b/test/reduce.js index c997a870..20b1dd56 100644 --- a/test/reduce.js +++ b/test/reduce.js @@ -22,7 +22,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options) var max_iterations = reduce_options.max_iterations || 1000; var max_timeout = reduce_options.max_timeout || 15000; var verbose = reduce_options.verbose; - var minify_options_json = JSON.stringify(minify_options); + var minify_options_json = JSON.stringify(minify_options, null, 2); var timeout = 1000; // start with a low timeout var differs; @@ -256,6 +256,15 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options) CHANGED = true; return node.expression; } + else if (node instanceof U.AST_LabeledStatement) { + if (node.body instanceof U.AST_Statement + && !has_loopcontrol(node.body, node.body, node)) { + // replace labelled statement with its non-labelled body + node.start._permute = REPLACEMENTS.length; + CHANGED = true; + return node.body; + } + } if (in_list) { // special case to drop object properties and switch branches @@ -268,14 +277,6 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options) // replace or skip statement if (node instanceof U.AST_Statement) { - if (node instanceof U.AST_LabeledStatement - && node.body instanceof U.AST_Statement - && !has_loopcontrol(node.body, node.body, node)) { - // replace labelled statement with its non-labelled body - node.start._permute = REPLACEMENTS.length; - CHANGED = true; - return node.body; - } node.start._permute++; CHANGED = true; return List.skip; @@ -379,13 +380,13 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options) console.error("// reduce test pass " + pass + ": " + testcase.length + " bytes"); } } - testcase += "\n// output: " + differs.unminified_result - + "\n// minify: " + differs.minified_result - + "\n// options: " + minify_options_json; + testcase += "\n// output: " + to_comment(differs.unminified_result) + + "\n// minify: " + to_comment(differs.minified_result) + + "\n// options: " + to_comment(minify_options_json); } else { // same stdout result produced when minified testcase = "// Can't reproduce test failure with minify options provided:" - + "\n// " + minify_options_json; + + "\n// " + to_comment(minify_options_json); } var result = U.minify(testcase.replace(/\u001b\[\d+m/g, ""), { compress: false, @@ -399,6 +400,10 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options) return result; }; +function to_comment(value) { + return ("" + value).replace(/\n/g, "\n// "); +} + function has_loopcontrol(body, loop, label) { var found = false; var tw = new U.TreeWalker(function(node) { -- cgit v1.2.3