• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
31 using namespace panda::ecmascript;
32 using namespace panda::ecmascript::base;
33 
34 namespace panda::test {
35 class JSProxyTest : public BaseTestWithScope<false> {
36 };
37 
JSObjectTestCreate(JSThread * thread)38 static JSFunction *JSObjectTestCreate(JSThread *thread)
39 {
40     EcmaVM *ecmaVM = thread->GetEcmaVM();
41     JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
42     return globalEnv->GetObjectFunction().GetObject<JSFunction>();
43 }
44 
HWTEST_F_L0(JSProxyTest,ProxyCreate)45 HWTEST_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 
SetPropertyCommon(JSThread * thread,JSHandle<JSTaggedValue> & targetHandle,JSHandle<JSTaggedValue> & handlerHandle,JSHandle<JSTaggedValue> & key,JSHandle<JSTaggedValue> & value)69 JSHandle<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
HandlerGetProperty(EcmaRuntimeCallInfo * argv)89 JSTaggedValue HandlerGetProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv)
90 {
91     return JSTaggedValue(10); // 10 : test case
92 }
93 
HWTEST_F_L0(JSProxyTest,GetProperty)94 HWTEST_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
HandlerGetOwnProperty(EcmaRuntimeCallInfo * argv)121 JSTaggedValue HandlerGetOwnProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv)
122 {
123     return JSTaggedValue(JSTaggedValue::Undefined());
124 }
125 
HWTEST_F_L0(JSProxyTest,GetOwnProperty)126 HWTEST_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)
HandlerSetProperty(EcmaRuntimeCallInfo * argv)155 JSTaggedValue HandlerSetProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv)
156 {
157     return JSTaggedValue(JSTaggedValue::False());
158 }
159 
PropertyCommon(JSThread * thread,JSHandle<JSTaggedValue> & targetHandle,JSHandle<JSTaggedValue> & handlerHandle,JSHandle<JSTaggedValue> & key,uint32_t value=0)160 JSHandle<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 
HWTEST_F_L0(JSProxyTest,SetProperty)179 HWTEST_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)
HandlerDefineOwnProperty(EcmaRuntimeCallInfo * argv)208 JSTaggedValue HandlerDefineOwnProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv)
209 {
210     return JSTaggedValue(JSTaggedValue::False());
211 }
212 
HWTEST_F_L0(JSProxyTest,DefineOwnProperty)213 HWTEST_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 
HandlerDeleteProperty(EcmaRuntimeCallInfo * argv)242 JSTaggedValue HandlerDeleteProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv)
243 {
244     return JSTaggedValue(JSTaggedValue::False());
245 }
246 
247 // ES6 9.5.10 [[Delete]] (P)
HWTEST_F_L0(JSProxyTest,DeleteProperty)248 HWTEST_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(thread, 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 
HandlerGetPrototype(EcmaRuntimeCallInfo * argv)282 JSTaggedValue HandlerGetPrototype([[maybe_unused]] EcmaRuntimeCallInfo *argv)
283 {
284     return JSTaggedValue(JSTaggedValue::Null());
285 }
286 
287 // ES6 9.5.1 [[GetPrototypeOf]] ( )
HWTEST_F_L0(JSProxyTest,GetPrototypeOf)288 HWTEST_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(thread, 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(thread, 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(thread, JSProxy::GetPrototype(thread, proxyHandle2), JSTaggedValue::Null()));
318 }
319 
HandlerSetPrototype(EcmaRuntimeCallInfo * argv)320 JSTaggedValue HandlerSetPrototype([[maybe_unused]] EcmaRuntimeCallInfo *argv)
321 {
322     return JSTaggedValue(JSTaggedValue::False());
323 }
324 
325 // ES6 9.5.2 [[SetPrototypeOf]] (V)
HWTEST_F_L0(JSProxyTest,SetPrototypeOf)326 HWTEST_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(thread, 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 
HandlerIsExtensible(EcmaRuntimeCallInfo * argv)357 JSTaggedValue HandlerIsExtensible([[maybe_unused]] EcmaRuntimeCallInfo *argv)
358 {
359     return JSTaggedValue(JSTaggedValue::False());
360 }
361 
362 // ES6 9.5.3 [[IsExtensible]] ( )
HWTEST_F_L0(JSProxyTest,IsExtensible)363 HWTEST_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 
HandlerPreventExtensions(EcmaRuntimeCallInfo * argv)393 JSTaggedValue HandlerPreventExtensions([[maybe_unused]] EcmaRuntimeCallInfo *argv)
394 {
395     return JSTaggedValue(JSTaggedValue::False());
396 }
397 
398 // ES6 9.5.4 [[PreventExtensions]] ( )
HWTEST_F_L0(JSProxyTest,PreventExtensions)399 HWTEST_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 
HandlerHasProperty(EcmaRuntimeCallInfo * argv)431 JSTaggedValue HandlerHasProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv)
432 {
433     return JSTaggedValue(JSTaggedValue::False());
434 }
435 
436 // ES6 9.5.7 [[HasProperty]] (P)
HWTEST_F_L0(JSProxyTest,HasProperty)437 HWTEST_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 
HandlerOwnPropertyKeys(EcmaRuntimeCallInfo * argv)460 JSTaggedValue 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]] ()
HWTEST_F_L0(JSProxyTest,OwnPropertyKeys)469 HWTEST_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(thread, res->Get(thread, 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 ||
492                 !JSTaggedValue::SameValue(thread, res2->Get(thread, 0), key.GetTaggedValue()));
493 }
494 
HandlerCall(EcmaRuntimeCallInfo * argv)495 JSTaggedValue HandlerCall([[maybe_unused]] EcmaRuntimeCallInfo *argv)
496 {
497     return JSTaggedValue(JSTaggedValue::False());
498 }
HandlerFunction(EcmaRuntimeCallInfo * argv)499 JSTaggedValue HandlerFunction([[maybe_unused]] EcmaRuntimeCallInfo *argv)
500 {
501     return JSTaggedValue(JSTaggedValue::True());
502 }
503 
504 // ES6 9.5.13 [[Call]] (thisArgument, argumentsList)
HWTEST_F_L0(JSProxyTest,Call)505 HWTEST_F_L0(JSProxyTest, Call)
506 {
507     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
508     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
509     // 1. handler has no "Call"
510     JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread));
511     JSHandle<JSTaggedValue> targetHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerFunction)));
512     EXPECT_TRUE(targetHandle->IsECMAObject());
513 
514     JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass));
515     EXPECT_TRUE(handlerHandle->IsECMAObject());
516 
517     JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
518     EXPECT_TRUE(*proxyHandle != nullptr);
519 
520     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
521     EcmaRuntimeCallInfo *info =
522         EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle<JSTaggedValue>(proxyHandle),
523         JSHandle<JSTaggedValue>(proxyHandle), undefined, 0);
524     JSTaggedValue res = JSProxy::CallInternal(info);
525     EXPECT_TRUE(JSTaggedValue::SameValue(thread, res, JSTaggedValue::True()));
526 
527     // 2. handler has "Call"
528     JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledApplyString();
529     JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerCall)));
530     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle);
531 
532     JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
533     EXPECT_TRUE(*proxyHandle2 != nullptr);
534 
535     EcmaRuntimeCallInfo *runtimeInfo =
536         EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle<JSTaggedValue>(proxyHandle2),
537         JSHandle<JSTaggedValue>(proxyHandle2), undefined, 0);
538     JSTaggedValue res2 = JSProxy::CallInternal(runtimeInfo);
539     EXPECT_TRUE(JSTaggedValue::SameValue(thread, res2, JSTaggedValue::False()));
540 }
541 
HandlerConstruct(EcmaRuntimeCallInfo * argv)542 JSTaggedValue HandlerConstruct([[maybe_unused]] EcmaRuntimeCallInfo *argv)
543 {
544     auto thread = argv->GetThread();
545     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
546     JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread));
547     JSHandle<JSTaggedValue> obj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass));
548 
549     JSHandle<JSTaggedValue> key(factory->NewFromASCII("x"));
550     PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(2))); // 2 : test case
551     JSObject::DefineOwnProperty(argv->GetThread(), JSHandle<JSObject>::Cast(obj), key, desc);
552     return JSTaggedValue(obj.GetTaggedValue());
553 }
HandlerConFunc(EcmaRuntimeCallInfo * argv)554 JSTaggedValue HandlerConFunc([[maybe_unused]] EcmaRuntimeCallInfo *argv)
555 {
556     auto thread = argv->GetThread();
557     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
558     JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread));
559     JSHandle<JSTaggedValue> obj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass));
560 
561     JSHandle<JSTaggedValue> key(factory->NewFromASCII("x"));
562     PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)));
563     JSObject::DefineOwnProperty(argv->GetThread(), JSHandle<JSObject>::Cast(obj), key, desc);
564     return JSTaggedValue(obj.GetTaggedValue());
565 }
566 
567 // ES6 9.5.14 [[Construct]] ( argumentsList, newTarget)
HWTEST_F_L0(JSProxyTest,Construct)568 HWTEST_F_L0(JSProxyTest, Construct)
569 {
570     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
571     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
572     // 1. handler has no "Construct"
573     JSHandle<JSTaggedValue> hclass(thread, JSObjectTestCreate(thread));
574     JSHandle<JSTaggedValue> targetHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerConFunc)));
575     JSHandle<JSFunction>::Cast(targetHandle)->GetJSHClass()->SetConstructor(true);
576     EXPECT_TRUE(targetHandle->IsECMAObject());
577 
578     JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass));
579     EXPECT_TRUE(handlerHandle->IsECMAObject());
580 
581     JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
582     EXPECT_TRUE(*proxyHandle != nullptr);
583     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
584     EcmaRuntimeCallInfo *info =
585         EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle<JSTaggedValue>(proxyHandle), handlerHandle, undefined, 0);
586     JSTaggedValue res = JSProxy::ConstructInternal(info);
587     JSHandle<JSTaggedValue> taggedRes(thread, res);
588     JSHandle<JSTaggedValue> key(factory->NewFromASCII("x"));
589     EXPECT_EQ(JSObject::GetProperty(thread, taggedRes, key).GetValue()->GetInt(), 1);
590 
591     // 2. handler has "Construct"
592     JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledProxyConstructString();
593     JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerConstruct)));
594     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle);
595 
596     JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
597     EXPECT_TRUE(*proxyHandle2 != nullptr);
598     EcmaRuntimeCallInfo *runtimeInfo =
599         EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle<JSTaggedValue>(proxyHandle2), targetHandle, undefined, 0);
600     JSTaggedValue res2 = JSProxy::ConstructInternal(runtimeInfo);
601     JSHandle<JSTaggedValue> taggedRes2(thread, res2);
602     EXPECT_EQ(JSObject::GetProperty(thread, taggedRes2, key).GetValue()->GetInt(), 2);
603 }
604 }  // namespace panda::test
605