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