Coverage Report

Created: 2025-06-13 06:17

/src/moddable/xs/sources/xsError.c
Line
Count
Source (jump to first uncovered line)
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
35.3k
{
74
35.3k
  txSlot* slot;
75
35.3k
  txSlot* prototype;
76
35.3k
  txSlot* instance;
77
35.3k
#if mxExplicitResourceManagement
78
35.3k
  txSlot* property;
79
35.3k
#endif
80
  
81
35.3k
  mxPush(mxObjectPrototype);
82
35.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
83
35.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
84
35.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_UNKNOWN_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
85
35.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
86
35.3k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_Error_prototype_get_stack), mxCallback(fx_Error_prototype_set_stack), mxID(_stack), XS_DONT_ENUM_FLAG);
87
35.3k
  mxErrorPrototype = *the->stack;
88
35.3k
  prototype = fxBuildHostConstructor(the, mxCallback(fx_Error), 1, mxID(_Error));
89
35.3k
  mxErrorConstructor = *the->stack;
90
35.3k
#if mxErrorIsError
91
35.3k
  slot = fxLastProperty(the, prototype);
92
35.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_isError), 1, mxID(_isError), XS_DONT_ENUM_FLAG);
93
35.3k
#endif
94
35.3k
  mxPop();
95
35.3k
  mxPush(mxErrorPrototype);
96
35.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
97
35.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_AGGREGATE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
98
35.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
99
35.3k
  mxAggregateErrorPrototype = *the->stack;
100
35.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_AggregateError), 2, mxID(_AggregateError));
101
35.3k
  instance->value.instance.prototype = prototype;
102
35.3k
  mxAggregateErrorConstructor = *the->stack;
103
35.3k
  mxPop();
104
35.3k
  mxPush(mxErrorPrototype);
105
35.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
106
35.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_EVAL_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
107
35.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
108
35.3k
  mxEvalErrorPrototype = *the->stack;
109
35.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_EvalError), 1, mxID(_EvalError));
110
35.3k
  instance->value.instance.prototype = prototype;
111
35.3k
  mxEvalErrorConstructor = *the->stack;
112
35.3k
  mxPop();
113
35.3k
  mxPush(mxErrorPrototype);
114
35.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
115
35.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_RANGE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
116
35.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
117
35.3k
  mxRangeErrorPrototype = *the->stack;
118
35.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_RangeError), 1, mxID(_RangeError));
119
35.3k
  instance->value.instance.prototype = prototype;
120
35.3k
  mxRangeErrorConstructor = *the->stack;
121
35.3k
  mxPop();
122
35.3k
  mxPush(mxErrorPrototype);
123
35.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
124
35.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_REFERENCE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
125
35.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
126
35.3k
  mxReferenceErrorPrototype = *the->stack;
127
35.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_ReferenceError), 1, mxID(_ReferenceError));
128
35.3k
  instance->value.instance.prototype = prototype;
129
35.3k
  mxReferenceErrorConstructor = *the->stack;
130
35.3k
  mxPop();
131
35.3k
  mxPush(mxErrorPrototype);
132
35.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
133
35.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_SYNTAX_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
134
35.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
135
35.3k
  mxSyntaxErrorPrototype = *the->stack;
136
35.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_SyntaxError), 1, mxID(_SyntaxError));
137
35.3k
  instance->value.instance.prototype = prototype;
138
35.3k
  mxSyntaxErrorConstructor = *the->stack;
139
35.3k
  mxPop();
140
35.3k
  mxPush(mxErrorPrototype);
141
35.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
142
35.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_TYPE_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
143
35.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
144
35.3k
  mxTypeErrorPrototype = *the->stack;
145
35.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_TypeError), 1, mxID(_TypeError));
146
35.3k
  instance->value.instance.prototype = prototype;
147
35.3k
  mxTypeErrorConstructor = *the->stack;
148
35.3k
  mxPop();
149
35.3k
  mxPush(mxErrorPrototype);
150
35.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
151
35.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_URI_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
152
35.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
153
35.3k
  mxURIErrorPrototype = *the->stack;
154
35.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_URIError), 1, mxID(_URIError));
155
35.3k
  instance->value.instance.prototype = prototype;
156
35.3k
  mxURIErrorConstructor = *the->stack;
157
35.3k
  mxPop();
158
159
35.3k
#if mxExplicitResourceManagement
160
35.3k
  mxPush(mxErrorPrototype);
161
35.3k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
162
35.3k
  slot = fxNextStringXProperty(the, slot, (txString)gxErrorNames[XS_SUPPRESSED_ERROR], mxID(_name), XS_DONT_ENUM_FLAG);
163
35.3k
  slot = fxNextStringXProperty(the, slot, "", mxID(_message), XS_DONT_ENUM_FLAG);
164
35.3k
  mxSuppressedErrorPrototype = *the->stack;
165
35.3k
  instance = fxBuildHostConstructor(the, mxCallback(fx_SuppressedError), 3, mxID(_SuppressedError));
166
35.3k
  instance->value.instance.prototype = prototype;
167
35.3k
  mxSuppressedErrorConstructor = *the->stack;
168
35.3k
  mxPop();
169
170
35.3k
  mxPush(mxObjectPrototype);
171
35.3k
    slot = fxLastProperty(the, fxNewObjectInstance(the));
172
35.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
173
35.3k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_DisposableStack_prototype_get_disposed), C_NULL, mxID(_disposed), XS_DONT_ENUM_FLAG);
174
35.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_adopt), 2, mxID(_adopt), XS_DONT_ENUM_FLAG);
175
35.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_defer), 1, mxID(_defer), XS_DONT_ENUM_FLAG);
176
35.3k
  property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_dispose), 0, mxID(_dispose), XS_DONT_ENUM_FLAG);
177
35.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_move), 0, mxID(_move), XS_DONT_ENUM_FLAG);
178
35.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_DisposableStack_prototype_use), 1, mxID(_use), XS_DONT_ENUM_FLAG);
179
35.3k
  slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_dispose), XS_DONT_ENUM_FLAG);
180
35.3k
  slot = fxNextStringXProperty(the, slot, "DisposableStack", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
181
35.3k
  mxDisposableStackPrototype = *the->stack;
182
35.3k
  slot = fxBuildHostConstructor(the, mxCallback(fx_DisposableStack), 0, mxID(_DisposableStack));
183
35.3k
  mxDisposableStackConstructor = *the->stack;
184
35.3k
  mxPop();
185
  
186
35.3k
  mxPush(mxObjectPrototype);
187
35.3k
    slot = fxLastProperty(the, fxNewObjectInstance(the));
188
35.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Error_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
189
35.3k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_get_disposed), C_NULL, mxID(_disposed), XS_DONT_ENUM_FLAG);
190
35.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_adopt), 2, mxID(_adopt), XS_DONT_ENUM_FLAG);
191
35.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_defer), 1, mxID(_defer), XS_DONT_ENUM_FLAG);
192
35.3k
  property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_disposeAsync), 0, mxID(_disposeAsync), XS_DONT_ENUM_FLAG);
193
35.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_move), 0, mxID(_move), XS_DONT_ENUM_FLAG);
194
35.3k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_AsyncDisposableStack_prototype_use), 1, mxID(_use), XS_DONT_ENUM_FLAG);
195
35.3k
  slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_asyncDispose), XS_DONT_ENUM_FLAG);
196
35.3k
  slot = fxNextStringXProperty(the, slot, "AsyncDisposableStack", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
197
35.3k
  mxAsyncDisposableStackPrototype = *the->stack;
198
35.3k
  slot = fxBuildHostConstructor(the, mxCallback(fx_AsyncDisposableStack), 0, mxID(_AsyncDisposableStack));
199
35.3k
  mxAsyncDisposableStackConstructor = *the->stack;
200
35.3k
  mxPop();
201
35.3k
#endif
202
35.3k
}
203
204
void fxCaptureErrorStack(txMachine* the, txSlot* internal, txSlot* frame)
205
2.70M
{
206
2.70M
  txSlot* slot = internal->value.reference = fxNewSlot(the);
207
2.70M
  slot->kind = XS_INSTANCE_KIND;
208
2.70M
  slot->value.instance.garbage = C_NULL;
209
2.70M
  slot->value.instance.prototype = C_NULL;
210
14.8M
  while (frame->next) {
211
12.1M
    txSlot* environment = mxFrameToEnvironment(frame);
212
12.1M
    txSlot* function = frame + 3; 
213
12.1M
    if (function->kind == XS_REFERENCE_KIND) {
214
11.9M
      function = function->value.reference;
215
11.9M
      if (mxIsFunction(function)) {
216
11.9M
        txSlot* name = mxBehaviorGetProperty(the, function, mxID(_name), 0, XS_OWN);
217
11.9M
        slot = slot->next = fxNewSlot(the);
218
11.9M
        slot->flag = XS_GET_ONLY;
219
11.9M
        slot->kind = XS_KEY_KIND;
220
11.9M
        slot->ID = environment->ID;
221
11.9M
        slot->value.key.string = C_NULL;
222
11.9M
        slot->value.key.sum = environment->value.environment.line;
223
11.9M
        if (name && ((name->kind == XS_STRING_KIND) || (name->kind == XS_STRING_X_KIND))) {
224
11.9M
          if (name->kind == XS_STRING_X_KIND)
225
0
            slot->kind = XS_KEY_X_KIND;
226
11.9M
          slot->value.key.string = name->value.string;
227
11.9M
        }
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.9M
      }
247
11.9M
    }
248
12.1M
    frame = frame->next;
249
12.1M
  }
250
2.70M
}
251
252
void fx_Error(txMachine* the)
253
300
{
254
300
  fx_Error_aux(the, XS_UNKNOWN_ERROR, 0);
255
300
}
256
257
void fx_Error_isError(txMachine* the)
258
93
{
259
93
  mxResult->kind = XS_BOOLEAN_KIND;
260
93
  mxResult->value.boolean = 0;
261
93
  if (mxArgc > 0) {
262
91
    txSlot* instance = fxGetInstance(the, mxArgv(0));
263
91
    if (instance) {
264
58
      txSlot* internal = instance->next;
265
58
      if (internal && (internal->kind == XS_ERROR_KIND)) {
266
30
        mxResult->value.boolean = 1;
267
30
      }
268
58
    }
269
91
  }
270
93
}
271
272
txSlot* fx_Error_aux(txMachine* the, txError error, txInteger i)
273
630k
{
274
630k
  txSlot* instance;
275
630k
  txSlot* slot;
276
630k
  if (mxIsUndefined(mxTarget))
277
90
    mxPushSlot(mxFunction);
278
630k
  else
279
630k
    mxPushSlot(mxTarget);
280
630k
  fxGetPrototypeFromConstructor(the, &mxErrorPrototypes(error));
281
630k
  instance = fxNewObjectInstance(the);
282
630k
  mxPullSlot(mxResult);
283
630k
  slot = instance->next = fxNewSlot(the);
284
630k
  slot->flag = XS_INTERNAL_FLAG;
285
630k
  slot->kind = XS_ERROR_KIND;
286
630k
  slot->value.error.info = C_NULL;
287
630k
  slot->value.error.which = error;
288
630k
  if (gxDefaults.captureErrorStack)
289
630k
    gxDefaults.captureErrorStack(the, slot, the->frame->next);
290
630k
  if ((mxArgc > i) && (mxArgv(i)->kind != XS_UNDEFINED_KIND)) {
291
629k
    fxToString(the, mxArgv(i));
292
629k
    slot = fxNextSlotProperty(the, slot, mxArgv(i), mxID(_message), XS_DONT_ENUM_FLAG);
293
629k
  }
294
630k
  i++;
295
630k
  if ((mxArgc > i) && (mxArgv(i)->kind == XS_REFERENCE_KIND)) {
296
2
    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
2
  }
303
630k
  return slot;
304
630k
}
305
306
void fx_Error_toString(txMachine* the)
307
344k
{
308
344k
  txSlot* name;
309
344k
  txSlot* message;
310
344k
  if (mxThis->kind != XS_REFERENCE_KIND)
311
7
    mxTypeError("this: not an object");
312
344k
  mxPushSlot(mxThis);
313
344k
  mxGetID(mxID(_name));
314
344k
  if (the->stack->kind == XS_UNDEFINED_KIND) 
315
343k
    fxStringX(the, the->stack, "Error");
316
813
  else  
317
813
    fxToString(the, the->stack);
318
344k
  name = the->stack;
319
344k
  mxPushSlot(mxThis);
320
344k
  mxGetID(mxID(_message));
321
344k
  if (the->stack->kind == XS_UNDEFINED_KIND) 
322
343k
    *the->stack = mxEmptyString;
323
816
  else  
324
816
    fxToString(the, the->stack);
325
344k
  message = the->stack;
326
344k
  if (c_isEmpty(name->value.string))
327
3
    *mxResult = *message;
328
344k
  else if (c_isEmpty(message->value.string))
329
344k
    *mxResult = *name;
330
19
  else {
331
19
    fxStringX(the, mxResult, "");
332
19
    fxConcatString(the, mxResult, name);
333
19
    fxConcatStringC(the, mxResult, ": ");
334
19
    fxConcatString(the, mxResult, message);
335
19
  }
336
344k
  the->stack += 2;
337
344k
}
338
339
void fx_AggregateError(txMachine* the)
340
538
{
341
538
  txSlot* stack = the->stack;
342
538
  txSlot* property = fx_Error_aux(the, XS_AGGREGATE_ERROR, 1);
343
538
  txSlot* array;
344
538
  txSlot** address;
345
538
  txIndex length = 0;
346
538
  txSlot* iterator;
347
538
  txSlot* next;
348
538
  txSlot* value;
349
538
  txSlot* slot;
350
  
351
538
  mxPush(mxArrayPrototype);
352
538
  array = fxNewArrayInstance(the);
353
538
  fxNextSlotProperty(the, property, the->stack, mxID(_errors), XS_DONT_ENUM_FLAG);
354
538
  address = &array->next->next;
355
538
  mxTemporary(iterator);
356
538
  mxTemporary(next);
357
538
  fxGetIterator(the, mxArgv(0), iterator, next, 0);
358
538
  mxTemporary(value);
359
78.6k
  while (fxIteratorNext(the, iterator, next, value)) {
360
78.0k
    mxTry(the) {
361
78.0k
      *address = slot = fxNewSlot(the);
362
78.0k
      slot->kind = value->kind;
363
78.0k
      slot->value = value->value;
364
78.0k
      address = &slot->next;
365
78.0k
      length++;
366
78.0k
    }
367
78.0k
    mxCatch(the) {
368
0
      fxIteratorReturn(the, iterator, 1);
369
0
      fxJump(the);
370
0
    }
371
78.0k
  }
372
538
  array->next->value.array.length = length;
373
538
  fxCacheArray(the, array);
374
  
375
538
  the->stack = stack;
376
538
}
377
378
void fx_EvalError(txMachine* the)
379
11
{
380
11
  fx_Error_aux(the, XS_EVAL_ERROR, 0);
381
11
}
382
383
void fx_RangeError(txMachine* the)
384
76
{
385
76
  fx_Error_aux(the, XS_RANGE_ERROR, 0);
386
76
}
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
629k
{
395
629k
  fx_Error_aux(the, XS_SYNTAX_ERROR, 0);
396
629k
}
397
398
void fx_TypeError(txMachine* the)
399
4
{
400
4
  fx_Error_aux(the, XS_TYPE_ERROR, 0);
401
4
}
402
403
void fx_URIError(txMachine* the)
404
4
{
405
4
  fx_Error_aux(the, XS_URI_ERROR, 0);
406
4
}
407
408
void fx_Error_prototype_get_stack(txMachine* the)
409
2
{
410
2
  txSlot* slot;
411
2
  if (mxThis->kind != XS_REFERENCE_KIND)
412
0
    mxTypeError("this: not an object");
413
2
  slot = mxThis->value.reference->next;
414
2
  if (slot && (slot->kind == XS_ERROR_KIND)) {
415
1
    fxStringX(the, mxResult, "");
416
1
    mxPushSlot(mxThis);
417
1
    mxGetID(mxID(_name));
418
1
    if (the->stack->kind != XS_UNDEFINED_KIND)  {
419
1
      fxToString(the, the->stack);
420
1
      fxConcatString(the, mxResult, the->stack);
421
1
    }
422
0
    else
423
0
      fxConcatStringC(the, mxResult, "Error");
424
1
    mxPop();
425
1
    mxPushSlot(mxThis);
426
1
    mxGetID(mxID(_message));
427
1
    if (the->stack->kind != XS_UNDEFINED_KIND) {
428
1
      fxToString(the, the->stack);
429
1
      if (!c_isEmpty(the->stack->value.string)) {
430
0
        fxConcatStringC(the, mxResult, ": ");
431
0
        fxConcatString(the, mxResult, the->stack);
432
0
      }
433
1
    }
434
1
    mxPop();
435
1
    slot = slot->value.reference;
436
1
    if (slot) {
437
1
      slot = slot->next;
438
2
      while (slot) {
439
1
        fxConcatStringC(the, mxResult, "\n at");
440
1
        if ((slot->value.key.string != C_NULL) && (mxStringLength(slot->value.key.string))) {
441
0
          fxConcatStringC(the, mxResult, " ");
442
0
          fxConcatString(the, mxResult, slot);
443
0
        }
444
1
        fxConcatStringC(the, mxResult, " (");
445
1
        if (slot->ID != XS_NO_ID) {
446
1
          fxIDToString(the, slot->ID, the->nameBuffer, sizeof(the->nameBuffer));
447
1
          fxConcatStringC(the, mxResult, the->nameBuffer);
448
1
          fxConcatStringC(the, mxResult, ":");
449
1
          fxIntegerToString(the, (txInteger)slot->value.key.sum, the->nameBuffer, sizeof(the->nameBuffer));
450
1
          fxConcatStringC(the, mxResult, the->nameBuffer);
451
1
        }
452
1
        fxConcatStringC(the, mxResult, ")");
453
1
        slot = slot->next;
454
1
      }
455
1
    }
456
1
  }
457
2
}
458
459
void fx_Error_prototype_set_stack(txMachine* the)
460
0
{
461
0
  if (mxThis->kind != XS_REFERENCE_KIND)
462
0
    mxTypeError("this: not an object");
463
0
  if (mxArgc < 1)
464
0
    mxTypeError("no value");
465
0
  mxPushSlot(mxArgv(0));
466
0
  mxPushSlot(mxThis);
467
0
  mxDefineID(mxID(_stack), XS_NO_FLAG, XS_GET_ONLY);
468
0
  mxPop();
469
0
}
470
471
static const txString gXSAbortStrings[] = {
472
  "debugger",
473
  "memory full",
474
  "JavaScript stack overflow",
475
  "fatal",
476
  "dead strip",
477
  "unhandled exception",
478
  "not enough keys",
479
  "too much computation",
480
  "unhandled rejection",
481
  "native stack overflow",
482
};
483
484
txString fxAbortString(int status)
485
0
{
486
0
  if ((status < 0) || (status >= (int)(sizeof(gXSAbortStrings) / sizeof(txString))))
487
0
    return "unknown";
488
489
0
  return gXSAbortStrings[status];
490
0
}
491
492
#if mxExplicitResourceManagement
493
494
void fx_SuppressedError(txMachine* the)
495
46
{
496
46
  txSlot* property = fx_Error_aux(the, XS_SUPPRESSED_ERROR, 2);
497
46
  property = fxNextSlotProperty(the, property, mxArgv(0), mxID(_error), XS_DONT_ENUM_FLAG);
498
46
  property = fxNextSlotProperty(the, property, mxArgv(1), mxID(_suppressed), XS_DONT_ENUM_FLAG);
499
46
}
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
298
{
506
298
  if (slot->kind == XS_REFERENCE_KIND) {
507
222
    txSlot* instance = slot->value.reference;
508
222
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_DISPOSABLE_STACK_KIND)) {
509
165
      if (mutable && (slot->flag & XS_DONT_SET_FLAG))
510
0
        mxTypeError("this: read-only DisposableStack instance");
511
165
      if (disposable && slot->value.disposableStack.disposed)
512
20
        mxReferenceError("this: disposed DisposableStack instance");
513
145
      return instance;
514
165
    }
515
222
  }
516
298
  mxTypeError("this: not a DisposableStack instance");
517
0
  return C_NULL;
518
298
}
519
520
void fx_DisposableStack(txMachine* the)
521
132k
{
522
132k
  txSlot* instance;
523
132k
  txSlot* property;
524
132k
  if (mxIsUndefined(mxTarget))
525
1
    mxTypeError("call: DisposableStack");
526
132k
  mxPushSlot(mxTarget);
527
132k
  fxGetPrototypeFromConstructor(the, &mxDisposableStackPrototype);
528
132k
  instance = fxNewSlot(the);
529
132k
  instance->kind = XS_INSTANCE_KIND;
530
132k
  instance->value.instance.garbage = C_NULL;
531
132k
  instance->value.instance.prototype = the->stack->value.reference;
532
132k
  the->stack->kind = XS_REFERENCE_KIND;
533
132k
  the->stack->value.reference = instance;
534
132k
  mxPullSlot(mxResult);
535
132k
  property = instance->next = fxNewSlot(the);
536
132k
  property->flag = XS_INTERNAL_FLAG;
537
132k
  property->kind = XS_DISPOSABLE_STACK_KIND;
538
132k
  property->value.disposableStack.stack = C_NULL;
539
132k
  property->value.disposableStack.disposed = 0;
540
132k
}
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
64
{
552
64
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
553
64
  txSlot* property = instance->next;
554
64
  if (mxArgc > 0) 
555
39
    mxPushSlot(mxArgv(0));
556
25
  else
557
25
    mxPushUndefined();
558
64
  if (mxArgc > 1) 
559
38
    mxPushSlot(mxArgv(1));
560
26
  else
561
26
    mxPushUndefined();
562
64
  fxDisposableStackPush(the, property);
563
64
  property->value.disposableStack.stack->flag |= XS_BASE_FLAG;
564
64
  mxPop();
565
64
  mxPullSlot(mxResult);
566
64
}
567
568
void fx_DisposableStack_prototype_defer(txMachine* the)
569
64
{
570
64
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
571
64
  txSlot* property = instance->next;
572
64
  mxPushUndefined();
573
64
  if (mxArgc > 0) 
574
42
    mxPushSlot(mxArgv(0));
575
22
  else
576
22
    mxPushUndefined();
577
64
  fxDisposableStackPush(the, property);
578
64
  mxPop();
579
64
  mxPop();
580
64
}  
581
582
void fx_DisposableStack_prototype_dispose(txMachine* the)
583
46
{
584
46
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 0);
585
46
  txSlot* property = instance->next;
586
46
  txSlot* exception;
587
46
  txBoolean selector = 1;
588
46
  txSlot* slot;
589
46
  if (property->value.disposableStack.disposed)
590
4
    return;
591
42
  property->value.disposableStack.disposed = 1;
592
42
  mxTemporary(exception);
593
42
  slot = property->value.disposableStack.stack;
594
68
  while (slot) {
595
26
    txSlot* dispose = slot;
596
26
    txSlot* resource = slot->next;
597
26
    mxTry(the) {
598
26
      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
22
      else {
607
22
        mxPushSlot(resource);
608
22
        mxPushSlot(dispose);
609
22
        mxCall();
610
22
        mxRunCount(0);
611
22
        mxPop();
612
22
      }
613
26
    }
614
26
    mxCatch(the) {
615
14
      if (selector == 0) {
616
9
        mxPush(mxSuppressedErrorConstructor);
617
9
        mxNew();
618
9
        mxPush(mxException);
619
9
        mxPushSlot(exception);
620
9
        mxRunCount(2);
621
9
        mxPullSlot(exception);
622
9
      }
623
5
      else {
624
5
        *exception = mxException;
625
5
        selector = 0;
626
5
      }
627
14
      mxException = mxUndefined;
628
14
    }
629
26
    slot = resource->next;
630
26
  }
631
42
  if (selector == 0) {
632
5
    mxException.kind = exception->kind;
633
5
    mxException.value = exception->value;
634
5
    fxJump(the);
635
5
  }
636
42
}
637
638
void fx_DisposableStack_prototype_move(txMachine* the)
639
31
{
640
31
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
641
31
  txSlot* property = instance->next;
642
31
  txSlot* resultInstance;
643
31
  txSlot* resultProperty;
644
31
  mxPush(mxDisposableStackConstructor);
645
31
  fxGetPrototypeFromConstructor(the, &mxDisposableStackPrototype);
646
31
  resultInstance = fxNewSlot(the);
647
31
  resultInstance->kind = XS_INSTANCE_KIND;
648
31
  resultInstance->value.instance.garbage = C_NULL;
649
31
  resultInstance->value.instance.prototype = the->stack->value.reference;
650
31
  the->stack->kind = XS_REFERENCE_KIND;
651
31
  the->stack->value.reference = resultInstance;
652
31
  mxPullSlot(mxResult);
653
31
  resultProperty = resultInstance->next = fxNewSlot(the);
654
31
  resultProperty->flag = XS_INTERNAL_FLAG;
655
31
  resultProperty->kind = XS_DISPOSABLE_STACK_KIND;
656
31
  resultProperty->value.disposableStack.stack = property->value.disposableStack.stack;
657
31
  resultProperty->value.disposableStack.disposed = 0;
658
31
  property->value.disposableStack.stack = C_NULL;
659
31
  property->value.disposableStack.disposed = 1;
660
31
}
661
662
void fx_DisposableStack_prototype_use(txMachine* the)
663
75
{
664
75
  txSlot* instance = fxCheckDisposableStackInstance(the, mxThis, 1, 1);
665
75
  txSlot* property = instance->next;
666
75
  txSlot* resource;
667
75
  if (mxArgc > 0)
668
31
    mxPushSlot(mxArgv(0));
669
44
  else
670
44
    mxPushUndefined();
671
75
  resource = the->stack;
672
75
  if (!mxIsNull(resource) && !mxIsUndefined(resource)) {
673
24
    mxPushSlot(resource);
674
24
    mxGetID(mxID(_Symbol_dispose));
675
24
    fxDisposableStackPush(the, property);
676
24
    mxPop();
677
24
  }
678
75
  mxPullSlot(mxResult);
679
75
}
680
681
void fxDisposableStackPush(txMachine* the, txSlot* property)
682
105
{
683
105
  txSlot* dispose = the->stack;
684
105
  txSlot* resource = dispose + 1;
685
105
  txSlot** address = &property->value.disposableStack.stack;
686
105
  txSlot* slot;
687
105
  if (!fxIsCallable(the, dispose))
688
59
    mxTypeError("dispose: not a function");
689
    
690
46
  slot = fxNewSlot(the);
691
46
  slot->next = *address;
692
46
  slot->kind = resource->kind;
693
46
  slot->value = resource->value;
694
46
  *address = slot;
695
  
696
46
  slot = fxNewSlot(the);
697
46
  slot->next = *address;
698
46
  slot->kind = dispose->kind;
699
46
  slot->value = dispose->value;
700
46
  *address = slot;
701
46
}
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
129
{
710
129
  if (slot->kind == XS_REFERENCE_KIND) {
711
67
    txSlot* instance = slot->value.reference;
712
67
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_ASYNC_DISPOSABLE_STACK_KIND)) {
713
16
      if (mutable && (slot->flag & XS_DONT_SET_FLAG))
714
0
        mxTypeError("this: read-only AsyncDisposableStack instance");
715
16
      if (disposable && slot->value.disposableStack.disposed)
716
0
        mxReferenceError("this: disposed AsyncDisposableStack instance");
717
16
      return instance;
718
16
    }
719
67
  }
720
129
  mxTypeError("this: not a AsyncDisposableStack instance");
721
0
  return C_NULL;
722
129
}
723
void fx_AsyncDisposableStack(txMachine* the)
724
331k
{
725
331k
  txSlot* instance;
726
331k
  txSlot* property;
727
331k
  txSlot* function;
728
331k
  txSlot* home;
729
331k
  if (mxIsUndefined(mxTarget))
730
1
    mxTypeError("call: AsyncDisposableStack");
731
331k
  mxPushSlot(mxTarget);
732
331k
  fxGetPrototypeFromConstructor(the, &mxAsyncDisposableStackPrototype);
733
331k
  instance = fxNewSlot(the);
734
331k
  instance->kind = XS_INSTANCE_KIND;
735
331k
  instance->value.instance.garbage = C_NULL;
736
331k
  instance->value.instance.prototype = the->stack->value.reference;
737
331k
  the->stack->kind = XS_REFERENCE_KIND;
738
331k
  the->stack->value.reference = instance;
739
331k
  mxPullSlot(mxResult);
740
331k
  property = instance->next = fxNewSlot(the);
741
331k
  property->flag = XS_INTERNAL_FLAG;
742
331k
  property->kind = XS_ASYNC_DISPOSABLE_STACK_KIND;
743
331k
  property->value.disposableStack.stack = C_NULL;
744
331k
  property->value.disposableStack.disposed = 0;
745
  
746
331k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
747
331k
  function = fxNewHostFunction(the, fxAsyncDisposableStackResolve, 1, XS_NO_ID, mxAsyncGeneratorResolveYieldProfileID);
748
331k
  home = mxFunctionInstanceHome(function);
749
331k
  home->value.home.object = instance;
750
331k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
751
331k
  mxPop();
752
331k
  function = fxNewHostFunction(the, fxAsyncDisposableStackReject, 1, XS_NO_ID, mxAsyncGeneratorRejectYieldProfileID);
753
331k
  home = mxFunctionInstanceHome(function);
754
331k
  home->value.home.object = instance;
755
331k
    property = fxNextSlotProperty(the, property, the->stack, XS_NO_ID, XS_INTERNAL_FLAG);
756
331k
  mxPop();
757
331k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
758
331k
    property = fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG);
759
331k
}
760
761
void fx_AsyncDisposableStack_prototype_get_disposed(txMachine* the)
762
16
{
763
16
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 0, 0);
764
16
  txSlot* property = instance->next;
765
16
  mxResult->value.boolean = property->value.disposableStack.disposed;
766
16
  mxResult->kind = XS_BOOLEAN_KIND;
767
16
}
768
769
void fx_AsyncDisposableStack_prototype_adopt(txMachine* the)
770
23
{
771
23
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 1);
772
23
  txSlot* property = instance->next;
773
23
  if (mxArgc > 0) 
774
0
    mxPushSlot(mxArgv(0));
775
23
  else
776
23
    mxPushUndefined();
777
23
  if (mxArgc > 1) 
778
0
    mxPushSlot(mxArgv(1));
779
23
  else
780
23
    mxPushUndefined();
781
23
  fxAsyncDisposableStackPush(the, property);
782
23
  property->value.disposableStack.stack->flag |= XS_BASE_FLAG;
783
23
  mxPop();
784
23
  mxPullSlot(mxResult);
785
23
}
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
44
{
892
44
  txSlot* instance = fxCheckAsyncDisposableStackInstance(the, mxThis, 1, 1);
893
44
  txSlot* property = instance->next;
894
44
  txSlot* resource;
895
44
  if (mxArgc > 0)
896
14
    mxPushSlot(mxArgv(0));
897
30
  else
898
30
    mxPushUndefined();
899
44
  resource = the->stack;
900
44
  if (!mxIsNull(resource) && !mxIsUndefined(resource)) {
901
14
    mxPushSlot(resource);
902
14
    mxGetID(mxID(_Symbol_asyncDispose));
903
14
    if (!fxIsCallable(the, the->stack)) {
904
14
      mxPop();
905
14
      mxPushSlot(resource);
906
14
      mxGetID(mxID(_Symbol_dispose));
907
14
    }
908
14
    fxAsyncDisposableStackPush(the, property);
909
14
    mxPop();
910
14
  }
911
44
  mxPullSlot(mxResult);
912
44
}
913
914
void fxAsyncDisposableStackPush(txMachine* the, txSlot* property)
915
14
{
916
14
  txSlot* dispose = the->stack;
917
14
  txSlot* resource = dispose + 1;
918
14
  txSlot** address = &property->value.disposableStack.stack;
919
14
  txSlot* slot;
920
14
  if (!fxIsCallable(the, dispose))
921
14
    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