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