diff --git a/es2panda/compiler/core/envScope.cpp b/es2panda/compiler/core/envScope.cpp index b45229fdb1d603c7d22384e6f4e3b6c1bed232ee..d37112b6b8734d85781bc8cf56ca109d830dc51e 100644 --- a/es2panda/compiler/core/envScope.cpp +++ b/es2panda/compiler/core/envScope.cpp @@ -16,6 +16,7 @@ #include "envScope.h" #include +#include #include namespace panda::es2panda::compiler { @@ -86,6 +87,10 @@ VariableEnvScope::VariableEnvScope(PandaGen *pg, binder::VariableScope *scope) { Initialize(pg); if (HasEnv()) { + if (scope_->Node()->IsClassDefinition() && scope_->Node()->AsClassDefinition()->IsSendable()) { + pg_->NewSendableLexEnv(scope_->Node(), scope->LexicalSlots()); + return; + } pg_->NewLexicalEnv(scope_->Node(), scope->LexicalSlots(), scope_); } } diff --git a/es2panda/compiler/core/function.cpp b/es2panda/compiler/core/function.cpp index b51e0521b0efb3693c04da2619154d35e0f320e6..57676ef6233872ae4ebccd027f7b95a0f478d04d 100644 --- a/es2panda/compiler/core/function.cpp +++ b/es2panda/compiler/core/function.cpp @@ -215,7 +215,6 @@ static void CompileFunction(PandaGen *pg) const auto *classDef = util::Helpers::GetClassDefiniton(decl); if (classDef->Super() == nullptr && classDef->NeedInstanceInitializer()) { RegScope rs(pg); - auto callee = pg->AllocReg(); auto thisReg = pg->AllocReg(); pg->GetThis(decl); @@ -223,9 +222,7 @@ static void CompileFunction(PandaGen *pg) auto [level, slot] = pg->Scope()->Find(classDef->InstanceInitializer()->Key()); pg->LoadLexicalVar(decl, level, slot); - pg->StoreAccumulator(decl, callee); - - pg->CallThis(decl, callee, 1); + pg->CallInit(decl, thisReg); } } diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index 5f7527ddbce7c3c9aac4a3b611d506c5efab882b..2fa6ed068721dfcf09d49455ccd3ec8e988f7306 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -475,7 +475,7 @@ void PandaGen::DefineClassField(const ir::AstNode *node, VReg obj, const Operand void PandaGen::DefineClassPrivateField(const ir::AstNode *node, uint32_t level, uint32_t slot, VReg obj) { - ra_.Emit(node, level, slot, obj); + ra_.Emit(node, 0, level, slot, obj); } void PandaGen::StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop, bool nameSetting) @@ -577,7 +577,7 @@ void PandaGen::StoreObjByName(const ir::AstNode *node, VReg obj, const util::Str void PandaGen::DefineFieldByName(const ir::AstNode *node, VReg obj, const util::StringView &prop) { - ra_.Emit(node, prop, obj); + ra_.Emit(node, 0, prop, obj); strings_.insert(prop); } @@ -614,12 +614,12 @@ void PandaGen::StoreObjByIndex(const ir::AstNode *node, VReg obj, int64_t index) void PandaGen::DefineFieldByValue(const ir::AstNode *node, VReg obj, VReg prop) { - ra_.Emit(node, prop, obj); + ra_.Emit(node, 0, prop, obj); } void PandaGen::DefineFieldByIndex(const ir::AstNode *node, VReg obj, int64_t index) { - ra_.Emit(node, index, obj); + ra_.Emit(node, 0, index, obj); } void PandaGen::StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop, bool nameSetting) @@ -1357,6 +1357,12 @@ void PandaGen::NotifyConcurrentResult(const ir::AstNode *node) } } +void PandaGen::CallInit(const ir::AstNode *node, VReg thisReg) +{ + // callee is in acc + ra_.Emit(node, 0, thisReg); +} + void PandaGen::NewObject(const ir::AstNode *node, VReg startReg, size_t argCount) { if (argCount <= util::Helpers::MAX_INT8) { @@ -1383,6 +1389,12 @@ void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction strings_.insert(name); } +void PandaGen::DefineSendableMethod(const ir::AstNode *node, const util::StringView &name, size_t formalParamCnt) +{ + ra_.Emit(node, 0, name, static_cast(formalParamCnt)); + strings_.insert(name); +} + void PandaGen::TypeOf(const ir::AstNode *node) { ra_.Emit(node, 0); @@ -1733,6 +1745,15 @@ void PandaGen::DefineClassWithBuffer(const ir::AstNode *node, const util::String strings_.insert(ctorId); } +void PandaGen::DefineSendableClass(const ir::AstNode *node, const util::StringView &ctorId, int32_t litIdx, VReg base) +{ + auto formalParamCnt = node->AsClassDefinition()->Ctor()->Function()->FormalParamsLength(); + std::string idxStr = std::string(context_->Binder()->Program()->RecordName()) + "_" + std::to_string(litIdx); + util::UString litId(idxStr, allocator_); + ra_.Emit(node, 0, ctorId, litId.View(), static_cast(formalParamCnt), base); + strings_.insert(ctorId); +} + void PandaGen::LoadLocalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable) { auto index = variable->Index(); @@ -1981,6 +2002,11 @@ void PandaGen::NewLexicalEnv(const ir::AstNode *node, uint32_t num, binder::Vari NewLexEnv(node, num); } +void PandaGen::NewSendableLexEnv(const ir::AstNode *node, uint32_t num) +{ + ra_.Emit(node, num); +} + void PandaGen::NewLexEnv(const ir::AstNode *node, uint32_t num) { num <= util::Helpers::MAX_INT8 ? ra_.Emit(node, num) : ra_.Emit(node, num); @@ -2197,6 +2223,13 @@ void PandaGen::CreatePrivateProperty(const ir::AstNode *node, uint32_t num, int3 ra_.Emit(node, num, litId.View()); } +void PandaGen::CreateSendablePrivateProperty(const ir::AstNode *node, uint32_t num, int32_t bufIdx) +{ + std::string idxStr = std::string(context_->Binder()->Program()->RecordName()) + "_" + std::to_string(bufIdx); + util::UString litId(idxStr, allocator_); + ra_.Emit(node, num, litId.View()); +} + void PandaGen::TestIn(const ir::AstNode *node, uint32_t level, uint32_t slot) { ra_.Emit(node, 0, level, slot); diff --git a/es2panda/compiler/core/pandagen.h b/es2panda/compiler/core/pandagen.h index 7d76bda3acfe83e49885c57e1f9228e719160544..49e6b4ea9473fa826973fdf5fdee646f93f15d93 100644 --- a/es2panda/compiler/core/pandagen.h +++ b/es2panda/compiler/core/pandagen.h @@ -378,9 +378,11 @@ public: void SuperCall(const ir::AstNode *node, VReg startReg, size_t argCount); void SuperCallSpread(const ir::AstNode *node, VReg vs); void NotifyConcurrentResult(const ir::AstNode *node); + void CallInit(const ir::AstNode *node, VReg thisReg); void NewObject(const ir::AstNode *node, VReg startReg, size_t argCount); void DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name); + void DefineSendableMethod(const ir::AstNode *node, const util::StringView &name, size_t formalParamCnt); void TypeOf(const ir::AstNode *node); void NewObjSpread(const ir::AstNode *node, VReg obj); @@ -434,6 +436,8 @@ public: void ThrowObjectNonCoercible(const ir::AstNode *node); void CloseIterator(const ir::AstNode *node, VReg iter); void DefineClassWithBuffer(const ir::AstNode *node, const util::StringView &ctorId, int32_t litIdx, VReg base); + void DefineSendableClass(const ir::AstNode *node, const util::StringView &ctorId, + int32_t litIdx, VReg base); void LoadLocalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable); void LoadExternalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable); @@ -452,6 +456,7 @@ public: void GenDebugger(const ir::AstNode *node); void CopyLexEnv(const ir::AstNode *node); void NewLexicalEnv(const ir::AstNode *node, uint32_t num, binder::VariableScope *scope); + void NewSendableLexEnv(const ir::AstNode *node, uint32_t num); void NewLexEnv(const ir::AstNode *node, uint32_t num); void NewLexEnvWithScopeInfo(const ir::AstNode *node, uint32_t num, int32_t scopeInfoIdx); void LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot); @@ -491,6 +496,7 @@ public: void ReArrangeIc(); void CreatePrivateProperty(const ir::AstNode *node, uint32_t num, int32_t bufIdx); + void CreateSendablePrivateProperty(const ir::AstNode *node, uint32_t num, int32_t bufIdx); void TestIn(const ir::AstNode *node, uint32_t level, uint32_t slot); void LoadPrivateProperty(const ir::AstNode *node, uint32_t level, uint32_t slot); void StorePrivateProperty(const ir::AstNode *node, uint32_t level, uint32_t slot, VReg obj); diff --git a/es2panda/ir/base/classDefinition.cpp b/es2panda/ir/base/classDefinition.cpp index 887b455d1f0f3eff56604568b92be4089d8b6ee9..e68031d4a49641042df70805b75e2398376ccd45 100644 --- a/es2panda/ir/base/classDefinition.cpp +++ b/es2panda/ir/base/classDefinition.cpp @@ -37,6 +37,7 @@ #include "ir/ts/tsTypeParameter.h" #include "ir/ts/tsTypeParameterDeclaration.h" #include "ir/ts/tsTypeParameterInstantiation.h" +#include "ir/ts/tsUnionType.h" #include "util/helpers.h" namespace panda::es2panda::ir { @@ -130,7 +131,8 @@ void ClassDefinition::InitializeClassName(compiler::PandaGen *pg) const } // NOLINTNEXTLINE(google-runtime-references) -int32_t ClassDefinition::CreateClassPublicBuffer(compiler::PandaGen *pg, util::BitSet &compiled) const +int32_t ClassDefinition::CreateClassPublicBuffer(compiler::PandaGen *pg, util::BitSet &compiled, + int32_t fieldTypeBufIdx) const { auto *buf = pg->NewLiteralBuffer(); compiler::LiteralBuffer staticBuf(pg->Allocator()); @@ -145,19 +147,20 @@ int32_t ClassDefinition::CreateClassPublicBuffer(compiler::PandaGen *pg, util::B continue; } const ir::MethodDefinition *prop = properties[i]->AsMethodDefinition(); + /* If it's sendable, put the getters/setters into literal buffer. + * If not, break at getters/setters to be compatible with api10. */ + if (prop->IsPrivate()) { + continue; + } if (prop->Computed()) { break; } - if (prop->IsAccessor()) { + if (prop->IsAccessor() && !isSendable_) { break; } - if (prop->IsPrivate()) { - continue; - } - if (prop->IsAbstract()) { compiled.Set(i); continue; @@ -174,7 +177,7 @@ int32_t ClassDefinition::CreateClassPublicBuffer(compiler::PandaGen *pg, util::B size_t bufferPos = literalBuf->Literals().size(); auto res = nameMap.insert({name, bufferPos}); - if (res.second) { + if (res.second || isSendable_) { if (!prop->IsStatic()) { instancePropertyCount++; } @@ -186,32 +189,18 @@ int32_t ClassDefinition::CreateClassPublicBuffer(compiler::PandaGen *pg, util::B bufferPos = res.first->second; } - Literal *value = nullptr; + const ir::FunctionExpression *func = prop->Value()->AsFunctionExpression(); + const util::StringView &internalName = func->Function()->Scope()->InternalName(); - switch (prop->Kind()) { - case ir::MethodDefinitionKind::METHOD: { - const ir::FunctionExpression *func = prop->Value()->AsFunctionExpression(); - const util::StringView &internalName = func->Function()->Scope()->InternalName(); + LiteralTag litTag = (prop->Kind() == MethodDefinitionKind::METHOD) ? LiteralTag::METHOD : + ((prop->Kind() == MethodDefinitionKind::SET) ? LiteralTag::SETTER : LiteralTag::GETTER); - value = pg->Allocator()->New(LiteralTag::METHOD, internalName); - literalBuf->ResetLiteral(bufferPos + 1, value); - Literal *methodAffiliate = pg->Allocator()->New(LiteralTag::METHODAFFILIATE, - func->Function()->FormalParamsLength()); - literalBuf->ResetLiteral(bufferPos + 2, methodAffiliate); // bufferPos + 2 is saved for method affiliate - compiled.Set(i); - break; - } - // TODO refactor this part later - case ir::MethodDefinitionKind::GET: - case ir::MethodDefinitionKind::SET: { - value = pg->Allocator()->New(); - literalBuf->ResetLiteral(bufferPos + 1, value); - break; - } - default: { - UNREACHABLE(); - } - } + Literal *value = pg->Allocator()->New(litTag, internalName); + literalBuf->ResetLiteral(bufferPos + 1, value); + Literal *methodAffiliate = pg->Allocator()->New(LiteralTag::METHODAFFILIATE, + func->Function()->FormalParamsLength()); + literalBuf->ResetLiteral(bufferPos + 2, methodAffiliate); // bufferPos + 2 is saved for method affiliate + compiled.Set(i); } /* Static items are stored at the end of the buffer */ @@ -221,6 +210,12 @@ int32_t ClassDefinition::CreateClassPublicBuffer(compiler::PandaGen *pg, util::B * is divided by 2 as key/value pairs count as one. */ buf->Add(pg->Allocator()->New(instancePropertyCount)); + if (IsSendable()) { + std::string recordName = std::string(pg->Binder()->Program()->RecordName()); + std::string fieldTypeIdxStr = recordName + "_" + std::to_string(fieldTypeBufIdx); + util::UString fieldTypeLitId(fieldTypeIdxStr, pg->Allocator()); + buf->Add(pg->Allocator()->New(LiteralTag::LITERALARRAY, fieldTypeLitId.View())); + } return pg->AddLiteralBuffer(buf); } @@ -394,6 +389,11 @@ void ClassDefinition::Compile(compiler::PandaGen *pg) const return; } + if (isSendable_) { + CompileSendableClass(pg); + return; + } + compiler::RegScope rs(pg); compiler::VReg classReg = pg->AllocReg(); @@ -528,4 +528,127 @@ void ClassDefinition::BuildClassEnvironment() } } +static void AddFieldType(FieldType &fieldType, const Expression *typeAnnotation) +{ + switch (typeAnnotation->Type()) { + case AstNodeType::TS_NUMBER_KEYWORD: { + fieldType |= FieldType::NUMBER; + break; + } + case AstNodeType::TS_STRING_KEYWORD: { + fieldType |= FieldType::STRING; + break; + } + case AstNodeType::TS_BOOLEAN_KEYWORD: { + fieldType |= FieldType::BOOLEAN; + break; + } + case AstNodeType::TS_TYPE_REFERENCE: { + fieldType |= FieldType::TS_TYPE_REF; + break; + } + default: { + UNREACHABLE(); + } + } +} + +int32_t ClassDefinition::CreateFieldTypeBuffer(compiler::PandaGen *pg) const +{ + ASSERT(IsSendable()); + auto *instanceBuf = pg->NewLiteralBuffer(); + compiler::LiteralBuffer staticBuf(pg->Allocator()); + uint32_t instanceFieldCnt {0}; + + if (HasInstancePrivateMethod()) { + ++instanceFieldCnt; + instanceBuf->Add(pg->Allocator()->New(scope_->instanceMethodValidation_)); + instanceBuf->Add(pg->Allocator()->New(0)); + } + for (auto *prop : body_) { + if (!prop->IsClassProperty()) { + continue; + } + + auto *classProp = prop->AsClassProperty(); + auto *buf = classProp->IsStatic() ? &staticBuf : (++instanceFieldCnt, instanceBuf); + if (classProp->IsPrivate()) { + auto slot = scope_->GetPrivateProperty(classProp->Key()->AsPrivateIdentifier()->Name(), false).slot; + buf->Add(pg->Allocator()->New(slot)); + } else { + auto name = util::Helpers::LiteralToPropName(pg->Allocator(), classProp->Key()); + buf->Add(pg->Allocator()->New(name)); + } + + FieldType fieldType = FieldType::NONE; + const auto *typeAnnotation = classProp->TypeAnnotation(); + ASSERT(typeAnnotation != nullptr); + if (typeAnnotation->IsTSUnionType()) { + for (const auto *type : typeAnnotation->AsTSUnionType()->Types()) { + AddFieldType(fieldType, type); + } + } else { + AddFieldType(fieldType, typeAnnotation); + } + buf->Add(pg->Allocator()->New(static_cast(fieldType))); + } + + instanceBuf->Insert(&staticBuf); + instanceBuf->Add(pg->Allocator()->New(instanceFieldCnt)); + return pg->AddLiteralBuffer(instanceBuf); +} + +void ClassDefinition::CompileSendableClass(compiler::PandaGen *pg) const +{ + compiler::RegScope rs(pg); + compiler::VReg classReg = pg->AllocReg(); + + compiler::LocalRegScope lrs(pg, scope_); + + compiler::VariableEnvScope envScope(pg, scope_); + + // For sendable class, to put the instruction createprivateproperty ahead, the hole in env should be filled. + if (ident_ != nullptr) { + binder::ScopeFindResult res = scope_->Find(ident_->Name()); + if (res.variable->LexicalBound()) { + pg->LoadConst(ident_, compiler::Constant::JS_UNDEFINED); + binder::LocalVariable *local = res.variable->AsLocalVariable(); + pg->StoreLexicalVar(ident_, res.lexLevel, local->LexIdx(), local); + } + } + + if (hasPrivateElement_) { + int32_t bufIdx = CreateClassPrivateBuffer(pg); + pg->CreateSendablePrivateProperty(this, scope_->privateFieldCnt_, bufIdx); + } + + compiler::VReg baseReg = CompileHeritageClause(pg); + util::StringView ctorId = ctor_->Function()->Scope()->InternalName(); + util::BitSet compiled(body_.size()); + + int32_t fieldTypeBufIdx = CreateFieldTypeBuffer(pg); + int32_t bufIdx = CreateClassPublicBuffer(pg, compiled, fieldTypeBufIdx); + pg->DefineSendableClass(this, ctorId, bufIdx, baseReg); + + pg->StoreAccumulator(this, classReg); + + if (HasStaticPrivateMethod()) { + pg->StoreLexicalVar(this, 0, scope_->staticMethodValidation_); + } + + InitializeClassName(pg); + + if (NeedInstanceInitializer()) { + auto *func = instanceInitializer_->Function(); + pg->DefineSendableMethod(func, func->Scope()->InternalName(), func->FormalParamsLength()); + pg->StoreLexicalVar(instanceInitializer_, 0, GetSlot(instanceInitializer_->Key())); + } + + pg->LoadAccumulator(this, classReg); + + if (NeedStaticInitializer()) { + StaticInitialize(pg, classReg); + } +} + } // namespace panda::es2panda::ir diff --git a/es2panda/ir/base/classDefinition.h b/es2panda/ir/base/classDefinition.h index dab0bcdb7ecf5a817c7904bb5438b205c564fa8d..6f05d7a53fc83eadab492d9f291e0952c1a269be 100644 --- a/es2panda/ir/base/classDefinition.h +++ b/es2panda/ir/base/classDefinition.h @@ -37,6 +37,15 @@ class LocalScope; namespace panda::es2panda::ir { +enum class FieldType { + NONE = 0, + NUMBER = (1 << 0), + STRING = (1 << 1), + BOOLEAN = (1 << 2), + TS_TYPE_REF = (1 << 3), +}; +DEFINE_BITOPS(FieldType) + class Identifier; class MethodDefinition; class TSTypeParameterDeclaration; @@ -211,6 +220,11 @@ public: isSendable_ = true; } + bool IsSendable() const + { + return isSendable_; + } + const FunctionExpression *Ctor() const; util::StringView GetName() const; @@ -226,13 +240,14 @@ public: private: compiler::VReg CompileHeritageClause(compiler::PandaGen *pg) const; void InitializeClassName(compiler::PandaGen *pg) const; - int32_t CreateClassPublicBuffer(compiler::PandaGen *pg, util::BitSet &compiled) const; + int32_t CreateClassPublicBuffer(compiler::PandaGen *pg, util::BitSet &compiled, int32_t fieldTypeBufIdx = 0) const; int32_t CreateClassPrivateBuffer(compiler::PandaGen *pg) const; void CompileMissingProperties(compiler::PandaGen *pg, const util::BitSet &compiled, compiler::VReg classReg) const; void StaticInitialize(compiler::PandaGen *pg, compiler::VReg classReg) const; void InstanceInitialize(compiler::PandaGen *pg, compiler::VReg classReg) const; void CompileComputedKeys(compiler::PandaGen *pg) const; - + int32_t CreateFieldTypeBuffer(compiler::PandaGen *pg) const; + void CompileSendableClass(compiler::PandaGen *pg) const; binder::ClassScope *scope_; Identifier *ident_; diff --git a/es2panda/ir/expressions/callExpression.cpp b/es2panda/ir/expressions/callExpression.cpp index e09d1f989a81031abb887059074654208d4646fc..0956850bfca8c928745a350df25ba39bc51f39cd 100644 --- a/es2panda/ir/expressions/callExpression.cpp +++ b/es2panda/ir/expressions/callExpression.cpp @@ -124,16 +124,13 @@ void CallExpression::Compile(compiler::PandaGen *pg) const const auto *classDef = util::Helpers::GetClassDefiniton(util::Helpers::GetContainingConstructor(this)); if (classDef->NeedInstanceInitializer()) { - auto callee = pg->AllocReg(); auto thisReg = pg->AllocReg(); + pg->MoveVreg(this, thisReg, newThis); auto [level, slot] = pg->Scope()->Find(classDef->InstanceInitializer()->Key()); pg->LoadLexicalVar(this, level, slot); - pg->StoreAccumulator(this, callee); - - pg->MoveVreg(this, thisReg, newThis); - pg->CallThis(this, callee, 1); + pg->CallInit(this, thisReg); } return; } diff --git a/es2panda/ir/expressions/literal.cpp b/es2panda/ir/expressions/literal.cpp index 367b717536f3d04d584bc661dd4685bfa76c1a06..00a47a297665c50bf38f9030f982855753e5e624 100644 --- a/es2panda/ir/expressions/literal.cpp +++ b/es2panda/ir/expressions/literal.cpp @@ -46,8 +46,11 @@ const util::StringView &Literal::GetString() const if (IsStringLiteral()) { return AsStringLiteral()->Str(); } - ASSERT(IsNumberLiteral()); - return AsNumberLiteral()->Str(); + if (IsNumberLiteral()) { + return AsNumberLiteral()->Str(); + } + ASSERT(IsTaggedLiteral()); + return AsTaggedLiteral()->Str(); } const util::StringView &Literal::GetMethod() const diff --git a/es2panda/test/base64/inputFile/expected.txt b/es2panda/test/base64/inputFile/expected.txt index 55e4b70a9513c86319c77654c6c23973b9b604cc..c5c05e5c7086e71c2e8e32416233f4bf9826ceb4 100644 --- a/es2panda/test/base64/inputFile/expected.txt +++ b/es2panda/test/base64/inputFile/expected.txt @@ -11,4 +11,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -UEFOREEAAAAAAAAACwAAAKQBAACMAAAAFQAAAAQAAAA8AAAAAQAAAKABAAAAAAAATAAAAAEAAABMAAAAuwAAAIwAAADhAAAADQEAAIwAAACkAQAAAgAAAHQAAAADAAAAfAAAAAAAAACIAAAAAQAAAIgAAAC7AAAADQEAAKEAAACvAAAAtgAAAD4BAAAnTF9FU1R5cGVBbm5vdGF0aW9uOwAZaGVsbG8gd29ybGQhAAtwcmludAAHc3RyADNMX0VTU2xvdE51bWJlckFubm90YXRpb247AAAAAACAQAAAAgAAJ0xfRVNUeXBlSW5mb1JlY29yZDsAAAAAAAEAAAIAABdmdW5jX21haW5fMAATTF9HTE9CQUw7AAAAAAABAAECAAABAAAAAAEAAIgCAWUBAAACAAWRAQAABlgBAAAA7u4AABFpbnB1dC5qcwAVU2xvdE51bWJlcgAAAAEATAEAAAUAAAA3BwMhAERwRIFEkj4AAEgAAAIAPwEBAGEFPwICAGEGYAUqAwYAZQkLAQIQiQD/////DwAFwgIABhAAAACKAQAA +UEFOREEAAAAAAAAACwABAKQBAACMAAAAFQAAAAQAAAA8AAAAAQAAAKABAAAAAAAATAAAAAEAAABMAAAAuwAAAIwAAADhAAAADQEAAIwAAACkAQAAAgAAAHQAAAADAAAAfAAAAAAAAACIAAAAAQAAAIgAAAC7AAAADQEAAKEAAACvAAAAtgAAAD4BAAAnTF9FU1R5cGVBbm5vdGF0aW9uOwAZaGVsbG8gd29ybGQhAAtwcmludAAHc3RyADNMX0VTU2xvdE51bWJlckFubm90YXRpb247AAAAAACAQAAAAgAAJ0xfRVNUeXBlSW5mb1JlY29yZDsAAAAAAAEAAAIAABdmdW5jX21haW5fMAATTF9HTE9CQUw7AAAAAAABAAECAAABAAAAAAEAAIgCAWUBAAACAAWRAQAABlgBAAAA7u4AABFpbnB1dC5qcwAVU2xvdE51bWJlcgAAAAEATAEAAAUAAAA3BwMhAERwRIFEkj4AAEgAAAIAPwEBAGEFPwICAGEGYAUqAwYAZQkLAQIQiQD/////DwAFwgIABhAAAACKAQAA diff --git a/es2panda/test/base64/inputString/expected.txt b/es2panda/test/base64/inputString/expected.txt index 9ee783b353dec5f39dd1f25f6d85678f784cd897..64fc8f414c58aeb00cc435edd05537f410f6e0c5 100644 --- a/es2panda/test/base64/inputString/expected.txt +++ b/es2panda/test/base64/inputString/expected.txt @@ -11,4 +11,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -UEFOREEAAAAAAAAACwAAAJQBAACMAAAAFQAAAAQAAAA8AAAAAQAAAJABAAAAAAAATAAAAAEAAABMAAAAuwAAAIwAAADhAAAADQEAAIwAAACUAQAAAgAAAHQAAAADAAAAfAAAAAAAAACIAAAAAQAAAIgAAAC7AAAADQEAAKEAAACvAAAAtgAAAD4BAAAnTF9FU1R5cGVBbm5vdGF0aW9uOwAZaGVsbG8gd29ybGQhAAtwcmludAAHc3RyADNMX0VTU2xvdE51bWJlckFubm90YXRpb247AAAAAACAQAAAAgAAJ0xfRVNUeXBlSW5mb1JlY29yZDsAAAAAAAEAAAIAABdmdW5jX21haW5fMAATTF9HTE9CQUw7AAAAAAABAAECAAABAAAAAAEAAIgCAVsBAAACAAWEAQAABk4BAAAA7u4AABVTbG90TnVtYmVyAAAAAQBCAQAABQAAADcHAyEARHBEgUSSPgAASAAAAgA/AQEAYQU/AgIAYQZgBSoDBgBlC2uJAP////8PAAEAAAAAAIABAAA= +UEFOREEAAAAAAAAACwABAJQBAACMAAAAFQAAAAQAAAA8AAAAAQAAAJABAAAAAAAATAAAAAEAAABMAAAAuwAAAIwAAADhAAAADQEAAIwAAACUAQAAAgAAAHQAAAADAAAAfAAAAAAAAACIAAAAAQAAAIgAAAC7AAAADQEAAKEAAACvAAAAtgAAAD4BAAAnTF9FU1R5cGVBbm5vdGF0aW9uOwAZaGVsbG8gd29ybGQhAAtwcmludAAHc3RyADNMX0VTU2xvdE51bWJlckFubm90YXRpb247AAAAAACAQAAAAgAAJ0xfRVNUeXBlSW5mb1JlY29yZDsAAAAAAAEAAAIAABdmdW5jX21haW5fMAATTF9HTE9CQUw7AAAAAAABAAECAAABAAAAAAEAAIgCAVsBAAACAAWEAQAABk4BAAAA7u4AABVTbG90TnVtYmVyAAAAAQBCAQAABQAAADcHAyEARHBEgUSSPgAASAAAAgA/AQEAYQU/AgIAYQZgBSoDBgBlC2uJAP////8PAAEAAAAAAIABAAA= diff --git a/es2panda/test/parser/sendable_class/sendable-class-field-type-expected.txt b/es2panda/test/parser/sendable_class/sendable-class-field-type-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..feb567d5370d0fcca8e9f593fe068a28f1a4362a --- /dev/null +++ b/es2panda/test/parser/sendable_class/sendable-class-field-type-expected.txt @@ -0,0 +1,177 @@ +.language ECMAScript + +.function any .Person(any a0, any a1, any a2) { +label_1: +label_0: + ldlexvar 0x0, 0x1 + callruntime.callinit 0x0, a2 + lda a2 + callruntime.notifyconcurrentresult + lda a2 + return +label_2: +} + +.function any .func_main_0(any a0, any a1, any a2) { +label_1: +label_0: + callruntime.newsendablelexenv 0x2 + callruntime.createsendableprivateproperty 0x1, _0 + ldhole + sta v0 + callruntime.definesendableclass 0x0, .Person, _2, 0x0, v0 + sta v0 + callruntime.definesendablemethod 0x1, .instance_initializer, 0x0 + stlexvar 0x0, 0x1 + poplexenv + lda v0 + sttoglobalrecord 0x2, Person + ldundefined + returnundefined +label_2: +} + +.function any .instance_initializer(any a0, any a1, any a2) { +label_1: +label_0: + ldundefined + definefieldbyname 0x0, name, a2 + ldundefined + callruntime.defineprivateproperty 0x2, 0x0, 0x0, a2 + ldundefined + definefieldbyname 0x4, mother, a2 + ldundefined + definefieldbyname 0x6, father, a2 + ldundefined + returnundefined +label_2: +} + + +======> literal array buffer <====== +------------------------------------ +slot _0 +{ + index: 0 + tag: 0 + val: 2 +}, +{ + index: 1 + tag: 2 + val: 0 +}, +------------------------------------ +slot _1 +{ + index: 0 + tag: 0 + val: 5 +}, +{ + index: 1 + tag: 5 + val: name +}, +{ + index: 2 + tag: 0 + val: 2 +}, +{ + index: 3 + tag: 2 + val: 2 +}, +{ + index: 4 + tag: 0 + val: 2 +}, +{ + index: 5 + tag: 2 + val: 0 +}, +{ + index: 6 + tag: 0 + val: 2 +}, +{ + index: 7 + tag: 2 + val: 1 +}, +{ + index: 8 + tag: 0 + val: 5 +}, +{ + index: 9 + tag: 5 + val: mother +}, +{ + index: 10 + tag: 0 + val: 2 +}, +{ + index: 11 + tag: 2 + val: 8 +}, +{ + index: 12 + tag: 0 + val: 5 +}, +{ + index: 13 + tag: 5 + val: father +}, +{ + index: 14 + tag: 0 + val: 2 +}, +{ + index: 15 + tag: 2 + val: 8 +}, +{ + index: 16 + tag: 0 + val: 2 +}, +{ + index: 17 + tag: 2 + val: 4 +}, +------------------------------------ +slot _2 +{ + index: 0 + tag: 0 + val: 2 +}, +{ + index: 1 + tag: 2 + val: 0 +}, +{ + index: 2 + tag: 0 + val: 24 +}, +{ + index: 3 + tag: 24 + val: _1 +}, diff --git a/es2panda/test/parser/sendable_class/sendable-class-field-type.ts b/es2panda/test/parser/sendable_class/sendable-class-field-type.ts new file mode 100644 index 0000000000000000000000000000000000000000..676d3b58f2734f41f1ffaa2710268dc86e8fa99a --- /dev/null +++ b/es2panda/test/parser/sendable_class/sendable-class-field-type.ts @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class Person { + name: string; + #age: number; + mother: Person; + father: Person; + constructor() { + "use sendable"; + } +} \ No newline at end of file diff --git a/es2panda/test/parser/sendable_class/sendable-class-getter-setter-expected.txt b/es2panda/test/parser/sendable_class/sendable-class-getter-setter-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..12ee7d8ee863f7321258b458f9e156be9739823a --- /dev/null +++ b/es2panda/test/parser/sendable_class/sendable-class-getter-setter-expected.txt @@ -0,0 +1,194 @@ +.language ECMAScript + +.function any .#14092125037830611713#Prop(any a0, any a1, any a2, any a3) { +label_1: +label_0: + lda a3 + stprivateproperty 0x0, 0x0, 0x0, a2 + ldundefined + callruntime.notifyconcurrentresult + returnundefined +label_2: +} + +.function any .A(any a0, any a1, any a2) { +label_1: +label_0: + ldlexvar 0x0, 0x1 + callruntime.callinit 0x0, a2 + lda a2 + callruntime.notifyconcurrentresult + lda a2 + return +label_2: +} + +.function any .Prop(any a0, any a1, any a2) { +label_1: +label_0: + lda a2 + ldprivateproperty 0x0, 0x0, 0x0 + sta v0 + callruntime.notifyconcurrentresult + lda v0 + return +label_2: +} + +.function any .func_main_0(any a0, any a1, any a2) { +label_1: +label_0: + callruntime.newsendablelexenv 0x2 + callruntime.createsendableprivateproperty 0x1, _0 + ldhole + sta v0 + callruntime.definesendableclass 0x0, .A, _2, 0x0, v0 + sta v0 + callruntime.definesendablemethod 0x1, .instance_initializer, 0x0 + stlexvar 0x0, 0x1 + poplexenv + lda v0 + sttoglobalrecord 0x2, A + ldundefined + returnundefined +label_2: +} + +.function any .instance_initializer(any a0, any a1, any a2) { +label_1: +label_0: + ldundefined + callruntime.defineprivateproperty 0x0, 0x0, 0x0, a2 + ldundefined + returnundefined +label_2: +} + + +======> literal array buffer <====== +------------------------------------ +slot _0 +{ + index: 0 + tag: 0 + val: 2 +}, +{ + index: 1 + tag: 2 + val: 0 +}, +------------------------------------ +slot _1 +{ + index: 0 + tag: 0 + val: 2 +}, +{ + index: 1 + tag: 2 + val: 0 +}, +{ + index: 2 + tag: 0 + val: 2 +}, +{ + index: 3 + tag: 2 + val: 2 +}, +{ + index: 4 + tag: 0 + val: 2 +}, +{ + index: 5 + tag: 2 + val: 1 +}, +------------------------------------ +slot _2 +{ + index: 0 + tag: 0 + val: 5 +}, +{ + index: 1 + tag: 5 + val: Prop +}, +{ + index: 2 + tag: 0 + val: 26 +}, +{ + index: 3 + tag: 26 + val: .Prop +}, +{ + index: 4 + tag: 0 + val: 9 +}, +{ + index: 5 + tag: 9 + val: 0 +}, +{ + index: 6 + tag: 0 + val: 5 +}, +{ + index: 7 + tag: 5 + val: Prop +}, +{ + index: 8 + tag: 0 + val: 27 +}, +{ + index: 9 + tag: 27 + val: .#14092125037830611713#Prop +}, +{ + index: 10 + tag: 0 + val: 9 +}, +{ + index: 11 + tag: 9 + val: 1 +}, +{ + index: 12 + tag: 0 + val: 2 +}, +{ + index: 13 + tag: 2 + val: 2 +}, +{ + index: 14 + tag: 0 + val: 24 +}, +{ + index: 15 + tag: 24 + val: _1 +}, diff --git a/es2panda/test/parser/sendable_class/sendable-class-getter-setter.ts b/es2panda/test/parser/sendable_class/sendable-class-getter-setter.ts new file mode 100644 index 0000000000000000000000000000000000000000..8dea2609a205803a3b38e49994677ee289758ea9 --- /dev/null +++ b/es2panda/test/parser/sendable_class/sendable-class-getter-setter.ts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A { + #prop: string; + constructor() { + "use sendable"; + } + get Prop() { + return this.#prop; + } + set Prop(prop: string) { + this.#prop = prop; + } +} \ No newline at end of file diff --git a/es2panda/test/runner.py b/es2panda/test/runner.py index 96e3a35c74dcd7691e0ce33e9e9db3d867bbf526..a6b63c7f94629ea7225cd75d7ce14536b001de1a 100755 --- a/es2panda/test/runner.py +++ b/es2panda/test/runner.py @@ -1520,6 +1520,7 @@ def main(): runner.add_directory("parser/binder", "js", ["--dump-assembly"]) runner.add_directory("parser/js/emptySource", "js", ["--dump-assembly"]) runner.add_directory("parser/js/language/arguments-object", "js", ["--parse-only"]) + runner.add_directory("parser/sendable_class", "ts", ["--dump-assembly", "--dump-literal-buffer"]) runners.append(runner) diff --git a/es2panda/util/helpers.cpp b/es2panda/util/helpers.cpp index 91cd6bd3e804b14c42ffbab80d7e0ab2b371ee1f..99f0eb71e3ff29244cff4814f8658090e436fb0e 100644 --- a/es2panda/util/helpers.cpp +++ b/es2panda/util/helpers.cpp @@ -723,7 +723,7 @@ bool Helpers::SetFuncFlagsForDirectives(const ir::StringLiteral *strLit, ir::Scr classDef->SetSendable(); func->AddFlag(ir::ScriptFunctionFlags::CONCURRENT); for (auto *stmt : classDef->Body()) { - if (stmt->IsMethodDefinition()){ + if (stmt->IsMethodDefinition()) { util::Concurrent::SetConcurrent(stmt->AsMethodDefinition()->Function(), strLit, lineIndex); } }