1 /*
2  * Copyright (c) 2021 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/builtins/builtins_function.h"
17 #include "ecmascript/builtins/builtins_boolean.h"
18 
19 #include "ecmascript/ecma_runtime_call_info.h"
20 #include "ecmascript/ecma_string.h"
21 #include "ecmascript/ecma_vm.h"
22 #include "ecmascript/global_env.h"
23 #include "ecmascript/js_array.h"
24 #include "ecmascript/js_function.h"
25 #include "ecmascript/js_object-inl.h"
26 
27 #include "ecmascript/object_factory.h"
28 #include "ecmascript/tagged_array-inl.h"
29 #include "ecmascript/tests/test_helper.h"
30 
31 using namespace panda::ecmascript;
32 using namespace panda::ecmascript::builtins;
33 using BuiltinsBase = panda::ecmascript::base::BuiltinsBase;
34 using JSArray = panda::ecmascript::JSArray;
35 
36 namespace panda::test {
37 class BuiltinsFunctionTest : public BaseTestWithScope<false> {
38 };
39 
40 // native function for test apply and call
TestFunctionApplyAndCall(EcmaRuntimeCallInfo *argv)41 JSTaggedValue TestFunctionApplyAndCall(EcmaRuntimeCallInfo *argv)
42 {
43     JSThread *thread = argv->GetThread();
44     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
45 
46     int result = 0;
47     for (uint32_t index = 0; index < argv->GetArgsNumber(); ++index) {
48         result += BuiltinsBase::GetCallArg(argv, index)->GetInt();
49     }
50     JSHandle<JSTaggedValue> thisValue(BuiltinsBase::GetThis(argv));
51 
52     JSTaggedValue testA = JSObject::GetProperty(thread, thisValue,
53         JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a"))).GetValue().GetTaggedValue();
54     JSTaggedValue testB = JSObject::GetProperty(thread, thisValue,
55         JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b"))).GetValue().GetTaggedValue();
56 
57     result = result + testA.GetInt() + testB.GetInt();
58     return BuiltinsBase::GetTaggedInt(result);
59 }
60 
61 enum class AlgorithmType {
62     PROTOTYPE_APPLY,
63     PROTOTYPE_BIND,
64     PROTOTYPE_CALL,
65 };
66 
FunctionAlgorithm(JSThread *thread, JSHandle<JSFunction> &thisArg, std::vector<JSTaggedValue> &args, uint32_t argLen, AlgorithmType type = AlgorithmType::PROTOTYPE_APPLY)67 static JSTaggedValue FunctionAlgorithm(JSThread *thread, JSHandle<JSFunction> &thisArg,
68                                        std::vector<JSTaggedValue> &args, uint32_t argLen,
69                                        AlgorithmType type = AlgorithmType::PROTOTYPE_APPLY)
70 {
71     auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), argLen);
72     ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined());
73     ecmaRuntimeCallInfos->SetThis(thisArg.GetTaggedValue());
74     for (size_t i = 0; i < args.size(); i++) {
75         ecmaRuntimeCallInfos->SetCallArg(i, args[i]);
76     }
77     auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos);
78     JSTaggedValue result;
79     switch (type) {
80         case AlgorithmType::PROTOTYPE_BIND:
81             result = BuiltinsFunction::FunctionPrototypeBind(ecmaRuntimeCallInfos);
82             break;
83         case AlgorithmType::PROTOTYPE_APPLY:
84             result = BuiltinsFunction::FunctionPrototypeApply(ecmaRuntimeCallInfos);
85             break;
86         case AlgorithmType::PROTOTYPE_CALL:
87             result = BuiltinsFunction::FunctionPrototypeCall(ecmaRuntimeCallInfos);
88             break;
89         default:
90             break;
91     }
92     TestHelper::TearDownFrame(thread, prev);
93     return result;
94 }
95 
96 // func.apply(thisArg)
HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeApply)97 HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeApply)
98 {
99     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
100 
101     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
102     // ecma 19.2.3.1: func
103     JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestFunctionApplyAndCall));
104 
105     // ecma 19.2.3.1: thisArg
106     JSHandle<JSObject> thisArg(thread, env->GetGlobalObject());
107     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
108                           JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")),
109                           JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)));
110     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
111                           JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")),
112                           JSHandle<JSTaggedValue>(thread, JSTaggedValue(2)));
113 
114     std::vector<JSTaggedValue> args{thisArg.GetTaggedValue()};
115     auto result = FunctionAlgorithm(thread, func, args, 6, AlgorithmType::PROTOTYPE_APPLY);
116 
117     ASSERT_EQ(result.GetRawData(), JSTaggedValue(3).GetRawData());
118 
119     JSObject::DeleteProperty(thread, (thisArg),
120                              JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")));
121     JSObject::DeleteProperty(thread, (thisArg),
122                              JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")));
123 }
124 
125 // func.apply(thisArg, argArray)
HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeApply1)126 HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeApply1)
127 {
128     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
129 
130     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
131 
132     // ecma 19.2.3.1: func
133     JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestFunctionApplyAndCall));
134 
135     // ecma 19.2.3.1: thisArg
136     JSHandle<JSObject> thisArg(thread, env->GetGlobalObject());
137     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
138                           JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")),
139                           JSHandle<JSTaggedValue>(thread, JSTaggedValue(10)));
140     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
141                           JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")),
142                           JSHandle<JSTaggedValue>(thread, JSTaggedValue(20)));
143 
144     // ecma 19.2.3.1: argArray
145     JSHandle<JSObject> array(JSArray::ArrayCreate(thread, JSTaggedNumber(2)));
146     PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(30)));
147     JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(0)), desc);
148 
149     PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(40)));
150     JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), desc1);
151 
152     std::vector<JSTaggedValue> args{thisArg.GetTaggedValue(), array.GetTaggedValue()};
153     auto result = FunctionAlgorithm(thread, func, args, 8, AlgorithmType::PROTOTYPE_APPLY);
154 
155     ASSERT_EQ(result.GetRawData(), JSTaggedValue(100).GetRawData());
156 
157     JSObject::DeleteProperty(thread, (thisArg),
158                              JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")));
159     JSObject::DeleteProperty(thread, (thisArg),
160                              JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")));
161 }
162 
163 // target.bind(thisArg)
HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind)164 HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind)
165 {
166     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
167 
168     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
169 
170     JSHandle<JSFunction> target = factory->NewJSFunction(env);
171     JSFunction::SetFunctionName(thread, JSHandle<JSFunctionBase>(target),
172                                 JSHandle<JSTaggedValue>(factory->NewFromASCII("target")),
173                                 JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
174     JSFunction::SetFunctionLength(thread, target, JSTaggedValue(2));
175 
176     JSHandle<JSObject> thisArg(thread, env->GetGlobalObject());
177 
178     std::vector<JSTaggedValue> args{thisArg.GetTaggedValue()};
179     auto result = FunctionAlgorithm(thread, target, args, 6, AlgorithmType::PROTOTYPE_BIND);
180 
181     ASSERT_TRUE(result.IsECMAObject());
182 
183     JSHandle<JSBoundFunction> resultFunc(thread, reinterpret_cast<TaggedObject *>(result.GetRawData()));
184     // test BoundTarget
185     ASSERT_EQ(resultFunc->GetBoundTarget(), target.GetTaggedValue());
186     // test BoundThis
187     ASSERT_EQ(resultFunc->GetBoundThis(), thisArg.GetTaggedValue());
188     // test BoundArguments
189     JSHandle<TaggedArray> array(thread, resultFunc->GetBoundArguments());
190     ASSERT_EQ(array->GetLength(), 0U);
191     // test name property
192     auto globalConst = thread->GlobalConstants();
193     JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
194     JSHandle<JSTaggedValue> resultFuncHandle(thread, *resultFunc);
195     JSHandle<EcmaString> resultName(JSObject::GetProperty(thread, resultFuncHandle, nameKey).GetValue());
196     JSHandle<EcmaString> boundTarget = factory->NewFromASCII("bound target");
197     ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultName, boundTarget), 0);
198     // test length property
199     JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
200     JSHandle<JSTaggedValue> resultLength(JSObject::GetProperty(thread, resultFuncHandle, lengthKey).GetValue());
201     ASSERT_EQ(JSTaggedValue::ToNumber(thread, resultLength).GetNumber(), 2.0);
202 }
203 
204 // target.bind(thisArg, 123, "helloworld")
HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind1)205 HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind1)
206 {
207     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
208 
209     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
210 
211     JSHandle<JSFunction> target = factory->NewJSFunction(env);
212     JSFunction::SetFunctionName(thread, JSHandle<JSFunctionBase>(target),
213                                 JSHandle<JSTaggedValue>(factory->NewFromASCII("target1")),
214                                 JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
215     JSFunction::SetFunctionLength(thread, target, JSTaggedValue(5));
216 
217     JSHandle<JSObject> thisArg(thread, env->GetGlobalObject());
218     JSHandle<EcmaString> str = factory->NewFromASCII("helloworld");
219 
220     std::vector<JSTaggedValue> args{thisArg.GetTaggedValue(), JSTaggedValue(static_cast<int32_t>(123)),
221         str.GetTaggedValue()};
222     auto result = FunctionAlgorithm(thread, target, args, 10, AlgorithmType::PROTOTYPE_BIND);
223 
224     ASSERT_TRUE(result.IsECMAObject());
225 
226     JSHandle<JSBoundFunction> resultFunc(thread, reinterpret_cast<TaggedObject *>(result.GetRawData()));
227     // test BoundTarget
228     ASSERT_EQ(resultFunc->GetBoundTarget(), target.GetTaggedValue());
229     // test BoundThis
230     ASSERT_EQ(resultFunc->GetBoundThis(), thisArg.GetTaggedValue());
231     // test BoundArguments
232     JSHandle<TaggedArray> array(thread, resultFunc->GetBoundArguments());
233     ASSERT_EQ(array->GetLength(), 2U);
234     JSTaggedValue elem = array->Get(0);
235     JSTaggedValue elem1 = array->Get(1);
236     ASSERT_EQ(elem.GetRawData(), JSTaggedValue(123).GetRawData());
237 
238     ASSERT_EQ(elem1.GetRawData(), str.GetTaggedType());
239     ASSERT_TRUE(elem1.IsString());
240     // test name property
241     auto globalConst = thread->GlobalConstants();
242     JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
243     JSHandle<JSTaggedValue> resultFuncHandle(thread, *resultFunc);
244     JSHandle<EcmaString> resultName(JSObject::GetProperty(thread, resultFuncHandle, nameKey).GetValue());
245     JSHandle<EcmaString> rulerName = factory->NewFromASCII("bound target1");
246     ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultName, rulerName), 0);
247     // test length property
248     JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
249     JSHandle<JSTaggedValue> resultLength(JSObject::GetProperty(thread, resultFuncHandle, lengthKey).GetValue());
250     // target.length is 5, (...args) length is 2
251     ASSERT_EQ(JSTaggedValue::ToNumber(thread, resultLength).GetNumber(), 3.0);
252 }
253 
254 // target.bind(thisArg, 123, "helloworld") set target_name = EmptyString()
HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind2)255 HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind2)
256 {
257     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
258 
259     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
260 
261     JSHandle<JSFunction> target = factory->NewJSFunction(env);
262     PropertyDescriptor nameDesc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(123)), false, false, true);
263     JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(target),
264                                          thread->GlobalConstants()->GetHandledNameString(), nameDesc);
265     JSFunction::SetFunctionLength(thread, target, JSTaggedValue(5));
266 
267     JSHandle<JSObject> thisArg(thread, env->GetGlobalObject());
268     JSHandle<EcmaString> str = factory->NewFromASCII("helloworld");
269     std::vector<JSTaggedValue> args{thisArg.GetTaggedValue(), JSTaggedValue(static_cast<int32_t>(123)),
270         str.GetTaggedValue()};
271     auto result = FunctionAlgorithm(thread, target, args, 10, AlgorithmType::PROTOTYPE_BIND);
272 
273     ASSERT_TRUE(result.IsECMAObject());
274 
275     JSHandle<JSBoundFunction> resultFunc(thread, reinterpret_cast<TaggedObject *>(result.GetRawData()));
276     // test BoundThis
277     ASSERT_EQ(resultFunc->GetBoundThis(), thisArg.GetTaggedValue());
278 
279     // test BoundTarget
280     ASSERT_EQ(resultFunc->GetBoundTarget(), target.GetTaggedValue());
281     // test BoundArguments
282     JSHandle<TaggedArray> array(thread, resultFunc->GetBoundArguments());
283     ASSERT_EQ(array->GetLength(), 2U);
284     JSTaggedValue elem = array->Get(0);
285     JSTaggedValue elem1 = array->Get(1);
286     ASSERT_EQ(elem.GetRawData(), JSTaggedValue(123).GetRawData());
287 
288     ASSERT_TRUE(elem1.IsString());
289     ASSERT_EQ(elem1.GetRawData(), str.GetTaggedType());
290 
291     // test name property
292     auto globalConst = thread->GlobalConstants();
293     JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
294     JSHandle<JSTaggedValue> resultFuncHandle(resultFunc);
295     JSHandle<EcmaString> resultName(JSObject::GetProperty(thread, resultFuncHandle, nameKey).GetValue());
296     JSHandle<EcmaString> rulerName = factory->NewFromASCII("bound ");
297     ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultName, rulerName), 0);
298     // test length property
299     JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
300     JSHandle<JSTaggedValue> resultLength(JSObject::GetProperty(thread, resultFuncHandle, lengthKey).GetValue());
301     // target.length is 5, (...args) length is 2
302     ASSERT_EQ(JSTaggedValue::ToNumber(thread, resultLength).GetNumber(), 3.0);
303 }
304 
305 // func.call(thisArg)
HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeCall)306 HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeCall)
307 {
308     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
309 
310     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
311 
312     // ecma 19.2.3.3: func
313     JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestFunctionApplyAndCall));
314 
315     // ecma 19.2.3.3: thisArg
316     JSHandle<JSObject> thisArg(thread, env->GetGlobalObject());
317     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
318                           JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")),
319                           JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)));
320     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
321                           JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")),
322                           JSHandle<JSTaggedValue>(thread, JSTaggedValue(2)));
323     std::vector<JSTaggedValue> args{thisArg.GetTaggedValue()};
324     auto result = FunctionAlgorithm(thread, func, args, 6, AlgorithmType::PROTOTYPE_CALL);
325 
326     ASSERT_EQ(result.GetRawData(), JSTaggedValue(3).GetRawData());
327 
328     JSObject::DeleteProperty(thread, (thisArg),
329                              JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")));
330     JSObject::DeleteProperty(thread, (thisArg),
331                              JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")));
332 }
333 
334 // func.call(thisArg, 123, 456, 789)
HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeCall1)335 HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeCall1)
336 {
337     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
338 
339     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
340 
341     // ecma 19.2.3.3: func
342     JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestFunctionApplyAndCall));
343 
344     // ecma 19.2.3.3: thisArg
345     JSHandle<JSObject> thisArg(thread, env->GetGlobalObject());
346     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
347                           JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")),
348                           JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)));
349     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
350                           JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")),
351                           JSHandle<JSTaggedValue>(thread, JSTaggedValue(2)));
352 
353     // func thisArg ...args
354     std::vector<JSTaggedValue> args{thisArg.GetTaggedValue(), JSTaggedValue(static_cast<int32_t>(123)),
355                                 JSTaggedValue(static_cast<int32_t>(456)), JSTaggedValue(static_cast<int32_t>(789))};
356     auto result = FunctionAlgorithm(thread, func, args, 12, AlgorithmType::PROTOTYPE_CALL);
357 
358     ASSERT_EQ(result.GetRawData(), JSTaggedValue(1371).GetRawData());
359 
360     JSObject::DeleteProperty(thread, (thisArg),
361                              JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")));
362     JSObject::DeleteProperty(thread, (thisArg),
363                              JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")));
364 }
365 
HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeHasInstance)366 HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeHasInstance)
367 {
368     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
369 
370     JSHandle<JSFunction> booleanCtor(env->GetBooleanFunction());
371 
372     auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*booleanCtor), 6);
373     ecmaRuntimeCallInfo1->SetFunction(booleanCtor.GetTaggedValue());
374     ecmaRuntimeCallInfo1->SetThis(JSTaggedValue::Undefined());
375     ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(123)));
376 
377     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
378     JSTaggedValue result = BuiltinsBoolean::BooleanConstructor(ecmaRuntimeCallInfo1);
379     TestHelper::TearDownFrame(thread, prev);
380 
381     JSHandle<JSObject> booleanInstance(thread, result);
382 
383     auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
384     ecmaRuntimeCallInfo2->SetFunction(JSTaggedValue::Undefined());
385     ecmaRuntimeCallInfo2->SetThis(booleanCtor.GetTaggedValue());
386     ecmaRuntimeCallInfo2->SetCallArg(0, booleanInstance.GetTaggedValue());
387 
388     prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
389     EXPECT_TRUE(BuiltinsFunction::FunctionPrototypeHasInstance(ecmaRuntimeCallInfo2).GetRawData());
390     TestHelper::TearDownFrame(thread, prev);
391 }
392 
393 /**
394  * @tc.name: FunctionPrototypeToString
395  * @tc.desc: Create msgs through "CreateEcmaRuntimeCallInfo" function, Set ArgsNumber and CallArg, then call
396  *           the "FunctionPrototypeToString" function to get the result of Function.prototype.call.toString().
397  * @tc.type: FUNC
398  * @tc.require: issueI5INW1
399  */
HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeToString)400 HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeToString)
401 {
402     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
403     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
404     CString key = "call";
405     JSHandle<JSTaggedValue> keyString(factory->NewFromUtf8(key));
406 
407     JSHandle<JSFunction> func = factory->NewJSFunction(
408                                 env, reinterpret_cast<void *>(BuiltinsFunction::FunctionPrototypeCall));
409     JSHandle<JSFunctionBase> baseFunction(func);
410     JSHandle<JSTaggedValue> handleUndefine(thread, JSTaggedValue::Undefined());
411     JSFunction::SetFunctionName(thread, baseFunction, keyString, handleUndefine);
412 
413     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
414     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
415     ecmaRuntimeCallInfo->SetThis(func.GetTaggedValue());
416 
417     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
418     JSTaggedValue result = BuiltinsFunction::FunctionPrototypeToString(ecmaRuntimeCallInfo);
419     ASSERT_TRUE(result.IsString());
420     JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
421     JSHandle<EcmaString> test = factory->NewFromASCII("function call() { [native code] }");
422     ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
423 }
424 }  // namespace panda::test
425