validate against multiple parents on AST_Node (#4032)
- fix related issues in `global_defs`, `ie8` & `reduce_vars`
This commit is contained in:
@@ -120,6 +120,13 @@ var AST_Node = DEFNODE("Node", "start end", {
|
|||||||
ctor.prototype._validate.call(this);
|
ctor.prototype._validate.call(this);
|
||||||
} while (ctor = ctor.BASE);
|
} 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);
|
}, null);
|
||||||
|
|
||||||
(AST_Node.log_function = function(fn, verbose) {
|
(AST_Node.log_function = function(fn, verbose) {
|
||||||
|
|||||||
@@ -3072,7 +3072,7 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
(function(def) {
|
(function(def) {
|
||||||
function to_node(value, orig) {
|
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, {
|
if (Array.isArray(value)) return make_node(AST_Array, orig, {
|
||||||
elements: value.map(function(value) {
|
elements: value.map(function(value) {
|
||||||
return to_node(value, orig);
|
return to_node(value, orig);
|
||||||
@@ -7642,6 +7642,8 @@ merge(Compressor.prototype, {
|
|||||||
single_use = false;
|
single_use = false;
|
||||||
} else if (recursive_ref(compressor, def)) {
|
} else if (recursive_ref(compressor, def)) {
|
||||||
single_use = false;
|
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) {
|
} else if (def.scope !== self.scope || def.orig[0] instanceof AST_SymbolFunarg) {
|
||||||
single_use = fixed.is_constant_expression(self.scope);
|
single_use = fixed.is_constant_expression(self.scope);
|
||||||
if (single_use == "f") {
|
if (single_use == "f") {
|
||||||
@@ -7650,8 +7652,6 @@ merge(Compressor.prototype, {
|
|||||||
scope.inlined = true;
|
scope.inlined = true;
|
||||||
} while (scope = scope.parent_scope);
|
} 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;
|
if (single_use) fixed.parent_scope = self.scope;
|
||||||
} else if (!fixed || !fixed.is_constant_expression()) {
|
} else if (!fixed || !fixed.is_constant_expression()) {
|
||||||
|
|||||||
@@ -178,13 +178,17 @@ function minify(files, options) {
|
|||||||
toplevel = toplevel[action](option);
|
toplevel = toplevel[action](option);
|
||||||
files[toplevel.start.file] = toplevel.print_to_string().replace(orig, "");
|
files[toplevel.start.file] = toplevel.print_to_string().replace(orig, "");
|
||||||
});
|
});
|
||||||
|
if (options.validate) toplevel.validate_ast();
|
||||||
if (timings) timings.rename = Date.now();
|
if (timings) timings.rename = Date.now();
|
||||||
if (options.rename) {
|
if (options.rename) {
|
||||||
toplevel.figure_out_scope(options.mangle);
|
toplevel.figure_out_scope(options.mangle);
|
||||||
toplevel.expand_names(options.mangle);
|
toplevel.expand_names(options.mangle);
|
||||||
}
|
}
|
||||||
if (timings) timings.compress = Date.now();
|
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 (timings) timings.scope = Date.now();
|
||||||
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
||||||
if (timings) timings.mangle = Date.now();
|
if (timings) timings.mangle = Date.now();
|
||||||
|
|||||||
@@ -269,6 +269,7 @@ function test_case(test) {
|
|||||||
quote_style: 3,
|
quote_style: 3,
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
|
input.validate_ast();
|
||||||
U.parse(input_code);
|
U.parse(input_code);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
log([
|
log([
|
||||||
@@ -315,8 +316,8 @@ function test_case(test) {
|
|||||||
output = U.mangle_properties(output, test.mangle.properties);
|
output = U.mangle_properties(output, test.mangle.properties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output = make_code(output, output_options);
|
var output_code = make_code(output, output_options);
|
||||||
if (expect != output) {
|
if (expect != output_code) {
|
||||||
log([
|
log([
|
||||||
"!!! failed",
|
"!!! failed",
|
||||||
"---INPUT---",
|
"---INPUT---",
|
||||||
@@ -329,14 +330,15 @@ function test_case(test) {
|
|||||||
"",
|
"",
|
||||||
].join("\n"), {
|
].join("\n"), {
|
||||||
input: input_formatted,
|
input: input_formatted,
|
||||||
output: output,
|
output: output_code,
|
||||||
expected: expect
|
expected: expect
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// expect == output
|
// expect == output
|
||||||
try {
|
try {
|
||||||
U.parse(output);
|
output.validate_ast();
|
||||||
|
U.parse(output_code);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
log([
|
log([
|
||||||
"!!! Test matched expected result but cannot parse output",
|
"!!! Test matched expected result but cannot parse output",
|
||||||
@@ -350,7 +352,7 @@ function test_case(test) {
|
|||||||
"",
|
"",
|
||||||
].join("\n"), {
|
].join("\n"), {
|
||||||
input: input_formatted,
|
input: input_formatted,
|
||||||
output: output,
|
output: output_code,
|
||||||
error: ex,
|
error: ex,
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
@@ -409,7 +411,7 @@ function test_case(test) {
|
|||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
actual = run_code(output, toplevel);
|
actual = run_code(output_code, toplevel);
|
||||||
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
|
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
|
||||||
log([
|
log([
|
||||||
"!!! failed",
|
"!!! failed",
|
||||||
|
|||||||
@@ -12,6 +12,20 @@ must_replace: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
repeated_nodes: {
|
||||||
|
options = {
|
||||||
|
global_defs: {
|
||||||
|
"@N": "rand()",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(N, N);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(rand(), rand());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
keyword: {
|
keyword: {
|
||||||
options = {
|
options = {
|
||||||
global_defs: {
|
global_defs: {
|
||||||
|
|||||||
@@ -2691,3 +2691,26 @@ issue_4028: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "string"
|
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"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1148,7 +1148,9 @@ function log(options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
errorln("//-------------------------------------------------------------");
|
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,
|
verbose: false,
|
||||||
}).code;
|
}).code;
|
||||||
if (reduced) {
|
if (reduced) {
|
||||||
|
|||||||
Reference in New Issue
Block a user