1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cstddef>
17 #include "ecmascript/builtins/builtins.h"
18 #include "ecmascript/builtins/builtins_function.h"
19 #include "ecmascript/builtins/builtins_object.h"
20 #include "ecmascript/compiler/aot_file/an_file_data_manager.h"
21 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
22 #include "ecmascript/compiler/circuit_builder_helper.h"
23 #include "ecmascript/deoptimizer/deoptimizer.h"
24 #include "ecmascript/ecma_global_storage.h"
25 #include "ecmascript/ecma_vm.h"
26 #include "ecmascript/global_env.h"
27 #include "ecmascript/js_api/js_api_tree_map.h"
28 #include "ecmascript/js_api/js_api_tree_set.h"
29 #include "ecmascript/js_api/js_api_vector.h"
30 #include "ecmascript/js_array.h"
31 #include "ecmascript/js_bigint.h"
32 #include "ecmascript/js_date_time_format.h"
33 #include "ecmascript/js_generator_object.h"
34 #include "ecmascript/js_map.h"
35 #include "ecmascript/js_map_iterator.h"
36 #include "ecmascript/js_primitive_ref.h"
37 #include "ecmascript/js_regexp.h"
38 #include "ecmascript/js_runtime_options.h"
39 #include "ecmascript/js_set.h"
40 #include "ecmascript/js_set_iterator.h"
41 #include "ecmascript/js_tagged_value.h"
42 #include "ecmascript/js_thread.h"
43 #include "ecmascript/js_weak_container.h"
44 #include "ecmascript/linked_hash_table.h"
45 #include "ecmascript/mem/mem_map_allocator.h"
46 #include "ecmascript/module/js_module_manager.h"
47 #include "ecmascript/module/js_module_source_text.h"
48 #include "ecmascript/napi/include/jsnapi.h"
49 #include "ecmascript/napi/include/jsnapi_internals.h"
50 #include "ecmascript/napi/jsnapi_helper.h"
51 #include "ecmascript/object_factory.h"
52 #include "ecmascript/pgo_profiler/pgo_profiler.h"
53 #include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
54 #include "ecmascript/pgo_profiler/pgo_profiler_encoder.h"
55 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
56 #include "ecmascript/tagged_array.h"
57 #include "ecmascript/tests/test_helper.h"
58 #include "ecmascript/tagged_tree.h"
59 #include "ecmascript/weak_vector.h"
60 #include "gtest/gtest.h"
61
62 using namespace panda;
63 using namespace panda::ecmascript;
64 using namespace panda::ecmascript::kungfu;
65
66 namespace panda::test {
67 using BuiltinsFunction = ecmascript::builtins::BuiltinsFunction;
68 using PGOProfilerManager = panda::ecmascript::pgo::PGOProfilerManager;
69 using FunctionForRef = Local<JSValueRef> (*)(JsiRuntimeCallInfo *);
70 class JSNApiTests : public testing::Test {
71 public:
SetUpTestCase()72 static void SetUpTestCase()
73 {
74 GTEST_LOG_(INFO) << "SetUpTestCase";
75 }
76
TearDownTestCase()77 static void TearDownTestCase()
78 {
79 GTEST_LOG_(INFO) << "TearDownCase";
80 }
81
SetUp()82 void SetUp() override
83 {
84 RuntimeOption option;
85 option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
86 vm_ = JSNApi::CreateJSVM(option);
87 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
88 thread_ = vm_->GetJSThread();
89 vm_->SetEnableForceGC(true);
90 thread_->ManagedCodeBegin();
91 }
92
TearDown()93 void TearDown() override
94 {
95 thread_->ManagedCodeEnd();
96 vm_->SetEnableForceGC(false);
97 JSNApi::DestroyJSVM(vm_);
98 }
99
TestNumberRef(T val,TaggedType expected)100 template <typename T> void TestNumberRef(T val, TaggedType expected)
101 {
102 LocalScope scope(vm_);
103 Local<NumberRef> obj = NumberRef::New(vm_, val);
104 ASSERT_TRUE(obj->IsNumber());
105 JSTaggedType res = JSNApiHelper::ToJSTaggedValue(*obj).GetRawData();
106 ASSERT_EQ(res, expected);
107 if constexpr (std::is_floating_point_v<T>) {
108 if (std::isnan(val)) {
109 ASSERT_TRUE(std::isnan(obj->Value()));
110 } else {
111 ASSERT_EQ(obj->Value(), val);
112 }
113 } else if constexpr (sizeof(T) >= sizeof(int32_t)) {
114 ASSERT_EQ(obj->IntegerValue(vm_), val);
115 } else if constexpr (std::is_signed_v<T>) {
116 ASSERT_EQ(obj->Int32Value(vm_), val);
117 } else {
118 ASSERT_EQ(obj->Uint32Value(vm_), val);
119 }
120 }
121
ConvertDouble(double val)122 TaggedType ConvertDouble(double val)
123 {
124 return base::bit_cast<JSTaggedType>(val) + JSTaggedValue::DOUBLE_ENCODE_OFFSET;
125 }
126
127 protected:
128 void RegisterStringCacheTable();
129
130 JSThread *thread_ = nullptr;
131 EcmaVM *vm_ = nullptr;
132 bool isStringCacheTableCreated_ = false;
133 };
134
RegisterStringCacheTable()135 void JSNApiTests::RegisterStringCacheTable()
136 {
137 constexpr uint32_t STRING_CACHE_TABLE_SIZE = 100;
138 auto res = ExternalStringCache::RegisterStringCacheTable(vm_, STRING_CACHE_TABLE_SIZE);
139 if (isStringCacheTableCreated_) {
140 ASSERT_FALSE(res);
141 } else {
142 ASSERT_TRUE(res);
143 }
144 }
145
FunctionCallback(JsiRuntimeCallInfo * info)146 Local<JSValueRef> FunctionCallback(JsiRuntimeCallInfo *info)
147 {
148 EscapeLocalScope scope(info->GetVM());
149 return scope.Escape(ArrayRef::New(info->GetVM(), info->GetArgsNumber()));
150 }
151
WeakRefCallback(EcmaVM * vm)152 void WeakRefCallback(EcmaVM *vm)
153 {
154 LocalScope scope(vm);
155 Local<ObjectRef> object = ObjectRef::New(vm);
156 Global<ObjectRef> globalObject(vm, object);
157 globalObject.SetWeak();
158 Local<ObjectRef> object1 = ObjectRef::New(vm);
159 Global<ObjectRef> globalObject1(vm, object1);
160 globalObject1.SetWeak();
161 vm->CollectGarbage(TriggerGCType::YOUNG_GC);
162 vm->CollectGarbage(TriggerGCType::OLD_GC);
163 globalObject.FreeGlobalHandleAddr();
164 }
165
ThreadCheck(const EcmaVM * vm)166 void ThreadCheck(const EcmaVM *vm)
167 {
168 EXPECT_TRUE(vm->GetJSThread()->GetThreadId() != JSThread::GetCurrentThreadId());
169 }
170
CheckReject(JsiRuntimeCallInfo * info)171 void CheckReject(JsiRuntimeCallInfo *info)
172 {
173 ASSERT_EQ(info->GetArgsNumber(), 1U);
174 Local<JSValueRef> reason = info->GetCallArgRef(0);
175 ASSERT_TRUE(reason->IsString(info->GetVM()));
176 ASSERT_EQ(Local<StringRef>(reason)->ToString(info->GetVM()), "Reject");
177 }
178
RejectCallback(JsiRuntimeCallInfo * info)179 Local<JSValueRef> RejectCallback(JsiRuntimeCallInfo *info)
180 {
181 LocalScope scope(info->GetVM());
182 CheckReject(info);
183 return JSValueRef::Undefined(info->GetVM());
184 }
185
186 /**
187 * @tc.number: ffi_interface_api_105
188 * @tc.name: JSValueRef_IsGeneratorObject
189 * @tc.desc: Determine if it is a Generator generator object
190 * @tc.type: FUNC
191 * @tc.require: parameter
192 */
HWTEST_F_L0(JSNApiTests,JSValueRef_IsGeneratorObject)193 HWTEST_F_L0(JSNApiTests, JSValueRef_IsGeneratorObject)
194 {
195 LocalScope scope(vm_);
196 ObjectFactory *factory = vm_->GetFactory();
197 auto env = vm_->GetGlobalEnv();
198 JSHandle<JSTaggedValue> genFunc = env->GetGeneratorFunctionFunction();
199 JSHandle<JSGeneratorObject> genObjHandleVal = factory->NewJSGeneratorObject(genFunc);
200 JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetGeneratorFunctionClass());
201 JSHandle<JSFunction> generatorFunc = JSHandle<JSFunction>::Cast(factory->NewJSObject(hclass));
202 JSFunction::InitializeJSFunction(thread_, generatorFunc, FunctionKind::GENERATOR_FUNCTION);
203 JSHandle<GeneratorContext> generatorContext = factory->NewGeneratorContext();
204 generatorContext->SetMethod(thread_, generatorFunc.GetTaggedValue());
205 JSHandle<JSTaggedValue> generatorContextVal = JSHandle<JSTaggedValue>::Cast(generatorContext);
206 genObjHandleVal->SetGeneratorContext(thread_, generatorContextVal.GetTaggedValue());
207 JSHandle<JSTaggedValue> genObjTagHandleVal = JSHandle<JSTaggedValue>::Cast(genObjHandleVal);
208 Local<JSValueRef> genObjectRef = JSNApiHelper::ToLocal<GeneratorObjectRef>(genObjTagHandleVal);
209 ASSERT_TRUE(genObjectRef->IsGeneratorObject(vm_));
210 }
211
JSObjectTestCreate(JSThread * thread)212 static JSFunction *JSObjectTestCreate(JSThread *thread)
213 {
214 EcmaVM *ecmaVM = thread->GetEcmaVM();
215 JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
216 return globalEnv->GetObjectFunction().GetObject<JSFunction>();
217 }
218
219 /**
220 * @tc.number: ffi_interface_api_106
221 * @tc.name: JSValueRef_IsProxy
222 * @tc.desc: Determine if it is the type of proxy
223 * @tc.type: FUNC
224 * @tc.require: parameter
225 */
HWTEST_F_L0(JSNApiTests,JSValueRef_IsProxy)226 HWTEST_F_L0(JSNApiTests, JSValueRef_IsProxy)
227 {
228 LocalScope scope(vm_);
229 JSHandle<JSTaggedValue> hclass(thread_, JSObjectTestCreate(thread_));
230 JSHandle<JSTaggedValue> targetHandle(
231 thread_->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(hclass), hclass));
232
233 JSHandle<JSTaggedValue> key(thread_->GetEcmaVM()->GetFactory()->NewFromASCII("x"));
234 JSHandle<JSTaggedValue> value(thread_, JSTaggedValue(1));
235 JSObject::SetProperty(thread_, targetHandle, key, value);
236 EXPECT_EQ(JSObject::GetProperty(thread_, targetHandle, key).GetValue()->GetInt(), 1);
237
238 JSHandle<JSTaggedValue> handlerHandle(
239 thread_->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(hclass), hclass));
240 EXPECT_TRUE(handlerHandle->IsECMAObject());
241
242 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread_, targetHandle, handlerHandle);
243 EXPECT_TRUE(*proxyHandle != nullptr);
244
245 EXPECT_EQ(JSProxy::GetProperty(thread_, proxyHandle, key).GetValue()->GetInt(), 1);
246 PropertyDescriptor desc(thread_);
247 JSProxy::GetOwnProperty(thread_, proxyHandle, key, desc);
248 EXPECT_EQ(desc.GetValue()->GetInt(), 1);
249 Local<JSValueRef> proxy = JSNApiHelper::ToLocal<JSProxy>(JSHandle<JSTaggedValue>(proxyHandle));
250 ASSERT_TRUE(proxy->IsProxy(vm_));
251 }
252
253 /**
254 * @tc.number: ffi_interface_api_107
255 * @tc.name: BufferRef_New_ByteLength
256 * @tc.desc:
257 * New:Create a buffer and specify the length size
258 * ByteLength:Returns the length of the buffer
259 * @tc.type: FUNC
260 * @tc.require: parameter
261 */
HWTEST_F_L0(JSNApiTests,BufferRef_New_ByteLength)262 HWTEST_F_L0(JSNApiTests, BufferRef_New_ByteLength)
263 {
264 LocalScope scope(vm_);
265 int32_t length = 10;
266 Local<BufferRef> buffer = BufferRef::New(vm_, length);
267 ASSERT_TRUE(buffer->IsBuffer(vm_));
268 EXPECT_EQ(buffer->ByteLength(vm_), length);
269 }
270
271 /**
272 * @tc.number: ffi_interface_api_108
273 * @tc.name: BufferRef_New_ByteLength_GetBuffer
274 * @tc.desc:
275 * New:Create a buffer and specify the length size
276 * ByteLength:Returns the length of the buffer
277 * GetBuffer:Return buffer pointer
278 * @tc.type: FUNC
279 * @tc.require: parameter
280 */
HWTEST_F_L0(JSNApiTests,BufferRef_New_ByteLength_GetBuffer)281 HWTEST_F_L0(JSNApiTests, BufferRef_New_ByteLength_GetBuffer)
282 {
283 LocalScope scope(vm_);
284 int32_t length = 10;
285 Local<BufferRef> buffer = BufferRef::New(vm_, length);
286 ASSERT_TRUE(buffer->IsBuffer(vm_));
287 EXPECT_EQ(buffer->ByteLength(vm_), 10U);
288 ASSERT_NE(buffer->GetBuffer(vm_), nullptr);
289 }
290
291 /**
292 * @tc.number: ffi_interface_api_109
293 * @tc.name: BufferRef_New01_ByteLength_GetBuffer_BufferToStringCallback
294 * @tc.desc:
295 * BufferToStringCallback:Implement callback when calling ToString (vm) mode in buffer
296 * @tc.type: FUNC
297 * @tc.require: parameter
298 */
HWTEST_F_L0(JSNApiTests,BufferRef_New01_ByteLength_GetBuffer_BufferToStringCallback)299 HWTEST_F_L0(JSNApiTests, BufferRef_New01_ByteLength_GetBuffer_BufferToStringCallback)
300 {
301 LocalScope scope(vm_);
302 static bool isFree = false;
303 struct Data {
304 int32_t length;
305 };
306 const int32_t length = 15;
307 NativePointerCallback deleter = []([[maybe_unused]] void *env, void *buffer, void *data) -> void {
308 delete[] reinterpret_cast<uint8_t *>(buffer);
309 Data *currentData = reinterpret_cast<Data *>(data);
310 delete currentData;
311 isFree = true;
312 };
313 isFree = false;
314 uint8_t *buffer = new uint8_t[length]();
315 Data *data = new Data();
316 data->length = length;
317 Local<BufferRef> bufferRef = BufferRef::New(vm_, buffer, length, deleter, data);
318 ASSERT_TRUE(bufferRef->IsBuffer(vm_));
319 ASSERT_TRUE(bufferRef->IsBuffer(vm_));
320 EXPECT_EQ(bufferRef->ByteLength(vm_), 15U);
321 Local<StringRef> bufferStr = bufferRef->ToString(vm_);
322 ASSERT_TRUE(bufferStr->IsString(vm_));
323 }
324
325 /**
326 * @tc.number: ffi_interface_api_110
327 * @tc.name: LocalScope_LocalScope
328 * @tc.desc: Build Escape LocalScope sub Vm scope
329 * @tc.type: FUNC
330 * @tc.require: parameter
331 */
HWTEST_F_L0(JSNApiTests,LocalScope_LocalScope)332 HWTEST_F_L0(JSNApiTests, LocalScope_LocalScope)
333 {
334 EscapeLocalScope scope(vm_);
335 LocalScope *perScope = nullptr;
336 perScope = &scope;
337 ASSERT_TRUE(perScope != nullptr);
338 }
339
340 /**
341 * @tc.number: ffi_interface_api_111
342 * @tc.name: JSNApi_CreateJSContext_SwitchCurrentContext_DestroyJSContext
343 * @tc.desc:
344 * CreateJSContext:Create Context Object Pointer
345 * SwitchCurrentContext:Record Update Context Object
346 * DestroyJSContext:Delete Context Object
347 * @tc.type: FUNC
348 * @tc.require: parameter
349 */
HWTEST_F_L0(JSNApiTests,JSNApi_SwitchCurrentContext_DestroyJSContext)350 HWTEST_F_L0(JSNApiTests, JSNApi_SwitchCurrentContext_DestroyJSContext)
351 {
352 LocalScope scope(vm_);
353 EXPECT_EQ(vm_->GetJSThread()->GetEcmaContexts().size(), 1);
354 EcmaContext *context = JSNApi::CreateJSContext(vm_);
355 GTEST_LOG_(WARNING) << "context test =" << context;
356 EXPECT_EQ(vm_->GetJSThread()->GetEcmaContexts().size(), 2);
357 EcmaContext *context1 = JSNApi::CreateJSContext(vm_);
358 EXPECT_EQ(vm_->GetJSThread()->GetEcmaContexts().size(), 3);
359 JSNApi::SwitchCurrentContext(vm_, context1);
360 EXPECT_EQ(vm_->GetJSThread()->GetEcmaContexts().size(), 3);
361 JSNApi::DestroyJSContext(vm_, context1);
362 EXPECT_EQ(vm_->GetJSThread()->GetEcmaContexts().size(), 2);
363 }
364
365 /**
366 * @tc.number: ffi_interface_api_112
367 * @tc.name: JSNApi_CreateJSVM_DestroyJSVM
368 * @tc.desc: Create/delete JSVM
369 * @tc.type: FUNC
370 * @tc.require: parameter
371 */
HWTEST_F_L0(JSNApiTests,JSNApi_CreateJSVM_DestroyJSVM)372 HWTEST_F_L0(JSNApiTests, JSNApi_CreateJSVM_DestroyJSVM)
373 {
374 LocalScope scope(vm_);
375 std::thread t1([&](){
376 EcmaVM *vm1_ = nullptr;
377 RuntimeOption option;
378 option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
379 vm1_ = JSNApi::CreateJSVM(option);
380 ASSERT_TRUE(vm1_ != nullptr) << "Cannot create Runtime";
381 vm1_->SetEnableForceGC(true);
382 vm1_->SetEnableForceGC(false);
383 JSNApi::DestroyJSVM(vm1_);
384 });
385 {
386 ThreadSuspensionScope suspensionScope(thread_);
387 t1.join();
388 }
389 }
390
391 /**
392 * @tc.number: ffi_interface_api_114
393 * @tc.name: JSNApi_GetUncaughtException
394 * @tc.desc: Get uncaught exceptions
395 * @tc.type: FUNC
396 * @tc.require: parameter
397 */
HWTEST_F_L0(JSNApiTests,JSNApi_GetUncaughtException)398 HWTEST_F_L0(JSNApiTests, JSNApi_GetUncaughtException)
399 {
400 LocalScope scope(vm_);
401 Local<ObjectRef> excep = JSNApi::GetUncaughtException(vm_);
402 ASSERT_TRUE(excep.IsNull()) << "CreateInstance occur Exception";
403 }
404
FuncRefNewCallbackForTest(JsiRuntimeCallInfo * info)405 Local<JSValueRef> FuncRefNewCallbackForTest(JsiRuntimeCallInfo *info)
406 {
407 GTEST_LOG_(INFO) << "runing FuncRefNewCallbackForTest";
408 EscapeLocalScope scope(info->GetVM());
409 return scope.Escape(ArrayRef::New(info->GetVM(), info->GetArgsNumber()));
410 }
411
412 /**
413 * @tc.number: ffi_interface_api_115
414 * @tc.name: ObjectRef_SetAccessorProperty
415 * @tc.desc:
416 * SetAccessorProperty:Set AccessorPro Properties
417 * GetVM:Obtain environment information for runtime calls
418 * LocalScope:Build Vm Scope
419 * @tc.type: FUNC
420 * @tc.require: parameter
421 */
HWTEST_F_L0(JSNApiTests,ObjectRef_SetAccessorProperty_JsiRuntimeCallInfo_GetVM)422 HWTEST_F_L0(JSNApiTests, ObjectRef_SetAccessorProperty_JsiRuntimeCallInfo_GetVM)
423 {
424 LocalScope scope(vm_);
425 Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, "TestKey");
426 FunctionForRef nativeFunc = FuncRefNewCallbackForTest;
427 Local<FunctionRef> getter = FunctionRef::New(vm_, nativeFunc);
428 Local<FunctionRef> setter = FunctionRef::New(vm_, nativeFunc);
429 Local<ObjectRef> object = ObjectRef::New(vm_);
430 ASSERT_TRUE(object->SetAccessorProperty(vm_, key, getter, setter));
431 }
432
433 /*
434 * @tc.number: ffi_interface_api_116
435 * @tc.name: JSNApi_IsBoolean
436 * @tc.desc: Judge whether obj is a boolean type
437 * @tc.type: FUNC
438 * @tc.require: parameter
439 */
HWTEST_F_L0(JSNApiTests,IsBoolean)440 HWTEST_F_L0(JSNApiTests, IsBoolean)
441 {
442 LocalScope scope(vm_);
443 char16_t utf16[] = u"This is a char16 array";
444 int size = sizeof(utf16);
445 Local<StringRef> obj = StringRef::NewFromUtf16(vm_, utf16, size);
446 ASSERT_FALSE(obj->IsBoolean());
447 }
448
449 /*
450 * @tc.number: ffi_interface_api_117
451 * @tc.name: JSNApi_IsNULL
452 * @tc.desc: Judge whether obj is a null type
453 * @tc.type: FUNC
454 * @tc.require: parameter
455 */
HWTEST_F_L0(JSNApiTests,IsNULL)456 HWTEST_F_L0(JSNApiTests, IsNULL)
457 {
458 LocalScope scope(vm_);
459 char16_t utf16[] = u"This is a char16 array";
460 int size = sizeof(utf16);
461 Local<StringRef> obj = StringRef::NewFromUtf16(vm_, utf16, size);
462 ASSERT_FALSE(obj->IsNull());
463 }
464
465 /*
466 * @tc.number: ffi_interface_api_118
467 * @tc.name: JSNApi_GetTime
468 * @tc.desc: This function is to catch time
469 * @tc.type: FUNC
470 * @tc.require: parameter
471 */
HWTEST_F_L0(JSNApiTests,GetTime)472 HWTEST_F_L0(JSNApiTests, GetTime)
473 {
474 LocalScope scope(vm_);
475 const double time = 14.29;
476 Local<DateRef> date = DateRef::New(vm_, time);
477 ASSERT_EQ(date->GetTime(vm_), time);
478 }
479
480 /*
481 * @tc.number: ffi_interface_api_119
482 * @tc.name: JSNApi_IsDetach
483 * @tc.desc: Judge whether arraybuffer is detached
484 * @tc.type: FUNC
485 * @tc.require: parameter
486 */
HWTEST_F_L0(JSNApiTests,IsDetach)487 HWTEST_F_L0(JSNApiTests, IsDetach)
488 {
489 LocalScope scope(vm_);
490 const int32_t length = 33;
491 Local<ArrayBufferRef> arraybuffer = ArrayBufferRef::New(vm_, length);
492 ASSERT_FALSE(arraybuffer->IsDetach(vm_));
493 }
494
495 /*
496 * @tc.number: ffi_interface_api_120
497 * @tc.name: JSNApi_Detach
498 * @tc.desc: This function is to detach arraybuffer
499 * @tc.type: FUNC
500 * @tc.require: parameter
501 */
HWTEST_F_L0(JSNApiTests,Detach)502 HWTEST_F_L0(JSNApiTests, Detach)
503 {
504 LocalScope scope(vm_);
505 const int32_t length = 33;
506 Local<ArrayBufferRef> arraybuffer = ArrayBufferRef::New(vm_, length);
507 arraybuffer->Detach(vm_);
508 }
509
510 /*
511 * @tc.number: ffi_interface_api_121
512 * @tc.name: JSNApi_New1
513 * @tc.desc: create a obj that is a arraybuffer type
514 * @tc.type: FUNC
515 * @tc.require: parameter
516 */
HWTEST_F_L0(JSNApiTests,New1)517 HWTEST_F_L0(JSNApiTests, New1)
518 {
519 LocalScope scope(vm_);
520 const int32_t length = 33;
521 Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
522 ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
523 ASSERT_EQ(arrayBuffer->ByteLength(vm_), length);
524 ASSERT_NE(arrayBuffer->GetBuffer(vm_), nullptr);
525 }
526
527 /*
528 * @tc.number: ffi_interface_api_122
529 * @tc.name: JSNApi_New1
530 * @tc.desc: create a obj that is a arraybuffer type
531 * @tc.type: FUNC
532 * @tc.require: parameter
533 */
HWTEST_F_L0(JSNApiTests,New2)534 HWTEST_F_L0(JSNApiTests, New2)
535 {
536 static bool isFree = false;
537 struct Data {
538 int32_t length;
539 };
540 const int32_t length = 15;
541 Data *data = new Data();
542 data->length = length;
543 NativePointerCallback deleter = []([[maybe_unused]] void *env, void *buffer, void *data) -> void {
544 delete[] reinterpret_cast<uint8_t *>(buffer);
545 Data *currentData = reinterpret_cast<Data *>(data);
546 ASSERT_EQ(currentData->length, 15); // 5 : size of arguments
547 delete currentData;
548 isFree = true;
549 };
550 {
551 LocalScope scope(vm_);
552 uint8_t *buffer = new uint8_t[length]();
553 Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, buffer, length, deleter, data);
554 ASSERT_TRUE(arrayBuffer->IsArrayBuffer(vm_));
555 ASSERT_EQ(arrayBuffer->ByteLength(vm_), length);
556 ASSERT_EQ(arrayBuffer->GetBuffer(vm_), buffer);
557 }
558 }
559
560 /*
561 * @tc.number: ffi_interface_api_123
562 * @tc.name: JSNApi_Bytelength
563 * @tc.desc: capture bytelength of arraybuffer
564 * @tc.type: FUNC
565 * @tc.require: parameter
566 */
HWTEST_F_L0(JSNApiTests,Bytelength)567 HWTEST_F_L0(JSNApiTests, Bytelength)
568 {
569 LocalScope scope(vm_);
570 const int32_t length = 33;
571 Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
572 ASSERT_EQ(arrayBuffer->ByteLength(vm_), length);
573 }
574
575 /*
576 * @tc.number: ffi_interface_api_124
577 * @tc.name: JSNApi_GetBuffer
578 * @tc.desc: capture buffer of arraybuffer
579 * @tc.type: FUNC
580 * @tc.require: parameter
581 */
HWTEST_F_L0(JSNApiTests,GetBuffer)582 HWTEST_F_L0(JSNApiTests, GetBuffer)
583 {
584 LocalScope scope(vm_);
585 const int32_t length = 33;
586 Local<ArrayBufferRef> arraybuffer = ArrayBufferRef::New(vm_, length);
587 ASSERT_NE(arraybuffer->GetBuffer(vm_), nullptr);
588 }
589
590 /*
591 * @tc.number: ffi_interface_api_125
592 * @tc.name: JSNApi_Is32Arraytest
593 * @tc.desc: judge whether obj is a int32array type,
594 * judge whether obj is a uint32array type,
595 * judge whether obj is a float32array type,
596 * judge whether obj is a float64array type,
597 * @tc.type: FUNC
598 * @tc.require: parameter
599 */
HWTEST_F_L0(JSNApiTests,Is32Arraytest)600 HWTEST_F_L0(JSNApiTests, Is32Arraytest)
601 {
602 LocalScope scope(vm_);
603 char16_t utf16[] = u"This is a char16 array";
604 int size = sizeof(utf16);
605 Local<StringRef> obj = StringRef::NewFromUtf16(vm_, utf16, size);
606 ASSERT_FALSE(obj->IsInt32Array(vm_));
607 ASSERT_FALSE(obj->IsUint32Array(vm_));
608 ASSERT_FALSE(obj->IsFloat32Array(vm_));
609 ASSERT_FALSE(obj->IsFloat64Array(vm_));
610 }
611
612 /*
613 * @tc.number: ffi_interface_api_126
614 * @tc.name: JSNApi_SynchronizVMInfo
615 * @tc.desc: capture synchronous info of vm
616 * @tc.type: FUNC
617 * @tc.require: parameter
618 */
HWTEST_F_L0(JSNApiTests,SynchronizVMInfo)619 HWTEST_F_L0(JSNApiTests, SynchronizVMInfo)
620 {
621 LocalScope scope(vm_);
622 std::thread t1([&]() {
623 JSRuntimeOptions option;
624 EcmaVM *hostVM = JSNApi::CreateEcmaVM(option);
625 {
626 LocalScope scope2(hostVM);
627 JSNApi::SynchronizVMInfo(vm_, hostVM);
628 }
629 JSNApi::DestroyJSVM(hostVM);
630 });
631 {
632 ThreadSuspensionScope suspensionScope(thread_);
633 t1.join();
634 }
635 }
636
637 /*
638 * @tc.number: ffi_interface_api_127
639 * @tc.name: JSNApi_IsProfiling
640 * @tc.desc: judge whether vm is profiling
641 * @tc.type: FUNC
642 * @tc.require: parameter
643 */
HWTEST_F_L0(JSNApiTests,IsProfiling)644 HWTEST_F_L0(JSNApiTests, IsProfiling)
645 {
646 LocalScope scope(vm_);
647 ASSERT_FALSE(JSNApi::IsProfiling(vm_));
648 }
649
650 /*
651 * @tc.number: ffi_interface_api_128
652 * @tc.name: JSNApi_SetProfilerState
653 * @tc.desc: This function is to set state of profiler
654 * @tc.type: FUNC
655 * @tc.require: parameter
656 */
HWTEST_F_L0(JSNApiTests,SetProfilerState)657 HWTEST_F_L0(JSNApiTests, SetProfilerState)
658 {
659 bool value = true;
660 bool value2 = false;
661 LocalScope scope(vm_);
662 JSNApi::SetProfilerState(vm_, value);
663 JSNApi::SetProfilerState(vm_, value2);
664 }
665
666 /*
667 * @tc.number: ffi_interface_api_129
668 * @tc.name: JSNApi_SetLoop
669 * @tc.desc: This function is to set loop
670 * @tc.type: FUNC
671 * @tc.require: parameter
672 */
HWTEST_F_L0(JSNApiTests,SetLoop)673 HWTEST_F_L0(JSNApiTests, SetLoop)
674 {
675 LocalScope scope(vm_);
676 void *data = reinterpret_cast<void *>(BuiltinsFunction::FunctionPrototypeInvokeSelf);
677 JSNApi::SetLoop(vm_, data);
678 }
679
680 /*
681 * @tc.number: ffi_interface_api_130
682 * @tc.name: JSNApi_SetHostPromiseRejectionTracker
683 * @tc.desc: This function is to set host promise rejection about tracker
684 * @tc.type: FUNC
685 * @tc.require: parameter
686 */
HWTEST_F_L0(JSNApiTests,SetHostPromiseRejectionTracker)687 HWTEST_F_L0(JSNApiTests, SetHostPromiseRejectionTracker)
688 {
689 LocalScope scope(vm_);
690 void *data = reinterpret_cast<void *>(BuiltinsFunction::FunctionPrototypeInvokeSelf);
691 void *cb = reinterpret_cast<void *>(BuiltinsFunction::FunctionPrototypeInvokeSelf);
692 JSNApi::SetHostPromiseRejectionTracker(vm_, cb, data);
693 }
694
695 /*
696 * @tc.number: ffi_interface_api_131
697 * @tc.name: JSNApi_SetHostResolveBufferTracker
698 * @tc.desc: This function is to set host resolve buffer about tracker
699 * @tc.type: FUNC
700 * @tc.require: parameter
701 */
HWTEST_F_L0(JSNApiTests,SetHostResolveBufferTracker)702 HWTEST_F_L0(JSNApiTests, SetHostResolveBufferTracker)
703 {
704 LocalScope scope(vm_);
705 JSNApi::SetHostResolveBufferTracker(vm_,
706 [&](std::string, uint8_t **, size_t *, std::string &) -> bool { return true; });
707 }
708
709 /*
710 * @tc.number: ffi_interface_api_132
711 * @tc.name: JSNApi_SetUnloadNativeModuleCallback
712 * @tc.desc: This function is to set unload native module about callback
713 * @tc.type: FUNC
714 * @tc.require: parameter
715 */
HWTEST_F_L0(JSNApiTests,SetUnloadNativeModuleCallback)716 HWTEST_F_L0(JSNApiTests, SetUnloadNativeModuleCallback)
717 {
718 LocalScope scope(vm_);
719 JSNApi::SetUnloadNativeModuleCallback(vm_, [&](const std::string &) -> bool { return true; });
720 }
721
722 /*
723 * @tc.number: ffi_interface_api_133
724 * @tc.name: JSNApi_SetNativePtrGetter
725 * @tc.desc: This function is to set a native pointer about getter
726 * @tc.type: FUNC
727 * @tc.require: parameter
728 */
HWTEST_F_L0(JSNApiTests,SetNativePtrGetter)729 HWTEST_F_L0(JSNApiTests, SetNativePtrGetter)
730 {
731 LocalScope scope(vm_);
732 void *cb = reinterpret_cast<void *>(BuiltinsFunction::FunctionPrototypeInvokeSelf);
733 JSNApi::SetNativePtrGetter(vm_, cb);
734 }
735
736 /*
737 * @tc.number: ffi_interface_api_134
738 * @tc.name: JSNApi_PreFork
739 * @tc.desc: This function is to set prefork
740 * @tc.type: FUNC
741 * @tc.require: parameter
742 */
HWTEST_F_L0(JSNApiTests,PreFork)743 HWTEST_F_L0(JSNApiTests, PreFork)
744 {
745 LocalScope scope(vm_);
746 JSNApi::PreFork(vm_);
747 }
748
749 /*
750 * @tc.number: ffi_interface_api_135
751 * @tc.name: JSNApi_PostFork
752 * @tc.desc: This function is to set postfork
753 * @tc.type: FUNC
754 * @tc.require: parameter
755 */
HWTEST_F_L0(JSNApiTests,PostFork)756 HWTEST_F_L0(JSNApiTests, PostFork)
757 {
758 RuntimeOption option;
759 ecmascript::ThreadNativeScope nativeScope(vm_->GetJSThread());
760 LocalScope scope(vm_);
761 JSNApi::PreFork(vm_);
762 JSNApi::PostFork(vm_, option);
763 }
764
765
766 /*
767 * @tc.number: ffi_interface_api_136
768 * @tc.name: JSNApi_NewFromUtf8
769 * @tc.desc: create a newfromutf8 object
770 * @tc.type: FUNC
771 * @tc.require: parameter
772 */
HWTEST_F_L0(JSNApiTests,NewFromUtf8)773 HWTEST_F_L0(JSNApiTests, NewFromUtf8)
774 {
775 LocalScope scope(vm_);
776 char utf8[] = "hello world!";
777 int length = strlen(utf8);
778 Local<StringRef> result = StringRef::NewFromUtf8(vm_, utf8, length);
779 ASSERT_EQ(result->Utf8Length(vm_), length + 1);
780 }
781
782 /*
783 * @tc.number: ffi_interface_api_137
784 * @tc.name: JSNApi_NewFromUtf16
785 * @tc.desc: create a newfromutf16 object
786 * @tc.type: FUNC
787 * @tc.require: parameter
788 */
HWTEST_F_L0(JSNApiTests,NewFromUtf16)789 HWTEST_F_L0(JSNApiTests, NewFromUtf16)
790 {
791 LocalScope scope(vm_);
792 char16_t utf16[] = u"This is a char16 array";
793 int length = sizeof(utf16);
794 Local<StringRef> result = StringRef::NewFromUtf16(vm_, utf16, length);
795 ASSERT_EQ(result->Length(vm_), length);
796 }
797
798 /*
799 * @tc.number: ffi_interface_api_138
800 * @tc.name: JSNApi_GetNapiWrapperString
801 * @tc.desc: This function is to get a napiwrapper string
802 * @tc.type: FUNC
803 * @tc.require: parameter
804 */
HWTEST_F_L0(JSNApiTests,GetNapiWrapperString)805 HWTEST_F_L0(JSNApiTests, GetNapiWrapperString)
806 {
807 LocalScope scope(vm_);
808 Local<StringRef> result = StringRef::GetNapiWrapperString(vm_);
809 ASSERT_TRUE(result->IsString(vm_));
810 }
811
812 /*
813 * @tc.number: ffi_interface_api_139
814 * @tc.name: JSNApi_JSExecutionScope
815 * @tc.desc: This function is to construct a object of jsexecutionscope
816 * @tc.type: FUNC
817 * @tc.require: parameter
818 */
HWTEST_F_L0(JSNApiTests,JSExecutionScope)819 HWTEST_F_L0(JSNApiTests, JSExecutionScope)
820 {
821 LocalScope scope(vm_);
822 JSExecutionScope jsexecutionScope(vm_);
823 }
824
825 /*
826 * @tc.number: ffi_interface_api_140
827 * @tc.name: WeakMapRef_GetSize_GetTotalElements_GetKey_GetValue
828 * @tc.desc: This function is to set a weakmap and capture it's size ,
829 * key, value and total elements
830 * @tc.type: FUNC
831 * @tc.require: parameter
832 */
HWTEST_F_L0(JSNApiTests,WeakMapRef_GetSize_GetTotalElements_GetKey_GetValue)833 HWTEST_F_L0(JSNApiTests, WeakMapRef_GetSize_GetTotalElements_GetKey_GetValue)
834 {
835 LocalScope scope(vm_);
836 JSThread *thread = vm_->GetJSThread();
837 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
838 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
839 JSHandle<JSTaggedValue> constructor = env->GetBuiltinsWeakMapFunction();
840 JSHandle<JSWeakMap> weakMap =
841 JSHandle<JSWeakMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
842 JSHandle<LinkedHashMap> hashMap = LinkedHashMap::Create(thread);
843 weakMap->SetLinkedMap(thread, hashMap);
844 JSHandle<JSTaggedValue> weakMapTag = JSHandle<JSTaggedValue>::Cast(weakMap);
845
846 Local<WeakMapRef> map = JSNApiHelper::ToLocal<WeakMapRef>(weakMapTag);
847 EXPECT_TRUE(map->IsWeakMap(vm_));
848 JSHandle<JSTaggedValue> value(factory->NewFromASCII("value"));
849 JSHandle<JSTaggedValue> key(factory->NewFromASCII("key"));
850 JSWeakMap::Set(thread, weakMap, key, value);
851 int32_t num = map->GetSize(vm_);
852 int32_t num1 = map->GetTotalElements(vm_);
853 ASSERT_EQ(num, 1);
854 ASSERT_EQ(num1, 1);
855 Local<JSValueRef> res1 = map->GetKey(vm_, 0);
856 ASSERT_EQ(res1->ToString(vm_)->ToString(vm_), "key");
857 Local<JSValueRef> res2 = map->GetValue(vm_, 0);
858 ASSERT_EQ(res2->ToString(vm_)->ToString(vm_), "value");
859 }
860
861 /*
862 * @tc.number: ffi_interface_api_141
863 * @tc.name: JSNApi_ IsAGJA
864 * @tc.desc: This function is to judge whether object is a argumentsobject or
865 * is a generatorfunction or is a asyncfunction
866 * @tc.type: FUNC
867 * @tc.require: parameter
868 */
HWTEST_F_L0(JSNApiTests,IsAGJA)869 HWTEST_F_L0(JSNApiTests, IsAGJA)
870 {
871 LocalScope scope(vm_);
872 char16_t utf16[] = u"This is a char16 array";
873 int size = sizeof(utf16);
874 Local<StringRef> obj = StringRef::NewFromUtf16(vm_, utf16, size);
875 ASSERT_FALSE(obj->IsArgumentsObject(vm_));
876 ASSERT_FALSE(obj->IsGeneratorFunction(vm_));
877 ASSERT_FALSE(obj->IsAsyncFunction(vm_));
878 }
879
880 /**
881 * @tc.number: ffi_interface_api_143
882 * @tc.name: Int32Array
883 * @tc.desc: Catch exceptions correctly
884 * @tc.type: FUNC
885 * @tc.require: parameter
886 */
HWTEST_F_L0(JSNApiTests,HasCaught)887 HWTEST_F_L0(JSNApiTests, HasCaught)
888 {
889 LocalScope scope(vm_);
890 Local<StringRef> message = StringRef::NewFromUtf8(vm_, "ErrorTest");
891 Local<JSValueRef> error = Exception::Error(vm_, message);
892 ASSERT_TRUE(error->IsError(vm_));
893 JSNApi::ThrowException(vm_, error);
894 TryCatch tryCatch(vm_);
895 ASSERT_TRUE(tryCatch.HasCaught());
896 vm_->GetJSThread()->ClearException();
897 ASSERT_FALSE(tryCatch.HasCaught());
898 }
899
900 /**
901 * @tc.number: ffi_interface_api_144
902 * @tc.name: Int32Array
903 * @tc.desc: Rethrow the exception
904 * @tc.type: FUNC
905 * @tc.require: parameter
906 */
HWTEST_F_L0(JSNApiTests,Rethrow)907 HWTEST_F_L0(JSNApiTests, Rethrow)
908 {
909 LocalScope scope(vm_);
910 TryCatch tryCatch(vm_);
911 tryCatch.Rethrow();
912 ASSERT_TRUE(tryCatch.getrethrow_());
913 }
914
915 /**
916 * @tc.number: ffi_interface_api_145
917 * @tc.name: Int32Array
918 * @tc.desc: Clear caught exceptions
919 * @tc.type: FUNC
920 * @tc.require: parameter
921 */
HWTEST_F_L0(JSNApiTests,GetAndClearException)922 HWTEST_F_L0(JSNApiTests, GetAndClearException)
923 {
924 LocalScope scope(vm_);
925 Local<StringRef> message = StringRef::NewFromUtf8(vm_, "ErrorTest");
926 Local<JSValueRef> error = Exception::Error(vm_, message);
927 ASSERT_TRUE(error->IsError(vm_));
928 JSNApi::ThrowException(vm_, error);
929 ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
930 TryCatch tryCatch(vm_);
931 tryCatch.GetAndClearException();
932 EXPECT_FALSE(vm_->GetJSThread()->HasPendingException());
933 }
934 /**
935 * @tc.number: ffi_interface_api_146
936 * @tc.name: Int32Array
937 * @tc.desc: trycatch class construction
938 * @tc.type: FUNC
939 * @tc.require: parameter
940 */
HWTEST_F_L0(JSNApiTests,TryCatch)941 HWTEST_F_L0(JSNApiTests, TryCatch)
942 {
943 LocalScope scope(vm_);
944 TryCatch tryCatch(vm_);
945 EXPECT_EQ(tryCatch.getrethrow_(), false);
946 EXPECT_FALSE(tryCatch.HasCaught());
947 tryCatch.Rethrow();
948 EXPECT_EQ(tryCatch.getrethrow_(), true);
949 }
950
HWTEST_F_L0(JSNApiTests,NewObjectWithProperties)951 HWTEST_F_L0(JSNApiTests, NewObjectWithProperties)
952 {
953 LocalScope scope(vm_);
954 Local<JSValueRef> keys[1100];
955 Local<JSValueRef> values[1100];
956 PropertyAttribute attributes[1100];
957 for (int i = 0; i < 1100; i += (i < 80 ? (i < 10 ? 1 : 80) : 1000)) {
958 for (int j = 0; j <= i; ++j) {
959 std::string strKey("TestKey" + std::to_string(i) + "_" + std::to_string(j));
960 std::string strVal("TestValue" + std::to_string(i) + "_" + std::to_string(j));
961 keys[j] = StringRef::NewFromUtf8(vm_, strKey.c_str());
962 values[j] = StringRef::NewFromUtf8(vm_, strVal.c_str());
963 attributes[j] = PropertyAttribute(values[j], true, true, true);
964 }
965 Local<ObjectRef> object = ObjectRef::NewWithProperties(vm_, i + 1, keys, attributes);
966 for (int j = 0; j <= i; ++j) {
967 Local<JSValueRef> value1 = object->Get(vm_, keys[j]);
968 EXPECT_TRUE(values[j]->IsStrictEquals(vm_, value1));
969 }
970 JSHandle<JSObject> obj(JSNApiHelper::ToJSHandle(object));
971 uint32_t propCount = obj->GetJSHClass()->NumberOfProps();
972 if (i + 1 > PropertyAttributes::MAX_FAST_PROPS_CAPACITY) {
973 EXPECT_TRUE(propCount == 0);
974 EXPECT_TRUE(obj->GetJSHClass()->IsDictionaryMode());
975 JSHandle<NameDictionary> dict(thread_, obj->GetProperties());
976 EXPECT_TRUE(dict->EntriesCount() == i + 1);
977 } else {
978 EXPECT_TRUE(propCount == i + 1);
979 int32_t in_idx = obj->GetJSHClass()->GetNextInlinedPropsIndex();
980 int32_t nonin_idx = obj->GetJSHClass()->GetNextNonInlinedPropsIndex();
981 if (i + 1 < JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS) {
982 EXPECT_TRUE(in_idx == i + 1);
983 EXPECT_TRUE(nonin_idx == -1);
984 } else {
985 EXPECT_TRUE(in_idx == -1);
986 EXPECT_TRUE(nonin_idx == 0);
987 }
988 }
989 }
990 }
991
HWTEST_F_L0(JSNApiTests,NewObjectWithPropertieNonPureStringKey)992 HWTEST_F_L0(JSNApiTests, NewObjectWithPropertieNonPureStringKey)
993 {
994 LocalScope scope(vm_);
995 Local<JSValueRef> keys[] = {
996 StringRef::NewFromUtf8(vm_, "1"),
997 };
998 Local<JSValueRef> values[] = {
999 StringRef::NewFromUtf8(vm_, "value1"),
1000 };
1001 PropertyAttribute attributes[] = {
1002 PropertyAttribute(values[0], true, true, true),
1003 };
1004 Local<ObjectRef> object = ObjectRef::NewWithProperties(vm_, 1, keys, attributes);
1005 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(object);
1006 EXPECT_TRUE(obj.GetTaggedValue() == JSTaggedValue::Undefined());
1007 thread_->ClearException();
1008 }
1009
HWTEST_F_L0(JSNApiTests,NewObjectWithPropertiesDuplicate)1010 HWTEST_F_L0(JSNApiTests, NewObjectWithPropertiesDuplicate)
1011 {
1012 LocalScope scope(vm_);
1013 Local<JSValueRef> keys[] = {
1014 StringRef::NewFromUtf8(vm_, "duplicateKey"),
1015 StringRef::NewFromUtf8(vm_, "simpleKey"),
1016 StringRef::NewFromUtf8(vm_, "duplicateKey"),
1017 };
1018 Local<JSValueRef> values[] = {
1019 StringRef::NewFromUtf8(vm_, "value1"),
1020 StringRef::NewFromUtf8(vm_, "value2"),
1021 StringRef::NewFromUtf8(vm_, "value3"),
1022 };
1023 PropertyAttribute attributes[] = {
1024 PropertyAttribute(values[0], true, true, true),
1025 PropertyAttribute(values[1], true, true, true),
1026 PropertyAttribute(values[2], true, true, true),
1027 };
1028 Local<ObjectRef> object = ObjectRef::NewWithProperties(vm_, 3, keys, attributes);
1029 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(object);
1030 EXPECT_TRUE(obj.GetTaggedValue() == JSTaggedValue::Undefined());
1031 thread_->ClearException();
1032 }
1033
HWTEST_F_L0(JSNApiTests,NewObjectWithNamedProperties)1034 HWTEST_F_L0(JSNApiTests, NewObjectWithNamedProperties)
1035 {
1036 LocalScope scope(vm_);
1037 const char *keys[1100];
1038 std::string strKeys[1100];
1039 Local<JSValueRef> values[1100];
1040 for (int i = 0; i < 1100; i += (i < 80 ? (i < 10 ? 1 : 80) : 1000)) {
1041 for (int j = 0; j <= i; ++j) {
1042 strKeys[j] = "TestKey" + std::to_string(i) + "_" + std::to_string(j);
1043 std::string strVal("TestValue" + std::to_string(i) + "_" + std::to_string(j));
1044 keys[j] = const_cast<char *>(strKeys[j].c_str());
1045 values[j] = StringRef::NewFromUtf8(vm_, strVal.c_str());
1046 }
1047 Local<ObjectRef> object = ObjectRef::NewWithNamedProperties(vm_, i + 1, keys, values);
1048 for (int j = 0; j <= i; ++j) {
1049 Local<JSValueRef> value1 = object->Get(vm_, StringRef::NewFromUtf8(vm_, keys[j]));
1050 EXPECT_TRUE(values[j]->IsStrictEquals(vm_, value1));
1051 }
1052 JSHandle<JSObject> obj(JSNApiHelper::ToJSHandle(object));
1053 uint32_t propCount = obj->GetJSHClass()->NumberOfProps();
1054 if (i + 1 > PropertyAttributes::MAX_FAST_PROPS_CAPACITY) {
1055 EXPECT_TRUE(propCount == 0);
1056 EXPECT_TRUE(obj->GetJSHClass()->IsDictionaryMode());
1057 JSHandle<NameDictionary> dict(thread_, obj->GetProperties());
1058 EXPECT_TRUE(dict->EntriesCount() == i + 1);
1059 } else {
1060 EXPECT_TRUE(propCount == i + 1);
1061 int32_t in_idx = obj->GetJSHClass()->GetNextInlinedPropsIndex();
1062 int32_t nonin_idx = obj->GetJSHClass()->GetNextNonInlinedPropsIndex();
1063 if (i + 1 < JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS) {
1064 EXPECT_TRUE(in_idx == i + 1);
1065 EXPECT_TRUE(nonin_idx == -1);
1066 } else {
1067 EXPECT_TRUE(in_idx == -1);
1068 EXPECT_TRUE(nonin_idx == 0);
1069 }
1070 }
1071 }
1072 }
1073
HWTEST_F_L0(JSNApiTests,NewObjectWithNamedPropertieNonPureStringKey)1074 HWTEST_F_L0(JSNApiTests, NewObjectWithNamedPropertieNonPureStringKey)
1075 {
1076 LocalScope scope(vm_);
1077 const char *keys[] = {
1078 "1",
1079 };
1080 Local<JSValueRef> values[] = {
1081 StringRef::NewFromUtf8(vm_, "value1"),
1082 };
1083 Local<ObjectRef> object = ObjectRef::NewWithNamedProperties(vm_, 2, keys, values);
1084 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(object);
1085 EXPECT_TRUE(obj.GetTaggedValue() == JSTaggedValue::Undefined());
1086 thread_->ClearException();
1087 }
1088
HWTEST_F_L0(JSNApiTests,NewObjectWithNamedPropertiesDuplicate)1089 HWTEST_F_L0(JSNApiTests, NewObjectWithNamedPropertiesDuplicate)
1090 {
1091 LocalScope scope(vm_);
1092 const char *keys[] = {
1093 "duplicateKey",
1094 "simpleKey",
1095 "duplicateKey",
1096 };
1097 Local<JSValueRef> values[] = {
1098 StringRef::NewFromUtf8(vm_, "value1"),
1099 StringRef::NewFromUtf8(vm_, "value2"),
1100 StringRef::NewFromUtf8(vm_, "value3"),
1101 };
1102 Local<ObjectRef> object = ObjectRef::NewWithNamedProperties(vm_, 3, keys, values);
1103 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(object);
1104 EXPECT_TRUE(obj.GetTaggedValue() == JSTaggedValue::Undefined());
1105 thread_->ClearException();
1106 }
1107
HWTEST_F_L0(JSNApiTests,GetNamedPropertyByPassingUtf8Key)1108 HWTEST_F_L0(JSNApiTests, GetNamedPropertyByPassingUtf8Key)
1109 {
1110 LocalScope scope(vm_);
1111 Local<ObjectRef> object = ObjectRef::New(vm_);
1112 const char* utf8Key = "TestKey";
1113 Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, utf8Key);
1114 Local<JSValueRef> value = ObjectRef::New(vm_);
1115 PropertyAttribute attribute(value, true, true, true);
1116
1117 ASSERT_TRUE(object->DefineProperty(vm_, key, attribute));
1118 Local<JSValueRef> value1 = object->Get(vm_, utf8Key);
1119 ASSERT_TRUE(value->IsStrictEquals(vm_, value1));
1120 }
1121
HWTEST_F_L0(JSNApiTests,SetNamedPropertyByPassingUtf8Key)1122 HWTEST_F_L0(JSNApiTests, SetNamedPropertyByPassingUtf8Key)
1123 {
1124 LocalScope scope(vm_);
1125 Local<ObjectRef> object = ObjectRef::New(vm_);
1126 const char* utf8Key = "TestKey";
1127 Local<JSValueRef> value = ObjectRef::New(vm_);
1128
1129 ASSERT_TRUE(object->Set(vm_, utf8Key, value));
1130 Local<JSValueRef> value1 = object->Get(vm_, utf8Key);
1131 ASSERT_TRUE(value->IsStrictEquals(vm_, value1));
1132 }
1133
HWTEST_F_L0(JSNApiTests,NapiFastPathGetNamedProperty)1134 HWTEST_F_L0(JSNApiTests, NapiFastPathGetNamedProperty)
1135 {
1136 LocalScope scope(vm_);
1137 Local<ObjectRef> object = ObjectRef::New(vm_);
1138 const char* utf8Key = "TestKey";
1139 Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, utf8Key);
1140 Local<JSValueRef> value = ObjectRef::New(vm_);
1141 PropertyAttribute attribute(value, true, true, true);
1142
1143 ASSERT_TRUE(object->DefineProperty(vm_, key, attribute));
1144 Local<JSValueRef> value1 = JSNApi::NapiGetNamedProperty(vm_, reinterpret_cast<uintptr_t>(*object), utf8Key);
1145 ASSERT_TRUE(value->IsStrictEquals(vm_, value1));
1146 }
1147
HWTEST_F_L0(JSNApiTests,NewObjectWithPropertiesDuplicateWithKeyNotFromStringTable)1148 HWTEST_F_L0(JSNApiTests, NewObjectWithPropertiesDuplicateWithKeyNotFromStringTable)
1149 {
1150 LocalScope scope(vm_);
1151 Local<JSValueRef> keys[] = {
1152 StringRef::NewFromUtf8WithoutStringTable(vm_, "duplicateKey"),
1153 StringRef::NewFromUtf8WithoutStringTable(vm_, "simpleKey"),
1154 StringRef::NewFromUtf8WithoutStringTable(vm_, "duplicateKey"),
1155 };
1156 Local<JSValueRef> values[] = {
1157 StringRef::NewFromUtf8WithoutStringTable(vm_, "value1"),
1158 StringRef::NewFromUtf8WithoutStringTable(vm_, "value2"),
1159 StringRef::NewFromUtf8WithoutStringTable(vm_, "value3"),
1160 };
1161 PropertyAttribute attributes[] = {
1162 PropertyAttribute(values[0], true, true, true),
1163 PropertyAttribute(values[1], true, true, true),
1164 PropertyAttribute(values[2], true, true, true),
1165 };
1166 Local<ObjectRef> object = ObjectRef::NewWithProperties(vm_, 3, keys, attributes);
1167 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(object);
1168 EXPECT_TRUE(obj.GetTaggedValue() == JSTaggedValue::Undefined());
1169 thread_->ClearException();
1170 }
1171
HWTEST_F_L0(JSNApiTests,EcmaObjectToInt)1172 HWTEST_F_L0(JSNApiTests, EcmaObjectToInt)
1173 {
1174 LocalScope scope(vm_);
1175 Local<FunctionRef> toPrimitiveFunc = FunctionRef::New(vm_,
1176 [](JsiRuntimeCallInfo *runtimeInfo) -> Local<JSValueRef> {
1177 EcmaVM *vm = runtimeInfo->GetVM();
1178 return JSValueRef::True(vm);
1179 });
1180 Local<ObjectRef> obj = ObjectRef::New(vm_);
1181 PropertyAttribute attribute(toPrimitiveFunc, true, true, true);
1182 Local<JSValueRef> toPrimitiveKey = JSNApiHelper::ToLocal<JSValueRef>(vm_->GetGlobalEnv()->GetToPrimitiveSymbol());
1183 obj->DefineProperty(vm_, toPrimitiveKey, attribute);
1184 {
1185 // Test that Uint32Value and Int32Value should transition to Running if needed.
1186 ThreadNativeScope nativeScope(thread_);
1187 uint32_t res = obj->Uint32Value(vm_);
1188 EXPECT_TRUE(res == 1);
1189 res = obj->Int32Value(vm_);
1190 EXPECT_TRUE(res == 1);
1191 }
1192 }
1193
HWTEST_F_L0(JSNApiTests,NapiTryFastTest)1194 HWTEST_F_L0(JSNApiTests, NapiTryFastTest)
1195 {
1196 Local<ObjectRef> object = ObjectRef::New(vm_);
1197 JSTaggedValue a(0);
1198 JSHandle<JSTaggedValue> handle(thread_, a);
1199 Local<JSValueRef> key = JSNApiHelper::ToLocal<JSValueRef>(handle);
1200 const char* utf8Key = "TestKey";
1201 Local<JSValueRef> key2 = StringRef::NewFromUtf8(vm_, utf8Key);
1202 Local<JSValueRef> value = ObjectRef::New(vm_);
1203 object->Set(vm_, key, value);
1204 object->Set(vm_, key2, value);
1205 Local<JSValueRef> res1 = JSNApi::NapiGetProperty(vm_, reinterpret_cast<uintptr_t>(*object),
1206 reinterpret_cast<uintptr_t>(*key));
1207 ASSERT_TRUE(value->IsStrictEquals(vm_, res1));
1208 Local<JSValueRef> res2 = JSNApi::NapiGetProperty(vm_, reinterpret_cast<uintptr_t>(*object),
1209 reinterpret_cast<uintptr_t>(*key2));
1210 ASSERT_TRUE(value->IsStrictEquals(vm_, res2));
1211
1212 Local<JSValueRef> flag = JSNApi::NapiHasProperty(vm_, reinterpret_cast<uintptr_t>(*object),
1213 reinterpret_cast<uintptr_t>(*key));
1214 ASSERT_TRUE(flag->BooleaValue(vm_));
1215 flag = JSNApi::NapiHasProperty(vm_, reinterpret_cast<uintptr_t>(*object), reinterpret_cast<uintptr_t>(*key2));
1216 ASSERT_TRUE(flag->BooleaValue(vm_));
1217
1218 flag = JSNApi::NapiDeleteProperty(vm_, reinterpret_cast<uintptr_t>(*object), reinterpret_cast<uintptr_t>(*key));
1219 ASSERT_TRUE(flag->BooleaValue(vm_));
1220 flag = JSNApi::NapiDeleteProperty(vm_, reinterpret_cast<uintptr_t>(*object), reinterpret_cast<uintptr_t>(*key2));
1221 ASSERT_TRUE(flag->BooleaValue(vm_));
1222
1223 flag = JSNApi::NapiHasProperty(vm_, reinterpret_cast<uintptr_t>(*object), reinterpret_cast<uintptr_t>(*key));
1224 ASSERT_FALSE(flag->BooleaValue(vm_));
1225 flag = JSNApi::NapiHasProperty(vm_, reinterpret_cast<uintptr_t>(*object), reinterpret_cast<uintptr_t>(*key2));
1226 ASSERT_FALSE(flag->BooleaValue(vm_));
1227 }
1228
HWTEST_F_L0(JSNApiTests,NapiTryFastHasMethodTest)1229 HWTEST_F_L0(JSNApiTests, NapiTryFastHasMethodTest)
1230 {
1231 LocalScope scope(vm_);
1232 auto array = JSArray::ArrayCreate(thread_, JSTaggedNumber(0));
1233 auto arr = JSNApiHelper::ToLocal<ObjectRef>(array);
1234 const char* utf8Key = "concat";
1235 Local<JSValueRef> key3 = StringRef::NewFromUtf8(vm_, utf8Key);
1236 auto flag = JSNApi::NapiHasProperty(vm_, reinterpret_cast<uintptr_t>(*arr), reinterpret_cast<uintptr_t>(*key3));
1237 ASSERT_TRUE(flag->BooleaValue(vm_));
1238 }
1239
HWTEST_F_L0(JSNApiTests,NapiExternalStringCacheTest001)1240 HWTEST_F_L0(JSNApiTests, NapiExternalStringCacheTest001)
1241 {
1242 isStringCacheTableCreated_ = ExternalStringCache::RegisterStringCacheTable(vm_, 0);
1243 ASSERT_FALSE(isStringCacheTableCreated_);
1244 }
1245
HWTEST_F_L0(JSNApiTests,NapiExternalStringCacheTest002)1246 HWTEST_F_L0(JSNApiTests, NapiExternalStringCacheTest002)
1247 {
1248 constexpr uint32_t STRING_CACHE_TABLE_SIZE = 300;
1249 isStringCacheTableCreated_ = ExternalStringCache::RegisterStringCacheTable(vm_, STRING_CACHE_TABLE_SIZE);
1250 ASSERT_FALSE(isStringCacheTableCreated_);
1251 }
1252
HWTEST_F_L0(JSNApiTests,NapiExternalStringCacheTest003)1253 HWTEST_F_L0(JSNApiTests, NapiExternalStringCacheTest003)
1254 {
1255 constexpr uint32_t STRING_CACHE_TABLE_SIZE = 100;
1256 isStringCacheTableCreated_ = ExternalStringCache::RegisterStringCacheTable(vm_, STRING_CACHE_TABLE_SIZE);
1257 ASSERT_TRUE(isStringCacheTableCreated_);
1258 }
1259
HWTEST_F_L0(JSNApiTests,NapiExternalStringCacheTest004)1260 HWTEST_F_L0(JSNApiTests, NapiExternalStringCacheTest004)
1261 {
1262 RegisterStringCacheTable();
1263 constexpr uint32_t PROPERTY_INDEX = 101;
1264 constexpr char property[] = "hello";
1265 auto res = ExternalStringCache::SetCachedString(vm_, property, PROPERTY_INDEX);
1266 ASSERT_FALSE(res);
1267 }
1268
HWTEST_F_L0(JSNApiTests,NapiExternalStringCacheTest005)1269 HWTEST_F_L0(JSNApiTests, NapiExternalStringCacheTest005)
1270 {
1271 RegisterStringCacheTable();
1272 constexpr uint32_t PROPERTY_INDEX = 0;
1273 constexpr char property[] = "hello";
1274 auto res = ExternalStringCache::SetCachedString(vm_, property, PROPERTY_INDEX);
1275 ASSERT_TRUE(res);
1276 }
1277
HWTEST_F_L0(JSNApiTests,NapiExternalStringCacheTest006)1278 HWTEST_F_L0(JSNApiTests, NapiExternalStringCacheTest006)
1279 {
1280 RegisterStringCacheTable();
1281 constexpr uint32_t PROPERTY_INDEX = 1;
1282 constexpr char property[] = "hello";
1283 auto res = ExternalStringCache::SetCachedString(vm_, property, PROPERTY_INDEX);
1284 ASSERT_TRUE(res);
1285
1286 constexpr uint32_t QUERY_PROPERTY_INDEX = 2;
1287 res = ExternalStringCache::HasCachedString(vm_, QUERY_PROPERTY_INDEX);
1288 ASSERT_FALSE(res);
1289 }
1290
HWTEST_F_L0(JSNApiTests,NapiExternalStringCacheTest007)1291 HWTEST_F_L0(JSNApiTests, NapiExternalStringCacheTest007)
1292 {
1293 RegisterStringCacheTable();
1294 constexpr uint32_t PROPERTY_INDEX = 2;
1295 constexpr char property[] = "hello";
1296 auto res = ExternalStringCache::SetCachedString(vm_, property, PROPERTY_INDEX);
1297 ASSERT_TRUE(res);
1298
1299 constexpr uint32_t QUERY_PROPERTY_INDEX = 2;
1300 res = ExternalStringCache::HasCachedString(vm_, QUERY_PROPERTY_INDEX);
1301 ASSERT_TRUE(res);
1302 }
1303
HWTEST_F_L0(JSNApiTests,NapiExternalStringCacheTest008)1304 HWTEST_F_L0(JSNApiTests, NapiExternalStringCacheTest008)
1305 {
1306 RegisterStringCacheTable();
1307 constexpr uint32_t PROPERTY_INDEX = 3;
1308 constexpr char property[] = "hello world";
1309 auto res = ExternalStringCache::SetCachedString(vm_, property, PROPERTY_INDEX);
1310 ASSERT_TRUE(res);
1311 Local<StringRef> value = ExternalStringCache::GetCachedString(vm_, PROPERTY_INDEX);
1312 ASSERT_FALSE(value->IsUndefined());
1313 EXPECT_EQ(value->ToString(vm_), property);
1314 }
1315
HWTEST_F_L0(JSNApiTests,SetExecuteMode)1316 HWTEST_F_L0(JSNApiTests, SetExecuteMode)
1317 {
1318 ecmascript::ModuleManager *moduleManager = thread_->GetCurrentEcmaContext()->GetModuleManager();
1319 ecmascript::ModuleExecuteMode res1 = moduleManager->GetExecuteMode();
1320 EXPECT_EQ(res1, ecmascript::ModuleExecuteMode::ExecuteZipMode);
1321
1322 JSNApi::SetExecuteBufferMode(vm_);
1323 ecmascript::ModuleExecuteMode res2 = moduleManager->GetExecuteMode();
1324 EXPECT_EQ(res2, ecmascript::ModuleExecuteMode::ExecuteBufferMode);
1325 }
1326 } // namespace panda::test
1327