fix corner cases with new.target (#4784)
This commit is contained in:
@@ -55,9 +55,10 @@ function DEFNODE(type, props, methods, base) {
|
||||
props.forEach(function(prop) {
|
||||
code.push("this.", prop, "=props.", prop, ";");
|
||||
});
|
||||
code.push("}");
|
||||
var proto = base && new base;
|
||||
if (proto && proto.initialize || methods && methods.initialize) code.push("this.initialize();");
|
||||
code.push("}}");
|
||||
code.push("}");
|
||||
var ctor = new Function(code.join(""))();
|
||||
if (proto) {
|
||||
ctor.prototype = proto;
|
||||
@@ -1818,6 +1819,9 @@ var AST_This = DEFNODE("This", null, {
|
||||
|
||||
var AST_NewTarget = DEFNODE("NewTarget", null, {
|
||||
$documentation: "The `new.target` symbol",
|
||||
initialize: function() {
|
||||
this.name = "new.target";
|
||||
},
|
||||
_validate: function() {
|
||||
if (this.name !== "new.target") throw new Error('name must be "new.target": ' + this.name);
|
||||
},
|
||||
|
||||
@@ -916,7 +916,7 @@ merge(Compressor.prototype, {
|
||||
tw.find_parent(AST_Scope).may_call_this();
|
||||
var exp = this.expression;
|
||||
if (exp instanceof AST_LambdaExpression) {
|
||||
var iife = !exp.name;
|
||||
var iife = is_iife_single(this);
|
||||
this.args.forEach(function(arg) {
|
||||
arg.walk(tw);
|
||||
if (arg instanceof AST_Spread) iife = false;
|
||||
@@ -1591,6 +1591,19 @@ merge(Compressor.prototype, {
|
||||
return node instanceof AST_LambdaExpression ? !is_arrow(node) : is_iife_call(node);
|
||||
}
|
||||
|
||||
function is_iife_single(call) {
|
||||
var exp = call.expression;
|
||||
if (exp.name) return false;
|
||||
if (!(call instanceof AST_New)) return true;
|
||||
var found = false;
|
||||
exp.walk(new TreeWalker(function(node) {
|
||||
if (found) return true;
|
||||
if (node instanceof AST_NewTarget) return found = true;
|
||||
if (node instanceof AST_Scope && node !== exp) return true;
|
||||
}));
|
||||
return !found;
|
||||
}
|
||||
|
||||
function is_undeclared_ref(node) {
|
||||
return node instanceof AST_SymbolRef && node.definition().undeclared;
|
||||
}
|
||||
@@ -2127,11 +2140,11 @@ merge(Compressor.prototype, {
|
||||
var iife, fn = compressor.self();
|
||||
if (fn instanceof AST_LambdaExpression
|
||||
&& !is_generator(fn)
|
||||
&& !fn.name
|
||||
&& !fn.uses_arguments
|
||||
&& !fn.pinned()
|
||||
&& (iife = compressor.parent()) instanceof AST_Call
|
||||
&& iife.expression === fn
|
||||
&& is_iife_single(iife)
|
||||
&& all(iife.args, function(arg) {
|
||||
return !(arg instanceof AST_Spread);
|
||||
})) {
|
||||
|
||||
29
lib/parse.js
29
lib/parse.js
@@ -1737,28 +1737,23 @@ function parse($TEXT, options) {
|
||||
var new_ = function(allow_calls) {
|
||||
var start = S.token;
|
||||
expect_token("operator", "new");
|
||||
var call;
|
||||
if (is("punc", ".") && is_token(peek(), "name", "target")) {
|
||||
next();
|
||||
next();
|
||||
return new AST_NewTarget({
|
||||
name: "new.target",
|
||||
start: start,
|
||||
end: prev(),
|
||||
});
|
||||
}
|
||||
var newexp = expr_atom(false), args;
|
||||
if (is("punc", "(")) {
|
||||
next();
|
||||
args = expr_list(")", !options.strict);
|
||||
call = new AST_NewTarget();
|
||||
} else {
|
||||
args = [];
|
||||
var exp = expr_atom(false), args;
|
||||
if (is("punc", "(")) {
|
||||
next();
|
||||
args = expr_list(")", !options.strict);
|
||||
} else {
|
||||
args = [];
|
||||
}
|
||||
call = new AST_New({ expression: exp, args: args });
|
||||
}
|
||||
var call = new AST_New({
|
||||
start : start,
|
||||
expression : newexp,
|
||||
args : args,
|
||||
end : prev()
|
||||
});
|
||||
call.start = start;
|
||||
call.end = prev();
|
||||
return subscripts(call, allow_calls);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user