1/*
2 * Copyright (c) 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#ifndef ECMASCRIPT_BUILTINS_BUILTINS_SHARED_ARRAY_H
17#define ECMASCRIPT_BUILTINS_BUILTINS_SHARED_ARRAY_H
18
19#include "ecmascript/base/builtins_base.h"
20
21// List of functions in Shared Array, excluding the '@@' properties.
22// V(name, func, length, stubIndex)
23// where BuiltinsSharedArray::func refers to the native implementation of SharedArray[name].
24//       kungfu::BuiltinsStubCSigns::stubIndex refers to the builtin stub index, or INVALID if no stub available.
25#define BUILTIN_SHARED_ARRAY_FUNCTIONS(V)                      \
26    /* SharedArray.from ( items [ , mapfn [ , thisArg ] ] ) */ \
27    V("from", From, 1, INVALID)                                \
28    V("create", Create, 2, INVALID)                            \
29    /* SendableArray.isArray ( arg ) */                        \
30    V("isArray", IsArray, 1, INVALID)                          \
31    // fixme(hzzhouzebin) Support later.
32    // /* SharedArray.of ( ...items ) */                          \
33    // V("of", Of, 0, INVALID)
34
35// List of functions in SharedArray.prototype, excluding the constructor and '@@' properties.
36// V(name, func, length, stubIndex)
37// where BuiltinsSharedArray::func refers to the native implementation of SharedArray.prototype[name].
38#define BUILTIN_SHARED_ARRAY_PROTOTYPE_FUNCTIONS(V)                              \
39    /* SharedArray.prototype.at ( index ) */                                     \
40    V("at", At, 1, INVALID)                                                      \
41    /* SharedArray.prototype.concat ( ...items ) */                              \
42    V("concat", Concat, 1, INVALID)                                              \
43    /* SharedArray.prototype.entries ( ) */                                      \
44    V("entries", Entries, 0, INVALID)                                            \
45    /* SharedArray.prototype.fill ( value [ , start [ , end ] ] ) */             \
46    V("fill", Fill, 1, INVALID)                                                  \
47    /* SharedArray.prototype.filter ( callbackfn [ , thisArg ] ) */              \
48    V("filter", Filter, 1, INVALID)                                              \
49    /* SharedArray.prototype.find ( predicate [ , thisArg ] ) */                 \
50    V("find", Find, 1, INVALID)                                                  \
51    /* SharedArray.prototype.findIndex ( predicate [ , thisArg ] ) */            \
52    V("findIndex", FindIndex, 1, INVALID)                                        \
53    /* SharedArray.prototype.forEach ( callbackfn [ , thisArg ] ) */             \
54    V("forEach", ForEach, 1, INVALID)                                            \
55    /* SharedArray.prototype.includes ( searchElement [ , fromIndex ] ) */       \
56    V("includes", Includes, 1, INVALID)                                          \
57    /* SharedArray.prototype.indexOf ( searchElement [ , fromIndex ] ) */        \
58    V("indexOf", IndexOf, 1, INVALID)                                            \
59    /* SharedArray.prototype.join ( separator ) */                               \
60    V("join", Join, 1, INVALID)                                                  \
61    /* SharedArray.prototype.keys ( ) */                                         \
62    V("keys", Keys, 0, INVALID)                                                  \
63    /* SharedArray.prototype.map ( callbackfn [ , thisArg ] ) */                 \
64    V("map", Map, 1, INVALID)                                                    \
65    /* SharedArray.prototype.pop ( ) */                                          \
66    V("pop", Pop, 0, INVALID)                                                    \
67    /* SharedArray.prototype.push ( ...items ) */                                \
68    V("push", Push, 1, INVALID)                                                  \
69    /* SharedArray.prototype.reduce ( callbackfn [ , initialValue ] ) */         \
70    V("reduce", Reduce, 1, INVALID)                                              \
71    /* SharedArray.prototype.shift ( ) */                                        \
72    V("shift", Shift, 0, INVALID)                                                \
73    /* SharedArray.prototype.slice ( start, end ) */                             \
74    V("slice", Slice, 2, INVALID)                                                \
75    /* SharedArray.prototype.sort ( comparefn ) */                               \
76    V("sort", Sort, 1, INVALID)                                                  \
77    /* SharedArray.prototype.toString ( ) */                                     \
78    V("toString", ToString, 0, INVALID)                                          \
79    /* SharedArray.prototype.values ( ) */                                       \
80    /* SharedArray.prototype.unshift ( ...items ) */                             \
81    V("unshift", Unshift, 1, INVALID)                                            \
82    V("values", Values, 0, INVALID)                                              \
83    V("shrinkTo", ShrinkTo, 0, INVALID)                                          \
84    V("extendTo", ExtendTo, 0, INVALID)                                          \
85    /* SharedArray.prototype.splice ( start, deleteCount, ...items ) */          \
86    V("splice", Splice, 2, INVALID)                                              \
87    /* SharedArray.prototype.every ( callbackfn [ , thisArg ] ) */               \
88    V("every", Every, 1, INVALID)                                                \
89    /* SharedArray.prototype.some ( callbackfn [ , thisArg ] ) */                \
90    V("some", Some, 1, INVALID)                                                  \
91    /* SendableArray.prototype.lastIndexOf ( searchElement [ , fromIndex ] ) */  \
92    V("lastIndexOf", LastIndexOf, 1, INVALID)
93    // fixme(hzzhouzebin) Support later.
94    // /* SharedArray.prototype.with ( index, value ) */                            \
95    // V("with", With, 2, INVALID)                                                  \
96    // /* SharedArray.prototype.reduceRight ( callbackfn [ , initialValue ] ) */    \
97    // V("reduceRight", ReduceRight, 1, INVALID)                                    \
98    // /* SharedArray.prototype.reverse ( ) */                                      \
99    // V("reverse", Reverse, 0, INVALID)                                            \
100    // /* SharedArray.prototype.copyWithin ( target, start [ , end ] ) */           \
101    // V("copyWithin", CopyWithin, 2, INVALID)                                      \
102    // /* SharedArray.prototype.findLast ( predicate [ , thisArg ] ) */             \
103    // V("findLast", FindLast, 1, INVALID)                                          \
104    // /* SharedArray.prototype.findLastIndex ( predicate [ , thisArg ] ) */        \
105    // V("findLastIndex", FindLastIndex, 1, INVALID)                                \
106    // /* SharedArray.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ) */ \
107    // V("toLocaleString", ToLocaleString, 0, INVALID)                              \
108    // /* SharedArray.prototype.toReversed ( ) */                                   \
109    // V("toReversed", ToReversed, 0, INVALID)                                      \
110    // /* SharedArray.prototype.toSorted ( comparefn ) */                           \
111    // V("toSorted", ToSorted, 1, INVALID)                                          \
112    // /* SharedArray.prototype.toSpliced ( start, skipCount, ...items ) */         \
113    // V("toSpliced", ToSpliced, 2, INVALID)
114
115namespace panda::ecmascript::builtins {
116class BuiltinsSharedArray : public base::BuiltinsBase {
117public:
118    static JSTaggedValue ArrayConstructor(EcmaRuntimeCallInfo *argv);
119    static JSTaggedValue From(EcmaRuntimeCallInfo *argv);
120    static JSTaggedValue Create(EcmaRuntimeCallInfo *argv);
121    static JSTaggedValue IsArray(EcmaRuntimeCallInfo *argv);
122    static JSTaggedValue Species(EcmaRuntimeCallInfo *argv);
123
124    // prototype
125    static JSTaggedValue Concat(EcmaRuntimeCallInfo *argv);
126    static JSTaggedValue Entries(EcmaRuntimeCallInfo *argv);
127    static JSTaggedValue Fill(EcmaRuntimeCallInfo *argv);
128    static JSTaggedValue Filter(EcmaRuntimeCallInfo *argv);
129    static JSTaggedValue Find(EcmaRuntimeCallInfo *argv);
130    static JSTaggedValue FindIndex(EcmaRuntimeCallInfo *argv);
131    static JSTaggedValue ForEach(EcmaRuntimeCallInfo *argv);
132    static JSTaggedValue IndexOf(EcmaRuntimeCallInfo *argv);
133    static JSTaggedValue Join(EcmaRuntimeCallInfo *argv);
134    static JSTaggedValue Keys(EcmaRuntimeCallInfo *argv);
135    static JSTaggedValue Map(EcmaRuntimeCallInfo *argv);
136    static JSTaggedValue Pop(EcmaRuntimeCallInfo *argv);
137    static JSTaggedValue Push(EcmaRuntimeCallInfo *argv);
138    static JSTaggedValue Reduce(EcmaRuntimeCallInfo *argv);
139    static JSTaggedValue Shift(EcmaRuntimeCallInfo *argv);
140    static JSTaggedValue Slice(EcmaRuntimeCallInfo *argv);
141    static JSTaggedValue Splice(EcmaRuntimeCallInfo *argv);
142    static JSTaggedValue Sort(EcmaRuntimeCallInfo *argv);
143    static JSTaggedValue ToString(EcmaRuntimeCallInfo *argv);
144    static JSTaggedValue Unshift(EcmaRuntimeCallInfo *argv);
145    static JSTaggedValue Values(EcmaRuntimeCallInfo *argv);
146    static JSTaggedValue Unscopables(EcmaRuntimeCallInfo *argv);
147    static JSTaggedValue Includes(EcmaRuntimeCallInfo *argv);
148    static JSTaggedValue At(EcmaRuntimeCallInfo *argv);
149    static JSTaggedValue ShrinkTo(EcmaRuntimeCallInfo *argv);
150    static JSTaggedValue ExtendTo(EcmaRuntimeCallInfo *argv);
151    static JSTaggedValue Every(EcmaRuntimeCallInfo *argv);
152    static JSTaggedValue Some(EcmaRuntimeCallInfo *argv);
153    static JSTaggedValue LastIndexOf(EcmaRuntimeCallInfo *argv);
154
155    // Excluding the '@@' internal properties
156    static Span<const base::BuiltinFunctionEntry> GetSharedArrayFunctions()
157    {
158        return Span<const base::BuiltinFunctionEntry>(SENDABLE_ARRAY_FUNCTIONS);
159    }
160
161    // Excluding the constructor and '@@' internal properties.
162    static Span<const base::BuiltinFunctionEntry> GetSharedArrayPrototypeFunctions()
163    {
164        return Span<const base::BuiltinFunctionEntry>(SENDABLE_ARRAY_PROTOTYPE_FUNCTIONS);
165    }
166
167    static size_t GetNumPrototypeInlinedProperties()
168    {
169        // 4 : 4 More inlined entries in SharedArray.prototype for the following functions/accessors:
170        //   (1) 'length' accessor
171        //   (2) SharedArray.prototype.constructor, i.e. Array()
172        //   (3) SharedArray.prototype[@@iterator]()
173        //   (4) SharedArray.prototype[@@unscopables]()
174        return GetSharedArrayPrototypeFunctions().Size() + 4;
175    }
176    static JSTaggedValue ReduceUnStableJSArray(JSThread *thread, JSHandle<JSTaggedValue> &thisHandle,
177        JSHandle<JSTaggedValue> &thisObjVal, int64_t k, int64_t len, JSMutableHandle<JSTaggedValue> &accumulator,
178        JSHandle<JSTaggedValue> &callbackFnHandle);
179
180    static JSTaggedValue FilterUnStableJSArray(JSThread *thread, JSHandle<JSTaggedValue> &thisArgHandle,
181        JSHandle<JSTaggedValue> &thisObjVal, int64_t k, int64_t len, uint32_t toIndex,
182        JSHandle<JSObject> newArrayHandle, JSHandle<JSTaggedValue> &callbackFnHandle);
183
184    static Span<const std::pair<std::string_view, bool>> GetPrototypeProperties()
185    {
186        return Span<const std::pair<std::string_view, bool>>(ARRAY_PROTOTYPE_PROPERTIES);
187    }
188    static Span<const std::pair<std::string_view, bool>> GetFunctionProperties()
189    {
190        return Span<const std::pair<std::string_view, bool>>(ARRAY_FUNCTION_PROPERTIES);
191    }
192private:
193    static JSTaggedValue PopInner(EcmaRuntimeCallInfo *argv, JSHandle<JSTaggedValue> &thisHandle,
194                                  JSHandle<JSObject> &thisObjHandle);
195#define BUILTIN_SENDABLE_ARRAY_FUNCTION_ENTRY(name, method, length, id) \
196    base::BuiltinFunctionEntry::Create(name, BuiltinsSharedArray::method, length, kungfu::BuiltinsStubCSigns::id),
197
198    static constexpr std::array SENDABLE_ARRAY_FUNCTIONS  = {
199        BUILTIN_SHARED_ARRAY_FUNCTIONS(BUILTIN_SENDABLE_ARRAY_FUNCTION_ENTRY)
200    };
201    static constexpr std::array SENDABLE_ARRAY_PROTOTYPE_FUNCTIONS = {
202        BUILTIN_SHARED_ARRAY_PROTOTYPE_FUNCTIONS(BUILTIN_SENDABLE_ARRAY_FUNCTION_ENTRY)
203    };
204#undef BUILTIN_SENDABLE_ARRAY_FUNCTION_ENTRY
205
206    static JSTaggedValue IndexOfSlowPath(
207        EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle);
208
209    static JSTaggedValue IndexOfSlowPath(
210        EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisObjVal,
211        int64_t length, int64_t fromIndex);
212
213    static JSTaggedValue LastIndexOfSlowPath(EcmaRuntimeCallInfo *argv, JSThread *thread,
214                                             const JSHandle<JSTaggedValue> &thisHandle);
215    static JSTaggedValue LastIndexOfSlowPath(EcmaRuntimeCallInfo *argv, JSThread *thread,
216                                             const JSHandle<JSTaggedValue> &thisObjVal, int64_t fromIndex);
217
218#define ARRAY_PROPERTIES_PAIR(name, func, length, id) \
219    std::pair<std::string_view, bool>(name, false),
220
221    static constexpr std::array ARRAY_PROTOTYPE_PROPERTIES = {
222        std::pair<std::string_view, bool>("length", false),
223        std::pair<std::string_view, bool>("constructor", false),
224        BUILTIN_SHARED_ARRAY_PROTOTYPE_FUNCTIONS(ARRAY_PROPERTIES_PAIR)
225        std::pair<std::string_view, bool>("[Symbol.iterator]", false),
226        std::pair<std::string_view, bool>("[Symbol.unscopables]", false)
227    };
228    static constexpr std::array ARRAY_FUNCTION_PROPERTIES = {
229        std::pair<std::string_view, bool>("length", false),
230        std::pair<std::string_view, bool>("name", false),
231        std::pair<std::string_view, bool>("prototype", false),
232        BUILTIN_SHARED_ARRAY_FUNCTIONS(ARRAY_PROPERTIES_PAIR)
233        std::pair<std::string_view, bool>("[Symbol.species]", true),
234    };
235    static JSTaggedValue CheckElementForEvery(JSThread *thread,
236                                              JSHandle<JSTaggedValue> &thisObjVal,
237                                              JSHandle<JSTaggedValue> &callbackFnHandle,
238                                              JSHandle<JSTaggedValue> &thisArgHandle,
239                                              uint32_t &k);
240#undef ARRAY_PROPERTIES_PAIR
241};
242}  // namespace panda::ecmascript::builtins
243
244#endif  // ECMASCRIPT_BUILTINS_BUILTINS_SHARED_ARRAY_H
245