Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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, nullptr, names, |
| 2222 ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK); | 2222 &ignore, 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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)) { | |
|
arv (Not doing code reviews)
2015/03/31 14:39:15
Add a TODO that this should be an error in sloppy
| |
| 3385 if (mode == ForEachStatement::ITERATE) { | |
| 3386 ReportMessageAt(first_initializer_loc, "for_of_loop_initializer"); | |
| 3387 } else { | |
| 3388 ReportMessageAt(first_initializer_loc, "for_in_loop_initializer"); | |
| 3389 } | |
| 3390 *ok = false; | |
| 3391 return nullptr; | |
| 3392 } | |
| 3377 ForEachStatement* loop = | 3393 ForEachStatement* loop = |
| 3378 factory()->NewForEachStatement(mode, labels, stmt_pos); | 3394 factory()->NewForEachStatement(mode, labels, stmt_pos); |
| 3379 Target target(&this->target_stack_, loop); | 3395 Target target(&this->target_stack_, loop); |
| 3380 | 3396 |
| 3381 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3397 Expression* enumerable = ParseExpression(true, CHECK_OK); |
| 3382 Expect(Token::RPAREN, CHECK_OK); | 3398 Expect(Token::RPAREN, CHECK_OK); |
| 3383 | 3399 |
| 3384 VariableProxy* each = | 3400 VariableProxy* each = |
| 3385 scope_->NewUnresolved(factory(), name, each_beg_pos, each_end_pos); | 3401 scope_->NewUnresolved(factory(), name, each_beg_pos, each_end_pos); |
| 3386 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3402 Statement* body = ParseSubStatement(NULL, CHECK_OK); |
| 3387 InitializeForEachStatement(loop, each, enumerable, body); | 3403 InitializeForEachStatement(loop, each, enumerable, body); |
| 3388 Block* result = | 3404 Block* result = |
| 3389 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); | 3405 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); |
| 3390 result->AddStatement(variable_statement, zone()); | 3406 result->AddStatement(variable_statement, zone()); |
| 3391 result->AddStatement(loop, zone()); | 3407 result->AddStatement(loop, zone()); |
| 3392 scope_ = saved_scope; | 3408 scope_ = saved_scope; |
| 3393 for_scope->set_end_position(scanner()->location().end_pos); | 3409 for_scope->set_end_position(scanner()->location().end_pos); |
| 3394 for_scope = for_scope->FinalizeBlockScope(); | 3410 for_scope = for_scope->FinalizeBlockScope(); |
| 3395 DCHECK(for_scope == NULL); | 3411 DCHECK(for_scope == NULL); |
| 3396 // Parsed for-in loop w/ variable/const declaration. | 3412 // Parsed for-in loop w/ variable/const declaration. |
| 3397 return result; | 3413 return result; |
| 3398 } else { | 3414 } else { |
| 3399 init = variable_statement; | 3415 init = variable_statement; |
| 3400 } | 3416 } |
| 3401 } else if ((peek() == Token::LET || peek() == Token::CONST) && | 3417 } else if ((peek() == Token::LET || peek() == Token::CONST) && |
| 3402 is_strict(language_mode())) { | 3418 is_strict(language_mode())) { |
| 3403 is_const = peek() == Token::CONST; | 3419 is_const = peek() == Token::CONST; |
| 3404 const AstRawString* name = NULL; | 3420 const AstRawString* name = NULL; |
| 3405 VariableDeclarationProperties decl_props = kHasNoInitializers; | 3421 VariableDeclarationProperties decl_props = kHasNoInitializers; |
| 3406 Block* variable_statement = | 3422 Scanner::Location first_initializer_loc = Scanner::Location::invalid(); |
| 3407 ParseVariableDeclarations(kForStatement, &decl_props, | 3423 Block* variable_statement = ParseVariableDeclarations( |
| 3408 &lexical_bindings, &name, CHECK_OK); | 3424 kForStatement, &decl_props, &lexical_bindings, &name, |
| 3409 bool accept_IN = name != NULL && decl_props != kHasInitializers; | 3425 &first_initializer_loc, CHECK_OK); |
| 3410 bool accept_OF = decl_props == kHasNoInitializers; | 3426 bool accept_IN = name != NULL; |
| 3427 bool accept_OF = true; | |
| 3411 ForEachStatement::VisitMode mode; | 3428 ForEachStatement::VisitMode mode; |
| 3412 int each_beg_pos = scanner()->location().beg_pos; | 3429 int each_beg_pos = scanner()->location().beg_pos; |
| 3413 int each_end_pos = scanner()->location().end_pos; | 3430 int each_end_pos = scanner()->location().end_pos; |
| 3414 | 3431 |
| 3415 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { | 3432 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { |
| 3416 if (!*ok) return nullptr; | 3433 if (!*ok) return nullptr; |
| 3417 | 3434 if (first_initializer_loc.IsValid() && |
| 3435 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) { | |
| 3436 if (mode == ForEachStatement::ITERATE) { | |
| 3437 ReportMessageAt(first_initializer_loc, "for_of_loop_initializer"); | |
| 3438 } else { | |
| 3439 ReportMessageAt(first_initializer_loc, "for_in_loop_initializer"); | |
| 3440 } | |
| 3441 *ok = false; | |
| 3442 return nullptr; | |
| 3443 } | |
| 3418 // Rewrite a for-in statement of the form | 3444 // Rewrite a for-in statement of the form |
| 3419 // | 3445 // |
| 3420 // for (let/const x in e) b | 3446 // for (let/const x in e) b |
| 3421 // | 3447 // |
| 3422 // into | 3448 // into |
| 3423 // | 3449 // |
| 3424 // <let x' be a temporary variable> | 3450 // <let x' be a temporary variable> |
| 3425 // for (x' in e) { | 3451 // for (x' in e) { |
| 3426 // let/const x; | 3452 // let/const x; |
| 3427 // x = x'; | 3453 // x = x'; |
| (...skipping 2131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5559 } else { | 5585 } else { |
| 5560 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); | 5586 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); |
| 5561 running_hash = StringHasher::ComputeRunningHash(running_hash, data, | 5587 running_hash = StringHasher::ComputeRunningHash(running_hash, data, |
| 5562 raw_string->length()); | 5588 raw_string->length()); |
| 5563 } | 5589 } |
| 5564 } | 5590 } |
| 5565 | 5591 |
| 5566 return running_hash; | 5592 return running_hash; |
| 5567 } | 5593 } |
| 5568 } } // namespace v8::internal | 5594 } } // namespace v8::internal |
| OLD | NEW |