@agoric/xsnap 0.14.3-u13.0 → 0.14.3-u16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/README.md +3 -3
  2. package/api.js +4 -2
  3. package/build.env +1 -1
  4. package/moddable/modules/data/base64/base64.js +28 -0
  5. package/moddable/modules/data/base64/manifest.json +11 -0
  6. package/moddable/modules/data/base64/modBase64.c +188 -0
  7. package/moddable/modules/data/binaryMessage/BinaryMessage.js +106 -0
  8. package/moddable/modules/data/crc/crc.c +205 -0
  9. package/moddable/modules/data/crc/crc.js +36 -0
  10. package/moddable/modules/data/crc/manifest.json +8 -0
  11. package/moddable/modules/data/hex/hex.js +28 -0
  12. package/moddable/modules/data/hex/manifest.json +11 -0
  13. package/moddable/modules/data/hex/modHex.c +139 -0
  14. package/moddable/modules/data/logical/logical.js +32 -0
  15. package/moddable/modules/data/logical/modLogical.c +98 -0
  16. package/moddable/modules/data/qrcode/manifest.json +9 -0
  17. package/moddable/modules/data/qrcode/qrcode.c +93 -0
  18. package/moddable/modules/data/qrcode/qrcode.js +23 -0
  19. package/moddable/modules/data/qrcode/qrcodegen.c +1025 -0
  20. package/moddable/modules/data/qrcode/qrcodegen.h +267 -0
  21. package/moddable/modules/data/text/decoder/manifest.json +8 -0
  22. package/moddable/modules/data/text/decoder/textdecoder.c +480 -0
  23. package/moddable/modules/data/text/decoder/textdecoder.js +27 -0
  24. package/moddable/modules/data/text/encoder/manifest.json +8 -0
  25. package/moddable/modules/data/text/encoder/textencoder.c +232 -0
  26. package/moddable/modules/data/text/encoder/textencoder.js +24 -0
  27. package/moddable/modules/data/tinyint/tinyint.c +150 -0
  28. package/moddable/modules/data/tinyint/tinyint.js +53 -0
  29. package/moddable/modules/data/url/manifest.json +17 -0
  30. package/moddable/modules/data/url/url.c +1959 -0
  31. package/moddable/modules/data/url/url.js +210 -0
  32. package/moddable/modules/data/wavreader/manifest.json +8 -0
  33. package/moddable/modules/data/wavreader/wavreader.js +128 -0
  34. package/moddable/modules/data/zlib/deflate.c +161 -0
  35. package/moddable/modules/data/zlib/deflate.js +63 -0
  36. package/moddable/modules/data/zlib/inflate.c +145 -0
  37. package/moddable/modules/data/zlib/inflate.js +66 -0
  38. package/moddable/modules/data/zlib/manifest_deflate.json +9 -0
  39. package/moddable/modules/data/zlib/manifest_inflate.json +9 -0
  40. package/moddable/modules/data/zlib/miniz.c +4924 -0
  41. package/moddable/xs/includes/xs.d.ts +73 -0
  42. package/moddable/xs/includes/xs.h +1533 -0
  43. package/moddable/xs/includes/xsmc.h +206 -0
  44. package/moddable/xs/makefiles/lin/makefile +33 -0
  45. package/moddable/xs/makefiles/lin/xsc.mk +118 -0
  46. package/moddable/xs/makefiles/lin/xsid.mk +90 -0
  47. package/moddable/xs/makefiles/lin/xsl.mk +168 -0
  48. package/moddable/xs/makefiles/lin/xst.mk +201 -0
  49. package/moddable/xs/makefiles/mac/makefile +33 -0
  50. package/moddable/xs/makefiles/mac/xsc.mk +130 -0
  51. package/moddable/xs/makefiles/mac/xsid.mk +102 -0
  52. package/moddable/xs/makefiles/mac/xsl.mk +177 -0
  53. package/moddable/xs/makefiles/mac/xst.mk +203 -0
  54. package/moddable/xs/makefiles/mac/xst_no_asan.txt +52 -0
  55. package/moddable/xs/makefiles/win/build.bat +26 -0
  56. package/moddable/xs/makefiles/win/xsc.mak +142 -0
  57. package/moddable/xs/makefiles/win/xsid.mak +113 -0
  58. package/moddable/xs/makefiles/win/xsl.mak +186 -0
  59. package/moddable/xs/makefiles/win/xst.mak +195 -0
  60. package/moddable/xs/platforms/lin_xs.h +99 -0
  61. package/moddable/xs/platforms/mac_xs.h +97 -0
  62. package/moddable/xs/platforms/wasm_xs.h +79 -0
  63. package/moddable/xs/platforms/win_xs.h +104 -0
  64. package/moddable/xs/platforms/xsHost.h +63 -0
  65. package/moddable/xs/platforms/xsPlatform.h +618 -0
  66. package/moddable/xs/sources/xsAPI.c +2555 -0
  67. package/moddable/xs/sources/xsAll.c +294 -0
  68. package/moddable/xs/sources/xsAll.h +2741 -0
  69. package/moddable/xs/sources/xsArguments.c +222 -0
  70. package/moddable/xs/sources/xsArray.c +2657 -0
  71. package/moddable/xs/sources/xsAtomics.c +844 -0
  72. package/moddable/xs/sources/xsBigInt.c +1859 -0
  73. package/moddable/xs/sources/xsBoolean.c +109 -0
  74. package/moddable/xs/sources/xsCode.c +4493 -0
  75. package/moddable/xs/sources/xsCommon.c +1710 -0
  76. package/moddable/xs/sources/xsCommon.h +1142 -0
  77. package/moddable/xs/sources/xsDataView.c +2890 -0
  78. package/moddable/xs/sources/xsDate.c +1541 -0
  79. package/moddable/xs/sources/xsDebug.c +2710 -0
  80. package/moddable/xs/sources/xsDefaults.c +134 -0
  81. package/moddable/xs/sources/xsError.c +353 -0
  82. package/moddable/xs/sources/xsFunction.c +776 -0
  83. package/moddable/xs/sources/xsGenerator.c +865 -0
  84. package/moddable/xs/sources/xsGlobal.c +839 -0
  85. package/moddable/xs/sources/xsJSON.c +1091 -0
  86. package/moddable/xs/sources/xsLexical.c +1969 -0
  87. package/moddable/xs/sources/xsLockdown.c +933 -0
  88. package/moddable/xs/sources/xsMapSet.c +1649 -0
  89. package/moddable/xs/sources/xsMarshall.c +1020 -0
  90. package/moddable/xs/sources/xsMath.c +624 -0
  91. package/moddable/xs/sources/xsMemory.c +1941 -0
  92. package/moddable/xs/sources/xsModule.c +3101 -0
  93. package/moddable/xs/sources/xsNumber.c +560 -0
  94. package/moddable/xs/sources/xsObject.c +1102 -0
  95. package/moddable/xs/sources/xsPlatforms.c +480 -0
  96. package/moddable/xs/sources/xsProfile.c +577 -0
  97. package/moddable/xs/sources/xsPromise.c +1199 -0
  98. package/moddable/xs/sources/xsProperty.c +636 -0
  99. package/moddable/xs/sources/xsProxy.c +1014 -0
  100. package/moddable/xs/sources/xsRegExp.c +1168 -0
  101. package/moddable/xs/sources/xsRun.c +4889 -0
  102. package/moddable/xs/sources/xsScope.c +1293 -0
  103. package/moddable/xs/sources/xsScript.c +288 -0
  104. package/moddable/xs/sources/xsScript.h +1186 -0
  105. package/moddable/xs/sources/xsSnapshot.c +2161 -0
  106. package/moddable/xs/sources/xsSnapshot.h +51 -0
  107. package/moddable/xs/sources/xsSourceMap.c +218 -0
  108. package/moddable/xs/sources/xsString.c +3332 -0
  109. package/moddable/xs/sources/xsSymbol.c +503 -0
  110. package/moddable/xs/sources/xsSyntaxical.c +4193 -0
  111. package/moddable/xs/sources/xsTree.c +1893 -0
  112. package/moddable/xs/sources/xsType.c +1488 -0
  113. package/moddable/xs/sources/xsdtoa.c +6672 -0
  114. package/moddable/xs/sources/xsmc.c +340 -0
  115. package/moddable/xs/sources/xsre.c +7578 -0
  116. package/package.json +39 -22
  117. package/scripts/get_xsnap_version.sh +14 -0
  118. package/scripts/test-package.sh +21 -0
  119. package/src/avaAssertXS.js +6 -2
  120. package/src/avaHandler.cjs +2 -5
  121. package/src/avaXS.js +7 -8
  122. package/src/build.js +161 -28
  123. package/src/replay.js +0 -3
  124. package/src/xsnap.js +105 -91
  125. package/src/xsrepl.js +2 -3
  126. package/xsnap-native/xsnap/makefiles/lin/makefile +10 -0
  127. package/xsnap-native/xsnap/makefiles/lin/xsnap-worker.mk +156 -0
  128. package/xsnap-native/xsnap/makefiles/lin/xsnap.mk +144 -0
  129. package/xsnap-native/xsnap/makefiles/mac/makefile +10 -0
  130. package/xsnap-native/xsnap/makefiles/mac/xsnap-worker.mk +165 -0
  131. package/xsnap-native/xsnap/makefiles/mac/xsnap.mk +153 -0
  132. package/xsnap-native/xsnap/sources/xsnap-worker.c +1008 -0
  133. package/xsnap-native/xsnap/sources/xsnap.c +717 -0
  134. package/xsnap-native/xsnap/sources/xsnap.h +142 -0
  135. package/xsnap-native/xsnap/sources/xsnapPlatform.c +1501 -0
  136. package/xsnap-native/xsnap/sources/xsnapPlatform.h +105 -0
  137. package/CHANGELOG.md +0 -646
@@ -0,0 +1,1199 @@
1
+ /*
2
+ * Copyright (c) 2016-2017 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
+ //#define mxPromisePrint 1
41
+
42
+ static void fxAddUnhandledRejection(txMachine* the, txSlot* promise);
43
+ static void fxCombinePromises(txMachine* the, txInteger which);
44
+ static txSlot* fxNewCombinePromisesFunction(txMachine* the, txInteger which, txSlot* already, txSlot* object);
45
+
46
+ enum {
47
+ XS_PROMISE_COMBINE_NONE = 0,
48
+ XS_PROMISE_COMBINE_FULFILLED = 1,
49
+ XS_PROMISE_COMBINE_REJECTED = 2,
50
+ XS_PROMISE_COMBINE_SETTLED = 4,
51
+ };
52
+
53
+ void fxBuildPromise(txMachine* the)
54
+ {
55
+ txSlot* slot;
56
+ mxPush(mxObjectPrototype);
57
+ slot = fxLastProperty(the, fxNewObjectInstance(the));
58
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Promise_prototype_catch), 1, mxID(_catch), XS_DONT_ENUM_FLAG);
59
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Promise_prototype_finally), 1, mxID(_finally_), XS_DONT_ENUM_FLAG);
60
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Promise_prototype_then), 2, mxID(_then), XS_DONT_ENUM_FLAG);
61
+ slot = fxNextStringXProperty(the, slot, "Promise", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
62
+ mxPromisePrototype = *the->stack;
63
+ slot = fxBuildHostConstructor(the, mxCallback(fx_Promise), 1, mxID(_Promise));
64
+ mxPromiseConstructor = *the->stack;
65
+ slot = fxLastProperty(the, slot);
66
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Promise_all), 1, mxID(_all), XS_DONT_ENUM_FLAG);
67
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Promise_allSettled), 1, mxID(_allSettled), XS_DONT_ENUM_FLAG);
68
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Promise_any), 1, mxID(_any), XS_DONT_ENUM_FLAG);
69
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Promise_race), 1, mxID(_race), XS_DONT_ENUM_FLAG);
70
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Promise_reject), 1, mxID(_reject), XS_DONT_ENUM_FLAG);
71
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Promise_resolve), 1, mxID(_resolve), XS_DONT_ENUM_FLAG);
72
+ slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_species_get), C_NULL, mxID(_Symbol_species), XS_DONT_ENUM_FLAG);
73
+ mxPop();
74
+ fxNewHostFunction(the, mxCallback(fxOnRejectedPromise), 1, XS_NO_ID, XS_NO_ID);
75
+ mxOnRejectedPromiseFunction = *the->stack;
76
+ mxPop();
77
+ fxNewHostFunction(the, mxCallback(fxOnResolvedPromise), 1, XS_NO_ID, XS_NO_ID);
78
+ mxOnResolvedPromiseFunction = *the->stack;
79
+ mxPop();
80
+ fxNewHostFunction(the, mxCallback(fxOnThenable), 1, XS_NO_ID, XS_NO_ID);
81
+ mxOnThenableFunction = *the->stack;
82
+ mxPop();
83
+ }
84
+
85
+ txSlot* fxNewPromiseInstance(txMachine* the)
86
+ {
87
+ #ifdef mxPromisePrint
88
+ static txID gID = 0;
89
+ #endif
90
+ txSlot* promise;
91
+ txSlot* slot;
92
+ txSlot* instance;
93
+ promise = fxNewSlot(the);
94
+ promise->kind = XS_INSTANCE_KIND;
95
+ promise->value.instance.garbage = C_NULL;
96
+ promise->value.instance.prototype = the->stack->value.reference;
97
+ the->stack->kind = XS_REFERENCE_KIND;
98
+ the->stack->value.reference = promise;
99
+ /* STATUS */
100
+ slot = promise->next = fxNewSlot(the);
101
+ slot->flag = XS_INTERNAL_FLAG;
102
+ #ifdef mxPromisePrint
103
+ slot->ID = gID++;
104
+ #endif
105
+ slot->kind = XS_PROMISE_KIND;
106
+ slot->value.integer = mxUndefinedStatus;
107
+ /* THENS */
108
+ slot = slot->next = fxNewSlot(the);
109
+ slot->flag = XS_INTERNAL_FLAG;
110
+ slot->value.reference = instance = fxNewSlot(the);
111
+ slot->kind = XS_REFERENCE_KIND;
112
+ instance->kind = XS_INSTANCE_KIND;
113
+ instance->value.instance.garbage = C_NULL;
114
+ instance->value.instance.prototype = C_NULL;
115
+ /* RESULT */
116
+ slot = slot->next = fxNewSlot(the);
117
+ slot->flag = XS_INTERNAL_FLAG;
118
+ #ifdef mxDebug
119
+ /* ENVIRONMENT */
120
+ slot = slot->next = fxNewSlot(the);
121
+ slot->flag = XS_INTERNAL_FLAG;
122
+ instance = the->frame;
123
+ while (instance) {
124
+ txSlot* environment = mxFrameToEnvironment(instance);
125
+ if (environment->ID != XS_NO_ID) {
126
+ slot->ID = environment->ID;
127
+ slot->value.environment.line = environment->value.environment.line;
128
+ break;
129
+ }
130
+ instance = instance->next;
131
+ }
132
+ #endif
133
+ return promise;
134
+ }
135
+
136
+ txSlot* fxNewPromiseCapability(txMachine* the, txSlot* resolveFunction, txSlot* rejectFunction)
137
+ {
138
+ txSlot* capability;
139
+ txSlot* slot;
140
+ txSlot* function;
141
+ mxNew();
142
+ resolveFunction->value.reference = fxNewHostFunction(the, fxNewPromiseCapabilityCallback, 2, XS_NO_ID, mxNewPromiseCapabilityCallbackProfileID);
143
+ resolveFunction->kind = XS_REFERENCE_KIND;
144
+ mxRunCount(1);
145
+ capability = resolveFunction->value.reference;
146
+ resolveFunction->kind = XS_UNDEFINED_KIND;
147
+ slot = mxFunctionInstanceHome(capability)->value.home.object;
148
+ if (!slot)
149
+ mxTypeError("executor not called");
150
+ slot = slot->next;
151
+ if (!mxIsReference(slot))
152
+ mxTypeError("resolve is no object");
153
+ function = slot->value.reference;
154
+ if (!mxIsFunction(function))
155
+ mxTypeError("resolve is no function");
156
+ resolveFunction->kind = XS_REFERENCE_KIND;
157
+ resolveFunction->value.reference = function;
158
+ slot = slot->next;
159
+ if (!mxIsReference(slot))
160
+ mxTypeError("reject is no object");
161
+ function = slot->value.reference;
162
+ if (!mxIsFunction(function))
163
+ mxTypeError("reject is no function");
164
+ rejectFunction->kind = XS_REFERENCE_KIND;
165
+ rejectFunction->value.reference = function;
166
+ return the->stack->value.reference;
167
+ }
168
+
169
+ void fxNewPromiseCapabilityCallback(txMachine* the)
170
+ {
171
+ txSlot* slot = mxFunctionInstanceHome(mxFunction->value.reference);
172
+ txSlot* object = slot->value.home.object;
173
+ txSlot* resolveFunction;
174
+ txSlot* rejectFunction;
175
+ if (object) {
176
+ resolveFunction = object->next;
177
+ rejectFunction = resolveFunction->next;
178
+ if (!mxIsUndefined(resolveFunction) || !mxIsUndefined(rejectFunction))
179
+ mxTypeError("executor already called");
180
+ }
181
+ else {
182
+ object = fxNewInstance(the);
183
+ resolveFunction = object->next = fxNewSlot(the);
184
+ rejectFunction = resolveFunction->next = fxNewSlot(the);
185
+ slot->value.home.object = object;
186
+ mxPop();
187
+ }
188
+ if (mxArgc > 0) {
189
+ resolveFunction->kind = mxArgv(0)->kind;
190
+ resolveFunction->value = mxArgv(0)->value;
191
+ }
192
+ if (mxArgc > 1) {
193
+ rejectFunction->kind = mxArgv(1)->kind;
194
+ rejectFunction->value = mxArgv(1)->value;
195
+ }
196
+ }
197
+
198
+ void fxAddUnhandledRejection(txMachine* the, txSlot* promise)
199
+ {
200
+ txSlot* reason = mxPromiseResult(promise);
201
+ txSlot* list = &mxUnhandledPromises;
202
+ txSlot** address = &list->value.reference->next;
203
+ txSlot* slot;
204
+ while ((slot = *address)) {
205
+ if (slot->value.weakRef.target == promise)
206
+ break;
207
+ slot = slot->next;
208
+ address = &slot->next;
209
+ }
210
+ if (!slot) {
211
+ #ifdef mxPromisePrint
212
+ fprintf(stderr, "fxAddUnhandledRejection %d\n", promise->next->ID);
213
+ #endif
214
+ slot = *address = fxNewSlot(the);
215
+ slot->kind = XS_WEAK_REF_KIND;
216
+ slot->value.weakRef.target = promise;
217
+ slot = slot->next = fxNewSlot(the);
218
+ slot->kind = reason->kind;
219
+ slot->value = reason->value;
220
+ }
221
+ }
222
+
223
+ void fxCheckUnhandledRejections(txMachine* the, txBoolean atExit)
224
+ {
225
+ txSlot* list = &mxUnhandledPromises;
226
+ txSlot** address = &list->value.reference->next;
227
+ txSlot* slot;
228
+ if (atExit) {
229
+ while ((slot = *address)) {
230
+ slot = slot->next;
231
+ *address = slot->next;
232
+ mxException.value = slot->value;
233
+ mxException.kind = slot->kind;
234
+ fxAbort(the, XS_UNHANDLED_REJECTION_EXIT);
235
+ }
236
+ }
237
+ else {
238
+ while ((slot = *address)) {
239
+ if (slot->value.weakRef.target == C_NULL) {
240
+ slot = slot->next;
241
+ *address = slot->next;
242
+ mxException.value = slot->value;
243
+ mxException.kind = slot->kind;
244
+ fxAbort(the, XS_UNHANDLED_REJECTION_EXIT);
245
+ }
246
+ else {
247
+ slot = slot->next;
248
+ address = &slot->next;
249
+ }
250
+ }
251
+ }
252
+ }
253
+
254
+ void fxCombinePromises(txMachine* the, txInteger which)
255
+ {
256
+ txSlot* stack = the->stack;
257
+ txSlot* resolveFunction;
258
+ txSlot* rejectFunction;
259
+ txSlot* promise;
260
+ txSlot* object;
261
+ txSlot* property;
262
+ txSlot* array;
263
+ txSlot* already;
264
+ txSlot* iterator;
265
+ txSlot* next;
266
+ txSlot* value;
267
+ txInteger index;
268
+
269
+ if (!mxIsReference(mxThis))
270
+ mxTypeError("this is no object");
271
+ mxTemporary(resolveFunction);
272
+ mxTemporary(rejectFunction);
273
+ mxPushSlot(mxThis);
274
+ promise = fxNewPromiseCapability(the, resolveFunction, rejectFunction);
275
+ mxPullSlot(mxResult);
276
+ {
277
+ mxTry(the) {
278
+ txSlot* resolve = C_NULL;
279
+ if (which) {
280
+ object = fxNewInstance(the);
281
+ property = fxNextIntegerProperty(the, object, 0, XS_NO_ID, XS_NO_FLAG);
282
+ property = fxNextReferenceProperty(the, property, promise, XS_NO_ID, XS_NO_FLAG);
283
+ if (which == XS_PROMISE_COMBINE_REJECTED)
284
+ property = fxNextSlotProperty(the, property, rejectFunction, XS_NO_ID, XS_NO_FLAG);
285
+ else
286
+ property = fxNextSlotProperty(the, property, resolveFunction, XS_NO_ID, XS_NO_FLAG);
287
+ mxPush(mxArrayPrototype);
288
+ array = fxNewArrayInstance(the);
289
+ already = array->next;
290
+ property = fxNextReferenceProperty(the, property, array, XS_NO_ID, XS_NO_FLAG);
291
+ mxPop();
292
+ }
293
+ mxPushSlot(mxThis);
294
+ mxGetID(mxID(_resolve));
295
+ resolve = the->stack;
296
+ if (!fxIsCallable(the, resolve))
297
+ mxTypeError("resolve is no function");
298
+ mxTemporary(iterator);
299
+ mxTemporary(next);
300
+ fxGetIterator(the, mxArgv(0), iterator, next, 0);
301
+ index = 0;
302
+ mxTemporary(value);
303
+ while (fxIteratorNext(the, iterator, next, value)) {
304
+ mxTry(the) {
305
+ mxPushSlot(mxThis);
306
+ mxPushSlot(resolve);
307
+ mxCall();
308
+ mxPushSlot(value);
309
+ mxRunCount(1);
310
+ mxDub();
311
+ mxGetID(mxID(_then));
312
+ mxCall();
313
+ if (which) {
314
+ already = already->next = fxNewSlot(the);
315
+ already->kind = XS_UNINITIALIZED_KIND;
316
+ array->next->value.array.length++;
317
+ }
318
+ if (which & XS_PROMISE_COMBINE_SETTLED) {
319
+ fxNewCombinePromisesFunction(the, which | XS_PROMISE_COMBINE_FULFILLED, already, object);
320
+ fxNewCombinePromisesFunction(the, which | XS_PROMISE_COMBINE_REJECTED, already, object);
321
+ }
322
+ else if (which & XS_PROMISE_COMBINE_FULFILLED) {
323
+ fxNewCombinePromisesFunction(the, which, already, object);
324
+ mxPushSlot(rejectFunction);
325
+ }
326
+ else if (which & XS_PROMISE_COMBINE_REJECTED) {
327
+ mxPushSlot(resolveFunction);
328
+ fxNewCombinePromisesFunction(the, which, already, object);
329
+ }
330
+ else {
331
+ mxPushSlot(resolveFunction);
332
+ mxPushSlot(rejectFunction);
333
+ }
334
+ mxRunCount(2);
335
+ mxPop();
336
+ index++;
337
+ }
338
+ mxCatch(the) {
339
+ fxIteratorReturn(the, iterator);
340
+ fxJump(the);
341
+ }
342
+ }
343
+ if (which) {
344
+ property = object->next;
345
+ property->value.integer += index;
346
+ index = property->value.integer;
347
+ }
348
+ if ((index == 0) && (which != XS_PROMISE_COMBINE_NONE)) {
349
+ mxPushUndefined();
350
+ if (which == XS_PROMISE_COMBINE_REJECTED)
351
+ mxPushSlot(rejectFunction);
352
+ else
353
+ mxPushSlot(resolveFunction);
354
+ mxCall();
355
+ if ((which == XS_PROMISE_COMBINE_SETTLED) || (which == XS_PROMISE_COMBINE_FULFILLED)) {
356
+ fxCacheArray(the, array);
357
+ mxPushReference(array);
358
+ }
359
+ else if (which == XS_PROMISE_COMBINE_REJECTED) {
360
+ mxPush(mxAggregateErrorConstructor);
361
+ mxNew();
362
+ fxCacheArray(the, array);
363
+ mxPushReference(array);
364
+ mxRunCount(1);
365
+ }
366
+ else {
367
+ mxPushUndefined();
368
+ }
369
+ mxRunCount(1);
370
+ }
371
+ }
372
+ mxCatch(the) {
373
+ fxRejectException(the, rejectFunction);
374
+ }
375
+ }
376
+ the->stack = stack;
377
+ }
378
+
379
+ void fxCombinePromisesCallback(txMachine* the)
380
+ {
381
+ txSlot* slot = mxFunctionInstanceHome(mxFunction->value.reference)->value.home.object->next;
382
+ txInteger which = slot->value.integer;
383
+ txSlot* instance;
384
+ txSlot* property;
385
+ slot = slot->next;
386
+ if (slot->value.closure->kind != XS_UNINITIALIZED_KIND)
387
+ return;
388
+ if (which & XS_PROMISE_COMBINE_SETTLED) {
389
+ mxPush(mxObjectPrototype);
390
+ instance = fxNewObjectInstance(the);
391
+ }
392
+ if (mxArgc > 0)
393
+ mxPushSlot(mxArgv(0));
394
+ else
395
+ mxPushUndefined();
396
+ if (which & XS_PROMISE_COMBINE_SETTLED) {
397
+ property = fxLastProperty(the, instance);
398
+ if (which & XS_PROMISE_COMBINE_FULFILLED) {
399
+ property = fxNextStringXProperty(the, property, "fulfilled", mxID(_status), XS_NO_FLAG);
400
+ property = fxNextSlotProperty(the, property, the->stack, mxID(_value), XS_NO_FLAG);
401
+ }
402
+ else {
403
+ property = fxNextStringXProperty(the, property, "rejected", mxID(_status), XS_NO_FLAG);
404
+ property = fxNextSlotProperty(the, property, the->stack, mxID(_reason), XS_NO_FLAG);
405
+ }
406
+ mxPop();
407
+ }
408
+ mxPullSlot(slot->value.closure);
409
+ slot = slot->next->value.reference->next;
410
+ slot->value.integer--;
411
+ if (slot->value.integer == 0) {
412
+ /* THIS */
413
+ slot = slot->next;
414
+ mxPushSlot(slot);
415
+ /* FUNCTION */
416
+ slot = slot->next;
417
+ mxPushSlot(slot);
418
+ mxCall();
419
+ /* ARGUMENTS */
420
+ slot = slot->next;
421
+ if (which == XS_PROMISE_COMBINE_REJECTED) {
422
+ mxPush(mxAggregateErrorConstructor);
423
+ mxNew();
424
+ }
425
+ fxCacheArray(the, slot->value.reference);
426
+ mxPushSlot(slot);
427
+ if (which == XS_PROMISE_COMBINE_REJECTED) {
428
+ mxRunCount(1);
429
+ }
430
+ /* COUNT */
431
+ mxRunCount(1);
432
+ mxPullSlot(mxResult);
433
+ }
434
+ }
435
+
436
+ txSlot* fxNewCombinePromisesFunction(txMachine* the, txInteger which, txSlot* already, txSlot* object)
437
+ {
438
+ txSlot* result;
439
+ txSlot* instance;
440
+ txSlot* property;
441
+ result = fxNewHostFunction(the, fxCombinePromisesCallback, 1, XS_NO_ID, mxCombinePromisesCallbackProfileID);
442
+ instance = fxNewInstance(the);
443
+ property = fxNextIntegerProperty(the, instance, which, XS_NO_ID, XS_NO_FLAG);
444
+ property = property->next = fxNewSlot(the);
445
+ property->kind = XS_CLOSURE_KIND;
446
+ property->value.closure = already;
447
+ property = fxNextReferenceProperty(the, property, object, XS_NO_ID, XS_NO_FLAG);
448
+ property = mxFunctionInstanceHome(result);
449
+ property->value.home.object = instance;
450
+ mxPop();
451
+ return result;
452
+ }
453
+
454
+ void fxOnRejectedPromise(txMachine* the)
455
+ {
456
+ txSlot* reaction = mxThis->value.reference;
457
+ txSlot* resolveFunction = reaction->next;
458
+ txSlot* rejectFunction = resolveFunction->next;
459
+ txSlot* resolveHandler = rejectFunction->next;
460
+ txSlot* rejectHandler = resolveHandler->next;
461
+ txSlot* argument = mxArgv(0);
462
+ txSlot* function = rejectFunction;
463
+ if (rejectHandler->kind == XS_REFERENCE_KIND) {
464
+ mxTry(the) {
465
+ /* THIS */
466
+ mxPushUndefined();
467
+ /* FUNCTION */
468
+ mxPushSlot(rejectHandler);
469
+ mxCall();
470
+ /* ARGUMENTS */
471
+ mxPushSlot(argument);
472
+ mxRunCount(1);
473
+ mxPullSlot(argument);
474
+ function = resolveFunction;
475
+ }
476
+ mxCatch(the) {
477
+ *argument = mxException;
478
+ mxException = mxUndefined;
479
+ function = rejectFunction;
480
+ }
481
+ }
482
+ if (function->kind == XS_REFERENCE_KIND) {
483
+ /* THIS */
484
+ mxPushUndefined();
485
+ /* FUNCTION */
486
+ mxPushSlot(function);
487
+ mxCall();
488
+ /* ARGUMENTS */
489
+ mxPushSlot(argument);
490
+ mxRunCount(1);
491
+ mxPop();
492
+ }
493
+ }
494
+
495
+ void fxOnResolvedPromise(txMachine* the)
496
+ {
497
+ txSlot* reaction = mxThis->value.reference;
498
+ txSlot* resolveFunction = reaction->next;
499
+ txSlot* rejectFunction = resolveFunction->next;
500
+ txSlot* resolveHandler = rejectFunction->next;
501
+ txSlot* argument = mxArgv(0);
502
+ txSlot* function = resolveFunction;
503
+ if (resolveHandler->kind == XS_REFERENCE_KIND) {
504
+ mxTry(the) {
505
+ /* THIS */
506
+ mxPushUndefined();
507
+ /* FUNCTION */
508
+ mxPushSlot(resolveHandler);
509
+ mxCall();
510
+ /* ARGUMENTS */
511
+ mxPushSlot(argument);
512
+ mxRunCount(1);
513
+ mxPullSlot(argument);
514
+ }
515
+ mxCatch(the) {
516
+ *argument = mxException;
517
+ mxException = mxUndefined;
518
+ function = rejectFunction;
519
+ }
520
+ }
521
+ if (function->kind == XS_REFERENCE_KIND) {
522
+ /* THIS */
523
+ mxPushUndefined();
524
+ /* FUNCTION */
525
+ mxPushSlot(function);
526
+ mxCall();
527
+ /* ARGUMENTS */
528
+ mxPushSlot(argument);
529
+ mxRunCount(1);
530
+ mxPop();
531
+ }
532
+ }
533
+
534
+ void fxOnThenable(txMachine* the)
535
+ {
536
+ txSlot* resolveFunction = mxArgv(0);
537
+ txSlot* rejectFunction = mxArgv(1);
538
+ txSlot* thenFunction = mxArgv(2);
539
+ mxTry(the) {
540
+ /* THIS */
541
+ mxPushSlot(mxThis);
542
+ /* FUNCTION */
543
+ mxPushSlot(thenFunction);
544
+ mxCall();
545
+ /* ARGUMENTS */
546
+ mxPushSlot(resolveFunction);
547
+ mxPushSlot(rejectFunction);
548
+ mxRunCount(2);
549
+ mxPop();
550
+ }
551
+ mxCatch(the) {
552
+ fxRejectException(the, rejectFunction);
553
+ }
554
+ }
555
+
556
+ void fxPromiseThen(txMachine* the, txSlot* promise, txSlot* onFullfilled, txSlot* onRejected, txSlot* resolveFunction, txSlot* rejectFunction)
557
+ {
558
+ txSlot* reaction;
559
+ txSlot* slot;
560
+ txSlot* status;
561
+
562
+ reaction = fxNewInstance(the);
563
+ slot = reaction->next = fxNewSlot(the);
564
+ if (resolveFunction) {
565
+ slot->kind = resolveFunction->kind;
566
+ slot->value = resolveFunction->value;
567
+ }
568
+ slot = slot->next = fxNewSlot(the);
569
+ if (rejectFunction) {
570
+ slot->kind = rejectFunction->kind;
571
+ slot->value = rejectFunction->value;
572
+ }
573
+ slot = slot->next = fxNewSlot(the);
574
+ if (onFullfilled) {
575
+ slot->kind = onFullfilled->kind;
576
+ slot->value = onFullfilled->value;
577
+ }
578
+ slot = slot->next = fxNewSlot(the);
579
+ if (onRejected) {
580
+ slot->kind = onRejected->kind;
581
+ slot->value = onRejected->value;
582
+ }
583
+
584
+ status = mxPromiseStatus(promise);
585
+ if (status->value.integer == mxPendingStatus) {
586
+ txSlot** address = &(mxPromiseThens(promise)->value.reference->next);
587
+ while ((slot = *address))
588
+ address = &(slot->next);
589
+ slot = *address = fxNewSlot(the);
590
+ slot->kind = XS_REFERENCE_KIND;
591
+ slot->value.reference = reaction;
592
+ }
593
+ else {
594
+ mxPushReference(reaction);
595
+ if (status->value.integer == mxFulfilledStatus)
596
+ mxPush(mxOnResolvedPromiseFunction);
597
+ else
598
+ mxPush(mxOnRejectedPromiseFunction);
599
+ mxCall();
600
+ slot = mxPromiseResult(promise);
601
+ mxPushSlot(slot);
602
+ fxQueueJob(the, 1, promise);
603
+ }
604
+ mxPop(); // reaction
605
+ }
606
+
607
+ void fxPushPromiseFunctions(txMachine* the, txSlot* promise)
608
+ {
609
+ txSlot* resolve;
610
+ txSlot* reject;
611
+ txSlot* object;
612
+ txSlot* slot;
613
+ resolve = fxNewHostFunction(the, fxResolvePromise, 1, XS_NO_ID, mxResolvePromiseProfileID);
614
+ reject = fxNewHostFunction(the, fxRejectPromise, 1, XS_NO_ID, mxRejectPromiseProfileID);
615
+ slot = object = fxNewInstance(the);
616
+ slot = object->next = fxNewSlot(the);
617
+ slot->kind = XS_BOOLEAN_KIND;
618
+ slot->value.boolean = 0;
619
+ slot = slot->next = fxNewSlot(the);
620
+ slot->kind = XS_REFERENCE_KIND;
621
+ slot->value.reference = promise;
622
+ slot = mxFunctionInstanceHome(resolve);
623
+ slot->value.home.object = object;
624
+ slot = mxFunctionInstanceHome(reject);
625
+ slot->value.home.object = object;
626
+ mxPop();
627
+ }
628
+
629
+ void fxRejectException(txMachine* the, txSlot* rejectFunction)
630
+ {
631
+ /* THIS */
632
+ mxPushUndefined();
633
+ /* FUNCTION */
634
+ mxPushSlot(rejectFunction);
635
+ mxCall();
636
+ /* ARGUMENTS */
637
+ mxPush(mxException);
638
+ mxException = mxUndefined;
639
+ mxRunCount(1);
640
+ mxPop();
641
+ }
642
+
643
+ void fxRejectPromise(txMachine* the)
644
+ {
645
+ txSlot* slot;
646
+ txSlot* promise;
647
+ txSlot* argument;
648
+ txSlot* result;
649
+ slot = mxFunctionInstanceHome(mxFunction->value.reference)->value.home.object->next;
650
+ if (slot->value.boolean)
651
+ return;
652
+ slot->value.boolean = 1;
653
+ mxPushSlot(slot->next);
654
+ promise = the->stack->value.reference;
655
+ slot->next = C_NULL;
656
+ if (mxArgc > 0)
657
+ mxPushSlot(mxArgv(0));
658
+ else
659
+ mxPushUndefined();
660
+ argument = the->stack;
661
+ #ifdef mxPromisePrint
662
+ fprintf(stderr, "fxRejectPromise %d\n", promise->next->ID);
663
+ #endif
664
+ result = mxPromiseResult(promise);
665
+ result->kind = argument->kind;
666
+ result->value = argument->value;
667
+ slot = mxPromiseThens(promise)->value.reference->next;
668
+ if (slot) {
669
+ while (slot) {
670
+ mxPushReference(slot->value.reference);
671
+ mxPush(mxOnRejectedPromiseFunction);
672
+ mxCall();
673
+ mxPushSlot(argument);
674
+ fxQueueJob(the, 1, promise);
675
+ slot = slot->next;
676
+ }
677
+ mxPromiseThens(promise)->value.reference->next = C_NULL;
678
+ }
679
+ else {
680
+ fxAddUnhandledRejection(the, promise);
681
+ }
682
+ slot = mxPromiseStatus(promise);
683
+ slot->value.integer = mxRejectedStatus;
684
+ }
685
+
686
+ void fxResolvePromise(txMachine* the)
687
+ {
688
+ txSlot* slot;
689
+ txSlot* promise;
690
+ txSlot* argument;
691
+ txSlot* result;
692
+ slot = mxFunctionInstanceHome(mxFunction->value.reference)->value.home.object->next;
693
+ if (slot->value.boolean)
694
+ return;
695
+ slot->value.boolean = 1;
696
+ mxPushSlot(slot->next);
697
+ promise = the->stack->value.reference;
698
+ slot->next = C_NULL;
699
+ if (mxArgc > 0)
700
+ mxPushSlot(mxArgv(0));
701
+ else
702
+ mxPushUndefined();
703
+ argument = the->stack;
704
+ #ifdef mxPromisePrint
705
+ fprintf(stderr, "fxResolvePromise %d\n", promise->next->ID);
706
+ #endif
707
+ mxTry(the) {
708
+ if (mxIsReference(argument)) {
709
+ if (argument->value.reference == promise)
710
+ mxTypeError("promise resolves itself");
711
+ mxPushSlot(argument);
712
+ mxGetID(mxID(_then));
713
+ slot = the->stack;
714
+ if (fxIsCallable(the, slot)) {
715
+ #ifdef mxPromisePrint
716
+ fprintf(stderr, "fxResolvePromise then %d\n", promise->next->ID);
717
+ #endif
718
+ mxPushSlot(argument);
719
+ mxPush(mxOnThenableFunction);
720
+ mxCall();
721
+ fxPushPromiseFunctions(the, promise);
722
+ mxPushSlot(slot);
723
+ fxQueueJob(the, 3, promise);
724
+ goto bail;
725
+ }
726
+ mxPop();
727
+ }
728
+ result = mxPromiseResult(promise);
729
+ result->kind = argument->kind;
730
+ result->value = argument->value;
731
+ slot = mxPromiseThens(promise)->value.reference->next;
732
+ while (slot) {
733
+ mxPushReference(slot->value.reference);
734
+ mxPush(mxOnResolvedPromiseFunction);
735
+ mxCall();
736
+ mxPushSlot(result);
737
+ fxQueueJob(the, 1, promise);
738
+ slot = slot->next;
739
+ }
740
+ mxPromiseThens(promise)->value.reference->next = C_NULL;
741
+ slot = mxPromiseStatus(promise);
742
+ slot->value.integer = mxFulfilledStatus;
743
+ }
744
+ bail:
745
+ mxCatch(the) {
746
+ result = mxPromiseResult(promise);
747
+ result->kind = mxException.kind;
748
+ result->value = mxException.value;
749
+ mxException = mxUndefined;
750
+ slot = mxPromiseThens(promise)->value.reference->next;
751
+ if (slot) {
752
+ while (slot) {
753
+ mxPushReference(slot->value.reference);
754
+ mxPush(mxOnRejectedPromiseFunction);
755
+ mxCall();
756
+ mxPushSlot(result);
757
+ fxQueueJob(the, 1, promise);
758
+ slot = slot->next;
759
+ }
760
+ mxPromiseThens(promise)->value.reference->next = C_NULL;
761
+ }
762
+ else {
763
+ fxAddUnhandledRejection(the, promise);
764
+ }
765
+ slot = mxPromiseStatus(promise);
766
+ slot->value.integer = mxRejectedStatus;
767
+ }
768
+ }
769
+
770
+ void fx_Promise(txMachine* the)
771
+ {
772
+ txSlot* stack = the->stack;
773
+ txSlot* promise;
774
+ txSlot* argument;
775
+ txSlot* status;
776
+ txSlot* resolveFunction;
777
+ txSlot* rejectFunction;
778
+ if (mxIsUndefined(mxTarget))
779
+ mxTypeError("call: Promise");
780
+ if (mxArgc < 1)
781
+ mxTypeError("no executor parameter");
782
+ argument = mxArgv(0);
783
+ if (!fxIsCallable(the, argument))
784
+ mxTypeError("executor is no function");
785
+ mxPushSlot(mxTarget);
786
+ fxGetPrototypeFromConstructor(the, &mxPromisePrototype);
787
+ promise = fxNewPromiseInstance(the);
788
+ #ifdef mxPromisePrint
789
+ fprintf(stderr, "fx_Promise %d\n", promise->next->ID);
790
+ #endif
791
+ mxPullSlot(mxResult);
792
+ status = mxPromiseStatus(promise);
793
+ status->value.integer = mxPendingStatus;
794
+ fxPushPromiseFunctions(the, promise);
795
+ resolveFunction = the->stack + 1;
796
+ rejectFunction = the->stack;
797
+ {
798
+ mxTry(the) {
799
+ /* THIS */
800
+ mxPushUndefined();
801
+ /* FUNCTION */
802
+ mxPushSlot(argument);
803
+ mxCall();
804
+ /* ARGUMENTS */
805
+ mxPushSlot(resolveFunction);
806
+ mxPushSlot(rejectFunction);
807
+ mxRunCount(2);
808
+ }
809
+ mxCatch(the) {
810
+ fxRejectException(the, rejectFunction);
811
+ }
812
+ }
813
+ the->stack = stack;
814
+ }
815
+
816
+ void fx_Promise_all(txMachine* the)
817
+ {
818
+ fxCombinePromises(the, XS_PROMISE_COMBINE_FULFILLED);
819
+ }
820
+
821
+ void fx_Promise_allSettled(txMachine* the)
822
+ {
823
+ fxCombinePromises(the, XS_PROMISE_COMBINE_SETTLED);
824
+ }
825
+
826
+ void fx_Promise_any(txMachine* the)
827
+ {
828
+ fxCombinePromises(the, XS_PROMISE_COMBINE_REJECTED);
829
+ }
830
+
831
+ void fx_Promise_race(txMachine* the)
832
+ {
833
+ fxCombinePromises(the, XS_PROMISE_COMBINE_NONE);
834
+ }
835
+
836
+ void fx_Promise_reject(txMachine* the)
837
+ {
838
+ txSlot* resolveFunction;
839
+ txSlot* rejectFunction;
840
+
841
+ if (!mxIsReference(mxThis))
842
+ mxTypeError("this is no object");
843
+ mxTemporary(resolveFunction);
844
+ mxTemporary(rejectFunction);
845
+ mxPushSlot(mxThis);
846
+ fxNewPromiseCapability(the, resolveFunction, rejectFunction);
847
+ mxPullSlot(mxResult);
848
+ /* THIS */
849
+ mxPushUndefined();
850
+ /* FUNCTION */
851
+ mxPushSlot(rejectFunction);
852
+ mxCall();
853
+ /* ARGUMENTS */
854
+ if (mxArgc > 0)
855
+ mxPushSlot(mxArgv(0));
856
+ else
857
+ mxPushUndefined();
858
+ mxRunCount(1);
859
+ mxPop();
860
+ }
861
+
862
+ void fx_Promise_resolve(txMachine* the)
863
+ {
864
+ if (!mxIsReference(mxThis))
865
+ mxTypeError("this is no object");
866
+ mxPushUndefined();
867
+ mxPushSlot(mxThis);
868
+ if (mxArgc > 0)
869
+ mxPushSlot(mxArgv(0));
870
+ else
871
+ mxPushUndefined();
872
+ fx_Promise_resolveAux(the);
873
+ mxPop();
874
+ mxPop();
875
+ mxPullSlot(mxResult);
876
+ }
877
+
878
+ void fx_Promise_resolveAux(txMachine* the)
879
+ {
880
+ txSlot* argument = the->stack;
881
+ txSlot* constructor = the->stack + 1;
882
+ txSlot* result = the->stack + 2;
883
+ txSlot* resolveFunction;
884
+ txSlot* rejectFunction;
885
+ // if (!mxIsReference(mxThis))
886
+ // mxTypeError("this is no object");
887
+ if (mxIsReference(argument)) {
888
+ txSlot* promise = argument->value.reference;
889
+ if (mxIsPromise(promise)) {
890
+ mxPushReference(promise);
891
+ mxGetID(mxID(_constructor));
892
+ if (fxIsSameValue(the, constructor, the->stack, 0)) {
893
+ *result = *argument;
894
+ mxPop();
895
+ return;
896
+ }
897
+ mxPop();
898
+ }
899
+ }
900
+ mxTemporary(resolveFunction);
901
+ mxTemporary(rejectFunction);
902
+ mxPushSlot(constructor);
903
+ fxNewPromiseCapability(the, resolveFunction, rejectFunction);
904
+ *result = *the->stack;
905
+ mxPop();
906
+ /* THIS */
907
+ mxPushUndefined();
908
+ /* FUNCTION */
909
+ mxPushSlot(resolveFunction);
910
+ mxCall();
911
+ /* ARGUMENTS */
912
+ mxPushSlot(argument);
913
+ /* COUNT */
914
+ mxRunCount(1);
915
+ mxPop();
916
+ mxPop(); // rejectFunction
917
+ mxPop(); // resolveFunction
918
+ }
919
+
920
+ void fx_Promise_prototype_catch(txMachine* the)
921
+ {
922
+ mxPushSlot(mxThis);
923
+ mxDub();
924
+ mxGetID(mxID(_then));
925
+ mxCall();
926
+ mxPushUndefined();
927
+ if (mxArgc > 0)
928
+ mxPushSlot(mxArgv(0));
929
+ else
930
+ mxPushUndefined();
931
+ mxRunCount(2);
932
+ mxPullSlot(mxResult);
933
+ }
934
+
935
+ #if 0
936
+ void fx_Promise_prototype_dumpAux(txMachine* the, txSlot* promise, txInteger c)
937
+ {
938
+ txInteger i;
939
+ txSlot* reference;
940
+ for (i = 0; i < c; i++)
941
+ fprintf(stderr, "\t");
942
+ fprintf(stderr, "promise %d\n", promise->next->ID);
943
+ reference = mxPromiseThens(promise)->value.reference->next;
944
+ c++;
945
+ while (reference) {
946
+ fx_Promise_prototype_dumpAux(the, reference->value.reference, c);
947
+ reference = reference->next;
948
+ }
949
+ }
950
+ #endif
951
+
952
+ void fx_Promise_prototype_finally(txMachine* the)
953
+ {
954
+ txSlot* constructor;
955
+ if (!mxIsReference(mxThis))
956
+ mxTypeError("this is no object");
957
+ mxPushSlot(mxThis);
958
+ mxGetID(mxID(_constructor));
959
+ fxToSpeciesConstructor(the, &mxPromiseConstructor);
960
+ constructor = the->stack;
961
+
962
+ mxPushSlot(mxThis);
963
+ mxDub();
964
+ mxGetID(mxID(_then));
965
+ mxCall();
966
+ if (mxArgc > 0) {
967
+ if (mxIsReference(mxArgv(0)) && mxIsCallable(mxArgv(0)->value.reference)) {
968
+ txSlot* function = fxNewHostFunction(the, fx_Promise_prototype_finallyAux, 1, XS_NO_ID, mx_Promise_prototype_finallyAuxProfileID);
969
+ txSlot* object = fxNewInstance(the);
970
+ txSlot* slot = object->next = fxNewSlot(the);
971
+ slot->kind = XS_REFERENCE_KIND;
972
+ slot->value.reference = constructor->value.reference;
973
+ slot = slot->next = fxNewSlot(the);
974
+ slot->kind = XS_REFERENCE_KIND;
975
+ slot->value.reference = mxArgv(0)->value.reference;
976
+ slot = slot->next = fxNewSlot(the);
977
+ slot->kind = XS_BOOLEAN_KIND;
978
+ slot->value.boolean = 1;
979
+ slot = mxFunctionInstanceHome(function);
980
+ slot->value.home.object = object;
981
+ mxPop();
982
+
983
+ function = fxNewHostFunction(the, fx_Promise_prototype_finallyAux, 1, XS_NO_ID, mx_Promise_prototype_finallyAuxProfileID);
984
+ object = fxNewInstance(the);
985
+ slot = object->next = fxNewSlot(the);
986
+ slot->kind = XS_REFERENCE_KIND;
987
+ slot->value.reference = constructor->value.reference;
988
+ slot = slot->next = fxNewSlot(the);
989
+ slot->kind = XS_REFERENCE_KIND;
990
+ slot->value.reference = mxArgv(0)->value.reference;
991
+ slot = slot->next = fxNewSlot(the);
992
+ slot->kind = XS_BOOLEAN_KIND;
993
+ slot->value.boolean = 0;
994
+ slot = mxFunctionInstanceHome(function);
995
+ slot->value.home.object = object;
996
+ mxPop();
997
+ }
998
+ else {
999
+ mxPushSlot(mxArgv(0));
1000
+ mxPushSlot(mxArgv(0));
1001
+ }
1002
+ }
1003
+ else {
1004
+ mxPushUndefined();
1005
+ mxPushUndefined();
1006
+ }
1007
+ mxRunCount(2);
1008
+ mxPullSlot(mxResult);
1009
+ }
1010
+
1011
+ void fx_Promise_prototype_finallyAux(txMachine* the)
1012
+ {
1013
+ txSlot* object = mxFunctionInstanceHome(mxFunction->value.reference)->value.home.object;
1014
+ txSlot* constructor = object->next;
1015
+ txSlot* onFinally = constructor->next;
1016
+ txSlot* success = onFinally->next;
1017
+ txSlot* argument;
1018
+ txSlot* function;
1019
+ txSlot* slot;
1020
+ txSlot* home;
1021
+
1022
+ {
1023
+ mxTry(the) {
1024
+ mxPushUndefined();
1025
+ mxPushSlot(onFinally);
1026
+ mxCall();
1027
+ mxRunCount(0);
1028
+ }
1029
+ mxCatch(the) {
1030
+ mxArgv(0)->kind = mxException.kind;
1031
+ mxArgv(0)->value = mxException.value;
1032
+ success->value.boolean = 0;
1033
+ mxPush(mxException);
1034
+ mxException = mxUndefined;
1035
+ }
1036
+ }
1037
+ argument = the->stack;
1038
+
1039
+ mxPushUndefined();
1040
+ mxPushSlot(constructor);
1041
+ mxPushSlot(argument);
1042
+ fx_Promise_resolveAux(the);
1043
+ mxPop();
1044
+ mxPop();
1045
+ mxDub();
1046
+ mxGetID(mxID(_then));
1047
+ mxCall();
1048
+
1049
+ if (success->value.boolean)
1050
+ function = fxNewHostFunction(the, fx_Promise_prototype_finallyReturn, 0, XS_NO_ID, mx_Promise_prototype_finallyReturnProfileID);
1051
+ else
1052
+ function = fxNewHostFunction(the, fx_Promise_prototype_finallyThrow, 0, XS_NO_ID, mx_Promise_prototype_finallyThrowProfileID);
1053
+ object = fxNewInstance(the);
1054
+ slot = object->next = fxNewSlot(the);
1055
+ slot->kind = mxArgv(0)->kind;
1056
+ slot->value = mxArgv(0)->value;
1057
+ home = mxFunctionInstanceHome(function);
1058
+ home->value.home.object = object;
1059
+ mxPop();
1060
+ mxRunCount(1);
1061
+
1062
+ mxPullSlot(mxResult);
1063
+ }
1064
+
1065
+ void fx_Promise_prototype_finallyReturn(txMachine* the)
1066
+ {
1067
+ txSlot* object = mxFunctionInstanceHome(mxFunction->value.reference)->value.home.object;
1068
+ txSlot* slot = object->next;
1069
+ mxResult->kind = slot->kind;
1070
+ mxResult->value = slot->value;
1071
+ }
1072
+
1073
+ void fx_Promise_prototype_finallyThrow(txMachine* the)
1074
+ {
1075
+ txSlot* object = mxFunctionInstanceHome(mxFunction->value.reference)->value.home.object;
1076
+ txSlot* slot = object->next;
1077
+ mxException.kind = slot->kind;
1078
+ mxException.value = slot->value;
1079
+ fxThrow(the, NULL, 0);
1080
+ }
1081
+
1082
+ void fx_Promise_prototype_then(txMachine* the)
1083
+ {
1084
+ txSlot* promise;
1085
+ txSlot* onFullfilled = C_NULL;
1086
+ txSlot* onRejected = C_NULL;
1087
+ txSlot* resolveFunction;
1088
+ txSlot* rejectFunction;
1089
+
1090
+ if (!mxIsReference(mxThis))
1091
+ mxTypeError("this is no object");
1092
+ promise = mxThis->value.reference;
1093
+ if (!mxIsPromise(promise))
1094
+ mxTypeError("this is no promise");
1095
+ #ifdef mxPromisePrint
1096
+ fprintf(stderr, "fx_Promise_prototype_then %d\n", promise->next->ID);
1097
+ #endif
1098
+
1099
+ if ((mxArgc > 0) && mxIsReference(mxArgv(0))) {
1100
+ onFullfilled = mxArgv(0);
1101
+ }
1102
+ if ((mxArgc > 1) && mxIsReference(mxArgv(1))) {
1103
+ onRejected = mxArgv(1);
1104
+ }
1105
+
1106
+ mxTemporary(resolveFunction);
1107
+ mxTemporary(rejectFunction);
1108
+ mxPushSlot(mxThis);
1109
+ mxGetID(mxID(_constructor));
1110
+ fxToSpeciesConstructor(the, &mxPromiseConstructor);
1111
+ fxNewPromiseCapability(the, resolveFunction, rejectFunction);
1112
+ mxPullSlot(mxResult);
1113
+
1114
+ fxPromiseThen(the, promise, onFullfilled, onRejected, resolveFunction, rejectFunction);
1115
+ }
1116
+
1117
+ void fxQueueJob(txMachine* the, txInteger count, txSlot* promise)
1118
+ {
1119
+ txSlot* slot;
1120
+ txSlot* job;
1121
+ txSlot* item;
1122
+ txSlot* stack;
1123
+ txSlot** address;
1124
+
1125
+ if (promise) {
1126
+ txSlot* list = &mxUnhandledPromises;
1127
+ txSlot** address = &list->value.reference->next;
1128
+ while ((slot = *address)) {
1129
+ if (slot->value.weakRef.target == promise) {
1130
+ slot = slot->next;
1131
+ *address = slot->next;
1132
+ break;
1133
+ }
1134
+ slot = slot->next;
1135
+ address = &slot->next;
1136
+ }
1137
+ #ifdef mxPromisePrint
1138
+ fprintf(stderr, "fxQueueJob %d\n", promise->next->ID);
1139
+ #endif
1140
+ }
1141
+ if (mxPendingJobs.value.reference->next == NULL) {
1142
+ fxQueuePromiseJobs(the);
1143
+ }
1144
+ count += 6;
1145
+ item = stack = the->stack + count;
1146
+ slot = job = fxNewInstance(the);
1147
+ while (count > 0) {
1148
+ item--;
1149
+ slot = slot->next = fxNewSlot(the);
1150
+ slot->kind = item->kind;
1151
+ slot->value = item->value;
1152
+ count--;
1153
+ }
1154
+ address = &(mxPendingJobs.value.reference->next);
1155
+ while ((slot = *address))
1156
+ address = &(slot->next);
1157
+ slot = *address = fxNewSlot(the);
1158
+ slot->kind = XS_REFERENCE_KIND;
1159
+ slot->value.reference = job;
1160
+ the->stack = stack;
1161
+ }
1162
+
1163
+ void fxRunPromiseJobs(txMachine* the)
1164
+ {
1165
+ txSlot* job;
1166
+ txSlot* slot;
1167
+ txInteger count;
1168
+
1169
+ #ifdef mxPromisePrint
1170
+ fprintf(stderr, "\n# fxRunPromiseJobs\n");
1171
+ #endif
1172
+ job = mxRunningJobs.value.reference->next = mxPendingJobs.value.reference->next;
1173
+ mxPendingJobs.value.reference->next = C_NULL;
1174
+ while (job) {
1175
+ mxTry(the) {
1176
+ count = 0;
1177
+ slot = job->value.reference->next;
1178
+ while (slot) {
1179
+ mxPushSlot(slot);
1180
+ count++;
1181
+ slot = slot->next;
1182
+ }
1183
+ mxRunCount(count - 6);
1184
+ mxPop();
1185
+ if (mxDuringJobs.kind == XS_REFERENCE_KIND)
1186
+ mxDuringJobs.value.reference->next = C_NULL;
1187
+ }
1188
+ mxCatch(the) {
1189
+ fxAbort(the, XS_UNHANDLED_EXCEPTION_EXIT);
1190
+ }
1191
+ job = job->next;
1192
+ }
1193
+ mxRunningJobs.value.reference->next = C_NULL;
1194
+ }
1195
+
1196
+
1197
+
1198
+
1199
+