Coverage Report

Created: 2026-03-07 07:04

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
28.3k
{
74
28.3k
  txSlot* slot;
75
28.3k
  txSlot* prototype;
76
28.3k
  txSlot* instance;
77
28.3k
#if mxExplicitResourceManagement
78
28.3k
  txSlot* property;
79
28.3k
#endif
80
  
81
28.3k
  mxPush(mxObjectPrototype);
82
28.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
83
28.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
84
28.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_UNKNOWN_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
85
28.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
86
28.3k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_Error_prototype_get_stack), mxCallback(fx_Error_prototype_set_stack), mxID(_stack), XS_DONT_ENUM_FLAG);
87
28.3k
  mxErrorPrototype = *the->stack;
88
28.3k
  prototype = fxBuildHostConstructor(the, mxCallback(fx_Error), 1, mxID(_Error));
89
28.3k
  mxErrorConstructor = *the->stack;
90
28.3k
#if mxErrorIsError
91
28.3k
  slot = fxLastProperty(the, prototype);
92
28.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_isError), 1, mxID(_isError), XS_DONT_ENUM_FLAG);
93
28.3k
#endif
94
28.3k
  mxPop();
95
28.3k
  mxPush(mxErrorPrototype);
96
28.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
97
28.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_AGGREGATE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
98
28.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
99
28.3k
  mxAggregateErrorPrototype = *the->stack;
100
28.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_AggregateError), 2, mxID(_AggregateError));
101
28.3k
  instance->value.instance.prototype = prototype;
102
28.3k
  mxAggregateErrorConstructor = *the->stack;
103
28.3k
  mxPop();
104
28.3k
  mxPush(mxErrorPrototype);
105
28.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
106
28.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_EVAL_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
107
28.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
108
28.3k
  mxEvalErrorPrototype = *the->stack;
109
28.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_EvalError), 1, mxID(_EvalError));
110
28.3k
  instance->value.instance.prototype = prototype;
111
28.3k
  mxEvalErrorConstructor = *the->stack;
112
28.3k
  mxPop();
113
28.3k
  mxPush(mxErrorPrototype);
114
28.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
115
28.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_RANGE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
116
28.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
117
28.3k
  mxRangeErrorPrototype = *the->stack;
118
28.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_RangeError), 1, mxID(_RangeError));
119
28.3k
  instance->value.instance.prototype = prototype;
120
28.3k
  mxRangeErrorConstructor = *the->stack;
121
28.3k
  mxPop();
122
28.3k
  mxPush(mxErrorPrototype);
123
28.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
124
28.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_REFERENCE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
125
28.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
126
28.3k
  mxReferenceErrorPrototype = *the->stack;
127
28.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_ReferenceError), 1, mxID(_ReferenceError));
128
28.3k
  instance->value.instance.prototype = prototype;
129
28.3k
  mxReferenceErrorConstructor = *the->stack;
130
28.3k
  mxPop();
131
28.3k
  mxPush(mxErrorPrototype);
132
28.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
133
28.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_SYNTAX_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
134
28.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
135
28.3k
  mxSyntaxErrorPrototype = *the->stack;
136
28.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_SyntaxError), 1, mxID(_SyntaxError));
137
28.3k
  instance->value.instance.prototype = prototype;
138
28.3k
  mxSyntaxErrorConstructor = *the->stack;
139
28.3k
  mxPop();
140
28.3k
  mxPush(mxErrorPrototype);
141
28.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
142
28.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_TYPE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
143
28.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
144
28.3k
  mxTypeErrorPrototype = *the->stack;
145
28.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_TypeError), 1, mxID(_TypeError));
146
28.3k
  instance->value.instance.prototype = prototype;
147
28.3k
  mxTypeErrorConstructor = *the->stack;
148
28.3k
  mxPop();
149
28.3k
  mxPush(mxErrorPrototype);
150
28.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
151
28.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_URI_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
152
28.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
153
28.3k
  mxURIErrorPrototype = *the->stack;
154
28.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_URIError), 1, mxID(_URIError));
155
28.3k
  instance->value.instance.prototype = prototype;
156
28.3k
  mxURIErrorConstructor = *the->stack;
157
28.3k
  mxPop();
158
159
28.3k
#if mxExplicitResourceManagement
160
28.3k
  mxPush(mxErrorPrototype);
161
28.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
162
28.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_SUPPRESSED_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
163
28.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
164
28.3k
  mxSuppressedErrorPrototype = *the->stack;
165
28.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_SuppressedError), 3, mxID(_SuppressedError));
166
28.3k
  instance->value.instance.prototype = prototype;
167
28.3k
  mxSuppressedErrorConstructor = *the->stack;
168
28.3k
  mxPop();
169
170
28.3k
  mxPush(mxObjectPrototype);
171
28.3k
    slot = fxLastProperty(the, fxNewObjectInstance(the));
172
28.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
173
28.3k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_DisposableStack_prototype_get_disposed), C_NULL, mxID(_disposed), XS_DONT_ENUM_FLAG);
174
28.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_adopt), 2, mxID(_adopt), XS_DONT_ENUM_FLAG);
175
28.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_defer), 1, mxID(_defer), XS_DONT_ENUM_FLAG);
176
28.3k
  property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_dispose), 0, mxID(_dispose), XS_DONT_ENUM_FLAG);
177
28.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_move), 0, mxID(_move), XS_DONT_ENUM_FLAG);
178
28.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_use), 1, mxID(_use), XS_DONT_ENUM_FLAG);
179
28.3k
  slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_dispose), XS_DONT_ENUM_FLAG);
180
28.3k
  slot = fxNextStringXProperty(the, slot, "DisposableStack", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
181
28.3k
  mxDisposableStackPrototype = *the->stack;
182
28.3k
  slot = fxBuildHostConstructor(the, mxCallback(fx_DisposableStack), 0, mxID(_DisposableStack));
183
28.3k
  mxDisposableStackConstructor = *the->stack;
184
28.3k
  mxPop();
185
  
186
28.3k
  mxPush(mxObjectPrototype);
187
28.3k
    slot = fxLastProperty(the, fxNewObjectInstance(the));
188
28.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
189
28.3k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_get_disposed), C_NULL, mxID(_disposed), XS_DONT_ENUM_FLAG);
190
28.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_adopt), 2, mxID(_adopt), XS_DONT_ENUM_FLAG);
191
28.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_defer), 1, mxID(_defer), XS_DONT_ENUM_FLAG);
192
28.3k
  property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_disposeAsync), 0, mxID(_disposeAsync), XS_DONT_ENUM_FLAG);
193
28.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_move), 0, mxID(_move), XS_DONT_ENUM_FLAG);
194
28.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_use), 1, mxID(_use), XS_DONT_ENUM_FLAG);
195
28.3k
  slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_asyncDispose), XS_DONT_ENUM_FLAG);
196
28.3k
  slot = fxNextStringXProperty(the, slot, "AsyncDisposableStack", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
197
28.3k
  mxAsyncDisposableStackPrototype = *the->stack;
198
28.3k
  slot = fxBuildHostConstructor(the, mxCallback(fx_AsyncDisposableStack), 0, mxID(_AsyncDisposableStack));
199
28.3k
  mxAsyncDisposableStackConstructor = *the->stack;
200
28.3k
  mxPop();
201
28.3k
#endif
202
28.3k
}
203
204
void fxCaptureErrorStack(txMachine* the, txSlot* internal, txSlot* frame)
205
1.87M
{
206
1.87M
  txSlot* slot = internal->value.reference = fxNewSlot(the);
207
1.87M
  slot->kind = XS_INSTANCE_KIND;
208
1.87M
  slot->value.instance.garbage = C_NULL;
209
1.87M
  slot->value.instance.prototype = C_NULL;
210
14.1M
  while (frame->next) {
211
12.2M
    txSlot* environment = mxFrameToEnvironment(frame);
212
12.2M
    txSlot* function = frame + 3; 
213
12.2M
    if (function->kind == XS_REFERENCE_KIND) {
214
12.2M
      function = function->value.reference;
215
12.2M
      if (mxIsFunction(function)) {
216
12.2M
        txSlot* name = mxBehaviorGetProperty(the, function, mxID(_name), 0, XS_OWN);
217
12.2M
        slot = slot->next = fxNewSlot(the);
218
12.2M
        slot->flag = XS_GET_ONLY;
219
12.2M
        slot->kind = XS_KEY_KIND;
220
12.2M
        slot->ID = environment->ID;
221
12.2M
        slot->value.key.string = C_NULL;
222
12.2M
        slot->value.key.sum = environment->value.environment.line;
223
12.2M
        if (name && ((name->kind == XS_STRING_KIND) || (name->kind == XS_STRING_X_KIND))) {
224
12.2M
          if (name->kind == XS_STRING_X_KIND)
225
0
            slot->kind = XS_KEY_X_KIND;
226
12.2M
          slot->value.key.string = name->value.string;
227
12.2M
        }
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
12.2M
      }
247
12.2M
    }
248
12.2M
    frame = frame->next;
249
12.2M
  }
250
1.87M
}
251
252
void fx_Error(txMachine* the)
253
40.7k
{
254
40.7k
  fx_Error_aux(the, XS_UNKNOWN_ERROR, 0);
255
40.7k
}
256
257
void fx_Error_isError(txMachine* the)
258
135
{
259
135
  mxResult->kind = XS_BOOLEAN_KIND;
260
135
  mxResult->value.boolean = 0;
261
135
  if (mxArgc > 0) {
262
96
    txSlot* instance = fxGetInstance(the, mxArgv(0));
263
96
    if (instance) {
264
45
      txSlot* internal = instance->next;
265
45
      if (internal && (internal->kind == XS_ERROR_KIND)) {
266
21
        mxResult->value.boolean = 1;
267
21
      }
268
45
    }
269
96
  }
270
135
}
271
272
txSlot* fx_Error_aux(txMachine* the, txError error, txInteger i)
273
372k
{
274
372k
  txSlot* instance;
275
372k
  txSlot* slot;
276
372k
  if (mxIsUndefined(mxTarget))
277
267
    mxPushSlot(mxFunction);
278
372k
  else
279
372k
    mxPushSlot(mxTarget);
280
372k
  fxGetPrototypeFromConstructor(the, &mxErrorPrototypes(error));
281
372k
  instance = fxNewObjectInstance(the);
282
372k
  mxPullSlot(mxResult);
283
372k
  slot = instance->next = fxNewSlot(the);
284
372k
  slot->flag = XS_INTERNAL_FLAG;
285
372k
  slot->kind = XS_ERROR_KIND;
286
372k
  slot->value.error.info = C_NULL;
287
372k
  slot->value.error.which = error;
288
372k
  if (gxDefaults.captureErrorStack)
289
372k
    gxDefaults.captureErrorStack(the, slot, the->frame->next);
290
372k
  if ((mxArgc > i) && (mxArgv(i)->kind != XS_UNDEFINED_KIND)) {
291
364k
    fxToString(the, mxArgv(i));
292
364k
    slot = fxNextSlotProperty(the, slot, mxArgv(i), mxID(_message), XS_DONT_ENUM_FLAG);
293
364k
  }
294
372k
  i++;
295
372k
  if ((mxArgc > i) && (mxArgv(i)->kind == XS_REFERENCE_KIND)) {
296
32.5k
    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
32.5k
  }
303
372k
  return slot;
304
372k
}
305
306
void fx_Error_toString(txMachine* the)
307
219k
{
308
219k
  txSlot* name;
309
219k
  txSlot* message;
310
219k
  if (mxThis->kind != XS_REFERENCE_KIND)
311
9
    mxTypeError("this: not an object");
312
219k
  mxPushSlot(mxThis);
313
219k
  mxGetID(mxID(_name));
314
219k
  if (the->stack->kind == XS_UNDEFINED_KIND) 
315
219k
    fxStringX(the, the->stack, "Error");
316
154
  else  
317
154
    fxToString(the, the->stack);
318
219k
  name = the->stack;
319
219k
  mxPushSlot(mxThis);
320
219k
  mxGetID(mxID(_message));
321
219k
  if (the->stack->kind == XS_UNDEFINED_KIND) 
322
219k
    *the->stack = mxEmptyString;
323
155
  else  
324
155
    fxToString(the, the->stack);
325
219k
  message = the->stack;
326
219k
  if (c_isEmpty(name->value.string))
327
3
    *mxResult = *message;
328
219k
  else if (c_isEmpty(message->value.string))
329
219k
    *mxResult = *name;
330
128
  else {
331
128
    fxStringX(the, mxResult, "");
332
128
    fxConcatString(the, mxResult, name);
333
128
    fxConcatStringC(the, mxResult, ": ");
334
128
    fxConcatString(the, mxResult, message);
335
128
  }
336
219k
  the->stack += 2;
337
219k
}
338
339
void fx_AggregateError(txMachine* the)
340
55
{
341
55
  txSlot* stack = the->stack;
342
55
  txSlot* property = fx_Error_aux(the, XS_AGGREGATE_ERROR, 1);
343
55
  txSlot* array;
344
55
  txSlot** address;
345
55
  txIndex length = 0;
346
55
  txSlot* iterator;
347
55
  txSlot* next;
348
55
  txSlot* value;
349
55
  txSlot* slot;
350
  
351
55
  mxPush(mxArrayPrototype);
352
55
  array = fxNewArrayInstance(the);
353
55
  fxNextSlotProperty(the, property, the->stack, mxID(_errors), XS_DONT_ENUM_FLAG);
354
55
  address = &array->next->next;
355
55
  mxTemporary(iterator);
356
55
  mxTemporary(next);
357
55
  fxGetIterator(the, mxArgv(0), iterator, next, 0);
358
55
  mxTemporary(value);
359
39.6k
  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
55
  array->next->value.array.length = length;
373
55
  fxCacheArray(the, array);
374
  
375
55
  the->stack = stack;
376
55
}
377
378
void fx_EvalError(txMachine* the)
379
7
{
380
7
  fx_Error_aux(the, XS_EVAL_ERROR, 0);
381
7
}
382
383
void fx_RangeError(txMachine* the)
384
117
{
385
117
  fx_Error_aux(the, XS_RANGE_ERROR, 0);
386
117
}
387
388
void fx_ReferenceError(txMachine* the)
389
4
{
390
4
  fx_Error_aux(the, XS_REFERENCE_ERROR, 0);
391
4
}
392
393
void fx_SyntaxError(txMachine* the)
394
331k
{
395
331k
  fx_Error_aux(the, XS_SYNTAX_ERROR, 0);
396
331k
}
397
398
void fx_TypeError(txMachine* the)
399
99
{
400
99
  fx_Error_aux(the, XS_TYPE_ERROR, 0);
401
99
}
402
403
void fx_URIError(txMachine* the)
404
5
{
405
5
  fx_Error_aux(the, XS_URI_ERROR, 0);
406
5
}
407
408
void fx_Error_prototype_get_stack(txMachine* the)
409
1
{
410
1
  txSlot* slot;
411
1
  if (mxThis->kind != XS_REFERENCE_KIND)
412
0
    mxTypeError("this: not an object");
413
1
  slot = mxThis->value.reference->next;
414
1
  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
1
}
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
27
{
496
27
  txSlot* property = fx_Error_aux(the, XS_SUPPRESSED_ERROR, 2);
497
27
  property = fxNextSlotProperty(the, property, mxArgv(0), mxID(_error), XS_DONT_ENUM_FLAG);
498
27
  property = fxNextSlotProperty(the, property, mxArgv(1), mxID(_suppressed), XS_DONT_ENUM_FLAG);
499
27
}
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
252
{
506
252
  if (slot->kind == XS_REFERENCE_KIND) {
507
185
    txSlot* instance = slot->value.reference;
508
185
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_DISPOSABLE_STACK_KIND)) {
509
131
      if (mutable && (slot->flag & XS_DONT_SET_FLAG))
510
0
        mxTypeError("this: read-only DisposableStack instance");
511
131
      if (disposable && slot->value.disposableStack.disposed)
512
20
        mxReferenceError("this: disposed DisposableStack instance");
513
111
      return instance;
514
131
    }
515
185
  }
516
252
  mxTypeError("this: not a DisposableStack instance");
517
0
  return C_NULL;
518
252
}
519
520
void fx_DisposableStack(txMachine* the)
521
116k
{
522
116k
  txSlot* instance;
523
116k
  txSlot* property;
524
116k
  if (mxIsUndefined(mxTarget))
525
1
    mxTypeError("call: DisposableStack");
526
116k
  mxPushSlot(mxTarget);
527
116k
  fxGetPrototypeFromConstructor(the, &mxDisposableStackPrototype);
528
116k
  instance = fxNewSlot(the);
529
116k
  instance->kind = XS_INSTANCE_KIND;
530
116k
  instance->value.instance.garbage = C_NULL;
531
116k
  instance->value.instance.prototype = the->stack->value.reference;
532
116k
  the->stack->kind = XS_REFERENCE_KIND;
533
116k
  the->stack->value.reference = instance;
534
116k
  mxPullSlot(mxResult);
535
116k
  property = instance->next = fxNewSlot(the);
536
116k
  property->flag = XS_INTERNAL_FLAG;
537
116k
  property->kind = XS_DISPOSABLE_STACK_KIND;
538
116k
  property->value.disposableStack.stack = C_NULL;
539
116k
  property->value.disposableStack.disposed = 0;
540
116k
}
541
542
void fx_DisposableStack_prototype_get_disposed(txMachine* the)
543
18
{
544
18
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 0, 0);
545
18
  txSlot* property = instance->next;
546
18
  mxResult->value.boolean = property->value.disposableStack.disposed;
547
18
  mxResult->kind = XS_BOOLEAN_KIND;
548
18
}
549
550
void fx_DisposableStack_prototype_adopt(txMachine* the)
551
59
{
552
59
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
553
59
  txSlot* property = instance->next;
554
59
  if (mxArgc > 0) 
555
35
    mxPushSlot(mxArgv(0));
556
24
  else
557
24
    mxPushUndefined();
558
59
  if (mxArgc > 1) 
559
34
    mxPushSlot(mxArgv(1));
560
25
  else
561
25
    mxPushUndefined();
562
59
  fxDisposableStackPush(the, property);
563
59
  property->value.disposableStack.stack->flag |= XS_BASE_FLAG;
564
59
  mxPop();
565
59
  mxPullSlot(mxResult);
566
59
}
567
568
void fx_DisposableStack_prototype_defer(txMachine* the)
569
45
{
570
45
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
571
45
  txSlot* property = instance->next;
572
45
  mxPushUndefined();
573
45
  if (mxArgc > 0) 
574
21
    mxPushSlot(mxArgv(0));
575
24
  else
576
24
    mxPushUndefined();
577
45
  fxDisposableStackPush(the, property);
578
45
  mxPop();
579
45
  mxPop();
580
45
}  
581
582
void fx_DisposableStack_prototype_dispose(txMachine* the)
583
44
{
584
44
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 0);
585
44
  txSlot* property = instance->next;
586
44
  txSlot* exception;
587
44
  txBoolean selector = 1;
588
44
  txSlot* slot;
589
44
  if (property->value.disposableStack.disposed)
590
3
    return;
591
41
  property->value.disposableStack.disposed = 1;
592
41
  mxTemporary(exception);
593
41
  slot = property->value.disposableStack.stack;
594
57
  while (slot) {
595
16
    txSlot* dispose = slot;
596
16
    txSlot* resource = slot->next;
597
16
    mxTry(the) {
598
16
      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
12
      else {
607
12
        mxPushSlot(resource);
608
12
        mxPushSlot(dispose);
609
12
        mxCall();
610
12
        mxRunCount(0);
611
12
        mxPop();
612
12
      }
613
16
    }
614
16
    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
16
    slot = resource->next;
630
16
  }
631
41
  if (selector == 0) {
632
3
    mxException.kind = exception->kind;
633
3
    mxException.value = exception->value;
634
3
    fxJump(the);
635
3
  }
636
41
}
637
638
void fx_DisposableStack_prototype_move(txMachine* the)
639
21
{
640
21
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
641
21
  txSlot* property = instance->next;
642
21
  txSlot* resultInstance;
643
21
  txSlot* resultProperty;
644
21
  mxPush(mxDisposableStackConstructor);
645
21
  fxGetPrototypeFromConstructor(the, &mxDisposableStackPrototype);
646
21
  resultInstance = fxNewSlot(the);
647
21
  resultInstance->kind = XS_INSTANCE_KIND;
648
21
  resultInstance->value.instance.garbage = C_NULL;
649
21
  resultInstance->value.instance.prototype = the->stack->value.reference;
650
21
  the->stack->kind = XS_REFERENCE_KIND;
651
21
  the->stack->value.reference = resultInstance;
652
21
  mxPullSlot(mxResult);
653
21
  resultProperty = resultInstance->next = fxNewSlot(the);
654
21
  resultProperty->flag = XS_INTERNAL_FLAG;
655
21
  resultProperty->kind = XS_DISPOSABLE_STACK_KIND;
656
21
  resultProperty->value.disposableStack.stack = property->value.disposableStack.stack;
657
21
  resultProperty->value.disposableStack.disposed = 0;
658
21
  property->value.disposableStack.stack = C_NULL;
659
21
  property->value.disposableStack.disposed = 1;
660
21
}
661
662
void fx_DisposableStack_prototype_use(txMachine* the)
663
65
{
664
65
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
665
65
  txSlot* property = instance->next;
666
65
  txSlot* resource;
667
65
  if (mxArgc > 0)
668
21
    mxPushSlot(mxArgv(0));
669
44
  else
670
44
    mxPushUndefined();
671
65
  resource = the->stack;
672
65
  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
65
  mxPullSlot(mxResult);
679
65
}
680
681
void fxDisposableStackPush(txMachine* the, txSlot* property)
682
73
{
683
73
  txSlot* dispose = the->stack;
684
73
  txSlot* resource = dispose + 1;
685
73
  txSlot** address = &property->value.disposableStack.stack;
686
73
  txSlot* slot;
687
73
  if (!fxIsCallable(the, dispose))
688
37
    mxTypeError("dispose: not a function");
689
    
690
36
  slot = fxNewSlot(the);
691
36
  slot->next = *address;
692
36
  slot->kind = resource->kind;
693
36
  slot->value = resource->value;
694
36
  *address = slot;
695
  
696
36
  slot = fxNewSlot(the);
697
36
  slot->next = *address;
698
36
  slot->kind = dispose->kind;
699
36
  slot->value = dispose->value;
700
36
  *address = slot;
701
36
}
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
105
{
710
105
  if (slot->kind == XS_REFERENCE_KIND) {
711
51
    txSlot* instance = slot->value.reference;
712
51
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_ASYNC_DISPOSABLE_STACK_KIND)) {
713
7
      if (mutable && (slot->flag & XS_DONT_SET_FLAG))
714
0
        mxTypeError("this: read-only AsyncDisposableStack instance");
715
7
      if (disposable && slot->value.disposableStack.disposed)
716
0
        mxReferenceError("this: disposed AsyncDisposableStack instance");
717
7
      return instance;
718
7
    }
719
51
  }
720
105
  mxTypeError("this: not a AsyncDisposableStack instance");
721
0
  return C_NULL;
722
105
}
723
void fx_AsyncDisposableStack(txMachine* the)
724
219k
{
725
219k
  txSlot* instance;
726
219k
  txSlot* property;
727
219k
  txSlot* function;
728
219k
  txSlot* home;
729
219k
  if (mxIsUndefined(mxTarget))
730
1
    mxTypeError("call: AsyncDisposableStack");
731
219k
  mxPushSlot(mxTarget);
732
219k
  fxGetPrototypeFromConstructor(the, &mxAsyncDisposableStackPrototype);
733
219k
  instance = fxNewSlot(the);
734
219k
  instance->kind = XS_INSTANCE_KIND;
735
219k
  instance->value.instance.garbage = C_NULL;
736
219k
  instance->value.instance.prototype = the->stack->value.reference;
737
219k
  the->stack->kind = XS_REFERENCE_KIND;
738
219k
  the->stack->value.reference = instance;
739
219k
  mxPullSlot(mxResult);
740
219k
  property = instance->next = fxNewSlot(the);
741
219k
  property->flag = XS_INTERNAL_FLAG;
742
219k
  property->kind = XS_ASYNC_DISPOSABLE_STACK_KIND;
743
219k
  property->value.disposableStack.stack = C_NULL;
744
219k
  property->value.disposableStack.disposed = 0;
745
  
746
219k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
747
219k
  function = fxNewHostFunction(the, fxAsyncDisposableStackResolve, 1, XS_NO_ID, mxAsyncGeneratorResolveYieldProfileID);
748
219k
  home = mxFunctionInstanceHome(function);
749
219k
  home->value.home.object = instance;
750
219k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
751
219k
  mxPop();
752
219k
  function = fxNewHostFunction(the, fxAsyncDisposableStackReject, 1, XS_NO_ID, mxAsyncGeneratorRejectYieldProfileID);
753
219k
  home = mxFunctionInstanceHome(function);
754
219k
  home->value.home.object = instance;
755
219k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
756
219k
  mxPop();
757
219k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
758
219k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
759
219k
}
760
761
void fx_AsyncDisposableStack_prototype_get_disposed(txMachine* the)
762
10
{
763
10
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 0, 0);
764
10
  txSlot* property = instance->next;
765
10
  mxResult->value.boolean = property->value.disposableStack.disposed;
766
10
  mxResult->kind = XS_BOOLEAN_KIND;
767
10
}
768
769
void fx_AsyncDisposableStack_prototype_adopt(txMachine* the)
770
21
{
771
21
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 1);
772
21
  txSlot* property = instance->next;
773
21
  if (mxArgc > 0) 
774
0
    mxPushSlot(mxArgv(0));
775
21
  else
776
21
    mxPushUndefined();
777
21
  if (mxArgc > 1) 
778
0
    mxPushSlot(mxArgv(1));
779
21
  else
780
21
    mxPushUndefined();
781
21
  fxAsyncDisposableStackPush(the, property);
782
21
  property->value.disposableStack.stack->flag |= XS_BASE_FLAG;
783
21
  mxPop();
784
21
  mxPullSlot(mxResult);
785
21
}
786
787
void fx_AsyncDisposableStack_prototype_defer(txMachine* the)
788
23
{
789
23
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 1);
790
23
  txSlot* property = instance->next;
791
23
  mxPushUndefined();
792
23
  if (mxArgc > 0) 
793
0
    mxPushSlot(mxArgv(0));
794
23
  else
795
23
    mxPushUndefined();
796
23
  fxAsyncDisposableStackPush(the, property);
797
23
  mxPop();
798
23
  mxPop();
799
23
}  
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
23
{
851
23
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 1);
852
23
  txSlot* property = instance->next;
853
23
  txSlot* resultInstance;
854
23
  txSlot* resultProperty;
855
23
  txSlot* function;
856
23
  txSlot* home;
857
23
  mxPush(mxAsyncDisposableStackConstructor);
858
23
  fxGetPrototypeFromConstructor(the, &mxAsyncDisposableStackPrototype);
859
23
  resultInstance = fxNewSlot(the);
860
23
  resultInstance->kind = XS_INSTANCE_KIND;
861
23
  resultInstance->value.instance.garbage = C_NULL;
862
23
  resultInstance->value.instance.prototype = the->stack->value.reference;
863
23
  the->stack->kind = XS_REFERENCE_KIND;
864
23
  the->stack->value.reference = resultInstance;
865
23
  mxPullSlot(mxResult);
866
23
  resultProperty = resultInstance->next = fxNewSlot(the);
867
23
  resultProperty->flag = XS_INTERNAL_FLAG;
868
23
  resultProperty->kind = XS_ASYNC_DISPOSABLE_STACK_KIND;
869
23
  resultProperty->value.disposableStack.stack = property->value.disposableStack.stack;
870
23
  resultProperty->value.disposableStack.disposed = 0;
871
  
872
23
    resultProperty = fxNextUndefinedProperty(the, resultProperty, XS_NO_ID, XS_INTERNAL_FLAG);
873
23
  function = fxNewHostFunction(the, fxAsyncDisposableStackResolve, 1, XS_NO_ID, mxAsyncGeneratorResolveYieldProfileID);
874
23
  home = mxFunctionInstanceHome(function);
875
23
  home->value.home.object = resultInstance;
876
23
    resultProperty = fxNextSlotProperty(the, resultProperty, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
877
23
  mxPop();
878
23
  function = fxNewHostFunction(the, fxAsyncDisposableStackReject, 1, XS_NO_ID, mxAsyncGeneratorRejectYieldProfileID);
879
23
  home = mxFunctionInstanceHome(function);
880
23
  home->value.home.object = resultInstance;
881
23
    resultProperty = fxNextSlotProperty(the, resultProperty, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
882
23
  mxPop();
883
23
    resultProperty = fxNextUndefinedProperty(the, resultProperty, XS_NO_ID, XS_INTERNAL_FLAG);
884
23
    resultProperty = fxNextUndefinedProperty(the, resultProperty, XS_NO_ID, XS_INTERNAL_FLAG);
885
  
886
23
  property->value.disposableStack.stack = C_NULL;
887
23
  property->value.disposableStack.disposed = 1;
888
23
}
889
890
void fx_AsyncDisposableStack_prototype_use(txMachine* the)
891
28
{
892
28
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 1);
893
28
  txSlot* property = instance->next;
894
28
  txSlot* resource;
895
28
  if (mxArgc > 0)
896
6
    mxPushSlot(mxArgv(0));
897
22
  else
898
22
    mxPushUndefined();
899
28
  resource = the->stack;
900
28
  if (!mxIsNull(resource) && !mxIsUndefined(resource)) {
901
6
    mxPushSlot(resource);
902
6
    mxGetID(mxID(_Symbol_asyncDispose));
903
6
    if (!fxIsCallable(the, the->stack)) {
904
6
      mxPop();
905
6
      mxPushSlot(resource);
906
6
      mxGetID(mxID(_Symbol_dispose));
907
6
    }
908
6
    fxAsyncDisposableStackPush(the, property);
909
6
    mxPop();
910
6
  }
911
28
  mxPullSlot(mxResult);
912
28
}
913
914
void fxAsyncDisposableStackPush(txMachine* the, txSlot* property)
915
6
{
916
6
  txSlot* dispose = the->stack;
917
6
  txSlot* resource = dispose + 1;
918
6
  txSlot** address = &property->value.disposableStack.stack;
919
6
  txSlot* slot;
920
6
  if (!fxIsCallable(the, dispose))
921
6
    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