14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 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/js_proxy.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/global_env.h"
194514f5e3Sopenharmony_ci#include "ecmascript/interpreter/interpreter.h"
204514f5e3Sopenharmony_ci#include "ecmascript/js_function.h"
214514f5e3Sopenharmony_ci#include "ecmascript/js_object-inl.h"
224514f5e3Sopenharmony_ci
234514f5e3Sopenharmony_cinamespace panda::ecmascript {
244514f5e3Sopenharmony_ci// ES6 9.5.15 ProxyCreate(target, handler)
254514f5e3Sopenharmony_ciJSHandle<JSProxy> JSProxy::ProxyCreate(JSThread *thread, const JSHandle<JSTaggedValue> &target,
264514f5e3Sopenharmony_ci                                       const JSHandle<JSTaggedValue> &handler)
274514f5e3Sopenharmony_ci{
284514f5e3Sopenharmony_ci    // 1. If Type(target) is not Object, throw a TypeError exception.
294514f5e3Sopenharmony_ci    if (!target->IsECMAObject()) {
304514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "ProxyCreate: target is not Object",
314514f5e3Sopenharmony_ci                                    JSHandle<JSProxy>(thread, JSTaggedValue::Exception()));
324514f5e3Sopenharmony_ci    }
334514f5e3Sopenharmony_ci
344514f5e3Sopenharmony_ci    // 2. If Type(handler) is not Object, throw a TypeError exception.
354514f5e3Sopenharmony_ci    if (!handler->IsECMAObject()) {
364514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "ProxyCreate: handler is not Object",
374514f5e3Sopenharmony_ci                                    JSHandle<JSProxy>(thread, JSTaggedValue::Exception()));
384514f5e3Sopenharmony_ci    }
394514f5e3Sopenharmony_ci    // 3. Let P be ! MakeBasicObject(« [[ProxyHandler]], [[ProxyTarget]] »).
404514f5e3Sopenharmony_ci    // 6. If IsCallable(target) is true, then P.[[Call]] as specified in 9.5.12.
414514f5e3Sopenharmony_ci
424514f5e3Sopenharmony_ci    // 8. Set the [[ProxyTarget]] internal slot of P to target.
434514f5e3Sopenharmony_ci    // 9. Set the [[ProxyHandler]] internal slot of P to handler.
444514f5e3Sopenharmony_ci    return thread->GetEcmaVM()->GetFactory()->NewJSProxy(target, handler);
454514f5e3Sopenharmony_ci}
464514f5e3Sopenharmony_ci
474514f5e3Sopenharmony_ci// ES6 9.5.1 [[GetPrototypeOf]] ( )
484514f5e3Sopenharmony_ciJSTaggedValue JSProxy::GetPrototype(JSThread *thread, const JSHandle<JSProxy> &proxy)
494514f5e3Sopenharmony_ci{
504514f5e3Sopenharmony_ci    STACK_LIMIT_CHECK(thread, JSTaggedValue::Exception());
514514f5e3Sopenharmony_ci    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
524514f5e3Sopenharmony_ci    // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
534514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handler(thread, proxy->GetHandler());
544514f5e3Sopenharmony_ci    // 2. If handler is null, throw a TypeError exception.
554514f5e3Sopenharmony_ci    if (handler->IsNull()) {
564514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetPrototype: handler is null", JSTaggedValue::Exception());
574514f5e3Sopenharmony_ci    }
584514f5e3Sopenharmony_ci    // 3. Assert: Type(handler) is Object.
594514f5e3Sopenharmony_ci    ASSERT(handler->IsECMAObject());
604514f5e3Sopenharmony_ci    // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
614514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> targetHandle(thread, proxy->GetTarget());
624514f5e3Sopenharmony_ci    // 5. Let trap be GetMethod(handler, "getPrototypeOf").
634514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> name(globalConst->GetHandledGetPrototypeOfString());
644514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trap = JSObject::GetMethod(thread, handler, name);
654514f5e3Sopenharmony_ci    // 6. ReturnIfAbrupt(trap).
664514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
674514f5e3Sopenharmony_ci
684514f5e3Sopenharmony_ci    // 7. If trap is undefined, then Return target.[[GetPrototypeOf]]().
694514f5e3Sopenharmony_ci    if (trap->IsUndefined()) {
704514f5e3Sopenharmony_ci        return JSTaggedValue::GetPrototype(thread, targetHandle);
714514f5e3Sopenharmony_ci    }
724514f5e3Sopenharmony_ci    // 8. Let handlerProto be Call(trap, handler, «target»).
734514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
744514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, trap, handler, undefined, 1);
754514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
764514f5e3Sopenharmony_ci    info->SetCallArg(targetHandle.GetTaggedValue());
774514f5e3Sopenharmony_ci    JSTaggedValue handlerProto = JSFunction::Call(info);
784514f5e3Sopenharmony_ci
794514f5e3Sopenharmony_ci    // 9. ReturnIfAbrupt(handlerProto).
804514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
814514f5e3Sopenharmony_ci    // 10. If Type(handlerProto) is neither Object nor Null, throw a TypeError exception.
824514f5e3Sopenharmony_ci    if (!handlerProto.IsECMAObject() && !handlerProto.IsNull()) {
834514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetPrototype: Type(handlerProto) is neither Object nor Null",
844514f5e3Sopenharmony_ci                                    JSTaggedValue::Exception());
854514f5e3Sopenharmony_ci    }
864514f5e3Sopenharmony_ci    // 11. Let extensibleTarget be IsExtensible(target).
874514f5e3Sopenharmony_ci    // 12. ReturnIfAbrupt(extensibleTarget).
884514f5e3Sopenharmony_ci    // 13. If extensibleTarget is true, return handlerProto.
894514f5e3Sopenharmony_ci    if (targetHandle->IsExtensible(thread)) {
904514f5e3Sopenharmony_ci        return handlerProto;
914514f5e3Sopenharmony_ci    }
924514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
934514f5e3Sopenharmony_ci
944514f5e3Sopenharmony_ci    // 14. Let targetProto be target.[[GetPrototypeOf]]().
954514f5e3Sopenharmony_ci    JSTaggedValue targetProto = JSTaggedValue::GetPrototype(thread, targetHandle);
964514f5e3Sopenharmony_ci    // 15. ReturnIfAbrupt(targetProto).
974514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
984514f5e3Sopenharmony_ci    // 16. If SameValue(handlerProto, targetProto) is false, throw a TypeError exception.
994514f5e3Sopenharmony_ci    if (!JSTaggedValue::SameValue(handlerProto, targetProto)) {
1004514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetPrototype: SameValue(handlerProto, targetProto) is false",
1014514f5e3Sopenharmony_ci                                    JSTaggedValue::Exception());
1024514f5e3Sopenharmony_ci    }
1034514f5e3Sopenharmony_ci    // 17. Return handlerProto.
1044514f5e3Sopenharmony_ci    return handlerProto;
1054514f5e3Sopenharmony_ci}
1064514f5e3Sopenharmony_ci
1074514f5e3Sopenharmony_ci// ES6 9.5.2 [[SetPrototypeOf]] (V)
1084514f5e3Sopenharmony_cibool JSProxy::SetPrototype(JSThread *thread, const JSHandle<JSProxy> &proxy, const JSHandle<JSTaggedValue> &proto)
1094514f5e3Sopenharmony_ci{
1104514f5e3Sopenharmony_ci    STACK_LIMIT_CHECK(thread, false);
1114514f5e3Sopenharmony_ci    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
1124514f5e3Sopenharmony_ci    // 1. Assert: Either Type(V) is Object or Type(V) is Null.
1134514f5e3Sopenharmony_ci    ASSERT(proto->IsECMAObject() || proto->IsNull());
1144514f5e3Sopenharmony_ci    // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
1154514f5e3Sopenharmony_ci    JSTaggedValue handler = proxy->GetHandler();
1164514f5e3Sopenharmony_ci    // 3. If handler is null, throw a TypeError exception.
1174514f5e3Sopenharmony_ci    if (handler.IsNull()) {
1184514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::SetPrototype: handler is null", false);
1194514f5e3Sopenharmony_ci    }
1204514f5e3Sopenharmony_ci    // 4. Assert: Type(handler) is Object.
1214514f5e3Sopenharmony_ci    ASSERT(handler.IsECMAObject());
1224514f5e3Sopenharmony_ci    // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
1234514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> targetHandle(thread, proxy->GetTarget());
1244514f5e3Sopenharmony_ci    // 6. Let trap be GetMethod(handler, "setPrototypeOf").
1254514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> name = globalConst->GetHandledSetPrototypeOfString();
1264514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trap(JSObject::GetMethod(thread, JSHandle<JSTaggedValue>(thread, handler), name));
1274514f5e3Sopenharmony_ci    // 7. ReturnIfAbrupt(trap).
1284514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
1294514f5e3Sopenharmony_ci
1304514f5e3Sopenharmony_ci    // 7. If trap is undefined, then Return target.[[SetPrototypeOf]](V).
1314514f5e3Sopenharmony_ci    if (trap->IsUndefined()) {
1324514f5e3Sopenharmony_ci        return JSTaggedValue::SetPrototype(thread, targetHandle, proto);
1334514f5e3Sopenharmony_ci    }
1344514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handlerTag(thread, proxy->GetHandler());
1354514f5e3Sopenharmony_ci    const uint32_t argsLength = 2;  // 2: target and proto
1364514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
1374514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, trap, handlerTag, undefined, argsLength);
1384514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
1394514f5e3Sopenharmony_ci    info->SetCallArg(targetHandle.GetTaggedValue(), proto.GetTaggedValue());
1404514f5e3Sopenharmony_ci    JSTaggedValue trapResult = JSFunction::Call(info);
1414514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
1424514f5e3Sopenharmony_ci    // 9. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target, V»)).
1434514f5e3Sopenharmony_ci    // If booleanTrapResult is false, return false
1444514f5e3Sopenharmony_ci    bool booleanTrapResult = trapResult.ToBoolean();
1454514f5e3Sopenharmony_ci    if (!booleanTrapResult) {
1464514f5e3Sopenharmony_ci        return false;
1474514f5e3Sopenharmony_ci    }
1484514f5e3Sopenharmony_ci    // 10. ReturnIfAbrupt(booleanTrapResult).
1494514f5e3Sopenharmony_ci    // 11. Let extensibleTarget be IsExtensible(target).
1504514f5e3Sopenharmony_ci    // 12. ReturnIfAbrupt(extensibleTarget).
1514514f5e3Sopenharmony_ci    // 13. If extensibleTarget is true, return booleanTrapResult
1524514f5e3Sopenharmony_ci    if (targetHandle->IsExtensible(thread)) {
1534514f5e3Sopenharmony_ci        return booleanTrapResult;
1544514f5e3Sopenharmony_ci    }
1554514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
1564514f5e3Sopenharmony_ci
1574514f5e3Sopenharmony_ci    // 14. Let targetProto be target.[[GetPrototypeOf]]().
1584514f5e3Sopenharmony_ci    JSTaggedValue targetProto = JSTaggedValue::GetPrototype(thread, targetHandle);
1594514f5e3Sopenharmony_ci    // 15. ReturnIfAbrupt(targetProto).
1604514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
1614514f5e3Sopenharmony_ci
1624514f5e3Sopenharmony_ci    // 16. If booleanTrapResult is true and SameValue(V, targetProto) is false, throw a TypeError exception.
1634514f5e3Sopenharmony_ci    if (booleanTrapResult && !JSTaggedValue::SameValue(proto.GetTaggedValue(), targetProto)) {
1644514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::SetPrototype: TypeError of targetProto and Result", false);
1654514f5e3Sopenharmony_ci    }
1664514f5e3Sopenharmony_ci    // 17. Return handlerProto.
1674514f5e3Sopenharmony_ci    return booleanTrapResult;
1684514f5e3Sopenharmony_ci}
1694514f5e3Sopenharmony_ci
1704514f5e3Sopenharmony_ci// ES6 9.5.3 [[IsExtensible]] ( )
1714514f5e3Sopenharmony_cibool JSProxy::IsExtensible(JSThread *thread, const JSHandle<JSProxy> &proxy)
1724514f5e3Sopenharmony_ci{
1734514f5e3Sopenharmony_ci    STACK_LIMIT_CHECK(thread, false);
1744514f5e3Sopenharmony_ci    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
1754514f5e3Sopenharmony_ci    // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
1764514f5e3Sopenharmony_ci    JSTaggedValue handler = proxy->GetHandler();
1774514f5e3Sopenharmony_ci    // 2. If handler is null, throw a TypeError exception.
1784514f5e3Sopenharmony_ci    if (handler.IsNull()) {
1794514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::IsExtensible: handler is null", false);
1804514f5e3Sopenharmony_ci    }
1814514f5e3Sopenharmony_ci    // 3. Assert: Type(handler) is Object.
1824514f5e3Sopenharmony_ci    ASSERT(handler.IsECMAObject());
1834514f5e3Sopenharmony_ci    // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
1844514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> targetHandle(thread, proxy->GetTarget());
1854514f5e3Sopenharmony_ci    // 5. Let trap be GetMethod(handler, "isExtensible").
1864514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> name = globalConst->GetHandledIsExtensibleString();
1874514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trap(JSObject::GetMethod(thread, JSHandle<JSTaggedValue>(thread, handler), name));
1884514f5e3Sopenharmony_ci    // 6. ReturnIfAbrupt(trap).
1894514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
1904514f5e3Sopenharmony_ci
1914514f5e3Sopenharmony_ci    // 7. If trap is undefined, then Return target.[[IsExtensible]]().
1924514f5e3Sopenharmony_ci    if (trap->IsUndefined()) {
1934514f5e3Sopenharmony_ci        return targetHandle->IsExtensible(thread);
1944514f5e3Sopenharmony_ci    }
1954514f5e3Sopenharmony_ci    // 8. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target»)).
1964514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> newTgt(thread, JSTaggedValue::Undefined());
1974514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handlerTag(thread, proxy->GetHandler());
1984514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
1994514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, trap, handlerTag, undefined, 1);
2004514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
2014514f5e3Sopenharmony_ci    info->SetCallArg(targetHandle.GetTaggedValue());
2024514f5e3Sopenharmony_ci    JSTaggedValue trapResult = JSFunction::Call(info);
2034514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
2044514f5e3Sopenharmony_ci    bool booleanTrapResult = trapResult.ToBoolean();
2054514f5e3Sopenharmony_ci    // 9. ReturnIfAbrupt(booleanTrapResult).
2064514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
2074514f5e3Sopenharmony_ci
2084514f5e3Sopenharmony_ci    // 10. Let targetResult be target.[[IsExtensible]]().
2094514f5e3Sopenharmony_ci    // 11. ReturnIfAbrupt(targetResult).
2104514f5e3Sopenharmony_ci    // 12. If SameValue(booleanTrapResult, targetResult) is false, throw a TypeError exception.
2114514f5e3Sopenharmony_ci    // 13. Return booleanTrapResult.
2124514f5e3Sopenharmony_ci    if (targetHandle->IsExtensible(thread) != booleanTrapResult) {
2134514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::IsExtensible: TypeError of targetResult", false);
2144514f5e3Sopenharmony_ci    }
2154514f5e3Sopenharmony_ci
2164514f5e3Sopenharmony_ci    return booleanTrapResult;
2174514f5e3Sopenharmony_ci}
2184514f5e3Sopenharmony_ci
2194514f5e3Sopenharmony_ci// ES6 9.5.4 [[PreventExtensions]] ( )
2204514f5e3Sopenharmony_cibool JSProxy::PreventExtensions(JSThread *thread, const JSHandle<JSProxy> &proxy)
2214514f5e3Sopenharmony_ci{
2224514f5e3Sopenharmony_ci    STACK_LIMIT_CHECK(thread, false);
2234514f5e3Sopenharmony_ci    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
2244514f5e3Sopenharmony_ci    // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
2254514f5e3Sopenharmony_ci    // 2. If handler is null, throw a TypeError exception.
2264514f5e3Sopenharmony_ci    // 3. Assert: Type(handler) is Object.
2274514f5e3Sopenharmony_ci    // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
2284514f5e3Sopenharmony_ci    // 5. Let trap be GetMethod(handler, "preventExtensions").
2294514f5e3Sopenharmony_ci    // 6. ReturnIfAbrupt(trap).
2304514f5e3Sopenharmony_ci    // 7. If trap is undefined, then
2314514f5e3Sopenharmony_ci    // a. Return target.[[PreventExtensions]]().
2324514f5e3Sopenharmony_ci    // 8. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target»)).
2334514f5e3Sopenharmony_ci    // 9. ReturnIfAbrupt(booleanTrapResult).
2344514f5e3Sopenharmony_ci    JSTaggedValue handler = proxy->GetHandler();
2354514f5e3Sopenharmony_ci    if (handler.IsNull()) {
2364514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::PreventExtensions: handler is null", false);
2374514f5e3Sopenharmony_ci    }
2384514f5e3Sopenharmony_ci    ASSERT(handler.IsECMAObject());
2394514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> targetHandle(thread, proxy->GetTarget());
2404514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> name = globalConst->GetHandledPreventExtensionsString();
2414514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trap(JSObject::GetMethod(thread, JSHandle<JSTaggedValue>(thread, handler), name));
2424514f5e3Sopenharmony_ci    // 6. ReturnIfAbrupt(trap).
2434514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
2444514f5e3Sopenharmony_ci
2454514f5e3Sopenharmony_ci    if (trap->IsUndefined()) {
2464514f5e3Sopenharmony_ci        return JSTaggedValue::PreventExtensions(thread, targetHandle);
2474514f5e3Sopenharmony_ci    }
2484514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handlerTag(thread, proxy->GetHandler());
2494514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
2504514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, trap, handlerTag, undefined, 1);
2514514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
2524514f5e3Sopenharmony_ci    info->SetCallArg(targetHandle.GetTaggedValue());
2534514f5e3Sopenharmony_ci    JSTaggedValue trapResult = JSFunction::Call(info);
2544514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
2554514f5e3Sopenharmony_ci    bool booleanTrapResult = trapResult.ToBoolean();
2564514f5e3Sopenharmony_ci    // 9. ReturnIfAbrupt(booleanTrapResult).
2574514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
2584514f5e3Sopenharmony_ci    // 10. If booleanTrapResult is true, then
2594514f5e3Sopenharmony_ci    // a. Let targetIsExtensible be target.[[IsExtensible]]().
2604514f5e3Sopenharmony_ci    // b. ReturnIfAbrupt(targetIsExtensible).
2614514f5e3Sopenharmony_ci    // c. If targetIsExtensible is true, throw a TypeError exception.
2624514f5e3Sopenharmony_ci    if (booleanTrapResult && targetHandle->IsExtensible(thread)) {
2634514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::PreventExtensions: targetIsExtensible is true", false);
2644514f5e3Sopenharmony_ci    }
2654514f5e3Sopenharmony_ci    // 11. Return booleanTrapResult.
2664514f5e3Sopenharmony_ci    return booleanTrapResult;
2674514f5e3Sopenharmony_ci}
2684514f5e3Sopenharmony_ci
2694514f5e3Sopenharmony_ci// ES6 9.5.5 [[GetOwnProperty]] (P)
2704514f5e3Sopenharmony_cibool JSProxy::GetOwnProperty(JSThread *thread, const JSHandle<JSProxy> &proxy, const JSHandle<JSTaggedValue> &key,
2714514f5e3Sopenharmony_ci                             PropertyDescriptor &desc)
2724514f5e3Sopenharmony_ci{
2734514f5e3Sopenharmony_ci    STACK_LIMIT_CHECK(thread, false);
2744514f5e3Sopenharmony_ci    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
2754514f5e3Sopenharmony_ci    // 1. Assert: IsPropertyKey(P) is true.
2764514f5e3Sopenharmony_ci    ASSERT(JSTaggedValue::IsPropertyKey(key));
2774514f5e3Sopenharmony_ci    // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
2784514f5e3Sopenharmony_ci    // 3. If handler is null, throw a TypeError exception.
2794514f5e3Sopenharmony_ci    // 4. Assert: Type(handler) is Object.
2804514f5e3Sopenharmony_ci    // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
2814514f5e3Sopenharmony_ci    // 6. Let trap be GetMethod(handler, "getOwnPropertyDescriptor").
2824514f5e3Sopenharmony_ci    // 7. ReturnIfAbrupt(trap).
2834514f5e3Sopenharmony_ci    // 8. If trap is undefined, then
2844514f5e3Sopenharmony_ci    // a. Return target.[[GetOwnProperty]](P).
2854514f5e3Sopenharmony_ci    // 9. Let trapResultObj be Call(trap, handler, «target, P»).
2864514f5e3Sopenharmony_ci    // 10. ReturnIfAbrupt(trapResultObj).
2874514f5e3Sopenharmony_ci    // 11. If Type(trapResultObj) is neither Object nor Undefined, throw a TypeError exception
2884514f5e3Sopenharmony_ci    JSTaggedValue handler = proxy->GetHandler();
2894514f5e3Sopenharmony_ci    if (handler.IsNull()) {
2904514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetOwnProperty: handler is null", false);
2914514f5e3Sopenharmony_ci    }
2924514f5e3Sopenharmony_ci    ASSERT(handler.IsECMAObject());
2934514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> targetHandle(thread, proxy->GetTarget());
2944514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> name = globalConst->GetHandledGetOwnPropertyDescriptorString();
2954514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trap(JSObject::GetMethod(thread, JSHandle<JSTaggedValue>(thread, handler), name));
2964514f5e3Sopenharmony_ci    // 7. ReturnIfAbrupt(trap).
2974514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
2984514f5e3Sopenharmony_ci
2994514f5e3Sopenharmony_ci    if (trap->IsUndefined()) {
3004514f5e3Sopenharmony_ci        return JSTaggedValue::GetOwnProperty(thread, targetHandle, key, desc);
3014514f5e3Sopenharmony_ci    }
3024514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handlerTag(thread, proxy->GetHandler());
3034514f5e3Sopenharmony_ci    const uint32_t argsLength = 2;  // 2: target and key
3044514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
3054514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, trap, handlerTag, undefined, argsLength);
3064514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
3074514f5e3Sopenharmony_ci    info->SetCallArg(targetHandle.GetTaggedValue(), key.GetTaggedValue());
3084514f5e3Sopenharmony_ci    JSTaggedValue trapResultObj = JSFunction::Call(info);
3094514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
3104514f5e3Sopenharmony_ci
3114514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> resultHandle(thread, trapResultObj);
3124514f5e3Sopenharmony_ci
3134514f5e3Sopenharmony_ci    // 11. If Type(trapResultObj) is neither Object nor Undefined, throw a TypeError exception.
3144514f5e3Sopenharmony_ci    if (!trapResultObj.IsECMAObject() && !trapResultObj.IsUndefined()) {
3154514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetOwnProperty: TypeError of trapResultObj", false);
3164514f5e3Sopenharmony_ci    }
3174514f5e3Sopenharmony_ci    // 12. Let targetDesc be target.[[GetOwnProperty]](P).
3184514f5e3Sopenharmony_ci    PropertyDescriptor targetDesc(thread);
3194514f5e3Sopenharmony_ci    bool found = JSTaggedValue::GetOwnProperty(thread, targetHandle, key, targetDesc);
3204514f5e3Sopenharmony_ci    // 13. ReturnIfAbrupt(targetDesc).
3214514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
3224514f5e3Sopenharmony_ci
3234514f5e3Sopenharmony_ci    // 14. If trapResultObj is undefined, then
3244514f5e3Sopenharmony_ci    if (resultHandle->IsUndefined()) {
3254514f5e3Sopenharmony_ci        // a. If targetDesc is undefined, return undefined.
3264514f5e3Sopenharmony_ci        if (!found) {
3274514f5e3Sopenharmony_ci            return false;
3284514f5e3Sopenharmony_ci        }
3294514f5e3Sopenharmony_ci        // b. If targetDesc.[[Configurable]] is false, throw a TypeError exception.
3304514f5e3Sopenharmony_ci        if (!targetDesc.IsConfigurable()) {
3314514f5e3Sopenharmony_ci            THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetOwnProperty: targetDesc.[[Configurable]] is false", false);
3324514f5e3Sopenharmony_ci        }
3334514f5e3Sopenharmony_ci        // c. Let extensibleTarget be IsExtensible(target).
3344514f5e3Sopenharmony_ci        // d. ReturnIfAbrupt(extensibleTarget).
3354514f5e3Sopenharmony_ci        // e. Assert: Type(extensibleTarget) is Boolean.
3364514f5e3Sopenharmony_ci        // f. If extensibleTarget is false, throw a TypeError exception.
3374514f5e3Sopenharmony_ci        if (!targetHandle->IsExtensible(thread)) {
3384514f5e3Sopenharmony_ci            THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetOwnProperty: extensibleTarget is false", false);
3394514f5e3Sopenharmony_ci        }
3404514f5e3Sopenharmony_ci        // g. Return undefined.
3414514f5e3Sopenharmony_ci        return false;
3424514f5e3Sopenharmony_ci    }
3434514f5e3Sopenharmony_ci    // 15. Let extensibleTarget be IsExtensible(target).
3444514f5e3Sopenharmony_ci    // 16. ReturnIfAbrupt(extensibleTarget).
3454514f5e3Sopenharmony_ci    // 17. Let resultDesc be ToPropertyDescriptor(trapResultObj).
3464514f5e3Sopenharmony_ci    PropertyDescriptor &resultDesc = desc;
3474514f5e3Sopenharmony_ci    JSObject::ToPropertyDescriptor(thread, resultHandle, resultDesc);
3484514f5e3Sopenharmony_ci    // 18. ReturnIfAbrupt(resultDesc)
3494514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
3504514f5e3Sopenharmony_ci    // 19. Call CompletePropertyDescriptor(resultDesc).
3514514f5e3Sopenharmony_ci    PropertyDescriptor::CompletePropertyDescriptor(thread, resultDesc);
3524514f5e3Sopenharmony_ci    // 20. Let valid be IsCompatiblePropertyDescriptor (extensibleTarget, resultDesc, targetDesc).
3534514f5e3Sopenharmony_ci    bool valid = JSObject::IsCompatiblePropertyDescriptor(targetHandle->IsExtensible(thread), resultDesc, targetDesc);
3544514f5e3Sopenharmony_ci    if (!valid) {
3554514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetOwnProperty: TypeError of valid", false);
3564514f5e3Sopenharmony_ci    }
3574514f5e3Sopenharmony_ci    // 22. If resultDesc.[[Configurable]] is false, then
3584514f5e3Sopenharmony_ci    if (!resultDesc.IsConfigurable()) {
3594514f5e3Sopenharmony_ci        // a. If targetDesc is undefined or targetDesc.[[Configurable]] is true, then
3604514f5e3Sopenharmony_ci        if (!found || targetDesc.IsConfigurable()) {
3614514f5e3Sopenharmony_ci            THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetOwnProperty: TypeError of targetDesc configurable", false);
3624514f5e3Sopenharmony_ci        }
3634514f5e3Sopenharmony_ci        // b. If resultDesc has a [[Writable]] field and resultDesc.[[Writable]] is false, then
3644514f5e3Sopenharmony_ci        //    If targetDesc.[[Writable]] is true, throw a TypeError exception.
3654514f5e3Sopenharmony_ci        if (resultDesc.HasWritable() && !resultDesc.IsWritable() && targetDesc.IsWritable()) {
3664514f5e3Sopenharmony_ci            THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetOwnProperty: TypeError of targetDesc writable", false);
3674514f5e3Sopenharmony_ci        }
3684514f5e3Sopenharmony_ci    }
3694514f5e3Sopenharmony_ci    // 23. Return resultDesc.
3704514f5e3Sopenharmony_ci    return true;
3714514f5e3Sopenharmony_ci}
3724514f5e3Sopenharmony_ci
3734514f5e3Sopenharmony_ci// ES6 9.5.6 [[DefineOwnProperty]] (P, Desc)
3744514f5e3Sopenharmony_cibool JSProxy::DefineOwnProperty(JSThread *thread, const JSHandle<JSProxy> &proxy, const JSHandle<JSTaggedValue> &key,
3754514f5e3Sopenharmony_ci                                const PropertyDescriptor &desc)
3764514f5e3Sopenharmony_ci{
3774514f5e3Sopenharmony_ci    STACK_LIMIT_CHECK(thread, false);
3784514f5e3Sopenharmony_ci    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
3794514f5e3Sopenharmony_ci    // step 1 ~ 10 are almost same as GetOwnProperty
3804514f5e3Sopenharmony_ci    ASSERT(JSTaggedValue::IsPropertyKey(key));
3814514f5e3Sopenharmony_ci    JSTaggedValue handler = proxy->GetHandler();
3824514f5e3Sopenharmony_ci    if (handler.IsNull()) {
3834514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::DefineOwnProperty: handler is Null", false);
3844514f5e3Sopenharmony_ci    }
3854514f5e3Sopenharmony_ci    ASSERT(handler.IsECMAObject());
3864514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> targetHandle(thread, proxy->GetTarget());
3874514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> name = globalConst->GetHandledDefinePropertyString();
3884514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trap(JSObject::GetMethod(thread, JSHandle<JSTaggedValue>(thread, handler), name));
3894514f5e3Sopenharmony_ci    // 7. ReturnIfAbrupt(trap).
3904514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
3914514f5e3Sopenharmony_ci    if (trap->IsUndefined()) {
3924514f5e3Sopenharmony_ci        return JSTaggedValue::DefineOwnProperty(thread, targetHandle, key, desc);
3934514f5e3Sopenharmony_ci    }
3944514f5e3Sopenharmony_ci
3954514f5e3Sopenharmony_ci    // 9. Let descObj be FromPropertyDescriptor(Desc).
3964514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> descObj = JSObject::FromPropertyDescriptor(thread, desc);
3974514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handlerTag(thread, proxy->GetHandler());
3984514f5e3Sopenharmony_ci    const uint32_t argsLength = 3;  // 3: target, key and desc
3994514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
4004514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, trap, handlerTag, undefined, argsLength);
4014514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
4024514f5e3Sopenharmony_ci    info->SetCallArg(targetHandle.GetTaggedValue(), key.GetTaggedValue(), descObj.GetTaggedValue());
4034514f5e3Sopenharmony_ci    JSTaggedValue trapResult = JSFunction::Call(info);
4044514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
4054514f5e3Sopenharmony_ci    bool booleanTrapResult = trapResult.ToBoolean();
4064514f5e3Sopenharmony_ci    // 11. ReturnIfAbrupt(booleanTrapResult).
4074514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
4084514f5e3Sopenharmony_ci    if (!booleanTrapResult) {
4094514f5e3Sopenharmony_ci        return false;
4104514f5e3Sopenharmony_ci    }
4114514f5e3Sopenharmony_ci    // 13. Let targetDesc be target.[[GetOwnProperty]](P).
4124514f5e3Sopenharmony_ci    PropertyDescriptor targetDesc(thread);
4134514f5e3Sopenharmony_ci    bool found = JSTaggedValue::GetOwnProperty(thread, targetHandle, key, targetDesc);
4144514f5e3Sopenharmony_ci    // 14. ReturnIfAbrupt(targetDesc).
4154514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
4164514f5e3Sopenharmony_ci
4174514f5e3Sopenharmony_ci    // 15. Let extensibleTarget be IsExtensible(target).
4184514f5e3Sopenharmony_ci    // 16. ReturnIfAbrupt(extensibleTarget).
4194514f5e3Sopenharmony_ci    // 17. If Desc has a [[Configurable]] field and if Desc.[[Configurable]] is false, then Let settingConfigFalse be
4204514f5e3Sopenharmony_ci    // true.
4214514f5e3Sopenharmony_ci    // 18. Else let settingConfigFalse be false.
4224514f5e3Sopenharmony_ci    bool settingConfigFalse = false;
4234514f5e3Sopenharmony_ci    if (desc.HasConfigurable() && !desc.IsConfigurable()) {
4244514f5e3Sopenharmony_ci        settingConfigFalse = true;
4254514f5e3Sopenharmony_ci    }
4264514f5e3Sopenharmony_ci    // 19. If targetDesc is undefined, then
4274514f5e3Sopenharmony_ci    if (!found) {
4284514f5e3Sopenharmony_ci        // a. If extensibleTarget is false, throw a TypeError exception.
4294514f5e3Sopenharmony_ci        if (!targetHandle->IsExtensible(thread)) {
4304514f5e3Sopenharmony_ci            THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::DefineOwnProperty: extensibleTarget is false", false);
4314514f5e3Sopenharmony_ci        }
4324514f5e3Sopenharmony_ci        // b. If settingConfigFalse is true, throw a TypeError exception.
4334514f5e3Sopenharmony_ci        if (settingConfigFalse) {
4344514f5e3Sopenharmony_ci            THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::DefineOwnProperty: settingConfigFalse is true", false);
4354514f5e3Sopenharmony_ci        }
4364514f5e3Sopenharmony_ci    } else {
4374514f5e3Sopenharmony_ci        // a. If IsCompatiblePropertyDescriptor(extensibleTarget, Desc , targetDesc) is false, throw a TypeError
4384514f5e3Sopenharmony_ci        // exception.
4394514f5e3Sopenharmony_ci        if (!JSObject::IsCompatiblePropertyDescriptor(targetHandle->IsExtensible(thread), desc, targetDesc)) {
4404514f5e3Sopenharmony_ci            THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::DefineOwnProperty: CompatiblePropertyDescriptor err", false);
4414514f5e3Sopenharmony_ci        }
4424514f5e3Sopenharmony_ci        // b. If settingConfigFalse is true and targetDesc.[[Configurable]] is true, throw a TypeError exception.
4434514f5e3Sopenharmony_ci        if (settingConfigFalse && targetDesc.IsConfigurable()) {
4444514f5e3Sopenharmony_ci            THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::DefineOwnProperty: TypeError of settingConfigFalse", false);
4454514f5e3Sopenharmony_ci        }
4464514f5e3Sopenharmony_ci        // c. If IsDataDescriptor(targetDesc) is true, targetDesc.[[Configurable]] is false, and targetDesc.[[Writable]]
4474514f5e3Sopenharmony_ci        // is true, then If Desc has a [[Writable]] field and Desc.[[Writable]] is false, throw a TypeError exception.
4484514f5e3Sopenharmony_ci        if (targetDesc.IsDataDescriptor() && !targetDesc.IsConfigurable() && targetDesc.IsWritable() &&
4494514f5e3Sopenharmony_ci            desc.HasWritable() && !desc.IsWritable()) {
4504514f5e3Sopenharmony_ci            THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::DefineOwnProperty: TypeError of DataDescriptor", false);
4514514f5e3Sopenharmony_ci        }
4524514f5e3Sopenharmony_ci    }
4534514f5e3Sopenharmony_ci    // 21. Return true.
4544514f5e3Sopenharmony_ci    return true;
4554514f5e3Sopenharmony_ci}
4564514f5e3Sopenharmony_ci
4574514f5e3Sopenharmony_ci// ES6 9.5.7 [[HasProperty]] (P)
4584514f5e3Sopenharmony_cibool JSProxy::HasProperty(JSThread *thread, const JSHandle<JSProxy> &proxy, const JSHandle<JSTaggedValue> &key)
4594514f5e3Sopenharmony_ci{
4604514f5e3Sopenharmony_ci    STACK_LIMIT_CHECK(thread, false);
4614514f5e3Sopenharmony_ci    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
4624514f5e3Sopenharmony_ci    // step 1 ~ 10 are almost same as GetOwnProperty
4634514f5e3Sopenharmony_ci    ASSERT(JSTaggedValue::IsPropertyKey(key));
4644514f5e3Sopenharmony_ci    JSTaggedValue handler = proxy->GetHandler();
4654514f5e3Sopenharmony_ci    if (handler.IsNull()) {
4664514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::HasProperty: handler is Null", false);
4674514f5e3Sopenharmony_ci    }
4684514f5e3Sopenharmony_ci    ASSERT(handler.IsECMAObject());
4694514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> targetHandle(thread, proxy->GetTarget());
4704514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> name = globalConst->GetHandledHasString();
4714514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trap(JSObject::GetMethod(thread, JSHandle<JSTaggedValue>(thread, handler), name));
4724514f5e3Sopenharmony_ci    // 7. ReturnIfAbrupt(trap).
4734514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
4744514f5e3Sopenharmony_ci    if (trap->IsUndefined()) {
4754514f5e3Sopenharmony_ci        return JSTaggedValue::HasProperty(thread, targetHandle, key);
4764514f5e3Sopenharmony_ci    }
4774514f5e3Sopenharmony_ci
4784514f5e3Sopenharmony_ci    // 9. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target, P»)).
4794514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handlerTag(thread, proxy->GetHandler());
4804514f5e3Sopenharmony_ci
4814514f5e3Sopenharmony_ci    const uint32_t argsLength = 2;  // 2: target and key
4824514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
4834514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, trap, handlerTag, undefined, argsLength);
4844514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
4854514f5e3Sopenharmony_ci    info->SetCallArg(targetHandle.GetTaggedValue(), key.GetTaggedValue());
4864514f5e3Sopenharmony_ci    JSTaggedValue trapResult = JSFunction::Call(info);
4874514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
4884514f5e3Sopenharmony_ci    bool booleanTrapResult = trapResult.ToBoolean();
4894514f5e3Sopenharmony_ci    // 10. ReturnIfAbrupt(booleanTrapResult).
4904514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
4914514f5e3Sopenharmony_ci
4924514f5e3Sopenharmony_ci    // 11. If booleanTrapResult is false, then
4934514f5e3Sopenharmony_ci    if (!booleanTrapResult) {
4944514f5e3Sopenharmony_ci        // a. Let targetDesc be target.[[GetOwnProperty]](P).
4954514f5e3Sopenharmony_ci        PropertyDescriptor targetDesc(thread);
4964514f5e3Sopenharmony_ci        bool found = JSTaggedValue::GetOwnProperty(thread, targetHandle, key, targetDesc);
4974514f5e3Sopenharmony_ci        // b. ReturnIfAbrupt(targetDesc).
4984514f5e3Sopenharmony_ci        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
4994514f5e3Sopenharmony_ci        // c. If targetDesc is not undefined, then
5004514f5e3Sopenharmony_ci        if (found) {
5014514f5e3Sopenharmony_ci            // i. If targetDesc.[[Configurable]] is false, throw a TypeError exception.
5024514f5e3Sopenharmony_ci            if (!targetDesc.IsConfigurable()) {
5034514f5e3Sopenharmony_ci                THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::HasProperty: TypeError of targetDesc", false);
5044514f5e3Sopenharmony_ci            }
5054514f5e3Sopenharmony_ci            // ii. Let extensibleTarget be IsExtensible(target).
5064514f5e3Sopenharmony_ci            // iii. ReturnIfAbrupt(extensibleTarget).
5074514f5e3Sopenharmony_ci            // iv. If extensibleTarget is false, throw a TypeError exception.
5084514f5e3Sopenharmony_ci            if (!targetHandle->IsExtensible(thread)) {
5094514f5e3Sopenharmony_ci                THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::HasProperty: extensibleTarget is false", false);
5104514f5e3Sopenharmony_ci            }
5114514f5e3Sopenharmony_ci        }
5124514f5e3Sopenharmony_ci    }
5134514f5e3Sopenharmony_ci    return booleanTrapResult;
5144514f5e3Sopenharmony_ci}
5154514f5e3Sopenharmony_ci
5164514f5e3Sopenharmony_ci// ES6 9.5.8 [[Get]] (P, Receiver)
5174514f5e3Sopenharmony_ciOperationResult JSProxy::GetProperty(JSThread *thread, const JSHandle<JSProxy> &proxy,
5184514f5e3Sopenharmony_ci                                     const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &receiver)
5194514f5e3Sopenharmony_ci{
5204514f5e3Sopenharmony_ci    STACK_LIMIT_CHECK(thread, OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false)));
5214514f5e3Sopenharmony_ci    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
5224514f5e3Sopenharmony_ci    // step 1 ~ 10 are almost same as GetOwnProperty
5234514f5e3Sopenharmony_ci    ASSERT(JSTaggedValue::IsPropertyKey(key));
5244514f5e3Sopenharmony_ci    JSTaggedValue handler = proxy->GetHandler();
5254514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> exceptionHandle(thread, JSTaggedValue::Exception());
5264514f5e3Sopenharmony_ci    if (handler.IsNull()) {
5274514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetProperty: handler is Null",
5284514f5e3Sopenharmony_ci                                    OperationResult(thread, exceptionHandle.GetTaggedValue(), PropertyMetaData(false)));
5294514f5e3Sopenharmony_ci    }
5304514f5e3Sopenharmony_ci    ASSERT(handler.IsECMAObject());
5314514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> targetHandle(thread, proxy->GetTarget());
5324514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> name = globalConst->GetHandledGetString();
5334514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trap(JSObject::GetMethod(thread, JSHandle<JSTaggedValue>(thread, handler), name));
5344514f5e3Sopenharmony_ci    // 7. ReturnIfAbrupt(trap).
5354514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(
5364514f5e3Sopenharmony_ci        thread, OperationResult(thread, exceptionHandle.GetTaggedValue(), PropertyMetaData(false)));
5374514f5e3Sopenharmony_ci
5384514f5e3Sopenharmony_ci    if (trap->IsUndefined()) {
5394514f5e3Sopenharmony_ci        return JSTaggedValue::GetProperty(thread, targetHandle, key, receiver);
5404514f5e3Sopenharmony_ci    }
5414514f5e3Sopenharmony_ci    // 9. Let trapResult be Call(trap, handler, «target, P, Receiver»).
5424514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handlerTag(thread, proxy->GetHandler());
5434514f5e3Sopenharmony_ci    const uint32_t argsLength = 3;  // 3: «target, P, Receiver»
5444514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
5454514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, trap, handlerTag, undefined, argsLength);
5464514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(
5474514f5e3Sopenharmony_ci        thread, OperationResult(thread, exceptionHandle.GetTaggedValue(), PropertyMetaData(false)));
5484514f5e3Sopenharmony_ci    info->SetCallArg(targetHandle.GetTaggedValue(), key.GetTaggedValue(), receiver.GetTaggedValue());
5494514f5e3Sopenharmony_ci    JSTaggedValue trapResult = JSFunction::Call(info);
5504514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> resultHandle(thread, trapResult);
5514514f5e3Sopenharmony_ci
5524514f5e3Sopenharmony_ci    // 10. ReturnIfAbrupt(trapResult).
5534514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(
5544514f5e3Sopenharmony_ci        thread, OperationResult(thread, exceptionHandle.GetTaggedValue(), PropertyMetaData(false)));
5554514f5e3Sopenharmony_ci
5564514f5e3Sopenharmony_ci    // 11. Let targetDesc be target.[[GetOwnProperty]](P).
5574514f5e3Sopenharmony_ci    PropertyDescriptor targetDesc(thread);
5584514f5e3Sopenharmony_ci    bool found = JSTaggedValue::GetOwnProperty(thread, targetHandle, key, targetDesc);
5594514f5e3Sopenharmony_ci    // 12. ReturnIfAbrupt(targetDesc).
5604514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(
5614514f5e3Sopenharmony_ci        thread, OperationResult(thread, exceptionHandle.GetTaggedValue(), PropertyMetaData(false)));
5624514f5e3Sopenharmony_ci
5634514f5e3Sopenharmony_ci    // 13. If targetDesc is not undefined, then
5644514f5e3Sopenharmony_ci    if (found) {
5654514f5e3Sopenharmony_ci        // a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is false and targetDesc.[[Writable]] is
5664514f5e3Sopenharmony_ci        // false, then
5674514f5e3Sopenharmony_ci        if (targetDesc.IsDataDescriptor() && !targetDesc.IsConfigurable() && !targetDesc.IsWritable()) {
5684514f5e3Sopenharmony_ci            // i. If SameValue(trapResult, targetDesc.[[Value]]) is false, throw a TypeError exception.
5694514f5e3Sopenharmony_ci            if (!JSTaggedValue::SameValue(resultHandle.GetTaggedValue(), targetDesc.GetValue().GetTaggedValue())) {
5704514f5e3Sopenharmony_ci                THROW_TYPE_ERROR_AND_RETURN(
5714514f5e3Sopenharmony_ci                    thread, "JSProxy::GetProperty: TypeError of trapResult",
5724514f5e3Sopenharmony_ci                    OperationResult(thread, exceptionHandle.GetTaggedValue(), PropertyMetaData(false)));
5734514f5e3Sopenharmony_ci            }
5744514f5e3Sopenharmony_ci        }
5754514f5e3Sopenharmony_ci        // b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]] is false and targetDesc.[[Get]] is
5764514f5e3Sopenharmony_ci        // undefined, then
5774514f5e3Sopenharmony_ci        if (targetDesc.IsAccessorDescriptor() && !targetDesc.IsConfigurable() &&
5784514f5e3Sopenharmony_ci            targetDesc.GetGetter()->IsUndefined()) {
5794514f5e3Sopenharmony_ci            // i. If trapResult is not undefined, throw a TypeError exception.
5804514f5e3Sopenharmony_ci            if (!resultHandle.GetTaggedValue().IsUndefined()) {
5814514f5e3Sopenharmony_ci                THROW_TYPE_ERROR_AND_RETURN(
5824514f5e3Sopenharmony_ci                    thread, "JSProxy::GetProperty: trapResult is not undefined",
5834514f5e3Sopenharmony_ci                    OperationResult(thread, exceptionHandle.GetTaggedValue(), PropertyMetaData(false)));
5844514f5e3Sopenharmony_ci            }
5854514f5e3Sopenharmony_ci        }
5864514f5e3Sopenharmony_ci    }
5874514f5e3Sopenharmony_ci    // 14. Return trapResult.
5884514f5e3Sopenharmony_ci    return OperationResult(thread, resultHandle.GetTaggedValue(), PropertyMetaData(true));
5894514f5e3Sopenharmony_ci}
5904514f5e3Sopenharmony_ci
5914514f5e3Sopenharmony_ci// ES6 9.5.9 [[Set]] ( P, V, Receiver)
5924514f5e3Sopenharmony_cibool JSProxy::SetProperty(JSThread *thread, const JSHandle<JSProxy> &proxy, const JSHandle<JSTaggedValue> &key,
5934514f5e3Sopenharmony_ci                          const JSHandle<JSTaggedValue> &value, const JSHandle<JSTaggedValue> &receiver, bool mayThrow)
5944514f5e3Sopenharmony_ci{
5954514f5e3Sopenharmony_ci    STACK_LIMIT_CHECK(thread, false);
5964514f5e3Sopenharmony_ci    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
5974514f5e3Sopenharmony_ci    // step 1 ~ 10 are almost same as GetOwnProperty
5984514f5e3Sopenharmony_ci    ASSERT(JSTaggedValue::IsPropertyKey(key));
5994514f5e3Sopenharmony_ci    JSTaggedValue handler = proxy->GetHandler();
6004514f5e3Sopenharmony_ci    if (handler.IsNull()) {
6014514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::SetProperty: handler is Null", false);
6024514f5e3Sopenharmony_ci    }
6034514f5e3Sopenharmony_ci    ASSERT(handler.IsECMAObject());
6044514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> targetHandle(thread, proxy->GetTarget());
6054514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> name = globalConst->GetHandledSetString();
6064514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trap(JSObject::GetMethod(thread, JSHandle<JSTaggedValue>(thread, handler), name));
6074514f5e3Sopenharmony_ci    // 7. ReturnIfAbrupt(trap).
6084514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
6094514f5e3Sopenharmony_ci    if (trap->IsUndefined()) {
6104514f5e3Sopenharmony_ci        return JSTaggedValue::SetProperty(thread, targetHandle, key, value, receiver, mayThrow);
6114514f5e3Sopenharmony_ci    }
6124514f5e3Sopenharmony_ci
6134514f5e3Sopenharmony_ci    // 9. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target, P, V, Receiver»))
6144514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handlerTag(thread, proxy->GetHandler());
6154514f5e3Sopenharmony_ci    const uint32_t argsLength = 4;  // 4: «target, P, V, Receiver»
6164514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
6174514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, trap, handlerTag, undefined, argsLength);
6184514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
6194514f5e3Sopenharmony_ci    info->SetCallArg(
6204514f5e3Sopenharmony_ci        targetHandle.GetTaggedValue(), key.GetTaggedValue(), value.GetTaggedValue(), receiver.GetTaggedValue());
6214514f5e3Sopenharmony_ci    JSTaggedValue trapResult = JSFunction::Call(info);
6224514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
6234514f5e3Sopenharmony_ci    bool booleanTrapResult = trapResult.ToBoolean();
6244514f5e3Sopenharmony_ci    // 11. ReturnIfAbrupt(booleanTrapResult).
6254514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
6264514f5e3Sopenharmony_ci    if (!booleanTrapResult) {
6274514f5e3Sopenharmony_ci        if (mayThrow) {
6284514f5e3Sopenharmony_ci            THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::SetProperty: 'set' return false", false);
6294514f5e3Sopenharmony_ci        }
6304514f5e3Sopenharmony_ci        return false;
6314514f5e3Sopenharmony_ci    }
6324514f5e3Sopenharmony_ci    // 13. Let targetDesc be target.[[GetOwnProperty]](P).
6334514f5e3Sopenharmony_ci    PropertyDescriptor targetDesc(thread);
6344514f5e3Sopenharmony_ci    bool found = JSTaggedValue::GetOwnProperty(thread, targetHandle, key, targetDesc);
6354514f5e3Sopenharmony_ci    // 14. If targetDesc is not undefined, then
6364514f5e3Sopenharmony_ci    if (found) {
6374514f5e3Sopenharmony_ci        // a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is false and targetDesc.[[Writable]] is
6384514f5e3Sopenharmony_ci        // false, then
6394514f5e3Sopenharmony_ci        if (targetDesc.IsDataDescriptor() && !targetDesc.IsConfigurable() && !targetDesc.IsWritable()) {
6404514f5e3Sopenharmony_ci            // i. If SameValue(trapResult, targetDesc.[[Value]]) is false, throw a TypeError exception.
6414514f5e3Sopenharmony_ci            if (!JSTaggedValue::SameValue(value, targetDesc.GetValue())) {
6424514f5e3Sopenharmony_ci                THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::SetProperty: TypeError of trapResult", false);
6434514f5e3Sopenharmony_ci            }
6444514f5e3Sopenharmony_ci        }
6454514f5e3Sopenharmony_ci        // b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]] is false, then
6464514f5e3Sopenharmony_ci        // i. If targetDesc.[[Set]] is undefined, throw a TypeError exception.
6474514f5e3Sopenharmony_ci        if (targetDesc.IsAccessorDescriptor() && !targetDesc.IsConfigurable() &&
6484514f5e3Sopenharmony_ci            targetDesc.GetSetter()->IsUndefined()) {
6494514f5e3Sopenharmony_ci            THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::SetProperty: TypeError of AccessorDescriptor", false);
6504514f5e3Sopenharmony_ci        }
6514514f5e3Sopenharmony_ci    }
6524514f5e3Sopenharmony_ci    return true;
6534514f5e3Sopenharmony_ci}
6544514f5e3Sopenharmony_ci
6554514f5e3Sopenharmony_ci// ES6 9.5.10 [[Delete]] (P)
6564514f5e3Sopenharmony_cibool JSProxy::DeleteProperty(JSThread *thread, const JSHandle<JSProxy> &proxy, const JSHandle<JSTaggedValue> &key)
6574514f5e3Sopenharmony_ci{
6584514f5e3Sopenharmony_ci    STACK_LIMIT_CHECK(thread, false);
6594514f5e3Sopenharmony_ci    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
6604514f5e3Sopenharmony_ci    // step 1 ~ 13 are almost same as GetOwnProperty
6614514f5e3Sopenharmony_ci    ASSERT(JSTaggedValue::IsPropertyKey(key));
6624514f5e3Sopenharmony_ci    JSTaggedValue handler = proxy->GetHandler();
6634514f5e3Sopenharmony_ci    if (handler.IsNull()) {
6644514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::DeleteProperty: handler is Null", false);
6654514f5e3Sopenharmony_ci    }
6664514f5e3Sopenharmony_ci    ASSERT(handler.IsECMAObject());
6674514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> targetHandle(thread, proxy->GetTarget());
6684514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> name = globalConst->GetHandledDeletePropertyString();
6694514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trap(JSObject::GetMethod(thread, JSHandle<JSTaggedValue>(thread, handler), name));
6704514f5e3Sopenharmony_ci    // 7. ReturnIfAbrupt(trap).
6714514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
6724514f5e3Sopenharmony_ci    if (trap->IsUndefined()) {
6734514f5e3Sopenharmony_ci        return JSTaggedValue::DeleteProperty(thread, targetHandle, key);
6744514f5e3Sopenharmony_ci    }
6754514f5e3Sopenharmony_ci
6764514f5e3Sopenharmony_ci    // 9. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target, P»)).
6774514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> newTgt(thread, JSTaggedValue::Undefined());
6784514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handlerTag(thread, proxy->GetHandler());
6794514f5e3Sopenharmony_ci    const uint32_t argsLength = 2;  // 2: target and key
6804514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
6814514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, trap, handlerTag, undefined, argsLength);
6824514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
6834514f5e3Sopenharmony_ci    info->SetCallArg(targetHandle.GetTaggedValue(), key.GetTaggedValue());
6844514f5e3Sopenharmony_ci    JSTaggedValue trapResult = JSFunction::Call(info);
6854514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
6864514f5e3Sopenharmony_ci    bool booleanTrapResult = trapResult.ToBoolean();
6874514f5e3Sopenharmony_ci    // 11. ReturnIfAbrupt(booleanTrapResult).
6884514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
6894514f5e3Sopenharmony_ci    if (!booleanTrapResult) {
6904514f5e3Sopenharmony_ci        return false;
6914514f5e3Sopenharmony_ci    }
6924514f5e3Sopenharmony_ci    // 13. Let targetDesc be target.[[GetOwnProperty]](P).
6934514f5e3Sopenharmony_ci    PropertyDescriptor targetDesc(thread);
6944514f5e3Sopenharmony_ci    bool found = JSTaggedValue::GetOwnProperty(thread, targetHandle, key, targetDesc);
6954514f5e3Sopenharmony_ci    // 14. If targetDesc is undefined, return true.
6964514f5e3Sopenharmony_ci    if (!found) {
6974514f5e3Sopenharmony_ci        return true;
6984514f5e3Sopenharmony_ci    }
6994514f5e3Sopenharmony_ci    // 15. If targetDesc.[[Configurable]] is false, throw a TypeError exception.
7004514f5e3Sopenharmony_ci    if (!targetDesc.IsConfigurable()) {
7014514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::DeleteProperty: targetDesc is not Configurable", false);
7024514f5e3Sopenharmony_ci    }
7034514f5e3Sopenharmony_ci    if (!targetHandle->IsExtensible(thread)) {
7044514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::DeleteProperty: targetHandle is not Extensible", false);
7054514f5e3Sopenharmony_ci    }
7064514f5e3Sopenharmony_ci    // 16. Return true.
7074514f5e3Sopenharmony_ci    return true;
7084514f5e3Sopenharmony_ci}
7094514f5e3Sopenharmony_ci
7104514f5e3Sopenharmony_ci// ES6 9.5.12 [[OwnPropertyKeys]] ()
7114514f5e3Sopenharmony_ciJSHandle<TaggedArray> JSProxy::OwnPropertyKeys(JSThread *thread, const JSHandle<JSProxy> &proxy)
7124514f5e3Sopenharmony_ci{
7134514f5e3Sopenharmony_ci    STACK_LIMIT_CHECK(thread, JSHandle<TaggedArray>(thread, JSTaggedValue::Exception()));
7144514f5e3Sopenharmony_ci    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
7154514f5e3Sopenharmony_ci    // step 1 ~ 4 get ProxyHandler and ProxyTarget
7164514f5e3Sopenharmony_ci    JSTaggedValue handler = proxy->GetHandler();
7174514f5e3Sopenharmony_ci    if (handler.IsNull()) {
7184514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "OwnPropertyKeys: handler is null",
7194514f5e3Sopenharmony_ci                                    JSHandle<TaggedArray>(thread, JSTaggedValue::Exception()));
7204514f5e3Sopenharmony_ci    }
7214514f5e3Sopenharmony_ci
7224514f5e3Sopenharmony_ci    ASSERT(handler.IsECMAObject());
7234514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> targetHandle(thread, proxy->GetTarget());
7244514f5e3Sopenharmony_ci
7254514f5e3Sopenharmony_ci    // 5.Let trap be GetMethod(handler, "ownKeys").
7264514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> key = globalConst->GetHandledOwnKeysString();
7274514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handlerHandle(thread, handler);
7284514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trap(JSObject::GetMethod(thread, handlerHandle, key));
7294514f5e3Sopenharmony_ci
7304514f5e3Sopenharmony_ci    // 6.ReturnIfAbrupt(trap).
7314514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
7324514f5e3Sopenharmony_ci
7334514f5e3Sopenharmony_ci    // 7.If trap is undefined, then
7344514f5e3Sopenharmony_ci    //    a.Return target.[[OwnPropertyKeys]]().
7354514f5e3Sopenharmony_ci    if (trap->IsUndefined()) {
7364514f5e3Sopenharmony_ci        return JSTaggedValue::GetOwnPropertyKeys(thread, targetHandle);
7374514f5e3Sopenharmony_ci    }
7384514f5e3Sopenharmony_ci
7394514f5e3Sopenharmony_ci    // 8.Let trapResultArray be Call(trap, handler, «target»).
7404514f5e3Sopenharmony_ci    JSHandle<JSFunction> tagFunc(targetHandle);
7414514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
7424514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, trap, handlerHandle, undefined, 1);
7434514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
7444514f5e3Sopenharmony_ci    info->SetCallArg(targetHandle.GetTaggedValue());
7454514f5e3Sopenharmony_ci    JSTaggedValue res = JSFunction::Call(info);
7464514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
7474514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trapResArr(thread, res);
7484514f5e3Sopenharmony_ci
7494514f5e3Sopenharmony_ci    // 9.Let trapResult be CreateListFromArrayLike(trapResultArray, «String, Symbol»).
7504514f5e3Sopenharmony_ci    // 10.ReturnIfAbrupt(trapResult)
7514514f5e3Sopenharmony_ci    // If trapResult contains any duplicate entries, throw a TypeError exception.
7524514f5e3Sopenharmony_ci    JSHandle<TaggedArray> trapRes(
7534514f5e3Sopenharmony_ci        JSObject::CreateListFromArrayLike<ElementTypes::STRING_AND_SYMBOL>(thread, trapResArr));
7544514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
7554514f5e3Sopenharmony_ci
7564514f5e3Sopenharmony_ci    if (trapRes->HasDuplicateEntry()) {
7574514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "OwnPropertyKeys: contains duplicate entries",
7584514f5e3Sopenharmony_ci                                    JSHandle<TaggedArray>(thread, JSTaggedValue::Exception()));
7594514f5e3Sopenharmony_ci    }
7604514f5e3Sopenharmony_ci
7614514f5e3Sopenharmony_ci    // 11.Let extensibleTarget be IsExtensible(target).
7624514f5e3Sopenharmony_ci    bool extensibleTarget = targetHandle->IsExtensible(thread);
7634514f5e3Sopenharmony_ci
7644514f5e3Sopenharmony_ci    // 12.ReturnIfAbrupt(extensibleTarget).
7654514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
7664514f5e3Sopenharmony_ci
7674514f5e3Sopenharmony_ci    // 13.Let targetKeys be target.[[OwnPropertyKeys]]().
7684514f5e3Sopenharmony_ci    JSHandle<TaggedArray> targetKeys = JSTaggedValue::GetOwnPropertyKeys(thread, targetHandle);
7694514f5e3Sopenharmony_ci
7704514f5e3Sopenharmony_ci    // 14.ReturnIfAbrupt(targetKeys).
7714514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
7724514f5e3Sopenharmony_ci
7734514f5e3Sopenharmony_ci    // 15.Assert: targetKeys is a List containing only String and Symbol values.
7744514f5e3Sopenharmony_ci    // 16.Let targetConfigurableKeys be an empty List.
7754514f5e3Sopenharmony_ci    // 17.Let targetNonconfigurableKeys be an empty List.
7764514f5e3Sopenharmony_ci    // 18.Repeat, for each element key of targetKeys,
7774514f5e3Sopenharmony_ci    //     a.Let desc be target.[[GetOwnProperty]](key).
7784514f5e3Sopenharmony_ci    //     b.ReturnIfAbrupt(desc).
7794514f5e3Sopenharmony_ci    //     c.If desc is not undefined and desc.[[Configurable]] is false, then
7804514f5e3Sopenharmony_ci    //        i.Append key as an element of targetNonconfigurableKeys.
7814514f5e3Sopenharmony_ci    //     d.Else,
7824514f5e3Sopenharmony_ci    //        i.Append key as an element of targetConfigurableKeys.
7834514f5e3Sopenharmony_ci    uint32_t length = targetKeys->GetLength();
7844514f5e3Sopenharmony_ci    JSHandle<TaggedArray> tgtCfigKeys = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(length);
7854514f5e3Sopenharmony_ci    JSHandle<TaggedArray> tgtNoCfigKeys = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(length);
7864514f5e3Sopenharmony_ci
7874514f5e3Sopenharmony_ci    uint32_t cfigLength = 0;
7884514f5e3Sopenharmony_ci    uint32_t noCfigLength = 0;
7894514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < length; i++) {
7904514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> targetKey(thread, targetKeys->Get(i));
7914514f5e3Sopenharmony_ci        ASSERT(targetKey->IsStringOrSymbol());
7924514f5e3Sopenharmony_ci
7934514f5e3Sopenharmony_ci        PropertyDescriptor desc(thread);
7944514f5e3Sopenharmony_ci        JSTaggedValue::GetOwnProperty(thread, targetHandle, targetKey, desc);
7954514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
7964514f5e3Sopenharmony_ci
7974514f5e3Sopenharmony_ci        if (!desc.IsEmpty() && !desc.IsConfigurable()) {
7984514f5e3Sopenharmony_ci            tgtNoCfigKeys->Set(thread, noCfigLength, targetKey);
7994514f5e3Sopenharmony_ci            noCfigLength++;
8004514f5e3Sopenharmony_ci        } else {
8014514f5e3Sopenharmony_ci            tgtCfigKeys->Set(thread, cfigLength, targetKey);
8024514f5e3Sopenharmony_ci            cfigLength++;
8034514f5e3Sopenharmony_ci        }
8044514f5e3Sopenharmony_ci    }
8054514f5e3Sopenharmony_ci
8064514f5e3Sopenharmony_ci    // 19.If extensibleTarget is true and targetNonconfigurableKeys is empty, then
8074514f5e3Sopenharmony_ci    //     a.Return trapResult.
8084514f5e3Sopenharmony_ci    if (extensibleTarget && (cfigLength == 0)) {
8094514f5e3Sopenharmony_ci        return trapRes;
8104514f5e3Sopenharmony_ci    }
8114514f5e3Sopenharmony_ci
8124514f5e3Sopenharmony_ci    // 20.Let uncheckedResultKeys be a new List which is a copy of trapResult.
8134514f5e3Sopenharmony_ci    JSHandle<TaggedArray> uncheckFesKeys =
8144514f5e3Sopenharmony_ci        thread->GetEcmaVM()->GetFactory()->CopyArray(trapRes, trapRes->GetLength(), trapRes->GetLength());
8154514f5e3Sopenharmony_ci    uint32_t uncheckLength = uncheckFesKeys->GetLength();
8164514f5e3Sopenharmony_ci
8174514f5e3Sopenharmony_ci    // 21.Repeat, for each key that is an element of targetNonconfigurableKeys,
8184514f5e3Sopenharmony_ci    //     a.If key is not an element of uncheckedResultKeys, throw a TypeError exception.
8194514f5e3Sopenharmony_ci    //     b.Remove key from uncheckedResultKeys
8204514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < noCfigLength; i++) {
8214514f5e3Sopenharmony_ci        uint32_t idx = uncheckFesKeys->GetIdx(tgtNoCfigKeys->Get(i));
8224514f5e3Sopenharmony_ci        if (idx == TaggedArray::MAX_ARRAY_INDEX) {
8234514f5e3Sopenharmony_ci            THROW_TYPE_ERROR_AND_RETURN(thread, "OwnPropertyKeys: key is not an element of uncheckedResultKeys",
8244514f5e3Sopenharmony_ci                                        JSHandle<TaggedArray>(thread, JSTaggedValue::Exception()));
8254514f5e3Sopenharmony_ci        }
8264514f5e3Sopenharmony_ci        uncheckFesKeys->Set(thread, idx, JSTaggedValue::Hole());
8274514f5e3Sopenharmony_ci        uncheckLength--;
8284514f5e3Sopenharmony_ci    }
8294514f5e3Sopenharmony_ci
8304514f5e3Sopenharmony_ci    // 22.If extensibleTarget is true, return trapResult.
8314514f5e3Sopenharmony_ci    if (extensibleTarget) {
8324514f5e3Sopenharmony_ci        return trapRes;
8334514f5e3Sopenharmony_ci    }
8344514f5e3Sopenharmony_ci
8354514f5e3Sopenharmony_ci    // 23.Repeat, for each key that is an element of targetConfigurableKeys,
8364514f5e3Sopenharmony_ci    //     a.If key is not an element of uncheckedResultKeys, throw a TypeError exception.
8374514f5e3Sopenharmony_ci    //     b.Remove key from uncheckedResultKeys
8384514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < cfigLength; i++) {
8394514f5e3Sopenharmony_ci        uint32_t idx = uncheckFesKeys->GetIdx(tgtCfigKeys->Get(i));
8404514f5e3Sopenharmony_ci        if (idx == TaggedArray::MAX_ARRAY_INDEX) {
8414514f5e3Sopenharmony_ci            THROW_TYPE_ERROR_AND_RETURN(thread, "OwnPropertyKeys: key is not an element of uncheckedResultKeys",
8424514f5e3Sopenharmony_ci                                        JSHandle<TaggedArray>(thread, JSTaggedValue::Exception()));
8434514f5e3Sopenharmony_ci        }
8444514f5e3Sopenharmony_ci        uncheckFesKeys->Set(thread, idx, JSTaggedValue::Hole());
8454514f5e3Sopenharmony_ci        uncheckLength--;
8464514f5e3Sopenharmony_ci    }
8474514f5e3Sopenharmony_ci
8484514f5e3Sopenharmony_ci    // 24.If uncheckedResultKeys is not empty, throw a TypeError exception.
8494514f5e3Sopenharmony_ci    if (uncheckLength != 0) {
8504514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "OwnPropertyKeys: uncheckedResultKeys is not empty",
8514514f5e3Sopenharmony_ci                                    JSHandle<TaggedArray>(thread, JSTaggedValue::Exception()));
8524514f5e3Sopenharmony_ci    }
8534514f5e3Sopenharmony_ci
8544514f5e3Sopenharmony_ci    // 25.Return trapResult.
8554514f5e3Sopenharmony_ci    return trapRes;
8564514f5e3Sopenharmony_ci}
8574514f5e3Sopenharmony_ci
8584514f5e3Sopenharmony_ciJSHandle<TaggedArray> JSProxy::GetAllPropertyKeys(JSThread *thread, const JSHandle<JSProxy> &proxy, uint32_t filter)
8594514f5e3Sopenharmony_ci{
8604514f5e3Sopenharmony_ci    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
8614514f5e3Sopenharmony_ci
8624514f5e3Sopenharmony_ci    JSTaggedValue handler = proxy->GetHandler();
8634514f5e3Sopenharmony_ci    if (handler.IsNull()) {
8644514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "OwnPropertyKeys: handler is null",
8654514f5e3Sopenharmony_ci                                    JSHandle<TaggedArray>(thread, JSTaggedValue::Exception()));
8664514f5e3Sopenharmony_ci    }
8674514f5e3Sopenharmony_ci
8684514f5e3Sopenharmony_ci    ASSERT(handler.IsECMAObject());
8694514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> targetHandle(thread, proxy->GetTarget());
8704514f5e3Sopenharmony_ci
8714514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> key = globalConst->GetHandledOwnKeysString();
8724514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handlerHandle(thread, handler);
8734514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trap(JSObject::GetMethod(thread, handlerHandle, key));
8744514f5e3Sopenharmony_ci
8754514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
8764514f5e3Sopenharmony_ci
8774514f5e3Sopenharmony_ci    if (trap->IsUndefined()) {
8784514f5e3Sopenharmony_ci        return JSTaggedValue::GetAllPropertyKeys(thread, targetHandle, filter);
8794514f5e3Sopenharmony_ci    }
8804514f5e3Sopenharmony_ci
8814514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
8824514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, trap, handlerHandle, undefined, 1);
8834514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
8844514f5e3Sopenharmony_ci    info->SetCallArg(targetHandle.GetTaggedValue());
8854514f5e3Sopenharmony_ci    JSTaggedValue res = JSFunction::Call(info);
8864514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
8874514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> trapResArr(thread, res);
8884514f5e3Sopenharmony_ci
8894514f5e3Sopenharmony_ci    JSHandle<TaggedArray> trapRes(
8904514f5e3Sopenharmony_ci        JSObject::CreateListFromArrayLike<ElementTypes::STRING_AND_SYMBOL>(thread, trapResArr));
8914514f5e3Sopenharmony_ci    JSHandle<TaggedArray> ownKeys = JSTaggedValue::GetOwnPropertyKeys(thread, targetHandle);
8924514f5e3Sopenharmony_ci    JSHandle<TaggedArray> reciveArray = JSTaggedValue::GetAllPropertyKeys(thread, targetHandle, filter);
8934514f5e3Sopenharmony_ci
8944514f5e3Sopenharmony_ci    uint32_t trapResLength = trapRes->GetLength();
8954514f5e3Sopenharmony_ci    uint32_t ownKeysLength = ownKeys->GetLength();
8964514f5e3Sopenharmony_ci    uint32_t reciveArrayLength = reciveArray->GetLength();
8974514f5e3Sopenharmony_ci    uint32_t newArrayLength = reciveArrayLength + trapResLength - ownKeysLength;
8984514f5e3Sopenharmony_ci
8994514f5e3Sopenharmony_ci    JSHandle<TaggedArray> resArray = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(newArrayLength);
9004514f5e3Sopenharmony_ci
9014514f5e3Sopenharmony_ci    uint32_t elementIndex = 0;
9024514f5e3Sopenharmony_ci    if (filter & NATIVE_KEY_SKIP_SYMBOLS) {
9034514f5e3Sopenharmony_ci        for (uint32_t index = 0; index < reciveArrayLength; index++) {
9044514f5e3Sopenharmony_ci            if (!ownKeys->Get(index).IsSymbol()) {
9054514f5e3Sopenharmony_ci                resArray->Set(thread, elementIndex, reciveArray->Get(index));
9064514f5e3Sopenharmony_ci                elementIndex++;
9074514f5e3Sopenharmony_ci            }
9084514f5e3Sopenharmony_ci        }
9094514f5e3Sopenharmony_ci        return resArray;
9104514f5e3Sopenharmony_ci    }
9114514f5e3Sopenharmony_ci
9124514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < trapResLength; i++) {
9134514f5e3Sopenharmony_ci        resArray->Set(thread, i, trapRes->Get(i));
9144514f5e3Sopenharmony_ci    }
9154514f5e3Sopenharmony_ci
9164514f5e3Sopenharmony_ci    uint32_t index = ownKeysLength;
9174514f5e3Sopenharmony_ci    for (uint32_t j = 0; j < reciveArrayLength - ownKeysLength; j++) {
9184514f5e3Sopenharmony_ci        resArray->Set(thread, trapResLength + j, reciveArray->Get(index));
9194514f5e3Sopenharmony_ci        index++;
9204514f5e3Sopenharmony_ci    }
9214514f5e3Sopenharmony_ci    return resArray;
9224514f5e3Sopenharmony_ci}
9234514f5e3Sopenharmony_ci
9244514f5e3Sopenharmony_ci// ES6 9.5.13 [[Call]] (thisArgument, argumentsList)
9254514f5e3Sopenharmony_ciJSTaggedValue JSProxy::CallInternal(EcmaRuntimeCallInfo *info)
9264514f5e3Sopenharmony_ci{
9274514f5e3Sopenharmony_ci    if (info == nullptr) {
9284514f5e3Sopenharmony_ci        return JSTaggedValue::Exception();
9294514f5e3Sopenharmony_ci    }
9304514f5e3Sopenharmony_ci
9314514f5e3Sopenharmony_ci    JSThread *thread = info->GetThread();
9324514f5e3Sopenharmony_ci    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
9334514f5e3Sopenharmony_ci    JSHandle<JSProxy> proxy(info->GetFunction());
9344514f5e3Sopenharmony_ci    // step 1 ~ 4 get ProxyHandler and ProxyTarget
9354514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handler(thread, proxy->GetHandler());
9364514f5e3Sopenharmony_ci    if (handler->IsNull()) {
9374514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "Call: handler is null", JSTaggedValue::Exception());
9384514f5e3Sopenharmony_ci    }
9394514f5e3Sopenharmony_ci    ASSERT(handler->IsECMAObject());
9404514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> target(thread, proxy->GetTarget());
9414514f5e3Sopenharmony_ci
9424514f5e3Sopenharmony_ci    // 5.Let trap be GetMethod(handler, "apply").
9434514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> key(globalConst->GetHandledApplyString());
9444514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> method = JSObject::GetMethod(thread, handler, key);
9454514f5e3Sopenharmony_ci
9464514f5e3Sopenharmony_ci    // 6.ReturnIfAbrupt(trap).
9474514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
9484514f5e3Sopenharmony_ci    uint32_t argc = info->GetArgsNumber();
9494514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> thisArg = info->GetThis();
9504514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
9514514f5e3Sopenharmony_ci    // 7.If trap is undefined, then
9524514f5e3Sopenharmony_ci    //   a.Return Call(target, thisArgument, argumentsList).
9534514f5e3Sopenharmony_ci    if (method->IsUndefined()) {
9544514f5e3Sopenharmony_ci        EcmaRuntimeCallInfo *runtimeInfo =
9554514f5e3Sopenharmony_ci            EcmaInterpreter::NewRuntimeCallInfo(thread, target, thisArg, undefined, argc);
9564514f5e3Sopenharmony_ci        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
9574514f5e3Sopenharmony_ci        runtimeInfo->SetCallArg(argc, 0, info, 0);
9584514f5e3Sopenharmony_ci        return JSFunction::Call(runtimeInfo);
9594514f5e3Sopenharmony_ci    }
9604514f5e3Sopenharmony_ci    // 8.Let argArray be CreateArrayFromList(argumentsList).
9614514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
9624514f5e3Sopenharmony_ci    JSHandle<TaggedArray> taggedArray = factory->NewTaggedArray(argc);
9634514f5e3Sopenharmony_ci    for (uint32_t index = 0; index < argc; ++index) {
9644514f5e3Sopenharmony_ci        taggedArray->Set(thread, index, info->GetCallArg(index));
9654514f5e3Sopenharmony_ci    }
9664514f5e3Sopenharmony_ci    JSHandle<JSArray> arrHandle = JSArray::CreateArrayFromList(thread, taggedArray);
9674514f5e3Sopenharmony_ci
9684514f5e3Sopenharmony_ci    // 9.Return Call(trap, handler, «target, thisArgument, argArray»).
9694514f5e3Sopenharmony_ci    const uint32_t argsLength = 3;  // 3: «target, thisArgument, argArray»
9704514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *runtimeInfo =
9714514f5e3Sopenharmony_ci        EcmaInterpreter::NewRuntimeCallInfo(thread, method, handler, undefined, argsLength);
9724514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
9734514f5e3Sopenharmony_ci    runtimeInfo->SetCallArg(target.GetTaggedValue(), thisArg.GetTaggedValue(), arrHandle.GetTaggedValue());
9744514f5e3Sopenharmony_ci    return JSFunction::Call(runtimeInfo);
9754514f5e3Sopenharmony_ci}
9764514f5e3Sopenharmony_ci
9774514f5e3Sopenharmony_ci// ES6 9.5.14 [[Construct]] ( argumentsList, newTarget)
9784514f5e3Sopenharmony_ciJSTaggedValue JSProxy::ConstructInternal(EcmaRuntimeCallInfo *info)
9794514f5e3Sopenharmony_ci{
9804514f5e3Sopenharmony_ci    if (info == nullptr) {
9814514f5e3Sopenharmony_ci        return JSTaggedValue::Exception();
9824514f5e3Sopenharmony_ci    }
9834514f5e3Sopenharmony_ci    JSThread *thread = info->GetThread();
9844514f5e3Sopenharmony_ci    // check stack overflow because infinite recursion may occur
9854514f5e3Sopenharmony_ci    if (thread->DoStackLimitCheck()) {
9864514f5e3Sopenharmony_ci        return JSTaggedValue::Exception();
9874514f5e3Sopenharmony_ci    }
9884514f5e3Sopenharmony_ci
9894514f5e3Sopenharmony_ci    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
9904514f5e3Sopenharmony_ci    // step 1 ~ 4 get ProxyHandler and ProxyTarget
9914514f5e3Sopenharmony_ci    JSHandle<JSProxy> proxy(info->GetFunction());
9924514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> handler(thread, proxy->GetHandler());
9934514f5e3Sopenharmony_ci    if (handler->IsNull()) {
9944514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor: handler is null", JSTaggedValue::Exception());
9954514f5e3Sopenharmony_ci    }
9964514f5e3Sopenharmony_ci    ASSERT(handler->IsECMAObject());
9974514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> target(thread, proxy->GetTarget());
9984514f5e3Sopenharmony_ci
9994514f5e3Sopenharmony_ci    // 5.Let trap be GetMethod(handler, "construct").
10004514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> key(globalConst->GetHandledProxyConstructString());
10014514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> method = JSObject::GetMethod(thread, handler, key);
10024514f5e3Sopenharmony_ci
10034514f5e3Sopenharmony_ci    // 6.ReturnIfAbrupt(trap).
10044514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
10054514f5e3Sopenharmony_ci    // 7.If trap is undefined, then
10064514f5e3Sopenharmony_ci    //   a.Assert: target has a [[Construct]] internal method.
10074514f5e3Sopenharmony_ci    //   b.Return Construct(target, argumentsList, newTarget).
10084514f5e3Sopenharmony_ci    if (method->IsUndefined()) {
10094514f5e3Sopenharmony_ci        if (!target->IsConstructor()) {
10104514f5e3Sopenharmony_ci            THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
10114514f5e3Sopenharmony_ci        }
10124514f5e3Sopenharmony_ci        ASSERT(target->IsConstructor());
10134514f5e3Sopenharmony_ci        info->SetFunction(target.GetTaggedValue());
10144514f5e3Sopenharmony_ci        return JSFunction::Construct(info);
10154514f5e3Sopenharmony_ci    }
10164514f5e3Sopenharmony_ci
10174514f5e3Sopenharmony_ci    // 8.Let argArray be CreateArrayFromList(argumentsList).
10184514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
10194514f5e3Sopenharmony_ci    uint32_t argc = info->GetArgsNumber();
10204514f5e3Sopenharmony_ci    JSHandle<TaggedArray> taggedArray = factory->NewTaggedArray(argc);
10214514f5e3Sopenharmony_ci    for (uint32_t index = 0; index < argc; ++index) {
10224514f5e3Sopenharmony_ci        taggedArray->Set(thread, index, info->GetCallArg(index));
10234514f5e3Sopenharmony_ci    }
10244514f5e3Sopenharmony_ci    JSHandle<JSArray> arrHandle = JSArray::CreateArrayFromList(thread, taggedArray);
10254514f5e3Sopenharmony_ci
10264514f5e3Sopenharmony_ci    // step 8 ~ 9 Call(trap, handler, «target, argArray, newTarget »).
10274514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> newTarget(thread, info->GetNewTargetValue());
10284514f5e3Sopenharmony_ci    const uint32_t argsLength = 3;  // 3: «target, argArray, newTarget »
10294514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
10304514f5e3Sopenharmony_ci
10314514f5e3Sopenharmony_ci    JSTaggedType *currentSp = reinterpret_cast<JSTaggedType *>(info);
10324514f5e3Sopenharmony_ci    InterpretedEntryFrame *currentEntryState = InterpretedEntryFrame::GetFrameFromSp(currentSp);
10334514f5e3Sopenharmony_ci    JSTaggedType *prevSp =  currentEntryState->base.prev;
10344514f5e3Sopenharmony_ci    thread->SetCurrentSPFrame(prevSp);
10354514f5e3Sopenharmony_ci
10364514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *runtimeInfo =
10374514f5e3Sopenharmony_ci        EcmaInterpreter::NewRuntimeCallInfo(thread, method, handler, undefined, argsLength);
10384514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
10394514f5e3Sopenharmony_ci    runtimeInfo->SetCallArg(target.GetTaggedValue(), arrHandle.GetTaggedValue(), newTarget.GetTaggedValue());
10404514f5e3Sopenharmony_ci    JSTaggedValue newObj = JSFunction::Call(runtimeInfo);
10414514f5e3Sopenharmony_ci
10424514f5e3Sopenharmony_ci    // 10.ReturnIfAbrupt(newObj).
10434514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
10444514f5e3Sopenharmony_ci    // 11.If Type(newObj) is not Object, throw a TypeError exception.
10454514f5e3Sopenharmony_ci    if (!newObj.IsECMAObject()) {
10464514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "new object is not object", JSTaggedValue::Exception());
10474514f5e3Sopenharmony_ci    }
10484514f5e3Sopenharmony_ci    // 12.Return newObj.
10494514f5e3Sopenharmony_ci    return newObj;
10504514f5e3Sopenharmony_ci}
10514514f5e3Sopenharmony_ci
10524514f5e3Sopenharmony_cibool JSProxy::IsArray(JSThread *thread) const
10534514f5e3Sopenharmony_ci{
10544514f5e3Sopenharmony_ci    // check stack overflow because infinite recursion may occur
10554514f5e3Sopenharmony_ci    if (thread->DoStackLimitCheck()) {
10564514f5e3Sopenharmony_ci        return false;
10574514f5e3Sopenharmony_ci    }
10584514f5e3Sopenharmony_ci    if (GetHandler().IsNull()) {
10594514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::IsArray: handler is null", false);
10604514f5e3Sopenharmony_ci    }
10614514f5e3Sopenharmony_ci    return GetTarget().IsArray(thread);
10624514f5e3Sopenharmony_ci}
10634514f5e3Sopenharmony_ci
10644514f5e3Sopenharmony_ciJSHandle<JSTaggedValue> JSProxy::GetSourceTarget(JSThread *thread) const
10654514f5e3Sopenharmony_ci{
10664514f5e3Sopenharmony_ci    JSMutableHandle<JSProxy> proxy(thread, JSTaggedValue(this));
10674514f5e3Sopenharmony_ci    JSMutableHandle<JSTaggedValue> target(thread, proxy->GetTarget());
10684514f5e3Sopenharmony_ci    while (target->IsJSProxy()) {
10694514f5e3Sopenharmony_ci        proxy.Update(target.GetTaggedValue());
10704514f5e3Sopenharmony_ci        target.Update(proxy->GetTarget());
10714514f5e3Sopenharmony_ci    }
10724514f5e3Sopenharmony_ci    return target;
10734514f5e3Sopenharmony_ci}
10744514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
1075