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
55namespace panda::ecmascript::builtins {
56class BuiltinsPromise : public base::BuiltinsBase {
57public:
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
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.
95    static Span<const base::BuiltinFunctionEntry> GetPromisePrototypeFunctions()
96    {
97        return Span<const base::BuiltinFunctionEntry>(PROMISE_PROTOTYPE_FUNCTIONS);
98    }
99
100private:
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