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_BUILTINS_BUILTINS_PROMISE_H
17 #define ECMASCRIPT_BUILTINS_BUILTINS_PROMISE_H
18 
19 #include "ecmascript/base/builtins_base.h"
20 #include "ecmascript/ecma_runtime_call_info.h"
21 #include "ecmascript/js_handle.h"
22 #include "ecmascript/js_promise.h"
23 #include "ecmascript/js_tagged_value.h"
24 #include "ecmascript/object_factory.h"
25 
26 // List of functions in Promise, excluding the '@@' propertiex.
27 // V(name, func, length, stubIndex)
28 // where BuiltinsPromise::func refers to the native implementation of Promise[name].
29 //       kungfu::BuiltinsStubCSigns::stubIndex refers to the builtin stub index, or INVALID if no stub available.
30 #define BUILTIN_PROMISE_FUNCTIONS(V)                \
31     /* Promise.all ( iterable ) */                  \
32     V("all",        All,        1, INVALID)         \
33     /* Promise.allSettled ( iterable ) */           \
34     V("allSettled", AllSettled, 1, INVALID)         \
35     /* Promise.any ( iterable ) */                  \
36     V("any",        Any,        1, INVALID)         \
37     /* Promise.race ( iterable ) */                 \
38     V("race",       Race,       1, INVALID)         \
39     /* Promise.reject ( r ) */                      \
40     V("reject",     Reject,     1, INVALID)         \
41     /* Promise.resolve ( x ) */                     \
42     V("resolve",    Resolve,    1, INVALID)
43 
44 // List of functions in Promise.prototype, excluding the constructor and '@@' properties.
45 // V(name, func, length, stubIndex)
46 // where BuiltinsPromise::func refers to the native implementation of Promise.prototype[name].
47 #define BUILTIN_PROMISE_PROTOTYPE_FUNCTIONS(V)                  \
48     /* Promise.prototype.catch ( onRejected ) */                \
49     V("catch",   Catch,   1, INVALID)                           \
50     /* Promise.prototype.finally ( onFinally ) */               \
51     V("finally", Finally, 1, INVALID)                           \
52     /* Promise.prototype.then ( onFulfilled, onRejected ) */    \
53     V("then",    Then,    2, INVALID)
54 
55 namespace panda::ecmascript::builtins {
56 class BuiltinsPromise : public base::BuiltinsBase {
57 public:
58     // 25.4.3.1 Promise ( executor )
59     static JSTaggedValue PromiseConstructor(EcmaRuntimeCallInfo *argv);
60     // 25.4.4.1 Promise.all ( iterable )
61     static JSTaggedValue All(EcmaRuntimeCallInfo *argv);
62     // 25.4.4.3 Promise.race ( iterable )
63     static JSTaggedValue Race(EcmaRuntimeCallInfo *argv);
64     // 25.4.4.4 Promise.reject ( r )
65     static JSTaggedValue Reject(EcmaRuntimeCallInfo *argv);
66     // 25.4.4.5 Promise.resolve ( x )
67     static JSTaggedValue Resolve(EcmaRuntimeCallInfo *argv);
68     // 25.4.4.6 get Promise [ @@species ]
69     static JSTaggedValue GetSpecies(EcmaRuntimeCallInfo *argv);
70     // 25.4.5.1 Promise.prototype.catch ( onRejected )
71     static JSTaggedValue Catch(EcmaRuntimeCallInfo *argv);
72     // 25.4.5.3 Promise.prototype.then ( onFulfilled , onRejected )
73     static JSTaggedValue Then(EcmaRuntimeCallInfo *argv);
74 
75     static JSTaggedValue PerformPromiseThen(JSThread *thread, const JSHandle<JSPromise> &promise,
76                                             const JSHandle<JSTaggedValue> &onFulfilled,
77                                             const JSHandle<JSTaggedValue> &onRejected,
78                                             const JSHandle<PromiseCapability> &capability);
79 
80     static JSTaggedValue Any(EcmaRuntimeCallInfo *argv);
81 
82     static JSTaggedValue AllSettled(EcmaRuntimeCallInfo *argv);
83 
84     static JSTaggedValue Finally(EcmaRuntimeCallInfo *argv);
85 
86     static JSTaggedValue GetPromiseResolve(JSThread *thread, JSHandle<JSTaggedValue> promiseConstructor);
87 
88     // Excluding the '@@' internal properties
GetPromiseFunctions()89     static Span<const base::BuiltinFunctionEntry> GetPromiseFunctions()
90     {
91         return Span<const base::BuiltinFunctionEntry>(PROMISE_FUNCTIONS);
92     }
93 
94     // Excluding the constructor and '@@' internal properties.
GetPromisePrototypeFunctions()95     static Span<const base::BuiltinFunctionEntry> GetPromisePrototypeFunctions()
96     {
97         return Span<const base::BuiltinFunctionEntry>(PROMISE_PROTOTYPE_FUNCTIONS);
98     }
99 
100 private:
101 #define BUILTIN_PROMISE_FUNCTION_ENTRY(name, method, length, id) \
102     base::BuiltinFunctionEntry::Create(name, BuiltinsPromise::method, length, kungfu::BuiltinsStubCSigns::id),
103 
104     static constexpr std::array PROMISE_FUNCTIONS  = {
105         BUILTIN_PROMISE_FUNCTIONS(BUILTIN_PROMISE_FUNCTION_ENTRY)
106     };
107     static constexpr std::array PROMISE_PROTOTYPE_FUNCTIONS = {
108         BUILTIN_PROMISE_PROTOTYPE_FUNCTIONS(BUILTIN_PROMISE_FUNCTION_ENTRY)
109     };
110 #undef BUILTIN_PROMISE_FUNCTION_ENTRY
111 
112     static JSTaggedValue PerformPromiseAll(JSThread *thread,
113                                            const JSHandle<PromiseIteratorRecord> &itRecord,
114                                            const JSHandle<JSTaggedValue> &ctor,
115                                            const JSHandle<PromiseCapability> &capa);
116 
117     static JSHandle<CompletionRecord> PerformPromiseRace(JSThread *thread,
118                                                          const JSHandle<PromiseIteratorRecord> &iteratorRecord,
119                                                          const JSHandle<PromiseCapability> &capability,
120                                                          const JSHandle<JSTaggedValue> &constructor);
121 
122     static JSHandle<CompletionRecord> PerformPromiseAllSettled(JSThread *thread,
123                                                                const JSHandle<PromiseIteratorRecord> &iterRecord,
124                                                                const JSHandle<JSTaggedValue> &constructor,
125                                                                const JSHandle<PromiseCapability> &resultCapa,
126                                                                const JSHandle<JSTaggedValue> &promiseResolve);
127 
128     static JSHandle<CompletionRecord> PerformPromiseAny(JSThread *thread,
129                                                         const JSHandle<PromiseIteratorRecord> &iteratorRecord,
130                                                         const JSHandle<JSTaggedValue> &constructor,
131                                                         const JSHandle<PromiseCapability> &resultCapability,
132                                                         const JSHandle<JSTaggedValue> &promiseResolve);
133 };
134 }  // namespace panda::ecmascript::builtins
135 #endif  // ECMASCRIPT_BUILTINS_BUILTINS_PROMISE_H