From 7e500d16bd65715a2f66d24b02af5c8cf7f8a2fb Mon Sep 17 00:00:00 2001 From: weibaoxiang Date: Fri, 11 Jul 2025 19:10:20 +0800 Subject: [PATCH 1/2] napi_delete Change-Id: I0280ae98c6a80bc23ace6cc2c4af7471a597d699 --- ecmascript/dynamic_object_accessor.cpp | 18 +- ecmascript/dynamic_object_accessor.h | 14 +- ecmascript/dynamic_object_descriptor.cpp | 20 +- ecmascript/dynamic_object_descriptor.h | 17 +- ecmascript/dynamic_type_converter.cpp | 77 ++++- ecmascript/dynamic_type_converter.h | 4 +- ecmascript/js_tagged_value.h | 6 +- ecmascript/mem/cmc_gc/hooks.cpp | 3 +- ecmascript/tests/BUILD.gn | 33 +- .../tests/dynamic_type_converter_test.cpp | 297 ++++++++++++++++++ libark_jsruntime.map | 3 + test/resource/js_runtime/ohos_test.xml | 10 + 12 files changed, 453 insertions(+), 49 deletions(-) create mode 100644 ecmascript/tests/dynamic_type_converter_test.cpp diff --git a/ecmascript/dynamic_object_accessor.cpp b/ecmascript/dynamic_object_accessor.cpp index 43cdc5e47b..07e30d6e8d 100644 --- a/ecmascript/dynamic_object_accessor.cpp +++ b/ecmascript/dynamic_object_accessor.cpp @@ -39,24 +39,24 @@ bool DynamicObjectAccessor::HasProperty(ThreadHolder *thread, const BaseObject * return JSTaggedValue::HasProperty(jsThread, holderHandle, keyHandle); } -JSTaggedValue DynamicObjectAccessor::GetProperty(ThreadHolder *thread, const BaseObject *obj, const char *name) const +uint64_t DynamicObjectAccessor::GetProperty(ThreadHolder *thread, const BaseObject *obj, const char *name) const { JSThread *jsThread = thread->GetJSThread(); ObjectFactory *factory = jsThread->GetEcmaVM()->GetFactory(); [[maybe_unused]] EcmaHandleScope handleScope(jsThread); JSHandle holderHandle(jsThread, TaggedObject::Cast(obj)); JSHandle keyHandle(factory->NewFromUtf8(name)); - return JSTaggedValue::GetProperty(jsThread, holderHandle, keyHandle).GetValue().GetTaggedValue(); + return JSTaggedValue::GetProperty(jsThread, holderHandle, keyHandle).GetValue().GetTaggedValue().GetRawData(); } -bool DynamicObjectAccessor::SetProperty(ThreadHolder *thread, BaseObject *obj, const char *name, JSTaggedValue value) +bool DynamicObjectAccessor::SetProperty(ThreadHolder *thread, BaseObject *obj, const char *name, uint64_t value) { JSThread *jsThread = thread->GetJSThread(); ObjectFactory *factory = jsThread->GetEcmaVM()->GetFactory(); [[maybe_unused]] EcmaHandleScope handleScope(jsThread); JSHandle holderHandle(jsThread, TaggedObject::Cast(obj)); JSHandle keyHandle(factory->NewFromUtf8(name)); - JSHandle valueHandle(jsThread, value); + JSHandle valueHandle(jsThread, JSTaggedValue(value)); return JSTaggedValue::SetProperty(jsThread, holderHandle, keyHandle, valueHandle); } @@ -68,22 +68,22 @@ bool DynamicObjectAccessor::HasElementByIdx(ThreadHolder *thread, const BaseObje return JSTaggedValue::HasProperty(jsThread, holderHandle, index); } -JSTaggedValue DynamicObjectAccessor::GetElementByIdx(ThreadHolder *thread, const BaseObject *obj, - const uint32_t index) const +uint64_t DynamicObjectAccessor::GetElementByIdx(ThreadHolder *thread, const BaseObject *obj, + const uint32_t index) const { JSThread *jsThread = thread->GetJSThread(); [[maybe_unused]] EcmaHandleScope handleScope(jsThread); JSHandle holderHandle(jsThread, TaggedObject::Cast(obj)); - return JSTaggedValue::GetProperty(jsThread, holderHandle, index).GetValue().GetTaggedValue(); + return JSTaggedValue::GetProperty(jsThread, holderHandle, index).GetValue().GetTaggedValue().GetRawData(); } bool DynamicObjectAccessor::SetElementByIdx(ThreadHolder *thread, BaseObject *obj, - const uint32_t index, JSTaggedValue value) + const uint32_t index, uint64_t value) { JSThread *jsThread = thread->GetJSThread(); [[maybe_unused]] EcmaHandleScope handleScope(jsThread); JSHandle holderHandle(jsThread, TaggedObject::Cast(obj)); - JSHandle valueHandle(jsThread, value); + JSHandle valueHandle(jsThread, JSTaggedValue(value)); return JSTaggedValue::SetProperty(jsThread, holderHandle, index, valueHandle); } } \ No newline at end of file diff --git a/ecmascript/dynamic_object_accessor.h b/ecmascript/dynamic_object_accessor.h index 8c0d86b978..d7fbde1ff6 100644 --- a/ecmascript/dynamic_object_accessor.h +++ b/ecmascript/dynamic_object_accessor.h @@ -27,22 +27,22 @@ public: bool HasProperty(ThreadHolder *thread, const BaseObject *obj, const char *name) const override; - JSTaggedValue GetProperty(ThreadHolder *thread, const BaseObject *obj, - const char *name) const override; + uint64_t GetProperty(ThreadHolder *thread, const BaseObject *obj, + const char *name) const override; bool SetProperty(ThreadHolder *thread, BaseObject *obj, - const char *name, JSTaggedValue value) override; + const char *name, uint64_t value) override; bool HasElementByIdx(ThreadHolder *thread, const BaseObject *obj, const uint32_t index) const override; - JSTaggedValue GetElementByIdx(ThreadHolder *thread, - const BaseObject *obj, - const uint32_t index) const override; + uint64_t GetElementByIdx(ThreadHolder *thread, + const BaseObject *obj, + const uint32_t index) const override; bool SetElementByIdx(ThreadHolder *thread, BaseObject *obj, - const uint32_t index, JSTaggedValue value) override; + const uint32_t index, uint64_t value) override; private: static DynamicObjectAccessor dynObjectAccessor_; diff --git a/ecmascript/dynamic_object_descriptor.cpp b/ecmascript/dynamic_object_descriptor.cpp index 85fa874eb3..59446dbbaf 100644 --- a/ecmascript/dynamic_object_descriptor.cpp +++ b/ecmascript/dynamic_object_descriptor.cpp @@ -26,32 +26,32 @@ void DynamicObjectDescriptor::Initialize() BaseObjectDispatcher::GetDispatcher().RegisterDynamicObjectDescriptor(&dynObjectDescriptor_); } -std::pair DynamicObjectDescriptor::GetProperty(ThreadHolder *thread, - const BaseObject *obj, - const char *name) const +std::pair DynamicObjectDescriptor::GetProperty(ThreadHolder *thread, + const BaseObject *obj, + const char *name) const { - return std::make_pair(JSTaggedValue(), HandlerBase()); + return std::make_pair(JSTaggedValue::Undefined().GetRawData(), HandlerBase()); } std::pair DynamicObjectDescriptor::SetProperty(ThreadHolder *thread, BaseObject *obj, const char *name, - JSTaggedValue value) + uint64_t value) { return std::make_pair(false, HandlerBase()); } -std::pair DynamicObjectDescriptor::GetElementByIdx(ThreadHolder *thread, - const BaseObject *obj, - uint32_t index) const +std::pair DynamicObjectDescriptor::GetElementByIdx(ThreadHolder *thread, + const BaseObject *obj, + uint32_t index) const { - return std::make_pair(JSTaggedValue::Undefined(), HandlerBase()); + return std::make_pair(JSTaggedValue::Undefined().GetRawData(), HandlerBase()); } std::pair DynamicObjectDescriptor::SetElementByIdx(ThreadHolder *thread, BaseObject *obj, uint32_t index, - JSTaggedValue value) + uint64_t value) { return std::make_pair(false, HandlerBase()); } diff --git a/ecmascript/dynamic_object_descriptor.h b/ecmascript/dynamic_object_descriptor.h index bd114d337e..34e0f58b2d 100644 --- a/ecmascript/dynamic_object_descriptor.h +++ b/ecmascript/dynamic_object_descriptor.h @@ -25,18 +25,21 @@ class DynamicObjectDescriptor : public DynamicObjectDescriptorInterface { public: static void Initialize(); - std::pair GetProperty(ThreadHolder *thread, + std::pair GetProperty(ThreadHolder *thread, const BaseObject *obj, const char *name) const override; - std::pair SetProperty(ThreadHolder *thread, BaseObject *obj, const char *name, - JSTaggedValue value) override; + std::pair SetProperty(ThreadHolder *thread, + BaseObject *obj, const char *name, + uint64_t value) override; - std::pair GetElementByIdx(ThreadHolder *thread, const BaseObject *obj, - uint32_t index) const override; + std::pair GetElementByIdx(ThreadHolder *thread, const BaseObject *obj, + uint32_t index) const override; - std::pair SetElementByIdx(ThreadHolder *thread, BaseObject *obj, uint32_t index, - JSTaggedValue value) override; + std::pair SetElementByIdx(ThreadHolder *thread, + BaseObject *obj, + uint32_t index, + uint64_t value) override; private: static DynamicObjectDescriptor dynObjectDescriptor_; diff --git a/ecmascript/dynamic_type_converter.cpp b/ecmascript/dynamic_type_converter.cpp index 56ea0c5ec1..b593752acf 100644 --- a/ecmascript/dynamic_type_converter.cpp +++ b/ecmascript/dynamic_type_converter.cpp @@ -13,9 +13,12 @@ * limitations under the License. */ -#include "ecmascript/js_tagged_value.h" #include "ecmascript/dynamic_type_converter.h" +#include "ecmascript/js_bigint.h" +#include "ecmascript/js_tagged_value.h" +#include "ecmascript/js_tagged_value-inl.h" #include "common_interfaces/objects/base_object_dispatcher.h" +#include "common_interfaces/objects/base_type.h" namespace panda::ecmascript { @@ -26,16 +29,74 @@ void DynamicTypeConverter::Initialize() BaseObjectDispatcher::GetDispatcher().RegisterDynamicTypeConverter(&dynTypeConverter_); } -JSTaggedValue DynamicTypeConverter::WrapTagged([[maybe_unused]] ThreadHolder *thread, - [[maybe_unused]] PandaType value) +JSTaggedValue DynamicTypeConverter::WrapTagged(ThreadHolder *thread, PandaType value) { - // fixme(liuzhijie) - return JSTaggedValue::Undefined(); + JSTaggedValue result; + std::visit( + [&](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + result = JSTaggedValue::Hole(); + } else if constexpr (std::is_same_v) { + result = JSTaggedValue(arg); + } else if constexpr (std::is_same_v || std::is_same_v) { + result = JSTaggedValue(static_cast(arg)); + } else if constexpr (std::is_same_v) { + result = JSTaggedValue(arg); + } else if constexpr (std::is_integral_v) { + result = JSTaggedValue(static_cast(arg)); + } else if constexpr (std::is_floating_point_v) { + result = JSTaggedValue(static_cast(arg)); + } else if constexpr (std::is_same_v) { + result = JSTaggedValue::Undefined(); + } else if constexpr (std::is_same_v) { + result = JSTaggedValue::Null(); + } else if constexpr (std::is_same_v) { + BigInt* bigInt = *BigInt::CreateBigint(thread->GetJSThread(), arg.length); + bigInt->SetSign(arg.sign); + for (uint32_t i = 0; i < arg.length; i++) { + bigInt->SetDigit(i, arg.data[i]); + } + result = JSTaggedValue(static_cast(bigInt)); + } else if constexpr (std::is_same_v) { + result = JSTaggedValue(static_cast(arg)); + } else { + LOG_ECMA(FATAL) << "this branch is unreachable"; + UNREACHABLE(); + } + }, + value); + return result; } -PandaType DynamicTypeConverter::UnwrapTagged([[maybe_unused]] JSTaggedValue value) +PandaType DynamicTypeConverter::UnwrapTagged(JSTaggedValue value) { - // fixme(liuzhijie) - return PandaType(); + if (value.IsBoolean()) { + return value.ToBoolean(); + } else if (value.IsInt()) { + return static_cast(value.GetInt()); + } else if (value.IsDouble()) { + return static_cast(value.GetDouble()); + } else if (value.IsUndefined()) { + return BaseUndefined(); + } else if (value.IsNull()) { + return BaseNull(); + } else if (value.IsBigInt()) { + BigInt *bigInt = BigInt::Cast(value.GetTaggedObject()); + BaseBigInt baseBigInt; + baseBigInt.length = bigInt->GetLength(); + baseBigInt.sign = bigInt->GetSign(); + baseBigInt.data.resize(baseBigInt.length); + for (uint32_t i = 0; i < baseBigInt.length; i++) { + baseBigInt.data[i] = bigInt->GetDigit(i); + } + return baseBigInt; + } else if (value.IsHeapObject()) { + return static_cast(value.GetTaggedObject()); + } else { + LOG_ECMA(FATAL) << "this branch is unreachable"; + UNREACHABLE(); + } + return std::monostate(); } } \ No newline at end of file diff --git a/ecmascript/dynamic_type_converter.h b/ecmascript/dynamic_type_converter.h index 82f26bd6b0..9cff51f442 100644 --- a/ecmascript/dynamic_type_converter.h +++ b/ecmascript/dynamic_type_converter.h @@ -24,9 +24,9 @@ class DynamicTypeConverter : public DynamicTypeConverterInterface { public: static void Initialize(); - JSTaggedValue WrapTagged(ThreadHolder *thread, PandaType value) override; + uint64_t WrapTagged(ThreadHolder *thread, PandaType value) override; - PandaType UnwrapTagged(JSTaggedValue value) override; + PandaType UnwrapTagged(uint64_t value) override; private: static DynamicTypeConverter dynTypeConverter_; diff --git a/ecmascript/js_tagged_value.h b/ecmascript/js_tagged_value.h index 3e67714096..04f4b5b94e 100644 --- a/ecmascript/js_tagged_value.h +++ b/ecmascript/js_tagged_value.h @@ -404,7 +404,7 @@ public: // ecma6 7.1 Type Conversion static JSTaggedValue ToPrimitive(JSThread *thread, const JSHandle &tagged, PreferredPrimitiveType type = NO_PREFERENCE); - bool ToBoolean() const; + bool PUBLIC_API ToBoolean() const; static JSTaggedNumber ToNumber(JSThread *thread, JSTaggedValue tagged); static JSTaggedNumber ToNumber(JSThread *thread, const JSHandle &tagged); static JSTaggedValue ToBigInt(JSThread *thread, const JSHandle &tagged); @@ -515,7 +515,7 @@ public: bool IsCellRecord() const; bool IsJSRegExp() const; bool IsNumber() const; - bool IsBigInt() const; + bool PUBLIC_API IsBigInt() const; bool IsString() const; bool IsLineString() const; bool IsTreeString() const; @@ -537,7 +537,7 @@ public: bool IsNativePointer() const; bool IsJSNativePointer() const; bool CheckIsJSNativePointer() const; - bool IsBoolean() const; + bool PUBLIC_API IsBoolean() const; bool IsSymbol() const; bool IsJSObject() const; bool IsOnlyJSObject() const; diff --git a/ecmascript/mem/cmc_gc/hooks.cpp b/ecmascript/mem/cmc_gc/hooks.cpp index 2b2fd64b43..06c99de5e7 100644 --- a/ecmascript/mem/cmc_gc/hooks.cpp +++ b/ecmascript/mem/cmc_gc/hooks.cpp @@ -21,6 +21,7 @@ #include "ecmascript/ecma_vm.h" #include "ecmascript/ecma_global_storage.h" #include "ecmascript/free_object.h" +#include "ecmascript/js_tagged_value.h" #include "ecmascript/mem/object_xray.h" #include "ecmascript/mem/tagged_object.h" #include "ecmascript/mem/tagged_state_word.h" @@ -265,7 +266,7 @@ void JitFortUnProt(size_t size, void* base) bool IsMachineCodeObject(uintptr_t objPtr) { - JSTaggedValue value(objPtr); + ecmascript::JSTaggedValue value(objPtr); return value.IsMachineCodeObject(); } diff --git a/ecmascript/tests/BUILD.gn b/ecmascript/tests/BUILD.gn index 9ed06b6599..b1967b1808 100644 --- a/ecmascript/tests/BUILD.gn +++ b/ecmascript/tests/BUILD.gn @@ -151,6 +151,33 @@ host_unittest_action("JS_Dump_Test") { deps += hiviewdfx_deps } +host_unittest_action("JS_DynamicTypeConverter_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "dynamic_type_converter_test.cpp", + ] + + configs = [ + "../../:asm_interp_enable_config", + "../../:ecma_test_config", + ] + + deps = [ "../../:libark_jsruntime_test" ] + + # hiviewdfx libraries + external_deps = hiviewdfx_ext_deps + external_deps += [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "runtime_core:libarkassembler_static", + "runtime_core:libarkverifier", + "zlib:libz", + ] + deps += hiviewdfx_deps +} + host_unittest_action("ECMA_StringHash_Test") { module_out_path = module_output_path @@ -3605,7 +3632,8 @@ group("unittest") { ] deps += [ - ":Dynamic_Object_Accessor_Test" + ":Dynamic_Object_Accessor_Test", + ":JS_DynamicTypeConverter_Test", ] } } @@ -3912,7 +3940,8 @@ group("host_unittest") { ] deps += [ - ":Dynamic_Object_Accessor_TestAction" + ":Dynamic_Object_Accessor_TestAction", + ":JS_DynamicTypeConverter_TestAction", ] } } diff --git a/ecmascript/tests/dynamic_type_converter_test.cpp b/ecmascript/tests/dynamic_type_converter_test.cpp new file mode 100644 index 0000000000..b34b086687 --- /dev/null +++ b/ecmascript/tests/dynamic_type_converter_test.cpp @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2025 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. + */ + +#include "common_interfaces/objects/base_type.h" +#include "ecmascript/dynamic_type_converter.h" +#include "ecmascript/global_env.h" +#include "ecmascript/js_bigint.h" +#include "ecmascript/js_tagged_value.h" +#include "ecmascript/js_tagged_value-inl.h" +#include "ecmascript/tests/test_helper.h" +#include "common_interfaces/thread/thread_holder.h" +#include "common_interfaces/thread/thread_holder_manager.h" + +using namespace panda::ecmascript; + +namespace panda::test { +class DynamicTypeConverterTest : public BaseTestWithScope {}; + +static JSHandle JSObjectCreate(JSThread *thread) +{ + JSHandle globalEnv = thread->GetEcmaVM()->GetGlobalEnv(); + JSHandle objFun = globalEnv->GetObjectFunction(); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle obj = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); + return obj; +} + +/** + * @tc.name: WrapTagged_Test0 + * @tc.desc: Convert PandaType to DynamicType by converter. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(DynamicTypeConverterTest, WrapTagged_Test0) +{ + DynamicTypeConverter dynTypeConverter_; + ThreadHolder *threadHolder = thread->GetThreadHolder(); + // 1. Test monostate (empty variant) + { + PandaType value = std::monostate{}; + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsHole()); + } + // 2. Test boolean types + { + PandaType value = true; + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsTrue()); + } + { + PandaType value = false; + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsFalse()); + } + // 3. Test all integer types + // int8_t + { + PandaType value = static_cast(42); + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsInt()); + EXPECT_EQ(result.GetInt(), 42); + } + // uint8_t + { + PandaType value = static_cast(255); + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsInt()); + EXPECT_EQ(result.GetInt(), 255); + } + // int16_t + { + PandaType value = static_cast(32767); + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsInt()); + EXPECT_EQ(result.GetInt(), 32767); + } + // uint16_t + { + PandaType value = static_cast(65535); + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsInt()); + EXPECT_EQ(result.GetInt(), 65535); + } +} + +/** + * @tc.name: WrapTagged_Test1 + * @tc.desc: Convert PandaType to DynamicType by converter. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(DynamicTypeConverterTest, WrapTagged_Test1) +{ + DynamicTypeConverter dynTypeConverter_; + ThreadHolder *threadHolder = thread->GetThreadHolder(); + // int32_t + { + PandaType value = static_cast(2147483647); + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsInt()); + EXPECT_EQ(result.GetInt(), 2147483647); + } + // uint32_t (special case) + { + PandaType value = static_cast(4294967295); + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsDouble()); + } + // 4. Test floating point types + { + PandaType value = 3.14f; + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsDouble()); + EXPECT_FLOAT_EQ(result.GetDouble(), 3.14f); + } + { + PandaType value = 2.71828; + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsDouble()); + EXPECT_DOUBLE_EQ(result.GetDouble(), 2.71828); + } + // 5. Test 64-bit integers (converted to double) + { + PandaType value = static_cast(9223372036854775807LL); + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsDouble()); + EXPECT_DOUBLE_EQ(result.GetDouble(), 9223372036854775807.0); + } + { + PandaType value = static_cast(18446744073709551615ULL); + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsDouble()); + EXPECT_DOUBLE_EQ(result.GetDouble(), 18446744073709551615.0); + } +} + +/** + * @tc.name: WrapTagged_Test2 + * @tc.desc: Convert PandaType to DynamicType by converter. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(DynamicTypeConverterTest, WrapTagged_Test2) +{ + DynamicTypeConverter dynTypeConverter_; + ThreadHolder *threadHolder = thread->GetThreadHolder(); + // 6. Test undefined and null + { + PandaType value = BaseUndefined{}; + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsUndefined()); + } + { + PandaType value = BaseNull{}; + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_TRUE(result.IsNull()); + } + // 7. Test BigInt with new struct definition + { + BaseBigInt bigIntValue; + bigIntValue.length = 3; + bigIntValue.sign = true; // Negative value + bigIntValue.data = {0x12345678, 0x9ABCDEF0, 0x13579BDF}; + PandaType value = bigIntValue; + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + + EXPECT_TRUE(result.IsBigInt()); + BigInt* bigInt = BigInt::Cast(result.GetTaggedObject()); + // Verify BigInt properties + EXPECT_EQ(bigInt->GetLength(), bigIntValue.length); + EXPECT_EQ(bigInt->GetSign(), bigIntValue.sign); + + // Verify all digits were copied correctly + for (uint32_t i = 0; i < bigIntValue.length; i++) { + EXPECT_EQ(bigInt->GetDigit(i), bigIntValue.data[i]); + } + } + // 8. Test object type + { + JSHandle obj = JSObjectCreate(thread); + PandaType value = static_cast(obj.GetTaggedValue().GetTaggedObject()); + JSTaggedValue result = dynTypeConverter_.WrapTagged(threadHolder, value); + EXPECT_EQ(result, obj.GetTaggedValue()); + } +} + +/** + * @tc.name: UnwrapTagged0 + * @tc.desc: Convert DynamicType to PandaType by converter. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(DynamicTypeConverterTest, UnwrapTagged_Test0) +{ + DynamicTypeConverter dynTypeConverter_; + /* Boolean type tests */ + { + // Test boolean true + JSTaggedValue trueValue = JSTaggedValue::True(); + auto result = dynTypeConverter_.UnwrapTagged(trueValue); + EXPECT_TRUE(std::holds_alternative(result)); + EXPECT_TRUE(std::get(result)); + + // Test boolean false + JSTaggedValue falseValue = JSTaggedValue::False(); + result = dynTypeConverter_.UnwrapTagged(falseValue); + EXPECT_TRUE(std::holds_alternative(result)); + EXPECT_FALSE(std::get(result)); + } + /* Integer type tests */ + { + // Test positive integer + JSTaggedValue intValue(42); + auto result = dynTypeConverter_.UnwrapTagged(intValue); + EXPECT_TRUE(std::holds_alternative(result)); + EXPECT_EQ(std::get(result), 42); + + // Test negative integer + JSTaggedValue negativeIntValue(-123); + result = dynTypeConverter_.UnwrapTagged(negativeIntValue); + EXPECT_TRUE(std::holds_alternative(result)); + EXPECT_EQ(std::get(result), -123); + } + /* Double type tests */ + { + JSTaggedValue doubleValue(3.14159); + auto result = dynTypeConverter_.UnwrapTagged(doubleValue); + EXPECT_TRUE(std::holds_alternative(result)); + EXPECT_DOUBLE_EQ(std::get(result), 3.14159); + } +} + +/** + * @tc.name: UnwrapTagged1 + * @tc.desc: Convert DynamicType to PandaType by converter. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(DynamicTypeConverterTest, UnwrapTagged_Test1) +{ + DynamicTypeConverter dynTypeConverter_; + /* Undefined type tests */ + { + JSTaggedValue undefinedValue = JSTaggedValue::Undefined(); + auto result = dynTypeConverter_.UnwrapTagged(undefinedValue); + EXPECT_TRUE(std::holds_alternative(result)); + } + /* Null type tests */ + { + JSTaggedValue nullValue = JSTaggedValue::Null(); + auto result = dynTypeConverter_.UnwrapTagged(nullValue); + EXPECT_TRUE(std::holds_alternative(result)); + } + /* BigInt type tests */ + { + const uint32_t length = 2; + bool sign = false; + uint64_t digits[length] = {123456789, 987654321}; + BigInt* bigInt = *BigInt::CreateBigint(thread, length); + bigInt->SetSign(sign); + for (uint32_t i = 0; i < length; i++) { + bigInt->SetDigit(i, digits[i]); + } + JSTaggedValue bigIntValue(bigInt); + auto result = dynTypeConverter_.UnwrapTagged(bigIntValue); + + EXPECT_TRUE(std::holds_alternative(result)); + const BaseBigInt& baseBigInt = std::get(result); + + EXPECT_EQ(baseBigInt.length, length); + EXPECT_EQ(baseBigInt.sign, sign); + EXPECT_EQ(baseBigInt.data.size(), length); + for (uint32_t i = 0; i < length; i++) { + EXPECT_EQ(baseBigInt.data[i], digits[i]); + } + } + /* HeapObject type tests */ + { + JSHandle obj = JSObjectCreate(thread); + auto result = dynTypeConverter_.UnwrapTagged(obj.GetTaggedValue()); + EXPECT_TRUE(std::holds_alternative(result)); + EXPECT_EQ(std::get(result), static_cast(obj.GetTaggedValue().GetTaggedObject())); + } +} +} diff --git a/libark_jsruntime.map b/libark_jsruntime.map index f3ad4eeefe..290459c0b7 100644 --- a/libark_jsruntime.map +++ b/libark_jsruntime.map @@ -124,6 +124,7 @@ panda::ecmascript::AotCrashInfo*; panda::Log::*; panda::AndroidLog*; + panda::ecmascript::ThreadHolder::*; panda::ecmascript::Method::*; panda::ecmascript::JSPandaFileManager::*; panda::ecmascript::DebugInfoExtractor::*; @@ -250,6 +251,8 @@ panda::ecmascript::JSPandaFile::GetRecordNameWithBundlePack*; panda::ecmascript::JSProxy::IsArray*; panda::ecmascript::JSSharedMap::Set*; + panda::ecmascript::JSTaggedValue::IsBoolean*; + panda::ecmascript::JSTaggedValue::IsBigInt*; panda::ecmascript::JSTaggedValue::IsTaggedArray*; panda::ecmascript::JSTaggedValue::IsJSProxy*; panda::ecmascript::JSTaggedValue::IsJSCOWArray*; diff --git a/test/resource/js_runtime/ohos_test.xml b/test/resource/js_runtime/ohos_test.xml index fd3736f9a3..1476d6f263 100755 --- a/test/resource/js_runtime/ohos_test.xml +++ b/test/resource/js_runtime/ohos_test.xml @@ -3619,4 +3619,14 @@