hoist_props: implement limited hoisting of class expressions (#2415)

This commit is contained in:
kzc
2017-10-30 11:20:54 -04:00
committed by Alex Lam S.L
parent d535daa2c7
commit 29bbc41dfe
2 changed files with 121 additions and 2 deletions

View File

@@ -619,7 +619,11 @@ merge(Compressor.prototype, {
function mark_escaped(d, node, value, level) { function mark_escaped(d, node, value, level) {
var parent = tw.parent(level); var parent = tw.parent(level);
if (value instanceof AST_Constant || value instanceof AST_Function) return; if (value instanceof AST_Constant
|| value instanceof AST_Function
|| value instanceof AST_ClassExpression) {
return;
}
if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right
|| parent instanceof AST_Call && node !== parent.expression || parent instanceof AST_Call && node !== parent.expression
|| parent instanceof AST_Return && node === parent.value && node.scope !== d.scope || parent instanceof AST_Return && node === parent.value && node.scope !== d.scope
@@ -4043,7 +4047,8 @@ merge(Compressor.prototype, {
function is_object(node) { function is_object(node) {
return node instanceof AST_Array return node instanceof AST_Array
|| node instanceof AST_Lambda || node instanceof AST_Lambda
|| node instanceof AST_Object; || node instanceof AST_Object
|| node instanceof AST_Class;
} }
OPT(AST_Binary, function(self, compressor){ OPT(AST_Binary, function(self, compressor){

View File

@@ -369,3 +369,117 @@ contains_this_3: {
} }
expect_stdout: "1 1 true" expect_stdout: "1 1 true"
} }
hoist_class: {
options = {
comparisons: true,
evaluate: true,
hoist_props: true,
inline: true,
keep_fnames: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function run(c, v) {
return new c(v).value;
}
var o = {
p: class Foo {
constructor(value) {
this.value = value * 10;
}
},
x: 1,
y: 2,
};
console.log(o.p.name, o.p === o.p, run(o.p, o.x), run(o.p, o.y));
}
expect: {
function run(c, v) {
return new c(v).value;
}
var o_p = class Foo {
constructor(value) {
this.value = 10 * value;
}
};
console.log(o_p.name, true, run(o_p, 1), run(o_p, 2));
}
node_version: ">=6"
expect_stdout: "Foo true 10 20"
}
hoist_class_with_new: {
options = {
comparisons: true,
evaluate: true,
hoist_props: true,
inline: true,
keep_fnames: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
p: class Foo {
constructor(value) {
this.value = value * 10;
}
},
x: 1,
y: 2,
};
console.log(o.p.name, o.p === o.p, new o.p(o.x).value, new o.p(o.y).value);
}
expect: {
// FIXME: class `o.p` not hoisted due to `new`
var o = {
p: class Foo {
constructor(value) {
this.value = 10 * value;
}
},
x: 1,
y: 2
};
console.log(o.p.name, o.p == o.p, new o.p(o.x).value, new o.p(o.y).value);
}
node_version: ">=6"
expect_stdout: "Foo true 10 20"
}
hoist_function_with_call: {
options = {
comparisons: true,
evaluate: true,
hoist_props: true,
inline: true,
keep_fnames: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
p: function Foo(value) {
return 10 * value;
},
x: 1,
y: 2
};
console.log(o.p.name, o.p === o.p, o.p(o.x), o.p(o.y));
}
expect: {
var o_p = function Foo(value){
return 10 * value
};
console.log(o_p.name, true, o_p(1), o_p(2));
}
expect_stdout: "Foo true 10 20"
}