Diff
Modified: trunk/JSTests/ChangeLog (223021 => 223022)
--- trunk/JSTests/ChangeLog 2017-10-07 19:24:04 UTC (rev 223021)
+++ trunk/JSTests/ChangeLog 2017-10-07 21:16:24 UTC (rev 223022)
@@ -1,3 +1,16 @@
+2017-10-07 Yusuke Suzuki <[email protected]>
+
+ `async` should be able to be used as an imported binding name
+ https://bugs.webkit.org/show_bug.cgi?id=176573
+
+ Reviewed by Darin Adler.
+
+ * modules/import-default-async.js: Added.
+ * modules/import-named-async-as.js: Added.
+ * modules/import-named-async.js: Added.
+ * modules/import-named-async/target.js: Added.
+ * modules/import-namespace-async.js: Added.
+
2017-09-29 Filip Pizlo <[email protected]>
Enable gigacage on iOS
Added: trunk/JSTests/modules/import-default-async.js (0 => 223022)
--- trunk/JSTests/modules/import-default-async.js (rev 0)
+++ trunk/JSTests/modules/import-default-async.js 2017-10-07 21:16:24 UTC (rev 223022)
@@ -0,0 +1,6 @@
+import { shouldBe } from "./resources/assert.js";
+import async from "./import-default-async.js"
+
+export default 42;
+
+shouldBe(async, 42);
Added: trunk/JSTests/modules/import-named-async/target.js (0 => 223022)
--- trunk/JSTests/modules/import-named-async/target.js (rev 0)
+++ trunk/JSTests/modules/import-named-async/target.js 2017-10-07 21:16:24 UTC (rev 223022)
@@ -0,0 +1 @@
+export let async = 42;
Added: trunk/JSTests/modules/import-named-async-as.js (0 => 223022)
--- trunk/JSTests/modules/import-named-async-as.js (rev 0)
+++ trunk/JSTests/modules/import-named-async-as.js 2017-10-07 21:16:24 UTC (rev 223022)
@@ -0,0 +1,6 @@
+import { shouldBe } from "./resources/assert.js";
+import { Cocoa as async } from "./import-named-async-as.js"
+
+export let Cocoa = 42;
+shouldBe(async, 42);
+shouldBe(Cocoa, 42);
Added: trunk/JSTests/modules/import-named-async.js (0 => 223022)
--- trunk/JSTests/modules/import-named-async.js (rev 0)
+++ trunk/JSTests/modules/import-named-async.js 2017-10-07 21:16:24 UTC (rev 223022)
@@ -0,0 +1,4 @@
+import { shouldBe } from "./resources/assert.js";
+import { async } from "./import-named-async/target.js"
+
+shouldBe(async, 42);
Added: trunk/JSTests/modules/import-namespace-async.js (0 => 223022)
--- trunk/JSTests/modules/import-namespace-async.js (rev 0)
+++ trunk/JSTests/modules/import-namespace-async.js 2017-10-07 21:16:24 UTC (rev 223022)
@@ -0,0 +1,5 @@
+import { shouldBe } from "./resources/assert.js";
+import * as async from "./import-namespace-async.js"
+
+export let Cocoa = 42;
+shouldBe(async.Cocoa, 42);
Modified: trunk/Source/_javascript_Core/ChangeLog (223021 => 223022)
--- trunk/Source/_javascript_Core/ChangeLog 2017-10-07 19:24:04 UTC (rev 223021)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-10-07 21:16:24 UTC (rev 223022)
@@ -1,3 +1,34 @@
+2017-10-07 Yusuke Suzuki <[email protected]>
+
+ `async` should be able to be used as an imported binding name
+ https://bugs.webkit.org/show_bug.cgi?id=176573
+
+ Reviewed by Darin Adler.
+
+ Previously, we have ASYNC keyword in the parser. This is introduced only for performance,
+ and ECMA262 spec does not categorize "async" to keyword. This makes parser code complicated,
+ since ASYNC should be handled as IDENT. If we missed this ASYNC keyword, we cause a bug.
+ For example, import declaration failed to bind imported binding to the name "async" because
+ the parser considered ASYNC as keyword.
+
+ This patch removes ASYNC keyword from the parser. By carefully handling ASYNC, we can keep
+ the current performance without using this ASYNC keyword.
+
+ * parser/Keywords.table:
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::parseStatementListItem):
+ (JSC::Parser<LexerType>::parseStatement):
+ (JSC::Parser<LexerType>::maybeParseAsyncFunctionDeclarationStatement):
+ (JSC::Parser<LexerType>::parseClass):
+ (JSC::Parser<LexerType>::parseExportDeclaration):
+ (JSC::Parser<LexerType>::parseAssignmentExpression):
+ (JSC::Parser<LexerType>::parseProperty):
+ (JSC::Parser<LexerType>::parsePrimaryExpression):
+ (JSC::Parser<LexerType>::parseMemberExpression):
+ (JSC::Parser<LexerType>::printUnexpectedTokenText):
+ * parser/ParserTokens.h:
+ * runtime/CommonIdentifiers.h:
+
2017-09-29 Filip Pizlo <[email protected]>
Enable gigacage on iOS
Modified: trunk/Source/_javascript_Core/parser/Keywords.table (223021 => 223022)
--- trunk/Source/_javascript_Core/parser/Keywords.table 2017-10-07 19:24:04 UTC (rev 223021)
+++ trunk/Source/_javascript_Core/parser/Keywords.table 2017-10-07 21:16:24 UTC (rev 223022)
@@ -7,7 +7,6 @@
false FALSETOKEN
# Keywords.
-async ASYNC
await AWAIT
break BREAK
case CASE
Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (223021 => 223022)
--- trunk/Source/_javascript_Core/parser/Parser.cpp 2017-10-07 19:24:04 UTC (rev 223021)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp 2017-10-07 21:16:24 UTC (rev 223022)
@@ -657,19 +657,19 @@
case FUNCTION:
result = parseFunctionDeclaration(context);
break;
- case ASYNC: {
- // Eagerly parse as AsyncFunctionDeclaration. This is the uncommon case,
- // but could be mistakenly parsed as an AsyncFunctionExpression.
- SavePoint savePoint = createSavePoint();
- next();
- if (UNLIKELY(match(FUNCTION) && !m_lexer->prevTerminator())) {
- result = parseAsyncFunctionDeclaration(context);
- break;
+ case IDENT:
+ if (UNLIKELY(*m_token.m_data.ident == m_vm->propertyNames->async)) {
+ // Eagerly parse as AsyncFunctionDeclaration. This is the uncommon case,
+ // but could be mistakenly parsed as an AsyncFunctionExpression.
+ SavePoint savePoint = createSavePoint();
+ next();
+ if (UNLIKELY(match(FUNCTION) && !m_lexer->prevTerminator())) {
+ result = parseAsyncFunctionDeclaration(context);
+ break;
+ }
+ restoreSavePoint(savePoint);
}
- restoreSavePoint(savePoint);
FALLTHROUGH;
- }
- case IDENT:
case AWAIT:
case YIELD: {
// This is a convenient place to notice labeled statements
@@ -1899,11 +1899,12 @@
goto identcase;
goto defaultCase;
}
- case ASYNC:
- if (maybeParseAsyncFunctionDeclarationStatement(context, result, parentAllowsFunctionDeclarationAsStatement))
- break;
+ case IDENT:
+ if (UNLIKELY(*m_token.m_data.ident == m_vm->propertyNames->async)) {
+ if (maybeParseAsyncFunctionDeclarationStatement(context, result, parentAllowsFunctionDeclarationAsStatement))
+ break;
+ }
FALLTHROUGH;
- case IDENT:
case AWAIT:
case YIELD: {
identcase:
@@ -1988,7 +1989,7 @@
template <typename LexerType>
template <class TreeBuilder> bool Parser<LexerType>::maybeParseAsyncFunctionDeclarationStatement(TreeBuilder& context, TreeStatement& result, bool parentAllowsFunctionDeclarationAsStatement)
{
- ASSERT(match(ASYNC));
+ ASSERT(matchContextualKeyword(m_vm->propertyNames->async));
SavePoint savePoint = createSavePoint();
next();
if (match(FUNCTION) && !m_lexer->prevTerminator()) {
@@ -2835,20 +2836,21 @@
ASSERT(ident);
next();
break;
- case ASYNC:
- if (!isGeneratorMethodParseMode(parseMode) && !isAsyncMethodParseMode(parseMode)) {
- ident = m_token.m_data.ident;
- next();
- if (match(OPENPAREN) || match(COLON) || match(EQUAL) || m_lexer->prevTerminator())
- break;
- if (Options::useAsyncIterator() && UNLIKELY(consume(TIMES)))
- parseMode = SourceParseMode::AsyncGeneratorWrapperMethodMode;
- else
- parseMode = SourceParseMode::AsyncMethodMode;
- goto parseMethod;
+ case IDENT:
+ if (UNLIKELY(*m_token.m_data.ident == m_vm->propertyNames->async)) {
+ if (!isGeneratorMethodParseMode(parseMode) && !isAsyncMethodParseMode(parseMode)) {
+ ident = m_token.m_data.ident;
+ next();
+ if (match(OPENPAREN) || match(COLON) || match(EQUAL) || m_lexer->prevTerminator())
+ break;
+ if (Options::useAsyncIterator() && UNLIKELY(consume(TIMES)))
+ parseMode = SourceParseMode::AsyncGeneratorWrapperMethodMode;
+ else
+ parseMode = SourceParseMode::AsyncMethodMode;
+ goto parseMethod;
+ }
}
FALLTHROUGH;
- case IDENT:
case AWAIT:
ident = m_token.m_data.ident;
ASSERT(ident);
@@ -3369,7 +3371,7 @@
if (match(IDENT))
localName = m_token.m_data.ident;
restoreSavePoint(savePoint);
- } else if (match(ASYNC)) {
+ } else if (matchContextualKeyword(m_vm->propertyNames->async)) {
SavePoint savePoint = createSavePoint();
next();
if (match(FUNCTION) && !m_lexer->prevTerminator()) {
@@ -3393,7 +3395,7 @@
} else if (match(CLASSTOKEN)) {
result = parseClassDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::ExportDefault);
} else {
- ASSERT(match(ASYNC));
+ ASSERT(matchContextualKeyword(m_vm->propertyNames->async));
next();
DepthManager statementDepth(&m_statementDepth);
m_statementDepth = 1;
@@ -3514,15 +3516,16 @@
result = parseClassDeclaration(context, ExportType::Exported);
break;
- case ASYNC: {
- next();
- semanticFailIfFalse(match(FUNCTION) && !m_lexer->prevTerminator(), "Expected 'function' keyword following 'async' keyword with no preceding line terminator");
- DepthManager statementDepth(&m_statementDepth);
- m_statementDepth = 1;
- result = parseAsyncFunctionDeclaration(context, ExportType::Exported);
- break;
- }
-
+ case IDENT:
+ if (*m_token.m_data.ident == m_vm->propertyNames->async) {
+ next();
+ semanticFailIfFalse(match(FUNCTION) && !m_lexer->prevTerminator(), "Expected 'function' keyword following 'async' keyword with no preceding line terminator");
+ DepthManager statementDepth(&m_statementDepth);
+ m_statementDepth = 1;
+ result = parseAsyncFunctionDeclaration(context, ExportType::Exported);
+ break;
+ }
+ FALLTHROUGH;
default:
failWithMessage("Expected either a declaration or a variable statement");
break;
@@ -3620,7 +3623,7 @@
restoreSavePoint(savePoint);
bool isAsyncArrow = false;
if (UNLIKELY(classifier.indicatesPossibleAsyncArrowFunction())) {
- ASSERT(match(ASYNC));
+ ASSERT(matchContextualKeyword(m_vm->propertyNames->async));
next();
isAsyncArrow = !m_lexer->prevTerminator();
}
@@ -3888,26 +3891,27 @@
parseProperty:
switch (m_token.m_type) {
- case ASYNC:
- if (parseMode == SourceParseMode::MethodMode) {
- SavePoint savePoint = createSavePoint();
- next();
+ case IDENT:
+ if (UNLIKELY(*m_token.m_data.ident == m_vm->propertyNames->async)) {
+ if (parseMode == SourceParseMode::MethodMode) {
+ SavePoint savePoint = createSavePoint();
+ next();
- if (match(COLON) || match(OPENPAREN) || match(COMMA) || match(CLOSEBRACE)) {
- restoreSavePoint(savePoint);
- wasIdent = true;
- goto namedProperty;
+ if (match(COLON) || match(OPENPAREN) || match(COMMA) || match(CLOSEBRACE)) {
+ restoreSavePoint(savePoint);
+ wasIdent = true;
+ goto namedProperty;
+ }
+
+ failIfTrue(m_lexer->prevTerminator(), "Expected a property name following keyword 'async'");
+ if (Options::useAsyncIterator() && UNLIKELY(consume(TIMES)))
+ parseMode = SourceParseMode::AsyncGeneratorWrapperMethodMode;
+ else
+ parseMode = SourceParseMode::AsyncMethodMode;
+ goto parseProperty;
}
-
- failIfTrue(m_lexer->prevTerminator(), "Expected a property name following keyword 'async'");
- if (Options::useAsyncIterator() && UNLIKELY(consume(TIMES)))
- parseMode = SourceParseMode::AsyncGeneratorWrapperMethodMode;
- else
- parseMode = SourceParseMode::AsyncMethodMode;
- goto parseProperty;
}
FALLTHROUGH;
- case IDENT:
case YIELD:
case AWAIT:
wasIdent = true;
@@ -4445,22 +4449,22 @@
if (m_parserState.functionParsePhase == FunctionParsePhase::Parameters)
failIfFalse(m_parserState.allowAwait, "Cannot use await _expression_ within parameters");
goto identifierExpression;
- case ASYNC: {
- JSTextPosition start = tokenStartPosition();
- const Identifier* ident = m_token.m_data.ident;
- JSTokenLocation location(tokenLocation());
- next();
- if (match(FUNCTION) && !m_lexer->prevTerminator())
- return parseAsyncFunctionExpression(context);
+ case IDENT: {
+ if (UNLIKELY(*m_token.m_data.ident == m_vm->propertyNames->async)) {
+ JSTextPosition start = tokenStartPosition();
+ const Identifier* ident = m_token.m_data.ident;
+ JSTokenLocation location(tokenLocation());
+ next();
+ if (match(FUNCTION) && !m_lexer->prevTerminator())
+ return parseAsyncFunctionExpression(context);
- // Avoid using variable if it is an arrow function parameter
- if (UNLIKELY(match(ARROWFUNCTION)))
- return 0;
+ // Avoid using variable if it is an arrow function parameter
+ if (UNLIKELY(match(ARROWFUNCTION)))
+ return 0;
- const bool isEval = false;
- return createResolveAndUseVariable(context, ident, isEval, start, location);
- }
- case IDENT: {
+ const bool isEval = false;
+ return createResolveAndUseVariable(context, ident, isEval, start, location);
+ }
identifierExpression:
JSTextPosition start = tokenStartPosition();
const Identifier* ident = m_token.m_data.ident;
@@ -4707,7 +4711,7 @@
base = context.createImportExpr(location, expr, expressionStart, expressionEnd, lastTokenEndPosition());
}
} else if (!baseIsNewTarget) {
- const bool isAsync = match(ASYNC);
+ const bool isAsync = matchContextualKeyword(m_vm->propertyNames->async);
base = parsePrimaryExpression(context);
failIfFalse(base, "Cannot parse base _expression_");
@@ -5064,7 +5068,6 @@
out.print("Invalid private name '", getToken(), "'");
return;
- case ASYNC:
case AWAIT:
case IDENT:
out.print("Unexpected identifier '", getToken(), "'");
Modified: trunk/Source/_javascript_Core/parser/ParserTokens.h (223021 => 223022)
--- trunk/Source/_javascript_Core/parser/ParserTokens.h 2017-10-07 19:24:04 UTC (rev 223021)
+++ trunk/Source/_javascript_Core/parser/ParserTokens.h 2017-10-07 21:16:24 UTC (rev 223022)
@@ -93,10 +93,9 @@
LET,
YIELD,
AWAIT,
- ASYNC,
FirstContextualKeywordToken = LET,
- LastContextualKeywordToken = ASYNC,
+ LastContextualKeywordToken = AWAIT,
FirstSafeContextualKeywordToken = AWAIT,
LastSafeContextualKeywordToken = LastContextualKeywordToken,
Modified: trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h (223021 => 223022)
--- trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h 2017-10-07 19:24:04 UTC (rev 223021)
+++ trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h 2017-10-07 21:16:24 UTC (rev 223022)
@@ -79,6 +79,7 @@
macro(arguments) \
macro(as) \
macro(assign) \
+ macro(async) \
macro(back) \
macro(bind) \
macro(buffer) \
@@ -219,7 +220,6 @@
macro(year)
#define JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(macro) \
- macro(async) \
macro(await) \
macro(break) \
macro(case) \