fix corner cases in optional_chains (#5110)

This commit is contained in:
Alex Lam S.L
2021-08-20 03:10:10 +01:00
committed by GitHub
parent befb99bd71
commit 9634a9d1fd
8 changed files with 228 additions and 93 deletions

View File

@@ -1818,10 +1818,7 @@ function parse($TEXT, options) {
if (is("punc")) {
switch (start.value) {
case "`":
var tmpl = template(null);
tmpl.start = start;
tmpl.end = prev();
return subscripts(tmpl, allow_calls);
return subscripts(template(null), allow_calls);
case "(":
next();
if (is("punc", ")")) {
@@ -2230,6 +2227,7 @@ function parse($TEXT, options) {
}
function template(tag) {
var start = tag ? tag.start : S.token;
var read = S.input.context().read_template;
var strings = [];
var expressions = [];
@@ -2240,58 +2238,60 @@ function parse($TEXT, options) {
}
next();
return new AST_Template({
start: start,
expressions: expressions,
strings: strings,
tag: tag,
end: prev(),
});
}
var subscripts = function(expr, allow_calls, optional) {
function subscripts(expr, allow_calls) {
var start = expr.start;
if (is("punc", "[")) {
next();
var prop = expression();
expect("]");
return subscripts(new AST_Sub({
start: start,
optional: optional,
expression: expr,
property: prop,
end: prev(),
}), allow_calls);
}
if (allow_calls && is("punc", "(")) {
next();
var call = new AST_Call({
start: start,
optional: optional,
expression: expr,
args: expr_list(")", !options.strict),
end: prev(),
});
return subscripts(call, true);
}
if (optional || is("punc", ".")) {
if (!optional) next();
return subscripts(new AST_Dot({
start: start,
optional: optional,
expression: expr,
property: as_name(),
end: prev(),
}), allow_calls);
}
if (is("punc", "`")) {
var tmpl = template(expr);
tmpl.start = expr.start;
tmpl.end = prev();
return subscripts(tmpl, allow_calls);
}
if (is("operator", "?") && is_token(peek(), "punc", ".")) {
next();
next();
return subscripts(expr, allow_calls, true);
var optional = null;
while (true) {
if (is("operator", "?") && is_token(peek(), "punc", ".")) {
next();
next();
optional = expr;
}
if (is("punc", "[")) {
next();
var prop = expression();
expect("]");
expr = new AST_Sub({
start: start,
optional: optional === expr,
expression: expr,
property: prop,
end: prev(),
});
} else if (allow_calls && is("punc", "(")) {
next();
expr = new AST_Call({
start: start,
optional: optional === expr,
expression: expr,
args: expr_list(")", !options.strict),
end: prev(),
});
} else if (optional === expr || is("punc", ".")) {
if (optional !== expr) next();
expr = new AST_Dot({
start: start,
optional: optional === expr,
expression: expr,
property: as_name(),
end: prev(),
});
} else if (is("punc", "`")) {
if (optional) croak("Invalid template on optional chain");
expr = template(expr);
} else {
break;
}
}
if (optional) expr.terminal = true;
if (expr instanceof AST_Call && !expr.pure) {
var start = expr.start;
var comments = start.comments_before;
@@ -2305,7 +2305,7 @@ function parse($TEXT, options) {
}
}
return expr;
};
}
function maybe_unary(no_in) {
var start = S.token;