Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d105ab9722 | ||
|
|
b39228892d | ||
|
|
ff72eaa3c3 | ||
|
|
0a1c9b34ce | ||
|
|
03e968be62 | ||
|
|
421bb7083a | ||
|
|
bdc8ef2218 | ||
|
|
bca52fcba2 | ||
|
|
d6d31cbb5a | ||
|
|
a051846d22 | ||
|
|
3485472866 | ||
|
|
c8d60d6983 | ||
|
|
6092bf23de | ||
|
|
7052ce5aef |
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -4,10 +4,10 @@ jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
node: [ "0.10", "0.12", 4, 6, 8, 10, latest ]
|
||||
os: [ ubuntu-latest, windows-latest ]
|
||||
node: [ "0.10", 0.12, 4, 6, 8, 10, latest ]
|
||||
script: [ compress, mocha, release/benchmark, release/jetstream ]
|
||||
name: ${{ matrix.os }} ${{ matrix.node }} ${{ matrix.script }}
|
||||
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
NODE: ${{ matrix.node }}
|
||||
|
||||
@@ -315,7 +315,7 @@ merge(Compressor.prototype, {
|
||||
if (value instanceof AST_Array) return native_fns.Array[name];
|
||||
if (value instanceof AST_Function) return native_fns.Function[name];
|
||||
if (value instanceof AST_Object) return native_fns.Object[name];
|
||||
if (value instanceof AST_RegExp) return native_fns.RegExp[name];
|
||||
if (value instanceof AST_RegExp) return native_fns.RegExp[name] && !value.value.global;
|
||||
}
|
||||
|
||||
function is_modified(compressor, tw, node, value, level, immutable) {
|
||||
@@ -1384,7 +1384,10 @@ merge(Compressor.prototype, {
|
||||
function is_last_node(node, parent) {
|
||||
if (node instanceof AST_Call) {
|
||||
var fn = node.expression;
|
||||
if (fn instanceof AST_SymbolRef) fn = fn.fixed_value();
|
||||
if (fn instanceof AST_SymbolRef) {
|
||||
if (fn.definition().recursive_refs > 0) return true;
|
||||
fn = fn.fixed_value();
|
||||
}
|
||||
if (!(fn instanceof AST_Lambda)) return true;
|
||||
if (fn.collapse_scanning) return false;
|
||||
fn.collapse_scanning = true;
|
||||
@@ -2528,9 +2531,8 @@ merge(Compressor.prototype, {
|
||||
return left.is_negative_zero() || right.is_negative_zero();
|
||||
case "*":
|
||||
case "/":
|
||||
return true;
|
||||
case "%":
|
||||
return left.is_negative_zero();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -3003,6 +3005,7 @@ merge(Compressor.prototype, {
|
||||
].concat(object_fns),
|
||||
Object: object_fns,
|
||||
RegExp: [
|
||||
"exec",
|
||||
"test",
|
||||
].concat(object_fns),
|
||||
String: [
|
||||
@@ -3085,6 +3088,7 @@ merge(Compressor.prototype, {
|
||||
cached.forEach(function(node) {
|
||||
delete node._eval;
|
||||
});
|
||||
if (ignore_side_effects) return val;
|
||||
if (!val || val instanceof RegExp) return val;
|
||||
if (typeof val == "function" || typeof val == "object") return this;
|
||||
return val;
|
||||
@@ -3369,15 +3373,18 @@ merge(Compressor.prototype, {
|
||||
var args = eval_args(this.args);
|
||||
if (!args) return this;
|
||||
if (!stat.value) return undefined;
|
||||
fn.argnames.forEach(function(sym, i) {
|
||||
if (!all(fn.argnames, function(sym, i) {
|
||||
var value = args[i];
|
||||
sym.definition().references.forEach(function(node) {
|
||||
var def = sym.definition();
|
||||
if (def.orig[def.orig.length - 1] !== sym) return false;
|
||||
def.references.forEach(function(node) {
|
||||
node._eval = function() {
|
||||
return value;
|
||||
};
|
||||
cached.push(node);
|
||||
});
|
||||
});
|
||||
return true;
|
||||
})) return this;
|
||||
fn.evaluating = true;
|
||||
var val = stat.value._eval(compressor, ignore_side_effects, cached, depth);
|
||||
delete fn.evaluating;
|
||||
@@ -3400,6 +3407,7 @@ merge(Compressor.prototype, {
|
||||
if (val == null || val === e) return this;
|
||||
var native_fn = native_fns[val.constructor.name];
|
||||
if (!native_fn || !native_fn[key]) return this;
|
||||
if (val instanceof RegExp && val.global && !(e instanceof AST_RegExp)) return this;
|
||||
}
|
||||
var args = eval_args(this.args);
|
||||
if (!args) return this;
|
||||
@@ -3413,6 +3421,8 @@ merge(Compressor.prototype, {
|
||||
line: this.start.line,
|
||||
col: this.start.col
|
||||
});
|
||||
} finally {
|
||||
if (val instanceof RegExp) val.lastIndex = 0;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
@@ -3909,14 +3919,18 @@ merge(Compressor.prototype, {
|
||||
} else if (node instanceof AST_Unary) {
|
||||
if (node.write_only) sym = node.expression;
|
||||
}
|
||||
if (!/strict/.test(compressor.option("pure_getters"))) return sym instanceof AST_SymbolRef && sym;
|
||||
while (sym instanceof AST_PropAccess && !sym.expression.may_throw_on_access(compressor)) {
|
||||
if (sym instanceof AST_Sub) props.unshift(sym.property);
|
||||
sym = sym.expression;
|
||||
if (/strict/.test(compressor.option("pure_getters"))) {
|
||||
while (sym instanceof AST_PropAccess && !sym.expression.may_throw_on_access(compressor)) {
|
||||
if (sym instanceof AST_Sub) props.unshift(sym.property);
|
||||
sym = sym.expression;
|
||||
}
|
||||
}
|
||||
return sym instanceof AST_SymbolRef && all(sym.definition().orig, function(sym) {
|
||||
if (!(sym instanceof AST_SymbolRef)) return;
|
||||
if (compressor.exposed(sym.definition())) return;
|
||||
if (!all(sym.definition().orig, function(sym) {
|
||||
return !(sym instanceof AST_SymbolLambda);
|
||||
}) && sym;
|
||||
})) return;
|
||||
return sym;
|
||||
};
|
||||
var in_use = [];
|
||||
var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
|
||||
@@ -6863,7 +6877,7 @@ merge(Compressor.prototype, {
|
||||
if (node.truthy) return true;
|
||||
if (node.falsy) return false;
|
||||
if (node.is_truthy()) return true;
|
||||
return node.evaluate(compressor);
|
||||
return node.evaluate(compressor, true);
|
||||
}
|
||||
|
||||
function is_indexFn(node) {
|
||||
|
||||
12
lib/parse.js
12
lib/parse.js
@@ -241,16 +241,16 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
if (signal_eof && !ch)
|
||||
throw EX_EOF;
|
||||
if (NEWLINE_CHARS[ch]) {
|
||||
S.newline_before = S.newline_before || !in_string;
|
||||
++S.line;
|
||||
S.col = 0;
|
||||
if (!in_string && ch == "\r" && peek() == "\n") {
|
||||
// treat a \r\n sequence as a single \n
|
||||
++S.pos;
|
||||
S.line++;
|
||||
if (!in_string) S.newline_before = true;
|
||||
if (ch == "\r" && peek() == "\n") {
|
||||
// treat `\r\n` as `\n`
|
||||
S.pos++;
|
||||
ch = "\n";
|
||||
}
|
||||
} else {
|
||||
++S.col;
|
||||
S.col++;
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
@@ -219,7 +219,12 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
var redef;
|
||||
while (redef = new_def.redefined()) new_def = redef;
|
||||
} else {
|
||||
new_def = self.globals.get(name) || scope.def_variable(node);
|
||||
new_def = self.globals.get(name);
|
||||
}
|
||||
if (new_def) {
|
||||
new_def.orig.push(node);
|
||||
} else {
|
||||
new_def = scope.def_variable(node);
|
||||
}
|
||||
old_def.orig.concat(old_def.references).forEach(function(node) {
|
||||
node.thedef = new_def;
|
||||
|
||||
@@ -185,7 +185,7 @@ function makePredicate(words) {
|
||||
|
||||
function all(array, predicate) {
|
||||
for (var i = array.length; --i >= 0;)
|
||||
if (!predicate(array[i]))
|
||||
if (!predicate(array[i], i))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.8.0",
|
||||
"version": "3.8.1",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
|
||||
@@ -207,8 +207,9 @@ function reminify(orig_options, input_code, input_formatted, stdout) {
|
||||
});
|
||||
return false;
|
||||
} else {
|
||||
var expected = stdout[options.toplevel ? 1 : 0];
|
||||
var actual = run_code(result.code, options.toplevel);
|
||||
var toplevel = sandbox.has_toplevel(options);
|
||||
var expected = stdout[toplevel ? 1 : 0];
|
||||
var actual = run_code(result.code, toplevel);
|
||||
if (typeof expected != "string" && typeof actual != "string" && expected.name == actual.name) {
|
||||
actual = expected;
|
||||
}
|
||||
@@ -378,7 +379,10 @@ function test_case(test) {
|
||||
}
|
||||
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 toplevel = test.options.toplevel;
|
||||
var toplevel = sandbox.has_toplevel({
|
||||
compress: test.options,
|
||||
mangle: test.mangle
|
||||
});
|
||||
var actual = stdout[toplevel ? 1 : 0];
|
||||
if (test.expect_stdout === true) {
|
||||
test.expect_stdout = actual;
|
||||
|
||||
@@ -7765,3 +7765,44 @@ issue_3700: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3744: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function f(a) {
|
||||
({
|
||||
get p() {
|
||||
switch (1) {
|
||||
case 0:
|
||||
f((a = 2, 3));
|
||||
case 1:
|
||||
console.log(function g(b) {
|
||||
return b || "PASS";
|
||||
}());
|
||||
}
|
||||
}
|
||||
}).p;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function f(a) {
|
||||
({
|
||||
get p() {
|
||||
switch (1) {
|
||||
case 0:
|
||||
f();
|
||||
case 1:
|
||||
console.log(b || "PASS");
|
||||
}
|
||||
var b;
|
||||
}
|
||||
}).p;
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -1240,11 +1240,11 @@ issue_2535_1: {
|
||||
expect: {
|
||||
y();
|
||||
x() && y();
|
||||
(x(), 1) && y();
|
||||
x(), y();
|
||||
x() && y();
|
||||
x() && y();
|
||||
x() && y();
|
||||
(x(), 0) && y();
|
||||
x();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2413,3 +2413,34 @@ issue_3673: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3746: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
A;
|
||||
} catch (e) {
|
||||
var e;
|
||||
}
|
||||
(function f(a) {
|
||||
e = a;
|
||||
})();
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
A;
|
||||
} catch (e) {
|
||||
var e;
|
||||
}
|
||||
(function(a) {
|
||||
e = a;
|
||||
})();
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -2161,3 +2161,16 @@ collapse_vars_regexp: {
|
||||
"abbb",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3738: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log(1 / (0 + ([] - 1) % 1));
|
||||
}
|
||||
expect: {
|
||||
console.log(1 / (0 + ([] - 1) % 1));
|
||||
}
|
||||
expect_stdout: "Infinity"
|
||||
}
|
||||
|
||||
@@ -2398,3 +2398,25 @@ issue_3703: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3750: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
(function(a) {
|
||||
return function a() {
|
||||
return a && console.log("PASS");
|
||||
}();
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function(a) {
|
||||
return function a() {
|
||||
return a && console.log("PASS");
|
||||
}();
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ wrongly_optimized: {
|
||||
function func() {
|
||||
foo();
|
||||
}
|
||||
// TODO: optimize to `func(), bar()`
|
||||
(func(), 1) && bar();
|
||||
func(), 1, bar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ wrongly_optimized: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
expression: true,
|
||||
}
|
||||
@@ -99,8 +100,8 @@ wrongly_optimized: {
|
||||
function func() {
|
||||
foo();
|
||||
}
|
||||
// TODO: optimize to `func(), bar()`
|
||||
if (func(), 1) bar();
|
||||
func(), 1;
|
||||
bar();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -255,3 +255,221 @@ issue_3434_4: {
|
||||
"false true",
|
||||
]
|
||||
}
|
||||
|
||||
exec: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
while (/a/.exec("AAA"))
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
for (;null;)
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
exec_global: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
while (/a/g.exec("AAA"))
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
for (;null;)
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
test: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
while (/a/.test("AAA"))
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
while (false)
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
test_global: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
while (/a/g.test("AAA"))
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
while (false)
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
var_exec: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var r = /a/;
|
||||
while (r.exec("AAA"))
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
var r = /a/;
|
||||
for (;null;)
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
var_exec_global: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var r = /a/g;
|
||||
while (r.exec("aaa"))
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
var r = /a/g;
|
||||
for (;r.exec("aaa");)
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"PASS",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
var_test: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var r = /a/;
|
||||
while (r.test("AAA"))
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
var r = /a/;
|
||||
while (false)
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
var_test_global: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var r = /a/g;
|
||||
while (r.test("aaa"))
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
var r = /a/g;
|
||||
while (r.test("aaa"))
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"PASS",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
lazy_boolean: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
passes: 2,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
/b/.exec({}) && console.log("PASS");
|
||||
/b/.test({}) && console.log("PASS");
|
||||
/b/g.exec({}) && console.log("PASS");
|
||||
/b/g.test({}) && console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
console.log("PASS");
|
||||
console.log("PASS");
|
||||
console.log("PASS");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"PASS",
|
||||
"PASS",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
reset_state_between_evaluate: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
passes: 2,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
for (var a in /[abc4]/g.exec("a"))
|
||||
return "PASS";
|
||||
return "FAIL";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
for (var a in /[abc4]/g.exec("a"))
|
||||
return "PASS";
|
||||
return "FAIL";
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// (beautified)
|
||||
var o = this;
|
||||
|
||||
for (var k in o) {
|
||||
0;
|
||||
}
|
||||
for (var k in o) {}
|
||||
|
||||
var a;
|
||||
|
||||
|
||||
8
test/input/reduce/setter.js
Normal file
8
test/input/reduce/setter.js
Normal file
@@ -0,0 +1,8 @@
|
||||
console.log(function f(a) {
|
||||
({
|
||||
set p(v) {
|
||||
f++;
|
||||
}
|
||||
});
|
||||
return f.length;
|
||||
}());
|
||||
20
test/input/reduce/setter.reduced.js
Normal file
20
test/input/reduce/setter.reduced.js
Normal file
@@ -0,0 +1,20 @@
|
||||
// (beautified)
|
||||
console.log(function f(a) {
|
||||
({
|
||||
set p(v) {
|
||||
f++;
|
||||
}
|
||||
});
|
||||
return f.length;
|
||||
}());
|
||||
// output: 1
|
||||
//
|
||||
// minify: 0
|
||||
//
|
||||
// options: {
|
||||
// "compress": {
|
||||
// "keep_fargs": false,
|
||||
// "unsafe": true
|
||||
// },
|
||||
// "mangle": false
|
||||
// }
|
||||
@@ -1,3 +1,4 @@
|
||||
// (beautified)
|
||||
var b = 0;
|
||||
|
||||
var expr2 = (0 - 1 - .1 - .1).toString();
|
||||
|
||||
@@ -51,7 +51,7 @@ describe("minify", function() {
|
||||
"var a=n(3),b=r(12);",
|
||||
'c("qux",a,b),o(11);',
|
||||
].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() {
|
||||
@@ -84,7 +84,7 @@ describe("minify", function() {
|
||||
"var a=n(3),b=r(12);",
|
||||
'c("qux",a,b),o(11);',
|
||||
].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() {
|
||||
@@ -113,7 +113,7 @@ describe("minify", function() {
|
||||
'"xxyyy";var y={y:2,a:3},a=4;',
|
||||
'console.log(x.x,y.y,y.a,a);',
|
||||
].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() {
|
||||
@@ -137,7 +137,7 @@ describe("minify", function() {
|
||||
'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);',
|
||||
].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() {
|
||||
|
||||
@@ -31,6 +31,19 @@ describe("test/reduce.js", function() {
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, read("test/input/reduce/label.reduced.js"));
|
||||
});
|
||||
it("Should retain setter arguments", function() {
|
||||
var result = reduce_test(read("test/input/reduce/setter.js"), {
|
||||
compress: {
|
||||
keep_fargs: false,
|
||||
unsafe: true,
|
||||
},
|
||||
mangle: false,
|
||||
}, {
|
||||
verbose: false,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, read("test/input/reduce/setter.reduced.js"));
|
||||
});
|
||||
it("Should handle test cases with --toplevel", function() {
|
||||
var result = reduce_test([
|
||||
"var Infinity = 42;",
|
||||
@@ -40,21 +53,56 @@ describe("test/reduce.js", function() {
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"// Can't reproduce test failure with minify options provided:",
|
||||
"// {",
|
||||
"// Can't reproduce test failure",
|
||||
"// minify options: {",
|
||||
'// "toplevel": true',
|
||||
"// }",
|
||||
].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",
|
||||
"// minify options: {",
|
||||
'// "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",
|
||||
"// minify options: {",
|
||||
'// "mangle": {',
|
||||
'// "toplevel": true',
|
||||
"// }",
|
||||
"// }",
|
||||
].join("\n"));
|
||||
});
|
||||
it("Should handle test result of NaN", function() {
|
||||
var result = reduce_test("throw 0 / 0;");
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"// Can't reproduce test failure with minify options provided:",
|
||||
"// {",
|
||||
'// "compress": {},',
|
||||
'// "mangle": false',
|
||||
"// }",
|
||||
"// Can't reproduce test failure",
|
||||
"// minify options: {}",
|
||||
].join("\n"));
|
||||
});
|
||||
it("Should print correct output for irreducible test case", function() {
|
||||
@@ -70,6 +118,7 @@ describe("test/reduce.js", function() {
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"// (beautified)",
|
||||
"console.log(function f(a) {",
|
||||
" return f.length;",
|
||||
"}());",
|
||||
@@ -118,6 +167,7 @@ describe("test/reduce.js", function() {
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"// (beautified)",
|
||||
code,
|
||||
"// output: 0.8",
|
||||
"// 1.6",
|
||||
@@ -138,11 +188,41 @@ describe("test/reduce.js", function() {
|
||||
it("Should reduce infinite loops with reasonable performance", function() {
|
||||
if (semver.satisfies(process.version, "0.10")) return;
|
||||
this.timeout(120000);
|
||||
var result = reduce_test("while (/9/.test(1 - .8));", {
|
||||
compress: {
|
||||
unsafe_math: true,
|
||||
},
|
||||
mangle: false,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code.replace(/ timed out after [0-9]+ms/, " timed out."), [
|
||||
"// (beautified)",
|
||||
"while (/9/.test(1 - .8)) {}",
|
||||
"// output: Error: Script execution timed out.",
|
||||
"// minify: ",
|
||||
"// options: {",
|
||||
'// "compress": {',
|
||||
'// "unsafe_math": true',
|
||||
"// },",
|
||||
'// "mangle": false',
|
||||
"// }",
|
||||
].join("\n"));
|
||||
});
|
||||
it("Should ignore difference in Error.message", function() {
|
||||
var result = reduce_test("null[function() {\n}];");
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, (semver.satisfies(process.version, "0.10") ? [
|
||||
"// Can't reproduce test failure",
|
||||
"// minify options: {}",
|
||||
] : [
|
||||
"// No differences except in error message",
|
||||
"// minify options: {}",
|
||||
]).join("\n"));
|
||||
});
|
||||
it("Should report trailing whitespace difference in stringified format", function() {
|
||||
var code = [
|
||||
"var a = 9007199254740992, b = 1;",
|
||||
"",
|
||||
"while (a++ + (1 - b) < a) {",
|
||||
" 0;",
|
||||
"for (var a in (1 - .8).toString()) {",
|
||||
" console.log();",
|
||||
"}",
|
||||
].join("\n");
|
||||
var result = reduce_test(code, {
|
||||
@@ -152,14 +232,16 @@ describe("test/reduce.js", function() {
|
||||
mangle: false,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code.replace(/ timed out after [0-9]+ms/, " timed out."), [
|
||||
assert.strictEqual(result.code, [
|
||||
"// (beautified)",
|
||||
code,
|
||||
"// output: ",
|
||||
"// minify: Error: Script execution timed out.",
|
||||
"// (stringified)",
|
||||
'// output: "\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n"',
|
||||
'// minify: "\\n\\n\\n"',
|
||||
"// options: {",
|
||||
'// "compress": {',
|
||||
'// "unsafe_math": true',
|
||||
"// },",
|
||||
'// },',
|
||||
'// "mangle": false',
|
||||
"// }",
|
||||
].join("\n"));
|
||||
|
||||
@@ -89,6 +89,22 @@ describe("sourcemaps", function() {
|
||||
assert.strictEqual(result.code, code);
|
||||
assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["console","log"],"mappings":"AAAAA,QAAQC,IAAI","sourceRoot":"//foo.bar/"}');
|
||||
});
|
||||
it("Should produce same source map with DOS or UNIX line endings", function() {
|
||||
var code = [
|
||||
'console.log("\\',
|
||||
'hello",',
|
||||
'"world");',
|
||||
];
|
||||
var dos = UglifyJS.minify(code.join("\r\n"), {
|
||||
sourceMap: true,
|
||||
});
|
||||
if (dos.error) throw dos.error;
|
||||
var unix = UglifyJS.minify(code.join("\n"), {
|
||||
sourceMap: true,
|
||||
});
|
||||
if (unix.error) throw unix.error;
|
||||
assert.strictEqual(dos.map, unix.map);
|
||||
});
|
||||
|
||||
describe("inSourceMap", function() {
|
||||
it("Should read the given string filename correctly when sourceMapIncludeSources is enabled", function() {
|
||||
|
||||
@@ -44,30 +44,37 @@ function test(original, estree, description) {
|
||||
try_beautify(transformed.code);
|
||||
}
|
||||
console.log("!!!!!! Failed... round", round);
|
||||
process.exit(1);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var num_iterations = ufuzz.num_iterations;
|
||||
var minify_options = require("./ufuzz/options.json").map(JSON.stringify);
|
||||
minify_options.unshift(null);
|
||||
for (var round = 1; round <= num_iterations; round++) {
|
||||
process.stdout.write(round + " of " + num_iterations + "\r");
|
||||
var code = ufuzz.createTopLevelCode();
|
||||
var uglified = UglifyJS.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ast: true
|
||||
minify_options.forEach(function(options) {
|
||||
var input = options ? UglifyJS.minify(code, JSON.parse(options)).code : code;
|
||||
var uglified = UglifyJS.minify(input, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ast: true
|
||||
}
|
||||
});
|
||||
var ok = test(uglified.code, uglified.ast.to_mozilla_ast(), "AST_Node.to_mozilla_ast()");
|
||||
try {
|
||||
ok = test(uglified.code, acorn.parse(input), "acorn.parse()") && ok;
|
||||
} catch (e) {
|
||||
console.log("//=============================================================");
|
||||
console.log("// acorn parser failed... round", round);
|
||||
console.log(e);
|
||||
console.log("// original code");
|
||||
console.log(input);
|
||||
}
|
||||
if (!ok) process.exit(1);
|
||||
});
|
||||
test(uglified.code, uglified.ast.to_mozilla_ast(), "AST_Node.to_mozilla_ast()");
|
||||
try {
|
||||
test(uglified.code, acorn.parse(code), "acorn.parse()");
|
||||
} catch (e) {
|
||||
console.log("//=============================================================");
|
||||
console.log("// acorn parser failed... round", round);
|
||||
console.log(e);
|
||||
console.log("// original code");
|
||||
console.log(code);
|
||||
}
|
||||
}
|
||||
console.log();
|
||||
|
||||
120
test/reduce.js
120
test/reduce.js
@@ -20,7 +20,7 @@ var sandbox = require("./sandbox");
|
||||
|
||||
module.exports = function reduce_test(testcase, minify_options, reduce_options) {
|
||||
if (testcase instanceof U.AST_Node) testcase = testcase.print_to_string();
|
||||
minify_options = minify_options || { compress: {}, mangle: false };
|
||||
minify_options = minify_options || {};
|
||||
reduce_options = reduce_options || {};
|
||||
var max_iterations = reduce_options.max_iterations || 1000;
|
||||
var max_timeout = reduce_options.max_timeout || 10000;
|
||||
@@ -36,16 +36,29 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
if (!differs) {
|
||||
// same stdout result produced when minified
|
||||
return {
|
||||
code: "// Can't reproduce test failure with minify options provided:"
|
||||
+ "\n// " + to_comment(minify_options_json)
|
||||
code: [
|
||||
"// Can't reproduce test failure",
|
||||
"// minify options: " + to_comment(minify_options_json)
|
||||
].join("\n")
|
||||
};
|
||||
} else if (differs.timed_out) {
|
||||
return {
|
||||
code: "// Can't reproduce test failure within " + max_timeout + "ms:"
|
||||
+ "\n// " + to_comment(minify_options_json)
|
||||
code: [
|
||||
"// Can't reproduce test failure within " + max_timeout + "ms",
|
||||
"// minify options: " + to_comment(minify_options_json)
|
||||
].join("\n")
|
||||
};
|
||||
} else if (differs.error) {
|
||||
return differs;
|
||||
} else if (is_error(differs.unminified_result)
|
||||
&& is_error(differs.minified_result)
|
||||
&& differs.unminified_result.name == differs.minified_result.name) {
|
||||
return {
|
||||
code: [
|
||||
"// No differences except in error message",
|
||||
"// minify options: " + to_comment(minify_options_json)
|
||||
].join("\n")
|
||||
};
|
||||
} else {
|
||||
max_timeout = Math.min(100 * differs.elapsed, max_timeout);
|
||||
// Replace expressions with constants that will be parsed into
|
||||
@@ -71,12 +84,13 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
// quick ignores
|
||||
if (node instanceof U.AST_Accessor) return;
|
||||
if (node instanceof U.AST_Directive) return;
|
||||
if (!in_list && node instanceof U.AST_EmptyStatement) return;
|
||||
if (node instanceof U.AST_Label) return;
|
||||
if (node instanceof U.AST_LabelRef) return;
|
||||
if (!in_list && node instanceof U.AST_SymbolDeclaration) return;
|
||||
if (node instanceof U.AST_Toplevel) return;
|
||||
|
||||
var parent = tt.parent();
|
||||
if (node instanceof U.AST_SymbolFunarg && parent instanceof U.AST_Accessor) return;
|
||||
|
||||
// ensure that the _permute prop is a number.
|
||||
// can not use `node.start._permute |= 0;` as it will erase fractional part.
|
||||
@@ -112,10 +126,25 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
}
|
||||
else if (node instanceof U.AST_Binary) {
|
||||
CHANGED = true;
|
||||
return [
|
||||
var permute = ((node.start._permute += step) * steps | 0) % 4;
|
||||
var expr = [
|
||||
node.left,
|
||||
node.right,
|
||||
][ ((node.start._permute += step) * steps | 0) % 2 ];
|
||||
][ permute & 1 ];
|
||||
if (permute < 2) return expr;
|
||||
// wrap with console.log()
|
||||
return new U.AST_Call({
|
||||
expression: new U.AST_Dot({
|
||||
expression: new U.AST_SymbolRef({
|
||||
name: "console",
|
||||
start: {},
|
||||
}),
|
||||
property: "log",
|
||||
start: {},
|
||||
}),
|
||||
args: [ expr ],
|
||||
start: {},
|
||||
});
|
||||
}
|
||||
else if (node instanceof U.AST_Catch || node instanceof U.AST_Finally) {
|
||||
// drop catch or finally block
|
||||
@@ -357,15 +386,11 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
}
|
||||
|
||||
// replace this node
|
||||
var newNode = U.parse(REPLACEMENTS[node.start._permute % REPLACEMENTS.length | 0], {
|
||||
var newNode = is_statement(node) ? new U.AST_EmptyStatement({
|
||||
start: {},
|
||||
}) : U.parse(REPLACEMENTS[node.start._permute % REPLACEMENTS.length | 0], {
|
||||
expression: true,
|
||||
});
|
||||
if (is_statement(node)) {
|
||||
newNode = new U.AST_SimpleStatement({
|
||||
body: newNode,
|
||||
start: {},
|
||||
});
|
||||
}
|
||||
newNode.start._permute = ++node.start._permute;
|
||||
CHANGED = true;
|
||||
return newNode;
|
||||
@@ -445,29 +470,62 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
console.error("// reduce test pass " + pass + ": " + testcase.length + " bytes");
|
||||
}
|
||||
}
|
||||
testcase = U.minify(testcase, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
beautify: true,
|
||||
braces: true,
|
||||
comments: true,
|
||||
},
|
||||
});
|
||||
testcase.code += [
|
||||
"",
|
||||
"// output: " + to_comment(differs.unminified_result),
|
||||
"// minify: " + to_comment(differs.minified_result),
|
||||
"// options: " + to_comment(minify_options_json),
|
||||
].join("\n").replace(/\u001b\[\d+m/g, "");
|
||||
testcase = try_beautify(result_cache, testcase, minify_options, differs.unminified_result, max_timeout);
|
||||
var lines = [ "" ];
|
||||
var unminified_result = strip_color_codes(differs.unminified_result);
|
||||
var minified_result = strip_color_codes(differs.minified_result);
|
||||
if (trim_trailing_whitespace(unminified_result) == trim_trailing_whitespace(minified_result)) {
|
||||
lines.push(
|
||||
"// (stringified)",
|
||||
"// output: " + JSON.stringify(unminified_result),
|
||||
"// minify: " + JSON.stringify(minified_result)
|
||||
);
|
||||
} else {
|
||||
lines.push(
|
||||
"// output: " + to_comment(unminified_result),
|
||||
"// minify: " + to_comment(minified_result)
|
||||
);
|
||||
}
|
||||
lines.push("// options: " + to_comment(minify_options_json));
|
||||
testcase.code += lines.join("\n");
|
||||
return testcase;
|
||||
}
|
||||
};
|
||||
|
||||
function strip_color_codes(value) {
|
||||
return ("" + value).replace(/\u001b\[\d+m/g, "");
|
||||
}
|
||||
|
||||
function to_comment(value) {
|
||||
return ("" + value).replace(/\n/g, "\n// ");
|
||||
}
|
||||
|
||||
function trim_trailing_whitespace(value) {
|
||||
return ("" + value).replace(/\s+$/, "");
|
||||
}
|
||||
|
||||
function try_beautify(result_cache, testcase, minify_options, expected, timeout) {
|
||||
var result = U.minify(testcase, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
beautify: true,
|
||||
braces: true,
|
||||
comments: true,
|
||||
},
|
||||
});
|
||||
if (result.error) return {
|
||||
code: testcase,
|
||||
};
|
||||
var toplevel = sandbox.has_toplevel(minify_options);
|
||||
var actual = run_code(result_cache, result.code, toplevel, timeout);
|
||||
if (!sandbox.same_stdout(expected, actual)) return {
|
||||
code: testcase,
|
||||
};
|
||||
result.code = "// (beautified)\n" + result.code;
|
||||
return result;
|
||||
}
|
||||
|
||||
function has_exit(fn) {
|
||||
var found = false;
|
||||
var tw = new U.TreeWalker(function(node) {
|
||||
@@ -543,7 +601,7 @@ function producesDifferentResultWhenMinified(result_cache, code, minify_options,
|
||||
var minified = U.minify(code, minify_options);
|
||||
if (minified.error) return minified;
|
||||
|
||||
var toplevel = minify_options.toplevel;
|
||||
var toplevel = sandbox.has_toplevel(minify_options);
|
||||
var elapsed = Date.now();
|
||||
var unminified_result = run_code(result_cache, code, toplevel, max_timeout);
|
||||
elapsed = Date.now() - elapsed;
|
||||
|
||||
@@ -87,3 +87,8 @@ exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expec
|
||||
} : function(expected, 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;
|
||||
};
|
||||
|
||||
@@ -742,6 +742,8 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
||||
return " ((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ") || a || 3).toString() ";
|
||||
case p++:
|
||||
return " /[abc4]/.test(((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ") || b || 5).toString()) ";
|
||||
case p++:
|
||||
return " /[abc4]/g.exec(((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ") || b || 5).toString()) ";
|
||||
case p++:
|
||||
return " ((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) +
|
||||
") || " + rng(10) + ").toString()[" +
|
||||
@@ -1010,7 +1012,7 @@ function log_suspects(minify_options, component) {
|
||||
var defs = default_options[component];
|
||||
var suspects = Object.keys(defs).filter(function(name) {
|
||||
var flip = name == "keep_fargs";
|
||||
if (flip ? name in options : (name in options ? options : defs)[name]) {
|
||||
if (flip === !(name in options ? options : defs)[name]) {
|
||||
var m = JSON.parse(JSON.stringify(minify_options));
|
||||
var o = JSON.parse(JSON.stringify(options));
|
||||
o[name] = flip;
|
||||
@@ -1020,7 +1022,7 @@ function log_suspects(minify_options, component) {
|
||||
errorln("Error testing options." + component + "." + name);
|
||||
errorln(result.error);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
@@ -1034,37 +1036,45 @@ function log_suspects(minify_options, component) {
|
||||
}
|
||||
}
|
||||
|
||||
function log_rename(options) {
|
||||
var m = JSON.parse(JSON.stringify(options));
|
||||
m.rename = false;
|
||||
var result = UglifyJS.minify(original_code, m);
|
||||
if (result.error) {
|
||||
errorln("Error testing options.rename");
|
||||
errorln(result.error);
|
||||
} else {
|
||||
var r = sandbox.run_code(result.code, m.toplevel);
|
||||
if (sandbox.same_stdout(original_result, r)) {
|
||||
errorln("Suspicious options:");
|
||||
errorln(" rename");
|
||||
errorln();
|
||||
function log_suspects_global(options) {
|
||||
var o = {};
|
||||
UglifyJS.minify("", o);
|
||||
var suspects = Object.keys(o).filter(function(component) {
|
||||
return typeof o[component] != "object";
|
||||
}).filter(function(component) {
|
||||
var m = JSON.parse(options);
|
||||
m[component] = false;
|
||||
var result = UglifyJS.minify(original_code, m);
|
||||
if (result.error) {
|
||||
errorln("Error testing options." + component);
|
||||
errorln(result.error);
|
||||
} else {
|
||||
var r = sandbox.run_code(result.code, sandbox.has_toplevel(m));
|
||||
return sandbox.same_stdout(original_result, r);
|
||||
}
|
||||
});
|
||||
if (suspects.length > 0) {
|
||||
errorln("Suspicious options:");
|
||||
suspects.forEach(function(name) {
|
||||
errorln(" " + name);
|
||||
});
|
||||
errorln();
|
||||
}
|
||||
}
|
||||
|
||||
function log(options) {
|
||||
var options_copy = JSON.parse(options);
|
||||
options = JSON.parse(options);
|
||||
var toplevel = sandbox.has_toplevel(JSON.parse(options));
|
||||
if (!ok) errorln("\n\n\n\n\n\n!!!!!!!!!!\n\n\n");
|
||||
errorln("//=============================================================");
|
||||
if (!ok) errorln("// !!!!!! Failed... round " + round);
|
||||
errorln("// original code");
|
||||
try_beautify(original_code, options.toplevel, original_result, errorln);
|
||||
try_beautify(original_code, toplevel, original_result, errorln);
|
||||
errorln();
|
||||
errorln();
|
||||
errorln("//-------------------------------------------------------------");
|
||||
if (typeof uglify_code == "string") {
|
||||
errorln("// uglified code");
|
||||
try_beautify(uglify_code, options.toplevel, uglify_result, errorln);
|
||||
try_beautify(uglify_code, toplevel, uglify_result, errorln);
|
||||
errorln();
|
||||
errorln();
|
||||
errorln("original result:");
|
||||
@@ -1072,7 +1082,7 @@ function log(options) {
|
||||
errorln("uglified result:");
|
||||
errorln(uglify_result);
|
||||
errorln("//-------------------------------------------------------------");
|
||||
var reduced = reduce_test(original_code, options_copy, {
|
||||
var reduced = reduce_test(original_code, JSON.parse(options), {
|
||||
verbose: false,
|
||||
}).code;
|
||||
if (reduced) {
|
||||
@@ -1094,11 +1104,11 @@ function log(options) {
|
||||
}
|
||||
}
|
||||
errorln("minify(options):");
|
||||
errorln(JSON.stringify(options, null, 2));
|
||||
errorln(JSON.stringify(JSON.parse(options), null, 2));
|
||||
errorln();
|
||||
if (!ok && typeof uglify_code == "string") {
|
||||
Object.keys(default_options).forEach(log_suspects.bind(null, options));
|
||||
log_rename(options);
|
||||
Object.keys(default_options).forEach(log_suspects.bind(null, JSON.parse(options)));
|
||||
log_suspects_global(options);
|
||||
errorln("!!!!!! Failed... round " + round);
|
||||
}
|
||||
}
|
||||
@@ -1133,16 +1143,17 @@ for (var round = 1; round <= num_iterations; round++) {
|
||||
if (!errored) orig_result.push(sandbox.run_code(original_code, true));
|
||||
(errored ? fallback_options : minify_options).forEach(function(options) {
|
||||
var o = JSON.parse(options);
|
||||
var toplevel = sandbox.has_toplevel(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) {
|
||||
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);
|
||||
if (!ok && typeof uglify_result == "string" && o.compress.unsafe_math) {
|
||||
ok = fuzzy_match(original_result, uglify_result);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1156,7 +1167,7 @@ for (var round = 1; round <= num_iterations; round++) {
|
||||
else if (errored) {
|
||||
println("//=============================================================");
|
||||
println("// original code");
|
||||
try_beautify(original_code, o.toplevel, original_result, println);
|
||||
try_beautify(original_code, toplevel, original_result, println);
|
||||
println();
|
||||
println();
|
||||
println("original result:");
|
||||
|
||||
Reference in New Issue
Block a user