Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: src/parsing/parser.cc

Issue 2578893005: Remove class fields desugaring (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698