1336783 - Part 1: Rework on reserved word and remove TokenStream::KeywordIsName.

This commit is contained in:
Gaming4JC 2019-06-09 16:14:01 -04:00 committed by Roy Tam
commit c1f6b0ff36
15 changed files with 851 additions and 722 deletions

View file

@ -26,14 +26,13 @@
#include "js/UniquePtr.h"
#include "js/Vector.h"
#include "vm/RegExpObject.h"
#include "vm/String.h"
struct KeywordInfo;
namespace js {
namespace frontend {
class AutoAwaitIsKeyword;
struct TokenPos {
uint32_t begin; // Offset of the token's first char.
uint32_t end; // Offset of 1 past the token's last char.
@ -120,9 +119,6 @@ struct Token
// TOK_DIV.
Operand,
// Treat keywords as names by returning TOK_NAME.
KeywordIsName,
// Treat subsequent characters as the tail of a template literal, after
// a template substitution, beginning with a "}", continuing with zero
// or more template literal characters, and ending with either "${" or
@ -164,10 +160,6 @@ struct Token
// If a semicolon is inserted automatically, the next token is already
// gotten with None, but we expect Operand.
OperandIsNone,
// If name of method definition is `get` or `set`, the next token is
// already gotten with KeywordIsName, but we expect None.
NoneIsKeywordIsName,
};
friend class TokenStream;
@ -224,11 +216,6 @@ struct Token
return u.name->JSAtom::asPropertyName(); // poor-man's type verification
}
bool nameContainsEscape() const {
PropertyName* n = name();
return pos.begin + n->length() != pos.end;
}
JSAtom* atom() const {
MOZ_ASSERT(type == TOK_STRING ||
type == TOK_TEMPLATE_HEAD ||
@ -254,10 +241,22 @@ struct Token
};
class CompileError : public JSErrorReport {
public:
public:
void throwError(JSContext* cx);
};
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);
// Ideally, tokenizing would be entirely independent of context. But the
// strict mode flag, which is in SharedContext, affects tokenizing, and
// TokenStream needs to see it.
@ -344,25 +343,26 @@ class MOZ_STACK_CLASS TokenStream
JSVersion versionNumber() const { return VersionNumber(options().version); }
JSVersion versionWithFlags() const { return options().version; }
private:
PropertyName* reservedWordToPropertyName(TokenKind tt) const;
public:
PropertyName* currentName() const {
if (isCurrentTokenType(TOK_YIELD))
return cx->names().yield;
MOZ_ASSERT(isCurrentTokenType(TOK_NAME));
return currentToken().name();
if (isCurrentTokenType(TOK_NAME)) {
return currentToken().name();
}
MOZ_ASSERT(TokenKindIsPossibleIdentifierName(currentToken().type));
return reservedWordToPropertyName(currentToken().type);
}
PropertyName* nextName() const {
if (nextToken().type == TOK_YIELD)
return cx->names().yield;
MOZ_ASSERT(nextToken().type == TOK_NAME);
return nextToken().name();
}
if (nextToken().type != TOK_NAME) {
return nextToken().name();
}
bool nextNameContainsEscape() const {
if (nextToken().type == TOK_YIELD)
return false;
MOZ_ASSERT(nextToken().type == TOK_NAME);
return nextToken().nameContainsEscape();
MOZ_ASSERT(TokenKindIsPossibleIdentifierName(nextToken().type));
return reservedWordToPropertyName(nextToken().type);
}
bool isCurrentTokenAssignment() const {
@ -498,9 +498,6 @@ class MOZ_STACK_CLASS TokenStream
{}
};
bool awaitIsKeyword = false;
friend class AutoAwaitIsKeyword;
uint32_t invalidTemplateEscapeOffset = 0;
InvalidEscapeType invalidTemplateEscapeType = InvalidEscapeType::None;
@ -508,14 +505,12 @@ class MOZ_STACK_CLASS TokenStream
typedef Token::Modifier Modifier;
static constexpr Modifier None = Token::None;
static constexpr Modifier Operand = Token::Operand;
static constexpr Modifier KeywordIsName = Token::KeywordIsName;
static constexpr Modifier TemplateTail = Token::TemplateTail;
typedef Token::ModifierException ModifierException;
static constexpr ModifierException NoException = Token::NoException;
static constexpr ModifierException NoneIsOperand = Token::NoneIsOperand;
static constexpr ModifierException OperandIsNone = Token::OperandIsNone;
static constexpr ModifierException NoneIsKeywordIsName = Token::NoneIsKeywordIsName;
void addModifierException(ModifierException modifierException) {
#ifdef DEBUG
@ -544,10 +539,6 @@ class MOZ_STACK_CLASS TokenStream
MOZ_ASSERT(next.type != TOK_DIV && next.type != TOK_REGEXP,
"next token requires contextual specifier to be parsed unambiguously");
break;
case NoneIsKeywordIsName:
MOZ_ASSERT(next.modifier == KeywordIsName);
MOZ_ASSERT(next.type != TOK_NAME);
break;
default:
MOZ_CRASH("unexpected modifier exception");
}
@ -574,12 +565,6 @@ class MOZ_STACK_CLASS TokenStream
return;
}
if (lookaheadToken.modifierException == NoneIsKeywordIsName) {
// getToken() permissibly following getToken(KeywordIsName).
if (modifier == None && lookaheadToken.modifier == KeywordIsName)
return;
}
MOZ_ASSERT_UNREACHABLE("this token was previously looked up with a "
"different modifier, potentially making "
"tokenization non-deterministic");
@ -714,36 +699,6 @@ class MOZ_STACK_CLASS TokenStream
MOZ_ALWAYS_TRUE(matched);
}
// Like matchToken(..., TOK_NAME) but further matching the name token only
// if it has the given characters, without containing escape sequences.
// If the name token has the given characters yet *does* contain an escape,
// a syntax error will be reported.
//
// This latter behavior makes this method unsuitable for use in any context
// where ASI might occur. In such places, an escaped "contextual keyword"
// on a new line is the start of an ExpressionStatement, not a continuation
// of a StatementListItem (or ImportDeclaration or ExportDeclaration, in
// modules).
MOZ_MUST_USE bool matchContextualKeyword(bool* matchedp, Handle<PropertyName*> keyword,
Modifier modifier = None)
{
TokenKind token;
if (!getToken(&token, modifier))
return false;
if (token == TOK_NAME && currentToken().name() == keyword) {
if (currentToken().nameContainsEscape()) {
reportError(JSMSG_ESCAPED_KEYWORD);
return false;
}
*matchedp = true;
} else {
*matchedp = false;
ungetToken();
}
return true;
}
MOZ_MUST_USE bool nextTokenEndsExpr(bool* endsExpr) {
TokenKind tt;
if (!peekToken(&tt))
@ -809,19 +764,6 @@ class MOZ_STACK_CLASS TokenStream
return sourceMapURL_.get();
}
// If |atom| is not a keyword in this version, return true with *ttp
// unchanged.
//
// If it is a reserved word in this version and strictness mode, and thus
// can't be present in correct code, report a SyntaxError and return false.
//
// If it is a keyword, like "if", return true with the keyword's TokenKind
// in *ttp.
MOZ_MUST_USE bool checkForKeyword(JSAtom* atom, TokenKind* ttp);
// Same semantics as above, but for the provided keyword.
MOZ_MUST_USE bool checkForKeyword(const KeywordInfo* kw, TokenKind* ttp);
// This class maps a userbuf offset (which is 0-indexed) to a line number
// (which is 1-indexed) and a column index (which is 0-indexed).
class SourceCoords
@ -1103,25 +1045,6 @@ class MOZ_STACK_CLASS TokenStream
StrictModeGetter* strictModeGetter; // used to test for strict mode
};
class MOZ_STACK_CLASS AutoAwaitIsKeyword
{
private:
TokenStream* ts_;
bool oldAwaitIsKeyword_;
public:
AutoAwaitIsKeyword(TokenStream* ts, bool awaitIsKeyword) {
ts_ = ts;
oldAwaitIsKeyword_ = ts_->awaitIsKeyword;
ts_->awaitIsKeyword = awaitIsKeyword;
}
~AutoAwaitIsKeyword() {
ts_->awaitIsKeyword = oldAwaitIsKeyword_;
ts_ = nullptr;
}
};
extern const char*
TokenKindToDesc(TokenKind tt);