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, 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |