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