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 V("of", Of, 1, INVALID) \ 32 // fixme(hzzhouzebin) Support later. 33 // /* SharedArray.of ( ...items ) */ \ 34 // V("of", Of, 0, INVALID) 35 36 // List of functions in SharedArray.prototype, excluding the constructor and '@@' properties. 37 // V(name, func, length, stubIndex) 38 // where BuiltinsSharedArray::func refers to the native implementation of SharedArray.prototype[name]. 39 #define BUILTIN_SHARED_ARRAY_PROTOTYPE_FUNCTIONS(V) \ 40 /* SharedArray.prototype.at ( index ) */ \ 41 V("at", At, 1, INVALID) \ 42 /* SharedArray.prototype.concat ( ...items ) */ \ 43 V("concat", Concat, 1, INVALID) \ 44 /* SharedArray.prototype.entries ( ) */ \ 45 V("entries", Entries, 0, INVALID) \ 46 /* SharedArray.prototype.fill ( value [ , start [ , end ] ] ) */ \ 47 V("fill", Fill, 1, INVALID) \ 48 /* SharedArray.prototype.filter ( callbackfn [ , thisArg ] ) */ \ 49 V("filter", Filter, 1, INVALID) \ 50 /* SharedArray.prototype.find ( predicate [ , thisArg ] ) */ \ 51 V("find", Find, 1, INVALID) \ 52 /* SharedArray.prototype.findIndex ( predicate [ , thisArg ] ) */ \ 53 V("findIndex", FindIndex, 1, INVALID) \ 54 /* SharedArray.prototype.forEach ( callbackfn [ , thisArg ] ) */ \ 55 V("forEach", ForEach, 1, INVALID) \ 56 /* SharedArray.prototype.includes ( searchElement [ , fromIndex ] ) */ \ 57 V("includes", Includes, 1, INVALID) \ 58 /* SharedArray.prototype.indexOf ( searchElement [ , fromIndex ] ) */ \ 59 V("indexOf", IndexOf, 1, INVALID) \ 60 /* SharedArray.prototype.join ( separator ) */ \ 61 V("join", Join, 1, INVALID) \ 62 /* SharedArray.prototype.keys ( ) */ \ 63 V("keys", Keys, 0, INVALID) \ 64 /* SharedArray.prototype.map ( callbackfn [ , thisArg ] ) */ \ 65 V("map", Map, 1, INVALID) \ 66 /* SharedArray.prototype.pop ( ) */ \ 67 V("pop", Pop, 0, INVALID) \ 68 /* SharedArray.prototype.push ( ...items ) */ \ 69 V("push", Push, 1, INVALID) \ 70 /* SharedArray.prototype.reduce ( callbackfn [ , initialValue ] ) */ \ 71 V("reduce", Reduce, 1, INVALID) \ 72 /* SharedArray.prototype.shift ( ) */ \ 73 V("shift", Shift, 0, INVALID) \ 74 /* SharedArray.prototype.slice ( start, end ) */ \ 75 V("slice", Slice, 2, INVALID) \ 76 /* SharedArray.prototype.sort ( comparefn ) */ \ 77 V("sort", Sort, 1, INVALID) \ 78 /* SharedArray.prototype.toString ( ) */ \ 79 V("toString", ToString, 0, INVALID) \ 80 /* SharedArray.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ) */ \ 81 V("toLocaleString", ToLocaleString, 0, INVALID) \ 82 /* SharedArray.prototype.values ( ) */ \ 83 /* SharedArray.prototype.unshift ( ...items ) */ \ 84 V("unshift", Unshift, 1, INVALID) \ 85 V("values", Values, 0, INVALID) \ 86 V("shrinkTo", ShrinkTo, 0, INVALID) \ 87 V("extendTo", ExtendTo, 0, INVALID) \ 88 /* SharedArray.prototype.splice ( start, deleteCount, ...items ) */ \ 89 V("splice", Splice, 2, INVALID) \ 90 /* SharedArray.prototype.every ( callbackfn [ , thisArg ] ) */ \ 91 V("every", Every, 1, INVALID) \ 92 /* SharedArray.prototype.some ( callbackfn [ , thisArg ] ) */ \ 93 V("some", Some, 1, INVALID) \ 94 /* SendableArray.prototype.lastIndexOf ( searchElement [ , fromIndex ] ) */ \ 95 V("lastIndexOf", LastIndexOf, 1, INVALID) \ 96 /* SharedArray.prototype.copyWithin ( target, start [ , end ] ) */ \ 97 V("copyWithin", CopyWithin, 2, INVALID) \ 98 /* SharedArray.prototype.reduceRight ( callbackfn [ , initialValue ] ) */ \ 99 V("reduceRight", ReduceRight, 1, INVALID) \ 100 /* SharedArray.prototype.reverse ( ) */ \ 101 V("reverse", Reverse, 0, 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 // fixme(hzzhouzebin) Support later. 107 // /* SharedArray.prototype.with ( index, value ) */ \ 108 // V("with", With, 2, INVALID) \ 109 // /* SharedArray.prototype.toReversed ( ) */ \ 110 // V("toReversed", ToReversed, 0, INVALID) \ 111 // /* SharedArray.prototype.toSorted ( comparefn ) */ \ 112 // V("toSorted", ToSorted, 1, INVALID) \ 113 // /* SharedArray.prototype.toSpliced ( start, skipCount, ...items ) */ \ 114 // V("toSpliced", ToSpliced, 2, INVALID) 115 116 namespace panda::ecmascript::builtins { 117 class BuiltinsSharedArray : public base::BuiltinsBase { 118 public: 119 static JSTaggedValue ArrayConstructor(EcmaRuntimeCallInfo *argv); 120 static JSTaggedValue From(EcmaRuntimeCallInfo *argv); 121 static JSTaggedValue Create(EcmaRuntimeCallInfo *argv); 122 static JSTaggedValue IsArray(EcmaRuntimeCallInfo *argv); 123 static JSTaggedValue Species(EcmaRuntimeCallInfo *argv); 124 125 // prototype 126 static JSTaggedValue Concat(EcmaRuntimeCallInfo *argv); 127 static JSTaggedValue Entries(EcmaRuntimeCallInfo *argv); 128 static JSTaggedValue Fill(EcmaRuntimeCallInfo *argv); 129 static JSTaggedValue Filter(EcmaRuntimeCallInfo *argv); 130 static JSTaggedValue Find(EcmaRuntimeCallInfo *argv); 131 static JSTaggedValue FindIndex(EcmaRuntimeCallInfo *argv); 132 static JSTaggedValue ForEach(EcmaRuntimeCallInfo *argv); 133 static JSTaggedValue IndexOf(EcmaRuntimeCallInfo *argv); 134 static JSTaggedValue Join(EcmaRuntimeCallInfo *argv); 135 static JSTaggedValue Keys(EcmaRuntimeCallInfo *argv); 136 static JSTaggedValue Map(EcmaRuntimeCallInfo *argv); 137 static JSTaggedValue Pop(EcmaRuntimeCallInfo *argv); 138 static JSTaggedValue Push(EcmaRuntimeCallInfo *argv); 139 static JSTaggedValue Reduce(EcmaRuntimeCallInfo *argv); 140 static JSTaggedValue Shift(EcmaRuntimeCallInfo *argv); 141 static JSTaggedValue Slice(EcmaRuntimeCallInfo *argv); 142 static JSTaggedValue Splice(EcmaRuntimeCallInfo *argv); 143 static JSTaggedValue Sort(EcmaRuntimeCallInfo *argv); 144 static JSTaggedValue ToString(EcmaRuntimeCallInfo *argv); 145 static JSTaggedValue ToLocaleString(EcmaRuntimeCallInfo *argv); 146 static JSTaggedValue Unshift(EcmaRuntimeCallInfo *argv); 147 static JSTaggedValue Values(EcmaRuntimeCallInfo *argv); 148 static JSTaggedValue Unscopables(EcmaRuntimeCallInfo *argv); 149 static JSTaggedValue Includes(EcmaRuntimeCallInfo *argv); 150 static JSTaggedValue At(EcmaRuntimeCallInfo *argv); 151 static JSTaggedValue ShrinkTo(EcmaRuntimeCallInfo *argv); 152 static JSTaggedValue ExtendTo(EcmaRuntimeCallInfo *argv); 153 static JSTaggedValue Every(EcmaRuntimeCallInfo *argv); 154 static JSTaggedValue Some(EcmaRuntimeCallInfo *argv); 155 static JSTaggedValue LastIndexOf(EcmaRuntimeCallInfo *argv); 156 static JSTaggedValue Of(EcmaRuntimeCallInfo *argv); 157 static JSTaggedValue CopyWithin(EcmaRuntimeCallInfo *argv); 158 static JSTaggedValue FindLast(EcmaRuntimeCallInfo *argv); 159 static JSTaggedValue FindLastIndex(EcmaRuntimeCallInfo *argv); 160 static JSTaggedValue Reverse(EcmaRuntimeCallInfo *argv); 161 static JSTaggedValue ReduceRight(EcmaRuntimeCallInfo *argv); 162 163 // Excluding the '@@' internal properties GetSharedArrayFunctions()164 static Span<const base::BuiltinFunctionEntry> GetSharedArrayFunctions() 165 { 166 return Span<const base::BuiltinFunctionEntry>(SENDABLE_ARRAY_FUNCTIONS); 167 } 168 169 // Excluding the constructor and '@@' internal properties. GetSharedArrayPrototypeFunctions()170 static Span<const base::BuiltinFunctionEntry> GetSharedArrayPrototypeFunctions() 171 { 172 return Span<const base::BuiltinFunctionEntry>(SENDABLE_ARRAY_PROTOTYPE_FUNCTIONS); 173 } 174 GetNumPrototypeInlinedProperties()175 static size_t GetNumPrototypeInlinedProperties() 176 { 177 // 4 : 4 More inlined entries in SharedArray.prototype for the following functions/accessors: 178 // (1) 'length' accessor 179 // (2) SharedArray.prototype.constructor, i.e. Array() 180 // (3) SharedArray.prototype[@@iterator]() 181 // (4) SharedArray.prototype[@@unscopables]() 182 return GetSharedArrayPrototypeFunctions().Size() + 4; 183 } 184 static JSTaggedValue ReduceUnStableJSArray(JSThread *thread, JSHandle<JSTaggedValue> &thisHandle, 185 JSHandle<JSObject> &thisObjHandle, int64_t k, int64_t len, JSMutableHandle<JSTaggedValue> &accumulator, 186 JSHandle<JSTaggedValue> &callbackFnHandle); 187 188 static JSTaggedValue FilterArray(JSThread *thread, JSHandle<JSTaggedValue> &thisArgHandle, 189 JSHandle<JSTaggedValue> &thisObjVal, JSHandle<JSObject>& newArrayHandle, 190 JSHandle<JSTaggedValue> &callbackFnHandle); 191 GetPrototypeProperties()192 static Span<const std::pair<std::string_view, bool>> GetPrototypeProperties() 193 { 194 return Span<const std::pair<std::string_view, bool>>(ARRAY_PROTOTYPE_PROPERTIES); 195 } GetFunctionProperties()196 static Span<const std::pair<std::string_view, bool>> GetFunctionProperties() 197 { 198 return Span<const std::pair<std::string_view, bool>>(ARRAY_FUNCTION_PROPERTIES); 199 } 200 201 static inline int64_t ConvertTagValueToInteger(JSThread *thread, JSHandle<JSTaggedValue>& number, int64_t len); 202 static inline int64_t GetNumberArgVal(JSThread *thread, EcmaRuntimeCallInfo *argv, uint32_t idx, int64_t len, 203 int64_t defVal); 204 static inline int64_t GetNumberArgValThrow(JSThread *thread, EcmaRuntimeCallInfo *argv, uint32_t idx, 205 int64_t len, const char* err); 206 207 static inline void SetElementValue(JSThread *thread, JSHandle<JSObject> arrHandle, uint32_t key, 208 const JSHandle<JSTaggedValue> &value); 209 static inline JSTaggedValue FastReverse(JSThread *thread, JSHandle<TaggedArray>& elements, 210 uint32_t lower, uint32_t len, ElementsKind kind); 211 212 private: 213 static inline JSTaggedValue GetElementByKey(JSThread *thread, JSHandle<JSObject>& thisObjHandle, uint32_t index); 214 static inline JSTaggedValue PopInner(EcmaRuntimeCallInfo *argv, JSHandle<JSTaggedValue> &thisHandle, 215 JSHandle<JSObject> &thisObjHandle); 216 static inline int64_t FillNewTaggedArray(JSThread *thread, EcmaRuntimeCallInfo *argv, int argc, 217 int64_t newArrayIdx, JSHandle<TaggedArray> &eleArray); 218 static inline int64_t CalNewArrayLen(JSThread *thread, EcmaRuntimeCallInfo *argv, int argc); 219 static inline JSTaggedValue IndexOfStable(EcmaRuntimeCallInfo *argv, JSThread *thread, 220 const JSHandle<JSTaggedValue> &thisHandle); 221 static inline JSTaggedValue FromSharedArray(JSThread *thread, const JSHandle<JSTaggedValue>& items, 222 JSHandle<JSObject>& newArrayHandle); 223 static inline JSTaggedValue FromArrayNoMaping(JSThread *thread, const JSHandle<JSTaggedValue>& items, 224 JSHandle<JSObject>& newArrayHandle); 225 template<bool itemIsSharedArray> 226 static inline JSTaggedValue FromArray(JSThread *thread, const JSHandle<JSTaggedValue>& items, 227 const JSHandle<JSTaggedValue>& thisArgHandle, 228 const JSHandle<JSTaggedValue> mapfn, 229 JSHandle<JSObject>& newArrayHandle); 230 231 #define BUILTIN_SENDABLE_ARRAY_FUNCTION_ENTRY(name, method, length, id) \ 232 base::BuiltinFunctionEntry::Create(name, BuiltinsSharedArray::method, length, kungfu::BuiltinsStubCSigns::id), 233 234 static constexpr std::array SENDABLE_ARRAY_FUNCTIONS = { 235 BUILTIN_SHARED_ARRAY_FUNCTIONS(BUILTIN_SENDABLE_ARRAY_FUNCTION_ENTRY) 236 }; 237 static constexpr std::array SENDABLE_ARRAY_PROTOTYPE_FUNCTIONS = { 238 BUILTIN_SHARED_ARRAY_PROTOTYPE_FUNCTIONS(BUILTIN_SENDABLE_ARRAY_FUNCTION_ENTRY) 239 }; 240 #undef BUILTIN_SENDABLE_ARRAY_FUNCTION_ENTRY 241 242 static JSTaggedValue IndexOfSlowPath( 243 EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle); 244 245 static JSTaggedValue IndexOfSlowPath( 246 EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisObjVal, 247 int64_t length, int64_t fromIndex); 248 249 static JSTaggedValue LastIndexOfSlowPath(EcmaRuntimeCallInfo *argv, JSThread *thread, 250 const JSHandle<JSTaggedValue> &thisHandle); 251 static JSTaggedValue LastIndexOfSlowPath(EcmaRuntimeCallInfo *argv, JSThread *thread, 252 const JSHandle<JSTaggedValue> &thisObjVal, int64_t fromIndex); 253 static JSTaggedValue ToLocaleStringInternalHandle(EcmaRuntimeCallInfo *argv, JSThread *thread, 254 EcmaContext *context, ObjectFactory *factory, const JSHandle<JSTaggedValue> &thisHandle, int64_t len); 255 static JSTaggedValue ReduceRightInternalHandle(EcmaRuntimeCallInfo *argv, JSThread *thread, 256 const JSHandle<JSTaggedValue> &thisHandle, JSHandle<JSObject>& thisObjHandle, uint32_t argc, int64_t len); 257 258 #define ARRAY_PROPERTIES_PAIR(name, func, length, id) \ 259 std::pair<std::string_view, bool>(name, false), 260 261 static constexpr std::array ARRAY_PROTOTYPE_PROPERTIES = { 262 std::pair<std::string_view, bool>("length", false), 263 std::pair<std::string_view, bool>("constructor", false), 264 BUILTIN_SHARED_ARRAY_PROTOTYPE_FUNCTIONS(ARRAY_PROPERTIES_PAIR) 265 std::pair<std::string_view, bool>("[Symbol.iterator]", false), 266 std::pair<std::string_view, bool>("[Symbol.unscopables]", false) 267 }; 268 static constexpr std::array ARRAY_FUNCTION_PROPERTIES = { 269 std::pair<std::string_view, bool>("length", false), 270 std::pair<std::string_view, bool>("name", false), 271 std::pair<std::string_view, bool>("prototype", false), 272 BUILTIN_SHARED_ARRAY_FUNCTIONS(ARRAY_PROPERTIES_PAIR) 273 std::pair<std::string_view, bool>("[Symbol.species]", true), 274 }; 275 static JSTaggedValue CheckElementMeetReq(JSThread *thread, 276 JSHandle<JSTaggedValue> &thisObjVal, 277 JSHandle<JSTaggedValue> &callbackFnHandle, bool isSome); 278 #undef ARRAY_PROPERTIES_PAIR 279 280 #define ARRAY_CHECK_SHARED_ARRAY(errMsg) \ 281 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); \ 282 if (UNLIKELY(!thisHandle->IsJSSharedArray())) { \ 283 auto error = ContainerError::BindError(thread, errMsg); \ 284 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); \ 285 } 286 }; 287 } // namespace panda::ecmascript::builtins 288 289 #endif // ECMASCRIPT_BUILTINS_BUILTINS_SHARED_ARRAY_H 290