1/** 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "classDefinition.h" 17 18#include "binder/binder.h" 19#include "binder/scope.h" 20#include "compiler/base/literals.h" 21#include "compiler/base/lreference.h" 22#include "compiler/core/pandagen.h" 23#include "typescript/checker.h" 24#include "ir/astDump.h" 25#include "ir/base/classProperty.h" 26#include "ir/base/methodDefinition.h" 27#include "ir/base/scriptFunction.h" 28#include "ir/expression.h" 29#include "ir/expressions/functionExpression.h" 30#include "ir/expressions/identifier.h" 31#include "ir/expressions/literals/nullLiteral.h" 32#include "ir/expressions/literals/numberLiteral.h" 33#include "ir/expressions/literals/stringLiteral.h" 34#include "ir/expressions/literals/taggedLiteral.h" 35#include "ir/ts/tsClassImplements.h" 36#include "ir/ts/tsIndexSignature.h" 37#include "ir/ts/tsTypeParameter.h" 38#include "ir/ts/tsTypeParameterDeclaration.h" 39#include "ir/ts/tsTypeParameterInstantiation.h" 40#include "ir/ts/tsUnionType.h" 41#include "util/helpers.h" 42 43namespace panda::es2panda::ir { 44 45const FunctionExpression *ClassDefinition::Ctor() const 46{ 47 ASSERT(ctor_ != nullptr); 48 return ctor_->Value(); 49} 50 51util::StringView ClassDefinition::GetName() const 52{ 53 if (ident_) { 54 return ident_->Name(); 55 } 56 57 if (exportDefault_) { 58 return parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME; 59 } 60 61 return ""; 62} 63 64void ClassDefinition::Iterate(const NodeTraverser &cb) const 65{ 66 if (ident_) { 67 cb(ident_); 68 } 69 70 if (typeParams_) { 71 cb(typeParams_); 72 } 73 74 if (superClass_) { 75 cb(superClass_); 76 } 77 78 if (superTypeParams_) { 79 cb(superTypeParams_); 80 } 81 82 for (auto *it : implements_) { 83 cb(it); 84 } 85 86 cb(ctor_); 87 88 for (auto *it : body_) { 89 cb(it); 90 } 91 92 for (auto *it : indexSignatures_) { 93 cb(it); 94 } 95} 96 97void ClassDefinition::Dump(ir::AstDumper *dumper) const 98{ 99 dumper->Add({{"id", AstDumper::Nullable(ident_)}, 100 {"typeParameters", AstDumper::Optional(typeParams_)}, 101 {"superClass", AstDumper::Nullable(superClass_)}, 102 {"superTypeParameters", AstDumper::Optional(superTypeParams_)}, 103 {"implements", implements_}, 104 {"constructor", ctor_}, 105 {"body", body_}, 106 {"indexSignatures", indexSignatures_}}); 107} 108 109compiler::VReg ClassDefinition::CompileHeritageClause(compiler::PandaGen *pg) const 110{ 111 compiler::VReg baseReg = pg->AllocReg(); 112 113 if (superClass_) { 114 superClass_->Compile(pg); 115 } else { 116 pg->LoadConst(this, compiler::Constant::JS_HOLE); 117 } 118 119 pg->StoreAccumulator(this, baseReg); 120 return baseReg; 121} 122 123void ClassDefinition::InitializeClassName(compiler::PandaGen *pg) const 124{ 125 if (!ident_) { 126 return; 127 } 128 129 compiler::LReference lref = compiler::LReference::CreateLRef(pg, ident_, true); 130 lref.SetValue(); 131} 132 133// NOLINTNEXTLINE(google-runtime-references) 134int32_t ClassDefinition::CreateClassPublicBuffer(compiler::PandaGen *pg, util::BitSet &compiled, 135 int32_t fieldTypeBufIdx) const 136{ 137 auto *buf = pg->NewLiteralBuffer(); 138 compiler::LiteralBuffer staticBuf(pg->Allocator()); 139 uint32_t instancePropertyCount = 0; 140 std::unordered_map<util::StringView, size_t> propNameMap; 141 std::unordered_map<util::StringView, size_t> staticPropNameMap; 142 143 const auto &properties = body_; 144 145 for (size_t i = 0; i < properties.size(); i++) { 146 if (!properties[i]->IsMethodDefinition()) { 147 continue; 148 } 149 const ir::MethodDefinition *prop = properties[i]->AsMethodDefinition(); 150 /* If it's sendable, put the getters/setters into literal buffer. 151 * If not, break at getters/setters to be compatible with api10. */ 152 if (prop->IsPrivate()) { 153 continue; 154 } 155 156 if (prop->Computed()) { 157 break; 158 } 159 160 if (prop->IsAccessor() && !isSendable_) { 161 break; 162 } 163 164 if (prop->IsAbstract()) { 165 compiled.Set(i); 166 continue; 167 } 168 169 if (prop->Value()->Function()->IsOverload()) { 170 compiled.Set(i); 171 continue; 172 } 173 174 util::StringView name = util::Helpers::LiteralToPropName(pg->Allocator(), prop->Key()); 175 compiler::LiteralBuffer *literalBuf = prop->IsStatic() ? &staticBuf : buf; 176 auto &nameMap = prop->IsStatic() ? staticPropNameMap : propNameMap; 177 178 size_t bufferPos = literalBuf->Literals().size(); 179 auto res = nameMap.insert({name, bufferPos}); 180 if (res.second || isSendable_) { 181 if (!prop->IsStatic()) { 182 instancePropertyCount++; 183 } 184 185 literalBuf->Add(pg->Allocator()->New<StringLiteral>(name)); 186 literalBuf->Add(nullptr); // save for method internalname 187 literalBuf->Add(nullptr); // save for method affiliate 188 } else { 189 bufferPos = res.first->second; 190 } 191 192 const ir::FunctionExpression *func = prop->Value()->AsFunctionExpression(); 193 const util::StringView &internalName = func->Function()->Scope()->InternalName(); 194 195 LiteralTag litTag = (prop->Kind() == MethodDefinitionKind::METHOD) ? LiteralTag::METHOD : 196 ((prop->Kind() == MethodDefinitionKind::SET) ? LiteralTag::SETTER : LiteralTag::GETTER); 197 198 Literal *value = pg->Allocator()->New<TaggedLiteral>(litTag, internalName); 199 literalBuf->ResetLiteral(bufferPos + 1, value); 200 Literal *methodAffiliate = pg->Allocator()->New<TaggedLiteral>(LiteralTag::METHODAFFILIATE, 201 func->Function()->FormalParamsLength()); 202 literalBuf->ResetLiteral(bufferPos + 2, methodAffiliate); // bufferPos + 2 is saved for method affiliate 203 compiled.Set(i); 204 } 205 206 /* Static items are stored at the end of the buffer */ 207 buf->Insert(&staticBuf); 208 209 /* The last literal item represents the offset of the first static property. The regular property literal count 210 * is divided by 2 as key/value pairs count as one. */ 211 buf->Add(pg->Allocator()->New<NumberLiteral>(instancePropertyCount)); 212 213 if (IsSendable()) { 214 std::string recordName = std::string(pg->Binder()->Program()->RecordName()); 215 std::string fieldTypeIdxStr = recordName + "_" + std::to_string(fieldTypeBufIdx); 216 util::UString fieldTypeLitId(fieldTypeIdxStr, pg->Allocator()); 217 buf->Add(pg->Allocator()->New<TaggedLiteral>(LiteralTag::LITERALARRAY, fieldTypeLitId.View())); 218 } 219 return pg->AddLiteralBuffer(buf); 220} 221 222int32_t ClassDefinition::CreateClassPrivateBuffer(compiler::PandaGen *pg) const 223{ 224 auto *buf = pg->NewLiteralBuffer(); 225 compiler::LiteralBuffer staticBuf(pg->Allocator()); 226 uint32_t instancePropertyCount = 0; 227 228 for (const auto *prop : body_) { 229 if (!prop->IsMethodDefinition()) { 230 continue; 231 } 232 233 const auto *methodDef = prop->AsMethodDefinition(); 234 if (!methodDef->IsPrivate()) { 235 continue; 236 } 237 238 compiler::LiteralBuffer *literalBuf = methodDef->IsStatic() ? &staticBuf : (instancePropertyCount++, buf); 239 const ir::FunctionExpression *func = methodDef->Value()->AsFunctionExpression(); 240 const util::StringView &internalName = func->Function()->Scope()->InternalName(); 241 Literal *value = nullptr; 242 Literal *methodAffiliate = pg->Allocator()->New<TaggedLiteral>(LiteralTag::METHODAFFILIATE, 243 func->Function()->FormalParamsLength()); 244 switch (methodDef->Kind()) { 245 case MethodDefinitionKind::METHOD: { 246 value = pg->Allocator()->New<TaggedLiteral>(LiteralTag::METHOD, internalName); 247 break; 248 } 249 case MethodDefinitionKind::GET: { 250 value = pg->Allocator()->New<TaggedLiteral>(LiteralTag::GETTER, internalName); 251 break; 252 } 253 case MethodDefinitionKind::SET: { 254 value = pg->Allocator()->New<TaggedLiteral>(LiteralTag::SETTER, internalName); 255 break; 256 } 257 default: { 258 UNREACHABLE(); 259 } 260 } 261 literalBuf->Add(value); 262 literalBuf->Add(methodAffiliate); 263 } 264 265 buf->Insert(&staticBuf); 266 buf->Add(pg->Allocator()->New<NumberLiteral>(instancePropertyCount)); 267 268 return pg->AddLiteralBuffer(buf); 269} 270 271void ClassDefinition::CompileMissingProperties(compiler::PandaGen *pg, const util::BitSet &compiled, 272 compiler::VReg classReg) const 273{ 274 const auto &properties = body_; 275 276 compiler::VReg protoReg = pg->AllocReg(); 277 278 pg->LoadObjByName(this, classReg, "prototype"); 279 pg->StoreAccumulator(this, protoReg); 280 281 for (size_t i = 0; i < properties.size(); i++) { 282 if (!properties[i]->IsMethodDefinition() || compiled.Test(i)) { 283 continue; 284 } 285 286 const ir::MethodDefinition *prop = properties[i]->AsMethodDefinition(); 287 if (prop->IsOptional() && prop->Value()->Function()->IsOverload()) { 288 continue; 289 } 290 291 if (prop->IsPrivate() || prop->IsAbstract()) { 292 continue; 293 } 294 295 compiler::VReg dest = prop->IsStatic() ? classReg : protoReg; 296 compiler::RegScope rs(pg); 297 298 switch (prop->Kind()) { 299 case ir::MethodDefinitionKind::METHOD: { 300 compiler::Operand key = prop->Computed() ? prop->KeyReg() : 301 pg->ToPropertyKey(prop->Key(), false); 302 303 pg->LoadAccumulator(this, dest); 304 const ir::FunctionExpression *func = prop->Value()->AsFunctionExpression(); 305 func->Compile(pg); 306 307 pg->StoreOwnProperty(prop->Value()->Parent(), dest, key, prop->Computed()); 308 break; 309 } 310 case ir::MethodDefinitionKind::GET: 311 case ir::MethodDefinitionKind::SET: { 312 CompileGetterOrSetter(pg, dest, prop); 313 break; 314 } 315 default: { 316 UNREACHABLE(); 317 } 318 } 319 } 320 321 if (NeedInstanceInitializer()) { 322 InstanceInitialize(pg, protoReg); 323 } 324} 325 326void ClassDefinition::StaticInitialize(compiler::PandaGen *pg, compiler::VReg classReg) const 327{ 328 compiler::VReg callee = pg->AllocReg(); 329 compiler::VReg thisReg = pg->AllocReg(); 330 331 const ir::FunctionExpression *func = staticInitializer_->Value(); 332 func->Compile(pg); 333 pg->StoreAccumulator(this, callee); 334 335 pg->MoveVreg(this, thisReg, classReg); 336 pg->CallThis(this, callee, 1); 337 338 pg->LoadAccumulator(this, classReg); 339} 340 341void ClassDefinition::InstanceInitialize(compiler::PandaGen *pg, compiler::VReg protoReg) const 342{ 343 pg->StoreAccumulator(this, protoReg); 344 instanceInitializer_->Value()->Compile(pg); 345 pg->StoreLexicalVar(instanceInitializer_, 0, GetSlot(instanceInitializer_->Key())); 346} 347 348void ClassDefinition::CompileComputedKeys(compiler::PandaGen *pg) const 349{ 350 for (const auto &stmt : body_) { 351 if (stmt->IsClassProperty()) { 352 const ir::ClassProperty *prop = stmt->AsClassProperty(); 353 354 // Do not process non-static public fields when not using define semantic. 355 if (!prop->IsStatic() && !pg->Binder()->Program()->UseDefineSemantic()) { 356 continue; 357 } 358 359 if (prop->IsComputed() && prop->NeedCompileKey()) { 360 prop->Key()->Compile(pg); 361 pg->ToComputedPropertyKey(prop->Key()); 362 pg->StoreLexicalVar(prop->Key(), 0, GetSlot(prop->Key())); 363 } 364 } else if (stmt->IsMethodDefinition()) { 365 auto *methodDef = stmt->AsMethodDefinition(); 366 if (methodDef->Computed()) { 367 compiler::VReg keyReg = pg->AllocReg(); 368 methodDef->SetKeyReg(keyReg); 369 methodDef->Key()->Compile(pg); 370 pg->ToComputedPropertyKey(methodDef->Key()); 371 pg->StoreAccumulator(methodDef->Key(), keyReg); 372 } 373 } 374 } 375} 376 377void ClassDefinition::Compile(compiler::PandaGen *pg) const 378{ 379 if (declare_) { 380 return; 381 } 382 383 if (isSendable_) { 384 CompileSendableClass(pg); 385 return; 386 } 387 388 compiler::RegScope rs(pg); 389 compiler::VReg classReg = pg->AllocReg(); 390 391 compiler::LabelTarget target(pg); 392 compiler::VariableEnvScope classEnvScope(pg, scope_, target); 393 compiler::VReg baseReg = CompileHeritageClause(pg); 394 util::StringView ctorId = ctor_->Function()->Scope()->InternalName(); 395 util::BitSet compiled(body_.size()); 396 397 if (hasComputedKey_) { 398 CompileComputedKeys(pg); 399 } 400 401 int32_t bufIdx = CreateClassPublicBuffer(pg, compiled); 402 pg->DefineClassWithBuffer(this, ctorId, bufIdx, baseReg); 403 404 pg->StoreAccumulator(this, classReg); 405 406 if (HasStaticPrivateMethod()) { 407 pg->StoreLexicalVar(this, 0, scope_->staticMethodValidation_); 408 } 409 410 InitializeClassName(pg); 411 412 CompileMissingProperties(pg, compiled, classReg); 413 414 if (hasPrivateElement_) { 415 int32_t bufIdx = CreateClassPrivateBuffer(pg); 416 pg->CreatePrivateProperty(this, scope_->privateFieldCnt_, bufIdx); 417 } 418 419 pg->LoadAccumulator(this, classReg); 420 421 if (NeedStaticInitializer()) { 422 StaticInitialize(pg, classReg); 423 } 424} 425 426checker::Type *ClassDefinition::Check(checker::Checker *checker) const 427{ 428 return checker->GlobalAnyType(); 429} 430 431void ClassDefinition::UpdateSelf(const NodeUpdater &cb, binder::Binder *binder) 432{ 433 auto scopeCtx = binder::LexicalScope<binder::ClassScope>::Enter(binder, scope_); 434 435 if (ident_) { 436 ident_ = std::get<ir::AstNode *>(cb(ident_))->AsIdentifier(); 437 } 438 439 if (typeParams_) { 440 typeParams_ = std::get<ir::AstNode *>(cb(typeParams_))->AsTSTypeParameterDeclaration(); 441 } 442 443 if (superClass_) { 444 superClass_ = std::get<ir::AstNode *>(cb(superClass_))->AsExpression(); 445 } 446 447 if (superTypeParams_) { 448 superTypeParams_ = std::get<ir::AstNode *>(cb(superTypeParams_))->AsTSTypeParameterInstantiation(); 449 } 450 451 for (auto iter = implements_.begin(); iter != implements_.end(); iter++) { 452 *iter = std::get<ir::AstNode *>(cb(*iter))->AsTSClassImplements(); 453 } 454 455 ctor_ = std::get<ir::AstNode *>(cb(ctor_))->AsMethodDefinition(); 456 457 for (auto iter = body_.begin(); iter != body_.end(); iter++) { 458 *iter = std::get<ir::AstNode *>(cb(*iter))->AsStatement(); 459 } 460 461 for (auto iter = indexSignatures_.begin(); iter != indexSignatures_.end(); iter++) { 462 *iter = std::get<ir::AstNode *>(cb(*iter))->AsTSIndexSignature(); 463 } 464} 465 466 467void ClassDefinition::BuildClassEnvironment(bool useDefineSemantic) 468{ 469 int instancePrivateMethodCnt = 0; 470 int staticPrivateMethodCnt = 0; 471 int privateFieldCnt = 0; 472 std::vector<const Statement *> privateProperties; 473 for (const auto *stmt : body_) { 474 if (stmt->IsMethodDefinition()) { 475 auto *methodDef = stmt->AsMethodDefinition(); 476 if (methodDef->IsPrivate()) { 477 privateProperties.push_back(stmt); 478 methodDef->IsStatic() ? staticPrivateMethodCnt ++ : instancePrivateMethodCnt++; 479 } else if (methodDef->Computed()) { 480 hasComputedKey_ = true; 481 } 482 continue; 483 } 484 485 if (stmt->IsClassStaticBlock()) { 486 needStaticInitializer_ = true; 487 continue; 488 } 489 490 ASSERT(stmt->IsClassProperty()); 491 const auto *prop = stmt->AsClassProperty(); 492 // Do not process non-static public fields when not using define semantic. 493 if (!prop->IsPrivate() && !prop->IsStatic() && !useDefineSemantic) { 494 continue; 495 } 496 497 prop->IsStatic() ? needStaticInitializer_ = true : needInstanceInitializer_ = true; 498 499 if (prop->IsComputed() && prop->NeedCompileKey()) { 500 hasComputedKey_ = true; 501 scope_->AddClassVariable(prop->Key()); 502 } else if (prop->IsPrivate()) { 503 privateFieldCnt++; 504 privateProperties.push_back(stmt); 505 } 506 } 507 508 if (!privateProperties.empty()) { 509 hasPrivateElement_ = true; 510 scope_->AddPrivateName(privateProperties, privateFieldCnt, instancePrivateMethodCnt, staticPrivateMethodCnt); 511 } 512 513 if (instancePrivateMethodCnt > 0) { 514 needInstanceInitializer_ = true; 515 } 516 517 if (NeedInstanceInitializer()) { 518 scope_->AddClassVariable(instanceInitializer_->Key()); 519 } 520} 521 522void ClassDefinition::AddFieldType(FieldType &fieldType, const Expression *typeAnnotation, 523 compiler::PandaGen *pg) const 524{ 525 switch (typeAnnotation->Type()) { 526 case AstNodeType::TS_NUMBER_KEYWORD: { 527 fieldType |= FieldType::NUMBER; 528 break; 529 } 530 case AstNodeType::TS_STRING_KEYWORD: { 531 fieldType |= FieldType::STRING; 532 break; 533 } 534 case AstNodeType::TS_BOOLEAN_KEYWORD: { 535 fieldType |= FieldType::BOOLEAN; 536 break; 537 } 538 case AstNodeType::TS_TYPE_REFERENCE: { 539 AddFieldTypeForTypeReference(typeAnnotation->AsTSTypeReference(), fieldType, pg); 540 break; 541 } 542 case AstNodeType::TS_BIGINT_KEYWORD: { 543 fieldType |= FieldType::BIGINT; 544 break; 545 } 546 case AstNodeType::TS_NULL_KEYWORD: { 547 fieldType |= FieldType::TS_NULL; 548 break; 549 } 550 case AstNodeType::TS_UNDEFINED_KEYWORD: { 551 fieldType |= FieldType::TS_UNDEFINED; 552 break; 553 } 554 default: { 555 UNREACHABLE(); 556 } 557 } 558} 559 560void ClassDefinition::AddFieldTypeForTypeReference(const TSTypeReference *typeReference, FieldType &fieldType, 561 compiler::PandaGen *pg) const 562{ 563 auto typeName = typeReference->TypeName(); 564 ASSERT(typeName != nullptr); 565 if (!typeName->IsIdentifier()) { 566 fieldType |= FieldType::GENERIC; 567 return; 568 } 569 570 util::StringView propertyName = typeName->AsIdentifier()->Name(); 571 binder::ScopeFindResult result = scope_->Find(propertyName); 572 573 // identify import type 574 parser::SourceTextModuleRecord *moduleRecord = pg->Binder()->Program()->TypeModuleRecord(); 575 const auto ®ularImportEntries = moduleRecord->GetRegularImportEntries(); 576 if (regularImportEntries.find(propertyName) != regularImportEntries.end()) { 577 fieldType |= FieldType::GENERIC; 578 return; 579 } 580 581 if (IsTypeParam(propertyName) || (result.variable != nullptr && result.variable->IsModuleVariable())) { 582 fieldType |= FieldType::GENERIC; 583 return; 584 } 585 586 // ts enum type 587 const ir::AstNode *declNode = GetDeclNodeFromIdentifier(typeName->AsIdentifier()); 588 if (declNode != nullptr) { 589 // If the result of "declNode->Original()" is nullptr, it means the declNode is original and not transformed. 590 auto originalNode = (declNode->Original() != nullptr) ? declNode->Original() : declNode; 591 if (originalNode->Type() == ir::AstNodeType::TS_ENUM_DECLARATION) { 592 fieldType |= FieldType::STRING | FieldType::NUMBER; 593 return; 594 } 595 } 596 597 // sendable class and sendable fuction 598 fieldType |= FieldType::TS_TYPE_REF; 599} 600 601const ir::AstNode *ClassDefinition::GetDeclNodeFromIdentifier(const ir::Identifier *identifier) const 602{ 603 if (identifier == nullptr) { 604 return nullptr; 605 } 606 607 std::vector<binder::Variable *> variables; 608 variables.reserve(identifier->TSVariables().size() + 1U); 609 variables.emplace_back(identifier->Variable()); 610 for (const auto &v : identifier->TSVariables()) { 611 variables.emplace_back(v); 612 } 613 614 for (const auto &v : variables) { 615 if (v == nullptr || v->Declaration() == nullptr || v->Declaration()->Node() == nullptr) { 616 continue; 617 } 618 619 auto res = v->Declaration()->Node(); 620 return res; 621 } 622 return nullptr; 623} 624 625bool ClassDefinition::IsTypeParam(const util::StringView &propertyName) const 626{ 627 if (typeParams_ == nullptr) { 628 return false; 629 } 630 631 for (auto param : typeParams_->Params()) { 632 util::StringView paramName = param->Name()->AsIdentifier()->Name(); 633 if (paramName == propertyName) { 634 return true; 635 } 636 } 637 return false; 638} 639 640int32_t ClassDefinition::CreateFieldTypeBuffer(compiler::PandaGen *pg) const 641{ 642 ASSERT(IsSendable()); 643 auto *instanceBuf = pg->NewLiteralBuffer(); 644 compiler::LiteralBuffer staticBuf(pg->Allocator()); 645 uint32_t instanceFieldCnt {0}; 646 647 for (auto *prop : body_) { 648 if (!prop->IsClassProperty()) { 649 continue; 650 } 651 652 auto *classProp = prop->AsClassProperty(); 653 auto *buf = classProp->IsStatic() ? &staticBuf : (++instanceFieldCnt, instanceBuf); 654 auto name = util::Helpers::LiteralToPropName(pg->Allocator(), classProp->Key()); 655 buf->Add(pg->Allocator()->New<StringLiteral>(name)); 656 657 FieldType fieldType = FieldType::NONE; 658 const auto *typeAnnotation = classProp->TypeAnnotation(); 659 if (typeAnnotation == nullptr) { 660 util::Helpers::ThrowError(ErrorType::GENERIC, pg->Binder()->Program(), prop->Start(), 661 "Field in sendable class must have type annotation"); 662 } 663 if (typeAnnotation->IsTSUnionType()) { 664 for (const auto *type : typeAnnotation->AsTSUnionType()->Types()) { 665 AddFieldType(fieldType, type, pg); 666 } 667 } else { 668 AddFieldType(fieldType, typeAnnotation, pg); 669 } 670 buf->Add(pg->Allocator()->New<NumberLiteral>(static_cast<uint8_t>(fieldType))); 671 } 672 673 instanceBuf->Insert(&staticBuf); 674 instanceBuf->Add(pg->Allocator()->New<NumberLiteral>(instanceFieldCnt)); 675 return pg->AddLiteralBuffer(instanceBuf); 676} 677 678void ClassDefinition::CompileSendableClass(compiler::PandaGen *pg) const 679{ 680 compiler::RegScope rs(pg); 681 compiler::VReg classReg = pg->AllocReg(); 682 683 compiler::LocalRegScope lrs(pg, scope_); 684 685 compiler::VReg baseReg = CompileHeritageClause(pg); 686 util::StringView ctorId = ctor_->Function()->Scope()->InternalName(); 687 util::BitSet compiled(body_.size()); 688 689 int32_t fieldTypeBufIdx = CreateFieldTypeBuffer(pg); 690 int32_t bufIdx = CreateClassPublicBuffer(pg, compiled, fieldTypeBufIdx); 691 pg->DefineSendableClass(this, ctorId, bufIdx, baseReg); 692 693 pg->StoreAccumulator(this, classReg); 694 695 InitializeClassName(pg); 696 697 if (NeedStaticInitializer()) { 698 StaticInitialize(pg, classReg); 699 } 700} 701 702void ClassDefinition::CompileGetterOrSetter(compiler::PandaGen *pg, compiler::VReg dest, 703 const MethodDefinition *prop) const 704{ 705 compiler::VReg keyReg = prop->Computed() ? prop->KeyReg() : pg->LoadPropertyKey(prop->Key(), false); 706 707 compiler::VReg undef = pg->AllocReg(); 708 pg->LoadConst(this, compiler::Constant::JS_UNDEFINED); 709 pg->StoreAccumulator(this, undef); 710 711 compiler::VReg getter = undef; 712 compiler::VReg setter = undef; 713 714 pg->LoadAccumulator(this, dest); 715 716 compiler::VReg accessor = pg->AllocReg(); 717 prop->Value()->Compile(pg); 718 pg->StoreAccumulator(prop->Value(), accessor); 719 720 if (prop->Kind() == ir::MethodDefinitionKind::GET) { 721 getter = accessor; 722 } else { 723 setter = accessor; 724 } 725 726 pg->DefineGetterSetterByValue(this, dest, keyReg, getter, setter, prop->Computed()); 727} 728 729} // namespace panda::es2panda::ir 730