aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/ast.js7
-rw-r--r--lib/compress.js6
-rw-r--r--lib/minify.js6
-rw-r--r--test/compress.js14
-rw-r--r--test/compress/global_defs.js14
-rw-r--r--test/compress/ie8.js23
-rw-r--r--test/ufuzz/index.js4
7 files changed, 63 insertions, 11 deletions
diff --git a/lib/ast.js b/lib/ast.js
index 31072a08..093e192c 100644
--- a/lib/ast.js
+++ b/lib/ast.js
@@ -120,6 +120,13 @@ var AST_Node = DEFNODE("Node", "start end", {
ctor.prototype._validate.call(this);
} while (ctor = ctor.BASE);
},
+ validate_ast: function() {
+ var marker = {};
+ this.walk(new TreeWalker(function(node) {
+ if (node.validate_visited === marker) throw new Error("invalid node reuse: " + node);
+ node.validate_visited = marker;
+ }));
+ },
}, null);
(AST_Node.log_function = function(fn, verbose) {
diff --git a/lib/compress.js b/lib/compress.js
index 792d5ab2..fbc2bf7d 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -3072,7 +3072,7 @@ merge(Compressor.prototype, {
(function(def) {
function to_node(value, orig) {
- if (value instanceof AST_Node) return make_node(value.CTOR, orig, value);
+ if (value instanceof AST_Node) return value.clone(true);
if (Array.isArray(value)) return make_node(AST_Array, orig, {
elements: value.map(function(value) {
return to_node(value, orig);
@@ -7642,6 +7642,8 @@ merge(Compressor.prototype, {
single_use = false;
} else if (recursive_ref(compressor, def)) {
single_use = false;
+ } else if (compressor.option("ie8") && fixed.name && def !== fixed.name.definition()) {
+ single_use = false;
} else if (def.scope !== self.scope || def.orig[0] instanceof AST_SymbolFunarg) {
single_use = fixed.is_constant_expression(self.scope);
if (single_use == "f") {
@@ -7650,8 +7652,6 @@ merge(Compressor.prototype, {
scope.inlined = true;
} while (scope = scope.parent_scope);
}
- } else if (compressor.option("ie8") && fixed.name && def !== fixed.name.definition()) {
- single_use = false;
}
if (single_use) fixed.parent_scope = self.scope;
} else if (!fixed || !fixed.is_constant_expression()) {
diff --git a/lib/minify.js b/lib/minify.js
index 13d36de0..3817b634 100644
--- a/lib/minify.js
+++ b/lib/minify.js
@@ -178,13 +178,17 @@ function minify(files, options) {
toplevel = toplevel[action](option);
files[toplevel.start.file] = toplevel.print_to_string().replace(orig, "");
});
+ if (options.validate) toplevel.validate_ast();
if (timings) timings.rename = Date.now();
if (options.rename) {
toplevel.figure_out_scope(options.mangle);
toplevel.expand_names(options.mangle);
}
if (timings) timings.compress = Date.now();
- if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel);
+ if (options.compress) {
+ toplevel = new Compressor(options.compress).compress(toplevel);
+ if (options.validate) toplevel.validate_ast();
+ }
if (timings) timings.scope = Date.now();
if (options.mangle) toplevel.figure_out_scope(options.mangle);
if (timings) timings.mangle = Date.now();
diff --git a/test/compress.js b/test/compress.js
index 2fe02806..0afd98a9 100644
--- a/test/compress.js
+++ b/test/compress.js
@@ -269,6 +269,7 @@ function test_case(test) {
quote_style: 3,
});
try {
+ input.validate_ast();
U.parse(input_code);
} catch (ex) {
log([
@@ -315,8 +316,8 @@ function test_case(test) {
output = U.mangle_properties(output, test.mangle.properties);
}
}
- output = make_code(output, output_options);
- if (expect != output) {
+ var output_code = make_code(output, output_options);
+ if (expect != output_code) {
log([
"!!! failed",
"---INPUT---",
@@ -329,14 +330,15 @@ function test_case(test) {
"",
].join("\n"), {
input: input_formatted,
- output: output,
+ output: output_code,
expected: expect
});
return false;
}
// expect == output
try {
- U.parse(output);
+ output.validate_ast();
+ U.parse(output_code);
} catch (ex) {
log([
"!!! Test matched expected result but cannot parse output",
@@ -350,7 +352,7 @@ function test_case(test) {
"",
].join("\n"), {
input: input_formatted,
- output: output,
+ output: output_code,
error: ex,
});
return false;
@@ -409,7 +411,7 @@ function test_case(test) {
});
return false;
}
- actual = run_code(output, toplevel);
+ actual = run_code(output_code, toplevel);
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
log([
"!!! failed",
diff --git a/test/compress/global_defs.js b/test/compress/global_defs.js
index f1ef81d9..006be292 100644
--- a/test/compress/global_defs.js
+++ b/test/compress/global_defs.js
@@ -12,6 +12,20 @@ must_replace: {
}
}
+repeated_nodes: {
+ options = {
+ global_defs: {
+ "@N": "rand()",
+ },
+ }
+ input: {
+ console.log(N, N);
+ }
+ expect: {
+ console.log(rand(), rand());
+ }
+}
+
keyword: {
options = {
global_defs: {
diff --git a/test/compress/ie8.js b/test/compress/ie8.js
index 19437074..6c0aa9e8 100644
--- a/test/compress/ie8.js
+++ b/test/compress/ie8.js
@@ -2691,3 +2691,26 @@ issue_4028: {
}
expect_stdout: "string"
}
+
+issue_2737: {
+ options = {
+ ie8: true,
+ reduce_vars: true,
+ unused: true,
+ }
+ input: {
+ (function(a) {
+ a();
+ })(function f() {
+ console.log(typeof f);
+ });
+ }
+ expect: {
+ (function(a) {
+ a();
+ })(function f() {
+ console.log(typeof f);
+ });
+ }
+ expect_stdout: "function"
+}
diff --git a/test/ufuzz/index.js b/test/ufuzz/index.js
index 8f853c9c..1123d57e 100644
--- a/test/ufuzz/index.js
+++ b/test/ufuzz/index.js
@@ -1148,7 +1148,9 @@ function log(options) {
}
}
errorln("//-------------------------------------------------------------");
- var reduced = reduce_test(original_code, JSON.parse(options), {
+ var reduce_options = JSON.parse(options);
+ reduce_options.validate = true;
+ var reduced = reduce_test(original_code, reduce_options, {
verbose: false,
}).code;
if (reduced) {