strong_equal: ["Please don't use '==' or '!=' in strong mode, use '===' or '!==' instead"],
strong_delete: ["Please don't use 'delete' in strong mode, use maps or sets instead"],
strong_var: ["Please don't use 'var' in strong mode, use 'let' or 'const' instead"],
+ strong_for_in: ["Please don't use 'for'-'in' loops in strong mode, use 'for'-'of' instead"],
strong_empty: ["Please don't use empty sub-statements in strong mode, make them explicit with '{}' instead"],
sloppy_lexical: ["Block-scoped declarations (let, const, function, class) not yet supported outside strict mode"],
malformed_arrow_function_parameter_list: ["Malformed arrow function parameter list"],
}
-bool Parser::CheckInOrOf(bool accept_OF,
- ForEachStatement::VisitMode* visit_mode) {
- if (Check(Token::IN)) {
- *visit_mode = ForEachStatement::ENUMERATE;
- return true;
- } else if (accept_OF && CheckContextualKeyword(CStrVector("of"))) {
- *visit_mode = ForEachStatement::ITERATE;
- return true;
- }
- return false;
-}
-
-
void Parser::InitializeForEachStatement(ForEachStatement* stmt,
Expression* each,
Expression* subject,
ForEachStatement::VisitMode mode;
int each_pos = position();
- if (name != NULL && CheckInOrOf(accept_OF, &mode)) {
+ if (name != NULL && CheckInOrOf(accept_OF, &mode, ok)) {
+ if (!*ok) return nullptr;
ForEachStatement* loop =
factory()->NewForEachStatement(mode, labels, stmt_pos);
Target target(&this->target_stack_, loop);
ForEachStatement::VisitMode mode;
int each_pos = position();
- if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
+ if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) {
+ if (!*ok) return nullptr;
+
// Rewrite a for-in statement of the form
//
// for (let/const x in e) b
expression->AsVariableProxy()->raw_name() ==
ast_value_factory()->let_string();
- if (CheckInOrOf(accept_OF, &mode)) {
+ if (CheckInOrOf(accept_OF, &mode, ok)) {
+ if (!*ok) return nullptr;
expression = this->CheckAndRewriteReferenceExpression(
expression, lhs_location, "invalid_lhs_in_for", CHECK_OK);
// Magical syntax support.
Expression* ParseV8Intrinsic(bool* ok);
- bool CheckInOrOf(bool accept_OF, ForEachStatement::VisitMode* visit_mode);
-
// Get odd-ball literals.
Literal* GetLiteralUndefined(int position);
}
-bool PreParser::CheckInOrOf(bool accept_OF) {
- if (Check(Token::IN) ||
- (accept_OF && CheckContextualKeyword(CStrVector("of")))) {
- return true;
- }
- return false;
-}
-
-
PreParser::Statement PreParser::ParseForStatement(bool* ok) {
// ForStatement ::
// 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
Expect(Token::LPAREN, CHECK_OK);
bool is_let_identifier_expression = false;
if (peek() != Token::SEMICOLON) {
+ ForEachStatement::VisitMode visit_mode;
if (peek() == Token::VAR || peek() == Token::CONST ||
(peek() == Token::LET && is_strict(language_mode()))) {
bool is_lexical = peek() == Token::LET ||
bool has_initializers = decl_props == kHasInitializers;
bool accept_IN = decl_count == 1 && !(is_lexical && has_initializers);
bool accept_OF = !has_initializers;
- if (accept_IN && CheckInOrOf(accept_OF)) {
+ if (accept_IN && CheckInOrOf(accept_OF, &visit_mode, ok)) {
+ if (!*ok) return Statement::Default();
ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
-
ParseSubStatement(CHECK_OK);
return Statement::Default();
}
Expression lhs = ParseExpression(false, CHECK_OK);
is_let_identifier_expression =
lhs.IsIdentifier() && lhs.AsIdentifier().IsLet();
- if (CheckInOrOf(lhs.IsIdentifier())) {
+ if (CheckInOrOf(lhs.IsIdentifier(), &visit_mode, ok)) {
+ if (!*ok) return Statement::Default();
ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
-
ParseSubStatement(CHECK_OK);
return Statement::Default();
}
}
}
+ bool CheckInOrOf(
+ bool accept_OF, ForEachStatement::VisitMode* visit_mode, bool* ok) {
+ if (Check(Token::IN)) {
+ if (is_strong(language_mode())) {
+ ReportMessageAt(scanner()->location(), "strong_for_in");
+ *ok = false;
+ } else {
+ *visit_mode = ForEachStatement::ENUMERATE;
+ }
+ return true;
+ } else if (accept_OF && CheckContextualKeyword(CStrVector("of"))) {
+ *visit_mode = ForEachStatement::ITERATE;
+ return true;
+ }
+ return false;
+ }
+
// Checks whether an octal literal was last seen between beg_pos and end_pos.
// If so, reports an error. Only called for strict mode and template strings.
void CheckOctalLiteral(int beg_pos, int end_pos, const char* error,
Scanner::Location class_name_location,
bool name_is_strict_reserved, int pos,
bool* ok);
-
- bool CheckInOrOf(bool accept_OF);
};
RunParserSyncTest(strong_context_data, data, kError, NULL, 0, always_flags,
arraysize(always_flags));
}
+
+
+TEST(StrongForIn) {
+ const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
+ const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
+ const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
+
+ const char* data[] = {
+ "for (x in []) {}",
+ "for (const x in []) {}",
+ NULL};
+
+ static const ParserFlag always_flags[] = {
+ kAllowStrongMode, kAllowHarmonyScoping
+ };
+ RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, always_flags,
+ arraysize(always_flags));
+ RunParserSyncTest(strict_context_data, data, kSuccess, NULL, 0, always_flags,
+ arraysize(always_flags));
+ RunParserSyncTest(strong_context_data, data, kError, NULL, 0, always_flags,
+ arraysize(always_flags));
+}
assertThrows("'use strong'; for (let x;;);", SyntaxError);
assertThrows("'use strong'; for (let x in []);", SyntaxError);
assertThrows("'use strong'; for (let x of []);", SyntaxError);
- assertThrows("'use strong'; with ({});", SyntaxError);
})();
--- /dev/null
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --strong-mode
+
+(function NoForInStatement() {
+ assertThrows("'use strong'; for (x in []) {}", SyntaxError);
+ assertThrows("'use strong'; for (let x in []) {}", SyntaxError);
+ assertThrows("'use strong'; for (const x in []) {}", SyntaxError);
+})();
+
+(function ForOfStatement() {
+ assertTrue(eval("'use strong'; for (x of []) {} true"));
+ assertTrue(eval("'use strong'; for (let x of []) {} true"));
+ assertTrue(eval("'use strong'; for (const x of []) {} true"));
+})();