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