Coverage Report

Created: 2026-07-14 06:35

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