Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(526)

Side by Side Diff: src/parser.cc

Issue 1033823002: [es6] emit error when for-in loop declarations are initialized in strict mode (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast.h" 8 #include "src/ast.h"
9 #include "src/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/base/platform/platform.h" 10 #include "src/base/platform/platform.h"
(...skipping 2200 matching lines...) Expand 10 before | Expand all | Expand 10 after
2211 } 2211 }
2212 2212
2213 2213
2214 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, 2214 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
2215 ZoneList<const AstRawString*>* names, 2215 ZoneList<const AstRawString*>* names,
2216 bool* ok) { 2216 bool* ok) {
2217 // VariableStatement :: 2217 // VariableStatement ::
2218 // VariableDeclarations ';' 2218 // VariableDeclarations ';'
2219 2219
2220 const AstRawString* ignore; 2220 const AstRawString* ignore;
2221 Block* result = 2221 Block* result = ParseVariableDeclarations(var_context, NULL, names, &ignore,
arv (Not doing code reviews) 2015/03/25 09:17:43 NULL -> nullptr
caitp (gmail) 2015/03/25 11:22:42 Acknowledged.
2222 ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK); 2222 nullptr, CHECK_OK);
2223 ExpectSemicolon(CHECK_OK); 2223 ExpectSemicolon(CHECK_OK);
2224 return result; 2224 return result;
2225 } 2225 }
2226 2226
2227 2227
2228 // If the variable declaration declares exactly one non-const 2228 // If the variable declaration declares exactly one non-const
2229 // variable, then *out is set to that variable. In all other cases, 2229 // variable, then *out is set to that variable. In all other cases,
2230 // *out is untouched; in particular, it is the caller's responsibility 2230 // *out is untouched; in particular, it is the caller's responsibility
2231 // to initialize it properly. This mechanism is used for the parsing 2231 // to initialize it properly. This mechanism is used for the parsing
2232 // of 'for-in' loops. 2232 // of 'for-in' loops.
2233 Block* Parser::ParseVariableDeclarations( 2233 Block* Parser::ParseVariableDeclarations(
2234 VariableDeclarationContext var_context, 2234 VariableDeclarationContext var_context,
2235 VariableDeclarationProperties* decl_props, 2235 VariableDeclarationProperties* decl_props,
2236 ZoneList<const AstRawString*>* names, 2236 ZoneList<const AstRawString*>* names, const AstRawString** out,
2237 const AstRawString** out, 2237 Scanner::Location* first_initializer_loc, bool* ok) {
2238 bool* ok) {
2239 // VariableDeclarations :: 2238 // VariableDeclarations ::
2240 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[','] 2239 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
2241 // 2240 //
2242 // The ES6 Draft Rev3 specifies the following grammar for const declarations 2241 // The ES6 Draft Rev3 specifies the following grammar for const declarations
2243 // 2242 //
2244 // ConstDeclaration :: 2243 // ConstDeclaration ::
2245 // const ConstBinding (',' ConstBinding)* ';' 2244 // const ConstBinding (',' ConstBinding)* ';'
2246 // ConstBinding :: 2245 // ConstBinding ::
2247 // Identifier '=' AssignmentExpression 2246 // Identifier '=' AssignmentExpression
2248 // 2247 //
2249 // TODO(ES6): 2248 // TODO(ES6):
2250 // ConstBinding :: 2249 // ConstBinding ::
2251 // BindingPattern '=' AssignmentExpression 2250 // BindingPattern '=' AssignmentExpression
2252
2253 int pos = peek_position(); 2251 int pos = peek_position();
2254 VariableMode mode = VAR; 2252 VariableMode mode = VAR;
2255 // True if the binding needs initialization. 'let' and 'const' declared 2253 // True if the binding needs initialization. 'let' and 'const' declared
2256 // bindings are created uninitialized by their declaration nodes and 2254 // bindings are created uninitialized by their declaration nodes and
2257 // need initialization. 'var' declared bindings are always initialized 2255 // need initialization. 'var' declared bindings are always initialized
2258 // immediately by their declaration nodes. 2256 // immediately by their declaration nodes.
2259 bool needs_init = false; 2257 bool needs_init = false;
2260 bool is_const = false; 2258 bool is_const = false;
2261 Token::Value init_op = Token::INIT_VAR; 2259 Token::Value init_op = Token::INIT_VAR;
2262 if (peek() == Token::VAR) { 2260 if (peek() == Token::VAR) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2301 // rewriter to add a '.result' assignment to such a block (to get compliant 2299 // rewriter to add a '.result' assignment to such a block (to get compliant
2302 // behavior for code such as print(eval('var x = 7')), and for cosmetic 2300 // behavior for code such as print(eval('var x = 7')), and for cosmetic
2303 // reasons when pretty-printing. Also, unless an assignment (initialization) 2301 // reasons when pretty-printing. Also, unless an assignment (initialization)
2304 // is inside an initializer block, it is ignored. 2302 // is inside an initializer block, it is ignored.
2305 // 2303 //
2306 // Create new block with one expected declaration. 2304 // Create new block with one expected declaration.
2307 Block* block = factory()->NewBlock(NULL, 1, true, pos); 2305 Block* block = factory()->NewBlock(NULL, 1, true, pos);
2308 int nvars = 0; // the number of variables declared 2306 int nvars = 0; // the number of variables declared
2309 const AstRawString* name = NULL; 2307 const AstRawString* name = NULL;
2310 bool is_for_iteration_variable; 2308 bool is_for_iteration_variable;
2309 bool initializer_recorded = false;
2311 do { 2310 do {
2312 if (fni_ != NULL) fni_->Enter(); 2311 if (fni_ != NULL) fni_->Enter();
2313 2312
2314 // Parse variable name. 2313 // Parse variable name.
2315 if (nvars > 0) Consume(Token::COMMA); 2314 if (nvars > 0) Consume(Token::COMMA);
2316 name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); 2315 name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
2316 Scanner::Location variable_loc = scanner()->location();
2317 if (fni_ != NULL) fni_->PushVariableName(name); 2317 if (fni_ != NULL) fni_->PushVariableName(name);
2318 2318
2319 // Declare variable. 2319 // Declare variable.
2320 // Note that we *always* must treat the initial value via a separate init 2320 // Note that we *always* must treat the initial value via a separate init
2321 // assignment for variables and constants because the value must be assigned 2321 // assignment for variables and constants because the value must be assigned
2322 // when the variable is encountered in the source. But the variable/constant 2322 // when the variable is encountered in the source. But the variable/constant
2323 // is declared (and set to 'undefined') upon entering the function within 2323 // is declared (and set to 'undefined') upon entering the function within
2324 // which the variable or constant is declared. Only function variables have 2324 // which the variable or constant is declared. Only function variables have
2325 // an initial value in the declaration (because they are initialized upon 2325 // an initial value in the declaration (because they are initialized upon
2326 // entering the function). 2326 // entering the function).
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
2381 2381
2382 Scope* initialization_scope = is_const ? declaration_scope : scope_; 2382 Scope* initialization_scope = is_const ? declaration_scope : scope_;
2383 Expression* value = NULL; 2383 Expression* value = NULL;
2384 int pos = -1; 2384 int pos = -1;
2385 // Harmony consts have non-optional initializers. 2385 // Harmony consts have non-optional initializers.
2386 if (peek() == Token::ASSIGN || 2386 if (peek() == Token::ASSIGN ||
2387 (mode == CONST && !is_for_iteration_variable)) { 2387 (mode == CONST && !is_for_iteration_variable)) {
2388 Expect(Token::ASSIGN, CHECK_OK); 2388 Expect(Token::ASSIGN, CHECK_OK);
2389 pos = position(); 2389 pos = position();
2390 value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); 2390 value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
2391 variable_loc.end_pos = scanner()->location().end_pos;
2392
2393 if (first_initializer_loc && !initializer_recorded) {
arv (Not doing code reviews) 2015/03/25 09:17:43 Can you use IsValid here instead of adding the boo
caitp (gmail) 2015/03/25 11:22:42 Acknowledged.
2394 *first_initializer_loc = variable_loc;
2395 initializer_recorded = true;
2396 }
2397
2391 // Don't infer if it is "a = function(){...}();"-like expression. 2398 // Don't infer if it is "a = function(){...}();"-like expression.
2392 if (fni_ != NULL && 2399 if (fni_ != NULL &&
2393 value->AsCall() == NULL && 2400 value->AsCall() == NULL &&
2394 value->AsCallNew() == NULL) { 2401 value->AsCallNew() == NULL) {
2395 fni_->Infer(); 2402 fni_->Infer();
2396 } else { 2403 } else {
2397 fni_->RemoveLastFunction(); 2404 fni_->RemoveLastFunction();
2398 } 2405 }
2399 if (decl_props != NULL) *decl_props = kHasInitializers; 2406 if (decl_props != NULL) *decl_props = kHasInitializers;
2400 // End position of the initializer is after the assignment expression. 2407 // End position of the initializer is after the assignment expression.
(...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after
3357 3364
3358 Expect(Token::FOR, CHECK_OK); 3365 Expect(Token::FOR, CHECK_OK);
3359 Expect(Token::LPAREN, CHECK_OK); 3366 Expect(Token::LPAREN, CHECK_OK);
3360 for_scope->set_start_position(scanner()->location().beg_pos); 3367 for_scope->set_start_position(scanner()->location().beg_pos);
3361 bool is_let_identifier_expression = false; 3368 bool is_let_identifier_expression = false;
3362 if (peek() != Token::SEMICOLON) { 3369 if (peek() != Token::SEMICOLON) {
3363 if (peek() == Token::VAR || 3370 if (peek() == Token::VAR ||
3364 (peek() == Token::CONST && is_sloppy(language_mode()))) { 3371 (peek() == Token::CONST && is_sloppy(language_mode()))) {
3365 const AstRawString* name = NULL; 3372 const AstRawString* name = NULL;
3366 VariableDeclarationProperties decl_props = kHasNoInitializers; 3373 VariableDeclarationProperties decl_props = kHasNoInitializers;
3374 Scanner::Location first_initializer_loc = Scanner::Location::invalid();
3367 Block* variable_statement = 3375 Block* variable_statement =
3368 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, 3376 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
3369 CHECK_OK); 3377 &first_initializer_loc, CHECK_OK);
3370 bool accept_OF = decl_props == kHasNoInitializers; 3378 bool accept_OF = true;
3371 ForEachStatement::VisitMode mode; 3379 ForEachStatement::VisitMode mode;
3372 int each_beg_pos = scanner()->location().beg_pos; 3380 int each_beg_pos = scanner()->location().beg_pos;
3373 int each_end_pos = scanner()->location().end_pos; 3381 int each_end_pos = scanner()->location().end_pos;
3374 3382
3375 if (name != NULL && CheckInOrOf(accept_OF, &mode, ok)) { 3383 if (name != NULL && CheckInOrOf(accept_OF, &mode, ok)) {
3376 if (!*ok) return nullptr; 3384 if (!*ok) return nullptr;
3385 if (first_initializer_loc.IsValid() &&
3386 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) {
3387 if (mode == ForEachStatement::ITERATE) {
3388 ReportMessageAt(first_initializer_loc, "for_of_loop_initializer");
3389 } else {
3390 ReportMessageAt(first_initializer_loc,
3391 "strict_for_in_loop_initializer");
3392 }
3393 *ok = false;
3394 return nullptr;
3395 }
3377 ForEachStatement* loop = 3396 ForEachStatement* loop =
3378 factory()->NewForEachStatement(mode, labels, stmt_pos); 3397 factory()->NewForEachStatement(mode, labels, stmt_pos);
3379 Target target(&this->target_stack_, loop); 3398 Target target(&this->target_stack_, loop);
3380 3399
3381 Expression* enumerable = ParseExpression(true, CHECK_OK); 3400 Expression* enumerable = ParseExpression(true, CHECK_OK);
3382 Expect(Token::RPAREN, CHECK_OK); 3401 Expect(Token::RPAREN, CHECK_OK);
3383 3402
3384 VariableProxy* each = 3403 VariableProxy* each =
3385 scope_->NewUnresolved(factory(), name, each_beg_pos, each_end_pos); 3404 scope_->NewUnresolved(factory(), name, each_beg_pos, each_end_pos);
3386 Statement* body = ParseSubStatement(NULL, CHECK_OK); 3405 Statement* body = ParseSubStatement(NULL, CHECK_OK);
3387 InitializeForEachStatement(loop, each, enumerable, body); 3406 InitializeForEachStatement(loop, each, enumerable, body);
3388 Block* result = 3407 Block* result =
3389 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); 3408 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
3390 result->AddStatement(variable_statement, zone()); 3409 result->AddStatement(variable_statement, zone());
3391 result->AddStatement(loop, zone()); 3410 result->AddStatement(loop, zone());
3392 scope_ = saved_scope; 3411 scope_ = saved_scope;
3393 for_scope->set_end_position(scanner()->location().end_pos); 3412 for_scope->set_end_position(scanner()->location().end_pos);
3394 for_scope = for_scope->FinalizeBlockScope(); 3413 for_scope = for_scope->FinalizeBlockScope();
3395 DCHECK(for_scope == NULL); 3414 DCHECK(for_scope == NULL);
3396 // Parsed for-in loop w/ variable/const declaration. 3415 // Parsed for-in loop w/ variable/const declaration.
3397 return result; 3416 return result;
3398 } else { 3417 } else {
3399 init = variable_statement; 3418 init = variable_statement;
3400 } 3419 }
3401 } else if ((peek() == Token::LET || peek() == Token::CONST) && 3420 } else if ((peek() == Token::LET || peek() == Token::CONST) &&
3402 is_strict(language_mode())) { 3421 is_strict(language_mode())) {
3403 is_const = peek() == Token::CONST; 3422 is_const = peek() == Token::CONST;
3404 const AstRawString* name = NULL; 3423 const AstRawString* name = NULL;
3405 VariableDeclarationProperties decl_props = kHasNoInitializers; 3424 VariableDeclarationProperties decl_props = kHasNoInitializers;
3406 Block* variable_statement = 3425 Block* variable_statement = ParseVariableDeclarations(
3407 ParseVariableDeclarations(kForStatement, &decl_props, 3426 kForStatement, &decl_props, &lexical_bindings, &name, nullptr,
3408 &lexical_bindings, &name, CHECK_OK); 3427 CHECK_OK);
3409 bool accept_IN = name != NULL && decl_props != kHasInitializers; 3428 bool accept_IN = name != NULL && decl_props != kHasInitializers;
3410 bool accept_OF = decl_props == kHasNoInitializers; 3429 bool accept_OF = decl_props == kHasNoInitializers;
3411 ForEachStatement::VisitMode mode; 3430 ForEachStatement::VisitMode mode;
3412 int each_beg_pos = scanner()->location().beg_pos; 3431 int each_beg_pos = scanner()->location().beg_pos;
3413 int each_end_pos = scanner()->location().end_pos; 3432 int each_end_pos = scanner()->location().end_pos;
3414 3433
3415 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { 3434 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) {
3416 if (!*ok) return nullptr; 3435 if (!*ok) return nullptr;
3417 3436
3418 // Rewrite a for-in statement of the form 3437 // Rewrite a for-in statement of the form
(...skipping 2140 matching lines...) Expand 10 before | Expand all | Expand 10 after
5559 } else { 5578 } else {
5560 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); 5579 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
5561 running_hash = StringHasher::ComputeRunningHash(running_hash, data, 5580 running_hash = StringHasher::ComputeRunningHash(running_hash, data,
5562 raw_string->length()); 5581 raw_string->length());
5563 } 5582 }
5564 } 5583 }
5565 5584
5566 return running_hash; 5585 return running_hash;
5567 } 5586 }
5568 } } // namespace v8::internal 5587 } } // namespace v8::internal
OLDNEW
« src/messages.js ('K') | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698