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