detect toplevel option properly (#3735)

fixes #3730
This commit is contained in:
Alex Lam S.L
2020-02-29 17:33:48 +00:00
committed by GitHub
parent 6092bf23de
commit c8d60d6983
6 changed files with 69 additions and 22 deletions

View File

@@ -207,8 +207,9 @@ function reminify(orig_options, input_code, input_formatted, stdout) {
}); });
return false; return false;
} else { } else {
var expected = stdout[options.toplevel ? 1 : 0]; var toplevel = sandbox.has_toplevel(options);
var actual = run_code(result.code, options.toplevel); var expected = stdout[toplevel ? 1 : 0];
var actual = run_code(result.code, toplevel);
if (typeof expected != "string" && typeof actual != "string" && expected.name == actual.name) { if (typeof expected != "string" && typeof actual != "string" && expected.name == actual.name) {
actual = expected; actual = expected;
} }
@@ -378,7 +379,10 @@ function test_case(test) {
} }
if (test.expect_stdout && (!test.node_version || semver.satisfies(process.version, test.node_version))) { if (test.expect_stdout && (!test.node_version || semver.satisfies(process.version, test.node_version))) {
var stdout = [ run_code(input_code), run_code(input_code, true) ]; var stdout = [ run_code(input_code), run_code(input_code, true) ];
var toplevel = test.options.toplevel; var toplevel = sandbox.has_toplevel({
compress: test.options,
mangle: test.mangle
});
var actual = stdout[toplevel ? 1 : 0]; var actual = stdout[toplevel ? 1 : 0];
if (test.expect_stdout === true) { if (test.expect_stdout === true) {
test.expect_stdout = actual; test.expect_stdout = actual;

View File

@@ -51,7 +51,7 @@ describe("minify", function() {
"var a=n(3),b=r(12);", "var a=n(3),b=r(12);",
'c("qux",a,b),o(11);', 'c("qux",a,b),o(11);',
].join("")); ].join(""));
assert.strictEqual(run_code(compressed), run_code(original)); assert.strictEqual(run_code(compressed, true), run_code(original, true));
}); });
it("Should work with nameCache", function() { it("Should work with nameCache", function() {
@@ -84,7 +84,7 @@ describe("minify", function() {
"var a=n(3),b=r(12);", "var a=n(3),b=r(12);",
'c("qux",a,b),o(11);', 'c("qux",a,b),o(11);',
].join("")); ].join(""));
assert.strictEqual(run_code(compressed), run_code(original)); assert.strictEqual(run_code(compressed, true), run_code(original, true));
}); });
it("Should avoid cached names when mangling top-level variables", function() { it("Should avoid cached names when mangling top-level variables", function() {
@@ -113,7 +113,7 @@ describe("minify", function() {
'"xxyyy";var y={y:2,a:3},a=4;', '"xxyyy";var y={y:2,a:3},a=4;',
'console.log(x.x,y.y,y.a,a);', 'console.log(x.x,y.y,y.a,a);',
].join("")); ].join(""));
assert.strictEqual(run_code(compressed), run_code(original)); assert.strictEqual(run_code(compressed, true), run_code(original, true));
}); });
it("Should avoid cached names when mangling inner-scoped variables", function() { it("Should avoid cached names when mangling inner-scoped variables", function() {
@@ -137,7 +137,7 @@ describe("minify", function() {
'var o=function(o,n){console.log("extend");o();n()};function n(){console.log("A")}', 'var o=function(o,n){console.log("extend");o();n()};function n(){console.log("A")}',
'var e=function(n){function e(){console.log("B")}o(e,n);return e}(n);', 'var e=function(n){function e(){console.log("B")}o(e,n);return e}(n);',
].join("")); ].join(""));
assert.strictEqual(run_code(compressed), run_code(original)); assert.strictEqual(run_code(compressed, true), run_code(original, true));
}); });
it("Should not parse invalid use of reserved words", function() { it("Should not parse invalid use of reserved words", function() {

View File

@@ -46,6 +46,44 @@ describe("test/reduce.js", function() {
"// }", "// }",
].join("\n")); ].join("\n"));
}); });
it("Should handle test cases with --compress toplevel", function() {
var result = reduce_test([
"var NaN = 42;",
"console.log(NaN);",
].join("\n"), {
compress: {
toplevel: true,
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"// Can't reproduce test failure with minify options provided:",
"// {",
'// "compress": {',
'// "toplevel": true',
"// }",
"// }",
].join("\n"));
});
it("Should handle test cases with --mangle toplevel", function() {
var result = reduce_test([
"var undefined = 42;",
"console.log(undefined);",
].join("\n"), {
mangle: {
toplevel: true,
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"// Can't reproduce test failure with minify options provided:",
"// {",
'// "mangle": {',
'// "toplevel": true',
"// }",
"// }",
].join("\n"));
});
it("Should handle test result of NaN", function() { it("Should handle test result of NaN", function() {
var result = reduce_test("throw 0 / 0;"); var result = reduce_test("throw 0 / 0;");
if (result.error) throw result.error; if (result.error) throw result.error;

View File

@@ -543,7 +543,7 @@ function producesDifferentResultWhenMinified(result_cache, code, minify_options,
var minified = U.minify(code, minify_options); var minified = U.minify(code, minify_options);
if (minified.error) return minified; if (minified.error) return minified;
var toplevel = minify_options.toplevel; var toplevel = sandbox.has_toplevel(minify_options);
var elapsed = Date.now(); var elapsed = Date.now();
var unminified_result = run_code(result_cache, code, toplevel, max_timeout); var unminified_result = run_code(result_cache, code, toplevel, max_timeout);
elapsed = Date.now() - elapsed; elapsed = Date.now() - elapsed;

View File

@@ -87,3 +87,8 @@ exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expec
} : function(expected, actual) { } : function(expected, actual) {
return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual); return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual);
}; };
exports.has_toplevel = function(options) {
return options.toplevel
|| options.mangle && options.mangle.toplevel
|| options.compress && options.compress.toplevel;
};

View File

@@ -1022,7 +1022,7 @@ function log_suspects(minify_options, component) {
errorln("Error testing options." + component + "." + name); errorln("Error testing options." + component + "." + name);
errorln(result.error); errorln(result.error);
} else { } else {
var r = sandbox.run_code(result.code, m.toplevel); var r = sandbox.run_code(result.code, sandbox.has_toplevel(m));
return sandbox.same_stdout(original_result, r); return sandbox.same_stdout(original_result, r);
} }
} }
@@ -1037,14 +1037,14 @@ function log_suspects(minify_options, component) {
} }
function log_rename(options) { function log_rename(options) {
var m = JSON.parse(JSON.stringify(options)); var m = JSON.parse(options);
m.rename = false; m.rename = false;
var result = UglifyJS.minify(original_code, m); var result = UglifyJS.minify(original_code, m);
if (result.error) { if (result.error) {
errorln("Error testing options.rename"); errorln("Error testing options.rename");
errorln(result.error); errorln(result.error);
} else { } else {
var r = sandbox.run_code(result.code, m.toplevel); var r = sandbox.run_code(result.code, sandbox.has_toplevel(m));
if (sandbox.same_stdout(original_result, r)) { if (sandbox.same_stdout(original_result, r)) {
errorln("Suspicious options:"); errorln("Suspicious options:");
errorln(" rename"); errorln(" rename");
@@ -1054,19 +1054,18 @@ function log_rename(options) {
} }
function log(options) { function log(options) {
var options_copy = JSON.parse(options); var toplevel = sandbox.has_toplevel(JSON.parse(options));
options = JSON.parse(options);
if (!ok) errorln("\n\n\n\n\n\n!!!!!!!!!!\n\n\n"); if (!ok) errorln("\n\n\n\n\n\n!!!!!!!!!!\n\n\n");
errorln("//============================================================="); errorln("//=============================================================");
if (!ok) errorln("// !!!!!! Failed... round " + round); if (!ok) errorln("// !!!!!! Failed... round " + round);
errorln("// original code"); errorln("// original code");
try_beautify(original_code, options.toplevel, original_result, errorln); try_beautify(original_code, toplevel, original_result, errorln);
errorln(); errorln();
errorln(); errorln();
errorln("//-------------------------------------------------------------"); errorln("//-------------------------------------------------------------");
if (typeof uglify_code == "string") { if (typeof uglify_code == "string") {
errorln("// uglified code"); errorln("// uglified code");
try_beautify(uglify_code, options.toplevel, uglify_result, errorln); try_beautify(uglify_code, toplevel, uglify_result, errorln);
errorln(); errorln();
errorln(); errorln();
errorln("original result:"); errorln("original result:");
@@ -1074,7 +1073,7 @@ function log(options) {
errorln("uglified result:"); errorln("uglified result:");
errorln(uglify_result); errorln(uglify_result);
errorln("//-------------------------------------------------------------"); errorln("//-------------------------------------------------------------");
var reduced = reduce_test(original_code, options_copy, { var reduced = reduce_test(original_code, JSON.parse(options), {
verbose: false, verbose: false,
}).code; }).code;
if (reduced) { if (reduced) {
@@ -1096,10 +1095,10 @@ function log(options) {
} }
} }
errorln("minify(options):"); errorln("minify(options):");
errorln(JSON.stringify(options, null, 2)); errorln(JSON.stringify(JSON.parse(options), null, 2));
errorln(); errorln();
if (!ok && typeof uglify_code == "string") { if (!ok && typeof uglify_code == "string") {
Object.keys(default_options).forEach(log_suspects.bind(null, options)); Object.keys(default_options).forEach(log_suspects.bind(null, JSON.parse(options)));
log_rename(options); log_rename(options);
errorln("!!!!!! Failed... round " + round); errorln("!!!!!! Failed... round " + round);
} }
@@ -1135,16 +1134,17 @@ for (var round = 1; round <= num_iterations; round++) {
if (!errored) orig_result.push(sandbox.run_code(original_code, true)); if (!errored) orig_result.push(sandbox.run_code(original_code, true));
(errored ? fallback_options : minify_options).forEach(function(options) { (errored ? fallback_options : minify_options).forEach(function(options) {
var o = JSON.parse(options); var o = JSON.parse(options);
var toplevel = sandbox.has_toplevel(o);
uglify_code = UglifyJS.minify(original_code, o); uglify_code = UglifyJS.minify(original_code, o);
original_result = orig_result[o.toplevel ? 1 : 0]; original_result = orig_result[toplevel ? 1 : 0];
if (!uglify_code.error) { if (!uglify_code.error) {
uglify_code = uglify_code.code; uglify_code = uglify_code.code;
uglify_result = sandbox.run_code(uglify_code, o.toplevel); uglify_result = sandbox.run_code(uglify_code, toplevel);
ok = sandbox.same_stdout(original_result, uglify_result); ok = sandbox.same_stdout(original_result, uglify_result);
if (!ok && typeof uglify_result == "string" && o.compress.unsafe_math) { if (!ok && typeof uglify_result == "string" && o.compress.unsafe_math) {
ok = fuzzy_match(original_result, uglify_result); ok = fuzzy_match(original_result, uglify_result);
if (!ok) { if (!ok) {
var fuzzy_result = sandbox.run_code(original_code.replace(/( - 0\.1){3}/g, " - 0.3")); var fuzzy_result = sandbox.run_code(original_code.replace(/( - 0\.1){3}/g, " - 0.3"), toplevel);
ok = sandbox.same_stdout(fuzzy_result, uglify_result); ok = sandbox.same_stdout(fuzzy_result, uglify_result);
} }
} }
@@ -1158,7 +1158,7 @@ for (var round = 1; round <= num_iterations; round++) {
else if (errored) { else if (errored) {
println("//============================================================="); println("//=============================================================");
println("// original code"); println("// original code");
try_beautify(original_code, o.toplevel, original_result, println); try_beautify(original_code, toplevel, original_result, println);
println(); println();
println(); println();
println("original result:"); println("original result:");