enhance inline (#5243)

This commit is contained in:
Alex Lam S.L
2021-12-27 16:53:12 +00:00
committed by GitHub
parent 835d130ccf
commit d51caaf358
3 changed files with 374 additions and 6 deletions

View File

@@ -12778,14 +12778,19 @@ Compressor.prototype.compress = function(node) {
(function(def) {
def(AST_Node, noop);
def(AST_Await, function(compressor, scope) {
return this.expression.try_inline(compressor, scope);
});
def(AST_Call, function(compressor, scope) {
if (compressor.option("inline") < 4) return;
var call = this;
if (call.is_expr_pure(compressor)) return;
var fn = call.expression;
if (!(fn instanceof AST_Function)) return;
if (!(fn instanceof AST_LambdaExpression)) return;
if (fn.name) return;
if (fn.uses_arguments) return;
if (is_arrow(fn) && fn.value) return;
if (is_generator(fn)) return;
if (fn.contains_this()) return;
if (!scope) scope = find_scope(compressor);
var defined = new Dictionary();
@@ -12795,6 +12800,7 @@ Compressor.prototype.compress = function(node) {
});
scope = scope.parent_scope;
}
if (is_async(fn) && !(compressor.option("awaits") && is_async(scope))) return;
var names = scope.var_names();
if (!fn.variables.all(function(def, name) {
if (!defined.has(name) && !names.has(name)) return true;
@@ -12864,9 +12870,16 @@ Compressor.prototype.compress = function(node) {
syms.each(function(orig, id) {
[].unshift.apply(defs[id].orig, orig);
});
return make_node(AST_BlockStatement, call, {
var inlined = make_node(AST_BlockStatement, call, {
body: body.concat(fn.body, make_node(AST_Return, call, { value: null })),
});
if (is_async(fn)) scan_local_returns(inlined, function(node) {
var value = node.value;
if (!value) return;
if (is_undefined(value)) return;
node.value = make_node(AST_Await, call, { expression: value });
});
return inlined;
function process(sym, argname) {
var def = argname.definition();
@@ -12901,11 +12914,31 @@ Compressor.prototype.compress = function(node) {
}
node.value = make_node(AST_UnaryPrefix, self, {
operator: op,
expression: value || make_node(AST_Undefined, node),
}).optimize(compressor);
expression: value || make_node(AST_Undefined, node).transform(compressor),
});
});
return inlined;
})
});
def(AST_Yield, function(compressor, scope) {
if (!compressor.option("yields")) return;
if (!this.nested) return;
var call = this.expression;
if (call.TYPE != "Call") return;
var fn = call.expression;
switch (fn.CTOR) {
case AST_AsyncGeneratorFunction:
fn = make_node(AST_AsyncFunction, fn, fn);
break;
case AST_GeneratorFunction:
fn = make_node(AST_Function, fn, fn);
break;
default:
return;
}
call = call.clone();
call.expression = fn;
return call.try_inline(compressor, scope);
});
})(function(node, func) {
node.DEFMETHOD("try_inline", func);
});

View File

@@ -395,6 +395,253 @@ inline_await_this: {
node_version: ">=8"
}
inline_block: {
options = {
awaits: true,
if_return: true,
inline: true,
}
input: {
console.log("foo");
(async function() {
console.log("bar");
(async function() {
for (var a of [ "baz" ])
return a;
})();
})().then(console.log);
console.log("moo");
}
expect: {
console.log("foo");
(async function() {
console.log("bar");
for (var a of [ "baz" ])
return void await a;
})().then(console.log);
console.log("moo");
}
expect_stdout: [
"foo",
"bar",
"moo",
"undefined",
]
node_version: ">=8"
}
inline_block_async: {
options = {
awaits: true,
if_return: true,
inline: true,
}
input: {
console.log("foo");
(async function() {
console.log("bar");
(async function() {
for (var a of [ "baz" ])
return {
then(r) {
console.log("moo");
r(a);
},
};
})();
})().then(console.log);
console.log("moz");
}
expect: {
console.log("foo");
(async function() {
console.log("bar");
for (var a of [ "baz" ])
return void await {
then(r) {
console.log("moo");
r(a);
},
};
})().then(console.log);
console.log("moz");
}
expect_stdout: [
"foo",
"bar",
"moz",
"moo",
"undefined",
]
node_version: ">=8"
}
inline_block_await: {
options = {
awaits: true,
if_return: true,
inline: true,
}
input: {
console.log("foo");
(async function() {
console.log("bar");
await async function() {
for (var a of [ "baz" ])
return a;
}();
})().then(console.log);
console.log("moo");
}
expect: {
console.log("foo");
(async function() {
console.log("bar");
for (var a of [ "baz" ])
return void await a;
})().then(console.log);
console.log("moo");
}
expect_stdout: [
"foo",
"bar",
"moo",
"undefined",
]
node_version: ">=8"
}
inline_block_await_async: {
options = {
awaits: true,
if_return: true,
inline: true,
}
input: {
console.log("foo");
(async function() {
console.log("bar");
await async function() {
for (var a of [ "baz" ])
return {
then(r) {
console.log("moo");
r(a);
},
};
}();
})().then(console.log);
console.log("moz");
}
expect: {
console.log("foo");
(async function() {
console.log("bar");
for (var a of [ "baz" ])
return void await {
then(r) {
console.log("moo");
r(a);
},
};;
})().then(console.log);
console.log("moz");
}
expect_stdout: [
"foo",
"bar",
"moz",
"moo",
"undefined",
]
node_version: ">=8"
}
inline_block_return: {
options = {
awaits: true,
if_return: true,
inline: true,
passes: 2,
side_effects: true,
}
input: {
console.log("foo");
(async function() {
console.log("bar");
return async function() {
for (var a of [ "baz" ])
return a;
}();
})().then(console.log);
console.log("moo");
}
expect: {
console.log("foo");
(async function() {
console.log("bar");
for (var a of [ "baz" ])
return a;
})().then(console.log);
console.log("moo");
}
expect_stdout: [
"foo",
"bar",
"moo",
"baz",
]
node_version: ">=8"
}
inline_block_return_async: {
options = {
awaits: true,
if_return: true,
inline: true,
passes: 2,
side_effects: true,
}
input: {
console.log("foo");
(async function() {
console.log("bar");
return async function() {
for (var a of [ "baz" ])
return {
then(r) {
console.log("moo");
r(a);
},
};
}();
})().then(console.log);
console.log("moz");
}
expect: {
console.log("foo");
(async function() {
console.log("bar");
for (var a of [ "baz" ])
return {
then(r) {
console.log("moo");
r(a);
},
};
})().then(console.log);
console.log("moz");
}
expect_stdout: [
"foo",
"bar",
"moz",
"moo",
"baz",
]
node_version: ">=8"
}
await_unary: {
options = {
awaits: true,

View File

@@ -749,7 +749,7 @@ lift_sequence: {
node_version: ">=4"
}
inline_nested_yield: {
inline_nested: {
options = {
inline: true,
sequences: true,
@@ -784,6 +784,94 @@ inline_nested_yield: {
node_version: ">=4"
}
inline_nested_async: {
options = {
awaits: true,
inline: true,
sequences: true,
side_effects: true,
yields: true,
}
input: {
console.log("foo");
var a = async function*() {
console.log(await(yield* async function*() {
yield {
then: r => r("bar"),
};
return "baz";
}()));
}();
console.log("moo");
a.next().then(function f(b) {
console.log(b.value);
b.done || a.next().then(f);
});
console.log("moz");
}
expect: {
console.log("foo");
var a = async function*() {
console.log((yield {
then: r => r("bar"),
}, await "baz"));
}();
console.log("moo"),
a.next().then(function f(b) {
console.log(b.value),
b.done || a.next().then(f);
}),
console.log("moz");
}
expect_stdout: [
"foo",
"moo",
"moz",
"bar",
"baz",
"undefined",
]
node_version: ">=10"
}
inline_nested_block: {
options = {
if_return: true,
inline: true,
yields: true,
}
input: {
var a = function*() {
yield* function*() {
for (var a of [ "foo", "bar" ])
yield a;
return "FAIL";
}();
}(), b;
do {
b = a.next();
console.log(b.value);
} while (!b.done);
}
expect: {
var a = function*() {
for (var a of [ "foo", "bar" ])
yield a;
"FAIL";
}(), b;
do {
b = a.next();
console.log(b.value);
} while (!b.done);
}
expect_stdout: [
"foo",
"bar",
"undefined",
]
node_version: ">=4"
}
dont_inline_nested: {
options = {
inline: true,