1/*
2 * Copyright (c) 2023-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/builtins/builtins_lazy_callback.h"
17
18#include "ecmascript/builtins/builtins.h"
19#include "ecmascript/layout_info-inl.h"
20
21namespace panda::ecmascript::builtins {
22JSTaggedValue BuiltinsLazyCallback::Date(JSThread *thread, const JSHandle<JSObject> &obj)
23{
24    [[maybe_unused]] EcmaHandleScope scope(thread);
25    LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
26    EcmaVM *vm = thread->GetEcmaVM();
27    ObjectFactory *factory = vm->GetFactory();
28    auto env = vm->GetGlobalEnv();
29    ResetLazyInternalAttr(thread, obj, "Date");
30
31    JSHandle<JSTaggedValue> objFuncPrototypeVal = env->GetObjectFunctionPrototype();
32    Builtins builtin(thread, factory, vm);
33    builtin.InitializeDate(env, objFuncPrototypeVal);
34    return env->GetDateFunction().GetTaggedValue();
35}
36
37JSTaggedValue BuiltinsLazyCallback::Set(JSThread *thread, const JSHandle<JSObject> &obj)
38{
39    [[maybe_unused]] EcmaHandleScope scope(thread);
40    LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
41    EcmaVM *vm = thread->GetEcmaVM();
42    ObjectFactory *factory = vm->GetFactory();
43    auto env = vm->GetGlobalEnv();
44    ResetLazyInternalAttr(thread, obj, "Set");
45
46    Builtins builtin(thread, factory, vm);
47    JSHandle<JSTaggedValue> objFuncPrototypeVal = env->GetObjectFunctionPrototype();
48    builtin.InitializeSet(env, objFuncPrototypeVal);
49    return env->GetBuiltinsSetFunction().GetTaggedValue();
50}
51
52JSTaggedValue BuiltinsLazyCallback::Map(JSThread *thread, const JSHandle<JSObject> &obj)
53{
54    [[maybe_unused]] EcmaHandleScope scope(thread);
55    LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
56    EcmaVM *vm = thread->GetEcmaVM();
57    ObjectFactory *factory = vm->GetFactory();
58    auto env = vm->GetGlobalEnv();
59    ResetLazyInternalAttr(thread, obj, "Map");
60
61    Builtins builtin(thread, factory, vm);
62    JSHandle<JSTaggedValue> objFuncPrototypeVal = env->GetObjectFunctionPrototype();
63    builtin.InitializeMap(env, objFuncPrototypeVal);
64    return env->GetBuiltinsMapFunction().GetTaggedValue();
65}
66
67JSTaggedValue BuiltinsLazyCallback::WeakMap(JSThread *thread, const JSHandle<JSObject> &obj)
68{
69    [[maybe_unused]] EcmaHandleScope scope(thread);
70    LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
71    EcmaVM *vm = thread->GetEcmaVM();
72    ObjectFactory *factory = vm->GetFactory();
73    auto env = vm->GetGlobalEnv();
74    ResetLazyInternalAttr(thread, obj, "WeakMap");
75    Builtins builtin(thread, factory, vm);
76    JSHandle<JSHClass> objFuncClass(env->GetObjectFunctionClass());
77    builtin.InitializeWeakMap(env, objFuncClass);
78    return env->GetBuiltinsWeakMapFunction().GetTaggedValue();
79}
80
81JSTaggedValue BuiltinsLazyCallback::WeakSet(JSThread *thread, const JSHandle<JSObject> &obj)
82{
83    [[maybe_unused]] EcmaHandleScope scope(thread);
84    LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
85    EcmaVM *vm = thread->GetEcmaVM();
86    ObjectFactory *factory = vm->GetFactory();
87    auto env = vm->GetGlobalEnv();
88    ResetLazyInternalAttr(thread, obj, "WeakSet");
89    Builtins builtin(thread, factory, vm);
90    JSHandle<JSHClass> objFuncClass(env->GetObjectFunctionClass());
91    builtin.InitializeWeakSet(env, objFuncClass);
92    return env->GetBuiltinsWeakSetFunction().GetTaggedValue();
93}
94
95JSTaggedValue BuiltinsLazyCallback::WeakRef(JSThread *thread, const JSHandle<JSObject> &obj)
96{
97    [[maybe_unused]] EcmaHandleScope scope(thread);
98    LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
99    EcmaVM *vm = thread->GetEcmaVM();
100    ObjectFactory *factory = vm->GetFactory();
101    auto env = vm->GetGlobalEnv();
102    ResetLazyInternalAttr(thread, obj, "WeakRef");
103    Builtins builtin(thread, factory, vm);
104    JSHandle<JSHClass> objFuncClass(env->GetObjectFunctionClass());
105    builtin.InitializeWeakRef(env, objFuncClass);
106    return env->GetBuiltinsWeakRefFunction().GetTaggedValue();
107}
108
109JSTaggedValue BuiltinsLazyCallback::FinalizationRegistry(JSThread *thread, const JSHandle<JSObject> &obj)
110{
111    [[maybe_unused]] EcmaHandleScope scope(thread);
112    LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
113    EcmaVM *vm = thread->GetEcmaVM();
114    ObjectFactory *factory = vm->GetFactory();
115    auto env = vm->GetGlobalEnv();
116    ResetLazyInternalAttr(thread, obj, "FinalizationRegistry");
117    Builtins builtin(thread, factory, vm);
118    JSHandle<JSHClass> objFuncClass(env->GetObjectFunctionClass());
119    builtin.InitializeFinalizationRegistry(env, objFuncClass);
120    return env->GetBuiltinsFinalizationRegistryFunction().GetTaggedValue();
121}
122
123JSTaggedValue BuiltinsLazyCallback::TypedArray(JSThread *thread, const JSHandle<JSObject> &obj)
124{
125    [[maybe_unused]] EcmaHandleScope scope(thread);
126    LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
127    EcmaVM *vm = thread->GetEcmaVM();
128    ObjectFactory *factory = vm->GetFactory();
129    auto env = vm->GetGlobalEnv();
130    ResetLazyInternalAttr(thread, obj, "TypedArray");
131
132#define RESET_TYPED_ARRAY_INTERNAL_ATTR(type)                                                             \
133    ResetLazyInternalAttr(thread, obj, #type);
134
135ITERATE_TYPED_ARRAY(RESET_TYPED_ARRAY_INTERNAL_ATTR)
136#undef RESET_TYPED_ARRAY_INTERNAL_ATTR
137
138    Builtins builtin(thread, factory, vm);
139    JSHandle<JSTaggedValue> objFuncPrototypeVal = env->GetObjectFunctionPrototype();
140    builtin.InitializeTypedArray(env, objFuncPrototypeVal);
141    return env->GetTypedArrayFunction().GetTaggedValue();
142}
143
144#define TYPED_ARRAY_CALLBACK(type)                                                                       \
145    JSTaggedValue BuiltinsLazyCallback::type(JSThread *thread, const JSHandle<JSObject> &obj)            \
146    {                                                                                                    \
147        [[maybe_unused]] EcmaHandleScope scope(thread);                                                  \
148        LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;                                         \
149        EcmaVM *vm = thread->GetEcmaVM();                                                                \
150        auto env = vm->GetGlobalEnv();                                                                   \
151        TypedArray(thread, obj);                                                                         \
152        return env->Get##type##Function().GetTaggedValue();                                              \
153    }
154
155ITERATE_TYPED_ARRAY(TYPED_ARRAY_CALLBACK)
156#undef TYPED_ARRAY_CALLBACK
157
158JSTaggedValue BuiltinsLazyCallback::ArrayBuffer(JSThread *thread, const JSHandle<JSObject> &obj)
159{
160    [[maybe_unused]] EcmaHandleScope scope(thread);
161    LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
162    EcmaVM *vm = thread->GetEcmaVM();
163    ObjectFactory *factory = vm->GetFactory();
164    auto env = vm->GetGlobalEnv();
165    ResetLazyInternalAttr(thread, obj, "ArrayBuffer");
166    Builtins builtin(thread, factory, vm);
167    JSHandle<JSHClass> objFuncClass(env->GetObjectFunctionClass());
168    builtin.InitializeArrayBuffer(env, objFuncClass);
169    return env->GetArrayBufferFunction().GetTaggedValue();
170}
171
172JSTaggedValue BuiltinsLazyCallback::DataView(JSThread *thread, const JSHandle<JSObject> &obj)
173{
174    [[maybe_unused]] EcmaHandleScope scope(thread);
175    LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
176    EcmaVM *vm = thread->GetEcmaVM();
177    ObjectFactory *factory = vm->GetFactory();
178    auto env = vm->GetGlobalEnv();
179    ResetLazyInternalAttr(thread, obj, "DataView");
180
181    Builtins builtin(thread, factory, vm);
182    JSHandle<JSTaggedValue> objFuncPrototypeVal = env->GetObjectFunctionPrototype();
183    builtin.InitializeDataView(env, objFuncPrototypeVal);
184    return env->GetDataViewFunction().GetTaggedValue();
185}
186
187JSTaggedValue BuiltinsLazyCallback::SharedArrayBuffer(JSThread *thread, const JSHandle<JSObject> &obj)
188{
189    [[maybe_unused]] EcmaHandleScope scope(thread);
190    LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;
191    EcmaVM *vm = thread->GetEcmaVM();
192    ObjectFactory *factory = vm->GetFactory();
193    auto env = vm->GetGlobalEnv();
194    ResetLazyInternalAttr(thread, obj, "SharedArrayBuffer");
195    Builtins builtin(thread, factory, vm);
196    JSHandle<JSHClass> objFuncClass(env->GetObjectFunctionClass());
197    builtin.InitializeSharedArrayBuffer(env, objFuncClass);
198    return env->GetSharedArrayBufferFunction().GetTaggedValue();
199}
200
201#ifdef ARK_SUPPORT_INTL
202#define INTL_CALLBACK(type)                                                                       \
203    JSTaggedValue BuiltinsLazyCallback::type(JSThread *thread, const JSHandle<JSObject> &obj)     \
204    {                                                                                             \
205        [[maybe_unused]] EcmaHandleScope scope(thread);                                           \
206        LOG_ECMA(DEBUG) << "BuiltinsLazyCallback::" << __func__;                                  \
207        EcmaVM *vm = thread->GetEcmaVM();                                                         \
208        auto env = vm->GetGlobalEnv();                                                            \
209        ObjectFactory *factory = vm->GetFactory();                                                \
210        ResetLazyInternalAttr(thread, obj, #type);                                                \
211        Builtins builtin(thread, factory, vm);                                                    \
212        builtin.Initialize##type(env);                                                            \
213        return env->Get##type##Function().GetTaggedValue();                                       \
214    }
215
216ITERATE_INTL(INTL_CALLBACK)
217#undef INTL_CALLBACK
218#endif
219
220void BuiltinsLazyCallback::ResetLazyInternalAttr(JSThread *thread, const JSHandle<JSObject> &object,
221    const char *name)
222{
223    JSHClass *hclass = object->GetClass();
224    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
225    JSHandle<JSTaggedValue> key(factory->NewFromUtf8ReadOnly(name));
226    if (LIKELY(!hclass->IsDictionaryMode())) {
227        LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
228        uint32_t propsNumber = hclass->NumberOfProps();
229        int entry = layoutInfo->FindElementWithCache(thread, hclass, key.GetTaggedValue(), propsNumber);
230        if (entry != -1) {
231            PropertyAttributes attr(layoutInfo->GetAttr(entry));
232            attr.SetIsAccessor(false);
233            layoutInfo->SetNormalAttr(thread, entry, attr);
234        }
235    } else {
236        TaggedArray *array = TaggedArray::Cast(object->GetProperties().GetTaggedObject());
237        ASSERT(array->IsDictionaryMode());
238        NameDictionary *dict = NameDictionary::Cast(array);
239        int entry = dict->FindEntry(key.GetTaggedValue());
240        if (entry != -1) {
241            auto attr = dict->GetAttributes(entry);
242            attr.SetIsAccessor(false);
243            dict->SetAttributes(thread, entry, attr);
244        }
245    }
246}
247}  // namespace panda::ecmascript::builtins
248