| 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/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "src/api.h" | 9 #include "src/api.h" |
| 10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 DCHECK_NULL(cached_parse_data_); | 157 DCHECK_NULL(cached_parse_data_); |
| 158 if (consume_cached_parse_data()) { | 158 if (consume_cached_parse_data()) { |
| 159 if (allow_lazy_) { | 159 if (allow_lazy_) { |
| 160 cached_parse_data_ = ParseData::FromCachedData(*info->cached_data()); | 160 cached_parse_data_ = ParseData::FromCachedData(*info->cached_data()); |
| 161 if (cached_parse_data_ != nullptr) return; | 161 if (cached_parse_data_ != nullptr) return; |
| 162 } | 162 } |
| 163 compile_options_ = ScriptCompiler::kNoCompileOptions; | 163 compile_options_ = ScriptCompiler::kNoCompileOptions; |
| 164 } | 164 } |
| 165 } | 165 } |
| 166 | 166 |
| 167 Expression* Parser::CallClassFieldInitializer(Scope* scope, | |
| 168 Expression* this_expr) { | |
| 169 // This produces the expression | |
| 170 // `.class_field_intializer(this_expr)`, where '.class_field_intializer' is | |
| 171 // the name | |
| 172 // of a synthetic variable. | |
| 173 // 'this_expr' will be 'this' in a base constructor and the result of calling | |
| 174 // 'super' in a derived one. | |
| 175 const AstRawString* init_fn_name = | |
| 176 ast_value_factory()->dot_class_field_init_string(); | |
| 177 VariableProxy* init_fn_proxy = scope->NewUnresolved(factory(), init_fn_name); | |
| 178 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); | |
| 179 args->Add(init_fn_proxy, zone()); | |
| 180 args->Add(this_expr, zone()); | |
| 181 return factory()->NewCallRuntime(Runtime::kInlineCall, args, | |
| 182 kNoSourcePosition); | |
| 183 } | |
| 184 | |
| 185 Expression* Parser::RewriteSuperCall(Expression* super_call) { | |
| 186 // TODO(bakkot) find a way to avoid this for classes without fields. | |
| 187 if (!allow_harmony_class_fields()) { | |
| 188 return super_call; | |
| 189 } | |
| 190 // This turns a super call `super()` into a do expression of the form | |
| 191 // do { | |
| 192 // tmp x = super(); | |
| 193 // if (.class-field-init) | |
| 194 // .class-field-init(x) | |
| 195 // x; // This isn't actually present; our do-expression representation | |
| 196 // allows specifying that the expression returns x directly. | |
| 197 // } | |
| 198 Variable* var_tmp = | |
| 199 scope()->NewTemporary(ast_value_factory()->empty_string()); | |
| 200 Block* block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); | |
| 201 Assignment* assignment = factory()->NewAssignment( | |
| 202 Token::ASSIGN, factory()->NewVariableProxy(var_tmp), super_call, | |
| 203 kNoSourcePosition); | |
| 204 block->statements()->Add( | |
| 205 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone()); | |
| 206 const AstRawString* init_fn_name = | |
| 207 ast_value_factory()->dot_class_field_init_string(); | |
| 208 VariableProxy* init_fn_proxy = | |
| 209 scope()->NewUnresolved(factory(), init_fn_name); | |
| 210 Expression* condition = init_fn_proxy; | |
| 211 Statement* initialize = factory()->NewExpressionStatement( | |
| 212 CallClassFieldInitializer(scope(), factory()->NewVariableProxy(var_tmp)), | |
| 213 kNoSourcePosition); | |
| 214 IfStatement* if_statement = factory()->NewIfStatement( | |
| 215 condition, initialize, factory()->NewEmptyStatement(kNoSourcePosition), | |
| 216 kNoSourcePosition); | |
| 217 block->statements()->Add(if_statement, zone()); | |
| 218 return factory()->NewDoExpression(block, var_tmp, kNoSourcePosition); | |
| 219 } | |
| 220 | |
| 221 FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name, | 167 FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name, |
| 222 bool call_super, | 168 bool call_super, |
| 223 bool requires_class_field_init, | |
| 224 int pos, int end_pos, | 169 int pos, int end_pos, |
| 225 LanguageMode language_mode) { | 170 LanguageMode language_mode) { |
| 226 int materialized_literal_count = -1; | 171 int materialized_literal_count = -1; |
| 227 int expected_property_count = -1; | 172 int expected_property_count = -1; |
| 228 const int parameter_count = 0; | 173 const int parameter_count = 0; |
| 229 if (name == nullptr) name = ast_value_factory()->empty_string(); | 174 if (name == nullptr) name = ast_value_factory()->empty_string(); |
| 230 | 175 |
| 231 FunctionKind kind = call_super ? FunctionKind::kDefaultSubclassConstructor | 176 FunctionKind kind = call_super ? FunctionKind::kDefaultSubclassConstructor |
| 232 : FunctionKind::kDefaultBaseConstructor; | 177 : FunctionKind::kDefaultBaseConstructor; |
| 233 DeclarationScope* function_scope = NewFunctionScope(kind); | 178 DeclarationScope* function_scope = NewFunctionScope(kind); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 expected_property_count = function_state.expected_property_count(); | 213 expected_property_count = function_state.expected_property_count(); |
| 269 } | 214 } |
| 270 | 215 |
| 271 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( | 216 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( |
| 272 name, function_scope, body, materialized_literal_count, | 217 name, function_scope, body, materialized_literal_count, |
| 273 expected_property_count, parameter_count, parameter_count, | 218 expected_property_count, parameter_count, parameter_count, |
| 274 FunctionLiteral::kNoDuplicateParameters, | 219 FunctionLiteral::kNoDuplicateParameters, |
| 275 FunctionLiteral::kAnonymousExpression, default_eager_compile_hint(), pos, | 220 FunctionLiteral::kAnonymousExpression, default_eager_compile_hint(), pos, |
| 276 true, GetNextFunctionLiteralId()); | 221 true, GetNextFunctionLiteralId()); |
| 277 | 222 |
| 278 function_literal->set_requires_class_field_init(requires_class_field_init); | |
| 279 | |
| 280 return function_literal; | 223 return function_literal; |
| 281 } | 224 } |
| 282 | 225 |
| 283 // ---------------------------------------------------------------------------- | 226 // ---------------------------------------------------------------------------- |
| 284 // The CHECK_OK macro is a convenient macro to enforce error | 227 // The CHECK_OK macro is a convenient macro to enforce error |
| 285 // handling for functions that may fail (by returning !*ok). | 228 // handling for functions that may fail (by returning !*ok). |
| 286 // | 229 // |
| 287 // CAUTION: This macro appends extra statements after a call, | 230 // CAUTION: This macro appends extra statements after a call, |
| 288 // thus it must never be used where only a single statement | 231 // thus it must never be used where only a single statement |
| 289 // is correct (e.g. an if statement branch w/o braces)! | 232 // is correct (e.g. an if statement branch w/o braces)! |
| (...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 DCHECK(expression->IsFunctionLiteral()); | 931 DCHECK(expression->IsFunctionLiteral()); |
| 989 result = expression->AsFunctionLiteral(); | 932 result = expression->AsFunctionLiteral(); |
| 990 } else { | 933 } else { |
| 991 ok = false; | 934 ok = false; |
| 992 } | 935 } |
| 993 } | 936 } |
| 994 } | 937 } |
| 995 } else if (IsDefaultConstructor(kind)) { | 938 } else if (IsDefaultConstructor(kind)) { |
| 996 DCHECK_EQ(scope(), outer); | 939 DCHECK_EQ(scope(), outer); |
| 997 bool is_subclass_constructor = IsSubclassConstructor(kind); | 940 bool is_subclass_constructor = IsSubclassConstructor(kind); |
| 998 result = DefaultConstructor( | 941 result = DefaultConstructor(raw_name, is_subclass_constructor, |
| 999 raw_name, is_subclass_constructor, info->requires_class_field_init(), | 942 info->start_position(), info->end_position(), |
| 1000 info->start_position(), info->end_position(), info->language_mode()); | 943 info->language_mode()); |
| 1001 if (!is_subclass_constructor && info->requires_class_field_init()) { | |
| 1002 result = InsertClassFieldInitializer(result); | |
| 1003 } | |
| 1004 } else if (info->is_class_field_initializer()) { | |
| 1005 Handle<SharedFunctionInfo> shared_info = info->shared_info(); | |
| 1006 DCHECK(!shared_info.is_null()); | |
| 1007 if (shared_info->length() == 0) { | |
| 1008 result = ParseClassFieldForInitializer( | |
| 1009 info->start_position() != info->end_position(), &ok); | |
| 1010 } else { | |
| 1011 result = SynthesizeClassFieldInitializer(shared_info->length()); | |
| 1012 } | |
| 1013 } else { | 944 } else { |
| 1014 result = ParseFunctionLiteral( | 945 result = ParseFunctionLiteral( |
| 1015 raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck, kind, | 946 raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck, kind, |
| 1016 kNoSourcePosition, function_type, info->language_mode(), &ok); | 947 kNoSourcePosition, function_type, info->language_mode(), &ok); |
| 1017 if (info->requires_class_field_init()) { | |
| 1018 result = InsertClassFieldInitializer(result); | |
| 1019 } | |
| 1020 } | 948 } |
| 1021 // Make sure the results agree. | 949 // Make sure the results agree. |
| 1022 DCHECK(ok == (result != nullptr)); | 950 DCHECK(ok == (result != nullptr)); |
| 1023 } | 951 } |
| 1024 | 952 |
| 1025 // Make sure the target stack is empty. | 953 // Make sure the target stack is empty. |
| 1026 DCHECK_NULL(target_stack_); | 954 DCHECK_NULL(target_stack_); |
| 1027 DCHECK_IMPLIES(result, | 955 DCHECK_IMPLIES(result, |
| 1028 info->function_literal_id() == result->function_literal_id()); | 956 info->function_literal_id() == result->function_literal_id()); |
| 1029 return result; | 957 return result; |
| (...skipping 2301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3331 } else { | 3259 } else { |
| 3332 statement = factory()->NewEmptyStatement(kNoSourcePosition); | 3260 statement = factory()->NewEmptyStatement(kNoSourcePosition); |
| 3333 } | 3261 } |
| 3334 result->Set(kFunctionNameAssignmentIndex, statement); | 3262 result->Set(kFunctionNameAssignmentIndex, statement); |
| 3335 } | 3263 } |
| 3336 | 3264 |
| 3337 MarkCollectedTailCallExpressions(); | 3265 MarkCollectedTailCallExpressions(); |
| 3338 return result; | 3266 return result; |
| 3339 } | 3267 } |
| 3340 | 3268 |
| 3341 Expression* Parser::InstallHomeObject(Expression* function_literal, | |
| 3342 Expression* home_object) { | |
| 3343 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); | |
| 3344 Variable* result_var = | |
| 3345 scope()->NewTemporary(ast_value_factory()->empty_string()); | |
| 3346 DoExpression* do_expr = | |
| 3347 factory()->NewDoExpression(do_block, result_var, kNoSourcePosition); | |
| 3348 Assignment* init = factory()->NewAssignment( | |
| 3349 Token::ASSIGN, factory()->NewVariableProxy(result_var), function_literal, | |
| 3350 kNoSourcePosition); | |
| 3351 do_block->statements()->Add( | |
| 3352 factory()->NewExpressionStatement(init, kNoSourcePosition), zone()); | |
| 3353 Property* home_object_property = factory()->NewProperty( | |
| 3354 factory()->NewVariableProxy(result_var), | |
| 3355 factory()->NewSymbolLiteral("home_object_symbol", kNoSourcePosition), | |
| 3356 kNoSourcePosition); | |
| 3357 Assignment* assignment = factory()->NewAssignment( | |
| 3358 Token::ASSIGN, home_object_property, home_object, kNoSourcePosition); | |
| 3359 do_block->statements()->Add( | |
| 3360 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone()); | |
| 3361 return do_expr; | |
| 3362 } | |
| 3363 | |
| 3364 const AstRawString* ClassFieldVariableName(bool is_name, | |
| 3365 AstValueFactory* ast_value_factory, | |
| 3366 int index) { | |
| 3367 std::string name = | |
| 3368 ".class-field-" + std::to_string(index) + (is_name ? "-name" : "-func"); | |
| 3369 return ast_value_factory->GetOneByteString(name.c_str()); | |
| 3370 } | |
| 3371 | |
| 3372 FunctionLiteral* Parser::SynthesizeClassFieldInitializer(int count) { | |
| 3373 DCHECK(count > 0); | |
| 3374 // Makes a function which reads the names and initializers for each class | |
| 3375 // field out of deterministically named local variables and sets each property | |
| 3376 // to the result of evaluating its corresponding initializer in turn. | |
| 3377 | |
| 3378 // This produces a function which looks like | |
| 3379 // function () { | |
| 3380 // this[.class-field-0-name] = .class-field-0-func(); | |
| 3381 // this[.class-field-1-name] = .class-field-1-func(); | |
| 3382 // [...] | |
| 3383 // this[.class-field-n-name] = .class-field-n-func(); | |
| 3384 // return this; | |
| 3385 // } | |
| 3386 // except that it performs defineProperty, so that instead of '=' it has | |
| 3387 // %DefineDataPropertyInLiteral(this, .class-field-0-name, | |
| 3388 // .class-field-0-func(), | |
| 3389 // DONT_ENUM, false) | |
| 3390 | |
| 3391 RaiseLanguageMode(STRICT); | |
| 3392 FunctionKind kind = FunctionKind::kConciseMethod; | |
| 3393 DeclarationScope* initializer_scope = NewFunctionScope(kind); | |
| 3394 SetLanguageMode(initializer_scope, language_mode()); | |
| 3395 initializer_scope->set_start_position(scanner()->location().end_pos); | |
| 3396 initializer_scope->set_end_position(scanner()->location().end_pos); | |
| 3397 FunctionState initializer_state(&function_state_, &scope_state_, | |
| 3398 initializer_scope); | |
| 3399 ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(count, zone()); | |
| 3400 for (int i = 0; i < count; ++i) { | |
| 3401 const AstRawString* name = | |
| 3402 ClassFieldVariableName(true, ast_value_factory(), i); | |
| 3403 VariableProxy* name_proxy = scope()->NewUnresolved(factory(), name); | |
| 3404 const AstRawString* function_name = | |
| 3405 ClassFieldVariableName(false, ast_value_factory(), i); | |
| 3406 VariableProxy* function_proxy = | |
| 3407 scope()->NewUnresolved(factory(), function_name); | |
| 3408 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); | |
| 3409 args->Add(function_proxy, zone()); | |
| 3410 args->Add(ThisExpression(kNoSourcePosition), zone()); | |
| 3411 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args, | |
| 3412 kNoSourcePosition); | |
| 3413 ZoneList<Expression*>* define_property_args = | |
| 3414 new (zone()) ZoneList<Expression*>(5, zone()); | |
| 3415 define_property_args->Add(ThisExpression(kNoSourcePosition), zone()); | |
| 3416 define_property_args->Add(name_proxy, zone()); | |
| 3417 define_property_args->Add(call, zone()); | |
| 3418 define_property_args->Add( | |
| 3419 factory()->NewNumberLiteral(DONT_ENUM, kNoSourcePosition), zone()); | |
| 3420 define_property_args->Add( | |
| 3421 factory()->NewNumberLiteral( | |
| 3422 false, // TODO(bakkot) function name inference a la class { x = | |
| 3423 // function(){}; static y = function(){}; } | |
| 3424 kNoSourcePosition), | |
| 3425 zone()); | |
| 3426 body->Add(factory()->NewExpressionStatement( | |
| 3427 factory()->NewCallRuntime( | |
| 3428 Runtime::kDefineDataProperty, | |
| 3429 define_property_args, // TODO(bakkot) verify that this is | |
| 3430 // the same as object_define_property | |
| 3431 kNoSourcePosition), | |
| 3432 kNoSourcePosition), | |
| 3433 zone()); | |
| 3434 } | |
| 3435 body->Add(factory()->NewReturnStatement(ThisExpression(kNoSourcePosition), | |
| 3436 kNoSourcePosition), | |
| 3437 zone()); | |
| 3438 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( | |
| 3439 ast_value_factory()->empty_string(), initializer_scope, body, | |
| 3440 initializer_state.materialized_literal_count(), | |
| 3441 initializer_state.expected_property_count(), 0, count, | |
| 3442 FunctionLiteral::kNoDuplicateParameters, | |
| 3443 FunctionLiteral::kAnonymousExpression, | |
| 3444 FunctionLiteral::kShouldLazyCompile, initializer_scope->start_position(), | |
| 3445 true, GetNextFunctionLiteralId()); | |
| 3446 function_literal->set_is_class_field_initializer(true); | |
| 3447 return function_literal; | |
| 3448 } | |
| 3449 | |
| 3450 FunctionLiteral* Parser::InsertClassFieldInitializer( | |
| 3451 FunctionLiteral* constructor) { | |
| 3452 Statement* call_initializer = factory()->NewExpressionStatement( | |
| 3453 CallClassFieldInitializer( | |
| 3454 constructor->scope(), | |
| 3455 constructor->scope()->NewUnresolved( | |
| 3456 factory(), ast_value_factory()->this_string(), kNoSourcePosition, | |
| 3457 THIS_VARIABLE)), | |
| 3458 kNoSourcePosition); | |
| 3459 constructor->body()->InsertAt(0, call_initializer, zone()); | |
| 3460 return constructor; | |
| 3461 } | |
| 3462 | |
| 3463 // If a class name is specified, this method declares the class variable | |
| 3464 // and sets class_info->proxy to point to that name. | |
| 3465 void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope, | 3269 void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope, |
| 3466 ClassInfo* class_info, int class_token_pos, | 3270 ClassInfo* class_info, int class_token_pos, |
| 3467 bool* ok) { | 3271 bool* ok) { |
| 3468 #ifdef DEBUG | 3272 #ifdef DEBUG |
| 3469 scope()->SetScopeName(name); | 3273 scope()->SetScopeName(name); |
| 3470 #endif | 3274 #endif |
| 3471 | 3275 |
| 3472 if (name != nullptr) { | 3276 if (name != nullptr) { |
| 3473 class_info->proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); | 3277 class_info->proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); |
| 3474 Declaration* declaration = factory()->NewVariableDeclaration( | 3278 Declaration* declaration = factory()->NewVariableDeclaration( |
| 3475 class_info->proxy, block_scope, class_token_pos); | 3279 class_info->proxy, block_scope, class_token_pos); |
| 3476 Declare(declaration, DeclarationDescriptor::NORMAL, CONST, | 3280 Declare(declaration, DeclarationDescriptor::NORMAL, CONST, |
| 3477 Variable::DefaultInitializationFlag(CONST), ok); | 3281 Variable::DefaultInitializationFlag(CONST), ok); |
| 3478 } | 3282 } |
| 3479 } | 3283 } |
| 3480 | 3284 |
| 3481 // This method declares a property of the given class. It updates the | 3285 // This method declares a property of the given class. It updates the |
| 3482 // following fields of class_info, as appropriate: | 3286 // following fields of class_info, as appropriate: |
| 3483 // - constructor | 3287 // - constructor |
| 3484 // - static_initializer_var | |
| 3485 // - instance_field_initializers | |
| 3486 // - properties | 3288 // - properties |
| 3487 void Parser::DeclareClassProperty(const AstRawString* class_name, | 3289 void Parser::DeclareClassProperty(const AstRawString* class_name, |
| 3488 ClassLiteralProperty* property, | 3290 ClassLiteralProperty* property, |
| 3489 ClassLiteralProperty::Kind kind, | 3291 ClassLiteralProperty::Kind kind, |
| 3490 bool is_static, bool is_constructor, | 3292 bool is_static, bool is_constructor, |
| 3491 ClassInfo* class_info, bool* ok) { | 3293 ClassInfo* class_info, bool* ok) { |
| 3492 if (is_constructor) { | 3294 if (is_constructor) { |
| 3493 DCHECK(!class_info->constructor); | 3295 DCHECK(!class_info->constructor); |
| 3494 class_info->constructor = GetPropertyValue(property)->AsFunctionLiteral(); | 3296 class_info->constructor = GetPropertyValue(property)->AsFunctionLiteral(); |
| 3495 DCHECK_NOT_NULL(class_info->constructor); | 3297 DCHECK_NOT_NULL(class_info->constructor); |
| 3496 class_info->constructor->set_raw_name( | 3298 class_info->constructor->set_raw_name( |
| 3497 class_name != nullptr ? class_name | 3299 class_name != nullptr ? class_name |
| 3498 : ast_value_factory()->empty_string()); | 3300 : ast_value_factory()->empty_string()); |
| 3499 return; | 3301 return; |
| 3500 } | 3302 } |
| 3501 | 3303 |
| 3502 if (property->kind() == ClassLiteralProperty::FIELD) { | 3304 if (property->kind() == ClassLiteralProperty::FIELD) { |
| 3503 DCHECK(allow_harmony_class_fields()); | 3305 DCHECK(allow_harmony_class_fields()); |
| 3504 if (property->is_static()) { | 3306 // TODO(littledan): Implement class fields |
| 3505 if (class_info->static_initializer_var == nullptr) { | |
| 3506 class_info->static_initializer_var = | |
| 3507 NewTemporary(ast_value_factory()->empty_string()); | |
| 3508 } | |
| 3509 // TODO(bakkot) only do this conditionally | |
| 3510 Expression* function = InstallHomeObject( | |
| 3511 property->value(), | |
| 3512 factory()->NewVariableProxy(class_info->static_initializer_var)); | |
| 3513 ZoneList<Expression*>* args = | |
| 3514 new (zone()) ZoneList<Expression*>(2, zone()); | |
| 3515 args->Add(function, zone()); | |
| 3516 args->Add(factory()->NewVariableProxy(class_info->static_initializer_var), | |
| 3517 zone()); | |
| 3518 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args, | |
| 3519 kNoSourcePosition); | |
| 3520 property->set_value(call); | |
| 3521 } else { | |
| 3522 // if (is_computed_name) { // TODO(bakkot) figure out why this is | |
| 3523 // necessary for non-computed names in full-codegen | |
| 3524 ZoneList<Expression*>* to_name_args = | |
| 3525 new (zone()) ZoneList<Expression*>(1, zone()); | |
| 3526 to_name_args->Add(property->key(), zone()); | |
| 3527 property->set_key(factory()->NewCallRuntime( | |
| 3528 Runtime::kToName, to_name_args, kNoSourcePosition)); | |
| 3529 //} | |
| 3530 const AstRawString* name = ClassFieldVariableName( | |
| 3531 true, ast_value_factory(), | |
| 3532 class_info->instance_field_initializers->length()); | |
| 3533 VariableProxy* name_proxy = | |
| 3534 factory()->NewVariableProxy(name, NORMAL_VARIABLE); | |
| 3535 Declaration* name_declaration = factory()->NewVariableDeclaration( | |
| 3536 name_proxy, scope(), kNoSourcePosition); | |
| 3537 Variable* name_var = | |
| 3538 Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST, | |
| 3539 kNeedsInitialization, ok, scope()); | |
| 3540 DCHECK(*ok); | |
| 3541 if (!*ok) return; | |
| 3542 class_info->instance_field_initializers->Add(property->value(), zone()); | |
| 3543 property->set_value(factory()->NewVariableProxy(name_var)); | |
| 3544 } | |
| 3545 } | 3307 } |
| 3546 class_info->properties->Add(property, zone()); | 3308 class_info->properties->Add(property, zone()); |
| 3547 } | 3309 } |
| 3548 | 3310 |
| 3549 // This method rewrites a class literal into a do-expression. | 3311 // This method rewrites a class literal into a do-expression. |
| 3550 // It uses the following fields of class_info: | 3312 // It uses the following fields of class_info: |
| 3551 // - constructor (if missing, it updates it with a default constructor) | 3313 // - constructor (if missing, it updates it with a default constructor) |
| 3552 // - proxy | 3314 // - proxy |
| 3553 // - extends | 3315 // - extends |
| 3554 // - static_initializer_var | |
| 3555 // - instance_field_initializers | |
| 3556 // - properties | 3316 // - properties |
| 3557 // - has_name_static_property | 3317 // - has_name_static_property |
| 3558 // - has_static_computed_names | 3318 // - has_static_computed_names |
| 3559 Expression* Parser::RewriteClassLiteral(const AstRawString* name, | 3319 Expression* Parser::RewriteClassLiteral(const AstRawString* name, |
| 3560 ClassInfo* class_info, int pos, | 3320 ClassInfo* class_info, int pos, |
| 3561 bool* ok) { | 3321 bool* ok) { |
| 3562 int end_pos = scanner()->location().end_pos; | 3322 int end_pos = scanner()->location().end_pos; |
| 3563 Block* do_block = factory()->NewBlock(nullptr, 1, false, pos); | 3323 Block* do_block = factory()->NewBlock(nullptr, 1, false, pos); |
| 3564 Variable* result_var = NewTemporary(ast_value_factory()->empty_string()); | 3324 Variable* result_var = NewTemporary(ast_value_factory()->empty_string()); |
| 3565 DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos); | 3325 DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos); |
| 3566 | 3326 |
| 3567 bool has_extends = class_info->extends != nullptr; | 3327 bool has_extends = class_info->extends != nullptr; |
| 3568 bool has_instance_fields = | |
| 3569 class_info->instance_field_initializers->length() > 0; | |
| 3570 DCHECK(!has_instance_fields || allow_harmony_class_fields()); | |
| 3571 bool has_default_constructor = class_info->constructor == nullptr; | 3328 bool has_default_constructor = class_info->constructor == nullptr; |
| 3572 if (has_default_constructor) { | 3329 if (has_default_constructor) { |
| 3573 class_info->constructor = | 3330 class_info->constructor = DefaultConstructor( |
| 3574 DefaultConstructor(name, has_extends, has_instance_fields, pos, end_pos, | 3331 name, has_extends, pos, end_pos, scope()->language_mode()); |
| 3575 scope()->language_mode()); | |
| 3576 } | 3332 } |
| 3577 | 3333 |
| 3578 if (has_instance_fields && !has_extends) { | |
| 3579 class_info->constructor = | |
| 3580 InsertClassFieldInitializer(class_info->constructor); | |
| 3581 class_info->constructor->set_requires_class_field_init(true); | |
| 3582 } // The derived case is handled by rewriting super calls. | |
| 3583 | |
| 3584 scope()->set_end_position(end_pos); | 3334 scope()->set_end_position(end_pos); |
| 3585 | 3335 |
| 3586 if (name != nullptr) { | 3336 if (name != nullptr) { |
| 3587 DCHECK_NOT_NULL(class_info->proxy); | 3337 DCHECK_NOT_NULL(class_info->proxy); |
| 3588 class_info->proxy->var()->set_initializer_position(end_pos); | 3338 class_info->proxy->var()->set_initializer_position(end_pos); |
| 3589 } | 3339 } |
| 3590 | 3340 |
| 3591 ClassLiteral* class_literal = factory()->NewClassLiteral( | 3341 ClassLiteral* class_literal = factory()->NewClassLiteral( |
| 3592 class_info->proxy, class_info->extends, class_info->constructor, | 3342 class_info->proxy, class_info->extends, class_info->constructor, |
| 3593 class_info->properties, pos, end_pos, | 3343 class_info->properties, pos, end_pos, |
| 3594 class_info->has_name_static_property, | 3344 class_info->has_name_static_property, |
| 3595 class_info->has_static_computed_names); | 3345 class_info->has_static_computed_names); |
| 3596 | 3346 |
| 3597 if (class_info->static_initializer_var != nullptr) { | |
| 3598 class_literal->set_static_initializer_proxy( | |
| 3599 factory()->NewVariableProxy(class_info->static_initializer_var)); | |
| 3600 } | |
| 3601 | |
| 3602 do_block->statements()->Add( | 3347 do_block->statements()->Add( |
| 3603 factory()->NewExpressionStatement( | 3348 factory()->NewExpressionStatement( |
| 3604 factory()->NewAssignment(Token::ASSIGN, | 3349 factory()->NewAssignment(Token::ASSIGN, |
| 3605 factory()->NewVariableProxy(result_var), | 3350 factory()->NewVariableProxy(result_var), |
| 3606 class_literal, kNoSourcePosition), | 3351 class_literal, kNoSourcePosition), |
| 3607 pos), | 3352 pos), |
| 3608 zone()); | 3353 zone()); |
| 3609 if (allow_harmony_class_fields() && | |
| 3610 (has_instance_fields || (has_extends && !has_default_constructor))) { | |
| 3611 // Default constructors for derived classes without fields will not try to | |
| 3612 // read this variable, so there's no need to create it. | |
| 3613 const AstRawString* init_fn_name = | |
| 3614 ast_value_factory()->dot_class_field_init_string(); | |
| 3615 Variable* init_fn_var = scope()->DeclareLocal( | |
| 3616 init_fn_name, CONST, kCreatedInitialized, NORMAL_VARIABLE); | |
| 3617 Expression* initializer = | |
| 3618 has_instance_fields | |
| 3619 ? static_cast<Expression*>(SynthesizeClassFieldInitializer( | |
| 3620 class_info->instance_field_initializers->length())) | |
| 3621 : factory()->NewBooleanLiteral(false, kNoSourcePosition); | |
| 3622 Assignment* assignment = factory()->NewAssignment( | |
| 3623 Token::INIT, factory()->NewVariableProxy(init_fn_var), initializer, | |
| 3624 kNoSourcePosition); | |
| 3625 do_block->statements()->Add( | |
| 3626 factory()->NewExpressionStatement(assignment, kNoSourcePosition), | |
| 3627 zone()); | |
| 3628 } | |
| 3629 for (int i = 0; i < class_info->instance_field_initializers->length(); ++i) { | |
| 3630 const AstRawString* function_name = | |
| 3631 ClassFieldVariableName(false, ast_value_factory(), i); | |
| 3632 VariableProxy* function_proxy = | |
| 3633 factory()->NewVariableProxy(function_name, NORMAL_VARIABLE); | |
| 3634 Declaration* function_declaration = factory()->NewVariableDeclaration( | |
| 3635 function_proxy, scope(), kNoSourcePosition); | |
| 3636 Variable* function_var = | |
| 3637 Declare(function_declaration, DeclarationDescriptor::NORMAL, CONST, | |
| 3638 kNeedsInitialization, ok, scope()); | |
| 3639 if (!*ok) return nullptr; | |
| 3640 Property* prototype_property = factory()->NewProperty( | |
| 3641 factory()->NewVariableProxy(result_var), | |
| 3642 factory()->NewStringLiteral(ast_value_factory()->prototype_string(), | |
| 3643 kNoSourcePosition), | |
| 3644 kNoSourcePosition); | |
| 3645 Expression* function_value = InstallHomeObject( | |
| 3646 class_info->instance_field_initializers->at(i), | |
| 3647 prototype_property); // TODO(bakkot) ideally this would be conditional, | |
| 3648 // especially in trivial cases | |
| 3649 Assignment* function_assignment = factory()->NewAssignment( | |
| 3650 Token::INIT, factory()->NewVariableProxy(function_var), function_value, | |
| 3651 kNoSourcePosition); | |
| 3652 do_block->statements()->Add(factory()->NewExpressionStatement( | |
| 3653 function_assignment, kNoSourcePosition), | |
| 3654 zone()); | |
| 3655 } | |
| 3656 do_block->set_scope(scope()->FinalizeBlockScope()); | 3354 do_block->set_scope(scope()->FinalizeBlockScope()); |
| 3657 do_expr->set_represented_function(class_info->constructor); | 3355 do_expr->set_represented_function(class_info->constructor); |
| 3658 AddFunctionForNameInference(class_info->constructor); | 3356 AddFunctionForNameInference(class_info->constructor); |
| 3659 | 3357 |
| 3660 return do_expr; | 3358 return do_expr; |
| 3661 } | 3359 } |
| 3662 | 3360 |
| 3663 Literal* Parser::GetLiteralUndefined(int position) { | 3361 Literal* Parser::GetLiteralUndefined(int position) { |
| 3664 return factory()->NewUndefinedLiteral(position); | 3362 return factory()->NewUndefinedLiteral(position); |
| 3665 } | 3363 } |
| (...skipping 1763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5429 | 5127 |
| 5430 return final_loop; | 5128 return final_loop; |
| 5431 } | 5129 } |
| 5432 | 5130 |
| 5433 #undef CHECK_OK | 5131 #undef CHECK_OK |
| 5434 #undef CHECK_OK_VOID | 5132 #undef CHECK_OK_VOID |
| 5435 #undef CHECK_FAILED | 5133 #undef CHECK_FAILED |
| 5436 | 5134 |
| 5437 } // namespace internal | 5135 } // namespace internal |
| 5438 } // namespace v8 | 5136 } // namespace v8 |
| OLD | NEW |