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/ast-literal-reindexer.h" | 9 #include "src/ast-literal-reindexer.h" |
10 #include "src/bailout-reason.h" | 10 #include "src/bailout-reason.h" |
(...skipping 1369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1380 } | 1380 } |
1381 return ParseClassDeclaration(NULL, ok); | 1381 return ParseClassDeclaration(NULL, ok); |
1382 case Token::CONST: | 1382 case Token::CONST: |
1383 if (allow_const()) { | 1383 if (allow_const()) { |
1384 return ParseVariableStatement(kStatementListItem, NULL, ok); | 1384 return ParseVariableStatement(kStatementListItem, NULL, ok); |
1385 } | 1385 } |
1386 break; | 1386 break; |
1387 case Token::VAR: | 1387 case Token::VAR: |
1388 return ParseVariableStatement(kStatementListItem, NULL, ok); | 1388 return ParseVariableStatement(kStatementListItem, NULL, ok); |
1389 case Token::LET: | 1389 case Token::LET: |
1390 if (is_strict(language_mode())) { | 1390 if (allow_let()) { |
1391 return ParseVariableStatement(kStatementListItem, NULL, ok); | 1391 return ParseVariableStatement(kStatementListItem, NULL, ok); |
1392 } | 1392 } |
1393 break; | 1393 break; |
1394 default: | 1394 default: |
1395 break; | 1395 break; |
1396 } | 1396 } |
1397 return ParseStatement(NULL, ok); | 1397 return ParseStatement(NULL, ok); |
1398 } | 1398 } |
1399 | 1399 |
1400 | 1400 |
(...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2042 // functions. The function CheckConflictingVarDeclarations checks for | 2042 // functions. The function CheckConflictingVarDeclarations checks for |
2043 // var and let bindings from different scopes whereas this is a check for | 2043 // var and let bindings from different scopes whereas this is a check for |
2044 // conflicting declarations within the same scope. This check also covers | 2044 // conflicting declarations within the same scope. This check also covers |
2045 // the special case | 2045 // the special case |
2046 // | 2046 // |
2047 // function () { let x; { var x; } } | 2047 // function () { let x; { var x; } } |
2048 // | 2048 // |
2049 // because the var declaration is hoisted to the function scope where 'x' | 2049 // because the var declaration is hoisted to the function scope where 'x' |
2050 // is already bound. | 2050 // is already bound. |
2051 DCHECK(IsDeclaredVariableMode(var->mode())); | 2051 DCHECK(IsDeclaredVariableMode(var->mode())); |
2052 if (is_strict(language_mode())) { | 2052 if (is_strict(language_mode()) || allow_harmony_sloppy()) { |
2053 // In harmony we treat re-declarations as early errors. See | 2053 // In harmony we treat re-declarations as early errors. See |
2054 // ES5 16 for a definition of early errors. | 2054 // ES5 16 for a definition of early errors. |
2055 if (declaration_kind == DeclarationDescriptor::NORMAL) { | 2055 if (declaration_kind == DeclarationDescriptor::NORMAL) { |
2056 ParserTraits::ReportMessage(MessageTemplate::kVarRedeclaration, name); | 2056 ParserTraits::ReportMessage(MessageTemplate::kVarRedeclaration, name); |
2057 } else { | 2057 } else { |
2058 ParserTraits::ReportMessage(MessageTemplate::kStrictParamDupe); | 2058 ParserTraits::ReportMessage(MessageTemplate::kStrictParamDupe); |
2059 } | 2059 } |
2060 *ok = false; | 2060 *ok = false; |
2061 return nullptr; | 2061 return nullptr; |
2062 } | 2062 } |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2200 pos, FunctionLiteral::DECLARATION, | 2200 pos, FunctionLiteral::DECLARATION, |
2201 FunctionLiteral::NORMAL_ARITY, CHECK_OK); | 2201 FunctionLiteral::NORMAL_ARITY, CHECK_OK); |
2202 // Even if we're not at the top-level of the global or a function | 2202 // Even if we're not at the top-level of the global or a function |
2203 // scope, we treat it as such and introduce the function with its | 2203 // scope, we treat it as such and introduce the function with its |
2204 // initial value upon entering the corresponding scope. | 2204 // initial value upon entering the corresponding scope. |
2205 // In ES6, a function behaves as a lexical binding, except in | 2205 // In ES6, a function behaves as a lexical binding, except in |
2206 // a script scope, or the initial scope of eval or another function. | 2206 // a script scope, or the initial scope of eval or another function. |
2207 VariableMode mode = | 2207 VariableMode mode = |
2208 is_strong(language_mode()) | 2208 is_strong(language_mode()) |
2209 ? CONST | 2209 ? CONST |
2210 : is_strict(language_mode()) && | 2210 : (is_strict(language_mode()) || allow_harmony_sloppy()) && |
2211 !(scope_->is_script_scope() || scope_->is_eval_scope() || | 2211 !(scope_->is_script_scope() || scope_->is_eval_scope() || |
2212 scope_->is_function_scope()) | 2212 scope_->is_function_scope()) |
2213 ? LET | 2213 ? LET |
2214 : VAR; | 2214 : VAR; |
2215 VariableProxy* proxy = NewUnresolved(name, mode); | 2215 VariableProxy* proxy = NewUnresolved(name, mode); |
2216 Declaration* declaration = | 2216 Declaration* declaration = |
2217 factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos); | 2217 factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos); |
2218 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); | 2218 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); |
2219 if (names) names->Add(name, zone()); | 2219 if (names) names->Add(name, zone()); |
| 2220 |
| 2221 // In ES'15 sloppy mode inside a block a let binding and a var binding are |
| 2222 // created. |
| 2223 // TODO(arv): A var binding should only be created if it does not introduce a |
| 2224 // conflict. |
| 2225 // if (allow_harmony_sloppy() && !is_strict(language_mode()) && |
| 2226 // !(scope_->is_script_scope() || scope_->is_eval_scope() || |
| 2227 // scope_->is_function_scope())) { |
| 2228 // Declaration* declaration = |
| 2229 // factory()->NewFunctionDeclaration(proxy, VAR, fun, scope_, pos); |
| 2230 // Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); |
| 2231 // } |
| 2232 |
2220 return factory()->NewEmptyStatement(RelocInfo::kNoPosition); | 2233 return factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
2221 } | 2234 } |
2222 | 2235 |
2223 | 2236 |
2224 Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, | 2237 Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, |
2225 bool* ok) { | 2238 bool* ok) { |
2226 // ClassDeclaration :: | 2239 // ClassDeclaration :: |
2227 // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}' | 2240 // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}' |
2228 // | 2241 // |
2229 // A ClassDeclaration | 2242 // A ClassDeclaration |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2280 is_strong(language_mode()) ? Token::INIT_CONST : Token::INIT_LET; | 2293 is_strong(language_mode()) ? Token::INIT_CONST : Token::INIT_LET; |
2281 Assignment* assignment = factory()->NewAssignment(init_op, proxy, value, pos); | 2294 Assignment* assignment = factory()->NewAssignment(init_op, proxy, value, pos); |
2282 Statement* assignment_statement = | 2295 Statement* assignment_statement = |
2283 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | 2296 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
2284 if (names) names->Add(name, zone()); | 2297 if (names) names->Add(name, zone()); |
2285 return assignment_statement; | 2298 return assignment_statement; |
2286 } | 2299 } |
2287 | 2300 |
2288 | 2301 |
2289 Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) { | 2302 Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) { |
2290 if (is_strict(language_mode())) { | 2303 if (is_strict(language_mode()) || allow_harmony_sloppy()) { |
2291 return ParseScopedBlock(labels, ok); | 2304 return ParseScopedBlock(labels, ok); |
2292 } | 2305 } |
2293 | 2306 |
2294 // Block :: | 2307 // Block :: |
2295 // '{' Statement* '}' | 2308 // '{' Statement* '}' |
2296 | 2309 |
2297 // Note that a Block does not introduce a new execution scope! | 2310 // Note that a Block does not introduce a new execution scope! |
2298 // (ECMA-262, 3rd, 12.2) | 2311 // (ECMA-262, 3rd, 12.2) |
2299 // | 2312 // |
2300 // Construct block expecting 16 statements. | 2313 // Construct block expecting 16 statements. |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2432 return; | 2445 return; |
2433 } | 2446 } |
2434 Consume(Token::VAR); | 2447 Consume(Token::VAR); |
2435 } else if (peek() == Token::CONST && allow_const()) { | 2448 } else if (peek() == Token::CONST && allow_const()) { |
2436 Consume(Token::CONST); | 2449 Consume(Token::CONST); |
2437 if (is_sloppy(language_mode()) && allow_legacy_const()) { | 2450 if (is_sloppy(language_mode()) && allow_legacy_const()) { |
2438 parsing_result->descriptor.mode = CONST_LEGACY; | 2451 parsing_result->descriptor.mode = CONST_LEGACY; |
2439 parsing_result->descriptor.init_op = Token::INIT_CONST_LEGACY; | 2452 parsing_result->descriptor.init_op = Token::INIT_CONST_LEGACY; |
2440 ++use_counts_[v8::Isolate::kLegacyConst]; | 2453 ++use_counts_[v8::Isolate::kLegacyConst]; |
2441 } else { | 2454 } else { |
2442 DCHECK(is_strict(language_mode())); | 2455 DCHECK(is_strict(language_mode()) || allow_harmony_sloppy()); |
2443 DCHECK(var_context != kStatement); | 2456 DCHECK(var_context != kStatement); |
2444 parsing_result->descriptor.mode = CONST; | 2457 parsing_result->descriptor.mode = CONST; |
2445 parsing_result->descriptor.init_op = Token::INIT_CONST; | 2458 parsing_result->descriptor.init_op = Token::INIT_CONST; |
2446 } | 2459 } |
2447 parsing_result->descriptor.is_const = true; | 2460 parsing_result->descriptor.is_const = true; |
2448 parsing_result->descriptor.needs_init = true; | 2461 parsing_result->descriptor.needs_init = true; |
2449 } else if (peek() == Token::LET && is_strict(language_mode())) { | 2462 } else if (peek() == Token::LET && allow_let()) { |
2450 Consume(Token::LET); | 2463 Consume(Token::LET); |
2451 DCHECK(var_context != kStatement); | 2464 DCHECK(var_context != kStatement); |
2452 parsing_result->descriptor.mode = LET; | 2465 parsing_result->descriptor.mode = LET; |
2453 parsing_result->descriptor.needs_init = true; | 2466 parsing_result->descriptor.needs_init = true; |
2454 parsing_result->descriptor.init_op = Token::INIT_LET; | 2467 parsing_result->descriptor.init_op = Token::INIT_LET; |
2455 } else { | 2468 } else { |
2456 UNREACHABLE(); // by current callers | 2469 UNREACHABLE(); // by current callers |
2457 } | 2470 } |
2458 | 2471 |
2459 parsing_result->descriptor.declaration_scope = | 2472 parsing_result->descriptor.declaration_scope = |
(...skipping 1031 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3491 Scope* saved_scope = scope_; | 3504 Scope* saved_scope = scope_; |
3492 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); | 3505 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); |
3493 scope_ = for_scope; | 3506 scope_ = for_scope; |
3494 Expect(Token::FOR, CHECK_OK); | 3507 Expect(Token::FOR, CHECK_OK); |
3495 Expect(Token::LPAREN, CHECK_OK); | 3508 Expect(Token::LPAREN, CHECK_OK); |
3496 for_scope->set_start_position(scanner()->location().beg_pos); | 3509 for_scope->set_start_position(scanner()->location().beg_pos); |
3497 bool is_let_identifier_expression = false; | 3510 bool is_let_identifier_expression = false; |
3498 DeclarationParsingResult parsing_result; | 3511 DeclarationParsingResult parsing_result; |
3499 if (peek() != Token::SEMICOLON) { | 3512 if (peek() != Token::SEMICOLON) { |
3500 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) || | 3513 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) || |
3501 (peek() == Token::LET && is_strict(language_mode()))) { | 3514 (peek() == Token::LET && allow_let())) { |
3502 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); | 3515 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); |
3503 is_const = parsing_result.descriptor.mode == CONST; | 3516 is_const = parsing_result.descriptor.mode == CONST; |
3504 | 3517 |
3505 int num_decl = parsing_result.declarations.length(); | 3518 int num_decl = parsing_result.declarations.length(); |
3506 bool accept_IN = num_decl >= 1; | 3519 bool accept_IN = num_decl >= 1; |
3507 bool accept_OF = true; | 3520 bool accept_OF = true; |
3508 ForEachStatement::VisitMode mode; | 3521 ForEachStatement::VisitMode mode; |
3509 int each_beg_pos = scanner()->location().beg_pos; | 3522 int each_beg_pos = scanner()->location().beg_pos; |
3510 int each_end_pos = scanner()->location().end_pos; | 3523 int each_end_pos = scanner()->location().end_pos; |
3511 | 3524 |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3966 // in all normal cases, function declarations are fully hoisted to a | 3979 // in all normal cases, function declarations are fully hoisted to a |
3967 // declaration scope and compiled relative to that. | 3980 // declaration scope and compiled relative to that. |
3968 // - (2) is the case iff the current declaration scope is still the original | 3981 // - (2) is the case iff the current declaration scope is still the original |
3969 // one relative to the deserialized scope chain. Otherwise we must be | 3982 // one relative to the deserialized scope chain. Otherwise we must be |
3970 // compiling a function in an inner declaration scope in the eval, e.g. a | 3983 // compiling a function in an inner declaration scope in the eval, e.g. a |
3971 // nested function, and hoisting works normally relative to that. | 3984 // nested function, and hoisting works normally relative to that. |
3972 Scope* declaration_scope = scope_->DeclarationScope(); | 3985 Scope* declaration_scope = scope_->DeclarationScope(); |
3973 Scope* original_declaration_scope = original_scope_->DeclarationScope(); | 3986 Scope* original_declaration_scope = original_scope_->DeclarationScope(); |
3974 Scope* scope = function_type == FunctionLiteral::DECLARATION && | 3987 Scope* scope = function_type == FunctionLiteral::DECLARATION && |
3975 is_sloppy(language_mode()) && | 3988 is_sloppy(language_mode()) && |
| 3989 !allow_harmony_sloppy() && |
3976 (original_scope_ == original_declaration_scope || | 3990 (original_scope_ == original_declaration_scope || |
3977 declaration_scope != original_declaration_scope) | 3991 declaration_scope != original_declaration_scope) |
3978 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind) | 3992 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind) |
3979 : NewScope(scope_, FUNCTION_SCOPE, kind); | 3993 : NewScope(scope_, FUNCTION_SCOPE, kind); |
3980 ZoneList<Statement*>* body = NULL; | 3994 ZoneList<Statement*>* body = NULL; |
3981 int materialized_literal_count = -1; | 3995 int materialized_literal_count = -1; |
3982 int expected_property_count = -1; | 3996 int expected_property_count = -1; |
3983 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | 3997 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
3984 ExpressionClassifier formals_classifier(&duplicate_finder); | 3998 ExpressionClassifier formals_classifier(&duplicate_finder); |
3985 FunctionLiteral::EagerCompileHint eager_compile_hint = | 3999 FunctionLiteral::EagerCompileHint eager_compile_hint = |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4023 | 4037 |
4024 // If we have a named function expression, we add a local variable | 4038 // If we have a named function expression, we add a local variable |
4025 // declaration to the body of the function with the name of the | 4039 // declaration to the body of the function with the name of the |
4026 // function and let it refer to the function itself (closure). | 4040 // function and let it refer to the function itself (closure). |
4027 // NOTE: We create a proxy and resolve it here so that in the | 4041 // NOTE: We create a proxy and resolve it here so that in the |
4028 // future we can change the AST to only refer to VariableProxies | 4042 // future we can change the AST to only refer to VariableProxies |
4029 // instead of Variables and Proxis as is the case now. | 4043 // instead of Variables and Proxis as is the case now. |
4030 Variable* fvar = NULL; | 4044 Variable* fvar = NULL; |
4031 Token::Value fvar_init_op = Token::INIT_CONST_LEGACY; | 4045 Token::Value fvar_init_op = Token::INIT_CONST_LEGACY; |
4032 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { | 4046 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { |
4033 if (is_strict(language_mode())) { | 4047 bool use_strict_const = is_strict(language_mode()) || |
| 4048 (!allow_legacy_const() && allow_harmony_sloppy()); |
| 4049 if (use_strict_const) { |
4034 fvar_init_op = Token::INIT_CONST; | 4050 fvar_init_op = Token::INIT_CONST; |
4035 } | 4051 } |
4036 VariableMode fvar_mode = | 4052 VariableMode fvar_mode = use_strict_const ? CONST : CONST_LEGACY; |
4037 is_strict(language_mode()) ? CONST : CONST_LEGACY; | |
4038 DCHECK(function_name != NULL); | 4053 DCHECK(function_name != NULL); |
4039 fvar = new (zone()) | 4054 fvar = new (zone()) |
4040 Variable(scope_, function_name, fvar_mode, Variable::NORMAL, | 4055 Variable(scope_, function_name, fvar_mode, Variable::NORMAL, |
4041 kCreatedInitialized, kNotAssigned); | 4056 kCreatedInitialized, kNotAssigned); |
4042 VariableProxy* proxy = factory()->NewVariableProxy(fvar); | 4057 VariableProxy* proxy = factory()->NewVariableProxy(fvar); |
4043 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration( | 4058 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration( |
4044 proxy, fvar_mode, scope_, RelocInfo::kNoPosition); | 4059 proxy, fvar_mode, scope_, RelocInfo::kNoPosition); |
4045 scope_->DeclareFunctionVar(fvar_declaration); | 4060 scope_->DeclareFunctionVar(fvar_declaration); |
4046 } | 4061 } |
4047 | 4062 |
(...skipping 1894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5942 Expression* Parser::SpreadCallNew(Expression* function, | 5957 Expression* Parser::SpreadCallNew(Expression* function, |
5943 ZoneList<v8::internal::Expression*>* args, | 5958 ZoneList<v8::internal::Expression*>* args, |
5944 int pos) { | 5959 int pos) { |
5945 args->InsertAt(0, function, zone()); | 5960 args->InsertAt(0, function, zone()); |
5946 | 5961 |
5947 return factory()->NewCallRuntime( | 5962 return factory()->NewCallRuntime( |
5948 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 5963 ast_value_factory()->reflect_construct_string(), NULL, args, pos); |
5949 } | 5964 } |
5950 } // namespace internal | 5965 } // namespace internal |
5951 } // namespace v8 | 5966 } // namespace v8 |
OLD | NEW |