* 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 <cstddef>
#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";
static constexpr char TEST_ORIGINAL_SOURCE[] = "string";
static constexpr char TEST_CHAR_STRING_STATE_SUSPEND[] = "suspended";
static const char TEST_STRING[] = "test";
static const char TEST_FROZEN_KEY[] = "frozen";
static const char TEST_SHOULD_FAIL[] = "should_fail";
static constexpr int32_t TEST_INT_VALUE = 42;
static constexpr int32_t TEST_NEG_INT_VALUE = -100;
static constexpr double TEST_DOUBLE_VALUE = 3.14159;
static constexpr double TEST_NEG_DOUBLE_VALUE = -2.71828;
static constexpr double TEST_LARGE_DOUBLE = 9876543210.123;
static constexpr int32_t TEST_ARRAYBUFFER_LENGTH = 32;
static constexpr int32_t TEST_DATAVIEW_BYTEOFFSET = 5;
static constexpr int32_t TEST_DATAVIEW_BYTELENGTH = 10;
static constexpr int32_t TEST_BUFFER_LENGTH = 15;
static constexpr int32_t TEST_DATAVIEW_LENGTH = 20;
static const char TEST_SYMBOL_DESCRIPTION[] = "testSymbol";
static constexpr int32_t TEST_STRING_LENGTH = 10;
static const char16_t TEST_UTF16_STRING[] = u"testUtf16";
static constexpr int32_t TEST_STRING_LENGTH_FOUR = 4;
static constexpr int32_t TEST_STRING_LENGTH_MINUS_ONE = -1;
static const char TEST_EMPTY_STRING[] = "";
static const char TEST_ERROR_INFO[] = "test error info";
static constexpr uint64_t TEST_BIGINT_VALUE = 12345678901234ULL;
static constexpr uint32_t TEST_BIGINT_WORDS_SIZE = 1;
static const char TEST_PROPERTY_KEY[] = "propertyKey";
static constexpr int32_t TEST_INDEX_VALUE = 1;
namespace panda::test {
using BuiltinsFunction = ecmascript::builtins::BuiltinsFunction;
using PGOProfilerManager = panda::ecmascript::pgo::PGOProfilerManager;
using FunctionForRef = Local<JSValueRef> (*)(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 <typename T> void TestNumberRef(T val, TaggedType expected)
{
LocalScope scope(vm_);
Local<NumberRef> 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<T>) {
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<T>) {
ASSERT_EQ(obj->Int32Value(vm_), val);
} else {
ASSERT_EQ(obj->Uint32Value(vm_), val);
}
}
TaggedType ConvertDouble(double val)
{
return base::bit_cast<JSTaggedType>(val) + JSTaggedValue::DOUBLE_ENCODE_OFFSET;
}
static void FakeReleaseSecureMemCallback(void* mapper)
{
if (mapper != nullptr) {
delete reinterpret_cast<uint32_t *>(mapper);
}
}
protected:
JSThread *thread_ = nullptr;
EcmaVM *vm_ = nullptr;
};
Local<JSValueRef> FunctionCallback(JsiRuntimeCallInfo *info)
{
EscapeLocalScope scope(info->GetVM());
return scope.Escape(ArrayRef::New(info->GetVM(), info->GetArgsNumber()));
}
void WeakRefCallback(EcmaVM *vm)
{
LocalScope scope(vm);
Local<ObjectRef> object = ObjectRef::New(vm);
Global<ObjectRef> globalObject(vm, object);
globalObject.SetWeak();
Local<ObjectRef> object1 = ObjectRef::New(vm);
Global<ObjectRef> 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<ObjectRef> 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());
}
HWTEST_F_L0(JSNApiTests, GetThreadName)
{
std::string threadName = vm_->GetJSThread()->GetThreadName();
ASSERT_FALSE(threadName.empty());
}
* @tc.number: ffi_interface_api_GetAllVMHeapMemoryInfo
* @tc.name: GetAllVMHeapMemoryInfo
* @tc.desc: Test GetAllVMHeapMemoryInfo API to retrieve all VM heap memory information including
* thread ID, thread name, and heap memory usage (in KB).
* @tc.type: FUNC
* @tc.require: Issue#12406
*/
HWTEST_F_L0(JSNApiTests, GetAllVMHeapMemoryInfo)
{
ThreadStateTransitionScope<JSThread, ThreadState::NATIVE> scope(thread_);
auto heapInfos = JSNApi::GetAllVMHeapMemoryInfo();
ASSERT_FALSE(heapInfos.empty());
uint32_t currentThreadId = vm_->GetJSThread()->GetThreadId();
bool foundCurrentThread = false;
bool foundSharedHeap = false;
for (const auto& info : heapInfos) {
if (info.threadId == currentThreadId) {
foundCurrentThread = true;
ASSERT_FALSE(info.threadName.empty());
ASSERT_EQ(info.heapType, "local");
}
if (info.heapType == "shared") {
foundSharedHeap = true;
ASSERT_EQ(info.threadId, 0U);
ASSERT_EQ(info.threadName, "[SharedHeap]");
}
}
ASSERT_TRUE(foundCurrentThread);
ASSERT_TRUE(foundSharedHeap);
}
* @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<FunctionRef> callback = FunctionRef::New(vm_, FunctionCallback);
ASSERT_TRUE(!callback.IsEmpty());
std::vector<Local<JSValueRef>> arguments;
arguments.emplace_back(JSValueRef::Undefined(vm_));
Local<JSValueRef> result = callback->Call(vm_, JSValueRef::Undefined(vm_),
arguments.data(), arguments.size());
ASSERT_TRUE(result->IsArray(vm_));
Local<ArrayRef> array(result);
ASSERT_EQ(static_cast<uint64_t>(array->Length(vm_)), arguments.size());
}
HWTEST_F_L0(JSNApiTests, GetProperty)
{
LocalScope scope(vm_);
Local<ObjectRef> globalObject = JSNApi::GetGlobalObject(vm_);
ASSERT_FALSE(globalObject.IsEmpty());
ASSERT_TRUE(globalObject->IsObject(vm_));
Local<ObjectRef> key = StringRef::NewFromUtf8(vm_, "Number");
Local<ObjectRef> property = globalObject->Get(vm_, key);
ASSERT_TRUE(property->IsFunction(vm_));
}
HWTEST_F_L0(JSNApiTests, SetProperty)
{
LocalScope scope(vm_);
Local<ObjectRef> globalObject = JSNApi::GetGlobalObject(vm_);
ASSERT_FALSE(globalObject.IsEmpty());
ASSERT_TRUE(globalObject->IsObject(vm_));
Local<ArrayRef> property = ArrayRef::New(vm_, 3);
ASSERT_TRUE(property->IsArray(vm_));
ASSERT_EQ(property->Length(vm_), 3U);
Local<ObjectRef> key = StringRef::NewFromUtf8(vm_, "Test");
bool result = globalObject->Set(vm_, key, property);
ASSERT_TRUE(result);
Local<ObjectRef> propertyGet = globalObject->Get(vm_, key);
ASSERT_TRUE(propertyGet->IsArray(vm_));
ASSERT_EQ(Local<ArrayRef>(propertyGet)->Length(vm_), 3U);
}
* @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<ObjectRef> globalObject = JSNApi::GetGlobalObject(vm_);
ASSERT_FALSE(globalObject.IsEmpty());
ASSERT_TRUE(globalObject->IsObject(vm_));
const char * const test { R"({"orientation": "portrait"})" };
Local<ObjectRef> jsonString = StringRef::NewFromUtf8(vm_, test);
Local<JSValueRef> result = JSON::Parse(vm_, jsonString);
ASSERT_TRUE(result->IsObject(vm_));
Local<ObjectRef> keyString = StringRef::NewFromUtf8(vm_, "orientation");
Local<JSValueRef> property = Local<ObjectRef>(result)->Get(vm_, keyString);
ASSERT_TRUE(property->IsString(vm_));
}
HWTEST_F_L0(JSNApiTests, JsonParser_2)
{
LocalScope scope(vm_);
Local<ObjectRef> globalObject = JSNApi::GetGlobalObject(vm_);
ASSERT_FALSE(globalObject.IsEmpty());
ASSERT_TRUE(globalObject->IsObject(vm_));
const char16_t * const test { uR"({"orientation": "portrait"})" };
Local<ObjectRef> jsonString = StringRef::NewFromUtf16(vm_, test);
Local<JSValueRef> result = JSON::Parse(vm_, jsonString);
ASSERT_TRUE(result->IsObject(vm_));
Local<ObjectRef> keyString = StringRef::NewFromUtf8(vm_, "orientation");
Local<JSValueRef> property = Local<ObjectRef>(result)->Get(vm_, keyString);
ASSERT_TRUE(property->IsString(vm_));
}
HWTEST_F_L0(JSNApiTests, StrictEqual)
{
LocalScope scope(vm_);
Local<StringRef> origin = StringRef::NewFromUtf8(vm_, "1");
Local<StringRef> target1 = StringRef::NewFromUtf8(vm_, "1");
Local<NumberRef> 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<FunctionRef> target = FunctionRef::New(vm_, nullptr);
Local<ArrayRef> origin = ArrayRef::New(vm_, 1);
ASSERT_FALSE(origin->InstanceOf(vm_, target));
}
HWTEST_F_L0(JSNApiTests, TypeOf)
{
LocalScope scope(vm_);
Local<StringRef> origin = StringRef::NewFromUtf8(vm_, "1");
Local<StringRef> typeString = origin->Typeof(vm_);
ASSERT_EQ(typeString->ToString(vm_), "string");
Local<NumberRef> 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<StringRef> description = StringRef::NewFromUtf8(vm_, "test");
Local<SymbolRef> 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<StringRef> testString = StringRef::NewFromUtf8(vm_, test.c_str());
EXPECT_EQ(testString->Utf8Length(vm_), 12);
char buffer[12];
EXPECT_EQ(testString->WriteUtf8(vm_, buffer, 12), 12);
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<StringRef> testString = StringRef::NewFromUtf8(vm_, test.c_str());
EXPECT_EQ(testString->Utf8Length(vm_), 4);
char buffer[4];
EXPECT_EQ(testString->WriteUtf8(vm_, buffer, 4), 4);
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;
Local<StringRef> 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');
Local<StringRef> 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<StringRef> testString1 =
StringRef::NewFromUtf8(vm_, test.c_str(), test.length());
Local<TypedArrayRef> 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<StringRef> testString1 =
StringRef::NewFromUtf8(vm_, test.c_str(), test.length());
Local<TypedArrayRef> typedArray = testString1->EncodeIntoUint8Array(vm_);
char *res = reinterpret_cast<char *>(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<StringRef> 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], '-');
}
* @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<StringRef> 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<StringRef> toString = StringRef::NewFromUtf8(vm_, "-123.3");
Local<JSValueRef> toValue(toString);
ASSERT_EQ(toString->ToNumber(vm_)->Value(), -123.3);
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<StringRef> toString = StringRef::NewFromUtf8(vm_, "-123");
Local<JSValueRef> toValue(toString);
ASSERT_EQ(toString->Int32Value(vm_), -123);
ASSERT_EQ(toString->BooleaValue(vm_), true);
ASSERT_EQ(toString->Uint32Value(vm_), 4294967173U);
ASSERT_EQ(toString->IntegerValue(vm_), -123);
}
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<void *>(Attach), reinterpret_cast<void *>(Detach));
size_t nativeBindingSize = 7 * sizeof(void *);
Local<NativePointerRef> nativeInfo = NativePointerRef::New(
vm_, reinterpret_cast<void *>(info),
[]([[maybe_unused]] void *env, void *data, [[maybe_unused]] void *info) {
auto externalInfo = reinterpret_cast<panda::JSNApi::NativeBindingInfo *>(data);
delete externalInfo;
},
nullptr, nativeBindingSize);
Local<ObjectRef> object = ObjectRef::New(vm_);
ASSERT_FALSE(object->IsNativeBindingObject(vm_));
bool result = object->ConvertToNativeBindingObject(vm_, nativeInfo);
ASSERT_TRUE(result);
ASSERT_TRUE(object->IsNativeBindingObject(vm_));
Local<NativePointerRef> nativeInfo1 = object->GetNativeBindingPointer(vm_);
auto info1 = static_cast<panda::JSNApi::NativeBindingInfo *>(nativeInfo1->Value());
ASSERT_EQ(info, info1);
Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, "TestKey");
Local<JSValueRef> value = ObjectRef::New(vm_);
PropertyAttribute attribute(value, true, true, true);
ASSERT_TRUE(object->DefineProperty(vm_, key, attribute));
Local<JSValueRef> 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<ObjectRef> object = ObjectRef::New(vm_);
Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, "TestKey");
Local<JSValueRef> value = ObjectRef::New(vm_);
PropertyAttribute attribute(value, true, true, true);
ASSERT_TRUE(object->DefineProperty(vm_, key, attribute));
Local<JSValueRef> value1 = object->Get(vm_, key);
ASSERT_TRUE(value->IsStrictEquals(vm_, value1));
}
HWTEST_F_L0(JSNApiTests, HasProperty)
{
LocalScope scope(vm_);
Local<ObjectRef> object = ObjectRef::New(vm_);
Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, "TestKey");
Local<JSValueRef> 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<ObjectRef> object = ObjectRef::New(vm_);
Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, "TestKey");
Local<JSValueRef> 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<FunctionRef> function = FunctionRef::New(vm_, nullptr);
Local<JSValueRef> protoType = function->GetPrototype(vm_);
ASSERT_TRUE(protoType->IsObject(vm_));
Local<FunctionRef> object = ObjectRef::New(vm_);
protoType = object->GetPrototype(vm_);
ASSERT_TRUE(protoType->IsObject(vm_));
auto info = CreateNativeBindingInfo(reinterpret_cast<void *>(Attach), reinterpret_cast<void *>(Detach));
size_t nativeBindingSize = 7 * sizeof(void *);
Local<NativePointerRef> nativeInfo = NativePointerRef::New(
vm_, reinterpret_cast<void *>(info),
[]([[maybe_unused]] void *env, void *data, [[maybe_unused]] void *info) {
auto externalInfo = reinterpret_cast<panda::JSNApi::NativeBindingInfo *>(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<StringRef>(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<JSValueRef> reason = info->GetCallArgRef(0);
ASSERT_TRUE(reason->IsString(info->GetVM()));
ASSERT_EQ(Local<StringRef>(reason)->ToString(info->GetVM()), "Reject");
}
Local<JSValueRef> RejectCallback(JsiRuntimeCallInfo *info)
{
LocalScope scope(info->GetVM());
CheckReject(info);
return JSValueRef::Undefined(info->GetVM());
}
HWTEST_F_L0(JSNApiTests, PromiseCatch)
{
LocalScope scope(vm_);
Local<PromiseCapabilityRef> capability = PromiseCapabilityRef::New(vm_);
Local<PromiseRef> promise = capability->GetPromise(vm_);
Local<FunctionRef> reject = FunctionRef::New(vm_, RejectCallback);
Local<PromiseRef> catchPromise = promise->Catch(vm_, reject);
ASSERT_TRUE(promise->IsPromise(vm_));
ASSERT_TRUE(catchPromise->IsPromise(vm_));
Local<StringRef> reason = StringRef::NewFromUtf8(vm_, "Reject");
ASSERT_TRUE(capability->Reject(vm_, reason));
vm_->ExecutePromisePendingJob();
}
HWTEST_F_L0(JSNApiTests, PromiseCatchUintPtr)
{
LocalScope scope(vm_);
Local<PromiseCapabilityRef> capability = PromiseCapabilityRef::New(vm_);
Local<PromiseRef> promise = capability->GetPromise(vm_);
Local<FunctionRef> reject = FunctionRef::New(vm_, RejectCallback);
Local<PromiseRef> catchPromise = promise->Catch(vm_, reject);
ASSERT_TRUE(promise->IsPromise(vm_));
ASSERT_TRUE(catchPromise->IsPromise(vm_));
Local<StringRef> reason = StringRef::NewFromUtf8(vm_, "Reject");
ASSERT_TRUE(capability->Reject(vm_, reinterpret_cast<uintptr_t>(*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<JSValueRef> value = info->GetCallArgRef(0);
ASSERT_TRUE(value->IsNumber());
ASSERT_EQ(Local<NumberRef>(value)->Value(), 300.3);
}
Local<JSValueRef> ResolvedCallback(JsiRuntimeCallInfo *info)
{
LocalScope scope(info->GetVM());
CheckResolve(info);
return JSValueRef::Undefined(info->GetVM());
}
HWTEST_F_L0(JSNApiTests, PromiseThen)
{
LocalScope scope(vm_);
Local<PromiseCapabilityRef> capability = PromiseCapabilityRef::New(vm_);
Local<PromiseRef> promise = capability->GetPromise(vm_);
Local<FunctionRef> resolve = FunctionRef::New(vm_, ResolvedCallback);
Local<FunctionRef> reject = FunctionRef::New(vm_, RejectCallback);
Local<PromiseRef> thenPromise = promise->Then(vm_, resolve, reject);
ASSERT_TRUE(promise->IsPromise(vm_));
ASSERT_TRUE(thenPromise->IsPromise(vm_));
Local<StringRef> value = NumberRef::New(vm_, 300.3);
ASSERT_TRUE(capability->Resolve(vm_, value));
vm_->ExecutePromisePendingJob();
}
HWTEST_F_L0(JSNApiTests, PromiseThenUintPtr)
{
LocalScope scope(vm_);
Local<PromiseCapabilityRef> capability = PromiseCapabilityRef::New(vm_);
Local<PromiseRef> promise = capability->GetPromise(vm_);
Local<FunctionRef> resolve = FunctionRef::New(vm_, ResolvedCallback);
Local<FunctionRef> reject = FunctionRef::New(vm_, RejectCallback);
Local<PromiseRef> thenPromise = promise->Then(vm_, resolve, reject);
ASSERT_TRUE(promise->IsPromise(vm_));
ASSERT_TRUE(thenPromise->IsPromise(vm_));
Local<StringRef> value = NumberRef::New(vm_, 300.3);
ASSERT_TRUE(capability->Resolve(vm_, reinterpret_cast<uintptr_t>(*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<ObjectRef> object = JSNApi::GetGlobalObject(vm_);
Local<StringRef> key = StringRef::NewFromUtf8(vm_, "Number");
Local<FunctionRef> numberConstructor = object->Get(vm_, key);
Local<JSValueRef> argv[1];
argv[0] = NumberRef::New(vm_, 1.3);
Local<JSValueRef> result = numberConstructor->Constructor(vm_, argv, 1);
ASSERT_TRUE(result->IsObject(vm_));
ASSERT_EQ(result->ToNumber(vm_)->Value(), 1.3);
}
* @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<ArrayBufferRef> 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<uint8_t *>(buffer);
Data *currentData = reinterpret_cast<Data *>(data);
ASSERT_EQ(currentData->length, 15);
delete currentData;
isFree = true;
};
{
LocalScope scope(vm_);
uint8_t *buffer = new uint8_t[length]();
Local<ArrayBufferRef> 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<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
JSNApi::TriggerGC(vm_);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<DataViewRef> 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);
ASSERT_EQ(dataView->ByteOffset(), 5U);
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<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<Int8ArrayRef> typedArray = Int8ArrayRef::New(vm_, arrayBuffer, 5, 6);
ASSERT_TRUE(typedArray->IsInt8Array(vm_));
ASSERT_EQ(typedArray->ByteLength(vm_), 6U);
ASSERT_EQ(typedArray->ByteOffset(vm_), 5U);
ASSERT_EQ(typedArray->ArrayLength(vm_), 6U);
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<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<Uint8ArrayRef> typedArray = Uint8ArrayRef::New(vm_, arrayBuffer, 5, 6);
ASSERT_TRUE(typedArray->IsUint8Array(vm_));
ASSERT_EQ(typedArray->ByteLength(vm_), 6U);
ASSERT_EQ(typedArray->ByteOffset(vm_), 5U);
ASSERT_EQ(typedArray->ArrayLength(vm_), 6U);
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<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<Uint8ClampedArrayRef> typedArray = Uint8ClampedArrayRef::New(vm_, arrayBuffer, 5, 6);
ASSERT_TRUE(typedArray->IsUint8ClampedArray(vm_));
ASSERT_EQ(typedArray->ByteLength(vm_), 6U);
ASSERT_EQ(typedArray->ByteOffset(vm_), 5U);
ASSERT_EQ(typedArray->ArrayLength(vm_), 6U);
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<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<Int16ArrayRef> typedArray = Int16ArrayRef::New(vm_, arrayBuffer, 4, 6);
ASSERT_TRUE(typedArray->IsInt16Array(vm_));
ASSERT_EQ(typedArray->ByteLength(vm_), 12U);
ASSERT_EQ(typedArray->ByteOffset(vm_), 4U);
ASSERT_EQ(typedArray->ArrayLength(vm_), 6U);
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<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<Uint16ArrayRef> typedArray = Uint16ArrayRef::New(vm_, arrayBuffer, 4, 6);
ASSERT_TRUE(typedArray->IsUint16Array(vm_));
ASSERT_EQ(typedArray->ByteLength(vm_), 12U);
ASSERT_EQ(typedArray->ByteOffset(vm_), 4U);
ASSERT_EQ(typedArray->ArrayLength(vm_), 6U);
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<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<Uint32ArrayRef> typedArray = Uint32ArrayRef::New(vm_, arrayBuffer, 4, 6);
ASSERT_TRUE(typedArray->IsUint32Array(vm_));
ASSERT_EQ(typedArray->ByteLength(vm_), 24U);
ASSERT_EQ(typedArray->ByteOffset(vm_), 4U);
ASSERT_EQ(typedArray->ArrayLength(vm_), 6U);
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<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<Int32ArrayRef> typedArray = Int32ArrayRef::New(vm_, arrayBuffer, 4, 6);
ASSERT_TRUE(typedArray->IsInt32Array(vm_));
ASSERT_EQ(typedArray->ByteLength(vm_), 24U);
ASSERT_EQ(typedArray->ByteOffset(vm_), 4U);
ASSERT_EQ(typedArray->ArrayLength(vm_), 6U);
ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_));
}
HWTEST_F_L0(JSNApiTests, Float32Array)
{
LocalScope scope(vm_);
const int32_t length = 30;
Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<Float32ArrayRef> typedArray = Float32ArrayRef::New(vm_, arrayBuffer, 4, 6);
ASSERT_TRUE(typedArray->IsFloat32Array(vm_));
ASSERT_EQ(typedArray->ByteLength(vm_), 24U);
ASSERT_EQ(typedArray->ByteOffset(vm_), 4U);
ASSERT_EQ(typedArray->ArrayLength(vm_), 6U);
ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_));
}
HWTEST_F_L0(JSNApiTests, Float64Array)
{
LocalScope scope(vm_);
const int32_t length = 57;
Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<Float64ArrayRef> typedArray = Float64ArrayRef::New(vm_, arrayBuffer, 8, 6);
ASSERT_TRUE(typedArray->IsFloat64Array(vm_));
ASSERT_EQ(typedArray->ByteLength(vm_), 48U);
ASSERT_EQ(typedArray->ByteOffset(vm_), 8U);
ASSERT_EQ(typedArray->ArrayLength(vm_), 6U);
ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), arrayBuffer->GetBuffer(vm_));
}
HWTEST_F_L0(JSNApiTests, BigInt64Array)
{
LocalScope scope(vm_);
const int32_t length = 57;
Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<BigInt64ArrayRef> typedArray = BigInt64ArrayRef::New(vm_, arrayBuffer, 8, 6);
ASSERT_TRUE(typedArray->IsBigInt64Array(vm_));
ASSERT_EQ(typedArray->ByteLength(vm_), 48U);
ASSERT_EQ(typedArray->ByteOffset(vm_), 8U);
ASSERT_EQ(typedArray->ArrayLength(vm_), 6U);
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<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<BigUint64ArrayRef> typedArray = BigUint64ArrayRef::New(vm_, arrayBuffer, 8, 6);
ASSERT_TRUE(typedArray->IsBigUint64Array(vm_));
ASSERT_EQ(typedArray->ByteLength(vm_), 48U);
ASSERT_EQ(typedArray->ByteOffset(vm_), 8U);
ASSERT_EQ(typedArray->ArrayLength(vm_), 6U);
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<StringRef> message = StringRef::NewFromUtf8(vm_, "ErrorTest");
Local<JSValueRef> 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<StringRef> message = StringRef::NewFromUtf8(vm_, "ErrorTest");
Local<JSValueRef> 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<StringRef> message = StringRef::NewFromUtf8(vm_, "ErrorTest");
Local<JSValueRef> 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<StringRef> message = StringRef::NewFromUtf8(vm_, "ErrorTest");
Local<JSValueRef> 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<StringRef> message = StringRef::NewFromUtf8(vm_, "ErrorTest");
Local<JSValueRef> 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<StringRef> message = StringRef::NewFromUtf8(vm_, "ErrorTest");
Local<JSValueRef> 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<GlobalEnv> env = vm_->GetGlobalEnv();
JSHandle<JSTaggedValue> set = env->GetBuiltinsSetFunction();
Local<FunctionRef> setLocal = JSNApiHelper::ToLocal<FunctionRef>(set);
JSHandle<JSTaggedValue> map = env->GetBuiltinsMapFunction();
Local<FunctionRef> mapLocal = JSNApiHelper::ToLocal<FunctionRef>(map);
JSHandle<JSTaggedValue> setPrototype(thread_, JSHandle<JSFunction>::Cast(set)->GetFunctionPrototype(thread_));
JSHandle<JSTaggedValue> mapPrototype(thread_, JSHandle<JSFunction>::Cast(map)->GetFunctionPrototype(thread_));
JSHandle<JSTaggedValue> mapPrototypeProto(thread_, JSTaggedValue::GetPrototype(thread_, mapPrototype));
bool same = JSTaggedValue::SameValue(thread_, setPrototype, mapPrototypeProto);
ASSERT_FALSE(same);
JSHandle<JSTaggedValue> mapProto(thread_, JSTaggedValue::GetPrototype(thread_, map));
bool same1 = JSTaggedValue::SameValue(thread_, set, mapProto);
ASSERT_FALSE(same1);
auto factory = vm_->GetFactory();
JSHandle<JSTaggedValue> defaultString = thread_->GlobalConstants()->GetHandledDefaultString();
PropertyDescriptor desc = PropertyDescriptor(thread_, defaultString);
bool success = JSObject::DefineOwnProperty(thread_, JSHandle<JSObject>::Cast(set), defaultString, desc);
ASSERT_TRUE(success);
JSHandle<JSTaggedValue> property1String(thread_, factory->NewFromASCII("property1").GetTaggedValue());
JSHandle<JSTaggedValue> func = env->GetTypedArrayFunction();
PropertyDescriptor desc1 = PropertyDescriptor(thread_, func);
bool success1 = JSObject::DefineOwnProperty(thread_, JSHandle<JSObject>::Cast(set), property1String, desc1);
ASSERT_TRUE(success1);
mapLocal->Inherit(vm_, setLocal);
JSHandle<JSTaggedValue> sonHandle = JSNApiHelper::ToJSHandle(mapLocal);
JSHandle<JSTaggedValue> sonPrototype(thread_, JSHandle<JSFunction>::Cast(sonHandle)->GetFunctionPrototype(thread_));
JSHandle<JSTaggedValue> sonPrototypeProto(thread_, JSTaggedValue::GetPrototype(thread_, sonPrototype));
bool same2 = JSTaggedValue::SameValue(thread_, setPrototype, sonPrototypeProto);
ASSERT_TRUE(same2);
JSHandle<JSTaggedValue> sonProto(thread_, JSTaggedValue::GetPrototype(thread_, map));
bool same3 = JSTaggedValue::SameValue(thread_, set, sonProto);
ASSERT_TRUE(same3);
JSHandle<JSObject> sonObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(sonHandle), sonHandle);
bool isInstance = JSObject::InstanceOf(thread_, JSHandle<JSTaggedValue>::Cast(sonObj), set);
ASSERT_TRUE(isInstance);
OperationResult res = JSObject::GetProperty(thread_, JSHandle<JSObject>::Cast(sonHandle), defaultString);
bool same4 = JSTaggedValue::SameValue(thread_, defaultString, res.GetValue());
ASSERT_TRUE(same4);
OperationResult res1 = JSObject::GetProperty(thread_, JSHandle<JSObject>::Cast(sonHandle), property1String);
bool same5 = JSTaggedValue::SameValue(thread_, func, res1.GetValue());
ASSERT_TRUE(same5);
Local<FunctionRef> son1 = FunctionRef::New(vm_, FunctionCallback, nullptr);
son1->Inherit(vm_, mapLocal);
JSHandle<JSFunction> son1Handle = JSHandle<JSFunction>::Cast(JSNApiHelper::ToJSHandle(son1));
ASSERT_TRUE(son1Handle->HasFunctionPrototype(thread_));
}
HWTEST_F_L0(JSNApiTests, InheritPrototype_002)
{
ecmascript::ThreadManagedScope managedScope(vm_->GetJSThread());
LocalScope scope(vm_);
JSHandle<GlobalEnv> env = vm_->GetGlobalEnv();
JSHandle<JSTaggedValue> weakSet = env->GetBuiltinsWeakSetFunction();
Local<FunctionRef> weakSetLocal = JSNApiHelper::ToLocal<FunctionRef>(weakSet);
JSHandle<JSTaggedValue> weakMap = env->GetBuiltinsWeakMapFunction();
Local<FunctionRef> weakMapLocal = JSNApiHelper::ToLocal<FunctionRef>(weakMap);
weakMapLocal->Inherit(vm_, weakSetLocal);
auto factory = vm_->GetFactory();
JSHandle<JSTaggedValue> property1String(thread_, factory->NewFromASCII("property1").GetTaggedValue());
JSHandle<JSTaggedValue> func = env->GetArrayFunction();
PropertyDescriptor desc1 = PropertyDescriptor(thread_, func);
bool success1 = JSObject::DefineOwnProperty(thread_, JSHandle<JSObject>::Cast(weakMap), property1String, desc1);
ASSERT_TRUE(success1);
JSHandle<JSTaggedValue> sonHandle = JSNApiHelper::ToJSHandle(weakMapLocal);
JSHandle<JSObject> sonObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(sonHandle), sonHandle);
JSHandle<JSTaggedValue> fatherHandle = JSNApiHelper::ToJSHandle(weakSetLocal);
JSHandle<JSObject> fatherObj =
factory->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(fatherHandle), fatherHandle);
JSHandle<JSTaggedValue> sonMethod = JSObject::GetMethod(thread_, JSHandle<JSTaggedValue>(sonObj), property1String);
JSHandle<JSTaggedValue> fatherMethod =
JSObject::GetMethod(thread_, JSHandle<JSTaggedValue>(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<GlobalEnv> env = vm_->GetGlobalEnv();
auto factory = vm_->GetFactory();
JSHandle<Method> invokeSelf =
factory->NewMethodForNativeFunction(reinterpret_cast<void *>(BuiltinsFunction::FunctionPrototypeInvokeSelf));
JSHandle<JSHClass> protoClass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithProto());
JSHandle<JSFunction> protoFunc = factory->NewJSFunctionByHClass(invokeSelf, protoClass);
Local<FunctionRef> protoLocal = JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(protoFunc));
JSHandle<JSHClass> noProtoClass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutProto());
JSHandle<JSFunction> noProtoFunc = factory->NewJSFunctionByHClass(invokeSelf, noProtoClass);
Local<FunctionRef> noProtoLocal = JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(noProtoFunc));
JSHandle<JSFunction> sonHandle = JSHandle<JSFunction>::Cast(JSNApiHelper::ToJSHandle(noProtoLocal));
EXPECT_FALSE(sonHandle->HasFunctionPrototype(thread_));
JSHandle<JSTaggedValue> defaultString = thread_->GlobalConstants()->GetHandledDefaultString();
PropertyDescriptor desc = PropertyDescriptor(thread_, defaultString);
JSObject::DefineOwnProperty(thread_, JSHandle<JSObject>::Cast(protoFunc), defaultString, desc);
noProtoLocal->Inherit(vm_, protoLocal);
JSHandle<JSFunction> son1Handle = JSHandle<JSFunction>::Cast(JSNApiHelper::ToJSHandle(noProtoLocal));
EXPECT_TRUE(son1Handle->HasFunctionPrototype(thread_));
OperationResult res = JSObject::GetProperty(thread_, JSHandle<JSObject>::Cast(son1Handle), defaultString);
EXPECT_EQ(JSTaggedValue::SameValue(thread_, defaultString, res.GetValue()), true);
JSHandle<JSTaggedValue> propertyString(thread_, factory->NewFromASCII("property").GetTaggedValue());
JSHandle<JSTaggedValue> func = env->GetArrayFunction();
PropertyDescriptor desc1 = PropertyDescriptor(thread_, func);
JSObject::DefineOwnProperty(thread_, JSHandle<JSObject>::Cast(protoFunc), propertyString, desc1);
OperationResult res1 = JSObject::GetProperty(thread_, JSHandle<JSObject>::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<GlobalEnv> env = vm_->GetGlobalEnv();
auto factory = vm_->GetFactory();
JSHandle<JSTaggedValue> weakSet = env->GetBuiltinsWeakSetFunction();
JSHandle<JSTaggedValue> deleteString(factory->NewFromASCII("delete"));
JSHandle<JSTaggedValue> addString(factory->NewFromASCII("add"));
JSHandle<JSTaggedValue> defaultString = thread_->GlobalConstants()->GetHandledDefaultString();
JSHandle<JSTaggedValue> deleteMethod = JSObject::GetMethod(thread_, weakSet, deleteString);
JSHandle<JSTaggedValue> addMethod = JSObject::GetMethod(thread_, weakSet, addString);
JSHandle<Method> invokeSelf =
factory->NewMethodForNativeFunction(reinterpret_cast<void *>(BuiltinsFunction::FunctionPrototypeInvokeSelf));
JSHandle<Method> ctor =
factory->NewMethodForNativeFunction(reinterpret_cast<void *>(BuiltinsFunction::FunctionConstructor));
JSHandle<JSHClass> protoClass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithProto());
JSHandle<JSFunction> funcFuncPrototype = factory->NewJSFunctionByHClass(invokeSelf, protoClass);
PropertyDescriptor desc = PropertyDescriptor(thread_, deleteMethod);
JSObject::DefineOwnProperty(thread_, JSHandle<JSObject>::Cast(funcFuncPrototype), deleteString, desc);
JSHandle<JSTaggedValue> funcFuncPrototypeValue(funcFuncPrototype);
JSHandle<JSHClass> funcFuncProtoIntanceClass =
factory->NewEcmaHClass(JSFunction::SIZE, JSType::JS_FUNCTION, funcFuncPrototypeValue);
JSHandle<JSFunction> protoFunc = factory->NewJSFunctionByHClass(ctor, funcFuncProtoIntanceClass);
EXPECT_TRUE(*protoFunc != nullptr);
PropertyDescriptor desc1 = PropertyDescriptor(thread_, addMethod);
JSObject::DefineOwnProperty(thread_, JSHandle<JSObject>::Cast(protoFunc), addString, desc1);
JSObject::DefineOwnProperty(thread_, JSHandle<JSObject>::Cast(protoFunc), deleteString, desc);
Local<FunctionRef> protoLocal = JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(protoFunc));
JSHandle<JSHClass> noProtoClass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutProto());
JSHandle<JSFunction> funcFuncNoProtoPrototype = factory->NewJSFunctionByHClass(invokeSelf, noProtoClass);
JSHandle<JSTaggedValue> funcFuncNoProtoPrototypeValue(funcFuncNoProtoPrototype);
JSHandle<JSHClass> funcFuncNoProtoProtoIntanceClass =
factory->NewEcmaHClass(JSFunction::SIZE, JSType::JS_FUNCTION, funcFuncNoProtoPrototypeValue);
JSHandle<JSFunction> noProtoFunc = factory->NewJSFunctionByHClass(ctor, funcFuncNoProtoProtoIntanceClass);
EXPECT_TRUE(*noProtoFunc != nullptr);
PropertyDescriptor desc2 = PropertyDescriptor(thread_, defaultString);
JSObject::DefineOwnProperty(thread_, JSHandle<JSObject>::Cast(noProtoFunc), addString, desc2);
Local<FunctionRef> noProtoLocal = JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(noProtoFunc));
noProtoLocal->Inherit(vm_, protoLocal);
JSHandle<JSFunction> sonHandle = JSHandle<JSFunction>::Cast(JSNApiHelper::ToJSHandle(noProtoLocal));
OperationResult res = JSObject::GetProperty(thread_, JSHandle<JSObject>::Cast(sonHandle), deleteString);
EXPECT_EQ(JSTaggedValue::SameValue(thread_, deleteMethod, res.GetValue()), true);
OperationResult res1 = JSObject::GetProperty(thread_, JSHandle<JSObject>::Cast(sonHandle), addString);
EXPECT_EQ(JSTaggedValue::SameValue(thread_, defaultString, res1.GetValue()), true);
}
HWTEST_F_L0(JSNApiTests, ClassFunction)
{
LocalScope scope(vm_);
Local<FunctionRef> cls = FunctionRef::NewClassFunction(vm_, FunctionCallback, nullptr, nullptr);
JSHandle<JSTaggedValue> clsObj = JSNApiHelper::ToJSHandle(Local<JSValueRef>(cls));
ASSERT_TRUE(clsObj->IsClassConstructor());
JSTaggedValue accessor = JSHandle<JSFunction>(clsObj)->GetPropertyInlinedProps(
thread_, JSFunction::CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX);
ASSERT_TRUE(accessor.IsInternalAccessor());
accessor = JSHandle<JSFunction>(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<ObjectRef> object1 = ObjectRef::New(vm_);
Global<ObjectRef> globalObject1(vm_, object1);
globalObject1.SetWeak();
NativeReferenceHelper *temp = nullptr;
{
LocalScope scope1(vm_);
Local<ObjectRef> object2 = ObjectRef::New(vm_);
Global<ObjectRef> globalObject2(vm_, object2);
NativeReferenceHelper *ref1 = new NativeReferenceHelper(vm_, globalObject2, WeakRefCallback);
ref1->SetWeakCallback();
temp = ref1;
}
{
LocalScope scope1(vm_);
Local<ObjectRef> object3 = ObjectRef::New(vm_);
Global<ObjectRef> globalObject3(vm_, object3);
globalObject3.SetWeak();
}
Local<ObjectRef> object4 = ObjectRef::New(vm_);
Global<ObjectRef> globalObject4(vm_, object4);
NativeReferenceHelper *ref2 = new NativeReferenceHelper(vm_, globalObject4, WeakRefCallback);
ref2->SetWeakCallback();
vm_->CollectGarbage(TriggerGCType::OLD_GC);
delete temp;
delete ref2;
}
* @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<StringRef> origin = StringRef::NewFromUtf8(vm_, "1");
ASSERT_EQ("1", origin->ToString(vm_));
JSHandle<JSTaggedValue> jsFunc = globalEnv->GetArrayFunction();
JSHandle<JSObject> objVal1 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(jsFunc), jsFunc);
JSHandle<JSObject> objVal2 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(jsFunc), jsFunc);
JSObject *newObj2 = *objVal2;
JSTaggedValue canBeGcValue(newObj2);
uint32_t arrayLength = 2;
JSHandle<TaggedArray> 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);
JSNApi::TRIGGER_GC_TYPE gcType = JSNApi::TRIGGER_GC_TYPE::OLD_GC;
JSNApi::TriggerGC(vm_, gcType);
gcType = JSNApi::TRIGGER_GC_TYPE::FULL_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<Heap *>(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<TaggedArray> array = thread_->GetEcmaVM()->GetFactory()->NewTaggedArray(
1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
}
}
beforeSize = heap->GetHeapObjectSize();
}
#endif
Local<StringRef> origin = StringRef::NewFromUtf8(vm_, "1");
ASSERT_EQ("1", origin->ToString(vm_));
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.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<IntegerRef> intValue = IntegerRef::New(vm_, 0);
EXPECT_EQ(intValue->Value(), 0);
Local<JSValueRef> jsValue = intValue->GetValue(vm_);
EXPECT_TRUE(*jsValue == nullptr);
JSHandle<JSTaggedValue> nullHandle(thread_, JSTaggedValue::Null());
JSHandle<JSHClass> jsClassHandle = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_PRIMITIVE_REF, nullHandle);
JSHandle<JSTaggedValue> jsTaggedValue(factory->NewJSObjectWithInit(jsClassHandle));
Local<PrimitiveRef> jsValueRef = JSNApiHelper::ToLocal<JSPrimitiveRef>(jsTaggedValue);
EXPECT_TRUE(*(jsValueRef->GetValue(vm_)) != nullptr);
}
HWTEST_F_L0(JSNApiTests, BigIntRef_New_Uint64)
{
uint64_t maxUint64 = std::numeric_limits<uint64_t>::max();
Local<BigIntRef> maxBigintUint64 = BigIntRef::New(vm_, maxUint64);
EXPECT_TRUE(maxBigintUint64->IsBigInt(vm_));
JSHandle<BigInt> maxBigintUint64Val(thread_, JSNApiHelper::ToJSTaggedValue(*maxBigintUint64));
EXPECT_EQ(maxBigintUint64Val->GetDigit(0), static_cast<uint32_t>(maxUint64 & 0xffffffff));
EXPECT_EQ(maxBigintUint64Val->GetDigit(1), static_cast<uint32_t>((maxUint64 >> BigInt::DATA_BITS) & 0xffffffff));
uint64_t minUint64 = std::numeric_limits<uint64_t>::min();
Local<BigIntRef> minBigintUint64 = BigIntRef::New(vm_, minUint64);
EXPECT_TRUE(minBigintUint64->IsBigInt(vm_));
JSHandle<BigInt> minBigintUint64Val(thread_, JSNApiHelper::ToJSTaggedValue(*minBigintUint64));
EXPECT_EQ(minBigintUint64Val->GetDigit(0), static_cast<uint32_t>(minUint64 & 0xffffffff));
EXPECT_EQ(minBigintUint64Val->GetLength(), 1U);
}
HWTEST_F_L0(JSNApiTests, BigIntRef_New_Int64)
{
int64_t maxInt64 = std::numeric_limits<int64_t>::max();
Local<BigIntRef> maxBigintInt64 = BigIntRef::New(vm_, maxInt64);
EXPECT_TRUE(maxBigintInt64->IsBigInt(vm_));
JSHandle<BigInt> maxBigintInt64Val(thread_, JSNApiHelper::ToJSTaggedValue(*maxBigintInt64));
EXPECT_EQ(maxBigintInt64Val->GetDigit(0), static_cast<uint32_t>(maxInt64 & 0xffffffff));
EXPECT_EQ(maxBigintInt64Val->GetDigit(1), static_cast<uint32_t>((maxInt64 >> BigInt::DATA_BITS) & 0xffffffff));
int64_t minInt64 = std::numeric_limits<int64_t>::min();
Local<BigIntRef> minBigintInt64 = BigIntRef::New(vm_, minInt64);
EXPECT_TRUE(minBigintInt64->IsBigInt(vm_));
JSHandle<BigInt> minBigintInt64Val(thread_, JSNApiHelper::ToJSTaggedValue(*minBigintInt64));
EXPECT_EQ(minBigintInt64Val->GetSign(), true);
EXPECT_EQ(minBigintInt64Val->GetDigit(0), static_cast<uint32_t>((-minInt64) & 0xffffffff));
EXPECT_EQ(minBigintInt64Val->GetDigit(1), static_cast<uint32_t>(((-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<uint64_t>::min() - 1,
std::numeric_limits<uint64_t>::min(),
std::numeric_limits<uint64_t>::max(),
};
Local<JSValueRef> bigWords = BigIntRef::CreateBigWords(vm_, sign, size, words);
EXPECT_TRUE(bigWords->IsBigInt(vm_));
Local<BigIntRef> bigWordsRef(bigWords);
EXPECT_EQ(bigWordsRef->GetWordsArraySize(vm_), size);
JSHandle<BigInt> 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]();
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<DateRef> data = DateRef::New(vm_, time);
EXPECT_TRUE(data->IsDate(vm_));
Local<StringRef> tostring = data->ToString(vm_);
Local<JSValueRef> 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<PromiseCapabilityRef> capability = PromiseCapabilityRef::New(vm_);
Local<PromiseRef> promise = capability->GetPromise(vm_);
Local<FunctionRef> reject = FunctionRef::New(vm_, RejectCallback);
Local<PromiseRef> catchPromise = promise->Finally(vm_, reject);
ASSERT_TRUE(promise->IsPromise(vm_));
ASSERT_TRUE(catchPromise->IsPromise(vm_));
Local<PromiseRef> catchPromise1 = promise->Then(vm_, reject, reject);
ASSERT_TRUE(catchPromise1->IsPromise(vm_));
Local<FunctionRef> callback = FunctionRef::New(vm_, FunctionCallback);
ASSERT_TRUE(!callback.IsEmpty());
Local<PromiseRef> 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<FunctionRef> callback = FunctionRef::New(vm_, FunctionCallback);
ASSERT_TRUE(!callback.IsEmpty());
std::vector<Local<JSValueRef>> arguments;
arguments.emplace_back(JSValueRef::Undefined(vm_));
Local<JSValueRef> result = callback->Call(vm_, JSValueRef::Undefined(vm_), arguments.data(), arguments.size());
ASSERT_TRUE(result->IsArray(vm_));
Local<ArrayRef> array(result);
ASSERT_EQ(static_cast<uint64_t>(array->Length(vm_)), arguments.size());
void *res = nullptr;
res = JSNApi::SerializeValue(vm_, result, JSValueRef::Undefined(vm_), JSValueRef::Undefined(vm_), true);
EXPECT_TRUE(res);
}
* @tc.name: JSNApi_SerializeValueWithOptions
* @tc.desc: Test SerializeValue overload with SerializeOptions struct
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, JSNApi_SerializeValueWithOptions)
{
LocalScope scope(vm_);
Local<FunctionRef> callback = FunctionRef::New(vm_, FunctionCallback);
ASSERT_TRUE(!callback.IsEmpty());
std::vector<Local<JSValueRef>> arguments;
arguments.emplace_back(JSValueRef::Undefined(vm_));
Local<JSValueRef> result = callback->Call(vm_, JSValueRef::Undefined(vm_), arguments.data(), arguments.size());
ASSERT_TRUE(result->IsArray(vm_));
Local<ArrayRef> array(result);
ASSERT_EQ(static_cast<uint64_t>(array->Length(vm_)), arguments.size());
SerializeOptions options(true, false, true);
void *res = JSNApi::SerializeValue(vm_, result, JSValueRef::Undefined(vm_),
JSValueRef::Undefined(vm_), options);
EXPECT_TRUE(res);
}
* @tc.name: JSNApi_SerializeValueWithErrorWithOptions
* @tc.desc: Test SerializeValueWithError overload with SerializeOptions struct
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, JSNApi_SerializeValueWithErrorWithOptions)
{
LocalScope scope(vm_);
Local<FunctionRef> callback = FunctionRef::New(vm_, FunctionCallback);
ASSERT_TRUE(!callback.IsEmpty());
std::vector<Local<JSValueRef>> arguments;
arguments.emplace_back(JSValueRef::Undefined(vm_));
Local<JSValueRef> result = callback->Call(vm_, JSValueRef::Undefined(vm_), arguments.data(), arguments.size());
ASSERT_TRUE(result->IsArray(vm_));
Local<ArrayRef> array(result);
ASSERT_EQ(static_cast<uint64_t>(array->Length(vm_)), arguments.size());
std::string error;
SerializeOptions options(true, false, true);
void *res = JSNApi::SerializeValueWithError(vm_, result, JSValueRef::Undefined(vm_),
JSValueRef::Undefined(vm_), error, options);
EXPECT_TRUE(res);
EXPECT_TRUE(error.empty());
}
* @tc.name: JSNApi_SerializeValueOptionsConsistency
* @tc.desc: Verify SerializeValue with options produces same result as original function
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, JSNApi_SerializeValueOptionsConsistency)
{
LocalScope scope(vm_);
Local<FunctionRef> callback = FunctionRef::New(vm_, FunctionCallback);
ASSERT_TRUE(!callback.IsEmpty());
std::vector<Local<JSValueRef>> arguments;
arguments.emplace_back(JSValueRef::Undefined(vm_));
Local<JSValueRef> result = callback->Call(vm_, JSValueRef::Undefined(vm_), arguments.data(), arguments.size());
SerializeOptions options(true, false, true);
void *res = JSNApi::SerializeValue(vm_, result, JSValueRef::Undefined(vm_),
JSValueRef::Undefined(vm_), options);
EXPECT_TRUE(res);
JSNApi::DeleteSerializationData(res);
}
HWTEST_F_L0(JSNApiTests, ModuleDeserializeReturnEarlyWhenDisableModuleSnapshot)
{
uint32_t originalVersion = vm_->GetApplicationVersionCode();
vm_->GetJSOptions().SetDisableModuleSnapshot(true);
int arkProperties = vm_->GetJSOptions().GetArkProperties();
vm_->GetJSOptions().SetArkProperties(arkProperties & (~ArkProperties::DISABLE_JSPANDAFILE_MODULE_SNAPSHOT));
JSNApi::ModuleDeserialize(vm_, originalVersion + 1);
EXPECT_EQ(vm_->GetApplicationVersionCode(), originalVersion);
}
HWTEST_F_L0(JSNApiTests, ModuleDeserializeReturnEarlyWhenDisableJSPandaFileAndModuleSnapshot)
{
uint32_t originalVersion = vm_->GetApplicationVersionCode();
vm_->GetJSOptions().SetDisableModuleSnapshot(false);
int arkProperties = vm_->GetJSOptions().GetArkProperties();
vm_->GetJSOptions().SetArkProperties(arkProperties | ArkProperties::DISABLE_JSPANDAFILE_MODULE_SNAPSHOT);
JSNApi::ModuleDeserialize(vm_, originalVersion + 1);
EXPECT_EQ(vm_->GetApplicationVersionCode(), originalVersion);
}
HWTEST_F_L0(JSNApiTests, ModuleDeserializeReturnEarlyWhenBothDisabled)
{
uint32_t originalVersion = vm_->GetApplicationVersionCode();
vm_->GetJSOptions().SetDisableModuleSnapshot(true);
int arkProperties = vm_->GetJSOptions().GetArkProperties();
vm_->GetJSOptions().SetArkProperties(arkProperties | ArkProperties::DISABLE_JSPANDAFILE_MODULE_SNAPSHOT);
JSNApi::ModuleDeserialize(vm_, originalVersion);
EXPECT_EQ(vm_->GetApplicationVersionCode(), originalVersion);
}
HWTEST_F_L0(JSNApiTests, ModuleDeserializeNormalExecution)
{
uint32_t originalVersion = vm_->GetApplicationVersionCode();
vm_->GetJSOptions().SetDisableModuleSnapshot(false);
int arkProperties = vm_->GetJSOptions().GetArkProperties();
vm_->GetJSOptions().SetArkProperties(arkProperties & (~ArkProperties::DISABLE_JSPANDAFILE_MODULE_SNAPSHOT));
JSNApi::ModuleDeserialize(vm_, originalVersion + 1);
EXPECT_EQ(vm_->GetApplicationVersionCode(), originalVersion + 1);
}
* @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<void *>(BuiltinsFunction::FunctionPrototypeInvokeSelf);
JSNApi::SetHostPromiseRejectionTracker(vm_, data, data);
PromiseRejectCallback res = vm_->GetPromiseRejectCallback();
ASSERT_EQ(res, reinterpret_cast<ecmascript::PromiseRejectCallback>(data));
}
HWTEST_F_L0(JSNApiTests, JSNApi_SetNativePtrGetter_SetHostEnqueueJob)
{
void *cb = reinterpret_cast<void *>(BuiltinsFunction::FunctionPrototypeInvokeSelf);
JSNApi::SetNativePtrGetter(vm_, cb);
NativePtrGetter res = vm_->GetNativePtrGetter();
ASSERT_EQ(res, reinterpret_cast<ecmascript::NativePtrGetter>(cb));
}
HWTEST_F_L0(JSNApiTests, NumberRef_New)
{
uint32_t input = 32;
int64_t input1 = 1;
Local<NumberRef> res = NumberRef::New(vm_, input);
Local<NumberRef> 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<ObjectRef> object = ObjectRef::New(vm_);
Local<ArrayRef> 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<ObjectRef> object = ObjectRef::NewWrappedNapiObject(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<void *>(new std::string("test"));
void *vp2 = static_cast<void *>(new std::string("test"));
std::string *sp1 = static_cast<std::string *>(vp1);
object->SetNativePointerField(vm_, 33, vp1, callBack, vp2);
void *res1 = object->GetNativePointerField(vm_, 33);
std::string *sp2 = static_cast<std::string *>(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<void *>(BuiltinsFunction::FunctionPrototypeInvokeSelf);
bool callNative = true;
size_t nativeBindingsize = 15;
Local<FunctionRef> res =
FunctionRef::NewClassFunction(vm_, FunctionCallback, deleter, cb, callNative, nativeBindingsize);
ASSERT_TRUE(res->IsFunction(vm_));
Local<JSValueRef> res1 = res->GetFunctionPrototype(vm_);
ASSERT_TRUE(res->IsFunction(vm_));
ASSERT_TRUE(!res1->IsArray(vm_));
Local<StringRef> origin = StringRef::NewFromUtf8(vm_, "1");
res->SetName(vm_, origin);
Local<StringRef> 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<void *>(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<StringRef> toString = StringRef::NewFromUtf8(vm_, "-123.3");
Local<JSValueRef> toValue(toString);
ASSERT_EQ(toString->ToNumber(vm_)->Value(), -123.3);
ASSERT_EQ(toString->ToBoolean(vm_)->Value(), true);
ASSERT_EQ(toValue->ToString(vm_)->ToString(vm_), "-123.3");
ASSERT_TRUE(toValue->ToObject(vm_)->IsObject(vm_));
Local<NativePointerRef> res = toValue->ToNativePointer(vm_);
ASSERT_TRUE(res->IsString(vm_));
}
HWTEST_F_L0(JSNApiTests, GeneratorObjectRef_IsGenerator)
{
ObjectFactory *factory = vm_->GetFactory();
auto env = vm_->GetGlobalEnv();
JSHandle<JSTaggedValue> genFunc = env->GetGeneratorFunctionFunction();
JSHandle<JSGeneratorObject> genObjHandleVal = factory->NewJSGeneratorObject(genFunc);
JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetGeneratorFunctionClass());
JSHandle<JSFunction> generatorFunc = JSHandle<JSFunction>::Cast(factory->NewJSObject(hclass));
JSFunction::InitializeJSFunction(thread_, generatorFunc, FunctionKind::GENERATOR_FUNCTION);
JSHandle<GeneratorContext> generatorContext = factory->NewGeneratorContext();
generatorContext->SetMethod(thread_, generatorFunc.GetTaggedValue());
JSHandle<JSTaggedValue> generatorContextVal = JSHandle<JSTaggedValue>::Cast(generatorContext);
genObjHandleVal->SetGeneratorContext(thread_, generatorContextVal.GetTaggedValue());
JSHandle<JSTaggedValue> genObjTagHandleVal = JSHandle<JSTaggedValue>::Cast(genObjHandleVal);
Local<GeneratorObjectRef> genObjectRef = JSNApiHelper::ToLocal<GeneratorObjectRef>(genObjTagHandleVal);
Local<JSValueRef> 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<uint64_t>::max();
Local<BigIntRef> 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<uint64_t>::max();
Local<BigIntRef> 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<BooleanRef> 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<IntegerRef> 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<MapRef> map = MapRef::New(vm_);
Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, "TestKey");
Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, "TestValue");
map->Set(vm_, key, value);
Local<JSValueRef> 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<JSValueRef> res1 = map->GetKey(vm_, 0);
ASSERT_EQ(res1->ToString(vm_)->ToString(vm_), key->ToString(vm_)->ToString(vm_));
Local<JSValueRef> 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<FunctionRef> 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<ObjectRef> object = ObjectRef::New(vm_);
Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, "TestKey");
Local<JSValueRef> 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<ObjectRef> object = ObjectRef::New(vm_);
Local<StringRef> toString = StringRef::NewFromUtf8(vm_, "-123.3");
Local<JSValueRef> toValue(toString);
bool res = object->Set(vm_, 12, toValue);
ASSERT_TRUE(res);
Local<JSValueRef> 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<void *>(new std::string("test"));
void *vp2 = static_cast<void *>(new std::string("test"));
Local<NativePointerRef> 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<ObjectRef> object = ObjectRef::New(vm_);
uint32_t num = 10;
Local<StringRef> toString = StringRef::NewFromUtf8(vm_, "-123.3");
Local<JSValueRef> 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<StringRef> toString = StringRef::NewFromUtf8(vm_, "-123.3");
Local<JSValueRef> promise(toString);
Local<StringRef> toString1 = StringRef::NewFromUtf8(vm_, "123.3");
Local<JSValueRef> reason(toString1);
void *data = static_cast<void *>(new std::string("test"));
PromiseRejectInfo promisereject(promise, reason, PromiseRejectInfo::PROMISE_REJECTION_EVENT::REJECT, data);
Local<JSValueRef> promise_res = promisereject.GetPromise();
Local<JSValueRef> 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)
{
TestNumberRef(0., JSTaggedValue::DOUBLE_ENCODE_OFFSET);
TestNumberRef(NAN, base::bit_cast<TaggedType>(ecmascript::base::NAN_VALUE) + JSTaggedValue::DOUBLE_ENCODE_OFFSET);
TestNumberRef(static_cast<int32_t>(0), JSTaggedValue::TAG_INT);
TestNumberRef(INT32_MIN, static_cast<JSTaggedType>(INT32_MIN) | JSTaggedValue::TAG_INT);
TestNumberRef(INT32_MAX, static_cast<JSTaggedType>(INT32_MAX) | JSTaggedValue::TAG_INT);
TestNumberRef(static_cast<uint32_t>(0), JSTaggedValue::TAG_INT);
TestNumberRef(static_cast<uint32_t>(INT32_MAX), static_cast<uint32_t>(INT32_MAX) | JSTaggedValue::TAG_INT);
auto val = static_cast<uint32_t>(INT32_MAX + 1UL);
TestNumberRef(val, ConvertDouble(static_cast<double>(val)));
TestNumberRef(UINT32_MAX, ConvertDouble(static_cast<double>(UINT32_MAX)));
TestNumberRef(static_cast<int64_t>(INT32_MIN), static_cast<JSTaggedType>(INT32_MIN) | JSTaggedValue::TAG_INT);
TestNumberRef(static_cast<int64_t>(INT32_MAX), static_cast<JSTaggedType>(INT32_MAX) | JSTaggedValue::TAG_INT);
TestNumberRef(INT64_MIN, ConvertDouble(static_cast<double>(INT64_MIN)));
TestNumberRef(INT64_MAX, ConvertDouble(static_cast<double>(INT64_MAX)));
}
HWTEST_F_L0(JSNApiTests, JSNApiInternalsTestBooleanRef)
{
LocalScope scope(vm_);
bool input = true;
Local<BooleanRef> 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<JSValueRef> null = JSValueRef::Null(vm_);
ASSERT_TRUE(null->IsNull());
ASSERT_EQ(JSNApiHelper::ToJSTaggedValue(*null).GetRawData(), JSTaggedValue::VALUE_NULL);
Local<JSValueRef> 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<GlobalEnv> env = vm_->GetGlobalEnv();
JSHandle<JSTaggedValue> set = env->GetBuiltinsSetFunction();
Local<FunctionRef> setLocal = JSNApiHelper::ToLocal<FunctionRef>(set);
JSHandle<JSTaggedValue> map = env->GetBuiltinsMapFunction();
Local<FunctionRef> mapLocal = JSNApiHelper::ToLocal<FunctionRef>(map);
JSHandle<JSTaggedValue> setPrototype(thread_, JSHandle<JSFunction>::Cast(set)->GetFunctionPrototype(thread_));
JSHandle<JSTaggedValue> mapPrototype(thread_, JSHandle<JSFunction>::Cast(map)->GetFunctionPrototype(thread_));
JSHandle<JSTaggedValue> mapPrototypeProto(thread_, JSTaggedValue::GetPrototype(thread_, mapPrototype));
bool same = JSTaggedValue::SameValue(thread_, setPrototype, mapPrototypeProto);
ASSERT_FALSE(same);
mapLocal->Inherit(vm_, setLocal);
JSHandle<JSTaggedValue> sonHandle = JSNApiHelper::ToJSHandle(mapLocal);
JSHandle<JSTaggedValue> sonPrototype(thread_, JSHandle<JSFunction>::Cast(sonHandle)->GetFunctionPrototype(thread_));
JSHandle<JSTaggedValue> sonPrototypeProto(thread_, JSTaggedValue::GetPrototype(thread_, sonPrototype));
bool same2 = JSTaggedValue::SameValue(thread_, setPrototype, sonPrototypeProto);
ASSERT_TRUE(same2);
Local<FunctionRef> son1 = FunctionRef::New(vm_, FunctionCallback, nullptr);
son1->Inherit(vm_, mapLocal);
JSHandle<JSFunction> son1Handle = JSHandle<JSFunction>::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<JSValueRef> 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<void *>(new std::string("test"));
void *vp2 = static_cast<void *>(new std::string("test"));
Local<NativePointerRef> 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<StringRef> toString = StringRef::NewFromUtf8(vm_, "-1.3");
Local<JSValueRef> 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<StringRef> testString = StringRef::NewFromUtf8(vm_, test.c_str());
EXPECT_EQ(testString->WriteUtf8(vm_, buffer, 4), 4);
ASSERT_FALSE(testString->IsTypedArray(vm_));
const int32_t length = 30;
Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<Uint32ArrayRef> 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<JSTaggedValue> regExpFunc = globalEnv->GetRegExpFunction();
JSHandle<JSRegExp> jSRegExp =
JSHandle<JSRegExp>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(regExpFunc), regExpFunc));
jSRegExp->SetOriginalSource(thread, JSTaggedValue::Undefined());
Local<RegExpRef> object = JSNApiHelper::ToLocal<RegExpRef>(JSHandle<JSTaggedValue>::Cast(jSRegExp));
ASSERT_EQ(object->GetOriginalSource(vm_)->ToString(vm_), "");
}
HWTEST_F_L0(JSNApiTests, GetOriginalSource_2)
{
LocalScope scope(vm_);
JSThread *thread = vm_->GetJSThread();
ObjectFactory *factory = vm_->GetFactory();
auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> regExpFunc = globalEnv->GetRegExpFunction();
JSHandle<JSRegExp> jSRegExp =
JSHandle<JSRegExp>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(regExpFunc), regExpFunc));
const char *utf8 = TEST_ORIGINAL_SOURCE;
JSHandle<JSTaggedValue> sourceString(factory->NewFromUtf8(utf8));
jSRegExp->SetOriginalSource(thread, sourceString);
Local<RegExpRef> object = JSNApiHelper::ToLocal<RegExpRef>(JSHandle<JSTaggedValue>::Cast(jSRegExp));
ASSERT_EQ(object->GetOriginalSource(vm_)->ToString(vm_), TEST_ORIGINAL_SOURCE);
}
HWTEST_F_L0(JSNApiTests, GetOriginalFlags)
{
LocalScope scope(vm_);
JSThread *thread = vm_->GetJSThread();
ObjectFactory *factory = vm_->GetFactory();
auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> regExpFunc = globalEnv->GetRegExpFunction();
JSHandle<JSRegExp> jSRegExp =
JSHandle<JSRegExp>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(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<RegExpRef> object = JSNApiHelper::ToLocal<RegExpRef>(JSHandle<JSTaggedValue>::Cast(jSRegExp));
ASSERT_EQ(object->GetOriginalFlags(vm_), TEST_CHAR_STRING_FLAGS);
}
HWTEST_F_L0(JSNApiTests, GetOriginalFlags_2)
{
LocalScope scope(vm_);
JSThread *thread = vm_->GetJSThread();
ObjectFactory *factory = vm_->GetFactory();
auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> regExpFunc = globalEnv->GetRegExpFunction();
JSHandle<JSRegExp> jSRegExp =
JSHandle<JSRegExp>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(regExpFunc), regExpFunc));
jSRegExp->SetOriginalFlags(thread, JSTaggedValue(RegExpParser::FLAG_HASINDICES));
Local<RegExpRef> object = JSNApiHelper::ToLocal<RegExpRef>(JSHandle<JSTaggedValue>::Cast(jSRegExp));
ASSERT_EQ(object->GetOriginalFlags(vm_), "");
}
HWTEST_F_L0(JSNApiTests, GetGeneratorState)
{
LocalScope scope(vm_);
JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
JSHandle<JSTaggedValue> genFunc = env->GetGeneratorFunctionFunction();
JSHandle<JSGeneratorObject> genObjHandleVal = factory->NewJSGeneratorObject(genFunc);
genObjHandleVal->SetGeneratorState(JSGeneratorState::COMPLETED);
JSHandle<JSTaggedValue> genObjTagHandleVal = JSHandle<JSTaggedValue>::Cast(genObjHandleVal);
Local<GeneratorObjectRef> object = JSNApiHelper::ToLocal<GeneratorObjectRef>(genObjTagHandleVal);
ASSERT_EQ(object->GetGeneratorState(vm_)->ToString(vm_)->ToString(vm_), TEST_CHAR_STRING_STATE);
}
HWTEST_F_L0(JSNApiTests, GetGeneratorState_2)
{
LocalScope scope(vm_);
JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
JSHandle<JSTaggedValue> genFunc = env->GetGeneratorFunctionFunction();
JSHandle<JSGeneratorObject> genObjHandleVal = factory->NewJSGeneratorObject(genFunc);
genObjHandleVal->SetGeneratorState(JSGeneratorState::EXECUTING);
JSHandle<JSTaggedValue> genObjTagHandleVal = JSHandle<JSTaggedValue>::Cast(genObjHandleVal);
Local<GeneratorObjectRef> object = JSNApiHelper::ToLocal<GeneratorObjectRef>(genObjTagHandleVal);
ASSERT_EQ(object->GetGeneratorState(vm_)->ToString(vm_)->ToString(vm_), TEST_CHAR_STRING_STATE_SUSPEND);
}
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<ObjectRef> object = ObjectRef::New(vm_);
Global<ObjectRef> 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;
}
HWTEST_F_L0(JSNApiTests, RegisterCallback_1)
{
LocalScope scope(vm_);
JSHandle<JSTaggedValue> undefined = thread_->GlobalConstants()->GetHandledUndefined();
EcmaRuntimeCallInfo *objCallInfo =
EcmaInterpreter::NewRuntimeCallInfo(thread_, undefined, undefined, undefined, 1);
ASSERT_TRUE(Callback::RegisterCallback(objCallInfo).IsFalse());
}
HWTEST_F_L0(JSNApiTests, RegisterCallback_2)
{
LocalScope scope(vm_);
JSHandle<GlobalEnv> globalEnv = vm_->GetGlobalEnv();
ObjectFactory *objectFactory = vm_->GetFactory();
JSHandle<JSFunction> current(objectFactory->NewJSFunction(globalEnv,
reinterpret_cast<void *>(Callback::RegisterCallback)));
JSHandle<JSTaggedValue> undefined = thread_->GlobalConstants()->GetHandledUndefined();
EcmaRuntimeCallInfo *objCallInfo =
EcmaInterpreter::NewRuntimeCallInfo(thread_, JSHandle<JSTaggedValue>::Cast(current), undefined, undefined, 1);
ASSERT_TRUE(Callback::RegisterCallback(objCallInfo).IsFalse());
}
* @tc.number: ffi_interface_api_054
* @tc.name: ToObject_Undefined_Null
* @tc.desc: Verify the behavior of ToObject when the value is undefined or null.
* When JSValueRef is undefined or null, ToObject should return Undefined.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ToObject_Undefined_Null)
{
LocalScope scope(vm_);
Local<JSValueRef> undefinedValue = JSValueRef::Undefined(vm_);
Local<ObjectRef> undefinedObj = undefinedValue->ToObject(vm_);
ASSERT_TRUE(undefinedObj->IsUndefined());
Local<JSValueRef> nullValue = JSValueRef::Null(vm_);
Local<ObjectRef> nullObj = nullValue->ToObject(vm_);
ASSERT_TRUE(nullObj->IsUndefined());
}
* @tc.number: ffi_interface_api_055
* @tc.name: ToEcmaObject_NonECMAObject
* @tc.desc: Verify the behavior of ToEcmaObject when the value is not an ECMAObject.
* When JSValueRef is undefined, null, or primitive types, ToEcmaObject should return Undefined.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ToEcmaObject_NonECMAObject)
{
LocalScope scope(vm_);
Local<JSValueRef> undefinedValue = JSValueRef::Undefined(vm_);
Local<ObjectRef> undefinedObj = undefinedValue->ToEcmaObject(vm_);
ASSERT_TRUE(undefinedObj->IsUndefined());
Local<JSValueRef> nullValue = JSValueRef::Null(vm_);
Local<ObjectRef> nullObj = nullValue->ToEcmaObject(vm_);
ASSERT_TRUE(nullObj->IsUndefined());
Local<NumberRef> numberValue = NumberRef::New(vm_, TEST_INT_VALUE);
Local<ObjectRef> numberObj = numberValue->ToEcmaObject(vm_);
ASSERT_TRUE(numberObj->IsUndefined());
Local<StringRef> stringValue = StringRef::NewFromUtf8(vm_, TEST_STRING);
Local<ObjectRef> stringObj = stringValue->ToEcmaObject(vm_);
ASSERT_TRUE(stringObj->IsUndefined());
Local<BooleanRef> boolValue = BooleanRef::New(vm_, true);
Local<ObjectRef> boolObj = boolValue->ToEcmaObject(vm_);
ASSERT_TRUE(boolObj->IsUndefined());
}
* @tc.number: ffi_interface_api_056
* @tc.name: IntegerValue_Infinite_NaN
* @tc.desc: Verify the behavior of IntegerValue when the value is Infinity or NaN.
* When the number is not finite or is NaN, IntegerValue should return 0.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, IntegerValue_Infinite_NaN)
{
LocalScope scope(vm_);
Local<NumberRef> posInf = NumberRef::New(vm_, std::numeric_limits<double>::infinity());
ASSERT_EQ(posInf->IntegerValue(vm_), 0);
Local<NumberRef> negInf = NumberRef::New(vm_, -std::numeric_limits<double>::infinity());
ASSERT_EQ(negInf->IntegerValue(vm_), 0);
Local<NumberRef> nanValue = NumberRef::New(vm_, std::numeric_limits<double>::quiet_NaN());
ASSERT_EQ(nanValue->IntegerValue(vm_), 0);
}
* @tc.number: ffi_interface_api_057
* @tc.name: GetValueDouble_Int_Double
* @tc.desc: Verify the behavior of GetValueDouble when the value is Int or Double type.
* When the value is Int type, isNumber should be true and return the value as double.
* When the value is Double type, isNumber should be true and return the double value.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, GetValueDouble_Int_Double)
{
LocalScope scope(vm_);
Local<NumberRef> intValue = NumberRef::New(vm_, TEST_INT_VALUE);
bool isIntNumber = false;
double intResult = intValue->GetValueDouble(isIntNumber);
ASSERT_TRUE(isIntNumber);
ASSERT_EQ(intResult, static_cast<double>(TEST_INT_VALUE));
Local<NumberRef> doubleValue = NumberRef::New(vm_, TEST_DOUBLE_VALUE);
bool isDoubleNumber = false;
double doubleResult = doubleValue->GetValueDouble(isDoubleNumber);
ASSERT_TRUE(isDoubleNumber);
ASSERT_DOUBLE_EQ(doubleResult, TEST_DOUBLE_VALUE);
Local<NumberRef> negIntValue = NumberRef::New(vm_, TEST_NEG_INT_VALUE);
bool isNegIntNumber = false;
double negIntResult = negIntValue->GetValueDouble(isNegIntNumber);
ASSERT_TRUE(isNegIntNumber);
ASSERT_EQ(negIntResult, static_cast<double>(TEST_NEG_INT_VALUE));
Local<NumberRef> negDoubleValue = NumberRef::New(vm_, TEST_NEG_DOUBLE_VALUE);
bool isNegDoubleNumber = false;
double negDoubleResult = negDoubleValue->GetValueDouble(isNegDoubleNumber);
ASSERT_TRUE(isNegDoubleNumber);
ASSERT_DOUBLE_EQ(negDoubleResult, TEST_NEG_DOUBLE_VALUE);
}
* @tc.number: ffi_interface_api_058
* @tc.name: GetValueInt32_Int_Double
* @tc.desc: Verify the behavior of GetValueInt32 when the value is Int or Double type.
* When the value is Int type, isNumber should be true and return the int32 value.
* When the value is Double type, isNumber should be true and return the converted int32 value.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, GetValueInt32_Int_Double)
{
LocalScope scope(vm_);
Local<NumberRef> intValue = NumberRef::New(vm_, TEST_INT_VALUE);
bool isIntNumber = false;
int32_t intResult = intValue->GetValueInt32(isIntNumber);
ASSERT_TRUE(isIntNumber);
ASSERT_EQ(intResult, TEST_INT_VALUE);
Local<NumberRef> negIntValue = NumberRef::New(vm_, TEST_NEG_INT_VALUE);
bool isNegIntNumber = false;
int32_t negIntResult = negIntValue->GetValueInt32(isNegIntNumber);
ASSERT_TRUE(isNegIntNumber);
ASSERT_EQ(negIntResult, TEST_NEG_INT_VALUE);
Local<NumberRef> doubleValue = NumberRef::New(vm_, TEST_DOUBLE_VALUE);
bool isDoubleNumber = false;
int32_t doubleResult = doubleValue->GetValueInt32(isDoubleNumber);
ASSERT_TRUE(isDoubleNumber);
ASSERT_EQ(doubleResult, static_cast<int32_t>(TEST_DOUBLE_VALUE));
Local<NumberRef> negDoubleValue = NumberRef::New(vm_, TEST_NEG_DOUBLE_VALUE);
bool isNegDoubleNumber = false;
int32_t negDoubleResult = negDoubleValue->GetValueInt32(isNegDoubleNumber);
ASSERT_TRUE(isNegDoubleNumber);
ASSERT_EQ(negDoubleResult, static_cast<int32_t>(TEST_NEG_DOUBLE_VALUE));
}
* @tc.number: ffi_interface_api_059
* @tc.name: GetValueInt64_Infinite_NaN_Double
* @tc.desc: Verify the behavior of GetValueInt64 when the value is Infinite, NaN, or normal Double.
* When the value is Infinite or NaN, should return 0.
* When the value is normal Double, should return the converted int64 value.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, GetValueInt64_Infinite_NaN_Double)
{
LocalScope scope(vm_);
Local<NumberRef> posInf = NumberRef::New(vm_, std::numeric_limits<double>::infinity());
bool isPosInfNumber = false;
int64_t posInfResult = posInf->GetValueInt64(isPosInfNumber);
ASSERT_TRUE(isPosInfNumber);
ASSERT_EQ(posInfResult, 0);
Local<NumberRef> negInf = NumberRef::New(vm_, -std::numeric_limits<double>::infinity());
bool isNegInfNumber = false;
int64_t negInfResult = negInf->GetValueInt64(isNegInfNumber);
ASSERT_TRUE(isNegInfNumber);
ASSERT_EQ(negInfResult, 0);
Local<NumberRef> nanValue = NumberRef::New(vm_, std::numeric_limits<double>::quiet_NaN());
bool isNanNumber = false;
int64_t nanResult = nanValue->GetValueInt64(isNanNumber);
ASSERT_TRUE(isNanNumber);
ASSERT_EQ(nanResult, 0);
Local<NumberRef> normalDouble = NumberRef::New(vm_, TEST_DOUBLE_VALUE);
bool isNormalDoubleNumber = false;
int64_t normalDoubleResult = normalDouble->GetValueInt64(isNormalDoubleNumber);
ASSERT_TRUE(isNormalDoubleNumber);
ASSERT_EQ(normalDoubleResult, static_cast<int64_t>(TEST_DOUBLE_VALUE));
Local<NumberRef> largeDouble = NumberRef::New(vm_, TEST_LARGE_DOUBLE);
bool isLargeDoubleNumber = false;
int64_t largeDoubleResult = largeDouble->GetValueInt64(isLargeDoubleNumber);
ASSERT_TRUE(isLargeDoubleNumber);
ASSERT_EQ(largeDoubleResult, static_cast<int64_t>(TEST_LARGE_DOUBLE));
Local<NumberRef> negDouble = NumberRef::New(vm_, TEST_NEG_DOUBLE_VALUE);
bool isNegDoubleNumber = false;
int64_t negDoubleResult = negDouble->GetValueInt64(isNegDoubleNumber);
ASSERT_TRUE(isNegDoubleNumber);
ASSERT_EQ(negDoubleResult, static_cast<int64_t>(TEST_NEG_DOUBLE_VALUE));
}
* @tc.number: ffi_interface_api_060
* @tc.name: ToEcmaObjectWithoutSwitchState_NormalObject
* @tc.desc: Verify the behavior of ToEcmaObjectWithoutSwitchState when the value is a normal object.
* When JSValueRef is a normal object, ToEcmaObjectWithoutSwitchState should return the object itself.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ToEcmaObjectWithoutSwitchState_NormalObject)
{
LocalScope scope(vm_);
Local<ObjectRef> obj = ObjectRef::New(vm_);
Local<ObjectRef> result = obj->ToEcmaObjectWithoutSwitchState(vm_);
ASSERT_TRUE(result->IsObject(vm_));
}
* @tc.number: ffi_interface_api_061
* @tc.name: ToEcmaObjectWithoutSwitchState_PrimitiveTypes
* @tc.desc: Verify the behavior of ToEcmaObjectWithoutSwitchState when the value is a primitive type.
* ToEcmaObjectWithoutSwitchState directly converts the value to ObjectRef without type checking.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ToEcmaObjectWithoutSwitchState_PrimitiveTypes)
{
LocalScope scope(vm_);
Local<NumberRef> numberValue = NumberRef::New(vm_, TEST_INT_VALUE);
Local<ObjectRef> numberObj = numberValue->ToEcmaObjectWithoutSwitchState(vm_);
ASSERT_TRUE(numberObj->IsNumber());
Local<StringRef> stringValue = StringRef::NewFromUtf8(vm_, TEST_STRING);
Local<ObjectRef> stringObj = stringValue->ToEcmaObjectWithoutSwitchState(vm_);
ASSERT_TRUE(stringObj->IsString(vm_));
Local<BooleanRef> boolValue = BooleanRef::New(vm_, true);
Local<ObjectRef> boolObj = boolValue->ToEcmaObjectWithoutSwitchState(vm_);
ASSERT_TRUE(boolObj->IsBoolean());
}
* @tc.number: ffi_interface_api_062
* @tc.name: ToEcmaObjectWithoutSwitchState_WithException
* @tc.desc: Verify the behavior of ToEcmaObjectWithoutSwitchState when there is a pending exception.
* When there is a pending exception, ToEcmaObjectWithoutSwitchState should return Undefined.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ToEcmaObjectWithoutSwitchState_WithException)
{
LocalScope scope(vm_);
Local<ObjectRef> obj = ObjectRef::New(vm_);
Local<StringRef> frozenKey = StringRef::NewFromUtf8(vm_, TEST_FROZEN_KEY);
obj->Freeze(vm_);
ASSERT_FALSE(vm_->GetJSThread()->HasPendingException());
obj->Set(vm_, frozenKey, StringRef::NewFromUtf8(vm_, TEST_SHOULD_FAIL));
ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
Local<ObjectRef> result = obj->ToEcmaObjectWithoutSwitchState(vm_);
ASSERT_TRUE(result->IsUndefined());
JSNApi::GetAndClearUncaughtException(vm_);
}
* @tc.number: ffi_interface_api_063
* @tc.name: ToEcmaObjectWithoutSwitchState_Array
* @tc.desc: Verify the behavior of ToEcmaObjectWithoutSwitchState when the value is an array.
* When JSValueRef is an array, ToEcmaObjectWithoutSwitchState should return the array itself.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ToEcmaObjectWithoutSwitchState_Array)
{
LocalScope scope(vm_);
Local<ArrayRef> array = ArrayRef::New(vm_, TEST_INT_VALUE);
Local<ObjectRef> arrayObj = array->ToEcmaObjectWithoutSwitchState(vm_);
ASSERT_TRUE(arrayObj->IsArray(vm_));
}
* @tc.number: ffi_interface_api_064
* @tc.name: ToEcmaObjectWithoutSwitchState_Function
* @tc.desc: Verify the behavior of ToEcmaObjectWithoutSwitchState when the value is a function.
* When JSValueRef is a function, ToEcmaObjectWithoutSwitchState should return the function itself.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ToEcmaObjectWithoutSwitchState_Function)
{
LocalScope scope(vm_);
Local<FunctionRef> func = FunctionRef::New(vm_, FunctionCallback);
Local<ObjectRef> funcObj = func->ToEcmaObjectWithoutSwitchState(vm_);
ASSERT_TRUE(funcObj->IsFunction(vm_));
}
* @tc.number: ffi_interface_api_065
* @tc.name: GetValueBool_True_False
* @tc.desc: Verify the behavior of GetValueBool when the value is true or false.
* When the value is true, GetValueBool should return true.
* When the value is false, GetValueBool should return false.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, GetValueBool_True_False)
{
LocalScope scope(vm_);
Local<BooleanRef> trueValue = BooleanRef::New(vm_, true);
bool isTrueBool = false;
bool trueResult = trueValue->GetValueBool(isTrueBool);
ASSERT_TRUE(isTrueBool);
ASSERT_TRUE(trueResult);
Local<BooleanRef> falseValue = BooleanRef::New(vm_, false);
bool isFalseBool = false;
bool falseResult = falseValue->GetValueBool(isFalseBool);
ASSERT_TRUE(isFalseBool);
ASSERT_FALSE(falseResult);
Local<NumberRef> numberValue = NumberRef::New(vm_, TEST_INT_VALUE);
bool isNumberBool = false;
bool numberResult = numberValue->GetValueBool(isNumberBool);
ASSERT_FALSE(isNumberBool);
ASSERT_FALSE(numberResult);
}
* @tc.number: ffi_interface_api_066
* @tc.name: ToBigInt_Boolean
* @tc.desc: Verify the behavior of ToBigInt when converting values.
* ToBigInt should succeed for Boolean values.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ToBigInt_Boolean)
{
LocalScope scope(vm_);
Local<BooleanRef> trueValue = BooleanRef::New(vm_, true);
Local<BigIntRef> bigIntFromTrue = trueValue->ToBigInt(vm_);
ASSERT_TRUE(bigIntFromTrue->IsBigInt(vm_));
Local<BooleanRef> falseValue = BooleanRef::New(vm_, false);
Local<BigIntRef> bigIntFromFalse = falseValue->ToBigInt(vm_);
ASSERT_TRUE(bigIntFromFalse->IsBigInt(vm_));
}
* @tc.number: ffi_interface_api_067
* @tc.name: IsNativeBindingObject_NonObject
* @tc.desc: Verify the behavior of IsNativeBindingObject when the value is not an ECMAObject.
* When the value is not an ECMAObject, IsNativeBindingObject should return false.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, IsNativeBindingObject_NonObject)
{
LocalScope scope(vm_);
Local<NumberRef> numberValue = NumberRef::New(vm_, TEST_INT_VALUE);
bool isNativeBinding = numberValue->IsNativeBindingObject(vm_);
ASSERT_FALSE(isNativeBinding);
Local<StringRef> stringValue = StringRef::NewFromUtf8(vm_, TEST_STRING);
isNativeBinding = stringValue->IsNativeBindingObject(vm_);
ASSERT_FALSE(isNativeBinding);
Local<BooleanRef> boolValue = BooleanRef::New(vm_, true);
isNativeBinding = boolValue->IsNativeBindingObject(vm_);
ASSERT_FALSE(isNativeBinding);
Local<JSValueRef> undefinedValue = JSValueRef::Undefined(vm_);
isNativeBinding = undefinedValue->IsNativeBindingObject(vm_);
ASSERT_FALSE(isNativeBinding);
}
* @tc.number: ffi_interface_api_068
* @tc.name: GetNativePointer_ValidPointer
* @tc.desc: Verify the behavior of GetNativePointer when the value has a valid native pointer.
* When the value has a valid native pointer, GetNativePointer should return the external pointer.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, GetNativePointer_ValidPointer)
{
LocalScope scope(vm_);
int* testData = new int(TEST_INT_VALUE);
Local<NativePointerRef> nativePtr = NativePointerRef::New(vm_, testData, nullptr, nullptr, 0);
bool isNativePointer = false;
void* externalPtr = nativePtr->GetNativePointerValue(vm_, isNativePointer);
ASSERT_TRUE(isNativePointer);
ASSERT_EQ(externalPtr, testData);
delete testData;
}
* @tc.number: ffi_interface_api_069
* @tc.name: GetNativePointerValue_InvalidPointer
* @tc.desc: Verify the behavior of GetNativePointerValue when the value is not a native pointer.
* When the value is not a native pointer, GetNativePointerValue should return nullptr and set isNativePointer to false.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, GetNativePointerValue_InvalidPointer)
{
LocalScope scope(vm_);
Local<NumberRef> numberValue = NumberRef::New(vm_, TEST_INT_VALUE);
bool isNativePointer = false;
void* externalPtr = numberValue->GetNativePointerValue(vm_, isNativePointer);
ASSERT_FALSE(isNativePointer);
ASSERT_EQ(externalPtr, nullptr);
Local<StringRef> stringValue = StringRef::NewFromUtf8(vm_, TEST_STRING);
isNativePointer = false;
externalPtr = stringValue->GetNativePointerValue(vm_, isNativePointer);
ASSERT_FALSE(isNativePointer);
ASSERT_EQ(externalPtr, nullptr);
Local<JSValueRef> undefinedValue = JSValueRef::Undefined(vm_);
isNativePointer = false;
externalPtr = undefinedValue->GetNativePointerValue(vm_, isNativePointer);
ASSERT_FALSE(isNativePointer);
ASSERT_EQ(externalPtr, nullptr);
}
* @tc.number: ffi_interface_api_070
* @tc.name: IsDetachedArraybuffer_NonArrayBuffer
* @tc.desc: Verify the behavior of IsDetachedArraybuffer when the value is not an ArrayBuffer.
* When the value is not an ArrayBuffer, isArrayBuffer should be set to false.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, IsDetachedArraybuffer_NonArrayBuffer)
{
LocalScope scope(vm_);
Local<NumberRef> numberValue = NumberRef::New(vm_, TEST_INT_VALUE);
bool isArrayBuffer = true;
bool isDetached = numberValue->IsDetachedArraybuffer(vm_, isArrayBuffer);
ASSERT_FALSE(isArrayBuffer);
ASSERT_FALSE(isDetached);
Local<StringRef> stringValue = StringRef::NewFromUtf8(vm_, TEST_STRING);
isArrayBuffer = true;
isDetached = stringValue->IsDetachedArraybuffer(vm_, isArrayBuffer);
ASSERT_FALSE(isArrayBuffer);
ASSERT_FALSE(isDetached);
}
* @tc.number: ffi_interface_api_071
* @tc.name: DetachedArraybuffer_AlreadyDetached
* @tc.desc: Verify the behavior of DetachedArraybuffer when ArrayBuffer is already detached.
* When the ArrayBuffer is already detached, DetachedArraybuffer should return early.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, DetachedArraybuffer_AlreadyDetached)
{
LocalScope scope(vm_);
Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, TEST_ARRAYBUFFER_LENGTH);
bool isArrayBuffer = false;
arrayBuffer->DetachedArraybuffer(vm_, isArrayBuffer);
ASSERT_TRUE(isArrayBuffer);
isArrayBuffer = false;
arrayBuffer->DetachedArraybuffer(vm_, isArrayBuffer);
ASSERT_FALSE(isArrayBuffer);
}
* @tc.number: ffi_interface_api_072
* @tc.name: DetachedArraybuffer_SendableAlreadyDetached
* @tc.desc: Verify the behavior of DetachedArraybuffer when SendableArrayBuffer is already detached.
* When the SendableArrayBuffer is already detached, DetachedArraybuffer should return early.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, DetachedArraybuffer_SendableAlreadyDetached)
{
LocalScope scope(vm_);
Local<ArrayBufferRef> sendableArrayBuffer = ArrayBufferRef::New(vm_, TEST_ARRAYBUFFER_LENGTH);
bool isArrayBuffer = false;
sendableArrayBuffer->DetachedArraybuffer(vm_, isArrayBuffer);
ASSERT_TRUE(isArrayBuffer);
isArrayBuffer = false;
sendableArrayBuffer->DetachedArraybuffer(vm_, isArrayBuffer);
ASSERT_FALSE(isArrayBuffer);
}
* @tc.number: ffi_interface_api_073
* @tc.name: DetachedArraybuffer_NonArrayBuffer
* @tc.desc: Verify the behavior of DetachedArraybuffer when the value is not an ArrayBuffer or SendableArrayBuffer.
* When the value is not an ArrayBuffer or SendableArrayBuffer, isArrayBuffer should be set to false.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, DetachedArraybuffer_NonArrayBuffer)
{
LocalScope scope(vm_);
Local<NumberRef> numberValue = NumberRef::New(vm_, TEST_INT_VALUE);
bool isArrayBuffer = true;
numberValue->DetachedArraybuffer(vm_, isArrayBuffer);
ASSERT_FALSE(isArrayBuffer);
Local<StringRef> stringValue = StringRef::NewFromUtf8(vm_, TEST_STRING);
isArrayBuffer = true;
stringValue->DetachedArraybuffer(vm_, isArrayBuffer);
ASSERT_FALSE(isArrayBuffer);
}
* @tc.number: ffi_interface_api_074
* @tc.name: GetDataViewInfo_NonDataView
* @tc.desc: Verify the behavior of GetDataViewInfo when the value is not a DataView.
* When the value is not a DataView, isDataView should be set to false.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, GetDataViewInfo_NonDataView)
{
LocalScope scope(vm_);
Local<NumberRef> numberValue = NumberRef::New(vm_, TEST_INT_VALUE);
bool isDataView = true;
numberValue->GetDataViewInfo(vm_, isDataView, nullptr, nullptr, nullptr, nullptr);
ASSERT_FALSE(isDataView);
Local<StringRef> stringValue = StringRef::NewFromUtf8(vm_, TEST_STRING);
isDataView = true;
stringValue->GetDataViewInfo(vm_, isDataView, nullptr, nullptr, nullptr, nullptr);
ASSERT_FALSE(isDataView);
}
* @tc.number: ffi_interface_api_075
* @tc.name: GetDataViewInfo_AllParameters
* @tc.desc: Verify the behavior of GetDataViewInfo with all parameters provided.
* GetDataViewInfo should successfully retrieve all information from DataView.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, GetDataViewInfo_AllParameters)
{
LocalScope scope(vm_);
Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, TEST_ARRAYBUFFER_LENGTH);
Local<DataViewRef> dataView = DataViewRef::New(vm_, arrayBuffer, TEST_DATAVIEW_BYTEOFFSET,
TEST_DATAVIEW_BYTELENGTH);
bool isDataView = false;
size_t byteLength = 0;
void* data = nullptr;
JSValueRef* arrayBufferPtr = nullptr;
size_t byteOffset = 0;
dataView->GetDataViewInfo(vm_, isDataView, &byteLength, &data, &arrayBufferPtr, &byteOffset);
ASSERT_TRUE(isDataView);
ASSERT_EQ(byteLength, static_cast<size_t>(TEST_DATAVIEW_BYTELENGTH));
ASSERT_NE(data, nullptr);
ASSERT_NE(arrayBufferPtr, nullptr);
ASSERT_EQ(byteOffset, static_cast<size_t>(TEST_DATAVIEW_BYTEOFFSET));
}
* @tc.number: ffi_interface_api_076
* @tc.name: GetDataViewInfo_OnlyByteLength
* @tc.desc: Verify the behavior of GetDataViewInfo with only byteLength parameter.
* GetDataViewInfo should successfully retrieve byteLength from DataView.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, GetDataViewInfo_OnlyByteLength)
{
LocalScope scope(vm_);
Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, TEST_ARRAYBUFFER_LENGTH);
Local<DataViewRef> dataView = DataViewRef::New(vm_, arrayBuffer, TEST_DATAVIEW_BYTEOFFSET,
TEST_DATAVIEW_BYTELENGTH);
bool isDataView = false;
size_t byteLength = 0;
dataView->GetDataViewInfo(vm_, isDataView, &byteLength, nullptr, nullptr, nullptr);
ASSERT_TRUE(isDataView);
ASSERT_EQ(byteLength, static_cast<size_t>(TEST_DATAVIEW_BYTELENGTH));
}
* @tc.number: ffi_interface_api_077
* @tc.name: GetDataViewInfo_OnlyDataAndArrayBuffer
* @tc.desc: Verify the behavior of GetDataViewInfo with only data and arrayBuffer parameters.
* GetDataViewInfo should successfully retrieve data and arrayBuffer from DataView.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, GetDataViewInfo_OnlyDataAndArrayBuffer)
{
LocalScope scope(vm_);
Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, TEST_ARRAYBUFFER_LENGTH);
Local<DataViewRef> dataView = DataViewRef::New(vm_, arrayBuffer, TEST_DATAVIEW_BYTEOFFSET,
TEST_DATAVIEW_BYTELENGTH);
bool isDataView = false;
void* data = nullptr;
JSValueRef* arrayBufferPtr = nullptr;
dataView->GetDataViewInfo(vm_, isDataView, nullptr, &data, &arrayBufferPtr, nullptr);
ASSERT_TRUE(isDataView);
ASSERT_NE(data, nullptr);
ASSERT_NE(arrayBufferPtr, nullptr);
}
* @tc.number: ffi_interface_api_078
* @tc.name: GetDataViewInfo_OnlyByteOffset
* @tc.desc: Verify the behavior of GetDataViewInfo with only byteOffset parameter.
* GetDataViewInfo should successfully retrieve byteOffset from DataView.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, GetDataViewInfo_OnlyByteOffset)
{
LocalScope scope(vm_);
Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, TEST_ARRAYBUFFER_LENGTH);
Local<DataViewRef> dataView = DataViewRef::New(vm_, arrayBuffer, TEST_DATAVIEW_BYTEOFFSET,
TEST_DATAVIEW_BYTELENGTH);
bool isDataView = false;
size_t byteOffset = 0;
dataView->GetDataViewInfo(vm_, isDataView, nullptr, nullptr, nullptr, &byteOffset);
ASSERT_TRUE(isDataView);
ASSERT_EQ(byteOffset, static_cast<size_t>(TEST_DATAVIEW_BYTEOFFSET));
}
* @tc.number: ffi_interface_api_079
* @tc.name: GetDataViewInfo_NullParameters
* @tc.desc: Verify the behavior of GetDataViewInfo with all null parameters.
* GetDataViewInfo should only set isDataView to true when all other parameters are null.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, GetDataViewInfo_NullParameters)
{
LocalScope scope(vm_);
Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, TEST_ARRAYBUFFER_LENGTH);
Local<DataViewRef> dataView = DataViewRef::New(vm_, arrayBuffer, TEST_DATAVIEW_BYTEOFFSET,
TEST_DATAVIEW_BYTELENGTH);
bool isDataView = false;
dataView->GetDataViewInfo(vm_, isDataView, nullptr, nullptr, nullptr, nullptr);
ASSERT_TRUE(isDataView);
}
* @tc.number: ffi_interface_api_080
* @tc.name: DataViewRef_NewWithoutSwitchState
* @tc.desc: Create a DataView using NewWithoutSwitchState and verify its properties.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, DataViewRef_NewWithoutSwitchState)
{
LocalScope scope(vm_);
Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, TEST_DATAVIEW_LENGTH);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<DataViewRef> dataView = DataViewRef::NewWithoutSwitchState(vm_, arrayBuffer, TEST_DATAVIEW_BYTEOFFSET,
TEST_DATAVIEW_BYTELENGTH);
ASSERT_TRUE(dataView->IsDataView(vm_));
ASSERT_EQ(dataView->ByteLength(), static_cast<uint32_t>(TEST_DATAVIEW_BYTELENGTH));
ASSERT_EQ(dataView->ByteOffset(), static_cast<uint32_t>(TEST_DATAVIEW_BYTEOFFSET));
}
* @tc.number: ffi_interface_api_081
* @tc.name: DataViewRef_NewWithoutSwitchState_OutOfRange
* @tc.desc: Verify that NewWithoutSwitchState returns hole when byteOffset + byteLength exceeds buffer length.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, DataViewRef_NewWithoutSwitchState_OutOfRange)
{
LocalScope scope(vm_);
Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, TEST_DATAVIEW_LENGTH);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
Local<DataViewRef> dataView = DataViewRef::NewWithoutSwitchState(vm_, arrayBuffer, TEST_DATAVIEW_BYTEOFFSET,
TEST_DATAVIEW_LENGTH);
ASSERT_TRUE(dataView->IsHole());
}
* @tc.number: ffi_interface_api_082
* @tc.name: MapIteratorRef_GetKind_Default
* @tc.desc: Verify GetKind returns correct string for default MapIterator.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, MapIteratorRef_GetKind_Default)
{
LocalScope scope(vm_);
Local<MapRef> mapRef = MapRef::New(vm_);
Local<MapIteratorRef> mapIterator = MapIteratorRef::New(vm_, mapRef);
ASSERT_TRUE(mapIterator->IsHeapObject());
Local<JSValueRef> kind = mapIterator->GetKind(vm_);
ASSERT_TRUE(kind->IsString(vm_));
}
* @tc.number: ffi_interface_api_083
* @tc.name: SetIteratorRef_GetKind_Value
* @tc.desc: Verify GetKind returns correct string for SetIterator.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, SetIteratorRef_GetKind_Value)
{
LocalScope scope(vm_);
JSThread *thread = vm_->GetJSThread();
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> constructor = env->GetBuiltinsSetFunction();
JSHandle<JSSet> set =
JSHandle<JSSet>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
JSHandle<LinkedHashSet> hashSet = LinkedHashSet::Create(thread);
set->SetLinkedSet(thread, hashSet);
JSHandle<JSTaggedValue> setTag = JSHandle<JSTaggedValue>::Cast(set);
Local<SetRef> setRef = JSNApiHelper::ToLocal<SetRef>(setTag);
Local<SetIteratorRef> setIterator = SetIteratorRef::New(vm_, setRef);
ASSERT_TRUE(setIterator->IsHeapObject());
Local<JSValueRef> kind = setIterator->GetKind(vm_);
ASSERT_TRUE(kind->IsString(vm_));
}
* @tc.number: ffi_interface_api_084
* @tc.name: BufferRef_New_WithContext
* @tc.desc: Create a BufferRef with context parameter.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, BufferRef_New_WithContext)
{
LocalScope scope(vm_);
Local<ObjectRef> context = ObjectRef::New(vm_);
Local<BufferRef> buffer = BufferRef::New(vm_, context, TEST_BUFFER_LENGTH);
ASSERT_TRUE(buffer->IsBuffer(vm_));
}
* @tc.number: ffi_interface_api_085
* @tc.name: BufferRef_New_WithBuffer
* @tc.desc: Create a BufferRef with external buffer and deleter callback.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, BufferRef_New_WithBuffer)
{
LocalScope scope(vm_);
static bool isFree = false;
struct Data {
int32_t length;
};
NativePointerCallback deleter = []([[maybe_unused]] void *env, void *buffer, void *data) -> void {
delete[] reinterpret_cast<uint8_t *>(buffer);
Data *currentData = reinterpret_cast<Data *>(data);
delete currentData;
isFree = true;
};
isFree = false;
uint8_t *buffer = new uint8_t[TEST_BUFFER_LENGTH]();
Data *data = new Data();
data->length = TEST_BUFFER_LENGTH;
Local<BufferRef> bufferRef = BufferRef::New(vm_, buffer, TEST_BUFFER_LENGTH, deleter, data);
ASSERT_TRUE(bufferRef->IsBuffer(vm_));
}
* @tc.number: ffi_interface_api_086
* @tc.name: BufferRef_GetBuffer
* @tc.desc: Verify GetBuffer returns valid pointer for BufferRef.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, BufferRef_GetBuffer)
{
LocalScope scope(vm_);
Local<BufferRef> buffer = BufferRef::New(vm_, TEST_BUFFER_LENGTH);
ASSERT_TRUE(buffer->IsBuffer(vm_));
void *ptr = buffer->GetBuffer(vm_);
EXPECT_NE(ptr, nullptr);
}
* @tc.number: ffi_interface_api_087
* @tc.name: SymbolRef_GetDescription_Empty
* @tc.desc: Verify GetDescription returns empty string for Symbol without description.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, SymbolRef_GetDescription_Empty)
{
LocalScope scope(vm_);
Local<SymbolRef> symbol = SymbolRef::New(vm_, Local<StringRef>());
ASSERT_TRUE(symbol->IsSymbol(vm_));
Local<StringRef> description = symbol->GetDescription(vm_);
ASSERT_TRUE(description->IsString(vm_));
}
* @tc.number: ffi_interface_api_088
* @tc.name: StringRef_GetBufferUtf16
* @tc.desc: Verify GetBufferUtf16 returns nullptr for non-utf16 string.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, StringRef_GetBufferUtf16)
{
LocalScope scope(vm_);
Local<StringRef> str = StringRef::NewFromUtf8(vm_, TEST_STRING);
ASSERT_TRUE(str->IsString(vm_));
uint32_t length = 0;
const uint16_t *buffer = str->GetBufferUtf16(vm_, length);
EXPECT_EQ(buffer, nullptr);
}
* @tc.number: ffi_interface_api_089
* @tc.name: StringRef_NewFromUtf8Replacement
* @tc.desc: Verify NewFromUtf8Replacement creates string correctly.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, StringRef_NewFromUtf8Replacement)
{
LocalScope scope(vm_);
Local<StringRef> str = StringRef::NewFromUtf8Replacement(vm_, TEST_STRING, TEST_STRING_LENGTH_MINUS_ONE);
ASSERT_TRUE(str->IsString(vm_));
Local<StringRef> strWithLength = StringRef::NewFromUtf8Replacement(vm_, TEST_STRING, TEST_STRING_LENGTH_FOUR);
ASSERT_TRUE(strWithLength->IsString(vm_));
}
* @tc.number: ffi_interface_api_090
* @tc.name: StringRef_NewFromUtf16WithoutStringTable
* @tc.desc: Verify NewFromUtf16WithoutStringTable creates string correctly.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, StringRef_NewFromUtf16WithoutStringTable)
{
LocalScope scope(vm_);
Local<StringRef> str = StringRef::NewFromUtf16WithoutStringTable(vm_, TEST_UTF16_STRING, -1);
ASSERT_TRUE(str->IsString(vm_));
}
* @tc.number: ffi_interface_api_091
* @tc.name: StringRef_EncodeIntoUint8Array_EmptyString
* @tc.desc: Verify EncodeIntoUint8Array returns undefined for empty string.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, StringRef_EncodeIntoUint8Array_EmptyString)
{
LocalScope scope(vm_);
Local<StringRef> emptyStr = StringRef::NewFromUtf8(vm_, TEST_EMPTY_STRING);
Local<TypedArrayRef> result = emptyStr->EncodeIntoUint8Array(vm_);
ASSERT_TRUE(result->IsUndefined());
}
* @tc.number: ffi_interface_api_092
* @tc.name: BigIntRef_GetWordsArray
* @tc.desc: Verify GetWordsArray returns correct words for BigInt.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, BigIntRef_GetWordsArray)
{
LocalScope scope(vm_);
Local<BigIntRef> bigint = BigIntRef::New(vm_, TEST_BIGINT_VALUE);
ASSERT_TRUE(bigint->IsBigInt(vm_));
uint32_t size = bigint->GetWordsArraySize(vm_);
ASSERT_EQ(size, TEST_BIGINT_WORDS_SIZE);
uint64_t words = 0;
bool signBit = false;
bigint->GetWordsArray(vm_, &signBit, size, &words);
EXPECT_FALSE(signBit);
EXPECT_NE(words, 0ULL);
}
* @tc.number: ffi_interface_api_093
* @tc.name: ObjectRef_CreateNativeModuleFailureInfo
* @tc.desc: Verify CreateNativeModuleFailureInfo returns undefined when error info is not enhanced.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ObjectRef_CreateNativeModuleFailureInfo)
{
LocalScope scope(vm_);
Local<ObjectRef> errorObj = ObjectRef::CreateNativeModuleFailureInfo(vm_, TEST_ERROR_INFO);
ASSERT_TRUE(errorObj->IsUndefined());
}
* @tc.number: ffi_interface_api_094
* @tc.name: ObjectRef_Set_NonHeapObject
* @tc.desc: Verify Set handles non-heap object correctly.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ObjectRef_Set_NonHeapObject)
{
LocalScope scope(vm_);
Local<ObjectRef> obj = ObjectRef::New(vm_);
ASSERT_TRUE(obj->IsObject(vm_));
Local<JSValueRef> key = NumberRef::New(vm_, 1);
Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, "test");
bool result = obj->Set(vm_, key, value);
EXPECT_TRUE(result);
}
* @tc.number: ffi_interface_api_095
* @tc.name: ObjectRef_Set_WithUtf8Key
* @tc.desc: Verify Set with utf8 key works correctly.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ObjectRef_Set_WithUtf8Key)
{
LocalScope scope(vm_);
Local<ObjectRef> obj = ObjectRef::New(vm_);
ASSERT_TRUE(obj->IsObject(vm_));
Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, TEST_STRING);
bool result = obj->Set(vm_, TEST_PROPERTY_KEY, value);
EXPECT_TRUE(result);
Local<JSValueRef> retrieved = obj->Get(vm_, TEST_PROPERTY_KEY);
ASSERT_TRUE(retrieved->IsString(vm_));
}
* @tc.number: ffi_interface_api_096
* @tc.name: ObjectRef_SetWithoutSwitchState
* @tc.desc: Verify SetWithoutSwitchState works correctly.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ObjectRef_SetWithoutSwitchState)
{
LocalScope scope(vm_);
Local<ObjectRef> obj = ObjectRef::New(vm_);
ASSERT_TRUE(obj->IsObject(vm_));
Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, TEST_STRING);
bool result = obj->SetWithoutSwitchState(vm_, TEST_PROPERTY_KEY, value);
EXPECT_TRUE(result);
}
* @tc.number: ffi_interface_api_097
* @tc.name: ObjectRef_Get_NonHeapObject
* @tc.desc: Verify Get handles non-heap object correctly.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ObjectRef_Get_NonHeapObject)
{
LocalScope scope(vm_);
Local<ObjectRef> obj = ObjectRef::New(vm_);
ASSERT_TRUE(obj->IsObject(vm_));
Local<JSValueRef> key = NumberRef::New(vm_, TEST_INDEX_VALUE);
Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, TEST_STRING);
obj->Set(vm_, key, value);
Local<JSValueRef> result = obj->Get(vm_, key);
ASSERT_TRUE(result->IsString(vm_));
}
* @tc.number: ffi_interface_api_098
* @tc.name: ObjectRef_Get_CharKey
* @tc.desc: Verify Get with char key works correctly.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ObjectRef_Get_CharKey)
{
LocalScope scope(vm_);
Local<ObjectRef> obj = ObjectRef::New(vm_);
ASSERT_TRUE(obj->IsObject(vm_));
Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, TEST_STRING);
obj->Set(vm_, TEST_PROPERTY_KEY, value);
Local<JSValueRef> result = obj->Get(vm_, TEST_PROPERTY_KEY);
ASSERT_TRUE(result->IsString(vm_));
}
* @tc.number: ffi_interface_api_099
* @tc.name: ObjectRef_Get_IntKey
* @tc.desc: Verify Get with int key works correctly.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ObjectRef_Get_IntKey)
{
LocalScope scope(vm_);
Local<ObjectRef> obj = ObjectRef::New(vm_);
ASSERT_TRUE(obj->IsObject(vm_));
Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, TEST_STRING);
obj->Set(vm_, TEST_INDEX_VALUE, value);
Local<JSValueRef> result = obj->Get(vm_, TEST_INDEX_VALUE);
ASSERT_TRUE(result->IsString(vm_));
}
* @tc.number: ffi_interface_api_100
* @tc.name: ObjectRef_GetOwnProperty_WithGetterSetter
* @tc.desc: Verify GetOwnProperty handles object with getter and setter.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ObjectRef_GetOwnProperty_WithGetterSetter)
{
LocalScope scope(vm_);
Local<ObjectRef> obj = ObjectRef::New(vm_);
ASSERT_TRUE(obj->IsObject(vm_));
Local<FunctionRef> getter = FunctionRef::New(vm_, nullptr);
Local<FunctionRef> setter = FunctionRef::New(vm_, nullptr);
PropertyAttribute attr(Local<JSValueRef>(), true, true, true);
obj->SetAccessorProperty(vm_, StringRef::NewFromUtf8(vm_, TEST_PROPERTY_KEY), getter, setter, attr);
PropertyAttribute property;
bool result = obj->GetOwnProperty(vm_, StringRef::NewFromUtf8(vm_, TEST_PROPERTY_KEY), property);
EXPECT_TRUE(result);
EXPECT_TRUE(property.HasGetter());
EXPECT_TRUE(property.HasSetter());
}
* @tc.number: ffi_interface_api_101
* @tc.name: ObjectRef_GetOwnProperty_WithWritable
* @tc.desc: Verify GetOwnProperty handles property with writable flag.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ObjectRef_GetOwnProperty_WithWritable)
{
LocalScope scope(vm_);
Local<ObjectRef> obj = ObjectRef::New(vm_);
ASSERT_TRUE(obj->IsObject(vm_));
Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, TEST_STRING);
PropertyAttribute attr(value, true, true, true);
obj->DefineProperty(vm_, StringRef::NewFromUtf8(vm_, TEST_PROPERTY_KEY), attr);
PropertyAttribute property;
bool result = obj->GetOwnProperty(vm_, StringRef::NewFromUtf8(vm_, TEST_PROPERTY_KEY), property);
EXPECT_TRUE(result);
EXPECT_TRUE(property.HasWritable());
EXPECT_TRUE(property.IsWritable());
}
* @tc.number: ffi_interface_api_102
* @tc.name: ObjectRef_GetOwnProperty_WithoutProperty
* @tc.desc: Verify GetOwnProperty returns false for non-existent property.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ObjectRef_GetOwnProperty_WithoutProperty)
{
LocalScope scope(vm_);
Local<ObjectRef> obj = ObjectRef::New(vm_);
ASSERT_TRUE(obj->IsObject(vm_));
PropertyAttribute property;
bool result = obj->GetOwnProperty(vm_, StringRef::NewFromUtf8(vm_, TEST_PROPERTY_KEY), property);
EXPECT_FALSE(result);
}
* @tc.number: ffi_interface_api_103
* @tc.name: ObjectRef_SetWithoutSwitchState_NumberKey
* @tc.desc: Verify SetWithoutSwitchState with number key.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ObjectRef_SetWithoutSwitchState_NumberKey)
{
LocalScope scope(vm_);
Local<ObjectRef> obj = ObjectRef::New(vm_);
ASSERT_TRUE(obj->IsObject(vm_));
Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, TEST_STRING);
bool result = obj->SetWithoutSwitchState(vm_, "123", value);
EXPECT_TRUE(result);
}
* @tc.number: ffi_interface_api_104
* @tc.name: ObjectRef_Freeze
* @tc.desc: Verify Freeze function freezes object correctly.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ObjectRef_Freeze)
{
LocalScope scope(vm_);
Local<ObjectRef> obj = ObjectRef::New(vm_);
ASSERT_TRUE(obj->IsObject(vm_));
Local<JSValueRef> result = obj->Freeze(vm_);
ASSERT_TRUE(result->IsObject(vm_));
}
* @tc.number: ffi_interface_api_105
* @tc.name: ObjectRef_Seal
* @tc.desc: Verify Seal function seals object correctly.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ObjectRef_Seal)
{
LocalScope scope(vm_);
Local<ObjectRef> obj = ObjectRef::New(vm_);
ASSERT_TRUE(obj->IsObject(vm_));
Local<JSValueRef> result = obj->Seal(vm_);
ASSERT_TRUE(result->IsObject(vm_));
}
* @tc.number: ffi_interface_api_106
* @tc.name: ArrayBufferRef_GetBuffer_Null
* @tc.desc: Verify GetBuffer returns valid buffer for internal ArrayBuffer.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ArrayBufferRef_GetBuffer_Null)
{
LocalScope scope(vm_);
Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, TEST_ARRAYBUFFER_LENGTH);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
void *buffer = arrayBuffer->GetBuffer(vm_);
EXPECT_NE(buffer, nullptr);
}
* @tc.number: ffi_interface_api_107
* @tc.name: ArrayBufferRef_GetBufferAndLength
* @tc.desc: Verify GetBufferAndLength returns buffer and length correctly.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, ArrayBufferRef_GetBufferAndLength)
{
LocalScope scope(vm_);
Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, TEST_ARRAYBUFFER_LENGTH);
ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
int32_t length = 0;
void *buffer = arrayBuffer->GetBufferAndLength(vm_, &length);
EXPECT_NE(buffer, nullptr);
EXPECT_EQ(length, TEST_ARRAYBUFFER_LENGTH);
}
* @tc.number: ffi_interface_api_108
* @tc.name: LocalScope_NestingLevels
* @tc.desc: Verify LocalScope nesting levels work correctly with LIFO order and ref creation.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, LocalScope_NestingLevels)
{
auto initialLevel = vm_->GetOpenHandleScopes();
EXPECT_GE(initialLevel, 0);
{
LocalScope scope1(vm_);
[[maybe_unused]] Local<IntegerRef> v1 = IntegerRef::New(vm_, 1);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 1);
}
{
LocalScope outerScope(vm_);
[[maybe_unused]] Local<IntegerRef> outerValue = IntegerRef::New(vm_, 42);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 1);
{
LocalScope innerScope(vm_);
[[maybe_unused]] Local<IntegerRef> innerValue = IntegerRef::New(vm_, 100);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 2);
}
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 1);
}
{
LocalScope level1(vm_);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 1);
{
LocalScope level2(vm_);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 2);
{
LocalScope level3(vm_);
[[maybe_unused]] Local<IntegerRef> v3 = IntegerRef::New(vm_, 3);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 3);
}
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 2);
}
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 1);
}
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel);
}
* @tc.number: ffi_interface_api_109
* @tc.name: LocalScope_ManualHeapAllocation
* @tc.desc: Verify manual heap allocation breaks LIFO order detection.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, LocalScope_ManualHeapAllocation)
{
auto initialLevel = vm_->GetOpenHandleScopes();
EXPECT_GE(initialLevel, 0);
LocalScope *scope1 = new LocalScope(vm_);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 1);
LocalScope *scope2 = new LocalScope(vm_);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 2);
delete scope1;
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 1);
delete scope2;
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel);
}
* @tc.number: ffi_interface_api_110
* @tc.name: LocalScope_CreateRefs
* @tc.desc: Verify creating LocalRefs doesn't change scope level.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, LocalScope_CreateRefs)
{
auto initialLevel = vm_->GetOpenHandleScopes();
EXPECT_GE(initialLevel, 0);
[[maybe_unused]] Local<IntegerRef> v1 = IntegerRef::New(vm_, 1);
[[maybe_unused]] Local<IntegerRef> v2 = IntegerRef::New(vm_, 2);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel);
constexpr int refCount = 10;
for (int i = 0; i < refCount; i++) {
[[maybe_unused]] Local<IntegerRef> value = IntegerRef::New(vm_, i);
}
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel);
[[maybe_unused]] Local<IntegerRef> intRef = IntegerRef::New(vm_, 42);
[[maybe_unused]] Local<IntegerRef> uintRef = IntegerRef::NewFromUnsigned(vm_, 100U);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel);
{
LocalScope s1(vm_);
[[maybe_unused]] Local<IntegerRef> v3 = IntegerRef::New(vm_, 3);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 1);
{
LocalScope s2(vm_);
[[maybe_unused]] Local<IntegerRef> v4 = IntegerRef::New(vm_, 4);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 2);
}
[[maybe_unused]] Local<IntegerRef> v5 = IntegerRef::New(vm_, 5);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 1);
}
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel);
}
* @tc.number: ffi_interface_api_111
* @tc.name: LocalScope_EscapeLocalScope
* @tc.desc: Verify EscapeLocalScope works correctly.
* @tc.type: FUNC
* @tc.require: parameter
*/
HWTEST_F_L0(JSNApiTests, LocalScope_EscapeLocalScope)
{
auto initialLevel = vm_->GetOpenHandleScopes();
EXPECT_GE(initialLevel, 0);
{
LocalScope outerScope(vm_);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 1);
{
EscapeLocalScope escapeScope(vm_);
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 2);
}
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel + 1);
}
EXPECT_EQ(vm_->GetOpenHandleScopes(), initialLevel);
}
}