Coverage Report

Created: 2026-11-12 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsGenerator.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
//#define mxPromisePrint 1
41
42
43
static txSlot* fxCheckIteratorStep(txMachine* the, txSlot* slot);
44
static txBoolean fxGetIteratorFlattenable(txMachine* the, txSlot* iterable, txSlot* iterator, txSlot* next, txBoolean optional);
45
static txSlot* fxNewIteratorHelperInstance(txMachine* the, txSlot* iterator, txInteger step);
46
47
static void fxNewGeneratorResult(txMachine* the, txBoolean done);
48
49
static txSlot* fxCheckGeneratorInstance(txMachine* the, txSlot* slot);
50
static void fx_Generator_prototype_aux(txMachine* the, txFlag status);
51
52
static void fxAsyncGeneratorStep(txMachine* the, txSlot* generator, txFlag status);
53
static txSlot* fxCheckAsyncGeneratorInstance(txMachine* the, txSlot* slot);
54
static void fx_AsyncGenerator_prototype_aux(txMachine* the, txFlag status);
55
56
static txSlot* fxCheckAsyncFromSyncIteratorInstance(txMachine* the, txSlot* slot);
57
static void fx_AsyncFromSyncIterator_prototype_aux(txMachine* the, txFlag status, txSlot* iterator, txBoolean* flag);
58
59
void fxBuildGenerator(txMachine* the)
60
30.4k
{
61
30.4k
  txSlot* slot;
62
30.4k
  txSlot* property;
63
64
30.4k
  mxPush(mxIteratorPrototype);
65
30.4k
  slot = fxLastProperty(the, the->stack->value.reference);
66
30.4k
#if mxECMAScript2025
67
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_prototype_drop), 1, mxID(_drop), XS_DONT_ENUM_FLAG);
68
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_prototype_every), 1, mxID(_every), XS_DONT_ENUM_FLAG);
69
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_prototype_filter), 1, mxID(_filter), XS_DONT_ENUM_FLAG);
70
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_prototype_find), 1, mxID(_find), XS_DONT_ENUM_FLAG);
71
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_prototype_flatMap), 1, mxID(_flatMap), XS_DONT_ENUM_FLAG);
72
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_prototype_forEach), 1, mxID(_forEach), XS_DONT_ENUM_FLAG);
73
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_prototype_map), 1, mxID(_map), XS_DONT_ENUM_FLAG);
74
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_prototype_reduce), 1, mxID(_reduce), XS_DONT_ENUM_FLAG);
75
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_prototype_some), 1, mxID(_some), XS_DONT_ENUM_FLAG);
76
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_prototype_take), 1, mxID(_take), XS_DONT_ENUM_FLAG);
77
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_prototype_toArray), 0, mxID(_toArray), XS_DONT_ENUM_FLAG);
78
30.4k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_Iterator_prototype_toStringTag_get), mxCallback(fx_Iterator_prototype_toStringTag_set), mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG);
79
30.4k
#endif
80
30.4k
#if mxExplicitResourceManagement
81
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_prototype_dispose), 0, mxID(_Symbol_dispose), XS_DONT_ENUM_FLAG);
82
30.4k
#endif
83
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_prototype_iterator), 0, mxID(_Symbol_iterator), XS_DONT_ENUM_FLAG);
84
30.4k
#if mxECMAScript2025
85
30.4k
  property = slot;
86
30.4k
  slot = fxBuildHostConstructor(the, mxCallback(fx_Iterator), 0, mxID(_Iterator));
87
30.4k
  mxIteratorConstructor = *the->stack;
88
30.4k
  slot = fxLastProperty(the, slot);
89
30.4k
#if mxECMAScript2026
90
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_concat), 0, mxID(_concat), XS_DONT_ENUM_FLAG);
91
30.4k
#endif
92
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Iterator_from), 1, mxID(_from), XS_DONT_ENUM_FLAG);
93
  
94
30.4k
  mxPush(mxIteratorPrototype);
95
30.4k
  property = fxNextHostAccessorProperty(the, property, mxCallback(fx_Iterator_prototype_constructor_get), mxCallback(fx_Iterator_prototype_constructor_set), mxID(_constructor), XS_DONT_ENUM_FLAG);
96
30.4k
  mxPop();
97
  
98
30.4k
  mxPush(mxIteratorPrototype);
99
30.4k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
100
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_IteratorHelper_prototype_next), 1, mxID(_next), XS_DONT_ENUM_FLAG);
101
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_IteratorHelper_prototype_return), 1, mxID(_return), XS_DONT_ENUM_FLAG);
102
30.4k
  slot = fxNextStringXProperty(the, slot, "Iterator Helper", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
103
30.4k
  mxPull(mxIteratorHelperPrototype);
104
  
105
30.4k
  mxPush(mxIteratorPrototype);
106
30.4k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
107
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_IteratorWrapper_prototype_next), 1, mxID(_next), XS_DONT_ENUM_FLAG);
108
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_IteratorWrapper_prototype_return), 1, mxID(_return), XS_DONT_ENUM_FLAG);
109
30.4k
  mxPull(mxIteratorWrapperPrototype);
110
111
30.4k
#endif
112
113
30.4k
  mxPush(mxIteratorPrototype);
114
30.4k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
115
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Generator_prototype_next), 1, mxID(_next), XS_DONT_ENUM_FLAG);
116
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Generator_prototype_return), 1, mxID(_return), XS_DONT_ENUM_FLAG);
117
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Generator_prototype_throw), 1, mxID(_throw), XS_DONT_ENUM_FLAG);
118
30.4k
  slot = fxNextStringXProperty(the, slot, "Generator", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
119
30.4k
  mxGeneratorPrototype = *the->stack;
120
30.4k
  mxPop();
121
  
122
30.4k
  mxPush(mxFunctionPrototype);
123
30.4k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
124
30.4k
  slot = fxNextSlotProperty(the, slot, &mxGeneratorPrototype, mxID(_prototype), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
125
30.4k
  property = mxBehaviorSetProperty(the, mxGeneratorPrototype.value.reference, mxID(_constructor), 0, XS_OWN);
126
30.4k
  property->flag = XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG;
127
30.4k
  property->kind = the->stack->kind;
128
30.4k
  property->value = the->stack->value;
129
30.4k
  slot = fxNextStringXProperty(the, slot, "GeneratorFunction", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
130
30.4k
  mxGeneratorFunctionPrototype = *the->stack;
131
30.4k
  slot = fxBuildHostConstructor(the, mxCallback(fx_GeneratorFunction), 1, mxID(_GeneratorFunction));
132
30.4k
  slot = mxBehaviorGetProperty(the, mxGeneratorFunctionPrototype.value.reference, mxID(_constructor), 0, XS_OWN);
133
30.4k
  slot->flag |= XS_DONT_SET_FLAG;
134
30.4k
  mxPop();
135
  
136
30.4k
  mxPush(mxIteratorPrototype);
137
30.4k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
138
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Enumerator_prototype_next), 0, mxID(_next), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG);
139
30.4k
  fxNewHostConstructor(the, mxCallback(fx_Enumerator), 0, XS_NO_ID);
140
30.4k
  mxPull(mxEnumeratorFunction);
141
142
30.4k
  mxPush(mxObjectPrototype);
143
30.4k
  slot = fxNewObjectInstance(the);
144
30.4k
#if mxExplicitResourceManagement
145
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncIterator_prototype_asyncDispose), 0, mxID(_Symbol_asyncDispose), XS_DONT_ENUM_FLAG);
146
30.4k
#endif
147
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncIterator_prototype_asyncIterator), 0, mxID(_Symbol_asyncIterator), XS_DONT_ENUM_FLAG);
148
30.4k
  mxPull(mxAsyncIteratorPrototype);
149
  
150
30.4k
  mxPush(mxAsyncIteratorPrototype);
151
30.4k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
152
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncGenerator_prototype_next), 1, mxID(_next), XS_DONT_ENUM_FLAG);
153
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncGenerator_prototype_return), 1, mxID(_return), XS_DONT_ENUM_FLAG);
154
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncGenerator_prototype_throw), 1, mxID(_throw), XS_DONT_ENUM_FLAG);
155
30.4k
  slot = fxNextStringXProperty(the, slot, "AsyncGenerator", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
156
30.4k
  mxAsyncGeneratorPrototype = *the->stack;
157
30.4k
  mxPop();
158
159
30.4k
  mxPush(mxFunctionPrototype);
160
30.4k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
161
30.4k
  slot = fxNextSlotProperty(the, slot, &mxAsyncGeneratorPrototype, mxID(_prototype), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
162
30.4k
  property = mxBehaviorSetProperty(the, mxAsyncGeneratorPrototype.value.reference, mxID(_constructor), 0, XS_OWN);
163
30.4k
  property->flag = XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG;
164
30.4k
  property->kind = the->stack->kind;
165
30.4k
  property->value = the->stack->value;
166
30.4k
  slot = fxNextStringXProperty(the, slot, "AsyncGeneratorFunction", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
167
30.4k
  mxAsyncGeneratorFunctionPrototype = *the->stack;
168
30.4k
  slot = fxBuildHostConstructor(the, mxCallback(fx_AsyncGeneratorFunction), 1, mxID(_AsyncGeneratorFunction));
169
30.4k
  slot = mxBehaviorGetProperty(the, mxAsyncGeneratorFunctionPrototype.value.reference, mxID(_constructor), 0, XS_OWN);
170
30.4k
  slot->flag |= XS_DONT_SET_FLAG;
171
30.4k
  mxPop();
172
  
173
30.4k
  mxPush(mxAsyncIteratorPrototype);
174
30.4k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
175
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncFromSyncIterator_prototype_next), 1, mxID(_next), XS_DONT_ENUM_FLAG);
176
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncFromSyncIterator_prototype_return), 1, mxID(_return), XS_DONT_ENUM_FLAG);
177
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncFromSyncIterator_prototype_throw), 1, mxID(_throw), XS_DONT_ENUM_FLAG);
178
30.4k
  slot = fxNextStringXProperty(the, slot, "Async-from-Sync Iterator", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
179
30.4k
  mxAsyncFromSyncIteratorPrototype = *the->stack;
180
30.4k
  mxPop();
181
30.4k
}
182
183
typedef txBoolean (*txIteratorStep)(txMachine* the, txSlot* iterator, txSlot* next, txSlot* extra, txSlot* value, txFlag status);
184
185
enum {
186
  mx_Iterator_prototype_drop = 0,
187
  mx_Iterator_prototype_filter,
188
  mx_Iterator_prototype_flatMap,
189
  mx_Iterator_prototype_map,
190
  mx_Iterator_prototype_take,
191
  mx_Iterator_concat,
192
  mxIteratorStepCount
193
};
194
195
static txBoolean fx_Iterator_prototype_drop_step(txMachine* the, txSlot* iterator, txSlot* next, txSlot* extra, txSlot* value, txFlag status);
196
static txBoolean fx_Iterator_prototype_filter_step(txMachine* the, txSlot* iterator, txSlot* next, txSlot* extra, txSlot* value, txFlag status);
197
static txBoolean fx_Iterator_prototype_flatMap_step(txMachine* the, txSlot* iterator, txSlot* next, txSlot* extra, txSlot* value, txFlag status);
198
static txBoolean fx_Iterator_prototype_map_step(txMachine* the, txSlot* iterator, txSlot* next, txSlot* extra, txSlot* value, txFlag status);
199
static txBoolean fx_Iterator_prototype_take_step(txMachine* the, txSlot* iterator, txSlot* next, txSlot* extra, txSlot* value, txFlag status);
200
static txBoolean fx_Iterator_concat_step(txMachine* the, txSlot* iterator, txSlot* next, txSlot* extra, txSlot* value, txFlag status);
201
202
const txIteratorStep ICACHE_FLASH_ATTR gxIteratorSteps[mxIteratorStepCount]  = {
203
  fx_Iterator_prototype_drop_step,
204
  fx_Iterator_prototype_filter_step,
205
  fx_Iterator_prototype_flatMap_step,
206
  fx_Iterator_prototype_map_step,
207
  fx_Iterator_prototype_take_step,
208
  fx_Iterator_concat_step,
209
};
210
211
const txID ICACHE_FLASH_ATTR gxIteratorStepIDs[mxIteratorStepCount]  = {
212
  mxID(_drop),
213
  mxID(_filter),
214
  mxID(_flatMap),
215
  mxID(_map),
216
  mxID(_take),
217
};
218
219
txSlot* fxCheckIteratorInstance(txMachine* the, txSlot* slot, txID id)
220
19.5M
{
221
19.5M
  txSlot* instance;
222
19.5M
  if (slot->kind == XS_REFERENCE_KIND) {
223
19.5M
    instance = slot->value.reference;
224
19.5M
    slot = instance->next;
225
19.5M
    if (slot && (slot->flag & XS_INTERNAL_FLAG) && (slot->ID == id) && (slot->kind == XS_REFERENCE_KIND)) {
226
19.5M
      return instance;
227
19.5M
    }
228
19.5M
  }
229
19.5M
  mxTypeError("this: not an iterator");
230
0
  return C_NULL;
231
19.5M
}
232
233
txSlot* fxCheckIteratorResult(txMachine* the, txSlot* result) 
234
19.5M
{
235
19.5M
  txSlot* value = result->value.reference->next;
236
19.5M
  while (value && (value->flag & XS_INTERNAL_FLAG))
237
1
    value = value->next;
238
19.5M
  mxCheck(the, (value != C_NULL) && (value->ID == mxID(_value)));
239
19.5M
  mxCheck(the, (value->next != C_NULL) && (value->next->ID == mxID(_done)));
240
19.5M
  return value;
241
19.5M
}
242
243
txSlot* fxCheckIteratorStep(txMachine* the, txSlot* slot) 
244
297k
{
245
297k
  if (slot && (slot->kind == XS_INTEGER_KIND)) {
246
297k
    txInteger step = slot->value.integer;
247
297k
    if ((0 <= step) && (step < mxIteratorStepCount)) {
248
297k
      if (slot->ID == gxIteratorStepIDs[step]) {
249
297k
        return slot;
250
297k
      }
251
297k
    }
252
297k
  }
253
297k
  mxTypeError("this: not an iterator helper");
254
0
  return C_NULL;
255
297k
}
256
257
txBoolean fxIteratorNext(txMachine* the, txSlot* iterator, txSlot* next, txSlot* value)
258
20.4M
{
259
20.4M
  mxPushSlot(iterator);
260
20.4M
  mxPushSlot(next);
261
20.4M
  mxCall();
262
20.4M
  mxRunCount(0);
263
20.4M
  if (!mxIsReference(the->stack))
264
5
    mxTypeError("iterator result: not an object");
265
20.4M
  mxDub();
266
20.4M
  mxGetID(mxID(_done));
267
20.4M
  if (fxToBoolean(the, the->stack)) {
268
1.55M
    mxPop();
269
1.55M
    mxPop();
270
1.55M
    return 0;
271
1.55M
  }
272
18.9M
  mxPop();
273
18.9M
  mxGetID(mxID(_value));
274
18.9M
  mxPullSlot(value);
275
18.9M
  return 1;
276
20.4M
}
277
278
void fxIteratorReturn(txMachine* the, txSlot* iterator, txBoolean abrupt)
279
251
{
280
251
  if (abrupt)
281
171
    mxPush(mxException);
282
251
  mxTry(the) {
283
251
    mxPushSlot(iterator);
284
251
    mxDub();
285
251
    mxGetID(mxID(_return));
286
251
    if (mxIsUndefined(the->stack) || mxIsNull(the->stack)) 
287
74
      mxPop();
288
177
    else {
289
177
      mxCall();
290
177
      mxRunCount(0);
291
177
      if (!mxIsReference(the->stack))
292
14
        mxTypeError("iterator result: not an object");
293
177
    }
294
237
    mxPop();
295
237
  }
296
237
  mxCatch(the) {
297
38
    if (!abrupt)
298
10
      fxJump(the);
299
38
  }
300
227
  if (abrupt)
301
171
    mxPull(mxException);
302
227
}
303
304
txBoolean fxGetIterator(txMachine* the, txSlot* iterable, txSlot* iterator, txSlot* next, txBoolean optional)
305
1.19M
{
306
1.19M
  mxPushSlot(iterable);
307
1.19M
  mxDub();
308
1.19M
  mxGetID(mxID(_Symbol_iterator));
309
1.19M
  if (optional && (mxIsUndefined(the->stack) || mxIsNull(the->stack))) {
310
2.87k
    mxPop();
311
2.87k
    mxPop();
312
2.87k
    return 0;
313
2.87k
  }
314
1.19M
  mxCall();
315
1.19M
  mxRunCount(0);
316
1.19M
  if (!mxIsReference(the->stack))
317
1
    mxTypeError("iterator: not an object");
318
1.19M
  if (next) {
319
1.00M
    mxDub();
320
1.00M
    mxGetID(mxID(_next));
321
1.00M
    mxPullSlot(next);
322
1.00M
  }
323
1.19M
  mxPullSlot(iterator);
324
1.19M
  return 1;
325
1.19M
}
326
327
txBoolean fxGetIteratorFlattenable(txMachine* the, txSlot* iterable, txSlot* iterator, txSlot* next, txBoolean optional)
328
106k
{
329
106k
  if (!mxIsReference(iterable)) {
330
17
    if (optional) {
331
14
      if ((iterable->kind != XS_STRING_KIND) && (iterable->kind != XS_STRING_X_KIND))
332
13
        mxTypeError("iterator: not a string");
333
14
    }
334
3
    else
335
3
      mxTypeError("iterator: not an object");
336
17
  }
337
106k
  mxPushSlot(iterable);
338
106k
  mxDub();
339
106k
  mxGetID(mxID(_Symbol_iterator));
340
106k
  if ((mxIsUndefined(the->stack) || mxIsNull(the->stack)))
341
26
    mxPop();
342
106k
  else {
343
106k
    mxCall();
344
106k
    mxRunCount(0);
345
106k
  }
346
106k
  if (!mxIsReference(the->stack))
347
0
    mxTypeError("iterator: not an object");
348
106k
  mxDub();
349
106k
  mxGetID(mxID(_next));
350
106k
  mxPullSlot(next);
351
106k
  mxPullSlot(iterator);
352
106k
  return 1;
353
106k
}
354
355
txSlot* fxNewIteratorInstance(txMachine* the, txSlot* iterable, txID id) 
356
1.62M
{
357
1.62M
  txSlot* instance;
358
1.62M
  txSlot* result;
359
1.62M
  txSlot* property;
360
1.62M
  instance = fxNewObjectInstance(the);
361
1.62M
  mxPush(mxObjectPrototype);
362
1.62M
  result = fxNewObjectInstance(the);
363
1.62M
  property = fxNextUndefinedProperty(the, result, mxID(_value), XS_DONT_DELETE_FLAG | XS_DONT_SET_FLAG);
364
1.62M
  property = fxNextBooleanProperty(the, property, 0, mxID(_done), XS_DONT_DELETE_FLAG | XS_DONT_SET_FLAG);
365
1.62M
  property = fxNextSlotProperty(the, instance, the->stack, id, XS_INTERNAL_FLAG);
366
1.62M
  property = fxNextSlotProperty(the, property, iterable, XS_NO_ID, XS_INTERNAL_FLAG);
367
1.62M
  property = fxNextIntegerProperty(the, property, 0, XS_NO_ID, XS_INTERNAL_FLAG);
368
1.62M
  mxPop();
369
1.62M
  return instance;
370
1.62M
}
371
372
void fxSetterThatIgnoresPrototypeProperties(txMachine* the, txSlot* reference, txID id, txString name, txSlot* value)
373
72
{
374
72
  txSlot* instance = fxGetInstance(the, reference);
375
72
  txSlot* home = mxFunctionInstanceHome(mxFunction->value.reference);
376
72
  txSlot* property;
377
72
  if (!instance)
378
58
    mxTypeError("set %s: not an object", name);
379
14
  if (home->value.home.object == instance)
380
7
    mxTypeError("set %s: not writable", name);
381
7
  mxTemporary(property);
382
7
  if (!mxBehaviorGetOwnProperty(the, instance, id, 0, property)) {
383
3
    if (!mxBehaviorDefineOwnProperty(the, instance, id, 0, value, XS_GET_ONLY))
384
0
      mxTypeError("set %s: not extensible", name);
385
3
  }
386
4
  else /*if (!mxIsProxy(instance))*/ {
387
4
    property = mxBehaviorSetProperty(the, instance, id, 0, XS_OWN);
388
4
    if (!property)
389
0
      mxTypeError("set %s: not writable", name);
390
4
        if (property->kind == XS_ACCESSOR_KIND) {
391
0
            txSlot* function = property->value.accessor.setter;
392
0
            if (!mxIsFunction(function))
393
0
                mxTypeError("set %s: not writable", name);
394
0
            mxPushSlot(reference);
395
0
            mxPushReference(function);
396
0
            mxCall();
397
0
            mxPushSlot(value);
398
0
            mxRunCount(1);
399
0
            mxPop();
400
0
       }
401
4
        else {
402
4
            property->kind = value->kind;
403
4
            property->value = value->value;
404
4
        }
405
4
  }
406
7
  mxPop();
407
7
}
408
409
void fx_Iterator(txMachine* the)
410
91
{
411
91
  if (!mxHasTarget)
412
2
    mxTypeError("call: Iterator");
413
89
  if (fxIsSameSlot(the, mxTarget, mxFunction))
414
1
    mxTypeError("new: Iterator");
415
88
  mxPushSlot(mxTarget);
416
88
  fxGetPrototypeFromConstructor(the, &mxIteratorPrototype);
417
88
  fxNewObjectInstance(the);
418
88
  mxPullSlot(mxResult);
419
88
}
420
421
void fx_Iterator_concat(txMachine* the)
422
334
{
423
334
  txSlot* list = fxNewInstance(the);
424
334
  txSlot* slot = list;
425
334
  txSlot* property;
426
334
  txInteger c = mxArgc, i;
427
395
  for (i = 0; i < c; i++) {
428
102
    txSlot* item = mxArgv(i);
429
102
    if (!mxIsReference(item))
430
21
      mxTypeError("items[%d]: not an object", i);
431
81
    mxPushSlot(item);
432
81
    slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
433
81
    mxGetID(mxID(_Symbol_iterator));
434
81
    if (!fxIsCallable(the, the->stack))
435
20
      mxTypeError("items[%d]: not iterable", i);
436
61
    slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
437
61
    mxPop();
438
61
  }
439
293
  mxPushNull();
440
293
  property = fxLastProperty(the, fxNewIteratorHelperInstance(the, the->stack, mx_Iterator_concat));
441
293
  property = fxNextReferenceProperty(the, property, list, XS_NO_ID, XS_INTERNAL_FLAG);
442
293
  mxPullSlot(mxResult);
443
293
  mxPop();
444
293
  mxPop();
445
293
}
446
447
txBoolean fx_Iterator_concat_step(txMachine* the, txSlot* iterator, txSlot* next, txSlot* extra, txSlot* value, txFlag status)
448
57
{
449
57
  if (status == XS_NO_STATUS) {
450
68
    for (;;) {
451
68
      if (mxIsNull(iterator)) {
452
46
        txSlot* iterable = extra->value.reference->next;
453
46
        if (!iterable)
454
6
          break;
455
40
        mxPushSlot(iterable);
456
40
        mxPushSlot(iterable->next);
457
40
        extra->value.reference->next = iterable->next->next;
458
40
        mxCall();
459
40
        mxRunCount(0);
460
40
        if (!mxIsReference(the->stack))
461
8
          mxTypeError("iterator: not an object");
462
32
        mxDub();
463
32
        mxGetID(mxID(_next));
464
32
        mxPullSlot(next);
465
32
        mxPullSlot(iterator);
466
32
      }
467
54
      if (fxIteratorNext(the, iterator, next, value))
468
34
        return 1;
469
20
      next->kind = XS_NULL_KIND;
470
20
      iterator->kind = XS_NULL_KIND;
471
20
    }
472
49
  }
473
8
  else if (status == XS_RETURN_STATUS) {
474
8
    if (!mxIsNull(iterator))
475
7
      fxIteratorReturn(the, iterator, 0);
476
8
  }
477
0
  else if (status == XS_THROW_STATUS) {
478
0
    if (!mxIsNull(iterator))
479
0
      fxIteratorReturn(the, iterator, 1);
480
0
  }
481
15
  return 0;
482
57
}
483
484
void fx_Iterator_from(txMachine* the)
485
36
{
486
36
  txSlot *iterator, *next, *property;
487
36
  mxTemporary(iterator);
488
36
  mxTemporary(next);
489
36
  fxGetIteratorFlattenable(the, mxArgv(0), iterator, next, 1);
490
36
  mxPush(mxIteratorConstructor);
491
36
  mxDub();
492
36
  mxGetID(mxID(_Symbol_hasInstance));
493
36
  mxCall();
494
36
  mxPushSlot(iterator);
495
36
  mxRunCount(1);
496
36
  if (fxToBoolean(the, the->stack)) {
497
10
    mxResult->kind = iterator->kind;
498
10
    mxResult->value = iterator->value;
499
10
  }
500
26
  else {
501
26
    mxPush(mxIteratorWrapperPrototype);
502
26
    property = fxLastProperty(the, fxNewIteratorInstance(the, iterator, mxID(_Iterator)));
503
26
    property = fxNextSlotProperty(the, property, next, XS_NO_ID, XS_INTERNAL_FLAG);
504
26
    mxPullSlot(mxResult);
505
26
  }
506
36
  mxPop();
507
36
  mxPop();
508
36
  mxPop();
509
36
}
510
511
void fx_Iterator_prototype_constructor_get(txMachine* the)
512
32
{
513
32
  mxPush(mxIteratorConstructor);
514
32
  mxPullSlot(mxResult);
515
32
}
516
517
void fx_Iterator_prototype_constructor_set(txMachine* the)
518
40
{
519
40
  fxSetterThatIgnoresPrototypeProperties(the, mxThis, mxID(_constructor), "constructor", mxArgv(0));
520
40
}
521
522
void fx_Iterator_prototype_dispose(txMachine* the)
523
3
{ 
524
3
  fxIteratorReturn(the, mxThis, 1);
525
3
}
526
527
void fx_Iterator_prototype_drop(txMachine* the)
528
1.75k
{
529
1.75k
  txSlot *iterator, *property;
530
1.75k
  txNumber limit;
531
1.75k
  if (!fxGetInstance(the, mxThis))
532
6
    mxTypeError("this: not an object");
533
1.74k
  iterator = mxThis;
534
1.74k
  {
535
1.74k
    mxTry(the) {
536
1.74k
      if (mxArgc > 0)
537
1.74k
        mxPushSlot(mxArgv(0));
538
5
      else
539
5
        mxPushUndefined();
540
1.74k
      limit = fxToNumber(the, the->stack);
541
1.74k
      if (c_isnan(limit))
542
11
        mxRangeError("limit: NaN");
543
1.73k
      if (c_isfinite(limit))
544
1.73k
        limit = c_trunc(limit);
545
1.73k
      if (limit < 0)
546
4
        mxRangeError("limit: < 0");
547
1.73k
    }
548
1.73k
    mxCatch(the) {
549
15
      fxIteratorReturn(the, iterator, 1);
550
15
      fxJump(the);
551
15
    }
552
1.74k
  }
553
1.71k
  property = fxLastProperty(the, fxNewIteratorHelperInstance(the, iterator, mx_Iterator_prototype_drop));
554
1.71k
  property = fxNextNumberProperty(the, property, limit, XS_NO_ID, XS_INTERNAL_FLAG);
555
1.71k
  mxPullSlot(mxResult);
556
1.71k
  mxPop();
557
1.71k
}
558
559
txBoolean fx_Iterator_prototype_drop_step(txMachine* the, txSlot* iterator, txSlot* next, txSlot* extra, txSlot* value, txFlag status)
560
1.76k
{
561
1.76k
  txNumber remaining = extra->value.number;
562
1.76k
  if (status == XS_NO_STATUS) {
563
5.05k
    while (remaining > 0) {
564
4.97k
      if (fxIteratorNext(the, iterator, next, value)) {
565
3.31k
        if (c_isfinite(remaining)) {
566
3.30k
          remaining--;
567
3.30k
          extra->value.number = remaining;
568
3.30k
        }
569
3.31k
      }
570
1.66k
      else
571
1.66k
        return 0;
572
4.97k
    }
573
87
    if (fxIteratorNext(the, iterator, next, value))
574
58
      return 1;
575
87
  }
576
15
  else if (status == XS_RETURN_STATUS)
577
15
    fxIteratorReturn(the, iterator, 0);
578
0
  else if (status == XS_THROW_STATUS)
579
0
    fxIteratorReturn(the, iterator, 1);
580
44
  return 0;
581
1.76k
}
582
583
void fx_Iterator_prototype_every(txMachine* the)
584
1.66k
{ 
585
1.66k
  txSlot *iterator, *predicate, *next, *value;
586
1.66k
  txInteger counter;
587
1.66k
  if (!fxGetInstance(the, mxThis))
588
3
    mxTypeError("this: not an object");
589
1.65k
  iterator = mxThis;
590
1.65k
  {
591
1.65k
    mxTry(the) {
592
1.65k
      if (mxArgc > 0)
593
1.65k
        mxPushSlot(mxArgv(0));
594
1
      else
595
1
        mxPushUndefined();
596
1.65k
      predicate = the->stack;
597
1.65k
      if (!fxIsCallable(the, predicate))
598
3
        mxTypeError("predicate: not a function");
599
1.65k
    }
600
1.65k
    mxCatch(the) {
601
3
      fxIteratorReturn(the, iterator, 1);
602
3
      fxJump(the);
603
3
    }
604
1.65k
  }
605
1.65k
  mxPushSlot(iterator);
606
1.65k
  mxGetID(mxID(_next));
607
1.65k
  next = the->stack;
608
1.65k
  mxTemporary(value);
609
1.65k
  counter = 0;
610
1.65k
  mxResult->kind = XS_BOOLEAN_KIND;
611
1.65k
  mxResult->value.boolean = 1;
612
1.65k
  {
613
62.2k
    while (fxIteratorNext(the, iterator, next, value)) {
614
60.6k
      mxTry(the) {
615
60.6k
        mxPushUndefined();
616
60.6k
        mxPushSlot(predicate);
617
60.6k
        mxCall();
618
60.6k
        mxPushSlot(value);
619
60.6k
        mxPushInteger(counter);
620
60.6k
        mxRunCount(2);
621
60.6k
        mxResult->value.boolean = fxToBoolean(the, the->stack);
622
60.6k
        mxPop();
623
60.6k
      }
624
60.6k
      mxCatch(the) {
625
2
        fxIteratorReturn(the, iterator, 1);
626
2
        fxJump(the);
627
2
      }
628
60.6k
      if (!mxResult->value.boolean) {
629
2
        fxIteratorReturn(the, iterator, 0);
630
2
        break;
631
2
      }
632
60.5k
      counter++;
633
60.5k
    }
634
1.65k
  }
635
1.65k
  mxPop();
636
1.65k
  mxPop();
637
1.65k
  mxPop();
638
1.65k
}
639
640
void fx_Iterator_prototype_filter(txMachine* the)
641
28
{ 
642
28
  txSlot *iterator, *predicate, *property;
643
28
  if (!fxGetInstance(the, mxThis))
644
3
    mxTypeError("this: not an object");
645
25
  iterator = mxThis;
646
25
  {
647
25
    mxTry(the) {
648
25
      if (mxArgc > 0)
649
23
        mxPushSlot(mxArgv(0));
650
2
      else
651
2
        mxPushUndefined();
652
25
      predicate = the->stack;
653
25
      if (!fxIsCallable(the, predicate))
654
4
        mxTypeError("predicate: not a function");
655
25
    }
656
21
    mxCatch(the) {
657
4
      fxIteratorReturn(the, iterator, 1);
658
4
      fxJump(the);
659
4
    }
660
25
  }
661
17
  property = fxLastProperty(the, fxNewIteratorHelperInstance(the, iterator, mx_Iterator_prototype_filter));
662
17
  property = fxNextSlotProperty(the, property, predicate, XS_NO_ID, XS_INTERNAL_FLAG);
663
17
  property = fxNextIntegerProperty(the, property, 0, XS_NO_ID, XS_INTERNAL_FLAG);
664
17
  mxPullSlot(mxResult);
665
17
  mxPop();
666
17
}
667
668
txBoolean fx_Iterator_prototype_filter_step(txMachine* the, txSlot* iterator, txSlot* next, txSlot* extra, txSlot* value, txFlag status)
669
34.8k
{
670
34.8k
  txSlot* counter = extra->next;
671
34.8k
  txBoolean selected = 0;
672
34.8k
  if (status == XS_NO_STATUS) {
673
35.1k
    while (fxIteratorNext(the, iterator, next, value)) {
674
35.1k
      mxTry(the) {
675
35.1k
        mxPushUndefined();
676
35.1k
        mxPushSlot(extra);
677
35.1k
        mxCall();
678
35.1k
        mxPushSlot(value);
679
35.1k
        mxPushSlot(counter);
680
35.1k
        mxRunCount(2);
681
35.1k
        selected = fxToBoolean(the, the->stack);
682
35.1k
        mxPop();
683
35.1k
        counter->value.integer++;
684
35.1k
      }
685
35.1k
      mxCatch(the) {
686
1
        fxIteratorReturn(the, iterator, 1);
687
1
        fxJump(the);
688
1
      }
689
35.1k
      if (selected)
690
34.8k
        return 1;
691
35.1k
    }
692
34.8k
  }
693
1
  else if (status == XS_RETURN_STATUS)
694
1
    fxIteratorReturn(the, iterator, 0);
695
0
  else if (status == XS_THROW_STATUS)
696
0
    fxIteratorReturn(the, iterator, 1);
697
12
  return 0;
698
34.8k
}
699
700
void fx_Iterator_prototype_find(txMachine* the)
701
1.65k
{ 
702
1.65k
  txSlot *iterator, *predicate, *next, *value;
703
1.65k
  txInteger counter;
704
1.65k
  txBoolean result;
705
1.65k
  if (!fxGetInstance(the, mxThis))
706
3
    mxTypeError("this: not an object");
707
1.65k
  iterator = mxThis;
708
1.65k
  {
709
1.65k
    mxTry(the) {
710
1.65k
      if (mxArgc > 0)
711
1.65k
        mxPushSlot(mxArgv(0));
712
1
      else
713
1
        mxPushUndefined();
714
1.65k
      predicate = the->stack;
715
1.65k
      if (!fxIsCallable(the, predicate))
716
3
        mxTypeError("predicate: not a function");
717
1.65k
    }
718
1.65k
    mxCatch(the) {
719
3
      fxIteratorReturn(the, iterator, 1);
720
3
      fxJump(the);
721
3
    }
722
1.65k
  }
723
1.64k
  mxPushSlot(iterator);
724
1.64k
  mxGetID(mxID(_next));
725
1.64k
  next = the->stack;
726
1.64k
  mxTemporary(value);
727
1.64k
  counter = 0;
728
1.64k
  {
729
6.57k
    while (fxIteratorNext(the, iterator, next, value)) {
730
4.93k
      mxTry(the) {
731
4.93k
        mxPushUndefined();
732
4.93k
        mxPushSlot(predicate);
733
4.93k
        mxCall();
734
4.93k
        mxPushSlot(value);
735
4.93k
        mxPushInteger(counter);
736
4.93k
        mxRunCount(2);
737
4.93k
        result = fxToBoolean(the, the->stack);
738
4.93k
        mxPop();
739
4.93k
      }
740
4.93k
      mxCatch(the) {
741
2
        fxIteratorReturn(the, iterator, 1);
742
2
        fxJump(the);
743
2
      }
744
4.93k
      if (result) {
745
3
        mxResult->kind = value->kind;
746
3
        mxResult->value = value->value;
747
3
        fxIteratorReturn(the, iterator, 0);
748
3
        break;
749
3
      }
750
4.92k
      counter++;
751
4.92k
    }
752
1.64k
  }
753
1.64k
  mxPop();
754
1.64k
  mxPop();
755
1.64k
  mxPop();
756
1.64k
}
757
758
void fx_Iterator_prototype_flatMap(txMachine* the)
759
40
{ 
760
40
  txSlot *iterator, *mapper, *property;
761
40
  if (!fxGetInstance(the, mxThis))
762
3
    mxTypeError("this: not an object");
763
37
  iterator = mxThis;
764
37
  {
765
37
    mxTry(the) {
766
37
      if (mxArgc > 0)
767
36
        mxPushSlot(mxArgv(0));
768
1
      else
769
1
        mxPushUndefined();
770
37
      mapper = the->stack;
771
37
      if (!fxIsCallable(the, mapper))
772
3
        mxTypeError("mapper: not a function");
773
37
    }
774
34
    mxCatch(the) {
775
3
      fxIteratorReturn(the, iterator, 1);
776
3
      fxJump(the);
777
3
    }
778
37
  }
779
31
  property = fxLastProperty(the, fxNewIteratorHelperInstance(the, iterator, mx_Iterator_prototype_flatMap));
780
31
  property = fxNextSlotProperty(the, property, mapper, XS_NO_ID, XS_INTERNAL_FLAG);
781
31
  property = fxNextIntegerProperty(the, property, 0, XS_NO_ID, XS_INTERNAL_FLAG);
782
31
  property = fxNextNullProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
783
31
  property = fxNextNullProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
784
31
  mxPullSlot(mxResult);
785
31
  mxPop();
786
31
}
787
788
txBoolean fx_Iterator_prototype_flatMap_step(txMachine* the, txSlot* iterator, txSlot* next, txSlot* extra, txSlot* value, txFlag status)
789
110k
{
790
110k
  txSlot* counter = extra->next;
791
110k
  txSlot* innerIterator = counter->next;
792
110k
  txSlot* innerNext = innerIterator->next;
793
110k
  if (status == XS_NO_STATUS) {
794
216k
  again:
795
216k
    if (mxIsNull(innerIterator)) {
796
106k
      if (fxIteratorNext(the, iterator, next, value)) {
797
106k
        mxTry(the) {
798
106k
          mxPushUndefined();
799
106k
          mxPushSlot(extra);
800
106k
          mxCall();
801
106k
          mxPushSlot(value);
802
106k
          mxPushSlot(counter);
803
106k
          mxRunCount(2);
804
106k
          fxGetIteratorFlattenable(the, the->stack, innerIterator, innerNext, 0);
805
106k
          mxPop();
806
106k
        }
807
106k
        mxCatch(the) {
808
5
          fxIteratorReturn(the, iterator, 1);
809
5
          fxJump(the);
810
5
        }
811
106k
        counter->value.integer++;
812
106k
      }
813
17
      else
814
17
        return 0;
815
106k
    }
816
216k
    if (fxIteratorNext(the, innerIterator, innerNext, value))
817
110k
      return 1;
818
106k
    innerIterator->kind = XS_NULL_KIND;
819
106k
    innerNext->kind = XS_NULL_KIND;
820
106k
    goto again;
821
216k
  }
822
2
  else if (status == XS_RETURN_STATUS) {
823
2
    if (!mxIsNull(innerIterator))
824
1
      fxIteratorReturn(the, innerIterator, 0);
825
2
    fxIteratorReturn(the, iterator, 0);
826
2
  }
827
0
  else if (status == XS_THROW_STATUS) {
828
0
    if (!mxIsNull(innerIterator))
829
0
      fxIteratorReturn(the, innerIterator, 1);
830
0
    fxIteratorReturn(the, iterator, 1);
831
0
  }
832
2
  return 0;
833
110k
}
834
835
void fx_Iterator_prototype_forEach(txMachine* the)
836
14
{ 
837
14
  txSlot *iterator, *procedure, *next, *value;
838
14
  txInteger counter;
839
14
  if (!fxGetInstance(the, mxThis))
840
3
    mxTypeError("this: not an object");
841
11
  iterator = mxThis;
842
11
  {
843
11
    mxTry(the) {
844
11
      if (mxArgc > 0)
845
10
        mxPushSlot(mxArgv(0));
846
1
      else
847
1
        mxPushUndefined();
848
11
      procedure = the->stack;
849
11
      if (!fxIsCallable(the, procedure))
850
3
        mxTypeError("procedure: not a function");
851
11
    }
852
8
    mxCatch(the) {
853
3
      fxIteratorReturn(the, iterator, 1);
854
3
      fxJump(the);
855
3
    }
856
11
  }
857
5
  mxPushSlot(iterator);
858
5
  mxGetID(mxID(_next));
859
5
  next = the->stack;
860
5
  mxTemporary(value);
861
5
  counter = 0;
862
5
  {
863
17
    while (fxIteratorNext(the, iterator, next, value)) {
864
13
      mxTry(the) {
865
13
        mxPushUndefined();
866
13
        mxPushSlot(procedure);
867
13
        mxCall();
868
13
        mxPushSlot(value);
869
13
        mxPushInteger(counter);
870
13
        mxRunCount(2);
871
13
        mxPop();
872
13
      }
873
13
      mxCatch(the) {
874
1
        fxIteratorReturn(the, iterator, 1);
875
1
        fxJump(the);
876
1
      }
877
12
      counter++;
878
12
    }
879
5
  }
880
4
  mxPop();
881
4
  mxPop();
882
4
  mxPop();
883
4
}
884
885
void fx_Iterator_prototype_iterator(txMachine* the)
886
62.9k
{
887
62.9k
  *mxResult = *mxThis;
888
62.9k
}
889
890
void fx_Iterator_prototype_map(txMachine* the)
891
23
{ 
892
23
  txSlot *iterator, *mapper, *property;
893
23
  if (!fxGetInstance(the, mxThis))
894
3
    mxTypeError("this: not an object");
895
20
  iterator = mxThis;
896
20
  {
897
20
    mxTry(the) {
898
20
      if (mxArgc > 0)
899
19
        mxPushSlot(mxArgv(0));
900
1
      else
901
1
        mxPushUndefined();
902
20
      mapper = the->stack;
903
20
      if (!fxIsCallable(the, mapper))
904
3
        mxTypeError("mapper: not a function");
905
20
    }
906
17
    mxCatch(the) {
907
3
      fxIteratorReturn(the, iterator, 1);
908
3
      fxJump(the);
909
3
    }
910
20
  }
911
14
  property = fxLastProperty(the, fxNewIteratorHelperInstance(the, iterator, mx_Iterator_prototype_map));
912
14
  property = fxNextSlotProperty(the, property, mapper, XS_NO_ID, XS_INTERNAL_FLAG);
913
14
  property = fxNextIntegerProperty(the, property, 0, XS_NO_ID, XS_INTERNAL_FLAG);
914
14
  mxPullSlot(mxResult);
915
14
  mxPop();
916
14
}
917
918
txBoolean fx_Iterator_prototype_map_step(txMachine* the, txSlot* iterator, txSlot* next, txSlot* extra, txSlot* value, txFlag status)
919
35.3k
{
920
35.3k
  txSlot* counter = extra->next;
921
35.3k
  if (status == XS_NO_STATUS) {
922
35.3k
    if (fxIteratorNext(the, iterator, next, value)) {
923
35.3k
      mxTry(the) {
924
35.3k
        mxPushUndefined();
925
35.3k
        mxPushSlot(extra);
926
35.3k
        mxCall();
927
35.3k
        mxPushSlot(value);
928
35.3k
        mxPushSlot(counter);
929
35.3k
        mxRunCount(2);
930
35.3k
        mxPullSlot(value);
931
35.3k
        counter->value.integer++;
932
35.3k
      }
933
35.3k
      mxCatch(the) {
934
1
        fxIteratorReturn(the, iterator, 1);
935
1
        fxJump(the);
936
1
      }
937
35.3k
      return 1;
938
35.3k
    }
939
35.3k
  }
940
1
  else if (status == XS_RETURN_STATUS)
941
1
    fxIteratorReturn(the, iterator, 0);
942
0
  else if (status == XS_THROW_STATUS)
943
0
    fxIteratorReturn(the, iterator, 1);
944
10
  return 0;
945
35.3k
}
946
947
void fx_Iterator_prototype_reduce(txMachine* the)
948
49.1k
{ 
949
49.1k
  txSlot *iterator, *reducer, *next, *value;
950
49.1k
  txInteger counter;
951
49.1k
  if (!fxGetInstance(the, mxThis))
952
9
    mxTypeError("this: not an object");
953
49.1k
  iterator = mxThis;
954
49.1k
  {
955
49.1k
    mxTry(the) {
956
49.1k
      if (mxArgc > 0)
957
49.1k
        mxPushSlot(mxArgv(0));
958
1
      else
959
1
        mxPushUndefined();
960
49.1k
      reducer = the->stack;
961
49.1k
      if (!fxIsCallable(the, reducer))
962
5
        mxTypeError("reducer: not a function");
963
49.1k
    }
964
49.1k
    mxCatch(the) {
965
5
      fxIteratorReturn(the, iterator, 1);
966
5
      fxJump(the);
967
5
    }
968
49.1k
  }
969
49.1k
  mxPushSlot(iterator);
970
49.1k
  mxGetID(mxID(_next));
971
49.1k
  next = the->stack;
972
49.1k
  mxTemporary(value);
973
49.1k
  if (mxArgc > 1) {
974
8
    mxPushSlot(mxArgv(1));
975
8
    counter = 0;
976
8
  }
977
49.1k
  else {
978
49.1k
    mxPushUndefined();
979
49.1k
    if (!fxIteratorNext(the, iterator, next, the->stack))
980
1
      mxTypeError("no initial value");
981
49.1k
    counter = 1;
982
49.1k
  }
983
49.1k
  mxPullSlot(mxResult);
984
49.1k
  {
985
84.2k
    while (fxIteratorNext(the, iterator, next, value)) {
986
35.0k
      mxTry(the) {
987
35.0k
        mxPushUndefined();
988
35.0k
        mxPushSlot(reducer);
989
35.0k
        mxCall();
990
35.0k
        mxPushSlot(mxResult);
991
35.0k
        mxPushSlot(value);
992
35.0k
        mxPushInteger(counter);
993
35.0k
        mxRunCount(3);
994
35.0k
        mxPullSlot(mxResult);
995
35.0k
        counter++;
996
35.0k
      }
997
35.0k
      mxCatch(the) {
998
0
        fxIteratorReturn(the, iterator, 1);
999
0
        fxJump(the);
1000
0
      }
1001
35.0k
    }
1002
49.1k
  }
1003
49.1k
  mxPop();
1004
49.1k
  mxPop();
1005
49.1k
  mxPop();
1006
49.1k
}
1007
1008
void fx_Iterator_prototype_some(txMachine* the)
1009
20
{ 
1010
20
  txSlot *iterator, *predicate, *next, *value;
1011
20
  txInteger counter;
1012
20
  if (!fxGetInstance(the, mxThis))
1013
3
    mxTypeError("this: not an object");
1014
17
  iterator = mxThis;
1015
17
  {
1016
17
    mxTry(the) {
1017
17
      if (mxArgc > 0)
1018
16
        mxPushSlot(mxArgv(0));
1019
1
      else
1020
1
        mxPushUndefined();
1021
17
      predicate = the->stack;
1022
17
      if (!fxIsCallable(the, predicate))
1023
3
        mxTypeError("predicate: not a function");
1024
17
    }
1025
14
    mxCatch(the) {
1026
3
      fxIteratorReturn(the, iterator, 1);
1027
3
      fxJump(the);
1028
3
    }
1029
17
  }
1030
11
  mxPushSlot(iterator);
1031
11
  mxGetID(mxID(_next));
1032
11
  next = the->stack;
1033
11
  mxTemporary(value);
1034
11
  counter = 0;
1035
11
  mxResult->kind = XS_BOOLEAN_KIND;
1036
11
  mxResult->value.boolean = 0;
1037
11
  {
1038
97.5k
    while (fxIteratorNext(the, iterator, next, value)) {
1039
97.5k
      mxTry(the) {
1040
97.5k
        mxPushUndefined();
1041
97.5k
        mxPushSlot(predicate);
1042
97.5k
        mxCall();
1043
97.5k
        mxPushSlot(value);
1044
97.5k
        mxPushInteger(counter);
1045
97.5k
        mxRunCount(2);
1046
97.5k
        mxResult->value.boolean = fxToBoolean(the, the->stack);
1047
97.5k
        mxPop();
1048
97.5k
      }
1049
97.5k
      mxCatch(the) {
1050
1
        fxIteratorReturn(the, iterator, 1);
1051
1
        fxJump(the);
1052
1
      }
1053
97.5k
      if (mxResult->value.boolean) {
1054
3
        fxIteratorReturn(the, iterator, 0);
1055
3
        break;
1056
3
      }
1057
97.5k
      counter++;
1058
97.5k
    }
1059
11
  }
1060
10
  mxPop();
1061
10
  mxPop();
1062
10
  mxPop();
1063
10
}
1064
1065
void fx_Iterator_prototype_take(txMachine* the)
1066
61.2k
{ 
1067
61.2k
  txSlot *iterator, *property;
1068
61.2k
  txNumber limit;
1069
61.2k
  if (!fxGetInstance(the, mxThis))
1070
5
    mxTypeError("this: not an object");
1071
61.2k
  iterator = mxThis;
1072
61.2k
  {
1073
61.2k
    mxTry(the) {
1074
61.2k
      if (mxArgc > 0)
1075
61.2k
        mxPushSlot(mxArgv(0));
1076
3
      else
1077
3
        mxPushUndefined();
1078
61.2k
      limit = fxToNumber(the, the->stack);
1079
61.2k
      if (c_isnan(limit))
1080
13
        mxRangeError("limit: NaN");
1081
61.2k
      if (c_isfinite(limit))
1082
61.2k
        limit = c_trunc(limit);
1083
61.2k
      if (limit < 0)
1084
13
        mxRangeError("limit: < 0");
1085
61.2k
    }
1086
61.2k
    mxCatch(the) {
1087
26
      fxIteratorReturn(the, iterator, 1);
1088
26
      fxJump(the);
1089
26
    }
1090
61.2k
  }
1091
61.2k
  property = fxLastProperty(the, fxNewIteratorHelperInstance(the, iterator, mx_Iterator_prototype_take));
1092
61.2k
  property = fxNextNumberProperty(the, property, limit, XS_NO_ID, XS_INTERNAL_FLAG);
1093
61.2k
  mxPullSlot(mxResult);
1094
61.2k
  mxPop();
1095
61.2k
}
1096
1097
txBoolean fx_Iterator_prototype_take_step(txMachine* the, txSlot* iterator, txSlot* next, txSlot* extra, txSlot* value, txFlag status)
1098
61.3k
{
1099
61.3k
  txNumber remaining = extra->value.number;
1100
61.3k
  if (status == XS_NO_STATUS) {
1101
61.2k
    if (remaining == 0) {
1102
14
      fxIteratorReturn(the, iterator, 0);
1103
14
      return 0;
1104
14
    }
1105
61.2k
    if (c_isfinite(remaining)) {
1106
61.2k
      remaining--;
1107
61.2k
      extra->value.number = remaining;
1108
61.2k
    }
1109
61.2k
    if (fxIteratorNext(the, iterator, next, value))
1110
91
      return 1;
1111
61.2k
  }
1112
18
  else if (status == XS_RETURN_STATUS)
1113
18
    fxIteratorReturn(the, iterator, 0);
1114
0
  else if (status == XS_THROW_STATUS)
1115
0
    fxIteratorReturn(the, iterator, 1);
1116
61.2k
  return 0;
1117
61.3k
}
1118
1119
void fx_Iterator_prototype_toArray(txMachine* the)
1120
16
{ 
1121
16
  txSlot *iterator, *next, *value, *instance, *internal, *item;
1122
16
  if (!fxGetInstance(the, mxThis))
1123
3
    mxTypeError("this: not an object");
1124
13
  iterator = mxThis;
1125
13
  mxPushSlot(iterator);
1126
13
  mxGetID(mxID(_next));
1127
13
  next = the->stack;
1128
13
  mxTemporary(value);
1129
13
  mxPush(mxArrayPrototype);
1130
13
  instance = fxNewArrayInstance(the);
1131
13
  mxPullSlot(mxResult);
1132
13
  internal = instance->next;
1133
13
  item = internal;
1134
178k
  while (fxIteratorNext(the, iterator, next, value)) {
1135
178k
    internal->value.array.length++;
1136
178k
    item->next = fxNewSlot(the);
1137
178k
    item = item->next;
1138
178k
    item->kind = value->kind;
1139
178k
    item->value = value->value;
1140
178k
  }
1141
13
  fxCacheArray(the, instance);
1142
13
  mxPop();
1143
13
  mxPop();
1144
13
}
1145
1146
void fx_Iterator_prototype_toStringTag_get(txMachine* the)
1147
32
{ 
1148
32
  mxPushStringC("Iterator");
1149
32
  mxPullSlot(mxResult);
1150
32
}
1151
1152
void fx_Iterator_prototype_toStringTag_set(txMachine* the)
1153
32
{ 
1154
32
  fxSetterThatIgnoresPrototypeProperties(the, mxThis, mxID(_Symbol_toStringTag), "Symbol(toStringTag)", mxArgv(0));
1155
32
}
1156
1157
txSlot* fxNewIteratorHelperInstance(txMachine* the, txSlot* iterator, txInteger step) 
1158
63.3k
{
1159
63.3k
  txSlot* instance;
1160
63.3k
  txSlot* property;
1161
63.3k
  mxPush(mxIteratorHelperPrototype);
1162
63.3k
  instance = fxNewIteratorInstance(the, iterator, mxID(_Iterator));
1163
63.3k
  property = fxLastProperty(the, instance);
1164
63.3k
  property->ID = gxIteratorStepIDs[step];
1165
63.3k
  property->value.integer = step;
1166
63.3k
  if (mxIsNull(iterator))
1167
293
    property = fxNextNullProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
1168
63.0k
  else {
1169
63.0k
    mxPushSlot(iterator);
1170
63.0k
    mxGetID(mxID(_next));
1171
63.0k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
1172
63.0k
    mxPop();
1173
63.0k
  }
1174
63.3k
  return instance;
1175
63.3k
}
1176
1177
void fx_IteratorHelper_prototype_next(txMachine* the)
1178
297k
{
1179
297k
  txSlot* instance = fxCheckIteratorInstance(the, mxThis, mxID(_Iterator));
1180
297k
  txSlot* result = instance->next;
1181
297k
  txSlot* iterator = result->next;
1182
297k
  txSlot* step = fxCheckIteratorStep(the, iterator->next);
1183
297k
  txSlot* next = step->next;
1184
297k
  txSlot* extra = next->next;
1185
297k
  txSlot* value = fxCheckIteratorResult(the, result);
1186
297k
  txSlot* done = value->next;
1187
297k
  if (step->flag & XS_DONT_SET_FLAG)
1188
3
    mxTypeError("recursive iterator");
1189
297k
  {
1190
297k
    mxTry(the) {
1191
297k
      step->flag |= XS_DONT_SET_FLAG;
1192
297k
      if (!done->value.boolean) {
1193
244k
        if (!(*gxIteratorSteps[step->value.integer])(the, iterator, next, extra, value, XS_NO_STATUS)) {
1194
61.2k
          value->kind = XS_UNDEFINED_KIND;
1195
61.2k
          done->value.boolean = 1;
1196
61.2k
        }
1197
244k
      }
1198
297k
      mxResult->kind = result->kind;
1199
297k
      mxResult->value = result->value;
1200
297k
      step->flag &= ~XS_DONT_SET_FLAG;
1201
297k
    }
1202
297k
    mxCatch(the) {
1203
39
      step->flag &= ~XS_DONT_SET_FLAG;
1204
39
      value->kind = XS_UNDEFINED_KIND;
1205
39
      done->value.boolean = 1;
1206
39
      fxJump(the);
1207
39
    }
1208
297k
  }
1209
297k
}
1210
1211
void fx_IteratorHelper_prototype_return(txMachine* the)
1212
70
{
1213
70
  txSlot* instance = fxCheckIteratorInstance(the, mxThis, mxID(_Iterator));
1214
70
  txSlot* result = instance->next;
1215
70
  txSlot* iterator = result->next;
1216
70
  txSlot* step = fxCheckIteratorStep(the, iterator->next);
1217
70
  txSlot* next = step->next;
1218
70
  txSlot* extra = next->next;
1219
70
  txSlot* value = fxCheckIteratorResult(the, result);
1220
70
  txSlot* done = value->next;
1221
70
  if (step->flag & XS_DONT_SET_FLAG)
1222
1
    mxTypeError("recursive iterator");
1223
69
  {
1224
69
    mxTry(the) {
1225
69
      step->flag |= XS_DONT_SET_FLAG;
1226
69
      if (!done->value.boolean) {
1227
45
        value->kind = XS_UNDEFINED_KIND;
1228
45
        done->value.boolean = 1;
1229
45
        (*gxIteratorSteps[step->value.integer])(the, iterator, next, extra, value, XS_RETURN_STATUS);
1230
45
      }
1231
69
      mxResult->kind = result->kind;
1232
69
      mxResult->value = result->value;
1233
69
      step->flag &= ~XS_DONT_SET_FLAG;
1234
69
    }
1235
69
    mxCatch(the) {
1236
2
      step->flag &= ~XS_DONT_SET_FLAG;
1237
2
      fxJump(the);
1238
2
    }
1239
69
  }
1240
69
}
1241
1242
void fx_IteratorWrapper_prototype_next(txMachine* the)
1243
44.1k
{
1244
44.1k
  txSlot* instance = fxCheckIteratorInstance(the, mxThis, mxID(_Iterator));
1245
44.1k
  txSlot* result = instance->next;
1246
44.1k
  txSlot* iterator = result->next;
1247
44.1k
  txSlot* step = iterator->next;
1248
44.1k
  txSlot* next = step->next;
1249
44.1k
  mxPushSlot(iterator);
1250
44.1k
  mxPushSlot(next);
1251
44.1k
  mxCall();
1252
44.1k
  mxRunCount(0);
1253
44.1k
  mxPullSlot(mxResult);
1254
44.1k
}
1255
1256
void fx_IteratorWrapper_prototype_return(txMachine* the)
1257
23
{
1258
23
  txSlot* instance = fxCheckIteratorInstance(the, mxThis, mxID(_Iterator));
1259
23
  txSlot* result = instance->next;
1260
23
  txSlot* iterator = result->next;
1261
23
  txSlot* value = fxCheckIteratorResult(the, result);
1262
23
  txSlot* done = value->next;
1263
23
  mxPushSlot(iterator);
1264
23
  mxDub();
1265
23
  mxGetID(mxID(_return));
1266
23
  if (mxIsUndefined(the->stack) || mxIsNull(the->stack)) {
1267
22
    mxPop();
1268
22
    value->kind = XS_UNDEFINED_KIND;
1269
22
    done->value.boolean = 1;
1270
22
    mxResult->kind = result->kind;
1271
22
    mxResult->value = result->value;
1272
22
  }
1273
1
  else {
1274
1
    mxCall();
1275
1
    mxRunCount(0);
1276
1
    mxPullSlot(mxResult);
1277
1
  }
1278
23
}
1279
1280
txSlot* fxCheckGeneratorInstance(txMachine* the, txSlot* slot)
1281
281k
{
1282
281k
  if (slot->kind == XS_REFERENCE_KIND) {
1283
281k
    txSlot* instance = slot->value.reference;
1284
281k
    slot = instance->next;
1285
281k
    if (slot && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_STACK_KIND))
1286
281k
      return instance;
1287
281k
  }
1288
281k
  mxTypeError("this: not a Generator instance");
1289
0
  return C_NULL;
1290
281k
}
1291
1292
txSlot* fxNewGeneratorInstance(txMachine* the)
1293
1.71M
{
1294
1.71M
  txSlot* prototype;
1295
1.71M
  txSlot* instance;
1296
1.71M
  txSlot* property;
1297
1298
1.71M
  prototype = (the->stack->kind == XS_REFERENCE_KIND) ? the->stack->value.reference : mxGeneratorPrototype.value.reference;
1299
1300
1.71M
  instance = fxNewSlot(the);
1301
1.71M
  instance->kind = XS_INSTANCE_KIND;
1302
1.71M
  instance->value.instance.garbage = C_NULL;
1303
1.71M
  instance->value.instance.prototype = prototype;
1304
1.71M
  the->stack->value.reference = instance;
1305
1.71M
  the->stack->kind = XS_REFERENCE_KIND;
1306
1307
1.71M
  property = instance->next = fxNewSlot(the);
1308
1.71M
  property->flag = XS_INTERNAL_FLAG;
1309
1.71M
  property->kind = XS_STACK_KIND;
1310
1.71M
  property->ID = XS_NO_ID;
1311
1.71M
    property->value.stack.length = 0;
1312
1.71M
    property->value.stack.address = C_NULL;
1313
  
1314
1.71M
    property = property->next = fxNewSlot(the);
1315
1.71M
  property->flag = XS_INTERNAL_FLAG;
1316
1.71M
  property->kind = XS_INTEGER_KIND;
1317
1.71M
  property->value.integer = XS_CODE_START_GENERATOR;
1318
  
1319
1.71M
  return instance;
1320
1.71M
}
1321
1322
void fxNewGeneratorResult(txMachine* the, txBoolean done)
1323
110k
{
1324
110k
  txSlot* value = the->stack;
1325
110k
  txSlot* slot;
1326
110k
  mxPush(mxObjectPrototype);
1327
110k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
1328
110k
  slot = fxNextSlotProperty(the, slot, value, mxID(_value), XS_DONT_DELETE_FLAG | XS_DONT_SET_FLAG);
1329
110k
  slot = fxNextBooleanProperty(the, slot, done, mxID(_done), XS_DONT_DELETE_FLAG | XS_DONT_SET_FLAG);
1330
110k
  mxPullSlot(value);
1331
110k
}
1332
1333
void fx_Generator(txMachine* the)
1334
0
{
1335
0
  if (mxHasTarget)
1336
0
    mxTypeError("new: Generator");
1337
0
}
1338
1339
void fx_Generator_prototype_aux(txMachine* the, txFlag status)
1340
281k
{
1341
281k
  txSlot* generator = fxCheckGeneratorInstance(the, mxThis);
1342
281k
  txSlot* stack = generator->next;
1343
281k
  txSlot* state = stack->next;
1344
1345
281k
  if (state->value.integer == XS_NO_CODE)
1346
3
    mxTypeError("generator is running");
1347
281k
  if ((state->value.integer == XS_CODE_START_GENERATOR) && (status != XS_NO_STATUS))
1348
28
    state->value.integer = XS_CODE_END;
1349
281k
  if (mxArgc > 0)
1350
8
    mxPushSlot(mxArgv(0));
1351
281k
  else
1352
281k
    mxPushUndefined();
1353
281k
  if (state->value.integer == XS_CODE_END) {
1354
76
    if (status == XS_THROW_STATUS) {
1355
1
      mxException.kind = the->stack->kind;
1356
1
      mxException.value = the->stack->value;
1357
1
      fxJump(the);
1358
1
    }
1359
75
    if (status == XS_NO_STATUS)
1360
16
      the->stack->kind = XS_UNDEFINED_KIND;
1361
75
    fxNewGeneratorResult(the, 1);
1362
75
    mxPullSlot(mxResult);
1363
75
  }
1364
281k
  else {
1365
281k
    mxTry(the) {
1366
281k
      the->scratch.kind = the->stack->kind;
1367
281k
      the->scratch.value = the->stack->value;
1368
281k
      the->status = status;
1369
281k
      state->value.integer = XS_NO_CODE;
1370
281k
      fxRunID(the, generator, XS_NO_ID);
1371
281k
      if (state->value.integer == XS_NO_CODE) {
1372
110k
        state->value.integer = XS_CODE_END;
1373
110k
        fxNewGeneratorResult(the, 1);
1374
110k
      }
1375
281k
      mxPullSlot(mxResult);
1376
281k
    }
1377
281k
    mxCatch(the) {
1378
16
      state->value.integer = XS_CODE_END;
1379
16
      fxJump(the);
1380
16
    }
1381
281k
  }
1382
281k
}
1383
1384
void fx_Generator_prototype_next(txMachine* the)
1385
281k
{
1386
281k
  fx_Generator_prototype_aux(the, XS_NO_STATUS);
1387
281k
}
1388
1389
void fx_Generator_prototype_return(txMachine* the)
1390
87
{
1391
87
  fx_Generator_prototype_aux(the, XS_RETURN_STATUS);
1392
87
}
1393
1394
void fx_Generator_prototype_throw(txMachine* the)
1395
10
{
1396
10
  fx_Generator_prototype_aux(the, XS_THROW_STATUS);
1397
10
}
1398
1399
txSlot* fxNewGeneratorFunctionInstance(txMachine* the, txID name)
1400
7.45k
{
1401
7.45k
  txSlot* instance;
1402
7.45k
  txSlot* property;
1403
1404
7.45k
  instance = fxNewFunctionInstance(the, name);
1405
7.45k
  property = fxLastProperty(the, instance);
1406
7.45k
  mxPush(mxGeneratorPrototype);
1407
7.45k
  fxNewObjectInstance(the);
1408
7.45k
  fxNextSlotProperty(the, property, the->stack, mxID(_prototype), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG);
1409
7.45k
  mxPop();
1410
  
1411
7.45k
  return instance;
1412
7.45k
}
1413
1414
void fx_GeneratorFunction(txMachine* the)
1415
47
{ 
1416
47
  txInteger c, i;
1417
47
  txStringStream stream;
1418
47
  txSlot* module = mxFunctionInstanceHome(mxFunction->value.reference)->value.home.module;
1419
47
  if (!module) module = mxProgram.value.reference;
1420
  
1421
47
  c = mxArgc;
1422
47
  i = 0;
1423
47
  mxPushStringX("(function* anonymous(");
1424
62
  while (c > 1) {
1425
15
    fxToString(the, mxArgv(i));
1426
15
    fxConcatString(the, the->stack, mxArgv(i));
1427
15
    if (c > 2)
1428
7
      fxConcatStringC(the, the->stack, ", ");
1429
15
    c--;
1430
15
    i++;
1431
15
  }
1432
47
  fxConcatStringC(the, the->stack, "\n){");
1433
47
  if (c > 0) {
1434
18
    fxToString(the, mxArgv(i));
1435
18
    fxConcatString(the, the->stack, mxArgv(i));
1436
18
  }
1437
47
  fxConcatStringC(the, the->stack, "\n})");
1438
47
  stream.slot = the->stack;
1439
47
  stream.offset = 0;
1440
47
  stream.size = mxStringLength(the->stack->value.string);
1441
47
  fxRunScript(the, fxParseScript(the, &stream, fxStringGetter, mxProgramFlag | mxGeneratorFlag), C_NULL, C_NULL, C_NULL, C_NULL, module);
1442
47
  mxPullSlot(mxResult);
1443
47
  if (mxHasTarget && !fxIsSameSlot(the, mxTarget, mxFunction)) {
1444
0
    mxPushSlot(mxTarget);
1445
0
    fxGetPrototypeFromConstructor(the, &mxGeneratorFunctionPrototype);
1446
0
    mxResult->value.reference->value.instance.prototype = the->stack->value.reference;
1447
0
    mxPop();
1448
0
  }
1449
47
}
1450
1451
void fx_Enumerator(txMachine* the)
1452
408k
{
1453
408k
  txSlot* iterator;
1454
408k
  txSlot* result;
1455
408k
  txSlot* slot;
1456
408k
  txSlot* keys;
1457
408k
  txSlot* visited;
1458
  
1459
408k
  mxPush(mxEnumeratorFunction);
1460
408k
  mxGetID(mxID(_prototype));
1461
408k
  iterator = fxNewObjectInstance(the);
1462
408k
  mxPullSlot(mxResult);
1463
408k
  mxPush(mxObjectPrototype);
1464
408k
  result = fxNewObjectInstance(the);
1465
408k
  slot = fxNextUndefinedProperty(the, result, mxID(_value), XS_DONT_DELETE_FLAG | XS_DONT_SET_FLAG);
1466
408k
  slot = fxNextBooleanProperty(the, slot, 0, mxID(_done), XS_DONT_DELETE_FLAG | XS_DONT_SET_FLAG);
1467
408k
  slot = fxNextSlotProperty(the, iterator, the->stack, mxID(_result), XS_GET_ONLY);
1468
408k
  mxPop();
1469
  
1470
408k
  slot = slot->next = fxNewSlot(the);
1471
408k
  slot->flag = XS_GET_ONLY;
1472
408k
  slot->ID = mxID(_iterable);
1473
408k
  slot->kind = mxThis->kind;
1474
408k
  slot->value = mxThis->value;
1475
408k
  if (mxIsUndefined(slot) || mxIsNull(slot))
1476
171
    return;
1477
408k
  fxToInstance(the, slot);
1478
    
1479
408k
  keys = fxNewInstance(the);
1480
408k
  mxBehaviorOwnKeys(the, slot->value.reference, XS_EACH_NAME_FLAG, keys);
1481
408k
  slot = slot->next = fxNewSlot(the);
1482
408k
  slot->flag = XS_GET_ONLY;
1483
408k
  slot->kind = XS_REFERENCE_KIND;
1484
408k
  slot->value.reference = keys;
1485
408k
  mxPop();
1486
  
1487
408k
  visited = fxNewInstance(the);
1488
408k
  slot = slot->next = fxNewSlot(the);
1489
408k
  slot->flag = XS_GET_ONLY;
1490
408k
  slot->kind = XS_REFERENCE_KIND;
1491
408k
  slot->value.reference = visited;
1492
408k
  mxPop();
1493
408k
}
1494
1495
void fx_Enumerator_prototype_next(txMachine* the)
1496
5.56M
{
1497
5.56M
  txSlot* iterator = fxGetInstance(the, mxThis);
1498
5.56M
  txSlot* result = iterator->next;
1499
5.56M
  txSlot* iterable = result->next;
1500
5.56M
  txSlot* at = C_NULL;
1501
5.56M
  if (mxIsReference(iterable)) {
1502
5.56M
    txSlot* instance = iterable->value.reference;
1503
5.56M
    txSlot* keys = iterable->next;
1504
5.56M
    txSlot* visited = keys->next;
1505
5.56M
    txSlot* slot;
1506
5.56M
    txSlot* former;
1507
  
1508
5.56M
    keys = keys->value.reference;
1509
5.56M
    visited = visited->value.reference;
1510
  
1511
5.56M
    mxPushUndefined();
1512
5.56M
    slot = the->stack;
1513
6.41M
  again:  
1514
17.4M
    while ((at = keys->next)) {
1515
16.1M
      if (mxBehaviorGetOwnProperty(the, instance, at->value.at.id, at->value.at.index, slot)) {
1516
16.1M
        txSlot** address = &(visited->next);
1517
1.63G
        while ((former = *address)) {
1518
1.62G
          if ((at->value.at.id == former->value.at.id) && (at->value.at.index == former->value.at.index))
1519
1.34M
            break;
1520
1.62G
          address = &(former->next);
1521
1.62G
        }
1522
16.1M
        if (!former) {
1523
14.7M
          *address = at;
1524
14.7M
          keys->next = at->next;
1525
14.7M
          at->next = NULL;
1526
14.7M
          if (!(slot->flag & XS_DONT_ENUM_FLAG)) {
1527
5.15M
            fxKeyAt(the, at->value.at.id, at->value.at.index, result->value.reference->next);
1528
5.15M
            break;
1529
5.15M
          }
1530
14.7M
        }
1531
1.34M
        else
1532
1.34M
          keys->next = at->next;
1533
16.1M
      }
1534
1
      else
1535
1
        keys->next = at->next;
1536
16.1M
    }
1537
6.41M
    if (!at) {
1538
1.25M
      if (mxBehaviorGetPrototype(the, instance, slot)) {
1539
851k
        iterable->value.reference = instance = slot->value.reference;
1540
851k
        mxBehaviorOwnKeys(the, instance, XS_EACH_NAME_FLAG, keys);
1541
851k
        goto again;
1542
851k
      }
1543
1.25M
    }
1544
5.56M
    mxPop();
1545
5.56M
  }
1546
5.56M
  if (!at) {
1547
407k
    result->value.reference->next->kind = XS_UNDEFINED_KIND;
1548
407k
    result->value.reference->next->next->value.boolean = 1;
1549
407k
  }
1550
5.56M
  mxResult->kind = result->kind;
1551
5.56M
  mxResult->value = result->value;
1552
5.56M
}
1553
1554
void fx_AsyncIterator_prototype_asyncDispose(txMachine* the)
1555
2
{ 
1556
2
  mxTry(the) {
1557
2
    mxPushUndefined();
1558
2
    mxPush(mxPromiseConstructor);
1559
2
    mxPushSlot(mxThis);
1560
2
    mxDub();
1561
2
    mxGetID(mxID(_return));
1562
2
    if (mxIsUndefined(the->stack)) {
1563
1
      mxPop();
1564
1
      the->stack->kind = XS_UNDEFINED_KIND;
1565
1
    }
1566
1
    else {
1567
1
      mxCall();
1568
1
      mxRunCount(0);    
1569
1
    }
1570
2
    fx_Promise_resolveAux(the);
1571
2
    mxPop();
1572
2
    mxPop();
1573
2
    mxPullSlot(mxResult);
1574
2
  }
1575
2
  mxCatch(the) {
1576
0
    txSlot* resolveFunction;
1577
0
    txSlot* rejectFunction;
1578
0
    mxTemporary(resolveFunction);
1579
0
    mxTemporary(rejectFunction);
1580
0
    mxPush(mxPromiseConstructor);
1581
0
    fxNewPromiseCapability(the, resolveFunction, rejectFunction);
1582
0
    mxPullSlot(mxResult);
1583
0
    fxRejectException(the, rejectFunction);
1584
0
  }
1585
2
}
1586
1587
void fx_AsyncIterator_prototype_asyncIterator(txMachine* the)
1588
13
{
1589
13
  *mxResult = *mxThis;
1590
13
}
1591
1592
void fxAsyncGeneratorRejectAwait(txMachine* the)
1593
1
{
1594
1
  txSlot* slot = mxFunctionInstanceHome(mxFunction->value.reference);
1595
1
  txSlot* generator = slot->value.home.object;
1596
1
  the->scratch.kind = mxArgv(0)->kind;
1597
1
  the->scratch.value = mxArgv(0)->value;
1598
1
  fxAsyncGeneratorStep(the, generator, XS_THROW_STATUS);
1599
1
}
1600
1601
void fxAsyncGeneratorRejectYield(txMachine* the)
1602
60
{
1603
60
  txSlot* home = mxFunctionInstanceHome(mxFunction->value.reference);
1604
60
  txSlot* generator = home->value.home.object;
1605
60
  txSlot* stack = generator->next;
1606
60
  txSlot* state = stack->next;
1607
60
  if (state->value.integer == XS_CODE_END) {
1608
59
    txSlot* queue = state->next;
1609
59
    txSlot* current = queue->value.list.first;
1610
59
    txSlot* resolveFunction = current->value.reference->next;
1611
59
    txSlot* rejectFunction = resolveFunction->next;
1612
1613
59
    mxPushUndefined();
1614
59
    mxPushSlot(rejectFunction);
1615
59
    mxCall();
1616
59
    mxPushSlot(mxArgv(0));
1617
  
1618
59
    queue->value.list.first = current = current->next;
1619
59
    if (current == C_NULL)
1620
28
      queue->value.list.last = C_NULL;
1621
  
1622
59
    mxRunCount(1);
1623
59
    mxPop();
1624
  
1625
59
    if (current) {
1626
31
      txSlot* resolveFunction = current->value.reference->next;
1627
31
      txSlot* rejectFunction = resolveFunction->next;
1628
31
      txSlot* status = rejectFunction->next;
1629
31
      txSlot* value = status->next;
1630
31
      the->scratch.kind = value->kind;
1631
31
      the->scratch.value = value->value;
1632
31
      fxAsyncGeneratorStep(the, generator, status->value.integer);
1633
31
    }
1634
59
  }
1635
1
  else {
1636
1
    mxPushSlot(mxArgv(0));
1637
1
    mxPull(the->scratch);
1638
1
    fxAsyncGeneratorStep(the, generator, XS_THROW_STATUS);
1639
1
  }
1640
60
}
1641
1642
void fxAsyncGeneratorResolveAwait(txMachine* the)
1643
5
{
1644
5
  txSlot* slot = mxFunctionInstanceHome(mxFunction->value.reference);
1645
5
  txSlot* generator = slot->value.home.object;
1646
5
  the->scratch.kind = mxArgv(0)->kind;
1647
5
  the->scratch.value = mxArgv(0)->value;
1648
5
  fxAsyncGeneratorStep(the, generator, XS_NO_STATUS);
1649
5
}
1650
1651
void fxAsyncGeneratorResolveYield(txMachine* the)
1652
105
{
1653
105
  txSlot* home = mxFunctionInstanceHome(mxFunction->value.reference);
1654
105
  txSlot* generator = home->value.home.object;
1655
105
  txSlot* stack = generator->next;
1656
105
  txSlot* state = stack->next;
1657
105
  txSlot* queue = state->next;
1658
105
  txSlot* current = queue->value.list.first;
1659
105
  if (current) {
1660
105
    txSlot* resolveFunction = current->value.reference->next;
1661
  
1662
105
    mxPushUndefined();
1663
105
    mxPushSlot(resolveFunction);
1664
105
    mxCall();
1665
105
    mxPushSlot(mxArgv(0));
1666
105
    fxNewGeneratorResult(the, (state->value.integer == XS_CODE_END) ? 1 : 0);
1667
  
1668
105
    queue->value.list.first = current = current->next;
1669
105
    if (current == C_NULL)
1670
51
      queue->value.list.last = C_NULL;
1671
  
1672
105
    mxRunCount(1);
1673
105
    mxPop();
1674
105
  }
1675
  
1676
105
  if (current) {
1677
54
    txSlot* resolveFunction = current->value.reference->next;
1678
54
    txSlot* rejectFunction = resolveFunction->next;
1679
54
    txSlot* status = rejectFunction->next;
1680
54
    txSlot* value = status->next;
1681
54
    the->scratch.kind = value->kind;
1682
54
    the->scratch.value = value->value;
1683
54
    fxAsyncGeneratorStep(the, generator, status->value.integer);
1684
54
  }
1685
105
}
1686
1687
void fxAsyncGeneratorStep(txMachine* the, txSlot* generator, txFlag status)
1688
3.06k
{
1689
3.06k
  txSlot* stack = generator->next;
1690
3.06k
  txSlot* state = stack->next;
1691
3.06k
  txSlot* queue = state->next;
1692
3.06k
  txSlot* resolveAwaitFunction = queue->next;
1693
3.06k
  txSlot* rejectAwaitFunction = resolveAwaitFunction->next;
1694
3.06k
  txSlot* resolveYieldFunction = rejectAwaitFunction->next;
1695
3.06k
  txSlot* rejectYieldFunction = resolveYieldFunction->next;
1696
3.06k
  txSlot* resolveFunction;
1697
3.06k
  txSlot* rejectFunction;
1698
3.06k
  txSlot* value;
1699
  
1700
3.06k
  mxTry(the) {
1701
3.06k
    if (state->value.integer == XS_CODE_END) {
1702
93
      mxPush(the->scratch);
1703
93
      value = the->stack;
1704
93
      mxTemporary(resolveFunction);
1705
93
      mxTemporary(rejectFunction);
1706
93
      mxPush(mxPromiseConstructor);
1707
93
      fxNewPromiseCapability(the, resolveFunction, rejectFunction);
1708
93
            fxPromiseThen(the, the->stack->value.reference, resolveYieldFunction, rejectYieldFunction, C_NULL, C_NULL);
1709
      /* THIS */
1710
93
      mxPushUndefined();
1711
      /* FUNCTION */
1712
93
      if (status == XS_THROW_STATUS)
1713
1
        mxPushSlot(rejectFunction);
1714
92
      else
1715
92
        mxPushSlot(resolveFunction);
1716
93
      mxCall();
1717
      /* ARGUMENTS */
1718
93
      mxPushSlot(value);
1719
93
      mxRunCount(1);
1720
93
      mxPop();
1721
93
    }
1722
2.97k
    else {
1723
2.97k
      the->status = status;
1724
2.97k
      status = XS_NO_STATUS;
1725
2.97k
      state->value.integer = XS_NO_CODE;
1726
2.97k
      fxRunID(the, generator, XS_NO_ID);
1727
2.97k
      if (state->value.integer == XS_NO_CODE)
1728
6
        state->value.integer = XS_CODE_END;
1729
2.97k
      value = the->stack;
1730
2.97k
      if (state->value.integer == XS_CODE_END) {
1731
6
        txSlot* current = queue->value.list.first;
1732
6
        if (current) {
1733
6
          if (value->kind == XS_UNINITIALIZED_KIND)
1734
5
            value->kind = XS_UNDEFINED_KIND;
1735
6
          mxPushUndefined();
1736
6
          if (status == XS_THROW_STATUS)
1737
0
            mxPushSlot(rejectYieldFunction);
1738
6
          else
1739
6
            mxPushSlot(resolveYieldFunction);
1740
6
          mxCall();
1741
6
          mxPushSlot(value);
1742
6
          mxRunCount(1);
1743
6
          mxPop();
1744
6
        }
1745
6
      }
1746
2.96k
      else if (state->value.integer == XS_CODE_AWAIT) {
1747
8
        mxPushUndefined();
1748
8
        mxPush(mxPromiseConstructor);
1749
8
        mxPushSlot(value);
1750
8
        fx_Promise_resolveAux(the);
1751
8
        mxPop();
1752
8
        mxPop();
1753
8
        fxPromiseThen(the, the->stack->value.reference, resolveAwaitFunction, rejectAwaitFunction, C_NULL, C_NULL);
1754
8
      }
1755
2.96k
      else if (state->value.integer == XS_CODE_YIELD) {
1756
10
        mxPushUndefined();
1757
10
        mxPush(mxPromiseConstructor);
1758
10
        mxPushSlot(value);
1759
10
        fx_Promise_resolveAux(the);
1760
10
        mxPop();
1761
10
        mxPop();
1762
10
        fxPromiseThen(the, the->stack->value.reference, resolveYieldFunction, rejectYieldFunction, C_NULL, C_NULL);
1763
10
      }
1764
2.95k
      else if (state->value.integer == XS_CODE_YIELD_STAR) {
1765
1
        txSlot* current = queue->value.list.first;
1766
1
        if (current) {
1767
1
          mxPushUndefined();
1768
1
          mxPushSlot(resolveYieldFunction);
1769
1
          mxCall();
1770
1
          mxPushSlot(value);
1771
1
          mxRunCount(1);
1772
1
          mxPop();
1773
1
        }
1774
1
      }
1775
2.97k
    }
1776
3.06k
    mxPop();
1777
3.06k
  }
1778
3.06k
  mxCatch(the) {
1779
66
    mxTemporary(resolveFunction);
1780
66
    mxTemporary(rejectFunction);
1781
66
    mxPush(mxPromiseConstructor);
1782
66
    fxNewPromiseCapability(the, resolveFunction, rejectFunction);
1783
66
        if (state->value.integer == XS_CODE_AWAIT) {
1784
0
            fxPromiseThen(the, the->stack->value.reference, resolveAwaitFunction, rejectAwaitFunction, C_NULL, C_NULL);
1785
0
        }
1786
66
        else {
1787
66
      state->value.integer = XS_CODE_END;
1788
66
            fxPromiseThen(the, the->stack->value.reference, resolveYieldFunction, rejectYieldFunction, C_NULL, C_NULL);
1789
66
        }
1790
66
        fxRejectException(the, rejectFunction);
1791
66
  }
1792
3.06k
}
1793
1794
txSlot* fxCheckAsyncGeneratorInstance(txMachine* the, txSlot* slot)
1795
3.12k
{
1796
3.12k
  if (slot->kind == XS_REFERENCE_KIND) {
1797
3.10k
    txSlot* instance = slot->value.reference;
1798
3.10k
    slot = instance->next;
1799
3.10k
    if (slot && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_STACK_KIND)) {
1800
3.07k
      slot = slot->next;
1801
3.07k
      if (slot && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_INTEGER_KIND)) {
1802
3.07k
        slot = slot->next;
1803
3.07k
        if (slot && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_LIST_KIND)) {
1804
3.07k
          return instance;
1805
3.07k
        }
1806
3.07k
      }
1807
3.07k
    }
1808
3.10k
  }
1809
3.12k
  mxTypeError("this: not an AsyncGenerator instance");
1810
0
  return C_NULL;
1811
3.12k
}
1812
1813
txSlot* fxNewAsyncGeneratorInstance(txMachine* the)
1814
64.0k
{
1815
64.0k
  txSlot* prototype;
1816
64.0k
  txSlot* instance;
1817
64.0k
  txSlot* property;
1818
64.0k
  txSlot* function;
1819
64.0k
  txSlot* home;
1820
1821
64.0k
  prototype = (the->stack->kind == XS_REFERENCE_KIND) ? the->stack->value.reference : mxAsyncGeneratorPrototype.value.reference;
1822
1823
64.0k
  instance = fxNewSlot(the);
1824
64.0k
  instance->kind = XS_INSTANCE_KIND;
1825
64.0k
  instance->value.instance.garbage = C_NULL;
1826
64.0k
  instance->value.instance.prototype = prototype;
1827
64.0k
  the->stack->value.reference = instance;
1828
64.0k
  the->stack->kind = XS_REFERENCE_KIND;
1829
1830
64.0k
  property = instance->next = fxNewSlot(the);
1831
64.0k
  property->flag = XS_INTERNAL_FLAG;
1832
64.0k
  property->kind = XS_STACK_KIND;
1833
64.0k
  property->ID = XS_NO_ID;
1834
64.0k
    property->value.stack.length = 0;
1835
64.0k
    property->value.stack.address = C_NULL;
1836
  
1837
64.0k
    property = property->next = fxNewSlot(the);
1838
64.0k
  property->flag = XS_INTERNAL_FLAG;
1839
64.0k
  property->kind = XS_INTEGER_KIND;
1840
64.0k
  property->value.integer = XS_CODE_START_ASYNC_GENERATOR;
1841
  
1842
64.0k
    property = property->next = fxNewSlot(the);
1843
64.0k
  property->flag = XS_INTERNAL_FLAG;
1844
64.0k
  property->kind = XS_LIST_KIND;
1845
64.0k
  property->value.list.first = C_NULL;
1846
64.0k
  property->value.list.last = C_NULL;
1847
  
1848
64.0k
  function = fxNewHostFunction(the, fxAsyncGeneratorResolveAwait, 1, XS_NO_ID, mxAsyncGeneratorResolveAwaitProfileID);
1849
64.0k
  home = mxFunctionInstanceHome(function);
1850
64.0k
  home->value.home.object = instance;
1851
64.0k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
1852
64.0k
  mxPop();
1853
  
1854
64.0k
  function = fxNewHostFunction(the, fxAsyncGeneratorRejectAwait, 1, XS_NO_ID, mxAsyncGeneratorRejectAwaitProfileID);
1855
64.0k
  home = mxFunctionInstanceHome(function);
1856
64.0k
  home->value.home.object = instance;
1857
64.0k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
1858
64.0k
  mxPop();
1859
  
1860
64.0k
  function = fxNewHostFunction(the, fxAsyncGeneratorResolveYield, 1, XS_NO_ID, mxAsyncGeneratorResolveYieldProfileID);
1861
64.0k
  home = mxFunctionInstanceHome(function);
1862
64.0k
  home->value.home.object = instance;
1863
64.0k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
1864
64.0k
  mxPop();
1865
  
1866
64.0k
  function = fxNewHostFunction(the, fxAsyncGeneratorRejectYield, 1, XS_NO_ID, mxAsyncGeneratorRejectYieldProfileID);
1867
64.0k
  home = mxFunctionInstanceHome(function);
1868
64.0k
  home->value.home.object = instance;
1869
64.0k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
1870
64.0k
  mxPop();
1871
  
1872
64.0k
  return instance;
1873
64.0k
}
1874
1875
1876
void fx_AsyncGenerator(txMachine* the)
1877
0
{
1878
0
  if (mxHasTarget)
1879
0
    mxTypeError("new: AsyncGenerator");
1880
0
}
1881
1882
void fx_AsyncGenerator_prototype_aux(txMachine* the, txFlag status)
1883
3.12k
{
1884
3.12k
  txSlot* stack = the->stack;
1885
3.12k
  txSlot* resolveFunction;
1886
3.12k
  txSlot* rejectFunction;
1887
3.12k
  txSlot* slot;
1888
3.12k
  txSlot* generator;
1889
3.12k
  txSlot* state;
1890
3.12k
  txSlot* queue;
1891
3.12k
  txSlot* instance;
1892
3.12k
  txSlot* property;
1893
  
1894
3.12k
  mxTemporary(resolveFunction);
1895
3.12k
  mxTemporary(rejectFunction);
1896
3.12k
  mxPush(mxPromiseConstructor);
1897
3.12k
  fxNewPromiseCapability(the, resolveFunction, rejectFunction);
1898
3.12k
  mxPullSlot(mxResult);
1899
#ifdef mxPromisePrint
1900
  fprintf(stderr, "fx_AsyncGenerator_prototype_aux %d\n", mxResult->value.reference->next->ID);
1901
#endif
1902
3.12k
  {
1903
3.12k
    mxTry(the) {
1904
3.12k
      generator = fxCheckAsyncGeneratorInstance(the, mxThis);
1905
3.12k
      state = generator->next->next;
1906
3.12k
      if (((status == XS_RETURN_STATUS) || (status == XS_THROW_STATUS)) && (state->value.integer == XS_CODE_START_ASYNC_GENERATOR))
1907
8
        state->value.integer = XS_CODE_END;
1908
3.12k
      instance = property = fxNewInstance(the);
1909
3.12k
      property = fxNextSlotProperty(the, property, resolveFunction, XS_NO_ID, XS_INTERNAL_FLAG);
1910
3.12k
      property = fxNextSlotProperty(the, property, rejectFunction, XS_NO_ID, XS_INTERNAL_FLAG);
1911
3.12k
      property = fxNextIntegerProperty(the, property, status, XS_NO_ID, XS_INTERNAL_FLAG);
1912
3.12k
      if (mxArgc > 0)
1913
7
        property = fxNextSlotProperty(the, property, mxArgv(0), XS_NO_ID, XS_INTERNAL_FLAG);
1914
3.11k
      else
1915
3.11k
        property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
1916
3.12k
      slot = fxNewSlot(the);
1917
3.12k
      slot->kind = XS_REFERENCE_KIND;
1918
3.12k
      slot->value.reference = instance;
1919
3.12k
      queue = state->next;
1920
3.12k
      if (queue->value.list.first) {
1921
95
        queue->value.list.last->next = slot;
1922
95
        queue->value.list.last = slot;
1923
95
      }
1924
3.02k
      else {
1925
3.02k
        queue->value.list.first = slot;
1926
3.02k
        queue->value.list.last = slot;
1927
3.02k
        if (state->value.integer != XS_CODE_AWAIT) {
1928
2.97k
          the->scratch.kind = property->kind;
1929
2.97k
          the->scratch.value = property->value;
1930
2.97k
          fxAsyncGeneratorStep(the, generator, status);
1931
2.97k
        }
1932
3.02k
      }
1933
3.12k
    }
1934
3.12k
    mxCatch(the) {
1935
50
      fxRejectException(the, rejectFunction);
1936
50
    }
1937
3.12k
  }
1938
3.12k
  the->stack = stack;
1939
3.12k
}
1940
1941
void fx_AsyncGenerator_prototype_next(txMachine* the)
1942
3.09k
{
1943
3.09k
  fx_AsyncGenerator_prototype_aux(the, XS_NO_STATUS);
1944
3.09k
}
1945
1946
void fx_AsyncGenerator_prototype_return(txMachine* the)
1947
19
{
1948
19
  fx_AsyncGenerator_prototype_aux(the, XS_RETURN_STATUS);
1949
19
}
1950
1951
void fx_AsyncGenerator_prototype_throw(txMachine* the)
1952
12
{
1953
12
  fx_AsyncGenerator_prototype_aux(the, XS_THROW_STATUS);
1954
12
}
1955
1956
txSlot* fxNewAsyncGeneratorFunctionInstance(txMachine* the, txID name)
1957
46.5k
{
1958
46.5k
  txSlot* instance;
1959
46.5k
  txSlot* property;
1960
1961
46.5k
  instance = fxNewFunctionInstance(the, name);
1962
46.5k
  property = fxLastProperty(the, instance);
1963
46.5k
  mxPush(mxAsyncGeneratorPrototype);
1964
46.5k
  fxNewObjectInstance(the);
1965
46.5k
  fxNextSlotProperty(the, property, the->stack, mxID(_prototype), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG);
1966
46.5k
  mxPop();
1967
  
1968
46.5k
  return instance;
1969
46.5k
}
1970
1971
void fx_AsyncGeneratorFunction(txMachine* the)
1972
19
{ 
1973
19
  txInteger c, i;
1974
19
  txStringStream stream;
1975
19
  txSlot* module = mxFunctionInstanceHome(mxFunction->value.reference)->value.home.module;
1976
19
  if (!module) module = mxProgram.value.reference;
1977
  
1978
19
  c = mxArgc;
1979
19
  i = 0;
1980
19
  mxPushStringX("(async function* anonymous(");
1981
41
  while (c > 1) {
1982
22
    fxToString(the, mxArgv(i));
1983
22
    fxConcatString(the, the->stack, mxArgv(i));
1984
22
    if (c > 2)
1985
11
      fxConcatStringC(the, the->stack, ", ");
1986
22
    c--;
1987
22
    i++;
1988
22
  }
1989
19
  fxConcatStringC(the, the->stack, "\n){");
1990
19
  if (c > 0) {
1991
16
    fxToString(the, mxArgv(i));
1992
16
    fxConcatString(the, the->stack, mxArgv(i));
1993
16
  }
1994
19
  fxConcatStringC(the, the->stack, "\n})");
1995
19
  stream.slot = the->stack;
1996
19
  stream.offset = 0;
1997
19
  stream.size = mxStringLength(the->stack->value.string);
1998
19
  fxRunScript(the, fxParseScript(the, &stream, fxStringGetter, mxProgramFlag | mxGeneratorFlag), C_NULL, C_NULL, C_NULL, C_NULL, module);
1999
19
  mxPullSlot(mxResult);
2000
19
  if (mxHasTarget && !fxIsSameSlot(the, mxTarget, mxFunction)) {
2001
0
    mxPushSlot(mxTarget);
2002
0
    fxGetPrototypeFromConstructor(the, &mxAsyncGeneratorFunctionPrototype);
2003
0
    mxResult->value.reference->value.instance.prototype = the->stack->value.reference;
2004
0
    mxPop();
2005
0
  }
2006
19
}
2007
2008
void fxAsyncFromSyncIteratorDone(txMachine* the)
2009
5
{
2010
5
  txSlot* slot = mxFunctionInstanceHome(mxFunction->value.reference);
2011
5
  txSlot* instance = slot->value.home.object;
2012
5
  txSlot* iterator = instance->next;
2013
5
  txSlot* nextFunction = iterator->next;
2014
5
  txSlot* doneFunction = nextFunction->next;
2015
5
  txSlot* doneFlag = doneFunction->next;
2016
5
  mxPushSlot(mxArgv(0));
2017
5
  fxNewGeneratorResult(the, doneFlag->value.boolean);
2018
5
  mxPullSlot(mxResult);
2019
5
}
2020
2021
void fxAsyncFromSyncIteratorFailed(txMachine* the)
2022
0
{
2023
0
  txSlot* slot = mxFunctionInstanceHome(mxFunction->value.reference);
2024
0
  txSlot* instance = slot->value.home.object;
2025
0
  txSlot* iterator = instance->next;
2026
0
  mxTry(the) {
2027
0
    mxPushSlot(iterator);
2028
0
    mxPushSlot(iterator);
2029
0
    mxGetID(mxID(_return));
2030
0
    if (!mxIsUndefined(the->stack) && !mxIsNull(the->stack)) {
2031
0
      mxCall();
2032
0
      mxRunCount(0);
2033
0
    }
2034
0
    mxPop();
2035
0
  }
2036
0
  mxCatch(the) {
2037
0
  }
2038
0
  mxException.kind = mxArgv(0)->kind;
2039
0
  mxException.value = mxArgv(0)->value;
2040
0
  fxThrow(the, NULL, 0);
2041
0
}
2042
2043
txSlot* fxCheckAsyncFromSyncIteratorInstance(txMachine* the, txSlot* slot)
2044
11
{
2045
11
  if (slot->kind == XS_REFERENCE_KIND) {
2046
11
    txSlot* instance = slot->value.reference;
2047
11
    slot = instance->next;
2048
11
    if (slot && (slot->flag & XS_INTERNAL_FLAG) && (slot->ID == mxID(_iterator)))
2049
11
      return instance;
2050
11
  }
2051
11
  mxTypeError("this: not an AsyncFromSyncIterator instance");
2052
0
  return C_NULL;
2053
11
}
2054
2055
txSlot* fxNewAsyncFromSyncIteratorInstance(txMachine* the)
2056
9
{
2057
9
  txSlot* iterator = the->stack;
2058
9
  txSlot* instance;
2059
9
  txSlot* slot;
2060
9
  txSlot* function;
2061
9
  txSlot* home;
2062
9
  mxPush(mxAsyncFromSyncIteratorPrototype);
2063
9
  instance = fxNewObjectInstance(the);
2064
9
  slot = fxLastProperty(the, instance);
2065
  
2066
9
  slot = fxNextSlotProperty(the, slot, iterator, mxID(_iterator), XS_INTERNAL_FLAG);
2067
2068
9
  mxPushSlot(iterator);
2069
9
  mxGetID(mxID(_next));
2070
9
  slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
2071
9
  mxPop();
2072
  
2073
9
  function = fxNewHostFunction(the, fxAsyncFromSyncIteratorDone, 1, XS_NO_ID, mxAsyncFromSyncIteratorDoneProfileID);
2074
9
  home = mxFunctionInstanceHome(function);
2075
9
  home->value.home.object = instance;
2076
9
    slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
2077
9
  mxPop();
2078
  
2079
9
    slot = fxNextBooleanProperty(the, slot, 0, XS_NO_ID, XS_INTERNAL_FLAG);
2080
    
2081
9
  function = fxNewHostFunction(the, fxAsyncFromSyncIteratorFailed, 1, XS_NO_ID, mxAsyncFromSyncIteratorDoneProfileID);
2082
9
  home = mxFunctionInstanceHome(function);
2083
9
  home->value.home.object = instance;
2084
9
    slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
2085
9
  mxPop();
2086
2087
9
  mxPullSlot(iterator);
2088
9
  return instance;
2089
9
}
2090
2091
void fx_AsyncFromSyncIterator_prototype_aux(txMachine* the, txFlag status, txSlot* iterator, txBoolean* flag)
2092
11
{
2093
11
  txSlot* stack = the->stack;
2094
11
  txSlot* resolveFunction;
2095
11
    txSlot* rejectFunction;
2096
11
  txSlot* slot;
2097
11
  txSlot* stepFunction = C_NULL;
2098
  
2099
11
  mxTemporary(resolveFunction);
2100
11
  mxTemporary(rejectFunction);
2101
11
  mxPush(mxPromiseConstructor);
2102
11
  fxNewPromiseCapability(the, resolveFunction, rejectFunction);
2103
11
  mxPullSlot(mxResult);
2104
#ifdef mxPromisePrint
2105
  fprintf(stderr, "fx_AsyncFromSyncIterator_prototype_aux %d %d\n", mxResult->value.reference->next->ID, status);
2106
#endif
2107
11
    {
2108
11
    mxTry(the) {
2109
11
      if (status == XS_NO_STATUS) {
2110
10
        stepFunction = iterator->next;
2111
10
      }
2112
1
      else if (status == XS_RETURN_STATUS) {
2113
1
        mxPushSlot(iterator);
2114
1
        mxGetID(mxID(_return));
2115
1
        if (mxIsUndefined(the->stack) || mxIsNull(the->stack)) {
2116
0
          mxPushUndefined();
2117
0
          mxPushSlot(resolveFunction);
2118
0
          mxCall();
2119
0
          mxPushUndefined();
2120
0
          fxNewGeneratorResult(the, 1);
2121
0
          mxRunCount(1);
2122
0
        }
2123
1
        else
2124
1
          stepFunction = the->stack;
2125
1
      }
2126
0
      else {
2127
0
        mxPushSlot(iterator);
2128
0
        mxGetID(mxID(_throw));
2129
0
        if (mxIsUndefined(the->stack) || mxIsNull(the->stack)) {
2130
0
          *flag = 0;
2131
0
          fxIteratorReturn(the, iterator, 0);
2132
0
          mxTypeError("no throw");
2133
0
        }
2134
0
        else
2135
0
          stepFunction = the->stack;
2136
0
      }
2137
11
      if (stepFunction) {
2138
11
        txSlot* doneFunction = iterator->next->next;
2139
11
        txSlot* doneFlag = doneFunction->next;
2140
11
        txSlot* failedFunction = doneFlag->next;
2141
11
        mxPushSlot(iterator);
2142
11
        mxPushSlot(stepFunction);
2143
11
        mxCall();
2144
11
        if (mxArgc == 0)
2145
5
          mxRunCount(0);
2146
6
        else {
2147
6
          mxPushSlot(mxArgv(0));
2148
6
          mxRunCount(1);
2149
6
        }
2150
11
        slot = the->stack;
2151
11
                if (!mxIsReference(slot)) {
2152
0
                    mxTypeError("iterator result: not an object");
2153
0
                }
2154
2155
11
        mxPushSlot(slot);
2156
11
        mxGetID(mxID(_done));
2157
11
        doneFlag->value.boolean = fxToBoolean(the, the->stack);
2158
2159
11
        mxPushUndefined();
2160
11
        mxPush(mxPromiseConstructor);
2161
11
        mxPushSlot(slot);
2162
11
        mxGetID(mxID(_value));
2163
11
        fx_Promise_resolveAux(the);
2164
11
        mxPop();
2165
11
        mxPop();
2166
11
        fxPromiseThen(the, the->stack->value.reference, doneFunction, failedFunction, resolveFunction, rejectFunction);
2167
11
      }
2168
11
    }
2169
11
    mxCatch(the) {
2170
2
      if (*flag)
2171
2
        fxIteratorReturn(the, iterator, 1);
2172
2
      fxRejectException(the, rejectFunction);
2173
2
    }
2174
11
    }
2175
11
  the->stack = stack;
2176
11
}
2177
2178
void fx_AsyncFromSyncIterator_prototype_next(txMachine* the)
2179
10
{
2180
10
  txBoolean flag = 1;
2181
10
  txSlot* instance = fxCheckAsyncFromSyncIteratorInstance(the, mxThis);
2182
10
  fx_AsyncFromSyncIterator_prototype_aux(the, XS_NO_STATUS, instance->next, &flag);
2183
10
}
2184
2185
void fx_AsyncFromSyncIterator_prototype_return(txMachine* the)
2186
1
{
2187
1
  txBoolean flag = 1;
2188
1
  txSlot* instance = fxCheckAsyncFromSyncIteratorInstance(the, mxThis);
2189
1
  fx_AsyncFromSyncIterator_prototype_aux(the, XS_RETURN_STATUS, instance->next, &flag);
2190
1
}
2191
2192
void fx_AsyncFromSyncIterator_prototype_throw(txMachine* the)
2193
0
{
2194
0
  txBoolean flag = 1;
2195
0
  txSlot* instance = fxCheckAsyncFromSyncIteratorInstance(the, mxThis);
2196
0
  fx_AsyncFromSyncIterator_prototype_aux(the, XS_THROW_STATUS, instance->next, &flag);
2197
0
}
2198
2199