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 2199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 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)) { | |
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 Loading... | |
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 |
OLD | NEW |