зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1351913 - Reduce calls to FindReservedWord when checking for forbidden identifiers during parsing. r=shu
--HG-- extra : rebase_source : 70a24f7c32f062f195167504722891c6df51ee4c
This commit is contained in:
Родитель
92a16eae93
Коммит
0129caa07f
|
@ -1014,12 +1014,15 @@ Parser<ParseHandler>::parse()
|
|||
bool
|
||||
ParserBase::isValidStrictBinding(PropertyName* name)
|
||||
{
|
||||
return name != context->names().eval &&
|
||||
name != context->names().arguments &&
|
||||
name != context->names().let &&
|
||||
name != context->names().static_ &&
|
||||
name != context->names().yield &&
|
||||
!IsStrictReservedWord(name);
|
||||
TokenKind tt = ReservedWordTokenKind(name);
|
||||
if (tt == TOK_NAME) {
|
||||
return name != context->names().eval &&
|
||||
name != context->names().arguments;
|
||||
}
|
||||
return tt != TOK_LET &&
|
||||
tt != TOK_STATIC &&
|
||||
tt != TOK_YIELD &&
|
||||
!TokenKindIsStrictReservedWord(tt);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -9086,75 +9089,80 @@ Parser<ParseHandler>::newName(PropertyName* name, TokenPos pos)
|
|||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::checkLabelOrIdentifierReference(HandlePropertyName ident,
|
||||
Parser<ParseHandler>::checkLabelOrIdentifierReference(PropertyName* ident,
|
||||
uint32_t offset,
|
||||
YieldHandling yieldHandling)
|
||||
YieldHandling yieldHandling,
|
||||
TokenKind hint /* = TOK_LIMIT */)
|
||||
{
|
||||
if (ident == context->names().yield) {
|
||||
if (yieldHandling == YieldIsKeyword ||
|
||||
versionNumber() >= JSVERSION_1_7)
|
||||
{
|
||||
errorAt(offset, JSMSG_RESERVED_ID, "yield");
|
||||
return false;
|
||||
TokenKind tt;
|
||||
if (hint == TOK_LIMIT) {
|
||||
tt = ReservedWordTokenKind(ident);
|
||||
} else {
|
||||
MOZ_ASSERT(hint == ReservedWordTokenKind(ident), "hint doesn't match actual token kind");
|
||||
tt = hint;
|
||||
}
|
||||
|
||||
if (tt == TOK_NAME)
|
||||
return true;
|
||||
if (TokenKindIsContextualKeyword(tt)) {
|
||||
if (tt == TOK_YIELD) {
|
||||
if (yieldHandling == YieldIsKeyword || versionNumber() >= JSVERSION_1_7) {
|
||||
errorAt(offset, JSMSG_RESERVED_ID, "yield");
|
||||
return false;
|
||||
}
|
||||
if (pc->sc()->needStrictChecks()) {
|
||||
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "yield"))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (tt == TOK_AWAIT) {
|
||||
if (awaitIsKeyword()) {
|
||||
errorAt(offset, JSMSG_RESERVED_ID, "await");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (pc->sc()->needStrictChecks()) {
|
||||
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "yield"))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ident == context->names().await) {
|
||||
if (awaitIsKeyword()) {
|
||||
errorAt(offset, JSMSG_RESERVED_ID, "await");
|
||||
return false;
|
||||
if (tt == TOK_LET) {
|
||||
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "let"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (tt == TOK_STATIC) {
|
||||
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "static"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsKeyword(ident) || IsReservedWordLiteral(ident)) {
|
||||
errorAt(offset, JSMSG_INVALID_ID, ReservedWordToCharZ(ident));
|
||||
if (TokenKindIsStrictReservedWord(tt)) {
|
||||
if (pc->sc()->needStrictChecks()) {
|
||||
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(tt)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (TokenKindIsKeyword(tt) || TokenKindIsReservedWordLiteral(tt)) {
|
||||
errorAt(offset, JSMSG_INVALID_ID, ReservedWordToCharZ(tt));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsFutureReservedWord(ident)) {
|
||||
errorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(ident));
|
||||
if (TokenKindIsFutureReservedWord(tt)) {
|
||||
errorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(tt));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pc->sc()->needStrictChecks()) {
|
||||
if (IsStrictReservedWord(ident)) {
|
||||
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(ident)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ident == context->names().let) {
|
||||
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "let"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ident == context->names().static_) {
|
||||
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "static"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected reserved word kind.");
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::checkBindingIdentifier(HandlePropertyName ident,
|
||||
Parser<ParseHandler>::checkBindingIdentifier(PropertyName* ident,
|
||||
uint32_t offset,
|
||||
YieldHandling yieldHandling)
|
||||
YieldHandling yieldHandling,
|
||||
TokenKind hint /* = TOK_LIMIT */)
|
||||
{
|
||||
if (!checkLabelOrIdentifierReference(ident, offset, yieldHandling))
|
||||
return false;
|
||||
|
||||
if (pc->sc()->needStrictChecks()) {
|
||||
if (ident == context->names().arguments) {
|
||||
if (!strictModeErrorAt(offset, JSMSG_BAD_STRICT_ASSIGN, "arguments"))
|
||||
|
@ -9169,7 +9177,7 @@ Parser<ParseHandler>::checkBindingIdentifier(HandlePropertyName ident,
|
|||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return checkLabelOrIdentifierReference(ident, offset, yieldHandling, hint);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
|
@ -9183,8 +9191,13 @@ Parser<ParseHandler>::labelOrIdentifierReference(YieldHandling yieldHandling)
|
|||
//
|
||||
// Use PropertyName* instead of TokenKind to reflect the normalization.
|
||||
|
||||
// Unless the name contains escapes, we can reuse the current TokenKind
|
||||
// to determine if the name is a restricted identifier.
|
||||
TokenKind hint = !tokenStream.currentNameHasEscapes()
|
||||
? tokenStream.currentToken().type
|
||||
: TOK_LIMIT;
|
||||
RootedPropertyName ident(context, tokenStream.currentName());
|
||||
if (!checkLabelOrIdentifierReference(ident, pos().begin, yieldHandling))
|
||||
if (!checkLabelOrIdentifierReference(ident, pos().begin, yieldHandling, hint))
|
||||
return nullptr;
|
||||
return ident;
|
||||
}
|
||||
|
@ -9193,8 +9206,11 @@ template <typename ParseHandler>
|
|||
PropertyName*
|
||||
Parser<ParseHandler>::bindingIdentifier(YieldHandling yieldHandling)
|
||||
{
|
||||
TokenKind hint = !tokenStream.currentNameHasEscapes()
|
||||
? tokenStream.currentToken().type
|
||||
: TOK_LIMIT;
|
||||
RootedPropertyName ident(context, tokenStream.currentName());
|
||||
if (!checkBindingIdentifier(ident, pos().begin, yieldHandling))
|
||||
if (!checkBindingIdentifier(ident, pos().begin, yieldHandling, hint))
|
||||
return nullptr;
|
||||
return ident;
|
||||
}
|
||||
|
|
|
@ -1416,17 +1416,19 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
Node classDefinition(YieldHandling yieldHandling, ClassContext classContext,
|
||||
DefaultHandling defaultHandling);
|
||||
|
||||
bool checkLabelOrIdentifierReference(HandlePropertyName ident,
|
||||
bool checkLabelOrIdentifierReference(PropertyName* ident,
|
||||
uint32_t offset,
|
||||
YieldHandling yieldHandling);
|
||||
YieldHandling yieldHandling,
|
||||
TokenKind hint = TOK_LIMIT);
|
||||
|
||||
bool checkLocalExportName(HandlePropertyName ident, uint32_t offset) {
|
||||
bool checkLocalExportName(PropertyName* ident, uint32_t offset) {
|
||||
return checkLabelOrIdentifierReference(ident, offset, YieldIsName);
|
||||
}
|
||||
|
||||
bool checkBindingIdentifier(HandlePropertyName ident,
|
||||
bool checkBindingIdentifier(PropertyName* ident,
|
||||
uint32_t offset,
|
||||
YieldHandling yieldHandling);
|
||||
YieldHandling yieldHandling,
|
||||
TokenKind hint = TOK_LIMIT);
|
||||
|
||||
PropertyName* labelOrIdentifierReference(YieldHandling yieldHandling);
|
||||
|
||||
|
|
|
@ -194,41 +194,29 @@ frontend::IsKeyword(JSLinearString* str)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
frontend::IsFutureReservedWord(JSLinearString* str)
|
||||
TokenKind
|
||||
frontend::ReservedWordTokenKind(PropertyName* str)
|
||||
{
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str))
|
||||
return TokenKindIsFutureReservedWord(rw->tokentype);
|
||||
return rw->tokentype;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
frontend::IsStrictReservedWord(JSLinearString* str)
|
||||
{
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str))
|
||||
return TokenKindIsStrictReservedWord(rw->tokentype);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
frontend::IsReservedWordLiteral(JSLinearString* str)
|
||||
{
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str))
|
||||
return TokenKindIsReservedWordLiteral(rw->tokentype);
|
||||
|
||||
return false;
|
||||
return TOK_NAME;
|
||||
}
|
||||
|
||||
const char*
|
||||
frontend::ReservedWordToCharZ(PropertyName* str)
|
||||
{
|
||||
const ReservedWordInfo* rw = FindReservedWord(str);
|
||||
if (rw == nullptr)
|
||||
return nullptr;
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str))
|
||||
return ReservedWordToCharZ(rw->tokentype);
|
||||
|
||||
switch (rw->tokentype) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char*
|
||||
frontend::ReservedWordToCharZ(TokenKind tt)
|
||||
{
|
||||
MOZ_ASSERT(tt != TOK_NAME);
|
||||
switch (tt) {
|
||||
#define EMIT_CASE(word, name, type) case type: return js_##word##_str;
|
||||
FOR_EACH_JAVASCRIPT_RESERVED_WORD(EMIT_CASE)
|
||||
#undef EMIT_CASE
|
||||
|
|
|
@ -242,17 +242,14 @@ struct Token
|
|||
}
|
||||
};
|
||||
|
||||
extern TokenKind
|
||||
ReservedWordTokenKind(PropertyName* str);
|
||||
|
||||
extern const char*
|
||||
ReservedWordToCharZ(PropertyName* str);
|
||||
|
||||
extern MOZ_MUST_USE bool
|
||||
IsFutureReservedWord(JSLinearString* str);
|
||||
|
||||
extern MOZ_MUST_USE bool
|
||||
IsReservedWordLiteral(JSLinearString* str);
|
||||
|
||||
extern MOZ_MUST_USE bool
|
||||
IsStrictReservedWord(JSLinearString* str);
|
||||
extern const char*
|
||||
ReservedWordToCharZ(TokenKind tt);
|
||||
|
||||
// Ideally, tokenizing would be entirely independent of context. But the
|
||||
// strict mode flag, which is in SharedContext, affects tokenizing, and
|
||||
|
@ -308,6 +305,16 @@ class TokenStreamBase
|
|||
return reservedWordToPropertyName(currentToken().type);
|
||||
}
|
||||
|
||||
bool currentNameHasEscapes() const {
|
||||
if (isCurrentTokenType(TOK_NAME)) {
|
||||
TokenPos pos = currentToken().pos;
|
||||
return (pos.end - pos.begin) != currentToken().name()->length();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(TokenKindIsPossibleIdentifierName(currentToken().type));
|
||||
return false;
|
||||
}
|
||||
|
||||
PropertyName* nextName() const {
|
||||
if (nextToken().type != TOK_NAME)
|
||||
return nextToken().name();
|
||||
|
|
Загрузка…
Ссылка в новой задаче