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
31using namespace panda::ecmascript;
32using namespace panda::ecmascript::builtins;
33using BuiltinsBase = panda::ecmascript::base::BuiltinsBase;
34using JSArray = panda::ecmascript::JSArray;
35
36namespace panda::test {
37class BuiltinsFunctionTest : public BaseTestWithScope<false> {
38};
39
40// native function for test apply and call
41JSTaggedValue 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
61enum class AlgorithmType {
62    PROTOTYPE_APPLY,
63    PROTOTYPE_BIND,
64    PROTOTYPE_CALL,
65};
66
67static 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)
97HWTEST_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)
126HWTEST_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)
164HWTEST_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")
205HWTEST_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()
255HWTEST_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)
306HWTEST_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)
335HWTEST_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
366HWTEST_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 */
400HWTEST_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