* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/module/static/static_module_proxy_handler.h"
#include "ecmascript/global_env.h"
#include "ecmascript/object_factory-inl.h"
#include "ecmascript/module/module_path_helper.h"
#include "ecmascript/module/js_module_deregister.h"
#include "ecmascript/module/js_shared_module_manager.h"
#include "ecmascript/shared_objects/js_shared_array.h"
#include "ecmascript/module/js_module_source_text.h"
#include "ecmascript/module/module_data_extractor.h"
#include "ecmascript/builtins/builtins_promise_job.h"
#include "ecmascript/interpreter/interpreter.h"
#include "ecmascript/js_promise.h"
#include "ecmascript/module/module_path_helper.h"
namespace panda::ecmascript {
JSHandle<JSProxy> StaticModuleProxyHandler::CreateStaticModuleProxyHandler(JSThread *thread,
const JSHandle<JSTaggedValue> exportObject)
{
EcmaVM *vm = thread->GetEcmaVM();
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> targetHandler(factory->NewJSFunction(vm->GetGlobalEnv()));
JSHandle<JSTaggedValue> setPrototype(factory->NewJSFunction(vm->GetGlobalEnv(),
reinterpret_cast<void *>(StaticModuleProxyHandler::SetPrototype)));
JSTaggedValue::SetProperty(thread, targetHandler,
thread->GlobalConstants()->GetHandledSetPrototypeOfString(), setPrototype);
JSHandle<JSTaggedValue> preventExtensions(factory->NewJSFunction(vm->GetGlobalEnv(),
reinterpret_cast<void *>(StaticModuleProxyHandler::PreventExtensions)));
JSTaggedValue::SetProperty(thread, targetHandler,
thread->GlobalConstants()->GetHandledPreventExtensionsString(), preventExtensions);
JSHandle<JSTaggedValue> getOwnProperty(factory->NewJSFunction(vm->GetGlobalEnv(),
reinterpret_cast<void *>(StaticModuleProxyHandler::GetOwnProperty)));
JSTaggedValue::SetProperty(thread, targetHandler,
thread->GlobalConstants()->GetHandledGetOwnPropertyDescriptorString(), getOwnProperty);
JSHandle<JSTaggedValue> defineOwnProperty(factory->NewJSFunction(vm->GetGlobalEnv(),
reinterpret_cast<void *>(StaticModuleProxyHandler::DefineOwnProperty)));
JSTaggedValue::SetProperty(thread, targetHandler,
thread->GlobalConstants()->GetHandledDefinePropertyString(), defineOwnProperty);
JSHandle<JSTaggedValue> hasProperty(factory->NewJSFunction(vm->GetGlobalEnv(),
reinterpret_cast<void *>(StaticModuleProxyHandler::HasProperty)));
JSTaggedValue::SetProperty(thread, targetHandler,
thread->GlobalConstants()->GetHandledHasString(), hasProperty);
JSHandle<JSTaggedValue> getProperty(factory->NewJSFunction(vm->GetGlobalEnv(),
reinterpret_cast<void *>(StaticModuleProxyHandler::GetProperty)));
JSTaggedValue::SetProperty(thread, targetHandler,
thread->GlobalConstants()->GetHandledGetString(), getProperty);
JSHandle<JSTaggedValue> setProperty(factory->NewJSFunction(vm->GetGlobalEnv(),
reinterpret_cast<void *>(StaticModuleProxyHandler::SetProperty)));
JSTaggedValue::SetProperty(thread, targetHandler,
thread->GlobalConstants()->GetHandledSetString(), setProperty);
JSHandle<JSTaggedValue> deleteProperty(factory->NewJSFunction(vm->GetGlobalEnv(),
reinterpret_cast<void *>(StaticModuleProxyHandler::DeleteProperty)));
JSTaggedValue::SetProperty(thread, targetHandler,
thread->GlobalConstants()->GetHandledDeletePropertyString(), deleteProperty);
JSHandle<JSTaggedValue> ownPropertyKeys(factory->NewJSFunction(vm->GetGlobalEnv(),
reinterpret_cast<void *>(StaticModuleProxyHandler::OwnPropertyKeys)));
JSTaggedValue::SetProperty(thread, targetHandler,
thread->GlobalConstants()->GetHandledOwnKeysString(), ownPropertyKeys);
return JSProxy::ProxyCreate(thread, exportObject, targetHandler);
}
JSTaggedValue StaticModuleProxyHandler::GetProperty(EcmaRuntimeCallInfo *argv)
{
JSThread *thread = argv->GetThread();
JSHandle<JSTaggedValue> obj(argv->GetCallArg(FIRST));
JSHandle<JSTaggedValue> key(argv->GetCallArg(SECOND));
return GetPropertyInternal(thread, obj, key);
}
JSTaggedValue StaticModuleProxyHandler::GetPropertyInternal(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
const JSHandle<JSTaggedValue> &key)
{
ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
return JSObject::GetProperty(thread, obj, key).GetValue().GetTaggedValue();
}
JSTaggedValue StaticModuleProxyHandler::OwnPropertyKeys(EcmaRuntimeCallInfo *argv)
{
JSHandle<JSTaggedValue> obj(argv->GetCallArg(FIRST));
JSThread *thread = argv->GetThread();
JSHandle<TaggedArray> symbolKeys = JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>(obj));
JSHandle<JSArray> propertyKeys = JSArray::CreateArrayFromList(thread, symbolKeys);
return propertyKeys.GetTaggedValue();
}
bool StaticModuleProxyHandler::GetOwnPropertyInternal(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc)
{
ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
if (key->IsSymbol()) {
return JSObject::GetOwnProperty(thread, JSHandle<JSObject>(obj), key, desc);
}
JSHandle<JSTaggedValue> value(thread, StaticModuleProxyHandler::GetPropertyInternal(thread, obj, key));
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
if (value->IsUndefined()) {
return false;
}
desc.SetValue(value);
desc.SetEnumerable(true);
desc.SetWritable(true);
desc.SetConfigurable(false);
return true;
}
JSTaggedValue StaticModuleProxyHandler::OwnEnumPropertyKeys(EcmaRuntimeCallInfo *argv)
{
JSHandle<JSTaggedValue> obj(argv->GetCallArg(FIRST));
JSThread *thread = argv->GetThread();
JSHandle<TaggedArray> symbolKeys = JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>(obj));
JSHandle<JSArray> propertyKeys = JSArray::CreateArrayFromList(thread, symbolKeys);
return propertyKeys.GetTaggedValue();
}
JSTaggedValue StaticModuleProxyHandler::PreventExtensions(EcmaRuntimeCallInfo *argv)
{
return JSTaggedValue::True();
}
JSTaggedValue StaticModuleProxyHandler::DefineOwnProperty(EcmaRuntimeCallInfo *argv)
{
JSThread *thread = argv->GetThread();
JSHandle<JSTaggedValue> obj(argv->GetCallArg(FIRST));
JSHandle<JSTaggedValue> key(argv->GetCallArg(SECOND));
JSHandle<JSTaggedValue> descObj(argv->GetCallArg(THIRD));
PropertyDescriptor desc(thread);
if (!descObj->IsUndefined()) {
JSObject::ToPropertyDescriptor(thread, descObj, desc);
}
if (key->IsSymbol()) {
bool res = JSObject::OrdinaryDefineOwnProperty(thread, JSHandle<JSObject>(obj), key, desc);
return JSTaggedValue(res);
}
PropertyDescriptor current(thread);
if (!GetOwnPropertyInternal(thread, obj, key, current)) {
return JSTaggedValue::False();
}
if (desc.IsAccessorDescriptor()) {
return JSTaggedValue::False();
}
if (desc.HasConfigurable() && desc.IsConfigurable()) {
return JSTaggedValue::False();
}
if (desc.HasEnumerable() && !desc.IsEnumerable()) {
return JSTaggedValue::False();
}
if (desc.HasWritable() && !desc.IsWritable()) {
return JSTaggedValue::False();
}
if (desc.HasValue()) {
JSHandle<JSTaggedValue> descValue = desc.GetValue();
JSHandle<JSTaggedValue> currentValue = current.GetValue();
return JSTaggedValue(JSTaggedValue::SameValue(thread, descValue, currentValue));
}
return JSTaggedValue::True();
}
JSTaggedValue StaticModuleProxyHandler::HasProperty(EcmaRuntimeCallInfo *argv)
{
JSThread *thread = argv->GetThread();
JSHandle<JSTaggedValue> obj(argv->GetCallArg(FIRST));
JSHandle<JSTaggedValue> key(argv->GetCallArg(SECOND));
return JSTaggedValue(JSObject::HasProperty(thread, JSHandle<JSObject>(obj), key));
}
JSTaggedValue StaticModuleProxyHandler::SetPrototype(EcmaRuntimeCallInfo *argv)
{
JSHandle<JSTaggedValue> proto(argv->GetCallArg(SECOND));
ASSERT(proto->IsECMAObject() || proto->IsNull());
return JSTaggedValue(proto->IsNull());
}
JSTaggedValue StaticModuleProxyHandler::GetPrototype(EcmaRuntimeCallInfo *argv)
{
return JSTaggedValue::Null();
}
JSTaggedValue StaticModuleProxyHandler::GetOwnProperty(EcmaRuntimeCallInfo *argv)
{
JSThread *thread = argv->GetThread();
JSHandle<JSTaggedValue> obj(argv->GetCallArg(FIRST));
JSHandle<JSTaggedValue> key(argv->GetCallArg(SECOND));
JSHandle<JSTaggedValue> descObj(argv->GetCallArg(THIRD));
PropertyDescriptor desc(thread);
if (!descObj->IsUndefined()) {
JSObject::ToPropertyDescriptor(thread, descObj, desc);
}
return JSTaggedValue(GetOwnPropertyInternal(thread, obj, key, desc));
}
JSTaggedValue StaticModuleProxyHandler::SetProperty(EcmaRuntimeCallInfo *argv)
{
JSThread *thread = argv->GetThread();
JSHandle<JSTaggedValue> mayThrow(argv->GetCallArg(FIRST));
if (mayThrow->ToBoolean()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot assign to read only property of Object Module",
JSTaggedValue::False());
}
return JSTaggedValue::False();
}
JSTaggedValue StaticModuleProxyHandler::DeleteProperty(EcmaRuntimeCallInfo *argv)
{
JSThread *thread = argv->GetThread();
JSHandle<JSTaggedValue> obj(argv->GetCallArg(FIRST));
JSHandle<JSTaggedValue> key(argv->GetCallArg(SECOND));
ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
if (key->IsSymbol()) {
return JSTaggedValue(JSObject::DeleteProperty(thread, JSHandle<JSObject>(obj), key));
}
JSHandle<JSTaggedValue> value(thread, GetPropertyInternal(thread, obj, key));
if (value->IsUndefined()) {
return JSTaggedValue::True();
}
return JSTaggedValue::False();
}
JSTaggedValue StaticModuleProxyHandler::IsExtensible(EcmaRuntimeCallInfo *argv)
{
return JSTaggedValue::False();
}
}