From 46dfcebc0e7dab82082ec69b80d029fda846d7c4 Mon Sep 17 00:00:00 2001 From: huyunhui Date: Mon, 15 Jan 2024 07:55:26 +0000 Subject: [PATCH 1/2] fix class tdz when class variable is used as lexical variable Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I8W8GF Signed-off-by: huyunhui Change-Id: Ic95da9bb7b94118b9417c47b381c60794a9ff4f8 --- es2panda/ir/base/classDefinition.cpp | 42 ++++++++++--------- es2panda/ir/base/methodDefinition.h | 11 +++++ .../test/compiler/js/class-tdz-2-expected.txt | 1 + es2panda/test/compiler/js/class-tdz-2.js | 24 +++++++++++ .../test/compiler/js/class-tdz-3-expected.txt | 1 + es2panda/test/compiler/js/class-tdz-3.js | 22 ++++++++++ 6 files changed, 82 insertions(+), 19 deletions(-) create mode 100644 es2panda/test/compiler/js/class-tdz-2-expected.txt create mode 100644 es2panda/test/compiler/js/class-tdz-2.js create mode 100644 es2panda/test/compiler/js/class-tdz-3-expected.txt create mode 100644 es2panda/test/compiler/js/class-tdz-3.js diff --git a/es2panda/ir/base/classDefinition.cpp b/es2panda/ir/base/classDefinition.cpp index 67d36bfe0b..a889c6f6ea 100644 --- a/es2panda/ir/base/classDefinition.cpp +++ b/es2panda/ir/base/classDefinition.cpp @@ -288,11 +288,7 @@ void ClassDefinition::CompileMissingProperties(compiler::PandaGen *pg, const uti continue; } - if (prop->IsPrivate()) { - continue; - } - - if (prop->IsAbstract()) { + if (prop->IsPrivate() || prop->IsAbstract()) { continue; } @@ -301,7 +297,8 @@ void ClassDefinition::CompileMissingProperties(compiler::PandaGen *pg, const uti switch (prop->Kind()) { case ir::MethodDefinitionKind::METHOD: { - compiler::Operand key = pg->ToPropertyKey(prop->Key(), prop->Computed()); + compiler::Operand key = prop->Computed() ? prop->KeyReg() : + pg->ToPropertyKey(prop->Key(), false); pg->LoadAccumulator(this, dest); const ir::FunctionExpression *func = prop->Value()->AsFunctionExpression(); @@ -312,7 +309,8 @@ void ClassDefinition::CompileMissingProperties(compiler::PandaGen *pg, const uti } case ir::MethodDefinitionKind::GET: case ir::MethodDefinitionKind::SET: { - compiler::VReg keyReg = pg->LoadPropertyKey(prop->Key(), prop->Computed()); + compiler::VReg keyReg = prop->Computed() ? prop->KeyReg() : + pg->LoadPropertyKey(prop->Key(), false); compiler::VReg undef = pg->AllocReg(); pg->LoadConst(this, compiler::Constant::JS_UNDEFINED); @@ -385,6 +383,15 @@ void ClassDefinition::CompileComputedKeys(compiler::PandaGen *pg) const pg->ToComputedPropertyKey(prop->Key()); pg->StoreLexicalVar(prop->Key(), 0, GetSlot(prop->Key())); } + } else if (stmt->IsMethodDefinition()) { + auto *methodDef = stmt->AsMethodDefinition(); + if (methodDef->Computed()) { + compiler::VReg keyReg = pg->AllocReg(); + methodDef->SetKeyReg(keyReg); + methodDef->Key()->Compile(pg); + pg->ToComputedPropertyKey(methodDef->Key()); + pg->StoreAccumulator(methodDef->Key(), keyReg); + } } } } @@ -409,6 +416,10 @@ void ClassDefinition::Compile(compiler::PandaGen *pg) const util::StringView ctorId = ctor_->Function()->Scope()->InternalName(); util::BitSet compiled(body_.size()); + if (hasComputedKey_) { + CompileComputedKeys(pg); + } + int32_t bufIdx = CreateClassPublicBuffer(pg, compiled); pg->DefineClassWithBuffer(this, ctorId, bufIdx, baseReg); @@ -422,10 +433,6 @@ void ClassDefinition::Compile(compiler::PandaGen *pg) const CompileMissingProperties(pg, compiled, classReg); - if (hasComputedKey_) { - CompileComputedKeys(pg); - } - if (hasPrivateElement_) { int32_t bufIdx = CreateClassPrivateBuffer(pg); pg->CreatePrivateProperty(this, scope_->privateFieldCnt_, bufIdx); @@ -492,6 +499,8 @@ void ClassDefinition::BuildClassEnvironment(bool useDefineSemantic) if (methodDef->IsPrivate()) { privateProperties.push_back(stmt); methodDef->IsStatic() ? staticPrivateMethodCnt ++ : instancePrivateMethodCnt++; + } else if (methodDef->Computed()) { + hasComputedKey_ = true; } continue; } @@ -503,22 +512,17 @@ void ClassDefinition::BuildClassEnvironment(bool useDefineSemantic) ASSERT(stmt->IsClassProperty()); const auto *prop = stmt->AsClassProperty(); - // Do not process non-static public fields when not using define semantic. if (!prop->IsPrivate() && !prop->IsStatic() && !useDefineSemantic) { continue; } + prop->IsStatic() ? needStaticInitializer_ = true : needInstanceInitializer_ = true; + if (prop->IsComputed() && prop->NeedCompileKey()) { hasComputedKey_ = true; scope_->AddClassVariable(prop->Key()); - } - if (prop->IsStatic()) { - needStaticInitializer_ = true; - } else { - needInstanceInitializer_ = true; - } - if (prop->Key()->IsPrivateIdentifier()) { + } else if (prop->IsPrivate()) { privateFieldCnt++; privateProperties.push_back(stmt); } diff --git a/es2panda/ir/base/methodDefinition.h b/es2panda/ir/base/methodDefinition.h index 217d886302..d5f9ce9085 100644 --- a/es2panda/ir/base/methodDefinition.h +++ b/es2panda/ir/base/methodDefinition.h @@ -151,6 +151,16 @@ public: overloads_.push_back(overload); } + void SetKeyReg(compiler::VReg keyReg) + { + keyReg_ = keyReg; + } + + compiler::VReg KeyReg() const + { + return keyReg_; + } + const ScriptFunction *Function() const; ScriptFunction *Function(); @@ -164,6 +174,7 @@ public: private: MethodDefinitionKind kind_; Expression *key_; + compiler::VReg keyReg_ {0}; FunctionExpression *value_; ModifierFlags modifiers_; ArenaVector overloads_; diff --git a/es2panda/test/compiler/js/class-tdz-2-expected.txt b/es2panda/test/compiler/js/class-tdz-2-expected.txt new file mode 100644 index 0000000000..499d2f8dc4 --- /dev/null +++ b/es2panda/test/compiler/js/class-tdz-2-expected.txt @@ -0,0 +1 @@ +ReferenceError diff --git a/es2panda/test/compiler/js/class-tdz-2.js b/es2panda/test/compiler/js/class-tdz-2.js new file mode 100644 index 0000000000..b687ce41d8 --- /dev/null +++ b/es2panda/test/compiler/js/class-tdz-2.js @@ -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. + */ + +try { + class A { + [A]() { + A; + }; + } +} catch (e) { + print(e.name); +} \ No newline at end of file diff --git a/es2panda/test/compiler/js/class-tdz-3-expected.txt b/es2panda/test/compiler/js/class-tdz-3-expected.txt new file mode 100644 index 0000000000..499d2f8dc4 --- /dev/null +++ b/es2panda/test/compiler/js/class-tdz-3-expected.txt @@ -0,0 +1 @@ +ReferenceError diff --git a/es2panda/test/compiler/js/class-tdz-3.js b/es2panda/test/compiler/js/class-tdz-3.js new file mode 100644 index 0000000000..e5f7a04694 --- /dev/null +++ b/es2panda/test/compiler/js/class-tdz-3.js @@ -0,0 +1,22 @@ +/* + * 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. + */ + +try { + class A { + [A] = ()=>{A;}; + } +} catch (e) { + print(e.name); +} \ No newline at end of file -- Gitee From 769f25771674f4191eb9e38e8ffa69e8e7563ade Mon Sep 17 00:00:00 2001 From: huyunhui Date: Tue, 16 Jan 2024 07:21:22 +0000 Subject: [PATCH 2/2] Signed-off-by: huyunhui Change-Id: I5029bd6e142c5adcf7e24c669ec7bd106b4b694a --- es2panda/ir/base/classDefinition.cpp | 51 +++++++++++++++------------- es2panda/ir/base/classDefinition.h | 1 + 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/es2panda/ir/base/classDefinition.cpp b/es2panda/ir/base/classDefinition.cpp index a889c6f6ea..040aee4556 100644 --- a/es2panda/ir/base/classDefinition.cpp +++ b/es2panda/ir/base/classDefinition.cpp @@ -309,29 +309,7 @@ void ClassDefinition::CompileMissingProperties(compiler::PandaGen *pg, const uti } case ir::MethodDefinitionKind::GET: case ir::MethodDefinitionKind::SET: { - compiler::VReg keyReg = prop->Computed() ? prop->KeyReg() : - pg->LoadPropertyKey(prop->Key(), false); - - compiler::VReg undef = pg->AllocReg(); - pg->LoadConst(this, compiler::Constant::JS_UNDEFINED); - pg->StoreAccumulator(this, undef); - - compiler::VReg getter = undef; - compiler::VReg setter = undef; - - pg->LoadAccumulator(this, dest); - - compiler::VReg accessor = pg->AllocReg(); - prop->Value()->Compile(pg); - pg->StoreAccumulator(prop->Value(), accessor); - - if (prop->Kind() == ir::MethodDefinitionKind::GET) { - getter = accessor; - } else { - setter = accessor; - } - - pg->DefineGetterSetterByValue(this, dest, keyReg, getter, setter, prop->Computed()); + CompileGetterOrSetter(pg, dest, prop); break; } default: { @@ -626,4 +604,31 @@ void ClassDefinition::CompileSendableClass(compiler::PandaGen *pg) const } } +void ClassDefinition::CompileGetterOrSetter(compiler::PandaGen *pg, compiler::VReg dest, + const MethodDefinition *prop) const +{ + compiler::VReg keyReg = prop->Computed() ? prop->KeyReg() : pg->LoadPropertyKey(prop->Key(), false); + + compiler::VReg undef = pg->AllocReg(); + pg->LoadConst(this, compiler::Constant::JS_UNDEFINED); + pg->StoreAccumulator(this, undef); + + compiler::VReg getter = undef; + compiler::VReg setter = undef; + + pg->LoadAccumulator(this, dest); + + compiler::VReg accessor = pg->AllocReg(); + prop->Value()->Compile(pg); + pg->StoreAccumulator(prop->Value(), accessor); + + if (prop->Kind() == ir::MethodDefinitionKind::GET) { + getter = accessor; + } else { + setter = accessor; + } + + pg->DefineGetterSetterByValue(this, dest, keyReg, getter, setter, prop->Computed()); +} + } // namespace panda::es2panda::ir diff --git a/es2panda/ir/base/classDefinition.h b/es2panda/ir/base/classDefinition.h index 86a584cbb5..5e3f461b12 100644 --- a/es2panda/ir/base/classDefinition.h +++ b/es2panda/ir/base/classDefinition.h @@ -248,6 +248,7 @@ private: void CompileComputedKeys(compiler::PandaGen *pg) const; int32_t CreateFieldTypeBuffer(compiler::PandaGen *pg) const; void CompileSendableClass(compiler::PandaGen *pg) const; + void CompileGetterOrSetter(compiler::PandaGen *pg, compiler::VReg dest, const MethodDefinition *prop) const; binder::ClassScope *scope_; Identifier *ident_; -- Gitee