/src/moddable/xs/sources/xsArray.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2016-2026 Moddable Tech, Inc. |
3 | | * |
4 | | * This file is part of the Moddable SDK Runtime. |
5 | | * |
6 | | * The Moddable SDK Runtime is free software: you can redistribute it and/or modify |
7 | | * it under the terms of the GNU Lesser General Public License as published by |
8 | | * the Free Software Foundation, either version 3 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * The Moddable SDK Runtime is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public License |
17 | | * along with the Moddable SDK Runtime. If not, see <http://www.gnu.org/licenses/>. |
18 | | * |
19 | | * This file incorporates work covered by the following copyright and |
20 | | * permission notice: |
21 | | * |
22 | | * Copyright (C) 2010-2016 Marvell International Ltd. |
23 | | * Copyright (C) 2002-2010 Kinoma, Inc. |
24 | | * |
25 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
26 | | * you may not use this file except in compliance with the License. |
27 | | * You may obtain a copy of the License at |
28 | | * |
29 | | * http://www.apache.org/licenses/LICENSE-2.0 |
30 | | * |
31 | | * Unless required by applicable law or agreed to in writing, software |
32 | | * distributed under the License is distributed on an "AS IS" BASIS, |
33 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
34 | | * See the License for the specific language governing permissions and |
35 | | * limitations under the License. |
36 | | */ |
37 | | |
38 | | #include "xsAll.h" |
39 | | |
40 | 929k | #define mxArraySize(ARRAY) (((ARRAY)->value.array.address) ? (((txChunk*)(((txByte*)((ARRAY)->value.array.address)) - sizeof(txChunk)))->size) / sizeof(txSlot) : 0) |
41 | | |
42 | | static txIndex fxCheckArrayLength(txMachine* the, txSlot* slot); |
43 | | static txBoolean fxCallThisItem(txMachine* the, txSlot* function, txIndex index, txSlot* item); |
44 | | static txSlot* fxCheckArray(txMachine* the, txSlot* slot, txBoolean mutable); |
45 | | static txSlot* fxCheckArrayItems(txMachine* the, txSlot* array, txIndex from, txIndex to); |
46 | | static int fxCompareArrayItem(txMachine* the, txSlot* function, txSlot* array, txInteger i); |
47 | | static txSlot* fxCreateArray(txMachine* the, txFlag flag, txIndex length); |
48 | | static txSlot* fxCreateArraySpecies(txMachine* the, txNumber length); |
49 | | static void fxFindThisItem(txMachine* the, txSlot* function, txNumber index, txSlot* item); |
50 | | static txNumber fxGetArrayLength(txMachine* the, txSlot* reference); |
51 | | static txIndex fxGetArrayLimit(txMachine* the, txSlot* reference); |
52 | | static void fxMoveThisItem(txMachine* the, txNumber from, txNumber to); |
53 | | static void fxReduceThisItem(txMachine* the, txSlot* function, txIndex index); |
54 | | static txBoolean fxSetArrayLength(txMachine* the, txSlot* array, txIndex target); |
55 | | static void fx_Array_from_aux(txMachine* the, txSlot* function, txSlot* value, txIndex index); |
56 | | static void fx_Array_fromAsync_items_next(txMachine* the); |
57 | | static void fx_Array_fromAsync_aux(txMachine* the, txSlot* closure); |
58 | | static void fx_Array_fromAsync_onIterated(txMachine* the); |
59 | | static void fx_Array_fromAsync_onMapped(txMachine* the); |
60 | | static void fx_Array_fromAsync_onRejected(txMachine* the); |
61 | | static txIndex fx_Array_prototype_flatAux(txMachine* the, txSlot* source, txIndex length, txIndex start, txIndex depth, txSlot* function); |
62 | | |
63 | | static txBoolean fxArrayDefineOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot, txFlag mask); |
64 | | static txBoolean fxArrayDeleteProperty(txMachine* the, txSlot* instance, txID id, txIndex index); |
65 | | static txBoolean fxArrayGetOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot); |
66 | | static txSlot* fxArrayGetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag); |
67 | | static txBoolean fxArrayHasProperty(txMachine* the, txSlot* instance, txID id, txIndex index); |
68 | | static void fxArrayOwnKeys(txMachine* the, txSlot* instance, txFlag flag, txSlot* keys); |
69 | | static txSlot* fxArraySetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag); |
70 | | |
71 | | const txBehavior ICACHE_FLASH_ATTR gxArrayBehavior = { |
72 | | fxArrayGetProperty, |
73 | | fxArraySetProperty, |
74 | | fxOrdinaryCall, |
75 | | fxOrdinaryConstruct, |
76 | | fxArrayDefineOwnProperty, |
77 | | fxArrayDeleteProperty, |
78 | | fxArrayGetOwnProperty, |
79 | | fxOrdinaryGetPropertyValue, |
80 | | fxOrdinaryGetPrototype, |
81 | | fxArrayHasProperty, |
82 | | fxOrdinaryIsExtensible, |
83 | | fxArrayOwnKeys, |
84 | | fxOrdinaryPreventExtensions, |
85 | | fxOrdinarySetPropertyValue, |
86 | | fxOrdinarySetPrototype, |
87 | | }; |
88 | | |
89 | | void fxBuildArray(txMachine* the) |
90 | 26.0k | { |
91 | 26.0k | txSlot* instance; |
92 | 26.0k | txSlot* slot; |
93 | 26.0k | txSlot* property; |
94 | 26.0k | txSlot* unscopable; |
95 | | |
96 | 26.0k | mxPush(mxObjectPrototype); |
97 | 26.0k | instance = fxNewArrayInstance(the); |
98 | | |
99 | 26.0k | fxNewHostFunction(the, mxCallback(fxArrayLengthGetter), 0, mxID(_length), XS_NO_ID); |
100 | 26.0k | property = mxFunctionInstanceHome(the->stack->value.reference); |
101 | 26.0k | property->value.home.object = instance; |
102 | 26.0k | fxNewHostFunction(the, mxCallback(fxArrayLengthSetter), 1, mxID(_length), XS_NO_ID); |
103 | 26.0k | property = mxFunctionInstanceHome(the->stack->value.reference); |
104 | 26.0k | property->value.home.object = instance; |
105 | 26.0k | mxPushUndefined(); |
106 | 26.0k | the->stack->flag = XS_DONT_DELETE_FLAG; |
107 | 26.0k | the->stack->kind = XS_ACCESSOR_KIND; |
108 | 26.0k | the->stack->value.accessor.getter = (the->stack + 2)->value.reference; |
109 | 26.0k | the->stack->value.accessor.setter = (the->stack + 1)->value.reference; |
110 | 26.0k | mxPull(mxArrayLengthAccessor); |
111 | 26.0k | mxPop(); |
112 | 26.0k | mxPop(); |
113 | | |
114 | 26.0k | slot = fxLastProperty(the, instance); |
115 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_at), 1, mxID(_at), XS_DONT_ENUM_FLAG); |
116 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_concat), 1, mxID(_concat), XS_DONT_ENUM_FLAG); |
117 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_copyWithin), 2, mxID(_copyWithin), XS_DONT_ENUM_FLAG); |
118 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_entries), 0, mxID(_entries), XS_DONT_ENUM_FLAG); |
119 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_every), 1, mxID(_every), XS_DONT_ENUM_FLAG); |
120 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_fill), 1, mxID(_fill), XS_DONT_ENUM_FLAG); |
121 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_filter), 1, mxID(_filter), XS_DONT_ENUM_FLAG); |
122 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_find), 1, mxID(_find), XS_DONT_ENUM_FLAG); |
123 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_findIndex), 1, mxID(_findIndex), XS_DONT_ENUM_FLAG); |
124 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_findLast), 1, mxID(_findLast), XS_DONT_ENUM_FLAG); |
125 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_findLastIndex), 1, mxID(_findLastIndex), XS_DONT_ENUM_FLAG); |
126 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_flat), 0, mxID(_flat), XS_DONT_ENUM_FLAG); |
127 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_flatMap), 1, mxID(_flatMap), XS_DONT_ENUM_FLAG); |
128 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_forEach), 1, mxID(_forEach), XS_DONT_ENUM_FLAG); |
129 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_includes), 1, mxID(_includes), XS_DONT_ENUM_FLAG); |
130 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_indexOf), 1, mxID(_indexOf), XS_DONT_ENUM_FLAG); |
131 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_join), 1, mxID(_join), XS_DONT_ENUM_FLAG); |
132 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_keys), 0, mxID(_keys), XS_DONT_ENUM_FLAG); |
133 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_lastIndexOf), 1, mxID(_lastIndexOf), XS_DONT_ENUM_FLAG); |
134 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_map), 1, mxID(_map), XS_DONT_ENUM_FLAG); |
135 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_pop), 0, mxID(_pop), XS_DONT_ENUM_FLAG); |
136 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_push), 1, mxID(_push), XS_DONT_ENUM_FLAG); |
137 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_reduce), 1, mxID(_reduce), XS_DONT_ENUM_FLAG); |
138 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_reduceRight), 1, mxID(_reduceRight), XS_DONT_ENUM_FLAG); |
139 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_reverse), 0, mxID(_reverse), XS_DONT_ENUM_FLAG); |
140 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_shift), 0, mxID(_shift), XS_DONT_ENUM_FLAG); |
141 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_slice), 2, mxID(_slice), XS_DONT_ENUM_FLAG); |
142 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_some), 1, mxID(_some), XS_DONT_ENUM_FLAG); |
143 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_sort), 1, mxID(_sort), XS_DONT_ENUM_FLAG); |
144 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_splice), 2, mxID(_splice), XS_DONT_ENUM_FLAG); |
145 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toLocaleString), 0, mxID(_toLocaleString), XS_DONT_ENUM_FLAG); |
146 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG); |
147 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_unshift), 1, mxID(_unshift), XS_DONT_ENUM_FLAG); |
148 | 26.0k | property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_values), 0, mxID(_values), XS_DONT_ENUM_FLAG); |
149 | 26.0k | mxPushSlot(property); |
150 | 26.0k | mxPull(mxArrayIteratorFunction); |
151 | 26.0k | slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_iterator), XS_DONT_ENUM_FLAG); |
152 | 26.0k | unscopable = fxLastProperty(the, fxNewInstance(the)); |
153 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_copyWithin), XS_NO_FLAG); |
154 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_at), XS_NO_FLAG); |
155 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_entries), XS_NO_FLAG); |
156 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_fill), XS_NO_FLAG); |
157 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_find), XS_NO_FLAG); |
158 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_findIndex), XS_NO_FLAG); |
159 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_findLast), XS_NO_FLAG); |
160 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_findLastIndex), XS_NO_FLAG); |
161 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_flat), XS_NO_FLAG); |
162 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_flatMap), XS_NO_FLAG); |
163 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_includes), XS_NO_FLAG); |
164 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_keys), XS_NO_FLAG); |
165 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_values), XS_NO_FLAG); |
166 | 26.0k | #if mxECMAScript2023 |
167 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_toReversed), XS_NO_FLAG); |
168 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_toSorted), XS_NO_FLAG); |
169 | 26.0k | unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_toSpliced), XS_NO_FLAG); |
170 | 26.0k | #endif |
171 | 26.0k | slot = fxNextSlotProperty(the, slot, the->stack++, mxID(_Symbol_unscopables), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG); |
172 | 26.0k | #if mxECMAScript2023 |
173 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toReversed), 0, mxID(_toReversed), XS_DONT_ENUM_FLAG); |
174 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toSorted), 1, mxID(_toSorted), XS_DONT_ENUM_FLAG); |
175 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toSpliced), 2, mxID(_toSpliced), XS_DONT_ENUM_FLAG); |
176 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_with), 2, mxID(_with), XS_DONT_ENUM_FLAG); |
177 | 26.0k | #endif |
178 | 26.0k | mxArrayPrototype = *the->stack; |
179 | 26.0k | slot = fxBuildHostConstructor(the, mxCallback(fx_Array), 1, mxID(_Array)); |
180 | 26.0k | mxArrayConstructor = *the->stack; |
181 | 26.0k | slot = fxLastProperty(the, slot); |
182 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_from), 1, mxID(_from), XS_DONT_ENUM_FLAG); |
183 | 26.0k | #if mxECMAScript2026 |
184 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_fromAsync), 1, mxID(_fromAsync), XS_DONT_ENUM_FLAG); |
185 | 26.0k | #endif |
186 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_isArray), 1, mxID(_isArray), XS_DONT_ENUM_FLAG); |
187 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_of), 0, mxID(_of), XS_DONT_ENUM_FLAG); |
188 | 26.0k | slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_species_get), C_NULL, mxID(_Symbol_species), XS_DONT_ENUM_FLAG); |
189 | 26.0k | mxPop(); |
190 | | |
191 | 26.0k | mxPush(mxIteratorPrototype); |
192 | 26.0k | slot = fxLastProperty(the, fxNewObjectInstance(the)); |
193 | 26.0k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_ArrayIterator_prototype_next), 0, mxID(_next), XS_DONT_ENUM_FLAG); |
194 | 26.0k | slot = fxNextStringXProperty(the, slot, "Array Iterator", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG); |
195 | 26.0k | mxPull(mxArrayIteratorPrototype); |
196 | 26.0k | } |
197 | | |
198 | | txNumber fxArgToIndex(txMachine* the, txInteger argi, txNumber index, txNumber length) |
199 | 7.39M | { |
200 | 7.39M | if ((mxArgc > argi) && (mxArgv(argi)->kind != XS_UNDEFINED_KIND)) { |
201 | 3.93M | txNumber i = c_trunc(fxToNumber(the, mxArgv(argi))); |
202 | 3.93M | if (c_isnan(i) || (i == 0)) |
203 | 1.88M | i = 0; |
204 | 3.93M | if (i < 0) { |
205 | 813k | i = length + i; |
206 | 813k | if (i < 0) |
207 | 405k | i = 0; |
208 | 813k | } |
209 | 3.12M | else if (i > length) |
210 | 1.05M | i = length; |
211 | 3.93M | index = i; |
212 | 3.93M | } |
213 | 7.39M | return index; |
214 | 7.39M | } |
215 | | |
216 | | txInteger fxArgToIndexInteger(txMachine* the, txInteger argi, txInteger index, txInteger length) |
217 | 986k | { |
218 | 986k | if (mxArgc <= argi) |
219 | 365 | return index; |
220 | | |
221 | 985k | txSlot *slot = mxArgv(argi); |
222 | 985k | if (slot->kind != XS_INTEGER_KIND) |
223 | 199k | return (txInteger)fxArgToIndex(the, argi, index, length); |
224 | | |
225 | 785k | index = slot->value.integer; |
226 | 785k | if (index < 0) { |
227 | 947 | index = length + index; |
228 | 947 | if (index < 0) |
229 | 920 | index = 0; |
230 | 947 | } |
231 | 785k | else if (index > length) |
232 | 755k | index = length; |
233 | | |
234 | 785k | return index; |
235 | 985k | } |
236 | | |
237 | | txNumber fxArgToLastIndex(txMachine* the, txInteger argi, txNumber index, txNumber length) |
238 | 221k | { |
239 | 221k | if (mxArgc > argi) { |
240 | 3.24k | txNumber i = c_trunc(fxToNumber(the, mxArgv(argi))); |
241 | 3.24k | if (c_isnan(i) || (i == 0)) |
242 | 273 | i = 0; |
243 | 3.24k | if (i < 0) { |
244 | 18 | i = length + i; |
245 | 18 | if (i < 0) |
246 | 5 | index = 0; |
247 | 13 | else |
248 | 13 | index = i + 1; |
249 | 18 | } |
250 | 3.22k | else if (i < length) |
251 | 478 | index = i + 1; |
252 | 3.24k | } |
253 | 221k | return index; |
254 | 221k | } |
255 | | |
256 | | txNumber fxArgToRange(txMachine* the, txInteger argi, txNumber index, txNumber min, txNumber max) |
257 | 573k | { |
258 | 573k | if ((mxArgc > argi) && (mxArgv(argi)->kind != XS_UNDEFINED_KIND)) { |
259 | 573k | txNumber i = c_trunc(fxToNumber(the, mxArgv(argi))); |
260 | 573k | if (c_isnan(i)) |
261 | 132k | i = min; |
262 | 573k | if (i <= min) |
263 | 133k | i = min; |
264 | 439k | else if (i > max) |
265 | 303k | i = max; |
266 | 573k | index = i; |
267 | 573k | } |
268 | 573k | return index; |
269 | 573k | } |
270 | | |
271 | | txNumber fxArgToRelativeIndex(txMachine* the, txInteger argi, txNumber index, txNumber length) |
272 | 120k | { |
273 | 120k | if ((mxArgc > argi) && (mxArgv(argi)->kind != XS_UNDEFINED_KIND)) { |
274 | 118k | txNumber i = c_trunc(fxToNumber(the, mxArgv(argi))); |
275 | 118k | if (c_isnan(i) || (i == 0)) |
276 | 55.8k | i = 0; |
277 | 118k | if (i < 0) |
278 | 59.1k | i = length + i; |
279 | 118k | index = i; |
280 | 118k | } |
281 | 120k | return index; |
282 | 120k | } |
283 | | |
284 | | void fxCacheArray(txMachine* the, txSlot* instance) |
285 | 6.44M | { |
286 | 6.44M | txSlot* array = instance->next; |
287 | 6.44M | txIndex length = array->value.array.length; |
288 | 6.44M | if (length) { |
289 | 6.22M | txSlot* address = (txSlot *)fxNewChunk(the, fxMultiplyChunkSizes(the, length, sizeof(txSlot))); |
290 | 6.22M | txSlot* srcSlot = array->next; |
291 | 6.22M | txSlot* dstSlot = address; |
292 | 6.22M | txIndex index = 0; |
293 | 66.6M | while (srcSlot) { |
294 | 60.4M | dstSlot->next = C_NULL; |
295 | 60.4M | *((txIndex*)dstSlot) = index; |
296 | 60.4M | dstSlot->ID = XS_NO_ID; |
297 | 60.4M | dstSlot->flag = XS_NO_FLAG; |
298 | 60.4M | dstSlot->kind = srcSlot->kind; |
299 | 60.4M | dstSlot->value = srcSlot->value; |
300 | 60.4M | srcSlot = srcSlot->next; |
301 | 60.4M | dstSlot++; |
302 | 60.4M | index++; |
303 | 60.4M | } |
304 | 6.22M | array->value.array.address = address; |
305 | 6.22M | array->next = C_NULL; |
306 | 6.22M | } |
307 | 6.44M | } |
308 | | |
309 | | txBoolean fxCallThisItem(txMachine* the, txSlot* function, txIndex index, txSlot* item) |
310 | 7.31M | { |
311 | 7.31M | mxPushSlot(mxThis); |
312 | 7.31M | if (mxHasIndex(index)) { |
313 | | /* THIS */ |
314 | 383k | if (mxArgc > 1) |
315 | 35 | mxPushSlot(mxArgv(1)); |
316 | 383k | else |
317 | 383k | mxPushUndefined(); |
318 | | /* FUNCTION */ |
319 | 383k | mxPushSlot(function); |
320 | 383k | mxCall(); |
321 | | /* ARGUMENTS */ |
322 | 383k | mxPushSlot(mxThis); |
323 | 383k | mxGetIndex(index); |
324 | 383k | if (item) { |
325 | 144k | item->kind = the->stack->kind; |
326 | 144k | item->value = the->stack->value; |
327 | 144k | } |
328 | 383k | mxPushUnsigned(index); |
329 | 383k | mxPushSlot(mxThis); |
330 | 383k | mxRunCount(3); |
331 | 383k | return 1; |
332 | 383k | } |
333 | 6.93M | return 0; |
334 | 7.31M | } |
335 | | |
336 | | txSlot* fxCheckArray(txMachine* the, txSlot* slot, txBoolean mutable) |
337 | 4.73M | { |
338 | 4.73M | txSlot* instance = fxToInstance(the, slot); |
339 | 4.73M | txSlot* array = instance->next; |
340 | 4.73M | if (array && (array->kind == XS_ARRAY_KIND) && (array->ID == XS_ARRAY_BEHAVIOR)) { |
341 | | #if mxAliasInstance |
342 | | if (instance->ID) { |
343 | | txSlot* alias = the->aliasArray[instance->ID]; |
344 | | if (alias) |
345 | | array = alias->next; |
346 | | else if (mutable) { |
347 | | instance = fxAliasInstance(the, instance); |
348 | | array = instance->next; |
349 | | } |
350 | | } |
351 | | #endif |
352 | 4.66M | { |
353 | 4.66M | txSlot* address = array->value.array.address; |
354 | 4.66M | txIndex size = (address) ? (((txChunk*)(((txByte*)address) - sizeof(txChunk)))->size) / sizeof(txSlot) : 0; |
355 | 4.66M | txSlot* prototype = instance->value.instance.prototype; |
356 | 4.66M | if (array->value.array.length != size) |
357 | 1.85M | return C_NULL; |
358 | 2.80M | if (mutable && ((instance->flag & XS_DONT_PATCH_FLAG) || (array->flag & XS_DONT_SET_FLAG))) |
359 | 6 | return C_NULL; |
360 | 8.41M | while (prototype) { |
361 | 5.61M | txSlot* property = prototype->next; |
362 | 8.41M | while (property) { |
363 | 8.41M | if (property->flag & XS_INTERNAL_FLAG) { |
364 | 2.80M | if ((property->kind == XS_ARRAY_KIND) && (property->value.array.address != C_NULL)) |
365 | 3.72k | return C_NULL; |
366 | 2.80M | } |
367 | 5.60M | else |
368 | 5.60M | break; |
369 | 2.80M | property = property->next; |
370 | 2.80M | } |
371 | 5.60M | prototype = prototype->value.instance.prototype; |
372 | 5.60M | } |
373 | 2.80M | return array; |
374 | 2.80M | } |
375 | 2.80M | } |
376 | 72.7k | return C_NULL; |
377 | 4.73M | } |
378 | | |
379 | | txSlot* fxCheckArrayItems(txMachine* the, txSlot* array, txIndex from, txIndex to) |
380 | 1.51M | { |
381 | 1.51M | txSlot* address = array->value.array.address; |
382 | 1.51M | txIndex length = array->value.array.length; |
383 | 1.51M | if (length < from) |
384 | 0 | return C_NULL; |
385 | 1.51M | if (length < to) |
386 | 464 | return C_NULL; |
387 | 1.51M | address += from; |
388 | 4.31M | while (from < to) { |
389 | 2.80M | if (address->flag) |
390 | 115 | return C_NULL; |
391 | 2.80M | if (address->kind == XS_ACCESSOR_KIND) |
392 | 2 | return C_NULL; |
393 | 2.80M | address++; |
394 | 2.80M | from++; |
395 | 2.80M | } |
396 | 1.51M | return array; |
397 | 1.51M | } |
398 | | |
399 | | txIndex fxCheckArrayLength(txMachine* the, txSlot* slot) |
400 | 6.50M | { |
401 | 6.50M | if (slot->kind == XS_INTEGER_KIND) { |
402 | 6.03M | if (slot->value.integer >= 0) |
403 | 6.03M | return (txIndex)slot->value.integer; |
404 | 6.03M | } |
405 | 470k | else if (slot->kind == XS_NUMBER_KIND) { |
406 | 470k | txIndex length = (txIndex)slot->value.number; |
407 | 470k | txNumber check = length; |
408 | 470k | if (slot->value.number == check) |
409 | 470k | return length; |
410 | 470k | } |
411 | 111 | else { |
412 | 111 | txUnsigned length; |
413 | 111 | txNumber check; |
414 | 111 | mxPushSlot(slot); |
415 | 111 | length = fxToUnsigned(the, the->stack); |
416 | 111 | mxPop(); |
417 | 111 | mxPushSlot(slot); |
418 | 111 | check = fxToNumber(the, the->stack); |
419 | 111 | mxPop(); |
420 | 111 | if (length == check) |
421 | 103 | return length; |
422 | 111 | } |
423 | 6.50M | mxRangeError("invalid length"); |
424 | 0 | return 0; |
425 | 6.50M | } |
426 | | |
427 | | int fxCompareArrayItem(txMachine* the, txSlot* function, txSlot* array, txInteger i) |
428 | 661k | { |
429 | 661k | txSlot* address = array->value.array.address; |
430 | 661k | txSlot* a = address + i; |
431 | 661k | txSlot* b = the->stack; |
432 | 661k | txSlot* ai = a->next; |
433 | 661k | txSlot* bi = b->next; |
434 | 661k | int result; |
435 | | |
436 | 661k | if (a->kind == XS_UNDEFINED_KIND) |
437 | 1.70k | result = (b->kind == XS_UNDEFINED_KIND) ? 0 : 1; |
438 | 660k | else if (b->kind == XS_UNDEFINED_KIND) |
439 | 138 | result = -1; |
440 | 659k | else { |
441 | 659k | if (function) { |
442 | | /* THIS */ |
443 | 469k | mxPushUndefined(); |
444 | | /* FUNCTION */ |
445 | 469k | mxPushSlot(function); |
446 | 469k | mxCall(); |
447 | | /* ARGUMENTS */ |
448 | 469k | mxPushSlot(a); |
449 | 469k | mxPushSlot(b); |
450 | 469k | mxRunCount(2); |
451 | 469k | if (the->stack->kind == XS_INTEGER_KIND) |
452 | 351k | result = the->stack->value.integer; |
453 | 117k | else { |
454 | 117k | txNumber number = fxToNumber(the, the->stack); |
455 | 117k | result = (number < 0) ? -1 : (number > 0) ? 1 : 0; |
456 | 117k | } |
457 | 469k | mxPop(); |
458 | 469k | } |
459 | 190k | else { |
460 | 190k | mxPushSlot(a); |
461 | 190k | mxPushSlot(b); |
462 | 190k | fxToString(the, the->stack + 1); |
463 | 190k | fxToString(the, the->stack); |
464 | 190k | result = fxUTF8Compare((the->stack + 1)->value.string, the->stack->value.string); |
465 | 190k | mxPop(); |
466 | 190k | mxPop(); |
467 | 190k | mxMeterSome(3); |
468 | 190k | } |
469 | 659k | } |
470 | 661k | if (result == 0) |
471 | 136k | result = (bi > ai) ? -1 : (bi < ai) ? 1 : 0; |
472 | 661k | return result; |
473 | 661k | } |
474 | | |
475 | | void fxConstructArrayEntry(txMachine* the, txSlot* entry) |
476 | 86.0k | { |
477 | 86.0k | txSlot* value = the->stack; |
478 | 86.0k | txSlot* key = the->stack + 1; |
479 | 86.0k | txSlot* instance; |
480 | 86.0k | txSlot* array; |
481 | 86.0k | txSlot* item; |
482 | 86.0k | mxPush(mxArrayPrototype); |
483 | 86.0k | instance = fxNewArrayInstance(the); |
484 | 86.0k | array = instance->next; |
485 | 86.0k | fxSetIndexSize(the, array, 2, XS_CHUNK); |
486 | 86.0k | item = array->value.array.address; |
487 | 86.0k | *((txIndex*)item) = 0; |
488 | 86.0k | item->ID = XS_NO_ID; |
489 | 86.0k | item->kind = key->kind; |
490 | 86.0k | item->value = key->value; |
491 | 86.0k | item++; |
492 | 86.0k | *((txIndex*)item) = 1; |
493 | 86.0k | item->ID = XS_NO_ID; |
494 | 86.0k | item->kind = value->kind; |
495 | 86.0k | item->value = value->value; |
496 | 86.0k | entry->kind = the->stack->kind; |
497 | 86.0k | entry->value = the->stack->value; |
498 | 86.0k | the->stack += 3; |
499 | 86.0k | } |
500 | | |
501 | | txSlot* fxCreateArray(txMachine* the, txFlag flag, txIndex length) |
502 | 478k | { |
503 | 478k | if (mxIsReference(mxThis) && mxIsConstructor(mxThis->value.reference)) |
504 | 63.2k | mxPushSlot(mxThis); |
505 | 415k | else |
506 | 415k | mxPush(mxArrayConstructor); |
507 | 478k | mxNew(); |
508 | 478k | if (flag) { |
509 | 217k | mxPushUnsigned(length); |
510 | 217k | mxRunCount(1); |
511 | 217k | } |
512 | 260k | else |
513 | 260k | mxRunCount(0); |
514 | 478k | mxPullSlot(mxResult); |
515 | 478k | return fxCheckArray(the, mxResult, XS_MUTABLE); |
516 | 478k | } |
517 | | |
518 | | txSlot* fxCreateArraySpecies(txMachine* the, txNumber length) |
519 | 446k | { |
520 | 446k | txSlot* instance = fxToInstance(the, mxThis); |
521 | 446k | txFlag flag = 1; |
522 | 446k | if (fxIsArray(the, instance)) { |
523 | 263k | mxPushSlot(mxThis); |
524 | 263k | mxGetID(mxID(_constructor)); |
525 | 263k | if (mxIsReference(the->stack)) { |
526 | 263k | mxGetID(mxID(_Symbol_species)); |
527 | 263k | if (the->stack->kind == XS_NULL_KIND) |
528 | 1 | the->stack->kind = XS_UNDEFINED_KIND; |
529 | 263k | } |
530 | 263k | } |
531 | 182k | else |
532 | 182k | mxPushUndefined(); |
533 | 446k | if (the->stack->kind == XS_UNDEFINED_KIND) { |
534 | 182k | *the->stack = mxArrayConstructor; |
535 | 182k | flag = 0; |
536 | 182k | } |
537 | 263k | else if (mxIsReference(the->stack) && mxIsConstructor(the->stack->value.reference)) { |
538 | 263k | if (the->stack->value.reference != mxArrayConstructor.value.reference) |
539 | 17 | flag = 0; |
540 | 263k | } |
541 | 40 | else |
542 | 40 | mxTypeError("invalid constructor"); |
543 | 446k | mxNew(); |
544 | 446k | mxPushNumber(length); |
545 | 446k | mxRunCount(1); |
546 | 446k | mxPullSlot(mxResult); |
547 | 446k | return (flag) ? mxResult->value.reference->next : C_NULL; |
548 | 446k | } |
549 | | |
550 | | void fxFindThisItem(txMachine* the, txSlot* function, txNumber index, txSlot* item) |
551 | 57.3k | { |
552 | | /* THIS */ |
553 | 57.3k | if (mxArgc > 1) |
554 | 2 | mxPushSlot(mxArgv(1)); |
555 | 57.3k | else |
556 | 57.3k | mxPushUndefined(); |
557 | | /* FUNCTION */ |
558 | 57.3k | mxPushSlot(function); |
559 | 57.3k | mxCall(); |
560 | | /* ARGUMENTS */ |
561 | 57.3k | mxPushSlot(mxThis); |
562 | 57.3k | mxGetIndex((txIndex)index); |
563 | 57.3k | if (item) { |
564 | 156 | item->kind = the->stack->kind; |
565 | 156 | item->value = the->stack->value; |
566 | 156 | } |
567 | 57.3k | mxPushNumber(index); |
568 | 57.3k | mxPushSlot(mxThis); |
569 | | /* ARGC */ |
570 | 57.3k | mxRunCount(3); |
571 | 57.3k | } |
572 | | |
573 | | txNumber fxGetArrayLength(txMachine* the, txSlot* reference) |
574 | 3.74M | { |
575 | 3.74M | txNumber length; |
576 | 3.74M | txSlot* instance = fxToInstance(the, reference); |
577 | 3.74M | mxPushReference(instance); |
578 | 3.74M | mxGetID(mxID(_length)); |
579 | 3.74M | length = fxToLength(the, the->stack); |
580 | 3.74M | mxPop(); |
581 | 3.74M | return length; |
582 | 3.74M | } |
583 | | |
584 | | txIndex fxGetArrayLimit(txMachine* the, txSlot* reference) |
585 | 7.35M | { |
586 | 7.35M | txNumber length; |
587 | 7.35M | txSlot* instance = fxToInstance(the, reference); |
588 | 7.35M | txSlot* array = instance->next; |
589 | 7.35M | if (array && (array->kind == XS_ARRAY_KIND) && (array->ID == XS_ARRAY_BEHAVIOR)) { |
590 | | #if mxAliasInstance |
591 | | if (instance->ID) { |
592 | | txSlot* alias = the->aliasArray[instance->ID]; |
593 | | if (alias) |
594 | | array = alias->next; |
595 | | } |
596 | | #endif |
597 | 7.19M | return array->value.array.length; |
598 | 7.19M | } |
599 | 157k | if (array && (array->kind == XS_TYPED_ARRAY_KIND) && (array->ID == XS_TYPED_ARRAY_BEHAVIOR)) { |
600 | 12.0k | txSlot* view = array->next; |
601 | 12.0k | txSlot* buffer = view->next; |
602 | 12.0k | if (mxThis->value.reference != instance) { // iterator |
603 | 12.0k | if (fxIsDataViewOutOfBound(the, view, buffer)) |
604 | 1 | mxTypeError("out of bound buffer"); |
605 | 12.0k | } |
606 | 12.0k | return fxGetDataViewSize(the, view, buffer) >> array->value.typedArray.dispatch->shift; |
607 | 12.0k | } |
608 | 145k | mxPushReference(instance); |
609 | 145k | mxGetID(mxID(_length)); |
610 | 145k | length = fxToLength(the, the->stack); |
611 | 145k | mxPop(); |
612 | 145k | if (length > 0xFFFFFFFF) { // @@ practical limit for iterations |
613 | 9 | txSlot* result = instance->next; |
614 | 9 | length = 0; |
615 | 10 | while (result && (result->flag & XS_INTERNAL_FLAG)) { |
616 | 8 | if (result->kind == XS_ARRAY_KIND) { |
617 | 7 | length = result->value.array.length; |
618 | 7 | break; |
619 | 7 | } |
620 | 1 | result = result->next; |
621 | 1 | } |
622 | 9 | } |
623 | 145k | return (txIndex)length; |
624 | 157k | } |
625 | | |
626 | | void fxIndexArray(txMachine* the, txSlot* array) |
627 | 7.72M | { |
628 | 7.72M | txSlot* address = array->value.array.address; |
629 | 7.72M | if (address) { |
630 | 1.43M | txIndex size = (((txChunk*)(((txByte*)address) - sizeof(txChunk)))->size) / sizeof(txSlot); |
631 | 1.43M | txIndex index = 0; |
632 | 13.5M | while (index < size) { |
633 | 12.0M | *((txIndex*)address) = index; |
634 | 12.0M | address->flag = XS_NO_FLAG; |
635 | 12.0M | address++; |
636 | 12.0M | index++; |
637 | 12.0M | } |
638 | 1.43M | } |
639 | 7.72M | } |
640 | | |
641 | | txBoolean fxIsArray(txMachine* the, txSlot* instance) |
642 | 1.74M | { |
643 | 1.78M | again: |
644 | 1.78M | if (instance) { |
645 | 1.78M | txSlot* internal = instance->next; |
646 | 1.78M | if (internal && (internal->flag & XS_INTERNAL_FLAG)) { |
647 | 993k | if ((internal->kind == XS_ARRAY_KIND) && (internal->ID == XS_ARRAY_BEHAVIOR)) |
648 | 323k | return 1; |
649 | 670k | if (internal->kind == XS_PROXY_KIND) { |
650 | 37.6k | instance = internal->value.proxy.target; |
651 | 37.6k | if (instance) |
652 | 37.6k | goto again; |
653 | 37.6k | mxTypeError("revoked proxy"); |
654 | | |
655 | 37.6k | } |
656 | 670k | } |
657 | 1.78M | } |
658 | 1.42M | return 0; |
659 | 1.78M | } |
660 | | |
661 | | void fxMoveThisItem(txMachine* the, txNumber from, txNumber to) |
662 | 3.89M | { |
663 | 3.89M | mxPushSlot(mxThis); |
664 | 3.89M | mxPushNumber(from); |
665 | 3.89M | if (mxHasAt()) { |
666 | 418k | mxPushSlot(mxThis); |
667 | 418k | mxPushNumber(from); |
668 | 418k | mxGetAt(); |
669 | 418k | mxPushSlot(mxThis); |
670 | 418k | mxPushNumber(to); |
671 | 418k | mxSetAt(); |
672 | 418k | mxPop(); |
673 | 418k | } |
674 | 3.48M | else { |
675 | 3.48M | mxPushSlot(mxThis); |
676 | 3.48M | mxPushNumber(to); |
677 | 3.48M | mxDeleteAt(); |
678 | 3.48M | mxPop(); |
679 | 3.48M | } |
680 | 3.89M | } |
681 | | |
682 | | txSlot* fxNewArrayInstance(txMachine* the) |
683 | 14.4M | { |
684 | 14.4M | txSlot* instance; |
685 | 14.4M | txSlot* property; |
686 | 14.4M | instance = fxNewObjectInstance(the); |
687 | 14.4M | instance->flag |= XS_EXOTIC_FLAG; |
688 | 14.4M | property = instance->next = fxNewSlot(the); |
689 | 14.4M | property->flag = XS_INTERNAL_FLAG | XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG; |
690 | 14.4M | property->ID = XS_ARRAY_BEHAVIOR; |
691 | 14.4M | property->kind = XS_ARRAY_KIND; |
692 | 14.4M | property->value.array.length = 0; |
693 | 14.4M | property->value.array.address = C_NULL; |
694 | 14.4M | return instance; |
695 | 14.4M | } |
696 | | |
697 | | void fxReduceThisItem(txMachine* the, txSlot* function, txIndex index) |
698 | 37.3k | { |
699 | 37.3k | mxPushSlot(mxThis); |
700 | 37.3k | if (fxHasIndex(the, index)) { |
701 | | /* THIS */ |
702 | 4.48k | mxPushUndefined(); |
703 | | /* FUNCTION */ |
704 | 4.48k | mxPushSlot(function); |
705 | 4.48k | mxCall(); |
706 | | /* ARGUMENTS */ |
707 | 4.48k | mxPushSlot(mxResult); |
708 | 4.48k | mxPushSlot(mxThis); |
709 | 4.48k | mxGetIndex(index); |
710 | 4.48k | mxPushUnsigned(index); |
711 | 4.48k | mxPushSlot(mxThis); |
712 | 4.48k | mxRunCount(4); |
713 | 4.48k | mxPullSlot(mxResult); |
714 | 4.48k | } |
715 | 37.3k | } |
716 | | |
717 | | txBoolean fxSetArrayLength(txMachine* the, txSlot* array, txIndex length) |
718 | 6.50M | { |
719 | 6.50M | txSlot* address = array->value.array.address; |
720 | 6.50M | txSlot* chunk = address; |
721 | 6.50M | txBoolean success = 1; |
722 | 6.50M | if (address) { |
723 | 244k | txSize size = (((txChunk*)(((txByte*)chunk) - sizeof(txChunk)))->size) / sizeof(txSlot); |
724 | 244k | txSlot* result = address + size; |
725 | 244k | txSlot* limit = result; |
726 | 244k | txIndex at; |
727 | 1.21M | while (result > address) { |
728 | 1.21M | result--; |
729 | 1.21M | at = *((txIndex*)result); |
730 | 1.21M | if (length > at) { |
731 | 243k | result++; |
732 | 243k | break; |
733 | 243k | } |
734 | 973k | else if (result->flag & XS_DONT_DELETE_FLAG) { |
735 | 4 | result++; |
736 | 4 | length = at + 1; |
737 | 4 | success = 0; |
738 | 4 | break; |
739 | 4 | } |
740 | 1.21M | } |
741 | 244k | if (result < limit) { |
742 | 656 | if (result > address) { |
743 | 553 | size = mxPtrDiff(result - address); |
744 | 553 | chunk = (txSlot*)fxNewChunk(the, fxMultiplyChunkSizes(the, size, sizeof(txSlot))); |
745 | 553 | address = array->value.array.address; |
746 | 553 | c_memcpy(chunk, address, size * sizeof(txSlot)); |
747 | 553 | } |
748 | 103 | else |
749 | 103 | chunk = C_NULL; |
750 | 656 | } |
751 | 244k | } |
752 | 6.50M | array->value.array.length = length; |
753 | 6.50M | array->value.array.address = chunk; |
754 | 6.50M | return success; |
755 | 6.50M | } |
756 | | |
757 | | void fxSortArrayItems(txMachine* the, txSlot* function, txSlot* array, txNumber LENGTH, txSlot* target) |
758 | 252k | { |
759 | 252k | txBoolean flag = mxThis->value.reference != target->value.reference; |
760 | 252k | txSlot* instance = C_NULL; |
761 | 252k | txIndex index; |
762 | 252k | txSlot* item; |
763 | 252k | txIndex length; |
764 | 252k | txIndex size; |
765 | 252k | again: |
766 | 252k | if (!array) { |
767 | 252k | LENGTH = fxGetArrayLength(the, mxThis); |
768 | 252k | if (LENGTH > 0xFFFFFFFF) |
769 | 0 | mxRangeError("array overflow"); |
770 | 252k | mxPush(mxArrayPrototype); |
771 | 252k | instance = fxNewArrayInstance(the); |
772 | 252k | array = instance->next; |
773 | 252k | item = array; |
774 | 252k | index = 0; |
775 | 6.30M | while (index < LENGTH) { |
776 | 6.04M | mxPushSlot(mxThis); |
777 | 6.04M | if (flag || fxHasIndex(the, index)) { |
778 | 4.27M | item->next = fxNewSlot(the); |
779 | 4.27M | item = item->next; |
780 | 4.27M | array->value.array.length++; |
781 | 4.27M | mxPushSlot(mxThis); |
782 | 4.27M | mxGetIndex(index); |
783 | 4.27M | mxPullSlot(item); |
784 | 4.27M | } |
785 | 6.04M | index++; |
786 | 6.04M | } |
787 | 252k | fxCacheArray(the, instance); |
788 | 252k | } |
789 | 252k | length = array->value.array.length; |
790 | 252k | size = mxArraySize(array); |
791 | | /* like GCC qsort */ |
792 | 252k | #define CHECK \ |
793 | 677k | if (size != mxArraySize(array)) { \ |
794 | 0 | array = C_NULL; \ |
795 | 0 | goto again; \ |
796 | 0 | } |
797 | 252k | #define COMPARE(INDEX) \ |
798 | 670k | fxCompareArrayItem(the, function, array, INDEX) |
799 | 252k | #define COPY \ |
800 | 386k | to->next = from->next; \ |
801 | 386k | to->ID = from->ID; \ |
802 | 386k | to->kind = from->kind; \ |
803 | 386k | to->value = from->value |
804 | 252k | #define MOVE(FROM,TO) \ |
805 | 252k | from = array->value.array.address + (FROM); \ |
806 | 194k | to = array->value.array.address + (TO); \ |
807 | 194k | COPY |
808 | 252k | #define PUSH(INDEX) \ |
809 | 252k | from = array->value.array.address + (INDEX); \ |
810 | 103k | mxPushUndefined(); \ |
811 | 103k | to = the->stack; \ |
812 | 103k | COPY |
813 | 252k | #define PULL(INDEX) \ |
814 | 252k | from = the->stack++; \ |
815 | 88.3k | to = array->value.array.address + (INDEX); \ |
816 | 88.3k | COPY |
817 | 252k | if (length > 0) { |
818 | 70.8k | txIndex i, j; |
819 | 70.8k | txSlot* from; |
820 | 70.8k | txSlot* to; |
821 | 70.8k | if (length > mxSortThreshold) { |
822 | 8.04k | txIndex lo = 0, hi = length - 1; |
823 | 8.04k | txSortPartition stack[mxSortPartitionCount]; |
824 | 8.04k | txSortPartition *top = stack + 1; |
825 | 23.0k | while (stack < top) { |
826 | 14.9k | txIndex mid = lo + ((hi - lo) >> 1); |
827 | 14.9k | PUSH(mid); |
828 | 14.9k | if (COMPARE(lo) > 0) { |
829 | 4.30k | CHECK; |
830 | 4.30k | MOVE(lo, mid); |
831 | 4.30k | PULL(lo); |
832 | 4.30k | PUSH(mid); |
833 | 4.30k | } |
834 | 10.6k | else |
835 | 14.9k | CHECK; |
836 | 14.9k | if (COMPARE(hi) < 0) { |
837 | 1.95k | CHECK; |
838 | 1.95k | MOVE(hi, mid); |
839 | 1.95k | PULL(hi); |
840 | 1.95k | PUSH(mid); |
841 | 1.95k | if (COMPARE(lo) > 0) { |
842 | 302 | CHECK; |
843 | 302 | MOVE(lo, mid); |
844 | 302 | PULL(lo); |
845 | 302 | PUSH(mid); |
846 | 302 | } |
847 | 1.65k | else |
848 | 1.95k | CHECK; |
849 | 1.95k | } |
850 | 13.0k | else |
851 | 14.9k | CHECK; |
852 | 14.9k | i = lo + 1; |
853 | 14.9k | j = hi - 1; |
854 | 22.1k | do { |
855 | 165k | while ((COMPARE(i) < 0) && (i <= j)) { CHECK; i++; } |
856 | 44.2k | CHECK; |
857 | 226k | while ((COMPARE(j) > 0) && (i <= j)) { CHECK; j--; } |
858 | 44.2k | CHECK; |
859 | 44.2k | if (i < j) { |
860 | 8.00k | PUSH(i); |
861 | 8.00k | MOVE(j, i); |
862 | 8.00k | PULL(j); |
863 | 8.00k | i++; |
864 | 8.00k | j--; |
865 | 8.00k | } |
866 | 14.1k | else if (i == j) { |
867 | 6.85k | i++; |
868 | 6.85k | j--; |
869 | 6.85k | break; |
870 | 6.85k | } |
871 | 44.2k | } while (i <= j); |
872 | 14.9k | if ((j - lo) <= mxSortThreshold) { |
873 | 8.92k | if ((hi - i) <= mxSortThreshold) { |
874 | 6.80k | top--; |
875 | 6.80k | lo = top->lo; |
876 | 6.80k | hi = top->hi; |
877 | 6.80k | } |
878 | 2.11k | else { |
879 | 2.11k | lo = i; |
880 | 2.11k | } |
881 | 8.92k | } |
882 | 6.06k | else if ((hi - i) <= mxSortThreshold) { |
883 | 1.34k | hi = j; |
884 | 1.34k | } |
885 | 4.71k | else if ((j - lo) > (hi - i)) { |
886 | 124 | top->lo = lo; |
887 | 124 | top->hi = j; |
888 | 124 | top++; |
889 | 124 | lo = i; |
890 | 124 | } |
891 | 4.58k | else { |
892 | 4.58k | top->lo = i; |
893 | 4.58k | top->hi = hi; |
894 | 4.58k | top++; |
895 | 4.58k | hi = j; |
896 | 4.58k | } |
897 | 14.9k | mxPop(); |
898 | 14.9k | } |
899 | 8.04k | } |
900 | 144k | for (i = 1; i < length; i++) { |
901 | 73.7k | PUSH(i); |
902 | 253k | for (j = i; (j > 0) && (COMPARE(j - 1) > 0); j--) { |
903 | 180k | CHECK; |
904 | 180k | MOVE(j - 1, j); |
905 | 180k | } |
906 | 147k | CHECK; |
907 | 147k | PULL(j); |
908 | 147k | } |
909 | 70.8k | } |
910 | 252k | if (instance) { |
911 | 238k | index = 0; |
912 | 357k | while (index < length) { |
913 | 119k | item = array->value.array.address + index; |
914 | 119k | mxPushSlot(item); |
915 | 119k | mxPushSlot(target); |
916 | 119k | if (flag) |
917 | 43.0k | mxDefineIndex(index, 0, XS_GET_ONLY); |
918 | 76.1k | else |
919 | 76.1k | mxSetIndex(index); |
920 | 119k | mxPop(); |
921 | 119k | index++; |
922 | 119k | } |
923 | 328k | while (index < LENGTH) { |
924 | 90.2k | mxPushSlot(target); |
925 | 90.2k | mxDeleteIndex(index); |
926 | 90.2k | mxPop(); |
927 | 90.2k | index++; |
928 | 90.2k | } |
929 | 238k | mxPop(); |
930 | 238k | } |
931 | 14.1k | else |
932 | 14.1k | fxIndexArray(the, array); |
933 | 252k | } |
934 | | |
935 | | txNumber fxToLength(txMachine* the, txSlot* slot) |
936 | 17.3M | { |
937 | 17.4M | again: |
938 | 17.4M | if (slot->kind == XS_INTEGER_KIND) { |
939 | 13.0M | txInteger length = slot->value.integer; |
940 | 13.0M | if (length < 0) |
941 | 9 | length = 0; |
942 | 13.0M | slot->value.number = (txNumber)length; |
943 | 13.0M | slot->kind = XS_NUMBER_KIND; |
944 | 13.0M | return (txNumber)length; |
945 | 13.0M | } |
946 | 4.45M | if (slot->kind == XS_NUMBER_KIND) { |
947 | 4.30M | txNumber length = slot->value.number; |
948 | 4.30M | if (c_isnan(length)) |
949 | 147k | length = 0; |
950 | 4.15M | else if (length <= 0) |
951 | 37.3k | length = 0; |
952 | 4.12M | else if (length > C_MAX_SAFE_INTEGER) |
953 | 107 | length = C_MAX_SAFE_INTEGER; |
954 | 4.12M | else |
955 | 4.12M | length = c_trunc(length); |
956 | 4.30M | slot->value.number = length; |
957 | 4.30M | return length; |
958 | 4.30M | } |
959 | 147k | fxToNumber(the, slot); |
960 | 147k | goto again; |
961 | 4.45M | } |
962 | | |
963 | | void fxArrayLengthGetter(txMachine* the) |
964 | 7.23M | { |
965 | 7.23M | txSlot* instance = fxToInstance(the, mxThis); |
966 | 7.23M | txSlot* array; |
967 | 7.34M | while (instance) { |
968 | 7.34M | if (instance->flag & XS_EXOTIC_FLAG) { |
969 | 7.23M | array = instance->next; |
970 | 7.23M | if ((array->kind == XS_ARRAY_KIND) && (array->ID == XS_ARRAY_BEHAVIOR)) |
971 | 7.23M | break; |
972 | 7.23M | } |
973 | 107k | instance = fxGetPrototype(the, instance); |
974 | 107k | } |
975 | 7.23M | if (!instance) |
976 | 0 | return; |
977 | | #if mxAliasInstance |
978 | | if (instance->ID) { |
979 | | txSlot* alias = the->aliasArray[instance->ID]; |
980 | | if (alias) |
981 | | array = alias->next; |
982 | | } |
983 | | #endif |
984 | 7.23M | if (((txInteger)array->value.array.length) < 0) { |
985 | 80 | mxResult->value.number = array->value.array.length; |
986 | 80 | mxResult->kind = XS_NUMBER_KIND; |
987 | 80 | } |
988 | 7.23M | else { |
989 | 7.23M | mxResult->value.integer = (txInteger)array->value.array.length; |
990 | 7.23M | mxResult->kind = XS_INTEGER_KIND; |
991 | 7.23M | } |
992 | 7.23M | } |
993 | | |
994 | | void fxArrayLengthSetter(txMachine* the) |
995 | 5.84M | { |
996 | 5.84M | txSlot* instance = fxToInstance(the, mxThis); |
997 | 5.84M | txSlot* array; |
998 | 5.84M | txIndex length; |
999 | 5.84M | while (instance) { |
1000 | 5.84M | if (instance->flag & XS_EXOTIC_FLAG) { |
1001 | 5.84M | array = instance->next; |
1002 | 5.84M | if (array->ID == XS_ARRAY_BEHAVIOR) |
1003 | 5.84M | break; |
1004 | 5.84M | } |
1005 | 13 | instance = fxGetPrototype(the, instance); |
1006 | 13 | } |
1007 | 5.84M | if (!instance) |
1008 | 0 | return; |
1009 | | #if mxAliasInstance |
1010 | | if (instance->ID) { |
1011 | | txSlot* alias = the->aliasArray[instance->ID]; |
1012 | | if (!alias) |
1013 | | alias = fxAliasInstance(the, instance); |
1014 | | array = alias->next; |
1015 | | } |
1016 | | #endif |
1017 | 5.84M | length = fxCheckArrayLength(the, mxArgv(0)); |
1018 | 5.84M | if (array->flag & XS_DONT_SET_FLAG) { |
1019 | 2 | if (the->frame->next->flag & XS_STRICT_FLAG) |
1020 | 1 | mxTypeError("set length: not writable"); |
1021 | 1 | else |
1022 | 1 | return; |
1023 | 2 | } |
1024 | 5.84M | fxSetArrayLength(the, array, length); |
1025 | 5.84M | } |
1026 | | |
1027 | | txBoolean fxArrayDefineOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* descriptor, txFlag mask) |
1028 | 18.4M | { |
1029 | 18.4M | if (id == mxID(_length)) { |
1030 | 154 | txSlot* array = instance->next; |
1031 | 154 | txSlot slot; |
1032 | 154 | txBoolean result = 1; |
1033 | 154 | txIndex length = ((descriptor->kind != XS_UNINITIALIZED_KIND) && (descriptor->kind != XS_ACCESSOR_KIND)) ? fxCheckArrayLength(the, descriptor) : 0; |
1034 | 154 | slot.flag = array->flag; |
1035 | 154 | slot.ID = id; |
1036 | 154 | slot.kind = XS_NUMBER_KIND; |
1037 | 154 | slot.value.number = array->value.array.length; |
1038 | 154 | if (!fxIsPropertyCompatible(the, &slot, descriptor, mask)) |
1039 | 30 | return 0; |
1040 | | #if mxAliasInstance |
1041 | | if (instance->ID) { |
1042 | | txSlot* alias = the->aliasArray[instance->ID]; |
1043 | | if (!alias) { |
1044 | | alias = fxAliasInstance(the, instance); |
1045 | | array = alias->next; |
1046 | | } |
1047 | | } |
1048 | | #endif |
1049 | 124 | if (descriptor->kind != XS_UNINITIALIZED_KIND) { |
1050 | 17 | if (array->value.array.length != length) |
1051 | 12 | result = fxSetArrayLength(the, array, length); |
1052 | 17 | } |
1053 | 124 | if ((mask & XS_DONT_SET_FLAG) && (descriptor->flag & XS_DONT_SET_FLAG) && !(array->flag & XS_DONT_SET_FLAG)) |
1054 | 75 | array->flag |= XS_DONT_SET_FLAG; |
1055 | 124 | return result; |
1056 | 154 | } |
1057 | 18.4M | return fxOrdinaryDefineOwnProperty(the, instance, id, index, descriptor, mask); |
1058 | 18.4M | } |
1059 | | |
1060 | | txBoolean fxArrayDeleteProperty(txMachine* the, txSlot* instance, txID id, txIndex index) |
1061 | 1.66M | { |
1062 | 1.66M | if (id == mxID(_length)) |
1063 | 1 | return 0; |
1064 | 1.66M | return fxOrdinaryDeleteProperty(the, instance, id, index); |
1065 | 1.66M | } |
1066 | | |
1067 | | txBoolean fxArrayGetOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* descriptor) |
1068 | 373k | { |
1069 | 373k | if (id == mxID(_length)) { |
1070 | 22.1k | txSlot* array = instance->next; |
1071 | 22.1k | descriptor->flag = array->flag; |
1072 | 22.1k | descriptor->ID = id; |
1073 | 22.1k | descriptor->kind = XS_NUMBER_KIND; |
1074 | 22.1k | descriptor->value.number = array->value.array.length; |
1075 | 22.1k | return 1; |
1076 | 22.1k | } |
1077 | 350k | return fxOrdinaryGetOwnProperty(the, instance, id, index, descriptor); |
1078 | 373k | } |
1079 | | |
1080 | | txSlot* fxArrayGetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag) |
1081 | 172M | { |
1082 | 172M | if (id == mxID(_length)) |
1083 | 7.23M | return &mxArrayLengthAccessor; |
1084 | 165M | return fxOrdinaryGetProperty(the, instance, id, index, flag); |
1085 | 172M | } |
1086 | | |
1087 | | txBoolean fxArrayHasProperty(txMachine* the, txSlot* instance, txID id, txIndex index) |
1088 | 40.5M | { |
1089 | 40.5M | if (id == mxID(_length)) |
1090 | 8 | return 1; |
1091 | 40.5M | return fxOrdinaryHasProperty(the, instance, id, index); |
1092 | 40.5M | } |
1093 | | |
1094 | | void fxArrayOwnKeys(txMachine* the, txSlot* instance, txFlag flag, txSlot* keys) |
1095 | 17.6k | { |
1096 | 17.6k | txSlot* property = instance->next; |
1097 | 17.6k | keys = fxQueueIndexKeys(the, property, flag, keys); |
1098 | 17.6k | if (flag & XS_EACH_NAME_FLAG) |
1099 | 17.6k | keys = fxQueueKey(the, mxID(_length), 0, keys); |
1100 | 17.6k | property = property->next; |
1101 | 17.6k | fxQueueIDKeys(the, property, flag, keys); |
1102 | 17.6k | } |
1103 | | |
1104 | | txSlot* fxArraySetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag) |
1105 | 24.2M | { |
1106 | 24.2M | if (id == mxID(_length)) { |
1107 | 5.84M | txSlot* array = instance->next; |
1108 | 5.84M | if (array->flag & XS_DONT_SET_FLAG) |
1109 | 1.35k | return array; |
1110 | 5.84M | return &mxArrayLengthAccessor; |
1111 | 5.84M | } |
1112 | 18.4M | return fxOrdinarySetProperty(the, instance, id, index, flag); |
1113 | 24.2M | } |
1114 | | |
1115 | | void fx_Array(txMachine* the) |
1116 | 1.17M | { |
1117 | 1.17M | txSlot* instance; |
1118 | 1.17M | txSlot* array; |
1119 | 1.17M | txSlot* argument; |
1120 | 1.17M | txIndex count = (txIndex)mxArgc; |
1121 | 1.17M | txBoolean flag = 0; |
1122 | 1.17M | txIndex index = 0; |
1123 | 1.17M | txSlot* slot; |
1124 | | |
1125 | 1.17M | if (!mxHasTarget) |
1126 | 218k | mxPushSlot(mxFunction); |
1127 | 956k | else |
1128 | 956k | mxPushSlot(mxTarget); |
1129 | 1.17M | fxGetPrototypeFromConstructor(the, &mxArrayPrototype); |
1130 | 1.17M | instance = fxNewArrayInstance(the); |
1131 | 1.17M | mxPullSlot(mxResult); |
1132 | 1.17M | array = instance->next; |
1133 | | |
1134 | 1.17M | if (count == 1) { |
1135 | 712k | argument = mxArgv(0); |
1136 | 712k | if ((argument->kind == XS_INTEGER_KIND) || (argument->kind == XS_NUMBER_KIND)) { |
1137 | 665k | count = fxCheckArrayLength(the, mxArgv(0)); |
1138 | 665k | flag = 1; |
1139 | 665k | } |
1140 | 712k | } |
1141 | 1.17M | if (array) { |
1142 | 1.17M | if (flag) |
1143 | 665k | fxSetArrayLength(the, array, count); |
1144 | 509k | else { |
1145 | 509k | fxSetIndexSize(the, array, count, XS_CHUNK); |
1146 | 509k | slot = array->value.array.address; |
1147 | 890k | while (index < count) { |
1148 | 380k | argument = mxArgv(index); |
1149 | 380k | *((txIndex*)slot) = index; |
1150 | 380k | slot->ID = XS_NO_ID; |
1151 | 380k | slot->kind = argument->kind; |
1152 | 380k | slot->value = argument->value; |
1153 | 380k | slot++; |
1154 | 380k | index++; |
1155 | 380k | } |
1156 | 509k | } |
1157 | 1.17M | } |
1158 | 6 | else { |
1159 | 6 | mxPushNumber(count); |
1160 | 6 | mxPushSlot(mxThis); |
1161 | 6 | mxSetID(mxID(_length)); |
1162 | 6 | mxPop(); |
1163 | 6 | if (!flag) { |
1164 | 0 | while (index < count) { |
1165 | 0 | mxPushSlot(mxArgv(index)); |
1166 | 0 | mxPushSlot(mxThis); |
1167 | 0 | mxDefineIndex(index, 0, XS_GET_ONLY); |
1168 | 0 | mxPop(); |
1169 | 0 | index++; |
1170 | 0 | } |
1171 | 0 | } |
1172 | 6 | } |
1173 | 1.17M | } |
1174 | | |
1175 | | void fx_Array_from(txMachine* the) |
1176 | 478k | { |
1177 | 478k | txSlot* function = (mxArgc > 1) && !mxIsUndefined(mxArgv(1)) ? fxArgToCallback(the, 1) : C_NULL; |
1178 | 478k | txIndex length = 0; |
1179 | 478k | txSlot* iterator; |
1180 | 478k | txSlot* next; |
1181 | 478k | txSlot* value; |
1182 | 478k | if (mxArgc > 0) { |
1183 | 289k | mxPushSlot(mxArgv(0)); |
1184 | 289k | mxGetID(mxID(_Symbol_iterator)); |
1185 | 289k | if (mxIsUndefined(the->stack) || mxIsNull(the->stack)) { |
1186 | 28.8k | txIndex index = 0; |
1187 | 28.8k | mxPushSlot(mxArgv(0)); |
1188 | 28.8k | mxGetID(mxID(_length)); |
1189 | 28.8k | if (mxIsUndefined(the->stack)) |
1190 | 28.8k | length = 0; |
1191 | 8 | else |
1192 | 8 | length = fxCheckArrayLength(the, the->stack); |
1193 | 28.8k | mxPop(); |
1194 | 28.8k | fxCreateArray(the, 1, length); |
1195 | 29.4k | while (index < length) { |
1196 | 527 | mxPushSlot(mxArgv(0)); |
1197 | 527 | mxGetIndex(index); |
1198 | 527 | fx_Array_from_aux(the, function, the->stack, index); |
1199 | 527 | mxPop(); |
1200 | 527 | index++; |
1201 | 527 | } |
1202 | 28.8k | } |
1203 | 260k | else { |
1204 | 260k | fxCreateArray(the, 0, 0); |
1205 | 260k | mxTemporary(iterator); |
1206 | 260k | mxTemporary(next); |
1207 | 260k | fxGetIterator(the, mxArgv(0), iterator, next, 0); |
1208 | 260k | mxTemporary(value); |
1209 | 260k | length = 0; |
1210 | 3.36M | while (fxIteratorNext(the, iterator, next, value)) { |
1211 | 3.09M | mxTry(the) { |
1212 | 3.09M | fx_Array_from_aux(the, function, value, length); |
1213 | 3.09M | length++; |
1214 | 3.09M | } |
1215 | 3.09M | mxCatch(the) { |
1216 | 4 | fxIteratorReturn(the, iterator, 1); |
1217 | 4 | fxJump(the); |
1218 | 4 | } |
1219 | 3.09M | } |
1220 | 260k | mxPop(); |
1221 | 260k | } |
1222 | 289k | } |
1223 | 188k | else { |
1224 | 188k | fxCreateArray(the, 1, 0); |
1225 | 188k | } |
1226 | 478k | mxPushUnsigned(length); |
1227 | 478k | mxPushSlot(mxResult); |
1228 | 478k | mxSetID(mxID(_length)); |
1229 | 478k | mxPop(); |
1230 | 478k | } |
1231 | | |
1232 | | void fx_Array_from_aux(txMachine* the, txSlot* function, txSlot* value, txIndex index) |
1233 | 3.09M | { |
1234 | 3.09M | if (function) { |
1235 | | /* THIS */ |
1236 | 34.2k | if (mxArgc > 2) |
1237 | 35 | mxPushSlot(mxArgv(2)); |
1238 | 34.2k | else |
1239 | 34.2k | mxPushUndefined(); |
1240 | | /* FUNCTION */ |
1241 | 34.2k | mxPushSlot(function); |
1242 | 34.2k | mxCall(); |
1243 | | /* ARGUMENTS */ |
1244 | 34.2k | mxPushSlot(value); |
1245 | 34.2k | mxPushInteger(index); |
1246 | 34.2k | mxRunCount(2); |
1247 | 34.2k | } |
1248 | 3.06M | else |
1249 | 3.06M | mxPushSlot(value); |
1250 | 3.09M | mxPushSlot(mxResult); |
1251 | 3.09M | mxDefineIndex(index, 0, XS_GET_ONLY); |
1252 | 3.09M | mxPop(); |
1253 | 3.09M | } |
1254 | | |
1255 | | void fx_Array_fromAsync(txMachine* the) |
1256 | 0 | { |
1257 | 0 | txSlot* stack = the->stack; |
1258 | 0 | txSlot* iterator; |
1259 | 0 | txSlot* resolveFunction; |
1260 | 0 | txSlot* rejectFunction; |
1261 | 0 | txSlot* promise; |
1262 | 0 | txSlot* instance; |
1263 | 0 | txSlot* property; |
1264 | 0 | txSlot* home; |
1265 | | |
1266 | 0 | mxTemporary(iterator); |
1267 | 0 | mxTemporary(resolveFunction); |
1268 | 0 | mxTemporary(rejectFunction); |
1269 | 0 | mxTemporary(promise); |
1270 | 0 | mxPush(mxPromiseConstructor); |
1271 | 0 | fxNewPromiseCapability(the, resolveFunction, rejectFunction); |
1272 | 0 | mxPullSlot(promise); |
1273 | 0 | { |
1274 | 0 | mxTry(the) { |
1275 | 0 | txSlot* function = (mxArgc > 1) && !mxIsUndefined(mxArgv(1)) ? fxArgToCallback(the, 1) : C_NULL; |
1276 | 0 | txNumber length = 0; |
1277 | | |
1278 | 0 | if (mxArgc == 0) |
1279 | 0 | mxTypeError("no items"); |
1280 | | |
1281 | 0 | mxPushSlot(mxArgv(0)); |
1282 | 0 | mxDub(); |
1283 | 0 | mxGetID(mxID(_Symbol_asyncIterator)); |
1284 | 0 | if (mxIsUndefined(the->stack) || mxIsNull(the->stack)) { |
1285 | 0 | mxPop(); |
1286 | 0 | mxDub(); |
1287 | 0 | mxGetID(mxID(_Symbol_iterator)); |
1288 | 0 | if (mxIsUndefined(the->stack) || mxIsNull(the->stack)) { |
1289 | 0 | mxPop(); |
1290 | 0 | mxDub(); |
1291 | 0 | mxGetID(mxID(_length)); |
1292 | 0 | length = fxToLength(the, the->stack); |
1293 | 0 | mxPop(); |
1294 | 0 | if (length > 0x7FFFFFFF) |
1295 | 0 | mxRangeError("array overflow"); |
1296 | 0 | mxPush(mxIteratorPrototype); |
1297 | 0 | property = fxLastProperty(the, fxNewIteratorInstance(the, mxArgv(0), mxID(_Array))); |
1298 | 0 | property = fxNextIntegerProperty(the, property, (txInteger)length, XS_NO_ID, XS_INTERNAL_FLAG); |
1299 | 0 | property = fxNextHostFunctionProperty(the, property, mxCallback(fx_Array_fromAsync_items_next), 0, mxID(_next), XS_DONT_ENUM_FLAG); |
1300 | 0 | fxNewAsyncFromSyncIteratorInstance(the); |
1301 | 0 | mxPullSlot(iterator); |
1302 | 0 | fxCreateArray(the, 1, (txIndex)length); |
1303 | 0 | } |
1304 | 0 | else { |
1305 | 0 | mxCall(); |
1306 | 0 | mxRunCount(0); |
1307 | 0 | fxNewAsyncFromSyncIteratorInstance(the); |
1308 | 0 | mxPullSlot(iterator); |
1309 | 0 | fxCreateArray(the, 0, 0); |
1310 | 0 | } |
1311 | 0 | } |
1312 | 0 | else { |
1313 | 0 | mxCall(); |
1314 | 0 | mxRunCount(0); |
1315 | 0 | mxPullSlot(iterator); |
1316 | 0 | fxCreateArray(the, 0, 0); |
1317 | 0 | } |
1318 | | |
1319 | 0 | property = instance = fxNewInstance(the); |
1320 | | |
1321 | 0 | property = fxNextSlotProperty(the, property, resolveFunction, XS_NO_ID, XS_INTERNAL_FLAG); |
1322 | 0 | property = fxNextSlotProperty(the, property, rejectFunction, XS_NO_ID, XS_INTERNAL_FLAG); |
1323 | | |
1324 | 0 | function = fxNewHostFunction(the, fx_Array_fromAsync_onIterated, 1, XS_NO_ID, XS_NO_ID); |
1325 | 0 | home = mxFunctionInstanceHome(function); |
1326 | 0 | home->value.home.object = instance; |
1327 | 0 | property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG); |
1328 | 0 | mxPop(); |
1329 | | |
1330 | 0 | function = fxNewHostFunction(the, fx_Array_fromAsync_onRejected, 1, XS_NO_ID, XS_NO_ID); |
1331 | 0 | home = mxFunctionInstanceHome(function); |
1332 | 0 | home->value.home.object = instance; |
1333 | 0 | property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG); |
1334 | 0 | mxPop(); |
1335 | | |
1336 | 0 | property = fxNextSlotProperty(the, property, mxResult, XS_NO_ID, XS_INTERNAL_FLAG); |
1337 | 0 | property = fxNextIntegerProperty(the, property, 0, XS_NO_ID, XS_INTERNAL_FLAG); |
1338 | | |
1339 | 0 | property = fxNextSlotProperty(the, property, iterator, XS_NO_ID, XS_INTERNAL_FLAG); |
1340 | 0 | if (mxArgc > 1) |
1341 | 0 | property = fxNextSlotProperty(the, property, mxArgv(1), XS_NO_ID, XS_INTERNAL_FLAG); |
1342 | 0 | else |
1343 | 0 | property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG); |
1344 | 0 | if (mxArgc > 2) |
1345 | 0 | property = fxNextSlotProperty(the, property, mxArgv(2), XS_NO_ID, XS_INTERNAL_FLAG); |
1346 | 0 | else |
1347 | 0 | property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG); |
1348 | 0 | function = fxNewHostFunction(the, fx_Array_fromAsync_onMapped, 1, XS_NO_ID, XS_NO_ID); |
1349 | 0 | home = mxFunctionInstanceHome(function); |
1350 | 0 | home->value.home.object = instance; |
1351 | 0 | property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG); |
1352 | 0 | mxPop(); |
1353 | | |
1354 | 0 | fx_Array_fromAsync_aux(the, instance); |
1355 | 0 | } |
1356 | 0 | mxCatch(the) { |
1357 | 0 | fxRejectException(the, rejectFunction); |
1358 | 0 | } |
1359 | 0 | } |
1360 | 0 | *mxResult = *promise; |
1361 | 0 | the->stack = stack; |
1362 | 0 | } |
1363 | | |
1364 | | void fx_Array_fromAsync_aux(txMachine* the, txSlot* closure) |
1365 | 0 | { |
1366 | 0 | txSlot* resolveFunction = closure->next; |
1367 | 0 | txSlot* rejectFunction = resolveFunction->next; |
1368 | 0 | txSlot* onIteratedFunction = rejectFunction->next; |
1369 | 0 | txSlot* onRejectedFunction = onIteratedFunction->next; |
1370 | 0 | txSlot* result = onRejectedFunction->next; |
1371 | 0 | txSlot* index = result->next; |
1372 | 0 | txSlot* iterator = index->next; |
1373 | |
|
1374 | 0 | mxPushUndefined(); |
1375 | 0 | mxPush(mxPromiseConstructor); |
1376 | |
|
1377 | 0 | mxPushSlot(iterator); |
1378 | 0 | mxDub(); |
1379 | 0 | mxGetID(mxID(_next)); |
1380 | 0 | mxCall(); |
1381 | 0 | mxRunCount(0); |
1382 | | |
1383 | 0 | fx_Promise_resolveAux(the); |
1384 | 0 | mxPop(); |
1385 | 0 | mxPop(); |
1386 | 0 | fxPromiseThen(the, the->stack->value.reference, onIteratedFunction, onRejectedFunction, C_NULL, rejectFunction); |
1387 | 0 | } |
1388 | | |
1389 | | void fx_Array_fromAsync_items_next(txMachine* the) |
1390 | 0 | { |
1391 | 0 | txSlot* iterator = fxCheckIteratorInstance(the, mxThis, mxID(_Array)); |
1392 | 0 | txSlot* result = iterator->next; |
1393 | 0 | txSlot* iterable = result->next; |
1394 | 0 | txSlot* index = iterable->next; |
1395 | 0 | txSlot* length = index->next; |
1396 | 0 | txSlot* value = fxCheckIteratorResult(the, result); |
1397 | 0 | txSlot* done = value->next; |
1398 | 0 | if (!done->value.boolean) { |
1399 | 0 | txIndex i = (txIndex)index->value.integer; |
1400 | 0 | txIndex c = (txIndex)length->value.integer; |
1401 | 0 | if (i < c) { |
1402 | 0 | mxPushSlot(iterable); |
1403 | 0 | mxGetIndex(i); |
1404 | 0 | mxPullSlot(value); |
1405 | 0 | index->value.integer = i + 1; |
1406 | 0 | } |
1407 | 0 | else { |
1408 | 0 | value->kind = XS_UNDEFINED_KIND; |
1409 | 0 | done->value.boolean = 1; |
1410 | 0 | } |
1411 | 0 | } |
1412 | 0 | mxResult->kind = result->kind; |
1413 | 0 | mxResult->value = result->value; |
1414 | 0 | } |
1415 | | |
1416 | | void fx_Array_fromAsync_onIterated(txMachine* the) |
1417 | 0 | { |
1418 | 0 | txSlot* slot = mxFunctionInstanceHome(mxFunction->value.reference); |
1419 | 0 | txSlot* closure = slot->value.home.object; |
1420 | 0 | txSlot* resolveFunction = closure->next; |
1421 | 0 | txSlot* rejectFunction = resolveFunction->next; |
1422 | 0 | txSlot* onIteratedFunction = rejectFunction->next; |
1423 | 0 | txSlot* onRejectedFunction = onIteratedFunction->next; |
1424 | 0 | txSlot* result = onRejectedFunction->next; |
1425 | 0 | txSlot* index = result->next; |
1426 | 0 | txSlot* iterator = index->next; |
1427 | 0 | txSlot* mapFunction = iterator->next; |
1428 | 0 | txSlot* mapThis = mapFunction->next; |
1429 | 0 | txSlot* onMappedFunction = mapThis->next; |
1430 | |
|
1431 | 0 | mxTry(the) { |
1432 | 0 | mxPushSlot(mxArgv(0)); |
1433 | 0 | mxGetID(mxID(_done)); |
1434 | 0 | if (fxToBoolean(the, the->stack)) { |
1435 | 0 | mxPushSlot(index); |
1436 | 0 | mxPushSlot(result); |
1437 | 0 | mxSetID(mxID(_length)); |
1438 | 0 | mxPop(); |
1439 | | |
1440 | 0 | mxPushUndefined(); |
1441 | 0 | mxPushSlot(resolveFunction); |
1442 | 0 | mxCall(); |
1443 | 0 | mxPushSlot(result); |
1444 | 0 | mxRunCount(1); |
1445 | 0 | mxPop(); |
1446 | 0 | return; |
1447 | 0 | } |
1448 | 0 | if (!mxIsUndefined(mapFunction)) { |
1449 | 0 | mxPushUndefined(); |
1450 | 0 | mxPush(mxPromiseConstructor); |
1451 | | |
1452 | 0 | mxPushSlot(mapThis); |
1453 | 0 | mxPushSlot(mapFunction); |
1454 | 0 | mxCall(); |
1455 | 0 | mxPushSlot(mxArgv(0)); |
1456 | 0 | mxGetID(mxID(_value)); |
1457 | 0 | mxPushSlot(index); |
1458 | 0 | mxRunCount(2); |
1459 | | |
1460 | 0 | fx_Promise_resolveAux(the); |
1461 | 0 | mxPop(); |
1462 | 0 | mxPop(); |
1463 | 0 | fxPromiseThen(the, the->stack->value.reference, onMappedFunction, onRejectedFunction, C_NULL, rejectFunction); |
1464 | 0 | } |
1465 | 0 | else { |
1466 | 0 | mxPushSlot(mxArgv(0)); |
1467 | 0 | mxGetID(mxID(_value)); |
1468 | 0 | mxPushSlot(result); |
1469 | 0 | mxDefineIndex(index->value.integer, 0, XS_GET_ONLY); |
1470 | 0 | mxPop(); |
1471 | 0 | index->value.integer++; |
1472 | 0 | fx_Array_fromAsync_aux(the, closure); |
1473 | 0 | } |
1474 | 0 | } |
1475 | 0 | mxCatch(the) { |
1476 | 0 | fxIteratorReturn(the, iterator, 1); |
1477 | 0 | fxThrow(the, NULL, 0); |
1478 | 0 | } |
1479 | 0 | } |
1480 | | |
1481 | | void fx_Array_fromAsync_onMapped(txMachine* the) |
1482 | 0 | { |
1483 | 0 | txSlot* slot = mxFunctionInstanceHome(mxFunction->value.reference); |
1484 | 0 | txSlot* closure = slot->value.home.object; |
1485 | 0 | txSlot* resolveFunction = closure->next; |
1486 | 0 | txSlot* rejectFunction = resolveFunction->next; |
1487 | 0 | txSlot* onIteratedFunction = rejectFunction->next; |
1488 | 0 | txSlot* onRejectedFunction = onIteratedFunction->next; |
1489 | 0 | txSlot* result = onRejectedFunction->next; |
1490 | 0 | txSlot* index = result->next; |
1491 | 0 | txSlot* iterator = index->next; |
1492 | | |
1493 | 0 | mxTry(the) { |
1494 | 0 | mxPushSlot(mxArgv(0)); |
1495 | 0 | mxPushSlot(result); |
1496 | 0 | mxDefineIndex(index->value.integer, 0, XS_GET_ONLY); |
1497 | 0 | mxPop(); |
1498 | 0 | index->value.integer++; |
1499 | 0 | fx_Array_fromAsync_aux(the, closure); |
1500 | 0 | } |
1501 | 0 | mxCatch(the) { |
1502 | 0 | fxIteratorReturn(the, iterator, 1); |
1503 | 0 | fxThrow(the, NULL, 0); |
1504 | 0 | } |
1505 | 0 | } |
1506 | | |
1507 | | void fx_Array_fromAsync_onRejected(txMachine* the) |
1508 | 0 | { |
1509 | 0 | txSlot* slot = mxFunctionInstanceHome(mxFunction->value.reference); |
1510 | 0 | txSlot* closure = slot->value.home.object; |
1511 | 0 | txSlot* resolveFunction = closure->next; |
1512 | 0 | txSlot* rejectFunction = resolveFunction->next; |
1513 | 0 | txSlot* onIteratedFunction = rejectFunction->next; |
1514 | 0 | txSlot* onRejectedFunction = onIteratedFunction->next; |
1515 | 0 | txSlot* result = onRejectedFunction->next; |
1516 | 0 | txSlot* index = result->next; |
1517 | 0 | txSlot* iterator = index->next; |
1518 | | |
1519 | 0 | fxIteratorReturn(the, iterator, 1); |
1520 | 0 | mxException.kind = mxArgv(0)->kind; |
1521 | 0 | mxException.value = mxArgv(0)->value; |
1522 | 0 | fxThrow(the, NULL, 0); |
1523 | 0 | } |
1524 | | |
1525 | | void fx_Array_isArray(txMachine* the) |
1526 | 1.58k | { |
1527 | 1.58k | mxResult->kind = XS_BOOLEAN_KIND; |
1528 | 1.58k | mxResult->value.boolean = (mxArgc > 0) ? fxIsArray(the, fxGetInstance(the, mxArgv(0))) : 0; |
1529 | 1.58k | } |
1530 | | |
1531 | | void fx_Array_of(txMachine* the) |
1532 | 44 | { |
1533 | 44 | txIndex count = (txIndex)mxArgc, index = 0; |
1534 | 44 | txSlot* array = fxCreateArray(the, 1, count); |
1535 | 44 | if (array) { |
1536 | 14 | txSlot* slot; |
1537 | 14 | fxSetIndexSize(the, array, count, XS_CHUNK); |
1538 | 14 | slot = array->value.array.address; |
1539 | 14 | while (index < count) { |
1540 | 0 | txSlot* argument = mxArgv(index); |
1541 | 0 | *((txIndex*)slot) = index; |
1542 | 0 | slot->ID = XS_NO_ID; |
1543 | 0 | slot->kind = argument->kind; |
1544 | 0 | slot->value = argument->value; |
1545 | 0 | slot++; |
1546 | 0 | mxMeterSome(4); |
1547 | 0 | index++; |
1548 | 0 | } |
1549 | 14 | mxMeterSome(4); |
1550 | 14 | } |
1551 | 30 | else { |
1552 | 96 | while (index < count) { |
1553 | 66 | mxPushSlot(mxArgv(index)); |
1554 | 66 | mxPushSlot(mxResult); |
1555 | 66 | mxDefineIndex(index, 0, XS_GET_ONLY); |
1556 | 66 | mxPop(); |
1557 | 66 | index++; |
1558 | 66 | } |
1559 | 30 | mxPushInteger(count); |
1560 | 30 | mxPushSlot(mxResult); |
1561 | 30 | mxSetID(mxID(_length)); |
1562 | 30 | mxPop(); |
1563 | 30 | } |
1564 | 44 | } |
1565 | | |
1566 | | void fx_Array_prototype_at(txMachine* the) |
1567 | 15.3k | { |
1568 | 15.3k | txSlot* array = fxCheckArray(the, mxThis, XS_IMMUTABLE); |
1569 | 15.3k | txNumber length = (array) ? array->value.array.length : fxGetArrayLength(the, mxThis); |
1570 | 15.3k | txNumber index = (mxArgc > 0) ? c_trunc(fxToNumber(the, mxArgv(0))) : C_NAN; |
1571 | 15.3k | if (c_isnan(index) || (index == 0)) |
1572 | 11.9k | index = 0; |
1573 | 15.3k | if (index < 0) |
1574 | 3.37k | index = length + index; |
1575 | 15.3k | if ((0 <= index) && (index < length)) { |
1576 | 9.56k | mxPushSlot(mxThis); |
1577 | 9.56k | mxPushNumber(index); |
1578 | 9.56k | mxGetAt(); |
1579 | 9.56k | mxPullSlot(mxResult); |
1580 | 9.56k | } |
1581 | 15.3k | } |
1582 | | |
1583 | | void fx_Array_prototype_concat(txMachine* the) |
1584 | 1.65k | { |
1585 | 1.65k | txSlot* resultArray = fxCreateArraySpecies(the, 0); |
1586 | 1.65k | txIndex resultLength = 0; |
1587 | 1.65k | txInteger c = mxArgc; |
1588 | 1.65k | txInteger i = -1; |
1589 | 1.65k | if (resultArray) { |
1590 | 1.61k | txSlot* list = fxNewInstance(the); |
1591 | 1.61k | txSlot* slot = list; |
1592 | 1.61k | txSlot* resultSlot; |
1593 | 1.61k | txIndex holeCount = 0; |
1594 | 1.61k | mxPushSlot(mxThis); |
1595 | 7.78k | for (;;) { |
1596 | 7.78k | txSlot* argument = the->stack; |
1597 | 7.78k | txBoolean flag = 0; |
1598 | 7.78k | if (mxIsReference(argument)) { |
1599 | 1.68k | mxPushSlot(argument); |
1600 | 1.68k | mxGetID(mxID(_Symbol_isConcatSpreadable)); |
1601 | 1.68k | if (mxIsUndefined(the->stack)) |
1602 | 1.65k | flag = fxIsArray(the, argument->value.reference); |
1603 | 28 | else |
1604 | 28 | flag = fxToBoolean(the, the->stack); |
1605 | 1.68k | mxPop(); |
1606 | 1.68k | } |
1607 | 7.78k | if (flag) { |
1608 | 1.65k | txIndex length, index; |
1609 | 1.65k | mxPushSlot(argument); |
1610 | 1.65k | mxGetID(mxID(_length)); |
1611 | 1.65k | length = (txIndex)fxToLength(the, the->stack); |
1612 | 1.65k | mxPop(); |
1613 | 1.65k | if (resultLength + length < resultLength) |
1614 | 3 | mxTypeError("array overflow"); |
1615 | 1.65k | index = 0; |
1616 | 2.21k | while (index < length) { |
1617 | 557 | mxPushSlot(argument); |
1618 | 557 | if (fxHasIndex(the, index)) { |
1619 | 217 | mxPushSlot(argument); |
1620 | 217 | mxGetIndex(index); |
1621 | 217 | slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG); |
1622 | 217 | mxMeterSome(2); |
1623 | 217 | mxPop(); |
1624 | 217 | } |
1625 | 340 | else { |
1626 | 340 | slot = slot->next = fxNewSlot(the); |
1627 | 340 | slot->kind = XS_UNINITIALIZED_KIND; |
1628 | 340 | holeCount++; |
1629 | 340 | } |
1630 | 557 | index++; |
1631 | 557 | resultLength++; |
1632 | 557 | } |
1633 | 1.65k | } |
1634 | 6.12k | else { |
1635 | 6.12k | slot = fxNextSlotProperty(the, slot, argument, XS_NO_ID, XS_NO_FLAG); |
1636 | 6.12k | mxMeterSome(4); |
1637 | 6.12k | resultLength++; |
1638 | 6.12k | if (resultLength == 0) |
1639 | 0 | mxTypeError("array overflow"); |
1640 | 6.12k | } |
1641 | 7.77k | mxPop(); |
1642 | 7.77k | i++; |
1643 | 7.77k | if (i == c) |
1644 | 1.60k | break; |
1645 | 6.16k | mxPushSlot(mxArgv(i)); |
1646 | 6.16k | } |
1647 | 1.61k | fxSetIndexSize(the, resultArray, resultLength - holeCount, XS_CHUNK); |
1648 | 1.61k | resultArray->value.array.length = resultLength; |
1649 | 1.61k | resultSlot = resultArray->value.array.address; |
1650 | 1.61k | slot = list->next; |
1651 | 1.61k | resultLength = 0; |
1652 | 8.28k | while (slot) { |
1653 | 6.67k | if (slot->kind != XS_UNINITIALIZED_KIND) { |
1654 | 6.33k | *((txIndex*)resultSlot) = resultLength; |
1655 | 6.33k | resultSlot->ID = XS_NO_ID; |
1656 | 6.33k | resultSlot->kind = slot->kind; |
1657 | 6.33k | resultSlot->value = slot->value; |
1658 | 6.33k | resultSlot++; |
1659 | 6.33k | } |
1660 | 6.67k | slot = slot->next; |
1661 | 6.67k | resultLength++; |
1662 | 6.67k | } |
1663 | 1.61k | mxMeterSome(3); |
1664 | 1.61k | mxPop(); |
1665 | 1.61k | } |
1666 | 40 | else { |
1667 | 40 | mxPushSlot(mxThis); |
1668 | 91 | for (;;) { |
1669 | 91 | txSlot* argument = the->stack; |
1670 | 91 | txBoolean flag = 0; |
1671 | 91 | if (mxIsReference(argument)) { |
1672 | 68 | mxPushSlot(argument); |
1673 | 68 | mxGetID(mxID(_Symbol_isConcatSpreadable)); |
1674 | 68 | if (mxIsUndefined(the->stack)) |
1675 | 57 | flag = fxIsArray(the, argument->value.reference); |
1676 | 11 | else |
1677 | 11 | flag = fxToBoolean(the, the->stack); |
1678 | 68 | mxPop(); |
1679 | 68 | } |
1680 | 91 | if (flag) { |
1681 | 34 | txIndex length, index; |
1682 | 34 | mxPushSlot(argument); |
1683 | 34 | mxGetID(mxID(_length)); |
1684 | 34 | length = (txIndex)fxToLength(the, the->stack); |
1685 | 34 | mxPop(); |
1686 | 34 | index = 0; |
1687 | 467 | while (index < length) { |
1688 | 433 | mxPushSlot(argument); |
1689 | 433 | if (fxHasIndex(the, index)) { |
1690 | 119 | mxPushSlot(argument); |
1691 | 119 | mxGetIndex(index); |
1692 | 119 | mxPushSlot(mxResult); |
1693 | 119 | mxDefineIndex(resultLength, 0, XS_GET_ONLY); |
1694 | 119 | mxPop(); |
1695 | 119 | } |
1696 | 433 | index++; |
1697 | 433 | resultLength++; |
1698 | 433 | } |
1699 | 34 | } |
1700 | 57 | else { |
1701 | 57 | mxPushSlot(argument); |
1702 | 57 | mxPushSlot(mxResult); |
1703 | 57 | mxDefineIndex(resultLength, 0, XS_GET_ONLY); |
1704 | 57 | mxPop(); |
1705 | 57 | resultLength++; |
1706 | 57 | } |
1707 | 91 | mxPop(); |
1708 | 91 | i++; |
1709 | 91 | if (i == c) |
1710 | 34 | break; |
1711 | 57 | mxPushSlot(mxArgv(i)); |
1712 | 57 | } |
1713 | 40 | mxPushInteger(resultLength); |
1714 | 40 | mxPushSlot(mxResult); |
1715 | 40 | mxSetID(mxID(_length)); |
1716 | 40 | mxPop(); |
1717 | 40 | } |
1718 | 1.65k | } |
1719 | | |
1720 | | void fx_Array_prototype_copyWithin(txMachine* the) |
1721 | 1.37M | { |
1722 | 1.37M | txNumber length = fxGetArrayLength(the, mxThis); |
1723 | 1.37M | txNumber to = fxArgToIndex(the, 0, 0, length); |
1724 | 1.37M | txNumber from = fxArgToIndex(the, 1, 0, length); |
1725 | 1.37M | txNumber final = fxArgToIndex(the, 2, length, length); |
1726 | 1.37M | txNumber count = (final > from) ? final - from : 0; |
1727 | 1.37M | txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE); |
1728 | 1.37M | if (count > length - to) |
1729 | 847k | count = length - to; |
1730 | 1.37M | if (array) { |
1731 | 565k | if (count > 0) { |
1732 | 278k | if (from < to) |
1733 | 178k | array = fxCheckArrayItems(the, array, (txIndex)from, (txIndex)(to + count)); |
1734 | 100k | else |
1735 | 100k | array = fxCheckArrayItems(the, array, (txIndex)to, (txIndex)(from + count)); |
1736 | 278k | } |
1737 | 565k | } |
1738 | 1.37M | if (array) { |
1739 | 565k | if (count > 0) { |
1740 | 278k | c_memmove(array->value.array.address + (txIndex)to, array->value.array.address + (txIndex)from, (txIndex)count * sizeof(txSlot)); |
1741 | 278k | fxIndexArray(the, array); |
1742 | 278k | mxMeterSome((txU4)count * 10); |
1743 | 278k | } |
1744 | 565k | } |
1745 | 805k | else { |
1746 | 805k | txNumber direction; |
1747 | 805k | if ((from < to) && (to < from + count)) { |
1748 | 22 | direction = -1; |
1749 | 22 | from += count - 1; |
1750 | 22 | to += count - 1; |
1751 | 22 | } |
1752 | 805k | else |
1753 | 805k | direction = 1; |
1754 | 1.42M | while (count > 0) { |
1755 | 624k | fxMoveThisItem(the, from, to); |
1756 | 624k | from += direction; |
1757 | 624k | to += direction; |
1758 | 624k | count--; |
1759 | 624k | mxCheckMetering(); |
1760 | 624k | } |
1761 | 805k | } |
1762 | 1.37M | mxResult->kind = mxThis->kind; |
1763 | 1.37M | mxResult->value = mxThis->value; |
1764 | 1.37M | } |
1765 | | |
1766 | | void fx_Array_prototype_entries(txMachine* the) |
1767 | 39 | { |
1768 | 39 | txSlot* property; |
1769 | 39 | fxToInstance(the, mxThis); |
1770 | 39 | mxPush(mxArrayIteratorPrototype); |
1771 | 39 | property = fxLastProperty(the, fxNewIteratorInstance(the, mxThis, mxID(_Array))); |
1772 | 39 | property = fxNextIntegerProperty(the, property, 2, XS_NO_ID, XS_INTERNAL_FLAG); |
1773 | 39 | mxPullSlot(mxResult); |
1774 | 39 | } |
1775 | | |
1776 | | void fx_Array_prototype_every(txMachine* the) |
1777 | 96.9k | { |
1778 | 96.9k | txIndex length = fxGetArrayLimit(the, mxThis); |
1779 | 96.9k | txIndex index = 0; |
1780 | 96.9k | txSlot* function = fxArgToCallback(the, 0); |
1781 | 96.9k | mxResult->kind = XS_BOOLEAN_KIND; |
1782 | 96.9k | mxResult->value.boolean = 1; |
1783 | 2.06M | while (index < length) { |
1784 | 1.96M | if (fxCallThisItem(the, function, index, C_NULL)) { |
1785 | 96.9k | mxResult->value.boolean = fxToBoolean(the, the->stack); |
1786 | 96.9k | mxPop(); |
1787 | 96.9k | if (!mxResult->value.boolean) |
1788 | 10 | break; |
1789 | 96.9k | } |
1790 | 1.96M | index++; |
1791 | 1.96M | mxCheckMetering(); |
1792 | 1.96M | } |
1793 | 96.9k | } |
1794 | | |
1795 | | void fx_Array_prototype_fill(txMachine* the) |
1796 | 916k | { |
1797 | 916k | txSlot* value; |
1798 | 916k | txSlot* array; |
1799 | 916k | if (mxArgc > 0) |
1800 | 915k | mxPushSlot(mxArgv(0)); |
1801 | 200 | else |
1802 | 200 | mxPushUndefined(); |
1803 | 916k | value = the->stack; |
1804 | 916k | array = fxCheckArray(the, mxThis, XS_MUTABLE); |
1805 | 916k | if (array) |
1806 | 403k | array = fxCheckArrayItems(the, array, 0, array->value.array.length); |
1807 | 916k | if (array) { |
1808 | 403k | txIndex length = array->value.array.length; |
1809 | 403k | txIndex start = (txIndex)fxArgToIndex(the, 1, 0, length); |
1810 | 403k | txIndex end = (txIndex)fxArgToIndex(the, 2, length, length); |
1811 | 403k | txSlot* address; |
1812 | 403k | txIndex size; |
1813 | 403k | if ((start == 0) && (end == length)) { |
1814 | 394k | fxSetIndexSize(the, array, length, XS_CHUNK); |
1815 | 394k | fxIndexArray(the, array); |
1816 | 394k | } |
1817 | 403k | address = array->value.array.address; |
1818 | 403k | size = (address) ? (((txChunk*)(((txByte*)address) - sizeof(txChunk)))->size) / sizeof(txSlot) : 0; |
1819 | 403k | if (length == size) { |
1820 | 1.01M | while (start < end) { |
1821 | 607k | txSlot* slot = array->value.array.address + start; |
1822 | 607k | if (slot->flag) { |
1823 | 0 | mxPushSlot(value); |
1824 | 0 | mxPushSlot(mxThis); |
1825 | 0 | mxSetIndex(start); |
1826 | 0 | mxPop(); |
1827 | 0 | mxMeterSome(1); |
1828 | 0 | } |
1829 | 607k | else { |
1830 | 607k | slot->ID = XS_NO_ID; |
1831 | 607k | slot->kind = value->kind; |
1832 | 607k | slot->value = value->value; |
1833 | 607k | mxMeterSome(5); |
1834 | 607k | } |
1835 | 607k | start++; |
1836 | 607k | mxCheckMetering(); |
1837 | 607k | } |
1838 | | |
1839 | 403k | } |
1840 | 0 | else { |
1841 | 0 | while (start < end) { |
1842 | 0 | mxPushSlot(value); |
1843 | 0 | mxPushSlot(mxThis); |
1844 | 0 | mxSetIndex(start); |
1845 | 0 | mxPop(); |
1846 | 0 | mxMeterSome(1); |
1847 | 0 | start++; |
1848 | 0 | mxCheckMetering(); |
1849 | 0 | } |
1850 | 0 | } |
1851 | 403k | } |
1852 | 512k | else { |
1853 | 512k | txNumber length = fxGetArrayLength(the, mxThis); |
1854 | 512k | txNumber start = fxArgToIndex(the, 1, 0, length); |
1855 | 512k | txNumber end = fxArgToIndex(the, 2, length, length); |
1856 | 512k | txSlot* value = the->stack; |
1857 | 1.48M | while (start < end) { |
1858 | 967k | mxPushSlot(value); |
1859 | 967k | mxPushSlot(mxThis); |
1860 | 967k | mxPushNumber(start); |
1861 | 967k | mxSetAt(); |
1862 | 967k | mxPop(); |
1863 | 967k | start++; |
1864 | 967k | mxCheckMetering(); |
1865 | 967k | } |
1866 | 512k | } |
1867 | 916k | mxPop(); |
1868 | 916k | mxResult->kind = mxThis->kind; |
1869 | 916k | mxResult->value = mxThis->value; |
1870 | 916k | } |
1871 | | |
1872 | | void fx_Array_prototype_filter(txMachine* the) |
1873 | 107k | { |
1874 | 107k | txIndex length = fxGetArrayLimit(the, mxThis); |
1875 | 107k | txIndex index = 0; |
1876 | 107k | txSlot* function = fxArgToCallback(the, 0); |
1877 | 107k | txSlot* resultArray = fxCreateArraySpecies(the, 0); |
1878 | 107k | txIndex resultLength = 0; |
1879 | 107k | txSlot* item; |
1880 | 107k | mxPushUndefined(); |
1881 | 107k | item = the->stack; |
1882 | 107k | if (resultArray) { |
1883 | 24 | txSlot* list = fxNewInstance(the); |
1884 | 24 | txSlot* slot = list; |
1885 | 24 | txSlot* resultSlot; |
1886 | 1.00M | while (index < length) { |
1887 | 1.00M | if (fxCallThisItem(the, function, index, item)) { |
1888 | 125 | if (fxToBoolean(the, the->stack)) { |
1889 | 67 | slot = fxNextSlotProperty(the, slot, item, XS_NO_ID, XS_NO_FLAG); |
1890 | 67 | mxMeterSome(4); |
1891 | 67 | resultLength++; |
1892 | 67 | } |
1893 | 125 | mxPop(); |
1894 | 125 | } |
1895 | 1.00M | index++; |
1896 | 1.00M | mxCheckMetering(); |
1897 | 1.00M | } |
1898 | 24 | fxSetIndexSize(the, resultArray, resultLength, XS_CHUNK); |
1899 | 24 | resultSlot = resultArray->value.array.address; |
1900 | 24 | slot = list->next; |
1901 | 24 | index = 0; |
1902 | 91 | while (slot) { |
1903 | 67 | *((txIndex*)resultSlot) = index; |
1904 | 67 | resultSlot->ID = XS_NO_ID; |
1905 | 67 | resultSlot->kind = slot->kind; |
1906 | 67 | resultSlot->value = slot->value; |
1907 | 67 | resultSlot++; |
1908 | 67 | slot = slot->next; |
1909 | 67 | index++; |
1910 | 67 | } |
1911 | 24 | mxPop(); |
1912 | 24 | mxMeterSome(-1); |
1913 | 24 | } |
1914 | 107k | else { |
1915 | 251k | while (index < length) { |
1916 | 144k | if (fxCallThisItem(the, function, index, item)) { |
1917 | 143k | if (fxToBoolean(the, the->stack)) { |
1918 | 94 | mxPushSlot(item); |
1919 | 94 | mxPushSlot(mxResult); |
1920 | 94 | mxDefineIndex(resultLength, 0, XS_GET_ONLY); |
1921 | 94 | mxPop(); |
1922 | 94 | resultLength++; |
1923 | 94 | } |
1924 | 143k | mxPop(); |
1925 | 143k | } |
1926 | 144k | index++; |
1927 | 144k | mxCheckMetering(); |
1928 | 144k | } |
1929 | 107k | } |
1930 | 107k | mxPop(); |
1931 | 107k | } |
1932 | | |
1933 | | void fx_Array_prototype_find(txMachine* the) |
1934 | 45 | { |
1935 | 45 | txIndex length = fxGetArrayLimit(the, mxThis); |
1936 | 45 | txIndex index = 0; |
1937 | 45 | txSlot* function = fxArgToCallback(the, 0); |
1938 | 45 | txSlot* item; |
1939 | 45 | mxPushUndefined(); |
1940 | 45 | item = the->stack; |
1941 | 87 | while (index < length) { |
1942 | 55 | fxFindThisItem(the, function, index, item); |
1943 | 55 | if (fxToBoolean(the, the->stack++)) { |
1944 | 13 | mxResult->kind = item->kind; |
1945 | 13 | mxResult->value = item->value; |
1946 | 13 | break; |
1947 | 13 | } |
1948 | 42 | index++; |
1949 | 42 | } |
1950 | 45 | mxPop(); |
1951 | 45 | } |
1952 | | |
1953 | | void fx_Array_prototype_findIndex(txMachine* the) |
1954 | 112 | { |
1955 | 112 | txIndex length = fxGetArrayLimit(the, mxThis); |
1956 | 112 | txIndex index = 0; |
1957 | 112 | txSlot* function = fxArgToCallback(the, 0); |
1958 | 112 | fxInteger(the, mxResult, -1); |
1959 | 172 | while (index < length) { |
1960 | 89 | fxFindThisItem(the, function, index, C_NULL); |
1961 | 89 | if (fxToBoolean(the, the->stack++)) { |
1962 | 29 | fxUnsigned(the, mxResult, index); |
1963 | 29 | break; |
1964 | 29 | } |
1965 | 60 | index++; |
1966 | 60 | } |
1967 | 112 | } |
1968 | | |
1969 | | void fx_Array_prototype_findLast(txMachine* the) |
1970 | 77 | { |
1971 | 77 | txNumber index = fxGetArrayLength(the, mxThis); |
1972 | 77 | txSlot* function = fxArgToCallback(the, 0); |
1973 | 77 | txSlot* item; |
1974 | 77 | mxPushUndefined(); |
1975 | 77 | item = the->stack; |
1976 | 156 | while (index > 0) { |
1977 | 101 | index--; |
1978 | 101 | fxFindThisItem(the, function, index, item); |
1979 | 101 | if (fxToBoolean(the, the->stack++)) { |
1980 | 22 | mxResult->kind = item->kind; |
1981 | 22 | mxResult->value = item->value; |
1982 | 22 | break; |
1983 | 22 | } |
1984 | 101 | } |
1985 | 77 | mxPop(); |
1986 | 77 | } |
1987 | | |
1988 | | void fx_Array_prototype_findLastIndex(txMachine* the) |
1989 | 40 | { |
1990 | 40 | txNumber index = fxGetArrayLength(the, mxThis); |
1991 | 40 | txSlot* function = fxArgToCallback(the, 0); |
1992 | 40 | fxInteger(the, mxResult, -1); |
1993 | 57.1k | while (index > 0) { |
1994 | 57.1k | index--; |
1995 | 57.1k | fxFindThisItem(the, function, index, C_NULL); |
1996 | 57.1k | if (fxToBoolean(the, the->stack++)) { |
1997 | 11 | fxUnsigned(the, mxResult, (txUnsigned)index); |
1998 | 11 | break; |
1999 | 11 | } |
2000 | 57.1k | } |
2001 | 40 | } |
2002 | | |
2003 | | void fx_Array_prototype_flat(txMachine* the) |
2004 | 40 | { |
2005 | 40 | txIndex length, depth = 1; |
2006 | 40 | mxPushSlot(mxThis); |
2007 | 40 | mxGetID(mxID(_length)); |
2008 | 40 | length = (txIndex)fxToLength(the, the->stack); |
2009 | 40 | mxPop(); |
2010 | 40 | if ((mxArgc > 0) && !mxIsUndefined(mxArgv(0))) |
2011 | 16 | depth = (txIndex)fxToLength(the, mxArgv(0)); |
2012 | 40 | fxCreateArraySpecies(the, 0); |
2013 | 40 | fx_Array_prototype_flatAux(the, mxThis, length, 0, depth, C_NULL); |
2014 | 40 | } |
2015 | | |
2016 | | txIndex fx_Array_prototype_flatAux(txMachine* the, txSlot* source, txIndex length, txIndex start, txIndex depth, txSlot* function) |
2017 | 88 | { |
2018 | 88 | txSlot* item; |
2019 | 88 | txIndex index = 0; |
2020 | 358 | while (index < length) { |
2021 | 270 | mxPushSlot(source); |
2022 | 270 | if (fxHasIndex(the, index)) { |
2023 | 185 | if (function) { |
2024 | | /* THIS */ |
2025 | 28 | if (mxArgc > 1) |
2026 | 3 | mxPushSlot(mxArgv(1)); |
2027 | 25 | else |
2028 | 25 | mxPushUndefined(); |
2029 | | /* FUNCTION */ |
2030 | 28 | mxPushSlot(function); |
2031 | 28 | mxCall(); |
2032 | | /* ARGUMENTS */ |
2033 | 28 | mxPushSlot(source); |
2034 | 28 | mxGetIndex(index); |
2035 | 28 | mxPushUnsigned(index); |
2036 | 28 | mxPushSlot(mxThis); |
2037 | 28 | mxRunCount(3); |
2038 | 28 | } |
2039 | 157 | else { |
2040 | 157 | mxPushSlot(source); |
2041 | 157 | mxGetIndex(index); |
2042 | 157 | } |
2043 | 185 | item = the->stack; |
2044 | 185 | if ((depth > 0) && mxIsReference(item) && fxIsArray(the, fxToInstance(the, item))) { |
2045 | 55 | txIndex itemLength; |
2046 | 55 | mxPushSlot(item); |
2047 | 55 | mxGetID(mxID(_length)); |
2048 | 55 | itemLength = (txIndex)fxToLength(the, the->stack); |
2049 | 55 | mxPop(); |
2050 | 55 | start = fx_Array_prototype_flatAux(the, item, itemLength, start, depth - 1, C_NULL); |
2051 | 55 | } |
2052 | 130 | else { |
2053 | 130 | mxPushSlot(mxResult); |
2054 | 130 | mxDefineIndex(start, 0, XS_GET_ONLY); |
2055 | 130 | mxPop(); |
2056 | 130 | start++; |
2057 | 130 | } |
2058 | 185 | } |
2059 | 270 | index++; |
2060 | 270 | } |
2061 | 88 | return start; |
2062 | 88 | } |
2063 | | |
2064 | | void fx_Array_prototype_flatMap(txMachine* the) |
2065 | 34 | { |
2066 | 34 | txIndex length = (txIndex)fxGetArrayLength(the, mxThis); |
2067 | 34 | txSlot* function = fxArgToCallback(the, 0); |
2068 | 34 | fxCreateArraySpecies(the, 0); |
2069 | 34 | fx_Array_prototype_flatAux(the, mxThis, length, 0, 1, function); |
2070 | 34 | } |
2071 | | |
2072 | | void fx_Array_prototype_forEach(txMachine* the) |
2073 | 1.33k | { |
2074 | 1.33k | txIndex length = fxGetArrayLimit(the, mxThis); |
2075 | 1.33k | txIndex index = 0; |
2076 | 1.33k | txSlot* function = fxArgToCallback(the, 0); |
2077 | 1.14M | while (index < length) { |
2078 | 1.14M | if (fxCallThisItem(the, function, index, C_NULL)) |
2079 | 141k | mxPop(); |
2080 | 1.14M | index++; |
2081 | 1.14M | mxCheckMetering(); |
2082 | 1.14M | } |
2083 | 1.33k | } |
2084 | | |
2085 | | void fx_Array_prototype_includes(txMachine* the) |
2086 | 29.1k | { |
2087 | 29.1k | txSlot* array = fxCheckArray(the, mxThis, XS_IMMUTABLE); |
2088 | 29.1k | txSlot* argument; |
2089 | 29.1k | if (mxArgc > 0) |
2090 | 29.1k | mxPushSlot(mxArgv(0)); |
2091 | 14 | else |
2092 | 14 | mxPushUndefined(); |
2093 | 29.1k | argument = the->stack; |
2094 | 29.1k | fxBoolean(the, mxResult, 0); |
2095 | 29.1k | if (array) { |
2096 | 10.1k | txIndex length = array->value.array.length; |
2097 | 10.1k | if (length) { |
2098 | 10.1k | txIndex index = (txIndex)fxArgToIndex(the, 1, 0, length); |
2099 | 30.4k | while (index < length) { |
2100 | 23.7k | mxPushSlot(mxThis); |
2101 | 23.7k | mxGetIndex(index); |
2102 | 23.7k | if (fxIsSameValue(the, the->stack++, argument, 1)) { |
2103 | 3.33k | mxResult->value.boolean = 1; |
2104 | 3.33k | break; |
2105 | 3.33k | } |
2106 | 20.3k | index++; |
2107 | 20.3k | mxCheckMetering(); |
2108 | 20.3k | } |
2109 | 10.1k | } |
2110 | 10.1k | } |
2111 | 19.0k | else { |
2112 | 19.0k | txNumber length = fxGetArrayLength(the, mxThis); |
2113 | 19.0k | if (length) { |
2114 | 19.0k | txNumber index = fxArgToIndex(the, 1, 0, length); |
2115 | 69.8k | while (index < length) { |
2116 | 57.2k | mxPushSlot(mxThis); |
2117 | 57.2k | mxPushNumber(index); |
2118 | 57.2k | mxGetAt(); |
2119 | 57.2k | if (fxIsSameValue(the, the->stack++, argument, 1)) { |
2120 | 6.40k | mxResult->value.boolean = 1; |
2121 | 6.40k | break; |
2122 | 6.40k | } |
2123 | 50.8k | index++; |
2124 | 50.8k | mxCheckMetering(); |
2125 | 50.8k | } |
2126 | 19.0k | } |
2127 | 19.0k | } |
2128 | 29.1k | mxPop(); |
2129 | 29.1k | } |
2130 | | |
2131 | | void fx_Array_prototype_indexOf(txMachine* the) |
2132 | 40.5k | { |
2133 | 40.5k | txSlot* array = fxCheckArray(the, mxThis, XS_IMMUTABLE); |
2134 | 40.5k | txSlot* argument; |
2135 | 40.5k | if (mxArgc > 0) |
2136 | 38.7k | mxPushSlot(mxArgv(0)); |
2137 | 1.71k | else |
2138 | 1.71k | mxPushUndefined(); |
2139 | 40.5k | argument = the->stack; |
2140 | 40.5k | fxInteger(the, mxResult, -1); |
2141 | 40.5k | if (array) { |
2142 | 33.3k | txIndex length = array->value.array.length; |
2143 | 33.3k | if (length) { |
2144 | 33.3k | txIndex index = (txIndex)fxArgToIndex(the, 1, 0, length); |
2145 | 424k | while (index < length) { |
2146 | 397k | mxPushSlot(mxThis); |
2147 | 397k | if (fxHasIndex(the, index)) { |
2148 | 397k | mxPushSlot(mxThis); |
2149 | 397k | mxGetIndex(index); |
2150 | 397k | if (fxIsSameSlot(the, the->stack++, argument)) { |
2151 | 5.96k | fxUnsigned(the, mxResult, index); |
2152 | 5.96k | break; |
2153 | 5.96k | } |
2154 | 397k | } |
2155 | 391k | index++; |
2156 | 391k | mxCheckMetering(); |
2157 | 391k | } |
2158 | 33.3k | } |
2159 | 33.3k | } |
2160 | 7.15k | else { |
2161 | 7.15k | txNumber length = fxGetArrayLength(the, mxThis); |
2162 | 7.15k | if (length) { |
2163 | 7.13k | txNumber index = fxArgToIndex(the, 1, 0, length); |
2164 | 2.98M | while (index < length) { |
2165 | 2.97M | mxPushSlot(mxThis); |
2166 | 2.97M | mxPushNumber(index); |
2167 | 2.97M | if (mxHasAt()) { |
2168 | 4.71k | mxPushSlot(mxThis); |
2169 | 4.71k | mxPushNumber(index); |
2170 | 4.71k | mxGetAt(); |
2171 | 4.71k | if (fxIsSameSlot(the, the->stack++, argument)) { |
2172 | 1.47k | fxNumber(the, mxResult, index); |
2173 | 1.47k | break; |
2174 | 1.47k | } |
2175 | 4.71k | } |
2176 | 2.97M | index++; |
2177 | 2.97M | mxCheckMetering(); |
2178 | 2.97M | } |
2179 | 7.13k | } |
2180 | 7.15k | } |
2181 | 40.5k | mxPop(); |
2182 | 40.5k | } |
2183 | | |
2184 | | void fx_Array_prototype_join(txMachine* the) |
2185 | 5.60M | { |
2186 | 5.60M | txIndex length = fxGetArrayLimit(the, mxThis); |
2187 | 5.60M | txIndex index = 0; |
2188 | 5.60M | txString string; |
2189 | 5.60M | txSlot* list = fxNewInstance(the); |
2190 | 5.60M | txSlot* slot = list; |
2191 | 5.60M | txBoolean comma = 0; |
2192 | 5.60M | txInteger size = 0; |
2193 | 5.60M | if ((mxArgc > 0) && (mxArgv(0)->kind != XS_UNDEFINED_KIND)) { |
2194 | 24 | mxPushSlot(mxArgv(0)); |
2195 | 24 | string = fxToString(the, the->stack); |
2196 | 24 | the->stack->kind += XS_KEY_KIND - XS_STRING_KIND; |
2197 | 24 | the->stack->value.key.sum = mxStringLength(string); |
2198 | 24 | } |
2199 | 5.60M | else { |
2200 | 5.60M | mxPushStringX(","); |
2201 | 5.60M | the->stack->kind += XS_KEY_KIND - XS_STRING_KIND; |
2202 | 5.60M | the->stack->value.key.sum = 1; |
2203 | 5.60M | } |
2204 | 26.1M | while (index < length) { |
2205 | 20.5M | if (comma) { |
2206 | 15.5M | slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG); |
2207 | 15.5M | size = fxAddChunkSizes(the, size, slot->value.key.sum); |
2208 | 15.5M | } |
2209 | 5.02M | else |
2210 | 5.02M | comma = 1; |
2211 | 20.5M | mxPushSlot(mxThis); |
2212 | 20.5M | mxGetIndex(index); |
2213 | 20.5M | if ((the->stack->kind != XS_UNDEFINED_KIND) && (the->stack->kind != XS_NULL_KIND)) { |
2214 | 11.5M | slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG); |
2215 | 11.5M | string = fxToString(the, slot); |
2216 | 11.5M | slot->kind += XS_KEY_KIND - XS_STRING_KIND; |
2217 | 11.5M | slot->value.key.sum = mxStringLength(string); |
2218 | 11.5M | size = fxAddChunkSizes(the, size, slot->value.key.sum); |
2219 | 11.5M | } |
2220 | 20.5M | mxPop(); |
2221 | 20.5M | index++; |
2222 | | |
2223 | 20.5M | mxCheckMetering(); |
2224 | 20.5M | } |
2225 | 5.60M | mxPop(); |
2226 | 5.60M | string = mxResult->value.string = fxNewChunk(the, fxAddChunkSizes(the, size, 1)); |
2227 | 5.60M | slot = list->next; |
2228 | 30.0M | while (slot) { |
2229 | 24.4M | c_memcpy(string, slot->value.key.string, slot->value.key.sum); |
2230 | 24.4M | string += slot->value.key.sum; |
2231 | 24.4M | slot = slot->next; |
2232 | 24.4M | } |
2233 | 5.60M | *string = 0; |
2234 | 5.60M | mxResult->kind = XS_STRING_KIND; |
2235 | 5.60M | mxPop(); |
2236 | 5.60M | } |
2237 | | |
2238 | | void fx_Array_prototype_keys(txMachine* the) |
2239 | 10 | { |
2240 | 10 | txSlot* property; |
2241 | 10 | fxToInstance(the, mxThis); |
2242 | 10 | mxPush(mxArrayIteratorPrototype); |
2243 | 10 | property = fxLastProperty(the, fxNewIteratorInstance(the, mxThis, mxID(_Array))); |
2244 | 10 | property = fxNextIntegerProperty(the, property, 1, XS_NO_ID, XS_INTERNAL_FLAG); |
2245 | 10 | mxPullSlot(mxResult); |
2246 | 10 | } |
2247 | | |
2248 | | void fx_Array_prototype_lastIndexOf(txMachine* the) |
2249 | 222k | { |
2250 | 222k | txSlot* array = fxCheckArray(the, mxThis, XS_IMMUTABLE); |
2251 | 222k | txSlot* argument; |
2252 | 222k | if (mxArgc > 0) |
2253 | 188k | mxPushSlot(mxArgv(0)); |
2254 | 34.1k | else |
2255 | 34.1k | mxPushUndefined(); |
2256 | 222k | argument = the->stack; |
2257 | 222k | fxInteger(the, mxResult, -1); |
2258 | 222k | if (array) { |
2259 | 182k | txIndex length = array->value.array.length; |
2260 | 182k | if (length) { |
2261 | 181k | txIndex index = (txIndex)fxArgToLastIndex(the, 1, length, length); |
2262 | 735k | while (index > 0) { |
2263 | 671k | index--; |
2264 | 671k | mxPushSlot(mxThis); |
2265 | 671k | if (fxHasIndex(the, index)) { |
2266 | 671k | mxPushSlot(mxThis); |
2267 | 671k | mxGetIndex(index); |
2268 | 671k | if (fxIsSameSlot(the, the->stack++, argument)) { |
2269 | 117k | fxUnsigned(the, mxResult, index); |
2270 | 117k | break; |
2271 | 117k | } |
2272 | 671k | } |
2273 | 553k | mxCheckMetering(); |
2274 | 553k | } |
2275 | 181k | } |
2276 | 182k | } |
2277 | 39.7k | else { |
2278 | 39.7k | txNumber length = fxGetArrayLength(the, mxThis); |
2279 | 39.7k | if (length) { |
2280 | 39.7k | txNumber index = fxArgToLastIndex(the, 1, length, length); |
2281 | 1.87M | while (index > 0) { |
2282 | 1.83M | index--; |
2283 | 1.83M | mxPushSlot(mxThis); |
2284 | 1.83M | mxPushNumber(index); |
2285 | 1.83M | if (mxHasAt()) { |
2286 | 82.0k | mxPushSlot(mxThis); |
2287 | 82.0k | mxPushNumber(index); |
2288 | 82.0k | mxGetAt(); |
2289 | 82.0k | if (fxIsSameSlot(the, the->stack++, argument)) { |
2290 | 984 | fxNumber(the, mxResult, index); |
2291 | 984 | break; |
2292 | 984 | } |
2293 | 82.0k | } |
2294 | 1.83M | mxCheckMetering(); |
2295 | 1.83M | } |
2296 | 39.7k | } |
2297 | 39.7k | } |
2298 | 222k | mxPop(); |
2299 | 222k | } |
2300 | | |
2301 | | void fx_Array_prototype_map(txMachine* the) |
2302 | 107k | { |
2303 | 107k | txNumber LENGTH = fxGetArrayLength(the, mxThis); |
2304 | 107k | txSlot* function = fxArgToCallback(the, 0); |
2305 | 107k | txSlot* resultArray = fxCreateArraySpecies(the, LENGTH); |
2306 | 107k | txIndex length = (txIndex)LENGTH; |
2307 | 107k | txIndex index = 0; |
2308 | 107k | if (resultArray) { |
2309 | 32.1k | txIndex resultLength = 0; |
2310 | 32.1k | fxSetIndexSize(the, resultArray, length, XS_CHUNK); |
2311 | 2.09M | while (index < length) { |
2312 | 2.06M | if (fxCallThisItem(the, function, index, C_NULL)) { |
2313 | 199 | txSlot* slot = resultArray->value.array.address + resultLength; |
2314 | 199 | *((txIndex*)slot) = index; |
2315 | 199 | slot->ID = XS_NO_ID; |
2316 | 199 | slot->kind = the->stack->kind; |
2317 | 199 | slot->value = the->stack->value; |
2318 | 199 | resultLength++; |
2319 | 199 | mxMeterSome(2); |
2320 | 199 | mxPop(); |
2321 | 199 | } |
2322 | 2.06M | index++; |
2323 | 2.06M | mxCheckMetering(); |
2324 | 2.06M | } |
2325 | 32.1k | if (resultLength < length) { |
2326 | 10 | fxSetIndexSize(the, resultArray, resultLength, XS_CHUNK); |
2327 | 10 | resultArray->value.array.length = length; |
2328 | 10 | } |
2329 | 32.1k | } |
2330 | 75.4k | else { |
2331 | 75.5k | while (index < length) { |
2332 | 170 | if (fxCallThisItem(the, function, index, C_NULL)) { |
2333 | 25 | mxPushSlot(mxResult); |
2334 | 25 | mxDefineIndex(index, 0, XS_GET_ONLY); |
2335 | 25 | mxPop(); |
2336 | 25 | } |
2337 | 170 | index++; |
2338 | 170 | mxCheckMetering(); |
2339 | 170 | } |
2340 | 75.4k | } |
2341 | 107k | } |
2342 | | |
2343 | | void fx_Array_prototype_pop(txMachine* the) |
2344 | 1.22k | { |
2345 | 1.22k | txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE); |
2346 | 1.22k | if (array) { |
2347 | 1.12k | txIndex length = array->value.array.length; |
2348 | 1.12k | if (length > 0) |
2349 | 200 | array = fxCheckArrayItems(the, array, length - 1, length); |
2350 | 1.12k | } |
2351 | 1.22k | if (array) { |
2352 | 1.12k | txIndex length = array->value.array.length; |
2353 | 1.12k | txSlot* address; |
2354 | 1.12k | mxMeterSome(2); |
2355 | 1.12k | if (length > 0) { |
2356 | 200 | length--; |
2357 | 200 | address = array->value.array.address + length; |
2358 | 200 | mxResult->kind = address->kind; |
2359 | 200 | mxResult->value = address->value; |
2360 | 200 | fxSetIndexSize(the, array, length, XS_CHUNK); |
2361 | 200 | mxMeterSome(8); |
2362 | 200 | } |
2363 | 1.12k | mxMeterSome(4); |
2364 | 1.12k | } |
2365 | 97 | else { |
2366 | 97 | txNumber length = fxGetArrayLength(the, mxThis); |
2367 | 97 | if (length > 0) { |
2368 | 80 | length--; |
2369 | 80 | mxPushSlot(mxThis); |
2370 | 80 | mxPushNumber(length); |
2371 | 80 | mxGetAt(); |
2372 | 80 | mxPullSlot(mxResult); |
2373 | 80 | mxPushSlot(mxThis); |
2374 | 80 | mxPushNumber(length); |
2375 | 80 | mxDeleteAt(); |
2376 | 80 | mxPop(); |
2377 | 80 | } |
2378 | 97 | mxPushNumber(length); |
2379 | 97 | mxPushSlot(mxThis); |
2380 | 97 | mxSetID(mxID(_length)); |
2381 | 97 | mxPop(); |
2382 | 97 | } |
2383 | 1.22k | } |
2384 | | |
2385 | | void fx_Array_prototype_push(txMachine* the) |
2386 | 395k | { |
2387 | 395k | txIndex c = mxArgc, i = 0; |
2388 | 395k | txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE); |
2389 | 395k | if (array) { |
2390 | 392k | txIndex length = array->value.array.length; |
2391 | 392k | txSlot* address; |
2392 | 392k | mxMeterSome(2); |
2393 | 392k | if (length + c < length) |
2394 | 0 | mxRangeError("array overflow"); |
2395 | 392k | fxSetIndexSize(the, array, length + c, XS_GROWABLE_CHUNK); |
2396 | 392k | address = array->value.array.address + length; |
2397 | 785k | while (i < c) { |
2398 | 393k | txSlot* argument = mxArgv(i); |
2399 | 393k | *((txIndex*)address) = length + i; |
2400 | 393k | address->ID = XS_NO_ID; |
2401 | 393k | address->kind = argument->kind; |
2402 | 393k | address->value = argument->value; |
2403 | 393k | address++; |
2404 | 393k | mxMeterSome(5); |
2405 | 393k | i++; |
2406 | 393k | } |
2407 | 392k | mxPushUnsigned(length + c); |
2408 | 392k | mxMeterSome(2); |
2409 | 392k | } |
2410 | 3.74k | else { |
2411 | 3.74k | txNumber length = fxGetArrayLength(the, mxThis); |
2412 | 3.74k | if (length + c > C_MAX_SAFE_INTEGER) |
2413 | 7 | mxTypeError("unsafe integer"); |
2414 | 7.45k | while (i < c) { |
2415 | 3.72k | mxPushSlot(mxArgv(i)); |
2416 | 3.72k | mxPushSlot(mxThis); |
2417 | 3.72k | mxPushNumber(length + i); |
2418 | 3.72k | mxSetAt(); |
2419 | 3.72k | mxPop(); |
2420 | 3.72k | i++; |
2421 | 3.72k | } |
2422 | 3.73k | mxPushNumber(length + c); |
2423 | 3.73k | mxPushSlot(mxThis); |
2424 | 3.73k | mxSetID(mxID(_length)); |
2425 | 3.73k | } |
2426 | 395k | mxPullSlot(mxResult); |
2427 | 395k | } |
2428 | | |
2429 | | void fx_Array_prototype_reduce(txMachine* the) |
2430 | 43 | { |
2431 | 43 | txIndex length = fxGetArrayLimit(the, mxThis); |
2432 | 43 | txIndex index = 0; |
2433 | 43 | txSlot* function = fxArgToCallback(the, 0); |
2434 | 43 | if (mxArgc > 1) |
2435 | 22 | *mxResult = *mxArgv(1); |
2436 | 21 | else { |
2437 | 21 | txBoolean flag = 0; |
2438 | 147 | while (!flag && (index < length)) { |
2439 | 126 | mxPushSlot(mxThis); |
2440 | 126 | if (fxHasIndex(the, index)) { |
2441 | 12 | mxPushSlot(mxThis); |
2442 | 12 | mxGetIndex(index); |
2443 | 12 | mxPullSlot(mxResult); |
2444 | 12 | flag = 1; |
2445 | 12 | } |
2446 | 126 | index++; |
2447 | 126 | } |
2448 | 21 | if (!flag) |
2449 | 8 | mxTypeError("no initial value"); |
2450 | 21 | } |
2451 | 37.2k | while (index < length) { |
2452 | 37.2k | fxReduceThisItem(the, function, index); |
2453 | 37.2k | index++; |
2454 | 37.2k | } |
2455 | 35 | } |
2456 | | |
2457 | | void fx_Array_prototype_reduceRight(txMachine* the) |
2458 | 26 | { |
2459 | 26 | txIndex length = fxGetArrayLimit(the, mxThis); |
2460 | 26 | txIndex index = length; |
2461 | 26 | txSlot* function = fxArgToCallback(the, 0); |
2462 | 26 | if (mxArgc > 1) |
2463 | 13 | *mxResult = *mxArgv(1); |
2464 | 13 | else { |
2465 | 13 | txBoolean flag = 0; |
2466 | 108 | while (!flag && (index > 0)) { |
2467 | 95 | index--; |
2468 | 95 | mxPushSlot(mxThis); |
2469 | 95 | if (fxHasIndex(the, index)) { |
2470 | 7 | mxPushSlot(mxThis); |
2471 | 7 | mxGetIndex(index); |
2472 | 7 | mxPullSlot(mxResult); |
2473 | 7 | flag = 1; |
2474 | 7 | } |
2475 | 95 | } |
2476 | 13 | if (!flag) |
2477 | 5 | mxTypeError("no initial value"); |
2478 | 13 | } |
2479 | 140 | while (index > 0) { |
2480 | 119 | index--; |
2481 | 119 | fxReduceThisItem(the, function, index); |
2482 | 119 | } |
2483 | 21 | } |
2484 | | |
2485 | | void fx_Array_prototype_reverse(txMachine* the) |
2486 | 55 | { |
2487 | 55 | txSlot* lowerSlot; |
2488 | 55 | txSlot* upperSlot; |
2489 | 55 | txNumber length = fxGetArrayLength(the, mxThis); |
2490 | 55 | txNumber middle = c_trunc(length / 2); |
2491 | 55 | txNumber lower = 0; |
2492 | 545k | while (lower != middle) { |
2493 | 545k | txNumber upper = length - lower - 1; |
2494 | 545k | mxPushSlot(mxThis); |
2495 | 545k | mxPushNumber(lower); |
2496 | 545k | if (mxHasAt()) { |
2497 | 54 | mxPushSlot(mxThis); |
2498 | 54 | mxPushNumber(lower); |
2499 | 54 | mxGetAt(); |
2500 | 54 | lowerSlot = the->stack; |
2501 | 54 | } |
2502 | 545k | else |
2503 | 545k | lowerSlot = C_NULL; |
2504 | 545k | mxPushSlot(mxThis); |
2505 | 545k | mxPushNumber(upper); |
2506 | 545k | if (mxHasAt()) { |
2507 | 63 | mxPushSlot(mxThis); |
2508 | 63 | mxPushNumber(upper); |
2509 | 63 | mxGetAt(); |
2510 | 63 | upperSlot = the->stack; |
2511 | 63 | } |
2512 | 545k | else |
2513 | 545k | upperSlot = C_NULL; |
2514 | 545k | if (upperSlot && lowerSlot) { |
2515 | 42 | mxPushSlot(upperSlot); |
2516 | 42 | mxPushSlot(mxThis); |
2517 | 42 | mxPushNumber(lower); |
2518 | 42 | mxSetAt(); |
2519 | 42 | mxPop(); |
2520 | 42 | mxPushSlot(lowerSlot); |
2521 | 42 | mxPushSlot(mxThis); |
2522 | 42 | mxPushNumber(upper); |
2523 | 42 | mxSetAt(); |
2524 | 42 | mxPop(); |
2525 | 42 | mxPop(); |
2526 | 42 | mxPop(); |
2527 | 42 | } |
2528 | 545k | else if (upperSlot) { |
2529 | 20 | mxPushSlot(upperSlot); |
2530 | 20 | mxPushSlot(mxThis); |
2531 | 20 | mxPushNumber(lower); |
2532 | 20 | mxSetAt(); |
2533 | 20 | mxPop(); |
2534 | 20 | mxPushSlot(mxThis); |
2535 | 20 | mxPushNumber(upper); |
2536 | 20 | mxDeleteAt(); |
2537 | 20 | mxPop(); |
2538 | 20 | mxPop(); |
2539 | 20 | } |
2540 | 545k | else if (lowerSlot) { |
2541 | 12 | mxPushSlot(mxThis); |
2542 | 12 | mxPushNumber(lower); |
2543 | 12 | mxDeleteAt(); |
2544 | 12 | mxPop(); |
2545 | 12 | mxPushSlot(lowerSlot); |
2546 | 12 | mxPushSlot(mxThis); |
2547 | 12 | mxPushNumber(upper); |
2548 | 12 | mxSetAt(); |
2549 | 12 | mxPop(); |
2550 | 12 | mxPop(); |
2551 | 12 | } |
2552 | 545k | lower++; |
2553 | 545k | mxCheckMetering(); |
2554 | 545k | } |
2555 | 55 | *mxResult = *mxThis; |
2556 | 55 | } |
2557 | | |
2558 | | void fx_Array_prototype_shift(txMachine* the) |
2559 | 139 | { |
2560 | 139 | txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE); |
2561 | 139 | if (array) |
2562 | 87 | array = fxCheckArrayItems(the, array, 0, array->value.array.length); |
2563 | 139 | if (array) { |
2564 | 87 | txIndex length = array->value.array.length; |
2565 | 87 | txSlot* address; |
2566 | 87 | mxMeterSome(2); |
2567 | 87 | if (length > 0) { |
2568 | 76 | mxMeterSome(3); |
2569 | 76 | address = array->value.array.address; |
2570 | 76 | length--; |
2571 | 76 | mxResult->kind = address->kind; |
2572 | 76 | mxResult->value = address->value; |
2573 | 76 | c_memmove(address, address + 1, length * sizeof(txSlot)); |
2574 | 76 | fxSetIndexSize(the, array, length, XS_CHUNK); |
2575 | 76 | fxIndexArray(the, array); |
2576 | 76 | mxMeterSome(length * 10); |
2577 | 76 | mxMeterSome(3); |
2578 | 76 | } |
2579 | 87 | mxMeterSome(4); |
2580 | 87 | } |
2581 | 52 | else { |
2582 | 52 | txNumber length = fxGetArrayLength(the, mxThis); |
2583 | 52 | if (length > 0) { |
2584 | 28 | txNumber index = 1; |
2585 | 28 | mxPushSlot(mxThis); |
2586 | 28 | mxGetIndex(0); |
2587 | 28 | mxPullSlot(mxResult); |
2588 | 874k | while (index < length) { |
2589 | 874k | mxPushSlot(mxThis); |
2590 | 874k | mxPushNumber(index); |
2591 | 874k | if (mxHasAt()) { |
2592 | 41 | mxPushSlot(mxThis); |
2593 | 41 | mxPushNumber(index); |
2594 | 41 | mxGetAt(); |
2595 | 41 | mxPushSlot(mxThis); |
2596 | 41 | mxPushNumber(index - 1); |
2597 | 41 | mxSetAt(); |
2598 | 41 | mxPop(); |
2599 | 41 | } |
2600 | 874k | else { |
2601 | 874k | mxPushSlot(mxThis); |
2602 | 874k | mxPushNumber(index - 1); |
2603 | 874k | mxDeleteAt(); |
2604 | 874k | mxPop(); |
2605 | 874k | } |
2606 | 874k | index++; |
2607 | 874k | mxCheckMetering(); |
2608 | 874k | } |
2609 | 28 | length--; |
2610 | 28 | mxPushSlot(mxThis); |
2611 | 28 | mxDeleteIndex((txIndex)length); |
2612 | 28 | mxPop(); |
2613 | 28 | } |
2614 | 52 | mxPushNumber(length); |
2615 | 52 | mxPushSlot(mxThis); |
2616 | 52 | mxSetID(mxID(_length)); |
2617 | 52 | mxPop(); |
2618 | 52 | } |
2619 | 139 | } |
2620 | | |
2621 | | void fx_Array_prototype_slice(txMachine* the) |
2622 | 22.8k | { |
2623 | 22.8k | txNumber LENGTH = fxGetArrayLength(the, mxThis); |
2624 | 22.8k | txNumber START = fxArgToIndex(the, 0, 0, LENGTH); |
2625 | 22.8k | txNumber END = fxArgToIndex(the, 1, LENGTH, LENGTH); |
2626 | 22.8k | txNumber COUNT = (END > START) ? END - START : 0; |
2627 | 22.8k | txSlot* resultArray = fxCreateArraySpecies(the, COUNT); |
2628 | 22.8k | txSlot* array = C_NULL; |
2629 | 22.8k | if (resultArray) |
2630 | 22.7k | array = fxCheckArray(the, mxThis, XS_IMMUTABLE); |
2631 | 22.8k | if (array) |
2632 | 22.6k | array = fxCheckArrayItems(the, array, (txIndex)START, (txIndex)(START + COUNT)); |
2633 | 22.8k | if (array) { |
2634 | 22.1k | txIndex start = (txIndex)START; |
2635 | 22.1k | txIndex count = (txIndex)COUNT; |
2636 | 22.1k | if (count) { |
2637 | 21.7k | fxSetIndexSize(the, resultArray, count, XS_CHUNK); |
2638 | 21.7k | c_memcpy(resultArray->value.array.address, array->value.array.address + start, count * sizeof(txSlot)); |
2639 | 21.7k | fxIndexArray(the, resultArray); |
2640 | 21.7k | mxMeterSome(count * 10); |
2641 | 21.7k | } |
2642 | 22.1k | mxMeterSome(3); |
2643 | 22.1k | } |
2644 | 693 | else { |
2645 | 693 | txNumber INDEX = 0; |
2646 | 2.00M | while (START < END) { |
2647 | 2.00M | mxPushSlot(mxThis); |
2648 | 2.00M | mxPushNumber(START); |
2649 | 2.00M | if (mxHasAt()) { |
2650 | 184 | mxPushSlot(mxThis); |
2651 | 184 | mxPushNumber(START); |
2652 | 184 | mxGetAt(); |
2653 | 184 | mxPushSlot(mxResult); |
2654 | 184 | mxPushNumber(INDEX); |
2655 | 184 | mxDefineAt(0, XS_GET_ONLY); |
2656 | 184 | mxPop(); |
2657 | 184 | } |
2658 | 2.00M | INDEX++; |
2659 | 2.00M | START++; |
2660 | 2.00M | mxCheckMetering(); |
2661 | 2.00M | } |
2662 | 693 | mxPushNumber(COUNT); |
2663 | 693 | mxPushSlot(mxResult); |
2664 | 693 | mxSetID(mxID(_length)); |
2665 | 693 | } |
2666 | 22.8k | } |
2667 | | |
2668 | | void fx_Array_prototype_some(txMachine* the) |
2669 | 115 | { |
2670 | 115 | txIndex length = fxGetArrayLimit(the, mxThis); |
2671 | 115 | txIndex index = 0; |
2672 | 115 | txSlot* function = fxArgToCallback(the, 0); |
2673 | 115 | mxResult->kind = XS_BOOLEAN_KIND; |
2674 | 115 | mxResult->value.boolean = 0; |
2675 | 1.00M | while (index < length) { |
2676 | 1.00M | if (fxCallThisItem(the, function, index, C_NULL)) { |
2677 | 424 | mxResult->value.boolean = fxToBoolean(the, the->stack); |
2678 | 424 | mxPop(); |
2679 | 424 | if (mxResult->value.boolean) |
2680 | 89 | break; |
2681 | 424 | } |
2682 | 1.00M | index++; |
2683 | 1.00M | mxCheckMetering(); |
2684 | 1.00M | } |
2685 | 115 | } |
2686 | | |
2687 | | |
2688 | | void fx_Array_prototype_sort(txMachine* the) |
2689 | 206k | { |
2690 | 206k | txSlot* function = C_NULL; |
2691 | 206k | /*txSlot* array =*/ fxCheckArray(the, mxThis, XS_MUTABLE); |
2692 | 206k | if (mxArgc > 0) { |
2693 | 57 | txSlot* slot = mxArgv(0); |
2694 | 57 | if (slot->kind != XS_UNDEFINED_KIND) { |
2695 | 56 | if (fxIsCallable(the, slot)) |
2696 | 24 | function = slot; |
2697 | 32 | else |
2698 | 32 | mxTypeError("compare: not a function"); |
2699 | 56 | } |
2700 | 57 | } |
2701 | | // if (function) |
2702 | 206k | fxSortArrayItems(the, function, C_NULL, fxGetArrayLength(the, mxThis), mxThis); |
2703 | | // else { |
2704 | | // if (array) |
2705 | | // array = fxCheckArrayItems(the, array, 0, array->value.array.length); |
2706 | | // fxSortArrayItems(the, function, array, fxGetArrayLength(the, mxThis), mxThis); |
2707 | | // } |
2708 | 206k | mxResult->kind = mxThis->kind; |
2709 | 206k | mxResult->value = mxThis->value; |
2710 | 206k | } |
2711 | | |
2712 | | void fx_Array_prototype_splice(txMachine* the) |
2713 | 207k | { |
2714 | 207k | txIndex c = (txIndex)mxArgc; |
2715 | 207k | txNumber LENGTH = fxGetArrayLength(the, mxThis); |
2716 | 207k | txNumber START = fxArgToIndex(the, 0, 0, LENGTH); |
2717 | 207k | txNumber INSERTIONS, DELETIONS; |
2718 | 207k | txSlot* resultArray; |
2719 | 207k | txSlot* array = C_NULL; |
2720 | 207k | if (c == 0) { |
2721 | 19 | INSERTIONS = 0; |
2722 | 19 | DELETIONS = 0; |
2723 | 19 | } |
2724 | 207k | else if (c == 1) { |
2725 | 54.1k | INSERTIONS = 0; |
2726 | 54.1k | DELETIONS = LENGTH - START; |
2727 | 54.1k | } |
2728 | 152k | else { |
2729 | 152k | INSERTIONS = c - 2; |
2730 | 152k | DELETIONS = fxArgToRange(the, 1, 0, 0, LENGTH - START); |
2731 | 152k | } |
2732 | 207k | if (LENGTH + INSERTIONS - DELETIONS > C_MAX_SAFE_INTEGER) |
2733 | 10 | mxTypeError("unsafe integer"); |
2734 | 207k | resultArray = fxCreateArraySpecies(the, DELETIONS); |
2735 | 207k | if (resultArray) |
2736 | 207k | array = fxCheckArray(the, mxThis, XS_MUTABLE); |
2737 | 207k | if (array) { |
2738 | 195k | if (INSERTIONS == DELETIONS) |
2739 | 176k | array = fxCheckArrayItems(the, array, (txIndex)START, (txIndex)(START + DELETIONS)); |
2740 | 18.8k | else |
2741 | 18.8k | array = fxCheckArrayItems(the, array, (txIndex)START, (txIndex)LENGTH); |
2742 | 195k | } |
2743 | 207k | if (array) { |
2744 | 195k | txSlot* address; |
2745 | 195k | txIndex length = (txIndex)LENGTH; |
2746 | 195k | txIndex start = (txIndex)START; |
2747 | 195k | txIndex insertions = (txIndex)INSERTIONS; |
2748 | 195k | txIndex deletions = (txIndex)DELETIONS; |
2749 | 195k | txIndex index; |
2750 | 195k | if (LENGTH + INSERTIONS - DELETIONS > 0xFFFFFFFF) |
2751 | 0 | mxTypeError("array overflow"); |
2752 | 195k | fxSetIndexSize(the, resultArray, deletions, XS_CHUNK); |
2753 | 195k | c_memcpy(resultArray->value.array.address, array->value.array.address + start, deletions * sizeof(txSlot)); |
2754 | 195k | fxIndexArray(the, resultArray); |
2755 | 195k | mxMeterSome(deletions * 10); |
2756 | 195k | mxMeterSome(4); |
2757 | 195k | if (insertions < deletions) { |
2758 | 18.8k | c_memmove(array->value.array.address + start + insertions, array->value.array.address + start + deletions, (length - (start + deletions)) * sizeof(txSlot)); |
2759 | 18.8k | fxSetIndexSize(the, array, length - (deletions - insertions), XS_CHUNK); |
2760 | 18.8k | mxMeterSome((length - (start + deletions)) * 10); |
2761 | 18.8k | mxMeterSome((deletions - insertions) * 4); |
2762 | 18.8k | } |
2763 | 176k | else if (insertions > deletions) { |
2764 | 8 | fxSetIndexSize(the, array, length + (insertions - deletions), XS_CHUNK); |
2765 | 8 | c_memmove(array->value.array.address + start + insertions, array->value.array.address + start + deletions, (length - (start + deletions)) * sizeof(txSlot)); |
2766 | 8 | mxMeterSome((length - (start + deletions)) * 10); |
2767 | 8 | } |
2768 | 195k | address = array->value.array.address + start; |
2769 | 195k | index = 2; |
2770 | 195k | while (index < c) { |
2771 | 99 | txSlot* argument = mxArgv(index); |
2772 | 99 | address->ID = XS_NO_ID; |
2773 | 99 | address->kind = argument->kind; |
2774 | 99 | address->value = argument->value; |
2775 | 99 | address++; |
2776 | 99 | mxMeterSome(5); |
2777 | 99 | index++; |
2778 | 99 | mxCheckMetering(); |
2779 | 99 | } |
2780 | 195k | fxIndexArray(the, array); |
2781 | 195k | mxMeterSome(4); |
2782 | 195k | } |
2783 | 11.5k | else { |
2784 | 11.5k | txNumber INDEX = 0; |
2785 | 15.4k | while (INDEX < DELETIONS) { |
2786 | 3.87k | txNumber FROM = START + INDEX; |
2787 | 3.87k | mxPushSlot(mxThis); |
2788 | 3.87k | mxPushNumber(FROM); |
2789 | 3.87k | if (mxHasAt()) { |
2790 | 434 | mxPushSlot(mxThis); |
2791 | 434 | mxPushNumber(FROM); |
2792 | 434 | mxGetAt(); |
2793 | 434 | mxPushSlot(mxResult); |
2794 | 434 | mxPushNumber(INDEX); |
2795 | 434 | mxDefineAt(0, XS_GET_ONLY); |
2796 | 434 | mxPop(); |
2797 | 434 | } |
2798 | 3.87k | INDEX++; |
2799 | 3.87k | mxCheckMetering(); |
2800 | 3.87k | } |
2801 | 11.5k | mxPushNumber(DELETIONS); |
2802 | 11.5k | mxPushSlot(mxResult); |
2803 | 11.5k | mxSetID(mxID(_length)); |
2804 | 11.5k | mxPop(); |
2805 | 11.5k | if (INSERTIONS < DELETIONS) { |
2806 | 2.32k | INDEX = START; |
2807 | 1.09M | while (INDEX < (LENGTH - DELETIONS)) { |
2808 | 1.09M | fxMoveThisItem(the, INDEX + DELETIONS, INDEX + INSERTIONS); |
2809 | 1.09M | INDEX++; |
2810 | 1.09M | mxCheckMetering(); |
2811 | 1.09M | } |
2812 | 2.32k | INDEX = LENGTH; |
2813 | 6.18k | while (INDEX > (LENGTH - DELETIONS + INSERTIONS)) { |
2814 | 3.85k | mxPushSlot(mxThis); |
2815 | 3.85k | mxPushNumber(INDEX - 1); |
2816 | 3.85k | mxDeleteAt(); |
2817 | 3.85k | mxPop(); |
2818 | 3.85k | INDEX--; |
2819 | 3.85k | mxCheckMetering(); |
2820 | 3.85k | } |
2821 | 2.32k | } |
2822 | 9.24k | else if (INSERTIONS > DELETIONS) { |
2823 | 25 | INDEX = LENGTH - DELETIONS; |
2824 | 873k | while (INDEX > START) { |
2825 | 873k | fxMoveThisItem(the, INDEX + DELETIONS - 1, INDEX + INSERTIONS - 1); |
2826 | 873k | INDEX--; |
2827 | 873k | mxCheckMetering(); |
2828 | 873k | } |
2829 | 25 | } |
2830 | 11.5k | INDEX = 0; |
2831 | 11.6k | while (INDEX < INSERTIONS) { |
2832 | 56 | mxPushSlot(mxArgv(2 + (txInteger)INDEX)); |
2833 | 56 | mxPushSlot(mxThis); |
2834 | 56 | mxPushNumber(START + INDEX); |
2835 | 56 | mxSetAt(); |
2836 | 56 | mxPop(); |
2837 | 56 | INDEX++; |
2838 | 56 | mxCheckMetering(); |
2839 | 56 | } |
2840 | 11.5k | mxPushNumber(LENGTH - DELETIONS + INSERTIONS); |
2841 | 11.5k | mxPushSlot(mxThis); |
2842 | 11.5k | mxSetID(mxID(_length)); |
2843 | 11.5k | mxPop(); |
2844 | 11.5k | } |
2845 | 207k | } |
2846 | | |
2847 | | void fx_Array_prototype_toLocaleString(txMachine* the) |
2848 | 70 | { |
2849 | 70 | txIndex length = fxGetArrayLimit(the, mxThis); |
2850 | 70 | txIndex index = 0; |
2851 | 70 | txString string; |
2852 | 70 | txSlot* list = fxNewInstance(the); |
2853 | 70 | txSlot* slot = list; |
2854 | 70 | txBoolean comma = 0; |
2855 | 70 | txInteger size = 0; |
2856 | | |
2857 | 70 | mxPushStringX(","); |
2858 | 70 | the->stack->kind += XS_KEY_KIND - XS_STRING_KIND; |
2859 | 70 | the->stack->value.key.sum = 1; |
2860 | 173 | while (index < length) { |
2861 | 103 | if (comma) { |
2862 | 47 | slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG); |
2863 | 47 | size = fxAddChunkSizes(the, size, slot->value.key.sum); |
2864 | 47 | } |
2865 | 56 | else |
2866 | 56 | comma = 1; |
2867 | 103 | mxPushSlot(mxThis); |
2868 | 103 | mxGetIndex(index); |
2869 | 103 | if ((the->stack->kind != XS_UNDEFINED_KIND) && (the->stack->kind != XS_NULL_KIND)) { |
2870 | 33 | mxDub(); |
2871 | 33 | mxGetID(mxID(_toLocaleString)); |
2872 | 33 | mxCall(); |
2873 | 33 | mxRunCount(0); |
2874 | 33 | slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG); |
2875 | 33 | string = fxToString(the, slot); |
2876 | 33 | slot->kind += XS_KEY_KIND - XS_STRING_KIND; |
2877 | 33 | slot->value.key.sum = mxStringLength(string); |
2878 | 33 | size = fxAddChunkSizes(the, size, slot->value.key.sum); |
2879 | 33 | } |
2880 | 103 | mxPop(); |
2881 | 103 | index++; |
2882 | | |
2883 | 103 | mxCheckMetering(); |
2884 | 103 | } |
2885 | 70 | string = mxResult->value.string = fxNewChunk(the, fxAddChunkSizes(the, size, 1)); |
2886 | 70 | slot = list->next; |
2887 | 148 | while (slot) { |
2888 | 78 | c_memcpy(string, slot->value.key.string, slot->value.key.sum); |
2889 | 78 | string += slot->value.key.sum; |
2890 | 78 | slot = slot->next; |
2891 | 78 | } |
2892 | 70 | *string = 0; |
2893 | 70 | mxResult->kind = XS_STRING_KIND; |
2894 | 70 | mxPop(); |
2895 | 70 | } |
2896 | | |
2897 | | void fx_Array_prototype_toReversed(txMachine* the) |
2898 | 50 | { |
2899 | 50 | txNumber LENGTH = fxGetArrayLength(the, mxThis); |
2900 | 50 | txIndex length, to, from; |
2901 | 50 | if (LENGTH > 0xFFFFFFFF) |
2902 | 1 | mxRangeError("array overflow"); |
2903 | 49 | length = (txIndex)LENGTH; |
2904 | 49 | fxNewArray(the, length); |
2905 | 49 | mxPullSlot(mxResult); |
2906 | 49 | from = length - 1; |
2907 | 49 | to = 0; |
2908 | 1.04M | while (to < length) { |
2909 | 1.04M | mxPushSlot(mxThis); |
2910 | 1.04M | mxPushUnsigned(from); |
2911 | 1.04M | mxGetAt(); |
2912 | 1.04M | mxPushSlot(mxResult); |
2913 | 1.04M | mxPushUnsigned(to); |
2914 | 1.04M | mxDefineAt(0, XS_GET_ONLY); |
2915 | 1.04M | mxPop(); |
2916 | 1.04M | from--; |
2917 | 1.04M | to++; |
2918 | 1.04M | mxCheckMetering(); |
2919 | 1.04M | } |
2920 | 49 | } |
2921 | | |
2922 | | void fx_Array_prototype_toSorted(txMachine* the) |
2923 | 42.7k | { |
2924 | 42.7k | txSlot* function = C_NULL; |
2925 | 42.7k | txNumber LENGTH; |
2926 | 42.7k | if (mxArgc > 0) { |
2927 | 42.7k | txSlot* slot = mxArgv(0); |
2928 | 42.7k | if (slot->kind != XS_UNDEFINED_KIND) { |
2929 | 41 | if (fxIsCallable(the, slot)) |
2930 | 1 | function = slot; |
2931 | 40 | else |
2932 | 40 | mxTypeError("compare: not a function"); |
2933 | 41 | } |
2934 | 42.7k | } |
2935 | 42.7k | LENGTH = fxGetArrayLength(the, mxThis); |
2936 | 42.7k | if (LENGTH > 0xFFFFFFFF) |
2937 | 1 | mxRangeError("array overflow"); |
2938 | 42.7k | fxNewArray(the, (txIndex)LENGTH); |
2939 | 42.7k | mxPullSlot(mxResult); |
2940 | 42.7k | fxSortArrayItems(the, function, C_NULL, LENGTH, mxResult); |
2941 | 42.7k | } |
2942 | | |
2943 | | void fx_Array_prototype_toSpliced(txMachine* the) |
2944 | 826k | { |
2945 | 826k | txIndex c = (txIndex)mxArgc, i; |
2946 | 826k | txNumber LENGTH = fxGetArrayLength(the, mxThis); |
2947 | 826k | txNumber START = fxArgToIndex(the, 0, 0, LENGTH); |
2948 | 826k | txNumber INSERTIONS, SKIP, RESULT_LENGTH; |
2949 | 826k | txSlot* array = C_NULL; |
2950 | 826k | if (c == 0) { |
2951 | 380k | INSERTIONS = 0; |
2952 | 380k | SKIP = 0; |
2953 | 380k | } |
2954 | 445k | else if (c == 1) { |
2955 | 157k | INSERTIONS = 0; |
2956 | 157k | SKIP = LENGTH - START; |
2957 | 157k | } |
2958 | 288k | else { |
2959 | 288k | INSERTIONS = c - 2; |
2960 | 288k | SKIP = fxArgToRange(the, 1, 0, 0, LENGTH - START); |
2961 | 288k | } |
2962 | 826k | RESULT_LENGTH = LENGTH + INSERTIONS - SKIP; |
2963 | 826k | if (RESULT_LENGTH > C_MAX_SAFE_INTEGER) |
2964 | 6 | mxTypeError("unsafe integer"); |
2965 | 826k | if (RESULT_LENGTH > 0xFFFFFFFF) |
2966 | 26 | mxRangeError("array overflow"); |
2967 | 826k | array = fxCheckArray(the, mxThis, XS_IMMUTABLE); |
2968 | 826k | if (array) |
2969 | 307k | array = fxCheckArrayItems(the, array, (txIndex)0, (txIndex)START); |
2970 | 826k | if (array) |
2971 | 307k | array = fxCheckArrayItems(the, array, (txIndex)(START + SKIP), (txIndex)LENGTH); |
2972 | 826k | if (array) { |
2973 | 307k | txIndex length = (txIndex)LENGTH; |
2974 | 307k | txIndex start = (txIndex)START; |
2975 | 307k | txIndex skip = (txIndex)SKIP; |
2976 | 307k | txIndex rest = length - (start + skip); |
2977 | 307k | txSlot* resultArray; |
2978 | 307k | txSlot* resultAddress; |
2979 | 307k | txSlot* address; |
2980 | 307k | fxNewArray(the, (txIndex)RESULT_LENGTH); |
2981 | 307k | mxPullSlot(mxResult); |
2982 | 307k | resultArray = mxResult->value.reference->next; |
2983 | 307k | resultAddress = resultArray->value.array.address; |
2984 | 307k | address = array->value.array.address; |
2985 | 307k | if (start > 0) { |
2986 | 82.9k | c_memcpy(resultAddress, address, start * sizeof(txSlot)); |
2987 | 82.9k | mxMeterSome(start * 10); |
2988 | 82.9k | resultAddress += start; |
2989 | 82.9k | address += start; |
2990 | 82.9k | } |
2991 | 307k | for (i = 2; i < c; i++) { |
2992 | 23 | txSlot* argument = mxArgv(i); |
2993 | 23 | resultAddress->ID = XS_NO_ID; |
2994 | 23 | resultAddress->kind = argument->kind; |
2995 | 23 | resultAddress->value = argument->value; |
2996 | 23 | resultAddress++; |
2997 | 23 | mxMeterSome(5); |
2998 | 23 | mxCheckMetering(); |
2999 | 23 | } |
3000 | 307k | address += skip; |
3001 | 307k | if (rest > 0) { |
3002 | 188k | c_memcpy(resultAddress, address, rest * sizeof(txSlot)); |
3003 | 188k | mxMeterSome(rest * 10); |
3004 | 188k | } |
3005 | 307k | fxIndexArray(the, resultArray); |
3006 | 307k | mxMeterSome(4); |
3007 | 307k | } |
3008 | 518k | else { |
3009 | 518k | txNumber from = 0; |
3010 | 518k | txNumber to = 0; |
3011 | 518k | fxNewArray(the, 0); |
3012 | 518k | mxPullSlot(mxResult); |
3013 | 1.27M | while (from < START) { |
3014 | 758k | mxPushSlot(mxThis); |
3015 | 758k | mxPushUnsigned(from); |
3016 | 758k | mxGetAt(); |
3017 | 758k | mxPushSlot(mxResult); |
3018 | 758k | mxPushUnsigned(to); |
3019 | 758k | mxDefineAt(0, XS_GET_ONLY); |
3020 | 758k | mxPop(); |
3021 | 758k | from++; |
3022 | 758k | to++; |
3023 | 758k | mxCheckMetering(); |
3024 | 758k | } |
3025 | 518k | for (i = 2; i < c; i++) { |
3026 | 32 | mxPushSlot(mxArgv(i)); |
3027 | 32 | mxPushSlot(mxResult); |
3028 | 32 | mxPushNumber(to); |
3029 | 32 | mxDefineAt(0, XS_GET_ONLY); |
3030 | 32 | mxPop(); |
3031 | 32 | to++; |
3032 | 32 | mxCheckMetering(); |
3033 | 32 | } |
3034 | 518k | from += SKIP; |
3035 | 1.28M | while (from < LENGTH) { |
3036 | 767k | mxPushSlot(mxThis); |
3037 | 767k | mxPushUnsigned(from); |
3038 | 767k | mxGetAt(); |
3039 | 767k | mxPushSlot(mxResult); |
3040 | 767k | mxPushUnsigned(to); |
3041 | 767k | mxDefineAt(0, XS_GET_ONLY); |
3042 | 767k | mxPop(); |
3043 | 767k | from++; |
3044 | 767k | to++; |
3045 | 767k | mxCheckMetering(); |
3046 | 767k | } |
3047 | 518k | } |
3048 | 826k | } |
3049 | | |
3050 | | void fx_Array_prototype_toString(txMachine* the) |
3051 | 5.62M | { |
3052 | 5.62M | mxPushSlot(mxThis); |
3053 | 5.62M | mxDub(); |
3054 | 5.62M | mxGetID(mxID(_join)); |
3055 | 5.62M | if (fxIsCallable(the, the->stack)) { |
3056 | 5.62M | mxCall(); |
3057 | 5.62M | mxRunCount(0); |
3058 | 5.62M | mxPullSlot(mxResult); |
3059 | 5.62M | } |
3060 | 51 | else { |
3061 | 51 | mxPop(); |
3062 | 51 | mxPop(); |
3063 | 51 | fx_Object_prototype_toString(the); |
3064 | 51 | } |
3065 | 5.62M | } |
3066 | | |
3067 | | void fx_Array_prototype_unshift(txMachine* the) |
3068 | 78 | { |
3069 | 78 | txIndex c = mxArgc, i; |
3070 | 78 | txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE); |
3071 | 78 | if (array) |
3072 | 11 | array = fxCheckArrayItems(the, array, 0, array->value.array.length); |
3073 | 78 | if (array) { |
3074 | 11 | txSlot* address; |
3075 | 11 | txIndex length = array->value.array.length; |
3076 | 11 | if (length + c < length) |
3077 | 0 | mxRangeError("array overflow"); |
3078 | 11 | if (c > 0) { |
3079 | 10 | fxSetIndexSize(the, array, length + c, XS_GROWABLE_CHUNK); |
3080 | 10 | address = array->value.array.address; |
3081 | 10 | c_memmove(address + c, address, length * sizeof(txSlot)); |
3082 | 10 | mxMeterSome(length * 10); |
3083 | 10 | i = 0; |
3084 | 41 | while (i < c) { |
3085 | 31 | txSlot* argument = mxArgv(i); |
3086 | 31 | address->ID = XS_NO_ID; |
3087 | 31 | address->kind = argument->kind; |
3088 | 31 | address->value = argument->value; |
3089 | 31 | address++; |
3090 | 31 | mxMeterSome(4); |
3091 | 31 | i++; |
3092 | 31 | mxCheckMetering(); |
3093 | 31 | } |
3094 | 10 | fxIndexArray(the, array); |
3095 | 10 | } |
3096 | 11 | mxPushUnsigned(length + c); |
3097 | 11 | mxMeterSome(2); |
3098 | 11 | } |
3099 | 67 | else { |
3100 | 67 | txNumber length = fxGetArrayLength(the, mxThis); |
3101 | 67 | txNumber index = length; |
3102 | 67 | if (c > 0) { |
3103 | 42 | if (length + c > C_MAX_SAFE_INTEGER) |
3104 | 10 | mxTypeError("unsafe integer"); |
3105 | 1.30M | while (index > 0) { |
3106 | 1.30M | fxMoveThisItem(the, index - 1, index + c - 1); |
3107 | 1.30M | index--; |
3108 | 1.30M | mxCheckMetering(); |
3109 | 1.30M | } |
3110 | 32 | i = 0; |
3111 | 71 | while (i < c) { |
3112 | 39 | mxPushSlot(mxArgv(i)); |
3113 | 39 | mxPushSlot(mxThis); |
3114 | 39 | mxSetIndex(i); |
3115 | 39 | mxPop(); |
3116 | 39 | i++; |
3117 | 39 | mxCheckMetering(); |
3118 | 39 | } |
3119 | 32 | } |
3120 | 57 | mxPushNumber(length + c); |
3121 | 57 | mxPushSlot(mxThis); |
3122 | 57 | mxSetID(mxID(_length)); |
3123 | 57 | } |
3124 | 68 | mxPullSlot(mxResult); |
3125 | 68 | } |
3126 | | |
3127 | | void fx_Array_prototype_values(txMachine* the) |
3128 | 609k | { |
3129 | 609k | txSlot* property; |
3130 | 609k | fxToInstance(the, mxThis); |
3131 | 609k | mxPush(mxArrayIteratorPrototype); |
3132 | 609k | property = fxLastProperty(the, fxNewIteratorInstance(the, mxThis, mxID(_Array))); |
3133 | 609k | property = fxNextIntegerProperty(the, property, 0, XS_NO_ID, XS_INTERNAL_FLAG); |
3134 | 609k | mxPullSlot(mxResult); |
3135 | 609k | } |
3136 | | |
3137 | | void fx_Array_prototype_with(txMachine* the) |
3138 | 120k | { |
3139 | 120k | txNumber LENGTH = fxGetArrayLength(the, mxThis), INDEX; |
3140 | 120k | txIndex length, index, i; |
3141 | 120k | if (LENGTH > 0xFFFFFFFF) |
3142 | 1 | mxRangeError("array overflow"); |
3143 | 120k | INDEX = fxArgToRelativeIndex(the, 0, 0, LENGTH); |
3144 | 120k | if ((INDEX < 0) || (LENGTH <= INDEX)) |
3145 | 23 | mxRangeError("invalid index"); |
3146 | 120k | length = (txIndex)LENGTH; |
3147 | 120k | fxNewArray(the, length); |
3148 | 120k | mxPullSlot(mxResult); |
3149 | 120k | index = (txIndex)INDEX; |
3150 | 120k | i = 0; |
3151 | 241k | while (i < index) { |
3152 | 121k | mxPushSlot(mxThis); |
3153 | 121k | mxPushUnsigned(i); |
3154 | 121k | mxGetAt(); |
3155 | 121k | mxPushSlot(mxResult); |
3156 | 121k | mxPushUnsigned(i); |
3157 | 121k | mxDefineAt(0, XS_GET_ONLY); |
3158 | 121k | mxPop(); |
3159 | 121k | i++; |
3160 | 121k | mxCheckMetering(); |
3161 | 121k | } |
3162 | 120k | if (mxArgc > 1) |
3163 | 112k | mxPushSlot(mxArgv(1)); |
3164 | 8.16k | else |
3165 | 8.16k | mxPushUndefined(); |
3166 | 120k | mxPushSlot(mxResult); |
3167 | 120k | mxPushUnsigned(i); |
3168 | 120k | mxDefineAt(0, XS_GET_ONLY); |
3169 | 120k | mxPop(); |
3170 | 120k | i++; |
3171 | 1.28M | while (i < length) { |
3172 | 1.16M | mxPushSlot(mxThis); |
3173 | 1.16M | mxPushUnsigned(i); |
3174 | 1.16M | mxGetAt(); |
3175 | 1.16M | mxPushSlot(mxResult); |
3176 | 1.16M | mxPushUnsigned(i); |
3177 | 1.16M | mxDefineAt(0, XS_GET_ONLY); |
3178 | 1.16M | mxPop(); |
3179 | 1.16M | i++; |
3180 | 1.16M | mxCheckMetering(); |
3181 | 1.16M | } |
3182 | 120k | } |
3183 | | |
3184 | | void fx_ArrayIterator_prototype_next(txMachine* the) |
3185 | 1.54M | { |
3186 | 1.54M | txSlot* iterator = fxCheckIteratorInstance(the, mxThis, mxID(_Array)); |
3187 | 1.54M | txSlot* result = iterator->next; |
3188 | 1.54M | txSlot* iterable = result->next; |
3189 | 1.54M | txSlot* index = iterable->next; |
3190 | 1.54M | txSlot* value = fxCheckIteratorResult(the, result); |
3191 | 1.54M | txSlot* done = value->next; |
3192 | 1.54M | if (!done->value.boolean) { |
3193 | 1.54M | txInteger kind = index->next->value.integer; |
3194 | 1.54M | txIndex length = fxGetArrayLimit(the, iterable); |
3195 | 1.54M | txIndex i = (txIndex)index->value.integer; |
3196 | 1.54M | if (i < length) { |
3197 | 948k | switch(kind) { |
3198 | 948k | case 0: |
3199 | 948k | mxPushSlot(iterable); |
3200 | 948k | mxGetIndex(i); |
3201 | 948k | mxPullSlot(value); |
3202 | 948k | break; |
3203 | 6 | case 1: |
3204 | 6 | mxPushUnsigned(i); |
3205 | 6 | mxPullSlot(value); |
3206 | 6 | break; |
3207 | 11 | case 2: |
3208 | 11 | mxPushUnsigned(i); |
3209 | 11 | mxPushSlot(iterable); |
3210 | 11 | mxGetIndex(i); |
3211 | 11 | fxConstructArrayEntry(the, value); |
3212 | 11 | break; |
3213 | 948k | } |
3214 | 948k | index->value.integer = i + 1; |
3215 | 948k | } |
3216 | 592k | else { |
3217 | 592k | value->kind = XS_UNDEFINED_KIND; |
3218 | 592k | done->value.boolean = 1; |
3219 | 592k | } |
3220 | 1.54M | } |
3221 | 1.54M | mxResult->kind = result->kind; |
3222 | 1.54M | mxResult->value = result->value; |
3223 | 1.54M | } |
3224 | | |