Coverage Report

Created: 2026-09-01 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
937k
#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
31.7k
{
91
31.7k
  txSlot* instance;
92
31.7k
  txSlot* slot;
93
31.7k
  txSlot* property;
94
31.7k
  txSlot* unscopable;
95
  
96
31.7k
  mxPush(mxObjectPrototype);
97
31.7k
  instance = fxNewArrayInstance(the);
98
99
31.7k
  fxNewHostFunction(the, mxCallback(fxArrayLengthGetter), 0, mxID(_length), XS_NO_ID);
100
31.7k
  property = mxFunctionInstanceHome(the->stack->value.reference);
101
31.7k
  property->value.home.object = instance;
102
31.7k
  fxNewHostFunction(the, mxCallback(fxArrayLengthSetter), 1, mxID(_length), XS_NO_ID);
103
31.7k
  property = mxFunctionInstanceHome(the->stack->value.reference);
104
31.7k
  property->value.home.object = instance;
105
31.7k
  mxPushUndefined();
106
31.7k
  the->stack->flag = XS_DONT_DELETE_FLAG;
107
31.7k
  the->stack->kind = XS_ACCESSOR_KIND;
108
31.7k
  the->stack->value.accessor.getter = (the->stack + 2)->value.reference;
109
31.7k
  the->stack->value.accessor.setter = (the->stack + 1)->value.reference;
110
31.7k
  mxPull(mxArrayLengthAccessor);
111
31.7k
  mxPop();
112
31.7k
  mxPop();
113
114
31.7k
  slot = fxLastProperty(the, instance);
115
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_at), 1, mxID(_at), XS_DONT_ENUM_FLAG);
116
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_concat), 1, mxID(_concat), XS_DONT_ENUM_FLAG);
117
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_copyWithin), 2, mxID(_copyWithin), XS_DONT_ENUM_FLAG);
118
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_entries), 0, mxID(_entries), XS_DONT_ENUM_FLAG);
119
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_every), 1, mxID(_every), XS_DONT_ENUM_FLAG);
120
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_fill), 1, mxID(_fill), XS_DONT_ENUM_FLAG);
121
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_filter), 1, mxID(_filter), XS_DONT_ENUM_FLAG);
122
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_find), 1, mxID(_find), XS_DONT_ENUM_FLAG);
123
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_findIndex), 1, mxID(_findIndex), XS_DONT_ENUM_FLAG);
124
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_findLast), 1, mxID(_findLast), XS_DONT_ENUM_FLAG);
125
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_findLastIndex), 1, mxID(_findLastIndex), XS_DONT_ENUM_FLAG);
126
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_flat), 0, mxID(_flat), XS_DONT_ENUM_FLAG);
127
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_flatMap), 1, mxID(_flatMap), XS_DONT_ENUM_FLAG);
128
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_forEach), 1, mxID(_forEach), XS_DONT_ENUM_FLAG);
129
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_includes), 1, mxID(_includes), XS_DONT_ENUM_FLAG);
130
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_indexOf), 1, mxID(_indexOf), XS_DONT_ENUM_FLAG);
131
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_join), 1, mxID(_join), XS_DONT_ENUM_FLAG);
132
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_keys), 0, mxID(_keys), XS_DONT_ENUM_FLAG);
133
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_lastIndexOf), 1, mxID(_lastIndexOf), XS_DONT_ENUM_FLAG);
134
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_map), 1, mxID(_map), XS_DONT_ENUM_FLAG);
135
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_pop), 0, mxID(_pop), XS_DONT_ENUM_FLAG);
136
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_push), 1, mxID(_push), XS_DONT_ENUM_FLAG);
137
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_reduce), 1, mxID(_reduce), XS_DONT_ENUM_FLAG);
138
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_reduceRight), 1, mxID(_reduceRight), XS_DONT_ENUM_FLAG);
139
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_reverse), 0, mxID(_reverse), XS_DONT_ENUM_FLAG);
140
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_shift), 0, mxID(_shift), XS_DONT_ENUM_FLAG);
141
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_slice), 2, mxID(_slice), XS_DONT_ENUM_FLAG);
142
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_some), 1, mxID(_some), XS_DONT_ENUM_FLAG);
143
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_sort), 1, mxID(_sort), XS_DONT_ENUM_FLAG);
144
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_splice), 2, mxID(_splice), XS_DONT_ENUM_FLAG);
145
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toLocaleString), 0, mxID(_toLocaleString), XS_DONT_ENUM_FLAG);
146
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
147
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_unshift), 1, mxID(_unshift), XS_DONT_ENUM_FLAG);
148
31.7k
  property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_values), 0, mxID(_values), XS_DONT_ENUM_FLAG);
149
31.7k
  mxPushSlot(property);
150
31.7k
  mxPull(mxArrayIteratorFunction);
151
31.7k
  slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_iterator), XS_DONT_ENUM_FLAG);
152
31.7k
  unscopable = fxLastProperty(the, fxNewInstance(the));
153
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_copyWithin), XS_NO_FLAG);
154
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_at), XS_NO_FLAG);
155
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_entries), XS_NO_FLAG);
156
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_fill), XS_NO_FLAG);
157
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_find), XS_NO_FLAG);
158
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_findIndex), XS_NO_FLAG);
159
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_findLast), XS_NO_FLAG);
160
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_findLastIndex), XS_NO_FLAG);
161
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_flat), XS_NO_FLAG);
162
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_flatMap), XS_NO_FLAG);
163
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_includes), XS_NO_FLAG);
164
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_keys), XS_NO_FLAG);
165
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_values), XS_NO_FLAG);
166
31.7k
#if mxECMAScript2023
167
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_toReversed), XS_NO_FLAG);
168
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_toSorted), XS_NO_FLAG);
169
31.7k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_toSpliced), XS_NO_FLAG);
170
31.7k
#endif
171
31.7k
  slot = fxNextSlotProperty(the, slot, the->stack++, mxID(_Symbol_unscopables), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
172
31.7k
#if mxECMAScript2023
173
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toReversed), 0, mxID(_toReversed), XS_DONT_ENUM_FLAG);
174
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toSorted), 1, mxID(_toSorted), XS_DONT_ENUM_FLAG);
175
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toSpliced), 2, mxID(_toSpliced), XS_DONT_ENUM_FLAG);
176
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_with), 2, mxID(_with), XS_DONT_ENUM_FLAG);
177
31.7k
#endif
178
31.7k
  mxArrayPrototype = *the->stack;
179
31.7k
  slot = fxBuildHostConstructor(the, mxCallback(fx_Array), 1, mxID(_Array));
180
31.7k
  mxArrayConstructor = *the->stack;
181
31.7k
  slot = fxLastProperty(the, slot);
182
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_from), 1, mxID(_from), XS_DONT_ENUM_FLAG);
183
31.7k
#if mxECMAScript2026
184
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_fromAsync), 1, mxID(_fromAsync), XS_DONT_ENUM_FLAG);
185
31.7k
#endif
186
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_isArray), 1, mxID(_isArray), XS_DONT_ENUM_FLAG);
187
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_of), 0, mxID(_of), XS_DONT_ENUM_FLAG);
188
31.7k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_species_get), C_NULL, mxID(_Symbol_species), XS_DONT_ENUM_FLAG);
189
31.7k
  mxPop();
190
191
31.7k
  mxPush(mxIteratorPrototype);
192
31.7k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
193
31.7k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_ArrayIterator_prototype_next), 0, mxID(_next), XS_DONT_ENUM_FLAG);
194
31.7k
  slot = fxNextStringXProperty(the, slot, "Array Iterator", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
195
31.7k
  mxPull(mxArrayIteratorPrototype);
196
31.7k
}
197
198
txNumber fxArgToIndex(txMachine* the, txInteger argi, txNumber index, txNumber length)
199
7.60M
{
200
7.60M
  if ((mxArgc > argi) && (mxArgv(argi)->kind != XS_UNDEFINED_KIND)) {
201
4.13M
    txNumber i = c_trunc(fxToNumber(the, mxArgv(argi)));
202
4.13M
    if (c_isnan(i) || (i == 0))
203
1.90M
      i = 0;
204
4.13M
    if (i < 0) {
205
867k
      i = length + i;
206
867k
      if (i < 0)
207
456k
        i = 0;
208
867k
    }
209
3.27M
    else if (i > length)
210
1.18M
      i = length;
211
4.13M
    index = i;
212
4.13M
  }
213
7.60M
  return index;
214
7.60M
}
215
216
txInteger fxArgToIndexInteger(txMachine* the, txInteger argi, txInteger index, txInteger length)
217
979k
{
218
979k
  if (mxArgc <= argi)
219
367
    return index;
220
221
978k
  txSlot *slot = mxArgv(argi);
222
978k
  if (slot->kind != XS_INTEGER_KIND)
223
213k
    return (txInteger)fxArgToIndex(the, argi, index, length);
224
225
765k
  index = slot->value.integer;
226
765k
  if (index < 0) {
227
958
    index = length + index;
228
958
    if (index < 0)
229
918
      index = 0;
230
958
  }
231
764k
  else if (index > length)
232
739k
    index = length;
233
234
765k
  return index;
235
978k
}
236
237
txNumber fxArgToLastIndex(txMachine* the, txInteger argi, txNumber index, txNumber length)
238
201k
{
239
201k
  if (mxArgc > argi) {
240
4.08k
    txNumber i = c_trunc(fxToNumber(the, mxArgv(argi)));
241
4.08k
    if (c_isnan(i) || (i == 0))
242
270
      i = 0;
243
4.08k
    if (i < 0) {
244
2.26k
      i = length + i;
245
2.26k
      if (i < 0)
246
20
        index = 0;
247
2.24k
      else
248
2.24k
        index = i + 1;
249
2.26k
    }
250
1.82k
    else if (i < length)
251
281
      index = i + 1;
252
4.08k
  }
253
201k
  return index;
254
201k
}
255
256
txNumber fxArgToRange(txMachine* the, txInteger argi, txNumber index, txNumber min, txNumber max)
257
612k
{
258
612k
  if ((mxArgc > argi) && (mxArgv(argi)->kind != XS_UNDEFINED_KIND)) {
259
612k
    txNumber i = c_trunc(fxToNumber(the, mxArgv(argi)));
260
612k
    if (c_isnan(i))
261
132k
      i = min;
262
612k
    if (i <= min)
263
133k
      i = min;
264
478k
    else if (i > max)
265
342k
      i = max;
266
612k
    index = i;
267
612k
  }
268
612k
  return index;
269
612k
}
270
271
txNumber fxArgToRelativeIndex(txMachine* the, txInteger argi, txNumber index, txNumber length)
272
154k
{
273
154k
  if ((mxArgc > argi) && (mxArgv(argi)->kind != XS_UNDEFINED_KIND)) {
274
151k
    txNumber i = c_trunc(fxToNumber(the, mxArgv(argi)));
275
151k
    if (c_isnan(i) || (i == 0))
276
69.2k
      i = 0;
277
151k
    if (i < 0)
278
82.4k
      i = length + i;
279
151k
    index = i;
280
151k
  }
281
154k
  return index;
282
154k
}
283
284
void fxCacheArray(txMachine* the, txSlot* instance)
285
12.3M
{
286
12.3M
  txSlot* array = instance->next;
287
12.3M
  txIndex length = array->value.array.length;
288
12.3M
  if (length) {
289
8.93M
    txSlot* address = (txSlot *)fxNewChunk(the, fxMultiplyChunkSizes(the, length, sizeof(txSlot)));
290
8.93M
    txSlot* srcSlot = array->next;
291
8.93M
    txSlot* dstSlot = address;
292
8.93M
    txIndex index = 0;
293
81.0M
    while (srcSlot) {
294
72.1M
      dstSlot->next = C_NULL;
295
72.1M
      *((txIndex*)dstSlot) = index; 
296
72.1M
      dstSlot->ID = XS_NO_ID;
297
72.1M
      dstSlot->flag = XS_NO_FLAG;
298
72.1M
      dstSlot->kind = srcSlot->kind;
299
72.1M
      dstSlot->value = srcSlot->value;
300
72.1M
      srcSlot = srcSlot->next;
301
72.1M
      dstSlot++;
302
72.1M
      index++;
303
72.1M
    }
304
8.93M
    array->value.array.address = address;
305
8.93M
    array->next = C_NULL;
306
8.93M
  }
307
12.3M
}
308
309
txBoolean fxCallThisItem(txMachine* the, txSlot* function, txIndex index, txSlot* item)
310
6.88M
{
311
6.88M
  mxPushSlot(mxThis);
312
6.88M
  if (mxHasIndex(index)) {
313
    /* THIS */
314
344k
    if (mxArgc > 1)
315
3.99k
      mxPushSlot(mxArgv(1));
316
340k
    else
317
340k
      mxPushUndefined();
318
    /* FUNCTION */
319
344k
    mxPushSlot(function);
320
344k
    mxCall();
321
    /* ARGUMENTS */
322
344k
    mxPushSlot(mxThis);
323
344k
    mxGetIndex(index);
324
344k
    if (item) {
325
144k
      item->kind = the->stack->kind;
326
144k
      item->value = the->stack->value;
327
144k
    }
328
344k
    mxPushUnsigned(index);
329
344k
    mxPushSlot(mxThis);
330
344k
    mxRunCount(3);
331
344k
    return 1;
332
344k
  }
333
6.53M
  return 0;
334
6.88M
}
335
336
txSlot* fxCheckArray(txMachine* the, txSlot* slot, txBoolean mutable)
337
4.78M
{
338
4.78M
  txSlot* instance = fxToInstance(the, slot);
339
4.78M
  txSlot* array = instance->next;
340
4.78M
  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.70M
    {
353
4.70M
      txSlot* address = array->value.array.address;
354
4.70M
      txIndex size = (address) ? (((txChunk*)(((txByte*)address) - sizeof(txChunk)))->size) / sizeof(txSlot) : 0;
355
4.70M
      txSlot* prototype = instance->value.instance.prototype;
356
4.70M
      if (array->value.array.length != size)
357
1.85M
        return C_NULL;
358
2.85M
      if (mutable && ((instance->flag & XS_DONT_PATCH_FLAG) || (array->flag & XS_DONT_SET_FLAG)))
359
6
        return C_NULL;
360
8.55M
      while (prototype) {
361
5.70M
        txSlot* property = prototype->next;
362
8.55M
        while (property) {
363
8.55M
          if (property->flag & XS_INTERNAL_FLAG) {
364
2.85M
            if ((property->kind == XS_ARRAY_KIND) && (property->value.array.address != C_NULL)) 
365
3.72k
              return C_NULL;
366
2.85M
          }
367
5.69M
          else 
368
5.69M
            break;
369
2.84M
          property = property->next;
370
2.84M
        }
371
5.69M
        prototype = prototype->value.instance.prototype;
372
5.69M
      }        
373
2.84M
      return array;
374
2.85M
    }
375
2.85M
  }
376
72.8k
  return C_NULL;
377
4.78M
}
378
379
txSlot* fxCheckArrayItems(txMachine* the, txSlot* array, txIndex from, txIndex to)
380
1.52M
{
381
1.52M
  txSlot* address = array->value.array.address;
382
1.52M
  txIndex length = array->value.array.length;
383
1.52M
  if (length < from)
384
0
    return C_NULL;
385
1.52M
  if (length < to)
386
455
    return C_NULL;
387
1.52M
  address += from;
388
5.30M
  while (from < to) {
389
3.78M
    if (address->flag)
390
1.41k
      return C_NULL;
391
3.77M
    if (address->kind == XS_ACCESSOR_KIND)
392
2
      return C_NULL;
393
3.77M
    address++;
394
3.77M
    from++;
395
3.77M
  }
396
1.51M
  return array;
397
1.52M
}
398
399
txIndex fxCheckArrayLength(txMachine* the, txSlot* slot)
400
6.45M
{
401
6.45M
  if (slot->kind == XS_INTEGER_KIND) {
402
5.97M
    if (slot->value.integer >= 0)
403
5.97M
      return (txIndex)slot->value.integer;
404
5.97M
  }
405
474k
  else if (slot->kind == XS_NUMBER_KIND) {
406
474k
    txIndex length = (txIndex)slot->value.number;
407
474k
    txNumber check = length;
408
474k
    if (slot->value.number == check)
409
474k
      return length;
410
474k
  }
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
102
      return length;
422
111
  }
423
6.45M
  mxRangeError("invalid length");
424
0
  return 0;
425
6.45M
}
426
427
int fxCompareArrayItem(txMachine* the, txSlot* function, txSlot* array, txInteger i)
428
690k
{
429
690k
  txSlot* address = array->value.array.address;
430
690k
  txSlot* a = address + i;
431
690k
  txSlot* b = the->stack;
432
690k
  txSlot* ai = a->next;
433
690k
  txSlot* bi = b->next;
434
690k
  int result;
435
  
436
690k
  if (a->kind == XS_UNDEFINED_KIND)
437
5.16k
    result = (b->kind == XS_UNDEFINED_KIND) ? 0 : 1;
438
685k
  else if (b->kind == XS_UNDEFINED_KIND)
439
228
    result = -1;
440
685k
  else {
441
685k
    if (function) {
442
      /* THIS */
443
494k
      mxPushUndefined();
444
      /* FUNCTION */
445
494k
      mxPushSlot(function);
446
494k
      mxCall();
447
      /* ARGUMENTS */
448
494k
      mxPushSlot(a);
449
494k
      mxPushSlot(b);
450
494k
      mxRunCount(2);
451
494k
      if (the->stack->kind == XS_INTEGER_KIND)
452
181k
        result = the->stack->value.integer;
453
313k
      else {
454
313k
        txNumber number = fxToNumber(the, the->stack);
455
313k
        result = (number < 0) ? -1 :  (number > 0) ? 1 : 0;
456
313k
      }
457
494k
      mxPop();
458
494k
    }
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
685k
  }
470
690k
  if (result == 0)
471
151k
    result = (bi > ai) ? -1 : (bi < ai) ? 1 : 0;
472
690k
  return result;
473
690k
}
474
475
void fxConstructArrayEntry(txMachine* the, txSlot* entry)
476
39.3k
{
477
39.3k
  txSlot* value = the->stack;
478
39.3k
  txSlot* key = the->stack + 1;
479
39.3k
  txSlot* instance;
480
39.3k
  txSlot* array;
481
39.3k
  txSlot* item;
482
39.3k
  mxPush(mxArrayPrototype);
483
39.3k
  instance = fxNewArrayInstance(the);
484
39.3k
  array = instance->next;
485
39.3k
  fxSetIndexSize(the, array, 2, XS_CHUNK);
486
39.3k
  item = array->value.array.address;
487
39.3k
  *((txIndex*)item) = 0;
488
39.3k
  item->ID = XS_NO_ID;
489
39.3k
  item->kind = key->kind;
490
39.3k
  item->value = key->value;
491
39.3k
  item++;
492
39.3k
  *((txIndex*)item) = 1;
493
39.3k
  item->ID = XS_NO_ID;
494
39.3k
  item->kind = value->kind;
495
39.3k
  item->value = value->value;
496
39.3k
  entry->kind = the->stack->kind;
497
39.3k
  entry->value = the->stack->value;
498
39.3k
  the->stack += 3;
499
39.3k
}
500
501
txSlot* fxCreateArray(txMachine* the, txFlag flag, txIndex length)
502
510k
{
503
510k
  if (mxIsReference(mxThis) && mxIsConstructor(mxThis->value.reference))
504
62.4k
    mxPushSlot(mxThis);
505
448k
  else
506
448k
    mxPush(mxArrayConstructor);
507
510k
  mxNew();
508
510k
  if (flag) {
509
168k
    mxPushUnsigned(length);
510
168k
    mxRunCount(1);
511
168k
  }
512
342k
  else
513
342k
    mxRunCount(0);
514
510k
  mxPullSlot(mxResult);
515
510k
  return fxCheckArray(the, mxResult, XS_MUTABLE);
516
510k
}
517
518
txSlot* fxCreateArraySpecies(txMachine* the, txNumber length)
519
449k
{
520
449k
  txSlot* instance = fxToInstance(the, mxThis);
521
449k
  txFlag flag = 1;
522
449k
  if (fxIsArray(the, instance)) {
523
266k
    mxPushSlot(mxThis);
524
266k
    mxGetID(mxID(_constructor));
525
266k
    if (mxIsReference(the->stack)) {
526
266k
      mxGetID(mxID(_Symbol_species));
527
266k
      if (the->stack->kind == XS_NULL_KIND)
528
1
        the->stack->kind = XS_UNDEFINED_KIND;
529
266k
    }
530
266k
  }
531
182k
  else
532
182k
    mxPushUndefined();
533
449k
    if (the->stack->kind == XS_UNDEFINED_KIND) {
534
182k
    *the->stack = mxArrayConstructor;
535
182k
        flag = 0;
536
182k
    }
537
266k
  else if (mxIsReference(the->stack) && mxIsConstructor(the->stack->value.reference)) {
538
266k
    if (the->stack->value.reference != mxArrayConstructor.value.reference)
539
18
      flag = 0;
540
266k
  }
541
38
  else
542
38
    mxTypeError("invalid constructor");
543
449k
  mxNew();
544
449k
  mxPushNumber(length);
545
449k
  mxRunCount(1);
546
449k
  mxPullSlot(mxResult);
547
449k
  return (flag) ? mxResult->value.reference->next : C_NULL;
548
449k
}
549
550
void fxFindThisItem(txMachine* the, txSlot* function, txNumber index, txSlot* item)
551
57.3k
{
552
  /* THIS */
553
57.3k
  if (mxArgc > 1)
554
4
    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
144
    item->kind = the->stack->kind;
565
144
    item->value = the->stack->value;
566
144
  }
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.82M
{
575
3.82M
  txNumber length;
576
3.82M
  txSlot* instance = fxToInstance(the, reference);
577
3.82M
  mxPushReference(instance);
578
3.82M
  mxGetID(mxID(_length));
579
3.82M
  length = fxToLength(the, the->stack);
580
3.82M
  mxPop();
581
3.82M
  return length;
582
3.82M
}
583
584
txIndex fxGetArrayLimit(txMachine* the, txSlot* reference)
585
7.58M
{
586
7.58M
  txNumber length;
587
7.58M
  txSlot* instance = fxToInstance(the, reference);
588
7.58M
  txSlot* array = instance->next;
589
7.58M
  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.43M
    return array->value.array.length;
598
7.43M
  }
599
154k
  if (array && (array->kind == XS_TYPED_ARRAY_KIND) && (array->ID == XS_TYPED_ARRAY_BEHAVIOR)) {
600
9.12k
    txSlot* view = array->next;
601
9.12k
    txSlot* buffer = view->next;
602
9.12k
    if (mxThis->value.reference != instance) { // iterator
603
9.12k
      if (fxIsDataViewOutOfBound(the, view, buffer))
604
1
        mxTypeError("out of bound buffer");
605
9.12k
    }
606
9.12k
    return fxGetDataViewSize(the, view, buffer) >> array->value.typedArray.dispatch->shift;
607
9.12k
  }
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
154k
}
625
626
void fxIndexArray(txMachine* the, txSlot* array) 
627
7.68M
{
628
7.68M
  txSlot* address = array->value.array.address;
629
7.68M
  if (address) {
630
1.45M
    txIndex size = (((txChunk*)(((txByte*)address) - sizeof(txChunk)))->size) / sizeof(txSlot);
631
1.45M
    txIndex index = 0;
632
14.8M
    while (index < size) {
633
13.4M
      *((txIndex*)address) = index; 
634
13.4M
      address->flag = XS_NO_FLAG;
635
13.4M
      address++;
636
13.4M
      index++;
637
13.4M
    }
638
1.45M
  }
639
7.68M
}
640
641
txBoolean fxIsArray(txMachine* the, txSlot* instance) 
642
1.44M
{
643
1.46M
again:
644
1.46M
  if (instance) {
645
1.46M
    txSlot* internal = instance->next;
646
1.46M
    if (internal && (internal->flag & XS_INTERNAL_FLAG)) {
647
967k
      if ((internal->kind == XS_ARRAY_KIND) && (internal->ID == XS_ARRAY_BEHAVIOR))
648
324k
        return 1;
649
643k
      if (internal->kind == XS_PROXY_KIND) {
650
21.4k
        instance = internal->value.proxy.target;
651
21.4k
        if (instance)
652
21.4k
          goto again;
653
21.4k
        mxTypeError("revoked proxy");
654
655
21.4k
      }
656
643k
    }
657
1.46M
  }
658
1.11M
  return 0;
659
1.46M
}
660
661
void fxMoveThisItem(txMachine* the, txNumber from, txNumber to)
662
4.40M
{
663
4.40M
  mxPushSlot(mxThis);
664
4.40M
  mxPushNumber(from);
665
4.40M
  if (mxHasAt()) {
666
379k
    mxPushSlot(mxThis);
667
379k
    mxPushNumber(from);
668
379k
    mxGetAt();
669
379k
    mxPushSlot(mxThis);
670
379k
    mxPushNumber(to);
671
379k
    mxSetAt();
672
379k
    mxPop();
673
379k
  }
674
4.02M
  else {
675
4.02M
    mxPushSlot(mxThis);
676
4.02M
    mxPushNumber(to);
677
4.02M
    mxDeleteAt();
678
4.02M
    mxPop();
679
4.02M
  }
680
4.40M
}
681
682
txSlot* fxNewArrayInstance(txMachine* the)
683
21.9M
{
684
21.9M
  txSlot* instance;
685
21.9M
  txSlot* property;
686
21.9M
  instance = fxNewObjectInstance(the);
687
21.9M
  instance->flag |= XS_EXOTIC_FLAG;
688
21.9M
  property = instance->next = fxNewSlot(the);
689
21.9M
  property->flag = XS_INTERNAL_FLAG | XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG;
690
21.9M
  property->ID = XS_ARRAY_BEHAVIOR;
691
21.9M
  property->kind = XS_ARRAY_KIND;
692
21.9M
  property->value.array.length = 0;
693
21.9M
  property->value.array.address = C_NULL;
694
21.9M
  return instance;
695
21.9M
}
696
697
void fxReduceThisItem(txMachine* the, txSlot* function, txIndex index)
698
8.73k
{
699
8.73k
  mxPushSlot(mxThis);
700
8.73k
  if (fxHasIndex(the, index)) {
701
    /* THIS */
702
5.32k
    mxPushUndefined();
703
    /* FUNCTION */
704
5.32k
    mxPushSlot(function);
705
5.32k
    mxCall();
706
    /* ARGUMENTS */
707
5.32k
    mxPushSlot(mxResult);
708
5.32k
    mxPushSlot(mxThis);
709
5.32k
    mxGetIndex(index);
710
5.32k
    mxPushUnsigned(index);
711
5.32k
    mxPushSlot(mxThis);
712
5.32k
    mxRunCount(4);
713
5.32k
    mxPullSlot(mxResult);
714
5.32k
  }
715
8.73k
}
716
717
txBoolean fxSetArrayLength(txMachine* the, txSlot* array, txIndex length)
718
6.45M
{
719
6.45M
  txSlot* address = array->value.array.address;
720
6.45M
  txSlot* chunk = address;
721
6.45M
  txBoolean success = 1;
722
6.45M
  if (address) {
723
327k
    txSize size = (((txChunk*)(((txByte*)chunk) - sizeof(txChunk)))->size) / sizeof(txSlot);
724
327k
    txSlot* result = address + size;
725
327k
    txSlot* limit = result;
726
327k
    txIndex at;
727
2.21M
    while (result > address) {
728
2.21M
      result--;
729
2.21M
      at = *((txIndex*)result);
730
2.21M
      if (length > at) {
731
327k
        result++;
732
327k
        break;
733
327k
      }
734
1.89M
      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
2.21M
    }
741
327k
    if (result < limit) {
742
1.35k
      if (result > address) {
743
1.26k
        size = mxPtrDiff(result - address);
744
1.26k
        chunk = (txSlot*)fxNewChunk(the, fxMultiplyChunkSizes(the, size, sizeof(txSlot)));
745
1.26k
        address = array->value.array.address;
746
1.26k
        c_memcpy(chunk, address, size * sizeof(txSlot));
747
1.26k
      }
748
96
      else
749
96
        chunk = C_NULL;
750
1.35k
    }  
751
327k
  }
752
6.45M
  array->value.array.length = length;
753
6.45M
  array->value.array.address = chunk;
754
6.45M
  return success;
755
6.45M
}
756
757
void fxSortArrayItems(txMachine* the, txSlot* function, txSlot* array, txNumber LENGTH, txSlot* target)
758
231k
{
759
231k
  txBoolean flag = mxThis->value.reference != target->value.reference;
760
231k
  txSlot* instance = C_NULL;
761
231k
  txIndex index;
762
231k
    txSlot* item;
763
231k
  txIndex length;
764
231k
  txIndex size;
765
231k
again:
766
231k
  if (!array) {
767
231k
    LENGTH = fxGetArrayLength(the, mxThis);
768
231k
    if (LENGTH > 0xFFFFFFFF)
769
0
      mxRangeError("array overflow");
770
231k
    mxPush(mxArrayPrototype);
771
231k
    instance = fxNewArrayInstance(the);
772
231k
    array = instance->next;
773
231k
    item = array;
774
231k
        index = 0;
775
6.29M
    while (index < LENGTH) {
776
6.06M
      mxPushSlot(mxThis);
777
6.06M
      if (flag || fxHasIndex(the, index)) {
778
4.28M
        item->next = fxNewSlot(the);
779
4.28M
        item = item->next;
780
4.28M
        array->value.array.length++;
781
4.28M
        mxPushSlot(mxThis);
782
4.28M
        mxGetIndex(index);
783
4.28M
        mxPullSlot(item);
784
4.28M
      }
785
6.06M
      index++;
786
6.06M
    }
787
231k
    fxCacheArray(the, instance);
788
231k
  }
789
231k
  length = array->value.array.length;
790
231k
  size = mxArraySize(array);
791
  /* like GCC qsort */
792
231k
  #define CHECK \
793
706k
    if (size != mxArraySize(array)) { \
794
0
      array = C_NULL; \
795
0
      goto again; \
796
0
    }
797
231k
  #define COMPARE(INDEX) \
798
699k
    fxCompareArrayItem(the, function, array, INDEX)
799
231k
  #define COPY \
800
304k
    to->next = from->next; \
801
304k
    to->ID = from->ID; \
802
304k
    to->kind = from->kind; \
803
304k
    to->value = from->value
804
231k
  #define MOVE(FROM,TO) \
805
231k
    from = array->value.array.address + (FROM); \
806
106k
    to = array->value.array.address + (TO); \
807
106k
    COPY
808
231k
  #define PUSH(INDEX) \
809
231k
    from = array->value.array.address + (INDEX); \
810
106k
    mxPushUndefined(); \
811
106k
    to = the->stack; \
812
106k
    COPY
813
231k
  #define PULL(INDEX) \
814
231k
    from = the->stack++; \
815
91.3k
    to = array->value.array.address + (INDEX); \
816
91.3k
    COPY
817
231k
  if (length > 0) {
818
49.3k
    txIndex i, j;
819
49.3k
    txSlot* from;
820
49.3k
    txSlot* to;
821
49.3k
    if (length > mxSortThreshold) {
822
8.05k
      txIndex lo = 0, hi = length - 1;
823
8.05k
      txSortPartition stack[mxSortPartitionCount];
824
8.05k
      txSortPartition *top = stack + 1;
825
22.9k
      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.02k
          CHECK;
830
4.02k
          MOVE(lo, mid);
831
4.02k
          PULL(lo);
832
4.02k
          PUSH(mid);
833
4.02k
        }
834
10.9k
        else
835
14.9k
          CHECK;
836
14.9k
        if (COMPARE(hi) < 0) {
837
2.17k
          CHECK;
838
2.17k
          MOVE(hi, mid);
839
2.17k
          PULL(hi);
840
2.17k
          PUSH(mid);
841
2.17k
          if (COMPARE(lo) > 0) {
842
387
            CHECK;
843
387
            MOVE(lo, mid);
844
387
            PULL(lo);
845
387
            PUSH(mid);
846
387
          }
847
1.78k
          else
848
2.17k
            CHECK;
849
2.17k
        }
850
12.7k
        else
851
14.9k
          CHECK;
852
14.9k
        i = lo + 1;
853
14.9k
        j = hi - 1;
854
24.0k
        do {
855
171k
          while ((COMPARE(i) < 0) && (i <= j)) { CHECK; i++; }
856
48.1k
                    CHECK;
857
337k
          while ((COMPARE(j) > 0) && (i <= j)) { CHECK; j--; }
858
48.1k
          CHECK;
859
48.1k
          if (i < j) {
860
10.0k
            PUSH(i);
861
10.0k
            MOVE(j, i);
862
10.0k
            PULL(j);
863
10.0k
            i++;
864
10.0k
            j--;
865
10.0k
          }
866
14.0k
          else if (i == j) {
867
6.95k
            i++;
868
6.95k
            j--;
869
6.95k
            break;
870
6.95k
          }
871
48.1k
        } while (i <= j);
872
14.9k
        if ((j - lo) <= mxSortThreshold) {
873
8.71k
          if ((hi - i) <= mxSortThreshold) {
874
6.94k
            top--;
875
6.94k
            lo = top->lo; 
876
6.94k
            hi = top->hi;
877
6.94k
          }
878
1.77k
          else {
879
1.77k
            lo = i;
880
1.77k
          }
881
8.71k
        }
882
6.21k
        else if ((hi - i) <= mxSortThreshold) {
883
1.36k
          hi = j;
884
1.36k
        }
885
4.84k
        else if ((j - lo) > (hi - i)) {
886
181
          top->lo = lo;
887
181
          top->hi = j; 
888
181
          top++;
889
181
          lo = i;
890
181
        }
891
4.66k
        else {
892
4.66k
          top->lo = i;
893
4.66k
          top->hi = hi; 
894
4.66k
          top++;
895
4.66k
          hi = j;
896
4.66k
        }
897
14.9k
        mxPop();
898
14.9k
      }
899
8.05k
    }
900
124k
    for (i = 1; i < length; i++) {
901
74.6k
      PUSH(i);
902
164k
      for (j = i; (j > 0) && (COMPARE(j - 1) > 0); j--) {
903
90.0k
        CHECK;
904
90.0k
        MOVE(j - 1, j);
905
90.0k
      }
906
149k
            CHECK;
907
149k
      PULL(j);
908
149k
    }
909
49.3k
  }
910
231k
  if (instance) {
911
216k
    index = 0;
912
315k
    while (index < length) {
913
98.7k
      item = array->value.array.address + index;
914
98.7k
      mxPushSlot(item);
915
98.7k
      mxPushSlot(target);
916
98.7k
      if (flag)
917
21.9k
        mxDefineIndex(index, 0, XS_GET_ONLY);
918
76.7k
      else
919
76.7k
        mxSetIndex(index);
920
98.7k
      mxPop();
921
98.7k
      index++;
922
98.7k
    }
923
311k
    while (index < LENGTH) {
924
94.5k
      mxPushSlot(target);
925
94.5k
      mxDeleteIndex(index);
926
94.5k
      mxPop();
927
94.5k
      index++;
928
94.5k
    }
929
216k
    mxPop();
930
216k
  }
931
14.1k
  else
932
14.1k
    fxIndexArray(the, array);
933
231k
}
934
935
txNumber fxToLength(txMachine* the, txSlot* slot)
936
16.2M
{
937
16.3M
again:
938
16.3M
  if (slot->kind == XS_INTEGER_KIND) {
939
12.1M
    txInteger length = slot->value.integer;
940
12.1M
    if (length < 0)
941
9
      length = 0;
942
12.1M
    slot->value.number = (txNumber)length;
943
12.1M
    slot->kind = XS_NUMBER_KIND;
944
12.1M
    return (txNumber)length;
945
12.1M
  }
946
4.23M
  if (slot->kind == XS_NUMBER_KIND) {
947
4.08M
    txNumber length = slot->value.number;
948
4.08M
    if (c_isnan(length))
949
147k
      length = 0;
950
3.93M
    else if (length <= 0)
951
37.3k
      length = 0;
952
3.89M
    else if (length > C_MAX_SAFE_INTEGER)
953
126
      length = C_MAX_SAFE_INTEGER;
954
3.89M
    else
955
3.89M
      length = c_trunc(length);
956
4.08M
    slot->value.number = length;
957
4.08M
    return length;
958
4.08M
  }
959
147k
  fxToNumber(the, slot);
960
147k
  goto again;
961
4.23M
}
962
963
void fxArrayLengthGetter(txMachine* the)
964
6.74M
{
965
6.74M
  txSlot* instance = fxToInstance(the, mxThis);
966
6.74M
  txSlot* array;
967
6.85M
  while (instance) {
968
6.85M
    if (instance->flag & XS_EXOTIC_FLAG) {
969
6.74M
      array = instance->next;
970
6.74M
      if ((array->kind == XS_ARRAY_KIND) && (array->ID == XS_ARRAY_BEHAVIOR))
971
6.74M
        break;
972
6.74M
    }
973
107k
    instance = fxGetPrototype(the, instance);
974
107k
  }
975
6.74M
  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
6.74M
  if (((txInteger)array->value.array.length) < 0) {
985
90
    mxResult->value.number = array->value.array.length;
986
90
    mxResult->kind = XS_NUMBER_KIND;
987
90
  }
988
6.74M
  else {
989
6.74M
    mxResult->value.integer = (txInteger)array->value.array.length;
990
6.74M
    mxResult->kind = XS_INTEGER_KIND;
991
6.74M
  }
992
6.74M
}
993
994
void fxArrayLengthSetter(txMachine* the)
995
5.83M
{
996
5.83M
  txSlot* instance = fxToInstance(the, mxThis);
997
5.83M
  txSlot* array;
998
5.83M
  txIndex length;
999
5.83M
  while (instance) {
1000
5.83M
    if (instance->flag & XS_EXOTIC_FLAG) {
1001
5.83M
      array = instance->next;
1002
5.83M
      if (array->ID == XS_ARRAY_BEHAVIOR)
1003
5.83M
        break;
1004
5.83M
    }
1005
13
    instance = fxGetPrototype(the, instance);
1006
13
  }
1007
5.83M
  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.83M
  length = fxCheckArrayLength(the, mxArgv(0));
1018
5.83M
  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.83M
  fxSetArrayLength(the, array, length);
1025
5.83M
}
1026
1027
txBoolean fxArrayDefineOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* descriptor, txFlag mask) 
1028
19.3M
{
1029
19.3M
  if (id == mxID(_length)) {
1030
160
    txSlot* array = instance->next;
1031
160
    txSlot slot;
1032
160
    txBoolean result = 1;
1033
160
        txIndex length = ((descriptor->kind != XS_UNINITIALIZED_KIND) && (descriptor->kind != XS_ACCESSOR_KIND)) ? fxCheckArrayLength(the, descriptor) : 0;
1034
160
        slot.flag = array->flag;
1035
160
    slot.ID = id;
1036
160
    slot.kind = XS_NUMBER_KIND;
1037
160
    slot.value.number = array->value.array.length;
1038
160
    if (!fxIsPropertyCompatible(the, &slot, descriptor, mask))
1039
27
      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
133
    if (descriptor->kind != XS_UNINITIALIZED_KIND) {
1050
20
      if (array->value.array.length != length)
1051
13
        result = fxSetArrayLength(the, array, length);
1052
20
    }
1053
133
    if ((mask & XS_DONT_SET_FLAG) && (descriptor->flag & XS_DONT_SET_FLAG) && !(array->flag & XS_DONT_SET_FLAG))
1054
76
      array->flag |= XS_DONT_SET_FLAG;
1055
133
    return result;
1056
160
  }
1057
19.3M
  return fxOrdinaryDefineOwnProperty(the, instance, id, index, descriptor, mask);
1058
19.3M
}
1059
1060
txBoolean fxArrayDeleteProperty(txMachine* the, txSlot* instance, txID id, txIndex index)
1061
1.77M
{
1062
1.77M
  if (id == mxID(_length))
1063
1
    return 0;
1064
1.77M
  return fxOrdinaryDeleteProperty(the, instance, id, index);
1065
1.77M
}
1066
1067
txBoolean fxArrayGetOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* descriptor)
1068
576k
{
1069
576k
  if (id == mxID(_length)) {
1070
30.8k
    txSlot* array = instance->next;
1071
30.8k
    descriptor->flag = array->flag;
1072
30.8k
    descriptor->ID = id;
1073
30.8k
    descriptor->kind = XS_NUMBER_KIND;
1074
30.8k
    descriptor->value.number = array->value.array.length;
1075
30.8k
    return 1;
1076
30.8k
  }
1077
545k
  return fxOrdinaryGetOwnProperty(the, instance, id, index, descriptor);
1078
576k
}
1079
1080
txSlot* fxArrayGetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag)
1081
171M
{
1082
171M
  if (id == mxID(_length))
1083
6.74M
    return &mxArrayLengthAccessor;
1084
165M
  return fxOrdinaryGetProperty(the, instance, id, index, flag);
1085
171M
}
1086
1087
txBoolean fxArrayHasProperty(txMachine* the, txSlot* instance, txID id, txIndex index) 
1088
43.2M
{
1089
43.2M
  if (id == mxID(_length))
1090
3
    return 1;
1091
43.2M
  return fxOrdinaryHasProperty(the, instance, id, index);
1092
43.2M
}
1093
1094
void fxArrayOwnKeys(txMachine* the, txSlot* instance, txFlag flag, txSlot* keys)
1095
26.3k
{
1096
26.3k
  txSlot* property = instance->next;
1097
26.3k
  keys = fxQueueIndexKeys(the, property, flag, keys);
1098
26.3k
  if (flag & XS_EACH_NAME_FLAG)
1099
26.3k
    keys = fxQueueKey(the, mxID(_length), 0, keys);
1100
26.3k
  property = property->next;
1101
26.3k
  fxQueueIDKeys(the, property, flag, keys);
1102
26.3k
}
1103
1104
txSlot* fxArraySetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag)
1105
24.3M
{
1106
24.3M
  if (id == mxID(_length)) {
1107
5.83M
    txSlot* array = instance->next;
1108
5.83M
    if (array->flag & XS_DONT_SET_FLAG)
1109
1.29k
      return array;
1110
5.83M
    return &mxArrayLengthAccessor;
1111
5.83M
  }
1112
18.5M
  return fxOrdinarySetProperty(the, instance, id, index, flag);
1113
24.3M
}
1114
1115
void fx_Array(txMachine* the)
1116
1.19M
{
1117
1.19M
  txSlot* instance;
1118
1.19M
  txSlot* array;
1119
1.19M
  txSlot* argument;
1120
1.19M
  txIndex count = (txIndex)mxArgc;
1121
1.19M
  txBoolean flag = 0;
1122
1.19M
  txIndex index = 0;
1123
1.19M
  txSlot* slot;
1124
  
1125
1.19M
  if (!mxHasTarget)
1126
202k
    mxPushSlot(mxFunction);
1127
991k
  else
1128
991k
    mxPushSlot(mxTarget);
1129
1.19M
  fxGetPrototypeFromConstructor(the, &mxArrayPrototype);
1130
1.19M
  instance = fxNewArrayInstance(the);
1131
1.19M
  mxPullSlot(mxResult);
1132
1.19M
  array = instance->next; 
1133
  
1134
1.19M
  if (count == 1) {
1135
641k
    argument = mxArgv(0);
1136
641k
    if ((argument->kind == XS_INTEGER_KIND) || (argument->kind == XS_NUMBER_KIND)) {
1137
619k
      count = fxCheckArrayLength(the, mxArgv(0));
1138
619k
      flag = 1;
1139
619k
    }
1140
641k
  }
1141
1.19M
  if (array) {
1142
1.19M
    if (flag)
1143
619k
      fxSetArrayLength(the, array, count);
1144
574k
    else {
1145
574k
      fxSetIndexSize(the, array, count, XS_CHUNK);
1146
574k
      slot = array->value.array.address;
1147
945k
      while (index < count) {
1148
370k
        argument = mxArgv(index);
1149
370k
        *((txIndex*)slot) = index;
1150
370k
        slot->ID = XS_NO_ID;
1151
370k
        slot->kind = argument->kind;
1152
370k
        slot->value = argument->value;
1153
370k
        slot++;
1154
370k
        index++;
1155
370k
      }
1156
574k
    }
1157
1.19M
  }
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.19M
}
1174
1175
void fx_Array_from(txMachine* the)
1176
510k
{
1177
510k
  txSlot* function = (mxArgc > 1) && !mxIsUndefined(mxArgv(1)) ? fxArgToCallback(the, 1) : C_NULL;
1178
510k
  txIndex length = 0;
1179
510k
  txSlot* iterator;
1180
510k
  txSlot* next;
1181
510k
  txSlot* value;
1182
510k
  if (mxArgc > 0) {
1183
371k
    mxPushSlot(mxArgv(0));
1184
371k
    mxGetID(mxID(_Symbol_iterator));
1185
371k
    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
342k
    else {
1204
342k
      fxCreateArray(the, 0, 0);
1205
342k
      mxTemporary(iterator);
1206
342k
      mxTemporary(next);
1207
342k
      fxGetIterator(the, mxArgv(0), iterator, next, 0);
1208
342k
      mxTemporary(value);
1209
342k
      length = 0;
1210
3.41M
      while (fxIteratorNext(the, iterator, next, value)) {
1211
3.07M
        mxTry(the) {
1212
3.07M
          fx_Array_from_aux(the, function, value, length);
1213
3.07M
          length++;
1214
3.07M
        }
1215
3.07M
        mxCatch(the) {
1216
4
          fxIteratorReturn(the, iterator, 1);
1217
4
          fxJump(the);
1218
4
        }
1219
3.07M
      }
1220
342k
      mxPop();
1221
342k
    }
1222
371k
  }
1223
139k
  else {
1224
139k
    fxCreateArray(the, 1, 0);
1225
139k
  }
1226
510k
  mxPushUnsigned(length);
1227
510k
  mxPushSlot(mxResult);
1228
510k
  mxSetID(mxID(_length));
1229
510k
  mxPop();
1230
510k
}
1231
1232
void fx_Array_from_aux(txMachine* the, txSlot* function, txSlot* value, txIndex index)
1233
3.07M
{
1234
3.07M
  if (function) {
1235
    /* THIS */
1236
62
    if (mxArgc > 2)
1237
36
      mxPushSlot(mxArgv(2));
1238
26
    else
1239
26
      mxPushUndefined();
1240
    /* FUNCTION */
1241
62
    mxPushSlot(function);
1242
62
    mxCall();
1243
    /* ARGUMENTS */
1244
62
    mxPushSlot(value);
1245
62
    mxPushInteger(index);
1246
62
    mxRunCount(2);
1247
62
  }
1248
3.07M
  else
1249
3.07M
    mxPushSlot(value);
1250
3.07M
  mxPushSlot(mxResult);
1251
3.07M
  mxDefineIndex(index, 0, XS_GET_ONLY);
1252
3.07M
  mxPop();
1253
3.07M
}
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
287
{
1527
287
  mxResult->kind = XS_BOOLEAN_KIND;
1528
287
  mxResult->value.boolean = (mxArgc > 0) ? fxIsArray(the, fxGetInstance(the, mxArgv(0))) : 0;
1529
287
}
1530
1531
void fx_Array_of(txMachine* the)
1532
45
{
1533
45
  txIndex count = (txIndex)mxArgc, index = 0;
1534
45
  txSlot* array = fxCreateArray(the, 1, count);
1535
45
  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
31
  else {
1552
98
    while (index < count) {
1553
67
      mxPushSlot(mxArgv(index));
1554
67
      mxPushSlot(mxResult);
1555
67
      mxDefineIndex(index, 0, XS_GET_ONLY);
1556
67
      mxPop();
1557
67
      index++;
1558
67
    }
1559
31
    mxPushInteger(count);
1560
31
    mxPushSlot(mxResult);
1561
31
    mxSetID(mxID(_length));
1562
31
    mxPop();
1563
31
  }
1564
45
}
1565
1566
void fx_Array_prototype_at(txMachine* the)
1567
9.99k
{
1568
9.99k
  txSlot* array = fxCheckArray(the, mxThis, XS_IMMUTABLE);
1569
9.99k
  txNumber length = (array) ? array->value.array.length : fxGetArrayLength(the, mxThis);
1570
9.99k
  txNumber index = (mxArgc > 0) ? c_trunc(fxToNumber(the, mxArgv(0))) : C_NAN;
1571
9.99k
  if (c_isnan(index) || (index == 0))
1572
9.76k
    index = 0;
1573
9.99k
  if (index < 0)
1574
211
    index = length + index;
1575
9.99k
  if ((0 <= index) && (index < length)) {
1576
7.27k
    mxPushSlot(mxThis);
1577
7.27k
    mxPushNumber(index);
1578
7.27k
    mxGetAt();
1579
7.27k
    mxPullSlot(mxResult);
1580
7.27k
  }
1581
9.99k
}
1582
1583
void fx_Array_prototype_concat(txMachine* the)
1584
1.92k
{
1585
1.92k
  txSlot* resultArray = fxCreateArraySpecies(the, 0);
1586
1.92k
  txIndex resultLength = 0;
1587
1.92k
  txInteger c = mxArgc;
1588
1.92k
  txInteger i = -1;
1589
1.92k
  if (resultArray) {
1590
1.88k
    txSlot* list = fxNewInstance(the);
1591
1.88k
    txSlot* slot = list;
1592
1.88k
    txSlot* resultSlot;
1593
1.88k
    txIndex holeCount = 0;
1594
1.88k
    mxPushSlot(mxThis);
1595
8.59k
    for (;;) {
1596
8.59k
      txSlot* argument = the->stack;
1597
8.59k
      txBoolean flag = 0;
1598
8.59k
      if (mxIsReference(argument)) {
1599
1.94k
        mxPushSlot(argument);
1600
1.94k
        mxGetID(mxID(_Symbol_isConcatSpreadable));
1601
1.94k
        if (mxIsUndefined(the->stack))
1602
1.92k
          flag = fxIsArray(the, argument->value.reference);
1603
23
        else
1604
23
          flag = fxToBoolean(the, the->stack);
1605
1.94k
        mxPop();
1606
1.94k
      }
1607
8.59k
      if (flag) { 
1608
1.91k
        txIndex length, index;
1609
1.91k
        mxPushSlot(argument);
1610
1.91k
        mxGetID(mxID(_length));
1611
1.91k
        length = (txIndex)fxToLength(the, the->stack);
1612
1.91k
        mxPop();
1613
1.91k
                if (resultLength + length < resultLength)
1614
3
                    mxTypeError("array overflow");
1615
1.91k
        index = 0;
1616
2.52k
        while (index < length) {
1617
607
          mxPushSlot(argument);
1618
607
          if (fxHasIndex(the, index)) {
1619
269
            mxPushSlot(argument);
1620
269
            mxGetIndex(index);
1621
269
            slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
1622
269
            mxMeterSome(2);
1623
269
            mxPop();
1624
269
          }
1625
338
          else {
1626
338
            slot = slot->next = fxNewSlot(the);
1627
338
            slot->kind = XS_UNINITIALIZED_KIND;
1628
338
            holeCount++;
1629
338
          }
1630
607
          index++;
1631
607
          resultLength++;
1632
607
        }
1633
1.91k
      }
1634
6.67k
      else {
1635
6.67k
        slot = fxNextSlotProperty(the, slot, argument, XS_NO_ID, XS_NO_FLAG);
1636
6.67k
        mxMeterSome(4);
1637
6.67k
        resultLength++;
1638
6.67k
        if (resultLength == 0)
1639
0
          mxTypeError("array overflow");
1640
6.67k
      }
1641
8.58k
      mxPop();
1642
8.58k
      i++;
1643
8.58k
      if (i == c)
1644
1.87k
        break;
1645
6.71k
      mxPushSlot(mxArgv(i));
1646
6.71k
    }
1647
1.87k
    fxSetIndexSize(the, resultArray, resultLength - holeCount, XS_CHUNK);
1648
1.87k
    resultArray->value.array.length = resultLength;
1649
1.87k
    resultSlot = resultArray->value.array.address;
1650
1.87k
    slot = list->next;
1651
1.87k
    resultLength = 0;
1652
9.15k
    while (slot) {
1653
7.27k
      if (slot->kind != XS_UNINITIALIZED_KIND) {
1654
6.93k
        *((txIndex*)resultSlot) = resultLength;
1655
6.93k
        resultSlot->ID = XS_NO_ID;
1656
6.93k
        resultSlot->kind = slot->kind;
1657
6.93k
        resultSlot->value = slot->value;
1658
6.93k
        resultSlot++;
1659
6.93k
      }
1660
7.27k
      slot = slot->next;
1661
7.27k
      resultLength++;
1662
7.27k
    }
1663
1.87k
    mxMeterSome(3);
1664
1.87k
    mxPop();
1665
1.87k
  }
1666
43
  else {
1667
43
    mxPushSlot(mxThis);
1668
103
    for (;;) {
1669
103
      txSlot* argument = the->stack;
1670
103
      txBoolean flag = 0;
1671
103
      if (mxIsReference(argument)) {
1672
76
        mxPushSlot(argument);
1673
76
        mxGetID(mxID(_Symbol_isConcatSpreadable));
1674
76
        if (mxIsUndefined(the->stack))
1675
62
          flag = fxIsArray(the, argument->value.reference);
1676
14
        else
1677
14
          flag = fxToBoolean(the, the->stack);
1678
76
        mxPop();
1679
76
      }
1680
103
      if (flag) { 
1681
39
        txIndex length, index;
1682
39
        mxPushSlot(argument);
1683
39
        mxGetID(mxID(_length));
1684
39
        length = (txIndex)fxToLength(the, the->stack);
1685
39
        mxPop();
1686
39
        index = 0;
1687
486
        while (index < length) {
1688
447
          mxPushSlot(argument);
1689
447
          if (fxHasIndex(the, index)) {
1690
132
            mxPushSlot(argument);
1691
132
            mxGetIndex(index);
1692
132
            mxPushSlot(mxResult);
1693
132
            mxDefineIndex(resultLength, 0, XS_GET_ONLY);
1694
132
            mxPop();
1695
132
          }
1696
447
          index++;
1697
447
          resultLength++;
1698
447
        }
1699
39
      }
1700
64
      else {
1701
64
        mxPushSlot(argument);
1702
64
        mxPushSlot(mxResult);
1703
64
        mxDefineIndex(resultLength, 0, XS_GET_ONLY);
1704
64
        mxPop();
1705
64
        resultLength++;
1706
64
      }
1707
103
      mxPop();
1708
103
      i++;
1709
103
      if (i == c)
1710
37
        break;
1711
66
      mxPushSlot(mxArgv(i));
1712
66
    }
1713
43
    mxPushInteger(resultLength);
1714
43
    mxPushSlot(mxResult);
1715
43
    mxSetID(mxID(_length));
1716
43
    mxPop();
1717
43
  }
1718
1.92k
}
1719
1720
void fx_Array_prototype_copyWithin(txMachine* the)
1721
1.64M
{
1722
1.64M
  txNumber length = fxGetArrayLength(the, mxThis);
1723
1.64M
  txNumber to = fxArgToIndex(the, 0, 0, length);
1724
1.64M
  txNumber from = fxArgToIndex(the, 1, 0, length);
1725
1.64M
  txNumber final = fxArgToIndex(the, 2, length, length);
1726
1.64M
  txNumber count = (final > from) ? final - from : 0;
1727
1.64M
  txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE);
1728
1.64M
  if (count > length - to)
1729
881k
    count = length - to;
1730
1.64M
  if (array) {
1731
616k
    if (count > 0) {
1732
328k
      if (from < to)
1733
178k
        array = fxCheckArrayItems(the, array, (txIndex)from, (txIndex)(to + count));
1734
150k
      else
1735
150k
        array = fxCheckArrayItems(the, array, (txIndex)to, (txIndex)(from + count));
1736
328k
    }
1737
616k
  }
1738
1.64M
  if (array) {
1739
616k
    if (count > 0) {
1740
328k
      c_memmove(array->value.array.address + (txIndex)to, array->value.array.address + (txIndex)from, (txIndex)count * sizeof(txSlot));
1741
328k
      fxIndexArray(the, array);
1742
328k
      mxMeterSome((txU4)count * 10);
1743
328k
    }
1744
616k
  }
1745
1.02M
  else {
1746
1.02M
    txNumber direction;
1747
1.02M
    if ((from < to) && (to < from + count)) {
1748
33
      direction = -1;
1749
33
      from += count - 1;
1750
33
      to += count - 1;
1751
33
    }
1752
1.02M
    else
1753
1.02M
      direction = 1;
1754
1.71M
    while (count > 0) {
1755
689k
      fxMoveThisItem(the, from, to);
1756
689k
      from += direction;
1757
689k
      to += direction;
1758
689k
      count--;
1759
689k
      mxCheckMetering();
1760
689k
    }  
1761
1.02M
  }  
1762
1.64M
  mxResult->kind = mxThis->kind;
1763
1.64M
  mxResult->value = mxThis->value;
1764
1.64M
}
1765
1766
void fx_Array_prototype_entries(txMachine* the)
1767
59
{
1768
59
  txSlot* property;
1769
59
  fxToInstance(the, mxThis);
1770
59
  mxPush(mxArrayIteratorPrototype);
1771
59
  property = fxLastProperty(the, fxNewIteratorInstance(the, mxThis, mxID(_Array)));
1772
59
  property = fxNextIntegerProperty(the, property, 2, XS_NO_ID, XS_INTERNAL_FLAG);
1773
59
  mxPullSlot(mxResult);
1774
59
}
1775
1776
void fx_Array_prototype_every(txMachine* the)
1777
52.9k
{
1778
52.9k
  txIndex length = fxGetArrayLimit(the, mxThis);
1779
52.9k
  txIndex index = 0;
1780
52.9k
  txSlot* function = fxArgToCallback(the, 0);
1781
52.9k
  mxResult->kind = XS_BOOLEAN_KIND;
1782
52.9k
  mxResult->value.boolean = 1;
1783
1.58M
  while (index < length) {
1784
1.52M
    if (fxCallThisItem(the, function, index, C_NULL)) {
1785
53.0k
      mxResult->value.boolean = fxToBoolean(the, the->stack);
1786
53.0k
      mxPop();
1787
53.0k
      if (!mxResult->value.boolean)
1788
12
        break;
1789
53.0k
    }
1790
1.52M
    index++;
1791
1.52M
    mxCheckMetering();
1792
1.52M
  }
1793
52.9k
}
1794
1795
void fx_Array_prototype_fill(txMachine* the)
1796
588k
{
1797
588k
  txSlot* value;
1798
588k
  txSlot* array;
1799
588k
  if (mxArgc > 0)
1800
588k
    mxPushSlot(mxArgv(0));
1801
742
  else
1802
742
    mxPushUndefined();
1803
588k
  value = the->stack;
1804
588k
  array = fxCheckArray(the, mxThis, XS_MUTABLE);
1805
588k
  if (array)
1806
283k
    array = fxCheckArrayItems(the, array, 0, array->value.array.length);
1807
588k
  if (array) {
1808
283k
    txIndex length = array->value.array.length;
1809
283k
    txIndex start = (txIndex)fxArgToIndex(the, 1, 0, length);
1810
283k
    txIndex end = (txIndex)fxArgToIndex(the, 2, length, length);
1811
283k
    txSlot* address;
1812
283k
    txIndex size;
1813
283k
    if ((start == 0) && (end == length)) {
1814
275k
      fxSetIndexSize(the, array, length, XS_CHUNK);
1815
275k
      fxIndexArray(the, array);
1816
275k
    }
1817
283k
    address = array->value.array.address;
1818
283k
    size = (address) ? (((txChunk*)(((txByte*)address) - sizeof(txChunk)))->size) / sizeof(txSlot) : 0;
1819
283k
    if (length == size) {
1820
700k
      while (start < end) {
1821
416k
        txSlot* slot = array->value.array.address + start;
1822
416k
        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
416k
        else {
1830
416k
          slot->ID = XS_NO_ID;
1831
416k
          slot->kind = value->kind;
1832
416k
          slot->value = value->value;
1833
416k
          mxMeterSome(5);
1834
416k
        }
1835
416k
        start++;
1836
416k
        mxCheckMetering();
1837
416k
      }
1838
      
1839
283k
    }
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
283k
  }
1852
305k
  else {
1853
305k
    txNumber length = fxGetArrayLength(the, mxThis);
1854
305k
    txNumber start = fxArgToIndex(the, 1, 0, length);
1855
305k
    txNumber end = fxArgToIndex(the, 2, length, length);
1856
305k
    txSlot* value = the->stack;
1857
972k
    while (start < end) {
1858
667k
      mxPushSlot(value);
1859
667k
      mxPushSlot(mxThis);
1860
667k
      mxPushNumber(start);
1861
667k
      mxSetAt();
1862
667k
      mxPop();
1863
667k
      start++;
1864
667k
      mxCheckMetering();
1865
667k
    }
1866
305k
  }
1867
588k
  mxPop();
1868
588k
  mxResult->kind = mxThis->kind;
1869
588k
  mxResult->value = mxThis->value;
1870
588k
}
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
26
    txSlot* list = fxNewInstance(the);
1884
26
    txSlot* slot = list;
1885
26
    txSlot* resultSlot;
1886
1.00M
    while (index < length) {
1887
1.00M
      if (fxCallThisItem(the, function, index, item)) {
1888
126
        if (fxToBoolean(the, the->stack)) {
1889
68
          slot = fxNextSlotProperty(the, slot, item, XS_NO_ID, XS_NO_FLAG);
1890
68
          mxMeterSome(4);
1891
68
          resultLength++;
1892
68
        }
1893
126
        mxPop();
1894
126
      }
1895
1.00M
      index++;
1896
1.00M
      mxCheckMetering();
1897
1.00M
    }
1898
26
    fxSetIndexSize(the, resultArray, resultLength, XS_CHUNK);
1899
26
    resultSlot = resultArray->value.array.address;
1900
26
    slot = list->next;
1901
26
    index = 0;
1902
94
    while (slot) {
1903
68
      *((txIndex*)resultSlot) = index;
1904
68
      resultSlot->ID = XS_NO_ID;
1905
68
      resultSlot->kind = slot->kind;
1906
68
      resultSlot->value = slot->value;
1907
68
      resultSlot++;
1908
68
      slot = slot->next;
1909
68
      index++;
1910
68
    }
1911
26
    mxPop();
1912
26
    mxMeterSome(-1);
1913
26
  }
1914
107k
  else {
1915
251k
    while (index < length) {
1916
144k
      if (fxCallThisItem(the, function, index, item)) {
1917
144k
        if (fxToBoolean(the, the->stack)) {
1918
222
          mxPushSlot(item);
1919
222
          mxPushSlot(mxResult);
1920
222
          mxDefineIndex(resultLength, 0, XS_GET_ONLY);
1921
222
          mxPop();
1922
222
          resultLength++;
1923
222
        }
1924
144k
        mxPop();
1925
144k
      }
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
47
{
1935
47
  txIndex length = fxGetArrayLimit(the, mxThis);
1936
47
  txIndex index = 0;
1937
47
  txSlot* function = fxArgToCallback(the, 0);
1938
47
  txSlot* item;
1939
47
  mxPushUndefined();
1940
47
  item = the->stack;
1941
90
  while (index < length) {
1942
56
    fxFindThisItem(the, function, index, item);
1943
56
    if (fxToBoolean(the, the->stack++)) {
1944
13
      mxResult->kind = item->kind;
1945
13
      mxResult->value = item->value;
1946
13
      break;
1947
13
    }
1948
43
    index++;
1949
43
  }
1950
47
  mxPop();
1951
47
}
1952
1953
void fx_Array_prototype_findIndex(txMachine* the)
1954
123
{
1955
123
  txIndex length = fxGetArrayLimit(the, mxThis);
1956
123
  txIndex index = 0;
1957
123
  txSlot* function = fxArgToCallback(the, 0);
1958
123
  fxInteger(the, mxResult, -1);
1959
187
  while (index < length) {
1960
105
    fxFindThisItem(the, function, index, C_NULL);
1961
105
    if (fxToBoolean(the, the->stack++)) {
1962
41
      fxUnsigned(the, mxResult, index);
1963
41
      break;
1964
41
    }
1965
64
    index++;
1966
64
  }
1967
123
}
1968
1969
void fx_Array_prototype_findLast(txMachine* the)
1970
72
{
1971
72
  txNumber index = fxGetArrayLength(the, mxThis);
1972
72
  txSlot* function = fxArgToCallback(the, 0);
1973
72
  txSlot* item;
1974
72
  mxPushUndefined();
1975
72
  item = the->stack;
1976
138
  while (index > 0) {
1977
88
    index--;
1978
88
    fxFindThisItem(the, function, index, item);
1979
88
    if (fxToBoolean(the, the->stack++)) {
1980
22
      mxResult->kind = item->kind;
1981
22
      mxResult->value = item->value;
1982
22
      break;
1983
22
    }
1984
88
  }
1985
72
  mxPop();
1986
72
}
1987
1988
void fx_Array_prototype_findLastIndex(txMachine* the)
1989
45
{
1990
45
  txNumber index = fxGetArrayLength(the, mxThis);
1991
45
  txSlot* function = fxArgToCallback(the, 0);
1992
45
  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
8
      fxUnsigned(the, mxResult, (txUnsigned)index);
1998
8
      break;
1999
8
    }
2000
57.1k
  }
2001
45
}
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
18
    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
95
{
2018
95
  txSlot* item;
2019
95
  txIndex index = 0;
2020
384
  while (index < length) {
2021
289
    mxPushSlot(source);
2022
289
    if (fxHasIndex(the, index)) {
2023
200
      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
172
      else {
2040
172
        mxPushSlot(source);
2041
172
        mxGetIndex(index);
2042
172
      }
2043
200
      item = the->stack;
2044
200
      if ((depth > 0) && mxIsReference(item) && fxIsArray(the, fxToInstance(the, item))) {
2045
61
        txIndex itemLength;
2046
61
        mxPushSlot(item);
2047
61
        mxGetID(mxID(_length));
2048
61
        itemLength = (txIndex)fxToLength(the, the->stack);
2049
61
        mxPop();
2050
61
        start = fx_Array_prototype_flatAux(the, item, itemLength, start, depth - 1, C_NULL);
2051
61
      }
2052
139
      else {
2053
139
        mxPushSlot(mxResult);
2054
139
        mxDefineIndex(start, 0, XS_GET_ONLY);
2055
139
        mxPop();
2056
139
        start++;
2057
139
      }
2058
200
    }
2059
289
    index++;
2060
289
  }
2061
95
  return start;
2062
95
}
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.09k
{
2074
1.09k
  txIndex length = fxGetArrayLimit(the, mxThis);
2075
1.09k
  txIndex index = 0;
2076
1.09k
  txSlot* function = fxArgToCallback(the, 0);
2077
1.10M
  while (index < length) {
2078
1.09M
    if (fxCallThisItem(the, function, index, C_NULL))
2079
99.7k
      mxPop();
2080
1.09M
    index++;
2081
1.09M
    mxCheckMetering();
2082
1.09M
  }
2083
1.09k
}
2084
2085
void fx_Array_prototype_includes(txMachine* the)
2086
35.9k
{
2087
35.9k
  txSlot* array = fxCheckArray(the, mxThis, XS_IMMUTABLE);
2088
35.9k
  txSlot* argument;
2089
35.9k
  if (mxArgc > 0)
2090
35.9k
    mxPushSlot(mxArgv(0));
2091
14
  else
2092
14
    mxPushUndefined();
2093
35.9k
  argument = the->stack;
2094
35.9k
  fxBoolean(the, mxResult, 0);
2095
35.9k
  if (array) {
2096
19.6k
    txIndex length = array->value.array.length;
2097
19.6k
    if (length) {
2098
19.6k
      txIndex index = (txIndex)fxArgToIndex(the, 1, 0, length);
2099
62.3k
      while (index < length) {
2100
49.2k
        mxPushSlot(mxThis);
2101
49.2k
        mxGetIndex(index);
2102
49.2k
        if (fxIsSameValue(the, the->stack++, argument, 1)) {
2103
6.48k
          mxResult->value.boolean = 1;
2104
6.48k
          break;
2105
6.48k
        }
2106
42.7k
        index++;
2107
42.7k
        mxCheckMetering();
2108
42.7k
      }
2109
19.6k
    }
2110
19.6k
  }
2111
16.3k
  else {
2112
16.3k
    txNumber length = fxGetArrayLength(the, mxThis);
2113
16.3k
    if (length) {
2114
16.2k
      txNumber index = fxArgToIndex(the, 1, 0, length);
2115
2.15M
      while (index < length) {
2116
2.14M
        mxPushSlot(mxThis);
2117
2.14M
        mxPushNumber(index);
2118
2.14M
        mxGetAt();
2119
2.14M
        if (fxIsSameValue(the, the->stack++, argument, 1)) {
2120
5.84k
          mxResult->value.boolean = 1;
2121
5.84k
          break;
2122
5.84k
        }
2123
2.13M
        index++;
2124
2.13M
        mxCheckMetering();
2125
2.13M
      }
2126
16.2k
    }
2127
16.3k
  }
2128
35.9k
  mxPop();
2129
35.9k
}
2130
2131
void fx_Array_prototype_indexOf(txMachine* the)
2132
39.1k
{
2133
39.1k
  txSlot* array = fxCheckArray(the, mxThis, XS_IMMUTABLE);
2134
39.1k
  txSlot* argument;
2135
39.1k
  if (mxArgc > 0)
2136
37.3k
    mxPushSlot(mxArgv(0));
2137
1.77k
  else
2138
1.77k
    mxPushUndefined();
2139
39.1k
  argument = the->stack;
2140
39.1k
  fxInteger(the, mxResult, -1);
2141
39.1k
  if (array) {
2142
32.0k
    txIndex length = array->value.array.length;
2143
32.0k
    if (length) {
2144
32.0k
      txIndex index = (txIndex)fxArgToIndex(the, 1, 0, length);
2145
421k
      while (index < length) {
2146
394k
        mxPushSlot(mxThis);
2147
394k
        if (fxHasIndex(the, index)) {
2148
394k
          mxPushSlot(mxThis);
2149
394k
          mxGetIndex(index);
2150
394k
          if (fxIsSameSlot(the, the->stack++, argument)) {
2151
4.64k
            fxUnsigned(the, mxResult, index);
2152
4.64k
            break;
2153
4.64k
          }
2154
394k
        }
2155
389k
        index++;
2156
389k
        mxCheckMetering();
2157
389k
      }
2158
32.0k
    }
2159
32.0k
  }
2160
7.13k
  else {
2161
7.13k
    txNumber length = fxGetArrayLength(the, mxThis);
2162
7.13k
    if (length) {
2163
7.11k
      txNumber index = fxArgToIndex(the, 1, 0, length);
2164
2.88M
      while (index < length) {
2165
2.87M
        mxPushSlot(mxThis);
2166
2.87M
        mxPushNumber(index);
2167
2.87M
        if (mxHasAt()) {
2168
4.70k
          mxPushSlot(mxThis);
2169
4.70k
          mxPushNumber(index);
2170
4.70k
          mxGetAt();
2171
4.70k
          if (fxIsSameSlot(the, the->stack++, argument)) {
2172
1.46k
            fxNumber(the, mxResult, index);
2173
1.46k
            break;
2174
1.46k
          }
2175
4.70k
        }
2176
2.87M
        index++;
2177
2.87M
        mxCheckMetering();
2178
2.87M
      }
2179
7.11k
    }
2180
7.13k
  }
2181
39.1k
  mxPop();
2182
39.1k
}
2183
2184
void fx_Array_prototype_join(txMachine* the)
2185
5.87M
{
2186
5.87M
  txIndex length = fxGetArrayLimit(the, mxThis);
2187
5.87M
  txIndex index = 0;
2188
5.87M
  txString string;
2189
5.87M
  txSlot* list = fxNewInstance(the);
2190
5.87M
  txSlot* slot = list;
2191
5.87M
  txBoolean comma = 0;
2192
5.87M
  txInteger size = 0;
2193
5.87M
  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.87M
  else {
2200
5.87M
    mxPushStringX(",");
2201
5.87M
    the->stack->kind += XS_KEY_KIND - XS_STRING_KIND;
2202
5.87M
    the->stack->value.key.sum = 1;
2203
5.87M
  }
2204
23.4M
  while (index < length) {
2205
17.5M
    if (comma) {
2206
12.3M
      slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
2207
12.3M
      size = fxAddChunkSizes(the, size, slot->value.key.sum);
2208
12.3M
    }
2209
5.16M
    else
2210
5.16M
      comma = 1;
2211
17.5M
    mxPushSlot(mxThis);
2212
17.5M
    mxGetIndex(index);
2213
17.5M
    if ((the->stack->kind != XS_UNDEFINED_KIND) && (the->stack->kind != XS_NULL_KIND)) {
2214
11.1M
      slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
2215
11.1M
      string = fxToString(the, slot);
2216
11.1M
      slot->kind += XS_KEY_KIND - XS_STRING_KIND;
2217
11.1M
      slot->value.key.sum = mxStringLength(string);
2218
11.1M
      size = fxAddChunkSizes(the, size, slot->value.key.sum);
2219
11.1M
    }
2220
17.5M
    mxPop();
2221
17.5M
    index++;
2222
2223
17.5M
    mxCheckMetering();
2224
17.5M
  }
2225
5.87M
  mxPop();
2226
5.87M
  string = mxResult->value.string = fxNewChunk(the, fxAddChunkSizes(the, size, 1));
2227
5.87M
  slot = list->next;
2228
29.4M
  while (slot) {
2229
23.5M
    c_memcpy(string, slot->value.key.string, slot->value.key.sum);
2230
23.5M
    string += slot->value.key.sum;
2231
23.5M
    slot = slot->next;
2232
23.5M
  }
2233
5.87M
  *string = 0;
2234
5.87M
  mxResult->kind = XS_STRING_KIND;
2235
5.87M
  mxPop();
2236
5.87M
}
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
219k
{
2250
219k
  txSlot* array = fxCheckArray(the, mxThis, XS_IMMUTABLE);
2251
219k
  txSlot* argument;
2252
219k
  if (mxArgc > 0)
2253
192k
    mxPushSlot(mxArgv(0));
2254
26.4k
  else
2255
26.4k
    mxPushUndefined();
2256
219k
  argument = the->stack;
2257
219k
  fxInteger(the, mxResult, -1);
2258
219k
  if (array) {
2259
186k
    txIndex length = array->value.array.length;
2260
186k
    if (length) {
2261
168k
      txIndex index = (txIndex)fxArgToLastIndex(the, 1, length, length);
2262
587k
      while (index > 0) {
2263
557k
        index--;
2264
557k
        mxPushSlot(mxThis);
2265
557k
        if (fxHasIndex(the, index)) {
2266
557k
          mxPushSlot(mxThis);
2267
557k
          mxGetIndex(index);
2268
557k
          if (fxIsSameSlot(the, the->stack++, argument)) {
2269
138k
            fxUnsigned(the, mxResult, index);
2270
138k
            break;
2271
138k
          }
2272
557k
        }
2273
418k
        mxCheckMetering();
2274
418k
      }
2275
168k
    }
2276
186k
  }
2277
32.9k
  else {
2278
32.9k
    txNumber length = fxGetArrayLength(the, mxThis);
2279
32.9k
    if (length) {
2280
32.9k
      txNumber index = fxArgToLastIndex(the, 1, length, length);
2281
3.14M
      while (index > 0) {
2282
3.11M
        index--;
2283
3.11M
        mxPushSlot(mxThis);
2284
3.11M
        mxPushNumber(index);
2285
3.11M
        if (mxHasAt()) {
2286
65.4k
          mxPushSlot(mxThis);
2287
65.4k
          mxPushNumber(index);
2288
65.4k
          mxGetAt();
2289
65.4k
          if (fxIsSameSlot(the, the->stack++, argument)) {
2290
1.02k
            fxNumber(the, mxResult, index);
2291
1.02k
            break;
2292
1.02k
          }
2293
65.4k
        }
2294
3.11M
        mxCheckMetering();
2295
3.11M
      }
2296
32.9k
    }
2297
32.9k
  }
2298
219k
  mxPop();
2299
219k
}
2300
2301
void fx_Array_prototype_map(txMachine* the)
2302
112k
{
2303
112k
  txNumber LENGTH = fxGetArrayLength(the, mxThis);
2304
112k
  txSlot* function = fxArgToCallback(the, 0);
2305
112k
  txSlot* resultArray = fxCreateArraySpecies(the, LENGTH);
2306
112k
  txIndex length = (txIndex)LENGTH;
2307
112k
  txIndex index = 0;
2308
112k
  if (resultArray) {
2309
37.4k
    txIndex resultLength = 0;
2310
37.4k
    fxSetIndexSize(the, resultArray, length, XS_CHUNK);
2311
2.14M
    while (index < length) {
2312
2.10M
      if (fxCallThisItem(the, function, index, C_NULL)) {
2313
42.7k
        txSlot* slot = resultArray->value.array.address + resultLength;
2314
42.7k
        *((txIndex*)slot) = index;
2315
42.7k
        slot->ID = XS_NO_ID;
2316
42.7k
        slot->kind = the->stack->kind;
2317
42.7k
        slot->value = the->stack->value;
2318
42.7k
        resultLength++;
2319
42.7k
        mxMeterSome(2);
2320
42.7k
        mxPop();
2321
42.7k
      }
2322
2.10M
      index++;
2323
2.10M
      mxCheckMetering();
2324
2.10M
    }
2325
37.4k
    if (resultLength < length) {
2326
10
      fxSetIndexSize(the, resultArray, resultLength, XS_CHUNK);
2327
10
      resultArray->value.array.length = length;
2328
10
    }
2329
37.4k
  }
2330
75.4k
  else {
2331
79.5k
    while (index < length) {
2332
4.11k
      if (fxCallThisItem(the, function, index, C_NULL)) {
2333
3.97k
        mxPushSlot(mxResult);
2334
3.97k
        mxDefineIndex(index, 0, XS_GET_ONLY);
2335
3.97k
        mxPop();
2336
3.97k
      }
2337
4.11k
      index++;
2338
4.11k
      mxCheckMetering();
2339
4.11k
    }
2340
75.4k
  }
2341
112k
}
2342
2343
void fx_Array_prototype_pop(txMachine* the)
2344
1.64k
{
2345
1.64k
  txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE);
2346
1.64k
  if (array) {
2347
1.51k
    txIndex length = array->value.array.length;
2348
1.51k
    if (length > 0)
2349
226
      array = fxCheckArrayItems(the, array, length - 1, length);
2350
1.51k
  }
2351
1.64k
  if (array) {
2352
1.51k
    txIndex length = array->value.array.length;
2353
1.51k
    txSlot* address;
2354
1.51k
    mxMeterSome(2);
2355
1.51k
    if (length > 0) {
2356
226
      length--;
2357
226
      address = array->value.array.address + length;
2358
226
      mxResult->kind = address->kind;
2359
226
      mxResult->value = address->value;
2360
226
      fxSetIndexSize(the, array, length, XS_CHUNK);
2361
226
      mxMeterSome(8);
2362
226
    }
2363
1.51k
    mxMeterSome(4);
2364
1.51k
  }
2365
125
  else {
2366
125
    txNumber length = fxGetArrayLength(the, mxThis);
2367
125
    if (length > 0) {
2368
108
      length--;
2369
108
      mxPushSlot(mxThis);
2370
108
      mxPushNumber(length);
2371
108
      mxGetAt();
2372
108
      mxPullSlot(mxResult);
2373
108
      mxPushSlot(mxThis);
2374
108
      mxPushNumber(length);
2375
108
      mxDeleteAt();
2376
108
      mxPop();
2377
108
    }
2378
125
    mxPushNumber(length);
2379
125
    mxPushSlot(mxThis);
2380
125
    mxSetID(mxID(_length));
2381
125
    mxPop();
2382
125
  }
2383
1.64k
}
2384
2385
void fx_Array_prototype_push(txMachine* the)
2386
434k
{
2387
434k
  txIndex c = mxArgc, i = 0;
2388
434k
  txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE);
2389
434k
  if (array) {
2390
430k
    txIndex length = array->value.array.length;
2391
430k
    txSlot* address;
2392
430k
    mxMeterSome(2);
2393
430k
    if (length + c < length)
2394
0
      mxRangeError("array overflow");
2395
430k
    fxSetIndexSize(the, array, length + c, XS_GROWABLE_CHUNK);
2396
430k
    address = array->value.array.address + length;
2397
864k
    while (i < c) {
2398
434k
      txSlot* argument = mxArgv(i);
2399
434k
      *((txIndex*)address) = length + i;
2400
434k
      address->ID = XS_NO_ID;
2401
434k
      address->kind = argument->kind;
2402
434k
      address->value = argument->value;
2403
434k
      address++;
2404
434k
      mxMeterSome(5);
2405
434k
      i++;
2406
434k
    }
2407
430k
    mxPushUnsigned(length + c);
2408
430k
    mxMeterSome(2);
2409
430k
  }
2410
3.74k
  else {
2411
3.74k
    txNumber length = fxGetArrayLength(the, mxThis);
2412
3.74k
    if (length + c > C_MAX_SAFE_INTEGER)
2413
10
      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
434k
  mxPullSlot(mxResult);
2427
434k
}
2428
2429
void fx_Array_prototype_reduce(txMachine* the)
2430
193
{
2431
193
  txIndex length = fxGetArrayLimit(the, mxThis);
2432
193
  txIndex index = 0;
2433
193
  txSlot* function = fxArgToCallback(the, 0);
2434
193
  if (mxArgc > 1)
2435
169
    *mxResult = *mxArgv(1);
2436
24
  else {
2437
24
    txBoolean flag = 0;
2438
153
    while (!flag && (index < length)) {
2439
129
      mxPushSlot(mxThis);
2440
129
      if (fxHasIndex(the, index)) {
2441
12
        mxPushSlot(mxThis);
2442
12
        mxGetIndex(index);
2443
12
        mxPullSlot(mxResult);
2444
12
        flag = 1;
2445
12
      }
2446
129
      index++;
2447
129
    }
2448
24
    if (!flag)
2449
11
      mxTypeError("no initial value");
2450
24
  }
2451
8.78k
  while (index < length) {
2452
8.60k
    fxReduceThisItem(the, function, index);
2453
8.60k
    index++;
2454
8.60k
  }
2455
182
}
2456
2457
void fx_Array_prototype_reduceRight(txMachine* the)
2458
25
{
2459
25
  txIndex length = fxGetArrayLimit(the, mxThis);
2460
25
  txIndex index = length;
2461
25
  txSlot* function = fxArgToCallback(the, 0);
2462
25
  if (mxArgc > 1)
2463
12
    *mxResult = *mxArgv(1);
2464
13
  else {
2465
13
    txBoolean flag = 0;
2466
105
    while (!flag && (index > 0)) {
2467
92
      index--;
2468
92
      mxPushSlot(mxThis);
2469
92
      if (fxHasIndex(the, index)) {
2470
8
        mxPushSlot(mxThis);
2471
8
        mxGetIndex(index);
2472
8
        mxPullSlot(mxResult);
2473
8
        flag = 1;
2474
8
      }
2475
92
    }
2476
13
    if (!flag)
2477
4
      mxTypeError("no initial value");
2478
13
  }
2479
154
  while (index > 0) {
2480
133
    index--;
2481
133
    fxReduceThisItem(the, function, index);
2482
133
  }
2483
21
}
2484
2485
void fx_Array_prototype_reverse(txMachine* the)
2486
63
{
2487
63
  txSlot* lowerSlot;
2488
63
  txSlot* upperSlot;
2489
63
  txNumber length = fxGetArrayLength(the, mxThis);
2490
63
  txNumber middle = c_trunc(length / 2);
2491
63
  txNumber lower = 0;
2492
524k
  while (lower != middle) {
2493
524k
    txNumber upper = length - lower - 1;
2494
524k
    mxPushSlot(mxThis);
2495
524k
    mxPushNumber(lower);
2496
524k
    if (mxHasAt()) {
2497
57
      mxPushSlot(mxThis);
2498
57
      mxPushNumber(lower);
2499
57
      mxGetAt();
2500
57
      lowerSlot = the->stack;
2501
57
    }
2502
524k
    else
2503
524k
      lowerSlot = C_NULL;
2504
524k
    mxPushSlot(mxThis);
2505
524k
    mxPushNumber(upper);
2506
524k
    if (mxHasAt()) {
2507
66
      mxPushSlot(mxThis);
2508
66
      mxPushNumber(upper);
2509
66
      mxGetAt();
2510
66
      upperSlot = the->stack;
2511
66
    }
2512
524k
    else
2513
524k
      upperSlot = C_NULL;
2514
524k
    if (upperSlot && lowerSlot) {
2515
40
      mxPushSlot(upperSlot);
2516
40
      mxPushSlot(mxThis);
2517
40
      mxPushNumber(lower);
2518
40
      mxSetAt();
2519
40
      mxPop();
2520
40
      mxPushSlot(lowerSlot);
2521
40
      mxPushSlot(mxThis);
2522
40
      mxPushNumber(upper);
2523
40
      mxSetAt();
2524
40
      mxPop();
2525
40
      mxPop();
2526
40
      mxPop();
2527
40
    }
2528
524k
    else if (upperSlot) {
2529
25
      mxPushSlot(upperSlot);
2530
25
      mxPushSlot(mxThis);
2531
25
      mxPushNumber(lower);
2532
25
      mxSetAt();
2533
25
      mxPop();
2534
25
      mxPushSlot(mxThis);
2535
25
      mxPushNumber(upper);
2536
25
      mxDeleteAt();
2537
25
      mxPop();
2538
25
      mxPop();
2539
25
    }
2540
524k
    else if (lowerSlot) {
2541
17
      mxPushSlot(mxThis);
2542
17
      mxPushNumber(lower);
2543
17
      mxDeleteAt();
2544
17
      mxPop();
2545
17
      mxPushSlot(lowerSlot);
2546
17
      mxPushSlot(mxThis);
2547
17
      mxPushNumber(upper);
2548
17
      mxSetAt();
2549
17
      mxPop();
2550
17
      mxPop();
2551
17
    }
2552
524k
    lower++;
2553
524k
    mxCheckMetering();
2554
524k
  }
2555
63
  *mxResult = *mxThis;
2556
63
}
2557
2558
void fx_Array_prototype_shift(txMachine* the)
2559
144
{
2560
144
  txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE);
2561
144
  if (array)
2562
79
    array = fxCheckArrayItems(the, array, 0, array->value.array.length);
2563
144
  if (array) {
2564
79
    txIndex length = array->value.array.length;
2565
79
    txSlot* address;
2566
79
    mxMeterSome(2);
2567
79
    if (length > 0) {
2568
68
      mxMeterSome(3);
2569
68
      address = array->value.array.address;
2570
68
      length--;
2571
68
      mxResult->kind = address->kind;
2572
68
      mxResult->value = address->value;
2573
68
      c_memmove(address, address + 1, length * sizeof(txSlot));
2574
68
      fxSetIndexSize(the, array, length, XS_CHUNK);
2575
68
      fxIndexArray(the, array);
2576
68
      mxMeterSome(length * 10);
2577
68
      mxMeterSome(3);
2578
68
    }
2579
79
    mxMeterSome(4);
2580
79
  }
2581
65
  else {
2582
65
    txNumber length = fxGetArrayLength(the, mxThis);
2583
65
    if (length > 0) {
2584
35
      txNumber index = 1;
2585
35
      mxPushSlot(mxThis);
2586
35
      mxGetIndex(0);
2587
35
      mxPullSlot(mxResult);
2588
1.53M
      while (index < length) {
2589
1.53M
        mxPushSlot(mxThis);
2590
1.53M
        mxPushNumber(index);
2591
1.53M
        if (mxHasAt()) {
2592
49
          mxPushSlot(mxThis);
2593
49
          mxPushNumber(index);
2594
49
          mxGetAt();
2595
49
          mxPushSlot(mxThis);
2596
49
          mxPushNumber(index - 1);
2597
49
          mxSetAt();
2598
49
          mxPop();
2599
49
        }
2600
1.53M
        else {
2601
1.53M
          mxPushSlot(mxThis);
2602
1.53M
          mxPushNumber(index - 1);
2603
1.53M
          mxDeleteAt();
2604
1.53M
          mxPop();
2605
1.53M
        }
2606
1.53M
        index++;
2607
1.53M
        mxCheckMetering();
2608
1.53M
      }
2609
35
      length--;
2610
35
      mxPushSlot(mxThis);
2611
35
      mxDeleteIndex((txIndex)length);
2612
35
      mxPop();
2613
35
    }
2614
65
    mxPushNumber(length);
2615
65
    mxPushSlot(mxThis);
2616
65
    mxSetID(mxID(_length));
2617
65
    mxPop();
2618
65
  }
2619
144
}
2620
2621
void fx_Array_prototype_slice(txMachine* the)
2622
19.8k
{
2623
19.8k
  txNumber LENGTH = fxGetArrayLength(the, mxThis);
2624
19.8k
  txNumber START = fxArgToIndex(the, 0, 0, LENGTH);
2625
19.8k
  txNumber END = fxArgToIndex(the, 1, LENGTH, LENGTH);
2626
19.8k
  txNumber COUNT = (END > START) ? END - START : 0;
2627
19.8k
  txSlot* resultArray = fxCreateArraySpecies(the, COUNT);
2628
19.8k
  txSlot* array = C_NULL;
2629
19.8k
  if (resultArray)
2630
19.8k
    array = fxCheckArray(the, mxThis, XS_IMMUTABLE);
2631
19.8k
  if (array)
2632
19.7k
    array = fxCheckArrayItems(the, array, (txIndex)START, (txIndex)(START + COUNT));
2633
19.8k
  if (array) {
2634
17.8k
    txIndex start = (txIndex)START;
2635
17.8k
    txIndex count = (txIndex)COUNT;
2636
17.8k
    if (count) {
2637
16.7k
      fxSetIndexSize(the, resultArray, count, XS_CHUNK);
2638
16.7k
      c_memcpy(resultArray->value.array.address, array->value.array.address + start, count * sizeof(txSlot));
2639
16.7k
      fxIndexArray(the, resultArray);
2640
16.7k
      mxMeterSome(count * 10);
2641
16.7k
    }
2642
17.8k
    mxMeterSome(3);
2643
17.8k
  }
2644
1.98k
  else {
2645
1.98k
    txNumber INDEX = 0;
2646
755k
    while (START < END) {
2647
753k
      mxPushSlot(mxThis);
2648
753k
      mxPushNumber(START);
2649
753k
      if (mxHasAt()) {
2650
1.48k
        mxPushSlot(mxThis);
2651
1.48k
        mxPushNumber(START);
2652
1.48k
        mxGetAt();
2653
1.48k
        mxPushSlot(mxResult);
2654
1.48k
        mxPushNumber(INDEX);
2655
1.48k
        mxDefineAt(0, XS_GET_ONLY);
2656
1.48k
        mxPop();
2657
1.48k
      }
2658
753k
      INDEX++;
2659
753k
      START++;
2660
753k
      mxCheckMetering();
2661
753k
    }
2662
1.98k
    mxPushNumber(COUNT);
2663
1.98k
    mxPushSlot(mxResult);
2664
1.98k
    mxSetID(mxID(_length));
2665
1.98k
  }
2666
19.8k
}
2667
2668
void fx_Array_prototype_some(txMachine* the)
2669
114
{
2670
114
  txIndex length = fxGetArrayLimit(the, mxThis);
2671
114
  txIndex index = 0;
2672
114
  txSlot* function = fxArgToCallback(the, 0);
2673
114
  mxResult->kind = XS_BOOLEAN_KIND;
2674
114
  mxResult->value.boolean = 0;
2675
1.00M
  while (index < length) {
2676
1.00M
    if (fxCallThisItem(the, function, index, C_NULL)) {
2677
422
      mxResult->value.boolean = fxToBoolean(the, the->stack);
2678
422
      mxPop();
2679
422
      if (mxResult->value.boolean)
2680
90
        break;
2681
422
    }
2682
1.00M
    index++;
2683
1.00M
    mxCheckMetering();
2684
1.00M
  }
2685
114
}
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
43
    txSlot* slot = mxArgv(0);
2694
43
    if (slot->kind != XS_UNDEFINED_KIND) {
2695
42
      if (fxIsCallable(the, slot))
2696
23
        function = slot;
2697
19
      else
2698
19
        mxTypeError("compare: not a function");
2699
42
    }
2700
43
  }
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
15
    INSERTIONS = 0;
2722
15
    DELETIONS = 0;
2723
15
  }
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
9
    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
110
      txSlot* argument = mxArgv(index);
2772
110
      address->ID = XS_NO_ID;
2773
110
      address->kind = argument->kind;
2774
110
      address->value = argument->value;
2775
110
      address++;
2776
110
      mxMeterSome(5);
2777
110
      index++;
2778
110
      mxCheckMetering();
2779
110
    }
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.89k
      txNumber FROM = START + INDEX;
2787
3.89k
      mxPushSlot(mxThis);
2788
3.89k
      mxPushNumber(FROM);
2789
3.89k
      if (mxHasAt()) {
2790
438
        mxPushSlot(mxThis);
2791
438
        mxPushNumber(FROM);
2792
438
        mxGetAt();
2793
438
        mxPushSlot(mxResult);
2794
438
        mxPushNumber(INDEX);
2795
438
        mxDefineAt(0, XS_GET_ONLY);
2796
438
        mxPop();
2797
438
      }
2798
3.89k
      INDEX++;
2799
3.89k
      mxCheckMetering();
2800
3.89k
    }
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.33k
      INDEX = START;
2807
1.97M
      while (INDEX < (LENGTH - DELETIONS)) {
2808
1.97M
        fxMoveThisItem(the, INDEX + DELETIONS, INDEX + INSERTIONS);
2809
1.97M
        INDEX++;
2810
1.97M
        mxCheckMetering();
2811
1.97M
      }
2812
2.33k
      INDEX = LENGTH;
2813
6.19k
      while (INDEX > (LENGTH - DELETIONS + INSERTIONS)) {
2814
3.86k
        mxPushSlot(mxThis);
2815
3.86k
        mxPushNumber(INDEX - 1);
2816
3.86k
        mxDeleteAt();
2817
3.86k
        mxPop();
2818
3.86k
        INDEX--;
2819
3.86k
        mxCheckMetering();
2820
3.86k
      }
2821
2.33k
    }
2822
9.24k
    else if (INSERTIONS > DELETIONS) {
2823
26
      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
26
    }
2830
11.5k
    INDEX = 0;
2831
11.6k
    while (INDEX < INSERTIONS) {
2832
58
      mxPushSlot(mxArgv(2 + (txInteger)INDEX));
2833
58
      mxPushSlot(mxThis);
2834
58
      mxPushNumber(START + INDEX);
2835
58
      mxSetAt();
2836
58
      mxPop();
2837
58
      INDEX++;
2838
58
      mxCheckMetering();
2839
58
    }
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
69
{
2849
69
  txIndex length = fxGetArrayLimit(the, mxThis);
2850
69
  txIndex index = 0;
2851
69
  txString string;
2852
69
  txSlot* list = fxNewInstance(the);
2853
69
  txSlot* slot = list;
2854
69
  txBoolean comma = 0;
2855
69
  txInteger size = 0;
2856
    
2857
69
  mxPushStringX(",");
2858
69
  the->stack->kind += XS_KEY_KIND - XS_STRING_KIND;
2859
69
  the->stack->value.key.sum = 1;
2860
156
  while (index < length) {
2861
87
    if (comma) {
2862
32
      slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
2863
32
      size = fxAddChunkSizes(the, size, slot->value.key.sum);
2864
32
    }
2865
55
    else
2866
55
      comma = 1;
2867
87
    mxPushSlot(mxThis);
2868
87
    mxGetIndex(index);
2869
87
    if ((the->stack->kind != XS_UNDEFINED_KIND) && (the->stack->kind != XS_NULL_KIND)) {
2870
31
      mxDub();
2871
31
      mxGetID(mxID(_toLocaleString));
2872
31
      mxCall();
2873
31
      mxRunCount(0);
2874
31
      slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
2875
31
      string = fxToString(the, slot);
2876
31
      slot->kind += XS_KEY_KIND - XS_STRING_KIND;
2877
31
      slot->value.key.sum = mxStringLength(string);
2878
31
      size = fxAddChunkSizes(the, size, slot->value.key.sum);
2879
31
    }
2880
87
    mxPop();
2881
87
    index++;
2882
    
2883
87
    mxCheckMetering();
2884
87
  }
2885
69
  string = mxResult->value.string = fxNewChunk(the, fxAddChunkSizes(the, size, 1));
2886
69
  slot = list->next;
2887
130
  while (slot) {
2888
61
    c_memcpy(string, slot->value.key.string, slot->value.key.sum);
2889
61
    string += slot->value.key.sum;
2890
61
    slot = slot->next;
2891
61
  }
2892
69
  *string = 0;
2893
69
  mxResult->kind = XS_STRING_KIND;
2894
69
  mxPop();
2895
69
}
2896
2897
void fx_Array_prototype_toReversed(txMachine* the)
2898
71
{
2899
71
  txNumber LENGTH = fxGetArrayLength(the, mxThis);
2900
71
  txIndex length, to, from;
2901
71
  if (LENGTH > 0xFFFFFFFF)
2902
1
    mxRangeError("array overflow");
2903
70
  length = (txIndex)LENGTH;
2904
70
  fxNewArray(the, length);
2905
70
  mxPullSlot(mxResult);
2906
70
  from = length - 1;
2907
70
  to = 0;
2908
1.22M
  while (to < length) {
2909
1.22M
    mxPushSlot(mxThis);
2910
1.22M
    mxPushUnsigned(from);
2911
1.22M
    mxGetAt();
2912
1.22M
    mxPushSlot(mxResult);
2913
1.22M
    mxPushUnsigned(to);
2914
1.22M
    mxDefineAt(0, XS_GET_ONLY);
2915
1.22M
    mxPop();
2916
1.22M
    from--;
2917
1.22M
    to++;
2918
1.22M
    mxCheckMetering();
2919
1.22M
  }
2920
70
}
2921
2922
void fx_Array_prototype_toSorted(txMachine* the)
2923
21.2k
{
2924
21.2k
  txSlot* function = C_NULL;
2925
21.2k
  txNumber LENGTH;
2926
21.2k
  if (mxArgc > 0) {
2927
21.1k
    txSlot* slot = mxArgv(0);
2928
21.1k
    if (slot->kind != XS_UNDEFINED_KIND) {
2929
28
      if (fxIsCallable(the, slot))
2930
1
        function = slot;
2931
27
      else
2932
27
        mxTypeError("compare: not a function");
2933
28
    }
2934
21.1k
  }
2935
21.2k
  LENGTH = fxGetArrayLength(the, mxThis);
2936
21.2k
  if (LENGTH > 0xFFFFFFFF)
2937
1
    mxRangeError("array overflow");
2938
21.2k
  fxNewArray(the, (txIndex)LENGTH);
2939
21.2k
  mxPullSlot(mxResult);
2940
21.2k
  fxSortArrayItems(the, function, C_NULL, LENGTH, mxResult);
2941
21.2k
}
2942
2943
void fx_Array_prototype_toSpliced(txMachine* the)
2944
865k
{
2945
865k
  txIndex c = (txIndex)mxArgc, i;
2946
865k
  txNumber LENGTH = fxGetArrayLength(the, mxThis);
2947
865k
  txNumber START = fxArgToIndex(the, 0, 0, LENGTH);
2948
865k
  txNumber INSERTIONS, SKIP, RESULT_LENGTH;
2949
865k
  txSlot* array = C_NULL;
2950
865k
  if (c == 0) {
2951
380k
    INSERTIONS = 0;
2952
380k
    SKIP = 0;
2953
380k
  }
2954
484k
  else if (c == 1) {
2955
157k
    INSERTIONS = 0;
2956
157k
    SKIP = LENGTH - START;
2957
157k
  }
2958
327k
  else {
2959
327k
    INSERTIONS = c - 2;
2960
327k
    SKIP = fxArgToRange(the, 1, 0, 0, LENGTH - START);
2961
327k
  }
2962
865k
  RESULT_LENGTH = LENGTH + INSERTIONS - SKIP;
2963
865k
  if (RESULT_LENGTH > C_MAX_SAFE_INTEGER)
2964
10
    mxTypeError("unsafe integer");
2965
865k
  if (RESULT_LENGTH > 0xFFFFFFFF)
2966
30
    mxRangeError("array overflow");
2967
865k
  array = fxCheckArray(the, mxThis, XS_IMMUTABLE);
2968
865k
  if (array)
2969
346k
    array = fxCheckArrayItems(the, array, (txIndex)0, (txIndex)START);
2970
865k
  if (array)
2971
346k
    array = fxCheckArrayItems(the, array, (txIndex)(START + SKIP), (txIndex)LENGTH);
2972
865k
  if (array) {
2973
346k
    txIndex length = (txIndex)LENGTH;
2974
346k
    txIndex start = (txIndex)START;
2975
346k
    txIndex skip = (txIndex)SKIP;
2976
346k
    txIndex rest = length - (start + skip);
2977
346k
    txSlot* resultArray;
2978
346k
    txSlot* resultAddress;
2979
346k
    txSlot* address;
2980
346k
    fxNewArray(the, (txIndex)RESULT_LENGTH);
2981
346k
    mxPullSlot(mxResult);
2982
346k
    resultArray = mxResult->value.reference->next;
2983
346k
    resultAddress = resultArray->value.array.address;
2984
346k
    address = array->value.array.address;
2985
346k
    if (start > 0) {
2986
121k
      c_memcpy(resultAddress, address, start * sizeof(txSlot));
2987
121k
      mxMeterSome(start * 10);
2988
121k
      resultAddress += start;
2989
121k
      address += start;
2990
121k
    }
2991
346k
    for (i = 2; i < c; i++) {
2992
30
      txSlot* argument = mxArgv(i);
2993
30
      resultAddress->ID = XS_NO_ID;
2994
30
      resultAddress->kind = argument->kind;
2995
30
      resultAddress->value = argument->value;
2996
30
      resultAddress++;
2997
30
      mxMeterSome(5);
2998
30
      mxCheckMetering();
2999
30
    }
3000
346k
    address += skip;
3001
346k
    if (rest > 0) {
3002
188k
      c_memcpy(resultAddress, address, rest * sizeof(txSlot));
3003
188k
      mxMeterSome(rest * 10);
3004
188k
    }
3005
346k
    fxIndexArray(the, resultArray);
3006
346k
    mxMeterSome(4);
3007
346k
  }
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
30
      mxPushSlot(mxArgv(i));
3027
30
      mxPushSlot(mxResult);
3028
30
      mxPushNumber(to);
3029
30
      mxDefineAt(0, XS_GET_ONLY);
3030
30
      mxPop();
3031
30
      to++;
3032
30
      mxCheckMetering();
3033
30
    }
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
865k
}
3049
3050
void fx_Array_prototype_toString(txMachine* the)
3051
5.88M
{
3052
5.88M
  mxPushSlot(mxThis);
3053
5.88M
  mxDub();
3054
5.88M
  mxGetID(mxID(_join));
3055
5.88M
  if (fxIsCallable(the, the->stack)) {
3056
5.88M
    mxCall();
3057
5.88M
    mxRunCount(0);
3058
5.88M
    mxPullSlot(mxResult);
3059
5.88M
  }
3060
51
  else {
3061
51
    mxPop();
3062
51
    mxPop();
3063
51
    fx_Object_prototype_toString(the);
3064
51
  }
3065
5.88M
}
3066
3067
void fx_Array_prototype_unshift(txMachine* the)
3068
85
{
3069
85
  txIndex c = mxArgc, i;
3070
85
  txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE);
3071
85
  if (array)
3072
13
    array = fxCheckArrayItems(the, array, 0, array->value.array.length);
3073
85
  if (array) {
3074
13
    txSlot* address;
3075
13
    txIndex length = array->value.array.length;
3076
13
    if (length + c < length)
3077
0
      mxRangeError("array overflow");
3078
13
    if (c > 0) {
3079
12
      fxSetIndexSize(the, array, length + c, XS_GROWABLE_CHUNK);
3080
12
      address = array->value.array.address;
3081
12
      c_memmove(address + c, address, length * sizeof(txSlot));
3082
12
      mxMeterSome(length * 10);
3083
12
      i = 0;
3084
53
      while (i < c) {
3085
41
        txSlot* argument = mxArgv(i);
3086
41
        address->ID = XS_NO_ID;
3087
41
        address->kind = argument->kind;
3088
41
        address->value = argument->value;
3089
41
        address++;
3090
41
        mxMeterSome(4);
3091
41
        i++;
3092
41
        mxCheckMetering();
3093
41
      }
3094
12
      fxIndexArray(the, array);
3095
12
    }
3096
13
    mxPushUnsigned(length + c);
3097
13
    mxMeterSome(2);
3098
13
  }
3099
72
  else {
3100
72
    txNumber length = fxGetArrayLength(the, mxThis);
3101
72
    txNumber index = length;
3102
72
    if (c > 0) {
3103
47
      if (length + c > C_MAX_SAFE_INTEGER)
3104
13
        mxTypeError("unsafe integer");
3105
874k
      while (index > 0) {
3106
874k
        fxMoveThisItem(the, index - 1, index + c - 1);
3107
874k
        index--;
3108
874k
        mxCheckMetering();
3109
874k
      }
3110
34
      i = 0;
3111
72
      while (i < c) {
3112
38
        mxPushSlot(mxArgv(i));
3113
38
        mxPushSlot(mxThis);
3114
38
        mxSetIndex(i);
3115
38
        mxPop();
3116
38
        i++;
3117
38
        mxCheckMetering();
3118
38
      }
3119
34
    }
3120
59
    mxPushNumber(length + c);
3121
59
    mxPushSlot(mxThis);
3122
59
    mxSetID(mxID(_length));
3123
59
  }
3124
72
  mxPullSlot(mxResult);
3125
72
}
3126
3127
void fx_Array_prototype_values(txMachine* the)
3128
616k
{
3129
616k
  txSlot* property;
3130
616k
  fxToInstance(the, mxThis);
3131
616k
  mxPush(mxArrayIteratorPrototype);
3132
616k
  property = fxLastProperty(the, fxNewIteratorInstance(the, mxThis, mxID(_Array)));
3133
616k
  property = fxNextIntegerProperty(the, property, 0, XS_NO_ID, XS_INTERNAL_FLAG);
3134
616k
  mxPullSlot(mxResult);
3135
616k
}
3136
3137
void fx_Array_prototype_with(txMachine* the)
3138
154k
{
3139
154k
  txNumber LENGTH = fxGetArrayLength(the, mxThis), INDEX;
3140
154k
  txIndex length, index, i;
3141
154k
  if (LENGTH > 0xFFFFFFFF)
3142
1
    mxRangeError("array overflow");
3143
154k
  INDEX = fxArgToRelativeIndex(the, 0, 0, LENGTH);
3144
154k
  if ((INDEX < 0) || (LENGTH <= INDEX))
3145
23
    mxRangeError("invalid index");
3146
154k
  length = (txIndex)LENGTH;
3147
154k
  fxNewArray(the, length);
3148
154k
  mxPullSlot(mxResult);
3149
154k
  index = (txIndex)INDEX;
3150
154k
  i = 0;
3151
327k
  while (i < index) {
3152
172k
    mxPushSlot(mxThis);
3153
172k
    mxPushUnsigned(i);
3154
172k
    mxGetAt();
3155
172k
    mxPushSlot(mxResult);
3156
172k
    mxPushUnsigned(i);
3157
172k
    mxDefineAt(0, XS_GET_ONLY);
3158
172k
    mxPop();
3159
172k
    i++;
3160
172k
    mxCheckMetering();
3161
172k
  }
3162
154k
  if (mxArgc > 1)
3163
145k
    mxPushSlot(mxArgv(1));
3164
8.48k
  else
3165
8.48k
    mxPushUndefined();
3166
154k
  mxPushSlot(mxResult);
3167
154k
  mxPushUnsigned(i);
3168
154k
  mxDefineAt(0, XS_GET_ONLY);
3169
154k
  mxPop();
3170
154k
  i++;
3171
1.34M
  while (i < length) {
3172
1.18M
    mxPushSlot(mxThis);
3173
1.18M
    mxPushUnsigned(i);
3174
1.18M
    mxGetAt();
3175
1.18M
    mxPushSlot(mxResult);
3176
1.18M
    mxPushUnsigned(i);
3177
1.18M
    mxDefineAt(0, XS_GET_ONLY);
3178
1.18M
    mxPop();
3179
1.18M
    i++;
3180
1.18M
    mxCheckMetering();
3181
1.18M
  }
3182
154k
}
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
945k
      switch(kind) {
3198
945k
      case 0: 
3199
945k
        mxPushSlot(iterable);
3200
945k
        mxGetIndex(i);
3201
945k
        mxPullSlot(value);
3202
945k
        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
945k
      }
3214
945k
            index->value.integer = i + 1;
3215
945k
    }
3216
603k
    else {
3217
603k
      value->kind = XS_UNDEFINED_KIND;
3218
603k
      done->value.boolean = 1;
3219
603k
    }
3220
1.54M
  }
3221
1.54M
  mxResult->kind = result->kind;
3222
1.54M
  mxResult->value = result->value;
3223
1.54M
}
3224