Coverage Report

Created: 2026-03-30 06:33

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-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
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
27.0k
{
74
27.0k
  txSlot* slot;
75
27.0k
  txSlot* prototype;
76
27.0k
  txSlot* instance;
77
27.0k
#if mxExplicitResourceManagement
78
27.0k
  txSlot* property;
79
27.0k
#endif
80
  
81
27.0k
  mxPush(mxObjectPrototype);
82
27.0k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
83
27.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
84
27.0k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_UNKNOWN_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
85
27.0k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
86
27.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_Error_prototype_get_stack), mxCallback(fx_Error_prototype_set_stack), mxID(_stack), XS_DONT_ENUM_FLAG);
87
27.0k
  mxErrorPrototype = *the->stack;
88
27.0k
  prototype = fxBuildHostConstructor(the, mxCallback(fx_Error), 1, mxID(_Error));
89
27.0k
  mxErrorConstructor = *the->stack;
90
27.0k
#if mxErrorIsError
91
27.0k
  slot = fxLastProperty(the, prototype);
92
27.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_isError), 1, mxID(_isError), XS_DONT_ENUM_FLAG);
93
27.0k
#endif
94
27.0k
  mxPop();
95
27.0k
  mxPush(mxErrorPrototype);
96
27.0k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
97
27.0k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_AGGREGATE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
98
27.0k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
99
27.0k
  mxAggregateErrorPrototype = *the->stack;
100
27.0k
  instance = fxBuildHostConstructor(the, mxCallback(fx_AggregateError), 2, mxID(_AggregateError));
101
27.0k
  instance->value.instance.prototype = prototype;
102
27.0k
  mxAggregateErrorConstructor = *the->stack;
103
27.0k
  mxPop();
104
27.0k
  mxPush(mxErrorPrototype);
105
27.0k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
106
27.0k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_EVAL_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
107
27.0k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
108
27.0k
  mxEvalErrorPrototype = *the->stack;
109
27.0k
  instance = fxBuildHostConstructor(the, mxCallback(fx_EvalError), 1, mxID(_EvalError));
110
27.0k
  instance->value.instance.prototype = prototype;
111
27.0k
  mxEvalErrorConstructor = *the->stack;
112
27.0k
  mxPop();
113
27.0k
  mxPush(mxErrorPrototype);
114
27.0k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
115
27.0k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_RANGE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
116
27.0k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
117
27.0k
  mxRangeErrorPrototype = *the->stack;
118
27.0k
  instance = fxBuildHostConstructor(the, mxCallback(fx_RangeError), 1, mxID(_RangeError));
119
27.0k
  instance->value.instance.prototype = prototype;
120
27.0k
  mxRangeErrorConstructor = *the->stack;
121
27.0k
  mxPop();
122
27.0k
  mxPush(mxErrorPrototype);
123
27.0k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
124
27.0k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_REFERENCE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
125
27.0k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
126
27.0k
  mxReferenceErrorPrototype = *the->stack;
127
27.0k
  instance = fxBuildHostConstructor(the, mxCallback(fx_ReferenceError), 1, mxID(_ReferenceError));
128
27.0k
  instance->value.instance.prototype = prototype;
129
27.0k
  mxReferenceErrorConstructor = *the->stack;
130
27.0k
  mxPop();
131
27.0k
  mxPush(mxErrorPrototype);
132
27.0k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
133
27.0k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_SYNTAX_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
134
27.0k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
135
27.0k
  mxSyntaxErrorPrototype = *the->stack;
136
27.0k
  instance = fxBuildHostConstructor(the, mxCallback(fx_SyntaxError), 1, mxID(_SyntaxError));
137
27.0k
  instance->value.instance.prototype = prototype;
138
27.0k
  mxSyntaxErrorConstructor = *the->stack;
139
27.0k
  mxPop();
140
27.0k
  mxPush(mxErrorPrototype);
141
27.0k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
142
27.0k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_TYPE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
143
27.0k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
144
27.0k
  mxTypeErrorPrototype = *the->stack;
145
27.0k
  instance = fxBuildHostConstructor(the, mxCallback(fx_TypeError), 1, mxID(_TypeError));
146
27.0k
  instance->value.instance.prototype = prototype;
147
27.0k
  mxTypeErrorConstructor = *the->stack;
148
27.0k
  mxPop();
149
27.0k
  mxPush(mxErrorPrototype);
150
27.0k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
151
27.0k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_URI_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
152
27.0k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
153
27.0k
  mxURIErrorPrototype = *the->stack;
154
27.0k
  instance = fxBuildHostConstructor(the, mxCallback(fx_URIError), 1, mxID(_URIError));
155
27.0k
  instance->value.instance.prototype = prototype;
156
27.0k
  mxURIErrorConstructor = *the->stack;
157
27.0k
  mxPop();
158
159
27.0k
#if mxExplicitResourceManagement
160
27.0k
  mxPush(mxErrorPrototype);
161
27.0k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
162
27.0k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_SUPPRESSED_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
163
27.0k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
164
27.0k
  mxSuppressedErrorPrototype = *the->stack;
165
27.0k
  instance = fxBuildHostConstructor(the, mxCallback(fx_SuppressedError), 3, mxID(_SuppressedError));
166
27.0k
  instance->value.instance.prototype = prototype;
167
27.0k
  mxSuppressedErrorConstructor = *the->stack;
168
27.0k
  mxPop();
169
170
27.0k
  mxPush(mxObjectPrototype);
171
27.0k
    slot = fxLastProperty(the, fxNewObjectInstance(the));
172
27.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
173
27.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_DisposableStack_prototype_get_disposed), C_NULL, mxID(_disposed), XS_DONT_ENUM_FLAG);
174
27.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_adopt), 2, mxID(_adopt), XS_DONT_ENUM_FLAG);
175
27.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_defer), 1, mxID(_defer), XS_DONT_ENUM_FLAG);
176
27.0k
  property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_dispose), 0, mxID(_dispose), XS_DONT_ENUM_FLAG);
177
27.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_move), 0, mxID(_move), XS_DONT_ENUM_FLAG);
178
27.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_use), 1, mxID(_use), XS_DONT_ENUM_FLAG);
179
27.0k
  slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_dispose), XS_DONT_ENUM_FLAG);
180
27.0k
  slot = fxNextStringXProperty(the, slot, "DisposableStack", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
181
27.0k
  mxDisposableStackPrototype = *the->stack;
182
27.0k
  slot = fxBuildHostConstructor(the, mxCallback(fx_DisposableStack), 0, mxID(_DisposableStack));
183
27.0k
  mxDisposableStackConstructor = *the->stack;
184
27.0k
  mxPop();
185
  
186
27.0k
  mxPush(mxObjectPrototype);
187
27.0k
    slot = fxLastProperty(the, fxNewObjectInstance(the));
188
27.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
189
27.0k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_get_disposed), C_NULL, mxID(_disposed), XS_DONT_ENUM_FLAG);
190
27.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_adopt), 2, mxID(_adopt), XS_DONT_ENUM_FLAG);
191
27.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_defer), 1, mxID(_defer), XS_DONT_ENUM_FLAG);
192
27.0k
  property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_disposeAsync), 0, mxID(_disposeAsync), XS_DONT_ENUM_FLAG);
193
27.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_move), 0, mxID(_move), XS_DONT_ENUM_FLAG);
194
27.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_use), 1, mxID(_use), XS_DONT_ENUM_FLAG);
195
27.0k
  slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_asyncDispose), XS_DONT_ENUM_FLAG);
196
27.0k
  slot = fxNextStringXProperty(the, slot, "AsyncDisposableStack", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
197
27.0k
  mxAsyncDisposableStackPrototype = *the->stack;
198
27.0k
  slot = fxBuildHostConstructor(the, mxCallback(fx_AsyncDisposableStack), 0, mxID(_AsyncDisposableStack));
199
27.0k
  mxAsyncDisposableStackConstructor = *the->stack;
200
27.0k
  mxPop();
201
27.0k
#endif
202
27.0k
}
203
204
void fxCaptureErrorStack(txMachine* the, txSlot* internal, txSlot* frame)
205
1.52M
{
206
1.52M
  txSlot* slot = internal->value.reference = fxNewSlot(the);
207
1.52M
  slot->kind = XS_INSTANCE_KIND;
208
1.52M
  slot->value.instance.garbage = C_NULL;
209
1.52M
  slot->value.instance.prototype = C_NULL;
210
12.7M
  while (frame->next) {
211
11.1M
    txSlot* environment = mxFrameToEnvironment(frame);
212
11.1M
    txSlot* function = frame + 3; 
213
11.1M
    if (function->kind == XS_REFERENCE_KIND) {
214
11.1M
      function = function->value.reference;
215
11.1M
      if (mxIsFunction(function)) {
216
11.1M
        txSlot* name = mxBehaviorGetProperty(the, function, mxID(_name), 0, XS_OWN);
217
11.1M
        slot = slot->next = fxNewSlot(the);
218
11.1M
        slot->flag = XS_GET_ONLY;
219
11.1M
        slot->kind = XS_KEY_KIND;
220
11.1M
        slot->ID = environment->ID;
221
11.1M
        slot->value.key.string = C_NULL;
222
11.1M
        slot->value.key.sum = environment->value.environment.line;
223
11.1M
        if (name && ((name->kind == XS_STRING_KIND) || (name->kind == XS_STRING_X_KIND))) {
224
11.1M
          if (name->kind == XS_STRING_X_KIND)
225
0
            slot->kind = XS_KEY_X_KIND;
226
11.1M
          slot->value.key.string = name->value.string;
227
11.1M
        }
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
11.1M
      }
247
11.1M
    }
248
11.1M
    frame = frame->next;
249
11.1M
  }
250
1.52M
}
251
252
void fx_Error(txMachine* the)
253
40.8k
{
254
40.8k
  fx_Error_aux(the, XS_UNKNOWN_ERROR, 0);
255
40.8k
}
256
257
void fx_Error_isError(txMachine* the)
258
234
{
259
234
  mxResult->kind = XS_BOOLEAN_KIND;
260
234
  mxResult->value.boolean = 0;
261
234
  if (mxArgc > 0) {
262
143
    txSlot* instance = fxGetInstance(the, mxArgv(0));
263
143
    if (instance) {
264
39
      txSlot* internal = instance->next;
265
39
      if (internal && (internal->kind == XS_ERROR_KIND)) {
266
21
        mxResult->value.boolean = 1;
267
21
      }
268
39
    }
269
143
  }
270
234
}
271
272
txSlot* fx_Error_aux(txMachine* the, txError error, txInteger i)
273
326k
{
274
326k
  txSlot* instance;
275
326k
  txSlot* slot;
276
326k
  if (mxIsUndefined(mxTarget))
277
359
    mxPushSlot(mxFunction);
278
325k
  else
279
325k
    mxPushSlot(mxTarget);
280
326k
  fxGetPrototypeFromConstructor(the, &mxErrorPrototypes(error));
281
326k
  instance = fxNewObjectInstance(the);
282
326k
  mxPullSlot(mxResult);
283
326k
  slot = instance->next = fxNewSlot(the);
284
326k
  slot->flag = XS_INTERNAL_FLAG;
285
326k
  slot->kind = XS_ERROR_KIND;
286
326k
  slot->value.error.info = C_NULL;
287
326k
  slot->value.error.which = error;
288
326k
  if (gxDefaults.captureErrorStack)
289
326k
    gxDefaults.captureErrorStack(the, slot, the->frame->next);
290
326k
  if ((mxArgc > i) && (mxArgv(i)->kind != XS_UNDEFINED_KIND)) {
291
317k
    fxToString(the, mxArgv(i));
292
317k
    slot = fxNextSlotProperty(the, slot, mxArgv(i), mxID(_message), XS_DONT_ENUM_FLAG);
293
317k
  }
294
326k
  i++;
295
326k
  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
326k
  return slot;
304
326k
}
305
306
void fx_Error_toString(txMachine* the)
307
223k
{
308
223k
  txSlot* name;
309
223k
  txSlot* message;
310
223k
  if (mxThis->kind != XS_REFERENCE_KIND)
311
9
    mxTypeError("this: not an object");
312
223k
  mxPushSlot(mxThis);
313
223k
  mxGetID(mxID(_name));
314
223k
  if (the->stack->kind == XS_UNDEFINED_KIND) 
315
222k
    fxStringX(the, the->stack, "Error");
316
254
  else  
317
254
    fxToString(the, the->stack);
318
223k
  name = the->stack;
319
223k
  mxPushSlot(mxThis);
320
223k
  mxGetID(mxID(_message));
321
223k
  if (the->stack->kind == XS_UNDEFINED_KIND) 
322
222k
    *the->stack = mxEmptyString;
323
253
  else  
324
253
    fxToString(the, the->stack);
325
223k
  message = the->stack;
326
223k
  if (c_isEmpty(name->value.string))
327
3
    *mxResult = *message;
328
223k
  else if (c_isEmpty(message->value.string))
329
222k
    *mxResult = *name;
330
225
  else {
331
225
    fxStringX(the, mxResult, "");
332
225
    fxConcatString(the, mxResult, name);
333
225
    fxConcatStringC(the, mxResult, ": ");
334
225
    fxConcatString(the, mxResult, message);
335
225
  }
336
223k
  the->stack += 2;
337
223k
}
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
108
{
385
108
  fx_Error_aux(the, XS_RANGE_ERROR, 0);
386
108
}
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
285k
{
395
285k
  fx_Error_aux(the, XS_SYNTAX_ERROR, 0);
396
285k
}
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
7
{
405
7
  fx_Error_aux(the, XS_URI_ERROR, 0);
406
7
}
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
28
{
496
28
  txSlot* property = fx_Error_aux(the, XS_SUPPRESSED_ERROR, 2);
497
28
  property = fxNextSlotProperty(the, property, mxArgv(0), mxID(_error), XS_DONT_ENUM_FLAG);
498
28
  property = fxNextSlotProperty(the, property, mxArgv(1), mxID(_suppressed), XS_DONT_ENUM_FLAG);
499
28
}
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
261
{
506
261
  if (slot->kind == XS_REFERENCE_KIND) {
507
193
    txSlot* instance = slot->value.reference;
508
193
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_DISPOSABLE_STACK_KIND)) {
509
135
      if (mutable && (slot->flag & XS_DONT_SET_FLAG))
510
0
        mxTypeError("this: read-only DisposableStack instance");
511
135
      if (disposable && slot->value.disposableStack.disposed)
512
22
        mxReferenceError("this: disposed DisposableStack instance");
513
113
      return instance;
514
135
    }
515
193
  }
516
261
  mxTypeError("this: not a DisposableStack instance");
517
0
  return C_NULL;
518
261
}
519
520
void fx_DisposableStack(txMachine* the)
521
118k
{
522
118k
  txSlot* instance;
523
118k
  txSlot* property;
524
118k
  if (mxIsUndefined(mxTarget))
525
1
    mxTypeError("call: DisposableStack");
526
118k
  mxPushSlot(mxTarget);
527
118k
  fxGetPrototypeFromConstructor(the, &mxDisposableStackPrototype);
528
118k
  instance = fxNewSlot(the);
529
118k
  instance->kind = XS_INSTANCE_KIND;
530
118k
  instance->value.instance.garbage = C_NULL;
531
118k
  instance->value.instance.prototype = the->stack->value.reference;
532
118k
  the->stack->kind = XS_REFERENCE_KIND;
533
118k
  the->stack->value.reference = instance;
534
118k
  mxPullSlot(mxResult);
535
118k
  property = instance->next = fxNewSlot(the);
536
118k
  property->flag = XS_INTERNAL_FLAG;
537
118k
  property->kind = XS_DISPOSABLE_STACK_KIND;
538
118k
  property->value.disposableStack.stack = C_NULL;
539
118k
  property->value.disposableStack.disposed = 0;
540
118k
}
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
60
{
552
60
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
553
60
  txSlot* property = instance->next;
554
60
  if (mxArgc > 0) 
555
35
    mxPushSlot(mxArgv(0));
556
25
  else
557
25
    mxPushUndefined();
558
60
  if (mxArgc > 1) 
559
34
    mxPushSlot(mxArgv(1));
560
26
  else
561
26
    mxPushUndefined();
562
60
  fxDisposableStackPush(the, property);
563
60
  property->value.disposableStack.stack->flag |= XS_BASE_FLAG;
564
60
  mxPop();
565
60
  mxPullSlot(mxResult);
566
60
}
567
568
void fx_DisposableStack_prototype_defer(txMachine* the)
569
43
{
570
43
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
571
43
  txSlot* property = instance->next;
572
43
  mxPushUndefined();
573
43
  if (mxArgc > 0) 
574
21
    mxPushSlot(mxArgv(0));
575
22
  else
576
22
    mxPushUndefined();
577
43
  fxDisposableStackPush(the, property);
578
43
  mxPop();
579
43
  mxPop();
580
43
}  
581
582
void fx_DisposableStack_prototype_dispose(txMachine* the)
583
47
{
584
47
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 0);
585
47
  txSlot* property = instance->next;
586
47
  txSlot* exception;
587
47
  txBoolean selector = 1;
588
47
  txSlot* slot;
589
47
  if (property->value.disposableStack.disposed)
590
3
    return;
591
44
  property->value.disposableStack.disposed = 1;
592
44
  mxTemporary(exception);
593
44
  slot = property->value.disposableStack.stack;
594
60
  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
44
  if (selector == 0) {
632
3
    mxException.kind = exception->kind;
633
3
    mxException.value = exception->value;
634
3
    fxJump(the);
635
3
  }
636
44
}
637
638
void fx_DisposableStack_prototype_move(txMachine* the)
639
28
{
640
28
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
641
28
  txSlot* property = instance->next;
642
28
  txSlot* resultInstance;
643
28
  txSlot* resultProperty;
644
28
  mxPush(mxDisposableStackConstructor);
645
28
  fxGetPrototypeFromConstructor(the, &mxDisposableStackPrototype);
646
28
  resultInstance = fxNewSlot(the);
647
28
  resultInstance->kind = XS_INSTANCE_KIND;
648
28
  resultInstance->value.instance.garbage = C_NULL;
649
28
  resultInstance->value.instance.prototype = the->stack->value.reference;
650
28
  the->stack->kind = XS_REFERENCE_KIND;
651
28
  the->stack->value.reference = resultInstance;
652
28
  mxPullSlot(mxResult);
653
28
  resultProperty = resultInstance->next = fxNewSlot(the);
654
28
  resultProperty->flag = XS_INTERNAL_FLAG;
655
28
  resultProperty->kind = XS_DISPOSABLE_STACK_KIND;
656
28
  resultProperty->value.disposableStack.stack = property->value.disposableStack.stack;
657
28
  resultProperty->value.disposableStack.disposed = 0;
658
28
  property->value.disposableStack.stack = C_NULL;
659
28
  property->value.disposableStack.disposed = 1;
660
28
}
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
214
{
710
214
  if (slot->kind == XS_REFERENCE_KIND) {
711
160
    txSlot* instance = slot->value.reference;
712
160
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_ASYNC_DISPOSABLE_STACK_KIND)) {
713
116
      if (mutable && (slot->flag & XS_DONT_SET_FLAG))
714
0
        mxTypeError("this: read-only AsyncDisposableStack instance");
715
116
      if (disposable && slot->value.disposableStack.disposed)
716
25
        mxReferenceError("this: disposed AsyncDisposableStack instance");
717
91
      return instance;
718
116
    }
719
160
  }
720
214
  mxTypeError("this: not a AsyncDisposableStack instance");
721
0
  return C_NULL;
722
214
}
723
void fx_AsyncDisposableStack(txMachine* the)
724
222k
{
725
222k
  txSlot* instance;
726
222k
  txSlot* property;
727
222k
  txSlot* function;
728
222k
  txSlot* home;
729
222k
  if (mxIsUndefined(mxTarget))
730
1
    mxTypeError("call: AsyncDisposableStack");
731
222k
  mxPushSlot(mxTarget);
732
222k
  fxGetPrototypeFromConstructor(the, &mxAsyncDisposableStackPrototype);
733
222k
  instance = fxNewSlot(the);
734
222k
  instance->kind = XS_INSTANCE_KIND;
735
222k
  instance->value.instance.garbage = C_NULL;
736
222k
  instance->value.instance.prototype = the->stack->value.reference;
737
222k
  the->stack->kind = XS_REFERENCE_KIND;
738
222k
  the->stack->value.reference = instance;
739
222k
  mxPullSlot(mxResult);
740
222k
  property = instance->next = fxNewSlot(the);
741
222k
  property->flag = XS_INTERNAL_FLAG;
742
222k
  property->kind = XS_ASYNC_DISPOSABLE_STACK_KIND;
743
222k
  property->value.disposableStack.stack = C_NULL;
744
222k
  property->value.disposableStack.disposed = 0;
745
  
746
222k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
747
222k
  function = fxNewHostFunction(the, fxAsyncDisposableStackResolve, 1, XS_NO_ID, mxAsyncGeneratorResolveYieldProfileID);
748
222k
  home = mxFunctionInstanceHome(function);
749
222k
  home->value.home.object = instance;
750
222k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
751
222k
  mxPop();
752
222k
  function = fxNewHostFunction(the, fxAsyncDisposableStackReject, 1, XS_NO_ID, mxAsyncGeneratorRejectYieldProfileID);
753
222k
  home = mxFunctionInstanceHome(function);
754
222k
  home->value.home.object = instance;
755
222k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
756
222k
  mxPop();
757
222k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
758
222k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
759
222k
}
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
58
{
771
58
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 1);
772
58
  txSlot* property = instance->next;
773
58
  if (mxArgc > 0) 
774
36
    mxPushSlot(mxArgv(0));
775
22
  else
776
22
    mxPushUndefined();
777
58
  if (mxArgc > 1) 
778
36
    mxPushSlot(mxArgv(1));
779
22
  else
780
22
    mxPushUndefined();
781
58
  fxAsyncDisposableStackPush(the, property);
782
58
  property->value.disposableStack.stack->flag |= XS_BASE_FLAG;
783
58
  mxPop();
784
58
  mxPullSlot(mxResult);
785
58
}
786
787
void fx_AsyncDisposableStack_prototype_defer(txMachine* the)
788
46
{
789
46
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 1);
790
46
  txSlot* property = instance->next;
791
46
  mxPushUndefined();
792
46
  if (mxArgc > 0) 
793
22
    mxPushSlot(mxArgv(0));
794
24
  else
795
24
    mxPushUndefined();
796
46
  fxAsyncDisposableStackPush(the, property);
797
46
  mxPop();
798
46
  mxPop();
799
46
}  
800
801
void fx_AsyncDisposableStack_prototype_disposeAsync(txMachine* the)
802
9
{
803
9
  txSlot* promise;
804
9
  txSlot* resolveFunction;
805
9
  txSlot* rejectFunction;
806
807
9
  mxPush(mxPromisePrototype);
808
9
  promise = fxNewPromiseInstance(the);
809
9
  mxPullSlot(mxResult);
810
9
  mxPromiseStatus(promise)->value.integer = mxPendingStatus;
811
9
  fxPushPromiseFunctions(the, promise);
812
9
  resolveFunction = the->stack + 1;
813
9
  rejectFunction = the->stack;
814
9
  mxTry(the) {
815
9
    txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 0);
816
9
    txSlot* property = instance->next;
817
9
    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
9
    else {
826
9
      txSlot* exception = property->next;
827
9
      txSlot* resolveStepFunction = exception->next;
828
9
      txSlot* rejectStepFunction = resolveStepFunction->next;
829
9
      property->value.disposableStack.disposed = 1;
830
9
      property = rejectStepFunction->next;
831
9
      property->kind = resolveFunction->kind;
832
9
      property->value = resolveFunction->value;
833
9
      property = property->next;
834
9
      property->kind = rejectFunction->kind;
835
9
      property->value = rejectFunction->value;
836
9
      mxPushUndefined();
837
9
      mxPushSlot(resolveStepFunction);
838
9
      mxCall();
839
9
      mxPushUndefined();
840
9
      mxRunCount(1);
841
9
      mxPop();
842
9
    }
843
9
  }
844
9
  mxCatch(the) {
845
0
    fxRejectException(the, rejectFunction);
846
0
  }
847
9
}
848
849
void fx_AsyncDisposableStack_prototype_move(txMachine* the)
850
26
{
851
26
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 1);
852
26
  txSlot* property = instance->next;
853
26
  txSlot* resultInstance;
854
26
  txSlot* resultProperty;
855
26
  txSlot* function;
856
26
  txSlot* home;
857
26
  mxPush(mxAsyncDisposableStackConstructor);
858
26
  fxGetPrototypeFromConstructor(the, &mxAsyncDisposableStackPrototype);
859
26
  resultInstance = fxNewSlot(the);
860
26
  resultInstance->kind = XS_INSTANCE_KIND;
861
26
  resultInstance->value.instance.garbage = C_NULL;
862
26
  resultInstance->value.instance.prototype = the->stack->value.reference;
863
26
  the->stack->kind = XS_REFERENCE_KIND;
864
26
  the->stack->value.reference = resultInstance;
865
26
  mxPullSlot(mxResult);
866
26
  resultProperty = resultInstance->next = fxNewSlot(the);
867
26
  resultProperty->flag = XS_INTERNAL_FLAG;
868
26
  resultProperty->kind = XS_ASYNC_DISPOSABLE_STACK_KIND;
869
26
  resultProperty->value.disposableStack.stack = property->value.disposableStack.stack;
870
26
  resultProperty->value.disposableStack.disposed = 0;
871
  
872
26
    resultProperty = fxNextUndefinedProperty(the, resultProperty, XS_NO_ID, XS_INTERNAL_FLAG);
873
26
  function = fxNewHostFunction(the, fxAsyncDisposableStackResolve, 1, XS_NO_ID, mxAsyncGeneratorResolveYieldProfileID);
874
26
  home = mxFunctionInstanceHome(function);
875
26
  home->value.home.object = resultInstance;
876
26
    resultProperty = fxNextSlotProperty(the, resultProperty, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
877
26
  mxPop();
878
26
  function = fxNewHostFunction(the, fxAsyncDisposableStackReject, 1, XS_NO_ID, mxAsyncGeneratorRejectYieldProfileID);
879
26
  home = mxFunctionInstanceHome(function);
880
26
  home->value.home.object = resultInstance;
881
26
    resultProperty = fxNextSlotProperty(the, resultProperty, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
882
26
  mxPop();
883
26
    resultProperty = fxNextUndefinedProperty(the, resultProperty, XS_NO_ID, XS_INTERNAL_FLAG);
884
26
    resultProperty = fxNextUndefinedProperty(the, resultProperty, XS_NO_ID, XS_INTERNAL_FLAG);
885
  
886
26
  property->value.disposableStack.stack = C_NULL;
887
26
  property->value.disposableStack.disposed = 1;
888
26
}
889
890
void fx_AsyncDisposableStack_prototype_use(txMachine* the)
891
60
{
892
60
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 1);
893
60
  txSlot* property = instance->next;
894
60
  txSlot* resource;
895
60
  if (mxArgc > 0)
896
16
    mxPushSlot(mxArgv(0));
897
44
  else
898
44
    mxPushUndefined();
899
60
  resource = the->stack;
900
60
  if (!mxIsNull(resource) && !mxIsUndefined(resource)) {
901
13
    mxPushSlot(resource);
902
13
    mxGetID(mxID(_Symbol_asyncDispose));
903
13
    if (!fxIsCallable(the, the->stack)) {
904
10
      mxPop();
905
10
      mxPushSlot(resource);
906
10
      mxGetID(mxID(_Symbol_dispose));
907
10
    }
908
13
    fxAsyncDisposableStackPush(the, property);
909
13
    mxPop();
910
13
  }
911
60
  mxPullSlot(mxResult);
912
60
}
913
914
void fxAsyncDisposableStackPush(txMachine* the, txSlot* property)
915
71
{
916
71
  txSlot* dispose = the->stack;
917
71
  txSlot* resource = dispose + 1;
918
71
  txSlot** address = &property->value.disposableStack.stack;
919
71
  txSlot* slot;
920
71
  if (!fxIsCallable(the, dispose))
921
49
    mxTypeError("dispose: no a function");
922
    
923
22
  slot = fxNewSlot(the);
924
22
  slot->next = *address;
925
22
  slot->kind = resource->kind;
926
22
  slot->value = resource->value;
927
22
  *address = slot;
928
  
929
22
  slot = fxNewSlot(the);
930
22
  slot->next = *address;
931
22
  slot->kind = dispose->kind;
932
22
  slot->value = dispose->value;
933
22
  *address = slot;
934
22
}
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
9
{
960
9
  txSlot* slot = mxFunctionInstanceHome(mxFunction->value.reference);
961
9
  txSlot* instance = slot->value.home.object;
962
9
  txSlot* property = instance->next;
963
9
  txSlot* exception = property->next;
964
9
  txSlot* resolveStepFunction = exception->next;
965
9
  txSlot* rejectStepFunction = resolveStepFunction->next;
966
9
  txSlot* resolveFunction = rejectStepFunction->next;
967
9
  txSlot* rejectFunction = resolveFunction->next;
968
969
9
  slot = property->value.disposableStack.stack;
970
9
  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
9
  else {
1007
9
    if (mxIsUndefined(exception)) {
1008
9
      mxPushUndefined();
1009
9
      mxPushSlot(resolveFunction);
1010
9
      mxCall();
1011
9
      mxPushUndefined();
1012
9
      mxRunCount(1);
1013
9
      mxPop();
1014
9
    }
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
9
  }
1024
9
}
1025
1026
#endif
1027
1028
1029
1030