mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 01:08:39 +09:00
1336783 - Part 1: Rework on reserved word and remove TokenStream::KeywordIsName.
This commit is contained in:
parent
2d3bf3352c
commit
c1f6b0ff36
15 changed files with 851 additions and 722 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue