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