зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1784513 - handle decorator member expressions with `.` in them; r=mgaudet
Currently we only support `IdentifierName`, but the grammar allows for multiple `IdentifierName`s separated by `.`: `DecoratorMemberExpression[?Yield, ?Await] . IdentifierName` Differential Revision: https://phabricator.services.mozilla.com/D154814
This commit is contained in:
Родитель
e3b648be1d
Коммит
313af2f09a
|
@ -389,7 +389,7 @@ MSG_DEF(JSMSG_DUPLICATE_ASSERT_KEY, 1, JSEXN_SYNTAXERR, "duplicate assert key
|
|||
MSG_DEF(JSMSG_COLON_AFTER_ASSERT_KEY, 0, JSEXN_SYNTAXERR, "missing : after assert key")
|
||||
MSG_DEF(JSMSG_ASSERT_STRING_LITERAL, 0, JSEXN_SYNTAXERR, "expected string literal")
|
||||
MSG_DEF(JSMSG_ASSERT_KEY_EXPECTED, 0, JSEXN_SYNTAXERR, "expected assertion key")
|
||||
MSG_DEF(JSMSG_DECORATOR_NAME_EXPECTED, 0, JSEXN_SYNTAXERR, "expected decorator name after @")
|
||||
MSG_DEF(JSMSG_DECORATOR_NAME_EXPECTED, 0, JSEXN_SYNTAXERR, "expected property name in decorator expression")
|
||||
MSG_DEF(JSMSG_CLASS_EXPECTED, 0, JSEXN_SYNTAXERR, "expected class")
|
||||
|
||||
// UTF-8 source text encoding errors
|
||||
|
|
|
@ -7671,25 +7671,53 @@ GeneralParser<ParseHandler, Unit>::decoratorList(YieldHandling yieldHandling) {
|
|||
return null();
|
||||
}
|
||||
|
||||
// Handle DecoratorMemberExpression
|
||||
decorator = handler_.newName(name, pos());
|
||||
|
||||
// Ok, this DecoratorMemberExpression is actually a list of
|
||||
// Identifiers separated by `.`
|
||||
if (tt == TokenKind::Dot) {
|
||||
ListNodeType ids =
|
||||
handler_.newList(ParseNodeKind::DecoratorList, pos());
|
||||
handler_.addList(ids, decorator);
|
||||
for (;;) {
|
||||
if (!tokenStream.getToken(&tt)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
// Reject invalid or missing identifiers, like dec1.(
|
||||
if (!(tt == TokenKind::Name || TokenKindIsContextualKeyword(tt))) {
|
||||
error(JSMSG_DECORATOR_NAME_EXPECTED);
|
||||
return null();
|
||||
}
|
||||
TaggedParserAtomIndex name = anyChars.currentName();
|
||||
Node id = handler_.newName(name, pos());
|
||||
handler_.addList(ids, id);
|
||||
|
||||
if (!tokenStream.getToken(&tt)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
if (tt != TokenKind::Dot) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
decorator = ids;
|
||||
}
|
||||
|
||||
// We've hit a `(`, so it's actually a DecoratorCallExpression
|
||||
if (tt == TokenKind::LeftParen) {
|
||||
// Handle DecoratorCallExpression
|
||||
Node decoratorName = handler_.newName(name, pos());
|
||||
bool isSpread = false;
|
||||
Node args = argumentList(yieldHandling, &isSpread);
|
||||
if (!args) {
|
||||
return null();
|
||||
}
|
||||
decorator = handler_.newCall(decoratorName, args,
|
||||
decorator = handler_.newCall(decorator, args,
|
||||
isSpread ? JSOp::SpreadCall : JSOp::Call);
|
||||
|
||||
if (!tokenStream.getToken(&tt)) {
|
||||
return null();
|
||||
}
|
||||
} else {
|
||||
// Handle DecoratorMemberExpression
|
||||
// TODO: Bug 1784513, handle decorator member expressions with `.` in
|
||||
// them.
|
||||
decorator = handler_.newName(name, pos());
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(decorator, "Decorator should exist");
|
||||
|
|
|
@ -18,6 +18,15 @@ Reflect.parse("@dec1('a') @(() => {}) @dec3 class c {@((a, b, c) => {}) @dec2('a
|
|||
Reflect.parse("x = @dec class { #x }");
|
||||
Reflect.parse("x = (class A { }, @dec class { })");
|
||||
Reflect.parse("@dec1 class A extends @dec2 class B extends @dec3 class {} {} {}");
|
||||
Reflect.parse("class c {@dec1.dec2.dec3 method() {};}");
|
||||
Reflect.parse("class c {@dec1 @dec2.dec3.dec4 @dec5 method() {};}");
|
||||
Reflect.parse("class c {@dec1('a') @dec2.dec3.dec4 @dec5 method() {};}");
|
||||
Reflect.parse("class c {@dec1('a') @dec2.dec3.dec4('b', 'c') @dec5 method() {};}");
|
||||
Reflect.parse("class c {@dec1('a') @dec2.dec3.dec4('b', 'c') @dec5.dec6 method() {};}");
|
||||
Reflect.parse("@dec1.dec2 class c {}");
|
||||
Reflect.parse("@dec1.dec2 @dec3.dec4 @dec5 class c {}");
|
||||
Reflect.parse("@dec1.dec2('a') @(() => {}) @dec4 class c {}");
|
||||
Reflect.parse("@dec1.dec2('a') @(() => {}) @dec4 class c {@((a, b, c) => {}) @dec5.dec6('a', 'b') @dec7 method(a, b) {};}");
|
||||
|
||||
assertThrowsInstanceOf(() => Reflect.parse("class c {@ method() {};}"), SyntaxError);
|
||||
assertThrowsInstanceOf(() => Reflect.parse("class c {@((a, b, c => {}) method(a, b) {};}"), SyntaxError);
|
||||
|
@ -27,5 +36,6 @@ assertThrowsInstanceOf(() => Reflect.parse("@dec1 f(a) {}"), SyntaxError);
|
|||
assertThrowsInstanceOf(() => Reflect.parse("@dec1 () => {}"), SyntaxError);
|
||||
assertThrowsInstanceOf(() => Reflect.parse("@class class { x; }"), SyntaxError);
|
||||
assertThrowsInstanceOf(() => Reflect.parse("@for class { x; }"), SyntaxError);
|
||||
|
||||
if (typeof reportCompare === "function") reportCompare(0, 0);
|
||||
assertThrowsInstanceOf(() => Reflect.parse("class c {@dec1. method() {};}"), SyntaxError);
|
||||
assertThrowsInstanceOf(() => Reflect.parse("@dec1. class c {method() {};}"), SyntaxError);
|
||||
assertThrowsInstanceOf(() => Reflect.parse("@dec1.(a) class c {method() {};}"), SyntaxError);
|
||||
|
|
Загрузка…
Ссылка в новой задаче