14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/builtins/builtins_function.h"
174514f5e3Sopenharmony_ci#include "ecmascript/builtins/builtins_boolean.h"
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include "ecmascript/ecma_runtime_call_info.h"
204514f5e3Sopenharmony_ci#include "ecmascript/ecma_string.h"
214514f5e3Sopenharmony_ci#include "ecmascript/ecma_vm.h"
224514f5e3Sopenharmony_ci#include "ecmascript/global_env.h"
234514f5e3Sopenharmony_ci#include "ecmascript/js_array.h"
244514f5e3Sopenharmony_ci#include "ecmascript/js_function.h"
254514f5e3Sopenharmony_ci#include "ecmascript/js_object-inl.h"
264514f5e3Sopenharmony_ci
274514f5e3Sopenharmony_ci#include "ecmascript/object_factory.h"
284514f5e3Sopenharmony_ci#include "ecmascript/tagged_array-inl.h"
294514f5e3Sopenharmony_ci#include "ecmascript/tests/test_helper.h"
304514f5e3Sopenharmony_ci
314514f5e3Sopenharmony_ciusing namespace panda::ecmascript;
324514f5e3Sopenharmony_ciusing namespace panda::ecmascript::builtins;
334514f5e3Sopenharmony_ciusing BuiltinsBase = panda::ecmascript::base::BuiltinsBase;
344514f5e3Sopenharmony_ciusing JSArray = panda::ecmascript::JSArray;
354514f5e3Sopenharmony_ci
364514f5e3Sopenharmony_cinamespace panda::test {
374514f5e3Sopenharmony_ciclass BuiltinsFunctionTest : public BaseTestWithScope<false> {
384514f5e3Sopenharmony_ci};
394514f5e3Sopenharmony_ci
404514f5e3Sopenharmony_ci// native function for test apply and call
414514f5e3Sopenharmony_ciJSTaggedValue TestFunctionApplyAndCall(EcmaRuntimeCallInfo *argv)
424514f5e3Sopenharmony_ci{
434514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
444514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
454514f5e3Sopenharmony_ci
464514f5e3Sopenharmony_ci    int result = 0;
474514f5e3Sopenharmony_ci    for (uint32_t index = 0; index < argv->GetArgsNumber(); ++index) {
484514f5e3Sopenharmony_ci        result += BuiltinsBase::GetCallArg(argv, index)->GetInt();
494514f5e3Sopenharmony_ci    }
504514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> thisValue(BuiltinsBase::GetThis(argv));
514514f5e3Sopenharmony_ci
524514f5e3Sopenharmony_ci    JSTaggedValue testA = JSObject::GetProperty(thread, thisValue,
534514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a"))).GetValue().GetTaggedValue();
544514f5e3Sopenharmony_ci    JSTaggedValue testB = JSObject::GetProperty(thread, thisValue,
554514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b"))).GetValue().GetTaggedValue();
564514f5e3Sopenharmony_ci
574514f5e3Sopenharmony_ci    result = result + testA.GetInt() + testB.GetInt();
584514f5e3Sopenharmony_ci    return BuiltinsBase::GetTaggedInt(result);
594514f5e3Sopenharmony_ci}
604514f5e3Sopenharmony_ci
614514f5e3Sopenharmony_cienum class AlgorithmType {
624514f5e3Sopenharmony_ci    PROTOTYPE_APPLY,
634514f5e3Sopenharmony_ci    PROTOTYPE_BIND,
644514f5e3Sopenharmony_ci    PROTOTYPE_CALL,
654514f5e3Sopenharmony_ci};
664514f5e3Sopenharmony_ci
674514f5e3Sopenharmony_cistatic JSTaggedValue FunctionAlgorithm(JSThread *thread, JSHandle<JSFunction> &thisArg,
684514f5e3Sopenharmony_ci                                       std::vector<JSTaggedValue> &args, uint32_t argLen,
694514f5e3Sopenharmony_ci                                       AlgorithmType type = AlgorithmType::PROTOTYPE_APPLY)
704514f5e3Sopenharmony_ci{
714514f5e3Sopenharmony_ci    auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), argLen);
724514f5e3Sopenharmony_ci    ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined());
734514f5e3Sopenharmony_ci    ecmaRuntimeCallInfos->SetThis(thisArg.GetTaggedValue());
744514f5e3Sopenharmony_ci    for (size_t i = 0; i < args.size(); i++) {
754514f5e3Sopenharmony_ci        ecmaRuntimeCallInfos->SetCallArg(i, args[i]);
764514f5e3Sopenharmony_ci    }
774514f5e3Sopenharmony_ci    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos);
784514f5e3Sopenharmony_ci    JSTaggedValue result;
794514f5e3Sopenharmony_ci    switch (type) {
804514f5e3Sopenharmony_ci        case AlgorithmType::PROTOTYPE_BIND:
814514f5e3Sopenharmony_ci            result = BuiltinsFunction::FunctionPrototypeBind(ecmaRuntimeCallInfos);
824514f5e3Sopenharmony_ci            break;
834514f5e3Sopenharmony_ci        case AlgorithmType::PROTOTYPE_APPLY:
844514f5e3Sopenharmony_ci            result = BuiltinsFunction::FunctionPrototypeApply(ecmaRuntimeCallInfos);
854514f5e3Sopenharmony_ci            break;
864514f5e3Sopenharmony_ci        case AlgorithmType::PROTOTYPE_CALL:
874514f5e3Sopenharmony_ci            result = BuiltinsFunction::FunctionPrototypeCall(ecmaRuntimeCallInfos);
884514f5e3Sopenharmony_ci            break;
894514f5e3Sopenharmony_ci        default:
904514f5e3Sopenharmony_ci            break;
914514f5e3Sopenharmony_ci    }
924514f5e3Sopenharmony_ci    TestHelper::TearDownFrame(thread, prev);
934514f5e3Sopenharmony_ci    return result;
944514f5e3Sopenharmony_ci}
954514f5e3Sopenharmony_ci
964514f5e3Sopenharmony_ci// func.apply(thisArg)
974514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeApply)
984514f5e3Sopenharmony_ci{
994514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1004514f5e3Sopenharmony_ci
1014514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1024514f5e3Sopenharmony_ci    // ecma 19.2.3.1: func
1034514f5e3Sopenharmony_ci    JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestFunctionApplyAndCall));
1044514f5e3Sopenharmony_ci
1054514f5e3Sopenharmony_ci    // ecma 19.2.3.1: thisArg
1064514f5e3Sopenharmony_ci    JSHandle<JSObject> thisArg(thread, env->GetGlobalObject());
1074514f5e3Sopenharmony_ci    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
1084514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")),
1094514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)));
1104514f5e3Sopenharmony_ci    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
1114514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")),
1124514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(thread, JSTaggedValue(2)));
1134514f5e3Sopenharmony_ci
1144514f5e3Sopenharmony_ci    std::vector<JSTaggedValue> args{thisArg.GetTaggedValue()};
1154514f5e3Sopenharmony_ci    auto result = FunctionAlgorithm(thread, func, args, 6, AlgorithmType::PROTOTYPE_APPLY);
1164514f5e3Sopenharmony_ci
1174514f5e3Sopenharmony_ci    ASSERT_EQ(result.GetRawData(), JSTaggedValue(3).GetRawData());
1184514f5e3Sopenharmony_ci
1194514f5e3Sopenharmony_ci    JSObject::DeleteProperty(thread, (thisArg),
1204514f5e3Sopenharmony_ci                             JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")));
1214514f5e3Sopenharmony_ci    JSObject::DeleteProperty(thread, (thisArg),
1224514f5e3Sopenharmony_ci                             JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")));
1234514f5e3Sopenharmony_ci}
1244514f5e3Sopenharmony_ci
1254514f5e3Sopenharmony_ci// func.apply(thisArg, argArray)
1264514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeApply1)
1274514f5e3Sopenharmony_ci{
1284514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1294514f5e3Sopenharmony_ci
1304514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1314514f5e3Sopenharmony_ci
1324514f5e3Sopenharmony_ci    // ecma 19.2.3.1: func
1334514f5e3Sopenharmony_ci    JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestFunctionApplyAndCall));
1344514f5e3Sopenharmony_ci
1354514f5e3Sopenharmony_ci    // ecma 19.2.3.1: thisArg
1364514f5e3Sopenharmony_ci    JSHandle<JSObject> thisArg(thread, env->GetGlobalObject());
1374514f5e3Sopenharmony_ci    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
1384514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")),
1394514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(thread, JSTaggedValue(10)));
1404514f5e3Sopenharmony_ci    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
1414514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")),
1424514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(thread, JSTaggedValue(20)));
1434514f5e3Sopenharmony_ci
1444514f5e3Sopenharmony_ci    // ecma 19.2.3.1: argArray
1454514f5e3Sopenharmony_ci    JSHandle<JSObject> array(JSArray::ArrayCreate(thread, JSTaggedNumber(2)));
1464514f5e3Sopenharmony_ci    PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(30)));
1474514f5e3Sopenharmony_ci    JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(0)), desc);
1484514f5e3Sopenharmony_ci
1494514f5e3Sopenharmony_ci    PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(40)));
1504514f5e3Sopenharmony_ci    JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), desc1);
1514514f5e3Sopenharmony_ci
1524514f5e3Sopenharmony_ci    std::vector<JSTaggedValue> args{thisArg.GetTaggedValue(), array.GetTaggedValue()};
1534514f5e3Sopenharmony_ci    auto result = FunctionAlgorithm(thread, func, args, 8, AlgorithmType::PROTOTYPE_APPLY);
1544514f5e3Sopenharmony_ci
1554514f5e3Sopenharmony_ci    ASSERT_EQ(result.GetRawData(), JSTaggedValue(100).GetRawData());
1564514f5e3Sopenharmony_ci
1574514f5e3Sopenharmony_ci    JSObject::DeleteProperty(thread, (thisArg),
1584514f5e3Sopenharmony_ci                             JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")));
1594514f5e3Sopenharmony_ci    JSObject::DeleteProperty(thread, (thisArg),
1604514f5e3Sopenharmony_ci                             JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")));
1614514f5e3Sopenharmony_ci}
1624514f5e3Sopenharmony_ci
1634514f5e3Sopenharmony_ci// target.bind(thisArg)
1644514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind)
1654514f5e3Sopenharmony_ci{
1664514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1674514f5e3Sopenharmony_ci
1684514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1694514f5e3Sopenharmony_ci
1704514f5e3Sopenharmony_ci    JSHandle<JSFunction> target = factory->NewJSFunction(env);
1714514f5e3Sopenharmony_ci    JSFunction::SetFunctionName(thread, JSHandle<JSFunctionBase>(target),
1724514f5e3Sopenharmony_ci                                JSHandle<JSTaggedValue>(factory->NewFromASCII("target")),
1734514f5e3Sopenharmony_ci                                JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
1744514f5e3Sopenharmony_ci    JSFunction::SetFunctionLength(thread, target, JSTaggedValue(2));
1754514f5e3Sopenharmony_ci
1764514f5e3Sopenharmony_ci    JSHandle<JSObject> thisArg(thread, env->GetGlobalObject());
1774514f5e3Sopenharmony_ci
1784514f5e3Sopenharmony_ci    std::vector<JSTaggedValue> args{thisArg.GetTaggedValue()};
1794514f5e3Sopenharmony_ci    auto result = FunctionAlgorithm(thread, target, args, 6, AlgorithmType::PROTOTYPE_BIND);
1804514f5e3Sopenharmony_ci
1814514f5e3Sopenharmony_ci    ASSERT_TRUE(result.IsECMAObject());
1824514f5e3Sopenharmony_ci
1834514f5e3Sopenharmony_ci    JSHandle<JSBoundFunction> resultFunc(thread, reinterpret_cast<TaggedObject *>(result.GetRawData()));
1844514f5e3Sopenharmony_ci    // test BoundTarget
1854514f5e3Sopenharmony_ci    ASSERT_EQ(resultFunc->GetBoundTarget(), target.GetTaggedValue());
1864514f5e3Sopenharmony_ci    // test BoundThis
1874514f5e3Sopenharmony_ci    ASSERT_EQ(resultFunc->GetBoundThis(), thisArg.GetTaggedValue());
1884514f5e3Sopenharmony_ci    // test BoundArguments
1894514f5e3Sopenharmony_ci    JSHandle<TaggedArray> array(thread, resultFunc->GetBoundArguments());
1904514f5e3Sopenharmony_ci    ASSERT_EQ(array->GetLength(), 0U);
1914514f5e3Sopenharmony_ci    // test name property
1924514f5e3Sopenharmony_ci    auto globalConst = thread->GlobalConstants();
1934514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
1944514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> resultFuncHandle(thread, *resultFunc);
1954514f5e3Sopenharmony_ci    JSHandle<EcmaString> resultName(JSObject::GetProperty(thread, resultFuncHandle, nameKey).GetValue());
1964514f5e3Sopenharmony_ci    JSHandle<EcmaString> boundTarget = factory->NewFromASCII("bound target");
1974514f5e3Sopenharmony_ci    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultName, boundTarget), 0);
1984514f5e3Sopenharmony_ci    // test length property
1994514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
2004514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> resultLength(JSObject::GetProperty(thread, resultFuncHandle, lengthKey).GetValue());
2014514f5e3Sopenharmony_ci    ASSERT_EQ(JSTaggedValue::ToNumber(thread, resultLength).GetNumber(), 2.0);
2024514f5e3Sopenharmony_ci}
2034514f5e3Sopenharmony_ci
2044514f5e3Sopenharmony_ci// target.bind(thisArg, 123, "helloworld")
2054514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind1)
2064514f5e3Sopenharmony_ci{
2074514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
2084514f5e3Sopenharmony_ci
2094514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2104514f5e3Sopenharmony_ci
2114514f5e3Sopenharmony_ci    JSHandle<JSFunction> target = factory->NewJSFunction(env);
2124514f5e3Sopenharmony_ci    JSFunction::SetFunctionName(thread, JSHandle<JSFunctionBase>(target),
2134514f5e3Sopenharmony_ci                                JSHandle<JSTaggedValue>(factory->NewFromASCII("target1")),
2144514f5e3Sopenharmony_ci                                JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
2154514f5e3Sopenharmony_ci    JSFunction::SetFunctionLength(thread, target, JSTaggedValue(5));
2164514f5e3Sopenharmony_ci
2174514f5e3Sopenharmony_ci    JSHandle<JSObject> thisArg(thread, env->GetGlobalObject());
2184514f5e3Sopenharmony_ci    JSHandle<EcmaString> str = factory->NewFromASCII("helloworld");
2194514f5e3Sopenharmony_ci
2204514f5e3Sopenharmony_ci    std::vector<JSTaggedValue> args{thisArg.GetTaggedValue(), JSTaggedValue(static_cast<int32_t>(123)),
2214514f5e3Sopenharmony_ci        str.GetTaggedValue()};
2224514f5e3Sopenharmony_ci    auto result = FunctionAlgorithm(thread, target, args, 10, AlgorithmType::PROTOTYPE_BIND);
2234514f5e3Sopenharmony_ci
2244514f5e3Sopenharmony_ci    ASSERT_TRUE(result.IsECMAObject());
2254514f5e3Sopenharmony_ci
2264514f5e3Sopenharmony_ci    JSHandle<JSBoundFunction> resultFunc(thread, reinterpret_cast<TaggedObject *>(result.GetRawData()));
2274514f5e3Sopenharmony_ci    // test BoundTarget
2284514f5e3Sopenharmony_ci    ASSERT_EQ(resultFunc->GetBoundTarget(), target.GetTaggedValue());
2294514f5e3Sopenharmony_ci    // test BoundThis
2304514f5e3Sopenharmony_ci    ASSERT_EQ(resultFunc->GetBoundThis(), thisArg.GetTaggedValue());
2314514f5e3Sopenharmony_ci    // test BoundArguments
2324514f5e3Sopenharmony_ci    JSHandle<TaggedArray> array(thread, resultFunc->GetBoundArguments());
2334514f5e3Sopenharmony_ci    ASSERT_EQ(array->GetLength(), 2U);
2344514f5e3Sopenharmony_ci    JSTaggedValue elem = array->Get(0);
2354514f5e3Sopenharmony_ci    JSTaggedValue elem1 = array->Get(1);
2364514f5e3Sopenharmony_ci    ASSERT_EQ(elem.GetRawData(), JSTaggedValue(123).GetRawData());
2374514f5e3Sopenharmony_ci
2384514f5e3Sopenharmony_ci    ASSERT_EQ(elem1.GetRawData(), str.GetTaggedType());
2394514f5e3Sopenharmony_ci    ASSERT_TRUE(elem1.IsString());
2404514f5e3Sopenharmony_ci    // test name property
2414514f5e3Sopenharmony_ci    auto globalConst = thread->GlobalConstants();
2424514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
2434514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> resultFuncHandle(thread, *resultFunc);
2444514f5e3Sopenharmony_ci    JSHandle<EcmaString> resultName(JSObject::GetProperty(thread, resultFuncHandle, nameKey).GetValue());
2454514f5e3Sopenharmony_ci    JSHandle<EcmaString> rulerName = factory->NewFromASCII("bound target1");
2464514f5e3Sopenharmony_ci    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultName, rulerName), 0);
2474514f5e3Sopenharmony_ci    // test length property
2484514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
2494514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> resultLength(JSObject::GetProperty(thread, resultFuncHandle, lengthKey).GetValue());
2504514f5e3Sopenharmony_ci    // target.length is 5, (...args) length is 2
2514514f5e3Sopenharmony_ci    ASSERT_EQ(JSTaggedValue::ToNumber(thread, resultLength).GetNumber(), 3.0);
2524514f5e3Sopenharmony_ci}
2534514f5e3Sopenharmony_ci
2544514f5e3Sopenharmony_ci// target.bind(thisArg, 123, "helloworld") set target_name = EmptyString()
2554514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind2)
2564514f5e3Sopenharmony_ci{
2574514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
2584514f5e3Sopenharmony_ci
2594514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2604514f5e3Sopenharmony_ci
2614514f5e3Sopenharmony_ci    JSHandle<JSFunction> target = factory->NewJSFunction(env);
2624514f5e3Sopenharmony_ci    PropertyDescriptor nameDesc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(123)), false, false, true);
2634514f5e3Sopenharmony_ci    JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(target),
2644514f5e3Sopenharmony_ci                                         thread->GlobalConstants()->GetHandledNameString(), nameDesc);
2654514f5e3Sopenharmony_ci    JSFunction::SetFunctionLength(thread, target, JSTaggedValue(5));
2664514f5e3Sopenharmony_ci
2674514f5e3Sopenharmony_ci    JSHandle<JSObject> thisArg(thread, env->GetGlobalObject());
2684514f5e3Sopenharmony_ci    JSHandle<EcmaString> str = factory->NewFromASCII("helloworld");
2694514f5e3Sopenharmony_ci    std::vector<JSTaggedValue> args{thisArg.GetTaggedValue(), JSTaggedValue(static_cast<int32_t>(123)),
2704514f5e3Sopenharmony_ci        str.GetTaggedValue()};
2714514f5e3Sopenharmony_ci    auto result = FunctionAlgorithm(thread, target, args, 10, AlgorithmType::PROTOTYPE_BIND);
2724514f5e3Sopenharmony_ci
2734514f5e3Sopenharmony_ci    ASSERT_TRUE(result.IsECMAObject());
2744514f5e3Sopenharmony_ci
2754514f5e3Sopenharmony_ci    JSHandle<JSBoundFunction> resultFunc(thread, reinterpret_cast<TaggedObject *>(result.GetRawData()));
2764514f5e3Sopenharmony_ci    // test BoundThis
2774514f5e3Sopenharmony_ci    ASSERT_EQ(resultFunc->GetBoundThis(), thisArg.GetTaggedValue());
2784514f5e3Sopenharmony_ci
2794514f5e3Sopenharmony_ci    // test BoundTarget
2804514f5e3Sopenharmony_ci    ASSERT_EQ(resultFunc->GetBoundTarget(), target.GetTaggedValue());
2814514f5e3Sopenharmony_ci    // test BoundArguments
2824514f5e3Sopenharmony_ci    JSHandle<TaggedArray> array(thread, resultFunc->GetBoundArguments());
2834514f5e3Sopenharmony_ci    ASSERT_EQ(array->GetLength(), 2U);
2844514f5e3Sopenharmony_ci    JSTaggedValue elem = array->Get(0);
2854514f5e3Sopenharmony_ci    JSTaggedValue elem1 = array->Get(1);
2864514f5e3Sopenharmony_ci    ASSERT_EQ(elem.GetRawData(), JSTaggedValue(123).GetRawData());
2874514f5e3Sopenharmony_ci
2884514f5e3Sopenharmony_ci    ASSERT_TRUE(elem1.IsString());
2894514f5e3Sopenharmony_ci    ASSERT_EQ(elem1.GetRawData(), str.GetTaggedType());
2904514f5e3Sopenharmony_ci
2914514f5e3Sopenharmony_ci    // test name property
2924514f5e3Sopenharmony_ci    auto globalConst = thread->GlobalConstants();
2934514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
2944514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> resultFuncHandle(resultFunc);
2954514f5e3Sopenharmony_ci    JSHandle<EcmaString> resultName(JSObject::GetProperty(thread, resultFuncHandle, nameKey).GetValue());
2964514f5e3Sopenharmony_ci    JSHandle<EcmaString> rulerName = factory->NewFromASCII("bound ");
2974514f5e3Sopenharmony_ci    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultName, rulerName), 0);
2984514f5e3Sopenharmony_ci    // test length property
2994514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
3004514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> resultLength(JSObject::GetProperty(thread, resultFuncHandle, lengthKey).GetValue());
3014514f5e3Sopenharmony_ci    // target.length is 5, (...args) length is 2
3024514f5e3Sopenharmony_ci    ASSERT_EQ(JSTaggedValue::ToNumber(thread, resultLength).GetNumber(), 3.0);
3034514f5e3Sopenharmony_ci}
3044514f5e3Sopenharmony_ci
3054514f5e3Sopenharmony_ci// func.call(thisArg)
3064514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeCall)
3074514f5e3Sopenharmony_ci{
3084514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
3094514f5e3Sopenharmony_ci
3104514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
3114514f5e3Sopenharmony_ci
3124514f5e3Sopenharmony_ci    // ecma 19.2.3.3: func
3134514f5e3Sopenharmony_ci    JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestFunctionApplyAndCall));
3144514f5e3Sopenharmony_ci
3154514f5e3Sopenharmony_ci    // ecma 19.2.3.3: thisArg
3164514f5e3Sopenharmony_ci    JSHandle<JSObject> thisArg(thread, env->GetGlobalObject());
3174514f5e3Sopenharmony_ci    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
3184514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")),
3194514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)));
3204514f5e3Sopenharmony_ci    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
3214514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")),
3224514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(thread, JSTaggedValue(2)));
3234514f5e3Sopenharmony_ci    std::vector<JSTaggedValue> args{thisArg.GetTaggedValue()};
3244514f5e3Sopenharmony_ci    auto result = FunctionAlgorithm(thread, func, args, 6, AlgorithmType::PROTOTYPE_CALL);
3254514f5e3Sopenharmony_ci
3264514f5e3Sopenharmony_ci    ASSERT_EQ(result.GetRawData(), JSTaggedValue(3).GetRawData());
3274514f5e3Sopenharmony_ci
3284514f5e3Sopenharmony_ci    JSObject::DeleteProperty(thread, (thisArg),
3294514f5e3Sopenharmony_ci                             JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")));
3304514f5e3Sopenharmony_ci    JSObject::DeleteProperty(thread, (thisArg),
3314514f5e3Sopenharmony_ci                             JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")));
3324514f5e3Sopenharmony_ci}
3334514f5e3Sopenharmony_ci
3344514f5e3Sopenharmony_ci// func.call(thisArg, 123, 456, 789)
3354514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeCall1)
3364514f5e3Sopenharmony_ci{
3374514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
3384514f5e3Sopenharmony_ci
3394514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
3404514f5e3Sopenharmony_ci
3414514f5e3Sopenharmony_ci    // ecma 19.2.3.3: func
3424514f5e3Sopenharmony_ci    JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestFunctionApplyAndCall));
3434514f5e3Sopenharmony_ci
3444514f5e3Sopenharmony_ci    // ecma 19.2.3.3: thisArg
3454514f5e3Sopenharmony_ci    JSHandle<JSObject> thisArg(thread, env->GetGlobalObject());
3464514f5e3Sopenharmony_ci    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
3474514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")),
3484514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)));
3494514f5e3Sopenharmony_ci    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(thisArg),
3504514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")),
3514514f5e3Sopenharmony_ci                          JSHandle<JSTaggedValue>(thread, JSTaggedValue(2)));
3524514f5e3Sopenharmony_ci
3534514f5e3Sopenharmony_ci    // func thisArg ...args
3544514f5e3Sopenharmony_ci    std::vector<JSTaggedValue> args{thisArg.GetTaggedValue(), JSTaggedValue(static_cast<int32_t>(123)),
3554514f5e3Sopenharmony_ci                                JSTaggedValue(static_cast<int32_t>(456)), JSTaggedValue(static_cast<int32_t>(789))};
3564514f5e3Sopenharmony_ci    auto result = FunctionAlgorithm(thread, func, args, 12, AlgorithmType::PROTOTYPE_CALL);
3574514f5e3Sopenharmony_ci
3584514f5e3Sopenharmony_ci    ASSERT_EQ(result.GetRawData(), JSTaggedValue(1371).GetRawData());
3594514f5e3Sopenharmony_ci
3604514f5e3Sopenharmony_ci    JSObject::DeleteProperty(thread, (thisArg),
3614514f5e3Sopenharmony_ci                             JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_a")));
3624514f5e3Sopenharmony_ci    JSObject::DeleteProperty(thread, (thisArg),
3634514f5e3Sopenharmony_ci                             JSHandle<JSTaggedValue>(factory->NewFromASCII("test_builtins_function_b")));
3644514f5e3Sopenharmony_ci}
3654514f5e3Sopenharmony_ci
3664514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeHasInstance)
3674514f5e3Sopenharmony_ci{
3684514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
3694514f5e3Sopenharmony_ci
3704514f5e3Sopenharmony_ci    JSHandle<JSFunction> booleanCtor(env->GetBooleanFunction());
3714514f5e3Sopenharmony_ci
3724514f5e3Sopenharmony_ci    auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*booleanCtor), 6);
3734514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo1->SetFunction(booleanCtor.GetTaggedValue());
3744514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo1->SetThis(JSTaggedValue::Undefined());
3754514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(123)));
3764514f5e3Sopenharmony_ci
3774514f5e3Sopenharmony_ci    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
3784514f5e3Sopenharmony_ci    JSTaggedValue result = BuiltinsBoolean::BooleanConstructor(ecmaRuntimeCallInfo1);
3794514f5e3Sopenharmony_ci    TestHelper::TearDownFrame(thread, prev);
3804514f5e3Sopenharmony_ci
3814514f5e3Sopenharmony_ci    JSHandle<JSObject> booleanInstance(thread, result);
3824514f5e3Sopenharmony_ci
3834514f5e3Sopenharmony_ci    auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
3844514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo2->SetFunction(JSTaggedValue::Undefined());
3854514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo2->SetThis(booleanCtor.GetTaggedValue());
3864514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo2->SetCallArg(0, booleanInstance.GetTaggedValue());
3874514f5e3Sopenharmony_ci
3884514f5e3Sopenharmony_ci    prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
3894514f5e3Sopenharmony_ci    EXPECT_TRUE(BuiltinsFunction::FunctionPrototypeHasInstance(ecmaRuntimeCallInfo2).GetRawData());
3904514f5e3Sopenharmony_ci    TestHelper::TearDownFrame(thread, prev);
3914514f5e3Sopenharmony_ci}
3924514f5e3Sopenharmony_ci
3934514f5e3Sopenharmony_ci/**
3944514f5e3Sopenharmony_ci * @tc.name: FunctionPrototypeToString
3954514f5e3Sopenharmony_ci * @tc.desc: Create msgs through "CreateEcmaRuntimeCallInfo" function, Set ArgsNumber and CallArg, then call
3964514f5e3Sopenharmony_ci *           the "FunctionPrototypeToString" function to get the result of Function.prototype.call.toString().
3974514f5e3Sopenharmony_ci * @tc.type: FUNC
3984514f5e3Sopenharmony_ci * @tc.require: issueI5INW1
3994514f5e3Sopenharmony_ci */
4004514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeToString)
4014514f5e3Sopenharmony_ci{
4024514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
4034514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
4044514f5e3Sopenharmony_ci    CString key = "call";
4054514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> keyString(factory->NewFromUtf8(key));
4064514f5e3Sopenharmony_ci
4074514f5e3Sopenharmony_ci    JSHandle<JSFunction> func = factory->NewJSFunction(
4084514f5e3Sopenharmony_ci                                env, reinterpret_cast<void *>(BuiltinsFunction::FunctionPrototypeCall));
4094514f5e3Sopenharmony_ci    JSHandle<JSFunctionBase> baseFunction(func);
4104514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handleUndefine(thread, JSTaggedValue::Undefined());
4114514f5e3Sopenharmony_ci    JSFunction::SetFunctionName(thread, baseFunction, keyString, handleUndefine);
4124514f5e3Sopenharmony_ci
4134514f5e3Sopenharmony_ci    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
4144514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
4154514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetThis(func.GetTaggedValue());
4164514f5e3Sopenharmony_ci
4174514f5e3Sopenharmony_ci    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
4184514f5e3Sopenharmony_ci    JSTaggedValue result = BuiltinsFunction::FunctionPrototypeToString(ecmaRuntimeCallInfo);
4194514f5e3Sopenharmony_ci    ASSERT_TRUE(result.IsString());
4204514f5e3Sopenharmony_ci    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
4214514f5e3Sopenharmony_ci    JSHandle<EcmaString> test = factory->NewFromASCII("function call() { [native code] }");
4224514f5e3Sopenharmony_ci    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
4234514f5e3Sopenharmony_ci}
4244514f5e3Sopenharmony_ci}  // namespace panda::test
425