Commit 0d43421a authored by caitpotter88's avatar caitpotter88 Committed by Commit bot

[esnext] implement frontend changes for async/await proposal

BUG=v8:4483
LOG=Y
R=littledan@chromium.org, adamk@chromium.org

Review-Url: https://codereview.chromium.org/1841543003
Cr-Commit-Position: refs/heads/master@{#36261}
parent 9c6ff183
...@@ -242,6 +242,8 @@ class AstValue : public ZoneObject { ...@@ -242,6 +242,8 @@ class AstValue : public ZoneObject {
#define STRING_CONSTANTS(F) \ #define STRING_CONSTANTS(F) \
F(anonymous_function, "(anonymous function)") \ F(anonymous_function, "(anonymous function)") \
F(arguments, "arguments") \ F(arguments, "arguments") \
F(async, "async") \
F(await, "await") \
F(constructor, "constructor") \ F(constructor, "constructor") \
F(default, "default") \ F(default, "default") \
F(done, "done") \ F(done, "done") \
......
...@@ -2587,12 +2587,12 @@ class FunctionLiteral final : public Expression { ...@@ -2587,12 +2587,12 @@ class FunctionLiteral final : public Expression {
int start_position() const; int start_position() const;
int end_position() const; int end_position() const;
int SourceSize() const { return end_position() - start_position(); } int SourceSize() const { return end_position() - start_position(); }
bool is_declaration() const { return IsDeclaration::decode(bitfield_); } bool is_declaration() const { return function_type() == kDeclaration; }
bool is_named_expression() const { bool is_named_expression() const {
return IsNamedExpression::decode(bitfield_); return function_type() == kNamedExpression;
} }
bool is_anonymous_expression() const { bool is_anonymous_expression() const {
return IsAnonymousExpression::decode(bitfield_); return function_type() == kAnonymousExpression;
} }
LanguageMode language_mode() const; LanguageMode language_mode() const;
...@@ -2669,6 +2669,9 @@ class FunctionLiteral final : public Expression { ...@@ -2669,6 +2669,9 @@ class FunctionLiteral final : public Expression {
bitfield_ = ShouldBeUsedOnceHint::update(bitfield_, true); bitfield_ = ShouldBeUsedOnceHint::update(bitfield_, true);
} }
FunctionType function_type() const {
return FunctionTypeBits::decode(bitfield_);
}
FunctionKind kind() const { return FunctionKindBits::decode(bitfield_); } FunctionKind kind() const { return FunctionKindBits::decode(bitfield_); }
int ast_node_count() { return ast_properties_.node_count(); } int ast_node_count() { return ast_properties_.node_count(); }
...@@ -2714,10 +2717,7 @@ class FunctionLiteral final : public Expression { ...@@ -2714,10 +2717,7 @@ class FunctionLiteral final : public Expression {
function_token_position_(RelocInfo::kNoPosition), function_token_position_(RelocInfo::kNoPosition),
yield_count_(0) { yield_count_(0) {
bitfield_ = bitfield_ =
IsDeclaration::encode(function_type == kDeclaration) | FunctionTypeBits::encode(function_type) | Pretenure::encode(false) |
IsNamedExpression::encode(function_type == kNamedExpression) |
IsAnonymousExpression::encode(function_type == kAnonymousExpression) |
Pretenure::encode(false) |
HasDuplicateParameters::encode(has_duplicate_parameters == HasDuplicateParameters::encode(has_duplicate_parameters ==
kHasDuplicateParameters) | kHasDuplicateParameters) |
IsFunction::encode(is_function) | IsFunction::encode(is_function) |
...@@ -2727,15 +2727,13 @@ class FunctionLiteral final : public Expression { ...@@ -2727,15 +2727,13 @@ class FunctionLiteral final : public Expression {
} }
private: private:
class IsDeclaration : public BitField16<bool, 0, 1> {}; class FunctionTypeBits : public BitField16<FunctionType, 0, 2> {};
class IsNamedExpression : public BitField16<bool, 1, 1> {}; class Pretenure : public BitField16<bool, 2, 1> {};
class IsAnonymousExpression : public BitField16<bool, 2, 1> {}; class HasDuplicateParameters : public BitField16<bool, 3, 1> {};
class Pretenure : public BitField16<bool, 3, 1> {}; class IsFunction : public BitField16<bool, 4, 1> {};
class HasDuplicateParameters : public BitField16<bool, 4, 1> {}; class ShouldEagerCompile : public BitField16<bool, 5, 1> {};
class IsFunction : public BitField16<bool, 5, 1> {}; class ShouldBeUsedOnceHint : public BitField16<bool, 6, 1> {};
class ShouldEagerCompile : public BitField16<bool, 6, 1> {}; class FunctionKindBits : public BitField16<FunctionKind, 7, 9> {};
class ShouldBeUsedOnceHint : public BitField16<bool, 7, 1> {};
class FunctionKindBits : public BitField16<FunctionKind, 8, 8> {};
// Start with 16-bit field, which should get packed together // Start with 16-bit field, which should get packed together
// with Expression's trailing 16-bit field. // with Expression's trailing 16-bit field.
......
...@@ -2457,6 +2457,7 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_string_padding) ...@@ -2457,6 +2457,7 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_string_padding)
#ifdef V8_I18N_SUPPORT #ifdef V8_I18N_SUPPORT
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(icu_case_mapping) EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(icu_case_mapping)
#endif #endif
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_async_await)
void InstallPublicSymbol(Factory* factory, Handle<Context> native_context, void InstallPublicSymbol(Factory* factory, Handle<Context> native_context,
const char* name, Handle<Symbol> value) { const char* name, Handle<Symbol> value) {
...@@ -3030,6 +3031,7 @@ bool Genesis::InstallExperimentalNatives() { ...@@ -3030,6 +3031,7 @@ bool Genesis::InstallExperimentalNatives() {
static const char* icu_case_mapping_natives[] = {"native icu-case-mapping.js", static const char* icu_case_mapping_natives[] = {"native icu-case-mapping.js",
nullptr}; nullptr};
#endif #endif
static const char* harmony_async_await_natives[] = {nullptr};
for (int i = ExperimentalNatives::GetDebuggerCount(); for (int i = ExperimentalNatives::GetDebuggerCount();
i < ExperimentalNatives::GetBuiltinsCount(); i++) { i < ExperimentalNatives::GetBuiltinsCount(); i++) {
......
...@@ -204,14 +204,16 @@ DEFINE_IMPLICATION(es_staging, move_object_start) ...@@ -204,14 +204,16 @@ DEFINE_IMPLICATION(es_staging, move_object_start)
V(harmony_simd, "harmony simd") \ V(harmony_simd, "harmony simd") \
V(harmony_do_expressions, "harmony do-expressions") \ V(harmony_do_expressions, "harmony do-expressions") \
V(harmony_regexp_property, "harmony unicode regexp property classes") \ V(harmony_regexp_property, "harmony unicode regexp property classes") \
V(icu_case_mapping, "case mapping with ICU rather than Unibrow") V(icu_case_mapping, "case mapping with ICU rather than Unibrow") \
V(harmony_async_await, "harmony async-await")
#else #else
#define HARMONY_INPROGRESS(V) \ #define HARMONY_INPROGRESS(V) \
V(harmony_function_sent, "harmony function.sent") \ V(harmony_function_sent, "harmony function.sent") \
V(harmony_sharedarraybuffer, "harmony sharedarraybuffer") \ V(harmony_sharedarraybuffer, "harmony sharedarraybuffer") \
V(harmony_simd, "harmony simd") \ V(harmony_simd, "harmony simd") \
V(harmony_do_expressions, "harmony do-expressions") \ V(harmony_do_expressions, "harmony do-expressions") \
V(harmony_regexp_property, "harmony unicode regexp property classes") V(harmony_regexp_property, "harmony unicode regexp property classes") \
V(harmony_async_await, "harmony async-await")
#endif #endif
// Features that are complete (but still behind --harmony/es-staging flag). // Features that are complete (but still behind --harmony/es-staging flag).
......
...@@ -963,11 +963,14 @@ enum FunctionKind { ...@@ -963,11 +963,14 @@ enum FunctionKind {
kBaseConstructor = 1 << 5, kBaseConstructor = 1 << 5,
kGetterFunction = 1 << 6, kGetterFunction = 1 << 6,
kSetterFunction = 1 << 7, kSetterFunction = 1 << 7,
kAsyncFunction = 1 << 8,
kAccessorFunction = kGetterFunction | kSetterFunction, kAccessorFunction = kGetterFunction | kSetterFunction,
kDefaultBaseConstructor = kDefaultConstructor | kBaseConstructor, kDefaultBaseConstructor = kDefaultConstructor | kBaseConstructor,
kDefaultSubclassConstructor = kDefaultConstructor | kSubclassConstructor, kDefaultSubclassConstructor = kDefaultConstructor | kSubclassConstructor,
kClassConstructor = kClassConstructor =
kBaseConstructor | kSubclassConstructor | kDefaultConstructor, kBaseConstructor | kSubclassConstructor | kDefaultConstructor,
kAsyncArrowFunction = kArrowFunction | kAsyncFunction,
kAsyncConciseMethod = kAsyncFunction | kConciseMethod
}; };
inline bool IsValidFunctionKind(FunctionKind kind) { inline bool IsValidFunctionKind(FunctionKind kind) {
...@@ -982,7 +985,10 @@ inline bool IsValidFunctionKind(FunctionKind kind) { ...@@ -982,7 +985,10 @@ inline bool IsValidFunctionKind(FunctionKind kind) {
kind == FunctionKind::kDefaultBaseConstructor || kind == FunctionKind::kDefaultBaseConstructor ||
kind == FunctionKind::kDefaultSubclassConstructor || kind == FunctionKind::kDefaultSubclassConstructor ||
kind == FunctionKind::kBaseConstructor || kind == FunctionKind::kBaseConstructor ||
kind == FunctionKind::kSubclassConstructor; kind == FunctionKind::kSubclassConstructor ||
kind == FunctionKind::kAsyncFunction ||
kind == FunctionKind::kAsyncArrowFunction ||
kind == FunctionKind::kAsyncConciseMethod;
} }
...@@ -997,6 +1003,10 @@ inline bool IsGeneratorFunction(FunctionKind kind) { ...@@ -997,6 +1003,10 @@ inline bool IsGeneratorFunction(FunctionKind kind) {
return kind & FunctionKind::kGeneratorFunction; return kind & FunctionKind::kGeneratorFunction;
} }
inline bool IsAsyncFunction(FunctionKind kind) {
DCHECK(IsValidFunctionKind(kind));
return kind & FunctionKind::kAsyncFunction;
}
inline bool IsConciseMethod(FunctionKind kind) { inline bool IsConciseMethod(FunctionKind kind) {
DCHECK(IsValidFunctionKind(kind)); DCHECK(IsValidFunctionKind(kind));
......
...@@ -358,6 +358,7 @@ class CallSite { ...@@ -358,6 +358,7 @@ class CallSite {
T(BadSetterArity, "Setter must have exactly one formal parameter.") \ T(BadSetterArity, "Setter must have exactly one formal parameter.") \
T(ConstructorIsAccessor, "Class constructor may not be an accessor") \ T(ConstructorIsAccessor, "Class constructor may not be an accessor") \
T(ConstructorIsGenerator, "Class constructor may not be a generator") \ T(ConstructorIsGenerator, "Class constructor may not be a generator") \
T(ConstructorIsAsync, "Class constructor may not be an async method") \
T(DerivedConstructorReturn, \ T(DerivedConstructorReturn, \
"Derived constructors may only return object or undefined") \ "Derived constructors may only return object or undefined") \
T(DuplicateConstructor, "A class may only have one constructor") \ T(DuplicateConstructor, "A class may only have one constructor") \
...@@ -432,6 +433,10 @@ class CallSite { ...@@ -432,6 +433,10 @@ class CallSite {
T(TemplateOctalLiteral, \ T(TemplateOctalLiteral, \
"Octal literals are not allowed in template strings.") \ "Octal literals are not allowed in template strings.") \
T(ThisFormalParameter, "'this' is not a valid formal parameter name") \ T(ThisFormalParameter, "'this' is not a valid formal parameter name") \
T(AwaitBindingIdentifier, \
"'await' is not a valid identifier name in an async function") \
T(AwaitExpressionFormalParameter, \
"Illegal await-expression in formal parameters of async function") \
T(TooManyArguments, \ T(TooManyArguments, \
"Too many arguments in function call (only 65535 allowed)") \ "Too many arguments in function call (only 65535 allowed)") \
T(TooManyParameters, \ T(TooManyParameters, \
......
...@@ -5786,6 +5786,7 @@ BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_crankshaft, ...@@ -5786,6 +5786,7 @@ BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_crankshaft,
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush) BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_arrow, kIsArrow) BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_arrow, kIsArrow)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator) BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_async, kIsAsyncFunction)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_concise_method, BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_concise_method,
kIsConciseMethod) kIsConciseMethod)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_getter_function, BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_getter_function,
...@@ -5795,6 +5796,10 @@ BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_setter_function, ...@@ -5795,6 +5796,10 @@ BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_setter_function,
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_default_constructor, BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_default_constructor,
kIsDefaultConstructor) kIsDefaultConstructor)
inline bool SharedFunctionInfo::is_resumable() const {
return is_generator() || is_async();
}
bool Script::HasValidSource() { bool Script::HasValidSource() {
Object* src = this->source(); Object* src = this->source();
if (!src->IsString()) return true; if (!src->IsString()) return true;
......
...@@ -4295,7 +4295,7 @@ class ScopeInfo : public FixedArray { ...@@ -4295,7 +4295,7 @@ class ScopeInfo : public FixedArray {
class HasSimpleParametersField class HasSimpleParametersField
: public BitField<bool, AsmFunctionField::kNext, 1> {}; : public BitField<bool, AsmFunctionField::kNext, 1> {};
class FunctionKindField class FunctionKindField
: public BitField<FunctionKind, HasSimpleParametersField::kNext, 8> {}; : public BitField<FunctionKind, HasSimpleParametersField::kNext, 9> {};
// BitFields representing the encoded information for context locals in the // BitFields representing the encoded information for context locals in the
// ContextLocalInfoEntries part. // ContextLocalInfoEntries part.
...@@ -6853,6 +6853,13 @@ class SharedFunctionInfo: public HeapObject { ...@@ -6853,6 +6853,13 @@ class SharedFunctionInfo: public HeapObject {
// Indicates that this function is a generator. // Indicates that this function is a generator.
DECL_BOOLEAN_ACCESSORS(is_generator) DECL_BOOLEAN_ACCESSORS(is_generator)
// Indicates that this function is an async function.
DECL_BOOLEAN_ACCESSORS(is_async)
// Indicates that this function can be suspended, either via YieldExpressions
// or AwaitExpressions.
inline bool is_resumable() const;
// Indicates that this function is an arrow function. // Indicates that this function is an arrow function.
DECL_BOOLEAN_ACCESSORS(is_arrow) DECL_BOOLEAN_ACCESSORS(is_arrow)
...@@ -7149,6 +7156,7 @@ class SharedFunctionInfo: public HeapObject { ...@@ -7149,6 +7156,7 @@ class SharedFunctionInfo: public HeapObject {
kIsGetterFunction, kIsGetterFunction,
kIsSetterFunction, kIsSetterFunction,
// byte 3 // byte 3
kIsAsyncFunction,
kDeserialized, kDeserialized,
kIsDeclaration, kIsDeclaration,
kCompilerHintsCount, // Pseudo entry kCompilerHintsCount, // Pseudo entry
...@@ -7171,7 +7179,7 @@ class SharedFunctionInfo: public HeapObject { ...@@ -7171,7 +7179,7 @@ class SharedFunctionInfo: public HeapObject {
ASSERT_FUNCTION_KIND_ORDER(kSetterFunction, kIsSetterFunction); ASSERT_FUNCTION_KIND_ORDER(kSetterFunction, kIsSetterFunction);
#undef ASSERT_FUNCTION_KIND_ORDER #undef ASSERT_FUNCTION_KIND_ORDER
class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 8> {}; class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 9> {};
class DeoptCountBits : public BitField<int, 0, 4> {}; class DeoptCountBits : public BitField<int, 0, 4> {};
class OptReenableTriesBits : public BitField<int, 4, 18> {}; class OptReenableTriesBits : public BitField<int, 4, 18> {};
......
...@@ -40,18 +40,22 @@ class ExpressionClassifier { ...@@ -40,18 +40,22 @@ class ExpressionClassifier {
LetPatternProduction = 1 << 7, LetPatternProduction = 1 << 7,
CoverInitializedNameProduction = 1 << 8, CoverInitializedNameProduction = 1 << 8,
TailCallExpressionProduction = 1 << 9, TailCallExpressionProduction = 1 << 9,
AsyncArrowFormalParametersProduction = 1 << 10,
AsyncBindingPatternProduction = 1 << 11,
ExpressionProductions = ExpressionProductions =
(ExpressionProduction | FormalParameterInitializerProduction | (ExpressionProduction | FormalParameterInitializerProduction |
TailCallExpressionProduction), TailCallExpressionProduction),
PatternProductions = (BindingPatternProduction | PatternProductions =
AssignmentPatternProduction | LetPatternProduction), (BindingPatternProduction | AssignmentPatternProduction |
LetPatternProduction | AsyncBindingPatternProduction),
FormalParametersProductions = (DistinctFormalParametersProduction | FormalParametersProductions = (DistinctFormalParametersProduction |
StrictModeFormalParametersProduction), StrictModeFormalParametersProduction),
StandardProductions = ExpressionProductions | PatternProductions, StandardProductions = ExpressionProductions | PatternProductions,
AllProductions = AllProductions =
(StandardProductions | FormalParametersProductions | (StandardProductions | FormalParametersProductions |
ArrowFormalParametersProduction | CoverInitializedNameProduction) ArrowFormalParametersProduction | CoverInitializedNameProduction |
AsyncArrowFormalParametersProduction | AsyncBindingPatternProduction)
}; };
enum FunctionProperties { NonSimpleParameter = 1 << 0 }; enum FunctionProperties { NonSimpleParameter = 1 << 0 };
...@@ -112,6 +116,14 @@ class ExpressionClassifier { ...@@ -112,6 +116,14 @@ class ExpressionClassifier {
bool is_valid_let_pattern() const { return is_valid(LetPatternProduction); } bool is_valid_let_pattern() const { return is_valid(LetPatternProduction); }
bool is_valid_async_arrow_formal_parameters() const {
return is_valid(AsyncArrowFormalParametersProduction);
}
bool is_valid_async_binding_pattern() const {
return is_valid(AsyncBindingPatternProduction);
}
const Error& expression_error() const { return expression_error_; } const Error& expression_error() const { return expression_error_; }
const Error& formal_parameter_initializer_error() const { const Error& formal_parameter_initializer_error() const {
...@@ -151,6 +163,13 @@ class ExpressionClassifier { ...@@ -151,6 +163,13 @@ class ExpressionClassifier {
const Error& tail_call_expression_error() const { const Error& tail_call_expression_error() const {
return tail_call_expression_error_; return tail_call_expression_error_;
} }
const Error& async_arrow_formal_parameters_error() const {
return async_arrow_formal_parameters_error_;
}
const Error& async_binding_pattern_error() const {
return async_binding_pattern_error_;
}
bool is_simple_parameter_list() const { bool is_simple_parameter_list() const {
return !(function_properties_ & NonSimpleParameter); return !(function_properties_ & NonSimpleParameter);
...@@ -228,6 +247,26 @@ class ExpressionClassifier { ...@@ -228,6 +247,26 @@ class ExpressionClassifier {
arrow_formal_parameters_error_.arg = arg; arrow_formal_parameters_error_.arg = arg;
} }
void RecordAsyncArrowFormalParametersError(const Scanner::Location& loc,
MessageTemplate::Template message,
const char* arg = nullptr) {
if (!is_valid_async_arrow_formal_parameters()) return;
invalid_productions_ |= AsyncArrowFormalParametersProduction;
async_arrow_formal_parameters_error_.location = loc;
async_arrow_formal_parameters_error_.message = message;
async_arrow_formal_parameters_error_.arg = arg;
}
void RecordAsyncBindingPatternError(const Scanner::Location& loc,
MessageTemplate::Template message,
const char* arg = nullptr) {
if (!is_valid_async_binding_pattern()) return;
invalid_productions_ |= AsyncBindingPatternProduction;
async_binding_pattern_error_.location = loc;
async_binding_pattern_error_.message = message;
async_binding_pattern_error_.arg = arg;
}
void RecordDuplicateFormalParameterError(const Scanner::Location& loc) { void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
if (!is_valid_formal_parameter_list_without_duplicates()) return; if (!is_valid_formal_parameter_list_without_duplicates()) return;
invalid_productions_ |= DistinctFormalParametersProduction; invalid_productions_ |= DistinctFormalParametersProduction;
...@@ -326,6 +365,11 @@ class ExpressionClassifier { ...@@ -326,6 +365,11 @@ class ExpressionClassifier {
cover_initialized_name_error_ = inner->cover_initialized_name_error_; cover_initialized_name_error_ = inner->cover_initialized_name_error_;
if (errors & TailCallExpressionProduction) if (errors & TailCallExpressionProduction)
tail_call_expression_error_ = inner->tail_call_expression_error_; tail_call_expression_error_ = inner->tail_call_expression_error_;
if (errors & AsyncArrowFormalParametersProduction)
async_arrow_formal_parameters_error_ =
inner->async_arrow_formal_parameters_error_;
if (errors & AsyncBindingPatternProduction)
async_binding_pattern_error_ = inner->async_binding_pattern_error_;
} }
// As an exception to the above, the result continues to be a valid arrow // As an exception to the above, the result continues to be a valid arrow
...@@ -373,6 +417,8 @@ class ExpressionClassifier { ...@@ -373,6 +417,8 @@ class ExpressionClassifier {
Error let_pattern_error_; Error let_pattern_error_;
Error cover_initialized_name_error_; Error cover_initialized_name_error_;
Error tail_call_expression_error_; Error tail_call_expression_error_;
Error async_arrow_formal_parameters_error_;
Error async_binding_pattern_error_;
DuplicateFinder* duplicate_finder_; DuplicateFinder* duplicate_finder_;
}; };
......
This diff is collapsed.
This diff is collapsed.
...@@ -355,6 +355,7 @@ class ParserTraits { ...@@ -355,6 +355,7 @@ class ParserTraits {
bool IsArguments(const AstRawString* identifier) const; bool IsArguments(const AstRawString* identifier) const;
bool IsEvalOrArguments(const AstRawString* identifier) const; bool IsEvalOrArguments(const AstRawString* identifier) const;
bool IsUndefined(const AstRawString* identifier) const; bool IsUndefined(const AstRawString* identifier) const;
bool IsAwait(const AstRawString* identifier) const;
V8_INLINE bool IsFutureStrictReserved(const AstRawString* identifier) const; V8_INLINE bool IsFutureStrictReserved(const AstRawString* identifier) const;
// Returns true if the expression is of type "this.foo". // Returns true if the expression is of type "this.foo".
...@@ -554,6 +555,8 @@ class ParserTraits { ...@@ -554,6 +555,8 @@ class ParserTraits {
const Scanner::Location& params_loc, const Scanner::Location& params_loc,
Scanner::Location* duplicate_loc, bool* ok); Scanner::Location* duplicate_loc, bool* ok);
V8_INLINE Expression* ParseAsyncFunctionExpression(bool* ok);
V8_INLINE DoExpression* ParseDoExpression(bool* ok); V8_INLINE DoExpression* ParseDoExpression(bool* ok);
void ReindexLiterals(const ParserFormalParameters& parameters); void ReindexLiterals(const ParserFormalParameters& parameters);
...@@ -637,6 +640,8 @@ class ParserTraits { ...@@ -637,6 +640,8 @@ class ParserTraits {
ZoneList<v8::internal::Expression*>* args, ZoneList<v8::internal::Expression*>* args,
int pos); int pos);
Expression* ExpressionListToExpression(ZoneList<Expression*>* args);
// Rewrite all DestructuringAssignments in the current FunctionState. // Rewrite all DestructuringAssignments in the current FunctionState.
V8_INLINE void RewriteDestructuringAssignments(); V8_INLINE void RewriteDestructuringAssignments();
...@@ -645,6 +650,8 @@ class ParserTraits { ...@@ -645,6 +650,8 @@ class ParserTraits {
V8_INLINE Expression* RewriteAssignExponentiation(Expression* left, V8_INLINE Expression* RewriteAssignExponentiation(Expression* left,
Expression* right, int pos); Expression* right, int pos);
V8_INLINE Expression* RewriteAwaitExpression(Expression* value, int pos);
V8_INLINE void QueueDestructuringAssignmentForRewriting( V8_INLINE void QueueDestructuringAssignmentForRewriting(
Expression* assignment); Expression* assignment);
V8_INLINE void QueueNonPatternForRewriting(Expression* expr); V8_INLINE void QueueNonPatternForRewriting(Expression* expr);
...@@ -772,7 +779,13 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -772,7 +779,13 @@ class Parser : public ParserBase<ParserTraits> {
Statement* ParseFunctionDeclaration(bool* ok); Statement* ParseFunctionDeclaration(bool* ok);
Statement* ParseHoistableDeclaration(ZoneList<const AstRawString*>* names, Statement* ParseHoistableDeclaration(ZoneList<const AstRawString*>* names,
bool* ok); bool* ok);
Statement* ParseHoistableDeclaration(int pos, bool is_generator, Statement* ParseHoistableDeclaration(int pos, ParseFunctionFlags flags,
ZoneList<const AstRawString*>* names,
bool* ok);
Statement* ParseAsyncFunctionDeclaration(ZoneList<const AstRawString*>* names,
bool* ok);
Expression* ParseAsyncFunctionExpression(bool* ok);
Statement* ParseFunctionDeclaration(int pos, bool is_generator,
ZoneList<const AstRawString*>* names, ZoneList<const AstRawString*>* names,
bool* ok); bool* ok);
Statement* ParseClassDeclaration(ZoneList<const AstRawString*>* names, Statement* ParseClassDeclaration(ZoneList<const AstRawString*>* names,
...@@ -1255,6 +1268,9 @@ void ParserTraits::AddParameterInitializationBlock( ...@@ -1255,6 +1268,9 @@ void ParserTraits::AddParameterInitializationBlock(
} }
} }
Expression* ParserTraits::ParseAsyncFunctionExpression(bool* ok) {
return parser_->ParseAsyncFunctionExpression(ok);
}
DoExpression* ParserTraits::ParseDoExpression(bool* ok) { DoExpression* ParserTraits::ParseDoExpression(bool* ok) {
return parser_->ParseDoExpression(ok); return parser_->ParseDoExpression(ok);
......
...@@ -51,6 +51,8 @@ PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) { ...@@ -51,6 +51,8 @@ PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
return PreParserIdentifier::Static(); return PreParserIdentifier::Static();
} else if (scanner->current_token() == Token::YIELD) { } else if (scanner->current_token() == Token::YIELD) {
return PreParserIdentifier::Yield(); return PreParserIdentifier::Yield();
} else if (scanner->current_token() == Token::ASYNC) {
return PreParserIdentifier::Async();
} }
if (scanner->UnescapedLiteralMatches("eval", 4)) { if (scanner->UnescapedLiteralMatches("eval", 4)) {
return PreParserIdentifier::Eval(); return PreParserIdentifier::Eval();
...@@ -193,6 +195,13 @@ PreParser::Statement PreParser::ParseStatementListItem(bool* ok) { ...@@ -193,6 +195,13 @@ PreParser::Statement PreParser::ParseStatementListItem(bool* ok) {
return ParseVariableStatement(kStatementListItem, ok); return ParseVariableStatement(kStatementListItem, ok);
} }
break; break;
case Token::ASYNC:
if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION &&
!scanner()->HasAnyLineTerminatorAfterNext()) {
Consume(Token::ASYNC);
return ParseAsyncFunctionDeclaration(ok);
}
/* falls through */
default: default:
break; break;
} }
...@@ -381,22 +390,44 @@ PreParser::Statement PreParser::ParseSubStatement( ...@@ -381,22 +390,44 @@ PreParser::Statement PreParser::ParseSubStatement(
} }
} }
PreParser::Statement PreParser::ParseHoistableDeclaration( PreParser::Statement PreParser::ParseHoistableDeclaration(
int pos, bool is_generator, bool* ok) { int pos, ParseFunctionFlags flags, bool* ok) {
const bool is_generator = flags & ParseFunctionFlags::kIsGenerator;
const bool is_async = flags & ParseFunctionFlags::kIsAsync;
DCHECK(!is_generator || !is_async);
bool is_strict_reserved = false; bool is_strict_reserved = false;
Identifier name = ParseIdentifierOrStrictReservedWord( Identifier name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK); &is_strict_reserved, CHECK_OK);
if (V8_UNLIKELY(is_async_function() && this->IsAwait(name))) {
ReportMessageAt(scanner()->location(),
MessageTemplate::kAwaitBindingIdentifier);
*ok = false;
return Statement::Default();
}
ParseFunctionLiteral(name, scanner()->location(), ParseFunctionLiteral(name, scanner()->location(),
is_strict_reserved ? kFunctionNameIsStrictReserved is_strict_reserved ? kFunctionNameIsStrictReserved
: kFunctionNameValidityUnknown, : kFunctionNameValidityUnknown,
is_generator ? FunctionKind::kGeneratorFunction is_generator ? FunctionKind::kGeneratorFunction
: FunctionKind::kNormalFunction, : is_async ? FunctionKind::kAsyncFunction
: FunctionKind::kNormalFunction,
pos, FunctionLiteral::kDeclaration, language_mode(), pos, FunctionLiteral::kDeclaration, language_mode(),
CHECK_OK); CHECK_OK);
return Statement::FunctionDeclaration(); return Statement::FunctionDeclaration();
} }
PreParser::Statement PreParser::ParseAsyncFunctionDeclaration(bool* ok) {
// AsyncFunctionDeclaration ::
// async [no LineTerminator here] function BindingIdentifier[Await]
// ( FormalParameters[Await] ) { AsyncFunctionBody }
DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
int pos = position();
Expect(Token::FUNCTION, CHECK_OK);
ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync;
return ParseHoistableDeclaration(pos, flags, ok);
}
PreParser::Statement PreParser::ParseHoistableDeclaration(bool* ok) { PreParser::Statement PreParser::ParseHoistableDeclaration(bool* ok) {
// FunctionDeclaration :: // FunctionDeclaration ::
...@@ -404,10 +435,14 @@ PreParser::Statement PreParser::ParseHoistableDeclaration(bool* ok) { ...@@ -404,10 +435,14 @@ PreParser::Statement PreParser::ParseHoistableDeclaration(bool* ok) {
// GeneratorDeclaration :: // GeneratorDeclaration ::
// 'function' '*' Identifier '(' FormalParameterListopt ')' // 'function' '*' Identifier '(' FormalParameterListopt ')'
// '{' FunctionBody '}' // '{' FunctionBody '}'
Expect(Token::FUNCTION, CHECK_OK); Expect(Token::FUNCTION, CHECK_OK);
int pos = position(); int pos = position();
bool is_generator = Check(Token::MUL); ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
return ParseHoistableDeclaration(pos, is_generator, CHECK_OK); if (Check(Token::MUL)) {
flags |= ParseFunctionFlags::kIsGenerator;
}
return ParseHoistableDeclaration(pos, flags, ok);
} }
...@@ -566,15 +601,17 @@ PreParser::Statement PreParser::ParseVariableDeclarations( ...@@ -566,15 +601,17 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
Consume(Token::FUNCTION); Consume(Token::FUNCTION);
int pos = position(); int pos = position();
bool is_generator = Check(Token::MUL); ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
if (allow_harmony_restrictive_declarations() && is_generator) { if (Check(Token::MUL)) {
PreParserTraits::ReportMessageAt( flags |= ParseFunctionFlags::kIsGenerator;
scanner()->location(), if (allow_harmony_restrictive_declarations()) {
MessageTemplate::kGeneratorInLegacyContext); PreParserTraits::ReportMessageAt(
*ok = false; scanner()->location(), MessageTemplate::kGeneratorInLegacyContext);
return Statement::Default(); *ok = false;
return Statement::Default();
}
} }
return ParseHoistableDeclaration(pos, is_generator, ok); return ParseHoistableDeclaration(pos, flags, ok);
} }
PreParser::Statement PreParser::ParseExpressionOrLabelledStatement( PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(
...@@ -1111,6 +1148,37 @@ PreParser::Expression PreParser::ParseFunctionLiteral( ...@@ -1111,6 +1148,37 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
return Expression::Default(); return Expression::Default();
} }
PreParser::Expression PreParser::ParseAsyncFunctionExpression(bool* ok) {
// AsyncFunctionDeclaration ::
// async [no LineTerminator here] function ( FormalParameters[Await] )
// { AsyncFunctionBody }
//
// async [no LineTerminator here] function BindingIdentifier[Await]
// ( FormalParameters[Await] ) { AsyncFunctionBody }
int pos = position();
Expect(Token::FUNCTION, CHECK_OK);
bool is_strict_reserved = false;
Identifier name;
FunctionLiteral::FunctionType type = FunctionLiteral::kAnonymousExpression;
if (peek_any_identifier()) {
type = FunctionLiteral::kNamedExpression;
name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
if (this->IsAwait(name)) {
ReportMessageAt(scanner()->location(),
MessageTemplate::kAwaitBindingIdentifier);
*ok = false;
return Expression::Default();
}
}
ParseFunctionLiteral(name, scanner()->location(),
is_strict_reserved ? kFunctionNameIsStrictReserved
: kFunctionNameValidityUnknown,
FunctionKind::kAsyncFunction, pos, type, language_mode(),
CHECK_OK);
return Expression::Default();
}
void PreParser::ParseLazyFunctionLiteralBody(bool* ok, void PreParser::ParseLazyFunctionLiteralBody(bool* ok,
Scanner::BookmarkScope* bookmark) { Scanner::BookmarkScope* bookmark) {
...@@ -1172,12 +1240,11 @@ PreParserExpression PreParser::ParseClassLiteral( ...@@ -1172,12 +1240,11 @@ PreParserExpression PreParser::ParseClassLiteral(
while (peek() != Token::RBRACE) { while (peek() != Token::RBRACE) {
if (Check(Token::SEMICOLON)) continue; if (Check(Token::SEMICOLON)) continue;
const bool in_class = true; const bool in_class = true;
const bool is_static = false;
bool is_computed_name = false; // Classes do not care about computed bool is_computed_name = false; // Classes do not care about computed
// property names here. // property names here.
Identifier name; Identifier name;
ExpressionClassifier property_classifier(this); ExpressionClassifier property_classifier(this);
ParsePropertyDefinition(&checker, in_class, has_extends, is_static, ParsePropertyDefinition(&checker, in_class, has_extends, MethodKind::Normal,
&is_computed_name, &has_seen_constructor, &is_computed_name, &has_seen_constructor,
&property_classifier, &name, CHECK_OK); &property_classifier, &name, CHECK_OK);
ValidateExpression(&property_classifier, CHECK_OK); ValidateExpression(&property_classifier, CHECK_OK);
......
...@@ -61,6 +61,9 @@ class PreParserIdentifier { ...@@ -61,6 +61,9 @@ class PreParserIdentifier {
static PreParserIdentifier Await() { static PreParserIdentifier Await() {
return PreParserIdentifier(kAwaitIdentifier); return PreParserIdentifier(kAwaitIdentifier);
} }
static PreParserIdentifier Async() {
return PreParserIdentifier(kAsyncIdentifier);
}
bool IsEval() const { return type_ == kEvalIdentifier; } bool IsEval() const { return type_ == kEvalIdentifier; }
bool IsArguments() const { return type_ == kArgumentsIdentifier; } bool IsArguments() const { return type_ == kArgumentsIdentifier; }
bool IsEvalOrArguments() const { return IsEval() || IsArguments(); } bool IsEvalOrArguments() const { return IsEval() || IsArguments(); }
...@@ -72,6 +75,7 @@ class PreParserIdentifier { ...@@ -72,6 +75,7 @@ class PreParserIdentifier {
bool IsConstructor() const { return type_ == kConstructorIdentifier; } bool IsConstructor() const { return type_ == kConstructorIdentifier; }
bool IsEnum() const { return type_ == kEnumIdentifier; } bool IsEnum() const { return type_ == kEnumIdentifier; }
bool IsAwait() const { return type_ == kAwaitIdentifier; } bool IsAwait() const { return type_ == kAwaitIdentifier; }
bool IsAsync() const { return type_ == kAsyncIdentifier; }
bool IsFutureStrictReserved() const { bool IsFutureStrictReserved() const {
return type_ == kFutureStrictReservedIdentifier || return type_ == kFutureStrictReservedIdentifier ||
type_ == kLetIdentifier || type_ == kStaticIdentifier || type_ == kLetIdentifier || type_ == kStaticIdentifier ||
...@@ -100,7 +104,8 @@ class PreParserIdentifier { ...@@ -100,7 +104,8 @@ class PreParserIdentifier {
kPrototypeIdentifier, kPrototypeIdentifier,
kConstructorIdentifier, kConstructorIdentifier,
kEnumIdentifier, kEnumIdentifier,
kAwaitIdentifier kAwaitIdentifier,
kAsyncIdentifier
}; };
explicit PreParserIdentifier(Type type) : type_(type) {} explicit PreParserIdentifier(Type type) : type_(type) {}
...@@ -622,6 +627,14 @@ class PreParserTraits { ...@@ -622,6 +627,14 @@ class PreParserTraits {
return identifier.IsArguments(); return identifier.IsArguments();
} }
static bool IsAwait(PreParserIdentifier identifier) {
return identifier.IsAwait();
}
static bool IsAsync(PreParserIdentifier identifier) {
return identifier.IsAsync();
}
static bool IsEvalOrArguments(PreParserIdentifier identifier) { static bool IsEvalOrArguments(PreParserIdentifier identifier) {
return identifier.IsEvalOrArguments(); return identifier.IsEvalOrArguments();
} }
...@@ -865,6 +878,8 @@ class PreParserTraits { ...@@ -865,6 +878,8 @@ class PreParserTraits {
PreParserExpression expression, const Scanner::Location& params_loc, PreParserExpression expression, const Scanner::Location& params_loc,
Scanner::Location* duplicate_loc, bool* ok); Scanner::Location* duplicate_loc, bool* ok);
V8_INLINE PreParserExpression ParseAsyncFunctionExpression(bool* ok);
void ReindexLiterals(const PreParserFormalParameters& paramaters) {} void ReindexLiterals(const PreParserFormalParameters& paramaters) {}
struct TemplateLiteralState {}; struct TemplateLiteralState {};
...@@ -937,6 +952,11 @@ class PreParserTraits { ...@@ -937,6 +952,11 @@ class PreParserTraits {
PreParserExpressionList args, PreParserExpressionList args,
int pos); int pos);
inline PreParserExpression ExpressionListToExpression(
PreParserExpressionList args) {
return PreParserExpression::Default();
}
inline void RewriteDestructuringAssignments() {} inline void RewriteDestructuringAssignments() {}
inline PreParserExpression RewriteExponentiation(PreParserExpression left, inline PreParserExpression RewriteExponentiation(PreParserExpression left,
...@@ -960,6 +980,9 @@ class PreParserTraits { ...@@ -960,6 +980,9 @@ class PreParserTraits {
inline void RewriteNonPattern(Type::ExpressionClassifier* classifier, inline void RewriteNonPattern(Type::ExpressionClassifier* classifier,
bool* ok); bool* ok);
inline PreParserExpression RewriteAwaitExpression(PreParserExpression value,
int pos);
V8_INLINE Zone* zone() const; V8_INLINE Zone* zone() const;
V8_INLINE ZoneList<PreParserExpression>* GetNonPatternList() const; V8_INLINE ZoneList<PreParserExpression>* GetNonPatternList() const;
...@@ -1076,8 +1099,11 @@ class PreParser : public ParserBase<PreParserTraits> { ...@@ -1076,8 +1099,11 @@ class PreParser : public ParserBase<PreParserTraits> {
bool* ok); bool* ok);
Statement ParseScopedStatement(bool legacy, bool* ok); Statement ParseScopedStatement(bool legacy, bool* ok);
Statement ParseHoistableDeclaration(bool* ok); Statement ParseHoistableDeclaration(bool* ok);
Statement ParseHoistableDeclaration(int pos, bool is_generator, bool* ok); Statement ParseHoistableDeclaration(int pos, ParseFunctionFlags flags,
bool* ok);
Statement ParseFunctionDeclaration(bool* ok); Statement ParseFunctionDeclaration(bool* ok);
Statement ParseAsyncFunctionDeclaration(bool* ok);
Expression ParseAsyncFunctionExpression(bool* ok);
Statement ParseClassDeclaration(bool* ok); Statement ParseClassDeclaration(bool* ok);
Statement ParseBlock(bool* ok); Statement ParseBlock(bool* ok);
Statement ParseVariableStatement(VariableDeclarationContext var_context, Statement ParseVariableStatement(VariableDeclarationContext var_context,
...@@ -1166,6 +1192,9 @@ void PreParserTraits::ParseArrowFunctionFormalParameterList( ...@@ -1166,6 +1192,9 @@ void PreParserTraits::ParseArrowFunctionFormalParameterList(
// lists that are too long. // lists that are too long.
} }
PreParserExpression PreParserTraits::ParseAsyncFunctionExpression(bool* ok) {
return pre_parser_->ParseAsyncFunctionExpression(ok);
}
PreParserExpression PreParserTraits::ParseDoExpression(bool* ok) { PreParserExpression PreParserTraits::ParseDoExpression(bool* ok) {
return pre_parser_->ParseDoExpression(ok); return pre_parser_->ParseDoExpression(ok);
...@@ -1177,6 +1206,10 @@ void PreParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier, ...@@ -1177,6 +1206,10 @@ void PreParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier,
pre_parser_->ValidateExpression(classifier, ok); pre_parser_->ValidateExpression(classifier, ok);
} }
PreParserExpression PreParserTraits::RewriteAwaitExpression(
PreParserExpression value, int pos) {
return value;
}
Zone* PreParserTraits::zone() const { Zone* PreParserTraits::zone() const {
return pre_parser_->function_state_->scope()->zone(); return pre_parser_->function_state_->scope()->zone();
......
...@@ -249,6 +249,7 @@ Token::Value Scanner::Next() { ...@@ -249,6 +249,7 @@ Token::Value Scanner::Next() {
if (V8_UNLIKELY(next_next_.token != Token::UNINITIALIZED)) { if (V8_UNLIKELY(next_next_.token != Token::UNINITIALIZED)) {
next_ = next_next_; next_ = next_next_;
next_next_.token = Token::UNINITIALIZED; next_next_.token = Token::UNINITIALIZED;
has_line_terminator_before_next_ = has_line_terminator_after_next_;
return current_.token; return current_.token;
} }
has_line_terminator_before_next_ = false; has_line_terminator_before_next_ = false;
...@@ -274,7 +275,12 @@ Token::Value Scanner::PeekAhead() { ...@@ -274,7 +275,12 @@ Token::Value Scanner::PeekAhead() {
return next_next_.token; return next_next_.token;
} }
TokenDesc prev = current_; TokenDesc prev = current_;
bool has_line_terminator_before_next =
has_line_terminator_before_next_ || has_multiline_comment_before_next_;
Next(); Next();
has_line_terminator_after_next_ =
has_line_terminator_before_next_ || has_multiline_comment_before_next_;
has_line_terminator_before_next_ = has_line_terminator_before_next;
Token::Value ret = next_.token; Token::Value ret = next_.token;
next_next_ = next_; next_next_ = next_;
next_ = current_; next_ = current_;
...@@ -1136,6 +1142,7 @@ uc32 Scanner::ScanUnicodeEscape() { ...@@ -1136,6 +1142,7 @@ uc32 Scanner::ScanUnicodeEscape() {
#define KEYWORDS(KEYWORD_GROUP, KEYWORD) \ #define KEYWORDS(KEYWORD_GROUP, KEYWORD) \
KEYWORD_GROUP('a') \ KEYWORD_GROUP('a') \
KEYWORD("async", Token::ASYNC) \
KEYWORD("await", Token::AWAIT) \ KEYWORD("await", Token::AWAIT) \
KEYWORD_GROUP('b') \ KEYWORD_GROUP('b') \
KEYWORD("break", Token::BREAK) \ KEYWORD("break", Token::BREAK) \
......
...@@ -442,6 +442,12 @@ class Scanner { ...@@ -442,6 +442,12 @@ class Scanner {
has_multiline_comment_before_next_; has_multiline_comment_before_next_;
} }
bool HasAnyLineTerminatorAfterNext() {
Token::Value ensure_next_next = PeekAhead();
USE(ensure_next_next);
return has_line_terminator_after_next_;
}
// Scans the input as a regular expression pattern, previous // Scans the input as a regular expression pattern, previous
// character(s) must be /(=). Returns true if a pattern is scanned. // character(s) must be /(=). Returns true if a pattern is scanned.
bool ScanRegExpPattern(bool seen_equal); bool ScanRegExpPattern(bool seen_equal);
...@@ -786,6 +792,7 @@ class Scanner { ...@@ -786,6 +792,7 @@ class Scanner {
// Whether there is a multi-line comment that contains a // Whether there is a multi-line comment that contains a
// line-terminator after the current token, and before the next. // line-terminator after the current token, and before the next.
bool has_multiline_comment_before_next_; bool has_multiline_comment_before_next_;
bool has_line_terminator_after_next_;
// Whether this scanner encountered an HTML comment. // Whether this scanner encountered an HTML comment.
bool found_html_comment_; bool found_html_comment_;
......
...@@ -149,6 +149,7 @@ namespace internal { ...@@ -149,6 +149,7 @@ namespace internal {
\ \
/* Future reserved words (ECMA-262, section 7.6.1.2). */ \ /* Future reserved words (ECMA-262, section 7.6.1.2). */ \
T(FUTURE_STRICT_RESERVED_WORD, NULL, 0) \ T(FUTURE_STRICT_RESERVED_WORD, NULL, 0) \
K(ASYNC, "async", 0) \
/* `await` is a reserved word in module code only */ \ /* `await` is a reserved word in module code only */ \
K(AWAIT, "await", 0) \ K(AWAIT, "await", 0) \
K(CLASS, "class", 0) \ K(CLASS, "class", 0) \
...@@ -201,6 +202,7 @@ class Token { ...@@ -201,6 +202,7 @@ class Token {
bool is_generator, bool is_module) { bool is_generator, bool is_module) {
switch (tok) { switch (tok) {
case IDENTIFIER: case IDENTIFIER:
case ASYNC:
return true; return true;
case ESCAPED_STRICT_RESERVED_WORD: case ESCAPED_STRICT_RESERVED_WORD:
case FUTURE_STRICT_RESERVED_WORD: case FUTURE_STRICT_RESERVED_WORD:
......
...@@ -1508,7 +1508,8 @@ enum ParserFlag { ...@@ -1508,7 +1508,8 @@ enum ParserFlag {
kAllowHarmonyFunctionSent, kAllowHarmonyFunctionSent,
kAllowHarmonyRestrictiveDeclarations, kAllowHarmonyRestrictiveDeclarations,
kAllowHarmonyExponentiationOperator, kAllowHarmonyExponentiationOperator,
kAllowHarmonyForIn kAllowHarmonyForIn,
kAllowHarmonyAsyncAwait
}; };
enum ParserSyncTestResult { enum ParserSyncTestResult {
...@@ -1529,6 +1530,8 @@ void SetParserFlags(i::ParserBase<Traits>* parser, ...@@ -1529,6 +1530,8 @@ void SetParserFlags(i::ParserBase<Traits>* parser,
parser->set_allow_harmony_exponentiation_operator( parser->set_allow_harmony_exponentiation_operator(
flags.Contains(kAllowHarmonyExponentiationOperator)); flags.Contains(kAllowHarmonyExponentiationOperator));
parser->set_allow_harmony_for_in(flags.Contains(kAllowHarmonyForIn)); parser->set_allow_harmony_for_in(flags.Contains(kAllowHarmonyForIn));
parser->set_allow_harmony_async_await(
flags.Contains(kAllowHarmonyAsyncAwait));
} }
...@@ -7448,6 +7451,234 @@ TEST(ExponentiationOperatorErrors) { ...@@ -7448,6 +7451,234 @@ TEST(ExponentiationOperatorErrors) {
arraysize(always_flags)); arraysize(always_flags));
} }
TEST(AsyncAwait) {
// clang-format off
const char* context_data[][2] = {
{ "'use strict';", "" },
{ "", "" },
{ NULL, NULL }
};
const char* data[] = {
"var asyncFn = async function() { await 1; };",
"var asyncFn = async function withName() { await 1; };",
"var asyncFn = async () => await 'test';",
"var asyncFn = async x => await x + 'test';",
"async function asyncFn() { await 1; }",
"var O = { async method() { await 1; } }",
"var O = { async ['meth' + 'od']() { await 1; } }",
"var O = { async 'method'() { await 1; } }",
"var O = { async 0() { await 1; } }",
"async function await() {}",
NULL
};
// clang-format on
static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
arraysize(always_flags));
// clang-format off
const char* async_body_context_data[][2] = {
{ "async function f() {", "}" },
{ "var f = async function() {", "}" },
{ "var f = async() => {", "}" },
{ "var O = { async method() {", "} }" },
{ "'use strict'; async function f() {", "}" },
{ "'use strict'; var f = async function() {", "}" },
{ "'use strict'; var f = async() => {", "}" },
{ "'use strict'; var O = { async method() {", "} }" },
{ NULL, NULL }
};
const char* body_context_data[][2] = {
{ "function f() {", "}" },
{ "function* g() {", "}" },
{ "var f = function() {", "}" },
{ "var g = function*() {", "}" },
{ "var O = { method() {", "} }" },
{ "var O = { *method() {", "} }" },
{ "var f = () => {", "}" },
{ "'use strict'; function f() {", "}" },
{ "'use strict'; function* g() {", "}" },
{ "'use strict'; var f = function() {", "}" },
{ "'use strict'; var g = function*() {", "}" },
{ "'use strict'; var O = { method() {", "} }" },
{ "'use strict'; var O = { *method() {", "} }" },
{ "'use strict'; var f = () => {", "}" },
{ NULL, NULL }
};
const char* body_data[] = {
"var async = 1; return async;",
"let async = 1; return async;",
"const async = 1; return async;",
"function async() {} return async();",
"var async = async => async; return async();",
"function foo() { var await = 1; return await; }",
"function foo(await) { return await; }",
"function* foo() { var await = 1; return await; }",
"function* foo(await) { return await; }",
"var f = (await) => await;",
"var f = () => { var await = 1; return await; }",
"var O = { method() { var await = 1; return await; } };",
"var O = { method(await) { return await; } };",
"var O = { *method() { var await = 1; return await; } };",
"var O = { *method(await) { return await; } };",
"(function await() {})",
NULL
};
// clang-format on
RunParserSyncTest(async_body_context_data, body_data, kSuccess, NULL, 0,
always_flags, arraysize(always_flags));
RunParserSyncTest(body_context_data, body_data, kSuccess, NULL, 0,
always_flags, arraysize(always_flags));
}
TEST(AsyncAwaitErrors) {
// clang-format off
const char* context_data[][2] = {
{ "'use strict';", "" },
{ "", "" },
{ NULL, NULL }
};
const char* strict_context_data[][2] = {
{ "'use strict';", "" },
{ NULL, NULL }
};
const char* error_data[] = {
"var asyncFn = async function() { var await = 1; };",
"var asyncFn = async function() { var { await } = 1; };",
"var asyncFn = async function() { var [ await ] = 1; };",
"var asyncFn = async function await() {};",
"var asyncFn = async () => var await = 'test';",
"var asyncFn = async await => await + 'test';",
"var asyncFn = async function(await) {};",
"var asyncFn = async function() { return async (await) => {}; }",
"var asyncFn = async (await) => 'test';",
"var asyncFn = async x => { var await = 1; }",
"var asyncFn = async x => { var { await } = 1; }",
"var asyncFn = async x => { var [ await ] = 1; }",
"async function f(await) {}",
"async function f() { var await = 1; }",
"async function f() { var { await } = 1; }",
"async function f() { var [ await ] = 1; }",
"var O = { async method(a, a) {} }",
"var O = { async ['meth' + 'od'](a, a) {} }",
"var O = { async 'method'(a, a) {} }",
"var O = { async 0(a, a) {} }",
"async function f() { var O = { async [await](a, a) {} } }",
"var asyncFn = async function() { await; }",
"async function f() { await; }",
"var O = { async method() { await; } };",
"var f = async() => await;",
"var f = async() => { await; };",
"var asyncFn = async function*() {}",
"async function* f() {}",
"var O = { *async method() {} };",
"var O = { async *method() {} };",
"var O = { async method*() {} };",
"var asyncFn = async function(x = await 1) { return x; }",
"async function f(x = await 1) { return x; }",
"var f = async(x = await 1) => x;",
"var O = { async method(x = await 1) { return x; } };",
"var f = async(x = await) => 1;",
"class C { async constructor() {} }",
"class C {}; class C2 extends C { async constructor() {} }",
"class C { static async prototype() {} }",
"class C {}; class C2 extends C { static async prototype() {} }",
"var f = async() => ((async(x = await 1) => x)();",
"var asyncFn = async function() { function await() {} }",
"var asyncFn = async() => { function await() {} }",
"var O = { async method() { function await() {} } }",
"async function foo() { function await() {} }",
NULL
};
const char* strict_error_data[] = {
"var O = { async method(eval) {} }",
"var O = { async ['meth' + 'od'](eval) {} }",
"var O = { async 'method'(eval) {} }",
"var O = { async 0(eval) {} }",
"var O = { async method(arguments) {} }",
"var O = { async ['meth' + 'od'](arguments) {} }",
"var O = { async 'method'(arguments) {} }",
"var O = { async 0(arguments) {} }",
"var O = { async method(dupe, dupe) {} }",
// TODO(caitp): preparser needs to report duplicate parameter errors, too.
// "var f = async(dupe, dupe) => {}",
NULL
};
// clang-format on
static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
arraysize(always_flags));
RunParserSyncTest(strict_context_data, strict_error_data, kError, NULL, 0,
always_flags, arraysize(always_flags));
}
TEST(AsyncAwaitModule) {
// clang-format off
const char* context_data[][2] = {
{ "", "" },
{ NULL, NULL }
};
const char* data[] = {
"export default async function() { await 1; }",
"export default async function async() { await 1; }",
"export async function async() { await 1; }",
NULL
};
// clang-format on
static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
RunModuleParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
arraysize(always_flags), NULL, 0, false);
}
TEST(AsyncAwaitModuleErrors) {
// clang-format off
const char* context_data[][2] = {
{ "", "" },
{ NULL, NULL }
};
const char* error_data[] = {
"export default (async function await() {})",
"export default async function await() {}",
"export async function await() {}",
"export async function() {}",
"export async",
NULL
};
// clang-format on
static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
RunModuleParserSyncTest(context_data, error_data, kError, NULL, 0,
always_flags, arraysize(always_flags), NULL, 0,
false);
}
TEST(RestrictiveForInErrors) { TEST(RestrictiveForInErrors) {
// clang-format off // clang-format off
const char* context_data[][2] = { const char* context_data[][2] = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment