@agoric/xsnap 0.14.3-u14.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 +37 -20
  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 -654
@@ -0,0 +1,1649 @@
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
+ #ifndef mxTableMinLength
41
+ #define mxTableMinLength (1)
42
+ #endif
43
+ #ifndef mxTableMaxLength
44
+ #define mxTableMaxLength (1024 * 1024)
45
+ #endif
46
+ #define mxTableThreshold(LENGTH) (((LENGTH) >> 1) + ((LENGTH) >> 2))
47
+
48
+ static txSlot* fxCheckMapInstance(txMachine* the, txSlot* slot, txBoolean mutable);
49
+ static txSlot* fxCheckMapKey(txMachine* the);
50
+ static txSlot* fxNewMapIteratorInstance(txMachine* the, txSlot* iterable, txInteger kind);
51
+
52
+ static txSlot* fxCheckSetInstance(txMachine* the, txSlot* slot, txBoolean mutable);
53
+ static txSlot* fxCheckSetValue(txMachine* the);
54
+ static txSlot* fxNewSetIteratorInstance(txMachine* the, txSlot* iterable, txInteger kind);
55
+
56
+ static void fxClearEntries(txMachine* the, txSlot* table, txSlot* list, txBoolean paired);
57
+ static txBoolean fxDeleteEntry(txMachine* the, txSlot* table, txSlot* list, txSlot* slot, txBoolean paired);
58
+ static txSlot* fxGetEntry(txMachine* the, txSlot* table, txSlot* slot);
59
+ static void fxPurgeEntries(txMachine* the, txSlot* list);
60
+ static void fxResizeEntries(txMachine* the, txSlot* table, txSlot* list);
61
+ static void fxSetEntry(txMachine* the, txSlot* table, txSlot* list, txSlot* slot, txSlot* pair);
62
+ static txBoolean fxTestEntry(txMachine* the, txSlot* a, txSlot* b);
63
+
64
+ static txSlot* fxCheckWeakMapInstance(txMachine* the, txSlot* slot, txBoolean mutable);
65
+ static txSlot* fxCheckWeakMapKey(txMachine* the, txBoolean mutable);
66
+
67
+ static txSlot* fxCheckWeakSetInstance(txMachine* the, txSlot* slot, txBoolean mutable);
68
+ static txSlot* fxCheckWeakSetValue(txMachine* the, txBoolean mutable);
69
+
70
+ static txBoolean fxDeleteWeakEntry(txMachine* the, txSlot* link, txSlot* slot);
71
+ static txSlot* fxGetWeakEntry(txMachine* the, txSlot* link, txSlot* slot);
72
+ static void fxSetWeakEntry(txMachine* the, txSlot* link, txSlot* slot, txSlot* pair);
73
+
74
+ static void fxKeepDuringJobs(txMachine* the, txSlot* target);
75
+ static txSlot* fxNewWeakRefInstance(txMachine* the);
76
+
77
+ static void fx_FinalizationRegistryCleanup(txMachine* the, txSlot* registry, txSlot* callback);
78
+
79
+ void fxBuildMapSet(txMachine* the)
80
+ {
81
+ txSlot* slot;
82
+ txSlot* property;
83
+
84
+ /* MAP */
85
+ mxPush(mxObjectPrototype);
86
+ slot = fxLastProperty(the, fxNewObjectInstance(the));
87
+ slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_Map_prototype_size), C_NULL, mxID(_size), XS_DONT_ENUM_FLAG);
88
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Map_prototype_clear), 0, mxID(_clear), XS_DONT_ENUM_FLAG);
89
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Map_prototype_delete), 1, mxID(_delete), XS_DONT_ENUM_FLAG);
90
+ property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Map_prototype_entries), 0, mxID(_entries), XS_DONT_ENUM_FLAG);
91
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Map_prototype_forEach), 1, mxID(_forEach), XS_DONT_ENUM_FLAG);
92
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Map_prototype_get), 1, mxID(_get), XS_DONT_ENUM_FLAG);
93
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Map_prototype_has), 1, mxID(_has), XS_DONT_ENUM_FLAG);
94
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Map_prototype_keys), 0, mxID(_keys), XS_DONT_ENUM_FLAG);
95
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Map_prototype_set), 2, mxID(_set), XS_DONT_ENUM_FLAG);
96
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Map_prototype_values), 0, mxID(_values), XS_DONT_ENUM_FLAG);
97
+ slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_iterator), XS_DONT_ENUM_FLAG);
98
+ slot = fxNextStringXProperty(the, slot, "Map", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
99
+ mxMapPrototype = *the->stack;
100
+ slot = fxBuildHostConstructor(the, mxCallback(fx_Map), 0, mxID(_Map));
101
+ mxMapConstructor = *the->stack;
102
+ slot = fxLastProperty(the, slot);
103
+ slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_species_get), C_NULL, mxID(_Symbol_species), XS_DONT_ENUM_FLAG);
104
+ mxPop();
105
+
106
+ mxPush(mxIteratorPrototype);
107
+ slot = fxLastProperty(the, fxNewObjectInstance(the));
108
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_MapIterator_prototype_next), 0, mxID(_next), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG);
109
+ slot = fxNextStringXProperty(the, slot, "Map Iterator", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
110
+ mxPull(mxMapIteratorPrototype);
111
+
112
+ /* SET */
113
+ mxPush(mxObjectPrototype);
114
+ slot = fxLastProperty(the, fxNewObjectInstance(the));
115
+ slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_Set_prototype_size), C_NULL, mxID(_size), XS_DONT_ENUM_FLAG);
116
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Set_prototype_add), 1, mxID(_add), XS_DONT_ENUM_FLAG);
117
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Set_prototype_clear), 0, mxID(_clear), XS_DONT_ENUM_FLAG);
118
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Set_prototype_delete), 1, mxID(_delete), XS_DONT_ENUM_FLAG);
119
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Set_prototype_entries), 0, mxID(_entries), XS_DONT_ENUM_FLAG);
120
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Set_prototype_forEach), 1, mxID(_forEach), XS_DONT_ENUM_FLAG);
121
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Set_prototype_has), 1, mxID(_has), XS_DONT_ENUM_FLAG);
122
+ property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Set_prototype_values), 0, mxID(_values), XS_DONT_ENUM_FLAG);
123
+ slot = fxNextSlotProperty(the, slot, property, mxID(_keys), XS_DONT_ENUM_FLAG);
124
+ slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_iterator), XS_DONT_ENUM_FLAG);
125
+ slot = fxNextStringXProperty(the, slot, "Set", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
126
+ mxSetPrototype = *the->stack;
127
+ slot = fxBuildHostConstructor(the, mxCallback(fx_Set), 0, mxID(_Set));
128
+ mxSetConstructor = *the->stack;
129
+ slot = fxLastProperty(the, slot);
130
+ slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_species_get), C_NULL, mxID(_Symbol_species), XS_DONT_ENUM_FLAG);
131
+ mxPop();
132
+
133
+ mxPush(mxIteratorPrototype);
134
+ slot = fxLastProperty(the, fxNewObjectInstance(the));
135
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_SetIterator_prototype_next), 0, mxID(_next), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG);
136
+ slot = fxNextStringXProperty(the, slot, "Set Iterator", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
137
+ mxPull(mxSetIteratorPrototype);
138
+
139
+ /* WEAK MAP */
140
+ mxPush(mxObjectPrototype);
141
+ slot = fxLastProperty(the, fxNewObjectInstance(the));
142
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_WeakMap_prototype_delete), 1, mxID(_delete), XS_DONT_ENUM_FLAG);
143
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_WeakMap_prototype_get), 1, mxID(_get), XS_DONT_ENUM_FLAG);
144
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_WeakMap_prototype_has), 1, mxID(_has), XS_DONT_ENUM_FLAG);
145
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_WeakMap_prototype_set), 2, mxID(_set), XS_DONT_ENUM_FLAG);
146
+ slot = fxNextStringXProperty(the, slot, "WeakMap", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
147
+ mxWeakMapPrototype = *the->stack;
148
+ slot = fxBuildHostConstructor(the, mxCallback(fx_WeakMap), 0, mxID(_WeakMap));
149
+ mxWeakMapConstructor = *the->stack;
150
+ mxPop();
151
+
152
+ /* WEAK SET */
153
+ mxPush(mxObjectPrototype);
154
+ slot = fxLastProperty(the, fxNewObjectInstance(the));
155
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_WeakSet_prototype_add), 1, mxID(_add), XS_DONT_ENUM_FLAG);
156
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_WeakSet_prototype_delete), 1, mxID(_delete), XS_DONT_ENUM_FLAG);
157
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_WeakSet_prototype_has), 1, mxID(_has), XS_DONT_ENUM_FLAG);
158
+ slot = fxNextStringXProperty(the, slot, "WeakSet", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
159
+ mxWeakSetPrototype = *the->stack;
160
+ slot = fxBuildHostConstructor(the, mxCallback(fx_WeakSet), 0, mxID(_WeakSet));
161
+ mxWeakSetConstructor = *the->stack;
162
+ mxPop();
163
+
164
+ /* WEAK REF */
165
+ mxPush(mxObjectPrototype);
166
+ slot = fxLastProperty(the, fxNewObjectInstance(the));
167
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_WeakRef_prototype_deref), 0, mxID(_deref), XS_DONT_ENUM_FLAG);
168
+ slot = fxNextStringXProperty(the, slot, "WeakRef", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
169
+ mxWeakRefPrototype = *the->stack;
170
+ slot = fxBuildHostConstructor(the, mxCallback(fx_WeakRef), 1, mxID(_WeakRef));
171
+ mxWeakRefConstructor = *the->stack;
172
+ mxPop();
173
+
174
+ /* FINALIZATION REGISTRY */
175
+ mxPush(mxObjectPrototype);
176
+ slot = fxLastProperty(the, fxNewObjectInstance(the));
177
+ // slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_FinalizationRegistry_prototype_cleanupSome), 0, mxID(_cleanupSome), XS_DONT_ENUM_FLAG);
178
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_FinalizationRegistry_prototype_register), 2, mxID(_register), XS_DONT_ENUM_FLAG);
179
+ slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_FinalizationRegistry_prototype_unregister), 1, mxID(_unregister), XS_DONT_ENUM_FLAG);
180
+ slot = fxNextStringXProperty(the, slot, "FinalizationRegistry", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
181
+ mxFinalizationRegistryPrototype = *the->stack;
182
+ slot = fxBuildHostConstructor(the, mxCallback(fx_FinalizationRegistry), 1, mxID(_FinalizationRegistry));
183
+ mxFinalizationRegistryConstructor = *the->stack;
184
+ mxPop();
185
+ }
186
+
187
+ txSlot* fxCheckMapInstance(txMachine* the, txSlot* slot, txBoolean mutable)
188
+ {
189
+ if (slot->kind == XS_REFERENCE_KIND) {
190
+ txSlot* instance = slot->value.reference;
191
+ if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_MAP_KIND) && (instance != mxMapPrototype.value.reference)) {
192
+ if (mutable && (slot->flag & XS_DONT_SET_FLAG))
193
+ mxTypeError("Map instance is read-only");
194
+ return instance;
195
+ }
196
+ }
197
+ mxTypeError("this is no Map instance");
198
+ return C_NULL;
199
+ }
200
+
201
+ txSlot* fxCheckMapKey(txMachine* the)
202
+ {
203
+ if (mxArgc > 0) {
204
+ txSlot* slot = mxArgv(0);
205
+ return slot;
206
+ }
207
+ mxTypeError("no key");
208
+ return C_NULL;
209
+ }
210
+
211
+ txSlot* fxNewMapInstance(txMachine* the)
212
+ {
213
+ txSlot* map;
214
+ txSlot* table;
215
+ txSlot* list;
216
+ txSlot* size;
217
+ txSlot** address;
218
+ map = fxNewSlot(the);
219
+ map->kind = XS_INSTANCE_KIND;
220
+ map->value.instance.garbage = C_NULL;
221
+ map->value.instance.prototype = the->stack->value.reference;
222
+ the->stack->kind = XS_REFERENCE_KIND;
223
+ the->stack->value.reference = map;
224
+ table = map->next = fxNewSlot(the);
225
+ list = table->next = fxNewSlot(the);
226
+ size = list->next = fxNewSlot(the);
227
+ address = (txSlot**)fxNewChunk(the, mxTableMinLength * sizeof(txSlot*));
228
+ c_memset(address, 0, mxTableMinLength * sizeof(txSlot*));
229
+ /* TABLE */
230
+ table->flag = XS_INTERNAL_FLAG;
231
+ table->kind = XS_MAP_KIND;
232
+ table->value.table.address = address;
233
+ table->value.table.length = mxTableMinLength;
234
+ /* LIST */
235
+ list->flag = XS_INTERNAL_FLAG;
236
+ list->kind = XS_LIST_KIND;
237
+ list->value.list.first = C_NULL;
238
+ list->value.list.last = C_NULL;
239
+ /* SIZE */
240
+ size->flag = XS_INTERNAL_FLAG;
241
+ size->kind = XS_INTEGER_KIND;
242
+ size->value.integer = 0;
243
+ return map;
244
+ }
245
+
246
+ void fx_Map(txMachine* the)
247
+ {
248
+ txSlot *function, *iterable, *iterator, *next, *value;
249
+ if (mxIsUndefined(mxTarget))
250
+ mxTypeError("call: Map");
251
+ mxPushSlot(mxTarget);
252
+ fxGetPrototypeFromConstructor(the, &mxMapPrototype);
253
+ fxNewMapInstance(the);
254
+ mxPullSlot(mxResult);
255
+ if (mxArgc < 1)
256
+ return;
257
+ iterable = mxArgv(0);
258
+ if ((iterable->kind == XS_UNDEFINED_KIND) || (iterable->kind == XS_NULL_KIND))
259
+ return;
260
+ mxPushSlot(mxResult);
261
+ mxGetID(mxID(_set));
262
+ function = the->stack;
263
+ if (!fxIsCallable(the, function))
264
+ mxTypeError("set is no function");
265
+ mxTemporary(iterator);
266
+ mxTemporary(next);
267
+ fxGetIterator(the, iterable, iterator, next, 0);
268
+ mxTemporary(value);
269
+ while (fxIteratorNext(the, iterator, next, value)) {
270
+ mxTry(the) {
271
+ if (value->kind != XS_REFERENCE_KIND)
272
+ mxTypeError("item is no object");
273
+ mxPushSlot(mxResult);
274
+ mxPushSlot(function);
275
+ mxCall();
276
+ mxPushSlot(value);
277
+ mxGetIndex(0);
278
+ mxPushSlot(value);
279
+ mxGetIndex(1);
280
+ mxRunCount(2);
281
+ mxPop();
282
+ }
283
+ mxCatch(the) {
284
+ fxIteratorReturn(the, iterator);
285
+ fxJump(the);
286
+ }
287
+ }
288
+ }
289
+
290
+ void fx_Map_prototype_clear(txMachine* the)
291
+ {
292
+ txSlot* instance = fxCheckMapInstance(the, mxThis, XS_MUTABLE);
293
+ txSlot* table = instance->next;
294
+ txSlot* list = table->next;
295
+ fxClearEntries(the, table, list, 1);
296
+ }
297
+
298
+ void fx_Map_prototype_delete(txMachine* the)
299
+ {
300
+ txSlot* instance = fxCheckMapInstance(the, mxThis, XS_MUTABLE);
301
+ txSlot* table = instance->next;
302
+ txSlot* list = table->next;
303
+ txSlot* key = fxCheckMapKey(the);
304
+ mxResult->value.boolean = fxDeleteEntry(the, table, list, key, 1);
305
+ mxResult->kind = XS_BOOLEAN_KIND;
306
+ }
307
+
308
+ void fx_Map_prototype_entries(txMachine* the)
309
+ {
310
+ fxCheckMapInstance(the, mxThis, XS_IMMUTABLE);
311
+ fxNewMapIteratorInstance(the, mxThis, 2);
312
+ }
313
+
314
+ void fx_Map_prototype_forEach(txMachine* the)
315
+ {
316
+ txSlot* instance = fxCheckMapInstance(the, mxThis, XS_IMMUTABLE);
317
+ txSlot* table = instance->next;
318
+ txSlot* list = table->next;
319
+ txSlot* function = fxArgToCallback(the, 0);
320
+ txSlot* key;
321
+ txSlot* value;
322
+ mxPushList();
323
+ key = the->stack->value.list.first = list->value.list.first;
324
+ while (key) {
325
+ value = key->next;
326
+ if (!(key->flag & XS_DONT_ENUM_FLAG)) {
327
+ /* THIS */
328
+ if (mxArgc > 1)
329
+ mxPushSlot(mxArgv(1));
330
+ else
331
+ mxPushUndefined();
332
+ /* FUNCTION */
333
+ mxPushSlot(function);
334
+ mxCall();
335
+ /* ARGUMENTS */
336
+ mxPushSlot(value);
337
+ mxPushSlot(key);
338
+ mxPushSlot(mxThis);
339
+ mxRunCount(3);
340
+ mxPop();
341
+ }
342
+ key = the->stack->value.list.first = value->next;
343
+ }
344
+ mxPop();
345
+ }
346
+
347
+ void fx_Map_prototype_get(txMachine* the)
348
+ {
349
+ txSlot* instance = fxCheckMapInstance(the, mxThis, XS_IMMUTABLE);
350
+ txSlot* table = instance->next;
351
+ txSlot* key = fxCheckMapKey(the);
352
+ txSlot* result = fxGetEntry(the, table, key);
353
+ if (result) {
354
+ txSlot* value = result->next;
355
+ mxResult->kind = value->kind;
356
+ mxResult->value = value->value;
357
+ }
358
+ }
359
+
360
+ void fx_Map_prototype_has(txMachine* the)
361
+ {
362
+ txSlot* instance = fxCheckMapInstance(the, mxThis, XS_IMMUTABLE);
363
+ txSlot* table = instance->next;
364
+ txSlot* key = fxCheckMapKey(the);
365
+ txSlot* result = fxGetEntry(the, table, key);
366
+ mxResult->kind = XS_BOOLEAN_KIND;
367
+ mxResult->value.boolean = (result) ? 1 : 0;
368
+ }
369
+
370
+ void fx_Map_prototype_keys(txMachine* the)
371
+ {
372
+ fxCheckMapInstance(the, mxThis, XS_IMMUTABLE);
373
+ fxNewMapIteratorInstance(the, mxThis, 0);
374
+ }
375
+
376
+ void fx_Map_prototype_set(txMachine* the)
377
+ {
378
+ txSlot* instance = fxCheckMapInstance(the, mxThis, XS_MUTABLE);
379
+ txSlot* table = instance->next;
380
+ txSlot* list = table->next;
381
+ txSlot* key = fxCheckMapKey(the);
382
+ fxSetEntry(the, table, list, key, (mxArgc > 1) ? mxArgv(1) : &mxUndefined);
383
+ *mxResult = *mxThis;
384
+ }
385
+
386
+ void fx_Map_prototype_size(txMachine* the)
387
+ {
388
+ txSlot* instance = fxCheckMapInstance(the, mxThis, XS_IMMUTABLE);
389
+ txSlot* table = instance->next;
390
+ txSlot* list = table->next;
391
+ mxResult->kind = XS_INTEGER_KIND;
392
+ mxResult->value.integer = list->next->value.integer;
393
+ }
394
+
395
+ void fx_Map_prototype_values(txMachine* the)
396
+ {
397
+ fxCheckMapInstance(the, mxThis, XS_IMMUTABLE);
398
+ fxNewMapIteratorInstance(the, mxThis, 1);
399
+ }
400
+
401
+ txSlot* fxNewMapIteratorInstance(txMachine* the, txSlot* iterable, txInteger kind)
402
+ {
403
+ txSlot* instance;
404
+ txSlot* property;
405
+ mxPush(mxMapIteratorPrototype);
406
+ instance = fxNewIteratorInstance(the, iterable, mxID(_Map));
407
+ property = fxLastProperty(the, instance);
408
+ property->kind = XS_LIST_KIND;
409
+ property->value.list.first = C_NULL;
410
+ property->value.list.last = C_NULL;
411
+ property = fxNextIntegerProperty(the, property, kind, XS_NO_ID, XS_INTERNAL_FLAG);
412
+ mxPullSlot(mxResult);
413
+ return instance;
414
+ }
415
+
416
+ void fx_MapIterator_prototype_next(txMachine* the)
417
+ {
418
+ txSlot* iterator = fxCheckIteratorInstance(the, mxThis, mxID(_Map));
419
+ txSlot* result = iterator->next;
420
+ txSlot* iterable = result->next;
421
+ mxResult->kind = result->kind;
422
+ mxResult->value = result->value;
423
+ result = fxCheckIteratorResult(the, result);
424
+ if (result->next->value.boolean == 0) {
425
+ txSlot* list = iterable->next;
426
+ txInteger kind = list->next->value.integer;
427
+ txSlot* key = list->value.list.first;
428
+ if (key)
429
+ key = key->next->next;
430
+ else
431
+ key = iterable->value.reference->next->next->value.list.first;
432
+ while (key && (key->flag & XS_DONT_ENUM_FLAG))
433
+ key = key->next->next;
434
+ if (key) {
435
+ txSlot* value = key->next;
436
+ if (kind == 2) {
437
+ mxPushSlot(key);
438
+ mxPushSlot(value);
439
+ fxConstructArrayEntry(the, result);
440
+ }
441
+ else if (kind == 1) {
442
+ result->kind = value->kind;
443
+ result->value = value->value;
444
+ }
445
+ else {
446
+ result->kind = key->kind;
447
+ result->value = key->value;
448
+ }
449
+ list->value.list.first = key;
450
+ }
451
+ else {
452
+ result->kind = XS_UNDEFINED_KIND;
453
+ result->next->value.boolean = 1;
454
+ list->value.list.first = C_NULL;
455
+ }
456
+ }
457
+ }
458
+
459
+ txSlot* fxCheckSetInstance(txMachine* the, txSlot* slot, txBoolean mutable)
460
+ {
461
+ if (slot->kind == XS_REFERENCE_KIND) {
462
+ txSlot* instance = slot->value.reference;
463
+ if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_SET_KIND) && (instance != mxSetPrototype.value.reference)) {
464
+ if (mutable && (slot->flag & XS_DONT_SET_FLAG))
465
+ mxTypeError("Set instance is read-only");
466
+ return instance;
467
+ }
468
+ }
469
+ mxTypeError("this is no Set instance");
470
+ return C_NULL;
471
+ }
472
+
473
+ txSlot* fxCheckSetValue(txMachine* the)
474
+ {
475
+ if (mxArgc > 0) {
476
+ txSlot* slot = mxArgv(0);
477
+ return slot;
478
+ }
479
+ mxTypeError("no value");
480
+ return C_NULL;
481
+ }
482
+
483
+ txSlot* fxNewSetInstance(txMachine* the)
484
+ {
485
+ txSlot* set;
486
+ txSlot* table;
487
+ txSlot* list;
488
+ txSlot* size;
489
+ txSlot** address;
490
+ set = fxNewSlot(the);
491
+ set->kind = XS_INSTANCE_KIND;
492
+ set->value.instance.garbage = C_NULL;
493
+ set->value.instance.prototype = the->stack->value.reference;
494
+ the->stack->kind = XS_REFERENCE_KIND;
495
+ the->stack->value.reference = set;
496
+ table = set->next = fxNewSlot(the);
497
+ list = table->next = fxNewSlot(the);
498
+ size = list->next = fxNewSlot(the);
499
+ address = (txSlot**)fxNewChunk(the, mxTableMinLength * sizeof(txSlot*));
500
+ c_memset(address, 0, mxTableMinLength * sizeof(txSlot*));
501
+ /* TABLE */
502
+ table->flag = XS_INTERNAL_FLAG;
503
+ table->kind = XS_SET_KIND;
504
+ table->value.table.address = address;
505
+ table->value.table.length = mxTableMinLength;
506
+ /* LIST */
507
+ list->flag = XS_INTERNAL_FLAG;
508
+ list->kind = XS_LIST_KIND;
509
+ list->value.list.first = C_NULL;
510
+ list->value.list.last = C_NULL;
511
+ /* SIZE */
512
+ size->flag = XS_INTERNAL_FLAG;
513
+ size->kind = XS_INTEGER_KIND;
514
+ size->value.integer = 0;
515
+ return set;
516
+ }
517
+
518
+ void fx_Set(txMachine* the)
519
+ {
520
+ txSlot *function, *iterable, *iterator, *next, *value;
521
+ if (mxIsUndefined(mxTarget))
522
+ mxTypeError("call: Set");
523
+ mxPushSlot(mxTarget);
524
+ fxGetPrototypeFromConstructor(the, &mxSetPrototype);
525
+ fxNewSetInstance(the);
526
+ mxPullSlot(mxResult);
527
+ if (mxArgc < 1)
528
+ return;
529
+ iterable = mxArgv(0);
530
+ if ((iterable->kind == XS_UNDEFINED_KIND) || (iterable->kind == XS_NULL_KIND))
531
+ return;
532
+ mxPushSlot(mxResult);
533
+ mxGetID(mxID(_add));
534
+ function = the->stack;
535
+ if (!fxIsCallable(the, function))
536
+ mxTypeError("add is no function");
537
+ mxTemporary(iterator);
538
+ mxTemporary(next);
539
+ fxGetIterator(the, iterable, iterator, next, 0);
540
+ mxTemporary(value);
541
+ while (fxIteratorNext(the, iterator, next, value)) {
542
+ mxTry(the) {
543
+ mxPushSlot(mxResult);
544
+ mxPushSlot(function);
545
+ mxCall();
546
+ mxPushSlot(value);
547
+ mxRunCount(1);
548
+ mxPop();
549
+ }
550
+ mxCatch(the) {
551
+ fxIteratorReturn(the, iterator);
552
+ fxJump(the);
553
+ }
554
+ }
555
+ }
556
+
557
+ void fx_Set_prototype_add(txMachine* the)
558
+ {
559
+ txSlot* instance = fxCheckSetInstance(the, mxThis, XS_MUTABLE);
560
+ txSlot* table = instance->next;
561
+ txSlot* list = table->next;
562
+ txSlot* value = fxCheckSetValue(the);
563
+ fxSetEntry(the, table, list, value, C_NULL);
564
+ *mxResult = *mxThis;
565
+ }
566
+
567
+ void fx_Set_prototype_clear(txMachine* the)
568
+ {
569
+ txSlot* instance = fxCheckSetInstance(the, mxThis, XS_MUTABLE);
570
+ txSlot* table = instance->next;
571
+ txSlot* list = table->next;
572
+ fxClearEntries(the, table, list, 0);
573
+ }
574
+
575
+ void fx_Set_prototype_delete(txMachine* the)
576
+ {
577
+ txSlot* instance = fxCheckSetInstance(the, mxThis, XS_MUTABLE);
578
+ txSlot* table = instance->next;
579
+ txSlot* list = table->next;
580
+ txSlot* value = fxCheckSetValue(the);
581
+ mxResult->value.boolean = fxDeleteEntry(the, table, list, value, 0);
582
+ mxResult->kind = XS_BOOLEAN_KIND;
583
+ }
584
+
585
+ void fx_Set_prototype_entries(txMachine* the)
586
+ {
587
+ fxCheckSetInstance(the, mxThis, XS_IMMUTABLE);
588
+ fxNewSetIteratorInstance(the, mxThis, 2);
589
+ }
590
+
591
+ void fx_Set_prototype_forEach(txMachine* the)
592
+ {
593
+ txSlot* instance = fxCheckSetInstance(the, mxThis, XS_IMMUTABLE);
594
+ txSlot* table = instance->next;
595
+ txSlot* list = table->next;
596
+ txSlot* function = fxArgToCallback(the, 0);
597
+ txSlot* value;
598
+ mxPushList();
599
+ value = the->stack->value.list.first = list->value.list.first;
600
+ while (value) {
601
+ if (!(value->flag & XS_DONT_ENUM_FLAG)) {
602
+ /* THIS */
603
+ if (mxArgc > 1)
604
+ mxPushSlot(mxArgv(1));
605
+ else
606
+ mxPushUndefined();
607
+ /* FUNCTION */
608
+ mxPushSlot(function);
609
+ mxCall();
610
+ /* ARGUMENTS */
611
+ mxPushSlot(value);
612
+ mxPushSlot(value);
613
+ mxPushSlot(mxThis);
614
+ mxRunCount(3);
615
+ mxPop();
616
+ }
617
+ value = the->stack->value.list.first = value->next;
618
+ }
619
+ mxPop();
620
+ }
621
+
622
+ void fx_Set_prototype_has(txMachine* the)
623
+ {
624
+ txSlot* instance = fxCheckSetInstance(the, mxThis, XS_IMMUTABLE);
625
+ txSlot* table = instance->next;
626
+ txSlot* value = fxCheckSetValue(the);
627
+ txSlot* result = fxGetEntry(the, table, value);
628
+ mxResult->kind = XS_BOOLEAN_KIND;
629
+ mxResult->value.boolean = (result) ? 1 : 0;
630
+ }
631
+
632
+ void fx_Set_prototype_size(txMachine* the)
633
+ {
634
+ txSlot* instance = fxCheckSetInstance(the, mxThis, XS_IMMUTABLE);
635
+ txSlot* table = instance->next;
636
+ txSlot* list = table->next;
637
+ mxResult->kind = XS_INTEGER_KIND;
638
+ mxResult->value.integer = list->next->value.integer;
639
+ }
640
+
641
+ void fx_Set_prototype_values(txMachine* the)
642
+ {
643
+ fxCheckSetInstance(the, mxThis, XS_IMMUTABLE);
644
+ fxNewSetIteratorInstance(the, mxThis, 1);
645
+ }
646
+
647
+ txSlot* fxNewSetIteratorInstance(txMachine* the, txSlot* iterable, txInteger kind)
648
+ {
649
+ txSlot* instance;
650
+ txSlot* property;
651
+ mxPush(mxSetIteratorPrototype);
652
+ instance = fxNewIteratorInstance(the, iterable, mxID(_Set));
653
+ property = fxLastProperty(the, instance);
654
+ property->kind = XS_LIST_KIND;
655
+ property->value.list.first = C_NULL;
656
+ property->value.list.last = C_NULL;
657
+ property = fxNextIntegerProperty(the, property, kind, XS_NO_ID, XS_INTERNAL_FLAG);
658
+ mxPullSlot(mxResult);
659
+ return instance;
660
+ }
661
+
662
+ void fx_SetIterator_prototype_next(txMachine* the)
663
+ {
664
+ txSlot* iterator = fxCheckIteratorInstance(the, mxThis, mxID(_Set));
665
+ txSlot* result = iterator->next;
666
+ txSlot* iterable = result->next;
667
+ mxResult->kind = result->kind;
668
+ mxResult->value = result->value;
669
+ result = fxCheckIteratorResult(the, result);
670
+ if (result->next->value.boolean == 0) {
671
+ txSlot* list = iterable->next;
672
+ txInteger kind = list->next->value.integer;
673
+ txSlot* value = list->value.list.first;
674
+ if (value)
675
+ value = value->next;
676
+ else
677
+ value = iterable->value.reference->next->next->value.list.first;
678
+ while (value && (value->flag & XS_DONT_ENUM_FLAG))
679
+ value = value->next;
680
+ if (value) {
681
+ if (kind == 2) {
682
+ mxPushSlot(value);
683
+ mxPushSlot(value);
684
+ fxConstructArrayEntry(the, result);
685
+ }
686
+ else {
687
+ result->kind = value->kind;
688
+ result->value = value->value;
689
+ }
690
+ list->value.list.first = value;
691
+ }
692
+ else {
693
+ result->kind = XS_UNDEFINED_KIND;
694
+ result->next->value.boolean = 1;
695
+ list->value.list.first = C_NULL;
696
+ }
697
+ }
698
+ }
699
+
700
+ void fxClearEntries(txMachine* the, txSlot* table, txSlot* list, txBoolean paired)
701
+ {
702
+ txSlot* slot = list->value.list.first;
703
+ while (slot) {
704
+ slot->flag = XS_DONT_ENUM_FLAG;
705
+ slot->kind = XS_UNDEFINED_KIND;
706
+ slot = slot->next;
707
+ }
708
+ c_memset(table->value.table.address, 0, table->value.table.length * sizeof(txSlot*));
709
+ list->next->value.integer = 0;
710
+ fxResizeEntries(the, table, list);
711
+ fxPurgeEntries(the, list);
712
+ }
713
+
714
+ txBoolean fxDeleteEntry(txMachine* the, txSlot* table, txSlot* list, txSlot* key, txBoolean paired)
715
+ {
716
+ txSlot* info = list->next;
717
+ txU4 sum = fxSumEntry(the, key);
718
+ txU4 index = sum & (table->value.table.length - 1);
719
+ txSlot** address = &(table->value.table.address[index]);
720
+ txSlot* entry;
721
+ txSlot* first;
722
+ txSlot* last;
723
+ while ((entry = *address)) {
724
+ if (entry->value.entry.sum == sum) {
725
+ first = entry->value.entry.slot;
726
+ if (fxTestEntry(the, first, key)) {
727
+ *address = entry->next;
728
+ entry->next = C_NULL;
729
+ first->flag = XS_DONT_ENUM_FLAG;
730
+ first->kind = XS_UNDEFINED_KIND;
731
+ if (paired) {
732
+ last = first->next;
733
+ last->flag = XS_DONT_ENUM_FLAG;
734
+ last->kind = XS_UNDEFINED_KIND;
735
+ }
736
+ info->value.integer--;
737
+ fxResizeEntries(the, table, list);
738
+ fxPurgeEntries(the, list);
739
+ return 1;
740
+ }
741
+ }
742
+ address = &entry->next;
743
+ }
744
+ return 0;
745
+ }
746
+
747
+ txSlot* fxGetEntry(txMachine* the, txSlot* table, txSlot* slot)
748
+ {
749
+ txU4 sum = fxSumEntry(the, slot);
750
+ txU4 index = sum & (table->value.table.length - 1);
751
+ txSlot* entry = table->value.table.address[index];
752
+ txSlot* result;
753
+ while (entry) {
754
+ if (entry->value.entry.sum == sum) {
755
+ result = entry->value.entry.slot;
756
+ if (fxTestEntry(the, result, slot))
757
+ return result;
758
+ }
759
+ entry = entry->next;
760
+ }
761
+ return C_NULL;
762
+ }
763
+
764
+ void fxPurgeEntries(txMachine* the, txSlot* list)
765
+ {
766
+ txSlot* former = C_NULL;
767
+ txSlot** address = &(list->value.list.first);
768
+ txSlot* slot;
769
+ while ((slot = *address)) {
770
+ if (slot->flag & XS_DONT_ENUM_FLAG) {
771
+ *address = slot->next;
772
+ }
773
+ else {
774
+ former = slot;
775
+ address = &slot->next;
776
+ }
777
+ }
778
+ list->value.list.last = former;
779
+ }
780
+
781
+ void fxResizeEntries(txMachine* the, txSlot* table, txSlot* list)
782
+ {
783
+ txSize size = list->next->value.integer;
784
+ txSize formerLength = table->value.table.length;
785
+ txSize currentLength = formerLength;
786
+ txSize high = mxTableThreshold(formerLength);
787
+ txSize low = mxTableThreshold(formerLength) >> 1;
788
+ if (high < size) {
789
+ currentLength = formerLength << 1;
790
+ if (currentLength > mxTableMaxLength)
791
+ currentLength = mxTableMaxLength;
792
+ }
793
+ else if (low >= size) {
794
+ currentLength = formerLength >> 1;
795
+ if (currentLength < mxTableMinLength)
796
+ currentLength = mxTableMinLength;
797
+ }
798
+ if (formerLength != currentLength) {
799
+ txSlot** currentAddress = (txSlot**)fxNewChunk(the, currentLength * sizeof(txSlot*));
800
+ if (currentAddress) {
801
+ txSlot** formerAddress = table->value.table.address;
802
+
803
+ txSize currentMask = currentLength - 1;
804
+ c_memset(currentAddress, 0, currentLength * sizeof(txSlot*));
805
+ while (formerLength) {
806
+ txSlot* entry;
807
+ while ((entry = *formerAddress)) {
808
+ txU4 index = entry->value.entry.sum & currentMask;
809
+ *formerAddress = entry->next;
810
+ entry->next = currentAddress[index];
811
+ currentAddress[index] = entry;
812
+ }
813
+ formerLength--;
814
+ formerAddress++;
815
+ }
816
+ table->value.table.address = currentAddress;
817
+ table->value.table.length = currentLength;
818
+ }
819
+ }
820
+ // {
821
+ // txSize holes = 0;
822
+ // txSize collisions = 0;
823
+ // txSize i = 0;
824
+ // while (i < table->value.table.length) {
825
+ // txSize j = 0;
826
+ // txSlot* entry = table->value.table.address[i];
827
+ // while (entry) {
828
+ // j++;
829
+ // entry = entry->next;
830
+ // }
831
+ // if (j == 0)
832
+ // holes++;
833
+ // else if (collisions < j)
834
+ // collisions = j;
835
+ // i++;
836
+ // }
837
+ // fprintf(stderr, "# size %d capacity %d holes %d collisions <%d\n", size, table->value.table.length, holes, collisions);
838
+ // }
839
+ }
840
+
841
+ void fxSetEntry(txMachine* the, txSlot* table, txSlot* list, txSlot* key, txSlot* pair)
842
+ {
843
+ txU4 sum = fxSumEntry(the, key);
844
+ txU4 index = sum & (table->value.table.length - 1);
845
+ txSlot** address = &(table->value.table.address[index]);
846
+ txSlot* entry = *address;
847
+ txSlot* first;
848
+ txSlot* last;
849
+ while (entry) {
850
+ if (entry->value.entry.sum == sum) {
851
+ first = entry->value.entry.slot;
852
+ if (fxTestEntry(the, first, key)) {
853
+ if (pair) {
854
+ last = first->next;
855
+ last->kind = pair->kind;
856
+ last->value = pair->value;
857
+ }
858
+ return;
859
+ }
860
+ }
861
+ entry = entry->next;
862
+ }
863
+ first = fxNewSlot(the);
864
+ first->kind = key->kind;
865
+ first->value = key->value;
866
+ mxPushClosure(first);
867
+ if (pair) {
868
+ first->next = last = fxNewSlot(the);
869
+ last->kind = pair->kind;
870
+ last->value = pair->value;
871
+ mxPushClosure(last);
872
+ }
873
+ entry = fxNewSlot(the);
874
+ address = &(table->value.table.address[index]);
875
+ entry->next = *address;
876
+ entry->kind = XS_ENTRY_KIND;
877
+ entry->value.entry.slot = first;
878
+ entry->value.entry.sum = sum;
879
+ *address = entry;
880
+ if (list->value.list.last)
881
+ list->value.list.last->next = first;
882
+ else
883
+ list->value.list.first = first;
884
+ if (pair)
885
+ list->value.list.last = last;
886
+ else
887
+ list->value.list.last = first;
888
+ if (pair)
889
+ mxPop();
890
+ mxPop();
891
+ list->next->value.integer++;
892
+ fxResizeEntries(the, table, list);
893
+ }
894
+
895
+ txU4 fxSumEntry(txMachine* the, txSlot* slot)
896
+ {
897
+ txU1 kind = slot->kind;
898
+ txU8 sum;
899
+
900
+ if ((XS_STRING_KIND == kind) || (XS_STRING_X_KIND == kind)) {
901
+ // Dan Bernstein: http://www.cse.yorku.ca/~oz/hash.html
902
+ txU1 *string = (txU1*)slot->value.string;
903
+ sum = 5381;
904
+ while ((kind = c_read8(string++))) {
905
+ sum = ((sum << 5) + sum) + kind;
906
+ }
907
+ }
908
+ else {
909
+ if (XS_REFERENCE_KIND == kind) {
910
+ txSlot* base = C_NULL;
911
+ sum = slot->value.reference - base;
912
+ }
913
+ else if (XS_INTEGER_KIND == kind) {
914
+ fxToNumber(the, slot);
915
+ sum = *((txU8*)&slot->value.number);
916
+ }
917
+ else if (XS_NUMBER_KIND == kind) {
918
+ if (slot->value.number == 0)
919
+ slot->value.number = 0;
920
+ else if (c_isnan(slot->value.number))
921
+ slot->value.number = C_NAN;
922
+ sum = *((txU8*)&slot->value.number);
923
+ }
924
+ else if ((XS_BIGINT_KIND == kind) || (XS_BIGINT_X_KIND == kind)) {
925
+ sum = fxToBigUint64(the, slot);
926
+ }
927
+ else if (XS_SYMBOL_KIND == kind) {
928
+ sum = slot->value.symbol;
929
+ }
930
+ else if (XS_BOOLEAN_KIND == kind) {
931
+ sum = slot->value.boolean;
932
+ }
933
+ else {
934
+ sum = 0;
935
+ }
936
+ // Thomas Wang: http://web.archive.org/web/20071223173210/http://www.concentric.net/~Ttwang/tech/inthash.htm
937
+ sum = (~sum) + (sum << 18); // sum = (sum << 18) - sum - 1;
938
+ sum = sum ^ (sum >> 31);
939
+ sum = sum * 21; // sum = (sum + (sum << 2)) + (sum << 4);
940
+ sum = sum ^ (sum >> 11);
941
+ sum = sum + (sum << 6);
942
+ sum = sum ^ (sum >> 22);
943
+ }
944
+ sum &= 0xFFFFFFFF;
945
+ return (txU4)sum;
946
+ }
947
+
948
+ txBoolean fxTestEntry(txMachine* the, txSlot* a, txSlot* b)
949
+ {
950
+ txBoolean result = 0;
951
+ if (a->kind == b->kind) {
952
+ if ((XS_UNDEFINED_KIND == a->kind) || (XS_NULL_KIND == a->kind))
953
+ result = 1;
954
+ else if (XS_BOOLEAN_KIND == a->kind)
955
+ result = a->value.boolean == b->value.boolean;
956
+ else if (XS_INTEGER_KIND == a->kind)
957
+ result = a->value.integer == b->value.integer;
958
+ else if (XS_NUMBER_KIND == a->kind)
959
+ result = ((c_isnan(a->value.number) && c_isnan(b->value.number)) || (a->value.number == b->value.number));
960
+ else if ((XS_STRING_KIND == a->kind) || (XS_STRING_X_KIND == a->kind))
961
+ result = c_strcmp(a->value.string, b->value.string) == 0;
962
+ else if (XS_SYMBOL_KIND == a->kind)
963
+ result = a->value.symbol == b->value.symbol;
964
+ else if ((XS_BIGINT_KIND == a->kind) || (XS_BIGINT_X_KIND == a->kind))
965
+ result = gxTypeBigInt.compare(the, 0, 1, 0, a, b);
966
+ else if (XS_REFERENCE_KIND == a->kind)
967
+ result = a->value.reference == b->value.reference;
968
+ }
969
+ else if ((XS_INTEGER_KIND == a->kind) && (XS_NUMBER_KIND == b->kind))
970
+ result = (!c_isnan(b->value.number)) && ((txNumber)(a->value.integer) == b->value.number);
971
+ else if ((XS_NUMBER_KIND == a->kind) && (XS_INTEGER_KIND == b->kind))
972
+ result = (!c_isnan(a->value.number)) && (a->value.number == (txNumber)(b->value.integer));
973
+ else if ((XS_STRING_KIND == a->kind) && (XS_STRING_X_KIND == b->kind))
974
+ result = c_strcmp(a->value.string, b->value.string) == 0;
975
+ else if ((XS_STRING_X_KIND == a->kind) && (XS_STRING_KIND == b->kind))
976
+ result = c_strcmp(a->value.string, b->value.string) == 0;
977
+ else if ((XS_BIGINT_KIND == a->kind) && (XS_BIGINT_X_KIND == b->kind))
978
+ result = gxTypeBigInt.compare(the, 0, 1, 0, a, b);
979
+ else if ((XS_BIGINT_X_KIND == a->kind) && (XS_BIGINT_KIND == b->kind))
980
+ result = gxTypeBigInt.compare(the, 0, 1, 0, a, b);
981
+ return result;
982
+ }
983
+
984
+ txSlot* fxCheckWeakMapInstance(txMachine* the, txSlot* slot, txBoolean mutable)
985
+ {
986
+ if (slot->kind == XS_REFERENCE_KIND) {
987
+ txSlot* instance = slot->value.reference;
988
+ if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_WEAK_MAP_KIND) && (instance != mxWeakMapPrototype.value.reference)) {
989
+ if (mutable && (slot->flag & XS_DONT_SET_FLAG))
990
+ mxTypeError("WeakMap instance is read-only");
991
+ return instance;
992
+ }
993
+ }
994
+ mxTypeError("this is no WeakMap instance");
995
+ return C_NULL;
996
+ }
997
+
998
+ txSlot* fxCheckWeakMapKey(txMachine* the, txBoolean mutable)
999
+ {
1000
+ if (mxArgc > 0) {
1001
+ txSlot* slot = mxArgv(0);
1002
+ if (slot->kind == XS_REFERENCE_KIND) {
1003
+ if (mutable && (slot->value.reference->flag & XS_MARK_FLAG))
1004
+ mxTypeError("WeakMap key is read-only");
1005
+ return slot;
1006
+ }
1007
+ }
1008
+ return C_NULL;
1009
+ }
1010
+
1011
+ txSlot* fxNewWeakMapInstance(txMachine* the)
1012
+ {
1013
+ txSlot* map;
1014
+ txSlot* list;
1015
+ map = fxNewSlot(the);
1016
+ map->kind = XS_INSTANCE_KIND;
1017
+ map->value.instance.garbage = C_NULL;
1018
+ map->value.instance.prototype = the->stack->value.reference;
1019
+ the->stack->kind = XS_REFERENCE_KIND;
1020
+ the->stack->value.reference = map;
1021
+ /* LIST */
1022
+ list = map->next = fxNewSlot(the);
1023
+ list->flag = XS_INTERNAL_FLAG;
1024
+ list->kind = XS_WEAK_MAP_KIND;
1025
+ list->value.weakList.first = C_NULL;
1026
+ list->value.weakList.link = the->firstWeakListLink;
1027
+ the->firstWeakListLink = list;
1028
+ return map;
1029
+ }
1030
+
1031
+ void fx_WeakMap(txMachine* the)
1032
+ {
1033
+ txSlot *function, *iterable, *iterator, *next, *value;
1034
+ if (mxIsUndefined(mxTarget))
1035
+ mxTypeError("call: WeakMap");
1036
+ mxPushSlot(mxTarget);
1037
+ fxGetPrototypeFromConstructor(the, &mxWeakMapPrototype);
1038
+ fxNewWeakMapInstance(the);
1039
+ mxPullSlot(mxResult);
1040
+ if (mxArgc < 1)
1041
+ return;
1042
+ iterable = mxArgv(0);
1043
+ if ((iterable->kind == XS_UNDEFINED_KIND) || (iterable->kind == XS_NULL_KIND))
1044
+ return;
1045
+ mxPushSlot(mxResult);
1046
+ mxGetID(mxID(_set));
1047
+ function = the->stack;
1048
+ if (!fxIsCallable(the, function))
1049
+ mxTypeError("set is no function");
1050
+ mxTemporary(iterator);
1051
+ mxTemporary(next);
1052
+ fxGetIterator(the, iterable, iterator, next, 0);
1053
+ mxTemporary(value);
1054
+ while (fxIteratorNext(the, iterator, next, value)) {
1055
+ mxTry(the) {
1056
+ mxPushSlot(mxResult);
1057
+ mxPushSlot(function);
1058
+ mxCall();
1059
+ if (value->kind != XS_REFERENCE_KIND)
1060
+ mxTypeError("item is no object");
1061
+ mxPushSlot(value);
1062
+ mxGetIndex(0);
1063
+ mxPushSlot(value);
1064
+ mxGetIndex(1);
1065
+ mxRunCount(2);
1066
+ mxPop();
1067
+ }
1068
+ mxCatch(the) {
1069
+ fxIteratorReturn(the, iterator);
1070
+ fxJump(the);
1071
+ }
1072
+ }
1073
+ }
1074
+
1075
+ void fx_WeakMap_prototype_delete(txMachine* the)
1076
+ {
1077
+ txSlot* instance = fxCheckWeakMapInstance(the, mxThis, XS_MUTABLE);
1078
+ txSlot* key = fxCheckWeakMapKey(the, XS_MUTABLE);
1079
+ mxResult->value.boolean = (key) ? fxDeleteWeakEntry(the, instance->next, key->value.reference) : 0;
1080
+ mxResult->kind = XS_BOOLEAN_KIND;
1081
+ }
1082
+
1083
+ void fx_WeakMap_prototype_get(txMachine* the)
1084
+ {
1085
+ txSlot* instance = fxCheckWeakMapInstance(the, mxThis, XS_IMMUTABLE);
1086
+ txSlot* key = fxCheckWeakMapKey(the, XS_IMMUTABLE);
1087
+ txSlot* result = (key) ? fxGetWeakEntry(the, instance->next, key->value.reference) : C_NULL;
1088
+ if (result) {
1089
+ txSlot* value = result->value.weakEntry.value;
1090
+ mxResult->kind = value->kind;
1091
+ mxResult->value = value->value;
1092
+ }
1093
+ }
1094
+
1095
+ void fx_WeakMap_prototype_has(txMachine* the)
1096
+ {
1097
+ txSlot* instance = fxCheckWeakMapInstance(the, mxThis, XS_IMMUTABLE);
1098
+ txSlot* key = fxCheckWeakMapKey(the, XS_IMMUTABLE);
1099
+ txSlot* result = (key) ? fxGetWeakEntry(the, instance->next, key->value.reference) : C_NULL;
1100
+ mxResult->kind = XS_BOOLEAN_KIND;
1101
+ mxResult->value.boolean = (result) ? 1 : 0;
1102
+ }
1103
+
1104
+ void fx_WeakMap_prototype_set(txMachine* the)
1105
+ {
1106
+ txSlot* instance = fxCheckWeakMapInstance(the, mxThis, XS_MUTABLE);
1107
+ txSlot* key = fxCheckWeakMapKey(the, XS_MUTABLE);
1108
+ if (!key)
1109
+ mxTypeError("key is no object");
1110
+ fxSetWeakEntry(the, instance->next, key->value.reference, (mxArgc > 1) ? mxArgv(1) : &mxUndefined);
1111
+ *mxResult = *mxThis;
1112
+ }
1113
+
1114
+ txSlot* fxCheckWeakSetInstance(txMachine* the, txSlot* slot, txBoolean mutable)
1115
+ {
1116
+ if (slot->kind == XS_REFERENCE_KIND) {
1117
+ txSlot* instance = slot->value.reference;
1118
+ if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_WEAK_SET_KIND) && (instance != mxWeakSetPrototype.value.reference)) {
1119
+ if (mutable && (slot->flag & XS_DONT_SET_FLAG))
1120
+ mxTypeError("WeakSet instance is read-only");
1121
+ return instance;
1122
+ }
1123
+ }
1124
+ mxTypeError("this is no WeakSet instance");
1125
+ return C_NULL;
1126
+ }
1127
+
1128
+ txSlot* fxCheckWeakSetValue(txMachine* the, txBoolean mutable)
1129
+ {
1130
+ if (mxArgc > 0) {
1131
+ txSlot* slot = mxArgv(0);
1132
+ if (slot->kind == XS_REFERENCE_KIND) {
1133
+ if (mutable && (slot->value.reference->flag & XS_MARK_FLAG))
1134
+ mxTypeError("WeakSet value is read-only");
1135
+ return slot;
1136
+ }
1137
+ }
1138
+ return C_NULL;
1139
+ }
1140
+
1141
+ txSlot* fxNewWeakSetInstance(txMachine* the)
1142
+ {
1143
+ txSlot* set;
1144
+ txSlot* list;
1145
+ set = fxNewSlot(the);
1146
+ set->kind = XS_INSTANCE_KIND;
1147
+ set->value.instance.garbage = C_NULL;
1148
+ set->value.instance.prototype = the->stack->value.reference;
1149
+ the->stack->kind = XS_REFERENCE_KIND;
1150
+ the->stack->value.reference = set;
1151
+ /* LIST */
1152
+ list = set->next = fxNewSlot(the);
1153
+ list->flag = XS_INTERNAL_FLAG;
1154
+ list->kind = XS_WEAK_SET_KIND;
1155
+ list->value.weakList.first = C_NULL;
1156
+ list->value.weakList.link = the->firstWeakListLink;
1157
+ the->firstWeakListLink = list;
1158
+ return set;
1159
+ }
1160
+
1161
+ void fx_WeakSet(txMachine* the)
1162
+ {
1163
+ txSlot *function, *iterable, *iterator, *next, *value;
1164
+ if (mxIsUndefined(mxTarget))
1165
+ mxTypeError("call: WeakSet");
1166
+ mxPushSlot(mxTarget);
1167
+ fxGetPrototypeFromConstructor(the, &mxWeakSetPrototype);
1168
+ fxNewWeakSetInstance(the);
1169
+ mxPullSlot(mxResult);
1170
+ if (mxArgc < 1)
1171
+ return;
1172
+ iterable = mxArgv(0);
1173
+ if ((iterable->kind == XS_UNDEFINED_KIND) || (iterable->kind == XS_NULL_KIND))
1174
+ return;
1175
+ mxPushSlot(mxResult);
1176
+ mxGetID(mxID(_add));
1177
+ function = the->stack;
1178
+ if (!fxIsCallable(the, function))
1179
+ mxTypeError("add is no function");
1180
+ mxTemporary(iterator);
1181
+ mxTemporary(next);
1182
+ fxGetIterator(the, iterable, iterator, next, 0);
1183
+ mxTemporary(value);
1184
+ while (fxIteratorNext(the, iterator, next, value)) {
1185
+ mxTry(the) {
1186
+ mxPushSlot(mxResult);
1187
+ mxPushSlot(function);
1188
+ mxCall();
1189
+ mxPushSlot(value);
1190
+ mxRunCount(1);
1191
+ mxPop();
1192
+ }
1193
+ mxCatch(the) {
1194
+ fxIteratorReturn(the, iterator);
1195
+ fxJump(the);
1196
+ }
1197
+ }
1198
+ }
1199
+
1200
+ void fx_WeakSet_prototype_add(txMachine* the)
1201
+ {
1202
+ txSlot* instance = fxCheckWeakSetInstance(the, mxThis, XS_MUTABLE);
1203
+ txSlot* value = fxCheckWeakSetValue(the, XS_MUTABLE);
1204
+ if (!value)
1205
+ mxTypeError("value is no object");
1206
+ fxSetWeakEntry(the, instance->next, value->value.reference, &mxUndefined);
1207
+ *mxResult = *mxThis;
1208
+ }
1209
+
1210
+ void fx_WeakSet_prototype_has(txMachine* the)
1211
+ {
1212
+ txSlot* instance = fxCheckWeakSetInstance(the, mxThis, XS_IMMUTABLE);
1213
+ txSlot* value = fxCheckWeakSetValue(the, XS_IMMUTABLE);
1214
+ txSlot* result = (value) ? fxGetWeakEntry(the, instance->next, value->value.reference) : C_NULL;
1215
+ mxResult->kind = XS_BOOLEAN_KIND;
1216
+ mxResult->value.boolean = (result) ? 1 : 0;
1217
+ }
1218
+
1219
+ void fx_WeakSet_prototype_delete(txMachine* the)
1220
+ {
1221
+ txSlot* instance = fxCheckWeakSetInstance(the, mxThis, XS_MUTABLE);
1222
+ txSlot* value = fxCheckWeakSetValue(the, XS_MUTABLE);
1223
+ mxResult->value.boolean = (value) ? fxDeleteWeakEntry(the, instance->next, value->value.reference) : 0;
1224
+ mxResult->kind = XS_BOOLEAN_KIND;
1225
+ }
1226
+
1227
+ txBoolean fxDeleteWeakEntry(txMachine* the, txSlot* list, txSlot* key)
1228
+ {
1229
+ txSlot* slot = (key->flag & XS_EXOTIC_FLAG) ? key->next : key;
1230
+ txSlot** address = &slot->next;
1231
+ while ((slot = *address)) {
1232
+ if (!(slot->flag & XS_INTERNAL_FLAG))
1233
+ break;
1234
+ if ((slot->kind == XS_WEAK_ENTRY_KIND) && (slot->value.weakEntry.check == list)) {
1235
+ slot->value.weakEntry.value->kind = XS_UNINITIALIZED_KIND;
1236
+ *address = slot->next;
1237
+ return 1;
1238
+ }
1239
+ address = &slot->next;
1240
+ }
1241
+ return 0;
1242
+ }
1243
+
1244
+ txSlot* fxGetWeakEntry(txMachine* the, txSlot* list, txSlot* key)
1245
+ {
1246
+ txSlot* slot = (key->flag & XS_EXOTIC_FLAG) ? key->next : key;
1247
+ slot = slot->next;
1248
+ while (slot) {
1249
+ if (!(slot->flag & XS_INTERNAL_FLAG))
1250
+ break;
1251
+ if ((slot->kind == XS_WEAK_ENTRY_KIND) && (slot->value.weakEntry.check == list))
1252
+ return slot;
1253
+ slot = slot->next;
1254
+ }
1255
+ return C_NULL;
1256
+ }
1257
+
1258
+ void fxSetWeakEntry(txMachine* the, txSlot* list, txSlot* key, txSlot* value)
1259
+ {
1260
+ txSlot* slot = (key->flag & XS_EXOTIC_FLAG) ? key->next : key;
1261
+ txSlot** address = &slot->next;
1262
+ txSlot* keyEntry;
1263
+ txSlot* listEntry;
1264
+ txSlot* closure;
1265
+ while ((slot = *address)) {
1266
+ if (!(slot->flag & XS_INTERNAL_FLAG))
1267
+ break;
1268
+ if ((slot->kind == XS_WEAK_ENTRY_KIND) && (slot->value.weakEntry.check == list)) {
1269
+ slot = slot->value.weakEntry.value;
1270
+ slot->kind = value->kind;
1271
+ slot->value = value->value;
1272
+ return;
1273
+ }
1274
+ address = &slot->next;
1275
+ }
1276
+
1277
+ keyEntry = fxNewSlot(the);
1278
+ mxPushClosure(keyEntry);
1279
+ listEntry = fxNewSlot(the);
1280
+ mxPushClosure(listEntry);
1281
+ closure = fxNewSlot(the);
1282
+ closure->kind = value->kind;
1283
+ closure->value = value->value;
1284
+
1285
+ slot = (key->flag & XS_EXOTIC_FLAG) ? key->next : key;
1286
+ address = &slot->next;
1287
+ while ((slot = *address)) {
1288
+ if (!(slot->flag & XS_INTERNAL_FLAG))
1289
+ break;
1290
+ address = &slot->next;
1291
+ }
1292
+
1293
+ keyEntry->next = *address;
1294
+ keyEntry->flag = XS_INTERNAL_FLAG;
1295
+ keyEntry->kind = XS_WEAK_ENTRY_KIND;
1296
+ keyEntry->value.weakEntry.check = list;
1297
+ keyEntry->value.weakEntry.value = closure;
1298
+ *address = keyEntry;
1299
+
1300
+ listEntry->next = list->value.weakList.first;
1301
+ listEntry->flag = XS_INTERNAL_FLAG;
1302
+ listEntry->kind = XS_WEAK_ENTRY_KIND;
1303
+ listEntry->value.weakEntry.check = key;
1304
+ listEntry->value.weakEntry.value = closure;
1305
+ list->value.weakList.first = listEntry;
1306
+
1307
+ mxPop();
1308
+ mxPop();
1309
+ }
1310
+
1311
+ void fxKeepDuringJobs(txMachine* the, txSlot* target)
1312
+ {
1313
+ txSlot* instance = mxDuringJobs.value.reference;
1314
+ txSlot** address = &(instance->next);
1315
+ txSlot* slot;
1316
+ while ((slot = *address)) {
1317
+ if (slot->value.reference == target)
1318
+ return;
1319
+ address = &(slot->next);
1320
+ }
1321
+ *address = slot = fxNewSlot(the);
1322
+ slot->value.reference = target;
1323
+ slot->kind = XS_REFERENCE_KIND;
1324
+ }
1325
+
1326
+ txSlot* fxCheckWeakRefInstance(txMachine* the, txSlot* slot)
1327
+ {
1328
+ if (slot->kind == XS_REFERENCE_KIND) {
1329
+ txSlot* instance = slot->value.reference;
1330
+ if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_WEAK_REF_KIND))
1331
+ return instance;
1332
+ }
1333
+ mxTypeError("this is no WeakRef instance");
1334
+ return C_NULL;
1335
+ }
1336
+
1337
+ txSlot* fxNewWeakRefInstance(txMachine* the)
1338
+ {
1339
+ txSlot* slot;
1340
+ txSlot* instance = fxNewSlot(the);
1341
+ instance->kind = XS_INSTANCE_KIND;
1342
+ instance->value.instance.garbage = C_NULL;
1343
+ instance->value.instance.prototype = the->stack->value.reference;
1344
+ the->stack->kind = XS_REFERENCE_KIND;
1345
+ the->stack->value.reference = instance;
1346
+ slot = instance->next = fxNewSlot(the);
1347
+ slot->flag = XS_INTERNAL_FLAG;
1348
+ slot->kind = XS_WEAK_REF_KIND;
1349
+ slot->value.weakRef.target = C_NULL;
1350
+ slot->value.weakRef.link = C_NULL;
1351
+ return instance;
1352
+ }
1353
+
1354
+ void fx_WeakRef(txMachine* the)
1355
+ {
1356
+ txSlot* target;
1357
+ txSlot* instance;
1358
+ if (mxIsUndefined(mxTarget))
1359
+ mxTypeError("call: WeakRef");
1360
+ if (mxArgc < 1)
1361
+ mxTypeError("new WeakRef: no target");
1362
+ target = mxArgv(0);
1363
+ if (!mxIsReference(target))
1364
+ mxTypeError("new WeakRef: target is no object");
1365
+ target = target->value.reference;
1366
+ mxPushSlot(mxTarget);
1367
+ fxGetPrototypeFromConstructor(the, &mxWeakRefPrototype);
1368
+ instance = fxNewWeakRefInstance(the);
1369
+ mxPullSlot(mxResult);
1370
+ fxKeepDuringJobs(the, target);
1371
+ instance->next->value.weakRef.target = target;
1372
+ }
1373
+
1374
+ void fx_WeakRef_prototype_deref(txMachine* the)
1375
+ {
1376
+ txSlot* instance = fxCheckWeakRefInstance(the, mxThis);
1377
+ txSlot* target = instance->next->value.weakRef.target;
1378
+ if (target) {
1379
+ mxResult->value.reference = target;
1380
+ mxResult->kind = XS_REFERENCE_KIND;
1381
+ fxKeepDuringJobs(the, target);
1382
+ }
1383
+ }
1384
+
1385
+ txSlot* fxCheckFinalizationRegistryInstance(txMachine* the, txSlot* slot)
1386
+ {
1387
+ if (slot->kind == XS_REFERENCE_KIND) {
1388
+ txSlot* instance = slot->value.reference;
1389
+ if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_CLOSURE_KIND) && (slot->value.closure->kind == XS_FINALIZATION_REGISTRY_KIND)) {
1390
+ if (slot->flag & XS_MARK_FLAG)
1391
+ mxTypeError("FinalizationRegistry instance is read-only");
1392
+ return instance;
1393
+ }
1394
+ }
1395
+ mxTypeError("this is no FinalizationRegistry instance");
1396
+ return C_NULL;
1397
+ }
1398
+
1399
+ void fx_FinalizationRegistry(txMachine* the)
1400
+ {
1401
+ txSlot* callback;
1402
+ txSlot* instance;
1403
+ txSlot* property;
1404
+ txSlot* registry;
1405
+ txSlot* slot;
1406
+ if (mxIsUndefined(mxTarget))
1407
+ mxTypeError("call: FinalizationRegistry");
1408
+ if (mxArgc < 1)
1409
+ mxTypeError("no callback");
1410
+ callback = mxArgv(0);
1411
+ if (!fxIsCallable(the, callback))
1412
+ mxTypeError("callback is no function");
1413
+ mxPushSlot(mxTarget);
1414
+ fxGetPrototypeFromConstructor(the, &mxFinalizationRegistryPrototype);
1415
+ instance = fxNewSlot(the);
1416
+ instance->kind = XS_INSTANCE_KIND;
1417
+ instance->value.instance.garbage = C_NULL;
1418
+ instance->value.instance.prototype = the->stack->value.reference;
1419
+ the->stack->kind = XS_REFERENCE_KIND;
1420
+ the->stack->value.reference = instance;
1421
+ mxPullSlot(mxResult);
1422
+ property = instance->next = fxNewSlot(the);
1423
+ property->flag = XS_INTERNAL_FLAG;
1424
+ property->kind = XS_CLOSURE_KIND;
1425
+ property->value.closure = C_NULL;
1426
+ registry = fxNewSlot(the);
1427
+ registry->kind = XS_FINALIZATION_REGISTRY_KIND;
1428
+ registry->value.finalizationRegistry.callback = C_NULL;
1429
+ registry->value.finalizationRegistry.flags = XS_NO_FLAG;
1430
+ property->value.closure = registry;
1431
+ slot = fxNewSlot(the);
1432
+ slot->kind = callback->kind;
1433
+ slot->value = callback->value;
1434
+ registry->value.finalizationRegistry.callback = slot;
1435
+ }
1436
+
1437
+
1438
+ #if 0
1439
+ // removed from FinalizationRegistry specification
1440
+ void fx_FinalizationRegistry_prototype_cleanupSome(txMachine* the)
1441
+ {
1442
+ txSlot* instance;
1443
+ txSlot* registry;
1444
+ txSlot* callback = C_NULL;
1445
+ txSlot** address;
1446
+ txSlot* slot;
1447
+ if (!mxIsReference(mxThis))
1448
+ mxTypeError("this is no object");
1449
+ instance = fxCheckFinalizationRegistryInstance(the, mxThis);
1450
+ registry = instance->next->value.closure;
1451
+ if (mxArgc > 0) {
1452
+ callback = mxArgv(0);
1453
+ if (mxIsUndefined(callback))
1454
+ callback = C_NULL;
1455
+ else if (!fxIsCallable(the, callback))
1456
+ mxTypeError("callback is no function");
1457
+ }
1458
+ fx_FinalizationRegistryCleanup(the, registry, callback);
1459
+ callback = registry->value.finalizationRegistry.callback;
1460
+ if (callback->next == C_NULL) {
1461
+ address = &(mxFinalizationRegistries.value.reference->next);
1462
+ while ((slot = *address)) {
1463
+ if (slot->value.closure == registry) {
1464
+ *address = slot->next;
1465
+ return;
1466
+ }
1467
+ address = &(slot->next);
1468
+ }
1469
+ }
1470
+ }
1471
+ #endif
1472
+
1473
+ void fx_FinalizationRegistry_prototype_register(txMachine* the)
1474
+ {
1475
+ txSlot* instance;
1476
+ txSlot* registry;
1477
+ txSlot* target;
1478
+ txSlot* token = C_NULL;
1479
+ txSlot* callback;
1480
+ txSlot** address;
1481
+ txSlot* slot;
1482
+ if (!mxIsReference(mxThis))
1483
+ mxTypeError("this is no object");
1484
+ instance = fxCheckFinalizationRegistryInstance(the, mxThis);
1485
+ registry = instance->next->value.closure;
1486
+ if (mxArgc < 1)
1487
+ mxTypeError("no target");
1488
+ target = mxArgv(0);
1489
+ if (!mxIsReference(target))
1490
+ mxTypeError("target is no object");
1491
+ if (mxArgc > 1) {
1492
+ if (fxIsSameValue(the, target, mxArgv(1), 1))
1493
+ mxTypeError("target and holdings are the same");
1494
+ }
1495
+ target = target->value.reference;
1496
+ if (mxArgc > 2) {
1497
+ token = mxArgv(2);
1498
+ if (mxIsUndefined(token))
1499
+ token = C_NULL;
1500
+ else if (mxIsReference(token))
1501
+ token = token->value.reference;
1502
+ else
1503
+ mxTypeError("token is no object");
1504
+ }
1505
+ callback = registry->value.finalizationRegistry.callback;
1506
+ address = &(callback->next);
1507
+ while ((slot = *address))
1508
+ address = &(slot->next);
1509
+ slot = *address = fxNewSlot(the);
1510
+ if (mxArgc > 1) {
1511
+ slot->kind = mxArgv(1)->kind;
1512
+ slot->value = mxArgv(1)->value;
1513
+ }
1514
+ slot = slot->next = fxNewSlot(the);
1515
+ slot->kind = XS_FINALIZATION_CELL_KIND;
1516
+ slot->value.finalizationCell.target = target;
1517
+ slot->value.finalizationCell.token = token;
1518
+
1519
+ address = &(mxFinalizationRegistries.value.reference->next);
1520
+ while ((slot = *address)) {
1521
+ if (slot->value.closure == registry)
1522
+ return;
1523
+ address = &(slot->next);
1524
+ }
1525
+ slot = *address = fxNewSlot(the);
1526
+ slot->kind = XS_CLOSURE_KIND;
1527
+ slot->value.closure = registry;
1528
+ }
1529
+
1530
+ void fx_FinalizationRegistry_prototype_unregister(txMachine* the)
1531
+ {
1532
+ txSlot* instance;
1533
+ txSlot* token;
1534
+ txSlot* registry;
1535
+ txSlot* callback;
1536
+ txSlot** address;
1537
+ txSlot* slot;
1538
+ if (!mxIsReference(mxThis))
1539
+ mxTypeError("this is no object");
1540
+ instance = fxCheckFinalizationRegistryInstance(the, mxThis);
1541
+ if (mxArgc < 1)
1542
+ mxTypeError("no token");
1543
+ token = mxArgv(0);
1544
+ if (!mxIsReference(token))
1545
+ mxTypeError("token is no object");
1546
+ token = token->value.reference;
1547
+ mxResult->kind = XS_BOOLEAN_KIND;
1548
+ mxResult->value.boolean = 0;
1549
+ registry = instance->next->value.closure;
1550
+ callback = registry->value.finalizationRegistry.callback;
1551
+ address = &(callback->next);
1552
+ while ((slot = *address)) {
1553
+ slot = slot->next;
1554
+ if (slot->value.finalizationCell.token && fxIsSameInstance(the, slot->value.finalizationCell.token, token)) {
1555
+ *address = slot->next;
1556
+ mxResult->value.boolean = 1;
1557
+ }
1558
+ else
1559
+ address = &(slot->next);
1560
+ }
1561
+ if (callback->next == C_NULL) {
1562
+ address = &(mxFinalizationRegistries.value.reference->next);
1563
+ while ((slot = *address)) {
1564
+ if (slot->value.closure == registry) {
1565
+ *address = slot->next;
1566
+ return;
1567
+ }
1568
+ address = &(slot->next);
1569
+ }
1570
+ }
1571
+ }
1572
+
1573
+ void fx_FinalizationRegistryCleanup(txMachine* the, txSlot* registry, txSlot* callback)
1574
+ {
1575
+ txSlot* slot;
1576
+ txUnsigned flags;
1577
+ txSlot** address;
1578
+ txSlot* value;
1579
+
1580
+ if (!(registry->value.finalizationRegistry.flags & XS_FINALIZATION_REGISTRY_CHANGED))
1581
+ return;
1582
+
1583
+ slot = registry->value.finalizationRegistry.callback->next;
1584
+ flags = 0;
1585
+ while (slot) {
1586
+ slot = slot->next;
1587
+ if (slot->value.finalizationCell.target == C_NULL) {
1588
+ flags = 1;
1589
+ break;
1590
+ }
1591
+ slot = slot->next;
1592
+ }
1593
+ if (!flags)
1594
+ return;
1595
+ if (!callback)
1596
+ callback = registry->value.finalizationRegistry.callback;
1597
+ flags = registry->value.finalizationRegistry.flags;
1598
+ {
1599
+ mxTry(the) {
1600
+ address = &(registry->value.finalizationRegistry.callback->next);
1601
+ while ((value = *address)) {
1602
+ slot = value->next;
1603
+ if (slot->value.finalizationCell.target == C_NULL) {
1604
+ *address = slot->next;
1605
+ mxPushUndefined();
1606
+ mxPushSlot(callback);
1607
+ mxCall();
1608
+ mxPushSlot(value);
1609
+ mxRunCount(1);
1610
+ mxPop();
1611
+ }
1612
+ else
1613
+ address = &(slot->next);
1614
+ }
1615
+ registry->value.finalizationRegistry.flags = flags;
1616
+ }
1617
+ mxCatch(the) {
1618
+ registry->value.finalizationRegistry.flags = flags;
1619
+ fxJump(the);
1620
+ }
1621
+ }
1622
+
1623
+ slot = registry->value.finalizationRegistry.callback->next;
1624
+ while (slot) {
1625
+ slot = slot->next;
1626
+ if (slot->value.finalizationCell.target == C_NULL)
1627
+ break;
1628
+ slot = slot->next;
1629
+ }
1630
+ if (!slot)
1631
+ registry->value.finalizationRegistry.flags &= ~XS_FINALIZATION_REGISTRY_CHANGED;
1632
+ }
1633
+
1634
+ void fxCleanupFinalizationRegistries(txMachine* the)
1635
+ {
1636
+ txSlot** address = &(mxFinalizationRegistries.value.reference->next);
1637
+ txSlot* closure;
1638
+ while ((closure = *address)) {
1639
+ txSlot* registry = closure->value.closure;
1640
+ if (registry->value.finalizationRegistry.flags & XS_FINALIZATION_REGISTRY_CHANGED) {
1641
+ fx_FinalizationRegistryCleanup(the, registry, C_NULL);
1642
+ address = &(mxFinalizationRegistries.value.reference->next);
1643
+ }
1644
+ else
1645
+ address = &(closure->next);
1646
+ }
1647
+ }
1648
+
1649
+