Coverage Report

Created: 2025-12-30 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsError.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2016-2025  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
static txSlot* fx_Error_aux(txMachine* the, txError error, txInteger i);
41
42
const int gxErrorWhichPrototypeStackIndex[XS_ERROR_COUNT] ICACHE_FLASH_ATTR = {
43
  mxErrorPrototypeStackIndex,
44
  mxErrorPrototypeStackIndex,
45
  mxEvalErrorPrototypeStackIndex,
46
  mxRangeErrorPrototypeStackIndex,
47
  mxReferenceErrorPrototypeStackIndex,
48
  mxSyntaxErrorPrototypeStackIndex,
49
  mxTypeErrorPrototypeStackIndex,
50
  mxURIErrorPrototypeStackIndex,
51
  mxAggregateErrorPrototypeStackIndex,
52
#if mxExplicitResourceManagement
53
  mxSuppressedErrorPrototypeStackIndex,
54
#else
55
  mxErrorPrototypeStackIndex,
56
#endif
57
};
58
59
const char *const gxErrorNames[XS_ERROR_COUNT] ICACHE_FLASH_ATTR = {
60
  "no error",
61
  "Error",
62
  "EvalError",
63
  "RangeError",
64
  "ReferenceError",
65
  "SyntaxError",
66
  "TypeError",
67
  "URIError",
68
  "AggregateError",
69
  "SuppressedError"
70
};
71
72
void fxBuildError(txMachine* the)
73
31.3k
{
74
31.3k
  txSlot* slot;
75
31.3k
  txSlot* prototype;
76
31.3k
  txSlot* instance;
77
31.3k
#if mxExplicitResourceManagement
78
31.3k
  txSlot* property;
79
31.3k
#endif
80
  
81
31.3k
  mxPush(mxObjectPrototype);
82
31.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
83
31.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
84
31.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_UNKNOWN_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
85
31.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
86
31.3k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_Error_prototype_get_stack), mxCallback(fx_Error_prototype_set_stack), mxID(_stack), XS_DONT_ENUM_FLAG);
87
31.3k
  mxErrorPrototype = *the->stack;
88
31.3k
  prototype = fxBuildHostConstructor(the, mxCallback(fx_Error), 1, mxID(_Error));
89
31.3k
  mxErrorConstructor = *the->stack;
90
31.3k
#if mxErrorIsError
91
31.3k
  slot = fxLastProperty(the, prototype);
92
31.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_isError), 1, mxID(_isError), XS_DONT_ENUM_FLAG);
93
31.3k
#endif
94
31.3k
  mxPop();
95
31.3k
  mxPush(mxErrorPrototype);
96
31.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
97
31.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_AGGREGATE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
98
31.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
99
31.3k
  mxAggregateErrorPrototype = *the->stack;
100
31.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_AggregateError), 2, mxID(_AggregateError));
101
31.3k
  instance->value.instance.prototype = prototype;
102
31.3k
  mxAggregateErrorConstructor = *the->stack;
103
31.3k
  mxPop();
104
31.3k
  mxPush(mxErrorPrototype);
105
31.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
106
31.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_EVAL_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
107
31.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
108
31.3k
  mxEvalErrorPrototype = *the->stack;
109
31.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_EvalError), 1, mxID(_EvalError));
110
31.3k
  instance->value.instance.prototype = prototype;
111
31.3k
  mxEvalErrorConstructor = *the->stack;
112
31.3k
  mxPop();
113
31.3k
  mxPush(mxErrorPrototype);
114
31.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
115
31.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_RANGE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
116
31.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
117
31.3k
  mxRangeErrorPrototype = *the->stack;
118
31.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_RangeError), 1, mxID(_RangeError));
119
31.3k
  instance->value.instance.prototype = prototype;
120
31.3k
  mxRangeErrorConstructor = *the->stack;
121
31.3k
  mxPop();
122
31.3k
  mxPush(mxErrorPrototype);
123
31.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
124
31.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_REFERENCE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
125
31.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
126
31.3k
  mxReferenceErrorPrototype = *the->stack;
127
31.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_ReferenceError), 1, mxID(_ReferenceError));
128
31.3k
  instance->value.instance.prototype = prototype;
129
31.3k
  mxReferenceErrorConstructor = *the->stack;
130
31.3k
  mxPop();
131
31.3k
  mxPush(mxErrorPrototype);
132
31.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
133
31.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_SYNTAX_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
134
31.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
135
31.3k
  mxSyntaxErrorPrototype = *the->stack;
136
31.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_SyntaxError), 1, mxID(_SyntaxError));
137
31.3k
  instance->value.instance.prototype = prototype;
138
31.3k
  mxSyntaxErrorConstructor = *the->stack;
139
31.3k
  mxPop();
140
31.3k
  mxPush(mxErrorPrototype);
141
31.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
142
31.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_TYPE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
143
31.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
144
31.3k
  mxTypeErrorPrototype = *the->stack;
145
31.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_TypeError), 1, mxID(_TypeError));
146
31.3k
  instance->value.instance.prototype = prototype;
147
31.3k
  mxTypeErrorConstructor = *the->stack;
148
31.3k
  mxPop();
149
31.3k
  mxPush(mxErrorPrototype);
150
31.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
151
31.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_URI_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
152
31.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
153
31.3k
  mxURIErrorPrototype = *the->stack;
154
31.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_URIError), 1, mxID(_URIError));
155
31.3k
  instance->value.instance.prototype = prototype;
156
31.3k
  mxURIErrorConstructor = *the->stack;
157
31.3k
  mxPop();
158
159
31.3k
#if mxExplicitResourceManagement
160
31.3k
  mxPush(mxErrorPrototype);
161
31.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
162
31.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_SUPPRESSED_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
163
31.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
164
31.3k
  mxSuppressedErrorPrototype = *the->stack;
165
31.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_SuppressedError), 3, mxID(_SuppressedError));
166
31.3k
  instance->value.instance.prototype = prototype;
167
31.3k
  mxSuppressedErrorConstructor = *the->stack;
168
31.3k
  mxPop();
169
170
31.3k
  mxPush(mxObjectPrototype);
171
31.3k
    slot = fxLastProperty(the, fxNewObjectInstance(the));
172
31.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
173
31.3k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_DisposableStack_prototype_get_disposed), C_NULL, mxID(_disposed), XS_DONT_ENUM_FLAG);
174
31.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_adopt), 2, mxID(_adopt), XS_DONT_ENUM_FLAG);
175
31.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_defer), 1, mxID(_defer), XS_DONT_ENUM_FLAG);
176
31.3k
  property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_dispose), 0, mxID(_dispose), XS_DONT_ENUM_FLAG);
177
31.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_move), 0, mxID(_move), XS_DONT_ENUM_FLAG);
178
31.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_use), 1, mxID(_use), XS_DONT_ENUM_FLAG);
179
31.3k
  slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_dispose), XS_DONT_ENUM_FLAG);
180
31.3k
  slot = fxNextStringXProperty(the, slot, "DisposableStack", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
181
31.3k
  mxDisposableStackPrototype = *the->stack;
182
31.3k
  slot = fxBuildHostConstructor(the, mxCallback(fx_DisposableStack), 0, mxID(_DisposableStack));
183
31.3k
  mxDisposableStackConstructor = *the->stack;
184
31.3k
  mxPop();
185
  
186
31.3k
  mxPush(mxObjectPrototype);
187
31.3k
    slot = fxLastProperty(the, fxNewObjectInstance(the));
188
31.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
189
31.3k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_get_disposed), C_NULL, mxID(_disposed), XS_DONT_ENUM_FLAG);
190
31.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_adopt), 2, mxID(_adopt), XS_DONT_ENUM_FLAG);
191
31.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_defer), 1, mxID(_defer), XS_DONT_ENUM_FLAG);
192
31.3k
  property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_disposeAsync), 0, mxID(_disposeAsync), XS_DONT_ENUM_FLAG);
193
31.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_move), 0, mxID(_move), XS_DONT_ENUM_FLAG);
194
31.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_use), 1, mxID(_use), XS_DONT_ENUM_FLAG);
195
31.3k
  slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_asyncDispose), XS_DONT_ENUM_FLAG);
196
31.3k
  slot = fxNextStringXProperty(the, slot, "AsyncDisposableStack", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
197
31.3k
  mxAsyncDisposableStackPrototype = *the->stack;
198
31.3k
  slot = fxBuildHostConstructor(the, mxCallback(fx_AsyncDisposableStack), 0, mxID(_AsyncDisposableStack));
199
31.3k
  mxAsyncDisposableStackConstructor = *the->stack;
200
31.3k
  mxPop();
201
31.3k
#endif
202
31.3k
}
203
204
void fxCaptureErrorStack(txMachine* the, txSlot* internal, txSlot* frame)
205
3.58M
{
206
3.58M
  txSlot* slot = internal->value.reference = fxNewSlot(the);
207
3.58M
  slot->kind = XS_INSTANCE_KIND;
208
3.58M
  slot->value.instance.garbage = C_NULL;
209
3.58M
  slot->value.instance.prototype = C_NULL;
210
48.4M
  while (frame->next) {
211
44.8M
    txSlot* environment = mxFrameToEnvironment(frame);
212
44.8M
    txSlot* function = frame + 3; 
213
44.8M
    if (function->kind == XS_REFERENCE_KIND) {
214
44.6M
      function = function->value.reference;
215
44.6M
      if (mxIsFunction(function)) {
216
44.6M
        txSlot* name = mxBehaviorGetProperty(the, function, mxID(_name), 0, XS_OWN);
217
44.6M
        slot = slot->next = fxNewSlot(the);
218
44.6M
        slot->flag = XS_GET_ONLY;
219
44.6M
        slot->kind = XS_KEY_KIND;
220
44.6M
        slot->ID = environment->ID;
221
44.6M
        slot->value.key.string = C_NULL;
222
44.6M
        slot->value.key.sum = environment->value.environment.line;
223
44.6M
        if (name && ((name->kind == XS_STRING_KIND) || (name->kind == XS_STRING_X_KIND))) {
224
44.6M
          if (name->kind == XS_STRING_X_KIND)
225
0
            slot->kind = XS_KEY_X_KIND;
226
44.6M
          slot->value.key.string = name->value.string;
227
44.6M
        }
228
0
        else {
229
0
          txSlot* code = mxFunctionInstanceCode(function);
230
0
          if (code->ID != XS_NO_ID) {
231
0
            txSlot* key = fxGetKey(the, code->ID);
232
0
            if ((key->kind == XS_KEY_KIND) || (key->kind == XS_KEY_X_KIND)) {
233
0
              slot->value.key.string = key->value.key.string;
234
0
              slot->kind = key->kind;
235
0
            }
236
0
            else if (key->kind == XS_REFERENCE_KIND) {
237
0
              name = key->value.reference->next->next;
238
0
              if (name && ((name->kind == XS_STRING_KIND) || (name->kind == XS_STRING_X_KIND))) {
239
0
                if (name->kind == XS_STRING_X_KIND)
240
0
                  slot->kind = XS_KEY_X_KIND;
241
0
                slot->value.key.string = name->value.string;
242
0
              }
243
0
            }
244
0
          }
245
0
        }
246
44.6M
      }
247
44.6M
    }
248
44.8M
    frame = frame->next;
249
44.8M
  }
250
3.58M
}
251
252
void fx_Error(txMachine* the)
253
106k
{
254
106k
  fx_Error_aux(the, XS_UNKNOWN_ERROR, 0);
255
106k
}
256
257
void fx_Error_isError(txMachine* the)
258
1.91k
{
259
1.91k
  mxResult->kind = XS_BOOLEAN_KIND;
260
1.91k
  mxResult->value.boolean = 0;
261
1.91k
  if (mxArgc > 0) {
262
1.62k
    txSlot* instance = fxGetInstance(the, mxArgv(0));
263
1.62k
    if (instance) {
264
1.48k
      txSlot* internal = instance->next;
265
1.48k
      if (internal && (internal->kind == XS_ERROR_KIND)) {
266
1.45k
        mxResult->value.boolean = 1;
267
1.45k
      }
268
1.48k
    }
269
1.62k
  }
270
1.91k
}
271
272
txSlot* fx_Error_aux(txMachine* the, txError error, txInteger i)
273
825k
{
274
825k
  txSlot* instance;
275
825k
  txSlot* slot;
276
825k
  if (mxIsUndefined(mxTarget))
277
625
    mxPushSlot(mxFunction);
278
825k
  else
279
825k
    mxPushSlot(mxTarget);
280
825k
  fxGetPrototypeFromConstructor(the, &mxErrorPrototypes(error));
281
825k
  instance = fxNewObjectInstance(the);
282
825k
  mxPullSlot(mxResult);
283
825k
  slot = instance->next = fxNewSlot(the);
284
825k
  slot->flag = XS_INTERNAL_FLAG;
285
825k
  slot->kind = XS_ERROR_KIND;
286
825k
  slot->value.error.info = C_NULL;
287
825k
  slot->value.error.which = error;
288
825k
  if (gxDefaults.captureErrorStack)
289
825k
    gxDefaults.captureErrorStack(the, slot, the->frame->next);
290
825k
  if ((mxArgc > i) && (mxArgv(i)->kind != XS_UNDEFINED_KIND)) {
291
815k
    fxToString(the, mxArgv(i));
292
815k
    slot = fxNextSlotProperty(the, slot, mxArgv(i), mxID(_message), XS_DONT_ENUM_FLAG);
293
815k
  }
294
825k
  i++;
295
825k
  if ((mxArgc > i) && (mxArgv(i)->kind == XS_REFERENCE_KIND)) {
296
65.3k
    if (mxBehaviorHasProperty(the, mxArgv(i)->value.reference, mxID(_cause), 0)) {
297
1
      mxPushSlot(mxArgv(i));
298
1
      mxGetID(mxID(_cause));
299
1
      slot = fxNextSlotProperty(the, slot, the->stack, mxID(_cause), XS_DONT_ENUM_FLAG);
300
1
      mxPop();
301
1
    }
302
65.3k
  }
303
825k
  return slot;
304
825k
}
305
306
void fx_Error_toString(txMachine* the)
307
267k
{
308
267k
  txSlot* name;
309
267k
  txSlot* message;
310
267k
  if (mxThis->kind != XS_REFERENCE_KIND)
311
12
    mxTypeError("this: not an object");
312
267k
  mxPushSlot(mxThis);
313
267k
  mxGetID(mxID(_name));
314
267k
  if (the->stack->kind == XS_UNDEFINED_KIND) 
315
266k
    fxStringX(the, the->stack, "Error");
316
326
  else  
317
326
    fxToString(the, the->stack);
318
267k
  name = the->stack;
319
267k
  mxPushSlot(mxThis);
320
267k
  mxGetID(mxID(_message));
321
267k
  if (the->stack->kind == XS_UNDEFINED_KIND) 
322
266k
    *the->stack = mxEmptyString;
323
325
  else  
324
325
    fxToString(the, the->stack);
325
267k
  message = the->stack;
326
267k
  if (c_isEmpty(name->value.string))
327
3
    *mxResult = *message;
328
267k
  else if (c_isEmpty(message->value.string))
329
266k
    *mxResult = *name;
330
315
  else {
331
315
    fxStringX(the, mxResult, "");
332
315
    fxConcatString(the, mxResult, name);
333
315
    fxConcatStringC(the, mxResult, ": ");
334
315
    fxConcatString(the, mxResult, message);
335
315
  }
336
267k
  the->stack += 2;
337
267k
}
338
339
void fx_AggregateError(txMachine* the)
340
286
{
341
286
  txSlot* stack = the->stack;
342
286
  txSlot* property = fx_Error_aux(the, XS_AGGREGATE_ERROR, 1);
343
286
  txSlot* array;
344
286
  txSlot** address;
345
286
  txIndex length = 0;
346
286
  txSlot* iterator;
347
286
  txSlot* next;
348
286
  txSlot* value;
349
286
  txSlot* slot;
350
  
351
286
  mxPush(mxArrayPrototype);
352
286
  array = fxNewArrayInstance(the);
353
286
  fxNextSlotProperty(the, property, the->stack, mxID(_errors), XS_DONT_ENUM_FLAG);
354
286
  address = &array->next->next;
355
286
  mxTemporary(iterator);
356
286
  mxTemporary(next);
357
286
  fxGetIterator(the, mxArgv(0), iterator, next, 0);
358
286
  mxTemporary(value);
359
39.8k
  while (fxIteratorNext(the, iterator, next, value)) {
360
39.6k
    mxTry(the) {
361
39.6k
      *address = slot = fxNewSlot(the);
362
39.6k
      slot->kind = value->kind;
363
39.6k
      slot->value = value->value;
364
39.6k
      address = &slot->next;
365
39.6k
      length++;
366
39.6k
    }
367
39.6k
    mxCatch(the) {
368
0
      fxIteratorReturn(the, iterator, 1);
369
0
      fxJump(the);
370
0
    }
371
39.6k
  }
372
286
  array->next->value.array.length = length;
373
286
  fxCacheArray(the, array);
374
  
375
286
  the->stack = stack;
376
286
}
377
378
void fx_EvalError(txMachine* the)
379
878
{
380
878
  fx_Error_aux(the, XS_EVAL_ERROR, 0);
381
878
}
382
383
void fx_RangeError(txMachine* the)
384
680
{
385
680
  fx_Error_aux(the, XS_RANGE_ERROR, 0);
386
680
}
387
388
void fx_ReferenceError(txMachine* the)
389
9
{
390
9
  fx_Error_aux(the, XS_REFERENCE_ERROR, 0);
391
9
}
392
393
void fx_SyntaxError(txMachine* the)
394
717k
{
395
717k
  fx_Error_aux(the, XS_SYNTAX_ERROR, 0);
396
717k
}
397
398
void fx_TypeError(txMachine* the)
399
277
{
400
277
  fx_Error_aux(the, XS_TYPE_ERROR, 0);
401
277
}
402
403
void fx_URIError(txMachine* the)
404
4
{
405
4
  fx_Error_aux(the, XS_URI_ERROR, 0);
406
4
}
407
408
void fx_Error_prototype_get_stack(txMachine* the)
409
2
{
410
2
  txSlot* slot;
411
2
  if (mxThis->kind != XS_REFERENCE_KIND)
412
0
    mxTypeError("this: not an object");
413
2
  slot = mxThis->value.reference->next;
414
2
  if (slot && (slot->kind == XS_ERROR_KIND)) {
415
1
    fxStringX(the, mxResult, "");
416
1
    mxPushSlot(mxThis);
417
1
    mxGetID(mxID(_name));
418
1
    if (the->stack->kind != XS_UNDEFINED_KIND)  {
419
1
      fxToString(the, the->stack);
420
1
      fxConcatString(the, mxResult, the->stack);
421
1
    }
422
0
    else
423
0
      fxConcatStringC(the, mxResult, "Error");
424
1
    mxPop();
425
1
    mxPushSlot(mxThis);
426
1
    mxGetID(mxID(_message));
427
1
    if (the->stack->kind != XS_UNDEFINED_KIND) {
428
1
      fxToString(the, the->stack);
429
1
      if (!c_isEmpty(the->stack->value.string)) {
430
0
        fxConcatStringC(the, mxResult, ": ");
431
0
        fxConcatString(the, mxResult, the->stack);
432
0
      }
433
1
    }
434
1
    mxPop();
435
1
    slot = slot->value.reference;
436
1
    if (slot) {
437
1
      slot = slot->next;
438
2
      while (slot) {
439
1
        fxConcatStringC(the, mxResult, "\n at");
440
1
        if ((slot->value.key.string != C_NULL) && (mxStringLength(slot->value.key.string))) {
441
0
          fxConcatStringC(the, mxResult, " ");
442
0
          fxConcatString(the, mxResult, slot);
443
0
        }
444
1
        fxConcatStringC(the, mxResult, " (");
445
1
        if (slot->ID != XS_NO_ID) {
446
1
          fxIDToString(the, slot->ID, the->nameBuffer, sizeof(the->nameBuffer));
447
1
          fxConcatStringC(the, mxResult, the->nameBuffer);
448
1
          fxConcatStringC(the, mxResult, ":");
449
1
          fxIntegerToString(the, (txInteger)slot->value.key.sum, the->nameBuffer, sizeof(the->nameBuffer));
450
1
          fxConcatStringC(the, mxResult, the->nameBuffer);
451
1
        }
452
1
        fxConcatStringC(the, mxResult, ")");
453
1
        slot = slot->next;
454
1
      }
455
1
    }
456
1
  }
457
2
}
458
459
void fx_Error_prototype_set_stack(txMachine* the)
460
0
{
461
0
  if (mxThis->kind != XS_REFERENCE_KIND)
462
0
    mxTypeError("this: not an object");
463
0
  if (mxArgc < 1)
464
0
    mxTypeError("no value");
465
0
  mxPushSlot(mxArgv(0));
466
0
  mxPushSlot(mxThis);
467
0
  mxDefineID(mxID(_stack), XS_NO_FLAG, XS_GET_ONLY);
468
0
  mxPop();
469
0
}
470
471
static const txString gXSAbortStrings[] = {
472
  "debugger",
473
  "memory full",
474
  "JavaScript stack overflow",
475
  "fatal",
476
  "dead strip",
477
  "unhandled exception",
478
  "not enough keys",
479
  "too much computation",
480
  "unhandled rejection",
481
  "native stack overflow",
482
};
483
484
txString fxAbortString(int status)
485
0
{
486
0
  if ((status < 0) || (status >= (int)(sizeof(gXSAbortStrings) / sizeof(txString))))
487
0
    return "unknown";
488
489
0
  return gXSAbortStrings[status];
490
0
}
491
492
#if mxExplicitResourceManagement
493
494
void fx_SuppressedError(txMachine* the)
495
25
{
496
25
  txSlot* property = fx_Error_aux(the, XS_SUPPRESSED_ERROR, 2);
497
25
  property = fxNextSlotProperty(the, property, mxArgv(0), mxID(_error), XS_DONT_ENUM_FLAG);
498
25
  property = fxNextSlotProperty(the, property, mxArgv(1), mxID(_suppressed), XS_DONT_ENUM_FLAG);
499
25
}
500
501
static txSlot* fxCheckDisposableStackInstance(txMachine* the, txSlot* slot, txBoolean mutable, txBoolean disposable);
502
static void fxDisposableStackPush(txMachine* the, txSlot* property);
503
504
txSlot* fxCheckDisposableStackInstance(txMachine* the, txSlot* slot, txBoolean mutable, txBoolean disposable)
505
283
{
506
283
  if (slot->kind == XS_REFERENCE_KIND) {
507
194
    txSlot* instance = slot->value.reference;
508
194
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_DISPOSABLE_STACK_KIND)) {
509
138
      if (mutable && (slot->flag & XS_DONT_SET_FLAG))
510
0
        mxTypeError("this: read-only DisposableStack instance");
511
138
      if (disposable && slot->value.disposableStack.disposed)
512
20
        mxReferenceError("this: disposed DisposableStack instance");
513
118
      return instance;
514
138
    }
515
194
  }
516
283
  mxTypeError("this: not a DisposableStack instance");
517
0
  return C_NULL;
518
283
}
519
520
void fx_DisposableStack(txMachine* the)
521
117k
{
522
117k
  txSlot* instance;
523
117k
  txSlot* property;
524
117k
  if (mxIsUndefined(mxTarget))
525
1
    mxTypeError("call: DisposableStack");
526
117k
  mxPushSlot(mxTarget);
527
117k
  fxGetPrototypeFromConstructor(the, &mxDisposableStackPrototype);
528
117k
  instance = fxNewSlot(the);
529
117k
  instance->kind = XS_INSTANCE_KIND;
530
117k
  instance->value.instance.garbage = C_NULL;
531
117k
  instance->value.instance.prototype = the->stack->value.reference;
532
117k
  the->stack->kind = XS_REFERENCE_KIND;
533
117k
  the->stack->value.reference = instance;
534
117k
  mxPullSlot(mxResult);
535
117k
  property = instance->next = fxNewSlot(the);
536
117k
  property->flag = XS_INTERNAL_FLAG;
537
117k
  property->kind = XS_DISPOSABLE_STACK_KIND;
538
117k
  property->value.disposableStack.stack = C_NULL;
539
117k
  property->value.disposableStack.disposed = 0;
540
117k
}
541
542
void fx_DisposableStack_prototype_get_disposed(txMachine* the)
543
19
{
544
19
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 0, 0);
545
19
  txSlot* property = instance->next;
546
19
  mxResult->value.boolean = property->value.disposableStack.disposed;
547
19
  mxResult->kind = XS_BOOLEAN_KIND;
548
19
}
549
550
void fx_DisposableStack_prototype_adopt(txMachine* the)
551
56
{
552
56
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
553
56
  txSlot* property = instance->next;
554
56
  if (mxArgc > 0) 
555
28
    mxPushSlot(mxArgv(0));
556
28
  else
557
28
    mxPushUndefined();
558
56
  if (mxArgc > 1) 
559
27
    mxPushSlot(mxArgv(1));
560
29
  else
561
29
    mxPushUndefined();
562
56
  fxDisposableStackPush(the, property);
563
56
  property->value.disposableStack.stack->flag |= XS_BASE_FLAG;
564
56
  mxPop();
565
56
  mxPullSlot(mxResult);
566
56
}
567
568
void fx_DisposableStack_prototype_defer(txMachine* the)
569
56
{
570
56
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
571
56
  txSlot* property = instance->next;
572
56
  mxPushUndefined();
573
56
  if (mxArgc > 0) 
574
34
    mxPushSlot(mxArgv(0));
575
22
  else
576
22
    mxPushUndefined();
577
56
  fxDisposableStackPush(the, property);
578
56
  mxPop();
579
56
  mxPop();
580
56
}  
581
582
void fx_DisposableStack_prototype_dispose(txMachine* the)
583
46
{
584
46
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 0);
585
46
  txSlot* property = instance->next;
586
46
  txSlot* exception;
587
46
  txBoolean selector = 1;
588
46
  txSlot* slot;
589
46
  if (property->value.disposableStack.disposed)
590
4
    return;
591
42
  property->value.disposableStack.disposed = 1;
592
42
  mxTemporary(exception);
593
42
  slot = property->value.disposableStack.stack;
594
60
  while (slot) {
595
18
    txSlot* dispose = slot;
596
18
    txSlot* resource = slot->next;
597
18
    mxTry(the) {
598
18
      if (dispose->flag & XS_BASE_FLAG) {
599
4
        mxPushUndefined();
600
4
        mxPushSlot(dispose);
601
4
        mxCall();
602
4
        mxPushSlot(resource);
603
4
        mxRunCount(1);
604
4
        mxPop();
605
4
      }
606
14
      else {
607
14
        mxPushSlot(resource);
608
14
        mxPushSlot(dispose);
609
14
        mxCall();
610
14
        mxRunCount(0);
611
14
        mxPop();
612
14
      }
613
18
    }
614
18
    mxCatch(the) {
615
6
      if (selector == 0) {
616
3
        mxPush(mxSuppressedErrorConstructor);
617
3
        mxNew();
618
3
        mxPush(mxException);
619
3
        mxPushSlot(exception);
620
3
        mxRunCount(2);
621
3
        mxPullSlot(exception);
622
3
      }
623
3
      else {
624
3
        *exception = mxException;
625
3
        selector = 0;
626
3
      }
627
6
      mxException = mxUndefined;
628
6
    }
629
18
    slot = resource->next;
630
18
  }
631
42
  if (selector == 0) {
632
3
    mxException.kind = exception->kind;
633
3
    mxException.value = exception->value;
634
3
    fxJump(the);
635
3
  }
636
42
}
637
638
void fx_DisposableStack_prototype_move(txMachine* the)
639
26
{
640
26
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
641
26
  txSlot* property = instance->next;
642
26
  txSlot* resultInstance;
643
26
  txSlot* resultProperty;
644
26
  mxPush(mxDisposableStackConstructor);
645
26
  fxGetPrototypeFromConstructor(the, &mxDisposableStackPrototype);
646
26
  resultInstance = fxNewSlot(the);
647
26
  resultInstance->kind = XS_INSTANCE_KIND;
648
26
  resultInstance->value.instance.garbage = C_NULL;
649
26
  resultInstance->value.instance.prototype = the->stack->value.reference;
650
26
  the->stack->kind = XS_REFERENCE_KIND;
651
26
  the->stack->value.reference = resultInstance;
652
26
  mxPullSlot(mxResult);
653
26
  resultProperty = resultInstance->next = fxNewSlot(the);
654
26
  resultProperty->flag = XS_INTERNAL_FLAG;
655
26
  resultProperty->kind = XS_DISPOSABLE_STACK_KIND;
656
26
  resultProperty->value.disposableStack.stack = property->value.disposableStack.stack;
657
26
  resultProperty->value.disposableStack.disposed = 0;
658
26
  property->value.disposableStack.stack = C_NULL;
659
26
  property->value.disposableStack.disposed = 1;
660
26
}
661
662
void fx_DisposableStack_prototype_use(txMachine* the)
663
80
{
664
80
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
665
80
  txSlot* property = instance->next;
666
80
  txSlot* resource;
667
80
  if (mxArgc > 0)
668
21
    mxPushSlot(mxArgv(0));
669
59
  else
670
59
    mxPushUndefined();
671
80
  resource = the->stack;
672
80
  if (!mxIsNull(resource) && !mxIsUndefined(resource)) {
673
16
    mxPushSlot(resource);
674
16
    mxGetID(mxID(_Symbol_dispose));
675
16
    fxDisposableStackPush(the, property);
676
16
    mxPop();
677
16
  }
678
80
  mxPullSlot(mxResult);
679
80
}
680
681
void fxDisposableStackPush(txMachine* the, txSlot* property)
682
79
{
683
79
  txSlot* dispose = the->stack;
684
79
  txSlot* resource = dispose + 1;
685
79
  txSlot** address = &property->value.disposableStack.stack;
686
79
  txSlot* slot;
687
79
  if (!fxIsCallable(the, dispose))
688
42
    mxTypeError("dispose: not a function");
689
    
690
37
  slot = fxNewSlot(the);
691
37
  slot->next = *address;
692
37
  slot->kind = resource->kind;
693
37
  slot->value = resource->value;
694
37
  *address = slot;
695
  
696
37
  slot = fxNewSlot(the);
697
37
  slot->next = *address;
698
37
  slot->kind = dispose->kind;
699
37
  slot->value = dispose->value;
700
37
  *address = slot;
701
37
}
702
703
static txSlot* fxCheckAsyncDisposableStackInstance(txMachine* the, txSlot* slot, txBoolean mutable, txBoolean disposable);
704
static void fxAsyncDisposableStackPush(txMachine* the, txSlot* property);
705
static void fxAsyncDisposableStackReject(txMachine* the);
706
static void fxAsyncDisposableStackResolve(txMachine* the);
707
708
txSlot* fxCheckAsyncDisposableStackInstance(txMachine* the, txSlot* slot, txBoolean mutable, txBoolean disposable)
709
128
{
710
128
  if (slot->kind == XS_REFERENCE_KIND) {
711
62
    txSlot* instance = slot->value.reference;
712
62
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_ASYNC_DISPOSABLE_STACK_KIND)) {
713
16
      if (mutable && (slot->flag & XS_DONT_SET_FLAG))
714
0
        mxTypeError("this: read-only AsyncDisposableStack instance");
715
16
      if (disposable && slot->value.disposableStack.disposed)
716
0
        mxReferenceError("this: disposed AsyncDisposableStack instance");
717
16
      return instance;
718
16
    }
719
62
  }
720
128
  mxTypeError("this: not a AsyncDisposableStack instance");
721
0
  return C_NULL;
722
128
}
723
void fx_AsyncDisposableStack(txMachine* the)
724
266k
{
725
266k
  txSlot* instance;
726
266k
  txSlot* property;
727
266k
  txSlot* function;
728
266k
  txSlot* home;
729
266k
  if (mxIsUndefined(mxTarget))
730
3
    mxTypeError("call: AsyncDisposableStack");
731
266k
  mxPushSlot(mxTarget);
732
266k
  fxGetPrototypeFromConstructor(the, &mxAsyncDisposableStackPrototype);
733
266k
  instance = fxNewSlot(the);
734
266k
  instance->kind = XS_INSTANCE_KIND;
735
266k
  instance->value.instance.garbage = C_NULL;
736
266k
  instance->value.instance.prototype = the->stack->value.reference;
737
266k
  the->stack->kind = XS_REFERENCE_KIND;
738
266k
  the->stack->value.reference = instance;
739
266k
  mxPullSlot(mxResult);
740
266k
  property = instance->next = fxNewSlot(the);
741
266k
  property->flag = XS_INTERNAL_FLAG;
742
266k
  property->kind = XS_ASYNC_DISPOSABLE_STACK_KIND;
743
266k
  property->value.disposableStack.stack = C_NULL;
744
266k
  property->value.disposableStack.disposed = 0;
745
  
746
266k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
747
266k
  function = fxNewHostFunction(the, fxAsyncDisposableStackResolve, 1, XS_NO_ID, mxAsyncGeneratorResolveYieldProfileID);
748
266k
  home = mxFunctionInstanceHome(function);
749
266k
  home->value.home.object = instance;
750
266k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
751
266k
  mxPop();
752
266k
  function = fxNewHostFunction(the, fxAsyncDisposableStackReject, 1, XS_NO_ID, mxAsyncGeneratorRejectYieldProfileID);
753
266k
  home = mxFunctionInstanceHome(function);
754
266k
  home->value.home.object = instance;
755
266k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
756
266k
  mxPop();
757
266k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
758
266k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
759
266k
}
760
761
void fx_AsyncDisposableStack_prototype_get_disposed(txMachine* the)
762
15
{
763
15
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 0, 0);
764
15
  txSlot* property = instance->next;
765
15
  mxResult->value.boolean = property->value.disposableStack.disposed;
766
15
  mxResult->kind = XS_BOOLEAN_KIND;
767
15
}
768
769
void fx_AsyncDisposableStack_prototype_adopt(txMachine* the)
770
24
{
771
24
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 1);
772
24
  txSlot* property = instance->next;
773
24
  if (mxArgc > 0) 
774
0
    mxPushSlot(mxArgv(0));
775
24
  else
776
24
    mxPushUndefined();
777
24
  if (mxArgc > 1) 
778
0
    mxPushSlot(mxArgv(1));
779
24
  else
780
24
    mxPushUndefined();
781
24
  fxAsyncDisposableStackPush(the, property);
782
24
  property->value.disposableStack.stack->flag |= XS_BASE_FLAG;
783
24
  mxPop();
784
24
  mxPullSlot(mxResult);
785
24
}
786
787
void fx_AsyncDisposableStack_prototype_defer(txMachine* the)
788
27
{
789
27
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 1);
790
27
  txSlot* property = instance->next;
791
27
  mxPushUndefined();
792
27
  if (mxArgc > 0) 
793
0
    mxPushSlot(mxArgv(0));
794
27
  else
795
27
    mxPushUndefined();
796
27
  fxAsyncDisposableStackPush(the, property);
797
27
  mxPop();
798
27
  mxPop();
799
27
}  
800
801
void fx_AsyncDisposableStack_prototype_disposeAsync(txMachine* the)
802
0
{
803
0
  txSlot* promise;
804
0
  txSlot* resolveFunction;
805
0
  txSlot* rejectFunction;
806
807
0
  mxPush(mxPromisePrototype);
808
0
  promise = fxNewPromiseInstance(the);
809
0
  mxPullSlot(mxResult);
810
0
  mxPromiseStatus(promise)->value.integer = mxPendingStatus;
811
0
  fxPushPromiseFunctions(the, promise);
812
0
  resolveFunction = the->stack + 1;
813
0
  rejectFunction = the->stack;
814
0
  mxTry(the) {
815
0
    txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 0);
816
0
    txSlot* property = instance->next;
817
0
    if (property->value.disposableStack.disposed) {
818
0
      mxPushUndefined();
819
0
      mxPushSlot(resolveFunction);
820
0
      mxCall();
821
0
      mxPushUndefined();
822
0
      mxRunCount(1);
823
0
      mxPop();
824
0
    }
825
0
    else {
826
0
      txSlot* exception = property->next;
827
0
      txSlot* resolveStepFunction = exception->next;
828
0
      txSlot* rejectStepFunction = resolveStepFunction->next;
829
0
      property->value.disposableStack.disposed = 1;
830
0
      property = rejectStepFunction->next;
831
0
      property->kind = resolveFunction->kind;
832
0
      property->value = resolveFunction->value;
833
0
      property = property->next;
834
0
      property->kind = rejectFunction->kind;
835
0
      property->value = rejectFunction->value;
836
0
      mxPushUndefined();
837
0
      mxPushSlot(resolveStepFunction);
838
0
      mxCall();
839
0
      mxPushUndefined();
840
0
      mxRunCount(1);
841
0
      mxPop();
842
0
    }
843
0
  }
844
0
  mxCatch(the) {
845
0
    fxRejectException(the, rejectFunction);
846
0
  }
847
0
}
848
849
void fx_AsyncDisposableStack_prototype_move(txMachine* the)
850
27
{
851
27
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 1);
852
27
  txSlot* property = instance->next;
853
27
  txSlot* resultInstance;
854
27
  txSlot* resultProperty;
855
27
  txSlot* function;
856
27
  txSlot* home;
857
27
  mxPush(mxAsyncDisposableStackConstructor);
858
27
  fxGetPrototypeFromConstructor(the, &mxAsyncDisposableStackPrototype);
859
27
  resultInstance = fxNewSlot(the);
860
27
  resultInstance->kind = XS_INSTANCE_KIND;
861
27
  resultInstance->value.instance.garbage = C_NULL;
862
27
  resultInstance->value.instance.prototype = the->stack->value.reference;
863
27
  the->stack->kind = XS_REFERENCE_KIND;
864
27
  the->stack->value.reference = resultInstance;
865
27
  mxPullSlot(mxResult);
866
27
  resultProperty = resultInstance->next = fxNewSlot(the);
867
27
  resultProperty->flag = XS_INTERNAL_FLAG;
868
27
  resultProperty->kind = XS_ASYNC_DISPOSABLE_STACK_KIND;
869
27
  resultProperty->value.disposableStack.stack = property->value.disposableStack.stack;
870
27
  resultProperty->value.disposableStack.disposed = 0;
871
  
872
27
    resultProperty = fxNextUndefinedProperty(the, resultProperty, XS_NO_ID, XS_INTERNAL_FLAG);
873
27
  function = fxNewHostFunction(the, fxAsyncDisposableStackResolve, 1, XS_NO_ID, mxAsyncGeneratorResolveYieldProfileID);
874
27
  home = mxFunctionInstanceHome(function);
875
27
  home->value.home.object = resultInstance;
876
27
    resultProperty = fxNextSlotProperty(the, resultProperty, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
877
27
  mxPop();
878
27
  function = fxNewHostFunction(the, fxAsyncDisposableStackReject, 1, XS_NO_ID, mxAsyncGeneratorRejectYieldProfileID);
879
27
  home = mxFunctionInstanceHome(function);
880
27
  home->value.home.object = resultInstance;
881
27
    resultProperty = fxNextSlotProperty(the, resultProperty, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
882
27
  mxPop();
883
27
    resultProperty = fxNextUndefinedProperty(the, resultProperty, XS_NO_ID, XS_INTERNAL_FLAG);
884
27
    resultProperty = fxNextUndefinedProperty(the, resultProperty, XS_NO_ID, XS_INTERNAL_FLAG);
885
  
886
27
  property->value.disposableStack.stack = C_NULL;
887
27
  property->value.disposableStack.disposed = 1;
888
27
}
889
890
void fx_AsyncDisposableStack_prototype_use(txMachine* the)
891
35
{
892
35
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 1);
893
35
  txSlot* property = instance->next;
894
35
  txSlot* resource;
895
35
  if (mxArgc > 0)
896
14
    mxPushSlot(mxArgv(0));
897
21
  else
898
21
    mxPushUndefined();
899
35
  resource = the->stack;
900
35
  if (!mxIsNull(resource) && !mxIsUndefined(resource)) {
901
13
    mxPushSlot(resource);
902
13
    mxGetID(mxID(_Symbol_asyncDispose));
903
13
    if (!fxIsCallable(the, the->stack)) {
904
13
      mxPop();
905
13
      mxPushSlot(resource);
906
13
      mxGetID(mxID(_Symbol_dispose));
907
13
    }
908
13
    fxAsyncDisposableStackPush(the, property);
909
13
    mxPop();
910
13
  }
911
35
  mxPullSlot(mxResult);
912
35
}
913
914
void fxAsyncDisposableStackPush(txMachine* the, txSlot* property)
915
13
{
916
13
  txSlot* dispose = the->stack;
917
13
  txSlot* resource = dispose + 1;
918
13
  txSlot** address = &property->value.disposableStack.stack;
919
13
  txSlot* slot;
920
13
  if (!fxIsCallable(the, dispose))
921
13
    mxTypeError("dispose: no a function");
922
    
923
0
  slot = fxNewSlot(the);
924
0
  slot->next = *address;
925
0
  slot->kind = resource->kind;
926
0
  slot->value = resource->value;
927
0
  *address = slot;
928
  
929
0
  slot = fxNewSlot(the);
930
0
  slot->next = *address;
931
0
  slot->kind = dispose->kind;
932
0
  slot->value = dispose->value;
933
0
  *address = slot;
934
0
}
935
936
void fxAsyncDisposableStackReject(txMachine* the)
937
0
{
938
0
  txSlot* slot = mxFunctionInstanceHome(mxFunction->value.reference);
939
0
  txSlot* instance = slot->value.home.object;
940
0
  txSlot* property = instance->next;
941
0
  txSlot* exception = property->next;
942
  
943
0
  if (mxIsUndefined(exception)) {
944
0
    mxPushSlot(mxArgv(0));
945
0
    mxPullSlot(exception);
946
0
  }
947
0
  else {
948
0
    mxPush(mxSuppressedErrorConstructor);
949
0
    mxNew();
950
0
    mxPushSlot(mxArgv(0));
951
0
    mxPushSlot(exception);
952
0
    mxRunCount(2);
953
0
    mxPullSlot(exception);
954
0
  }
955
0
  fxAsyncDisposableStackResolve(the);
956
0
}
957
958
void fxAsyncDisposableStackResolve(txMachine* the)
959
0
{
960
0
  txSlot* slot = mxFunctionInstanceHome(mxFunction->value.reference);
961
0
  txSlot* instance = slot->value.home.object;
962
0
  txSlot* property = instance->next;
963
0
  txSlot* exception = property->next;
964
0
  txSlot* resolveStepFunction = exception->next;
965
0
  txSlot* rejectStepFunction = resolveStepFunction->next;
966
0
  txSlot* resolveFunction = rejectStepFunction->next;
967
0
  txSlot* rejectFunction = resolveFunction->next;
968
969
0
  slot = property->value.disposableStack.stack;
970
0
  if (slot) {
971
0
    txSlot* dispose = slot;
972
0
    txSlot* resource = slot->next;
973
0
    property->value.disposableStack.stack = resource->next;
974
0
    mxTry(the) {
975
0
      mxPushUndefined();
976
0
      mxPush(mxPromiseConstructor);
977
0
      if (dispose->flag & XS_BASE_FLAG) {
978
0
        mxPushUndefined();
979
0
        mxPushSlot(dispose);
980
0
        mxCall();
981
0
        mxPushSlot(resource);
982
0
        mxRunCount(1);
983
0
      }
984
0
      else {
985
0
        mxPushSlot(resource);
986
0
        mxPushSlot(dispose);
987
0
        mxCall();
988
0
        mxRunCount(0);
989
0
      }
990
0
      fx_Promise_resolveAux(the);
991
0
      mxPop();
992
0
      mxPop();
993
0
      fxPromiseThen(the, the->stack->value.reference, resolveStepFunction, rejectStepFunction, C_NULL, C_NULL);
994
0
      mxPop();
995
0
    }
996
0
    mxCatch(the) {
997
0
      mxPushUndefined();
998
0
      mxPushSlot(rejectStepFunction);
999
0
      mxCall();
1000
0
      mxPush(mxException);
1001
0
      mxException = mxUndefined;
1002
0
      mxRunCount(1);
1003
0
      mxPop();
1004
0
    }
1005
0
  }
1006
0
  else {
1007
0
    if (mxIsUndefined(exception)) {
1008
0
      mxPushUndefined();
1009
0
      mxPushSlot(resolveFunction);
1010
0
      mxCall();
1011
0
      mxPushUndefined();
1012
0
      mxRunCount(1);
1013
0
      mxPop();
1014
0
    }
1015
0
    else {
1016
0
      mxPushUndefined();
1017
0
      mxPushSlot(rejectFunction);
1018
0
      mxCall();
1019
0
      mxPushSlot(exception);
1020
0
      mxRunCount(1);
1021
0
      mxPop();
1022
0
    }
1023
0
  }
1024
0
}
1025
1026
#endif
1027
1028
1029
1030