Coverage Report

Created: 2026-02-26 07:08

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
19.2k
{
74
19.2k
  txSlot* slot;
75
19.2k
  txSlot* prototype;
76
19.2k
  txSlot* instance;
77
19.2k
#if mxExplicitResourceManagement
78
19.2k
  txSlot* property;
79
19.2k
#endif
80
  
81
19.2k
  mxPush(mxObjectPrototype);
82
19.2k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
83
19.2k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
84
19.2k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_UNKNOWN_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
85
19.2k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
86
19.2k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_Error_prototype_get_stack), mxCallback(fx_Error_prototype_set_stack), mxID(_stack), XS_DONT_ENUM_FLAG);
87
19.2k
  mxErrorPrototype = *the->stack;
88
19.2k
  prototype = fxBuildHostConstructor(the, mxCallback(fx_Error), 1, mxID(_Error));
89
19.2k
  mxErrorConstructor = *the->stack;
90
19.2k
#if mxErrorIsError
91
19.2k
  slot = fxLastProperty(the, prototype);
92
19.2k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_isError), 1, mxID(_isError), XS_DONT_ENUM_FLAG);
93
19.2k
#endif
94
19.2k
  mxPop();
95
19.2k
  mxPush(mxErrorPrototype);
96
19.2k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
97
19.2k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_AGGREGATE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
98
19.2k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
99
19.2k
  mxAggregateErrorPrototype = *the->stack;
100
19.2k
  instance = fxBuildHostConstructor(the, mxCallback(fx_AggregateError), 2, mxID(_AggregateError));
101
19.2k
  instance->value.instance.prototype = prototype;
102
19.2k
  mxAggregateErrorConstructor = *the->stack;
103
19.2k
  mxPop();
104
19.2k
  mxPush(mxErrorPrototype);
105
19.2k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
106
19.2k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_EVAL_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
107
19.2k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
108
19.2k
  mxEvalErrorPrototype = *the->stack;
109
19.2k
  instance = fxBuildHostConstructor(the, mxCallback(fx_EvalError), 1, mxID(_EvalError));
110
19.2k
  instance->value.instance.prototype = prototype;
111
19.2k
  mxEvalErrorConstructor = *the->stack;
112
19.2k
  mxPop();
113
19.2k
  mxPush(mxErrorPrototype);
114
19.2k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
115
19.2k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_RANGE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
116
19.2k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
117
19.2k
  mxRangeErrorPrototype = *the->stack;
118
19.2k
  instance = fxBuildHostConstructor(the, mxCallback(fx_RangeError), 1, mxID(_RangeError));
119
19.2k
  instance->value.instance.prototype = prototype;
120
19.2k
  mxRangeErrorConstructor = *the->stack;
121
19.2k
  mxPop();
122
19.2k
  mxPush(mxErrorPrototype);
123
19.2k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
124
19.2k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_REFERENCE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
125
19.2k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
126
19.2k
  mxReferenceErrorPrototype = *the->stack;
127
19.2k
  instance = fxBuildHostConstructor(the, mxCallback(fx_ReferenceError), 1, mxID(_ReferenceError));
128
19.2k
  instance->value.instance.prototype = prototype;
129
19.2k
  mxReferenceErrorConstructor = *the->stack;
130
19.2k
  mxPop();
131
19.2k
  mxPush(mxErrorPrototype);
132
19.2k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
133
19.2k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_SYNTAX_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
134
19.2k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
135
19.2k
  mxSyntaxErrorPrototype = *the->stack;
136
19.2k
  instance = fxBuildHostConstructor(the, mxCallback(fx_SyntaxError), 1, mxID(_SyntaxError));
137
19.2k
  instance->value.instance.prototype = prototype;
138
19.2k
  mxSyntaxErrorConstructor = *the->stack;
139
19.2k
  mxPop();
140
19.2k
  mxPush(mxErrorPrototype);
141
19.2k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
142
19.2k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_TYPE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
143
19.2k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
144
19.2k
  mxTypeErrorPrototype = *the->stack;
145
19.2k
  instance = fxBuildHostConstructor(the, mxCallback(fx_TypeError), 1, mxID(_TypeError));
146
19.2k
  instance->value.instance.prototype = prototype;
147
19.2k
  mxTypeErrorConstructor = *the->stack;
148
19.2k
  mxPop();
149
19.2k
  mxPush(mxErrorPrototype);
150
19.2k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
151
19.2k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_URI_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
152
19.2k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
153
19.2k
  mxURIErrorPrototype = *the->stack;
154
19.2k
  instance = fxBuildHostConstructor(the, mxCallback(fx_URIError), 1, mxID(_URIError));
155
19.2k
  instance->value.instance.prototype = prototype;
156
19.2k
  mxURIErrorConstructor = *the->stack;
157
19.2k
  mxPop();
158
159
19.2k
#if mxExplicitResourceManagement
160
19.2k
  mxPush(mxErrorPrototype);
161
19.2k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
162
19.2k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_SUPPRESSED_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
163
19.2k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
164
19.2k
  mxSuppressedErrorPrototype = *the->stack;
165
19.2k
  instance = fxBuildHostConstructor(the, mxCallback(fx_SuppressedError), 3, mxID(_SuppressedError));
166
19.2k
  instance->value.instance.prototype = prototype;
167
19.2k
  mxSuppressedErrorConstructor = *the->stack;
168
19.2k
  mxPop();
169
170
19.2k
  mxPush(mxObjectPrototype);
171
19.2k
    slot = fxLastProperty(the, fxNewObjectInstance(the));
172
19.2k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
173
19.2k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_DisposableStack_prototype_get_disposed), C_NULL, mxID(_disposed), XS_DONT_ENUM_FLAG);
174
19.2k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_adopt), 2, mxID(_adopt), XS_DONT_ENUM_FLAG);
175
19.2k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_defer), 1, mxID(_defer), XS_DONT_ENUM_FLAG);
176
19.2k
  property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_dispose), 0, mxID(_dispose), XS_DONT_ENUM_FLAG);
177
19.2k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_move), 0, mxID(_move), XS_DONT_ENUM_FLAG);
178
19.2k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_use), 1, mxID(_use), XS_DONT_ENUM_FLAG);
179
19.2k
  slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_dispose), XS_DONT_ENUM_FLAG);
180
19.2k
  slot = fxNextStringXProperty(the, slot, "DisposableStack", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
181
19.2k
  mxDisposableStackPrototype = *the->stack;
182
19.2k
  slot = fxBuildHostConstructor(the, mxCallback(fx_DisposableStack), 0, mxID(_DisposableStack));
183
19.2k
  mxDisposableStackConstructor = *the->stack;
184
19.2k
  mxPop();
185
  
186
19.2k
  mxPush(mxObjectPrototype);
187
19.2k
    slot = fxLastProperty(the, fxNewObjectInstance(the));
188
19.2k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
189
19.2k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_get_disposed), C_NULL, mxID(_disposed), XS_DONT_ENUM_FLAG);
190
19.2k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_adopt), 2, mxID(_adopt), XS_DONT_ENUM_FLAG);
191
19.2k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_defer), 1, mxID(_defer), XS_DONT_ENUM_FLAG);
192
19.2k
  property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_disposeAsync), 0, mxID(_disposeAsync), XS_DONT_ENUM_FLAG);
193
19.2k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_move), 0, mxID(_move), XS_DONT_ENUM_FLAG);
194
19.2k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_use), 1, mxID(_use), XS_DONT_ENUM_FLAG);
195
19.2k
  slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_asyncDispose), XS_DONT_ENUM_FLAG);
196
19.2k
  slot = fxNextStringXProperty(the, slot, "AsyncDisposableStack", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
197
19.2k
  mxAsyncDisposableStackPrototype = *the->stack;
198
19.2k
  slot = fxBuildHostConstructor(the, mxCallback(fx_AsyncDisposableStack), 0, mxID(_AsyncDisposableStack));
199
19.2k
  mxAsyncDisposableStackConstructor = *the->stack;
200
19.2k
  mxPop();
201
19.2k
#endif
202
19.2k
}
203
204
void fxCaptureErrorStack(txMachine* the, txSlot* internal, txSlot* frame)
205
1.60M
{
206
1.60M
  txSlot* slot = internal->value.reference = fxNewSlot(the);
207
1.60M
  slot->kind = XS_INSTANCE_KIND;
208
1.60M
  slot->value.instance.garbage = C_NULL;
209
1.60M
  slot->value.instance.prototype = C_NULL;
210
13.1M
  while (frame->next) {
211
11.5M
    txSlot* environment = mxFrameToEnvironment(frame);
212
11.5M
    txSlot* function = frame + 3; 
213
11.5M
    if (function->kind == XS_REFERENCE_KIND) {
214
11.5M
      function = function->value.reference;
215
11.5M
      if (mxIsFunction(function)) {
216
11.5M
        txSlot* name = mxBehaviorGetProperty(the, function, mxID(_name), 0, XS_OWN);
217
11.5M
        slot = slot->next = fxNewSlot(the);
218
11.5M
        slot->flag = XS_GET_ONLY;
219
11.5M
        slot->kind = XS_KEY_KIND;
220
11.5M
        slot->ID = environment->ID;
221
11.5M
        slot->value.key.string = C_NULL;
222
11.5M
        slot->value.key.sum = environment->value.environment.line;
223
11.5M
        if (name && ((name->kind == XS_STRING_KIND) || (name->kind == XS_STRING_X_KIND))) {
224
11.5M
          if (name->kind == XS_STRING_X_KIND)
225
0
            slot->kind = XS_KEY_X_KIND;
226
11.5M
          slot->value.key.string = name->value.string;
227
11.5M
        }
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.5M
      }
247
11.5M
    }
248
11.5M
    frame = frame->next;
249
11.5M
  }
250
1.60M
}
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
79
{
259
79
  mxResult->kind = XS_BOOLEAN_KIND;
260
79
  mxResult->value.boolean = 0;
261
79
  if (mxArgc > 0) {
262
63
    txSlot* instance = fxGetInstance(the, mxArgv(0));
263
63
    if (instance) {
264
36
      txSlot* internal = instance->next;
265
36
      if (internal && (internal->kind == XS_ERROR_KIND)) {
266
21
        mxResult->value.boolean = 1;
267
21
      }
268
36
    }
269
63
  }
270
79
}
271
272
txSlot* fx_Error_aux(txMachine* the, txError error, txInteger i)
273
273k
{
274
273k
  txSlot* instance;
275
273k
  txSlot* slot;
276
273k
  if (mxIsUndefined(mxTarget))
277
233
    mxPushSlot(mxFunction);
278
273k
  else
279
273k
    mxPushSlot(mxTarget);
280
273k
  fxGetPrototypeFromConstructor(the, &mxErrorPrototypes(error));
281
273k
  instance = fxNewObjectInstance(the);
282
273k
  mxPullSlot(mxResult);
283
273k
  slot = instance->next = fxNewSlot(the);
284
273k
  slot->flag = XS_INTERNAL_FLAG;
285
273k
  slot->kind = XS_ERROR_KIND;
286
273k
  slot->value.error.info = C_NULL;
287
273k
  slot->value.error.which = error;
288
273k
  if (gxDefaults.captureErrorStack)
289
273k
    gxDefaults.captureErrorStack(the, slot, the->frame->next);
290
273k
  if ((mxArgc > i) && (mxArgv(i)->kind != XS_UNDEFINED_KIND)) {
291
265k
    fxToString(the, mxArgv(i));
292
265k
    slot = fxNextSlotProperty(the, slot, mxArgv(i), mxID(_message), XS_DONT_ENUM_FLAG);
293
265k
  }
294
273k
  i++;
295
273k
  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
273k
  return slot;
304
273k
}
305
306
void fx_Error_toString(txMachine* the)
307
37.1k
{
308
37.1k
  txSlot* name;
309
37.1k
  txSlot* message;
310
37.1k
  if (mxThis->kind != XS_REFERENCE_KIND)
311
9
    mxTypeError("this: not an object");
312
37.1k
  mxPushSlot(mxThis);
313
37.1k
  mxGetID(mxID(_name));
314
37.1k
  if (the->stack->kind == XS_UNDEFINED_KIND) 
315
36.9k
    fxStringX(the, the->stack, "Error");
316
120
  else  
317
120
    fxToString(the, the->stack);
318
37.1k
  name = the->stack;
319
37.1k
  mxPushSlot(mxThis);
320
37.1k
  mxGetID(mxID(_message));
321
37.1k
  if (the->stack->kind == XS_UNDEFINED_KIND) 
322
36.9k
    *the->stack = mxEmptyString;
323
121
  else  
324
121
    fxToString(the, the->stack);
325
37.1k
  message = the->stack;
326
37.1k
  if (c_isEmpty(name->value.string))
327
3
    *mxResult = *message;
328
37.1k
  else if (c_isEmpty(message->value.string))
329
37.0k
    *mxResult = *name;
330
94
  else {
331
94
    fxStringX(the, mxResult, "");
332
94
    fxConcatString(the, mxResult, name);
333
94
    fxConcatStringC(the, mxResult, ": ");
334
94
    fxConcatString(the, mxResult, message);
335
94
  }
336
37.1k
  the->stack += 2;
337
37.1k
}
338
339
void fx_AggregateError(txMachine* the)
340
45
{
341
45
  txSlot* stack = the->stack;
342
45
  txSlot* property = fx_Error_aux(the, XS_AGGREGATE_ERROR, 1);
343
45
  txSlot* array;
344
45
  txSlot** address;
345
45
  txIndex length = 0;
346
45
  txSlot* iterator;
347
45
  txSlot* next;
348
45
  txSlot* value;
349
45
  txSlot* slot;
350
  
351
45
  mxPush(mxArrayPrototype);
352
45
  array = fxNewArrayInstance(the);
353
45
  fxNextSlotProperty(the, property, the->stack, mxID(_errors), XS_DONT_ENUM_FLAG);
354
45
  address = &array->next->next;
355
45
  mxTemporary(iterator);
356
45
  mxTemporary(next);
357
45
  fxGetIterator(the, mxArgv(0), iterator, next, 0);
358
45
  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
45
  array->next->value.array.length = length;
373
45
  fxCacheArray(the, array);
374
  
375
45
  the->stack = stack;
376
45
}
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
78
{
385
78
  fx_Error_aux(the, XS_RANGE_ERROR, 0);
386
78
}
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
232k
{
395
232k
  fx_Error_aux(the, XS_SYNTAX_ERROR, 0);
396
232k
}
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
243
{
506
243
  if (slot->kind == XS_REFERENCE_KIND) {
507
177
    txSlot* instance = slot->value.reference;
508
177
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_DISPOSABLE_STACK_KIND)) {
509
126
      if (mutable && (slot->flag & XS_DONT_SET_FLAG))
510
0
        mxTypeError("this: read-only DisposableStack instance");
511
126
      if (disposable && slot->value.disposableStack.disposed)
512
16
        mxReferenceError("this: disposed DisposableStack instance");
513
110
      return instance;
514
126
    }
515
177
  }
516
243
  mxTypeError("this: not a DisposableStack instance");
517
0
  return C_NULL;
518
243
}
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
17
{
544
17
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 0, 0);
545
17
  txSlot* property = instance->next;
546
17
  mxResult->value.boolean = property->value.disposableStack.disposed;
547
17
  mxResult->kind = XS_BOOLEAN_KIND;
548
17
}
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
43
{
584
43
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 0);
585
43
  txSlot* property = instance->next;
586
43
  txSlot* exception;
587
43
  txBoolean selector = 1;
588
43
  txSlot* slot;
589
43
  if (property->value.disposableStack.disposed)
590
3
    return;
591
40
  property->value.disposableStack.disposed = 1;
592
40
  mxTemporary(exception);
593
40
  slot = property->value.disposableStack.stack;
594
56
  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
40
  if (selector == 0) {
632
3
    mxException.kind = exception->kind;
633
3
    mxException.value = exception->value;
634
3
    fxJump(the);
635
3
  }
636
40
}
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
58
{
664
58
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
665
58
  txSlot* property = instance->next;
666
58
  txSlot* resource;
667
58
  if (mxArgc > 0)
668
21
    mxPushSlot(mxArgv(0));
669
37
  else
670
37
    mxPushUndefined();
671
58
  resource = the->stack;
672
58
  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
58
  mxPullSlot(mxResult);
679
58
}
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
37.0k
{
725
37.0k
  txSlot* instance;
726
37.0k
  txSlot* property;
727
37.0k
  txSlot* function;
728
37.0k
  txSlot* home;
729
37.0k
  if (mxIsUndefined(mxTarget))
730
1
    mxTypeError("call: AsyncDisposableStack");
731
37.0k
  mxPushSlot(mxTarget);
732
37.0k
  fxGetPrototypeFromConstructor(the, &mxAsyncDisposableStackPrototype);
733
37.0k
  instance = fxNewSlot(the);
734
37.0k
  instance->kind = XS_INSTANCE_KIND;
735
37.0k
  instance->value.instance.garbage = C_NULL;
736
37.0k
  instance->value.instance.prototype = the->stack->value.reference;
737
37.0k
  the->stack->kind = XS_REFERENCE_KIND;
738
37.0k
  the->stack->value.reference = instance;
739
37.0k
  mxPullSlot(mxResult);
740
37.0k
  property = instance->next = fxNewSlot(the);
741
37.0k
  property->flag = XS_INTERNAL_FLAG;
742
37.0k
  property->kind = XS_ASYNC_DISPOSABLE_STACK_KIND;
743
37.0k
  property->value.disposableStack.stack = C_NULL;
744
37.0k
  property->value.disposableStack.disposed = 0;
745
  
746
37.0k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
747
37.0k
  function = fxNewHostFunction(the, fxAsyncDisposableStackResolve, 1, XS_NO_ID, mxAsyncGeneratorResolveYieldProfileID);
748
37.0k
  home = mxFunctionInstanceHome(function);
749
37.0k
  home->value.home.object = instance;
750
37.0k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
751
37.0k
  mxPop();
752
37.0k
  function = fxNewHostFunction(the, fxAsyncDisposableStackReject, 1, XS_NO_ID, mxAsyncGeneratorRejectYieldProfileID);
753
37.0k
  home = mxFunctionInstanceHome(function);
754
37.0k
  home->value.home.object = instance;
755
37.0k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
756
37.0k
  mxPop();
757
37.0k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
758
37.0k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
759
37.0k
}
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