improve class compatibility in side_effects (#5279)

This commit is contained in:
Alex Lam S.L
2022-01-09 13:15:42 +00:00
committed by GitHub
parent f473b4db38
commit e9d9d5a9d2
3 changed files with 265 additions and 22 deletions

View File

@@ -8290,17 +8290,26 @@ Compressor.prototype.compress = function(node) {
if (!base && !values) return null; if (!base && !values) return null;
exprs = []; exprs = [];
} }
if (base) { if (base || !compressor.has_directive("use strict")) {
var node = to_class_expr(self, true); var node = to_class_expr(self, true);
if (!base) node.extends = null;
node.properties = []; node.properties = [];
if (exprs.length) node.properties.push(make_node(AST_ClassMethod, self, { if (values) {
key: make_sequence(self, exprs), node.properties.push(make_node(AST_ClassField, self, {
value: make_node(AST_Function, self, { static: true,
argnames: [], key: exprs.length ? make_sequence(self, exprs) : "c",
body: [], value: make_sequence(self, values),
}).init_vars(node), }));
})); } else if (exprs.length) {
exprs = [ node ]; node.properties.push(make_node(AST_ClassMethod, self, {
key: make_sequence(self, exprs),
value: make_node(AST_Function, self, {
argnames: [],
body: [],
}).init_vars(node),
}));
}
return node;
} }
if (values) exprs.push(make_node(AST_Call, self, { if (values) exprs.push(make_node(AST_Call, self, {
expression: make_node(AST_Arrow, self, { expression: make_node(AST_Arrow, self, {

View File

@@ -434,6 +434,33 @@ static_side_effects: {
console.log(a); console.log(a);
} }
expect: { expect: {
var a = "FAIL 1";
(class {
static c = a = "PASS";
});
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=12"
}
static_side_effects_strict: {
options = {
inline: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
var a = "FAIL 1";
class A {
static p = a = "PASS";
q = a = "FAIL 2";
}
console.log(a);
}
expect: {
"use strict";
var a = "FAIL 1"; var a = "FAIL 1";
a = "PASS"; a = "PASS";
console.log(a); console.log(a);
@@ -807,6 +834,33 @@ unused_await: {
})(); })();
} }
expect: { expect: {
var await = "PASS";
(async function() {
(class {
static c = console.log(await);
});
})();
}
expect_stdout: true
node_version: ">=12 <16"
}
unused_await_strict: {
options = {
inline: true,
unused: true,
}
input: {
"use strict";
var await = "PASS";
(async function() {
class A {
static p = console.log(await);
}
})();
}
expect: {
"use strict";
var await = "PASS"; var await = "PASS";
(async function() { (async function() {
(() => console.log(await))(); (() => console.log(await))();
@@ -1149,6 +1203,31 @@ issue_4705: {
} }
} }
expect: { expect: {
(class {
[console.log("PASS")]() {}
});
}
expect_stdout: "PASS"
node_version: ">=12"
}
issue_4705_strict: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
var a = "PASS";
class A {
p = a = "FAIL";
[console.log(a)];
}
}
expect: {
"use strict";
console.log("PASS"); console.log("PASS");
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -1371,9 +1450,40 @@ issue_4756: {
expect: { expect: {
try { try {
(class extends 42 { (class extends 42 {
[console.log("foo")]() {} static [console.log("foo")] = console.log("bar");
}), });
(() => console.log("bar"))(); } catch (e) {
console.log("baz");
}
}
expect_stdout: [
"foo",
"baz",
]
node_version: ">=12"
}
issue_4756_strict: {
options = {
toplevel: true,
unused: true,
}
input: {
"use strict";
try {
class A extends 42 {
static [console.log("foo")] = console.log("bar");
}
} catch (e) {
console.log("baz");
}
}
expect: {
"use strict";
try {
(class extends 42 {
static [console.log("foo")] = console.log("bar");
});
} catch (e) { } catch (e) {
console.log("baz"); console.log("baz");
} }
@@ -1440,7 +1550,7 @@ issue_4829_1: {
input: { input: {
"use strict"; "use strict";
try { try {
class A extends { f(){} }.f {} class A extends { f() {} }.f {}
} catch (e) { } catch (e) {
console.log("PASS"); console.log("PASS");
} }
@@ -1646,6 +1756,37 @@ issue_4962_1: {
})(function g() {}); })(function g() {});
} }
expect: { expect: {
(function g() {}),
void class {
static c = function() {
while (console.log(typeof g));
}();
};
}
expect_stdout: "undefined"
node_version: ">=12"
}
issue_4962_1_strict: {
options = {
ie: true,
inline: true,
reduce_vars: true,
unused: true,
}
input: {
"use strict";
(function() {
function f() {
while (console.log(typeof g));
}
class A {
static p = f();
}
})(function g() {});
}
expect: {
"use strict";
(function g() {}); (function g() {});
while (console.log(typeof g)); while (console.log(typeof g));
} }
@@ -1671,6 +1812,36 @@ issue_4962_2: {
}, typeof g)); }, typeof g));
} }
expect: { expect: {
console.log(function f() {}(function g() {
(class {
static c = f;
});
}));
}
expect_stdout: "undefined"
node_version: ">=12"
}
issue_4962_2_strict: {
options = {
ie: true,
inline: true,
reduce_vars: true,
unused: true,
}
input: {
"use strict";
console.log(function f() {}(function g() {
function h() {
f;
}
class A {
static p = h();
}
}, typeof g));
}
expect: {
"use strict";
console.log(function f() {}(function g() { console.log(function f() {}(function g() {
f; f;
})); }));
@@ -2026,6 +2197,40 @@ issue_5082_1: {
})(); })();
} }
expect: { expect: {
(function() {
class A {
p = console.log("PASS");
q() {}
}
(class {
static c = new A();
});
})();
}
expect_stdout: "PASS"
node_version: ">=12"
}
issue_5082_1_strict: {
options = {
inline: true,
reduce_vars: true,
unused: true,
}
input: {
"use strict";
(function() {
class A {
p = console.log("PASS");
q() {}
}
class B {
static P = new A();
}
})();
}
expect: {
"use strict";
(function() { (function() {
class A { class A {
p = console.log("PASS"); p = console.log("PASS");
@@ -2057,6 +2262,41 @@ issue_5082_2: {
})(); })();
} }
expect: { expect: {
(function() {
class A {
p = console.log("PASS");
q() {}
}
(class {
static c = new A();
});
})();
}
expect_stdout: "PASS"
node_version: ">=12"
}
issue_5082_2_static: {
options = {
inline: true,
passes: 2,
reduce_vars: true,
unused: true,
}
input: {
"use strict";
(function() {
class A {
p = console.log("PASS");
q() {}
}
class B {
static P = new A();
}
})();
}
expect: {
"use strict";
void new class { void new class {
p = console.log("PASS"); p = console.log("PASS");
q() {} q() {}

View File

@@ -2501,7 +2501,7 @@ for (var round = 1; round <= num_iterations; round++) {
} }
} }
// ignore declaration order of global variables // ignore declaration order of global variables
if (!ok && !toplevel) { if (!ok && !toplevel && uglify_result.name != "SyntaxError" && original_result.name != "SyntaxError") {
ok = sandbox.same_stdout(run_code(sort_globals(original_code)), run_code(sort_globals(uglify_code))); ok = sandbox.same_stdout(run_code(sort_globals(original_code)), run_code(sort_globals(uglify_code)));
} }
// ignore numerical imprecision caused by `unsafe_math` // ignore numerical imprecision caused by `unsafe_math`
@@ -2519,14 +2519,8 @@ for (var round = 1; round <= num_iterations; round++) {
// ignore difference in error message caused by Temporal Dead Zone // ignore difference in error message caused by Temporal Dead Zone
if (!ok && errored && uglify_result.name == "ReferenceError" && original_result.name == "ReferenceError") ok = true; if (!ok && errored && uglify_result.name == "ReferenceError" && original_result.name == "ReferenceError") ok = true;
// ignore difference due to implicit strict-mode in `class` // ignore difference due to implicit strict-mode in `class`
if (!ok && /\bclass\b/.test(original_code)) { if (!ok && uglify_result.name == "SyntaxError" && /\bclass\b/.test(original_code)) {
var original_strict = run_code('"use strict";\n' + original_code, toplevel); ok = typeof run_code('"use strict";\n' + original_code, toplevel) != "string";
var uglify_strict = run_code('"use strict";\n' + uglify_code, toplevel);
if (typeof original_strict != "string") {
ok = typeof uglify_strict != "string";
} else {
ok = sandbox.same_stdout(original_strict, uglify_strict);
}
} }
// ignore difference in error message caused by `import` symbol redeclaration // ignore difference in error message caused by `import` symbol redeclaration
if (!ok && errored && /\bimport\b/.test(original_code)) { if (!ok && errored && /\bimport\b/.test(original_code)) {