Upgrade V8 to 5.1.281.57 DO NOT MERGE
FPIIM-449
Change-Id: Id981b686b4d587ac31697662eb98bb34be42ad90
(cherry picked from commit 3b9bc31999c9787eb726ecdbfd5796bfdec32a18)
diff --git a/src/parsing/expression-classifier.h b/src/parsing/expression-classifier.h
index fa1a2f9..71fa3d3 100644
--- a/src/parsing/expression-classifier.h
+++ b/src/parsing/expression-classifier.h
@@ -36,18 +36,16 @@
AssignmentPatternProduction = 1 << 3,
DistinctFormalParametersProduction = 1 << 4,
StrictModeFormalParametersProduction = 1 << 5,
- StrongModeFormalParametersProduction = 1 << 6,
- ArrowFormalParametersProduction = 1 << 7,
- LetPatternProduction = 1 << 8,
- CoverInitializedNameProduction = 1 << 9,
+ ArrowFormalParametersProduction = 1 << 6,
+ LetPatternProduction = 1 << 7,
+ CoverInitializedNameProduction = 1 << 8,
ExpressionProductions =
(ExpressionProduction | FormalParameterInitializerProduction),
PatternProductions = (BindingPatternProduction |
AssignmentPatternProduction | LetPatternProduction),
FormalParametersProductions = (DistinctFormalParametersProduction |
- StrictModeFormalParametersProduction |
- StrongModeFormalParametersProduction),
+ StrictModeFormalParametersProduction),
StandardProductions = ExpressionProductions | PatternProductions,
AllProductions =
(StandardProductions | FormalParametersProductions |
@@ -110,12 +108,6 @@
return is_valid(StrictModeFormalParametersProduction);
}
- // Note: callers should also check is_valid_strict_mode_formal_parameters()
- // and is_valid_formal_parameter_list_without_duplicates().
- bool is_valid_strong_mode_formal_parameters() const {
- return is_valid(StrongModeFormalParametersProduction);
- }
-
bool is_valid_let_pattern() const { return is_valid(LetPatternProduction); }
const Error& expression_error() const { return expression_error_; }
@@ -142,10 +134,6 @@
return strict_mode_formal_parameter_error_;
}
- const Error& strong_mode_formal_parameter_error() const {
- return strong_mode_formal_parameter_error_;
- }
-
const Error& let_pattern_error() const { return let_pattern_error_; }
bool has_cover_initialized_name() const {
@@ -252,16 +240,6 @@
strict_mode_formal_parameter_error_.arg = arg;
}
- void RecordStrongModeFormalParameterError(const Scanner::Location& loc,
- MessageTemplate::Template message,
- const char* arg = nullptr) {
- if (!is_valid_strong_mode_formal_parameters()) return;
- invalid_productions_ |= StrongModeFormalParametersProduction;
- strong_mode_formal_parameter_error_.location = loc;
- strong_mode_formal_parameter_error_.message = message;
- strong_mode_formal_parameter_error_.arg = arg;
- }
-
void RecordLetPatternError(const Scanner::Location& loc,
MessageTemplate::Template message,
const char* arg = nullptr) {
@@ -323,9 +301,6 @@
if (errors & StrictModeFormalParametersProduction)
strict_mode_formal_parameter_error_ =
inner->strict_mode_formal_parameter_error_;
- if (errors & StrongModeFormalParametersProduction)
- strong_mode_formal_parameter_error_ =
- inner->strong_mode_formal_parameter_error_;
if (errors & LetPatternProduction)
let_pattern_error_ = inner->let_pattern_error_;
if (errors & CoverInitializedNameProduction)
@@ -372,7 +347,6 @@
Error arrow_formal_parameters_error_;
Error duplicate_formal_parameter_error_;
Error strict_mode_formal_parameter_error_;
- Error strong_mode_formal_parameter_error_;
Error let_pattern_error_;
Error cover_initialized_name_error_;
DuplicateFinder* duplicate_finder_;
diff --git a/src/parsing/parameter-initializer-rewriter.cc b/src/parsing/parameter-initializer-rewriter.cc
index 003bbeb..3e3587b 100644
--- a/src/parsing/parameter-initializer-rewriter.cc
+++ b/src/parsing/parameter-initializer-rewriter.cc
@@ -62,7 +62,7 @@
void Rewriter::VisitVariableProxy(VariableProxy* proxy) {
if (proxy->is_resolved()) {
Variable* var = proxy->var();
- DCHECK_EQ(var->mode(), TEMPORARY);
+ if (var->mode() != TEMPORARY) return;
if (old_scope_->RemoveTemporary(var)) {
var->set_scope(new_scope_);
new_scope_->AddTemporary(var);
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
index 6be19b3..dde6b1d 100644
--- a/src/parsing/parser-base.h
+++ b/src/parsing/parser-base.h
@@ -24,6 +24,10 @@
kFunctionNameValidityUnknown
};
+enum AllowLabelledFunctionStatement {
+ kAllowLabelledFunctionStatement,
+ kDisallowLabelledFunctionStatement,
+};
struct FormalParametersBase {
explicit FormalParametersBase(Scope* scope) : scope(scope) {}
@@ -108,14 +112,11 @@
stack_overflow_(false),
allow_lazy_(false),
allow_natives_(false),
+ allow_tailcalls_(false),
allow_harmony_sloppy_(false),
allow_harmony_sloppy_function_(false),
allow_harmony_sloppy_let_(false),
- allow_harmony_default_parameters_(false),
- allow_harmony_destructuring_bind_(false),
- allow_harmony_destructuring_assignment_(false),
- allow_strong_mode_(false),
- allow_legacy_const_(true),
+ allow_harmony_restrictive_declarations_(false),
allow_harmony_do_expressions_(false),
allow_harmony_function_name_(false),
allow_harmony_function_sent_(false) {}
@@ -124,19 +125,25 @@
bool allow_##name() const { return allow_##name##_; } \
void set_allow_##name(bool allow) { allow_##name##_ = allow; }
+#define SCANNER_ACCESSORS(name) \
+ bool allow_##name() const { return scanner_->allow_##name(); } \
+ void set_allow_##name(bool allow) { \
+ return scanner_->set_allow_##name(allow); \
+ }
+
ALLOW_ACCESSORS(lazy);
ALLOW_ACCESSORS(natives);
+ ALLOW_ACCESSORS(tailcalls);
ALLOW_ACCESSORS(harmony_sloppy);
ALLOW_ACCESSORS(harmony_sloppy_function);
ALLOW_ACCESSORS(harmony_sloppy_let);
- ALLOW_ACCESSORS(harmony_default_parameters);
- ALLOW_ACCESSORS(harmony_destructuring_bind);
- ALLOW_ACCESSORS(harmony_destructuring_assignment);
- ALLOW_ACCESSORS(strong_mode);
- ALLOW_ACCESSORS(legacy_const);
+ ALLOW_ACCESSORS(harmony_restrictive_declarations);
ALLOW_ACCESSORS(harmony_do_expressions);
ALLOW_ACCESSORS(harmony_function_name);
ALLOW_ACCESSORS(harmony_function_sent);
+ SCANNER_ACCESSORS(harmony_exponentiation_operator);
+
+#undef SCANNER_ACCESSORS
#undef ALLOW_ACCESSORS
uintptr_t stack_limit() const { return stack_limit_; }
@@ -368,7 +375,6 @@
Scope* NewScope(Scope* parent, ScopeType scope_type, FunctionKind kind) {
DCHECK(ast_value_factory());
- DCHECK(scope_type != MODULE_SCOPE || FLAG_harmony_modules);
Scope* result = new (zone())
Scope(zone(), parent, scope_type, ast_value_factory(), kind);
result->Initialize();
@@ -481,12 +487,7 @@
bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode, bool* ok) {
if (Check(Token::IN)) {
- if (is_strong(language_mode())) {
- ReportMessageAt(scanner()->location(), MessageTemplate::kStrongForIn);
- *ok = false;
- } else {
- *visit_mode = ForEachStatement::ENUMERATE;
- }
+ *visit_mode = ForEachStatement::ENUMERATE;
return true;
} else if (CheckContextualKeyword(CStrVector("of"))) {
*visit_mode = ForEachStatement::ITERATE;
@@ -547,12 +548,6 @@
*ok = false;
return;
}
- if (is_strong(language_mode) && this->IsUndefined(function_name)) {
- Traits::ReportMessageAt(function_name_loc,
- MessageTemplate::kStrongUndefined);
- *ok = false;
- return;
- }
}
// Determine precedence of given token.
@@ -570,8 +565,7 @@
bool is_generator() const { return function_state_->is_generator(); }
bool allow_const() {
- return is_strict(language_mode()) || allow_harmony_sloppy() ||
- allow_legacy_const();
+ return is_strict(language_mode()) || allow_harmony_sloppy();
}
bool allow_let() {
@@ -593,7 +587,8 @@
}
void GetUnexpectedTokenMessage(
- Token::Value token, MessageTemplate::Template* message, const char** arg,
+ Token::Value token, MessageTemplate::Template* message,
+ Scanner::Location* location, const char** arg,
MessageTemplate::Template default_ = MessageTemplate::kUnexpectedToken);
void ReportUnexpectedToken(Token::Value token);
@@ -657,10 +652,6 @@
!classifier->is_valid_strict_mode_formal_parameters()) {
ReportClassifierError(classifier->strict_mode_formal_parameter_error());
*ok = false;
- } else if (is_strong(language_mode) &&
- !classifier->is_valid_strong_mode_formal_parameters()) {
- ReportClassifierError(classifier->strong_mode_formal_parameter_error());
- *ok = false;
}
}
@@ -698,33 +689,25 @@
void ExpressionUnexpectedToken(ExpressionClassifier* classifier) {
MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
const char* arg;
- GetUnexpectedTokenMessage(peek(), &message, &arg);
- classifier->RecordExpressionError(scanner()->peek_location(), message, arg);
+ Scanner::Location location = scanner()->peek_location();
+ GetUnexpectedTokenMessage(peek(), &message, &location, &arg);
+ classifier->RecordExpressionError(location, message, arg);
}
void BindingPatternUnexpectedToken(ExpressionClassifier* classifier) {
MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
const char* arg;
- GetUnexpectedTokenMessage(peek(), &message, &arg);
- classifier->RecordBindingPatternError(scanner()->peek_location(), message,
- arg);
+ Scanner::Location location = scanner()->peek_location();
+ GetUnexpectedTokenMessage(peek(), &message, &location, &arg);
+ classifier->RecordBindingPatternError(location, message, arg);
}
void ArrowFormalParametersUnexpectedToken(ExpressionClassifier* classifier) {
MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
const char* arg;
- GetUnexpectedTokenMessage(peek(), &message, &arg);
- classifier->RecordArrowFormalParametersError(scanner()->peek_location(),
- message, arg);
- }
-
- void FormalParameterInitializerUnexpectedToken(
- ExpressionClassifier* classifier) {
- MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
- const char* arg;
- GetUnexpectedTokenMessage(peek(), &message, &arg);
- classifier->RecordFormalParameterInitializerError(
- scanner()->peek_location(), message, arg);
+ Scanner::Location location = scanner()->peek_location();
+ GetUnexpectedTokenMessage(peek(), &message, &location, &arg);
+ classifier->RecordArrowFormalParametersError(location, message, arg);
}
// Recursive descent functions:
@@ -804,10 +787,6 @@
ExpressionT ParseSuperExpression(bool is_new,
ExpressionClassifier* classifier, bool* ok);
ExpressionT ParseNewTargetExpression(bool* ok);
- ExpressionT ParseStrongInitializationExpression(
- ExpressionClassifier* classifier, bool* ok);
- ExpressionT ParseStrongSuperCallExpression(ExpressionClassifier* classifier,
- bool* ok);
void ParseFormalParameter(FormalParametersT* parameters,
ExpressionClassifier* classifier, bool* ok);
@@ -825,10 +804,6 @@
ExpressionT CheckAndRewriteReferenceExpression(
ExpressionT expression, int beg_pos, int end_pos,
MessageTemplate::Template message, bool* ok);
- ExpressionT ClassifyAndRewriteReferenceExpression(
- ExpressionClassifier* classifier, ExpressionT expression, int beg_pos,
- int end_pos, MessageTemplate::Template message,
- ParseErrorType type = kSyntaxError);
ExpressionT CheckAndRewriteReferenceExpression(
ExpressionT expression, int beg_pos, int end_pos,
MessageTemplate::Template message, ParseErrorType type, bool* ok);
@@ -841,10 +816,6 @@
Traits::IsEvalOrArguments(Traits::AsIdentifier(expression))) {
return false;
}
- if (is_strong(language_mode()) &&
- Traits::IsUndefined(Traits::AsIdentifier(expression))) {
- return false;
- }
return true;
}
@@ -858,8 +829,12 @@
void CheckPossibleEvalCall(ExpressionT expression, Scope* scope) {
if (Traits::IsIdentifier(expression) &&
Traits::IsEval(Traits::AsIdentifier(expression))) {
- scope->DeclarationScope()->RecordEvalCall();
scope->RecordEvalCall();
+ if (is_sloppy(scope->language_mode())) {
+ // For sloppy scopes we also have to record the call at function level,
+ // in case it includes declarations that will be hoisted.
+ scope->DeclarationScope()->RecordEvalCall();
+ }
}
}
@@ -945,14 +920,11 @@
bool allow_lazy_;
bool allow_natives_;
+ bool allow_tailcalls_;
bool allow_harmony_sloppy_;
bool allow_harmony_sloppy_function_;
bool allow_harmony_sloppy_let_;
- bool allow_harmony_default_parameters_;
- bool allow_harmony_destructuring_bind_;
- bool allow_harmony_destructuring_assignment_;
- bool allow_strong_mode_;
- bool allow_legacy_const_;
+ bool allow_harmony_restrictive_declarations_;
bool allow_harmony_do_expressions_;
bool allow_harmony_function_name_;
bool allow_harmony_function_sent_;
@@ -987,32 +959,28 @@
*function_state_stack_ = outer_function_state_;
}
-
template <class Traits>
void ParserBase<Traits>::GetUnexpectedTokenMessage(
- Token::Value token, MessageTemplate::Template* message, const char** arg,
+ Token::Value token, MessageTemplate::Template* message,
+ Scanner::Location* location, const char** arg,
MessageTemplate::Template default_) {
+ *arg = nullptr;
switch (token) {
case Token::EOS:
*message = MessageTemplate::kUnexpectedEOS;
- *arg = nullptr;
break;
case Token::SMI:
case Token::NUMBER:
*message = MessageTemplate::kUnexpectedTokenNumber;
- *arg = nullptr;
break;
case Token::STRING:
*message = MessageTemplate::kUnexpectedTokenString;
- *arg = nullptr;
break;
case Token::IDENTIFIER:
*message = MessageTemplate::kUnexpectedTokenIdentifier;
- *arg = nullptr;
break;
case Token::FUTURE_RESERVED_WORD:
*message = MessageTemplate::kUnexpectedReserved;
- *arg = nullptr;
break;
case Token::LET:
case Token::STATIC:
@@ -1021,17 +989,22 @@
*message = is_strict(language_mode())
? MessageTemplate::kUnexpectedStrictReserved
: MessageTemplate::kUnexpectedTokenIdentifier;
- *arg = nullptr;
break;
case Token::TEMPLATE_SPAN:
case Token::TEMPLATE_TAIL:
*message = MessageTemplate::kUnexpectedTemplateString;
- *arg = nullptr;
break;
case Token::ESCAPED_STRICT_RESERVED_WORD:
case Token::ESCAPED_KEYWORD:
*message = MessageTemplate::kInvalidEscapedReservedWord;
- *arg = nullptr;
+ break;
+ case Token::ILLEGAL:
+ if (scanner()->has_error()) {
+ *message = scanner()->error();
+ *location = scanner()->error_location();
+ } else {
+ *message = MessageTemplate::kInvalidOrUnexpectedToken;
+ }
break;
default:
const char* name = Token::String(token);
@@ -1053,7 +1026,7 @@
Scanner::Location source_location, Token::Value token,
MessageTemplate::Template message) {
const char* arg;
- GetUnexpectedTokenMessage(token, &message, &arg);
+ GetUnexpectedTokenMessage(token, &message, &source_location, &arg);
Traits::ReportMessageAt(source_location, message, arg);
}
@@ -1105,19 +1078,6 @@
classifier->RecordBindingPatternError(
scanner()->location(), MessageTemplate::kStrictEvalArguments);
}
- if (is_strong(language_mode())) {
- classifier->RecordExpressionError(scanner()->location(),
- MessageTemplate::kStrongArguments);
- }
- }
- if (this->IsUndefined(name)) {
- classifier->RecordStrongModeFormalParameterError(
- scanner()->location(), MessageTemplate::kStrongUndefined);
- if (is_strong(language_mode())) {
- // TODO(dslomov): allow 'undefined' in nested patterns.
- classifier->RecordPatternError(scanner()->location(),
- MessageTemplate::kStrongUndefined);
- }
}
if (classifier->duplicate_finder() != nullptr &&
@@ -1218,8 +1178,7 @@
}
int js_flags = flags.FromJust();
Next();
- return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index,
- is_strong(language_mode()), pos);
+ return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
}
@@ -1262,15 +1221,6 @@
case Token::THIS: {
BindingPatternUnexpectedToken(classifier);
Consume(Token::THIS);
- if (FLAG_strong_this && is_strong(language_mode())) {
- // Constructors' usages of 'this' in strong mode are parsed separately.
- // TODO(rossberg): this does not work with arrow functions yet.
- if (IsClassConstructor(function_state_->kind())) {
- ReportMessage(MessageTemplate::kStrongConstructorThis);
- *ok = false;
- return this->EmptyExpression();
- }
- }
return this->ThisExpression(scope_, factory(), beg_pos);
}
@@ -1313,15 +1263,9 @@
return this->ParseRegExpLiteral(false, classifier, ok);
case Token::LBRACK:
- if (!allow_harmony_destructuring_bind()) {
- BindingPatternUnexpectedToken(classifier);
- }
return this->ParseArrayLiteral(classifier, ok);
case Token::LBRACE:
- if (!allow_harmony_destructuring_bind()) {
- BindingPatternUnexpectedToken(classifier);
- }
return this->ParseObjectLiteral(classifier, ok);
case Token::LPAREN: {
@@ -1394,7 +1338,7 @@
CHECK_OK);
class_name_location = scanner()->location();
}
- return this->ParseClassLiteral(name, class_name_location,
+ return this->ParseClassLiteral(classifier, name, class_name_location,
is_strict_reserved_name,
class_token_position, ok);
}
@@ -1510,12 +1454,6 @@
while (peek() != Token::RBRACK) {
ExpressionT elem = this->EmptyExpression();
if (peek() == Token::COMMA) {
- if (is_strong(language_mode())) {
- ReportMessageAt(scanner()->peek_location(),
- MessageTemplate::kStrongEllision);
- *ok = false;
- return this->EmptyExpression();
- }
elem = this->GetLiteralTheHole(peek_position(), factory());
} else if (peek() == Token::ELLIPSIS) {
int start_pos = peek_position();
@@ -1559,9 +1497,8 @@
// Update the scope information before the pre-parsing bailout.
int literal_index = function_state_->NextMaterializedLiteralIndex();
- ExpressionT result =
- factory()->NewArrayLiteral(values, first_spread_index, literal_index,
- is_strong(language_mode()), pos);
+ ExpressionT result = factory()->NewArrayLiteral(values, first_spread_index,
+ literal_index, pos);
if (first_spread_index >= 0) {
result = factory()->NewRewritableExpression(result);
Traits::QueueNonPatternForRewriting(result);
@@ -1823,7 +1760,6 @@
typename Traits::Type::PropertyList properties =
this->NewPropertyList(4, zone_);
int number_of_boilerplate_properties = 0;
- bool has_function = false;
bool has_computed_names = false;
ObjectLiteralChecker checker(this);
@@ -1845,12 +1781,6 @@
has_computed_names = true;
}
- // Mark top-level object literals that contain function literals and
- // pretenure the literal so it can be added as a constant function
- // property. (Parser only.)
- this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, property,
- &has_function);
-
// Count CONSTANT or COMPUTED properties to maintain the enumeration order.
if (!has_computed_names && this->IsBoilerplateProperty(property)) {
number_of_boilerplate_properties++;
@@ -1876,8 +1806,6 @@
return factory()->NewObjectLiteral(properties,
literal_index,
number_of_boilerplate_properties,
- has_function,
- is_strong(language_mode()),
pos);
}
@@ -1984,6 +1912,13 @@
Token::String(Token::ARROW));
ValidateArrowFormalParameters(&arrow_formals_classifier, expression,
parenthesized_formals, CHECK_OK);
+ // This reads strangely, but is correct: it checks whether any
+ // sub-expression of the parameter list failed to be a valid formal
+ // parameter initializer. Since YieldExpressions are banned anywhere
+ // in an arrow parameter list, this is correct.
+ // TODO(adamk): Rename "FormalParameterInitializerError" to refer to
+ // "YieldExpression", which is its only use.
+ ValidateFormalParameterInitializer(&arrow_formals_classifier, ok);
Scanner::Location loc(lhs_beg_pos, scanner()->location().end_pos);
Scope* scope =
this->NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction);
@@ -2039,23 +1974,10 @@
// Now pending non-pattern expressions must be discarded.
arrow_formals_classifier.Discard();
- if (!(allow_harmony_destructuring_bind() ||
- allow_harmony_default_parameters())) {
- BindingPatternUnexpectedToken(classifier);
- }
-
- if (allow_harmony_destructuring_assignment() && IsValidPattern(expression) &&
- peek() == Token::ASSIGN) {
+ if (IsValidPattern(expression) && peek() == Token::ASSIGN) {
classifier->ForgiveCoverInitializedNameError();
ValidateAssignmentPattern(classifier, CHECK_OK);
is_destructuring_assignment = true;
- } else if (allow_harmony_default_parameters() &&
- !allow_harmony_destructuring_assignment()) {
- // TODO(adamk): This branch should be removed once the destructuring
- // assignment and default parameter flags are removed.
- expression = this->ClassifyAndRewriteReferenceExpression(
- classifier, expression, lhs_beg_pos, scanner()->location().end_pos,
- MessageTemplate::kInvalidLhsInAssignment);
} else {
expression = this->CheckAndRewriteReferenceExpression(
expression, lhs_beg_pos, scanner()->location().end_pos,
@@ -2108,6 +2030,11 @@
Traits::SetFunctionNameFromIdentifierRef(right, expression);
}
+ if (op == Token::ASSIGN_EXP) {
+ DCHECK(!is_destructuring_assignment);
+ return Traits::RewriteAssignExponentiation(expression, right, pos);
+ }
+
ExpressionT result = factory()->NewAssignment(op, expression, right, pos);
if (is_destructuring_assignment) {
@@ -2127,14 +2054,15 @@
int pos = peek_position();
classifier->RecordPatternError(scanner()->peek_location(),
MessageTemplate::kInvalidDestructuringTarget);
- FormalParameterInitializerUnexpectedToken(classifier);
+ classifier->RecordFormalParameterInitializerError(
+ scanner()->peek_location(), MessageTemplate::kYieldInParameter);
Expect(Token::YIELD, CHECK_OK);
ExpressionT generator_object =
factory()->NewVariableProxy(function_state_->generator_object_variable());
ExpressionT expression = Traits::EmptyExpression();
- Yield::Kind kind = Yield::kSuspend;
+ bool delegating = false; // yield*
if (!scanner()->HasAnyLineTerminatorBeforeNext()) {
- if (Check(Token::MUL)) kind = Yield::kDelegating;
+ if (Check(Token::MUL)) delegating = true;
switch (peek()) {
case Token::EOS:
case Token::SEMICOLON:
@@ -2146,10 +2074,8 @@
// The above set of tokens is the complete set of tokens that can appear
// after an AssignmentExpression, and none of them can start an
// AssignmentExpression. This allows us to avoid looking for an RHS for
- // a Yield::kSuspend operation, given only one look-ahead token.
- if (kind == Yield::kSuspend)
- break;
- DCHECK_EQ(Yield::kDelegating, kind);
+ // a regular yield, given only one look-ahead token.
+ if (!delegating) break;
// Delegating yields require an RHS; fall through.
default:
expression = ParseAssignmentExpression(false, classifier, CHECK_OK);
@@ -2157,13 +2083,16 @@
break;
}
}
- if (kind == Yield::kDelegating) {
+
+ if (delegating) {
return Traits::RewriteYieldStar(generator_object, expression, pos);
}
+
+ expression = Traits::BuildIteratorResult(expression, false);
// Hackily disambiguate o from o.next and o [Symbol.iterator]().
// TODO(verwaest): Come up with a better solution.
typename Traits::Type::YieldExpression yield =
- factory()->NewYield(generator_object, expression, kind, pos);
+ factory()->NewYield(generator_object, expression, pos);
return yield;
}
@@ -2215,10 +2144,12 @@
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Token::Value op = Next();
- Scanner::Location op_location = scanner()->location();
int pos = position();
+
+ const bool is_right_associative = op == Token::EXP;
+ const int next_prec = is_right_associative ? prec1 : prec1 + 1;
ExpressionT y =
- ParseBinaryExpression(prec1 + 1, accept_IN, classifier, CHECK_OK);
+ ParseBinaryExpression(next_prec, accept_IN, classifier, CHECK_OK);
Traits::RewriteNonPattern(classifier, CHECK_OK);
if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos,
@@ -2237,11 +2168,7 @@
case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
default: break;
}
- if (cmp == Token::EQ && is_strong(language_mode())) {
- ReportMessageAt(op_location, MessageTemplate::kStrongEqual);
- *ok = false;
- return this->EmptyExpression();
- } else if (FLAG_harmony_instanceof && cmp == Token::INSTANCEOF) {
+ if (FLAG_harmony_instanceof && cmp == Token::INSTANCEOF) {
x = Traits::RewriteInstanceof(x, y, pos);
} else {
x = factory()->NewCompareOperation(cmp, x, y, pos);
@@ -2250,6 +2177,9 @@
x = factory()->NewUnaryOperation(Token::NOT, x, pos);
}
}
+
+ } else if (op == Token::EXP) {
+ x = Traits::RewriteExponentiation(x, y, pos);
} else {
// We have a "normal" binary operation.
x = factory()->NewBinaryOperation(op, x, y, pos);
@@ -2287,11 +2217,7 @@
Traits::RewriteNonPattern(classifier, CHECK_OK);
if (op == Token::DELETE && is_strict(language_mode())) {
- if (is_strong(language_mode())) {
- ReportMessage(MessageTemplate::kStrongDelete);
- *ok = false;
- return this->EmptyExpression();
- } else if (this->IsIdentifier(expression)) {
+ if (this->IsIdentifier(expression)) {
// "delete identifier" is a syntax error in strict mode.
ReportMessage(MessageTemplate::kStrictDelete);
*ok = false;
@@ -2299,6 +2225,12 @@
}
}
+ if (peek() == Token::EXP) {
+ ReportUnexpectedToken(Next());
+ *ok = false;
+ return this->EmptyExpression();
+ }
+
// Allow Traits do rewrite the expression.
return this->BuildUnaryExpression(expression, op, pos, factory());
} else if (Token::IsCountOp(op)) {
@@ -2386,12 +2318,6 @@
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
- if (is_strong(language_mode()) && this->IsIdentifier(result) &&
- this->IsEval(this->AsIdentifier(result))) {
- ReportMessage(MessageTemplate::kStrongDirectEval);
- *ok = false;
- return this->EmptyExpression();
- }
int pos;
if (scanner()->current_token() == Token::IDENTIFIER ||
scanner()->current_token() == Token::SUPER) {
@@ -2609,148 +2535,6 @@
template <class Traits>
typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseStrongInitializationExpression(
- ExpressionClassifier* classifier, bool* ok) {
- // InitializationExpression :: (strong mode)
- // 'this' '.' IdentifierName '=' AssignmentExpression
- // 'this' '[' Expression ']' '=' AssignmentExpression
-
- FuncNameInferrer::State fni_state(fni_);
-
- Consume(Token::THIS);
- int pos = position();
- function_state_->set_this_location(scanner()->location());
- ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos);
-
- ExpressionT left = this->EmptyExpression();
- switch (peek()) {
- case Token::LBRACK: {
- Consume(Token::LBRACK);
- int pos = position();
- ExpressionT index = this->ParseExpression(true, classifier, CHECK_OK);
- Traits::RewriteNonPattern(classifier, CHECK_OK);
- left = factory()->NewProperty(this_expr, index, pos);
- if (fni_ != NULL) {
- this->PushPropertyName(fni_, index);
- }
- Expect(Token::RBRACK, CHECK_OK);
- break;
- }
- case Token::PERIOD: {
- Consume(Token::PERIOD);
- int pos = position();
- IdentifierT name = ParseIdentifierName(CHECK_OK);
- left = factory()->NewProperty(
- this_expr, factory()->NewStringLiteral(name, pos), pos);
- if (fni_ != NULL) {
- this->PushLiteralName(fni_, name);
- }
- break;
- }
- default:
- ReportMessage(MessageTemplate::kStrongConstructorThis);
- *ok = false;
- return this->EmptyExpression();
- }
-
- if (peek() != Token::ASSIGN) {
- ReportMessageAt(function_state_->this_location(),
- MessageTemplate::kStrongConstructorThis);
- *ok = false;
- return this->EmptyExpression();
- }
- Consume(Token::ASSIGN);
- left = this->MarkExpressionAsAssigned(left);
-
- ExpressionT right =
- this->ParseAssignmentExpression(true, classifier, CHECK_OK);
- Traits::RewriteNonPattern(classifier, CHECK_OK);
- this->CheckAssigningFunctionLiteralToProperty(left, right);
- function_state_->AddProperty();
- if (fni_ != NULL) {
- // Check if the right hand side is a call to avoid inferring a
- // name if we're dealing with "this.a = function(){...}();"-like
- // expression.
- if (!right->IsCall() && !right->IsCallNew()) {
- fni_->Infer();
- } else {
- fni_->RemoveLastFunction();
- }
- }
-
- if (function_state_->return_location().IsValid()) {
- ReportMessageAt(function_state_->return_location(),
- MessageTemplate::kStrongConstructorReturnMisplaced);
- *ok = false;
- return this->EmptyExpression();
- }
-
- return factory()->NewAssignment(Token::ASSIGN, left, right, pos);
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseStrongSuperCallExpression(
- ExpressionClassifier* classifier, bool* ok) {
- // SuperCallExpression :: (strong mode)
- // 'super' '(' ExpressionList ')'
- BindingPatternUnexpectedToken(classifier);
-
- Consume(Token::SUPER);
- int pos = position();
- Scanner::Location super_loc = scanner()->location();
- ExpressionT expr = this->SuperCallReference(scope_, factory(), pos);
-
- if (peek() != Token::LPAREN) {
- ReportMessage(MessageTemplate::kStrongConstructorSuper);
- *ok = false;
- return this->EmptyExpression();
- }
-
- Scanner::Location spread_pos;
- typename Traits::Type::ExpressionList args =
- ParseArguments(&spread_pos, classifier, CHECK_OK);
-
- // TODO(rossberg): This doesn't work with arrow functions yet.
- if (!IsSubclassConstructor(function_state_->kind())) {
- ReportMessage(MessageTemplate::kUnexpectedSuper);
- *ok = false;
- return this->EmptyExpression();
- } else if (function_state_->super_location().IsValid()) {
- ReportMessageAt(scanner()->location(),
- MessageTemplate::kStrongSuperCallDuplicate);
- *ok = false;
- return this->EmptyExpression();
- } else if (function_state_->this_location().IsValid()) {
- ReportMessageAt(scanner()->location(),
- MessageTemplate::kStrongSuperCallMisplaced);
- *ok = false;
- return this->EmptyExpression();
- } else if (function_state_->return_location().IsValid()) {
- ReportMessageAt(function_state_->return_location(),
- MessageTemplate::kStrongConstructorReturnMisplaced);
- *ok = false;
- return this->EmptyExpression();
- }
-
- function_state_->set_super_location(super_loc);
- if (spread_pos.IsValid()) {
- args = Traits::PrepareSpreadArguments(args);
- expr = Traits::SpreadCall(expr, args, pos);
- } else {
- expr = factory()->NewCall(expr, args, pos);
- }
-
- // Explicit calls to the super constructor using super() perform an implicit
- // binding assignment to the 'this' variable.
- ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos);
- return factory()->NewAssignment(Token::INIT, this_expr, expr, pos);
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
ParserBase<Traits>::ParseSuperExpression(bool is_new,
ExpressionClassifier* classifier,
bool* ok) {
@@ -2768,13 +2552,6 @@
// new super() is never allowed.
// super() is only allowed in derived constructor
if (!is_new && peek() == Token::LPAREN && IsSubclassConstructor(kind)) {
- if (is_strong(language_mode())) {
- // Super calls in strong mode are parsed separately.
- ReportMessageAt(scanner()->location(),
- MessageTemplate::kStrongConstructorSuper);
- *ok = false;
- return this->EmptyExpression();
- }
// TODO(rossberg): This might not be the correct FunctionState for the
// method here.
function_state_->set_super_location(scanner()->location());
@@ -2878,6 +2655,11 @@
ParseTemplateLiteral(expression, pos, classifier, CHECK_OK);
break;
}
+ case Token::ILLEGAL: {
+ ReportUnexpectedTokenAt(scanner()->peek_location(), Token::ILLEGAL);
+ *ok = false;
+ return this->EmptyExpression();
+ }
default:
return expression;
}
@@ -2894,7 +2676,6 @@
// BindingElement[?Yield, ?GeneratorParameter]
bool is_rest = parameters->has_rest;
- Token::Value next = peek();
ExpressionT pattern = ParsePrimaryExpression(classifier, ok);
if (!*ok) return;
@@ -2902,11 +2683,6 @@
if (!*ok) return;
if (!Traits::IsIdentifier(pattern)) {
- if (!allow_harmony_destructuring_bind()) {
- ReportUnexpectedToken(next);
- *ok = false;
- return;
- }
parameters->is_simple = false;
ValidateFormalParameterInitializer(classifier, ok);
if (!*ok) return;
@@ -2914,7 +2690,7 @@
}
ExpressionT initializer = Traits::EmptyExpression();
- if (!is_rest && allow_harmony_default_parameters() && Check(Token::ASSIGN)) {
+ if (!is_rest && Check(Token::ASSIGN)) {
ExpressionClassifier init_classifier(this);
initializer = ParseAssignmentExpression(true, &init_classifier, ok);
if (!*ok) return;
@@ -3099,6 +2875,10 @@
body->Add(factory()->NewReturnStatement(expression, pos), zone());
materialized_literal_count = function_state.materialized_literal_count();
expected_property_count = function_state.expected_property_count();
+ // ES6 14.6.1 Static Semantics: IsInTailPosition
+ if (allow_tailcalls() && !is_sloppy(language_mode())) {
+ this->MarkTailPosition(expression);
+ }
}
super_loc = function_state.super_location();
@@ -3253,47 +3033,25 @@
ParserBase<Traits>::CheckAndRewriteReferenceExpression(
ExpressionT expression, int beg_pos, int end_pos,
MessageTemplate::Template message, ParseErrorType type, bool* ok) {
- ExpressionClassifier classifier(this);
- ExpressionT result = ClassifyAndRewriteReferenceExpression(
- &classifier, expression, beg_pos, end_pos, message, type);
- ValidateExpression(&classifier, ok);
- if (!*ok) return this->EmptyExpression();
- return result;
-}
-
-
-template <typename Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ClassifyAndRewriteReferenceExpression(
- ExpressionClassifier* classifier, ExpressionT expression, int beg_pos,
- int end_pos, MessageTemplate::Template message, ParseErrorType type) {
- Scanner::Location location(beg_pos, end_pos);
- if (this->IsIdentifier(expression)) {
- if (is_strict(language_mode()) &&
- this->IsEvalOrArguments(this->AsIdentifier(expression))) {
- classifier->RecordExpressionError(
- location, MessageTemplate::kStrictEvalArguments, kSyntaxError);
- return expression;
- }
- if (is_strong(language_mode()) &&
- this->IsUndefined(this->AsIdentifier(expression))) {
- classifier->RecordExpressionError(
- location, MessageTemplate::kStrongUndefined, kSyntaxError);
- return expression;
- }
+ if (this->IsIdentifier(expression) && is_strict(language_mode()) &&
+ this->IsEvalOrArguments(this->AsIdentifier(expression))) {
+ ReportMessageAt(Scanner::Location(beg_pos, end_pos),
+ MessageTemplate::kStrictEvalArguments, kSyntaxError);
+ *ok = false;
+ return this->EmptyExpression();
}
if (expression->IsValidReferenceExpression()) {
return expression;
- } else if (expression->IsCall()) {
+ }
+ if (expression->IsCall()) {
// If it is a call, make it a runtime error for legacy web compatibility.
// Rewrite `expr' to `expr[throw ReferenceError]'.
- int pos = location.beg_pos;
- ExpressionT error = this->NewThrowReferenceError(message, pos);
- return factory()->NewProperty(expression, error, pos);
- } else {
- classifier->RecordExpressionError(location, message, type);
- return expression;
+ ExpressionT error = this->NewThrowReferenceError(message, beg_pos);
+ return factory()->NewProperty(expression, error, beg_pos);
}
+ ReportMessageAt(Scanner::Location(beg_pos, end_pos), message, type);
+ *ok = false;
+ return this->EmptyExpression();
}
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
index 968e8ed..fa2893b 100644
--- a/src/parsing/parser.cc
+++ b/src/parsing/parser.cc
@@ -439,6 +439,14 @@
*x = factory->NewNumberLiteral(value, pos, has_dot);
return true;
}
+ case Token::EXP: {
+ double value = Pow(x_val, y_val);
+ int int_value = static_cast<int>(value);
+ *x = factory->NewNumberLiteral(
+ int_value == value && value != -0.0 ? int_value : value, pos,
+ has_dot);
+ return true;
+ }
default:
break;
}
@@ -491,6 +499,20 @@
return factory->NewUnaryOperation(op, expression, pos);
}
+Expression* ParserTraits::BuildIteratorResult(Expression* value, bool done) {
+ int pos = RelocInfo::kNoPosition;
+ AstNodeFactory* factory = parser_->factory();
+ Zone* zone = parser_->zone();
+
+ if (value == nullptr) value = factory->NewUndefinedLiteral(pos);
+
+ auto args = new (zone) ZoneList<Expression*>(2, zone);
+ args->Add(value, zone);
+ args->Add(factory->NewBooleanLiteral(done, pos), zone);
+
+ return factory->NewCallRuntime(Runtime::kInlineCreateIterResultObject, args,
+ pos);
+}
Expression* ParserTraits::NewThrowReferenceError(
MessageTemplate::Template message, int pos) {
@@ -734,14 +756,17 @@
function_token_position, type, language_mode, ok);
}
-
ClassLiteral* ParserTraits::ParseClassLiteral(
- const AstRawString* name, Scanner::Location class_name_location,
- bool name_is_strict_reserved, int pos, bool* ok) {
- return parser_->ParseClassLiteral(name, class_name_location,
+ Type::ExpressionClassifier* classifier, const AstRawString* name,
+ Scanner::Location class_name_location, bool name_is_strict_reserved,
+ int pos, bool* ok) {
+ return parser_->ParseClassLiteral(classifier, name, class_name_location,
name_is_strict_reserved, pos, ok);
}
+void ParserTraits::MarkTailPosition(Expression* expression) {
+ expression->MarkTail();
+}
Parser::Parser(ParseInfo* info)
: ParserBase<ParserTraits>(info->zone(), &scanner_, info->stack_limit(),
@@ -762,18 +787,18 @@
DCHECK(!info->script().is_null() || info->source_stream() != NULL);
set_allow_lazy(info->allow_lazy_parsing());
set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
+ set_allow_tailcalls(FLAG_harmony_tailcalls && !info->is_native() &&
+ info->isolate()->is_tail_call_elimination_enabled());
set_allow_harmony_sloppy(FLAG_harmony_sloppy);
set_allow_harmony_sloppy_function(FLAG_harmony_sloppy_function);
set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let);
- set_allow_harmony_default_parameters(FLAG_harmony_default_parameters);
- set_allow_harmony_destructuring_bind(FLAG_harmony_destructuring_bind);
- set_allow_harmony_destructuring_assignment(
- FLAG_harmony_destructuring_assignment);
- set_allow_strong_mode(FLAG_strong_mode);
- set_allow_legacy_const(FLAG_legacy_const);
set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
set_allow_harmony_function_name(FLAG_harmony_function_name);
set_allow_harmony_function_sent(FLAG_harmony_function_sent);
+ set_allow_harmony_restrictive_declarations(
+ FLAG_harmony_restrictive_declarations);
+ set_allow_harmony_exponentiation_operator(
+ FLAG_harmony_exponentiation_operator);
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) {
use_counts_[feature] = 0;
@@ -901,7 +926,7 @@
kNormalFunction, &function_factory);
// Don't count the mode in the use counters--give the program a chance
- // to enable script/module-wide strict/strong mode below.
+ // to enable script/module-wide strict mode below.
scope_->SetLanguageMode(info->language_mode());
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
bool ok = true;
@@ -926,8 +951,7 @@
// unchanged if the property already exists.
InsertSloppyBlockFunctionVarBindings(scope, &ok);
}
- if (ok && (is_strict(language_mode()) || allow_harmony_sloppy() ||
- allow_harmony_destructuring_bind())) {
+ if (ok) {
CheckConflictingVarDeclarations(scope_, &ok);
}
@@ -1154,28 +1178,7 @@
}
Scanner::Location token_loc = scanner()->peek_location();
- Scanner::Location old_this_loc = function_state_->this_location();
- Scanner::Location old_super_loc = function_state_->super_location();
Statement* stat = ParseStatementListItem(CHECK_OK);
-
- if (is_strong(language_mode()) && scope_->is_function_scope() &&
- IsClassConstructor(function_state_->kind())) {
- Scanner::Location this_loc = function_state_->this_location();
- Scanner::Location super_loc = function_state_->super_location();
- if (this_loc.beg_pos != old_this_loc.beg_pos &&
- this_loc.beg_pos != token_loc.beg_pos) {
- ReportMessageAt(this_loc, MessageTemplate::kStrongConstructorThis);
- *ok = false;
- return nullptr;
- }
- if (super_loc.beg_pos != old_super_loc.beg_pos &&
- super_loc.beg_pos != token_loc.beg_pos) {
- ReportMessageAt(super_loc, MessageTemplate::kStrongConstructorSuper);
- *ok = false;
- return nullptr;
- }
- }
-
if (stat == NULL || stat->IsEmpty()) {
directive_prologue = false; // End of directive prologue.
continue;
@@ -1189,43 +1192,21 @@
if ((e_stat = stat->AsExpressionStatement()) != NULL &&
(literal = e_stat->expression()->AsLiteral()) != NULL &&
literal->raw_value()->IsString()) {
- // Check "use strict" directive (ES5 14.1), "use asm" directive, and
- // "use strong" directive (experimental).
+ // Check "use strict" directive (ES5 14.1), "use asm" directive.
bool use_strict_found =
literal->raw_value()->AsString() ==
ast_value_factory()->use_strict_string() &&
token_loc.end_pos - token_loc.beg_pos ==
ast_value_factory()->use_strict_string()->length() + 2;
- bool use_strong_found =
- allow_strong_mode() &&
- literal->raw_value()->AsString() ==
- ast_value_factory()->use_strong_string() &&
- token_loc.end_pos - token_loc.beg_pos ==
- ast_value_factory()->use_strong_string()->length() + 2;
- if (use_strict_found || use_strong_found) {
- // Strong mode implies strict mode. If there are several "use strict"
- // / "use strong" directives, do the strict mode changes only once.
+ if (use_strict_found) {
if (is_sloppy(scope_->language_mode())) {
RaiseLanguageMode(STRICT);
}
- if (use_strong_found) {
- RaiseLanguageMode(STRONG);
- if (IsClassConstructor(function_state_->kind())) {
- // "use strong" cannot occur in a class constructor body, to avoid
- // unintuitive strong class object semantics.
- ParserTraits::ReportMessageAt(
- token_loc, MessageTemplate::kStrongConstructorDirective);
- *ok = false;
- return nullptr;
- }
- }
if (!scope_->HasSimpleParameters()) {
// TC39 deemed "use strict" directives to be an error when occurring
// in the body of a function with non-simple parameter list, on
// 29/7/2015. https://goo.gl/ueA7Ln
- //
- // In V8, this also applies to "use strong " directives.
const AstRawString* string = literal->raw_value()->AsString();
ParserTraits::ReportMessageAt(
token_loc, MessageTemplate::kIllegalLanguageModeDirective,
@@ -1294,7 +1275,7 @@
default:
break;
}
- return ParseStatement(NULL, ok);
+ return ParseStatement(NULL, kAllowLabelledFunctionStatement, ok);
}
@@ -1445,10 +1426,6 @@
*ok = false;
ReportMessage(MessageTemplate::kStrictEvalArguments);
return NULL;
- } else if (is_strong(language_mode()) && IsUndefined(local_name)) {
- *ok = false;
- ReportMessage(MessageTemplate::kStrongUndefined);
- return NULL;
}
VariableProxy* proxy = NewUnresolved(local_name, IMPORT);
ImportDeclaration* declaration =
@@ -1594,9 +1571,9 @@
if (peek() == Token::EXTENDS || peek() == Token::LBRACE) {
// ClassDeclaration[+Default] ::
// 'class' ('extends' LeftHandExpression)? '{' ClassBody '}'
- default_export =
- ParseClassLiteral(default_string, Scanner::Location::invalid(),
- false, position(), CHECK_OK);
+ default_export = ParseClassLiteral(nullptr, default_string,
+ Scanner::Location::invalid(), false,
+ position(), CHECK_OK);
result = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
} else {
result = ParseClassDeclaration(&names, CHECK_OK);
@@ -1748,8 +1725,8 @@
return result;
}
-
Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
+ AllowLabelledFunctionStatement allow_function,
bool* ok) {
// Statement ::
// EmptyStatement
@@ -1759,12 +1736,12 @@
Next();
return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
}
- return ParseSubStatement(labels, ok);
+ return ParseSubStatement(labels, allow_function, ok);
}
-
-Statement* Parser::ParseSubStatement(ZoneList<const AstRawString*>* labels,
- bool* ok) {
+Statement* Parser::ParseSubStatement(
+ ZoneList<const AstRawString*>* labels,
+ AllowLabelledFunctionStatement allow_function, bool* ok) {
// Statement ::
// Block
// VariableStatement
@@ -1793,12 +1770,6 @@
return ParseBlock(labels, ok);
case Token::SEMICOLON:
- if (is_strong(language_mode())) {
- ReportMessageAt(scanner()->peek_location(),
- MessageTemplate::kStrongEmpty);
- *ok = false;
- return NULL;
- }
Next();
return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
@@ -1839,26 +1810,18 @@
case Token::SWITCH:
return ParseSwitchStatement(labels, ok);
- case Token::FUNCTION: {
- // FunctionDeclaration is only allowed in the context of SourceElements
- // (Ecma 262 5th Edition, clause 14):
- // SourceElement:
- // Statement
- // FunctionDeclaration
- // Common language extension is to allow function declaration in place
- // of any statement. This language extension is disabled in strict mode.
- //
- // In Harmony mode, this case also handles the extension:
- // Statement:
- // GeneratorDeclaration
- if (is_strict(language_mode())) {
- ReportMessageAt(scanner()->peek_location(),
- MessageTemplate::kStrictFunction);
- *ok = false;
- return NULL;
- }
- return ParseFunctionDeclaration(NULL, ok);
- }
+ case Token::FUNCTION:
+ // FunctionDeclaration only allowed as a StatementListItem, not in
+ // an arbitrary Statement position. Exceptions such as
+ // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
+ // are handled by calling ParseScopedStatement rather than
+ // ParseSubStatement directly.
+ ReportMessageAt(scanner()->peek_location(),
+ is_strict(language_mode())
+ ? MessageTemplate::kStrictFunction
+ : MessageTemplate::kSloppyFunction);
+ *ok = false;
+ return nullptr;
case Token::DEBUGGER:
return ParseDebuggerStatement(ok);
@@ -1866,17 +1829,8 @@
case Token::VAR:
return ParseVariableStatement(kStatement, NULL, ok);
- case Token::CONST:
- // In ES6 CONST is not allowed as a Statement, only as a
- // LexicalDeclaration, however we continue to allow it in sloppy mode for
- // backwards compatibility.
- if (is_sloppy(language_mode()) && allow_legacy_const()) {
- return ParseVariableStatement(kStatement, NULL, ok);
- }
-
- // Fall through.
default:
- return ParseExpressionOrLabelledStatement(labels, ok);
+ return ParseExpressionOrLabelledStatement(labels, allow_function, ok);
}
}
@@ -1958,13 +1912,6 @@
}
var = declaration_scope->DeclareLocal(
name, mode, declaration->initialization(), kind, kNotAssigned);
- } else if ((mode == CONST_LEGACY || var->mode() == CONST_LEGACY) &&
- !declaration_scope->is_script_scope()) {
- // Duplicate legacy const definitions throw at runtime.
- DCHECK(is_sloppy(language_mode()));
- Expression* expression = NewThrowSyntaxError(
- MessageTemplate::kVarRedeclaration, name, declaration->position());
- declaration_scope->SetIllegalRedeclaration(expression);
} else if ((IsLexicalVariableMode(mode) ||
IsLexicalVariableMode(var->mode())) &&
// Lexical bindings may appear for some parameters in sloppy
@@ -2160,12 +2107,10 @@
// In ES6, a function behaves as a lexical binding, except in
// a script scope, or the initial scope of eval or another function.
VariableMode mode =
- is_strong(language_mode())
- ? CONST
- : (is_strict(language_mode()) || allow_harmony_sloppy_function()) &&
- !scope_->is_declaration_scope()
- ? LET
- : VAR;
+ (is_strict(language_mode()) || allow_harmony_sloppy_function()) &&
+ !scope_->is_declaration_scope()
+ ? LET
+ : VAR;
VariableProxy* proxy = NewUnresolved(name, mode);
Declaration* declaration =
factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
@@ -2211,13 +2156,12 @@
bool is_strict_reserved = false;
const AstRawString* name =
ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
- ClassLiteral* value = ParseClassLiteral(name, scanner()->location(),
+ ClassLiteral* value = ParseClassLiteral(nullptr, name, scanner()->location(),
is_strict_reserved, pos, CHECK_OK);
- VariableMode mode = is_strong(language_mode()) ? CONST : LET;
- VariableProxy* proxy = NewUnresolved(name, mode);
+ VariableProxy* proxy = NewUnresolved(name, LET);
Declaration* declaration =
- factory()->NewVariableDeclaration(proxy, mode, scope_, pos);
+ factory()->NewVariableDeclaration(proxy, LET, scope_, pos);
Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
proxy->var()->set_initializer_position(position());
Assignment* assignment =
@@ -2337,23 +2281,12 @@
}
if (peek() == Token::VAR) {
- if (is_strong(language_mode())) {
- Scanner::Location location = scanner()->peek_location();
- ReportMessageAt(location, MessageTemplate::kStrongVar);
- *ok = false;
- return nullptr;
- }
Consume(Token::VAR);
} else if (peek() == Token::CONST && allow_const()) {
Consume(Token::CONST);
- if (is_sloppy(language_mode()) && allow_legacy_const()) {
- parsing_result->descriptor.mode = CONST_LEGACY;
- ++use_counts_[v8::Isolate::kLegacyConst];
- } else {
- DCHECK(is_strict(language_mode()) || allow_harmony_sloppy());
- DCHECK(var_context != kStatement);
- parsing_result->descriptor.mode = CONST;
- }
+ DCHECK(is_strict(language_mode()) || allow_harmony_sloppy());
+ DCHECK(var_context != kStatement);
+ parsing_result->descriptor.mode = CONST;
} else if (peek() == Token::LET && allow_let()) {
Consume(Token::LET);
DCHECK(var_context != kStatement);
@@ -2378,17 +2311,11 @@
int decl_pos = peek_position();
{
ExpressionClassifier pattern_classifier(this);
- Token::Value next = peek();
pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
ValidateBindingPattern(&pattern_classifier, CHECK_OK);
if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
ValidateLetPattern(&pattern_classifier, CHECK_OK);
}
- if (!allow_harmony_destructuring_bind() && !pattern->IsVariableProxy()) {
- ReportUnexpectedToken(next);
- *ok = false;
- return nullptr;
- }
}
Scanner::Location variable_loc = scanner()->location();
@@ -2492,9 +2419,9 @@
return false;
}
-
Statement* Parser::ParseExpressionOrLabelledStatement(
- ZoneList<const AstRawString*>* labels, bool* ok) {
+ ZoneList<const AstRawString*>* labels,
+ AllowLabelledFunctionStatement allow_function, bool* ok) {
// ExpressionStatement | LabelledStatement ::
// Expression ';'
// Identifier ':' Statement
@@ -2513,42 +2440,6 @@
*ok = false;
return nullptr;
- case Token::THIS:
- if (!FLAG_strong_this) break;
- // Fall through.
- case Token::SUPER:
- if (is_strong(language_mode()) &&
- IsClassConstructor(function_state_->kind())) {
- bool is_this = peek() == Token::THIS;
- Expression* expr;
- ExpressionClassifier classifier(this);
- if (is_this) {
- expr = ParseStrongInitializationExpression(&classifier, CHECK_OK);
- } else {
- expr = ParseStrongSuperCallExpression(&classifier, CHECK_OK);
- }
- RewriteNonPattern(&classifier, CHECK_OK);
- switch (peek()) {
- case Token::SEMICOLON:
- Consume(Token::SEMICOLON);
- break;
- case Token::RBRACE:
- case Token::EOS:
- break;
- default:
- if (!scanner()->HasAnyLineTerminatorBeforeNext()) {
- ReportMessageAt(function_state_->this_location(),
- is_this
- ? MessageTemplate::kStrongConstructorThis
- : MessageTemplate::kStrongConstructorSuper);
- *ok = false;
- return nullptr;
- }
- }
- return factory()->NewExpressionStatement(expr, pos);
- }
- break;
-
default:
break;
}
@@ -2581,7 +2472,15 @@
// during the scope processing.
scope_->RemoveUnresolved(var);
Expect(Token::COLON, CHECK_OK);
- return ParseStatement(labels, ok);
+ // ES#sec-labelled-function-declarations Labelled Function Declarations
+ if (peek() == Token::FUNCTION && is_sloppy(language_mode())) {
+ if (allow_function == kAllowLabelledFunctionStatement) {
+ return ParseFunctionDeclaration(labels, ok);
+ } else {
+ return ParseScopedStatement(labels, true, ok);
+ }
+ }
+ return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok);
}
// If we have an extension, we allow a native function declaration.
@@ -2621,11 +2520,11 @@
Expect(Token::LPAREN, CHECK_OK);
Expression* condition = ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
- Statement* then_statement = ParseSubStatement(labels, CHECK_OK);
+ Statement* then_statement = ParseScopedStatement(labels, false, CHECK_OK);
Statement* else_statement = NULL;
if (peek() == Token::ELSE) {
Next();
- else_statement = ParseSubStatement(labels, CHECK_OK);
+ else_statement = ParseScopedStatement(labels, false, CHECK_OK);
} else {
else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
}
@@ -2724,15 +2623,6 @@
return_value = GetLiteralUndefined(position());
}
} else {
- if (is_strong(language_mode()) &&
- IsClassConstructor(function_state_->kind())) {
- int pos = peek_position();
- ReportMessageAt(Scanner::Location(pos, pos + 1),
- MessageTemplate::kStrongConstructorReturnValue);
- *ok = false;
- return NULL;
- }
-
int pos = peek_position();
return_value = ParseExpression(true, CHECK_OK);
@@ -2778,22 +2668,18 @@
}
// ES6 14.6.1 Static Semantics: IsInTailPosition
- if (FLAG_harmony_tailcalls && !is_sloppy(language_mode())) {
+ if (allow_tailcalls() && !is_sloppy(language_mode())) {
function_state_->AddExpressionInTailPosition(return_value);
}
}
ExpectSemicolon(CHECK_OK);
if (is_generator()) {
- Expression* generator = factory()->NewVariableProxy(
- function_state_->generator_object_variable());
- Expression* yield = factory()->NewYield(
- generator, return_value, Yield::kFinal, loc.beg_pos);
- result = factory()->NewExpressionStatement(yield, loc.beg_pos);
- } else {
- result = factory()->NewReturnStatement(return_value, loc.beg_pos);
+ return_value = BuildIteratorResult(return_value, true);
}
+ result = factory()->NewReturnStatement(return_value, loc.beg_pos);
+
Scope* decl_scope = scope_->DeclarationScope();
if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) {
ReportMessageAt(loc, MessageTemplate::kIllegalReturn);
@@ -2822,27 +2708,11 @@
Expression* expr = ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
- scope_->DeclarationScope()->RecordWithStatement();
Scope* with_scope = NewScope(scope_, WITH_SCOPE);
- Block* body;
+ Statement* body;
{ BlockState block_state(&scope_, with_scope);
with_scope->set_start_position(scanner()->peek_location().beg_pos);
-
- // The body of the with statement must be enclosed in an additional
- // lexical scope in case the body is a FunctionDeclaration.
- body = factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
- Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
- block_scope->set_start_position(scanner()->location().beg_pos);
- {
- BlockState block_state(&scope_, block_scope);
- Target target(&this->target_stack_, body);
- Statement* stmt = ParseSubStatement(labels, CHECK_OK);
- body->statements()->Add(stmt, zone());
- block_scope->set_end_position(scanner()->location().end_pos);
- block_scope = block_scope->FinalizeBlockScope();
- body->set_scope(block_scope);
- }
-
+ body = ParseScopedStatement(labels, true, CHECK_OK);
with_scope->set_end_position(scanner()->location().end_pos);
}
return factory()->NewWithStatement(with_scope, expr, body, pos);
@@ -2878,13 +2748,6 @@
stat = ParseStatementListItem(CHECK_OK);
statements->Add(stat, zone());
}
- if (is_strong(language_mode()) && stat != NULL && !stat->IsJump() &&
- peek() != Token::RBRACE) {
- ReportMessageAt(scanner()->location(),
- MessageTemplate::kStrongSwitchFallthrough);
- *ok = false;
- return NULL;
- }
return factory()->NewCaseClause(label, statements, pos);
}
@@ -3108,8 +2971,11 @@
pattern, pattern->position(),
factory()->NewVariableProxy(catch_variable));
+ Block* init_block =
+ factory()->NewBlock(nullptr, 8, true, RelocInfo::kNoPosition);
PatternRewriter::DeclareAndInitializeVariables(
- catch_block, &descriptor, &decl, nullptr, CHECK_OK);
+ init_block, &descriptor, &decl, nullptr, CHECK_OK);
+ catch_block->statements()->Add(init_block, zone());
}
Expect(Token::LBRACE, CHECK_OK);
@@ -3183,7 +3049,7 @@
Target target(&this->target_stack_, loop);
Expect(Token::DO, CHECK_OK);
- Statement* body = ParseSubStatement(NULL, CHECK_OK);
+ Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
@@ -3213,7 +3079,7 @@
Expect(Token::LPAREN, CHECK_OK);
Expression* cond = ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
- Statement* body = ParseSubStatement(NULL, CHECK_OK);
+ Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
if (loop != NULL) loop->Initialize(cond, body);
return loop;
@@ -3257,76 +3123,15 @@
throw_call, pos);
}
-
void Parser::InitializeForEachStatement(ForEachStatement* stmt,
Expression* each, Expression* subject,
- Statement* body,
- bool is_destructuring) {
- DCHECK(!is_destructuring || allow_harmony_destructuring_assignment());
+ Statement* body) {
ForOfStatement* for_of = stmt->AsForOfStatement();
-
if (for_of != NULL) {
- Variable* iterator = scope_->NewTemporary(
- ast_value_factory()->dot_iterator_string());
- Variable* result = scope_->NewTemporary(
- ast_value_factory()->dot_result_string());
-
- Expression* assign_iterator;
- Expression* next_result;
- Expression* result_done;
- Expression* assign_each;
-
- // iterator = subject[Symbol.iterator]()
- // Hackily disambiguate o from o.next and o [Symbol.iterator]().
- // TODO(verwaest): Come up with a better solution.
- assign_iterator = factory()->NewAssignment(
- Token::ASSIGN, factory()->NewVariableProxy(iterator),
- GetIterator(subject, factory(), subject->position() - 2),
- subject->position());
-
- // !%_IsJSReceiver(result = iterator.next()) &&
- // %ThrowIteratorResultNotAnObject(result)
- {
- // result = iterator.next()
- Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
- // Hackily disambiguate o from o.next and o [Symbol.iterator]().
- // TODO(verwaest): Come up with a better solution.
- next_result = BuildIteratorNextResult(iterator_proxy, result,
- subject->position() - 1);
- }
-
- // result.done
- {
- Expression* done_literal = factory()->NewStringLiteral(
- ast_value_factory()->done_string(), RelocInfo::kNoPosition);
- Expression* result_proxy = factory()->NewVariableProxy(result);
- result_done = factory()->NewProperty(
- result_proxy, done_literal, RelocInfo::kNoPosition);
- }
-
- // each = result.value
- {
- Expression* value_literal = factory()->NewStringLiteral(
- ast_value_factory()->value_string(), RelocInfo::kNoPosition);
- Expression* result_proxy = factory()->NewVariableProxy(result);
- Expression* result_value = factory()->NewProperty(
- result_proxy, value_literal, RelocInfo::kNoPosition);
- assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
- RelocInfo::kNoPosition);
- if (is_destructuring) {
- assign_each = PatternRewriter::RewriteDestructuringAssignment(
- this, assign_each->AsAssignment(), scope_);
- }
- }
-
- for_of->Initialize(each, subject, body,
- iterator,
- assign_iterator,
- next_result,
- result_done,
- assign_each);
+ InitializeForOfStatement(for_of, each, subject, body,
+ RelocInfo::kNoPosition);
} else {
- if (is_destructuring) {
+ if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
Variable* temp =
scope_->NewTemporary(ast_value_factory()->empty_string());
VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
@@ -3347,6 +3152,70 @@
}
}
+void Parser::InitializeForOfStatement(ForOfStatement* for_of, Expression* each,
+ Expression* iterable, Statement* body,
+ int iterable_pos) {
+ Variable* iterator =
+ scope_->NewTemporary(ast_value_factory()->dot_iterator_string());
+ Variable* result =
+ scope_->NewTemporary(ast_value_factory()->dot_result_string());
+
+ Expression* assign_iterator;
+ Expression* next_result;
+ Expression* result_done;
+ Expression* assign_each;
+
+ // Hackily disambiguate o from o.next and o [Symbol.iterator]().
+ // TODO(verwaest): Come up with a better solution.
+ int get_iterator_pos = iterable_pos != RelocInfo::kNoPosition
+ ? iterable_pos
+ : iterable->position() - 2;
+ int next_result_pos = iterable_pos != RelocInfo::kNoPosition
+ ? iterable_pos
+ : iterable->position() - 1;
+
+ // iterator = iterable[Symbol.iterator]()
+ assign_iterator = factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(iterator),
+ GetIterator(iterable, factory(), get_iterator_pos), iterable->position());
+
+ // !%_IsJSReceiver(result = iterator.next()) &&
+ // %ThrowIteratorResultNotAnObject(result)
+ {
+ // result = iterator.next()
+ Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
+ next_result =
+ BuildIteratorNextResult(iterator_proxy, result, next_result_pos);
+ }
+
+ // result.done
+ {
+ Expression* done_literal = factory()->NewStringLiteral(
+ ast_value_factory()->done_string(), RelocInfo::kNoPosition);
+ Expression* result_proxy = factory()->NewVariableProxy(result);
+ result_done = factory()->NewProperty(result_proxy, done_literal,
+ RelocInfo::kNoPosition);
+ }
+
+ // each = result.value
+ {
+ Expression* value_literal = factory()->NewStringLiteral(
+ ast_value_factory()->value_string(), RelocInfo::kNoPosition);
+ Expression* result_proxy = factory()->NewVariableProxy(result);
+ Expression* result_value = factory()->NewProperty(
+ result_proxy, value_literal, RelocInfo::kNoPosition);
+ assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
+ RelocInfo::kNoPosition);
+ if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
+ assign_each = PatternRewriter::RewriteDestructuringAssignment(
+ this, assign_each->AsAssignment(), scope_);
+ }
+ }
+
+ for_of->Initialize(each, iterable, body, iterator, assign_iterator,
+ next_result, result_done, assign_each);
+}
+
Statement* Parser::DesugarLexicalBindingsInForStatement(
Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names,
ForStatement* loop, Statement* init, Expression* cond, Statement* next,
@@ -3595,6 +3464,28 @@
return outer_block;
}
+Statement* Parser::ParseScopedStatement(ZoneList<const AstRawString*>* labels,
+ bool legacy, bool* ok) {
+ if (is_strict(language_mode()) || peek() != Token::FUNCTION ||
+ (legacy && allow_harmony_restrictive_declarations())) {
+ return ParseSubStatement(labels, kDisallowLabelledFunctionStatement, ok);
+ } else {
+ if (legacy) {
+ ++use_counts_[v8::Isolate::kLegacyFunctionDeclaration];
+ }
+ // Make a block around the statement for a lexical binding
+ // is introduced by a FunctionDeclaration.
+ Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
+ BlockState block_state(&scope_, body_scope);
+ Block* block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
+ Statement* body = ParseFunctionDeclaration(NULL, CHECK_OK);
+ block->statements()->Add(body, zone());
+ body_scope->set_end_position(scanner()->location().end_pos);
+ body_scope = body_scope->FinalizeBlockScope();
+ block->set_scope(body_scope);
+ return block;
+ }
+}
Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
bool* ok) {
@@ -3617,7 +3508,7 @@
ParseVariableDeclarations(kForStatement, &parsing_result, nullptr,
CHECK_OK);
- ForEachStatement::VisitMode mode;
+ ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE;
int each_beg_pos = scanner()->location().beg_pos;
int each_end_pos = scanner()->location().end_pos;
@@ -3706,9 +3597,11 @@
factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
{
+ DontCollectExpressionsInTailPositionScope no_tail_calls(
+ function_state_);
BlockState block_state(&scope_, body_scope);
- Statement* body = ParseSubStatement(NULL, CHECK_OK);
+ Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
auto each_initialization_block =
factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
@@ -3729,8 +3622,7 @@
body_block->statements()->Add(body, zone());
VariableProxy* temp_proxy =
factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
- InitializeForEachStatement(loop, temp_proxy, enumerable, body_block,
- false);
+ InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
}
body_scope->set_end_position(scanner()->location().end_pos);
body_scope = body_scope->FinalizeBlockScope();
@@ -3785,7 +3677,7 @@
ExpressionClassifier classifier(this);
Expression* expression = ParseExpression(false, &classifier, CHECK_OK);
int lhs_end_pos = scanner()->location().end_pos;
- ForEachStatement::VisitMode mode;
+ ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE;
is_let_identifier_expression =
expression->IsVariableProxy() &&
expression->AsVariableProxy()->raw_name() ==
@@ -3793,9 +3685,8 @@
bool is_for_each = CheckInOrOf(&mode, ok);
if (!*ok) return nullptr;
- bool is_destructuring =
- is_for_each && allow_harmony_destructuring_assignment() &&
- (expression->IsArrayLiteral() || expression->IsObjectLiteral());
+ bool is_destructuring = is_for_each && (expression->IsArrayLiteral() ||
+ expression->IsObjectLiteral());
if (is_destructuring) {
ValidateAssignmentPattern(&classifier, CHECK_OK);
@@ -3825,25 +3716,10 @@
Expect(Token::RPAREN, CHECK_OK);
- // Make a block around the statement in case a lexical binding
- // is introduced, e.g. by a FunctionDeclaration.
- // This block must not use for_scope as its scope because if a
- // lexical binding is introduced which overlaps with the for-in/of,
- // expressions in head of the loop should actually have variables
- // resolved in the outer scope.
- Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE);
- {
- BlockState block_state(&scope_, body_scope);
- Block* block =
- factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
- Statement* body = ParseSubStatement(NULL, CHECK_OK);
- block->statements()->Add(body, zone());
- InitializeForEachStatement(loop, expression, enumerable, block,
- is_destructuring);
- body_scope->set_end_position(scanner()->location().end_pos);
- body_scope = body_scope->FinalizeBlockScope();
- block->set_scope(body_scope);
- }
+ // For legacy compat reasons, give for loops similar treatment to
+ // if statements in allowing a function declaration for a body
+ Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
+ InitializeForEachStatement(loop, expression, enumerable, body);
Statement* final_loop = loop->IsForOfStatement()
? FinalizeForOfStatement(
@@ -3900,7 +3776,7 @@
}
Expect(Token::RPAREN, CHECK_OK);
- body = ParseSubStatement(NULL, CHECK_OK);
+ body = ParseScopedStatement(NULL, true, CHECK_OK);
}
Statement* result = NULL;
@@ -4064,7 +3940,6 @@
parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
} else if (expr->IsAssignment()) {
Assignment* assignment = expr->AsAssignment();
- DCHECK(parser_->allow_harmony_default_parameters());
DCHECK(!assignment->is_compound());
initializer = assignment->value();
expr = assignment->target();
@@ -4227,7 +4102,8 @@
if (is_generator) {
// For generators, allocating variables in contexts is currently a win
// because it minimizes the work needed to suspend and resume an
- // activation.
+ // activation. The machine code produced for generators (by full-codegen)
+ // relies on this forced context allocation, but not in an essential way.
scope_->ForceContextAllocation();
// Calling a generator returns a generator object. That object is stored
@@ -4347,7 +4223,7 @@
// temp_zone is deallocated. These objects are instead allocated in a
// parser-persistent zone (see parser_zone_ in AstNodeFactory).
{
- Zone temp_zone;
+ Zone temp_zone(zone()->allocator());
AstNodeFactory::BodyScope inner(factory(), &temp_zone, use_temp_zone);
body = ParseEagerFunctionBody(function_name, pos, formals, kind,
@@ -4365,16 +4241,6 @@
// Parsing the body may change the language mode in our scope.
language_mode = scope->language_mode();
- if (is_strong(language_mode) && IsSubclassConstructor(kind)) {
- if (!function_state.super_location().IsValid()) {
- ReportMessageAt(function_name_location,
- MessageTemplate::kStrongSuperCallMissing,
- kReferenceError);
- *ok = false;
- return nullptr;
- }
- }
-
// Validate name and parameter names. We can do this only after parsing the
// function, since the function can declare itself strict.
CheckFunctionName(language_mode, function_name, function_name_validity,
@@ -4391,10 +4257,7 @@
if (is_sloppy(language_mode) && allow_harmony_sloppy_function()) {
InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK);
}
- if (is_strict(language_mode) || allow_harmony_sloppy() ||
- allow_harmony_destructuring_bind()) {
- CheckConflictingVarDeclarations(scope, CHECK_OK);
- }
+ CheckConflictingVarDeclarations(scope, CHECK_OK);
if (body) {
// If body can be inspected, rewrite queued destructuring assignments
@@ -4677,15 +4540,12 @@
if (IsGeneratorFunction(kind)) {
// We produce:
//
- // try { InitialYield; ...body...; FinalYield }
+ // try { InitialYield; ...body...; return {value: undefined, done: true} }
// finally { %GeneratorClose(generator) }
//
// - InitialYield yields the actual generator object.
- // - FinalYield yields {value: foo, done: true} where foo is the
- // completion value of body. (This is needed here in case the body
- // falls through without an explicit return.)
- // - Any return statement inside the body will be converted into a similar
- // FinalYield.
+ // - Any return statement inside the body will have its argument wrapped
+ // in a "done" iterator result object.
// - If the generator terminates for whatever reason, we must close it.
// Hence the finally clause.
@@ -4703,8 +4563,8 @@
Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition);
VariableProxy* get_proxy = factory()->NewVariableProxy(
function_state_->generator_object_variable());
- Yield* yield = factory()->NewYield(
- get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition);
+ Yield* yield =
+ factory()->NewYield(get_proxy, assignment, RelocInfo::kNoPosition);
try_block->statements()->Add(
factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
zone());
@@ -4712,15 +4572,9 @@
ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK);
- VariableProxy* get_proxy = factory()->NewVariableProxy(
- function_state_->generator_object_variable());
- Expression* undefined =
- factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
- Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal,
- RelocInfo::kNoPosition);
- try_block->statements()->Add(
- factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
- zone());
+ Statement* final_return = factory()->NewReturnStatement(
+ BuildIteratorResult(nullptr, true), RelocInfo::kNoPosition);
+ try_block->statements()->Add(final_return, zone());
Block* finally_block =
factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);
@@ -4801,7 +4655,7 @@
const List<Expression*>& expressions_in_tail_position =
function_state_->expressions_in_tail_position();
for (int i = 0; i < expressions_in_tail_position.length(); ++i) {
- expressions_in_tail_position[i]->MarkTail();
+ MarkTailPosition(expressions_in_tail_position[i]);
}
return result;
}
@@ -4825,14 +4679,13 @@
#define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
SET_ALLOW(natives);
SET_ALLOW(harmony_sloppy);
+ SET_ALLOW(harmony_sloppy_function);
SET_ALLOW(harmony_sloppy_let);
- SET_ALLOW(harmony_default_parameters);
- SET_ALLOW(harmony_destructuring_bind);
- SET_ALLOW(harmony_destructuring_assignment);
- SET_ALLOW(strong_mode);
SET_ALLOW(harmony_do_expressions);
SET_ALLOW(harmony_function_name);
SET_ALLOW(harmony_function_sent);
+ SET_ALLOW(harmony_exponentiation_operator);
+ SET_ALLOW(harmony_restrictive_declarations);
#undef SET_ALLOW
}
PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
@@ -4844,8 +4697,8 @@
return result;
}
-
-ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
+ClassLiteral* Parser::ParseClassLiteral(ExpressionClassifier* classifier,
+ const AstRawString* name,
Scanner::Location class_name_location,
bool name_is_strict_reserved, int pos,
bool* ok) {
@@ -4861,11 +4714,6 @@
*ok = false;
return NULL;
}
- if (is_strong(language_mode()) && IsUndefined(name)) {
- ReportMessageAt(class_name_location, MessageTemplate::kStrongUndefined);
- *ok = false;
- return NULL;
- }
Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
BlockState block_state(&scope_, block_scope);
@@ -4883,9 +4731,13 @@
Expression* extends = NULL;
if (Check(Token::EXTENDS)) {
block_scope->set_start_position(scanner()->location().end_pos);
- ExpressionClassifier classifier(this);
- extends = ParseLeftHandSideExpression(&classifier, CHECK_OK);
- RewriteNonPattern(&classifier, CHECK_OK);
+ ExpressionClassifier extends_classifier(this);
+ extends = ParseLeftHandSideExpression(&extends_classifier, CHECK_OK);
+ RewriteNonPattern(&extends_classifier, CHECK_OK);
+ if (classifier != nullptr) {
+ classifier->Accumulate(&extends_classifier,
+ ExpressionClassifier::ExpressionProductions);
+ }
} else {
block_scope->set_start_position(scanner()->location().end_pos);
}
@@ -4906,12 +4758,16 @@
const bool is_static = false;
bool is_computed_name = false; // Classes do not care about computed
// property names here.
- ExpressionClassifier classifier(this);
+ ExpressionClassifier property_classifier(this);
const AstRawString* property_name = nullptr;
ObjectLiteral::Property* property = ParsePropertyDefinition(
&checker, in_class, has_extends, is_static, &is_computed_name,
- &has_seen_constructor, &classifier, &property_name, CHECK_OK);
- RewriteNonPattern(&classifier, CHECK_OK);
+ &has_seen_constructor, &property_classifier, &property_name, CHECK_OK);
+ RewriteNonPattern(&property_classifier, CHECK_OK);
+ if (classifier != nullptr) {
+ classifier->Accumulate(&property_classifier,
+ ExpressionClassifier::ExpressionProductions);
+ }
if (has_seen_constructor && constructor == NULL) {
constructor = GetPropertyValue(property)->AsFunctionLiteral();
@@ -4938,8 +4794,8 @@
end_pos, block_scope->language_mode());
}
- // Note that we do not finalize this block scope because strong
- // mode uses it as a sentinel value indicating an anonymous class.
+ // Note that we do not finalize this block scope because it is
+ // used as a sentinel value indicating an anonymous class.
block_scope->set_end_position(end_pos);
if (name != NULL) {
@@ -4997,7 +4853,7 @@
// Check that the expected number of arguments are being passed.
if (function->nargs != -1 && function->nargs != args->length()) {
- ReportMessage(MessageTemplate::kIllegalAccess);
+ ReportMessage(MessageTemplate::kRuntimeWrongNumArgs);
*ok = false;
return NULL;
}
@@ -5331,12 +5187,11 @@
ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone());
args->Add(factory()->NewArrayLiteral(
const_cast<ZoneList<Expression*>*>(cooked_strings),
- cooked_idx, is_strong(language_mode()), pos),
+ cooked_idx, pos),
zone());
args->Add(
factory()->NewArrayLiteral(
- const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx,
- is_strong(language_mode()), pos),
+ const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos),
zone());
// Ensure hash is suitable as a Smi value
@@ -5425,7 +5280,6 @@
}
int literal_index = function_state_->NextMaterializedLiteralIndex();
args->Add(factory()->NewArrayLiteral(unspread, literal_index,
- is_strong(language_mode()),
RelocInfo::kNoPosition),
zone());
@@ -5511,8 +5365,6 @@
v8::Isolate::UseCounterFeature feature;
if (is_sloppy(mode))
feature = v8::Isolate::kSloppyMode;
- else if (is_strong(mode))
- feature = v8::Isolate::kStrongMode;
else if (is_strict(mode))
feature = v8::Isolate::kStrictMode;
else
@@ -5523,8 +5375,8 @@
void Parser::RaiseLanguageMode(LanguageMode mode) {
- SetLanguageMode(scope_,
- static_cast<LanguageMode>(scope_->language_mode() | mode));
+ LanguageMode old = scope_->language_mode();
+ SetLanguageMode(scope_, old > mode ? old : mode);
}
@@ -5532,6 +5384,16 @@
parser_->RewriteDestructuringAssignments();
}
+Expression* ParserTraits::RewriteExponentiation(Expression* left,
+ Expression* right, int pos) {
+ return parser_->RewriteExponentiation(left, right, pos);
+}
+
+Expression* ParserTraits::RewriteAssignExponentiation(Expression* left,
+ Expression* right,
+ int pos) {
+ return parser_->RewriteAssignExponentiation(left, right, pos);
+}
void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier,
bool* ok) {
@@ -5605,7 +5467,6 @@
void Parser::RewriteDestructuringAssignments() {
- if (!allow_harmony_destructuring_assignment()) return;
const auto& assignments =
function_state_->destructuring_assignments_to_rewrite();
for (int i = assignments.length() - 1; i >= 0; --i) {
@@ -5622,6 +5483,60 @@
}
}
+Expression* Parser::RewriteExponentiation(Expression* left, Expression* right,
+ int pos) {
+ ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
+ args->Add(left, zone());
+ args->Add(right, zone());
+ return factory()->NewCallRuntime(Context::MATH_POW_METHOD_INDEX, args, pos);
+}
+
+Expression* Parser::RewriteAssignExponentiation(Expression* left,
+ Expression* right, int pos) {
+ ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
+ if (left->IsVariableProxy()) {
+ VariableProxy* lhs = left->AsVariableProxy();
+
+ Expression* result;
+ DCHECK_NOT_NULL(lhs->raw_name());
+ result =
+ this->ExpressionFromIdentifier(lhs->raw_name(), lhs->position(),
+ lhs->end_position(), scope_, factory());
+ args->Add(left, zone());
+ args->Add(right, zone());
+ Expression* call =
+ factory()->NewCallRuntime(Context::MATH_POW_METHOD_INDEX, args, pos);
+ return factory()->NewAssignment(Token::ASSIGN, result, call, pos);
+ } else if (left->IsProperty()) {
+ Property* prop = left->AsProperty();
+ auto temp_obj = scope_->NewTemporary(ast_value_factory()->empty_string());
+ auto temp_key = scope_->NewTemporary(ast_value_factory()->empty_string());
+ Expression* assign_obj = factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(temp_obj), prop->obj(),
+ RelocInfo::kNoPosition);
+ Expression* assign_key = factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(temp_key), prop->key(),
+ RelocInfo::kNoPosition);
+ args->Add(factory()->NewProperty(factory()->NewVariableProxy(temp_obj),
+ factory()->NewVariableProxy(temp_key),
+ left->position()),
+ zone());
+ args->Add(right, zone());
+ Expression* call =
+ factory()->NewCallRuntime(Context::MATH_POW_METHOD_INDEX, args, pos);
+ Expression* target = factory()->NewProperty(
+ factory()->NewVariableProxy(temp_obj),
+ factory()->NewVariableProxy(temp_key), RelocInfo::kNoPosition);
+ Expression* assign =
+ factory()->NewAssignment(Token::ASSIGN, target, call, pos);
+ return factory()->NewBinaryOperation(
+ Token::COMMA, assign_obj,
+ factory()->NewBinaryOperation(Token::COMMA, assign_key, assign, pos),
+ pos);
+ }
+ UNREACHABLE();
+ return nullptr;
+}
Expression* Parser::RewriteSpreads(ArrayLiteral* lit) {
// Array literals containing spreads are rewritten using do expressions, e.g.
@@ -5673,45 +5588,6 @@
Variable* each =
scope_->NewTemporary(ast_value_factory()->dot_for_string());
Expression* subject = spread->expression();
- Variable* iterator =
- scope_->NewTemporary(ast_value_factory()->dot_iterator_string());
- Variable* element =
- scope_->NewTemporary(ast_value_factory()->dot_result_string());
- // iterator = subject[Symbol.iterator]()
- Expression* assign_iterator = factory()->NewAssignment(
- Token::ASSIGN, factory()->NewVariableProxy(iterator),
- GetIterator(subject, factory(), spread->expression_position()),
- subject->position());
- // !%_IsJSReceiver(element = iterator.next()) &&
- // %ThrowIteratorResultNotAnObject(element)
- Expression* next_element;
- {
- // element = iterator.next()
- Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
- next_element = BuildIteratorNextResult(iterator_proxy, element,
- spread->expression_position());
- }
- // element.done
- Expression* element_done;
- {
- Expression* done_literal = factory()->NewStringLiteral(
- ast_value_factory()->done_string(), RelocInfo::kNoPosition);
- Expression* element_proxy = factory()->NewVariableProxy(element);
- element_done = factory()->NewProperty(element_proxy, done_literal,
- RelocInfo::kNoPosition);
- }
- // each = element.value
- Expression* assign_each;
- {
- Expression* value_literal = factory()->NewStringLiteral(
- ast_value_factory()->value_string(), RelocInfo::kNoPosition);
- Expression* element_proxy = factory()->NewVariableProxy(element);
- Expression* element_value = factory()->NewProperty(
- element_proxy, value_literal, RelocInfo::kNoPosition);
- assign_each = factory()->NewAssignment(
- Token::ASSIGN, factory()->NewVariableProxy(each), element_value,
- RelocInfo::kNoPosition);
- }
// %AppendElement($R, each)
Statement* append_body;
{
@@ -5728,11 +5604,10 @@
// for (each of spread) %AppendElement($R, each)
ForEachStatement* loop = factory()->NewForEachStatement(
ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition);
- ForOfStatement* for_of = loop->AsForOfStatement();
- for_of->Initialize(factory()->NewVariableProxy(each), subject,
- append_body, iterator, assign_iterator, next_element,
- element_done, assign_each);
- do_block->statements()->Add(for_of, zone());
+ InitializeForOfStatement(loop->AsForOfStatement(),
+ factory()->NewVariableProxy(each), subject,
+ append_body, spread->expression_position());
+ do_block->statements()->Add(loop, zone());
}
}
// Now, rewind the original array literal to truncate everything from the
@@ -6055,9 +5930,8 @@
Block* then = factory->NewBlock(nullptr, 4+1, false, nopos);
Variable* var_tmp = scope->NewTemporary(avfactory->empty_string());
- BuildIteratorClose(
- then->statements(), var_iterator, factory->NewUndefinedLiteral(nopos),
- var_tmp);
+ BuildIteratorClose(then->statements(), var_iterator, Nothing<Variable*>(),
+ var_tmp);
then->statements()->Add(throw_call, zone);
check_throw = factory->NewIfStatement(
condition, then, factory->NewEmptyStatement(nopos), nopos);
@@ -6128,13 +6002,11 @@
set_mode_return = factory->NewExpressionStatement(assignment, nopos);
}
-
- // RawYield(output);
+ // Yield(output);
Statement* yield_output;
{
Expression* output_proxy = factory->NewVariableProxy(var_output);
- Yield* yield = factory->NewYield(
- generator, output_proxy, Yield::kInitial, nopos);
+ Yield* yield = factory->NewYield(generator, output_proxy, nopos);
yield_output = factory->NewExpressionStatement(yield, nopos);
}
@@ -6232,8 +6104,7 @@
case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
auto case_return = new (zone) ZoneList<Statement*>(5, zone);
- BuildIteratorClose(case_return, var_iterator,
- factory->NewVariableProxy(var_input, nopos), var_output);
+ BuildIteratorClose(case_return, var_iterator, Just(var_input), var_output);
case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
auto case_throw = new (zone) ZoneList<Statement*>(5, zone);
@@ -6311,7 +6182,8 @@
// if (!IS_CALLABLE(C)) {
// throw MakeTypeError(kCalledNonCallableInstanceOf);
// }
-// handler_result = %ordinary_has_instance(C, O);
+// handler_result = %_GetOrdinaryHasInstance()
+// handler_result = %_Call(handler_result, C, O);
// } else {
// handler_result = !!(%_Call(handler_result, C, O));
// }
@@ -6356,8 +6228,8 @@
factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
Expression* call =
NewThrowTypeError(MessageTemplate::kNonObjectInInstanceOfCheck,
- avfactory->empty_string(), nopos);
- Statement* throw_call = factory->NewExpressionStatement(call, nopos);
+ avfactory->empty_string(), pos);
+ Statement* throw_call = factory->NewExpressionStatement(call, pos);
validate_C =
factory->NewIfStatement(is_receiver_call,
@@ -6384,7 +6256,8 @@
// if (!IS_CALLABLE(C)) {
// throw MakeTypeError(kCalledNonCallableInstanceOf);
// }
- // result = %ordinary_has_instance(C, O);
+ // handler_result = %_GetOrdinaryHasInstance()
+ // handler_result = %_Call(handler_result, C, O);
// } else {
// handler_result = !!%_Call(handler_result, C, O);
// }
@@ -6394,17 +6267,29 @@
Token::EQ_STRICT, factory->NewVariableProxy(var_handler_result),
factory->NewUndefinedLiteral(nopos), nopos);
- Block* then_side = factory->NewBlock(nullptr, 2, false, nopos);
+ Block* then_side = factory->NewBlock(nullptr, 3, false, nopos);
{
Expression* throw_expr =
NewThrowTypeError(MessageTemplate::kCalledNonCallableInstanceOf,
- avfactory->empty_string(), nopos);
- Statement* validate_C = CheckCallable(var_C, throw_expr);
- ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
+ avfactory->empty_string(), pos);
+ Statement* validate_C = CheckCallable(var_C, throw_expr, pos);
+
+ ZoneList<Expression*>* empty_args =
+ new (zone) ZoneList<Expression*>(0, zone);
+ Expression* ordinary_has_instance = factory->NewCallRuntime(
+ Runtime::kInlineGetOrdinaryHasInstance, empty_args, pos);
+ Expression* handler_proxy = factory->NewVariableProxy(var_handler_result);
+ Expression* assignment_handler = factory->NewAssignment(
+ Token::ASSIGN, handler_proxy, ordinary_has_instance, nopos);
+ Statement* assignment_get_handler =
+ factory->NewExpressionStatement(assignment_handler, nopos);
+
+ ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(3, zone);
+ args->Add(factory->NewVariableProxy(var_handler_result), zone);
args->Add(factory->NewVariableProxy(var_C), zone);
args->Add(factory->NewVariableProxy(var_O), zone);
- CallRuntime* call = factory->NewCallRuntime(
- Context::ORDINARY_HAS_INSTANCE_INDEX, args, pos);
+ Expression* call =
+ factory->NewCallRuntime(Runtime::kInlineCall, args, pos);
Expression* result_proxy = factory->NewVariableProxy(var_handler_result);
Expression* assignment =
factory->NewAssignment(Token::ASSIGN, result_proxy, call, nopos);
@@ -6412,6 +6297,7 @@
factory->NewExpressionStatement(assignment, nopos);
then_side->statements()->Add(validate_C, zone);
+ then_side->statements()->Add(assignment_get_handler, zone);
then_side->statements()->Add(assignment_return, zone);
}
@@ -6455,7 +6341,8 @@
return instanceof;
}
-Statement* ParserTraits::CheckCallable(Variable* var, Expression* error) {
+Statement* ParserTraits::CheckCallable(Variable* var, Expression* error,
+ int pos) {
auto factory = parser_->factory();
auto avfactory = parser_->ast_value_factory();
const int nopos = RelocInfo::kNoPosition;
@@ -6468,7 +6355,7 @@
Expression* condition = factory->NewCompareOperation(
Token::EQ_STRICT, type_of, function_literal, nopos);
- Statement* throw_call = factory->NewExpressionStatement(error, nopos);
+ Statement* throw_call = factory->NewExpressionStatement(error, pos);
validate_var = factory->NewIfStatement(
condition, factory->NewEmptyStatement(nopos), throw_call, nopos);
@@ -6478,17 +6365,21 @@
void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements,
Variable* iterator,
- Expression* input,
+ Maybe<Variable*> input,
Variable* var_output) {
//
// This function adds four statements to [statements], corresponding to the
// following code:
//
// let iteratorReturn = iterator.return;
- // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return input;
- // output = %_Call(iteratorReturn, iterator);
+ // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return |input|;
+ // output = %_Call(iteratorReturn, iterator|, input|);
// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
//
+ // Here, |...| denotes optional parts, depending on the presence of the
+ // input variable. The reason for allowing input is that BuildIteratorClose
+ // can then be reused to handle the return case in yield*.
+ //
const int nopos = RelocInfo::kNoPosition;
auto factory = parser_->factory();
@@ -6510,25 +6401,33 @@
get_return = factory->NewExpressionStatement(assignment, nopos);
}
- // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return input;
+ // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return |input|;
Statement* check_return;
{
Expression* condition = factory->NewCompareOperation(
Token::EQ, factory->NewVariableProxy(var_return),
factory->NewNullLiteral(nopos), nopos);
- Statement* return_input = factory->NewReturnStatement(input, nopos);
+ Expression* value = input.IsJust()
+ ? static_cast<Expression*>(
+ factory->NewVariableProxy(input.FromJust()))
+ : factory->NewUndefinedLiteral(nopos);
+
+ Statement* return_input = factory->NewReturnStatement(value, nopos);
check_return = factory->NewIfStatement(
condition, return_input, factory->NewEmptyStatement(nopos), nopos);
}
- // output = %_Call(iteratorReturn, iterator);
+ // output = %_Call(iteratorReturn, iterator, |input|);
Statement* call_return;
{
auto args = new (zone) ZoneList<Expression*>(3, zone);
args->Add(factory->NewVariableProxy(var_return), zone);
args->Add(factory->NewVariableProxy(iterator), zone);
+ if (input.IsJust()) {
+ args->Add(factory->NewVariableProxy(input.FromJust()), zone);
+ }
Expression* call =
factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
@@ -6568,9 +6467,124 @@
statements->Add(validate_output, zone);
}
+void ParserTraits::FinalizeIteratorUse(Variable* completion,
+ Expression* condition, Variable* iter,
+ Block* iterator_use, Block* target) {
+ if (!FLAG_harmony_iterator_close) return;
-// Runtime encoding of different completion modes.
-enum ForOfLoopBodyCompletion { BODY_COMPLETED, BODY_ABORTED, BODY_THREW };
+ //
+ // This function adds two statements to [target], corresponding to the
+ // following code:
+ //
+ // completion = kNormalCompletion;
+ // try {
+ // try {
+ // iterator_use
+ // } catch(e) {
+ // if (completion === kAbruptCompletion) completion = kThrowCompletion;
+ // %ReThrow(e);
+ // }
+ // } finally {
+ // if (condition) {
+ // #BuildIteratorCloseForCompletion(iter, completion)
+ // }
+ // }
+ //
+
+ const int nopos = RelocInfo::kNoPosition;
+ auto factory = parser_->factory();
+ auto avfactory = parser_->ast_value_factory();
+ auto scope = parser_->scope_;
+ auto zone = parser_->zone();
+
+ // completion = kNormalCompletion;
+ Statement* initialize_completion;
+ {
+ Expression* proxy = factory->NewVariableProxy(completion);
+ Expression* assignment = factory->NewAssignment(
+ Token::ASSIGN, proxy,
+ factory->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
+ initialize_completion = factory->NewExpressionStatement(assignment, nopos);
+ }
+
+ // if (completion === kAbruptCompletion) completion = kThrowCompletion;
+ Statement* set_completion_throw;
+ {
+ Expression* condition = factory->NewCompareOperation(
+ Token::EQ_STRICT, factory->NewVariableProxy(completion),
+ factory->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);
+
+ Expression* proxy = factory->NewVariableProxy(completion);
+ Expression* assignment = factory->NewAssignment(
+ Token::ASSIGN, proxy,
+ factory->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos);
+ Statement* statement = factory->NewExpressionStatement(assignment, nopos);
+ set_completion_throw = factory->NewIfStatement(
+ condition, statement, factory->NewEmptyStatement(nopos), nopos);
+ }
+
+ // if (condition) {
+ // #BuildIteratorCloseForCompletion(iter, completion)
+ // }
+ Block* maybe_close;
+ {
+ Block* block = factory->NewBlock(nullptr, 2, true, nopos);
+ parser_->BuildIteratorCloseForCompletion(block->statements(), iter,
+ completion);
+ DCHECK(block->statements()->length() == 2);
+
+ maybe_close = factory->NewBlock(nullptr, 1, true, nopos);
+ maybe_close->statements()->Add(
+ factory->NewIfStatement(condition, block,
+ factory->NewEmptyStatement(nopos), nopos),
+ zone);
+ }
+
+ // try { #try_block }
+ // catch(e) {
+ // #set_completion_throw;
+ // %ReThrow(e);
+ // }
+ Statement* try_catch;
+ {
+ Scope* catch_scope = parser_->NewScope(scope, CATCH_SCOPE);
+ Variable* catch_variable =
+ catch_scope->DeclareLocal(avfactory->dot_catch_string(), VAR,
+ kCreatedInitialized, Variable::NORMAL);
+
+ Statement* rethrow;
+ // We use %ReThrow rather than the ordinary throw because we want to
+ // preserve the original exception message. This is also why we create a
+ // TryCatchStatementForReThrow below (which does not clear the pending
+ // message), rather than a TryCatchStatement.
+ {
+ auto args = new (zone) ZoneList<Expression*>(1, zone);
+ args->Add(factory->NewVariableProxy(catch_variable), zone);
+ rethrow = factory->NewExpressionStatement(
+ factory->NewCallRuntime(Runtime::kReThrow, args, nopos), nopos);
+ }
+
+ Block* catch_block = factory->NewBlock(nullptr, 2, false, nopos);
+ catch_block->statements()->Add(set_completion_throw, zone);
+ catch_block->statements()->Add(rethrow, zone);
+
+ try_catch = factory->NewTryCatchStatementForReThrow(
+ iterator_use, catch_scope, catch_variable, catch_block, nopos);
+ }
+
+ // try { #try_catch } finally { #maybe_close }
+ Statement* try_finally;
+ {
+ Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
+ try_block->statements()->Add(try_catch, zone);
+
+ try_finally =
+ factory->NewTryFinallyStatement(try_block, maybe_close, nopos);
+ }
+
+ target->statements()->Add(initialize_completion, zone);
+ target->statements()->Add(try_finally, zone);
+}
void ParserTraits::BuildIteratorCloseForCompletion(
ZoneList<Statement*>* statements, Variable* iterator,
@@ -6581,16 +6595,17 @@
//
// let iteratorReturn = iterator.return;
// if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
- // let output;
- // if (completion === BODY_THREW) {
+ // if (completion === kThrowCompletion) {
// if (!IS_CALLABLE(iteratorReturn)) {
// throw MakeTypeError(kReturnMethodNotCallable);
// }
- // try { output = %_Call(iteratorReturn, iterator) } catch (_) { }
+ // try { %_Call(iteratorReturn, iterator) } catch (_) { }
// } else {
- // output = %_Call(iteratorReturn, iterator);
+ // let output = %_Call(iteratorReturn, iterator);
+ // if (!IS_RECEIVER(output)) {
+ // %ThrowIterResultNotAnObject(output);
+ // }
// }
- // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
// }
//
@@ -6600,11 +6615,9 @@
auto scope = parser_->scope_;
auto zone = parser_->zone();
- // let output;
- Variable* var_output = scope->NewTemporary(avfactory->empty_string());
// let iteratorReturn = iterator.return;
- Variable* var_return = var_output; // Reusing the output variable.
+ Variable* var_return = scope->NewTemporary(avfactory->empty_string());
Statement* get_return;
{
Expression* iterator_proxy = factory->NewVariableProxy(iterator);
@@ -6626,25 +6639,10 @@
Expression* throw_expr = NewThrowTypeError(
MessageTemplate::kReturnMethodNotCallable,
avfactory->empty_string(), nopos);
- check_return_callable = CheckCallable(var_return, throw_expr);
+ check_return_callable = CheckCallable(var_return, throw_expr, nopos);
}
- // output = %_Call(iteratorReturn, iterator);
- Statement* call_return;
- {
- auto args = new (zone) ZoneList<Expression*>(2, zone);
- args->Add(factory->NewVariableProxy(var_return), zone);
- args->Add(factory->NewVariableProxy(iterator), zone);
- Expression* call =
- factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
-
- Expression* output_proxy = factory->NewVariableProxy(var_output);
- Expression* assignment = factory->NewAssignment(
- Token::ASSIGN, output_proxy, call, nopos);
- call_return = factory->NewExpressionStatement(assignment, nopos);
- }
-
- // try { output = %_Call(iteratorReturn, iterator) } catch (_) { }
+ // try { %_Call(iteratorReturn, iterator) } catch (_) { }
Statement* try_call_return;
{
auto args = new (zone) ZoneList<Expression*>(2, zone);
@@ -6653,12 +6651,10 @@
Expression* call =
factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
- Expression* assignment = factory->NewAssignment(
- Token::ASSIGN, factory->NewVariableProxy(var_output), call, nopos);
Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
- try_block->statements()->Add(
- factory->NewExpressionStatement(assignment, nopos), zone);
+ try_block->statements()->Add(factory->NewExpressionStatement(call, nopos),
+ zone);
Block* catch_block = factory->NewBlock(nullptr, 0, false, nopos);
@@ -6671,29 +6667,27 @@
try_block, catch_scope, catch_variable, catch_block, nopos);
}
- // if (completion === ABRUPT_THROW) {
- // #check_return_callable;
- // #try_call_return;
- // } else {
- // #call_return;
+ // let output = %_Call(iteratorReturn, iterator);
+ // if (!IS_RECEIVER(output)) {
+ // %ThrowIteratorResultNotAnObject(output);
// }
- Statement* call_return_carefully;
+ Block* validate_return;
{
- Expression* condition = factory->NewCompareOperation(
- Token::EQ_STRICT, factory->NewVariableProxy(completion),
- factory->NewSmiLiteral(BODY_THREW, nopos), nopos);
+ Variable* var_output = scope->NewTemporary(avfactory->empty_string());
+ Statement* call_return;
+ {
+ auto args = new (zone) ZoneList<Expression*>(2, zone);
+ args->Add(factory->NewVariableProxy(var_return), zone);
+ args->Add(factory->NewVariableProxy(iterator), zone);
+ Expression* call =
+ factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
- Block* then_block = factory->NewBlock(nullptr, 2, false, nopos);
- then_block->statements()->Add(check_return_callable, zone);
- then_block->statements()->Add(try_call_return, zone);
+ Expression* output_proxy = factory->NewVariableProxy(var_output);
+ Expression* assignment =
+ factory->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
+ call_return = factory->NewExpressionStatement(assignment, nopos);
+ }
- call_return_carefully =
- factory->NewIfStatement(condition, then_block, call_return, nopos);
- }
-
- // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output);
- Statement* validate_output;
- {
Expression* is_receiver_call;
{
auto args = new (zone) ZoneList<Expression*>(1, zone);
@@ -6711,8 +6705,32 @@
throw_call = factory->NewExpressionStatement(call, nopos);
}
- validate_output = factory->NewIfStatement(
+ Statement* check_return = factory->NewIfStatement(
is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
+
+ validate_return = factory->NewBlock(nullptr, 2, false, nopos);
+ validate_return->statements()->Add(call_return, zone);
+ validate_return->statements()->Add(check_return, zone);
+ }
+
+ // if (completion === kThrowCompletion) {
+ // #check_return_callable;
+ // #try_call_return;
+ // } else {
+ // #validate_return;
+ // }
+ Statement* call_return_carefully;
+ {
+ Expression* condition = factory->NewCompareOperation(
+ Token::EQ_STRICT, factory->NewVariableProxy(completion),
+ factory->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos);
+
+ Block* then_block = factory->NewBlock(nullptr, 2, false, nopos);
+ then_block->statements()->Add(check_return_callable, zone);
+ then_block->statements()->Add(try_call_return, zone);
+
+ call_return_carefully =
+ factory->NewIfStatement(condition, then_block, validate_return, nopos);
}
// if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { ... }
@@ -6722,12 +6740,9 @@
Token::EQ, factory->NewVariableProxy(var_return),
factory->NewNullLiteral(nopos), nopos);
- Block* block = factory->NewBlock(nullptr, 2, false, nopos);
- block->statements()->Add(call_return_carefully, zone);
- block->statements()->Add(validate_output, zone);
-
- maybe_call_return = factory->NewIfStatement(
- condition, factory->NewEmptyStatement(nopos), block, nopos);
+ maybe_call_return =
+ factory->NewIfStatement(condition, factory->NewEmptyStatement(nopos),
+ call_return_carefully, nopos);
}
@@ -6742,25 +6757,35 @@
//
// This function replaces the loop with the following wrapping:
//
- // let completion = BODY_COMPLETED;
+ // let each;
+ // let completion = kNormalCompletion;
// try {
- // #loop;
- // } catch(e) {
- // if (completion === BODY_ABORTED) completion = BODY_THREW;
- // throw e;
+ // try {
+ // #loop;
+ // } catch(e) {
+ // if (completion === kAbruptCompletion) completion = kThrowCompletion;
+ // %ReThrow(e);
+ // }
// } finally {
- // if (!(completion === BODY_COMPLETED || IS_UNDEFINED(#iterator))) {
- // #BuildIteratorClose(#iterator, completion) // See above.
+ // if (!(completion === kNormalCompletion || IS_UNDEFINED(#iterator))) {
+ // #BuildIteratorCloseForCompletion(#iterator, completion)
// }
// }
//
// where the loop's body is wrapped as follows:
//
// {
- // {{completion = BODY_ABORTED;}}
// #loop-body
- // {{completion = BODY_COMPLETED;}}
+ // {{completion = kNormalCompletion;}}
// }
+ //
+ // and the loop's assign_each is wrapped as follows
+ //
+ // do {
+ // {{completion = kAbruptCompletion;}}
+ // #assign-each
+ // }
+ //
const int nopos = RelocInfo::kNoPosition;
auto factory = parser_->factory();
@@ -6768,129 +6793,41 @@
auto scope = parser_->scope_;
auto zone = parser_->zone();
- // let completion = BODY_COMPLETED;
Variable* var_completion = scope->NewTemporary(avfactory->empty_string());
- Statement* initialize_completion;
+
+ // let each;
+ Variable* var_each = scope->NewTemporary(avfactory->empty_string());
+ Statement* initialize_each;
{
- Expression* proxy = factory->NewVariableProxy(var_completion);
+ Expression* proxy = factory->NewVariableProxy(var_each);
Expression* assignment = factory->NewAssignment(
Token::ASSIGN, proxy,
- factory->NewSmiLiteral(BODY_COMPLETED, nopos), nopos);
- initialize_completion =
+ factory->NewUndefinedLiteral(nopos), nopos);
+ initialize_each =
factory->NewExpressionStatement(assignment, nopos);
}
- // if (completion === BODY_ABORTED) completion = BODY_THREW;
- Statement* set_completion_throw;
+ // !(completion === kNormalCompletion || IS_UNDEFINED(#iterator))
+ Expression* closing_condition;
{
- Expression* condition = factory->NewCompareOperation(
+ Expression* lhs = factory->NewCompareOperation(
Token::EQ_STRICT, factory->NewVariableProxy(var_completion),
- factory->NewSmiLiteral(BODY_ABORTED, nopos), nopos);
-
- Expression* proxy = factory->NewVariableProxy(var_completion);
- Expression* assignment = factory->NewAssignment(
- Token::ASSIGN, proxy, factory->NewSmiLiteral(BODY_THREW, nopos),
- nopos);
- Statement* statement = factory->NewExpressionStatement(assignment, nopos);
- set_completion_throw = factory->NewIfStatement(
- condition, statement, factory->NewEmptyStatement(nopos), nopos);
- }
-
- // if (!(completion === BODY_COMPLETED || IS_UNDEFINED(#iterator))) {
- // #BuildIteratorClose(#iterator, completion)
- // }
- Block* maybe_close;
- {
- Expression* condition1 = factory->NewCompareOperation(
- Token::EQ_STRICT, factory->NewVariableProxy(var_completion),
- factory->NewSmiLiteral(BODY_COMPLETED, nopos), nopos);
- Expression* condition2 = factory->NewCompareOperation(
+ factory->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
+ Expression* rhs = factory->NewCompareOperation(
Token::EQ_STRICT, factory->NewVariableProxy(loop->iterator()),
factory->NewUndefinedLiteral(nopos), nopos);
- Expression* condition = factory->NewBinaryOperation(
- Token::OR, condition1, condition2, nopos);
-
- Block* block = factory->NewBlock(nullptr, 2, false, nopos);
- BuildIteratorCloseForCompletion(
- block->statements(), loop->iterator(), var_completion);
- DCHECK(block->statements()->length() == 2);
-
- maybe_close = factory->NewBlock(nullptr, 1, false, nopos);
- maybe_close->statements()->Add(factory->NewIfStatement(
- condition, factory->NewEmptyStatement(nopos), block, nopos), zone);
+ closing_condition = factory->NewUnaryOperation(
+ Token::NOT, factory->NewBinaryOperation(Token::OR, lhs, rhs, nopos),
+ nopos);
}
- // try { #try_block }
- // catch(e) {
- // #set_completion_throw;
- // throw e;
- // }
- Statement* try_catch;
- {
- Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
- Variable* catch_variable = catch_scope->DeclareLocal(
- avfactory->dot_catch_string(), VAR, kCreatedInitialized,
- Variable::NORMAL);
-
- Statement* rethrow;
- {
- Expression* proxy = factory->NewVariableProxy(catch_variable);
- rethrow = factory->NewExpressionStatement(
- factory->NewThrow(proxy, nopos), nopos);
- }
-
- Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
- try_block->statements()->Add(loop, zone);
-
- Block* catch_block = factory->NewBlock(nullptr, 2, false, nopos);
- catch_block->statements()->Add(set_completion_throw, zone);
- catch_block->statements()->Add(rethrow, zone);
-
- try_catch = factory->NewTryCatchStatement(
- try_block, catch_scope, catch_variable, catch_block, nopos);
- }
-
- // try { #try_catch } finally { #maybe_close }
- Statement* try_finally;
- {
- Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
- try_block->statements()->Add(try_catch, zone);
-
- try_finally =
- factory->NewTryFinallyStatement(try_block, maybe_close, nopos);
- }
-
- // #initialize_completion;
- // #try_finally;
- Statement* final_loop;
- {
- Block* block = factory->NewBlock(nullptr, 2, false, nopos);
- block->statements()->Add(initialize_completion, zone);
- block->statements()->Add(try_finally, zone);
- final_loop = block;
- }
-
- // {{completion = BODY_ABORTED;}}
- Statement* set_completion_break;
- {
- Expression* proxy = factory->NewVariableProxy(var_completion);
- Expression* assignment = factory->NewAssignment(
- Token::ASSIGN, proxy,
- factory->NewSmiLiteral(BODY_ABORTED, nopos), nopos);
-
- Block* block = factory->NewBlock(nullptr, 1, true, nopos);
- block->statements()->Add(
- factory->NewExpressionStatement(assignment, nopos), zone);
- set_completion_break = block;
- }
-
- // {{completion = BODY_COMPLETED;}}
+ // {{completion = kNormalCompletion;}}
Statement* set_completion_normal;
{
Expression* proxy = factory->NewVariableProxy(var_completion);
Expression* assignment = factory->NewAssignment(
- Token::ASSIGN, proxy, factory->NewSmiLiteral(BODY_COMPLETED, nopos),
- nopos);
+ Token::ASSIGN, proxy,
+ factory->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
Block* block = factory->NewBlock(nullptr, 1, true, nopos);
block->statements()->Add(
@@ -6898,13 +6835,54 @@
set_completion_normal = block;
}
- // { #set_completion_break; #loop-body; #set_completion_normal }
+ // {{completion = kAbruptCompletion;}}
+ Statement* set_completion_abrupt;
+ {
+ Expression* proxy = factory->NewVariableProxy(var_completion);
+ Expression* assignment = factory->NewAssignment(
+ Token::ASSIGN, proxy,
+ factory->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);
+
+ Block* block = factory->NewBlock(nullptr, 1, true, nopos);
+ block->statements()->Add(factory->NewExpressionStatement(assignment, nopos),
+ zone);
+ set_completion_abrupt = block;
+ }
+
+ // { #loop-body; #set_completion_normal }
Block* new_body = factory->NewBlock(nullptr, 2, false, nopos);
- new_body->statements()->Add(set_completion_break, zone);
- new_body->statements()->Add(loop->body(), zone);
- new_body->statements()->Add(set_completion_normal, zone);
+ {
+ new_body->statements()->Add(loop->body(), zone);
+ new_body->statements()->Add(set_completion_normal, zone);
+ }
+
+ // { #set_completion_abrupt; #assign-each }
+ Block* new_assign_each = factory->NewBlock(nullptr, 2, false, nopos);
+ {
+ new_assign_each->statements()->Add(set_completion_abrupt, zone);
+ new_assign_each->statements()->Add(
+ factory->NewExpressionStatement(loop->assign_each(), nopos), zone);
+ }
+
+ // Now put things together.
loop->set_body(new_body);
+ loop->set_assign_each(
+ factory->NewDoExpression(new_assign_each, var_each, nopos));
+
+ Statement* final_loop;
+ {
+ Block* target = factory->NewBlock(nullptr, 3, false, nopos);
+ target->statements()->Add(initialize_each, zone);
+
+ Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
+ try_block->statements()->Add(loop, zone);
+
+ FinalizeIteratorUse(var_completion, closing_condition, loop->iterator(),
+ try_block, target);
+ final_loop = target;
+ }
+
return final_loop;
}
diff --git a/src/parsing/parser.h b/src/parsing/parser.h
index d4fb62f..c82682e 100644
--- a/src/parsing/parser.h
+++ b/src/parsing/parser.h
@@ -53,7 +53,6 @@
FLAG_ACCESSOR(kEval, is_eval, set_eval)
FLAG_ACCESSOR(kGlobal, is_global, set_global)
FLAG_ACCESSOR(kStrictMode, is_strict_mode, set_strict_mode)
- FLAG_ACCESSOR(kStrongMode, is_strong_mode, set_strong_mode)
FLAG_ACCESSOR(kNative, is_native, set_native)
FLAG_ACCESSOR(kModule, is_module, set_module)
FLAG_ACCESSOR(kAllowLazyParsing, allow_lazy_parsing, set_allow_lazy_parsing)
@@ -132,17 +131,17 @@
Handle<Context> context() { return context_; }
void clear_script() { script_ = Handle<Script>::null(); }
void set_isolate(Isolate* isolate) { isolate_ = isolate; }
+ void set_shared_info(Handle<SharedFunctionInfo> shared) { shared_ = shared; }
void set_context(Handle<Context> context) { context_ = context; }
void set_script(Handle<Script> script) { script_ = script; }
//--------------------------------------------------------------------------
LanguageMode language_mode() {
- return construct_language_mode(is_strict_mode(), is_strong_mode());
+ return construct_language_mode(is_strict_mode());
}
void set_language_mode(LanguageMode language_mode) {
STATIC_ASSERT(LANGUAGE_END == 3);
- set_strict_mode(language_mode & STRICT_BIT);
- set_strong_mode(language_mode & STRONG_BIT);
+ set_strict_mode(is_strict(language_mode));
}
void ReopenHandlesInNewHandleScope() {
@@ -165,13 +164,12 @@
kEval = 1 << 2,
kGlobal = 1 << 3,
kStrictMode = 1 << 4,
- kStrongMode = 1 << 5,
- kNative = 1 << 6,
- kParseRestriction = 1 << 7,
- kModule = 1 << 8,
- kAllowLazyParsing = 1 << 9,
+ kNative = 1 << 5,
+ kParseRestriction = 1 << 6,
+ kModule = 1 << 7,
+ kAllowLazyParsing = 1 << 8,
// ---------- Output flags --------------------------
- kAstValueFactoryOwned = 1 << 10
+ kAstValueFactoryOwned = 1 << 9
};
//------------- Inputs to parsing and scope analysis -----------------------
@@ -205,7 +203,6 @@
void SetFlag(Flag f, bool v) { flags_ = v ? flags_ | f : flags_ & ~f; }
bool GetFlag(Flag f) const { return (flags_ & f) != 0; }
- void set_shared_info(Handle<SharedFunctionInfo> shared) { shared_ = shared; }
void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
};
@@ -404,16 +401,6 @@
fni->AddFunction(func_to_infer);
}
- static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
- Scope* scope, ObjectLiteralProperty* property, bool* has_function) {
- Expression* value = property->value();
- if (scope->DeclarationScope()->is_script_scope() &&
- value->AsFunctionLiteral() != NULL) {
- *has_function = true;
- value->AsFunctionLiteral()->set_pretenure();
- }
- }
-
// If we assign a function literal to a property we pretenure the
// literal so it can be added as a constant function property.
static void CheckAssigningFunctionLiteralToProperty(Expression* left,
@@ -444,6 +431,8 @@
Expression* BuildUnaryExpression(Expression* expression, Token::Value op,
int pos, AstNodeFactory* factory);
+ Expression* BuildIteratorResult(Expression* value, bool done);
+
// Generate AST node that throws a ReferenceError with the given type.
Expression* NewThrowReferenceError(MessageTemplate::Template message,
int pos);
@@ -464,6 +453,9 @@
MessageTemplate::Template message,
const AstRawString* arg, int pos);
+ void FinalizeIteratorUse(Variable* completion, Expression* condition,
+ Variable* iter, Block* iterator_use, Block* result);
+
Statement* FinalizeForOfStatement(ForOfStatement* loop, int pos);
// Reporting errors.
@@ -581,11 +573,14 @@
const ParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok);
- ClassLiteral* ParseClassLiteral(const AstRawString* name,
+ ClassLiteral* ParseClassLiteral(Type::ExpressionClassifier* classifier,
+ const AstRawString* name,
Scanner::Location class_name_location,
bool name_is_strict_reserved, int pos,
bool* ok);
+ V8_INLINE void MarkTailPosition(Expression* expression);
+
V8_INLINE void CheckConflictingVarDeclarations(v8::internal::Scope* scope,
bool* ok);
@@ -644,6 +639,11 @@
// Rewrite all DestructuringAssignments in the current FunctionState.
V8_INLINE void RewriteDestructuringAssignments();
+ V8_INLINE Expression* RewriteExponentiation(Expression* left,
+ Expression* right, int pos);
+ V8_INLINE Expression* RewriteAssignExponentiation(Expression* left,
+ Expression* right, int pos);
+
V8_INLINE void QueueDestructuringAssignmentForRewriting(
Expression* assignment);
V8_INLINE void QueueNonPatternForRewriting(Expression* expr);
@@ -670,13 +670,12 @@
private:
Parser* parser_;
- void BuildIteratorClose(
- ZoneList<Statement*>* statements, Variable* iterator,
- Expression* input, Variable* output);
+ void BuildIteratorClose(ZoneList<Statement*>* statements, Variable* iterator,
+ Maybe<Variable*> input, Variable* output);
void BuildIteratorCloseForCompletion(
ZoneList<Statement*>* statements, Variable* iterator,
Variable* body_threw);
- Statement* CheckCallable(Variable* var, Expression* error);
+ Statement* CheckCallable(Variable* var, Expression* error, int pos);
};
@@ -705,6 +704,13 @@
private:
friend class ParserTraits;
+ // Runtime encoding of different completion modes.
+ enum CompletionKind {
+ kNormalCompletion,
+ kThrowCompletion,
+ kAbruptCompletion
+ };
+
// Limit the allowed number of local variables in a function. The hard limit
// is that offsets computed by FullCodeGenerator::StackOperand and similar
// functions are ints, and they should not overflow. In addition, accessing
@@ -754,8 +760,12 @@
ZoneList<const AstRawString*>* local_names,
Scanner::Location* reserved_loc, bool* ok);
ZoneList<ImportDeclaration*>* ParseNamedImports(int pos, bool* ok);
- Statement* ParseStatement(ZoneList<const AstRawString*>* labels, bool* ok);
- Statement* ParseSubStatement(ZoneList<const AstRawString*>* labels, bool* ok);
+ Statement* ParseStatement(ZoneList<const AstRawString*>* labels,
+ AllowLabelledFunctionStatement allow_function,
+ bool* ok);
+ Statement* ParseSubStatement(ZoneList<const AstRawString*>* labels,
+ AllowLabelledFunctionStatement allow_function,
+ bool* ok);
Statement* ParseStatementAsUnlabelled(ZoneList<const AstRawString*>* labels,
bool* ok);
Statement* ParseFunctionDeclaration(ZoneList<const AstRawString*>* names,
@@ -897,7 +907,8 @@
ZoneList<const AstRawString*>* names,
bool* ok);
Statement* ParseExpressionOrLabelledStatement(
- ZoneList<const AstRawString*>* labels, bool* ok);
+ ZoneList<const AstRawString*>* labels,
+ AllowLabelledFunctionStatement allow_function, bool* ok);
IfStatement* ParseIfStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
Statement* ParseContinueStatement(bool* ok);
@@ -920,6 +931,14 @@
class CollectExpressionsInTailPositionToListScope;
TryStatement* ParseTryStatement(bool* ok);
DebuggerStatement* ParseDebuggerStatement(bool* ok);
+ // Parse a SubStatement in strict mode, or with an extra block scope in
+ // sloppy mode to handle
+ // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
+ // The legacy parameter indicates whether function declarations are
+ // banned by the ES2015 specification in this location, and they are being
+ // permitted here to match previous V8 behavior.
+ Statement* ParseScopedStatement(ZoneList<const AstRawString*>* labels,
+ bool legacy, bool* ok);
// !%_IsJSReceiver(result = iterator.next()) &&
// %ThrowIteratorResultNotAnObject(result)
@@ -929,8 +948,10 @@
// Initialize the components of a for-in / for-of statement.
void InitializeForEachStatement(ForEachStatement* stmt, Expression* each,
- Expression* subject, Statement* body,
- bool is_destructuring);
+ Expression* subject, Statement* body);
+ void InitializeForOfStatement(ForOfStatement* stmt, Expression* each,
+ Expression* iterable, Statement* body,
+ int iterable_pos);
Statement* DesugarLexicalBindingsInForStatement(
Scope* inner_scope, VariableMode mode,
ZoneList<const AstRawString*>* names, ForStatement* loop, Statement* init,
@@ -944,8 +965,8 @@
int function_token_position, FunctionLiteral::FunctionType type,
LanguageMode language_mode, bool* ok);
-
- ClassLiteral* ParseClassLiteral(const AstRawString* name,
+ ClassLiteral* ParseClassLiteral(ExpressionClassifier* classifier,
+ const AstRawString* name,
Scanner::Location class_name_location,
bool name_is_strict_reserved, int pos,
bool* ok);
@@ -1035,6 +1056,11 @@
V8_INLINE void RewriteDestructuringAssignments();
+ V8_INLINE Expression* RewriteExponentiation(Expression* left,
+ Expression* right, int pos);
+ V8_INLINE Expression* RewriteAssignExponentiation(Expression* left,
+ Expression* right, int pos);
+
friend class NonPatternRewriter;
V8_INLINE Expression* RewriteSpreads(ArrayLiteral* lit);
diff --git a/src/parsing/pattern-rewriter.cc b/src/parsing/pattern-rewriter.cc
index 768a948..e699255 100644
--- a/src/parsing/pattern-rewriter.cc
+++ b/src/parsing/pattern-rewriter.cc
@@ -17,6 +17,8 @@
ZoneList<const AstRawString*>* names, bool* ok) {
PatternRewriter rewriter;
+ DCHECK(block->ignore_completion_value());
+
rewriter.scope_ = declaration_descriptor->scope;
rewriter.parser_ = declaration_descriptor->parser;
rewriter.context_ = BINDING;
@@ -234,22 +236,20 @@
if (IsImmutableVariableMode(descriptor_->mode)) {
arguments->Add(value, zone());
- value = NULL; // zap the value to avoid the unnecessary assignment
-
// Construct the call to Runtime_InitializeConstGlobal
// and add it to the initialization statement block.
// Note that the function does different things depending on
// the number of arguments (1 or 2).
- initialize =
- factory()->NewCallRuntime(Runtime::kInitializeConstGlobal, arguments,
- descriptor_->initialization_pos);
+ initialize = factory()->NewCallRuntime(Runtime::kInitializeConstGlobal,
+ arguments, value->position());
+ value = NULL; // zap the value to avoid the unnecessary assignment
} else {
// Add language mode.
// We may want to pass singleton to avoid Literal allocations.
LanguageMode language_mode = initialization_scope->language_mode();
- arguments->Add(factory()->NewNumberLiteral(language_mode,
- descriptor_->declaration_pos),
- zone());
+ arguments->Add(
+ factory()->NewNumberLiteral(language_mode, RelocInfo::kNoPosition),
+ zone());
// Be careful not to assign a value to the global variable if
// we're in a with. The initialization value should not
@@ -257,12 +257,11 @@
// which is why we need to generate a separate assignment node.
if (value != NULL && !descriptor_->scope->inside_with()) {
arguments->Add(value, zone());
- value = NULL; // zap the value to avoid the unnecessary assignment
// Construct the call to Runtime_InitializeVarGlobal
// and add it to the initialization statement block.
- initialize =
- factory()->NewCallRuntime(Runtime::kInitializeVarGlobal, arguments,
- descriptor_->declaration_pos);
+ initialize = factory()->NewCallRuntime(Runtime::kInitializeVarGlobal,
+ arguments, value->position());
+ value = NULL; // zap the value to avoid the unnecessary assignment
} else {
initialize = NULL;
}
@@ -270,7 +269,7 @@
if (initialize != NULL) {
block_->statements()->Add(
- factory()->NewExpressionStatement(initialize, RelocInfo::kNoPosition),
+ factory()->NewExpressionStatement(initialize, initialize->position()),
zone());
}
} else if (value != nullptr && (descriptor_->mode == CONST_LEGACY ||
@@ -286,7 +285,7 @@
DCHECK_NOT_NULL(proxy->var());
DCHECK_NOT_NULL(value);
// Add break location for destructured sub-pattern.
- int pos = IsSubPattern() ? pattern->position() : RelocInfo::kNoPosition;
+ int pos = IsSubPattern() ? pattern->position() : value->position();
Assignment* assignment =
factory()->NewAssignment(Token::INIT, proxy, value, pos);
block_->statements()->Add(
@@ -303,7 +302,7 @@
// property).
VariableProxy* proxy = initialization_scope->NewUnresolved(factory(), name);
// Add break location for destructured sub-pattern.
- int pos = IsSubPattern() ? pattern->position() : RelocInfo::kNoPosition;
+ int pos = IsSubPattern() ? pattern->position() : value->position();
Assignment* assignment =
factory()->NewAssignment(Token::INIT, proxy, value, pos);
block_->statements()->Add(
@@ -365,7 +364,7 @@
PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
int pos = assign->position();
Block* old_block = block_;
- block_ = factory()->NewBlock(nullptr, 8, false, pos);
+ block_ = factory()->NewBlock(nullptr, 8, true, pos);
Variable* temp = nullptr;
Expression* pattern = assign->target();
Expression* old_value = current_value_;
@@ -414,16 +413,27 @@
void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
Variable** temp_var) {
+ DCHECK(block_->ignore_completion_value());
+
auto temp = *temp_var = CreateTempVar(current_value_);
-
- block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
-
auto iterator = CreateTempVar(parser_->GetIterator(
factory()->NewVariableProxy(temp), factory(), RelocInfo::kNoPosition));
auto done = CreateTempVar(
factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition));
auto result = CreateTempVar();
auto v = CreateTempVar();
+ auto completion = CreateTempVar();
+ auto nopos = RelocInfo::kNoPosition;
+
+ // For the purpose of iterator finalization, we temporarily set block_ to a
+ // new block. In the main body of this function, we write to block_ (both
+ // explicitly and implicitly via recursion). At the end of the function, we
+ // wrap this new block in a try-finally statement, restore block_ to its
+ // original value, and add the try-finally statement to block_.
+ auto target = block_;
+ if (FLAG_harmony_iterator_close) {
+ block_ = factory()->NewBlock(nullptr, 8, true, nopos);
+ }
Spread* spread = nullptr;
for (Expression* value : *node->values()) {
@@ -433,88 +443,201 @@
}
PatternContext context = SetInitializerContextIfNeeded(value);
+
// if (!done) {
+ // done = true; // If .next, .done or .value throws, don't close.
// result = IteratorNext(iterator);
- // v = (done = result.done) ? undefined : result.value;
+ // if (result.done) {
+ // v = undefined;
+ // } else {
+ // v = result.value;
+ // done = false;
+ // }
// }
- auto next_block =
- factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition);
- next_block->statements()->Add(factory()->NewExpressionStatement(
- parser_->BuildIteratorNextResult(
- factory()->NewVariableProxy(iterator),
- result, RelocInfo::kNoPosition),
+ Statement* if_not_done;
+ {
+ auto result_done = factory()->NewProperty(
+ factory()->NewVariableProxy(result),
+ factory()->NewStringLiteral(ast_value_factory()->done_string(),
RelocInfo::kNoPosition),
- zone());
+ RelocInfo::kNoPosition);
- auto assign_to_done = factory()->NewAssignment(
- Token::ASSIGN, factory()->NewVariableProxy(done),
- factory()->NewProperty(
- factory()->NewVariableProxy(result),
- factory()->NewStringLiteral(ast_value_factory()->done_string(),
- RelocInfo::kNoPosition),
- RelocInfo::kNoPosition),
- RelocInfo::kNoPosition);
- auto next_value = factory()->NewConditional(
- assign_to_done, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
- factory()->NewProperty(
- factory()->NewVariableProxy(result),
- factory()->NewStringLiteral(ast_value_factory()->value_string(),
- RelocInfo::kNoPosition),
- RelocInfo::kNoPosition),
- RelocInfo::kNoPosition);
- next_block->statements()->Add(
- factory()->NewExpressionStatement(
- factory()->NewAssignment(Token::ASSIGN,
- factory()->NewVariableProxy(v), next_value,
- RelocInfo::kNoPosition),
- RelocInfo::kNoPosition),
- zone());
+ auto assign_undefined = factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(v),
+ factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition);
- auto if_statement = factory()->NewIfStatement(
- factory()->NewUnaryOperation(Token::NOT,
- factory()->NewVariableProxy(done),
- RelocInfo::kNoPosition),
- next_block, factory()->NewEmptyStatement(RelocInfo::kNoPosition),
- RelocInfo::kNoPosition);
- block_->statements()->Add(if_statement, zone());
+ auto assign_value = factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(v),
+ factory()->NewProperty(
+ factory()->NewVariableProxy(result),
+ factory()->NewStringLiteral(ast_value_factory()->value_string(),
+ RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition);
+
+ auto unset_done = factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(done),
+ factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition);
+
+ auto inner_else =
+ factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition);
+ inner_else->statements()->Add(
+ factory()->NewExpressionStatement(assign_value, nopos), zone());
+ inner_else->statements()->Add(
+ factory()->NewExpressionStatement(unset_done, nopos), zone());
+
+ auto inner_if = factory()->NewIfStatement(
+ result_done,
+ factory()->NewExpressionStatement(assign_undefined, nopos),
+ inner_else, nopos);
+
+ auto next_block =
+ factory()->NewBlock(nullptr, 3, true, RelocInfo::kNoPosition);
+ next_block->statements()->Add(
+ factory()->NewExpressionStatement(
+ factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(done),
+ factory()->NewBooleanLiteral(true, nopos), nopos),
+ nopos),
+ zone());
+ next_block->statements()->Add(
+ factory()->NewExpressionStatement(
+ parser_->BuildIteratorNextResult(
+ factory()->NewVariableProxy(iterator), result,
+ RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition),
+ zone());
+ next_block->statements()->Add(inner_if, zone());
+
+ if_not_done = factory()->NewIfStatement(
+ factory()->NewUnaryOperation(Token::NOT,
+ factory()->NewVariableProxy(done),
+ RelocInfo::kNoPosition),
+ next_block, factory()->NewEmptyStatement(RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition);
+ }
+ block_->statements()->Add(if_not_done, zone());
if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
+ if (FLAG_harmony_iterator_close) {
+ // completion = kAbruptCompletion;
+ Expression* proxy = factory()->NewVariableProxy(completion);
+ Expression* assignment = factory()->NewAssignment(
+ Token::ASSIGN, proxy,
+ factory()->NewSmiLiteral(kAbruptCompletion, nopos), nopos);
+ block_->statements()->Add(
+ factory()->NewExpressionStatement(assignment, nopos), zone());
+ }
+
RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
+
+ if (FLAG_harmony_iterator_close) {
+ // completion = kNormalCompletion;
+ Expression* proxy = factory()->NewVariableProxy(completion);
+ Expression* assignment = factory()->NewAssignment(
+ Token::ASSIGN, proxy,
+ factory()->NewSmiLiteral(kNormalCompletion, nopos), nopos);
+ block_->statements()->Add(
+ factory()->NewExpressionStatement(assignment, nopos), zone());
+ }
}
set_context(context);
}
if (spread != nullptr) {
- // array = [];
- // if (!done) %concat_iterable_to_array(array, iterator);
- auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
- auto array = CreateTempVar(factory()->NewArrayLiteral(
- empty_exprs,
- // Reuse pattern's literal index - it is unused since there is no
- // actual literal allocated.
- node->literal_index(), is_strong(scope()->language_mode()),
- RelocInfo::kNoPosition));
+ // A spread can only occur as the last component. It is not handled by
+ // RecurseIntoSubpattern above.
- auto arguments = new (zone()) ZoneList<Expression*>(2, zone());
- arguments->Add(factory()->NewVariableProxy(array), zone());
- arguments->Add(factory()->NewVariableProxy(iterator), zone());
- auto spread_into_array_call =
- factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX,
- arguments, RelocInfo::kNoPosition);
+ // let array = [];
+ // while (!done) {
+ // result = IteratorNext(iterator);
+ // if (result.done) {
+ // done = true;
+ // } else {
+ // %AppendElement(array, result.value);
+ // }
+ // }
- auto if_statement = factory()->NewIfStatement(
- factory()->NewUnaryOperation(Token::NOT,
- factory()->NewVariableProxy(done),
- RelocInfo::kNoPosition),
- factory()->NewExpressionStatement(spread_into_array_call,
- RelocInfo::kNoPosition),
- factory()->NewEmptyStatement(RelocInfo::kNoPosition),
- RelocInfo::kNoPosition);
- block_->statements()->Add(if_statement, zone());
+ // let array = [];
+ Variable* array;
+ {
+ auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
+ array = CreateTempVar(factory()->NewArrayLiteral(
+ empty_exprs,
+ // Reuse pattern's literal index - it is unused since there is no
+ // actual literal allocated.
+ node->literal_index(), RelocInfo::kNoPosition));
+ }
+ // result = IteratorNext(iterator);
+ Statement* get_next = factory()->NewExpressionStatement(
+ parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
+ result, nopos),
+ nopos);
+
+ // done = true;
+ Statement* set_done = factory()->NewExpressionStatement(
+ factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(done),
+ factory()->NewBooleanLiteral(true, nopos), nopos),
+ nopos);
+
+ // %AppendElement(array, result.value);
+ Statement* append_element;
+ {
+ auto args = new (zone()) ZoneList<Expression*>(2, zone());
+ args->Add(factory()->NewVariableProxy(array), zone());
+ args->Add(factory()->NewProperty(
+ factory()->NewVariableProxy(result),
+ factory()->NewStringLiteral(
+ ast_value_factory()->value_string(), nopos),
+ nopos),
+ zone());
+ append_element = factory()->NewExpressionStatement(
+ factory()->NewCallRuntime(Runtime::kAppendElement, args, nopos),
+ nopos);
+ }
+
+ // if (result.done) { #set_done } else { #append_element }
+ Statement* set_done_or_append;
+ {
+ Expression* result_done =
+ factory()->NewProperty(factory()->NewVariableProxy(result),
+ factory()->NewStringLiteral(
+ ast_value_factory()->done_string(), nopos),
+ nopos);
+ set_done_or_append = factory()->NewIfStatement(result_done, set_done,
+ append_element, nopos);
+ }
+
+ // while (!done) {
+ // #get_next;
+ // #set_done_or_append;
+ // }
+ WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
+ {
+ Expression* condition = factory()->NewUnaryOperation(
+ Token::NOT, factory()->NewVariableProxy(done), nopos);
+ Block* body = factory()->NewBlock(nullptr, 2, true, nopos);
+ body->statements()->Add(get_next, zone());
+ body->statements()->Add(set_done_or_append, zone());
+ loop->Initialize(condition, body);
+ }
+
+ block_->statements()->Add(loop, zone());
RecurseIntoSubpattern(spread->expression(),
factory()->NewVariableProxy(array));
}
+
+ if (FLAG_harmony_iterator_close) {
+ Expression* closing_condition = factory()->NewUnaryOperation(
+ Token::NOT, factory()->NewVariableProxy(done), nopos);
+ parser_->FinalizeIteratorUse(completion, closing_condition, iterator,
+ block_, target);
+ block_ = target;
+ }
}
diff --git a/src/parsing/preparse-data.h b/src/parsing/preparse-data.h
index dbe1022..1c99450 100644
--- a/src/parsing/preparse-data.h
+++ b/src/parsing/preparse-data.h
@@ -6,6 +6,7 @@
#define V8_PARSING_PREPARSE_DATA_H_
#include "src/allocation.h"
+#include "src/collector.h"
#include "src/hashmap.h"
#include "src/messages.h"
#include "src/parsing/preparse-data-format.h"
diff --git a/src/parsing/preparser.cc b/src/parsing/preparser.cc
index d335c8b..da1c35b 100644
--- a/src/parsing/preparser.cc
+++ b/src/parsing/preparser.cc
@@ -78,8 +78,6 @@
int pos, Scanner* scanner, PreParserFactory* factory) {
if (scanner->UnescapedLiteralMatches("use strict", 10)) {
return PreParserExpression::UseStrictStringLiteral();
- } else if (scanner->UnescapedLiteralMatches("use strong", 10)) {
- return PreParserExpression::UseStrongStringLiteral();
}
return PreParserExpression::StringLiteral();
}
@@ -132,25 +130,16 @@
int end_pos = scanner()->location().end_pos;
CheckStrictOctalLiteral(start_position, end_pos, &ok);
if (!ok) return kPreParseSuccess;
-
- if (is_strong(scope_->language_mode()) && IsSubclassConstructor(kind)) {
- if (!function_state.super_location().IsValid()) {
- ReportMessageAt(Scanner::Location(start_position, start_position + 1),
- MessageTemplate::kStrongSuperCallMissing,
- kReferenceError);
- return kPreParseSuccess;
- }
- }
}
}
return kPreParseSuccess;
}
-
PreParserExpression PreParserTraits::ParseClassLiteral(
- PreParserIdentifier name, Scanner::Location class_name_location,
- bool name_is_strict_reserved, int pos, bool* ok) {
- return pre_parser_->ParseClassLiteral(name, class_name_location,
+ Type::ExpressionClassifier* classifier, PreParserIdentifier name,
+ Scanner::Location class_name_location, bool name_is_strict_reserved,
+ int pos, bool* ok) {
+ return pre_parser_->ParseClassLiteral(classifier, name, class_name_location,
name_is_strict_reserved, pos, ok);
}
@@ -205,7 +194,7 @@
default:
break;
}
- return ParseStatement(ok);
+ return ParseStatement(kAllowLabelledFunctionStatement, ok);
}
@@ -226,62 +215,26 @@
}
bool starts_with_identifier = peek() == Token::IDENTIFIER;
Scanner::Location token_loc = scanner()->peek_location();
- Scanner::Location old_this_loc = function_state_->this_location();
- Scanner::Location old_super_loc = function_state_->super_location();
Statement statement = ParseStatementListItem(ok);
if (!*ok) return;
- if (is_strong(language_mode()) && scope_->is_function_scope() &&
- IsClassConstructor(function_state_->kind())) {
- Scanner::Location this_loc = function_state_->this_location();
- Scanner::Location super_loc = function_state_->super_location();
- if (this_loc.beg_pos != old_this_loc.beg_pos &&
- this_loc.beg_pos != token_loc.beg_pos) {
- ReportMessageAt(this_loc, MessageTemplate::kStrongConstructorThis);
- *ok = false;
- return;
- }
- if (super_loc.beg_pos != old_super_loc.beg_pos &&
- super_loc.beg_pos != token_loc.beg_pos) {
- ReportMessageAt(super_loc, MessageTemplate::kStrongConstructorSuper);
- *ok = false;
- return;
- }
- }
-
if (directive_prologue) {
bool use_strict_found = statement.IsUseStrictLiteral();
- bool use_strong_found =
- statement.IsUseStrongLiteral() && allow_strong_mode();
if (use_strict_found) {
scope_->SetLanguageMode(
static_cast<LanguageMode>(scope_->language_mode() | STRICT));
- } else if (use_strong_found) {
- scope_->SetLanguageMode(static_cast<LanguageMode>(
- scope_->language_mode() | STRONG));
- if (IsClassConstructor(function_state_->kind())) {
- // "use strong" cannot occur in a class constructor body, to avoid
- // unintuitive strong class object semantics.
- PreParserTraits::ReportMessageAt(
- token_loc, MessageTemplate::kStrongConstructorDirective);
- *ok = false;
- return;
- }
} else if (!statement.IsStringLiteral()) {
directive_prologue = false;
}
- if ((use_strict_found || use_strong_found) &&
- !scope_->HasSimpleParameters()) {
+ if (use_strict_found && !scope_->HasSimpleParameters()) {
// TC39 deemed "use strict" directives to be an error when occurring
// in the body of a function with non-simple parameter list, on
// 29/7/2015. https://goo.gl/ueA7Ln
- //
- // In V8, this also applies to "use strong " directives.
PreParserTraits::ReportMessageAt(
token_loc, MessageTemplate::kIllegalLanguageModeDirective,
- use_strict_found ? "use strict" : "use strong");
+ "use strict");
*ok = false;
return;
}
@@ -310,8 +263,8 @@
#define DUMMY ) // to make indentation work
#undef DUMMY
-
-PreParser::Statement PreParser::ParseStatement(bool* ok) {
+PreParser::Statement PreParser::ParseStatement(
+ AllowLabelledFunctionStatement allow_function, bool* ok) {
// Statement ::
// EmptyStatement
// ...
@@ -320,11 +273,20 @@
Next();
return Statement::Default();
}
- return ParseSubStatement(ok);
+ return ParseSubStatement(allow_function, ok);
}
+PreParser::Statement PreParser::ParseScopedStatement(bool legacy, bool* ok) {
+ if (is_strict(language_mode()) || peek() != Token::FUNCTION ||
+ (legacy && allow_harmony_restrictive_declarations())) {
+ return ParseSubStatement(kDisallowLabelledFunctionStatement, ok);
+ } else {
+ return ParseFunctionDeclaration(CHECK_OK);
+ }
+}
-PreParser::Statement PreParser::ParseSubStatement(bool* ok) {
+PreParser::Statement PreParser::ParseSubStatement(
+ AllowLabelledFunctionStatement allow_function, bool* ok) {
// Statement ::
// Block
// VariableStatement
@@ -355,12 +317,6 @@
return ParseBlock(ok);
case Token::SEMICOLON:
- if (is_strong(language_mode())) {
- PreParserTraits::ReportMessageAt(scanner()->peek_location(),
- MessageTemplate::kStrongEmpty);
- *ok = false;
- return Statement::Default();
- }
Next();
return Statement::Default();
@@ -397,20 +353,18 @@
case Token::TRY:
return ParseTryStatement(ok);
- case Token::FUNCTION: {
- Scanner::Location start_location = scanner()->peek_location();
- Statement statement = ParseFunctionDeclaration(CHECK_OK);
- Scanner::Location end_location = scanner()->location();
- if (is_strict(language_mode())) {
- PreParserTraits::ReportMessageAt(start_location.beg_pos,
- end_location.end_pos,
- MessageTemplate::kStrictFunction);
- *ok = false;
- return Statement::Default();
- } else {
- return statement;
- }
- }
+ case Token::FUNCTION:
+ // FunctionDeclaration only allowed as a StatementListItem, not in
+ // an arbitrary Statement position. Exceptions such as
+ // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
+ // are handled by calling ParseScopedStatement rather than
+ // ParseSubStatement directly.
+ ReportMessageAt(scanner()->peek_location(),
+ is_strict(language_mode())
+ ? MessageTemplate::kStrictFunction
+ : MessageTemplate::kSloppyFunction);
+ *ok = false;
+ return Statement::Default();
case Token::DEBUGGER:
return ParseDebuggerStatement(ok);
@@ -418,17 +372,8 @@
case Token::VAR:
return ParseVariableStatement(kStatement, ok);
- case Token::CONST:
- // In ES6 CONST is not allowed as a Statement, only as a
- // LexicalDeclaration, however we continue to allow it in sloppy mode for
- // backwards compatibility.
- if (is_sloppy(language_mode()) && allow_legacy_const()) {
- return ParseVariableStatement(kStatement, ok);
- }
-
- // Fall through.
default:
- return ParseExpressionOrLabelledStatement(ok);
+ return ParseExpressionOrLabelledStatement(allow_function, ok);
}
}
@@ -468,8 +413,8 @@
bool is_strict_reserved = false;
Identifier name =
ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
- ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos,
- CHECK_OK);
+ ParseClassLiteral(nullptr, name, scanner()->location(), is_strict_reserved,
+ pos, CHECK_OK);
return Statement::Default();
}
@@ -527,12 +472,6 @@
bool lexical = false;
bool is_pattern = false;
if (peek() == Token::VAR) {
- if (is_strong(language_mode())) {
- Scanner::Location location = scanner()->peek_location();
- ReportMessageAt(location, MessageTemplate::kStrongVar);
- *ok = false;
- return Statement::Default();
- }
Consume(Token::VAR);
} else if (peek() == Token::CONST && allow_const()) {
// TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
@@ -546,8 +485,7 @@
// existing pages. Therefore we keep allowing const with the old
// non-harmony semantics in sloppy mode.
Consume(Token::CONST);
- if (is_strict(language_mode()) ||
- (allow_harmony_sloppy() && !allow_legacy_const())) {
+ if (is_strict(language_mode()) || allow_harmony_sloppy()) {
DCHECK(var_context != kStatement);
require_initializer = true;
lexical = true;
@@ -574,19 +512,12 @@
PreParserExpression pattern = PreParserExpression::Default();
{
ExpressionClassifier pattern_classifier(this);
- Token::Value next = peek();
pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
ValidateBindingPattern(&pattern_classifier, CHECK_OK);
if (lexical) {
ValidateLetPattern(&pattern_classifier, CHECK_OK);
}
-
- if (!allow_harmony_destructuring_bind() && !pattern.IsIdentifier()) {
- ReportUnexpectedToken(next);
- *ok = false;
- return Statement::Default();
- }
}
is_pattern = pattern.IsObjectLiteral() || pattern.IsArrayLiteral();
@@ -625,8 +556,8 @@
return Statement::Default();
}
-
-PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
+PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(
+ AllowLabelledFunctionStatement allow_function, bool* ok) {
// ExpressionStatement | LabelledStatement ::
// Expression ';'
// Identifier ':' Statement
@@ -640,45 +571,6 @@
*ok = false;
return Statement::Default();
- case Token::THIS:
- if (!FLAG_strong_this) break;
- // Fall through.
- case Token::SUPER:
- if (is_strong(language_mode()) &&
- IsClassConstructor(function_state_->kind())) {
- bool is_this = peek() == Token::THIS;
- Expression expr = Expression::Default();
- ExpressionClassifier classifier(this);
- if (is_this) {
- expr = ParseStrongInitializationExpression(&classifier, CHECK_OK);
- } else {
- expr = ParseStrongSuperCallExpression(&classifier, CHECK_OK);
- }
- ValidateExpression(&classifier, CHECK_OK);
- switch (peek()) {
- case Token::SEMICOLON:
- Consume(Token::SEMICOLON);
- break;
- case Token::RBRACE:
- case Token::EOS:
- break;
- default:
- if (!scanner()->HasAnyLineTerminatorBeforeNext()) {
- ReportMessageAt(function_state_->this_location(),
- is_this
- ? MessageTemplate::kStrongConstructorThis
- : MessageTemplate::kStrongConstructorSuper);
- *ok = false;
- return Statement::Default();
- }
- }
- return Statement::ExpressionStatement(expr);
- }
- break;
-
- // TODO(arv): Handle `let [`
- // https://code.google.com/p/v8/issues/detail?id=3847
-
default:
break;
}
@@ -698,7 +590,16 @@
DCHECK(is_sloppy(language_mode()) ||
!IsFutureStrictReserved(expr.AsIdentifier()));
Consume(Token::COLON);
- Statement statement = ParseStatement(ok);
+ // ES#sec-labelled-function-declarations Labelled Function Declarations
+ if (peek() == Token::FUNCTION && is_sloppy(language_mode())) {
+ if (allow_function == kAllowLabelledFunctionStatement) {
+ return ParseFunctionDeclaration(ok);
+ } else {
+ return ParseScopedStatement(true, ok);
+ }
+ }
+ Statement statement =
+ ParseStatement(kDisallowLabelledFunctionStatement, ok);
return statement.IsJumpStatement() ? Statement::Default() : statement;
// Preparsing is disabled for extensions (because the extension details
// aren't passed to lazily compiled functions), so we don't
@@ -726,10 +627,10 @@
Expect(Token::LPAREN, CHECK_OK);
ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
- Statement stat = ParseSubStatement(CHECK_OK);
+ Statement stat = ParseScopedStatement(false, CHECK_OK);
if (peek() == Token::ELSE) {
Next();
- Statement else_stat = ParseSubStatement(CHECK_OK);
+ Statement else_stat = ParseScopedStatement(false, CHECK_OK);
stat = (stat.IsJumpStatement() && else_stat.IsJumpStatement()) ?
Statement::Jump() : Statement::Default();
} else {
@@ -795,14 +696,6 @@
tok != Token::SEMICOLON &&
tok != Token::RBRACE &&
tok != Token::EOS) {
- if (is_strong(language_mode()) &&
- IsClassConstructor(function_state_->kind())) {
- int pos = peek_position();
- ReportMessageAt(Scanner::Location(pos, pos + 1),
- MessageTemplate::kStrongConstructorReturnValue);
- *ok = false;
- return Statement::Default();
- }
ParseExpression(true, CHECK_OK);
}
ExpectSemicolon(CHECK_OK);
@@ -825,7 +718,7 @@
Scope* with_scope = NewScope(scope_, WITH_SCOPE);
BlockState block_state(&scope_, with_scope);
- ParseSubStatement(CHECK_OK);
+ ParseScopedStatement(true, CHECK_OK);
return Statement::Default();
}
@@ -857,13 +750,6 @@
statement = ParseStatementListItem(CHECK_OK);
token = peek();
}
- if (is_strong(language_mode()) && !statement.IsJumpStatement() &&
- token != Token::RBRACE) {
- ReportMessageAt(scanner()->location(),
- MessageTemplate::kStrongSwitchFallthrough);
- *ok = false;
- return Statement::Default();
- }
}
Expect(Token::RBRACE, ok);
return Statement::Default();
@@ -875,7 +761,7 @@
// 'do' Statement 'while' '(' Expression ')' ';'
Expect(Token::DO, CHECK_OK);
- ParseSubStatement(CHECK_OK);
+ ParseScopedStatement(true, CHECK_OK);
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
ParseExpression(true, CHECK_OK);
@@ -893,7 +779,7 @@
Expect(Token::LPAREN, CHECK_OK);
ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
- ParseSubStatement(ok);
+ ParseScopedStatement(true, ok);
return Statement::Default();
}
@@ -945,7 +831,7 @@
}
Expect(Token::RPAREN, CHECK_OK);
- ParseSubStatement(CHECK_OK);
+ ParseScopedStatement(true, CHECK_OK);
return Statement::Default();
}
} else {
@@ -958,7 +844,6 @@
bool is_for_each = CheckInOrOf(&mode, ok);
if (!*ok) return Statement::Default();
bool is_destructuring = is_for_each &&
- allow_harmony_destructuring_assignment() &&
(lhs->IsArrayLiteral() || lhs->IsObjectLiteral());
if (is_destructuring) {
@@ -983,7 +868,7 @@
}
Expect(Token::RPAREN, CHECK_OK);
- ParseSubStatement(CHECK_OK);
+ ParseScopedStatement(true, CHECK_OK);
return Statement::Default();
}
}
@@ -1009,7 +894,7 @@
}
Expect(Token::RPAREN, CHECK_OK);
- ParseSubStatement(ok);
+ ParseScopedStatement(true, ok);
return Statement::Default();
}
@@ -1156,16 +1041,6 @@
CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
}
- if (is_strong(language_mode) && IsSubclassConstructor(kind)) {
- if (!function_state.super_location().IsValid()) {
- ReportMessageAt(function_name_location,
- MessageTemplate::kStrongSuperCallMissing,
- kReferenceError);
- *ok = false;
- return Expression::Default();
- }
- }
-
return Expression::Default();
}
@@ -1186,10 +1061,10 @@
scope_->uses_super_property(), scope_->calls_eval());
}
-
PreParserExpression PreParser::ParseClassLiteral(
- PreParserIdentifier name, Scanner::Location class_name_location,
- bool name_is_strict_reserved, int pos, bool* ok) {
+ ExpressionClassifier* classifier, PreParserIdentifier name,
+ Scanner::Location class_name_location, bool name_is_strict_reserved,
+ int pos, bool* ok) {
// All parts of a ClassDeclaration and ClassExpression are strict code.
if (name_is_strict_reserved) {
ReportMessageAt(class_name_location,
@@ -1202,13 +1077,8 @@
*ok = false;
return EmptyExpression();
}
- LanguageMode class_language_mode = language_mode();
- if (is_strong(class_language_mode) && IsUndefined(name)) {
- ReportMessageAt(class_name_location, MessageTemplate::kStrongUndefined);
- *ok = false;
- return EmptyExpression();
- }
+ LanguageMode class_language_mode = language_mode();
Scope* scope = NewScope(scope_, BLOCK_SCOPE);
BlockState block_state(&scope_, scope);
scope_->SetLanguageMode(
@@ -1218,9 +1088,13 @@
bool has_extends = Check(Token::EXTENDS);
if (has_extends) {
- ExpressionClassifier classifier(this);
- ParseLeftHandSideExpression(&classifier, CHECK_OK);
- ValidateExpression(&classifier, CHECK_OK);
+ ExpressionClassifier extends_classifier(this);
+ ParseLeftHandSideExpression(&extends_classifier, CHECK_OK);
+ ValidateExpression(&extends_classifier, CHECK_OK);
+ if (classifier != nullptr) {
+ classifier->Accumulate(&extends_classifier,
+ ExpressionClassifier::ExpressionProductions);
+ }
}
ClassLiteralChecker checker(this);
@@ -1234,11 +1108,15 @@
bool is_computed_name = false; // Classes do not care about computed
// property names here.
Identifier name;
- ExpressionClassifier classifier(this);
+ ExpressionClassifier property_classifier(this);
ParsePropertyDefinition(&checker, in_class, has_extends, is_static,
&is_computed_name, &has_seen_constructor,
- &classifier, &name, CHECK_OK);
- ValidateExpression(&classifier, CHECK_OK);
+ &property_classifier, &name, CHECK_OK);
+ ValidateExpression(&property_classifier, CHECK_OK);
+ if (classifier != nullptr) {
+ classifier->Accumulate(&property_classifier,
+ ExpressionClassifier::ExpressionProductions);
+ }
}
Expect(Token::RBRACE, CHECK_OK);
diff --git a/src/parsing/preparser.h b/src/parsing/preparser.h
index 253251c..f2f6951 100644
--- a/src/parsing/preparser.h
+++ b/src/parsing/preparser.h
@@ -144,11 +144,6 @@
IsUseStrictField::encode(true));
}
- static PreParserExpression UseStrongStringLiteral() {
- return PreParserExpression(TypeField::encode(kStringLiteralExpression) |
- IsUseStrongField::encode(true));
- }
-
static PreParserExpression This() {
return PreParserExpression(TypeField::encode(kExpression) |
ExpressionTypeField::encode(kThisExpression));
@@ -214,11 +209,6 @@
IsUseStrictField::decode(code_);
}
- bool IsUseStrongLiteral() const {
- return TypeField::decode(code_) == kStringLiteralExpression &&
- IsUseStrongField::decode(code_);
- }
-
bool IsThis() const {
return TypeField::decode(code_) == kExpression &&
ExpressionTypeField::decode(code_) == kThisExpression;
@@ -317,7 +307,6 @@
// of the Type field, so they can share the storage.
typedef BitField<ExpressionType, TypeField::kNext, 3> ExpressionTypeField;
typedef BitField<bool, TypeField::kNext, 1> IsUseStrictField;
- typedef BitField<bool, IsUseStrictField::kNext, 1> IsUseStrongField;
typedef BitField<PreParserIdentifier::Type, TypeField::kNext, 10>
IdentifierTypeField;
typedef BitField<bool, TypeField::kNext, 1> HasCoverInitializedNameField;
@@ -366,9 +355,6 @@
if (expression.IsUseStrictLiteral()) {
return PreParserStatement(kUseStrictExpressionStatement);
}
- if (expression.IsUseStrongLiteral()) {
- return PreParserStatement(kUseStrongExpressionStatement);
- }
if (expression.IsStringLiteral()) {
return PreParserStatement(kStringLiteralExpressionStatement);
}
@@ -376,15 +362,13 @@
}
bool IsStringLiteral() {
- return code_ == kStringLiteralExpressionStatement;
+ return code_ == kStringLiteralExpressionStatement || IsUseStrictLiteral();
}
bool IsUseStrictLiteral() {
return code_ == kUseStrictExpressionStatement;
}
- bool IsUseStrongLiteral() { return code_ == kUseStrongExpressionStatement; }
-
bool IsFunctionDeclaration() {
return code_ == kFunctionDeclaration;
}
@@ -399,7 +383,6 @@
kJumpStatement,
kStringLiteralExpressionStatement,
kUseStrictExpressionStatement,
- kUseStrongExpressionStatement,
kFunctionDeclaration
};
@@ -424,18 +407,17 @@
}
PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern,
int js_flags, int literal_index,
- bool is_strong, int pos) {
+ int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewArrayLiteral(PreParserExpressionList values,
int literal_index,
- bool is_strong,
int pos) {
return PreParserExpression::ArrayLiteral();
}
PreParserExpression NewArrayLiteral(PreParserExpressionList values,
int first_spread_index, int literal_index,
- bool is_strong, int pos) {
+ int pos) {
return PreParserExpression::ArrayLiteral();
}
PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
@@ -454,8 +436,6 @@
PreParserExpression NewObjectLiteral(PreParserExpressionList properties,
int literal_index,
int boilerplate_properties,
- bool has_function,
- bool is_strong,
int pos) {
return PreParserExpression::ObjectLiteral();
}
@@ -496,7 +476,6 @@
}
PreParserExpression NewYield(PreParserExpression generator_object,
PreParserExpression expression,
- Yield::Kind yield_kind,
int pos) {
return PreParserExpression::Default();
}
@@ -683,9 +662,6 @@
UNREACHABLE();
}
- static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
- Scope* scope, PreParserExpression property, bool* has_function) {}
-
static void CheckAssigningFunctionLiteralToProperty(
PreParserExpression left, PreParserExpression right) {}
@@ -710,6 +686,10 @@
return PreParserExpression::Default();
}
+ PreParserExpression BuildIteratorResult(PreParserExpression value,
+ bool done) {
+ return PreParserExpression::Default();
+ }
PreParserExpression NewThrowReferenceError(MessageTemplate::Template message,
int pos) {
return PreParserExpression::Default();
@@ -902,11 +882,14 @@
int function_token_position, FunctionLiteral::FunctionType type,
LanguageMode language_mode, bool* ok);
- PreParserExpression ParseClassLiteral(PreParserIdentifier name,
+ PreParserExpression ParseClassLiteral(Type::ExpressionClassifier* classifier,
+ PreParserIdentifier name,
Scanner::Location class_name_location,
bool name_is_strict_reserved, int pos,
bool* ok);
+ V8_INLINE void MarkTailPosition(PreParserExpression) {}
+
PreParserExpressionList PrepareSpreadArguments(PreParserExpressionList list) {
return list;
}
@@ -922,6 +905,16 @@
inline void RewriteDestructuringAssignments() {}
+ inline PreParserExpression RewriteExponentiation(PreParserExpression left,
+ PreParserExpression right,
+ int pos) {
+ return left;
+ }
+ inline PreParserExpression RewriteAssignExponentiation(
+ PreParserExpression left, PreParserExpression right, int pos) {
+ return left;
+ }
+
inline void QueueDestructuringAssignmentForRewriting(PreParserExpression) {}
inline void QueueNonPatternForRewriting(PreParserExpression) {}
@@ -1029,8 +1022,11 @@
Statement ParseStatementListItem(bool* ok);
void ParseStatementList(int end_token, bool* ok,
Scanner::BookmarkScope* bookmark = nullptr);
- Statement ParseStatement(bool* ok);
- Statement ParseSubStatement(bool* ok);
+ Statement ParseStatement(AllowLabelledFunctionStatement allow_function,
+ bool* ok);
+ Statement ParseSubStatement(AllowLabelledFunctionStatement allow_function,
+ bool* ok);
+ Statement ParseScopedStatement(bool legacy, bool* ok);
Statement ParseFunctionDeclaration(bool* ok);
Statement ParseClassDeclaration(bool* ok);
Statement ParseBlock(bool* ok);
@@ -1042,7 +1038,8 @@
Scanner::Location* first_initializer_loc,
Scanner::Location* bindings_loc,
bool* ok);
- Statement ParseExpressionOrLabelledStatement(bool* ok);
+ Statement ParseExpressionOrLabelledStatement(
+ AllowLabelledFunctionStatement allow_function, bool* ok);
Statement ParseIfStatement(bool* ok);
Statement ParseContinueStatement(bool* ok);
Statement ParseBreakStatement(bool* ok);
@@ -1075,7 +1072,8 @@
void ParseLazyFunctionLiteralBody(bool* ok,
Scanner::BookmarkScope* bookmark = nullptr);
- PreParserExpression ParseClassLiteral(PreParserIdentifier name,
+ PreParserExpression ParseClassLiteral(ExpressionClassifier* classifier,
+ PreParserIdentifier name,
Scanner::Location class_name_location,
bool name_is_strict_reserved, int pos,
bool* ok);
@@ -1140,8 +1138,7 @@
PreParserExpression PreParserTraits::RewriteYieldStar(
PreParserExpression generator, PreParserExpression expression, int pos) {
- return pre_parser_->factory()->NewYield(
- generator, expression, Yield::kDelegating, pos);
+ return PreParserExpression::Default();
}
PreParserExpression PreParserTraits::RewriteInstanceof(PreParserExpression lhs,
diff --git a/src/parsing/rewriter.cc b/src/parsing/rewriter.cc
index c8e8fed..915a464 100644
--- a/src/parsing/rewriter.cc
+++ b/src/parsing/rewriter.cc
@@ -355,14 +355,7 @@
if (processor.HasStackOverflow()) return false;
if (processor.result_assigned()) {
- DCHECK(function->end_position() != RelocInfo::kNoPosition);
- // Set the position of the assignment statement one character past the
- // source code, such that it definitely is not in the source code range
- // of an immediate inner scope. For example in
- // eval('with ({x:1}) x = 1');
- // the end position of the function generated for executing the eval code
- // coincides with the end of the with scope which is the position of '1'.
- int pos = function->end_position();
+ int pos = RelocInfo::kNoPosition;
VariableProxy* result_proxy =
processor.factory()->NewVariableProxy(result, pos);
Statement* result_statement =
diff --git a/src/parsing/scanner.cc b/src/parsing/scanner.cc
index 2d5a579..698cb5e 100644
--- a/src/parsing/scanner.cc
+++ b/src/parsing/scanner.cc
@@ -40,7 +40,8 @@
: unicode_cache_(unicode_cache),
bookmark_c0_(kNoBookmark),
octal_pos_(Location::invalid()),
- found_html_comment_(false) {
+ found_html_comment_(false),
+ allow_harmony_exponentiation_operator_(false) {
bookmark_current_.literal_chars = &bookmark_current_literal_;
bookmark_current_.raw_literal_chars = &bookmark_current_raw_literal_;
bookmark_next_.literal_chars = &bookmark_next_literal_;
@@ -60,15 +61,19 @@
Scan();
}
-
-template <bool capture_raw>
+template <bool capture_raw, bool unicode>
uc32 Scanner::ScanHexNumber(int expected_length) {
DCHECK(expected_length <= 4); // prevent overflow
+ int begin = source_pos() - 2;
uc32 x = 0;
for (int i = 0; i < expected_length; i++) {
int d = HexValue(c0_);
if (d < 0) {
+ ReportScannerError(Location(begin, begin + expected_length + 2),
+ unicode
+ ? MessageTemplate::kInvalidUnicodeEscapeSequence
+ : MessageTemplate::kInvalidHexEscapeSequence);
return -1;
}
x = x * 16 + d;
@@ -78,20 +83,23 @@
return x;
}
-
template <bool capture_raw>
-uc32 Scanner::ScanUnlimitedLengthHexNumber(int max_value) {
+uc32 Scanner::ScanUnlimitedLengthHexNumber(int max_value, int beg_pos) {
uc32 x = 0;
int d = HexValue(c0_);
- if (d < 0) {
- return -1;
- }
+ if (d < 0) return -1;
+
while (d >= 0) {
x = x * 16 + d;
- if (x > max_value) return -1;
+ if (x > max_value) {
+ ReportScannerError(Location(beg_pos, source_pos() + 1),
+ MessageTemplate::kUndefinedUnicodeCodePoint);
+ return -1;
+ }
Advance<capture_raw>();
d = HexValue(c0_);
}
+
return x;
}
@@ -565,7 +573,14 @@
case '*':
// * *=
- token = Select('=', Token::ASSIGN_MUL, Token::MUL);
+ Advance();
+ if (c0_ == '*' && allow_harmony_exponentiation_operator()) {
+ token = Select('=', Token::ASSIGN_EXP, Token::EXP);
+ } else if (c0_ == '=') {
+ token = Select(Token::ASSIGN_MUL);
+ } else {
+ token = Token::MUL;
+ }
break;
case '%':
@@ -847,7 +862,9 @@
uc32 c = c0_;
Advance();
if (c == '\\') {
- if (c0_ < 0 || !ScanEscape<false, false>()) return Token::ILLEGAL;
+ if (c0_ < 0 || !ScanEscape<false, false>()) {
+ return Token::ILLEGAL;
+ }
} else {
AddLiteralChar(c);
}
@@ -879,7 +896,6 @@
StartRawLiteral();
const bool capture_raw = true;
const bool in_template_literal = true;
-
while (true) {
uc32 c = c0_;
Advance<capture_raw>();
@@ -1099,18 +1115,19 @@
// Accept both \uxxxx and \u{xxxxxx}. In the latter case, the number of
// hex digits between { } is arbitrary. \ and u have already been read.
if (c0_ == '{') {
+ int begin = source_pos() - 2;
Advance<capture_raw>();
- uc32 cp = ScanUnlimitedLengthHexNumber<capture_raw>(0x10ffff);
- if (cp < 0) {
- return -1;
- }
- if (c0_ != '}') {
+ uc32 cp = ScanUnlimitedLengthHexNumber<capture_raw>(0x10ffff, begin);
+ if (cp < 0 || c0_ != '}') {
+ ReportScannerError(source_pos(),
+ MessageTemplate::kInvalidUnicodeEscapeSequence);
return -1;
}
Advance<capture_raw>();
return cp;
}
- return ScanHexNumber<capture_raw>(4);
+ const bool unicode = true;
+ return ScanHexNumber<capture_raw, unicode>(4);
}
@@ -1420,7 +1437,6 @@
flag = RegExp::kUnicode;
break;
case 'y':
- if (!FLAG_harmony_regexps) return Nothing<RegExp::Flags>();
flag = RegExp::kSticky;
break;
default:
diff --git a/src/parsing/scanner.h b/src/parsing/scanner.h
index 3f9bbb5..22c504c 100644
--- a/src/parsing/scanner.h
+++ b/src/parsing/scanner.h
@@ -10,13 +10,14 @@
#include "src/allocation.h"
#include "src/base/logging.h"
#include "src/char-predicates.h"
+#include "src/collector.h"
#include "src/globals.h"
#include "src/hashmap.h"
#include "src/list.h"
+#include "src/messages.h"
#include "src/parsing/token.h"
#include "src/unicode.h"
#include "src/unicode-decoder.h"
-#include "src/utils.h"
namespace v8 {
namespace internal {
@@ -354,6 +355,10 @@
// (the token last returned by Next()).
Location location() const { return current_.location; }
+ bool has_error() const { return scanner_error_ != MessageTemplate::kNone; }
+ MessageTemplate::Template error() const { return scanner_error_; }
+ Location error_location() const { return scanner_error_location_; }
+
// Similar functions for the upcoming token.
// One token look-ahead (past the token returned by Next()).
@@ -450,6 +455,12 @@
bool FoundHtmlComment() const { return found_html_comment_; }
+#define DECLARE_ACCESSORS(name) \
+ inline bool allow_##name() const { return allow_##name##_; } \
+ inline void set_allow_##name(bool allow) { allow_##name##_ = allow; }
+ DECLARE_ACCESSORS(harmony_exponentiation_operator)
+#undef ACCESSOR
+
private:
// The current and look-ahead token.
struct TokenDesc {
@@ -476,6 +487,7 @@
current_.raw_literal_chars = NULL;
next_next_.token = Token::UNINITIALIZED;
found_html_comment_ = false;
+ scanner_error_ = MessageTemplate::kNone;
}
// Support BookmarkScope functionality.
@@ -486,6 +498,19 @@
void DropBookmark();
static void CopyTokenDesc(TokenDesc* to, TokenDesc* from);
+ void ReportScannerError(const Location& location,
+ MessageTemplate::Template error) {
+ if (has_error()) return;
+ scanner_error_ = error;
+ scanner_error_location_ = location;
+ }
+
+ void ReportScannerError(int pos, MessageTemplate::Template error) {
+ if (has_error()) return;
+ scanner_error_ = error;
+ scanner_error_location_ = Location(pos, pos + 1);
+ }
+
// Literal buffer support
inline void StartLiteral() {
LiteralBuffer* free_buffer =
@@ -631,13 +656,13 @@
return current_.raw_literal_chars->is_one_byte();
}
- template <bool capture_raw>
+ template <bool capture_raw, bool unicode = false>
uc32 ScanHexNumber(int expected_length);
// Scan a number of any length but not bigger than max_value. For example, the
// number can be 000000001, so it's very long in characters but its value is
// small.
template <bool capture_raw>
- uc32 ScanUnlimitedLengthHexNumber(int max_value);
+ uc32 ScanUnlimitedLengthHexNumber(int max_value, int beg_pos);
// Scans a single JavaScript token.
void Scan();
@@ -758,6 +783,11 @@
// Whether this scanner encountered an HTML comment.
bool found_html_comment_;
+
+ bool allow_harmony_exponentiation_operator_;
+
+ MessageTemplate::Template scanner_error_;
+ Location scanner_error_location_;
};
} // namespace internal
diff --git a/src/parsing/token.h b/src/parsing/token.h
index 7a62b4d..fae9ea8 100644
--- a/src/parsing/token.h
+++ b/src/parsing/token.h
@@ -63,6 +63,7 @@
T(ASSIGN_MUL, "*=", 2) \
T(ASSIGN_DIV, "/=", 2) \
T(ASSIGN_MOD, "%=", 2) \
+ T(ASSIGN_EXP, "**=", 2) \
\
/* Binary operators sorted by precedence. */ \
/* IsBinaryOp() relies on this block of enum values */ \
@@ -82,6 +83,7 @@
T(MUL, "*", 13) \
T(DIV, "/", 13) \
T(MOD, "%", 13) \
+ T(EXP, "**", 14) \
\
/* Compare operators sorted by precedence. */ \
/* IsCompareOp() relies on this block of enum values */ \
@@ -214,12 +216,10 @@
}
static bool IsAssignmentOp(Value tok) {
- return INIT <= tok && tok <= ASSIGN_MOD;
+ return INIT <= tok && tok <= ASSIGN_EXP;
}
- static bool IsBinaryOp(Value op) {
- return COMMA <= op && op <= MOD;
- }
+ static bool IsBinaryOp(Value op) { return COMMA <= op && op <= EXP; }
static bool IsTruncatingBinaryOp(Value op) {
return BIT_OR <= op && op <= ROR;