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 return factory()->NewEmptyStatement(RelocInfo::kNoPosition); | 2220 return factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2280 is_strong(language_mode()) ? Token::INIT_CONST : Token::INIT_LET; | 2280 is_strong(language_mode()) ? Token::INIT_CONST : Token::INIT_LET; |
2281 Assignment* assignment = factory()->NewAssignment(init_op, proxy, value, pos); | 2281 Assignment* assignment = factory()->NewAssignment(init_op, proxy, value, pos); |
2282 Statement* assignment_statement = | 2282 Statement* assignment_statement = |
2283 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | 2283 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
2284 if (names) names->Add(name, zone()); | 2284 if (names) names->Add(name, zone()); |
2285 return assignment_statement; | 2285 return assignment_statement; |
2286 } | 2286 } |
2287 | 2287 |
2288 | 2288 |
2289 Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) { | 2289 Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) { |
2290 if (is_strict(language_mode())) { | 2290 if (is_strict(language_mode()) || allow_harmony_sloppy()) { |
2291 return ParseScopedBlock(labels, ok); | 2291 return ParseScopedBlock(labels, ok); |
2292 } | 2292 } |
2293 | 2293 |
2294 // Block :: | 2294 // Block :: |
2295 // '{' Statement* '}' | 2295 // '{' Statement* '}' |
2296 | 2296 |
2297 // Note that a Block does not introduce a new execution scope! | 2297 // Note that a Block does not introduce a new execution scope! |
2298 // (ECMA-262, 3rd, 12.2) | 2298 // (ECMA-262, 3rd, 12.2) |
2299 // | 2299 // |
2300 // Construct block expecting 16 statements. | 2300 // Construct block expecting 16 statements. |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2432 return; | 2432 return; |
2433 } | 2433 } |
2434 Consume(Token::VAR); | 2434 Consume(Token::VAR); |
2435 } else if (peek() == Token::CONST && allow_const()) { | 2435 } else if (peek() == Token::CONST && allow_const()) { |
2436 Consume(Token::CONST); | 2436 Consume(Token::CONST); |
2437 if (is_sloppy(language_mode()) && allow_legacy_const()) { | 2437 if (is_sloppy(language_mode()) && allow_legacy_const()) { |
2438 parsing_result->descriptor.mode = CONST_LEGACY; | 2438 parsing_result->descriptor.mode = CONST_LEGACY; |
2439 parsing_result->descriptor.init_op = Token::INIT_CONST_LEGACY; | 2439 parsing_result->descriptor.init_op = Token::INIT_CONST_LEGACY; |
2440 ++use_counts_[v8::Isolate::kLegacyConst]; | 2440 ++use_counts_[v8::Isolate::kLegacyConst]; |
2441 } else { | 2441 } else { |
2442 DCHECK(is_strict(language_mode())); | 2442 DCHECK(is_strict(language_mode()) || allow_harmony_sloppy()); |
2443 DCHECK(var_context != kStatement); | 2443 DCHECK(var_context != kStatement); |
2444 parsing_result->descriptor.mode = CONST; | 2444 parsing_result->descriptor.mode = CONST; |
2445 parsing_result->descriptor.init_op = Token::INIT_CONST; | 2445 parsing_result->descriptor.init_op = Token::INIT_CONST; |
2446 } | 2446 } |
2447 parsing_result->descriptor.is_const = true; | 2447 parsing_result->descriptor.is_const = true; |
2448 parsing_result->descriptor.needs_init = true; | 2448 parsing_result->descriptor.needs_init = true; |
2449 } else if (peek() == Token::LET && is_strict(language_mode())) { | 2449 } else if (peek() == Token::LET && allow_let()) { |
2450 Consume(Token::LET); | 2450 Consume(Token::LET); |
2451 DCHECK(var_context != kStatement); | 2451 DCHECK(var_context != kStatement); |
2452 parsing_result->descriptor.mode = LET; | 2452 parsing_result->descriptor.mode = LET; |
2453 parsing_result->descriptor.needs_init = true; | 2453 parsing_result->descriptor.needs_init = true; |
2454 parsing_result->descriptor.init_op = Token::INIT_LET; | 2454 parsing_result->descriptor.init_op = Token::INIT_LET; |
2455 } else { | 2455 } else { |
2456 UNREACHABLE(); // by current callers | 2456 UNREACHABLE(); // by current callers |
2457 } | 2457 } |
2458 | 2458 |
2459 parsing_result->descriptor.declaration_scope = | 2459 parsing_result->descriptor.declaration_scope = |
(...skipping 1031 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3491 Scope* saved_scope = scope_; | 3491 Scope* saved_scope = scope_; |
3492 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); | 3492 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); |
3493 scope_ = for_scope; | 3493 scope_ = for_scope; |
3494 Expect(Token::FOR, CHECK_OK); | 3494 Expect(Token::FOR, CHECK_OK); |
3495 Expect(Token::LPAREN, CHECK_OK); | 3495 Expect(Token::LPAREN, CHECK_OK); |
3496 for_scope->set_start_position(scanner()->location().beg_pos); | 3496 for_scope->set_start_position(scanner()->location().beg_pos); |
3497 bool is_let_identifier_expression = false; | 3497 bool is_let_identifier_expression = false; |
3498 DeclarationParsingResult parsing_result; | 3498 DeclarationParsingResult parsing_result; |
3499 if (peek() != Token::SEMICOLON) { | 3499 if (peek() != Token::SEMICOLON) { |
3500 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) || | 3500 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) || |
3501 (peek() == Token::LET && is_strict(language_mode()))) { | 3501 (peek() == Token::LET && allow_let())) { |
3502 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); | 3502 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); |
3503 is_const = parsing_result.descriptor.mode == CONST; | 3503 is_const = parsing_result.descriptor.mode == CONST; |
3504 | 3504 |
3505 int num_decl = parsing_result.declarations.length(); | 3505 int num_decl = parsing_result.declarations.length(); |
3506 bool accept_IN = num_decl >= 1; | 3506 bool accept_IN = num_decl >= 1; |
3507 bool accept_OF = true; | 3507 bool accept_OF = true; |
3508 ForEachStatement::VisitMode mode; | 3508 ForEachStatement::VisitMode mode; |
3509 int each_beg_pos = scanner()->location().beg_pos; | 3509 int each_beg_pos = scanner()->location().beg_pos; |
3510 int each_end_pos = scanner()->location().end_pos; | 3510 int each_end_pos = scanner()->location().end_pos; |
3511 | 3511 |
(...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 | 3966 // in all normal cases, function declarations are fully hoisted to a |
3967 // declaration scope and compiled relative to that. | 3967 // declaration scope and compiled relative to that. |
3968 // - (2) is the case iff the current declaration scope is still the original | 3968 // - (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 | 3969 // 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 | 3970 // compiling a function in an inner declaration scope in the eval, e.g. a |
3971 // nested function, and hoisting works normally relative to that. | 3971 // nested function, and hoisting works normally relative to that. |
3972 Scope* declaration_scope = scope_->DeclarationScope(); | 3972 Scope* declaration_scope = scope_->DeclarationScope(); |
3973 Scope* original_declaration_scope = original_scope_->DeclarationScope(); | 3973 Scope* original_declaration_scope = original_scope_->DeclarationScope(); |
3974 Scope* scope = function_type == FunctionLiteral::DECLARATION && | 3974 Scope* scope = function_type == FunctionLiteral::DECLARATION && |
3975 is_sloppy(language_mode()) && | 3975 is_sloppy(language_mode()) && |
| 3976 !allow_harmony_sloppy() && |
3976 (original_scope_ == original_declaration_scope || | 3977 (original_scope_ == original_declaration_scope || |
3977 declaration_scope != original_declaration_scope) | 3978 declaration_scope != original_declaration_scope) |
3978 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind) | 3979 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind) |
3979 : NewScope(scope_, FUNCTION_SCOPE, kind); | 3980 : NewScope(scope_, FUNCTION_SCOPE, kind); |
3980 ZoneList<Statement*>* body = NULL; | 3981 ZoneList<Statement*>* body = NULL; |
3981 int materialized_literal_count = -1; | 3982 int materialized_literal_count = -1; |
3982 int expected_property_count = -1; | 3983 int expected_property_count = -1; |
3983 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | 3984 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
3984 ExpressionClassifier formals_classifier(&duplicate_finder); | 3985 ExpressionClassifier formals_classifier(&duplicate_finder); |
3985 FunctionLiteral::EagerCompileHint eager_compile_hint = | 3986 FunctionLiteral::EagerCompileHint eager_compile_hint = |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4023 | 4024 |
4024 // If we have a named function expression, we add a local variable | 4025 // 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 | 4026 // declaration to the body of the function with the name of the |
4026 // function and let it refer to the function itself (closure). | 4027 // function and let it refer to the function itself (closure). |
4027 // NOTE: We create a proxy and resolve it here so that in the | 4028 // 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 | 4029 // future we can change the AST to only refer to VariableProxies |
4029 // instead of Variables and Proxis as is the case now. | 4030 // instead of Variables and Proxis as is the case now. |
4030 Variable* fvar = NULL; | 4031 Variable* fvar = NULL; |
4031 Token::Value fvar_init_op = Token::INIT_CONST_LEGACY; | 4032 Token::Value fvar_init_op = Token::INIT_CONST_LEGACY; |
4032 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { | 4033 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { |
4033 if (is_strict(language_mode())) { | 4034 bool use_strict_const = is_strict(language_mode()) || |
| 4035 (!allow_legacy_const() && allow_harmony_sloppy()); |
| 4036 if (use_strict_const) { |
4034 fvar_init_op = Token::INIT_CONST; | 4037 fvar_init_op = Token::INIT_CONST; |
4035 } | 4038 } |
4036 VariableMode fvar_mode = | 4039 VariableMode fvar_mode = use_strict_const ? CONST : CONST_LEGACY; |
4037 is_strict(language_mode()) ? CONST : CONST_LEGACY; | |
4038 DCHECK(function_name != NULL); | 4040 DCHECK(function_name != NULL); |
4039 fvar = new (zone()) | 4041 fvar = new (zone()) |
4040 Variable(scope_, function_name, fvar_mode, Variable::NORMAL, | 4042 Variable(scope_, function_name, fvar_mode, Variable::NORMAL, |
4041 kCreatedInitialized, kNotAssigned); | 4043 kCreatedInitialized, kNotAssigned); |
4042 VariableProxy* proxy = factory()->NewVariableProxy(fvar); | 4044 VariableProxy* proxy = factory()->NewVariableProxy(fvar); |
4043 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration( | 4045 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration( |
4044 proxy, fvar_mode, scope_, RelocInfo::kNoPosition); | 4046 proxy, fvar_mode, scope_, RelocInfo::kNoPosition); |
4045 scope_->DeclareFunctionVar(fvar_declaration); | 4047 scope_->DeclareFunctionVar(fvar_declaration); |
4046 } | 4048 } |
4047 | 4049 |
(...skipping 1894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5942 Expression* Parser::SpreadCallNew(Expression* function, | 5944 Expression* Parser::SpreadCallNew(Expression* function, |
5943 ZoneList<v8::internal::Expression*>* args, | 5945 ZoneList<v8::internal::Expression*>* args, |
5944 int pos) { | 5946 int pos) { |
5945 args->InsertAt(0, function, zone()); | 5947 args->InsertAt(0, function, zone()); |
5946 | 5948 |
5947 return factory()->NewCallRuntime( | 5949 return factory()->NewCallRuntime( |
5948 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 5950 ast_value_factory()->reflect_construct_string(), NULL, args, pos); |
5949 } | 5951 } |
5950 } // namespace internal | 5952 } // namespace internal |
5951 } // namespace v8 | 5953 } // namespace v8 |
OLD | NEW |