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