diff --git a/BUILD.gn b/BUILD.gn index d2f02cbf76d5efbe65cb6fcd498e830194bee111..b012909891deb52689a90e174e84bf17884f9710 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1045,6 +1045,9 @@ ecma_source = [ "ecmascript/require/js_cjs_module_cache.cpp", "ecmascript/require/js_cjs_module.cpp", "ecmascript/require/js_require_manager.cpp", + "ecmascript/dynamic_object_accessor.cpp", + "ecmascript/dynamic_object_descriptor.cpp", + "ecmascript/dynamic_type_converter.cpp", ] # ecmascript use implement from common_components @@ -1317,9 +1320,6 @@ ohos_source_set("libcommon_components_set") { "common_components/serialize/serialize_utils.cpp", "common_components/thread/thread_holder.cpp", "common_components/thread/thread_holder_manager.cpp", - "ecmascript/dynamic_object_accessor.cpp", - "ecmascript/dynamic_object_descriptor.cpp", - "ecmascript/dynamic_type_converter.cpp", ] public_configs = [ "$js_root:ark_jsruntime_public_config" ] diff --git a/ecmascript/dynamic_object_accessor.cpp b/ecmascript/dynamic_object_accessor.cpp index 43cdc5e47b57cdc68d12ee08d1a2d9f37e162b77..d19f8dfaf2d2fe5e09bb6d02e0a8f925a5b8a6c6 100644 --- a/ecmascript/dynamic_object_accessor.cpp +++ b/ecmascript/dynamic_object_accessor.cpp @@ -19,6 +19,7 @@ #include "ecmascript/object_operator.h" #include "ecmascript/object_factory.h" #include "common_interfaces/objects/base_object_dispatcher.h" +#include "common_interfaces/objects/base_object_accessor.h" namespace panda::ecmascript { @@ -39,24 +40,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 +69,55 @@ 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); } + +} + +namespace panda { +PUBLIC_API uint64_t ZzmDynamicObjectAccessor::GetProperty(const BaseObject *obj, const char *name) +{ + JSThread *jsThread = JSThread::GetCurrent(); + + jsThread->ManagedCodeBegin(); + ecmascript::ObjectFactory *factory = jsThread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] ecmascript::EcmaHandleScope handleScope(jsThread); + ecmascript::JSHandle holderHandle(jsThread, ecmascript::TaggedObject::Cast(obj)); + ecmascript::JSHandle keyHandle(factory->NewFromUtf8(name)); + auto ret = ecmascript::JSTaggedValue::GetProperty(jsThread, holderHandle, keyHandle).GetValue().GetTaggedValue().GetRawData(); + jsThread->ManagedCodeEnd(); + return ret; +} + +PUBLIC_API bool ZzmDynamicObjectAccessor::SetProperty(BaseObject *obj, const char *name, uint64_t value) +{ + JSThread *jsThread = JSThread::GetCurrent(); + ecmascript::ObjectFactory *factory = jsThread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] ecmascript::EcmaHandleScope handleScope(jsThread); + ecmascript::JSHandle holderHandle(jsThread, ecmascript::TaggedObject::Cast(obj)); + ecmascript::JSHandle keyHandle(factory->NewFromUtf8(name)); + ecmascript::JSHandle valueHandle(jsThread, ecmascript::JSTaggedValue(value)); + return ecmascript::JSTaggedValue::SetProperty(jsThread, holderHandle, keyHandle, valueHandle); +} + +PUBLIC_API ObjectType ZzmDynamicObjectAccessor::GetJSType(panda::BaseObject *obj) +{ + return obj->GetBaseClass()->GetObjectType(); +} } \ No newline at end of file diff --git a/ecmascript/dynamic_object_accessor.h b/ecmascript/dynamic_object_accessor.h index 8c0d86b97833b58f2755d41f2aad52958d718c73..d7fbde1ff6f9b5d33d61115a6f015f914143328e 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 85fa874eb3031a1865d6b23aff39326a58dccd5c..59446dbbaf4add14982bfd108a4d667e6f74764c 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 bd114d337eb7a7eb991c40716ca7a2b386a7a2d7..34e0f58b2d41d6ef8c316b7f7358ed7019b35535 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 56ea0c5ec1376bb693d14f01d002a0e7b9b2ccb7..65a9f3b0b67e3eb65b2dcb7549e107ab08279792 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,75 @@ void DynamicTypeConverter::Initialize() BaseObjectDispatcher::GetDispatcher().RegisterDynamicTypeConverter(&dynTypeConverter_); } -JSTaggedValue DynamicTypeConverter::WrapTagged([[maybe_unused]] ThreadHolder *thread, - [[maybe_unused]] PandaType value) +uint64_t 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.GetRawData(); } -PandaType DynamicTypeConverter::UnwrapTagged([[maybe_unused]] JSTaggedValue value) +PandaType DynamicTypeConverter::UnwrapTagged(JSTaggedType rawValue) { - // fixme(liuzhijie) - return PandaType(); + JSTaggedValue value(rawValue); + 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 82f26bd6b05ac8171d99afc0ced19becec76dbba..9cff51f4420d6a192e5cf0c5990b2b0380b16494 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 3e67714096724249c15fc15b2f5e0a9cb12ae0b7..04f4b5b94eb77662d2e00833bad3f65acde0e52c 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 2b2fd64b436620a98cabaa59a976e3f8ba1245a6..06c99de5e746bb908b7dbf9203b48cfbe0e680a1 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 9ed06b659943f554c62983e6f58d592fdc572b99..b1967b18083c1a52427012d530ad61ecf0bed800 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 0000000000000000000000000000000000000000..b34b08668790f2e7a1304c64d1ee40a6a4717644 --- /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 f3ad4eeefe5e91d04e943174cea86813abc4f21c..290459c0b704f2e58c0c4f77e8eb90018573ecb9 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 fd3736f9a303f838764b6e1d9c455d5feb6ff56f..1476d6f2634cc654e67aa957eef00143f947b6bf 100755 --- a/test/resource/js_runtime/ohos_test.xml +++ b/test/resource/js_runtime/ohos_test.xml @@ -3619,4 +3619,14 @@