1 /*
2 * Copyright (c) 2025 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/module/static/static_module_proxy_handler.h"
17 #include "ecmascript/global_env.h"
18 #include "ecmascript/object_factory-inl.h"
19 #include "ecmascript/module/module_path_helper.h"
20 #include "ecmascript/module/js_module_deregister.h"
21 #include "ecmascript/module/js_shared_module_manager.h"
22 #include "ecmascript/shared_objects/js_shared_array.h"
23 #include "ecmascript/module/js_module_source_text.h"
24 #include "ecmascript/module/module_data_extractor.h"
25 #include "ecmascript/builtins/builtins_promise_job.h"
26 #include "ecmascript/interpreter/interpreter.h"
27 #include "ecmascript/js_promise.h"
28 #include "ecmascript/module/module_path_helper.h"
29
30 namespace panda::ecmascript {
CreateStaticModuleProxyHandler(JSThread * thread,const JSHandle<JSTaggedValue> exportObject)31 JSHandle<JSProxy> StaticModuleProxyHandler::CreateStaticModuleProxyHandler(JSThread *thread,
32 const JSHandle<JSTaggedValue> exportObject)
33 {
34 EcmaVM *vm = thread->GetEcmaVM();
35 ObjectFactory *factory = vm->GetFactory();
36 JSHandle<JSTaggedValue> targetHandler(factory->NewJSFunction(vm->GetGlobalEnv()));
37
38 JSHandle<JSTaggedValue> setPrototype(factory->NewJSFunction(vm->GetGlobalEnv(),
39 reinterpret_cast<void *>(StaticModuleProxyHandler::SetPrototype)));
40 JSTaggedValue::SetProperty(thread, targetHandler,
41 thread->GlobalConstants()->GetHandledSetPrototypeOfString(), setPrototype);
42
43 JSHandle<JSTaggedValue> preventExtensions(factory->NewJSFunction(vm->GetGlobalEnv(),
44 reinterpret_cast<void *>(StaticModuleProxyHandler::PreventExtensions)));
45 JSTaggedValue::SetProperty(thread, targetHandler,
46 thread->GlobalConstants()->GetHandledPreventExtensionsString(), preventExtensions);
47
48 JSHandle<JSTaggedValue> getOwnProperty(factory->NewJSFunction(vm->GetGlobalEnv(),
49 reinterpret_cast<void *>(StaticModuleProxyHandler::GetOwnProperty)));
50 JSTaggedValue::SetProperty(thread, targetHandler,
51 thread->GlobalConstants()->GetHandledGetOwnPropertyDescriptorString(), getOwnProperty);
52
53 JSHandle<JSTaggedValue> defineOwnProperty(factory->NewJSFunction(vm->GetGlobalEnv(),
54 reinterpret_cast<void *>(StaticModuleProxyHandler::DefineOwnProperty)));
55 JSTaggedValue::SetProperty(thread, targetHandler,
56 thread->GlobalConstants()->GetHandledDefinePropertyString(), defineOwnProperty);
57
58 JSHandle<JSTaggedValue> hasProperty(factory->NewJSFunction(vm->GetGlobalEnv(),
59 reinterpret_cast<void *>(StaticModuleProxyHandler::HasProperty)));
60 JSTaggedValue::SetProperty(thread, targetHandler,
61 thread->GlobalConstants()->GetHandledHasString(), hasProperty);
62
63 JSHandle<JSTaggedValue> getProperty(factory->NewJSFunction(vm->GetGlobalEnv(),
64 reinterpret_cast<void *>(StaticModuleProxyHandler::GetProperty)));
65 JSTaggedValue::SetProperty(thread, targetHandler,
66 thread->GlobalConstants()->GetHandledGetString(), getProperty);
67
68 JSHandle<JSTaggedValue> setProperty(factory->NewJSFunction(vm->GetGlobalEnv(),
69 reinterpret_cast<void *>(StaticModuleProxyHandler::SetProperty)));
70 JSTaggedValue::SetProperty(thread, targetHandler,
71 thread->GlobalConstants()->GetHandledSetString(), setProperty);
72
73 JSHandle<JSTaggedValue> deleteProperty(factory->NewJSFunction(vm->GetGlobalEnv(),
74 reinterpret_cast<void *>(StaticModuleProxyHandler::DeleteProperty)));
75 JSTaggedValue::SetProperty(thread, targetHandler,
76 thread->GlobalConstants()->GetHandledDeletePropertyString(), deleteProperty);
77
78 JSHandle<JSTaggedValue> ownPropertyKeys(factory->NewJSFunction(vm->GetGlobalEnv(),
79 reinterpret_cast<void *>(StaticModuleProxyHandler::OwnPropertyKeys)));
80 JSTaggedValue::SetProperty(thread, targetHandler,
81 thread->GlobalConstants()->GetHandledOwnKeysString(), ownPropertyKeys);
82
83 return JSProxy::ProxyCreate(thread, exportObject, targetHandler);
84 }
85
GetProperty(EcmaRuntimeCallInfo * argv)86 JSTaggedValue StaticModuleProxyHandler::GetProperty(EcmaRuntimeCallInfo *argv)
87 {
88 JSThread *thread = argv->GetThread();
89 JSHandle<JSTaggedValue> obj(argv->GetCallArg(FIRST));
90 JSHandle<JSTaggedValue> key(argv->GetCallArg(SECOND));
91 // 1. Assert: IsPropertyKey(P) is true.
92 // 2. If Type(P) is Symbol, then
93 // a. Return ? OrdinaryGet(O, P, Receiver).
94 return GetPropertyInternal(thread, obj, key);
95 }
96
GetPropertyInternal(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & key)97 JSTaggedValue StaticModuleProxyHandler::GetPropertyInternal(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
98 const JSHandle<JSTaggedValue> &key)
99 {
100 // 1. Assert: IsPropertyKey(P) is true.
101 ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
102 // 2. If Type(P) is Symbol, then
103 // a. Return ? OrdinaryGet(O, P, Receiver).
104 return JSObject::GetProperty(thread, obj, key).GetValue().GetTaggedValue();
105 }
106
107
OwnPropertyKeys(EcmaRuntimeCallInfo * argv)108 JSTaggedValue StaticModuleProxyHandler::OwnPropertyKeys(EcmaRuntimeCallInfo *argv)
109 {
110 JSHandle<JSTaggedValue> obj(argv->GetCallArg(FIRST));
111 JSThread *thread = argv->GetThread();
112 JSHandle<TaggedArray> symbolKeys = JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>(obj)); //todo copy array
113 JSHandle<JSArray> propertyKeys = JSArray::CreateArrayFromList(thread, symbolKeys);
114 return propertyKeys.GetTaggedValue();
115 }
116
GetOwnPropertyInternal(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & key,PropertyDescriptor & desc)117 bool StaticModuleProxyHandler::GetOwnPropertyInternal(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
118 const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc)
119 {
120 ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
121 // 1. If Type(P) is Symbol, return OrdinaryGetOwnProperty(O, P).
122 if (key->IsSymbol()) {
123 return JSObject::GetOwnProperty(thread, JSHandle<JSObject>(obj), key, desc);
124 }
125 // 2. Let value be ? O.[[Get]](P, O).
126 JSHandle<JSTaggedValue> value(thread, StaticModuleProxyHandler::GetPropertyInternal(thread, obj, key));
127 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
128 if (value->IsUndefined()) {
129 return false;
130 }
131 // 3. Return PropertyDescriptor {
132 // [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false }.
133 desc.SetValue(value);
134 desc.SetEnumerable(true);
135 desc.SetWritable(true);
136 desc.SetConfigurable(false);
137 return true;
138 }
139
OwnEnumPropertyKeys(EcmaRuntimeCallInfo * argv)140 JSTaggedValue StaticModuleProxyHandler::OwnEnumPropertyKeys(EcmaRuntimeCallInfo *argv)
141 {
142 JSHandle<JSTaggedValue> obj(argv->GetCallArg(FIRST));
143 JSThread *thread = argv->GetThread();
144 JSHandle<TaggedArray> symbolKeys = JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>(obj)); //todo copy array
145 JSHandle<JSArray> propertyKeys = JSArray::CreateArrayFromList(thread, symbolKeys);
146 return propertyKeys.GetTaggedValue();
147 }
148
PreventExtensions(EcmaRuntimeCallInfo * argv)149 JSTaggedValue StaticModuleProxyHandler::PreventExtensions(EcmaRuntimeCallInfo *argv)
150 {
151 return JSTaggedValue::True();
152 }
153
DefineOwnProperty(EcmaRuntimeCallInfo * argv)154 JSTaggedValue StaticModuleProxyHandler::DefineOwnProperty(EcmaRuntimeCallInfo *argv)
155 {
156 JSThread *thread = argv->GetThread();
157 JSHandle<JSTaggedValue> obj(argv->GetCallArg(FIRST));
158 JSHandle<JSTaggedValue> key(argv->GetCallArg(SECOND));
159 JSHandle<JSTaggedValue> descObj(argv->GetCallArg(THIRD));
160 PropertyDescriptor desc(thread);
161 if (!descObj->IsUndefined()) {
162 JSObject::ToPropertyDescriptor(thread, descObj, desc);
163 }
164 // 1. If Type(P) is Symbol, return ! OrdinaryDefineOwnProperty(O, P, Desc).
165 if (key->IsSymbol()) {
166 bool res = JSObject::OrdinaryDefineOwnProperty(thread, JSHandle<JSObject>(obj), key, desc);
167 return JSTaggedValue(res);
168 }
169
170 // 2. Let current be ? O.[[GetOwnProperty]](P).
171 PropertyDescriptor current(thread);
172 // 3. If current is undefined, return false.
173 if (!GetOwnPropertyInternal(thread, obj, key, current)) {
174 return JSTaggedValue::False();
175 }
176 // 4. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is true, return false.
177 // 5. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
178 // 6. If IsAccessorDescriptor(Desc) is true, return false.
179 // 7. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, return false.
180 if (desc.IsAccessorDescriptor()) {
181 return JSTaggedValue::False();
182 }
183 if (desc.HasConfigurable() && desc.IsConfigurable()) {
184 return JSTaggedValue::False();
185 }
186 if (desc.HasEnumerable() && !desc.IsEnumerable()) {
187 return JSTaggedValue::False();
188 }
189 if (desc.HasWritable() && !desc.IsWritable()) {
190 return JSTaggedValue::False();
191 }
192
193 // 8. If Desc has a [[Value]] field, return SameValue(Desc.[[Value]], current.[[Value]]).
194 if (desc.HasValue()) {
195 JSHandle<JSTaggedValue> descValue = desc.GetValue();
196 JSHandle<JSTaggedValue> currentValue = current.GetValue();
197 return JSTaggedValue(JSTaggedValue::SameValue(thread, descValue, currentValue));
198 }
199
200 // 9. Return true.
201 return JSTaggedValue::True();
202 }
203
HasProperty(EcmaRuntimeCallInfo * argv)204 JSTaggedValue StaticModuleProxyHandler::HasProperty(EcmaRuntimeCallInfo *argv)
205 {
206 JSThread *thread = argv->GetThread();
207 JSHandle<JSTaggedValue> obj(argv->GetCallArg(FIRST));
208 JSHandle<JSTaggedValue> key(argv->GetCallArg(SECOND));
209 return JSTaggedValue(JSObject::HasProperty(thread, JSHandle<JSObject>(obj), key));
210 }
211
SetPrototype(EcmaRuntimeCallInfo * argv)212 JSTaggedValue StaticModuleProxyHandler::SetPrototype(EcmaRuntimeCallInfo *argv)
213 {
214 // 1. Assert: Either Type(V) is Object or Type(V) is Null.
215 JSHandle<JSTaggedValue> proto(argv->GetCallArg(SECOND));
216 ASSERT(proto->IsECMAObject() || proto->IsNull());
217 return JSTaggedValue(proto->IsNull());
218 }
219
GetPrototype(EcmaRuntimeCallInfo * argv)220 JSTaggedValue StaticModuleProxyHandler::GetPrototype(EcmaRuntimeCallInfo *argv)
221 {
222 // 1. Assert: Either Type(V) is Object or Type(V) is Null.
223 return JSTaggedValue::Null();
224 }
225
226
GetOwnProperty(EcmaRuntimeCallInfo * argv)227 JSTaggedValue StaticModuleProxyHandler::GetOwnProperty(EcmaRuntimeCallInfo *argv)
228 {
229 JSThread *thread = argv->GetThread();
230 JSHandle<JSTaggedValue> obj(argv->GetCallArg(FIRST));
231 JSHandle<JSTaggedValue> key(argv->GetCallArg(SECOND));
232 JSHandle<JSTaggedValue> descObj(argv->GetCallArg(THIRD));
233 PropertyDescriptor desc(thread);
234 if (!descObj->IsUndefined()) {
235 JSObject::ToPropertyDescriptor(thread, descObj, desc);
236 }
237 return JSTaggedValue(GetOwnPropertyInternal(thread, obj, key, desc));
238 }
239
SetProperty(EcmaRuntimeCallInfo * argv)240 JSTaggedValue StaticModuleProxyHandler::SetProperty(EcmaRuntimeCallInfo *argv)
241 {
242 JSThread *thread = argv->GetThread();
243 JSHandle<JSTaggedValue> mayThrow(argv->GetCallArg(FIRST));
244 if (mayThrow->ToBoolean()) {
245 THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot assign to read only property of Object Module",
246 JSTaggedValue::False());
247 }
248 return JSTaggedValue::False();
249 }
250
DeleteProperty(EcmaRuntimeCallInfo * argv)251 JSTaggedValue StaticModuleProxyHandler::DeleteProperty(EcmaRuntimeCallInfo *argv)
252 {
253 JSThread *thread = argv->GetThread();
254 JSHandle<JSTaggedValue> obj(argv->GetCallArg(FIRST));
255 JSHandle<JSTaggedValue> key(argv->GetCallArg(SECOND));
256 // 1. Assert: IsPropertyKey(P) is true.
257 ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
258 // 2. If Type(P) is Symbol, then
259 // Return ? OrdinaryDelete(O, P).
260 if (key->IsSymbol()) {
261 return JSTaggedValue(JSObject::DeleteProperty(thread, JSHandle<JSObject>(obj), key));
262 }
263 // 3. Let exports be O.[[Exports]].
264 JSHandle<JSTaggedValue> value(thread, GetPropertyInternal(thread, obj, key));
265 // 4. If P is an element of exports, return false.
266 if (value->IsUndefined()) {
267 return JSTaggedValue::True();
268 }
269 return JSTaggedValue::False();
270 }
271
IsExtensible(EcmaRuntimeCallInfo * argv)272 JSTaggedValue StaticModuleProxyHandler::IsExtensible(EcmaRuntimeCallInfo *argv)
273 {
274 return JSTaggedValue::False();
275 }
276 } // namespace panda::ecmascript
277