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

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: Add TODO 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') | src/preparser.cc » ('J')
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 2199 matching lines...) Expand 10 before | Expand all | Expand 10 after
2210 } 2210 }
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 = ParseVariableDeclarations(var_context, nullptr, names,
2221 ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK); 2221 &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 VariableDeclarationProperties* decl_props,
marja 2015/04/07 08:30:34 Isn't decl_props now unnecessary? If not, why not?
caitp (gmail) 2015/04/07 11:56:20 Yes, it can be removed
2235 ZoneList<const AstRawString*>* names, 2235 ZoneList<const AstRawString*>* names, const AstRawString** out,
2236 const AstRawString** out, 2236 Scanner::Location* first_initializer_loc, bool* ok) {
2237 bool* ok) {
2238 // VariableDeclarations :: 2237 // VariableDeclarations ::
2239 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[','] 2238 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
2240 // 2239 //
2241 // The ES6 Draft Rev3 specifies the following grammar for const declarations 2240 // The ES6 Draft Rev3 specifies the following grammar for const declarations
2242 // 2241 //
2243 // ConstDeclaration :: 2242 // ConstDeclaration ::
2244 // const ConstBinding (',' ConstBinding)* ';' 2243 // const ConstBinding (',' ConstBinding)* ';'
2245 // ConstBinding :: 2244 // ConstBinding ::
2246 // Identifier '=' AssignmentExpression 2245 // Identifier '=' AssignmentExpression
2247 // 2246 //
2248 // TODO(ES6): 2247 // TODO(ES6):
2249 // ConstBinding :: 2248 // ConstBinding ::
2250 // BindingPattern '=' AssignmentExpression 2249 // BindingPattern '=' AssignmentExpression
2251
marja 2015/04/07 08:30:34 Nit: this was probably an accidental deletion.
2252 int pos = peek_position(); 2250 int pos = peek_position();
2253 VariableMode mode = VAR; 2251 VariableMode mode = VAR;
2254 // True if the binding needs initialization. 'let' and 'const' declared 2252 // True if the binding needs initialization. 'let' and 'const' declared
2255 // bindings are created uninitialized by their declaration nodes and 2253 // bindings are created uninitialized by their declaration nodes and
2256 // need initialization. 'var' declared bindings are always initialized 2254 // need initialization. 'var' declared bindings are always initialized
2257 // immediately by their declaration nodes. 2255 // immediately by their declaration nodes.
2258 bool needs_init = false; 2256 bool needs_init = false;
2259 bool is_const = false; 2257 bool is_const = false;
2260 Token::Value init_op = Token::INIT_VAR; 2258 Token::Value init_op = Token::INIT_VAR;
2261 if (peek() == Token::VAR) { 2259 if (peek() == Token::VAR) {
(...skipping 45 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; 2404 if (decl_props != NULL) *decl_props = kHasInitializers;
2400 // End position of the initializer is after the assignment expression. 2405 // End position of the initializer is after the assignment expression.
(...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after
3357 3362
3358 Expect(Token::FOR, CHECK_OK); 3363 Expect(Token::FOR, CHECK_OK);
3359 Expect(Token::LPAREN, CHECK_OK); 3364 Expect(Token::LPAREN, CHECK_OK);
3360 for_scope->set_start_position(scanner()->location().beg_pos); 3365 for_scope->set_start_position(scanner()->location().beg_pos);
3361 bool is_let_identifier_expression = false; 3366 bool is_let_identifier_expression = false;
3362 if (peek() != Token::SEMICOLON) { 3367 if (peek() != Token::SEMICOLON) {
3363 if (peek() == Token::VAR || 3368 if (peek() == Token::VAR ||
3364 (peek() == Token::CONST && is_sloppy(language_mode()))) { 3369 (peek() == Token::CONST && is_sloppy(language_mode()))) {
3365 const AstRawString* name = NULL; 3370 const AstRawString* name = NULL;
3366 VariableDeclarationProperties decl_props = kHasNoInitializers; 3371 VariableDeclarationProperties decl_props = kHasNoInitializers;
3372 Scanner::Location first_initializer_loc = Scanner::Location::invalid();
3367 Block* variable_statement = 3373 Block* variable_statement =
3368 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, 3374 ParseVariableDeclarations(kForStatement, &decl_props, nullptr, &name,
3369 CHECK_OK); 3375 &first_initializer_loc, CHECK_OK);
3370 bool accept_OF = decl_props == kHasNoInitializers; 3376 bool accept_OF = true;
3371 ForEachStatement::VisitMode mode; 3377 ForEachStatement::VisitMode mode;
3372 int each_beg_pos = scanner()->location().beg_pos; 3378 int each_beg_pos = scanner()->location().beg_pos;
3373 int each_end_pos = scanner()->location().end_pos; 3379 int each_end_pos = scanner()->location().end_pos;
3374 3380
3375 if (name != NULL && CheckInOrOf(accept_OF, &mode, ok)) { 3381 if (name != NULL && CheckInOrOf(accept_OF, &mode, ok)) {
3376 if (!*ok) return nullptr; 3382 if (!*ok) return nullptr;
3383 if (first_initializer_loc.IsValid() &&
3384 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) {
3385 if (mode == ForEachStatement::ITERATE) {
3386 ReportMessageAt(first_initializer_loc, "for_of_loop_initializer");
3387 } else {
3388 // TODO(caitp): This should be an error in sloppy mode too.
3389 ReportMessageAt(first_initializer_loc, "for_in_loop_initializer");
3390 }
3391 *ok = false;
3392 return nullptr;
3393 }
3377 ForEachStatement* loop = 3394 ForEachStatement* loop =
3378 factory()->NewForEachStatement(mode, labels, stmt_pos); 3395 factory()->NewForEachStatement(mode, labels, stmt_pos);
3379 Target target(&this->target_stack_, loop); 3396 Target target(&this->target_stack_, loop);
3380 3397
3381 Expression* enumerable = ParseExpression(true, CHECK_OK); 3398 Expression* enumerable = ParseExpression(true, CHECK_OK);
3382 Expect(Token::RPAREN, CHECK_OK); 3399 Expect(Token::RPAREN, CHECK_OK);
3383 3400
3384 VariableProxy* each = 3401 VariableProxy* each =
3385 scope_->NewUnresolved(factory(), name, each_beg_pos, each_end_pos); 3402 scope_->NewUnresolved(factory(), name, each_beg_pos, each_end_pos);
3386 Statement* body = ParseSubStatement(NULL, CHECK_OK); 3403 Statement* body = ParseSubStatement(NULL, CHECK_OK);
3387 InitializeForEachStatement(loop, each, enumerable, body); 3404 InitializeForEachStatement(loop, each, enumerable, body);
3388 Block* result = 3405 Block* result =
3389 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); 3406 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
3390 result->AddStatement(variable_statement, zone()); 3407 result->AddStatement(variable_statement, zone());
3391 result->AddStatement(loop, zone()); 3408 result->AddStatement(loop, zone());
3392 scope_ = saved_scope; 3409 scope_ = saved_scope;
3393 for_scope->set_end_position(scanner()->location().end_pos); 3410 for_scope->set_end_position(scanner()->location().end_pos);
3394 for_scope = for_scope->FinalizeBlockScope(); 3411 for_scope = for_scope->FinalizeBlockScope();
3395 DCHECK(for_scope == NULL); 3412 DCHECK(for_scope == NULL);
3396 // Parsed for-in loop w/ variable/const declaration. 3413 // Parsed for-in loop w/ variable/const declaration.
3397 return result; 3414 return result;
3398 } else { 3415 } else {
3399 init = variable_statement; 3416 init = variable_statement;
3400 } 3417 }
3401 } else if ((peek() == Token::LET || peek() == Token::CONST) && 3418 } else if ((peek() == Token::LET || peek() == Token::CONST) &&
3402 is_strict(language_mode())) { 3419 is_strict(language_mode())) {
3403 is_const = peek() == Token::CONST; 3420 is_const = peek() == Token::CONST;
3404 const AstRawString* name = NULL; 3421 const AstRawString* name = NULL;
3405 VariableDeclarationProperties decl_props = kHasNoInitializers; 3422 VariableDeclarationProperties decl_props = kHasNoInitializers;
3406 Block* variable_statement = 3423 Scanner::Location first_initializer_loc = Scanner::Location::invalid();
3407 ParseVariableDeclarations(kForStatement, &decl_props, 3424 Block* variable_statement = ParseVariableDeclarations(
3408 &lexical_bindings, &name, CHECK_OK); 3425 kForStatement, &decl_props, &lexical_bindings, &name,
3409 bool accept_IN = name != NULL && decl_props != kHasInitializers; 3426 &first_initializer_loc, CHECK_OK);
3410 bool accept_OF = decl_props == kHasNoInitializers; 3427 bool accept_IN = name != NULL;
3428 bool accept_OF = true;
3411 ForEachStatement::VisitMode mode; 3429 ForEachStatement::VisitMode mode;
3412 int each_beg_pos = scanner()->location().beg_pos; 3430 int each_beg_pos = scanner()->location().beg_pos;
3413 int each_end_pos = scanner()->location().end_pos; 3431 int each_end_pos = scanner()->location().end_pos;
3414 3432
3415 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { 3433 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) {
3416 if (!*ok) return nullptr; 3434 if (!*ok) return nullptr;
3417 3435 if (first_initializer_loc.IsValid() &&
3436 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) {
3437 if (mode == ForEachStatement::ITERATE) {
3438 ReportMessageAt(first_initializer_loc, "for_of_loop_initializer");
3439 } else {
3440 ReportMessageAt(first_initializer_loc, "for_in_loop_initializer");
3441 }
3442 *ok = false;
3443 return nullptr;
3444 }
3418 // Rewrite a for-in statement of the form 3445 // Rewrite a for-in statement of the form
3419 // 3446 //
3420 // for (let/const x in e) b 3447 // for (let/const x in e) b
3421 // 3448 //
3422 // into 3449 // into
3423 // 3450 //
3424 // <let x' be a temporary variable> 3451 // <let x' be a temporary variable>
3425 // for (x' in e) { 3452 // for (x' in e) {
3426 // let/const x; 3453 // let/const x;
3427 // x = x'; 3454 // x = x';
(...skipping 2129 matching lines...) Expand 10 before | Expand all | Expand 10 after
5557 } else { 5584 } else {
5558 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); 5585 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
5559 running_hash = StringHasher::ComputeRunningHash(running_hash, data, 5586 running_hash = StringHasher::ComputeRunningHash(running_hash, data,
5560 raw_string->length()); 5587 raw_string->length());
5561 } 5588 }
5562 } 5589 }
5563 5590
5564 return running_hash; 5591 return running_hash;
5565 } 5592 }
5566 } } // namespace v8::internal 5593 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | src/preparser.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698