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 
21 namespace panda::ecmascript::builtins {
Date(JSThread *thread, const JSHandle<JSObject> &obj)22 JSTaggedValue 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 
Set(JSThread *thread, const JSHandle<JSObject> &obj)37 JSTaggedValue 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 
Map(JSThread *thread, const JSHandle<JSObject> &obj)52 JSTaggedValue 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 
WeakMap(JSThread *thread, const JSHandle<JSObject> &obj)67 JSTaggedValue 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 
WeakSet(JSThread *thread, const JSHandle<JSObject> &obj)81 JSTaggedValue 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 
WeakRef(JSThread *thread, const JSHandle<JSObject> &obj)95 JSTaggedValue 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 
FinalizationRegistry(JSThread *thread, const JSHandle<JSObject> &obj)109 JSTaggedValue 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 
TypedArray(JSThread *thread, const JSHandle<JSObject> &obj)123 JSTaggedValue 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 
135 ITERATE_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 
155 ITERATE_TYPED_ARRAY(TYPED_ARRAY_CALLBACK)
156 #undef TYPED_ARRAY_CALLBACK
157 
ArrayBuffer(JSThread *thread, const JSHandle<JSObject> &obj)158 JSTaggedValue 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 
DataView(JSThread *thread, const JSHandle<JSObject> &obj)172 JSTaggedValue 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 
SharedArrayBuffer(JSThread *thread, const JSHandle<JSObject> &obj)187 JSTaggedValue 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 
216 ITERATE_INTL(INTL_CALLBACK)
217 #undef INTL_CALLBACK
218 #endif
219 
ResetLazyInternalAttr(JSThread *thread, const JSHandle<JSObject> &object, const char *name)220 void 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