@@ -6033,7 +6033,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var NO_MERGE = makePredicate("arguments await yield");
|
var NO_MERGE = makePredicate("arguments await yield");
|
||||||
AST_Scope.DEFMETHOD("merge_variables", function(compressor) {
|
AST_Scope.DEFMETHOD("merge_variables", function(compressor) {
|
||||||
if (!compressor.option("merge_vars")) return;
|
if (!compressor.option("merge_vars")) return;
|
||||||
var in_try, root, segment = {}, self = this;
|
var in_arg = [], in_try, root, segment = {}, self = this;
|
||||||
var first = [], last = [], index = 0;
|
var first = [], last = [], index = 0;
|
||||||
var declarations = new Dictionary();
|
var declarations = new Dictionary();
|
||||||
var references = Object.create(null);
|
var references = Object.create(null);
|
||||||
@@ -6183,45 +6183,29 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Scope) {
|
if (node instanceof AST_Scope) {
|
||||||
|
var parent = tw.parent();
|
||||||
|
var in_iife = parent && parent.TYPE == "Call" && parent.expression === node;
|
||||||
|
if (!in_iife) {
|
||||||
push();
|
push();
|
||||||
segment.block = node;
|
segment.block = node;
|
||||||
|
}
|
||||||
if (node === self) root = segment;
|
if (node === self) root = segment;
|
||||||
if (node instanceof AST_Lambda) {
|
if (node instanceof AST_Lambda) {
|
||||||
if (node.name) references[node.name.definition().id] = false;
|
if (node.name) references[node.name.definition().id] = false;
|
||||||
var parent = tw.parent();
|
|
||||||
var in_iife = parent && parent.TYPE == "Call" && parent.expression === node;
|
|
||||||
var marker = node.uses_arguments && !tw.has_directive("use strict") ? function(node) {
|
var marker = node.uses_arguments && !tw.has_directive("use strict") ? function(node) {
|
||||||
if (node instanceof AST_SymbolFunarg) references[node.definition().id] = false;
|
if (node instanceof AST_SymbolFunarg) references[node.definition().id] = false;
|
||||||
} : function(node) {
|
} : function(node) {
|
||||||
if (node instanceof AST_SymbolFunarg) mark(node);
|
if (node instanceof AST_SymbolFunarg) mark(node);
|
||||||
};
|
};
|
||||||
var scanner = new TreeWalker(function(ref) {
|
in_arg.push(node);
|
||||||
if (ref instanceof AST_SymbolDeclaration) references[ref.definition().id] = false;
|
|
||||||
if (!(ref instanceof AST_SymbolRef)) return;
|
|
||||||
var def = ref.definition();
|
|
||||||
var ldef = node.variables.get(ref.name);
|
|
||||||
if (ldef && (ldef === def
|
|
||||||
|| def.undeclared
|
|
||||||
|| node.parent_scope.find_variable(ref.name) === def)) {
|
|
||||||
references[def.id] = false;
|
|
||||||
references[ldef.id] = false;
|
|
||||||
} else if (in_iife) {
|
|
||||||
var save = segment;
|
|
||||||
pop();
|
|
||||||
mark(ref, true);
|
|
||||||
segment = save;
|
|
||||||
} else {
|
|
||||||
mark(ref, true);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
node.argnames.forEach(function(argname) {
|
node.argnames.forEach(function(argname) {
|
||||||
argname.mark_symbol(marker, scanner);
|
argname.mark_symbol(marker, tw);
|
||||||
});
|
});
|
||||||
if (node.rest) node.rest.mark_symbol(marker, scanner);
|
if (node.rest) node.rest.mark_symbol(marker, tw);
|
||||||
|
in_arg.pop();
|
||||||
}
|
}
|
||||||
walk_lambda(node, tw);
|
walk_lambda(node, tw);
|
||||||
pop();
|
if (!in_iife) pop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Sub) {
|
if (node instanceof AST_Sub) {
|
||||||
@@ -6433,7 +6417,16 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mark(sym, read) {
|
function mark(sym, read) {
|
||||||
var def = sym.definition(), ldef, seg = segment;
|
var def = sym.definition(), ldef;
|
||||||
|
if (read && !all(in_arg, function(fn) {
|
||||||
|
ldef = fn.variables.get(sym.name);
|
||||||
|
if (!ldef) return true;
|
||||||
|
if (!is_funarg(ldef)) return true;
|
||||||
|
return ldef !== def
|
||||||
|
&& !def.undeclared
|
||||||
|
&& fn.parent_scope.find_variable(sym.name) !== def;
|
||||||
|
})) return references[def.id] = references[ldef.id] = false;
|
||||||
|
var seg = segment;
|
||||||
if (in_try) {
|
if (in_try) {
|
||||||
push();
|
push();
|
||||||
seg = segment;
|
seg = segment;
|
||||||
|
|||||||
@@ -69,9 +69,7 @@ function make_code(ast, options) {
|
|||||||
function parse_test(file) {
|
function parse_test(file) {
|
||||||
var script = fs.readFileSync(file, "utf8");
|
var script = fs.readFileSync(file, "utf8");
|
||||||
try {
|
try {
|
||||||
var ast = U.parse(script, {
|
var ast = U.parse(script, { filename: file });
|
||||||
filename: file
|
|
||||||
});
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Caught error while parsing tests in " + file);
|
console.error("Caught error while parsing tests in " + file);
|
||||||
console.error(e);
|
console.error(e);
|
||||||
@@ -98,7 +96,7 @@ function parse_test(file) {
|
|||||||
file: file,
|
file: file,
|
||||||
line: node.start.line,
|
line: node.start.line,
|
||||||
col: node.start.col,
|
col: node.start.col,
|
||||||
code: make_code(node, { beautify: false })
|
code: make_code(node, { beautify: false }),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +140,7 @@ function parse_test(file) {
|
|||||||
].indexOf(label.name) >= 0, tmpl("Unsupported label {name} [{line},{col}]", {
|
].indexOf(label.name) >= 0, tmpl("Unsupported label {name} [{line},{col}]", {
|
||||||
name: label.name,
|
name: label.name,
|
||||||
line: label.start.line,
|
line: label.start.line,
|
||||||
col: label.start.col
|
col: label.start.col,
|
||||||
}));
|
}));
|
||||||
var stat = node.body;
|
var stat = node.body;
|
||||||
if (label.name == "expect_exact" || label.name == "node_version") {
|
if (label.name == "expect_exact" || label.name == "node_version") {
|
||||||
@@ -155,12 +153,12 @@ function parse_test(file) {
|
|||||||
var ctor = global[body.expression.name];
|
var ctor = global[body.expression.name];
|
||||||
assert.ok(ctor === Error || ctor.prototype instanceof Error, tmpl("Unsupported expect_stdout format [{line},{col}]", {
|
assert.ok(ctor === Error || ctor.prototype instanceof Error, tmpl("Unsupported expect_stdout format [{line},{col}]", {
|
||||||
line: label.start.line,
|
line: label.start.line,
|
||||||
col: label.start.col
|
col: label.start.col,
|
||||||
}));
|
}));
|
||||||
test[label.name] = ctor.apply(null, body.args.map(function(node) {
|
test[label.name] = ctor.apply(null, body.args.map(function(node) {
|
||||||
assert.ok(node instanceof U.AST_Constant, tmpl("Unsupported expect_stdout format [{line},{col}]", {
|
assert.ok(node instanceof U.AST_Constant, tmpl("Unsupported expect_stdout format [{line},{col}]", {
|
||||||
line: label.start.line,
|
line: label.start.line,
|
||||||
col: label.start.col
|
col: label.start.col,
|
||||||
}));
|
}));
|
||||||
return node.value;
|
return node.value;
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -726,8 +726,8 @@ issue_4401: {
|
|||||||
expect: {
|
expect: {
|
||||||
(function() {
|
(function() {
|
||||||
var a = (b => b(a))(console.log || a);
|
var a = (b => b(a))(console.log || a);
|
||||||
var c = console.log;
|
var a = console.log;
|
||||||
c && c(typeof b);
|
a && a(typeof b);
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
|
|||||||
@@ -184,12 +184,12 @@ merge_vars_2: {
|
|||||||
expect: {
|
expect: {
|
||||||
var a = 0;
|
var a = 0;
|
||||||
1 && --a,
|
1 && --a,
|
||||||
b = function f() {
|
a = function f() {
|
||||||
const c = a && f;
|
const c = a && f;
|
||||||
c.var += 0;
|
c.var += 0;
|
||||||
}(),
|
}(),
|
||||||
void console.log(b);
|
void console.log(a);
|
||||||
var b;
|
var a;
|
||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2239,3 +2239,77 @@ issue_5407: {
|
|||||||
]
|
]
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5444_1: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 42;
|
||||||
|
var b = function({} = setImmediate(function() {
|
||||||
|
console.log(a++);
|
||||||
|
})) {
|
||||||
|
return this;
|
||||||
|
}();
|
||||||
|
console.log(typeof b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 42;
|
||||||
|
var b = function({} = setImmediate(function() {
|
||||||
|
console.log(a++);
|
||||||
|
})) {
|
||||||
|
return this;
|
||||||
|
}();
|
||||||
|
console.log(typeof b);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"object",
|
||||||
|
"42",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5444_2: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b = a++) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
console.log(f("FAIL") || "PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b = a++) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
console.log(f("FAIL") || "PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5444_3: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b = function(c = a *= this) {
|
||||||
|
return c;
|
||||||
|
}()) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
console.log(f("FAIL") || "PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b = function(c = a *= this) {
|
||||||
|
return c;
|
||||||
|
}()) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
console.log(f("FAIL") || "PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1815,8 +1815,8 @@ issue_4288: {
|
|||||||
console.log(typeof b);
|
console.log(typeof b);
|
||||||
}()]: a,
|
}()]: a,
|
||||||
}) {
|
}) {
|
||||||
var b = a;
|
var a = a;
|
||||||
b++;
|
a++;
|
||||||
}
|
}
|
||||||
f(0);
|
f(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -237,12 +237,12 @@ merge_vars_2: {
|
|||||||
"use strict";
|
"use strict";
|
||||||
var a = 0;
|
var a = 0;
|
||||||
1 && --a,
|
1 && --a,
|
||||||
b = function f() {
|
a = function f() {
|
||||||
let c = a && f;
|
let c = a && f;
|
||||||
c.var += 0;
|
c.var += 0;
|
||||||
}(),
|
}(),
|
||||||
void console.log(b);
|
void console.log(a);
|
||||||
var b;
|
var a;
|
||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
|
|||||||
Reference in New Issue
Block a user