Check strict mode immediately

* check and convert to strict mode ahead of following tokens
* identifier which has a valid keyword in strict mode is also converted to the complete keyword
* fixes #513

Signed-off-by: HyukWoo Park <hyukwoo.park@samsung.com>
This commit is contained in:
HyukWoo Park 2020-01-07 14:30:24 +09:00 committed by Patrick Kim
commit 47bf20782e
3 changed files with 44 additions and 30 deletions

View file

@ -484,7 +484,7 @@ StringView Scanner::ScannerResult::relatedSource(const StringView& source)
Value Scanner::ScannerResult::valueStringLiteralToValue(Scanner* scannerInstance)
{
if (this->type == Token::KeywordToken && !this->hasKeywordButUseString) {
if (this->type == Token::KeywordToken) {
return keywordToString(scannerInstance->escargotContext, this->valueKeywordKind).string();
}
@ -500,7 +500,7 @@ Value Scanner::ScannerResult::valueStringLiteralToValue(Scanner* scannerInstance
StringView Scanner::ScannerResult::valueStringLiteral(Scanner* scannerInstance)
{
if (this->type == Token::KeywordToken && !this->hasKeywordButUseString) {
if (this->type == Token::KeywordToken) {
AtomicString as = keywordToString(scannerInstance->escargotContext, this->valueKeywordKind);
return StringView(as.string(), 0, as.string()->length());
}

View file

@ -245,7 +245,6 @@ public:
, octal(false)
, hasAllocatedString(false)
, hasNonComputedNumberLiteral(false)
, hasKeywordButUseString(false)
, prec(0)
, lineNumber(0)
, lineStart(0)
@ -263,7 +262,6 @@ public:
bool octal : 1;
bool hasAllocatedString : 1;
bool hasNonComputedNumberLiteral : 1;
bool hasKeywordButUseString : 1;
unsigned char prec : 8; // max prec is 11
// we don't needs init prec.
// prec is initialized by another function before use
@ -304,7 +302,6 @@ public:
this->octal = false;
this->hasAllocatedString = false;
this->hasNonComputedNumberLiteral = false;
this->hasKeywordButUseString = false;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
this->start = start;
@ -319,7 +316,6 @@ public:
this->octal = false;
this->hasAllocatedString = false;
this->hasNonComputedNumberLiteral = false;
this->hasKeywordButUseString = false;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
this->start = start;
@ -334,7 +330,6 @@ public:
this->octal = false;
this->hasAllocatedString = false;
this->hasNonComputedNumberLiteral = false;
this->hasKeywordButUseString = false;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
this->start = start;
@ -347,7 +342,6 @@ public:
this->type = type;
this->startWithZero = false;
this->octal = octal;
this->hasKeywordButUseString = true;
this->hasNonComputedNumberLiteral = false;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
@ -363,7 +357,6 @@ public:
this->type = type;
this->startWithZero = false;
this->octal = octal;
this->hasKeywordButUseString = true;
this->hasNonComputedNumberLiteral = false;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
@ -382,7 +375,6 @@ public:
this->startWithZero = false;
this->octal = false;
this->hasAllocatedString = false;
this->hasKeywordButUseString = true;
this->hasNonComputedNumberLiteral = hasNonComputedNumberLiteral;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
@ -397,7 +389,6 @@ public:
this->startWithZero = false;
this->octal = false;
this->hasAllocatedString = false;
this->hasKeywordButUseString = true;
this->hasNonComputedNumberLiteral = false;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
@ -560,6 +551,34 @@ public:
bool isFutureReservedWord(const StringView& id);
void convertToKeywordInStrictMode(ScannerResult* token)
{
ASSERT(token->type == Token::IdentifierToken);
const StringView& keyword = token->relatedSource(this->source);
if (keyword.equals("let")) {
token->setKeywordResult(token->lineNumber, token->lineStart, token->start, token->end, KeywordKind::LetKeyword);
} else if (keyword.equals("yield")) {
token->setKeywordResult(token->lineNumber, token->lineStart, token->start, token->end, KeywordKind::YieldKeyword);
} else if (keyword.equals("static")) {
token->setKeywordResult(token->lineNumber, token->lineStart, token->start, token->end, KeywordKind::StaticKeyword);
} else if (keyword.equals("public")) {
token->setKeywordResult(token->lineNumber, token->lineStart, token->start, token->end, KeywordKind::PublicKeyword);
} else if (keyword.equals("private")) {
token->setKeywordResult(token->lineNumber, token->lineStart, token->start, token->end, KeywordKind::PrivateKeyword);
} else if (keyword.equals("package")) {
token->setKeywordResult(token->lineNumber, token->lineStart, token->start, token->end, KeywordKind::PackageKeyword);
} else if (keyword.equals("protected")) {
token->setKeywordResult(token->lineNumber, token->lineStart, token->start, token->end, KeywordKind::ProtectedKeyword);
} else if (keyword.equals("interface")) {
token->setKeywordResult(token->lineNumber, token->lineStart, token->start, token->end, KeywordKind::InterfaceKeyword);
} else if (keyword.equals("implements")) {
token->setKeywordResult(token->lineNumber, token->lineStart, token->start, token->end, KeywordKind::ImplementsKeyword);
} else {
RELEASE_ASSERT_NOT_REACHED();
}
}
template <typename T>
bool isStrictModeReservedWord(const T& id)
{

View file

@ -278,7 +278,7 @@ public:
this->hasLineTerminator = false;
if (this->context->strict && next->type == Token::IdentifierToken && this->scanner->isStrictModeReservedWord(next->relatedSource(this->scanner->source))) {
next->type = Token::KeywordToken;
this->scanner->convertToKeywordInStrictMode(next);
}
}
@ -657,7 +657,7 @@ public:
this->hasLineTerminator = tokenLineNumber != next->lineNumber;
if (this->context->strict && next->type == Token::IdentifierToken && this->scanner->isStrictModeReservedWord(next->relatedSource(this->scanner->source))) {
next->type = Token::KeywordToken;
this->scanner->convertToKeywordInStrictMode(next);
}
//this->lookahead = *next;
@ -4548,35 +4548,31 @@ public:
// ECMA-262 14.1.1 Directive Prologues
template <class ASTBuilder>
ASTNode parseDirective(ASTBuilder& builder, bool& useStrict)
ASTNode parseDirective(ASTBuilder& builder)
{
ALLOC_TOKEN(token);
*token = this->lookahead;
bool isLiteral = false;
useStrict = false;
ASSERT(token->type == StringLiteralToken);
// check strict mode early before lexing of following tokens
if (!token->hasAllocatedString && token->valueStringLiteral(this->scanner).equals("use strict")) {
this->currentScopeContext->m_isStrict = this->context->strict = true;
}
MetaNode node = this->createNode();
ASTNode expr = this->parseExpression(builder);
if (expr->type() == Literal) {
isLiteral = true;
if (token->valueStringLiteral(this->scanner).equals("use strict")) {
useStrict = true;
}
}
this->consumeSemicolon();
if (isLiteral) {
if (expr->type() == Literal) {
return this->finalize(node, builder.createDirectiveNode(expr));
} else {
return this->finalize(node, builder.createExpressionStatementNode(expr));
}
return this->finalize(node, builder.createExpressionStatementNode(expr));
}
template <class ASTBuilder>
void parseDirectivePrologues(ASTBuilder& builder, ASTStatementContainer container)
{
ASSERT(container);
bool useStrict = false;
Scanner::SmallScannerResult firstRestricted;
ALLOC_TOKEN(token);
@ -4586,15 +4582,14 @@ public:
break;
}
ASTNode statement = this->parseDirective(builder, useStrict);
ASTNode statement = this->parseDirective(builder);
container->appendChild(statement);
if (statement->type() != Directive) {
break;
}
if (!token->hasAllocatedString && useStrict) {
this->currentScopeContext->m_isStrict = this->context->strict = true;
if (this->context->strict) {
if (firstRestricted) {
this->throwUnexpectedToken(firstRestricted, Messages::StrictOctalLiteral);
}
@ -4856,7 +4851,7 @@ public:
computed = this->match(LeftSquareBracket);
keyNode = this->parseObjectPropertyKey(builder);
if (token->type == Token::KeywordToken && (this->qualifiedPropertyName(&this->lookahead) || this->match(Multiply)) && token->valueStringLiteral(this->scanner) == "static") {
if (token->type == Token::KeywordToken && (this->qualifiedPropertyName(&this->lookahead) || this->match(Multiply)) && token->relatedSource(this->scanner->source) == "static") {
*token = this->lookahead;
isStatic = true;
computed = this->match(LeftSquareBracket);