enhance inline (#5243)
This commit is contained in:
@@ -12778,14 +12778,19 @@ Compressor.prototype.compress = function(node) {
|
|||||||
|
|
||||||
(function(def) {
|
(function(def) {
|
||||||
def(AST_Node, noop);
|
def(AST_Node, noop);
|
||||||
|
def(AST_Await, function(compressor, scope) {
|
||||||
|
return this.expression.try_inline(compressor, scope);
|
||||||
|
});
|
||||||
def(AST_Call, function(compressor, scope) {
|
def(AST_Call, function(compressor, scope) {
|
||||||
if (compressor.option("inline") < 4) return;
|
if (compressor.option("inline") < 4) return;
|
||||||
var call = this;
|
var call = this;
|
||||||
if (call.is_expr_pure(compressor)) return;
|
if (call.is_expr_pure(compressor)) return;
|
||||||
var fn = call.expression;
|
var fn = call.expression;
|
||||||
if (!(fn instanceof AST_Function)) return;
|
if (!(fn instanceof AST_LambdaExpression)) return;
|
||||||
if (fn.name) return;
|
if (fn.name) return;
|
||||||
if (fn.uses_arguments) return;
|
if (fn.uses_arguments) return;
|
||||||
|
if (is_arrow(fn) && fn.value) return;
|
||||||
|
if (is_generator(fn)) return;
|
||||||
if (fn.contains_this()) return;
|
if (fn.contains_this()) return;
|
||||||
if (!scope) scope = find_scope(compressor);
|
if (!scope) scope = find_scope(compressor);
|
||||||
var defined = new Dictionary();
|
var defined = new Dictionary();
|
||||||
@@ -12795,6 +12800,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
});
|
});
|
||||||
scope = scope.parent_scope;
|
scope = scope.parent_scope;
|
||||||
}
|
}
|
||||||
|
if (is_async(fn) && !(compressor.option("awaits") && is_async(scope))) return;
|
||||||
var names = scope.var_names();
|
var names = scope.var_names();
|
||||||
if (!fn.variables.all(function(def, name) {
|
if (!fn.variables.all(function(def, name) {
|
||||||
if (!defined.has(name) && !names.has(name)) return true;
|
if (!defined.has(name) && !names.has(name)) return true;
|
||||||
@@ -12864,9 +12870,16 @@ Compressor.prototype.compress = function(node) {
|
|||||||
syms.each(function(orig, id) {
|
syms.each(function(orig, id) {
|
||||||
[].unshift.apply(defs[id].orig, orig);
|
[].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 })),
|
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) {
|
function process(sym, argname) {
|
||||||
var def = argname.definition();
|
var def = argname.definition();
|
||||||
@@ -12901,11 +12914,31 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
node.value = make_node(AST_UnaryPrefix, self, {
|
node.value = make_node(AST_UnaryPrefix, self, {
|
||||||
operator: op,
|
operator: op,
|
||||||
expression: value || make_node(AST_Undefined, node),
|
expression: value || make_node(AST_Undefined, node).transform(compressor),
|
||||||
}).optimize(compressor);
|
});
|
||||||
});
|
});
|
||||||
return inlined;
|
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) {
|
})(function(node, func) {
|
||||||
node.DEFMETHOD("try_inline", func);
|
node.DEFMETHOD("try_inline", func);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -395,6 +395,253 @@ inline_await_this: {
|
|||||||
node_version: ">=8"
|
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: {
|
await_unary: {
|
||||||
options = {
|
options = {
|
||||||
awaits: true,
|
awaits: true,
|
||||||
|
|||||||
@@ -749,7 +749,7 @@ lift_sequence: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
inline_nested_yield: {
|
inline_nested: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
@@ -784,6 +784,94 @@ inline_nested_yield: {
|
|||||||
node_version: ">=4"
|
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: {
|
dont_inline_nested: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user