• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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_ARRAY_H
17 #define ECMASCRIPT_BUILTINS_BUILTINS_ARRAY_H
18 
19 #include "ecmascript/base/builtins_base.h"
20 
21 // List of functions in Array, excluding the '@@' properties.
22 // V(name, func, length, stubIndex)
23 // where BuiltinsArray::func refers to the native implementation of Array[name].
24 //       kungfu::BuiltinsStubCSigns::stubIndex refers to the builtin stub index, or INVALID if no stub available.
25 #define BUILTIN_ARRAY_FUNCTIONS(V)                          \
26     /* Array.from ( items [ , mapfn [ , thisArg ] ] ) */    \
27     V("from",    From,    1, ArrayFrom)                     \
28     /* Array.isArray ( arg ) */                             \
29     V("isArray", IsArray, 1, INVALID)                       \
30     /* Array.of ( ...items ) */                             \
31     V("of",      Of,      0, INVALID)
32 
33 // List of functions in Array.prototype, excluding the constructor and '@@' properties.
34 // V(name, func, length, stubIndex)
35 // where BuiltinsArray::func refers to the native implementation of Array.prototype[name].
36 #define BUILTIN_ARRAY_PROTOTYPE_FUNCTIONS(V)                                \
37     /* Array.prototype.at ( index ) */                                      \
38     V("at",             At,               1, INVALID)                       \
39     /* Array.prototype.concat ( ...items ) */                               \
40     V("concat",         Concat,           1, ArrayConcat)                   \
41     /* Array.prototype.copyWithin ( target, start [ , end ] ) */            \
42     V("copyWithin",     CopyWithin,       2, INVALID)                       \
43     /* Array.prototype.entries ( ) */                                       \
44     V("entries",        Entries,          0, INVALID)                       \
45     /* Array.prototype.every ( callbackfn [ , thisArg ] ) */                \
46     V("every",          Every,            1, INVALID)                       \
47     /* Array.prototype.fill ( value [ , start [ , end ] ] ) */              \
48     V("fill",           Fill,             1, INVALID)                       \
49     /* Array.prototype.filter ( callbackfn [ , thisArg ] ) */               \
50     V("filter",         Filter,           1, INVALID)                       \
51     /* Array.prototype.find ( predicate [ , thisArg ] ) */                  \
52     V("find",           Find,             1, ArrayFind)                     \
53     /* Array.prototype.findIndex ( predicate [ , thisArg ] ) */             \
54     V("findIndex",      FindIndex,        1, ArrayFindIndex)                \
55     /* Array.prototype.findLast ( predicate [ , thisArg ] ) */              \
56     V("findLast",       FindLast,         1, INVALID)                       \
57     /* Array.prototype.findLastIndex ( predicate [ , thisArg ] ) */         \
58     V("findLastIndex",  FindLastIndex,    1, INVALID)                       \
59     /* Array.prototype.flat ( [ depth ] ) */                                \
60     V("flat",           Flat,             0, INVALID)                       \
61     /* Array.prototype.flatMap ( mapperFunction [ , thisArg ] ) */          \
62     V("flatMap",        FlatMap,          1, INVALID)                       \
63     /* Array.prototype.forEach ( callbackfn [ , thisArg ] ) */              \
64     V("forEach",        ForEach,          1, ArrayForEach)                  \
65     /* Array.prototype.includes ( searchElement [ , fromIndex ] ) */        \
66     V("includes",       Includes,         1, ArrayIncludes)                 \
67     /* Array.prototype.indexOf ( searchElement [ , fromIndex ] ) */         \
68     V("indexOf",        IndexOf,          1, ArrayIndexOf)                  \
69     /* Array.prototype.join ( separator ) */                                \
70     V("join",           Join,             1, INVALID)                       \
71     /* Array.prototype.keys ( ) */                                          \
72     V("keys",           Keys,             0, INVALID)                       \
73     /* Array.prototype.lastIndexOf ( searchElement [ , fromIndex ] ) */     \
74     V("lastIndexOf",    LastIndexOf,      1, ArrayLastIndexOf)              \
75     /* Array.prototype.map ( callbackfn [ , thisArg ] ) */                  \
76     V("map",            Map,              1, INVALID)                       \
77     /* Array.prototype.pop ( ) */                                           \
78     V("pop",            Pop,              0, ArrayPop)                      \
79     /* Array.prototype.push ( ...items ) */                                 \
80     V("push",           Push,             1, INVALID)                       \
81     /* Array.prototype.reduce ( callbackfn [ , initialValue ] ) */          \
82     V("reduce",         Reduce,           1, ArrayReduce)                   \
83     /* Array.prototype.reduceRight ( callbackfn [ , initialValue ] ) */     \
84     V("reduceRight",    ReduceRight,      1, INVALID)                       \
85     /* Array.prototype.reverse ( ) */                                       \
86     V("reverse",        Reverse,          0, ArrayReverse)                  \
87     /* Array.prototype.shift ( ) */                                         \
88     V("shift",          Shift,            0, INVALID)                       \
89     /* Array.prototype.slice ( start, end ) */                              \
90     V("slice",          Slice,            2, ArraySlice)                    \
91     /* Array.prototype.some ( callbackfn [ , thisArg ] ) */                 \
92     V("some",           Some,             1, INVALID)                       \
93     /* Array.prototype.sort ( comparefn ) */                                \
94     V("sort",           Sort,             1, SORT)                          \
95     /* Array.prototype.splice ( start, deleteCount, ...items ) */           \
96     V("splice",         Splice,           2, ArraySplice)                   \
97     /* Array.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ) */  \
98     V("toLocaleString", ToLocaleString,   0, INVALID)                       \
99     /* Array.prototype.toReversed ( ) */                                    \
100     V("toReversed",     ToReversed,       0, INVALID)                       \
101     /* Array.prototype.toSorted ( comparefn ) */                            \
102     V("toSorted",       ToSorted,         1, INVALID)                       \
103     /* Array.prototype.toSpliced ( start, skipCount, ...items ) */          \
104     V("toSpliced",      ToSpliced,        2, INVALID)                       \
105     /* Array.prototype.toString ( ) */                                      \
106     V("toString",       ToString,         0, INVALID)                       \
107     /* Array.prototype.unshift ( ...items ) */                              \
108     V("unshift",        Unshift,          1, INVALID)                       \
109     /* Array.prototype.values ( ) */                                        \
110     V("values",         Values,           0, ArrayValues)                   \
111     /* Array.prototype.with ( index, value ) */                             \
112     V("with",           With,             2, INVALID)
113 
114 namespace panda::ecmascript::builtins {
115 static constexpr uint8_t INDEX_TWO = 2;
116 static constexpr uint8_t INDEX_THREE = 3;
117 static const CString STRING_SEPERATOR = ",";
118 class BuiltinsArray : public base::BuiltinsBase {
119 public:
120     // 22.1.1
121     static JSTaggedValue ArrayConstructor(EcmaRuntimeCallInfo *argv);
122 
123     // 22.1.2.1
124     static JSTaggedValue From(EcmaRuntimeCallInfo *argv);
125     // 22.1.2.2
126     static JSTaggedValue IsArray(EcmaRuntimeCallInfo *argv);
127     // 22.1.2.3
128     static JSTaggedValue Of(EcmaRuntimeCallInfo *argv);
129     // 22.1.2.5
130     static JSTaggedValue Species(EcmaRuntimeCallInfo *argv);
131 
132     // prototype
133     // 22.1.3.1
134     static JSTaggedValue Concat(EcmaRuntimeCallInfo *argv);
135     // 22.1.3.3
136     static JSTaggedValue CopyWithin(EcmaRuntimeCallInfo *argv);
137     // 22.1.3.4
138     static JSTaggedValue Entries(EcmaRuntimeCallInfo *argv);
139     // 22.1.3.5
140     static JSTaggedValue Every(EcmaRuntimeCallInfo *argv);
141     // 22.1.3.6
142     static JSTaggedValue Fill(EcmaRuntimeCallInfo *argv);
143     // 22.1.3.7
144     static JSTaggedValue Filter(EcmaRuntimeCallInfo *argv);
145     // 22.1.3.8
146     static JSTaggedValue Find(EcmaRuntimeCallInfo *argv);
147     // 22.1.3.9
148     static JSTaggedValue FindIndex(EcmaRuntimeCallInfo *argv);
149     // 22.1.3.10
150     static JSTaggedValue ForEach(EcmaRuntimeCallInfo *argv);
151     // 22.1.3.11
152     static JSTaggedValue IndexOf(EcmaRuntimeCallInfo *argv);
153     // 22.1.3.12
154     static JSTaggedValue Join(EcmaRuntimeCallInfo *argv);
155     // 22.1.3.13
156     static JSTaggedValue Keys(EcmaRuntimeCallInfo *argv);
157     // 22.1.3.14
158     static JSTaggedValue LastIndexOf(EcmaRuntimeCallInfo *argv);
159     // 22.1.3.15
160     static JSTaggedValue Map(EcmaRuntimeCallInfo *argv);
161     // 22.1.3.16
162     static JSTaggedValue Pop(EcmaRuntimeCallInfo *argv);
163     // 22.1.3.17
164     static JSTaggedValue Push(EcmaRuntimeCallInfo *argv);
165     // 22.1.3.18
166     static JSTaggedValue Reduce(EcmaRuntimeCallInfo *argv);
167     // 22.1.3.19
168     static JSTaggedValue ReduceRight(EcmaRuntimeCallInfo *argv);
169     // 22.1.3.20
170     static JSTaggedValue Reverse(EcmaRuntimeCallInfo *argv);
171     // 22.1.3.21
172     static JSTaggedValue Shift(EcmaRuntimeCallInfo *argv);
173     // 22.1.3.22
174     static JSTaggedValue Slice(EcmaRuntimeCallInfo *argv);
175     // 22.1.3.23
176     static JSTaggedValue Some(EcmaRuntimeCallInfo *argv);
177     // 22.1.3.24
178     static JSTaggedValue Sort(EcmaRuntimeCallInfo *argv);
179     // 22.1.3.25
180     static JSTaggedValue Splice(EcmaRuntimeCallInfo *argv);
181     // 22.1.3.26
182     static JSTaggedValue ToLocaleString(EcmaRuntimeCallInfo *argv);
183     // 22.1.3.27
184     static JSTaggedValue ToString(EcmaRuntimeCallInfo *argv); // no change
185     // 22.1.3.28
186     static JSTaggedValue Unshift(EcmaRuntimeCallInfo *argv); // done
187     // 22.1.3.29
188     static JSTaggedValue Values(EcmaRuntimeCallInfo *argv); // no change
189     // 22.1.3.31
190     static JSTaggedValue Unscopables(EcmaRuntimeCallInfo *argv); // no change
191     // es12 23.1.3.13
192     static JSTaggedValue Includes(EcmaRuntimeCallInfo *argv); // no change
193     // es12 23.1.3.10
194     static JSTaggedValue Flat(EcmaRuntimeCallInfo *argv);
195     // es12 23.1.3.11
196     static JSTaggedValue FlatMap(EcmaRuntimeCallInfo *argv);
197     // 23.1.3.1 Array.prototype.at ( index )
198     static JSTaggedValue At(EcmaRuntimeCallInfo *argv); // no change
199     // 23.1.3.33 Array.prototype.toReversed ( )
200     static JSTaggedValue ToReversed(EcmaRuntimeCallInfo *argv); // no change
201     // 23.1.3.39 Array.prototype.with ( index, value )
202     static JSTaggedValue With(EcmaRuntimeCallInfo *argv); // done
203     // 23.1.3.34 Array.prototype.toSorted ( comparefn )
204     static JSTaggedValue ToSorted(EcmaRuntimeCallInfo *argv);
205     // 23.1.3.11
206     static JSTaggedValue FindLast(EcmaRuntimeCallInfo *argv); // no change
207     // 23.1.3.12
208     static JSTaggedValue FindLastIndex(EcmaRuntimeCallInfo *argv); // no change
209     // 23.1.3.35 Array.prototype.toSpliced ( start, skipCount, ...items )
210     static JSTaggedValue ToSpliced(EcmaRuntimeCallInfo *argv);
211 
212     // Excluding the '@@' internal properties
GetArrayFunctions()213     static Span<const base::BuiltinFunctionEntry> GetArrayFunctions()
214     {
215         return Span<const base::BuiltinFunctionEntry>(ARRAY_FUNCTIONS);
216     }
217 
218     // Excluding the constructor and '@@' internal properties.
GetArrayPrototypeFunctions()219     static Span<const base::BuiltinFunctionEntry> GetArrayPrototypeFunctions()
220     {
221         return Span<const base::BuiltinFunctionEntry>(ARRAY_PROTOTYPE_FUNCTIONS);
222     }
223 
GetNumPrototypeInlinedProperties()224     static size_t GetNumPrototypeInlinedProperties()
225     {
226         // 4 : 4 More inlined entries in Array.prototype for the following functions/accessors:
227         //   (1) 'length' accessor
228         //   (2) Array.prototype.constructor, i.e. Array()
229         //   (3) Array.prototype[@@iterator]()
230         //   (4) Array.prototype[@@unscopables]()
231         return GetArrayPrototypeFunctions().Size() + 4;
232     }
233     static JSTaggedValue ReduceUnStableJSArray(JSThread *thread, JSHandle<JSTaggedValue> &thisHandle,
234         JSHandle<JSTaggedValue> &thisObjVal, int64_t k, int64_t len, JSMutableHandle<JSTaggedValue> &accumulator,
235         JSHandle<JSTaggedValue> &callbackFnHandle);
236 
237     static JSTaggedValue FilterUnStableJSArray(JSThread *thread, JSHandle<JSTaggedValue> &thisArgHandle,
238         JSHandle<JSTaggedValue> &thisObjVal, int64_t k, int64_t len, uint32_t toIndex,
239         JSHandle<JSObject> newArrayHandle, JSHandle<JSTaggedValue> &callbackFnHandle);
240 
241 private:
242 #define BUILTIN_ARRAY_FUNCTION_ENTRY(name, method, length, id) \
243     base::BuiltinFunctionEntry::Create(name, BuiltinsArray::method, length, kungfu::BuiltinsStubCSigns::id),
244 
245     static constexpr std::array ARRAY_FUNCTIONS  = {
246         BUILTIN_ARRAY_FUNCTIONS(BUILTIN_ARRAY_FUNCTION_ENTRY)
247     };
248     static constexpr std::array ARRAY_PROTOTYPE_FUNCTIONS = {
249         BUILTIN_ARRAY_PROTOTYPE_FUNCTIONS(BUILTIN_ARRAY_FUNCTION_ENTRY)
250     };
251 #undef BUILTIN_ARRAY_FUNCTION_ENTRY
252 
253     static JSTaggedValue IndexOfStable(
254         EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle);
255     static JSTaggedValue IndexOfSlowPath(
256         EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle);
257     static JSTaggedValue IndexOfSlowPath(
258         EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisObjVal,
259         int64_t length, int64_t fromIndex);
260 
261     static JSTaggedValue LastIndexOfStable(
262         EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle);
263     static JSTaggedValue LastIndexOfSlowPath(
264         EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle);
265     static JSTaggedValue LastIndexOfSlowPath(
266         EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisObjVal, int64_t fromIndex);
267 };
268 }  // namespace panda::ecmascript::builtins
269 
270 #endif  // ECMASCRIPT_BUILTINS_BUILTINS_ARRAY_H
271