* Copyright (c) 2023-2024 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/builtins/builtins_lazy_callback.h"
#include "ecmascript/builtins/builtins.h"
#include "ecmascript/layout_info-inl.h"
namespace panda::ecmascript::builtins {
JSTaggedValue BuiltinsLazyCallback::Date(JSThread *thread, const JSHandle<JSObject> &obj)
{
[[maybe_unused]] EcmaHandleScope scope(thread);
LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
EcmaVM *vm = thread->GetEcmaVM();
ObjectFactory *factory = vm->GetFactory();
auto env = vm->GetGlobalEnv();
ResetLazyInternalAttr(thread, obj, "Date");
JSHandle<JSTaggedValue> objFuncPrototypeVal = env->GetObjectFunctionPrototype();
Builtins builtin(thread, factory, vm);
builtin.InitializeDate(env, objFuncPrototypeVal);
return env->GetDateFunction().GetTaggedValue();
}
JSTaggedValue BuiltinsLazyCallback::Set(JSThread *thread, const JSHandle<JSObject> &obj)
{
[[maybe_unused]] EcmaHandleScope scope(thread);
LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
EcmaVM *vm = thread->GetEcmaVM();
ObjectFactory *factory = vm->GetFactory();
auto env = vm->GetGlobalEnv();
ResetLazyInternalAttr(thread, obj, "Set");
Builtins builtin(thread, factory, vm);
JSHandle<JSTaggedValue> objFuncPrototypeVal = env->GetObjectFunctionPrototype();
builtin.InitializeSet(env, objFuncPrototypeVal);
return env->GetBuiltinsSetFunction().GetTaggedValue();
}
JSTaggedValue BuiltinsLazyCallback::Map(JSThread *thread, const JSHandle<JSObject> &obj)
{
[[maybe_unused]] EcmaHandleScope scope(thread);
LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
EcmaVM *vm = thread->GetEcmaVM();
ObjectFactory *factory = vm->GetFactory();
auto env = vm->GetGlobalEnv();
ResetLazyInternalAttr(thread, obj, "Map");
Builtins builtin(thread, factory, vm);
JSHandle<JSTaggedValue> objFuncPrototypeVal = env->GetObjectFunctionPrototype();
builtin.InitializeMap(env, objFuncPrototypeVal);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return env->GetBuiltinsMapFunction().GetTaggedValue();
}
JSTaggedValue BuiltinsLazyCallback::WeakMap(JSThread *thread, const JSHandle<JSObject> &obj)
{
[[maybe_unused]] EcmaHandleScope scope(thread);
LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
EcmaVM *vm = thread->GetEcmaVM();
ObjectFactory *factory = vm->GetFactory();
auto env = vm->GetGlobalEnv();
ResetLazyInternalAttr(thread, obj, "WeakMap");
Builtins builtin(thread, factory, vm);
JSHandle<JSHClass> objFuncClass(env->GetObjectFunctionClass());
builtin.InitializeWeakMap(env, objFuncClass);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return env->GetBuiltinsWeakMapFunction().GetTaggedValue();
}
JSTaggedValue BuiltinsLazyCallback::WeakSet(JSThread *thread, const JSHandle<JSObject> &obj)
{
[[maybe_unused]] EcmaHandleScope scope(thread);
LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
EcmaVM *vm = thread->GetEcmaVM();
ObjectFactory *factory = vm->GetFactory();
auto env = vm->GetGlobalEnv();
ResetLazyInternalAttr(thread, obj, "WeakSet");
Builtins builtin(thread, factory, vm);
JSHandle<JSHClass> objFuncClass(env->GetObjectFunctionClass());
builtin.InitializeWeakSet(env, objFuncClass);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return env->GetBuiltinsWeakSetFunction().GetTaggedValue();
}
JSTaggedValue BuiltinsLazyCallback::WeakRef(JSThread *thread, const JSHandle<JSObject> &obj)
{
[[maybe_unused]] EcmaHandleScope scope(thread);
LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
EcmaVM *vm = thread->GetEcmaVM();
ObjectFactory *factory = vm->GetFactory();
auto env = vm->GetGlobalEnv();
ResetLazyInternalAttr(thread, obj, "WeakRef");
Builtins builtin(thread, factory, vm);
JSHandle<JSHClass> objFuncClass(env->GetObjectFunctionClass());
builtin.InitializeWeakRef(env, objFuncClass);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return env->GetBuiltinsWeakRefFunction().GetTaggedValue();
}
JSTaggedValue BuiltinsLazyCallback::FinalizationRegistry(JSThread *thread, const JSHandle<JSObject> &obj)
{
[[maybe_unused]] EcmaHandleScope scope(thread);
LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
EcmaVM *vm = thread->GetEcmaVM();
ObjectFactory *factory = vm->GetFactory();
auto env = vm->GetGlobalEnv();
ResetLazyInternalAttr(thread, obj, "FinalizationRegistry");
Builtins builtin(thread, factory, vm);
JSHandle<JSHClass> objFuncClass(env->GetObjectFunctionClass());
builtin.InitializeFinalizationRegistry(env, objFuncClass);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return env->GetBuiltinsFinalizationRegistryFunction().GetTaggedValue();
}
JSTaggedValue BuiltinsLazyCallback::TypedArray(JSThread *thread, const JSHandle<JSObject> &obj)
{
[[maybe_unused]] EcmaHandleScope scope(thread);
LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
EcmaVM *vm = thread->GetEcmaVM();
ObjectFactory *factory = vm->GetFactory();
auto env = vm->GetGlobalEnv();
ResetLazyInternalAttr(thread, obj, "TypedArray");
#define RESET_TYPED_ARRAY_INTERNAL_ATTR(type) \
ResetLazyInternalAttr(thread, obj, #type);
ITERATE_TYPED_ARRAY(RESET_TYPED_ARRAY_INTERNAL_ATTR)
#undef RESET_TYPED_ARRAY_INTERNAL_ATTR
Builtins builtin(thread, factory, vm);
JSHandle<JSTaggedValue> objFuncPrototypeVal = env->GetObjectFunctionPrototype();
builtin.InitializeTypedArray(env, objFuncPrototypeVal);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return env->GetTypedArrayFunction().GetTaggedValue();
}
#define TYPED_ARRAY_CALLBACK(type) \
JSTaggedValue BuiltinsLazyCallback::type(JSThread *thread, const JSHandle<JSObject> &obj) \
{ \
[[maybe_unused]] EcmaHandleScope scope(thread); \
LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__; \
EcmaVM *vm = thread->GetEcmaVM(); \
auto env = vm->GetGlobalEnv(); \
TypedArray(thread, obj); \
return env->Get##type##Function().GetTaggedValue(); \
}
ITERATE_TYPED_ARRAY(TYPED_ARRAY_CALLBACK)
#undef TYPED_ARRAY_CALLBACK
JSTaggedValue BuiltinsLazyCallback::ArrayBuffer(JSThread *thread, const JSHandle<JSObject> &obj)
{
[[maybe_unused]] EcmaHandleScope scope(thread);
LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
EcmaVM *vm = thread->GetEcmaVM();
ObjectFactory *factory = vm->GetFactory();
auto env = vm->GetGlobalEnv();
ResetLazyInternalAttr(thread, obj, "ArrayBuffer");
Builtins builtin(thread, factory, vm);
JSHandle<JSHClass> objFuncClass(env->GetObjectFunctionClass());
builtin.InitializeArrayBuffer(env, objFuncClass);
return env->GetArrayBufferFunction().GetTaggedValue();
}
JSTaggedValue BuiltinsLazyCallback::DataView(JSThread *thread, const JSHandle<JSObject> &obj)
{
[[maybe_unused]] EcmaHandleScope scope(thread);
LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
EcmaVM *vm = thread->GetEcmaVM();
ObjectFactory *factory = vm->GetFactory();
auto env = vm->GetGlobalEnv();
ResetLazyInternalAttr(thread, obj, "DataView");
Builtins builtin(thread, factory, vm);
JSHandle<JSTaggedValue> objFuncPrototypeVal = env->GetObjectFunctionPrototype();
builtin.InitializeDataView(env, objFuncPrototypeVal);
return env->GetDataViewFunction().GetTaggedValue();
}
JSTaggedValue BuiltinsLazyCallback::SharedArrayBuffer(JSThread *thread, const JSHandle<JSObject> &obj)
{
[[maybe_unused]] EcmaHandleScope scope(thread);
LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
EcmaVM *vm = thread->GetEcmaVM();
ObjectFactory *factory = vm->GetFactory();
auto env = vm->GetGlobalEnv();
ResetLazyInternalAttr(thread, obj, "SharedArrayBuffer");
Builtins builtin(thread, factory, vm);
JSHandle<JSHClass> objFuncClass(env->GetObjectFunctionClass());
builtin.InitializeSharedArrayBuffer(env, objFuncClass);
return env->GetSharedArrayBufferFunction().GetTaggedValue();
}
#ifdef ARK_SUPPORT_INTL
#define INTL_CALLBACK(type) \
JSTaggedValue BuiltinsLazyCallback::type(JSThread *thread, const JSHandle<JSObject> &obj) \
{ \
[[maybe_unused]] EcmaHandleScope scope(thread); \
LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__; \
EcmaVM *vm = thread->GetEcmaVM(); \
auto env = vm->GetGlobalEnv(); \
ObjectFactory *factory = vm->GetFactory(); \
ResetLazyInternalAttr(thread, obj, #type); \
Builtins builtin(thread, factory, vm); \
builtin.Initialize##type(env); \
return env->Get##type##Function().GetTaggedValue(); \
}
ITERATE_INTL(INTL_CALLBACK)
#undef INTL_CALLBACK
#endif
void BuiltinsLazyCallback::ResetLazyInternalAttr(JSThread *thread, const JSHandle<JSObject> &object,
const char *name)
{
JSHClass *hclass = object->GetClass();
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSTaggedValue> key(factory->NewFromUtf8ReadOnly(name));
if (LIKELY(!hclass->IsDictionaryMode())) {
LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetLayout(thread).GetTaggedObject());
uint32_t propsNumber = hclass->NumberOfProps();
#if ENABLE_V70_OPTIMIZATION
int entry = layoutInfo->FindElement(thread, hclass, key.GetTaggedValue(), propsNumber);
#else
int entry = layoutInfo->FindElementWithCache(thread, hclass, key.GetTaggedValue(), propsNumber);
#endif
if (entry != -1) {
PropertyAttributes attr(layoutInfo->GetAttr(thread, entry));
attr.SetIsAccessor(false);
layoutInfo->SetNormalAttr(thread, entry, attr);
}
} else {
TaggedArray *array = TaggedArray::Cast(object->GetProperties(thread).GetTaggedObject());
ASSERT(array->IsDictionaryMode());
NameDictionary *dict = NameDictionary::Cast(array);
int entry = dict->FindEntry(thread, key.GetTaggedValue());
if (entry != -1) {
auto attr = dict->GetAttributes(thread, entry);
attr.SetIsAccessor(false);
dict->SetAttributes(thread, entry, attr);
}
}
}
}