1/* 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecmascript/base/builtins_base.h" 17#include "ecmascript/ecma_runtime_call_info.h" 18#include "ecmascript/ecma_string.h" 19#include "ecmascript/ecma_vm.h" 20#include "ecmascript/global_env.h" 21#include "ecmascript/interpreter/interpreter.h" 22#include "ecmascript/js_function.h" 23#include "ecmascript/js_handle.h" 24#include "ecmascript/js_hclass.h" 25#include "ecmascript/js_object-inl.h" 26#include "ecmascript/js_proxy.h" 27#include "ecmascript/js_tagged_value-inl.h" 28#include "ecmascript/object_factory.h" 29#include "ecmascript/tests/test_helper.h" 30 31using namespace panda::ecmascript; 32using namespace panda::ecmascript::base; 33 34namespace panda::test { 35class JSProxyTest : public BaseTestWithScope<false> { 36}; 37 38static JSFunction *JSObjectTestCreate(JSThread *thread) 39{ 40 EcmaVM *ecmaVM = thread->GetEcmaVM(); 41 JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv(); 42 return globalEnv->GetObjectFunction().GetObject<JSFunction>(); 43} 44 45HWTEST_F_L0(JSProxyTest, ProxyCreate) 46{ 47 JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread)); 48 JSHandle<JSTaggedValue> targetHandle( 49 thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(hclass), hclass)); 50 51 JSHandle<JSTaggedValue> key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("x")); 52 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1)); 53 JSObject::SetProperty(thread, targetHandle, key, value); 54 EXPECT_EQ(JSObject::GetProperty(thread, targetHandle, key).GetValue()->GetInt(), 1); 55 56 JSHandle<JSTaggedValue> handlerHandle( 57 thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(hclass), hclass)); 58 EXPECT_TRUE(handlerHandle->IsECMAObject()); 59 60 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 61 EXPECT_TRUE(*proxyHandle != nullptr); 62 63 EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle, key).GetValue()->GetInt(), 1); 64 PropertyDescriptor desc(thread); 65 JSProxy::GetOwnProperty(thread, proxyHandle, key, desc); 66 EXPECT_EQ(desc.GetValue()->GetInt(), 1); 67} 68 69JSHandle<JSProxy> SetPropertyCommon(JSThread *thread, JSHandle<JSTaggedValue>& targetHandle, 70 JSHandle<JSTaggedValue>& handlerHandle, JSHandle<JSTaggedValue>& key, JSHandle<JSTaggedValue>& value) 71{ 72 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 73 // 1. handler has no "get" 74 JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread)); 75 targetHandle = JSHandle<JSTaggedValue>(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 76 EXPECT_TRUE(targetHandle->IsECMAObject()); 77 JSObject::SetProperty(thread, targetHandle, key, value); 78 EXPECT_EQ(JSObject::GetProperty(thread, targetHandle, key).GetValue()->GetInt(), 1); 79 80 handlerHandle = JSHandle<JSTaggedValue>(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 81 EXPECT_TRUE(handlerHandle->IsECMAObject()); 82 83 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 84 return proxyHandle; 85} 86 87// ES6 9.5.8 [[Get]] (P, Receiver) 88// Called by the following function 89JSTaggedValue HandlerGetProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv) 90{ 91 return JSTaggedValue(10); // 10 : test case 92} 93 94HWTEST_F_L0(JSProxyTest, GetProperty) 95{ 96 JSHandle<JSTaggedValue> targetHandle; 97 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 98 JSHandle<JSTaggedValue> key(factory->NewFromASCII("x")); 99 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1)); 100 JSHandle<JSTaggedValue> handlerHandle; 101 JSHandle<JSProxy> proxyHandle = SetPropertyCommon(thread, targetHandle, handlerHandle, key, value); 102 EXPECT_TRUE(*proxyHandle != nullptr); 103 104 EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle, key).GetValue()->GetInt(), 1); 105 106 // 2. handler has "get" 107 EcmaVM *vm = thread->GetEcmaVM(); 108 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 109 JSHandle<JSTaggedValue> getKey = thread->GlobalConstants()->GetHandledGetString(); 110 JSHandle<JSTaggedValue> getHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerGetProperty))); 111 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), getKey, getHandle); 112 113 JSHandle<JSProxy> proxyHandle2(JSProxy::ProxyCreate(thread, targetHandle, handlerHandle)); 114 EXPECT_TRUE(*proxyHandle2 != nullptr); 115 JSHandle<JSTaggedValue> key2(factory->NewFromASCII("y")); 116 EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle2, key2).GetValue()->GetInt(), 10); 117} 118 119// ES6 9.5.5 [[GetOwnProperty]] (P) 120// Called by the following function 121JSTaggedValue HandlerGetOwnProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv) 122{ 123 return JSTaggedValue(JSTaggedValue::Undefined()); 124} 125 126HWTEST_F_L0(JSProxyTest, GetOwnProperty) 127{ 128 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 129 JSHandle<JSTaggedValue> targetHandle; 130 JSHandle<JSTaggedValue> handlerHandle; 131 JSHandle<JSTaggedValue> key(factory->NewFromASCII("x")); 132 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1)); 133 JSHandle<JSProxy> proxyHandle = SetPropertyCommon(thread, targetHandle, handlerHandle, key, value); 134 EXPECT_TRUE(*proxyHandle != nullptr); 135 136 PropertyDescriptor desc(thread); 137 JSProxy::GetOwnProperty(thread, proxyHandle, key, desc); 138 EXPECT_EQ(desc.GetValue()->GetInt(), 1); 139 140 // 2. handler has "get" 141 EcmaVM *vm = thread->GetEcmaVM(); 142 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 143 JSHandle<JSTaggedValue> defineKey = thread->GlobalConstants()->GetHandledGetOwnPropertyDescriptorString(); 144 JSHandle<JSTaggedValue> defineHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerGetOwnProperty))); 145 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), defineKey, defineHandle); 146 147 JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 148 EXPECT_TRUE(*proxyHandle2 != nullptr); 149 JSHandle<JSTaggedValue> key2(factory->NewFromASCII("y")); 150 PropertyDescriptor desc2(thread); 151 EXPECT_FALSE(JSProxy::GetOwnProperty(thread, proxyHandle2, key2, desc2)); 152} 153 154// ES6 9.5.9 [[Set]] ( P, V, Receiver) 155JSTaggedValue HandlerSetProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv) 156{ 157 return JSTaggedValue(JSTaggedValue::False()); 158} 159 160JSHandle<JSProxy> PropertyCommon(JSThread *thread, JSHandle<JSTaggedValue>& targetHandle, 161 JSHandle<JSTaggedValue>& handlerHandle, JSHandle<JSTaggedValue>& key, uint32_t value = 0) 162{ 163 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 164 JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread)); 165 targetHandle = JSHandle<JSTaggedValue>(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 166 EXPECT_TRUE(targetHandle->IsECMAObject()); 167 168 if (value) { 169 PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(value))); 170 JSObject::DefineOwnProperty(thread, JSHandle<JSObject>::Cast(targetHandle), key, desc); 171 } 172 handlerHandle = JSHandle<JSTaggedValue>(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 173 EXPECT_TRUE(handlerHandle->IsECMAObject()); 174 175 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 176 return proxyHandle; 177} 178 179HWTEST_F_L0(JSProxyTest, SetProperty) 180{ 181 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 182 JSHandle<JSTaggedValue> key(factory->NewFromASCII("x")); 183 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1)); 184 JSHandle<JSTaggedValue> targetHandle; 185 JSHandle<JSTaggedValue> handlerHandle; 186 JSHandle<JSProxy> proxyHandle = PropertyCommon(thread, targetHandle, handlerHandle, key); 187 EXPECT_TRUE(*proxyHandle != nullptr); 188 189 EXPECT_TRUE(JSProxy::SetProperty(thread, proxyHandle, key, value)); 190 EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle, key).GetValue()->GetInt(), 1); 191 EXPECT_EQ(JSObject::GetProperty(thread, targetHandle, key).GetValue()->GetInt(), 1); 192 193 // 2. handler has "set" 194 EcmaVM *vm = thread->GetEcmaVM(); 195 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 196 JSHandle<JSTaggedValue> setKey = thread->GlobalConstants()->GetHandledSetString(); 197 JSHandle<JSTaggedValue> setHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerSetProperty))); 198 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), setKey, setHandle); 199 200 JSHandle<JSProxy> proxyHandle2(JSProxy::ProxyCreate(thread, targetHandle, handlerHandle)); 201 EXPECT_TRUE(*proxyHandle2 != nullptr); 202 JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(10)); 203 EXPECT_FALSE(JSProxy::SetProperty(thread, proxyHandle2, key, value2)); 204 EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle2, key).GetValue()->GetInt(), 1); 205} 206 207// ES6 9.5.6 [[DefineOwnProperty]] (P, Desc) 208JSTaggedValue HandlerDefineOwnProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv) 209{ 210 return JSTaggedValue(JSTaggedValue::False()); 211} 212 213HWTEST_F_L0(JSProxyTest, DefineOwnProperty) 214{ 215 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 216 JSHandle<JSTaggedValue> key(factory->NewFromASCII("x")); 217 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1)); 218 JSHandle<JSTaggedValue> targetHandle; 219 JSHandle<JSTaggedValue> handlerHandle; 220 JSHandle<JSProxy> proxyHandle = PropertyCommon(thread, targetHandle, handlerHandle, key); 221 EXPECT_TRUE(*proxyHandle != nullptr); 222 223 PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1))); 224 EXPECT_TRUE(JSProxy::DefineOwnProperty(thread, proxyHandle, key, desc)); 225 EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle, key).GetValue()->GetInt(), 1); 226 EXPECT_EQ(JSObject::GetProperty(thread, targetHandle, key).GetValue()->GetInt(), 1); 227 228 // 2. handler has "defineProperty" 229 EcmaVM *vm = thread->GetEcmaVM(); 230 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 231 JSHandle<JSTaggedValue> setKey = thread->GlobalConstants()->GetHandledDefinePropertyString(); 232 JSHandle<JSTaggedValue> setHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerDefineOwnProperty))); 233 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), setKey, setHandle); 234 235 JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 236 EXPECT_TRUE(*proxyHandle2 != nullptr); 237 PropertyDescriptor desc2(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(10))); 238 EXPECT_FALSE(JSProxy::DefineOwnProperty(thread, proxyHandle, key, desc2)); 239 EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle2, key).GetValue()->GetInt(), 1); 240} 241 242JSTaggedValue HandlerDeleteProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv) 243{ 244 return JSTaggedValue(JSTaggedValue::False()); 245} 246 247// ES6 9.5.10 [[Delete]] (P) 248HWTEST_F_L0(JSProxyTest, DeleteProperty) 249{ 250 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 251 JSHandle<JSTaggedValue> key(factory->NewFromASCII("x")); 252 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1)); 253 JSHandle<JSTaggedValue> targetHandle; 254 JSHandle<JSTaggedValue> handlerHandle; 255 JSHandle<JSProxy> proxyHandle = PropertyCommon(thread, targetHandle, handlerHandle, key); 256 EXPECT_TRUE(*proxyHandle != nullptr); 257 258 PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), true, true, true); 259 EXPECT_TRUE(JSProxy::DefineOwnProperty(thread, proxyHandle, key, desc)); 260 EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle, key).GetValue()->GetInt(), 1); 261 EXPECT_EQ(JSObject::GetProperty(thread, targetHandle, key).GetValue()->GetInt(), 1); 262 EXPECT_TRUE(JSProxy::DeleteProperty(thread, proxyHandle, key)); 263 PropertyDescriptor resDesc(thread); 264 JSProxy::GetOwnProperty(thread, proxyHandle, key, resDesc); 265 EXPECT_TRUE(JSTaggedValue::SameValue(resDesc.GetValue().GetTaggedValue(), JSTaggedValue::Undefined())); 266 267 // 2. handler has "deleteProperty" 268 EcmaVM *vm = thread->GetEcmaVM(); 269 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 270 JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledDeletePropertyString(); 271 JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerDeleteProperty))); 272 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle); 273 274 JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 275 EXPECT_TRUE(*proxyHandle2 != nullptr); 276 PropertyDescriptor desc2(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), true, true, true); 277 EXPECT_TRUE(JSProxy::DefineOwnProperty(thread, proxyHandle2, key, desc2)); 278 EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle2, key).GetValue()->GetInt(), 1); 279 EXPECT_FALSE(JSProxy::DeleteProperty(thread, proxyHandle2, key)); 280} 281 282JSTaggedValue HandlerGetPrototype([[maybe_unused]] EcmaRuntimeCallInfo *argv) 283{ 284 return JSTaggedValue(JSTaggedValue::Null()); 285} 286 287// ES6 9.5.1 [[GetPrototypeOf]] ( ) 288HWTEST_F_L0(JSProxyTest, GetPrototypeOf) 289{ 290 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 291 // 1. handler has no "GetPrototypeOf" 292 JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread)); 293 JSHandle<JSTaggedValue> proto(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 294 JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 295 EXPECT_TRUE(targetHandle->IsECMAObject()); 296 JSObject::SetPrototype(thread, JSHandle<JSObject>(targetHandle), proto); 297 EXPECT_TRUE( 298 JSTaggedValue::SameValue(JSTaggedValue::GetPrototype(thread, targetHandle), proto.GetTaggedValue())); 299 300 JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 301 EXPECT_TRUE(handlerHandle->IsECMAObject()); 302 303 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 304 EXPECT_TRUE(*proxyHandle != nullptr); 305 306 EXPECT_TRUE(JSTaggedValue::SameValue(JSProxy::GetPrototype(thread, proxyHandle), proto.GetTaggedValue())); 307 308 // 2. handler has "GetPrototypeOf" 309 EcmaVM *vm = thread->GetEcmaVM(); 310 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 311 JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledGetPrototypeOfString(); 312 JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerGetPrototype))); 313 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle); 314 315 JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 316 EXPECT_TRUE(*proxyHandle2 != nullptr); 317 EXPECT_TRUE(JSTaggedValue::SameValue(JSProxy::GetPrototype(thread, proxyHandle2), JSTaggedValue::Null())); 318} 319 320JSTaggedValue HandlerSetPrototype([[maybe_unused]] EcmaRuntimeCallInfo *argv) 321{ 322 return JSTaggedValue(JSTaggedValue::False()); 323} 324 325// ES6 9.5.2 [[SetPrototypeOf]] (V) 326HWTEST_F_L0(JSProxyTest, SetPrototypeOf) 327{ 328 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 329 // 1. handler has no "SetPrototypeOf" 330 JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread)); 331 JSHandle<JSTaggedValue> proto(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 332 JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 333 EXPECT_TRUE(targetHandle->IsECMAObject()); 334 335 JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 336 EXPECT_TRUE(handlerHandle->IsECMAObject()); 337 338 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 339 EXPECT_TRUE(*proxyHandle != nullptr); 340 341 JSProxy::SetPrototype(thread, proxyHandle, proto); 342 EXPECT_TRUE( 343 JSTaggedValue::SameValue(JSTaggedValue::GetPrototype(thread, targetHandle), proto.GetTaggedValue())); 344 345 // 2. handler has "SetPrototypeOf" 346 EcmaVM *vm = thread->GetEcmaVM(); 347 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 348 JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledSetPrototypeOfString(); 349 JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerSetPrototype))); 350 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle); 351 352 JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 353 EXPECT_TRUE(*proxyHandle2 != nullptr); 354 EXPECT_FALSE(JSProxy::SetPrototype(thread, proxyHandle2, proto)); 355} 356 357JSTaggedValue HandlerIsExtensible([[maybe_unused]] EcmaRuntimeCallInfo *argv) 358{ 359 return JSTaggedValue(JSTaggedValue::False()); 360} 361 362// ES6 9.5.3 [[IsExtensible]] ( ) 363HWTEST_F_L0(JSProxyTest, IsExtensible) 364{ 365 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 366 // 1. handler has no "IsExtensible" 367 JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread)); 368 JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 369 EXPECT_TRUE(targetHandle->IsECMAObject()); 370 371 JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 372 EXPECT_TRUE(handlerHandle->IsECMAObject()); 373 374 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 375 EXPECT_TRUE(*proxyHandle != nullptr); 376 377 bool status1 = JSProxy::IsExtensible(thread, proxyHandle); 378 bool status2 = JSHandle<JSObject>::Cast(targetHandle)->IsExtensible(); 379 EXPECT_TRUE(status1 == status2); 380 381 // 2. handler has "IsExtensible" 382 EcmaVM *vm = thread->GetEcmaVM(); 383 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 384 JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledIsExtensibleString(); 385 JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerIsExtensible))); 386 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle); 387 388 JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 389 EXPECT_TRUE(*proxyHandle2 != nullptr); 390 EXPECT_FALSE(JSProxy::IsExtensible(thread, proxyHandle2)); 391} 392 393JSTaggedValue HandlerPreventExtensions([[maybe_unused]] EcmaRuntimeCallInfo *argv) 394{ 395 return JSTaggedValue(JSTaggedValue::False()); 396} 397 398// ES6 9.5.4 [[PreventExtensions]] ( ) 399HWTEST_F_L0(JSProxyTest, PreventExtensions) 400{ 401 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 402 // 1. handler has no "PreventExtensions" 403 JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread)); 404 JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 405 EXPECT_TRUE(targetHandle->IsECMAObject()); 406 407 JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 408 EXPECT_TRUE(handlerHandle->IsECMAObject()); 409 410 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 411 EXPECT_TRUE(*proxyHandle != nullptr); 412 413 bool status1 = JSProxy::PreventExtensions(thread, proxyHandle); 414 EXPECT_TRUE(status1); 415 bool status2 = JSHandle<JSObject>::Cast(targetHandle)->IsExtensible(); 416 EXPECT_FALSE(status2); 417 418 // 2. handler has "PreventExtensions" 419 EcmaVM *vm = thread->GetEcmaVM(); 420 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 421 JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledPreventExtensionsString(); 422 JSHandle<JSTaggedValue> funcHandle( 423 factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerPreventExtensions))); 424 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle); 425 426 JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 427 EXPECT_TRUE(*proxyHandle2 != nullptr); 428 EXPECT_FALSE(JSProxy::PreventExtensions(thread, proxyHandle2)); 429} 430 431JSTaggedValue HandlerHasProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv) 432{ 433 return JSTaggedValue(JSTaggedValue::False()); 434} 435 436// ES6 9.5.7 [[HasProperty]] (P) 437HWTEST_F_L0(JSProxyTest, HasProperty) 438{ 439 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 440 JSHandle<JSTaggedValue> key(factory->NewFromASCII("x")); 441 JSHandle<JSTaggedValue> targetHandle; 442 JSHandle<JSTaggedValue> handlerHandle; 443 JSHandle<JSProxy> proxyHandle = PropertyCommon(thread, targetHandle, handlerHandle, key, 1); // 1: value 444 EXPECT_TRUE(*proxyHandle != nullptr); 445 446 EXPECT_TRUE(JSProxy::HasProperty(thread, proxyHandle, key)); 447 448 // 2. handler has "HasProperty" 449 EcmaVM *vm = thread->GetEcmaVM(); 450 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 451 JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledHasString(); 452 JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerHasProperty))); 453 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle); 454 455 JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 456 EXPECT_TRUE(*proxyHandle2 != nullptr); 457 EXPECT_FALSE(JSProxy::HasProperty(thread, proxyHandle2, key)); 458} 459 460JSTaggedValue HandlerOwnPropertyKeys([[maybe_unused]] EcmaRuntimeCallInfo *argv) 461{ 462 auto thread = argv->GetThread(); 463 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 464 JSHandle<JSArray> arr = factory->NewJSArray(); 465 return JSTaggedValue(arr.GetTaggedValue()); 466} 467 468// ES6 9.5.12 [[OwnPropertyKeys]] () 469HWTEST_F_L0(JSProxyTest, OwnPropertyKeys) 470{ 471 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 472 JSHandle<JSTaggedValue> key(factory->NewFromASCII("x")); 473 JSHandle<JSTaggedValue> targetHandle; 474 JSHandle<JSTaggedValue> handlerHandle; 475 JSHandle<JSProxy> proxyHandle = PropertyCommon(thread, targetHandle, handlerHandle, key, 1); // 1: value 476 EXPECT_TRUE(*proxyHandle != nullptr); 477 JSHandle<TaggedArray> res = JSProxy::OwnPropertyKeys(thread, proxyHandle); 478 479 EXPECT_TRUE(JSTaggedValue::SameValue(res->Get(0), key.GetTaggedValue())); 480 481 // 2. handler has "OwnPropertyKeys" 482 EcmaVM *vm = thread->GetEcmaVM(); 483 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 484 JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledOwnKeysString(); 485 JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerOwnPropertyKeys))); 486 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle); 487 488 JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 489 EXPECT_TRUE(*proxyHandle2 != nullptr); 490 JSHandle<TaggedArray> res2 = JSProxy::OwnPropertyKeys(thread, proxyHandle2); 491 EXPECT_TRUE(res2->GetLength() == 0U || !JSTaggedValue::SameValue(res2->Get(0), key.GetTaggedValue())); 492} 493 494JSTaggedValue HandlerCall([[maybe_unused]] EcmaRuntimeCallInfo *argv) 495{ 496 return JSTaggedValue(JSTaggedValue::False()); 497} 498JSTaggedValue HandlerFunction([[maybe_unused]] EcmaRuntimeCallInfo *argv) 499{ 500 return JSTaggedValue(JSTaggedValue::True()); 501} 502 503// ES6 9.5.13 [[Call]] (thisArgument, argumentsList) 504HWTEST_F_L0(JSProxyTest, Call) 505{ 506 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 507 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 508 // 1. handler has no "Call" 509 JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread)); 510 JSHandle<JSTaggedValue> targetHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerFunction))); 511 EXPECT_TRUE(targetHandle->IsECMAObject()); 512 513 JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 514 EXPECT_TRUE(handlerHandle->IsECMAObject()); 515 516 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 517 EXPECT_TRUE(*proxyHandle != nullptr); 518 519 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 520 EcmaRuntimeCallInfo *info = 521 EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle<JSTaggedValue>(proxyHandle), 522 JSHandle<JSTaggedValue>(proxyHandle), undefined, 0); 523 JSTaggedValue res = JSProxy::CallInternal(info); 524 EXPECT_TRUE(JSTaggedValue::SameValue(res, JSTaggedValue::True())); 525 526 // 2. handler has "Call" 527 JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledApplyString(); 528 JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerCall))); 529 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle); 530 531 JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 532 EXPECT_TRUE(*proxyHandle2 != nullptr); 533 534 EcmaRuntimeCallInfo *runtimeInfo = 535 EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle<JSTaggedValue>(proxyHandle2), 536 JSHandle<JSTaggedValue>(proxyHandle2), undefined, 0); 537 JSTaggedValue res2 = JSProxy::CallInternal(runtimeInfo); 538 EXPECT_TRUE(JSTaggedValue::SameValue(res2, JSTaggedValue::False())); 539} 540 541JSTaggedValue HandlerConstruct([[maybe_unused]] EcmaRuntimeCallInfo *argv) 542{ 543 auto thread = argv->GetThread(); 544 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 545 JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread)); 546 JSHandle<JSTaggedValue> obj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 547 548 JSHandle<JSTaggedValue> key(factory->NewFromASCII("x")); 549 PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(2))); // 2 : test case 550 JSObject::DefineOwnProperty(argv->GetThread(), JSHandle<JSObject>::Cast(obj), key, desc); 551 return JSTaggedValue(obj.GetTaggedValue()); 552} 553JSTaggedValue HandlerConFunc([[maybe_unused]] EcmaRuntimeCallInfo *argv) 554{ 555 auto thread = argv->GetThread(); 556 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 557 JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread)); 558 JSHandle<JSTaggedValue> obj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 559 560 JSHandle<JSTaggedValue> key(factory->NewFromASCII("x")); 561 PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1))); 562 JSObject::DefineOwnProperty(argv->GetThread(), JSHandle<JSObject>::Cast(obj), key, desc); 563 return JSTaggedValue(obj.GetTaggedValue()); 564} 565 566// ES6 9.5.14 [[Construct]] ( argumentsList, newTarget) 567HWTEST_F_L0(JSProxyTest, Construct) 568{ 569 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 570 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 571 // 1. handler has no "Construct" 572 JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread)); 573 JSHandle<JSTaggedValue> targetHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerConFunc))); 574 JSHandle<JSFunction>::Cast(targetHandle)->GetJSHClass()->SetConstructor(true); 575 EXPECT_TRUE(targetHandle->IsECMAObject()); 576 577 JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass)); 578 EXPECT_TRUE(handlerHandle->IsECMAObject()); 579 580 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 581 EXPECT_TRUE(*proxyHandle != nullptr); 582 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 583 EcmaRuntimeCallInfo *info = 584 EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle<JSTaggedValue>(proxyHandle), handlerHandle, undefined, 0); 585 JSTaggedValue res = JSProxy::ConstructInternal(info); 586 JSHandle<JSTaggedValue> taggedRes(thread, res); 587 JSHandle<JSTaggedValue> key(factory->NewFromASCII("x")); 588 EXPECT_EQ(JSObject::GetProperty(thread, taggedRes, key).GetValue()->GetInt(), 1); 589 590 // 2. handler has "Construct" 591 JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledProxyConstructString(); 592 JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerConstruct))); 593 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle); 594 595 JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle); 596 EXPECT_TRUE(*proxyHandle2 != nullptr); 597 EcmaRuntimeCallInfo *runtimeInfo = 598 EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle<JSTaggedValue>(proxyHandle2), targetHandle, undefined, 0); 599 JSTaggedValue res2 = JSProxy::ConstructInternal(runtimeInfo); 600 JSHandle<JSTaggedValue> taggedRes2(thread, res2); 601 EXPECT_EQ(JSObject::GetProperty(thread, taggedRes2, key).GetValue()->GetInt(), 2); 602} 603} // namespace panda::test 604