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

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: delete decl_props Created 5 years, 8 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
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, 2213 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
2214 ZoneList<const AstRawString*>* names, 2214 ZoneList<const AstRawString*>* names,
2215 bool* ok) { 2215 bool* ok) {
2216 // VariableStatement :: 2216 // VariableStatement ::
2217 // VariableDeclarations ';' 2217 // VariableDeclarations ';'
2218 2218
2219 const AstRawString* ignore; 2219 const AstRawString* ignore;
2220 Block* result = 2220 Block* result =
2221 ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK); 2221 ParseVariableDeclarations(var_context, names, &ignore, nullptr, CHECK_OK);
2222 ExpectSemicolon(CHECK_OK); 2222 ExpectSemicolon(CHECK_OK);
2223 return result; 2223 return result;
2224 } 2224 }
2225 2225
2226 2226
2227 // If the variable declaration declares exactly one non-const 2227 // If the variable declaration declares exactly one non-const
2228 // variable, then *out is set to that variable. In all other cases, 2228 // variable, then *out is set to that variable. In all other cases,
2229 // *out is untouched; in particular, it is the caller's responsibility 2229 // *out is untouched; in particular, it is the caller's responsibility
2230 // to initialize it properly. This mechanism is used for the parsing 2230 // to initialize it properly. This mechanism is used for the parsing
2231 // of 'for-in' loops. 2231 // of 'for-in' loops.
2232 Block* Parser::ParseVariableDeclarations( 2232 Block* Parser::ParseVariableDeclarations(
2233 VariableDeclarationContext var_context, 2233 VariableDeclarationContext var_context,
2234 VariableDeclarationProperties* decl_props, 2234 ZoneList<const AstRawString*>* names, const AstRawString** out,
2235 ZoneList<const AstRawString*>* names, 2235 Scanner::Location* first_initializer_loc, bool* ok) {
2236 const AstRawString** out,
2237 bool* ok) {
2238 // VariableDeclarations :: 2236 // VariableDeclarations ::
2239 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[','] 2237 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
2240 // 2238 //
2241 // The ES6 Draft Rev3 specifies the following grammar for const declarations 2239 // The ES6 Draft Rev3 specifies the following grammar for const declarations
2242 // 2240 //
2243 // ConstDeclaration :: 2241 // ConstDeclaration ::
2244 // const ConstBinding (',' ConstBinding)* ';' 2242 // const ConstBinding (',' ConstBinding)* ';'
2245 // ConstBinding :: 2243 // ConstBinding ::
2246 // Identifier '=' AssignmentExpression 2244 // Identifier '=' AssignmentExpression
2247 // 2245 //
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
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;
2311 do { 2309 do {
2312 if (fni_ != NULL) fni_->Enter(); 2310 if (fni_ != NULL) fni_->Enter();
2313 2311
2314 // Parse variable name. 2312 // Parse variable name.
2315 if (nvars > 0) Consume(Token::COMMA); 2313 if (nvars > 0) Consume(Token::COMMA);
2316 name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); 2314 name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
2315 Scanner::Location variable_loc = scanner()->location();
2317 if (fni_ != NULL) fni_->PushVariableName(name); 2316 if (fni_ != NULL) fni_->PushVariableName(name);
2318 2317
2319 // Declare variable. 2318 // Declare variable.
2320 // Note that we *always* must treat the initial value via a separate init 2319 // 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 2320 // assignment for variables and constants because the value must be assigned
2322 // when the variable is encountered in the source. But the variable/constant 2321 // when the variable is encountered in the source. But the variable/constant
2323 // is declared (and set to 'undefined') upon entering the function within 2322 // is declared (and set to 'undefined') upon entering the function within
2324 // which the variable or constant is declared. Only function variables have 2323 // which the variable or constant is declared. Only function variables have
2325 // an initial value in the declaration (because they are initialized upon 2324 // an initial value in the declaration (because they are initialized upon
2326 // entering the function). 2325 // entering the function).
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
2381 2380
2382 Scope* initialization_scope = is_const ? declaration_scope : scope_; 2381 Scope* initialization_scope = is_const ? declaration_scope : scope_;
2383 Expression* value = NULL; 2382 Expression* value = NULL;
2384 int pos = -1; 2383 int pos = -1;
2385 // Harmony consts have non-optional initializers. 2384 // Harmony consts have non-optional initializers.
2386 if (peek() == Token::ASSIGN || 2385 if (peek() == Token::ASSIGN ||
2387 (mode == CONST && !is_for_iteration_variable)) { 2386 (mode == CONST && !is_for_iteration_variable)) {
2388 Expect(Token::ASSIGN, CHECK_OK); 2387 Expect(Token::ASSIGN, CHECK_OK);
2389 pos = position(); 2388 pos = position();
2390 value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); 2389 value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
2390 variable_loc.end_pos = scanner()->location().end_pos;
2391
2392 if (first_initializer_loc && !first_initializer_loc->IsValid()) {
2393 *first_initializer_loc = variable_loc;
2394 }
2395
2391 // Don't infer if it is "a = function(){...}();"-like expression. 2396 // Don't infer if it is "a = function(){...}();"-like expression.
2392 if (fni_ != NULL && 2397 if (fni_ != NULL &&
2393 value->AsCall() == NULL && 2398 value->AsCall() == NULL &&
2394 value->AsCallNew() == NULL) { 2399 value->AsCallNew() == NULL) {
2395 fni_->Infer(); 2400 fni_->Infer();
2396 } else { 2401 } else {
2397 fni_->RemoveLastFunction(); 2402 fni_->RemoveLastFunction();
2398 } 2403 }
2399 if (decl_props != NULL) *decl_props = kHasInitializers;
2400 // End position of the initializer is after the assignment expression. 2404 // End position of the initializer is after the assignment expression.
2401 var->set_initializer_position(scanner()->location().end_pos); 2405 var->set_initializer_position(scanner()->location().end_pos);
2402 } else { 2406 } else {
2403 // End position of the initializer is after the variable. 2407 // End position of the initializer is after the variable.
2404 var->set_initializer_position(position()); 2408 var->set_initializer_position(position());
2405 } 2409 }
2406 2410
2407 // Make sure that 'const x' and 'let x' initialize 'x' to undefined. 2411 // Make sure that 'const x' and 'let x' initialize 'x' to undefined.
2408 if (value == NULL && needs_init) { 2412 if (value == NULL && needs_init) {
2409 value = GetLiteralUndefined(position()); 2413 value = GetLiteralUndefined(position());
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after
3356 scope_ = for_scope; 3360 scope_ = for_scope;
3357 3361
3358 Expect(Token::FOR, CHECK_OK); 3362 Expect(Token::FOR, CHECK_OK);
3359 Expect(Token::LPAREN, CHECK_OK); 3363 Expect(Token::LPAREN, CHECK_OK);
3360 for_scope->set_start_position(scanner()->location().beg_pos); 3364 for_scope->set_start_position(scanner()->location().beg_pos);
3361 bool is_let_identifier_expression = false; 3365 bool is_let_identifier_expression = false;
3362 if (peek() != Token::SEMICOLON) { 3366 if (peek() != Token::SEMICOLON) {
3363 if (peek() == Token::VAR || 3367 if (peek() == Token::VAR ||
3364 (peek() == Token::CONST && is_sloppy(language_mode()))) { 3368 (peek() == Token::CONST && is_sloppy(language_mode()))) {
3365 const AstRawString* name = NULL; 3369 const AstRawString* name = NULL;
3366 VariableDeclarationProperties decl_props = kHasNoInitializers; 3370 Scanner::Location first_initializer_loc = Scanner::Location::invalid();
3367 Block* variable_statement = 3371 Block* variable_statement = ParseVariableDeclarations(
3368 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, 3372 kForStatement, nullptr, &name, &first_initializer_loc, CHECK_OK);
3369 CHECK_OK); 3373 bool accept_OF = true;
3370 bool accept_OF = decl_props == kHasNoInitializers;
3371 ForEachStatement::VisitMode mode; 3374 ForEachStatement::VisitMode mode;
3372 int each_beg_pos = scanner()->location().beg_pos; 3375 int each_beg_pos = scanner()->location().beg_pos;
3373 int each_end_pos = scanner()->location().end_pos; 3376 int each_end_pos = scanner()->location().end_pos;
3374 3377
3375 if (name != NULL && CheckInOrOf(accept_OF, &mode, ok)) { 3378 if (name != NULL && CheckInOrOf(accept_OF, &mode, ok)) {
3376 if (!*ok) return nullptr; 3379 if (!*ok) return nullptr;
3380 if (first_initializer_loc.IsValid() &&
3381 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) {
3382 if (mode == ForEachStatement::ITERATE) {
3383 ReportMessageAt(first_initializer_loc, "for_of_loop_initializer");
3384 } else {
3385 // TODO(caitp): This should be an error in sloppy mode too.
3386 ReportMessageAt(first_initializer_loc, "for_in_loop_initializer");
3387 }
3388 *ok = false;
3389 return nullptr;
3390 }
3377 ForEachStatement* loop = 3391 ForEachStatement* loop =
3378 factory()->NewForEachStatement(mode, labels, stmt_pos); 3392 factory()->NewForEachStatement(mode, labels, stmt_pos);
3379 Target target(&this->target_stack_, loop); 3393 Target target(&this->target_stack_, loop);
3380 3394
3381 Expression* enumerable = ParseExpression(true, CHECK_OK); 3395 Expression* enumerable = ParseExpression(true, CHECK_OK);
3382 Expect(Token::RPAREN, CHECK_OK); 3396 Expect(Token::RPAREN, CHECK_OK);
3383 3397
3384 VariableProxy* each = 3398 VariableProxy* each =
3385 scope_->NewUnresolved(factory(), name, each_beg_pos, each_end_pos); 3399 scope_->NewUnresolved(factory(), name, each_beg_pos, each_end_pos);
3386 Statement* body = ParseSubStatement(NULL, CHECK_OK); 3400 Statement* body = ParseSubStatement(NULL, CHECK_OK);
3387 InitializeForEachStatement(loop, each, enumerable, body); 3401 InitializeForEachStatement(loop, each, enumerable, body);
3388 Block* result = 3402 Block* result =
3389 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); 3403 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
3390 result->AddStatement(variable_statement, zone()); 3404 result->AddStatement(variable_statement, zone());
3391 result->AddStatement(loop, zone()); 3405 result->AddStatement(loop, zone());
3392 scope_ = saved_scope; 3406 scope_ = saved_scope;
3393 for_scope->set_end_position(scanner()->location().end_pos); 3407 for_scope->set_end_position(scanner()->location().end_pos);
3394 for_scope = for_scope->FinalizeBlockScope(); 3408 for_scope = for_scope->FinalizeBlockScope();
3395 DCHECK(for_scope == NULL); 3409 DCHECK(for_scope == NULL);
3396 // Parsed for-in loop w/ variable/const declaration. 3410 // Parsed for-in loop w/ variable/const declaration.
3397 return result; 3411 return result;
3398 } else { 3412 } else {
3399 init = variable_statement; 3413 init = variable_statement;
3400 } 3414 }
3401 } else if ((peek() == Token::LET || peek() == Token::CONST) && 3415 } else if ((peek() == Token::LET || peek() == Token::CONST) &&
3402 is_strict(language_mode())) { 3416 is_strict(language_mode())) {
3403 is_const = peek() == Token::CONST; 3417 is_const = peek() == Token::CONST;
3404 const AstRawString* name = NULL; 3418 const AstRawString* name = NULL;
3405 VariableDeclarationProperties decl_props = kHasNoInitializers; 3419 Scanner::Location first_initializer_loc = Scanner::Location::invalid();
3406 Block* variable_statement = 3420 Block* variable_statement =
3407 ParseVariableDeclarations(kForStatement, &decl_props, 3421 ParseVariableDeclarations(kForStatement, &lexical_bindings, &name,
3408 &lexical_bindings, &name, CHECK_OK); 3422 &first_initializer_loc, CHECK_OK);
3409 bool accept_IN = name != NULL && decl_props != kHasInitializers; 3423 bool accept_IN = name != NULL;
3410 bool accept_OF = decl_props == kHasNoInitializers; 3424 bool accept_OF = true;
3411 ForEachStatement::VisitMode mode; 3425 ForEachStatement::VisitMode mode;
3412 int each_beg_pos = scanner()->location().beg_pos; 3426 int each_beg_pos = scanner()->location().beg_pos;
3413 int each_end_pos = scanner()->location().end_pos; 3427 int each_end_pos = scanner()->location().end_pos;
3414 3428
3415 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { 3429 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) {
3416 if (!*ok) return nullptr; 3430 if (!*ok) return nullptr;
3417 3431 if (first_initializer_loc.IsValid() &&
3432 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) {
3433 if (mode == ForEachStatement::ITERATE) {
3434 ReportMessageAt(first_initializer_loc, "for_of_loop_initializer");
3435 } else {
3436 ReportMessageAt(first_initializer_loc, "for_in_loop_initializer");
3437 }
3438 *ok = false;
3439 return nullptr;
3440 }
3418 // Rewrite a for-in statement of the form 3441 // Rewrite a for-in statement of the form
3419 // 3442 //
3420 // for (let/const x in e) b 3443 // for (let/const x in e) b
3421 // 3444 //
3422 // into 3445 // into
3423 // 3446 //
3424 // <let x' be a temporary variable> 3447 // <let x' be a temporary variable>
3425 // for (x' in e) { 3448 // for (x' in e) {
3426 // let/const x; 3449 // let/const x;
3427 // x = x'; 3450 // x = x';
(...skipping 2129 matching lines...) Expand 10 before | Expand all | Expand 10 after
5557 } else { 5580 } else {
5558 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); 5581 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
5559 running_hash = StringHasher::ComputeRunningHash(running_hash, data, 5582 running_hash = StringHasher::ComputeRunningHash(running_hash, data,
5560 raw_string->length()); 5583 raw_string->length());
5561 } 5584 }
5562 } 5585 }
5563 5586
5564 return running_hash; 5587 return running_hash;
5565 } 5588 }
5566 } } // namespace v8::internal 5589 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698