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 }
91
TearDown()92 void TearDown() override
93 {
94 vm_->SetEnableForceGC(false);
95 JSNApi::DestroyJSVM(vm_);
96 }
97
TestNumberRef(T val,TaggedType expected)98 template <typename T> void TestNumberRef(T val, TaggedType expected)
99 {
100 LocalScope scope(vm_);
101 Local<NumberRef> obj = NumberRef::New(vm_, val);
102 ASSERT_TRUE(obj->IsNumber());
103 JSTaggedType res = JSNApiHelper::ToJSTaggedValue(*obj).GetRawData();
104 ASSERT_EQ(res, expected);
105 if constexpr (std::is_floating_point_v<T>) {
106 if (std::isnan(val)) {
107 ASSERT_TRUE(std::isnan(obj->Value()));
108 } else {
109 ASSERT_EQ(obj->Value(), val);
110 }
111 } else if constexpr (sizeof(T) >= sizeof(int32_t)) {
112 ASSERT_EQ(obj->IntegerValue(vm_), val);
113 } else if constexpr (std::is_signed_v<T>) {
114 ASSERT_EQ(obj->Int32Value(vm_), val);
115 } else {
116 ASSERT_EQ(obj->Uint32Value(vm_), val);
117 }
118 }
119
ConvertDouble(double val)120 TaggedType ConvertDouble(double val)
121 {
122 return base::bit_cast<JSTaggedType>(val) + JSTaggedValue::DOUBLE_ENCODE_OFFSET;
123 }
124
125 protected:
126 JSThread *thread_ = nullptr;
127 EcmaVM *vm_ = nullptr;
128 };
129
FunctionCallback(JsiRuntimeCallInfo * info)130 Local<JSValueRef> FunctionCallback(JsiRuntimeCallInfo *info)
131 {
132 EscapeLocalScope scope(info->GetVM());
133 return scope.Escape(ArrayRef::New(info->GetVM(), info->GetArgsNumber()));
134 }
135
WeakRefCallback(EcmaVM * vm)136 void WeakRefCallback(EcmaVM *vm)
137 {
138 LocalScope scope(vm);
139 Local<ObjectRef> object = ObjectRef::New(vm);
140 Global<ObjectRef> globalObject(vm, object);
141 globalObject.SetWeak();
142 Local<ObjectRef> object1 = ObjectRef::New(vm);
143 Global<ObjectRef> globalObject1(vm, object1);
144 globalObject1.SetWeak();
145 vm->CollectGarbage(TriggerGCType::YOUNG_GC);
146 vm->CollectGarbage(TriggerGCType::OLD_GC);
147 globalObject.FreeGlobalHandleAddr();
148 }
149
ThreadCheck(const EcmaVM * vm)150 void ThreadCheck(const EcmaVM *vm)
151 {
152 EXPECT_TRUE(vm->GetJSThread()->GetThreadId() != JSThread::GetCurrentThreadId());
153 }
154
CheckReject(JsiRuntimeCallInfo * info)155 void CheckReject(JsiRuntimeCallInfo *info)
156 {
157 ASSERT_EQ(info->GetArgsNumber(), 1U);
158 Local<JSValueRef> reason = info->GetCallArgRef(0);
159 ASSERT_TRUE(reason->IsString());
160 ASSERT_EQ(Local<StringRef>(reason)->ToString(), "Reject");
161 }
162
RejectCallback(JsiRuntimeCallInfo * info)163 Local<JSValueRef> RejectCallback(JsiRuntimeCallInfo *info)
164 {
165 LocalScope scope(info->GetVM());
166 CheckReject(info);
167 return JSValueRef::Undefined(info->GetVM());
168 }
169
170 /**
171 * @tc.number: ffi_interface_api_105
172 * @tc.name: JSValueRef_IsGeneratorObject
173 * @tc.desc: Determine if it is a Generator generator object
174 * @tc.type: FUNC
175 * @tc.require: parameter
176 */
HWTEST_F_L0(JSNApiTests,JSValueRef_IsGeneratorObject)177 HWTEST_F_L0(JSNApiTests, JSValueRef_IsGeneratorObject)
178 {
179 LocalScope scope(vm_);
180 ObjectFactory *factory = vm_->GetFactory();
181 auto env = vm_->GetGlobalEnv();
182 JSHandle<JSTaggedValue> genFunc = env->GetGeneratorFunctionFunction();
183 JSHandle<JSGeneratorObject> genObjHandleVal = factory->NewJSGeneratorObject(genFunc);
184 JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetGeneratorFunctionClass());
185 JSHandle<JSFunction> generatorFunc = JSHandle<JSFunction>::Cast(factory->NewJSObject(hclass));
186 JSFunction::InitializeJSFunction(thread_, generatorFunc, FunctionKind::GENERATOR_FUNCTION);
187 JSHandle<GeneratorContext> generatorContext = factory->NewGeneratorContext();
188 generatorContext->SetMethod(thread_, generatorFunc.GetTaggedValue());
189 JSHandle<JSTaggedValue> generatorContextVal = JSHandle<JSTaggedValue>::Cast(generatorContext);
190 genObjHandleVal->SetGeneratorContext(thread_, generatorContextVal.GetTaggedValue());
191 JSHandle<JSTaggedValue> genObjTagHandleVal = JSHandle<JSTaggedValue>::Cast(genObjHandleVal);
192 Local<JSValueRef> genObjectRef = JSNApiHelper::ToLocal<GeneratorObjectRef>(genObjTagHandleVal);
193 ASSERT_TRUE(genObjectRef->IsGeneratorObject());
194 }
195
JSObjectTestCreate(JSThread * thread)196 static JSFunction *JSObjectTestCreate(JSThread *thread)
197 {
198 EcmaVM *ecmaVM = thread->GetEcmaVM();
199 JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
200 return globalEnv->GetObjectFunction().GetObject<JSFunction>();
201 }
202
203 /**
204 * @tc.number: ffi_interface_api_106
205 * @tc.name: JSValueRef_IsProxy
206 * @tc.desc: Determine if it is the type of proxy
207 * @tc.type: FUNC
208 * @tc.require: parameter
209 */
HWTEST_F_L0(JSNApiTests,JSValueRef_IsProxy)210 HWTEST_F_L0(JSNApiTests, JSValueRef_IsProxy)
211 {
212 LocalScope scope(vm_);
213 JSHandle<JSTaggedValue> hclass(thread_, JSObjectTestCreate(thread_));
214 JSHandle<JSTaggedValue> targetHandle(
215 thread_->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(hclass), hclass));
216
217 JSHandle<JSTaggedValue> key(thread_->GetEcmaVM()->GetFactory()->NewFromASCII("x"));
218 JSHandle<JSTaggedValue> value(thread_, JSTaggedValue(1));
219 JSObject::SetProperty(thread_, targetHandle, key, value);
220 EXPECT_EQ(JSObject::GetProperty(thread_, targetHandle, key).GetValue()->GetInt(), 1);
221
222 JSHandle<JSTaggedValue> handlerHandle(
223 thread_->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(hclass), hclass));
224 EXPECT_TRUE(handlerHandle->IsECMAObject());
225
226 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread_, targetHandle, handlerHandle);
227 EXPECT_TRUE(*proxyHandle != nullptr);
228
229 EXPECT_EQ(JSProxy::GetProperty(thread_, proxyHandle, key).GetValue()->GetInt(), 1);
230 PropertyDescriptor desc(thread_);
231 JSProxy::GetOwnProperty(thread_, proxyHandle, key, desc);
232 EXPECT_EQ(desc.GetValue()->GetInt(), 1);
233 Local<JSValueRef> proxy = JSNApiHelper::ToLocal<JSProxy>(JSHandle<JSTaggedValue>(proxyHandle));
234 ASSERT_TRUE(proxy->IsProxy());
235 }
236
237 /**
238 * @tc.number: ffi_interface_api_107
239 * @tc.name: BufferRef_New_ByteLength
240 * @tc.desc:
241 * New:Create a buffer and specify the length size
242 * ByteLength:Returns the length of the buffer
243 * @tc.type: FUNC
244 * @tc.require: parameter
245 */
HWTEST_F_L0(JSNApiTests,BufferRef_New_ByteLength)246 HWTEST_F_L0(JSNApiTests, BufferRef_New_ByteLength)
247 {
248 LocalScope scope(vm_);
249 int32_t length = 10;
250 Local<BufferRef> buffer = BufferRef::New(vm_, length);
251 ASSERT_TRUE(buffer->IsBuffer());
252 EXPECT_EQ(buffer->ByteLength(vm_), length);
253 }
254
255 /**
256 * @tc.number: ffi_interface_api_108
257 * @tc.name: BufferRef_New_ByteLength_GetBuffer
258 * @tc.desc:
259 * New:Create a buffer and specify the length size
260 * ByteLength:Returns the length of the buffer
261 * GetBuffer:Return buffer pointer
262 * @tc.type: FUNC
263 * @tc.require: parameter
264 */
HWTEST_F_L0(JSNApiTests,BufferRef_New_ByteLength_GetBuffer)265 HWTEST_F_L0(JSNApiTests, BufferRef_New_ByteLength_GetBuffer)
266 {
267 LocalScope scope(vm_);
268 int32_t length = 10;
269 Local<BufferRef> buffer = BufferRef::New(vm_, length);
270 ASSERT_TRUE(buffer->IsBuffer());
271 EXPECT_EQ(buffer->ByteLength(vm_), 10U);
272 ASSERT_NE(buffer->GetBuffer(), nullptr);
273 }
274
275 /**
276 * @tc.number: ffi_interface_api_109
277 * @tc.name: BufferRef_New01_ByteLength_GetBuffer_BufferToStringCallback
278 * @tc.desc:
279 * BufferToStringCallback:Implement callback when calling ToString (vm) mode in buffer
280 * @tc.type: FUNC
281 * @tc.require: parameter
282 */
HWTEST_F_L0(JSNApiTests,BufferRef_New01_ByteLength_GetBuffer_BufferToStringCallback)283 HWTEST_F_L0(JSNApiTests, BufferRef_New01_ByteLength_GetBuffer_BufferToStringCallback)
284 {
285 LocalScope scope(vm_);
286 static bool isFree = false;
287 struct Data {
288 int32_t length;
289 };
290 const int32_t length = 15;
291 Deleter deleter = [](void *buffer, void *data) -> void {
292 delete[] reinterpret_cast<uint8_t *>(buffer);
293 Data *currentData = reinterpret_cast<Data *>(data);
294 delete currentData;
295 isFree = true;
296 };
297 isFree = false;
298 uint8_t *buffer = new uint8_t[length]();
299 Data *data = new Data();
300 data->length = length;
301 Local<BufferRef> bufferRef = BufferRef::New(vm_, buffer, length, deleter, data);
302 ASSERT_TRUE(bufferRef->IsBuffer());
303 ASSERT_TRUE(bufferRef->IsBuffer());
304 EXPECT_EQ(bufferRef->ByteLength(vm_), 15U);
305 Local<StringRef> bufferStr = bufferRef->ToString(vm_);
306 ASSERT_TRUE(bufferStr->IsString());
307 }
308
309 /**
310 * @tc.number: ffi_interface_api_110
311 * @tc.name: LocalScope_LocalScope
312 * @tc.desc: Build Escape LocalScope sub Vm scope
313 * @tc.type: FUNC
314 * @tc.require: parameter
315 */
HWTEST_F_L0(JSNApiTests,LocalScope_LocalScope)316 HWTEST_F_L0(JSNApiTests, LocalScope_LocalScope)
317 {
318 EscapeLocalScope scope(vm_);
319 LocalScope *perScope = nullptr;
320 perScope = &scope;
321 ASSERT_TRUE(perScope != nullptr);
322 }
323
324 /**
325 * @tc.number: ffi_interface_api_111
326 * @tc.name: JSNApi_CreateJSContext_SwitchCurrentContext_DestroyJSContext
327 * @tc.desc:
328 * CreateJSContext:Create Context Object Pointer
329 * SwitchCurrentContext:Record Update Context Object
330 * DestroyJSContext:Delete Context Object
331 * @tc.type: FUNC
332 * @tc.require: parameter
333 */
HWTEST_F_L0(JSNApiTests,JSNApi_SwitchCurrentContext_DestroyJSContext)334 HWTEST_F_L0(JSNApiTests, JSNApi_SwitchCurrentContext_DestroyJSContext)
335 {
336 LocalScope scope(vm_);
337 EXPECT_EQ(vm_->GetJSThread()->GetEcmaContexts().size(), 1);
338 EcmaContext *context = JSNApi::CreateJSContext(vm_);
339 GTEST_LOG_(WARNING) << "context test =" << context;
340 EXPECT_EQ(vm_->GetJSThread()->GetEcmaContexts().size(), 2);
341 EcmaContext *context1 = JSNApi::CreateJSContext(vm_);
342 EXPECT_EQ(vm_->GetJSThread()->GetEcmaContexts().size(), 3);
343 JSNApi::SwitchCurrentContext(vm_, context1);
344 EXPECT_EQ(vm_->GetJSThread()->GetEcmaContexts().size(), 3);
345 JSNApi::DestroyJSContext(vm_, context1);
346 EXPECT_EQ(vm_->GetJSThread()->GetEcmaContexts().size(), 2);
347 }
348
349 /**
350 * @tc.number: ffi_interface_api_112
351 * @tc.name: JSNApi_CreateJSVM_DestroyJSVM
352 * @tc.desc: Create/delete JSVM
353 * @tc.type: FUNC
354 * @tc.require: parameter
355 */
HWTEST_F_L0(JSNApiTests,JSNApi_CreateJSVM_DestroyJSVM)356 HWTEST_F_L0(JSNApiTests, JSNApi_CreateJSVM_DestroyJSVM)
357 {
358 LocalScope scope(vm_);
359 EcmaVM *vm1_ = nullptr;
360 RuntimeOption option;
361 option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
362 vm1_ = JSNApi::CreateJSVM(option);
363 ASSERT_TRUE(vm1_ != nullptr) << "Cannot create Runtime";
364 vm1_->SetEnableForceGC(true);
365 vm1_->SetEnableForceGC(false);
366 JSNApi::DestroyJSVM(vm1_);
367 }
368
369 /**
370 * @tc.number: ffi_interface_api_114
371 * @tc.name: JSNApi_GetUncaughtException
372 * @tc.desc: Get uncaught exceptions
373 * @tc.type: FUNC
374 * @tc.require: parameter
375 */
HWTEST_F_L0(JSNApiTests,JSNApi_GetUncaughtException)376 HWTEST_F_L0(JSNApiTests, JSNApi_GetUncaughtException)
377 {
378 LocalScope scope(vm_);
379 Local<ObjectRef> excep = JSNApi::GetUncaughtException(vm_);
380 ASSERT_TRUE(excep.IsNull()) << "CreateInstance occur Exception";
381 }
382
FuncRefNewCallbackForTest(JsiRuntimeCallInfo * info)383 Local<JSValueRef> FuncRefNewCallbackForTest(JsiRuntimeCallInfo *info)
384 {
385 GTEST_LOG_(INFO) << "runing FuncRefNewCallbackForTest";
386 EscapeLocalScope scope(info->GetVM());
387 return scope.Escape(ArrayRef::New(info->GetVM(), info->GetArgsNumber()));
388 }
389
390 /**
391 * @tc.number: ffi_interface_api_115
392 * @tc.name: ObjectRef_SetAccessorProperty
393 * @tc.desc:
394 * SetAccessorProperty:Set AccessorPro Properties
395 * GetVM:Obtain environment information for runtime calls
396 * LocalScope:Build Vm Scope
397 * @tc.type: FUNC
398 * @tc.require: parameter
399 */
HWTEST_F_L0(JSNApiTests,ObjectRef_SetAccessorProperty_JsiRuntimeCallInfo_GetVM)400 HWTEST_F_L0(JSNApiTests, ObjectRef_SetAccessorProperty_JsiRuntimeCallInfo_GetVM)
401 {
402 LocalScope scope(vm_);
403 Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, "TestKey");
404 FunctionForRef nativeFunc = FuncRefNewCallbackForTest;
405 Local<FunctionRef> getter = FunctionRef::New(vm_, nativeFunc);
406 Local<FunctionRef> setter = FunctionRef::New(vm_, nativeFunc);
407 Local<ObjectRef> object = ObjectRef::New(vm_);
408 ASSERT_TRUE(object->SetAccessorProperty(vm_, key, getter, setter));
409 }
410
411 /*
412 * @tc.number: ffi_interface_api_116
413 * @tc.name: JSNApi_IsBoolean
414 * @tc.desc: Judge whether obj is a boolean type
415 * @tc.type: FUNC
416 * @tc.require: parameter
417 */
HWTEST_F_L0(JSNApiTests,IsBoolean)418 HWTEST_F_L0(JSNApiTests, IsBoolean)
419 {
420 LocalScope scope(vm_);
421 char16_t utf16[] = u"This is a char16 array";
422 int size = sizeof(utf16);
423 Local<StringRef> obj = StringRef::NewFromUtf16(vm_, utf16, size);
424 ASSERT_FALSE(obj->IsBoolean());
425 }
426
427 /*
428 * @tc.number: ffi_interface_api_117
429 * @tc.name: JSNApi_IsNULL
430 * @tc.desc: Judge whether obj is a null type
431 * @tc.type: FUNC
432 * @tc.require: parameter
433 */
HWTEST_F_L0(JSNApiTests,IsNULL)434 HWTEST_F_L0(JSNApiTests, IsNULL)
435 {
436 LocalScope scope(vm_);
437 char16_t utf16[] = u"This is a char16 array";
438 int size = sizeof(utf16);
439 Local<StringRef> obj = StringRef::NewFromUtf16(vm_, utf16, size);
440 ASSERT_FALSE(obj->IsNull());
441 }
442
443 /*
444 * @tc.number: ffi_interface_api_118
445 * @tc.name: JSNApi_GetTime
446 * @tc.desc: This function is to catch time
447 * @tc.type: FUNC
448 * @tc.require: parameter
449 */
HWTEST_F_L0(JSNApiTests,GetTime)450 HWTEST_F_L0(JSNApiTests, GetTime)
451 {
452 LocalScope scope(vm_);
453 const double time = 14.29;
454 Local<DateRef> date = DateRef::New(vm_, time);
455 ASSERT_EQ(date->GetTime(), time);
456 }
457
458 /*
459 * @tc.number: ffi_interface_api_119
460 * @tc.name: JSNApi_IsDetach
461 * @tc.desc: Judge whether arraybuffer is detached
462 * @tc.type: FUNC
463 * @tc.require: parameter
464 */
HWTEST_F_L0(JSNApiTests,IsDetach)465 HWTEST_F_L0(JSNApiTests, IsDetach)
466 {
467 LocalScope scope(vm_);
468 const int32_t length = 33;
469 Local<ArrayBufferRef> arraybuffer = ArrayBufferRef::New(vm_, length);
470 ASSERT_FALSE(arraybuffer->IsDetach());
471 }
472
473 /*
474 * @tc.number: ffi_interface_api_120
475 * @tc.name: JSNApi_Detach
476 * @tc.desc: This function is to detach arraybuffer
477 * @tc.type: FUNC
478 * @tc.require: parameter
479 */
HWTEST_F_L0(JSNApiTests,Detach)480 HWTEST_F_L0(JSNApiTests, Detach)
481 {
482 LocalScope scope(vm_);
483 const int32_t length = 33;
484 Local<ArrayBufferRef> arraybuffer = ArrayBufferRef::New(vm_, length);
485 arraybuffer->Detach(vm_);
486 }
487
488 /*
489 * @tc.number: ffi_interface_api_121
490 * @tc.name: JSNApi_New1
491 * @tc.desc: create a obj that is a arraybuffer type
492 * @tc.type: FUNC
493 * @tc.require: parameter
494 */
HWTEST_F_L0(JSNApiTests,New1)495 HWTEST_F_L0(JSNApiTests, New1)
496 {
497 LocalScope scope(vm_);
498 const int32_t length = 33;
499 Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
500 ASSERT_TRUE(arrayBuffer->IsArrayBuffer());
501 ASSERT_EQ(arrayBuffer->ByteLength(vm_), length);
502 ASSERT_NE(arrayBuffer->GetBuffer(), nullptr);
503 }
504
505 /*
506 * @tc.number: ffi_interface_api_122
507 * @tc.name: JSNApi_New1
508 * @tc.desc: create a obj that is a arraybuffer type
509 * @tc.type: FUNC
510 * @tc.require: parameter
511 */
HWTEST_F_L0(JSNApiTests,New2)512 HWTEST_F_L0(JSNApiTests, New2)
513 {
514 static bool isFree = false;
515 struct Data {
516 int32_t length;
517 };
518 const int32_t length = 15;
519 Data *data = new Data();
520 data->length = length;
521 Deleter deleter = [](void *buffer, void *data) -> void {
522 delete[] reinterpret_cast<uint8_t *>(buffer);
523 Data *currentData = reinterpret_cast<Data *>(data);
524 ASSERT_EQ(currentData->length, 15); // 5 : size of arguments
525 delete currentData;
526 isFree = true;
527 };
528 {
529 LocalScope scope(vm_);
530 uint8_t *buffer = new uint8_t[length]();
531 Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, buffer, length, deleter, data);
532 ASSERT_TRUE(arrayBuffer->IsArrayBuffer());
533 ASSERT_EQ(arrayBuffer->ByteLength(vm_), length);
534 ASSERT_EQ(arrayBuffer->GetBuffer(), buffer);
535 }
536 }
537
538 /*
539 * @tc.number: ffi_interface_api_123
540 * @tc.name: JSNApi_Bytelength
541 * @tc.desc: capture bytelength of arraybuffer
542 * @tc.type: FUNC
543 * @tc.require: parameter
544 */
HWTEST_F_L0(JSNApiTests,Bytelength)545 HWTEST_F_L0(JSNApiTests, Bytelength)
546 {
547 LocalScope scope(vm_);
548 const int32_t length = 33;
549 Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
550 ASSERT_EQ(arrayBuffer->ByteLength(vm_), length);
551 }
552
553 /*
554 * @tc.number: ffi_interface_api_124
555 * @tc.name: JSNApi_GetBuffer
556 * @tc.desc: capture buffer of arraybuffer
557 * @tc.type: FUNC
558 * @tc.require: parameter
559 */
HWTEST_F_L0(JSNApiTests,GetBuffer)560 HWTEST_F_L0(JSNApiTests, GetBuffer)
561 {
562 LocalScope scope(vm_);
563 const int32_t length = 33;
564 Local<ArrayBufferRef> arraybuffer = ArrayBufferRef::New(vm_, length);
565 ASSERT_NE(arraybuffer->GetBuffer(), nullptr);
566 }
567
568 /*
569 * @tc.number: ffi_interface_api_125
570 * @tc.name: JSNApi_Is32Arraytest
571 * @tc.desc: judge whether obj is a int32array type,
572 * judge whether obj is a uint32array type,
573 * judge whether obj is a float32array type,
574 * judge whether obj is a float64array type,
575 * @tc.type: FUNC
576 * @tc.require: parameter
577 */
HWTEST_F_L0(JSNApiTests,Is32Arraytest)578 HWTEST_F_L0(JSNApiTests, Is32Arraytest)
579 {
580 LocalScope scope(vm_);
581 char16_t utf16[] = u"This is a char16 array";
582 int size = sizeof(utf16);
583 Local<StringRef> obj = StringRef::NewFromUtf16(vm_, utf16, size);
584 ASSERT_FALSE(obj->IsInt32Array());
585 ASSERT_FALSE(obj->IsUint32Array());
586 ASSERT_FALSE(obj->IsFloat32Array());
587 ASSERT_FALSE(obj->IsFloat64Array());
588 }
589
590 /*
591 * @tc.number: ffi_interface_api_126
592 * @tc.name: JSNApi_SynchronizVMInfo
593 * @tc.desc: capture synchronous info of vm
594 * @tc.type: FUNC
595 * @tc.require: parameter
596 */
HWTEST_F_L0(JSNApiTests,SynchronizVMInfo)597 HWTEST_F_L0(JSNApiTests, SynchronizVMInfo)
598 {
599 LocalScope scope(vm_);
600 JSRuntimeOptions option;
601 EcmaVM *hostVM = JSNApi::CreateEcmaVM(option);
602 LocalScope scope2(hostVM);
603 JSNApi::SynchronizVMInfo(vm_, hostVM);
604 }
605
606 /*
607 * @tc.number: ffi_interface_api_127
608 * @tc.name: JSNApi_IsProfiling
609 * @tc.desc: judge whether vm is profiling
610 * @tc.type: FUNC
611 * @tc.require: parameter
612 */
HWTEST_F_L0(JSNApiTests,IsProfiling)613 HWTEST_F_L0(JSNApiTests, IsProfiling)
614 {
615 LocalScope scope(vm_);
616 ASSERT_FALSE(JSNApi::IsProfiling(vm_));
617 }
618
619 /*
620 * @tc.number: ffi_interface_api_128
621 * @tc.name: JSNApi_SetProfilerState
622 * @tc.desc: This function is to set state of profiler
623 * @tc.type: FUNC
624 * @tc.require: parameter
625 */
HWTEST_F_L0(JSNApiTests,SetProfilerState)626 HWTEST_F_L0(JSNApiTests, SetProfilerState)
627 {
628 bool value = true;
629 bool value2 = false;
630 LocalScope scope(vm_);
631 JSNApi::SetProfilerState(vm_, value);
632 JSNApi::SetProfilerState(vm_, value2);
633 }
634
635 /*
636 * @tc.number: ffi_interface_api_129
637 * @tc.name: JSNApi_SetLoop
638 * @tc.desc: This function is to set loop
639 * @tc.type: FUNC
640 * @tc.require: parameter
641 */
HWTEST_F_L0(JSNApiTests,SetLoop)642 HWTEST_F_L0(JSNApiTests, SetLoop)
643 {
644 LocalScope scope(vm_);
645 void *data = reinterpret_cast<void *>(BuiltinsFunction::FunctionPrototypeInvokeSelf);
646 JSNApi::SetLoop(vm_, data);
647 }
648
649 /*
650 * @tc.number: ffi_interface_api_130
651 * @tc.name: JSNApi_SetHostPromiseRejectionTracker
652 * @tc.desc: This function is to set host promise rejection about tracker
653 * @tc.type: FUNC
654 * @tc.require: parameter
655 */
HWTEST_F_L0(JSNApiTests,SetHostPromiseRejectionTracker)656 HWTEST_F_L0(JSNApiTests, SetHostPromiseRejectionTracker)
657 {
658 LocalScope scope(vm_);
659 void *data = reinterpret_cast<void *>(BuiltinsFunction::FunctionPrototypeInvokeSelf);
660 void *cb = reinterpret_cast<void *>(BuiltinsFunction::FunctionPrototypeInvokeSelf);
661 JSNApi::SetHostPromiseRejectionTracker(vm_, cb, data);
662 }
663
664 /*
665 * @tc.number: ffi_interface_api_131
666 * @tc.name: JSNApi_SetHostResolveBufferTracker
667 * @tc.desc: This function is to set host resolve buffer about tracker
668 * @tc.type: FUNC
669 * @tc.require: parameter
670 */
HWTEST_F_L0(JSNApiTests,SetHostResolveBufferTracker)671 HWTEST_F_L0(JSNApiTests, SetHostResolveBufferTracker)
672 {
673 LocalScope scope(vm_);
674 JSNApi::SetHostResolveBufferTracker(vm_, [&](std::string, uint8_t **, size_t *) -> bool { return true; });
675 }
676
677 /*
678 * @tc.number: ffi_interface_api_132
679 * @tc.name: JSNApi_SetUnloadNativeModuleCallback
680 * @tc.desc: This function is to set unload native module about callback
681 * @tc.type: FUNC
682 * @tc.require: parameter
683 */
HWTEST_F_L0(JSNApiTests,SetUnloadNativeModuleCallback)684 HWTEST_F_L0(JSNApiTests, SetUnloadNativeModuleCallback)
685 {
686 LocalScope scope(vm_);
687 JSNApi::SetUnloadNativeModuleCallback(vm_, [&](const std::string &) -> bool { return true; });
688 }
689
690 /*
691 * @tc.number: ffi_interface_api_133
692 * @tc.name: JSNApi_SetNativePtrGetter
693 * @tc.desc: This function is to set a native pointer about getter
694 * @tc.type: FUNC
695 * @tc.require: parameter
696 */
HWTEST_F_L0(JSNApiTests,SetNativePtrGetter)697 HWTEST_F_L0(JSNApiTests, SetNativePtrGetter)
698 {
699 LocalScope scope(vm_);
700 void *cb = reinterpret_cast<void *>(BuiltinsFunction::FunctionPrototypeInvokeSelf);
701 JSNApi::SetNativePtrGetter(vm_, cb);
702 }
703
704 /*
705 * @tc.number: ffi_interface_api_134
706 * @tc.name: JSNApi_PreFork
707 * @tc.desc: This function is to set prefork
708 * @tc.type: FUNC
709 * @tc.require: parameter
710 */
HWTEST_F_L0(JSNApiTests,PreFork)711 HWTEST_F_L0(JSNApiTests, PreFork)
712 {
713 LocalScope scope(vm_);
714 JSNApi::PreFork(vm_);
715 }
716
717 /*
718 * @tc.number: ffi_interface_api_135
719 * @tc.name: JSNApi_PostFork
720 * @tc.desc: This function is to set postfork
721 * @tc.type: FUNC
722 * @tc.require: parameter
723 */
HWTEST_F_L0(JSNApiTests,PostFork)724 HWTEST_F_L0(JSNApiTests, PostFork)
725 {
726 RuntimeOption option;
727 LocalScope scope(vm_);
728 JSNApi::PostFork(vm_, option);
729 }
730
731
732 /*
733 * @tc.number: ffi_interface_api_136
734 * @tc.name: JSNApi_NewFromUtf8
735 * @tc.desc: create a newfromutf8 object
736 * @tc.type: FUNC
737 * @tc.require: parameter
738 */
HWTEST_F_L0(JSNApiTests,NewFromUtf8)739 HWTEST_F_L0(JSNApiTests, NewFromUtf8)
740 {
741 LocalScope scope(vm_);
742 char utf8[] = "hello world!";
743 int length = strlen(utf8);
744 Local<StringRef> result = StringRef::NewFromUtf8(vm_, utf8, length);
745 ASSERT_EQ(result->Utf8Length(vm_), length + 1);
746 }
747
748 /*
749 * @tc.number: ffi_interface_api_137
750 * @tc.name: JSNApi_NewFromUtf16
751 * @tc.desc: create a newfromutf16 object
752 * @tc.type: FUNC
753 * @tc.require: parameter
754 */
HWTEST_F_L0(JSNApiTests,NewFromUtf16)755 HWTEST_F_L0(JSNApiTests, NewFromUtf16)
756 {
757 LocalScope scope(vm_);
758 char16_t utf16[] = u"This is a char16 array";
759 int length = sizeof(utf16);
760 Local<StringRef> result = StringRef::NewFromUtf16(vm_, utf16, length);
761 ASSERT_EQ(result->Length(), length);
762 }
763
764 /*
765 * @tc.number: ffi_interface_api_138
766 * @tc.name: JSNApi_GetNapiWrapperString
767 * @tc.desc: This function is to get a napiwrapper string
768 * @tc.type: FUNC
769 * @tc.require: parameter
770 */
HWTEST_F_L0(JSNApiTests,GetNapiWrapperString)771 HWTEST_F_L0(JSNApiTests, GetNapiWrapperString)
772 {
773 LocalScope scope(vm_);
774 Local<StringRef> result = StringRef::GetNapiWrapperString(vm_);
775 ASSERT_TRUE(result->IsString());
776 }
777
778 /*
779 * @tc.number: ffi_interface_api_139
780 * @tc.name: JSNApi_JSExecutionScope
781 * @tc.desc: This function is to construct a object of jsexecutionscope
782 * @tc.type: FUNC
783 * @tc.require: parameter
784 */
HWTEST_F_L0(JSNApiTests,JSExecutionScope)785 HWTEST_F_L0(JSNApiTests, JSExecutionScope)
786 {
787 LocalScope scope(vm_);
788 JSExecutionScope jsexecutionScope(vm_);
789 }
790
791 /*
792 * @tc.number: ffi_interface_api_140
793 * @tc.name: WeakMapRef_GetSize_GetTotalElements_GetKey_GetValue
794 * @tc.desc: This function is to set a weakmap and capture it's size ,
795 * key, value and total elements
796 * @tc.type: FUNC
797 * @tc.require: parameter
798 */
HWTEST_F_L0(JSNApiTests,WeakMapRef_GetSize_GetTotalElements_GetKey_GetValue)799 HWTEST_F_L0(JSNApiTests, WeakMapRef_GetSize_GetTotalElements_GetKey_GetValue)
800 {
801 LocalScope scope(vm_);
802 JSThread *thread = vm_->GetJSThread();
803 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
804 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
805 JSHandle<JSTaggedValue> constructor = env->GetBuiltinsWeakMapFunction();
806 JSHandle<JSWeakMap> weakMap =
807 JSHandle<JSWeakMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
808 JSHandle<LinkedHashMap> hashMap = LinkedHashMap::Create(thread);
809 weakMap->SetLinkedMap(thread, hashMap);
810 JSHandle<JSTaggedValue> weakMapTag = JSHandle<JSTaggedValue>::Cast(weakMap);
811
812 Local<WeakMapRef> map = JSNApiHelper::ToLocal<WeakMapRef>(weakMapTag);
813 EXPECT_TRUE(map->IsWeakMap());
814 JSHandle<JSTaggedValue> value(factory->NewFromASCII("value"));
815 JSHandle<JSTaggedValue> key(factory->NewFromASCII("key"));
816 JSWeakMap::Set(thread, weakMap, key, value);
817 int32_t num = map->GetSize();
818 int32_t num1 = map->GetTotalElements();
819 ASSERT_EQ(num, 1);
820 ASSERT_EQ(num1, 1);
821 Local<JSValueRef> res1 = map->GetKey(vm_, 0);
822 ASSERT_EQ(res1->ToString(vm_)->ToString(), "key");
823 Local<JSValueRef> res2 = map->GetValue(vm_, 0);
824 ASSERT_EQ(res2->ToString(vm_)->ToString(), "value");
825 }
826
827 /*
828 * @tc.number: ffi_interface_api_141
829 * @tc.name: JSNApi_ IsAGJA
830 * @tc.desc: This function is to judge whether object is a argumentsobject or
831 * is a generatorfunction or is a asyncfunction
832 * @tc.type: FUNC
833 * @tc.require: parameter
834 */
HWTEST_F_L0(JSNApiTests,IsAGJA)835 HWTEST_F_L0(JSNApiTests, IsAGJA)
836 {
837 LocalScope scope(vm_);
838 char16_t utf16[] = u"This is a char16 array";
839 int size = sizeof(utf16);
840 Local<StringRef> obj = StringRef::NewFromUtf16(vm_, utf16, size);
841 ASSERT_FALSE(obj->IsArgumentsObject());
842 ASSERT_FALSE(obj->IsGeneratorFunction());
843 ASSERT_FALSE(obj->IsAsyncFunction());
844 }
845
846 /**
847 * @tc.number: ffi_interface_api_143
848 * @tc.name: Int32Array
849 * @tc.desc: Catch exceptions correctly
850 * @tc.type: FUNC
851 * @tc.require: parameter
852 */
HWTEST_F_L0(JSNApiTests,HasCaught)853 HWTEST_F_L0(JSNApiTests, HasCaught)
854 {
855 LocalScope scope(vm_);
856 Local<StringRef> message = StringRef::NewFromUtf8(vm_, "ErrorTest");
857 Local<JSValueRef> error = Exception::Error(vm_, message);
858 ASSERT_TRUE(error->IsError());
859 JSNApi::ThrowException(vm_, error);
860 TryCatch tryCatch(vm_);
861 ASSERT_TRUE(tryCatch.HasCaught());
862 vm_->GetJSThread()->ClearException();
863 ASSERT_FALSE(tryCatch.HasCaught());
864 }
865
866 /**
867 * @tc.number: ffi_interface_api_144
868 * @tc.name: Int32Array
869 * @tc.desc: Rethrow the exception
870 * @tc.type: FUNC
871 * @tc.require: parameter
872 */
HWTEST_F_L0(JSNApiTests,Rethrow)873 HWTEST_F_L0(JSNApiTests, Rethrow)
874 {
875 LocalScope scope(vm_);
876 TryCatch tryCatch(vm_);
877 tryCatch.Rethrow();
878 ASSERT_TRUE(tryCatch.getrethrow_());
879 }
880
881 /**
882 * @tc.number: ffi_interface_api_145
883 * @tc.name: Int32Array
884 * @tc.desc: Clear caught exceptions
885 * @tc.type: FUNC
886 * @tc.require: parameter
887 */
HWTEST_F_L0(JSNApiTests,GetAndClearException)888 HWTEST_F_L0(JSNApiTests, GetAndClearException)
889 {
890 LocalScope scope(vm_);
891 Local<StringRef> message = StringRef::NewFromUtf8(vm_, "ErrorTest");
892 Local<JSValueRef> error = Exception::Error(vm_, message);
893 ASSERT_TRUE(error->IsError());
894 JSNApi::ThrowException(vm_, error);
895 ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
896 TryCatch tryCatch(vm_);
897 tryCatch.GetAndClearException();
898 EXPECT_FALSE(vm_->GetJSThread()->HasPendingException());
899 }
900 /**
901 * @tc.number: ffi_interface_api_146
902 * @tc.name: Int32Array
903 * @tc.desc: trycatch class construction
904 * @tc.type: FUNC
905 * @tc.require: parameter
906 */
HWTEST_F_L0(JSNApiTests,TryCatch)907 HWTEST_F_L0(JSNApiTests, TryCatch)
908 {
909 LocalScope scope(vm_);
910 TryCatch tryCatch(vm_);
911 EXPECT_EQ(tryCatch.getrethrow_(), false);
912 EXPECT_FALSE(tryCatch.HasCaught());
913 tryCatch.Rethrow();
914 EXPECT_EQ(tryCatch.getrethrow_(), true);
915 }
916
HWTEST_F_L0(JSNApiTests,NewObjectWithProperties)917 HWTEST_F_L0(JSNApiTests, NewObjectWithProperties)
918 {
919 LocalScope scope(vm_);
920 Local<JSValueRef> keys[1100];
921 Local<JSValueRef> values[1100];
922 PropertyAttribute attributes[1100];
923 for (int i = 0; i < 1100; i += (i < 80 ? (i < 10 ? 1 : 80) : 1000)) {
924 for (int j = 0; j <= i; ++j) {
925 std::string strKey("TestKey" + std::to_string(i) + "_" + std::to_string(j));
926 std::string strVal("TestValue" + std::to_string(i) + "_" + std::to_string(j));
927 keys[j] = StringRef::NewFromUtf8(vm_, strKey.c_str());
928 values[j] = StringRef::NewFromUtf8(vm_, strVal.c_str());
929 attributes[j] = PropertyAttribute(values[j], true, true, true);
930 }
931 Local<ObjectRef> object = ObjectRef::NewWithProperties(vm_, i + 1, keys, attributes);
932 for (int j = 0; j <= i; ++j) {
933 Local<JSValueRef> value1 = object->Get(vm_, keys[j]);
934 EXPECT_TRUE(values[j]->IsStrictEquals(vm_, value1));
935 }
936 JSHandle<JSObject> obj(JSNApiHelper::ToJSHandle(object));
937 uint32_t propCount = obj->GetJSHClass()->NumberOfProps();
938 if (i + 1 > PropertyAttributes::MAX_FAST_PROPS_CAPACITY) {
939 EXPECT_TRUE(propCount == 0);
940 EXPECT_TRUE(obj->GetJSHClass()->IsDictionaryMode());
941 JSHandle<NameDictionary> dict(thread_, obj->GetProperties());
942 EXPECT_TRUE(dict->EntriesCount() == i + 1);
943 } else {
944 EXPECT_TRUE(propCount == i + 1);
945 int32_t in_idx = obj->GetJSHClass()->GetNextInlinedPropsIndex();
946 int32_t nonin_idx = obj->GetJSHClass()->GetNextNonInlinedPropsIndex();
947 if (i + 1 < JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS) {
948 EXPECT_TRUE(in_idx == i + 1);
949 EXPECT_TRUE(nonin_idx == -1);
950 } else {
951 EXPECT_TRUE(in_idx == -1);
952 EXPECT_TRUE(nonin_idx == 0);
953 }
954 }
955 }
956 }
957
HWTEST_F_L0(JSNApiTests,NewObjectWithPropertieNonPureStringKey)958 HWTEST_F_L0(JSNApiTests, NewObjectWithPropertieNonPureStringKey)
959 {
960 LocalScope scope(vm_);
961 Local<JSValueRef> keys[] = {
962 StringRef::NewFromUtf8(vm_, "1"),
963 };
964 Local<JSValueRef> values[] = {
965 StringRef::NewFromUtf8(vm_, "value1"),
966 };
967 PropertyAttribute attributes[] = {
968 PropertyAttribute(values[0], true, true, true),
969 };
970 Local<ObjectRef> object = ObjectRef::NewWithProperties(vm_, 1, keys, attributes);
971 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(object);
972 EXPECT_TRUE(obj.GetTaggedValue() == JSTaggedValue::Undefined());
973 thread_->ClearException();
974 }
975
HWTEST_F_L0(JSNApiTests,NewObjectWithPropertiesDuplicate)976 HWTEST_F_L0(JSNApiTests, NewObjectWithPropertiesDuplicate)
977 {
978 LocalScope scope(vm_);
979 Local<JSValueRef> keys[] = {
980 StringRef::NewFromUtf8(vm_, "duplicateKey"),
981 StringRef::NewFromUtf8(vm_, "simpleKey"),
982 StringRef::NewFromUtf8(vm_, "duplicateKey"),
983 };
984 Local<JSValueRef> values[] = {
985 StringRef::NewFromUtf8(vm_, "value1"),
986 StringRef::NewFromUtf8(vm_, "value2"),
987 StringRef::NewFromUtf8(vm_, "value3"),
988 };
989 PropertyAttribute attributes[] = {
990 PropertyAttribute(values[0], true, true, true),
991 PropertyAttribute(values[1], true, true, true),
992 PropertyAttribute(values[2], true, true, true),
993 };
994 Local<ObjectRef> object = ObjectRef::NewWithProperties(vm_, 3, keys, attributes);
995 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(object);
996 EXPECT_TRUE(obj.GetTaggedValue() == JSTaggedValue::Undefined());
997 thread_->ClearException();
998 }
999
HWTEST_F_L0(JSNApiTests,NewObjectWithNamedProperties)1000 HWTEST_F_L0(JSNApiTests, NewObjectWithNamedProperties)
1001 {
1002 LocalScope scope(vm_);
1003 const char *keys[1100];
1004 std::string strKeys[1100];
1005 Local<JSValueRef> values[1100];
1006 for (int i = 0; i < 1100; i += (i < 80 ? (i < 10 ? 1 : 80) : 1000)) {
1007 for (int j = 0; j <= i; ++j) {
1008 strKeys[j] = "TestKey" + std::to_string(i) + "_" + std::to_string(j);
1009 std::string strVal("TestValue" + std::to_string(i) + "_" + std::to_string(j));
1010 keys[j] = const_cast<char *>(strKeys[j].c_str());
1011 values[j] = StringRef::NewFromUtf8(vm_, strVal.c_str());
1012 }
1013 Local<ObjectRef> object = ObjectRef::NewWithNamedProperties(vm_, i + 1, keys, values);
1014 for (int j = 0; j <= i; ++j) {
1015 Local<JSValueRef> value1 = object->Get(vm_, StringRef::NewFromUtf8(vm_, keys[j]));
1016 EXPECT_TRUE(values[j]->IsStrictEquals(vm_, value1));
1017 }
1018 JSHandle<JSObject> obj(JSNApiHelper::ToJSHandle(object));
1019 uint32_t propCount = obj->GetJSHClass()->NumberOfProps();
1020 if (i + 1 > PropertyAttributes::MAX_FAST_PROPS_CAPACITY) {
1021 EXPECT_TRUE(propCount == 0);
1022 EXPECT_TRUE(obj->GetJSHClass()->IsDictionaryMode());
1023 JSHandle<NameDictionary> dict(thread_, obj->GetProperties());
1024 EXPECT_TRUE(dict->EntriesCount() == i + 1);
1025 } else {
1026 EXPECT_TRUE(propCount == i + 1);
1027 int32_t in_idx = obj->GetJSHClass()->GetNextInlinedPropsIndex();
1028 int32_t nonin_idx = obj->GetJSHClass()->GetNextNonInlinedPropsIndex();
1029 if (i + 1 < JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS) {
1030 EXPECT_TRUE(in_idx == i + 1);
1031 EXPECT_TRUE(nonin_idx == -1);
1032 } else {
1033 EXPECT_TRUE(in_idx == -1);
1034 EXPECT_TRUE(nonin_idx == 0);
1035 }
1036 }
1037 }
1038 }
1039
HWTEST_F_L0(JSNApiTests,NewObjectWithNamedPropertieNonPureStringKey)1040 HWTEST_F_L0(JSNApiTests, NewObjectWithNamedPropertieNonPureStringKey)
1041 {
1042 LocalScope scope(vm_);
1043 const char *keys[] = {
1044 "1",
1045 };
1046 Local<JSValueRef> values[] = {
1047 StringRef::NewFromUtf8(vm_, "value1"),
1048 };
1049 Local<ObjectRef> object = ObjectRef::NewWithNamedProperties(vm_, 2, keys, values);
1050 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(object);
1051 EXPECT_TRUE(obj.GetTaggedValue() == JSTaggedValue::Undefined());
1052 thread_->ClearException();
1053 }
1054
HWTEST_F_L0(JSNApiTests,NewObjectWithNamedPropertiesDuplicate)1055 HWTEST_F_L0(JSNApiTests, NewObjectWithNamedPropertiesDuplicate)
1056 {
1057 LocalScope scope(vm_);
1058 const char *keys[] = {
1059 "duplicateKey",
1060 "simpleKey",
1061 "duplicateKey",
1062 };
1063 Local<JSValueRef> values[] = {
1064 StringRef::NewFromUtf8(vm_, "value1"),
1065 StringRef::NewFromUtf8(vm_, "value2"),
1066 StringRef::NewFromUtf8(vm_, "value3"),
1067 };
1068 Local<ObjectRef> object = ObjectRef::NewWithNamedProperties(vm_, 3, keys, values);
1069 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(object);
1070 EXPECT_TRUE(obj.GetTaggedValue() == JSTaggedValue::Undefined());
1071 thread_->ClearException();
1072 }
1073 } // namespace panda::test