Coverage Report

Created: 2026-10-17 07:25

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