/* * Copyright (c) 2023-2024 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 #include "ecmascript/builtins/builtins.h" #include "ecmascript/builtins/builtins_function.h" #include "ecmascript/builtins/builtins_object.h" #include "ecmascript/compiler/aot_file/an_file_data_manager.h" #include "ecmascript/compiler/aot_file/aot_file_manager.h" #include "ecmascript/compiler/circuit_builder_helper.h" #include "ecmascript/deoptimizer/deoptimizer.h" #include "ecmascript/ecma_global_storage.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/global_env.h" #include "ecmascript/js_api/js_api_tree_map.h" #include "ecmascript/js_api/js_api_tree_set.h" #include "ecmascript/js_api/js_api_vector.h" #include "ecmascript/js_array.h" #include "ecmascript/js_bigint.h" #include "ecmascript/js_date_time_format.h" #include "ecmascript/js_generator_object.h" #include "ecmascript/js_map.h" #include "ecmascript/js_map_iterator.h" #include "ecmascript/js_object-inl.h" #include "ecmascript/js_primitive_ref.h" #include "ecmascript/js_regexp.h" #include "ecmascript/js_runtime_options.h" #include "ecmascript/js_set.h" #include "ecmascript/js_set_iterator.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/js_thread.h" #include "ecmascript/js_weak_container.h" #include "ecmascript/linked_hash_table.h" #include "ecmascript/mem/mem_map_allocator.h" #include "ecmascript/module/js_module_manager.h" #include "ecmascript/module/js_module_source_text.h" #include "ecmascript/napi/include/jsnapi.h" #include "ecmascript/napi/include/jsnapi_internals.h" #include "ecmascript/napi/jsnapi_helper.h" #include "ecmascript/object_factory.h" #include "ecmascript/pgo_profiler/pgo_profiler.h" #include "ecmascript/pgo_profiler/pgo_profiler_decoder.h" #include "ecmascript/pgo_profiler/pgo_profiler_encoder.h" #include "ecmascript/pgo_profiler/pgo_profiler_manager.h" #include "ecmascript/tagged_array.h" #include "ecmascript/tests/test_helper.h" #include "ecmascript/tagged_tree.h" #include "ecmascript/weak_vector.h" #include "ecmascript/regexp/regexp_parser.h" #include "gtest/gtest.h" #include "jsnapi_expo.h" using namespace panda; using namespace panda::ecmascript; using namespace panda::ecmascript::kungfu; static constexpr char TEST_CHAR_STRING_FLAGS[] = "gimsuy"; static constexpr char TEST_CHAR_STRING_STATE[] = "closed"; namespace panda::test { using BuiltinsFunction = ecmascript::builtins::BuiltinsFunction; using PGOProfilerManager = panda::ecmascript::pgo::PGOProfilerManager; using FunctionForRef = Local (*)(JsiRuntimeCallInfo *); class JSNApiTests : public testing::Test { public: static void SetUpTestCase() { GTEST_LOG_(INFO) << "SetUpTestCase"; } static void TearDownTestCase() { GTEST_LOG_(INFO) << "TearDownCase"; } void SetUp() override { RuntimeOption option; option.SetLogLevel(common::LOG_LEVEL::ERROR); vm_ = JSNApi::CreateJSVM(option); ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime"; thread_ = vm_->GetJSThread(); vm_->SetEnableForceGC(true); thread_->ManagedCodeBegin(); } void TearDown() override { thread_->ManagedCodeEnd(); vm_->SetEnableForceGC(false); JSNApi::DestroyJSVM(vm_); } template void TestNumberRef(T val, TaggedType expected) { LocalScope scope(vm_); Local obj = NumberRef::New(vm_, val); ASSERT_TRUE(obj->IsNumber()); JSTaggedType res = JSNApiHelper::ToJSTaggedValue(*obj).GetRawData(); ASSERT_EQ(res, expected); if constexpr (std::is_floating_point_v) { if (std::isnan(val)) { ASSERT_TRUE(std::isnan(obj->Value())); } else { ASSERT_EQ(obj->Value(), val); } } else if constexpr (sizeof(T) >= sizeof(int32_t)) { ASSERT_EQ(obj->IntegerValue(vm_), val); } else if constexpr (std::is_signed_v) { ASSERT_EQ(obj->Int32Value(vm_), val); } else { ASSERT_EQ(obj->Uint32Value(vm_), val); } } TaggedType ConvertDouble(double val) { return base::bit_cast(val) + JSTaggedValue::DOUBLE_ENCODE_OFFSET; } static void FakeReleaseSecureMemCallback(void* mapper) { if (mapper != nullptr) { delete reinterpret_cast(mapper); } } protected: JSThread *thread_ = nullptr; EcmaVM *vm_ = nullptr; }; Local FunctionCallback(JsiRuntimeCallInfo *info) { EscapeLocalScope scope(info->GetVM()); return scope.Escape(ArrayRef::New(info->GetVM(), info->GetArgsNumber())); } void WeakRefCallback(EcmaVM *vm) { LocalScope scope(vm); Local object = ObjectRef::New(vm); Global globalObject(vm, object); globalObject.SetWeak(); Local object1 = ObjectRef::New(vm); Global globalObject1(vm, object1); globalObject1.SetWeak(); vm->CollectGarbage(TriggerGCType::YOUNG_GC); vm->CollectGarbage(TriggerGCType::OLD_GC); globalObject.FreeGlobalHandleAddr(); } void ThreadCheck(const EcmaVM *vm) { EXPECT_TRUE(vm->GetJSThread()->GetThreadId() != JSThread::GetCurrentThreadId()); } HWTEST_F_L0(JSNApiTests, GetGlobalObject) { LocalScope scope(vm_); Local globalObject = JSNApi::GetGlobalObject(vm_); ASSERT_FALSE(globalObject.IsEmpty()); ASSERT_TRUE(globalObject->IsObject(vm_)); } HWTEST_F_L0(JSNApiTests, ThreadIdCheck) { EXPECT_TRUE(vm_->GetJSThread()->GetThreadId() == JSThread::GetCurrentThreadId()); } /** * @tc.number: ffi_interface_api_001 * @tc.name: RegisterFunction * @tc.desc:Through the FunctionRef:: New method, we can obtain a reference to the function, register and execute it, * confirm that the return value is an array, and the length of the array is the same as the length of * the passed in parameter list. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, RegisterFunction) { LocalScope scope(vm_); Local callback = FunctionRef::New(vm_, FunctionCallback); ASSERT_TRUE(!callback.IsEmpty()); std::vector> arguments; arguments.emplace_back(JSValueRef::Undefined(vm_)); Local result = callback->Call(vm_, JSValueRef::Undefined(vm_), arguments.data(), arguments.size()); ASSERT_TRUE(result->IsArray(vm_)); Local array(result); ASSERT_EQ(static_cast(array->Length(vm_)), arguments.size()); } HWTEST_F_L0(JSNApiTests, GetProperty) { LocalScope scope(vm_); Local globalObject = JSNApi::GetGlobalObject(vm_); ASSERT_FALSE(globalObject.IsEmpty()); ASSERT_TRUE(globalObject->IsObject(vm_)); Local key = StringRef::NewFromUtf8(vm_, "Number"); Local property = globalObject->Get(vm_, key); ASSERT_TRUE(property->IsFunction(vm_)); } HWTEST_F_L0(JSNApiTests, SetProperty) { LocalScope scope(vm_); Local globalObject = JSNApi::GetGlobalObject(vm_); ASSERT_FALSE(globalObject.IsEmpty()); ASSERT_TRUE(globalObject->IsObject(vm_)); Local property = ArrayRef::New(vm_, 3); // 3 : length ASSERT_TRUE(property->IsArray(vm_)); ASSERT_EQ(property->Length(vm_), 3U); // 3 : test case of input Local key = StringRef::NewFromUtf8(vm_, "Test"); bool result = globalObject->Set(vm_, key, property); ASSERT_TRUE(result); Local propertyGet = globalObject->Get(vm_, key); ASSERT_TRUE(propertyGet->IsArray(vm_)); ASSERT_EQ(Local(propertyGet)->Length(vm_), 3U); // 3 : test case of input } /** * @tc.number: ffi_interface_api_002 * @tc.name: JsonParser * @tc.desc:Construct a BufferRef function to determine whether it is a Get * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, JsonParser) { LocalScope scope(vm_); Local globalObject = JSNApi::GetGlobalObject(vm_); ASSERT_FALSE(globalObject.IsEmpty()); ASSERT_TRUE(globalObject->IsObject(vm_)); const char * const test { R"({"orientation": "portrait"})" }; Local jsonString = StringRef::NewFromUtf8(vm_, test); Local result = JSON::Parse(vm_, jsonString); ASSERT_TRUE(result->IsObject(vm_)); Local keyString = StringRef::NewFromUtf8(vm_, "orientation"); Local property = Local(result)->Get(vm_, keyString); ASSERT_TRUE(property->IsString(vm_)); } HWTEST_F_L0(JSNApiTests, StrictEqual) { LocalScope scope(vm_); Local origin = StringRef::NewFromUtf8(vm_, "1"); Local target1 = StringRef::NewFromUtf8(vm_, "1"); Local target = NumberRef::New(vm_, 1); ASSERT_FALSE(origin->IsStrictEquals(vm_, target)); ASSERT_TRUE(origin->IsStrictEquals(vm_, target1)); } /** * @tc.number: ffi_interface_api_003 * @tc.name: InstanceOf * @tc.desc:Verifying whether the InstanceOf method can correctly determine whether an object is an * instance of another object. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, InstanceOf) { LocalScope scope(vm_); Local target = FunctionRef::New(vm_, nullptr); Local origin = ArrayRef::New(vm_, 1); ASSERT_FALSE(origin->InstanceOf(vm_, target)); } HWTEST_F_L0(JSNApiTests, TypeOf) { LocalScope scope(vm_); Local origin = StringRef::NewFromUtf8(vm_, "1"); Local typeString = origin->Typeof(vm_); ASSERT_EQ(typeString->ToString(vm_), "string"); Local target = NumberRef::New(vm_, 1); typeString = target->Typeof(vm_); ASSERT_EQ(typeString->ToString(vm_), "number"); } /** * @tc.number: ffi_interface_api_004 * @tc.name: Symbol * @tc.desc: Determine if it is a symbol type * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, Symbol) { LocalScope scope(vm_); Local description = StringRef::NewFromUtf8(vm_, "test"); Local symbol = SymbolRef::New(vm_, description); ASSERT_FALSE(description->IsSymbol(vm_)); ASSERT_TRUE(symbol->IsSymbol(vm_)); } /** * @tc.number: ffi_interface_api_005 * @tc.name: StringUtf8_001 * @tc.desc: * Utf8Length:Read the non Chinese value length of StringRef according to utf8 type * WriteUtf8:Write the non Chinese value of StringRef to the char array buffer * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, StringUtf8_001) { LocalScope scope(vm_); std::string test = "Hello world"; Local testString = StringRef::NewFromUtf8(vm_, test.c_str()); EXPECT_EQ(testString->Utf8Length(vm_), 12); // 12 : length of testString("Hello World") char buffer[12]; // 12 : length of testString EXPECT_EQ(testString->WriteUtf8(vm_, buffer, 12), 12); // 12 : length of testString("Hello World") std::string res(buffer); ASSERT_EQ(res, test); } /** * @tc.number: ffi_interface_api_006 * @tc.name: StringUtf8_002 * @tc.desc: * Utf8Length:Read the non Chinese value length of StringRef according to utf8 type * WriteUtf8:Write the non Chinese value of StringRef to the char array buffer * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, StringUtf8_002) { LocalScope scope(vm_); std::string test = "年"; Local testString = StringRef::NewFromUtf8(vm_, test.c_str()); EXPECT_EQ(testString->Utf8Length(vm_), 4); // 4 : length of testString("年") char buffer[4]; // 4 : length of testString EXPECT_EQ(testString->WriteUtf8(vm_, buffer, 4), 4); // 4 : length of testString("年") std::string res(buffer); ASSERT_EQ(res, test); } HWTEST_F_L0(JSNApiTests, StringUtf8_003) { LocalScope scope(vm_); std::string str1 = "a"; std::string str2 = "b"; std::string test = str1 + '\0' + str2; // isWriteBuffer == false, \u0000 ==> C080 Local testString1 = StringRef::NewFromUtf8(vm_, test.c_str(), test.length()); EXPECT_EQ(testString1->Utf8Length(vm_, false), 5); char buffer1[4]; testString1->WriteUtf8(vm_, buffer1, 4, false); EXPECT_EQ(buffer1[0], 'a'); EXPECT_EQ(buffer1[1], '\xC0'); EXPECT_EQ(buffer1[2], '\x80'); EXPECT_EQ(buffer1[3], 'b'); // isWriteBuffer == true, \u0000 ==> 0x00U Local testString2 = StringRef::NewFromUtf8(vm_, test.c_str(), test.length()); EXPECT_EQ(testString2->Utf8Length(vm_, true), 4); char buffer2[4]; testString2->WriteUtf8(vm_, buffer2, 4, true); EXPECT_EQ(buffer2[0], 'a'); EXPECT_EQ(buffer2[1], '\0'); EXPECT_EQ(buffer2[2], 'b'); } HWTEST_F_L0(JSNApiTests, StringEncodeIntoUint8_001) { LocalScope scope(vm_); std::string test = ""; Local testString1 = StringRef::NewFromUtf8(vm_, test.c_str(), test.length()); Local typedArray = testString1->EncodeIntoUint8Array(vm_); EXPECT_TRUE(typedArray->IsUndefined()); } HWTEST_F_L0(JSNApiTests, StringEncodeIntoUint8_002) { LocalScope scope(vm_); std::string test = "abc123"; char excepted[7] = {0x61, 0x62, 0x63, 0x31, 0x32, 0x33, 0}; Local testString1 = StringRef::NewFromUtf8(vm_, test.c_str(), test.length()); Local typedArray = testString1->EncodeIntoUint8Array(vm_); char *res = reinterpret_cast(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_)); ASSERT_STREQ(res, excepted); } /** * @tc.number: ffi_interface_api_007 * @tc.name: StringLatin1_001 * @tc.desc: * WriteLatin1:Write the Chinese value of StringRef to the char array buffer * Length:Obtain the length of the Chinese value of StringRef * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, StringLatin1_001) { LocalScope scope(vm_); std::string test = "中"; Local testString = StringRef::NewFromUtf8(vm_, test.c_str()); EXPECT_EQ(testString->Length(vm_), 1U); char buffer[1]; EXPECT_EQ(testString->WriteLatin1(vm_, buffer, 1), 1); EXPECT_EQ(buffer[0], '-'); // '-' == 0x2D } /** * @tc.number: ffi_interface_api_008 * @tc.name: StringLatin1_002 * @tc.desc: * WriteLatin1:Write the non Chinese value of StringRef to the char array buffer * Length:Obtain the length of the non Chinese value of StringRef * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, StringLatin1_002) { LocalScope scope(vm_); std::string test = "En123"; Local testString = StringRef::NewFromUtf8(vm_, test.c_str()); EXPECT_EQ(testString->Length(vm_), 5U); char buffer[5]; EXPECT_EQ(testString->WriteLatin1(vm_, buffer, 5), 5); EXPECT_EQ(buffer[0], 'E'); EXPECT_EQ(buffer[1], 'n'); EXPECT_EQ(buffer[2], '1'); EXPECT_EQ(buffer[3], '2'); EXPECT_EQ(buffer[4], '3'); } /** * @tc.number: ffi_interface_api_009 * @tc.name: ToType * @tc.desc: * ToString:Obtain the length of the non Chinese value of StringRef * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, ToType) { LocalScope scope(vm_); Local toString = StringRef::NewFromUtf8(vm_, "-123.3"); Local toValue(toString); ASSERT_EQ(toString->ToNumber(vm_)->Value(), -123.3); // -123 : test case of input ASSERT_EQ(toString->ToBoolean(vm_)->Value(), true); ASSERT_EQ(toValue->ToString(vm_)->ToString(vm_), "-123.3"); ASSERT_TRUE(toValue->ToObject(vm_)->IsObject(vm_)); } HWTEST_F_L0(JSNApiTests, TypeValue) { LocalScope scope(vm_); Local toString = StringRef::NewFromUtf8(vm_, "-123"); Local toValue(toString); ASSERT_EQ(toString->Int32Value(vm_), -123); // -123 : test case of input ASSERT_EQ(toString->BooleaValue(vm_), true); ASSERT_EQ(toString->Uint32Value(vm_), 4294967173U); // 4294967173 : test case of input ASSERT_EQ(toString->IntegerValue(vm_), -123); // -123 : test case of input } void *Detach() { GTEST_LOG_(INFO) << "detach is running"; return nullptr; } void Attach([[maybe_unused]] int *buffer) { GTEST_LOG_(INFO) << "attach is running"; } static panda::JSNApi::NativeBindingInfo *CreateNativeBindingInfo(void *attach, void *detach) { GTEST_LOG_(INFO) << "CreateNativeBindingInfo"; panda::JSNApi::NativeBindingInfo *info = panda::JSNApi::NativeBindingInfo::CreateNewInstance(); info->attachData = attach; info->detachData = detach; return info; } HWTEST_F_L0(JSNApiTests, CreateNativeObject) { LocalScope scope(vm_); auto info = CreateNativeBindingInfo(reinterpret_cast(Attach), reinterpret_cast(Detach)); size_t nativeBindingSize = 7 * sizeof(void *); // 7 : params num Local nativeInfo = NativePointerRef::New( vm_, reinterpret_cast(info), []([[maybe_unused]] void *env, void *data, [[maybe_unused]] void *info) { auto externalInfo = reinterpret_cast(data); delete externalInfo; }, nullptr, nativeBindingSize); Local object = ObjectRef::New(vm_); ASSERT_FALSE(object->IsNativeBindingObject(vm_)); bool result = object->ConvertToNativeBindingObject(vm_, nativeInfo); ASSERT_TRUE(result); ASSERT_TRUE(object->IsNativeBindingObject(vm_)); Local nativeInfo1 = object->GetNativeBindingPointer(vm_); auto info1 = static_cast(nativeInfo1->Value()); ASSERT_EQ(info, info1); Local key = StringRef::NewFromUtf8(vm_, "TestKey"); Local value = ObjectRef::New(vm_); PropertyAttribute attribute(value, true, true, true); ASSERT_TRUE(object->DefineProperty(vm_, key, attribute)); Local value1 = object->Get(vm_, key); ASSERT_TRUE(value->IsStrictEquals(vm_, value1)); ASSERT_TRUE(object->Has(vm_, key)); ASSERT_TRUE(object->Delete(vm_, key)); ASSERT_FALSE(object->Has(vm_, key)); } /** * @tc.number: ffi_interface_api_010 * @tc.name: DefineProperty * @tc.desc: Set Key values and corresponding attribute values * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, DefineProperty) { LocalScope scope(vm_); Local object = ObjectRef::New(vm_); Local key = StringRef::NewFromUtf8(vm_, "TestKey"); Local value = ObjectRef::New(vm_); PropertyAttribute attribute(value, true, true, true); ASSERT_TRUE(object->DefineProperty(vm_, key, attribute)); Local value1 = object->Get(vm_, key); ASSERT_TRUE(value->IsStrictEquals(vm_, value1)); } HWTEST_F_L0(JSNApiTests, HasProperty) { LocalScope scope(vm_); Local object = ObjectRef::New(vm_); Local key = StringRef::NewFromUtf8(vm_, "TestKey"); Local value = ObjectRef::New(vm_); PropertyAttribute attribute(value, true, true, true); ASSERT_TRUE(object->DefineProperty(vm_, key, attribute)); ASSERT_TRUE(object->Has(vm_, key)); } HWTEST_F_L0(JSNApiTests, DeleteProperty) { LocalScope scope(vm_); Local object = ObjectRef::New(vm_); Local key = StringRef::NewFromUtf8(vm_, "TestKey"); Local value = ObjectRef::New(vm_); PropertyAttribute attribute(value, true, true, true); ASSERT_TRUE(object->DefineProperty(vm_, key, attribute)); ASSERT_TRUE(object->Delete(vm_, key)); ASSERT_FALSE(object->Has(vm_, key)); } /** * @tc.number: ffi_interface_api_011 * @tc.name: GetPrototype * @tc.desc:Verify that the GetPrototype method correctly returns the prototype of the function or object, * and verify that the returned prototype is of an object type. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, GetPrototype) { LocalScope scope(vm_); Local function = FunctionRef::New(vm_, nullptr); Local protoType = function->GetPrototype(vm_); ASSERT_TRUE(protoType->IsObject(vm_)); Local object = ObjectRef::New(vm_); protoType = object->GetPrototype(vm_); ASSERT_TRUE(protoType->IsObject(vm_)); auto info = CreateNativeBindingInfo(reinterpret_cast(Attach), reinterpret_cast(Detach)); size_t nativeBindingSize = 7 * sizeof(void *); // 7 : params num Local nativeInfo = NativePointerRef::New( vm_, reinterpret_cast(info), []([[maybe_unused]] void *env, void *data, [[maybe_unused]] void *info) { auto externalInfo = reinterpret_cast(data); delete externalInfo; }, nullptr, nativeBindingSize); bool result = object->ConvertToNativeBindingObject(vm_, nativeInfo); ASSERT_TRUE(result); protoType = object->GetPrototype(vm_); ASSERT_TRUE(protoType->IsObject(vm_)); } /* * @tc.number: ffi_interface_api_012 * @tc.name: CheckReject * @tc.desc: The function of CheckReject is similar to that of CheckResolve, * but it is used to check whether a function call provides the correct cause of the error, * which is achieved through ASSERT_ EQ (Local(reason) ->ToString(vm_), * check if the value of this string is equal to "Reject". * @tc.type: FUNC * @tc.require: parameter info */ void CheckReject(JsiRuntimeCallInfo *info) { ASSERT_EQ(info->GetArgsNumber(), 1U); Local reason = info->GetCallArgRef(0); ASSERT_TRUE(reason->IsString(info->GetVM())); ASSERT_EQ(Local(reason)->ToString(info->GetVM()), "Reject"); } Local RejectCallback(JsiRuntimeCallInfo *info) { LocalScope scope(info->GetVM()); CheckReject(info); return JSValueRef::Undefined(info->GetVM()); } HWTEST_F_L0(JSNApiTests, PromiseCatch) { LocalScope scope(vm_); Local capability = PromiseCapabilityRef::New(vm_); Local promise = capability->GetPromise(vm_); Local reject = FunctionRef::New(vm_, RejectCallback); Local catchPromise = promise->Catch(vm_, reject); ASSERT_TRUE(promise->IsPromise(vm_)); ASSERT_TRUE(catchPromise->IsPromise(vm_)); Local reason = StringRef::NewFromUtf8(vm_, "Reject"); ASSERT_TRUE(capability->Reject(vm_, reason)); vm_->ExecutePromisePendingJob(); } HWTEST_F_L0(JSNApiTests, PromiseCatchUintPtr) { LocalScope scope(vm_); Local capability = PromiseCapabilityRef::New(vm_); Local promise = capability->GetPromise(vm_); Local reject = FunctionRef::New(vm_, RejectCallback); Local catchPromise = promise->Catch(vm_, reject); ASSERT_TRUE(promise->IsPromise(vm_)); ASSERT_TRUE(catchPromise->IsPromise(vm_)); Local reason = StringRef::NewFromUtf8(vm_, "Reject"); ASSERT_TRUE(capability->Reject(vm_, reinterpret_cast(*reason))); vm_->ExecutePromisePendingJob(); } /* * @tc.number: ffi_interface_api_013 * @tc.name: CheckResolve_New_Reject * @tc.desc: Verify whether a specific function call provided the correct parameters (a number 300.3), * where ASSERT_ TRUE (value ->IsNumber()) Check if this parameter is a number. * New:Used to verify whether the creation of a new PromiseCapabilityRef object was successful. * Reject:Used to verify whether the reason for rejecting the Promise object was successfully obtained. * @tc.type: FUNC * @tc.require: parameter info */ void CheckResolve(JsiRuntimeCallInfo *info) { ASSERT_EQ(info->GetArgsNumber(), 1U); Local value = info->GetCallArgRef(0); ASSERT_TRUE(value->IsNumber()); ASSERT_EQ(Local(value)->Value(), 300.3); // 300.3 : test case of input } Local ResolvedCallback(JsiRuntimeCallInfo *info) { LocalScope scope(info->GetVM()); CheckResolve(info); return JSValueRef::Undefined(info->GetVM()); } HWTEST_F_L0(JSNApiTests, PromiseThen) { LocalScope scope(vm_); Local capability = PromiseCapabilityRef::New(vm_); Local promise = capability->GetPromise(vm_); Local resolve = FunctionRef::New(vm_, ResolvedCallback); Local reject = FunctionRef::New(vm_, RejectCallback); Local thenPromise = promise->Then(vm_, resolve, reject); ASSERT_TRUE(promise->IsPromise(vm_)); ASSERT_TRUE(thenPromise->IsPromise(vm_)); Local value = NumberRef::New(vm_, 300.3); // 300.3 : test case of input ASSERT_TRUE(capability->Resolve(vm_, value)); vm_->ExecutePromisePendingJob(); } HWTEST_F_L0(JSNApiTests, PromiseThenUintPtr) { LocalScope scope(vm_); Local capability = PromiseCapabilityRef::New(vm_); Local promise = capability->GetPromise(vm_); Local resolve = FunctionRef::New(vm_, ResolvedCallback); Local reject = FunctionRef::New(vm_, RejectCallback); Local thenPromise = promise->Then(vm_, resolve, reject); ASSERT_TRUE(promise->IsPromise(vm_)); ASSERT_TRUE(thenPromise->IsPromise(vm_)); Local value = NumberRef::New(vm_, 300.3); // 300.3 : test case of input ASSERT_TRUE(capability->Resolve(vm_, reinterpret_cast(*value))); vm_->ExecutePromisePendingJob(); } /** * @tc.number: ffi_interface_api_014 * @tc.name: Constructor_IsObject * @tc.desc: Used to verify whether the creation of a new PromiseCapabilityRef object was successful. * Used to verify whether obtaining a PromiseRef object was successful. IsObject:Determine if it is an object * @tc.type: FUNC * @tc.require: parameter isobject */ HWTEST_F_L0(JSNApiTests, Constructor_IsObject) { LocalScope scope(vm_); Local object = JSNApi::GetGlobalObject(vm_); Local key = StringRef::NewFromUtf8(vm_, "Number"); Local numberConstructor = object->Get(vm_, key); Local argv[1]; argv[0] = NumberRef::New(vm_, 1.3); // 1.3 : test case of input Local result = numberConstructor->Constructor(vm_, argv, 1); ASSERT_TRUE(result->IsObject(vm_)); ASSERT_EQ(result->ToNumber(vm_)->Value(), 1.3); // 1.3 : size of arguments } /** * @tc.number: ffi_interface_api_015 * @tc.name: Constructor_IsBuffer * @tc.desc: Construct a BufferRef function to determine whether it is a Buffer. * The constructor used to verify the success of the FunctionRef class. * @tc.type: FUNC * @tc.require: parameter parameter */ HWTEST_F_L0(JSNApiTests, ArrayBuffer) { LocalScope scope(vm_); const int32_t length = 15; Local arrayBuffer = ArrayBufferRef::New(vm_, length); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); ASSERT_EQ(arrayBuffer->ByteLength(vm_), length); ASSERT_NE(arrayBuffer->GetBuffer(vm_), nullptr); JSNApi::TriggerGC(vm_); } HWTEST_F_L0(JSNApiTests, ArrayBufferWithBuffer) { static bool isFree = false; struct Data { int32_t length; }; const int32_t length = 15; Data *data = new Data(); data->length = length; NativePointerCallback deleter = []([[maybe_unused]] void *env, void *buffer, void *data) -> void { delete[] reinterpret_cast(buffer); Data *currentData = reinterpret_cast(data); ASSERT_EQ(currentData->length, 15); // 5 : size of arguments delete currentData; isFree = true; }; { LocalScope scope(vm_); uint8_t *buffer = new uint8_t[length](); Local arrayBuffer = ArrayBufferRef::New(vm_, buffer, length, deleter, data); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); ASSERT_EQ(arrayBuffer->ByteLength(vm_), length); ASSERT_EQ(arrayBuffer->GetBuffer(vm_), buffer); } JSNApi::TriggerGC(vm_, JSNApi::TRIGGER_GC_TYPE::FULL_GC); ASSERT_TRUE(isFree); } HWTEST_F_L0(JSNApiTests, DataView) { LocalScope scope(vm_); const int32_t length = 15; Local arrayBuffer = ArrayBufferRef::New(vm_, length); JSNApi::TriggerGC(vm_); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); // 5 : offset of byte, 7 : length Local dataView = DataViewRef::New(vm_, arrayBuffer, 5, 7); ASSERT_TRUE(dataView->IsDataView(vm_)); ASSERT_EQ(dataView->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_)); ASSERT_EQ(dataView->ByteLength(), 7U); // 7 : size of arguments ASSERT_EQ(dataView->ByteOffset(), 5U); // 5 : size of arguments // 5 : offset of byte, 11 : length dataView = DataViewRef::New(vm_, arrayBuffer, 5, 11); ASSERT_TRUE(dataView->IsUndefined()); } /** * @tc.number: ffi_interface_api_016 * @tc.name: Int8Array_IsUndefined * @tc.desc:Using the functions of Int8Array and verifying if its attribute values are correct. * Used to determine whether a given object represents an undefined value. Determine if it is an int8 array. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, Int8Array) { LocalScope scope(vm_); const int32_t length = 15; Local arrayBuffer = ArrayBufferRef::New(vm_, length); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); // 5 : offset of byte, 6 : length Local typedArray = Int8ArrayRef::New(vm_, arrayBuffer, 5, 6); ASSERT_TRUE(typedArray->IsInt8Array(vm_)); ASSERT_EQ(typedArray->ByteLength(vm_), 6U); // 6 : length of bytes ASSERT_EQ(typedArray->ByteOffset(vm_), 5U); // 5 : offset of byte ASSERT_EQ(typedArray->ArrayLength(vm_), 6U); // 6 : length of array ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_)); } /** * @tc.number: ffi_interface_api_017 * @tc.name: Uint8Array_ ByteLength_ByteOffset_ArrayLength_GetArrayBuffer * @tc.desc:Using the functions of Uint8Array and verifying if its attribute values are correct. * Used to verify whether the length, offset, array length, and associated * ArrayBufferRef object of the bytes obtained from the array were successful. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, Uint8Array) { LocalScope scope(vm_); const int32_t length = 15; Local arrayBuffer = ArrayBufferRef::New(vm_, length); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); // 5 : offset of byte, 6 : length Local typedArray = Uint8ArrayRef::New(vm_, arrayBuffer, 5, 6); ASSERT_TRUE(typedArray->IsUint8Array(vm_)); ASSERT_EQ(typedArray->ByteLength(vm_), 6U); // 6 : length of bytes ASSERT_EQ(typedArray->ByteOffset(vm_), 5U); // 5 : offset of byte ASSERT_EQ(typedArray->ArrayLength(vm_), 6U); // 6 : length of array ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_)); } /** * @tc.number: ffi_interface_api_018 * @tc.name: Uint8ClampedArray * @tc.desc:Using the functions of Uint8ClampedArray and verifying if its attribute values are correct. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, Uint8ClampedArray) { LocalScope scope(vm_); const int32_t length = 15; Local arrayBuffer = ArrayBufferRef::New(vm_, length); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); // 5 : offset of byte, 6 : length Local typedArray = Uint8ClampedArrayRef::New(vm_, arrayBuffer, 5, 6); ASSERT_TRUE(typedArray->IsUint8ClampedArray(vm_)); ASSERT_EQ(typedArray->ByteLength(vm_), 6U); // 6 : length of bytes ASSERT_EQ(typedArray->ByteOffset(vm_), 5U); // 5 : offset of byte ASSERT_EQ(typedArray->ArrayLength(vm_), 6U); // 6 : length of array ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_)); } /** * @tc.number: ffi_interface_api_019 * @tc.name: Int16Array * @tc.desc:Using the functions of Int16Array and verifying if its attribute values are correct. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, Int16Array) { LocalScope scope(vm_); const int32_t length = 30; Local arrayBuffer = ArrayBufferRef::New(vm_, length); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); // 4 : offset of byte, 6 : length Local typedArray = Int16ArrayRef::New(vm_, arrayBuffer, 4, 6); ASSERT_TRUE(typedArray->IsInt16Array(vm_)); ASSERT_EQ(typedArray->ByteLength(vm_), 12U); // 12 : length of bytes ASSERT_EQ(typedArray->ByteOffset(vm_), 4U); // 4 : offset of byte ASSERT_EQ(typedArray->ArrayLength(vm_), 6U); // 6 : length of array ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_)); } /** * @tc.number: ffi_interface_api_020 * @tc.name: Uint16Array * @tc.desc:Using the functions of Uint16Array and verifying if its attribute values are correct. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, Uint16Array) { LocalScope scope(vm_); const int32_t length = 30; Local arrayBuffer = ArrayBufferRef::New(vm_, length); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); // 4 : offset of byte, 6 : length Local typedArray = Uint16ArrayRef::New(vm_, arrayBuffer, 4, 6); ASSERT_TRUE(typedArray->IsUint16Array(vm_)); ASSERT_EQ(typedArray->ByteLength(vm_), 12U); // 12 : length of bytes ASSERT_EQ(typedArray->ByteOffset(vm_), 4U); // 4 : offset of byte ASSERT_EQ(typedArray->ArrayLength(vm_), 6U); // 6 : length of array ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_)); } /* * @tc.number: ffi_interface_api_021 * @tc.name: Uint32Array * @tc.desc: Verify that the Uint32Array method correctly created a Uint32Array with the specified length and offset, * and verify that its attribute values match expectations. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, Uint32Array) { LocalScope scope(vm_); const int32_t length = 30; Local arrayBuffer = ArrayBufferRef::New(vm_, length); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); // 4 : offset of byte, 6 : length Local typedArray = Uint32ArrayRef::New(vm_, arrayBuffer, 4, 6); ASSERT_TRUE(typedArray->IsUint32Array(vm_)); ASSERT_EQ(typedArray->ByteLength(vm_), 24U); // 24 : length of bytes ASSERT_EQ(typedArray->ByteOffset(vm_), 4U); // 4 : offset of byte ASSERT_EQ(typedArray->ArrayLength(vm_), 6U); // 6 : length of array ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_)); } /** * @tc.number: ffi_interface_api_022 * @tc.name: Int32Array * @tc.desc:Using the functions of Int32Array and verifying if its attribute values are correct. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, Int32Array) { LocalScope scope(vm_); const int32_t length = 30; Local arrayBuffer = ArrayBufferRef::New(vm_, length); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); // 4 : offset of byte, 6 : length Local typedArray = Int32ArrayRef::New(vm_, arrayBuffer, 4, 6); ASSERT_TRUE(typedArray->IsInt32Array(vm_)); ASSERT_EQ(typedArray->ByteLength(vm_), 24U); // 24 : length of bytes ASSERT_EQ(typedArray->ByteOffset(vm_), 4U); // 4 : offset of byte ASSERT_EQ(typedArray->ArrayLength(vm_), 6U); // 6 : length of array ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_)); } HWTEST_F_L0(JSNApiTests, Float32Array) { LocalScope scope(vm_); const int32_t length = 30; Local arrayBuffer = ArrayBufferRef::New(vm_, length); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); // 4 : offset of byte, 6 : length Local typedArray = Float32ArrayRef::New(vm_, arrayBuffer, 4, 6); ASSERT_TRUE(typedArray->IsFloat32Array(vm_)); ASSERT_EQ(typedArray->ByteLength(vm_), 24U); // 24 : length of bytes ASSERT_EQ(typedArray->ByteOffset(vm_), 4U); // 4 : offset of byte ASSERT_EQ(typedArray->ArrayLength(vm_), 6U); // 6 : length of array ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_)); } HWTEST_F_L0(JSNApiTests, Float64Array) { LocalScope scope(vm_); const int32_t length = 57; Local arrayBuffer = ArrayBufferRef::New(vm_, length); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); // 8 : offset of byte, 6 : length Local typedArray = Float64ArrayRef::New(vm_, arrayBuffer, 8, 6); ASSERT_TRUE(typedArray->IsFloat64Array(vm_)); ASSERT_EQ(typedArray->ByteLength(vm_), 48U); // 48 : length of bytes ASSERT_EQ(typedArray->ByteOffset(vm_), 8U); // 8 : offset of byte ASSERT_EQ(typedArray->ArrayLength(vm_), 6U); // 6 : length of array ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_)); } HWTEST_F_L0(JSNApiTests, BigInt64Array) { LocalScope scope(vm_); const int32_t length = 57; Local arrayBuffer = ArrayBufferRef::New(vm_, length); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); // 8 : offset of byte, 6 : length Local typedArray = BigInt64ArrayRef::New(vm_, arrayBuffer, 8, 6); ASSERT_TRUE(typedArray->IsBigInt64Array(vm_)); ASSERT_EQ(typedArray->ByteLength(vm_), 48U); // 48 : length of bytes ASSERT_EQ(typedArray->ByteOffset(vm_), 8U); // 8 : offset of byte ASSERT_EQ(typedArray->ArrayLength(vm_), 6U); // 6 : length of array ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_)); } /** * @tc.number: ffi_interface_api_023 * @tc.name: IsBigInt64Array * @tc.desc: Used to determine whether a given object is a BigInt64Array. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, BigUint64Array) { LocalScope scope(vm_); const int32_t length = 57; Local arrayBuffer = ArrayBufferRef::New(vm_, length); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); // 8 : offset of byte, 6 : length Local typedArray = BigUint64ArrayRef::New(vm_, arrayBuffer, 8, 6); ASSERT_TRUE(typedArray->IsBigUint64Array(vm_)); ASSERT_EQ(typedArray->ByteLength(vm_), 48U); // 48 : length of bytes ASSERT_EQ(typedArray->ByteOffset(vm_), 8U); // 8 : offset of byte ASSERT_EQ(typedArray->ArrayLength(vm_), 6U); // 6 : length of array ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_)); } /** * @tc.number: ffi_interface_api_024 * @tc.name: Error_ThrowException_HasPendingException * @tc.desc: * Error:Build error message * ThrowException:Throw an exception, error is the exception information * HasPendingException:Determine if there are any uncaught exceptions * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, Error_ThrowException_HasPendingException) { LocalScope scope(vm_); Local message = StringRef::NewFromUtf8(vm_, "ErrorTest"); Local error = Exception::Error(vm_, message); ASSERT_TRUE(error->IsError(vm_)); JSNApi::ThrowException(vm_, error); ASSERT_TRUE(thread_->HasPendingException()); } HWTEST_F_L0(JSNApiTests, RangeError) { LocalScope scope(vm_); Local message = StringRef::NewFromUtf8(vm_, "ErrorTest"); Local error = Exception::RangeError(vm_, message); ASSERT_TRUE(error->IsError(vm_)); JSNApi::ThrowException(vm_, error); ASSERT_TRUE(thread_->HasPendingException()); } /** * @tc.number: ffi_interface_api_025 * @tc.name: TypeError * @tc.desc:Tested the ability to create and throw a type error exception, and verified whether the exception * was correctly recognized and handled. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, TypeError) { LocalScope scope(vm_); Local message = StringRef::NewFromUtf8(vm_, "ErrorTest"); Local error = Exception::TypeError(vm_, message); ASSERT_TRUE(error->IsError(vm_)); JSNApi::ThrowException(vm_, error); ASSERT_TRUE(thread_->HasPendingException()); } HWTEST_F_L0(JSNApiTests, ReferenceError) { LocalScope scope(vm_); Local message = StringRef::NewFromUtf8(vm_, "ErrorTest"); Local error = Exception::ReferenceError(vm_, message); ASSERT_TRUE(error->IsError(vm_)); JSNApi::ThrowException(vm_, error); ASSERT_TRUE(thread_->HasPendingException()); } HWTEST_F_L0(JSNApiTests, SyntaxError) { LocalScope scope(vm_); Local message = StringRef::NewFromUtf8(vm_, "ErrorTest"); Local error = Exception::SyntaxError(vm_, message); ASSERT_TRUE(error->IsError(vm_)); JSNApi::ThrowException(vm_, error); ASSERT_TRUE(thread_->HasPendingException()); } /** * @tc.number: ffi_interface_api_026 * @tc.name: OOMError * @tc.desc:Create and throw a memory overflow error exception function, and verify * whether the exception is correctly recognized and handled. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, OOMError) { LocalScope scope(vm_); Local message = StringRef::NewFromUtf8(vm_, "ErrorTest"); Local error = Exception::OOMError(vm_, message); ASSERT_TRUE(error->IsError(vm_)); JSNApi::ThrowException(vm_, error); ASSERT_TRUE(thread_->HasPendingException()); } HWTEST_F_L0(JSNApiTests, InheritPrototype_001) { ecmascript::ThreadManagedScope managedScope(vm_->GetJSThread()); LocalScope scope(vm_); JSHandle env = vm_->GetGlobalEnv(); // new with Builtins::Set Prototype JSHandle set = env->GetBuiltinsSetFunction(); Local setLocal = JSNApiHelper::ToLocal(set); // new with Builtins::Map Prototype JSHandle map = env->GetBuiltinsMapFunction(); Local mapLocal = JSNApiHelper::ToLocal(map); JSHandle setPrototype(thread_, JSHandle::Cast(set)->GetFunctionPrototype(thread_)); JSHandle mapPrototype(thread_, JSHandle::Cast(map)->GetFunctionPrototype(thread_)); JSHandle mapPrototypeProto(thread_, JSTaggedValue::GetPrototype(thread_, mapPrototype)); bool same = JSTaggedValue::SameValue(thread_, setPrototype, mapPrototypeProto); // before inherit, map.Prototype.__proto__ should be different from set.Prototype ASSERT_FALSE(same); // before inherit, map.__proto__ should be different from set JSHandle mapProto(thread_, JSTaggedValue::GetPrototype(thread_, map)); bool same1 = JSTaggedValue::SameValue(thread_, set, mapProto); ASSERT_FALSE(same1); // Set property to Set Function auto factory = vm_->GetFactory(); JSHandle defaultString = thread_->GlobalConstants()->GetHandledDefaultString(); PropertyDescriptor desc = PropertyDescriptor(thread_, defaultString); bool success = JSObject::DefineOwnProperty(thread_, JSHandle::Cast(set), defaultString, desc); ASSERT_TRUE(success); JSHandle property1String(thread_, factory->NewFromASCII("property1").GetTaggedValue()); JSHandle func = env->GetTypedArrayFunction(); PropertyDescriptor desc1 = PropertyDescriptor(thread_, func); bool success1 = JSObject::DefineOwnProperty(thread_, JSHandle::Cast(set), property1String, desc1); ASSERT_TRUE(success1); mapLocal->Inherit(vm_, setLocal); JSHandle sonHandle = JSNApiHelper::ToJSHandle(mapLocal); JSHandle sonPrototype(thread_, JSHandle::Cast(sonHandle)->GetFunctionPrototype(thread_)); JSHandle sonPrototypeProto(thread_, JSTaggedValue::GetPrototype(thread_, sonPrototype)); bool same2 = JSTaggedValue::SameValue(thread_, setPrototype, sonPrototypeProto); ASSERT_TRUE(same2); JSHandle sonProto(thread_, JSTaggedValue::GetPrototype(thread_, map)); bool same3 = JSTaggedValue::SameValue(thread_, set, sonProto); ASSERT_TRUE(same3); // son = new Son(), Son() inherit from Parent(), Test whether son.InstanceOf(Parent) is true JSHandle sonObj = factory->NewJSObjectByConstructor(JSHandle::Cast(sonHandle), sonHandle); bool isInstance = JSObject::InstanceOf(thread_, JSHandle::Cast(sonObj), set); ASSERT_TRUE(isInstance); // Test whether son Function can access to property of parent Function OperationResult res = JSObject::GetProperty(thread_, JSHandle::Cast(sonHandle), defaultString); bool same4 = JSTaggedValue::SameValue(thread_, defaultString, res.GetValue()); ASSERT_TRUE(same4); OperationResult res1 = JSObject::GetProperty(thread_, JSHandle::Cast(sonHandle), property1String); bool same5 = JSTaggedValue::SameValue(thread_, func, res1.GetValue()); ASSERT_TRUE(same5); // new with empty Function Constructor Local son1 = FunctionRef::New(vm_, FunctionCallback, nullptr); son1->Inherit(vm_, mapLocal); JSHandle son1Handle = JSHandle::Cast(JSNApiHelper::ToJSHandle(son1)); ASSERT_TRUE(son1Handle->HasFunctionPrototype(thread_)); } HWTEST_F_L0(JSNApiTests, InheritPrototype_002) { ecmascript::ThreadManagedScope managedScope(vm_->GetJSThread()); LocalScope scope(vm_); JSHandle env = vm_->GetGlobalEnv(); // new with Builtins::weakSet Prototype JSHandle weakSet = env->GetBuiltinsWeakSetFunction(); Local weakSetLocal = JSNApiHelper::ToLocal(weakSet); // new with Builtins::weakMap Prototype JSHandle weakMap = env->GetBuiltinsWeakMapFunction(); Local weakMapLocal = JSNApiHelper::ToLocal(weakMap); weakMapLocal->Inherit(vm_, weakSetLocal); auto factory = vm_->GetFactory(); JSHandle property1String(thread_, factory->NewFromASCII("property1").GetTaggedValue()); JSHandle func = env->GetArrayFunction(); PropertyDescriptor desc1 = PropertyDescriptor(thread_, func); bool success1 = JSObject::DefineOwnProperty(thread_, JSHandle::Cast(weakMap), property1String, desc1); ASSERT_TRUE(success1); JSHandle sonHandle = JSNApiHelper::ToJSHandle(weakMapLocal); JSHandle sonObj = factory->NewJSObjectByConstructor(JSHandle::Cast(sonHandle), sonHandle); JSHandle fatherHandle = JSNApiHelper::ToJSHandle(weakSetLocal); JSHandle fatherObj = factory->NewJSObjectByConstructor(JSHandle::Cast(fatherHandle), fatherHandle); JSHandle sonMethod = JSObject::GetMethod(thread_, JSHandle(sonObj), property1String); JSHandle fatherMethod = JSObject::GetMethod(thread_, JSHandle(fatherObj), property1String); bool same = JSTaggedValue::SameValue(thread_, sonMethod, fatherMethod); ASSERT_TRUE(same); } HWTEST_F_L0(JSNApiTests, InheritPrototype_003) { ecmascript::ThreadManagedScope managedScope(vm_->GetJSThread()); LocalScope scope(vm_); JSHandle env = vm_->GetGlobalEnv(); auto factory = vm_->GetFactory(); JSHandle invokeSelf = factory->NewMethodForNativeFunction(reinterpret_cast(BuiltinsFunction::FunctionPrototypeInvokeSelf)); // father type JSHandle protoClass = JSHandle::Cast(env->GetFunctionClassWithProto()); JSHandle protoFunc = factory->NewJSFunctionByHClass(invokeSelf, protoClass); Local protoLocal = JSNApiHelper::ToLocal(JSHandle(protoFunc)); // son type JSHandle noProtoClass = JSHandle::Cast(env->GetFunctionClassWithoutProto()); JSHandle noProtoFunc = factory->NewJSFunctionByHClass(invokeSelf, noProtoClass); Local noProtoLocal = JSNApiHelper::ToLocal(JSHandle(noProtoFunc)); JSHandle sonHandle = JSHandle::Cast(JSNApiHelper::ToJSHandle(noProtoLocal)); EXPECT_FALSE(sonHandle->HasFunctionPrototype(thread_)); JSHandle defaultString = thread_->GlobalConstants()->GetHandledDefaultString(); PropertyDescriptor desc = PropertyDescriptor(thread_, defaultString); JSObject::DefineOwnProperty(thread_, JSHandle::Cast(protoFunc), defaultString, desc); noProtoLocal->Inherit(vm_, protoLocal); JSHandle son1Handle = JSHandle::Cast(JSNApiHelper::ToJSHandle(noProtoLocal)); EXPECT_TRUE(son1Handle->HasFunctionPrototype(thread_)); OperationResult res = JSObject::GetProperty(thread_, JSHandle::Cast(son1Handle), defaultString); EXPECT_EQ(JSTaggedValue::SameValue(thread_, defaultString, res.GetValue()), true); JSHandle propertyString(thread_, factory->NewFromASCII("property").GetTaggedValue()); JSHandle func = env->GetArrayFunction(); PropertyDescriptor desc1 = PropertyDescriptor(thread_, func); JSObject::DefineOwnProperty(thread_, JSHandle::Cast(protoFunc), propertyString, desc1); OperationResult res1 = JSObject::GetProperty(thread_, JSHandle::Cast(son1Handle), propertyString); EXPECT_EQ(JSTaggedValue::SameValue(thread_, func, res1.GetValue()), true); } HWTEST_F_L0(JSNApiTests, InheritPrototype_004) { ecmascript::ThreadManagedScope managedScope(vm_->GetJSThread()); LocalScope scope(vm_); JSHandle env = vm_->GetGlobalEnv(); auto factory = vm_->GetFactory(); JSHandle weakSet = env->GetBuiltinsWeakSetFunction(); JSHandle deleteString(factory->NewFromASCII("delete")); JSHandle addString(factory->NewFromASCII("add")); JSHandle defaultString = thread_->GlobalConstants()->GetHandledDefaultString(); JSHandle deleteMethod = JSObject::GetMethod(thread_, weakSet, deleteString); JSHandle addMethod = JSObject::GetMethod(thread_, weakSet, addString); JSHandle invokeSelf = factory->NewMethodForNativeFunction(reinterpret_cast(BuiltinsFunction::FunctionPrototypeInvokeSelf)); JSHandle ctor = factory->NewMethodForNativeFunction(reinterpret_cast(BuiltinsFunction::FunctionConstructor)); JSHandle protoClass = JSHandle::Cast(env->GetFunctionClassWithProto()); JSHandle funcFuncPrototype = factory->NewJSFunctionByHClass(invokeSelf, protoClass); // add method in funcPrototype PropertyDescriptor desc = PropertyDescriptor(thread_, deleteMethod); JSObject::DefineOwnProperty(thread_, JSHandle::Cast(funcFuncPrototype), deleteString, desc); JSHandle funcFuncPrototypeValue(funcFuncPrototype); JSHandle funcFuncProtoIntanceClass = factory->NewEcmaHClass(JSFunction::SIZE, JSType::JS_FUNCTION, funcFuncPrototypeValue); // new with NewJSFunctionByHClass::function Class JSHandle protoFunc = factory->NewJSFunctionByHClass(ctor, funcFuncProtoIntanceClass); EXPECT_TRUE(*protoFunc != nullptr); // add method in funcnction PropertyDescriptor desc1 = PropertyDescriptor(thread_, addMethod); JSObject::DefineOwnProperty(thread_, JSHandle::Cast(protoFunc), addString, desc1); JSObject::DefineOwnProperty(thread_, JSHandle::Cast(protoFunc), deleteString, desc); // father type Local protoLocal = JSNApiHelper::ToLocal(JSHandle(protoFunc)); JSHandle noProtoClass = JSHandle::Cast(env->GetFunctionClassWithoutProto()); JSHandle funcFuncNoProtoPrototype = factory->NewJSFunctionByHClass(invokeSelf, noProtoClass); JSHandle funcFuncNoProtoPrototypeValue(funcFuncNoProtoPrototype); JSHandle funcFuncNoProtoProtoIntanceClass = factory->NewEcmaHClass(JSFunction::SIZE, JSType::JS_FUNCTION, funcFuncNoProtoPrototypeValue); // new with NewJSFunctionByHClass::function Class JSHandle noProtoFunc = factory->NewJSFunctionByHClass(ctor, funcFuncNoProtoProtoIntanceClass); EXPECT_TRUE(*noProtoFunc != nullptr); // set property that has same key with fater type PropertyDescriptor desc2 = PropertyDescriptor(thread_, defaultString); JSObject::DefineOwnProperty(thread_, JSHandle::Cast(noProtoFunc), addString, desc2); // son type Local noProtoLocal = JSNApiHelper::ToLocal(JSHandle(noProtoFunc)); noProtoLocal->Inherit(vm_, protoLocal); JSHandle sonHandle = JSHandle::Cast(JSNApiHelper::ToJSHandle(noProtoLocal)); OperationResult res = JSObject::GetProperty(thread_, JSHandle::Cast(sonHandle), deleteString); EXPECT_EQ(JSTaggedValue::SameValue(thread_, deleteMethod, res.GetValue()), true); // test if the property value changed after inherit OperationResult res1 = JSObject::GetProperty(thread_, JSHandle::Cast(sonHandle), addString); EXPECT_EQ(JSTaggedValue::SameValue(thread_, defaultString, res1.GetValue()), true); } HWTEST_F_L0(JSNApiTests, ClassFunction) { LocalScope scope(vm_); Local cls = FunctionRef::NewClassFunction(vm_, FunctionCallback, nullptr, nullptr); JSHandle clsObj = JSNApiHelper::ToJSHandle(Local(cls)); ASSERT_TRUE(clsObj->IsClassConstructor()); JSTaggedValue accessor = JSHandle(clsObj)->GetPropertyInlinedProps( thread_, JSFunction::CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX); ASSERT_TRUE(accessor.IsInternalAccessor()); accessor = JSHandle(clsObj)->GetPropertyInlinedProps(thread_, JSFunction::LENGTH_INLINE_PROPERTY_INDEX); ASSERT_TRUE(!accessor.IsUndefinedOrNull()); } HWTEST_F_L0(JSNApiTests, WeakRefSecondPassCallback) { ecmascript::ThreadManagedScope managedScope(vm_->GetJSThread()); LocalScope scope(vm_); Local object1 = ObjectRef::New(vm_); Global globalObject1(vm_, object1); globalObject1.SetWeak(); NativeReferenceHelper *temp = nullptr; { LocalScope scope1(vm_); Local object2 = ObjectRef::New(vm_); Global globalObject2(vm_, object2); NativeReferenceHelper *ref1 = new NativeReferenceHelper(vm_, globalObject2, WeakRefCallback); ref1->SetWeakCallback(); temp = ref1; } { LocalScope scope1(vm_); Local object3 = ObjectRef::New(vm_); Global globalObject3(vm_, object3); globalObject3.SetWeak(); } Local object4 = ObjectRef::New(vm_); Global globalObject4(vm_, object4); NativeReferenceHelper *ref2 = new NativeReferenceHelper(vm_, globalObject4, WeakRefCallback); ref2->SetWeakCallback(); vm_->CollectGarbage(TriggerGCType::OLD_GC); delete temp; delete ref2; } // CMC-GC support evacuate all region /** * @tc.number: ffi_interface_api_027 * @tc.name: TriggerGC_OLD_GC * @tc.desc: GC trigger, gcType is the trigger type * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, TriggerGC_OLD_GC) { if (g_isEnableCMCGC) { return; } ecmascript::ThreadManagedScope managedScope(vm_->GetJSThread()); vm_->SetEnableForceGC(false); auto globalEnv = vm_->GetGlobalEnv(); auto factory = vm_->GetFactory(); Local origin = StringRef::NewFromUtf8(vm_, "1"); ASSERT_EQ("1", origin->ToString(vm_)); JSHandle jsFunc = globalEnv->GetArrayFunction(); JSHandle objVal1 = factory->NewJSObjectByConstructor(JSHandle(jsFunc), jsFunc); JSHandle objVal2 = factory->NewJSObjectByConstructor(JSHandle(jsFunc), jsFunc); JSObject *newObj2 = *objVal2; JSTaggedValue canBeGcValue(newObj2); uint32_t arrayLength = 2; JSHandle taggedArray = factory->NewTaggedArray(arrayLength); taggedArray->Set(thread_, 0, objVal1); taggedArray->Set(thread_, 1, canBeGcValue); EXPECT_EQ(taggedArray->GetIdx(thread_, objVal1.GetTaggedValue()), 0U); EXPECT_EQ(taggedArray->GetIdx(thread_, canBeGcValue), 1U); // trigger gc JSNApi::TRIGGER_GC_TYPE gcType = JSNApi::TRIGGER_GC_TYPE::OLD_GC; JSNApi::TriggerGC(vm_, gcType); gcType = JSNApi::TRIGGER_GC_TYPE::SHARED_GC; JSNApi::TriggerGC(vm_, gcType); gcType = JSNApi::TRIGGER_GC_TYPE::SHARED_FULL_GC; JSNApi::TriggerGC(vm_, gcType); EXPECT_EQ(taggedArray->GetIdx(thread_, objVal1.GetTaggedValue()), 0U); EXPECT_EQ(taggedArray->GetIdx(thread_, canBeGcValue), TaggedArray::MAX_ARRAY_INDEX); ASSERT_EQ("1", origin->ToString(vm_)); vm_->SetEnableForceGC(true); } HWTEST_F_L0(JSNApiTests, Hint_GC) { ecmascript::ThreadManagedScope managedScope(thread_); vm_->SetEnableForceGC(false); [[maybe_unused]] auto heap = const_cast(thread_->GetEcmaVM()->GetHeap()); #ifdef NDEBUG size_t beforeSize = heap->GetHeapObjectSize(); if (!g_isEnableCMCGC) { heap->CollectGarbage(TriggerGCType::OLD_GC); { [[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread_); for (int i = 0; i < 2049; i++) { [[maybe_unused]] JSHandle array = thread_->GetEcmaVM()->GetFactory()->NewTaggedArray( 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE); } } beforeSize = heap->GetHeapObjectSize(); } #endif Local origin = StringRef::NewFromUtf8(vm_, "1"); ASSERT_EQ("1", origin->ToString(vm_)); // trigger gc JSNApi::MemoryReduceDegree degree = JSNApi::MemoryReduceDegree::LOW; JSNApi::HintGC(vm_, degree, GCReason::HINT_GC); degree = JSNApi::MemoryReduceDegree::MIDDLE; JSNApi::HintGC(vm_, degree, GCReason::HINT_GC); degree = JSNApi::MemoryReduceDegree::HIGH; JSNApi::HintGC(vm_, degree, GCReason::HINT_GC); ASSERT_EQ("1", origin->ToString(vm_)); #ifdef NDEBUG if (!g_isEnableCMCGC) { size_t afterSize = heap->GetHeapObjectSize(); EXPECT_TRUE(afterSize < beforeSize); } #endif vm_->SetEnableForceGC(true); } /* @tc.number: ffi_interface_api_028 * @tc.name: addWorker_DeleteWorker * @tc.desc: * addWorker:Using a WorkerVm as a parameter to modify the workInfo of the current vm * DeleteWorker:Delete WorkerVm * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, addWorker_DeleteWorker) { std::thread t1([&]() { JSRuntimeOptions option; EcmaVM *workerVm = JSNApi::CreateEcmaVM(option); JSNApi::AddWorker(vm_, workerVm); bool hasDeleted = JSNApi::DeleteWorker(vm_, workerVm); JSNApi::DestroyJSVM(workerVm); EXPECT_TRUE(hasDeleted); }); { ecmascript::ThreadSuspensionScope suspensionScope(thread_); t1.join(); } bool hasDeleted = JSNApi::DeleteWorker(vm_, nullptr); EXPECT_FALSE(hasDeleted); } /** * @tc.number: ffi_interface_api_029 * @tc.name: PrimitiveRef_GetValue * @tc.desc:Create an IntegerRef object with an initial value of 0 * and test whether the GetValue method can correctly return the associated JSValueRef object. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, PrimitiveRef_GetValue) { auto factory = vm_->GetFactory(); Local intValue = IntegerRef::New(vm_, 0); EXPECT_EQ(intValue->Value(), 0); Local jsValue = intValue->GetValue(vm_); EXPECT_TRUE(*jsValue == nullptr); JSHandle nullHandle(thread_, JSTaggedValue::Null()); JSHandle jsClassHandle = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_PRIMITIVE_REF, nullHandle); JSHandle jsTaggedValue(factory->NewJSObjectWithInit(jsClassHandle)); Local jsValueRef = JSNApiHelper::ToLocal(jsTaggedValue); EXPECT_TRUE(*(jsValueRef->GetValue(vm_)) != nullptr); } HWTEST_F_L0(JSNApiTests, BigIntRef_New_Uint64) { uint64_t maxUint64 = std::numeric_limits::max(); Local maxBigintUint64 = BigIntRef::New(vm_, maxUint64); EXPECT_TRUE(maxBigintUint64->IsBigInt(vm_)); JSHandle maxBigintUint64Val(thread_, JSNApiHelper::ToJSTaggedValue(*maxBigintUint64)); EXPECT_EQ(maxBigintUint64Val->GetDigit(0), static_cast(maxUint64 & 0xffffffff)); EXPECT_EQ(maxBigintUint64Val->GetDigit(1), static_cast((maxUint64 >> BigInt::DATA_BITS) & 0xffffffff)); uint64_t minUint64 = std::numeric_limits::min(); Local minBigintUint64 = BigIntRef::New(vm_, minUint64); EXPECT_TRUE(minBigintUint64->IsBigInt(vm_)); JSHandle minBigintUint64Val(thread_, JSNApiHelper::ToJSTaggedValue(*minBigintUint64)); EXPECT_EQ(minBigintUint64Val->GetDigit(0), static_cast(minUint64 & 0xffffffff)); EXPECT_EQ(minBigintUint64Val->GetLength(), 1U); } HWTEST_F_L0(JSNApiTests, BigIntRef_New_Int64) { int64_t maxInt64 = std::numeric_limits::max(); Local maxBigintInt64 = BigIntRef::New(vm_, maxInt64); EXPECT_TRUE(maxBigintInt64->IsBigInt(vm_)); JSHandle maxBigintInt64Val(thread_, JSNApiHelper::ToJSTaggedValue(*maxBigintInt64)); EXPECT_EQ(maxBigintInt64Val->GetDigit(0), static_cast(maxInt64 & 0xffffffff)); EXPECT_EQ(maxBigintInt64Val->GetDigit(1), static_cast((maxInt64 >> BigInt::DATA_BITS) & 0xffffffff)); int64_t minInt64 = std::numeric_limits::min(); Local minBigintInt64 = BigIntRef::New(vm_, minInt64); EXPECT_TRUE(minBigintInt64->IsBigInt(vm_)); JSHandle minBigintInt64Val(thread_, JSNApiHelper::ToJSTaggedValue(*minBigintInt64)); EXPECT_EQ(minBigintInt64Val->GetSign(), true); EXPECT_EQ(minBigintInt64Val->GetDigit(0), static_cast((-minInt64) & 0xffffffff)); EXPECT_EQ(minBigintInt64Val->GetDigit(1), static_cast(((-minInt64) >> BigInt::DATA_BITS) & 0xffffffff)); } /** * @tc.number: ffi_interface_api_030 * @tc.name: BigIntRef_CreateBigWords_GetWordsArray_GetWordsArraySize * @tc.desc: * IsBigInt:Determine if it is bigint * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, BigIntRef_CreateBigWords_GetWordsArray_GetWordsArraySize) { bool sign = false; uint32_t size = 3; const uint32_t MULTIPLE = 2; const uint64_t words[3] = { std::numeric_limits::min() - 1, std::numeric_limits::min(), std::numeric_limits::max(), }; Local bigWords = BigIntRef::CreateBigWords(vm_, sign, size, words); EXPECT_TRUE(bigWords->IsBigInt(vm_)); Local bigWordsRef(bigWords); EXPECT_EQ(bigWordsRef->GetWordsArraySize(vm_), size); JSHandle bigintUint64Val(thread_, JSNApiHelper::ToJSTaggedValue(*bigWords)); EXPECT_EQ(bigintUint64Val->GetSign(), false); EXPECT_EQ(bigintUint64Val->GetLength(), size * MULTIPLE); bool resultSignBit = true; uint64_t *resultWords = new uint64_t[3](); // 3 : length of words array bigWordsRef->GetWordsArray(vm_, &resultSignBit, size, resultWords); EXPECT_EQ(resultSignBit, false); EXPECT_EQ(resultWords[0], words[0]); EXPECT_EQ(resultWords[1], words[1]); EXPECT_EQ(resultWords[2], words[2]); delete[] resultWords; } /** * @tc.number: ffi_interface_api_031 * @tc.name: DateRef_New_ToString_GetTime_BigIntRef_CreateBigWords_GetWordsArray * @tc.desc:The purpose of testing is to verify whether the DateRef method correctly converts time to Date type * and converts Date type to string type, while also verifying whether its operation to obtain time is correct. * Used to verify the success of creating a BigIntRef object and obtaining a * word array of large integer objects. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, DateRef_New_ToString_GetTime) { double time = 1.1; Local data = DateRef::New(vm_, time); EXPECT_TRUE(data->IsDate(vm_)); Local tostring = data->ToString(vm_); Local toValue(tostring); EXPECT_TRUE(tostring->IsString(vm_)); double dou = data->GetTime(vm_); EXPECT_EQ(dou, 1.1); } HWTEST_F_L0(JSNApiTests, PromiseRef_Finally) { LocalScope scope(vm_); Local capability = PromiseCapabilityRef::New(vm_); Local promise = capability->GetPromise(vm_); Local reject = FunctionRef::New(vm_, RejectCallback); Local catchPromise = promise->Finally(vm_, reject); ASSERT_TRUE(promise->IsPromise(vm_)); ASSERT_TRUE(catchPromise->IsPromise(vm_)); Local catchPromise1 = promise->Then(vm_, reject, reject); ASSERT_TRUE(catchPromise1->IsPromise(vm_)); Local callback = FunctionRef::New(vm_, FunctionCallback); ASSERT_TRUE(!callback.IsEmpty()); Local catchPromise2 = promise->Then(vm_, callback); ASSERT_TRUE(catchPromise2->IsPromise(vm_)); } /* * @tc.number: ffi_interface_api_032 * @tc.name: JSNApi_SerializeValue * @tc.desc: The main function of Undefined is to initialize some variables for subsequent testing, * testing the correctness and reliability of the JSNApi:: SerializeValue function, * and ensuring that it can serialize values correctly. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, JSNApi_SerializeValue) { LocalScope scope(vm_); Local callback = FunctionRef::New(vm_, FunctionCallback); ASSERT_TRUE(!callback.IsEmpty()); std::vector> arguments; arguments.emplace_back(JSValueRef::Undefined(vm_)); Local result = callback->Call(vm_, JSValueRef::Undefined(vm_), arguments.data(), arguments.size()); ASSERT_TRUE(result->IsArray(vm_)); Local array(result); ASSERT_EQ(static_cast(array->Length(vm_)), arguments.size()); void *res = nullptr; res = JSNApi::SerializeValue(vm_, result, JSValueRef::Undefined(vm_), JSValueRef::Undefined(vm_), true); EXPECT_TRUE(res); } /* * @tc.number: ffi_interface_api_033 * @tc.name: JSNApi_SetHostPromiseRejectionTracker_Call * @tc.desc: Can the host Promise reject callback function of the JavaScript virtual machine be set correctly. * @ Using the functions of Uint8Array and verifying if its attribute values are correct. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, JSNApi_SetHostPromiseRejectionTracker) { void *data = reinterpret_cast(BuiltinsFunction::FunctionPrototypeInvokeSelf); // 设置 JavaScript 虚拟机的宿主 Promise 拒绝回调函数为 data 所指向的函数。 JSNApi::SetHostPromiseRejectionTracker(vm_, data, data); // 首先获取GetJS虚拟机中的当前线程->GetCurrentEcmaContext获取当前上下文->从上下文中获取Promise拒绝回调函数 PromiseRejectCallback res = vm_->GetPromiseRejectCallback(); // 检查回调函数的地址是否等于我们之前设置的 data 的地址 ASSERT_EQ(res, reinterpret_cast(data)); } HWTEST_F_L0(JSNApiTests, JSNApi_SetNativePtrGetter_SetHostEnqueueJob) { void *cb = reinterpret_cast(BuiltinsFunction::FunctionPrototypeInvokeSelf); JSNApi::SetNativePtrGetter(vm_, cb); NativePtrGetter res = vm_->GetNativePtrGetter(); ASSERT_EQ(res, reinterpret_cast(cb)); } HWTEST_F_L0(JSNApiTests, NumberRef_New) { uint32_t input = 32; int64_t input1 = 1; Local res = NumberRef::New(vm_, input); Local res1 = NumberRef::New(vm_, input1); ASSERT_TRUE(res->IsNumber()); ASSERT_TRUE(res1->IsNumber()); } /** * @tc.number: ffi_interface_api_034 * @tc.name: ObjectRef_GetOwnEnumerablePropertyNames * @tc.desc:Use the GetOwnEnumerablePropertyNames method to obtain all enumerable property names of the object * and return an ArrayRef object. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, ObjectRef_GetOwnEnumerablePropertyNames) { LocalScope scope(vm_); Local object = ObjectRef::New(vm_); Local res = object->GetOwnEnumerablePropertyNames(vm_); ASSERT_TRUE(res->IsArray(vm_)); } /** * @tc.number: ffi_interface_api_035 * @tc.name: ObjectRef_SetNativePointerFieldCount_GetNativePointerFieldCount * @tc.desc: * SetNativePointerFieldCount:Set the count value of the local pointer field to count * GetNativePointerField:Get native pointer object * SetNativePointerField:Set native pointer properties, including pointers, callback methods, * data, and number of bindings * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, ObjectRef_SetNativePointerFieldCount_GetNativePointerFieldCount) { LocalScope scope(vm_); Local object = ObjectRef::New(vm_); int32_t input = 34; object->SetNativePointerFieldCount(vm_, input); int32_t res = object->GetNativePointerFieldCount(vm_); ASSERT_EQ(res, input); NativePointerCallback callBack = nullptr; void *vp1 = static_cast(new std::string("test")); void *vp2 = static_cast(new std::string("test")); std::string *sp1 = static_cast(vp1); object->SetNativePointerField(vm_, 33, vp1, callBack, vp2); void *res1 = object->GetNativePointerField(vm_, 33); std::string *sp2 = static_cast(res1); ASSERT_EQ(sp1, sp2); } /** * @tc.number: ffi_interface_api_036 * @tc.name: FunctionRef_GetFunctionPrototype_SetName_GetName * @tc.desc:Mainly used to verify the correctness of methods such as creating, obtaining prototypes, * setting names, and obtaining FunctionRef objects. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, FunctionRef_GetFunctionPrototype_SetName_GetName) { LocalScope scope(vm_); NativePointerCallback deleter = nullptr; void *cb = reinterpret_cast(BuiltinsFunction::FunctionPrototypeInvokeSelf); bool callNative = true; size_t nativeBindingsize = 15; Local res = FunctionRef::NewClassFunction(vm_, FunctionCallback, deleter, cb, callNative, nativeBindingsize); ASSERT_TRUE(res->IsFunction(vm_)); Local res1 = res->GetFunctionPrototype(vm_); ASSERT_TRUE(res->IsFunction(vm_)); ASSERT_TRUE(!res1->IsArray(vm_)); Local origin = StringRef::NewFromUtf8(vm_, "1"); res->SetName(vm_, origin); Local s = res->GetName(vm_); std::string str = s->ToString(vm_); ASSERT_EQ("1", str); } HWTEST_F_L0(JSNApiTests, JSNApi_SetAssetPath_GetAssetPath) { LocalScope scope(vm_); std::string str = "/data/storage/el1/bundle/moduleName/ets/modules.abc"; JSNApi::SetAssetPath(vm_, str); std::string res = JSNApi::GetAssetPath(vm_); ASSERT_EQ(str, res); void *data = reinterpret_cast(BuiltinsFunction::FunctionPrototypeInvokeSelf); JSNApi::SetLoop(vm_, data); void *res1 = vm_->GetLoop(); ASSERT_EQ(res1, data); } /** * @tc.number: ffi_interface_api_037 * @tc.name: SetAssetPath * @tc.desc:The resource file path used to verify the success of the setup program. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, JSValueRef_ToNativePointer) { LocalScope scope(vm_); Local toString = StringRef::NewFromUtf8(vm_, "-123.3"); Local toValue(toString); ASSERT_EQ(toString->ToNumber(vm_)->Value(), -123.3); // -123 : test case of input ASSERT_EQ(toString->ToBoolean(vm_)->Value(), true); ASSERT_EQ(toValue->ToString(vm_)->ToString(vm_), "-123.3"); ASSERT_TRUE(toValue->ToObject(vm_)->IsObject(vm_)); Local res = toValue->ToNativePointer(vm_); ASSERT_TRUE(res->IsString(vm_)); } HWTEST_F_L0(JSNApiTests, GeneratorObjectRef_IsGenerator) { ObjectFactory *factory = vm_->GetFactory(); auto env = vm_->GetGlobalEnv(); JSHandle genFunc = env->GetGeneratorFunctionFunction(); JSHandle genObjHandleVal = factory->NewJSGeneratorObject(genFunc); JSHandle hclass = JSHandle::Cast(env->GetGeneratorFunctionClass()); JSHandle generatorFunc = JSHandle::Cast(factory->NewJSObject(hclass)); JSFunction::InitializeJSFunction(thread_, generatorFunc, FunctionKind::GENERATOR_FUNCTION); JSHandle generatorContext = factory->NewGeneratorContext(); generatorContext->SetMethod(thread_, generatorFunc.GetTaggedValue()); JSHandle generatorContextVal = JSHandle::Cast(generatorContext); genObjHandleVal->SetGeneratorContext(thread_, generatorContextVal.GetTaggedValue()); JSHandle genObjTagHandleVal = JSHandle::Cast(genObjHandleVal); Local genObjectRef = JSNApiHelper::ToLocal(genObjTagHandleVal); Local res = genObjectRef->GetGeneratorFunction(vm_); ASSERT_TRUE(res->IsGeneratorFunction(vm_)); } /** * @tc.number: ffi_interface_api_038 * @tc.name: BigIntToInt64 * @tc.desc:Is the method of converting BigInt objects to 64 bit signed integers correct, and is it able to * handle lossless conversions correctly. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, BigIntToInt64) { LocalScope scope(vm_); uint64_t maxUint64 = std::numeric_limits::max(); Local maxBigintUint64 = BigIntRef::New(vm_, maxUint64); EXPECT_TRUE(maxBigintUint64->IsBigInt(vm_)); int64_t num = -11; int64_t num1 = num; bool lossless = true; maxBigintUint64->BigIntToInt64(vm_, &num, &lossless); EXPECT_TRUE(num != num1); } /** * @tc.number: ffi_interface_api_039 * @tc.name: BigIntToUint64 * @tc.desc:Is the method for converting BigInt objects to 64 bit unsigned integers correct and can lossless * conversions be handled correctly. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, BigIntToUint64) { LocalScope scope(vm_); uint64_t maxUint64 = std::numeric_limits::max(); Local maxBigintUint64 = BigIntRef::New(vm_, maxUint64); EXPECT_TRUE(maxBigintUint64->IsBigInt(vm_)); uint64_t num = -11; uint64_t num1 = num; bool lossless = true; maxBigintUint64->BigIntToUint64(vm_, &num, &lossless); EXPECT_TRUE(num != num1); } HWTEST_F_L0(JSNApiTests, BooleanRef_New) { LocalScope scope(vm_); bool input = true; Local res = BooleanRef::New(vm_, input); EXPECT_TRUE(res->IsBoolean()); EXPECT_TRUE(res->BooleaValue(vm_)); } /** * @tc.number: ffi_interface_api_040 * @tc.name: NewFromUnsigned * @tc.desc:Verify that the NewFromUnsigned method of IntegerRef can correctly create an IntegerRef object * representing unsigned integers, and that the value of the object is correct. * Value () method to obtain the value of this object, and then assert that this value is equal to * the input unsigned integer 1. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, NewFromUnsigned) { LocalScope scope(vm_); unsigned int input = 1; [[maybe_unused]] Local res = IntegerRef::NewFromUnsigned(vm_, input); EXPECT_TRUE(res->IntegerValue(vm_) == 1); EXPECT_TRUE(res->Value() == 1); } HWTEST_F_L0(JSNApiTests, SetBundleName_GetBundleName) { LocalScope scope(vm_); std::string str = "11"; JSNApi::SetBundleName(vm_, str); std::string res = JSNApi::GetBundleName(vm_); ASSERT_EQ(str, res); } HWTEST_F_L0(JSNApiTests, SetModuleName_GetModuleName) { LocalScope scope(vm_); std::string str = "11"; JSNApi::SetModuleName(vm_, str); std::string res = JSNApi::GetModuleName(vm_); ASSERT_EQ(str, res); } /** * @tc.number: ffi_interface_api_041 * @tc.name: IsBundle * @tc.desc: Determine if it is a type of Bundle * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, IsBundle) { LocalScope scope(vm_); bool res = JSNApi::IsBundle(vm_); ASSERT_EQ(res, true); } /** * @tc.number: ffi_interface_api_042 * @tc.name: ObjectRef_Delete * @tc.desc:MapRef_GetSize_GetTotalElements_Get_GetKey_GetValue_New_Set * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, MapRef_GetSize_GetTotalElements_Get_GetKey_GetValue_New_Set) { LocalScope scope(vm_); Local map = MapRef::New(vm_); Local key = StringRef::NewFromUtf8(vm_, "TestKey"); Local value = StringRef::NewFromUtf8(vm_, "TestValue"); map->Set(vm_, key, value); Local res = map->Get(vm_, key); ASSERT_EQ(res->ToString(vm_)->ToString(vm_), value->ToString(vm_)->ToString(vm_)); int32_t num = map->GetSize(vm_); int32_t num1 = map->GetTotalElements(vm_); ASSERT_EQ(num, 1); ASSERT_EQ(num1, 1); Local res1 = map->GetKey(vm_, 0); ASSERT_EQ(res1->ToString(vm_)->ToString(vm_), key->ToString(vm_)->ToString(vm_)); Local res2 = map->GetValue(vm_, 0); ASSERT_EQ(res2->ToString(vm_)->ToString(vm_), value->ToString(vm_)->ToString(vm_)); } HWTEST_F_L0(JSNApiTests, GetSourceCode) { LocalScope scope(vm_); Local callback = FunctionRef::New(vm_, FunctionCallback); bool res = callback->IsNative(vm_); EXPECT_TRUE(res); } /** * @tc.number: ffi_interface_api_043 * @tc.name: ObjectRef_Delete_GetSourceCode * @tc.desc:Verify that the Delete method of the Object Ref object correctly deletes a property and that * the object no longer contains the property. * Using the functions of getsourcecode and verifying if its attribute values are correct. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, ObjectRef_Delete) { LocalScope scope(vm_); Local object = ObjectRef::New(vm_); Local key = StringRef::NewFromUtf8(vm_, "TestKey"); Local value = ObjectRef::New(vm_); PropertyAttribute attribute(value, true, true, true); ASSERT_TRUE(object->DefineProperty(vm_, key, attribute)); ASSERT_TRUE(object->Delete(vm_, key)); ASSERT_FALSE(object->Has(vm_, key)); } /** * @tc.number: ffi_interface_api_044 * @tc.name: Has * @tc.desc: Used to verify whether a given check object has the specified properties. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, ObjectRef_Set1) { LocalScope scope(vm_); Local object = ObjectRef::New(vm_); Local toString = StringRef::NewFromUtf8(vm_, "-123.3"); Local toValue(toString); bool res = object->Set(vm_, 12, toValue); ASSERT_TRUE(res); Local res1 = object->Get(vm_, 12); ASSERT_EQ(res1->ToString(vm_)->ToString(vm_), toValue->ToString(vm_)->ToString(vm_)); } HWTEST_F_L0(JSNApiTests, NativePointerRef_New) { LocalScope scope(vm_); NativePointerCallback callBack = nullptr; void *vp1 = static_cast(new std::string("test")); void *vp2 = static_cast(new std::string("test")); Local res = NativePointerRef::New(vm_, vp1, callBack, vp2, 0); ASSERT_EQ(res->Value(), vp1); } /** * @tc.number: ffi_interface_api_045 * @tc.name: PromiseRejectInfo_GetData * @tc.desc:Construct a BufferRef function to determine whether it is a ObjectRef_Has_Delete * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, ObjectRef_Has_Delete) { LocalScope scope(vm_); Local object = ObjectRef::New(vm_); uint32_t num = 10; Local toString = StringRef::NewFromUtf8(vm_, "-123.3"); Local toValue(toString); bool res = object->Set(vm_, num, toValue); ASSERT_TRUE(res); bool res1 = object->Has(vm_, num); ASSERT_TRUE(res1); bool res2 = object->Delete(vm_, num); ASSERT_TRUE(res2); bool res3 = object->Has(vm_, num); ASSERT_FALSE(res3); } /** * @tc.number: ffi_interface_api_046 * @tc.name: PromiseRejectInfo_GetData * @tc.desc:Mainly tested whether the GetData method of the PromiseRejectInfo object can correctly return * the incoming data, and whether the GetPromise and GetReason methods can correctly return Promise and the * reason for rejection. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, PromiseRejectInfo_GetData) { LocalScope scope(vm_); Local toString = StringRef::NewFromUtf8(vm_, "-123.3"); Local promise(toString); Local toString1 = StringRef::NewFromUtf8(vm_, "123.3"); Local reason(toString1); void *data = static_cast(new std::string("test")); // 创建一个PromiseRejectInfo对象,并传入被拒绝的Promise,拒绝的原因,拒绝事件类型以及自定义数据 PromiseRejectInfo promisereject(promise, reason, PromiseRejectInfo::PROMISE_REJECTION_EVENT::REJECT, data); // 从上一步创建的PromiseRejectInfo对象中获取被拒绝的Promise,并在下面断言被拒绝的Promise与原始Promise相同 Local promise_res = promisereject.GetPromise(); // 获取拒绝的原因,并在下面断言拒绝原因与原始拒绝原因相同 Local reason_res = promisereject.GetReason(); ASSERT_EQ(promise_res->ToString(vm_)->ToString(vm_), promise->ToString(vm_)->ToString(vm_)); ASSERT_EQ(reason_res->ToString(vm_)->ToString(vm_), reason->ToString(vm_)->ToString(vm_)); // 获取自定义数据,并在下面断言自定义数据与传入的数据相同 void *dataRes = promisereject.GetData(); ASSERT_EQ(dataRes, data); } /** * @tc.number: ffi_interface_api_047 * @tc.name: FunctionCallScope * @tc.desc:Create and use the function call scope function, and verify whether the depth of function calls is * correct when entering and exiting the scope. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, FunctionCallScope) { { FunctionCallScope callScope(vm_); ASSERT_FALSE(vm_->IsTopLevelCallDepth()); } ASSERT_TRUE(vm_->IsTopLevelCallDepth()); } HWTEST_F_L0(JSNApiTests, AotTrigger) { std::string bundle; std::string module; int32_t trigger = -1; JSNApi::SetRequestAotCallback(vm_, [&](const std::string &bundleName, const std::string &moduleName, int32_t triggerMode) -> bool { bundle = bundleName; module = moduleName; trigger = triggerMode; return 100; }); ASSERT_FALSE(ecmascript::pgo::PGOProfilerManager::GetInstance()->RequestAot("com.test.test", "requestAot", RequestAotMode::RE_COMPILE_ON_IDLE)); ASSERT_EQ(bundle, "com.test.test"); ASSERT_EQ(module, "requestAot"); ASSERT_EQ(trigger, 0); } HWTEST_F_L0(JSNApiTests, JSNApiInternalsTest) { #define CHECK_VALUE(VAL) ASSERT_EQ(JSValueRefInternals::VAL, JSTaggedValue::VAL) CHECK_VALUE(BIT_PER_BYTE); CHECK_VALUE(TAG_BITS_SIZE); CHECK_VALUE(TAG_BITS_SHIFT); CHECK_VALUE(TAG_MARK); CHECK_VALUE(TAG_INT); CHECK_VALUE(TAG_INT32_INC_MAX); CHECK_VALUE(TAG_INT32_DEC_MIN); CHECK_VALUE(TAG_OBJECT); CHECK_VALUE(TAG_WEAK); CHECK_VALUE(TAG_NULL); CHECK_VALUE(TAG_SPECIAL); CHECK_VALUE(TAG_BOOLEAN); CHECK_VALUE(TAG_EXCEPTION); CHECK_VALUE(TAG_OPTIMIZED_OUT); CHECK_VALUE(TAG_SPECIAL_MASK); CHECK_VALUE(TAG_BOOLEAN_MASK); CHECK_VALUE(TAG_HEAPOBJECT_MASK); CHECK_VALUE(TAG_WEAK_MASK); CHECK_VALUE(VALUE_HOLE); CHECK_VALUE(VALUE_NULL); CHECK_VALUE(VALUE_FALSE); CHECK_VALUE(VALUE_TRUE); CHECK_VALUE(VALUE_UNDEFINED); CHECK_VALUE(VALUE_EXCEPTION); CHECK_VALUE(VALUE_ZERO); CHECK_VALUE(VALUE_OPTIMIZED_OUT); CHECK_VALUE(INT_SIGN_BIT_OFFSET); CHECK_VALUE(DOUBLE_ENCODE_OFFSET_BIT); CHECK_VALUE(DOUBLE_ENCODE_OFFSET); CHECK_VALUE(VALUE_POSITIVE_ZERO); CHECK_VALUE(VALUE_NEGATIVE_ZERO); #undef CHECK_VALUE } HWTEST_F_L0(JSNApiTests, JSNApiInternalsTestNumberRef) { // double TestNumberRef(0., JSTaggedValue::DOUBLE_ENCODE_OFFSET); TestNumberRef(NAN, base::bit_cast(ecmascript::base::NAN_VALUE) + JSTaggedValue::DOUBLE_ENCODE_OFFSET); // int32_t TestNumberRef(static_cast(0), JSTaggedValue::TAG_INT); TestNumberRef(INT32_MIN, static_cast(INT32_MIN) | JSTaggedValue::TAG_INT); TestNumberRef(INT32_MAX, static_cast(INT32_MAX) | JSTaggedValue::TAG_INT); // uint32_t TestNumberRef(static_cast(0), JSTaggedValue::TAG_INT); TestNumberRef(static_cast(INT32_MAX), static_cast(INT32_MAX) | JSTaggedValue::TAG_INT); auto val = static_cast(INT32_MAX + 1UL); TestNumberRef(val, ConvertDouble(static_cast(val))); TestNumberRef(UINT32_MAX, ConvertDouble(static_cast(UINT32_MAX))); // int64_t TestNumberRef(static_cast(INT32_MIN), static_cast(INT32_MIN) | JSTaggedValue::TAG_INT); TestNumberRef(static_cast(INT32_MAX), static_cast(INT32_MAX) | JSTaggedValue::TAG_INT); TestNumberRef(INT64_MIN, ConvertDouble(static_cast(INT64_MIN))); TestNumberRef(INT64_MAX, ConvertDouble(static_cast(INT64_MAX))); } HWTEST_F_L0(JSNApiTests, JSNApiInternalsTestBooleanRef) { LocalScope scope(vm_); bool input = true; Local res = BooleanRef::New(vm_, input); EXPECT_TRUE(res->IsBoolean()); EXPECT_TRUE(res->BooleaValue(vm_)); ASSERT_EQ(JSNApiHelper::ToJSTaggedValue(*res).GetRawData(), JSTaggedValue::VALUE_TRUE); input = false; res = BooleanRef::New(vm_, input); EXPECT_TRUE(res->IsBoolean()); EXPECT_FALSE(res->BooleaValue(vm_)); ASSERT_EQ(JSNApiHelper::ToJSTaggedValue(*res).GetRawData(), JSTaggedValue::VALUE_FALSE); } HWTEST_F_L0(JSNApiTests, JSNApiInternalsTestNullUndefined) { LocalScope scope(vm_); Local null = JSValueRef::Null(vm_); ASSERT_TRUE(null->IsNull()); ASSERT_EQ(JSNApiHelper::ToJSTaggedValue(*null).GetRawData(), JSTaggedValue::VALUE_NULL); Local undefined = JSValueRef::Undefined(vm_); ASSERT_TRUE(undefined->IsUndefined()); ASSERT_EQ(JSNApiHelper::ToJSTaggedValue(*undefined).GetRawData(), JSTaggedValue::VALUE_UNDEFINED); } /** * @tc.number: ffi_interface_api_048 * @tc.name: FunctionRef_New_GetFunctionPrototype * @tc.desc:The Inheritance Characteristics of Function References and the Function of Obtaining Function Headers * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, FunctionRef_New_GetFunctionPrototype) { LocalScope scope(vm_); JSHandle env = vm_->GetGlobalEnv(); JSHandle set = env->GetBuiltinsSetFunction(); Local setLocal = JSNApiHelper::ToLocal(set); JSHandle map = env->GetBuiltinsMapFunction(); Local mapLocal = JSNApiHelper::ToLocal(map); JSHandle setPrototype(thread_, JSHandle::Cast(set)->GetFunctionPrototype(thread_)); JSHandle mapPrototype(thread_, JSHandle::Cast(map)->GetFunctionPrototype(thread_)); JSHandle mapPrototypeProto(thread_, JSTaggedValue::GetPrototype(thread_, mapPrototype)); bool same = JSTaggedValue::SameValue(thread_, setPrototype, mapPrototypeProto); ASSERT_FALSE(same); mapLocal->Inherit(vm_, setLocal); JSHandle sonHandle = JSNApiHelper::ToJSHandle(mapLocal); JSHandle sonPrototype(thread_, JSHandle::Cast(sonHandle)->GetFunctionPrototype(thread_)); JSHandle sonPrototypeProto(thread_, JSTaggedValue::GetPrototype(thread_, sonPrototype)); bool same2 = JSTaggedValue::SameValue(thread_, setPrototype, sonPrototypeProto); ASSERT_TRUE(same2); Local son1 = FunctionRef::New(vm_, FunctionCallback, nullptr); son1->Inherit(vm_, mapLocal); JSHandle son1Handle = JSHandle::Cast(JSNApiHelper::ToJSHandle(son1)); ASSERT_TRUE(son1Handle->HasFunctionPrototype(thread_)); } /* * @tc.number: ffi_interface_api_049 * @tc.name: PrintExceptionInfo * @tc.desc: Obtain and print abnormal information correctly. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, PrintExceptionInfo) { LocalScope scope(vm_); std::thread t1([&](){ RuntimeOption option; option.SetLogLevel(common::LOG_LEVEL::ERROR); auto *vm = JSNApi::CreateJSVM(option); ASSERT_TRUE(vm != nullptr) << "Cannot create Runtime"; JSNApi::PrintExceptionInfo(vm); JSNApi::DestroyJSVM(vm); }); { ecmascript::ThreadSuspensionScope suspensionScope(thread_); t1.join(); } } /* * @tc.number: ffi_interface_api_050 * @tc.name: IsNull * @tc.desc: Verify that localnull correctly represents a null value, ensuring that the JavaScript virtual machine * can handle null values correctly. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, IsNull) { LocalScope scope(vm_); Local localNull = JSValueRef::Null(vm_); ASSERT_TRUE(localNull->IsNull()); } /* * @tc.number: ffi_interface_api_051 * @tc.name: IsNativePointer * @tc.desc: Verify that a NativePointerRef object created with a local pointer is correctly * recognized as a local pointer. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, IsNativePointer) { LocalScope scope(vm_); NativePointerCallback callBack = nullptr; void *vp1 = static_cast(new std::string("test")); void *vp2 = static_cast(new std::string("test")); Local res = NativePointerRef::New(vm_, vp1, callBack, vp2, 0); ASSERT_TRUE(res->IsNativePointer(vm_)); } /* * @tc.number: ffi_interface_api_052 * @tc.name: ToType_ToBoolean_ToString_ToObject * @tc.desc: Verify whether the ToType method of the JavaScript virtual machine can correctly convert string types to * the corresponding JavaScript data types. * Among them, there is the result of checking the string "-1.3" when it is converted to a Boolean value. * Check if the string wrapped in JSValueRef yields a result of "-1.3" when converted to a string. * Check if the string wrapped in JSValueRef actually becomes an object when converted to an object. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, ToType_ToBoolean_ToString_ToObject) { LocalScope scope(vm_); Local toString = StringRef::NewFromUtf8(vm_, "-1.3"); Local toValue(toString); ASSERT_EQ(toString->ToNumber(vm_)->Value(), -1.3); ASSERT_EQ(toString->ToBoolean(vm_)->Value(), true); ASSERT_EQ(toValue->ToString(vm_)->ToString(vm_), "-1.3"); ASSERT_TRUE(toValue->ToObject(vm_)->IsObject(vm_)); } /** * @tc.number: ffi_interface_api_053 * @tc.name: IsTypedArray * @tc.desc:Verify that the TypedArray method correctly created a Uint32Array containing the specified * offset and length, and verify that its property values match expectations. * @tc.type: FUNC * @tc.require: parameter */ HWTEST_F_L0(JSNApiTests, IsTypedArray) { LocalScope scope(vm_); std::string test = "abc"; char buffer[4]; memset_s(buffer, sizeof(buffer), 0, sizeof(buffer)); Local testString = StringRef::NewFromUtf8(vm_, test.c_str()); EXPECT_EQ(testString->WriteUtf8(vm_, buffer, 4), 4); // testString 是一个字符串,而不是类型化数组 ASSERT_FALSE(testString->IsTypedArray(vm_)); const int32_t length = 30; Local arrayBuffer = ArrayBufferRef::New(vm_, length); ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_)); Local typedArray = Uint32ArrayRef::New(vm_, arrayBuffer, 4, 6); // 是否是类型化数组 ASSERT_TRUE(typedArray->IsTypedArray(vm_)); ASSERT_FALSE(typedArray->IsUndefined()); ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_)); } HWTEST_F_L0(JSNApiTests, GetOriginalSource) { LocalScope scope(vm_); JSThread *thread = vm_->GetJSThread(); ObjectFactory *factory = vm_->GetFactory(); auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle regExpFunc = globalEnv->GetRegExpFunction(); JSHandle jSRegExp = JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(regExpFunc), regExpFunc)); jSRegExp->SetOriginalSource(thread, JSTaggedValue::Undefined()); Local object = JSNApiHelper::ToLocal(JSHandle::Cast(jSRegExp)); ASSERT_EQ(object->GetOriginalSource(vm_)->ToString(vm_), ""); } HWTEST_F_L0(JSNApiTests, GetOriginalFlags) { LocalScope scope(vm_); JSThread *thread = vm_->GetJSThread(); ObjectFactory *factory = vm_->GetFactory(); auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle regExpFunc = globalEnv->GetRegExpFunction(); JSHandle jSRegExp = JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(regExpFunc), regExpFunc)); jSRegExp->SetOriginalFlags(thread, JSTaggedValue(RegExpParser::FLAG_GLOBAL | RegExpParser::FLAG_IGNORECASE | RegExpParser::FLAG_MULTILINE | RegExpParser::FLAG_DOTALL | RegExpParser::FLAG_UTF16 | RegExpParser::FLAG_STICKY)); Local object = JSNApiHelper::ToLocal(JSHandle::Cast(jSRegExp)); ASSERT_EQ(object->GetOriginalFlags(vm_), TEST_CHAR_STRING_FLAGS); } HWTEST_F_L0(JSNApiTests, GetGeneratorState) { LocalScope scope(vm_); JSHandle env = thread_->GetEcmaVM()->GetGlobalEnv(); ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory(); JSHandle genFunc = env->GetGeneratorFunctionFunction(); JSHandle genObjHandleVal = factory->NewJSGeneratorObject(genFunc); genObjHandleVal->SetGeneratorState(JSGeneratorState::COMPLETED); JSHandle genObjTagHandleVal = JSHandle::Cast(genObjHandleVal); Local object = JSNApiHelper::ToLocal(genObjTagHandleVal); ASSERT_EQ(object->GetGeneratorState(vm_)->ToString(vm_)->ToString(vm_), TEST_CHAR_STRING_STATE); } HWTEST_F_L0(JSNApiTests, SetReleaseSecureMemCallback) { JSNApi::SetReleaseSecureMemCallback(FakeReleaseSecureMemCallback); ReleaseSecureMemCallback releaseSecureMemCallBack1 = ecmascript::Runtime::GetInstance()->GetReleaseSecureMemCallback(); ASSERT_FALSE(releaseSecureMemCallBack1 == nullptr); JSNApi::SetReleaseSecureMemCallback(nullptr); ReleaseSecureMemCallback releaseSecureMemCallBack2 = ecmascript::Runtime::GetInstance()->GetReleaseSecureMemCallback(); ASSERT_FALSE(releaseSecureMemCallBack2 == nullptr); } static bool g_finalizeCallbackExecuted = false; void FinalizeCallback([[maybe_unused]] EcmaVM *vm) { g_finalizeCallbackExecuted = true; } HWTEST_F_L0(JSNApiTests, IgnoreFinalizeCallback) { ecmascript::ThreadManagedScope managedScope(vm_->GetJSThread()); NativeReferenceHelper *ref = nullptr; g_finalizeCallbackExecuted = false; { LocalScope scope(vm_); Local object = ObjectRef::New(vm_); Global globalObject(vm_, object); ref = new NativeReferenceHelper(vm_, globalObject, FinalizeCallback); ref->SetWeakCallback(); } vm_->GetJSThread()->IgnoreFinalizeCallback(); vm_->CollectGarbage(TriggerGCType::FULL_GC); vm_->CollectGarbage(TriggerGCType::FULL_GC); ASSERT_FALSE(g_finalizeCallbackExecuted); delete ref; } } // namespace panda::test