Coverage Report

Created: 2026-10-17 07:25

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