• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #ifndef ECMASCRIPT_JSFUCNTION_H
17 #define ECMASCRIPT_JSFUCNTION_H
18 
19 #include "ecmascript/accessor_data.h"
20 #include "ecmascript/ecma_macros.h"
21 #include "ecmascript/ecma_runtime_call_info.h"
22 #include "ecmascript/js_object-inl.h"
23 #include "ecmascript/lexical_env.h"
24 
25 namespace panda::ecmascript {
26 using panda::coretypes::DynClass;
27 class JSThread;
28 
29 class JSFunctionBase : public JSObject {
30 public:
31     CAST_CHECK(JSFunctionBase, IsJSFunctionBase);
32 
SetConstructor(bool flag)33     inline void SetConstructor(bool flag)
34     {
35         JSHClass *hclass = GetJSHClass();
36         hclass->SetConstructor(flag);
37     }
38 
39     static bool SetFunctionName(JSThread *thread, const JSHandle<JSFunctionBase> &func,
40                                 const JSHandle<JSTaggedValue> &name, const JSHandle<JSTaggedValue> &prefix);
41     static JSHandle<JSTaggedValue> GetFunctionName(JSThread *thread, const JSHandle<JSFunctionBase> &func);
42 
SetCallTarget(const JSThread * thread,JSMethod * p)43     void SetCallTarget([[maybe_unused]] const JSThread *thread, JSMethod *p)
44     {
45         SetMethod(p);
46     }
47 
48     static constexpr size_t METHOD_OFFSET = JSObject::SIZE;
49     ACCESSORS_NATIVE_FIELD(Method, JSMethod, METHOD_OFFSET, LAST_OFFSET)
50     DEFINE_ALIGN_SIZE(LAST_OFFSET);
51 
52     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, SIZE, SIZE)
53 };
54 
55 static_assert((JSFunctionBase::SIZE % static_cast<uint8_t>(MemAlignment::MEM_ALIGN_OBJECT)) == 0);
56 
57 class JSFunction : public JSFunctionBase {
58 public:
59     static constexpr int LENGTH_OF_INLINE_PROPERTIES = 3;
60     static constexpr int LENGTH_INLINE_PROPERTY_INDEX = 0;
61     static constexpr int NAME_INLINE_PROPERTY_INDEX = 1;
62     static constexpr int PROTOTYPE_INLINE_PROPERTY_INDEX = 2;
63     static constexpr int CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX = 1;
64 
65     /* -------------- Common API Begin, Don't change those interface!!! ----------------- */
66     CAST_CHECK(JSFunction, IsJSFunction);
67 
68     static void InitializeJSFunction(JSThread *thread, const JSHandle<GlobalEnv> &env, const JSHandle<JSFunction> &func,
69                                      FunctionKind kind = FunctionKind::NORMAL_FUNCTION, bool strict = true);
70     // ecma6 7.3
71     static bool OrdinaryHasInstance(JSThread *thread, const JSHandle<JSTaggedValue> &constructor,
72                                     const JSHandle<JSTaggedValue> &obj);
73 
74     static JSTaggedValue SpeciesConstructor(const JSHandle<JSFunction> &func,
75                                             const JSHandle<JSFunction> &defaultConstructor);
76 
77     // ecma6 9.2
78     // 7.3.12 Call(F, V, argumentsList)
79 
80     static JSTaggedValue Call(JSThread *thread, const JSHandle<JSTaggedValue> &func,
81                               const JSHandle<JSTaggedValue> &thisArg, uint32_t argc, const JSTaggedType argv[]);
82 
83     static JSTaggedValue Construct(JSThread *thread, const JSHandle<JSTaggedValue> &func, uint32_t argc,
84                                    const JSTaggedType argv[], const JSHandle<JSTaggedValue> &newTarget);
85     static JSTaggedValue Invoke(JSThread *thread, const JSHandle<JSTaggedValue> &thisArg,
86                                  const JSHandle<JSTaggedValue> &key, uint32_t argc, const JSTaggedType argv[]);
87     // 9.2.1[[Call]](thisArgument, argumentsList)
88     // 9.3.1[[Call]](thisArgument, argumentsList)
89     static JSTaggedValue CallInternal(JSThread *thread, const JSHandle<JSFunction> &func,
90                                       const JSHandle<JSTaggedValue> &thisArg, uint32_t argc, const JSTaggedType argv[]);
91     // 9.2.2[[Construct]](argumentsList, newTarget)
92     // 9.3.2[[Construct]](argumentsList, newTarget)
93     static JSTaggedValue ConstructInternal(JSThread *thread, const JSHandle<JSFunction> &func, uint32_t argc,
94                                             const JSTaggedType argv[], const JSHandle<JSTaggedValue> &newTarget);
95 
96     static bool AddRestrictedFunctionProperties(const JSHandle<JSFunction> &func, const JSHandle<JSTaggedValue> &realm);
97     static bool MakeConstructor(JSThread *thread, const JSHandle<JSFunction> &func,
98                                 const JSHandle<JSTaggedValue> &proto, bool writable = true);
99     static bool SetFunctionLength(JSThread *thread, const JSHandle<JSFunction> &func, JSTaggedValue length,
100                                   bool cfg = true);
101     static JSHandle<JSObject> NewJSFunctionPrototype(JSThread *thread, ObjectFactory *factory,
102                                                      const JSHandle<JSFunction> &func);
103     static DynClass *GetOrCreateInitialDynClass(JSThread *thread, const JSHandle<JSFunction> &fun);
104     static JSTaggedValue AccessCallerArgumentsThrowTypeError(EcmaRuntimeCallInfo *argv);
105     static bool IsDynClass(JSTaggedValue object);
106     static JSTaggedValue PrototypeGetter(JSThread *thread, const JSHandle<JSObject> &self);
107     static bool PrototypeSetter(JSThread *thread, const JSHandle<JSObject> &self, const JSHandle<JSTaggedValue> &value,
108                                 bool mayThrow);
109     static JSTaggedValue NameGetter(JSThread *thread, const JSHandle<JSObject> &self);
110     static bool NameSetter(JSThread *thread, const JSHandle<JSObject> &self, const JSHandle<JSTaggedValue> &value,
111                            bool mayThrow);
112     static void SetFunctionNameNoPrefix(JSThread *thread, JSFunction *func, JSTaggedValue name);
113     static JSHandle<DynClass> GetInstanceDynClass(JSThread *thread, JSHandle<JSFunction> constructor,
114                                                   JSHandle<JSTaggedValue> newTarget);
115 
GetFunctionPrototype()116     inline JSTaggedValue GetFunctionPrototype() const
117     {
118         ASSERT(HasFunctionPrototype());
119         JSTaggedValue protoOrDyn = GetProtoOrDynClass();
120         if (protoOrDyn.IsJSHClass()) {
121             return JSHClass::Cast(protoOrDyn.GetTaggedObject())->GetPrototype();
122         }
123 
124         return protoOrDyn;
125     }
126 
SetFunctionPrototype(const JSThread * thread,JSTaggedValue proto)127     inline void SetFunctionPrototype(const JSThread *thread, JSTaggedValue proto)
128     {
129         SetProtoOrDynClass(thread, proto);
130         if (proto.IsJSHClass()) {
131             proto = JSHClass::Cast(proto.GetTaggedObject())->GetPrototype();
132         }
133         if (proto.IsECMAObject()) {
134             proto.GetTaggedObject()->GetClass()->SetIsPrototype(true);
135         }
136     }
137 
HasInitialDynClass()138     inline bool HasInitialDynClass() const
139     {
140         JSTaggedValue protoOrDyn = GetProtoOrDynClass();
141         return protoOrDyn.IsJSHClass();
142     }
143 
HasFunctionPrototype()144     inline bool HasFunctionPrototype() const
145     {
146         JSTaggedValue protoOrDyn = GetProtoOrDynClass();
147         return !protoOrDyn.IsHole();
148     }
149 
GetInitialDynClass()150     inline DynClass *GetInitialDynClass() const
151     {
152         ASSERT(HasInitialDynClass());
153         JSTaggedValue protoOrDyn = GetProtoOrDynClass();
154         return reinterpret_cast<DynClass *>(protoOrDyn.GetTaggedObject());
155     }
156 
SetFunctionLength(const JSThread * thread,JSTaggedValue length)157     inline void SetFunctionLength(const JSThread *thread, JSTaggedValue length)
158     {
159         ASSERT(!IsPropertiesDict());
160         SetPropertyInlinedProps(thread, LENGTH_INLINE_PROPERTY_INDEX, length);
161     }
162 
IsBase()163     inline bool IsBase() const
164     {
165         FunctionKind kind = GetFunctionKind();
166         return kind <= FunctionKind::CLASS_CONSTRUCTOR;
167     }
168 
IsDerivedConstructor()169     inline bool IsDerivedConstructor() const
170     {
171         FunctionKind kind = GetFunctionKind();
172         return kind == FunctionKind::DERIVED_CONSTRUCTOR;
173     }
174 
IsArrowFunction(FunctionKind kind)175     inline static bool IsArrowFunction(FunctionKind kind)
176     {
177         return (kind >= FunctionKind::ARROW_FUNCTION) && (kind <= FunctionKind::ASYNC_ARROW_FUNCTION);
178     }
179 
IsClassConstructor(FunctionKind kind)180     inline static bool IsClassConstructor(FunctionKind kind)
181     {
182         return (kind == FunctionKind::CLASS_CONSTRUCTOR) || (kind == FunctionKind::DERIVED_CONSTRUCTOR);
183     }
184 
IsConstructorKind(FunctionKind kind)185     inline static bool IsConstructorKind(FunctionKind kind)
186     {
187         return (kind >= FunctionKind::BUILTIN_PROXY_CONSTRUCTOR) && (kind <= FunctionKind::DERIVED_CONSTRUCTOR);
188     }
189 
IsBuiltinConstructor(FunctionKind kind)190     inline static bool IsBuiltinConstructor(FunctionKind kind)
191     {
192         return kind >= FunctionKind::BUILTIN_PROXY_CONSTRUCTOR && kind <= FunctionKind::BUILTIN_CONSTRUCTOR;
193     }
194 
HasPrototype(FunctionKind kind)195     inline static bool HasPrototype(FunctionKind kind)
196     {
197         return kind >= FunctionKind::BUILTIN_CONSTRUCTOR && kind <= FunctionKind::GENERATOR_FUNCTION;
198     }
199 
HasAccessor(FunctionKind kind)200     inline static bool HasAccessor(FunctionKind kind)
201     {
202         return kind >= FunctionKind::NORMAL_FUNCTION && kind <= FunctionKind::ASYNC_FUNCTION;
203     }
204 
IsClassConstructor()205     inline bool IsClassConstructor() const
206     {
207         return GetClass()->IsClassConstructor();
208     }
209 
SetClassConstructor(bool flag)210     inline void SetClassConstructor(bool flag)
211     {
212         GetClass()->SetClassConstructor(flag);
213     }
214 
215     /* -------------- Common API End, Don't change those interface!!! ----------------- */
216     static void InitializeJSFunction(JSThread *thread, const JSHandle<JSFunction> &func,
217                                      FunctionKind kind = FunctionKind::NORMAL_FUNCTION, bool strict = true);
218     static JSHClass *GetOrCreateInitialJSHClass(JSThread *thread, const JSHandle<JSFunction> &fun);
219     static JSHandle<JSHClass> GetInstanceJSHClass(JSThread *thread, JSHandle<JSFunction> constructor,
220                                                   JSHandle<JSTaggedValue> newTarget);
221 
222     static constexpr size_t PROTO_OR_DYNCLASS_OFFSET = JSFunctionBase::SIZE;
223     ACCESSORS(ProtoOrDynClass, PROTO_OR_DYNCLASS_OFFSET, LEXICAL_ENV_OFFSET)
224     ACCESSORS(LexicalEnv, LEXICAL_ENV_OFFSET, HOME_OBJECT_OFFSET)
225     ACCESSORS(HomeObject, HOME_OBJECT_OFFSET, FUNCTION_EXTRA_INFO_OFFSET)
226     ACCESSORS(FunctionExtraInfo, FUNCTION_EXTRA_INFO_OFFSET, CONSTANT_POOL_OFFSET)
227     ACCESSORS(ConstantPool, CONSTANT_POOL_OFFSET, PROFILE_TYPE_INFO_OFFSET)
228     ACCESSORS(ProfileTypeInfo, PROFILE_TYPE_INFO_OFFSET, BIT_FIELD_OFFSET)
229     ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET)
230     DEFINE_ALIGN_SIZE(LAST_OFFSET);
231 
232     // define BitField
233     static constexpr uint32_t FUNCTION_KIND_BITS = 4;
234     static constexpr uint32_t STRICT_BITS = 1;
235     static constexpr uint32_t RESOLVED_BITS = 1;
236     static constexpr uint32_t THIS_MODE_BITS = 2;
237     FIRST_BIT_FIELD(BitField, FunctionKind, FunctionKind, FUNCTION_KIND_BITS)
238     NEXT_BIT_FIELD(BitField, Strict, bool, STRICT_BITS, FunctionKind)
239     NEXT_BIT_FIELD(BitField, Resolved, bool, RESOLVED_BITS, Strict)
240     NEXT_BIT_FIELD(BitField, ThisMode, FunctionMode, THIS_MODE_BITS, Resolved)
241 
242     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunctionBase, PROTO_OR_DYNCLASS_OFFSET, BIT_FIELD_OFFSET)
243     DECL_DUMP()
244 
245 private:
246     static JSHandle<JSHClass> GetOrCreateDerivedJSHClass(JSThread *thread, JSHandle<JSFunction> derived,
247                                                          JSHandle<JSFunction> constructor,
248                                                          JSHandle<JSHClass> ctorInitialDynClass);
249 };
250 
251 class JSGeneratorFunction : public JSFunction {
252 public:
253     CAST_CHECK(JSGeneratorFunction, IsGeneratorFunction);
254 
255     static constexpr size_t SIZE = JSFunction::SIZE;
256 
257     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, SIZE, SIZE)
258 
259     DECL_DUMP()
260 };
261 
262 class JSBoundFunction : public JSFunctionBase {
263 public:
264     CAST_CHECK(JSBoundFunction, IsBoundFunction);
265 
266     // 9.4.1.1[[Call]](thisArgument, argumentsList)
267     static JSTaggedValue CallInternal(JSThread *thread, const JSHandle<JSBoundFunction> &func);
268 
269     // 9.4.1.2[[Construct]](argumentsList, newTarget)
270     static JSTaggedValue ConstructInternal(JSThread *thread, const JSHandle<JSBoundFunction> &func,
271                                            const JSHandle<JSTaggedValue> &newTarget);
272 
273     static constexpr size_t BOUND_TARGET_OFFSET = JSFunctionBase::SIZE;
274     ACCESSORS(BoundTarget, BOUND_TARGET_OFFSET, BOUND_THIS_OFFSET);
275     ACCESSORS(BoundThis, BOUND_THIS_OFFSET, BOUND_ARGUMENTS_OFFSET);
276     ACCESSORS(BoundArguments, BOUND_ARGUMENTS_OFFSET, SIZE);
277 
278     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunctionBase, BOUND_TARGET_OFFSET, SIZE)
279 
280     DECL_DUMP()
281 };
282 
283 class JSProxyRevocFunction : public JSFunction {
284 public:
285     CAST_CHECK(JSProxyRevocFunction, IsProxyRevocFunction);
286 
287     static void ProxyRevocFunctions(const JSThread *thread, const JSHandle<JSProxyRevocFunction> &revoker);
288 
289     static constexpr size_t REVOCABLE_PROXY_OFFSET = JSFunction::SIZE;
290     ACCESSORS(RevocableProxy, REVOCABLE_PROXY_OFFSET, SIZE);
291 
292     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, REVOCABLE_PROXY_OFFSET, SIZE)
293 
294     DECL_DUMP()
295 };
296 
297 // ResolveFunction/RejectFunction
298 class JSPromiseReactionsFunction : public JSFunction {
299 public:
300     CAST_CHECK(JSPromiseReactionsFunction, IsJSPromiseReactionFunction);
301 
302     static constexpr size_t PROMISE_OFFSET = JSFunction::SIZE;
303     ACCESSORS(Promise, PROMISE_OFFSET, ALREADY_RESOLVED_OFFSET);
304     ACCESSORS(AlreadyResolved, ALREADY_RESOLVED_OFFSET, SIZE);
305 
306     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, PROMISE_OFFSET, SIZE)
307 
308     DECL_DUMP()
309 };
310 
311 // ExecutorFunction
312 class JSPromiseExecutorFunction : public JSFunction {
313 public:
314     CAST_CHECK(JSPromiseExecutorFunction, IsJSPromiseExecutorFunction);
315 
316     static constexpr size_t CAPABILITY_OFFSET = JSFunction::SIZE;
317     ACCESSORS(Capability, CAPABILITY_OFFSET, SIZE);
318 
319     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, CAPABILITY_OFFSET, SIZE)
320 
321     DECL_DUMP()
322 };
323 
324 class JSPromiseAllResolveElementFunction : public JSFunction {
325 public:
326     CAST_CHECK(JSPromiseAllResolveElementFunction, IsJSPromiseAllResolveElementFunction);
327 
328     static constexpr size_t INDEX_OFFSET = JSFunction::SIZE;
329     ACCESSORS(Index, INDEX_OFFSET, VALUES_OFFSET);
330     ACCESSORS(Values, VALUES_OFFSET, CAPABILITIES_OFFSET);
331     ACCESSORS(Capabilities, CAPABILITIES_OFFSET, REMAINING_ELEMENTS_OFFSET);
332     ACCESSORS(RemainingElements, REMAINING_ELEMENTS_OFFSET, ALREADY_CALLED_OFFSET);
333     ACCESSORS(AlreadyCalled, ALREADY_CALLED_OFFSET, SIZE);
334 
335     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, INDEX_OFFSET, SIZE)
336 
337     DECL_DUMP()
338 };
339 
340 class JSIntlBoundFunction : public JSFunction {
341 public:
342     CAST_CHECK(JSIntlBoundFunction, IsJSIntlBoundFunction);
343 
344     static JSTaggedValue IntlNameGetter(JSThread *thread, const JSHandle<JSObject> &self);
345 
346     static constexpr size_t NUMBER_FORMAT_OFFSET = JSFunction::SIZE;
347 
348     ACCESSORS(NumberFormat, NUMBER_FORMAT_OFFSET, DATETIME_FORMAT_OFFSET);
349     ACCESSORS(DateTimeFormat, DATETIME_FORMAT_OFFSET, COLLATOR_OFFSET);
350     ACCESSORS(Collator, COLLATOR_OFFSET, SIZE);
351 
352     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, NUMBER_FORMAT_OFFSET, SIZE)
353     DECL_DUMP()
354 };
355 }  // namespace panda::ecmascript
356 
357 #endif  // ECMASCRIPT_JSFUCNTION_H
358