• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "ecmascript/napi/jsnapi_helper.h"
17 #include "ecmascript/tests/test_helper.h"
18 #include "ecmascript/serializer/base_deserializer.h"
19 #include "ecmascript/serializer/value_serializer.h"
20 #include "gtest/gtest.h"
21 #include "jsnapi_expo.h"
22 
23 using namespace panda::ecmascript;
24 
25 namespace panda::test {
26 class JSNApiTests : public testing::Test {
27 public:
SetUpTestCase()28     static void SetUpTestCase()
29     {
30         GTEST_LOG_(INFO) << "SetUpTestCase";
31     }
32 
TearDownTestCase()33     static void TearDownTestCase()
34     {
35         GTEST_LOG_(INFO) << "TearDownCase";
36     }
37 
SetUp()38     void SetUp() override
39     {
40         RuntimeOption option;
41         option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
42         vm_ = JSNApi::CreateJSVM(option);
43         ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
44         thread_ = vm_->GetJSThread();
45         vm_->SetEnableForceGC(true);
46         thread_->ManagedCodeBegin();
47         staticKey = StringRef::NewFromUtf8(vm_, "static");
48         nonStaticKey = StringRef::NewFromUtf8(vm_, "nonStatic");
49         instanceKey = StringRef::NewFromUtf8(vm_, "instance");
50         getterSetterKey = StringRef::NewFromUtf8(vm_, "getterSetter");
51         invalidKey = StringRef::NewFromUtf8(vm_, "invalid");
52     }
53 
TearDown()54     void TearDown() override
55     {
56         thread_->ManagedCodeEnd();
57         vm_->SetEnableForceGC(false);
58         JSNApi::DestroyJSVM(vm_);
59     }
60 
61     template <typename T>
TestNumberRef(T val,TaggedType expected)62     void TestNumberRef(T val, TaggedType expected)
63     {
64         LocalScope scope(vm_);
65         Local<NumberRef> obj = NumberRef::New(vm_, val);
66         ASSERT_TRUE(obj->IsNumber());
67         JSTaggedType res = JSNApiHelper::ToJSTaggedValue(*obj).GetRawData();
68         ASSERT_EQ(res, expected);
69         if constexpr (std::is_floating_point_v<T>) {
70             if (std::isnan(val)) {
71                 ASSERT_TRUE(std::isnan(obj->Value()));
72             } else {
73                 ASSERT_EQ(obj->Value(), val);
74             }
75         } else if constexpr (sizeof(T) >= sizeof(int32_t)) {
76             ASSERT_EQ(obj->IntegerValue(vm_), val);
77         } else if constexpr (std::is_signed_v<T>) {
78             ASSERT_EQ(obj->Int32Value(vm_), val);
79         } else {
80             ASSERT_EQ(obj->Uint32Value(vm_), val);
81         }
82     }
83 
ConvertDouble(double val)84     TaggedType ConvertDouble(double val)
85     {
86         return base::bit_cast<JSTaggedType>(val) + JSTaggedValue::DOUBLE_ENCODE_OFFSET;
87     }
88 
89 protected:
90     JSThread *thread_ = nullptr;
91     EcmaVM *vm_ = nullptr;
92     Local<StringRef> staticKey;
93     Local<StringRef> nonStaticKey;
94     Local<StringRef> instanceKey;
95     Local<StringRef> getterSetterKey;
96     Local<StringRef> invalidKey;
97 };
98 
FunctionCallback(JsiRuntimeCallInfo * info)99 panda::JSValueRef FunctionCallback(JsiRuntimeCallInfo *info)
100 {
101     EcmaVM *vm = info->GetVM();
102     Local<JSValueRef> jsThisRef = info->GetThisRef();
103     Local<ObjectRef> thisRef = jsThisRef->ToObject(vm);
104     return **thisRef;
105 }
106 
GetNewSendableClassFunction(EcmaVM * vm,Local<FunctionRef> parent,bool isDict=false,bool duplicated=false,bool isParent=false)107 Local<FunctionRef> GetNewSendableClassFunction(
108     EcmaVM *vm, Local<FunctionRef> parent, bool isDict = false, bool duplicated = false, bool isParent = false)
109 {
110     FunctionRef::SendablePropertiesInfos infos;
111 
112     if (isDict) {
113         uint32_t maxInline = std::max(JSSharedFunction::MAX_INLINE, JSSharedObject::MAX_INLINE);
114         for (uint32_t i = 0; i < maxInline; ++i) {
115             Local<StringRef> tempStr = StringRef::NewFromUtf8(vm, std::to_string(i).c_str());
116             infos.instancePropertiesInfo.keys.push_back(tempStr);
117             infos.instancePropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
118             infos.instancePropertiesInfo.attributes.push_back(PropertyAttribute(tempStr, true, true, true));
119             infos.staticPropertiesInfo.keys.push_back(tempStr);
120             infos.staticPropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
121             infos.staticPropertiesInfo.attributes.push_back(PropertyAttribute(tempStr, true, true, true));
122             infos.nonStaticPropertiesInfo.keys.push_back(tempStr);
123             infos.nonStaticPropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
124             infos.nonStaticPropertiesInfo.attributes.push_back(PropertyAttribute(tempStr, true, true, true));
125         }
126     }
127 
128     std::string instanceKey = "instance";
129     std::string staticKey = "static";
130     std::string nonStaticKey = "nonStatic";
131 
132     if (isParent) {
133         instanceKey = "parentInstance";
134         staticKey = "parentStatic";
135         nonStaticKey = "parentNonStatic";
136     }
137 
138     Local<StringRef> instanceStr = StringRef::NewFromUtf8(vm, instanceKey.c_str());
139     infos.instancePropertiesInfo.keys.push_back(instanceStr);
140     infos.instancePropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
141     infos.instancePropertiesInfo.attributes.push_back(PropertyAttribute(instanceStr, true, true, true));
142 
143     Local<StringRef> staticStr = StringRef::NewFromUtf8(vm, staticKey.c_str());
144     infos.staticPropertiesInfo.keys.push_back(staticStr);
145     infos.staticPropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
146     infos.staticPropertiesInfo.attributes.push_back(PropertyAttribute(staticStr, true, true, true));
147 
148     Local<StringRef> nonStaticStr = StringRef::NewFromUtf8(vm, nonStaticKey.c_str());
149     infos.nonStaticPropertiesInfo.keys.push_back(nonStaticStr);
150     infos.nonStaticPropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
151     infos.nonStaticPropertiesInfo.attributes.push_back(PropertyAttribute(nonStaticStr, true, true, true));
152 
153     if (duplicated) {
154         Local<StringRef> duplicatedKey = StringRef::NewFromUtf8(vm, "parentInstance");
155         Local<NumberRef> duplicatedValue = NumberRef::New(vm, 0);
156         infos.instancePropertiesInfo.keys.push_back(duplicatedKey);
157         infos.instancePropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
158         infos.instancePropertiesInfo.attributes.push_back(PropertyAttribute(duplicatedValue, true, true, true));
159     }
160 
161     Local<FunctionRef> constructor = FunctionRef::NewSendableClassFunction(
162         vm, FunctionCallback, nullptr, nullptr, StringRef::NewFromUtf8(vm, "name"), infos, parent);
163 
164     return constructor;
165 }
166 
HWTEST_F_L0(JSNApiTests,NewSendableClassFunction)167 HWTEST_F_L0(JSNApiTests, NewSendableClassFunction)
168 {
169     LocalScope scope(vm_);
170     Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_));
171 
172     ASSERT_EQ("name", constructor->GetName(vm_)->ToString(vm_));
173     ASSERT_TRUE(constructor->IsFunction(vm_));
174     JSHandle<JSTaggedValue> jsConstructor = JSNApiHelper::ToJSHandle(constructor);
175     ASSERT_TRUE(jsConstructor->IsClassConstructor());
176 
177     Local<JSValueRef> functionPrototype = constructor->GetFunctionPrototype(vm_);
178     ASSERT_TRUE(functionPrototype->IsObject(vm_));
179     JSHandle<JSTaggedValue> jsPrototype = JSNApiHelper::ToJSHandle(functionPrototype);
180     ASSERT_TRUE(jsPrototype->IsClassPrototype());
181 
182     const GlobalEnvConstants *globalConst = thread_->GlobalConstants();
183     auto prototype = JSTaggedValue::GetProperty(
184                          thread_, JSNApiHelper::ToJSHandle(constructor), globalConst->GetHandledPrototypeString())
185                          .GetValue();
186     ASSERT_FALSE(prototype->IsUndefined());
187     ASSERT_TRUE(prototype->IsECMAObject() || prototype->IsNull());
188 }
189 
HWTEST_F_L0(JSNApiTests,NewSendableClassFunctionProperties)190 HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionProperties)
191 {
192     LocalScope scope(vm_);
193     Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_));
194     Local<ObjectRef> prototype = constructor->GetFunctionPrototype(vm_);
195 
196     ASSERT_EQ("static", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString(vm_));
197     ASSERT_EQ("nonStatic", prototype->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
198     ASSERT_EQ("undefined", constructor->Get(vm_, invalidKey)->ToString(vm_)->ToString(vm_));
199     ASSERT_EQ("undefined", prototype->Get(vm_, invalidKey)->ToString(vm_)->ToString(vm_));
200 
201     // set static property on constructor
202     constructor->Set(vm_, staticKey, StringRef::NewFromUtf8(vm_, "static0"));
203     ASSERT_EQ("static0", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString(vm_));
204 
205     // set non static property on prototype
206     prototype->Set(vm_, nonStaticKey, StringRef::NewFromUtf8(vm_, "nonStatic0"));
207     ASSERT_EQ("nonStatic0", prototype->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
208 
209     // set invalid property on constructor
210     ASSERT_FALSE(vm_->GetJSThread()->HasPendingException());
211     constructor->Set(vm_, invalidKey, StringRef::NewFromUtf8(vm_, "invalid"));
212     ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
213     JSNApi::GetAndClearUncaughtException(vm_);
214     ASSERT_EQ("undefined", constructor->Get(vm_, invalidKey)->ToString(vm_)->ToString(vm_));
215 
216     // set invalid property on prototype
217     ASSERT_FALSE(vm_->GetJSThread()->HasPendingException());
218     prototype->Set(vm_, invalidKey, StringRef::NewFromUtf8(vm_, "invalid"));
219     ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
220     JSNApi::GetAndClearUncaughtException(vm_);
221     ASSERT_EQ("undefined", prototype->Get(vm_, invalidKey)->ToString(vm_)->ToString(vm_));
222 }
223 
HWTEST_F_L0(JSNApiTests,NewSendableClassFunctionDictProperties)224 HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionDictProperties)
225 {
226     LocalScope scope(vm_);
227     Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_), true);
228     Local<ObjectRef> prototype = constructor->GetFunctionPrototype(vm_);
229 
230     ASSERT_EQ("static", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString(vm_));
231     ASSERT_EQ("nonStatic", prototype->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
232     ASSERT_EQ("undefined", constructor->Get(vm_, invalidKey)->ToString(vm_)->ToString(vm_));
233     ASSERT_EQ("undefined", prototype->Get(vm_, invalidKey)->ToString(vm_)->ToString(vm_));
234 
235     // set static property on constructor
236     constructor->Set(vm_, staticKey, StringRef::NewFromUtf8(vm_, "static0"));
237     ASSERT_EQ("static0", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString(vm_));
238 
239     // set non static property on prototype
240     prototype->Set(vm_, nonStaticKey, StringRef::NewFromUtf8(vm_, "nonStatic0"));
241     ASSERT_EQ("nonStatic0", prototype->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
242 
243     // set invalid property on constructor
244     ASSERT_FALSE(vm_->GetJSThread()->HasPendingException());
245     constructor->Set(vm_, invalidKey, StringRef::NewFromUtf8(vm_, "invalid"));
246     ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
247     JSNApi::GetAndClearUncaughtException(vm_);
248     ASSERT_EQ("undefined", constructor->Get(vm_, invalidKey)->ToString(vm_)->ToString(vm_));
249 
250     // set invalid property on prototype
251     ASSERT_FALSE(vm_->GetJSThread()->HasPendingException());
252     prototype->Set(vm_, invalidKey, StringRef::NewFromUtf8(vm_, "invalid"));
253     ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
254     JSNApi::GetAndClearUncaughtException(vm_);
255     ASSERT_EQ("undefined", prototype->Get(vm_, invalidKey)->ToString(vm_)->ToString(vm_));
256 }
257 
HWTEST_F_L0(JSNApiTests,NewSendableClassFunctionInstance)258 HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionInstance)
259 {
260     LocalScope scope(vm_);
261     Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_));
262     Local<ObjectRef> obj = constructor->Constructor(vm_, nullptr, 0);
263     Local<ObjectRef> obj0 = constructor->Constructor(vm_, nullptr, 0);
264 
265     ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(constructor)));
266     ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj0), JSNApiHelper::ToJSHandle(constructor)));
267 
268     // set instance property
269     ASSERT_EQ("undefined", obj->Get(vm_, instanceKey)->ToString(vm_)->ToString(vm_));
270     ASSERT_EQ("undefined", obj0->Get(vm_, instanceKey)->ToString(vm_)->ToString(vm_));
271     obj->Set(vm_, instanceKey, StringRef::NewFromUtf8(vm_, "instance"));
272     ASSERT_EQ("instance", obj->Get(vm_, instanceKey)->ToString(vm_)->ToString(vm_));
273     ASSERT_EQ("undefined", obj0->Get(vm_, instanceKey)->ToString(vm_)->ToString(vm_));
274 
275     // set non static property on prototype and get from instance
276     ASSERT_EQ("nonStatic", obj->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
277     ASSERT_EQ("nonStatic", obj0->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
278     Local<ObjectRef> prototype = obj->GetPrototype(vm_);
279     prototype->Set(vm_, nonStaticKey, StringRef::NewFromUtf8(vm_, "nonStatic0"));
280     ASSERT_EQ("nonStatic0", obj->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
281     ASSERT_EQ("nonStatic0", obj0->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
282 
283     // set non static property on instance
284     ASSERT_FALSE(vm_->GetJSThread()->HasPendingException());
285     obj->Set(vm_, nonStaticKey, StringRef::NewFromUtf8(vm_, "nonStatic1"));
286     ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
287     JSNApi::GetAndClearUncaughtException(vm_);
288     ASSERT_EQ("nonStatic0", obj->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
289     ASSERT_EQ("nonStatic0", obj0->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
290 
291     // set invalid property on instance
292     ASSERT_EQ("undefined", obj->Get(vm_, invalidKey)->ToString(vm_)->ToString(vm_));
293     ASSERT_FALSE(vm_->GetJSThread()->HasPendingException());
294     obj->Set(vm_, invalidKey, StringRef::NewFromUtf8(vm_, "invalid"));
295     ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
296     JSNApi::GetAndClearUncaughtException(vm_);
297     ASSERT_EQ("undefined", obj->Get(vm_, invalidKey)->ToString(vm_)->ToString(vm_));
298 }
299 
HWTEST_F_L0(JSNApiTests,NewSendableClassFunctionDictInstance)300 HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionDictInstance)
301 {
302     LocalScope scope(vm_);
303     Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_), true);
304     Local<ObjectRef> obj = constructor->Constructor(vm_, nullptr, 0);
305     Local<ObjectRef> obj0 = constructor->Constructor(vm_, nullptr, 0);
306 
307     ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(constructor)));
308     ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj0), JSNApiHelper::ToJSHandle(constructor)));
309 
310     // set instance property
311     ASSERT_EQ("undefined", obj->Get(vm_, instanceKey)->ToString(vm_)->ToString(vm_));
312     ASSERT_EQ("undefined", obj0->Get(vm_, instanceKey)->ToString(vm_)->ToString(vm_));
313     obj->Set(vm_, instanceKey, StringRef::NewFromUtf8(vm_, "instance"));
314     ASSERT_EQ("instance", obj->Get(vm_, instanceKey)->ToString(vm_)->ToString(vm_));
315     ASSERT_EQ("undefined", obj0->Get(vm_, instanceKey)->ToString(vm_)->ToString(vm_));
316 
317     // set non static property on prototype and get from instance
318     ASSERT_EQ("nonStatic", obj->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
319     ASSERT_EQ("nonStatic", obj0->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
320     Local<ObjectRef> prototype = obj->GetPrototype(vm_);
321     prototype->Set(vm_, nonStaticKey, StringRef::NewFromUtf8(vm_, "nonStatic0"));
322     ASSERT_EQ("nonStatic0", obj->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
323     ASSERT_EQ("nonStatic0", obj0->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
324 
325     // set non static property on instance
326     ASSERT_FALSE(vm_->GetJSThread()->HasPendingException());
327     obj->Set(vm_, nonStaticKey, StringRef::NewFromUtf8(vm_, "nonStatic1"));
328     ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
329     JSNApi::GetAndClearUncaughtException(vm_);
330     ASSERT_EQ("nonStatic0", obj->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
331     ASSERT_EQ("nonStatic0", obj0->Get(vm_, nonStaticKey)->ToString(vm_)->ToString(vm_));
332 
333     // set invalid property on instance
334     ASSERT_EQ("undefined", obj->Get(vm_, invalidKey)->ToString(vm_)->ToString(vm_));
335     ASSERT_FALSE(vm_->GetJSThread()->HasPendingException());
336     obj->Set(vm_, invalidKey, StringRef::NewFromUtf8(vm_, "invalid"));
337     ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
338     JSNApi::GetAndClearUncaughtException(vm_);
339     ASSERT_EQ("undefined", obj->Get(vm_, invalidKey)->ToString(vm_)->ToString(vm_));
340 }
341 
HWTEST_F_L0(JSNApiTests,NewSendableClassFunctionInherit)342 HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionInherit)
343 {
344     LocalScope scope(vm_);
345     Local<FunctionRef> parent = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_), false, false, true);
346     Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, parent);
347     Local<ObjectRef> obj = constructor->Constructor(vm_, nullptr, 0);
348 
349     ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(constructor)));
350     ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(parent)));
351 
352     // set parent instance property on instance
353     Local<StringRef> parentInstanceKey = StringRef::NewFromUtf8(vm_, "parentInstance");
354     ASSERT_EQ("undefined", obj->Get(vm_, parentInstanceKey)->ToString(vm_)->ToString(vm_));
355     obj->Set(vm_, parentInstanceKey, StringRef::NewFromUtf8(vm_, "parentInstance"));
356     ASSERT_EQ("parentInstance", obj->Get(vm_, parentInstanceKey)->ToString(vm_)->ToString(vm_));
357 
358     // get parent static property from constructor
359     Local<StringRef> parentStaticKey = StringRef::NewFromUtf8(vm_, "parentStatic");
360     ASSERT_EQ("parentStatic", constructor->Get(vm_, parentStaticKey)->ToString(vm_)->ToString(vm_));
361 
362     // get parent non static property form instance
363     Local<StringRef> parentNonStaticKey = StringRef::NewFromUtf8(vm_, "parentNonStatic");
364     ASSERT_EQ("parentNonStatic", obj->Get(vm_, parentNonStaticKey)->ToString(vm_)->ToString(vm_));
365 }
366 
HWTEST_F_L0(JSNApiTests,NewSendableClassFunctionDictInherit)367 HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionDictInherit)
368 {
369     LocalScope scope(vm_);
370     Local<FunctionRef> parent = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_), true, false, true);
371     Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, parent);
372     Local<ObjectRef> obj = constructor->Constructor(vm_, nullptr, 0);
373 
374     ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(constructor)));
375     ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(parent)));
376 
377     // set parent instance property on instance
378     Local<StringRef> parentInstanceKey = StringRef::NewFromUtf8(vm_, "parentInstance");
379     ASSERT_EQ("undefined", obj->Get(vm_, parentInstanceKey)->ToString(vm_)->ToString(vm_));
380     obj->Set(vm_, parentInstanceKey, StringRef::NewFromUtf8(vm_, "parentInstance"));
381     ASSERT_EQ("parentInstance", obj->Get(vm_, parentInstanceKey)->ToString(vm_)->ToString(vm_));
382 
383     // get parent static property from constructor
384     Local<StringRef> parentStaticKey = StringRef::NewFromUtf8(vm_, "parentStatic");
385     ASSERT_EQ("parentStatic", constructor->Get(vm_, parentStaticKey)->ToString(vm_)->ToString(vm_));
386 
387     // get parent non static property form instance
388     Local<StringRef> parentNonStaticKey = StringRef::NewFromUtf8(vm_, "parentNonStatic");
389     ASSERT_EQ("parentNonStatic", obj->Get(vm_, parentNonStaticKey)->ToString(vm_)->ToString(vm_));
390 }
391 
HWTEST_F_L0(JSNApiTests,NewSendableClassFunctionInheritWithDuplicatedKey)392 HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionInheritWithDuplicatedKey)
393 {
394     LocalScope scope(vm_);
395     Local<FunctionRef> parent = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_), false, false, true);
396     Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, parent, false, true);
397     Local<ObjectRef> obj = constructor->Constructor(vm_, nullptr, 0);
398 
399     ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(constructor)));
400     ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(parent)));
401 
402     // set duplicated instance property on instance
403     Local<StringRef> parentInstanceKey = StringRef::NewFromUtf8(vm_, "parentInstance");
404     ASSERT_EQ("undefined", obj->Get(vm_, parentInstanceKey)->ToString(vm_)->ToString(vm_));
405     obj->Set(vm_, parentInstanceKey, NumberRef::New(vm_, 0));
406     EXPECT_TRUE(NumberRef::New(vm_, 0)->IsStrictEquals(vm_, obj->Get(vm_, parentInstanceKey)));
407 }
408 
HWTEST_F_L0(JSNApiTests,NewSendable)409 HWTEST_F_L0(JSNApiTests, NewSendable)
410 {
411     LocalScope scope(vm_);
412     Local<FunctionRef> func = FunctionRef::NewSendable(
413         vm_,
414         [](JsiRuntimeCallInfo *runtimeInfo) -> JSValueRef {
415             EcmaVM *vm = runtimeInfo->GetVM();
416             LocalScope scope(vm);
417             return **StringRef::NewFromUtf8(vm, "funcResult");
418         },
419         nullptr);
420     Local<JSValueRef> res = func->Call(vm_, JSValueRef::Undefined(vm_), nullptr, 0);
421     ASSERT_EQ("funcResult", res->ToString(vm_)->ToString(vm_));
422 }
423 
HWTEST_F_L0(JSNApiTests,NewSendableClassFunctionFunction)424 HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionFunction)
425 {
426     LocalScope scope(vm_);
427 
428     FunctionRef::SendablePropertiesInfos infos;
429 
430     Local<FunctionRef> func = FunctionRef::NewSendable(
431         vm_,
432         [](JsiRuntimeCallInfo *runtimeInfo) -> JSValueRef {
433             EcmaVM *vm = runtimeInfo->GetVM();
434             LocalScope scope(vm);
435             return **StringRef::NewFromUtf8(vm, "funcResult");
436         },
437         nullptr);
438     infos.staticPropertiesInfo.keys.push_back(staticKey);
439     infos.staticPropertiesInfo.types.push_back(FunctionRef::SendableType::OBJECT);
440     infos.staticPropertiesInfo.attributes.push_back(PropertyAttribute(func, true, true, true));
441 
442     Local<FunctionRef> constructor = FunctionRef::NewSendableClassFunction(
443         vm_, FunctionCallback, nullptr, nullptr, StringRef::NewFromUtf8(vm_, "name"), infos, JSValueRef::Hole(vm_));
444 
445     Local<FunctionRef> staticValue = constructor->Get(vm_, staticKey);
446     ASSERT_TRUE(staticValue->IsFunction(vm_));
447     Local<JSValueRef> res = staticValue->Call(vm_, JSValueRef::Undefined(vm_), nullptr, 0);
448     ASSERT_EQ("funcResult", res->ToString(vm_)->ToString(vm_));
449 }
450 
HWTEST_F_L0(JSNApiTests,NewSendableClassFunctionGetterSetter)451 HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionGetterSetter)
452 {
453     LocalScope scope(vm_);
454 
455     FunctionRef::SendablePropertiesInfos infos;
456 
457     Local<StringRef> getterSetter = StringRef::NewFromUtf8(vm_, "getterSetter");
458     infos.staticPropertiesInfo.keys.push_back(getterSetter);
459     infos.staticPropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
460     infos.staticPropertiesInfo.attributes.push_back(PropertyAttribute(getterSetter, true, true, true));
461     Local<FunctionRef> staticGetter = FunctionRef::NewSendable(
462         vm_,
463         [](JsiRuntimeCallInfo *info) -> JSValueRef {
464             Local<JSValueRef> value = info->GetThisRef();
465             Local<ObjectRef> obj = value->ToObject(info->GetVM());
466             Local<JSValueRef> temp = obj->Get(info->GetVM(), StringRef::NewFromUtf8(info->GetVM(), "getterSetter"));
467             return **temp->ToString(info->GetVM());
468         },
469         nullptr);
470     Local<FunctionRef> staticSetter = FunctionRef::NewSendable(
471         vm_,
472         [](JsiRuntimeCallInfo *info) -> JSValueRef {
473             Local<JSValueRef> arg = info->GetCallArgRef(0);
474             Local<JSValueRef> value = info->GetThisRef();
475             Local<ObjectRef> obj = value->ToObject(info->GetVM());
476             obj->Set(info->GetVM(), StringRef::NewFromUtf8(info->GetVM(), "getterSetter"), arg);
477             return **JSValueRef::Undefined(info->GetVM());
478         },
479         nullptr);
480     Local<JSValueRef> staticValue = panda::ObjectRef::CreateSendableAccessorData(vm_, staticGetter, staticSetter);
481     infos.staticPropertiesInfo.keys.push_back(staticKey);
482     infos.staticPropertiesInfo.types.push_back(FunctionRef::SendableType::OBJECT);
483     infos.staticPropertiesInfo.attributes.push_back(PropertyAttribute(staticValue, true, true, true));
484 
485     Local<FunctionRef> constructor = FunctionRef::NewSendableClassFunction(
486         vm_, FunctionCallback, nullptr, nullptr, StringRef::NewFromUtf8(vm_, "name"), infos, JSValueRef::Hole(vm_));
487 
488     ASSERT_EQ("getterSetter", constructor->Get(vm_, getterSetter)->ToString(vm_)->ToString(vm_));
489     ASSERT_EQ("getterSetter", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString(vm_));
490     constructor->Set(vm_, staticKey, StringRef::NewFromUtf8(vm_, "getterSetter0"));
491     ASSERT_EQ("getterSetter0", constructor->Get(vm_, getterSetter)->ToString(vm_)->ToString(vm_));
492     ASSERT_EQ("getterSetter0", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString(vm_));
493 }
494 
HWTEST_F_L0(JSNApiTests,NewSendableClassFunctionStringify)495 HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionStringify)
496 {
497     LocalScope scope(vm_);
498 
499     FunctionRef::SendablePropertiesInfos infos;
500     Local<FunctionRef> constructor = FunctionRef::NewSendableClassFunction(
501         vm_, FunctionCallback, nullptr, nullptr, StringRef::NewFromUtf8(vm_, "name"), infos, JSValueRef::Hole(vm_));
502 
503     Local<ObjectRef> obj = constructor->Constructor(vm_, nullptr, 0);
504     ASSERT_EQ("[object Object]", obj->ToString(vm_)->ToString(vm_));
505 }
506 
HWTEST_F_L0(JSNApiTests,NewObjectWithProperties)507 HWTEST_F_L0(JSNApiTests, NewObjectWithProperties)
508 {
509     LocalScope scope(vm_);
510 
511     FunctionRef::SendablePropertiesInfo info;
512     Local<StringRef> str = StringRef::NewFromUtf8(vm_, "str");
513     info.keys.push_back(str);
514     info.types.push_back(FunctionRef::SendableType::NONE);
515     info.attributes.push_back(PropertyAttribute(str, true, true, true));
516 
517     Local<ObjectRef> object = ObjectRef::NewSWithProperties(vm_, info);
518     Local<JSValueRef> value = object->Get(vm_, str);
519     EXPECT_TRUE(str->IsStrictEquals(vm_, value));
520 }
521 
HWTEST_F_L0(JSNApiTests,SendableMapRef_GetSize_GetTotalElements_Get_GetKey_GetValue)522 HWTEST_F_L0(JSNApiTests, SendableMapRef_GetSize_GetTotalElements_Get_GetKey_GetValue)
523 {
524     LocalScope scope(vm_);
525     Local<SendableMapRef> map = SendableMapRef::New(vm_);
526     Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, "TestKey");
527     Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, "TestValue");
528     map->Set(vm_, key, value);
529     Local<JSValueRef> res = map->Get(vm_, key);
530     ASSERT_EQ(res->ToString(vm_)->ToString(vm_), value->ToString(vm_)->ToString(vm_));
531     int32_t num = map->GetSize(vm_);
532     int32_t num1 = map->GetTotalElements(vm_);
533     ASSERT_EQ(num, 1);
534     ASSERT_EQ(num1, 1);
535     Local<JSValueRef> res1 = map->GetKey(vm_, 0);
536     ASSERT_EQ(res1->ToString(vm_)->ToString(vm_), key->ToString(vm_)->ToString(vm_));
537     Local<JSValueRef> res2 = map->GetValue(vm_, 0);
538     ASSERT_EQ(res2->ToString(vm_)->ToString(vm_), value->ToString(vm_)->ToString(vm_));
539 }
540 
HWTEST_F_L0(JSNApiTests,SendableSetRef_GetSize_GetTotalElements_GetValue)541 HWTEST_F_L0(JSNApiTests, SendableSetRef_GetSize_GetTotalElements_GetValue)
542 {
543     LocalScope scope(vm_);
544     Local<SendableSetRef> set = SendableSetRef::New(vm_);
545     EXPECT_TRUE(set->IsSharedSet(vm_));
546     Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, "TestValue");
547     set->Add(vm_, value);
548     int32_t num = set->GetSize(vm_);
549     int32_t num1 = set->GetTotalElements(vm_);
550     ASSERT_EQ(num, 1);
551     ASSERT_EQ(num1, 1);
552     Local<JSValueRef> res = set->GetValue(vm_, 0);
553     ASSERT_EQ(res->ToString(vm_)->ToString(vm_), value->ToString(vm_)->ToString(vm_));
554 }
555 
HWTEST_F_L0(JSNApiTests,SendableArrayRef_New_Len_GetVal_SetPro)556 HWTEST_F_L0(JSNApiTests, SendableArrayRef_New_Len_GetVal_SetPro)
557 {
558     LocalScope scope(vm_);
559     uint32_t length = 4;
560     Local<SendableArrayRef> array = SendableArrayRef::New(vm_, length);
561     EXPECT_TRUE(array->IsSharedArray(vm_));
562     Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, "TestValue");
563     uint32_t arrayLength = array->Length(vm_);
564     ASSERT_EQ(arrayLength, length);
565     Local<JSValueRef> res = array->GetValueAt(vm_, value, length);
566     uint32_t index = 1;
567     bool flag = array->SetProperty(vm_, res, index, value);
568     EXPECT_FALSE(flag);
569 }
570 
HWTEST_F_L0(JSNApiTests,WeakSetRef_New_add)571 HWTEST_F_L0(JSNApiTests, WeakSetRef_New_add)
572 {
573     LocalScope scope(vm_);
574     Local<WeakSetRef> object = WeakSetRef::New(vm_);
575     Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, "TestValue");
576     object->Add(vm_, value);
577     ASSERT_EQ(object->GetSize(vm_), 1);
578 }
579 
HWTEST_F_L0(JSNApiTests,JSValueRef_IsWeakMap_Set_Has)580 HWTEST_F_L0(JSNApiTests, JSValueRef_IsWeakMap_Set_Has)
581 {
582     LocalScope scope(vm_);
583     Local<WeakMapRef> map = WeakMapRef::New(vm_);
584     EXPECT_TRUE(map->IsWeakMap(vm_));
585     Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, "TestKey");
586     Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, "TestValue");
587     map->Set(vm_, key, value);
588     EXPECT_TRUE(map->Has(vm_, key));
589 }
590 
HWTEST_F_L0(JSNApiTests,SetRef_Add)591 HWTEST_F_L0(JSNApiTests, SetRef_Add)
592 {
593     LocalScope scope(vm_);
594     Local<SetRef> set = SetRef::New(vm_);
595     Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, "TestValue");
596     set->Add(vm_, value);
597     ASSERT_EQ(set->GetSize(vm_), 1);
598 }
599 
HWTEST_F_L0(JSNApiTests,Promise_GetPromiseResult)600 HWTEST_F_L0(JSNApiTests, Promise_GetPromiseResult)
601 {
602     LocalScope scope(vm_);
603     Local<PromiseCapabilityRef> capability = PromiseCapabilityRef::New(vm_);
604 
605     Local<PromiseRef> promise = capability->GetPromise(vm_);
606     promise->GetPromiseResult(vm_);
607     ASSERT_TRUE(promise->IsPromise(vm_));
608 }
609 
HWTEST_F_L0(JSNApiTests,Promise_GetPromiseState)610 HWTEST_F_L0(JSNApiTests, Promise_GetPromiseState)
611 {
612     LocalScope scope(vm_);
613     Local<PromiseCapabilityRef> cap = PromiseCapabilityRef::New(vm_);
614 
615     Local<PromiseRef> promise = cap->GetPromise(vm_);
616     promise->GetPromiseState(vm_);
617     ASSERT_TRUE(promise->IsPromise(vm_));
618 }
619 
HWTEST_F_L0(JSNApiTests,NapiHasOwnProperty)620 HWTEST_F_L0(JSNApiTests, NapiHasOwnProperty)
621 {
622     Local<ObjectRef> object = ObjectRef::New(vm_);
623     JSTaggedValue value(0);
624     JSHandle<JSTaggedValue> handle(thread_, value);
625     Local<JSValueRef> key = JSNApiHelper::ToLocal<JSValueRef>(handle);
626     const char* utf8Key = "TestKeyForOwnProperty";
627     Local<JSValueRef> key2 = StringRef::NewFromUtf8(vm_, utf8Key);
628     Local<JSValueRef> value2 = ObjectRef::New(vm_);
629     object->Set(vm_, key, value2);
630     object->Set(vm_, key2, value2);
631 
632     Local<JSValueRef> flag = JSNApi::NapiHasOwnProperty(vm_, reinterpret_cast<uintptr_t>(*object),
633                                                      reinterpret_cast<uintptr_t>(*key));
634     ASSERT_TRUE(flag->BooleaValue(vm_));
635     flag = JSNApi::NapiHasOwnProperty(vm_, reinterpret_cast<uintptr_t>(*object), reinterpret_cast<uintptr_t>(*key2));
636     ASSERT_TRUE(flag->BooleaValue(vm_));
637 
638     flag = JSNApi::NapiDeleteProperty(vm_, reinterpret_cast<uintptr_t>(*object), reinterpret_cast<uintptr_t>(*key));
639     ASSERT_TRUE(flag->BooleaValue(vm_));
640     flag = JSNApi::NapiDeleteProperty(vm_, reinterpret_cast<uintptr_t>(*object), reinterpret_cast<uintptr_t>(*key2));
641     ASSERT_TRUE(flag->BooleaValue(vm_));
642 
643     flag = JSNApi::NapiHasOwnProperty(vm_, reinterpret_cast<uintptr_t>(*object), reinterpret_cast<uintptr_t>(*key));
644     ASSERT_FALSE(flag->BooleaValue(vm_));
645     flag = JSNApi::NapiHasOwnProperty(vm_, reinterpret_cast<uintptr_t>(*object), reinterpret_cast<uintptr_t>(*key2));
646     ASSERT_FALSE(flag->BooleaValue(vm_));
647 }
648 
HWTEST_F_L0(JSNApiTests,DeleteSerializationData)649 HWTEST_F_L0(JSNApiTests, DeleteSerializationData)
650 {
651     LocalScope scope(vm_);
652     void *data = JSNApi::SerializeValue(vm_, StringRef::NewFromUtf8(vm_, "testData"),
653         StringRef::NewFromUtf8(vm_, "testTransfer"), JSValueRef::Undefined(vm_));
654     JSNApi::DeleteSerializationData(data);
655     ASSERT_EQ(reinterpret_cast<ecmascript::SerializeData *>(data), nullptr);
656 }
657 
HWTEST_F_L0(JSNApiTests,JSNApi_DeserializeValue_String)658 HWTEST_F_L0(JSNApiTests, JSNApi_DeserializeValue_String)
659 {
660     LocalScope scope(vm_);
661     vm_->SetEnableForceGC(true);
662     void *recoder = JSNApi::SerializeValue(vm_, StringRef::NewFromUtf8(vm_, "testData"), JSValueRef::Undefined(vm_),
663         JSValueRef::Undefined(vm_));
664     void *hint = nullptr;
665     Local<JSValueRef> local = JSNApi::DeserializeValue(vm_, recoder, hint);
666     ASSERT_FALSE(local->IsObject(vm_));
667 }
668 
HWTEST_F_L0(JSNApiTests,NewSharedFloat64Array)669 HWTEST_F_L0(JSNApiTests, NewSharedFloat64Array)
670 {
671     LocalScope scope(vm_);
672     Local<SendableArrayBufferRef> buffer = SendableArrayBufferRef::New(vm_, 57);
673     ASSERT_TRUE(buffer->IsSendableArrayBuffer(vm_));
674 
675     Local<SharedFloat64ArrayRef> typedArray = SharedFloat64ArrayRef::New(vm_, buffer, 8, 6);
676     ASSERT_TRUE(typedArray->IsJSSharedFloat64Array(vm_));
677     ASSERT_EQ(typedArray->ByteLength(vm_), 48U); // 48 : length of bytes
678     ASSERT_EQ(typedArray->ByteOffset(vm_), 8U);  // 8 : offset of byte
679     ASSERT_EQ(typedArray->ArrayLength(vm_), 6U); // 6 : length of array
680     ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), buffer->GetBuffer(vm_));
681 }
682 
HWTEST_F_L0(JSNApiTests,NewSharedBigInt64Array)683 HWTEST_F_L0(JSNApiTests, NewSharedBigInt64Array)
684 {
685     LocalScope scope(vm_);
686     Local<SendableArrayBufferRef> buffer = SendableArrayBufferRef::New(vm_, 57);
687     ASSERT_TRUE(buffer->IsSendableArrayBuffer(vm_));
688 
689     Local<SharedBigInt64ArrayRef> typedArray = SharedBigInt64ArrayRef::New(vm_, buffer, 8, 6);
690     ASSERT_TRUE(typedArray->IsJSSharedBigInt64Array(vm_));
691     ASSERT_EQ(typedArray->ByteLength(vm_), 48U); // 48 : length of bytes
692     ASSERT_EQ(typedArray->ByteOffset(vm_), 8U);  // 8 : offset of byte
693     ASSERT_EQ(typedArray->ArrayLength(vm_), 6U); // 6 : length of array
694     ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), buffer->GetBuffer(vm_));
695 }
696 
HWTEST_F_L0(JSNApiTests,NewSharedBigUint64Array)697 HWTEST_F_L0(JSNApiTests, NewSharedBigUint64Array)
698 {
699     LocalScope scope(vm_);
700     Local<SendableArrayBufferRef> buffer = SendableArrayBufferRef::New(vm_, 57);
701     ASSERT_TRUE(buffer->IsSendableArrayBuffer(vm_));
702 
703     Local<SharedBigUint64ArrayRef> typedArray = SharedBigUint64ArrayRef::New(vm_, buffer, 8, 6);
704     ASSERT_TRUE(typedArray->IsJSSharedBigUint64Array(vm_));
705     ASSERT_EQ(typedArray->ByteLength(vm_), 48U); // 48 : length of bytes
706     ASSERT_EQ(typedArray->ByteOffset(vm_), 8U);  // 8 : offset of byte
707     ASSERT_EQ(typedArray->ArrayLength(vm_), 6U); // 6 : length of array
708     ASSERT_EQ(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_), buffer->GetBuffer(vm_));
709 }
710 
711 }  // namespace panda::test
712