xbintsc 0.3.14 → 0.3.16

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 (201) hide show
  1. package/README.md +22 -22
  2. package/README.zh-CN.md +20 -19
  3. package/bin/xbintsc.js +1 -2
  4. package/dist/src/cli/main.js +8 -5
  5. package/dist/src/cli/main.js.map +1 -1
  6. package/dist/src/codegen/generator/state.js +8 -0
  7. package/dist/src/codegen/generator/state.js.map +1 -1
  8. package/dist/src/codegen/generator/tables.d.ts +5 -6
  9. package/dist/src/codegen/generator/tables.js +13 -6
  10. package/dist/src/codegen/generator/tables.js.map +1 -1
  11. package/dist/src/driver/bundler/graph.d.ts +8 -0
  12. package/dist/src/driver/bundler/graph.js +85 -0
  13. package/dist/src/driver/bundler/graph.js.map +1 -0
  14. package/dist/src/driver/bundler/merge.d.ts +11 -0
  15. package/dist/src/driver/bundler/merge.js +288 -0
  16. package/dist/src/driver/bundler/merge.js.map +1 -0
  17. package/dist/src/driver/bundler/resolve.d.ts +12 -0
  18. package/dist/src/driver/bundler/resolve.js +246 -0
  19. package/dist/src/driver/bundler/resolve.js.map +1 -0
  20. package/dist/src/driver/bundler/symbols.d.ts +15 -0
  21. package/dist/src/driver/bundler/symbols.js +51 -0
  22. package/dist/src/driver/bundler/symbols.js.map +1 -0
  23. package/dist/src/driver/bundler/types.d.ts +36 -0
  24. package/dist/src/driver/bundler/types.js +5 -0
  25. package/dist/src/driver/bundler/types.js.map +1 -0
  26. package/dist/src/driver/index.d.ts +1 -2
  27. package/dist/src/driver/index.js +1 -2
  28. package/dist/src/driver/index.js.map +1 -1
  29. package/dist/src/driver/modules.d.ts +9 -16
  30. package/dist/src/driver/modules.js +8 -644
  31. package/dist/src/driver/modules.js.map +1 -1
  32. package/dist/src/driver/paths.d.ts +0 -9
  33. package/dist/src/driver/paths.js +0 -31
  34. package/dist/src/driver/paths.js.map +1 -1
  35. package/dist/src/driver/toolchain-provider.d.ts +10 -10
  36. package/dist/src/driver/toolchain-provider.js +9 -38
  37. package/dist/src/driver/toolchain-provider.js.map +1 -1
  38. package/dist/src/driver/toolchain.js +8 -2
  39. package/dist/src/driver/toolchain.js.map +1 -1
  40. package/dist/src/extensions/catalog.js +2 -1
  41. package/dist/src/extensions/catalog.js.map +1 -1
  42. package/dist/src/extensions/gui/index.d.ts +24 -0
  43. package/dist/src/extensions/gui/index.js +101 -0
  44. package/dist/src/extensions/gui/index.js.map +1 -0
  45. package/dist/src/extensions/native.d.ts +2 -3
  46. package/dist/src/extensions/native.js +2 -3
  47. package/dist/src/extensions/native.js.map +1 -1
  48. package/dist/tests/driver/paths.test.js +1 -9
  49. package/dist/tests/driver/paths.test.js.map +1 -1
  50. package/dist/tests/driver/toolchain-provider.test.js +12 -79
  51. package/dist/tests/driver/toolchain-provider.test.js.map +1 -1
  52. package/dist/tests/e2e/compile-basics.test.d.ts +4 -0
  53. package/dist/tests/e2e/compile-basics.test.js +134 -0
  54. package/dist/tests/e2e/compile-basics.test.js.map +1 -0
  55. package/dist/tests/e2e/compile-builtins.test.d.ts +4 -0
  56. package/dist/tests/e2e/compile-builtins.test.js +191 -0
  57. package/dist/tests/e2e/compile-builtins.test.js.map +1 -0
  58. package/dist/tests/e2e/compile-control-flow.test.d.ts +4 -0
  59. package/dist/tests/e2e/compile-control-flow.test.js +190 -0
  60. package/dist/tests/e2e/compile-control-flow.test.js.map +1 -0
  61. package/dist/tests/e2e/compile-modules.test.d.ts +4 -0
  62. package/dist/tests/e2e/compile-modules.test.js +48 -0
  63. package/dist/tests/e2e/compile-modules.test.js.map +1 -0
  64. package/dist/tests/e2e/compile-objects-classes.test.d.ts +4 -0
  65. package/dist/tests/e2e/compile-objects-classes.test.js +362 -0
  66. package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -0
  67. package/dist/tests/e2e/differential-helpers.d.ts +12 -0
  68. package/dist/tests/e2e/differential-helpers.js +16 -0
  69. package/dist/tests/e2e/differential-helpers.js.map +1 -0
  70. package/dist/tests/e2e/differential-language.test.d.ts +4 -0
  71. package/dist/tests/e2e/{differential.test.js → differential-language.test.js} +5 -287
  72. package/dist/tests/e2e/differential-language.test.js.map +1 -0
  73. package/dist/tests/e2e/differential-symbols.test.d.ts +4 -0
  74. package/dist/tests/e2e/differential-symbols.test.js +92 -0
  75. package/dist/tests/e2e/differential-symbols.test.js.map +1 -0
  76. package/dist/tests/e2e/differential-values.test.d.ts +4 -0
  77. package/dist/tests/e2e/differential-values.test.js +197 -0
  78. package/dist/tests/e2e/differential-values.test.js.map +1 -0
  79. package/dist/tests/e2e/gui.test.d.ts +12 -0
  80. package/dist/tests/e2e/gui.test.js +493 -0
  81. package/dist/tests/e2e/gui.test.js.map +1 -0
  82. package/dist/tests/e2e/native-extensions.test.d.ts +4 -5
  83. package/dist/tests/e2e/native-extensions.test.js +6 -7
  84. package/dist/tests/e2e/native-extensions.test.js.map +1 -1
  85. package/dist/tests/e2e/runtime-coverage-buffer.test.d.ts +4 -0
  86. package/dist/tests/e2e/runtime-coverage-buffer.test.js +97 -0
  87. package/dist/tests/e2e/runtime-coverage-buffer.test.js.map +1 -0
  88. package/dist/tests/e2e/runtime-coverage-globals.test.d.ts +4 -0
  89. package/dist/tests/e2e/runtime-coverage-globals.test.js +149 -0
  90. package/dist/tests/e2e/runtime-coverage-globals.test.js.map +1 -0
  91. package/dist/tests/e2e/runtime-coverage-node-modules.test.d.ts +4 -0
  92. package/dist/tests/e2e/runtime-coverage-node-modules.test.js +177 -0
  93. package/dist/tests/e2e/runtime-coverage-node-modules.test.js.map +1 -0
  94. package/dist/tests/e2e/runtime-coverage-streams.test.d.ts +4 -0
  95. package/dist/tests/e2e/runtime-coverage-streams.test.js +161 -0
  96. package/dist/tests/e2e/runtime-coverage-streams.test.js.map +1 -0
  97. package/dist/tests/e2e/runtime-coverage-system.test.d.ts +4 -0
  98. package/dist/tests/e2e/runtime-coverage-system.test.js +91 -0
  99. package/dist/tests/e2e/runtime-coverage-system.test.js.map +1 -0
  100. package/dist/tests/e2e/timers.test.d.ts +7 -0
  101. package/dist/tests/e2e/timers.test.js +63 -0
  102. package/dist/tests/e2e/timers.test.js.map +1 -0
  103. package/package.json +2 -2
  104. package/runtime/ext_gui/css.cpp +743 -0
  105. package/runtime/ext_gui/css.h +98 -0
  106. package/runtime/ext_gui/document.cpp +264 -0
  107. package/runtime/ext_gui/document.h +89 -0
  108. package/runtime/ext_gui/dom.cpp +472 -0
  109. package/runtime/ext_gui/dom.h +71 -0
  110. package/runtime/ext_gui/gui.cpp +457 -0
  111. package/runtime/ext_gui/gui_engine.h +81 -0
  112. package/runtime/ext_gui/image.cpp +125 -0
  113. package/runtime/ext_gui/image.h +42 -0
  114. package/runtime/ext_gui/layout.cpp +748 -0
  115. package/runtime/ext_gui/layout.h +93 -0
  116. package/runtime/ext_gui/paint.cpp +137 -0
  117. package/runtime/ext_gui/paint.h +75 -0
  118. package/runtime/ext_gui/renderer.cpp +959 -0
  119. package/runtime/ext_gui/renderer.h +68 -0
  120. package/runtime/ext_gui/stb_image.h +7988 -0
  121. package/runtime/ext_gui/style.cpp +771 -0
  122. package/runtime/ext_gui/style.h +117 -0
  123. package/runtime/ext_gui/text.cpp +378 -0
  124. package/runtime/ext_gui/text.h +78 -0
  125. package/runtime/ext_gui/window.cpp +405 -0
  126. package/runtime/ext_node/fs/fs_common.h +13 -527
  127. package/runtime/ext_node/fs/meta_ops.c +3 -3
  128. package/runtime/ext_node/fs/parts/buffer-bridge.inc +6 -0
  129. package/runtime/ext_node/fs/parts/builtins.inc +69 -0
  130. package/runtime/ext_node/fs/parts/dir.inc +47 -0
  131. package/runtime/ext_node/fs/parts/encoding.inc +186 -0
  132. package/runtime/ext_node/fs/parts/errors.inc +66 -0
  133. package/runtime/ext_node/fs/parts/flags.inc +39 -0
  134. package/runtime/ext_node/fs/parts/platform.inc +86 -0
  135. package/runtime/ext_node/fs/parts/promisify.inc +15 -0
  136. package/runtime/ext_node/fs/parts/time.inc +9 -0
  137. package/runtime/rt.h +36 -4
  138. package/runtime/rt_internal.h +10 -23
  139. package/runtime/xt_builtins.c +4 -0
  140. package/runtime/xt_containers/access.inc +168 -0
  141. package/runtime/xt_containers/arrays.inc +108 -0
  142. package/runtime/xt_containers/boxes.inc +11 -0
  143. package/runtime/xt_containers/objects.inc +326 -0
  144. package/runtime/xt_containers.c +8 -618
  145. package/runtime/xt_ext.h +0 -1
  146. package/runtime/xt_io/base64.inc +87 -0
  147. package/runtime/xt_io/console.inc +119 -0
  148. package/runtime/xt_io/exception.inc +142 -0
  149. package/runtime/xt_io/inspect.inc +212 -0
  150. package/runtime/xt_io.c +11 -556
  151. package/runtime/xt_loop.c +262 -24
  152. package/runtime/xt_regex/api.inc +58 -0
  153. package/runtime/xt_regex/helpers.inc +68 -0
  154. package/runtime/xt_regex/matcher.inc +248 -0
  155. package/runtime/xt_regex/parser.inc +236 -0
  156. package/runtime/xt_regex/types.inc +58 -0
  157. package/runtime/xt_regex.h +9 -672
  158. package/runtime/xt_stdlib2/helpers.inc +2 -4
  159. package/runtime/xt_values/arithmetic.inc +150 -0
  160. package/runtime/xt_values/comparison.inc +112 -0
  161. package/runtime/xt_values/constructors.inc +41 -0
  162. package/runtime/xt_values/conversions.inc +115 -0
  163. package/runtime/xt_values/number-format.inc +180 -0
  164. package/runtime/xt_values/strings.inc +22 -0
  165. package/runtime/xt_values.c +10 -626
  166. package/scripts/build-gui.ts +317 -0
  167. package/scripts/build-runtime.ts +7 -8
  168. package/scripts/coverage-runtime.ts +4 -4
  169. package/scripts/package-release.ts +12 -84
  170. package/src/cli/main.ts +8 -4
  171. package/src/codegen/generator/state.ts +8 -0
  172. package/src/codegen/generator/tables.ts +13 -6
  173. package/src/driver/bundler/graph.ts +95 -0
  174. package/src/driver/bundler/merge.ts +312 -0
  175. package/src/driver/bundler/resolve.ts +240 -0
  176. package/src/driver/bundler/symbols.ts +55 -0
  177. package/src/driver/bundler/types.ts +37 -0
  178. package/src/driver/index.ts +1 -9
  179. package/src/driver/modules.ts +9 -693
  180. package/src/driver/paths.ts +0 -31
  181. package/src/driver/toolchain-provider.ts +12 -45
  182. package/src/driver/toolchain.ts +7 -2
  183. package/src/extensions/catalog.ts +2 -1
  184. package/src/extensions/gui/index.ts +107 -0
  185. package/src/extensions/native.ts +2 -3
  186. package/dist/src/driver/toolchain-download.d.ts +0 -50
  187. package/dist/src/driver/toolchain-download.js +0 -102
  188. package/dist/src/driver/toolchain-download.js.map +0 -1
  189. package/dist/tests/driver/toolchain-download.test.d.ts +0 -1
  190. package/dist/tests/driver/toolchain-download.test.js +0 -53
  191. package/dist/tests/driver/toolchain-download.test.js.map +0 -1
  192. package/dist/tests/e2e/compile.test.d.ts +0 -8
  193. package/dist/tests/e2e/compile.test.js +0 -893
  194. package/dist/tests/e2e/compile.test.js.map +0 -1
  195. package/dist/tests/e2e/differential.test.d.ts +0 -7
  196. package/dist/tests/e2e/differential.test.js.map +0 -1
  197. package/dist/tests/e2e/runtime-coverage.test.d.ts +0 -11
  198. package/dist/tests/e2e/runtime-coverage.test.js +0 -646
  199. package/dist/tests/e2e/runtime-coverage.test.js.map +0 -1
  200. package/scripts/fetch-toolchain.ts +0 -101
  201. package/src/driver/toolchain-download.ts +0 -135
@@ -4,6 +4,10 @@
4
4
  * Objects (linear property lists) and arrays (dynamic vectors), plus the
5
5
  * generic `xt_get`/`xt_set` member access used by the codegen and the boxing
6
6
  * helpers used for captured `let` bindings.
7
+ *
8
+ * The implementation is grouped by functional area under `xt_containers/` and
9
+ * `#include`d here as a single translation unit, so the internal helpers stay
10
+ * `static` while each file stays focused on one area.
7
11
  */
8
12
 
9
13
  #include "rt_internal.h"
@@ -12,621 +16,7 @@
12
16
  #include <stdlib.h>
13
17
  #include <string.h>
14
18
 
15
- /* ------------------------------------------------------------------------- */
16
- /* Objects */
17
- /* ------------------------------------------------------------------------- */
18
-
19
- static void xt_object_reserve(xt_object *obj, uint32_t needed) {
20
- if (needed <= obj->capacity) return;
21
- uint32_t capacity = obj->capacity ? obj->capacity * 2 : 8;
22
- while (capacity < needed) capacity *= 2;
23
- obj->properties = (xt_property *)realloc(obj->properties, sizeof(xt_property) * capacity);
24
- if (!obj->properties) {
25
- fprintf(stderr, "xbintsc: out of memory growing object\n");
26
- abort();
27
- }
28
- obj->capacity = capacity;
29
- }
30
-
31
- xt_value xt_object_new(void) { return xt_object_new_with_proto(XT_UNDEFINED); }
32
-
33
- xt_value xt_object_new_with_proto(xt_value proto) {
34
- xt_object *obj = (xt_object *)xt_alloc(sizeof(xt_object), XT_OBJECT_KIND_OBJECT);
35
- obj->count = 0;
36
- obj->capacity = 0;
37
- obj->properties = NULL;
38
- obj->prototype = proto;
39
- obj->frozen = 0;
40
- obj->is_array_base = 0;
41
- return XT_FROM_PTR(XT_TAG_OBJECT, obj);
42
- }
43
-
44
- xt_object *xt_as_object(xt_value value) {
45
- if (XT_IS_OBJECT(value)) return (xt_object *)XT_GET_PTR(value);
46
- if (XT_IS_FUNCTION(value)) {
47
- /* Functions carry their own property bag (used for static members). */
48
- xt_function *fn = (xt_function *)XT_GET_PTR(value);
49
- if (!fn->properties) fn->properties = (xt_object *)XT_GET_PTR(xt_object_new_with_proto(XT_UNDEFINED));
50
- return fn->properties;
51
- }
52
- return NULL;
53
- }
54
-
55
- static xt_property *xt_object_find(xt_object *obj, xt_value key) {
56
- for (uint32_t i = 0; i < obj->count; i++) {
57
- if (xt_property_key_equals(obj->properties[i].key, key)) return &obj->properties[i];
58
- }
59
- return NULL;
60
- }
61
-
62
- /*
63
- * JavaScript enumerates own string keys in a canonical order: array-index
64
- * keys (the canonical decimal form of an integer in [0, 2^32 - 2]) first, in
65
- * ascending numeric order, then the remaining keys in insertion order. We keep
66
- * the physical property array in exactly that order so every consumer
67
- * (`Object.keys`, `for...in`, `JSON.stringify`, ...) is correct for free.
68
- */
69
- static int xt_key_is_array_index(xt_string *key, uint32_t *out) {
70
- if (key->length == 0 || key->length > 10) return 0;
71
- if (key->data[0] == '0' && key->length != 1) return 0; /* "0" is canonical, "01" is not */
72
- uint64_t value = 0;
73
- for (uint32_t i = 0; i < key->length; i++) {
74
- char ch = key->data[i];
75
- if (ch < '0' || ch > '9') return 0;
76
- value = value * 10 + (uint64_t)(ch - '0');
77
- }
78
- if (value > 4294967294ULL) return 0; /* 2^32 - 2 is the largest array index */
79
- *out = (uint32_t)value;
80
- return 1;
81
- }
82
-
83
- /* Insert a new property for `key`, preserving JavaScript key order. Symbols
84
- * are not array indices and simply append in insertion order. */
85
- static xt_property *xt_object_insert_property(xt_object *obj, xt_value key) {
86
- uint32_t index = 0;
87
- uint32_t position = obj->count;
88
- if (XT_IS_STRING(key) && xt_key_is_array_index(xt_as_string(key), &index)) {
89
- for (uint32_t i = 0; i < obj->count; i++) {
90
- uint32_t existing = 0;
91
- xt_value existingKey = obj->properties[i].key;
92
- if (!XT_IS_STRING(existingKey) ||
93
- !xt_key_is_array_index(xt_as_string(existingKey), &existing)) {
94
- position = i; /* first non-index key: the integer prefix ends here */
95
- break;
96
- }
97
- if (existing > index) {
98
- position = i;
99
- break;
100
- }
101
- }
102
- }
103
- xt_object_reserve(obj, obj->count + 1);
104
- for (uint32_t i = obj->count; i > position; i--) obj->properties[i] = obj->properties[i - 1];
105
- xt_property *prop = &obj->properties[position];
106
- prop->key = key;
107
- prop->value = XT_UNDEFINED;
108
- prop->getter = XT_UNDEFINED;
109
- prop->setter = XT_UNDEFINED;
110
- obj->count++;
111
- return prop;
112
- }
113
-
114
- xt_property *xt_object_find_property(xt_object *obj, xt_value key) {
115
- return obj ? xt_object_find(obj, key) : NULL;
116
- }
117
-
118
- /* Normalise a property key to a string value or a symbol value. */
119
- xt_value xt_to_property_key(xt_value key) {
120
- if (xt_is_symbol(key)) return key;
121
- return xt_to_string(key);
122
- }
123
-
124
- /* Two property keys are equal when they are the same symbol, or equal
125
- * strings. */
126
- int xt_property_key_equals(xt_value a, xt_value b) {
127
- if (XT_IS_STRING(a) && XT_IS_STRING(b)) return xt_string_equals(xt_as_string(a), xt_as_string(b));
128
- return a == b;
129
- }
130
-
131
- static int xt_key_is_prototype(xt_value key) {
132
- if (!XT_IS_STRING(key)) return 0;
133
- xt_string *k = xt_as_string(key);
134
- return k && k->length == 9 && memcmp(k->data, "prototype", 9) == 0;
135
- }
136
-
137
- xt_value xt_object_get(xt_value value, xt_value key) {
138
- /* A function's `.prototype` lives in a dedicated field (set by
139
- `xt_function_set_prototype`), not in its property bag. Expose it as a
140
- normal property so `Class.prototype` returns the object instances use. */
141
- if (XT_IS_FUNCTION(value) && xt_key_is_prototype(key)) {
142
- return ((xt_function *)XT_GET_PTR(value))->prototype;
143
- }
144
- xt_object *obj = xt_as_object(value);
145
- if (!obj) return XT_UNDEFINED;
146
- /* Only plain objects (and function property bags) use the `xt_object`
147
- layout. Containers such as Map/Set/Date/RegExp/Promise/Array must not be
148
- interpreted as property tables, or property lookup reads past the end of
149
- their real representation. */
150
- if (obj->header.kind != XT_OBJECT_KIND_OBJECT && obj->header.kind != XT_OBJECT_KIND_ERROR)
151
- return XT_UNDEFINED;
152
- xt_value k = xt_to_property_key(key);
153
- /* Walk the prototype chain like JavaScript property lookup. */
154
- xt_object *cur = obj;
155
- while (cur) {
156
- xt_property *prop = xt_object_find(cur, k);
157
- if (prop) {
158
- /* Invoke accessors with the original receiver as `this`, so getters
159
- inherited from a prototype still see the instance. */
160
- if (prop->getter != XT_UNDEFINED && XT_IS_FUNCTION(prop->getter)) {
161
- return xt_call_with_this(prop->getter, value, 0, NULL);
162
- }
163
- if (prop->getter != XT_UNDEFINED) return XT_UNDEFINED;
164
- return prop->value;
165
- }
166
- if (!XT_IS_OBJECT(cur->prototype)) break;
167
- cur = (xt_object *)XT_GET_PTR(cur->prototype);
168
- }
169
- return XT_UNDEFINED;
170
- }
171
-
172
- xt_value xt_object_set(xt_value value, xt_value key, xt_value newValue) {
173
- if (XT_IS_FUNCTION(value) && xt_key_is_prototype(key)) {
174
- return xt_function_set_prototype(value, newValue);
175
- }
176
- xt_object *obj = xt_as_object(value);
177
- if (!obj) return newValue;
178
- if (obj->header.kind != XT_OBJECT_KIND_OBJECT && obj->header.kind != XT_OBJECT_KIND_ERROR)
179
- return newValue;
180
- if (obj->frozen) return newValue;
181
- xt_value k = xt_to_property_key(key);
182
- xt_property *prop = xt_object_find(obj, k);
183
- if (prop) {
184
- if (prop->setter != XT_UNDEFINED) {
185
- if (XT_IS_FUNCTION(prop->setter)) {
186
- xt_value argument = newValue;
187
- xt_call_with_this(prop->setter, value, 1, &argument);
188
- }
189
- return newValue;
190
- }
191
- if (prop->getter != XT_UNDEFINED) return newValue; /* accessor without setter */
192
- prop->value = newValue;
193
- return newValue;
194
- }
195
- /* No own property: an inherited accessor still intercepts the assignment
196
- (JavaScript assigns through prototype setters instead of shadowing). */
197
- xt_object *ancestor = XT_IS_OBJECT(obj->prototype) ? (xt_object *)XT_GET_PTR(obj->prototype) : NULL;
198
- while (ancestor) {
199
- xt_property *inherited = xt_object_find(ancestor, k);
200
- if (inherited) {
201
- if (inherited->setter != XT_UNDEFINED) {
202
- if (XT_IS_FUNCTION(inherited->setter)) {
203
- xt_value argument = newValue;
204
- xt_call_with_this(inherited->setter, value, 1, &argument);
205
- }
206
- return newValue;
207
- }
208
- if (inherited->getter != XT_UNDEFINED) return newValue; /* getter-only accessor */
209
- break; /* plain inherited data property: create an own shadowing property */
210
- }
211
- ancestor = XT_IS_OBJECT(ancestor->prototype) ? (xt_object *)XT_GET_PTR(ancestor->prototype) : NULL;
212
- }
213
- xt_property *inserted = xt_object_insert_property(obj, k);
214
- inserted->value = newValue;
215
- return newValue;
216
- }
217
-
218
- static xt_property *xt_object_ensure_property(xt_object *obj, xt_value key) {
219
- xt_value propertyKey = xt_to_property_key(key);
220
- xt_property *prop = xt_object_find(obj, propertyKey);
221
- if (prop) return prop;
222
- return xt_object_insert_property(obj, propertyKey);
223
- }
224
-
225
- xt_value xt_object_define_getter(xt_value value, xt_value key, xt_value getter) {
226
- xt_object *obj = xt_as_object(value);
227
- if (!obj) return value;
228
- xt_object_ensure_property(obj, key)->getter = getter;
229
- return value;
230
- }
231
-
232
- xt_value xt_object_define_setter(xt_value value, xt_value key, xt_value setter) {
233
- xt_object *obj = xt_as_object(value);
234
- if (!obj) return value;
235
- xt_object_ensure_property(obj, key)->setter = setter;
236
- return value;
237
- }
238
-
239
- xt_value xt_object_get_prototype(xt_value value) {
240
- xt_object *obj = xt_as_object(value);
241
- if (obj) return obj->prototype;
242
- return XT_UNDEFINED;
243
- }
244
-
245
- xt_value xt_object_set_prototype(xt_value value, xt_value proto) {
246
- xt_object *obj = xt_as_object(value);
247
- if (obj && !obj->frozen) obj->prototype = proto;
248
- return value;
249
- }
250
-
251
- xt_value xt_object_freeze(xt_value value) {
252
- xt_object *obj = xt_as_object(value);
253
- if (obj) obj->frozen = 1;
254
- return value;
255
- }
256
-
257
- int xt_object_is_frozen(xt_value value) {
258
- xt_object *obj = xt_as_object(value);
259
- return obj ? obj->frozen : 0;
260
- }
261
-
262
- xt_value xt_object_has_own(xt_value value, xt_value key) {
263
- xt_object *obj = xt_as_object(value);
264
- if (!obj) return XT_FALSE;
265
- return xt_bool(xt_object_find(obj, xt_to_property_key(key)) != NULL);
266
- }
267
-
268
- xt_value xt_object_from_entries(xt_value entries) {
269
- xt_value result = xt_object_new();
270
- xt_array *array = xt_as_array(entries);
271
- if (!array) return result;
272
- for (uint32_t i = 0; i < array->length; i++) {
273
- xt_array *pair = xt_as_array(array->items[i]);
274
- if (!pair || pair->length < 2) continue;
275
- xt_object_set(result, pair->items[0], pair->items[1]);
276
- }
277
- return result;
278
- }
279
-
280
- xt_value xt_object_has(xt_value value, xt_value key) {
281
- if (!XT_IS_OBJECT(value)) return XT_FALSE;
282
- xt_object *obj = (xt_object *)XT_GET_PTR(value);
283
- return xt_bool(xt_object_find(obj, xt_to_property_key(key)) != NULL);
284
- }
285
-
286
- /* `Object.getOwnPropertySymbols`: the symbol-keyed own properties, in
287
- * insertion order. String keys are skipped. */
288
- xt_value xt_object_own_property_symbols(xt_value value) {
289
- xt_value result = xt_array_new(0, NULL);
290
- if (!XT_IS_OBJECT(value)) return result;
291
- xt_object *obj = (xt_object *)XT_GET_PTR(value);
292
- if (obj->header.kind != XT_OBJECT_KIND_OBJECT && obj->header.kind != XT_OBJECT_KIND_ERROR)
293
- return result;
294
- for (uint32_t i = 0; i < obj->count; i++) {
295
- if (xt_is_symbol(obj->properties[i].key)) xt_array_push(result, obj->properties[i].key);
296
- }
297
- return result;
298
- }
299
-
300
- xt_value xt_object_keys(xt_value value) {
301
- xt_value result = xt_array_new(0, NULL);
302
- if (XT_IS_OBJECT(value)) {
303
- xt_object *obj = (xt_object *)XT_GET_PTR(value);
304
- for (uint32_t i = 0; i < obj->count; i++) {
305
- if (XT_IS_STRING(obj->properties[i].key)) xt_array_push(result, obj->properties[i].key);
306
- }
307
- return result;
308
- }
309
- if (XT_IS_ARRAY(value)) {
310
- xt_array *array = (xt_array *)XT_GET_PTR(value);
311
- for (uint32_t i = 0; i < array->length; i++) {
312
- char buffer[32];
313
- snprintf(buffer, sizeof(buffer), "%u", i);
314
- xt_array_push(result, xt_string_from_cstr(buffer));
315
- }
316
- if (XT_IS_OBJECT(array->extra)) {
317
- xt_object *extra = (xt_object *)XT_GET_PTR(array->extra);
318
- for (uint32_t i = 0; i < extra->count; i++) {
319
- if (XT_IS_STRING(extra->properties[i].key)) xt_array_push(result, extra->properties[i].key);
320
- }
321
- }
322
- return result;
323
- }
324
- if (XT_IS_STRING(value)) {
325
- xt_string *s = xt_as_string(value);
326
- for (uint32_t i = 0; i < s->length; i++) {
327
- char buffer[32];
328
- snprintf(buffer, sizeof(buffer), "%u", i);
329
- xt_array_push(result, xt_string_from_cstr(buffer));
330
- }
331
- return result;
332
- }
333
- return result;
334
- }
335
-
336
- /* Convenience used by codegen for `obj.prop`. */
337
- xt_value xt_object_get_cstr(xt_value value, const char *key) {
338
- xt_value k = xt_string_from_cstr(key);
339
- return xt_object_get(value, k);
340
- }
341
-
342
- /* ------------------------------------------------------------------------- */
343
- /* Arrays */
344
- /* ------------------------------------------------------------------------- */
345
-
346
- void xt_array_reserve(xt_array *array, uint32_t needed) {
347
- if (needed <= array->capacity) return;
348
- uint32_t capacity = array->capacity ? array->capacity * 2 : 8;
349
- while (capacity < needed) capacity *= 2;
350
- array->items = (xt_value *)realloc(array->items, sizeof(xt_value) * capacity);
351
- if (!array->items) {
352
- fprintf(stderr, "xbintsc: out of memory growing array\n");
353
- abort();
354
- }
355
- for (uint32_t i = array->capacity; i < capacity; i++) array->items[i] = XT_UNDEFINED;
356
- array->capacity = capacity;
357
- }
358
-
359
- xt_value xt_array_new(int32_t count, xt_value *items) {
360
- xt_array *array = (xt_array *)xt_alloc(sizeof(xt_array), XT_OBJECT_KIND_ARRAY);
361
- array->length = 0;
362
- array->capacity = 0;
363
- array->items = NULL;
364
- array->extra = XT_UNDEFINED;
365
- if (count > 0) {
366
- xt_array_reserve(array, (uint32_t)count);
367
- for (int32_t i = 0; i < count; i++) array->items[i] = items[i];
368
- array->length = (uint32_t)count;
369
- }
370
- return XT_FROM_PTR(XT_TAG_ARRAY, array);
371
- }
372
-
373
- /* Named properties of an array live in a lazily-created side object. Returns
374
- * XT_UNDEFINED when `create` is false and no such object exists yet. */
375
- static xt_value xt_array_extra(xt_array *array, int create) {
376
- if (!XT_IS_OBJECT(array->extra)) {
377
- if (!create) return XT_UNDEFINED;
378
- array->extra = xt_object_new();
379
- }
380
- return array->extra;
381
- }
382
-
383
- xt_value xt_array_get(xt_value value, xt_value index) {
384
- if (!XT_IS_ARRAY(value)) return XT_UNDEFINED;
385
- xt_array *array = (xt_array *)XT_GET_PTR(value);
386
- int32_t i = xt_to_int32(index);
387
- if (i < 0 || (uint32_t)i >= array->length) return XT_UNDEFINED;
388
- return array->items[i];
389
- }
390
-
391
- xt_value xt_array_set(xt_value value, xt_value index, xt_value newValue) {
392
- if (!XT_IS_ARRAY(value)) return newValue;
393
- xt_array *array = (xt_array *)XT_GET_PTR(value);
394
- int32_t i = xt_to_int32(index);
395
- if (i < 0) return newValue;
396
- xt_array_reserve(array, (uint32_t)i + 1);
397
- for (uint32_t j = array->length; j < (uint32_t)i; j++) array->items[j] = XT_UNDEFINED;
398
- array->items[i] = newValue;
399
- if ((uint32_t)i >= array->length) array->length = (uint32_t)i + 1;
400
- return newValue;
401
- }
402
-
403
- xt_value xt_array_push(xt_value value, xt_value newValue) {
404
- if (!XT_IS_ARRAY(value)) return xt_number(0);
405
- xt_array *array = (xt_array *)XT_GET_PTR(value);
406
- xt_array_reserve(array, array->length + 1);
407
- array->items[array->length++] = newValue;
408
- return xt_number((double)array->length);
409
- }
410
-
411
- xt_value xt_array_length(xt_value value) {
412
- if (XT_IS_ARRAY(value)) return xt_number((double)((xt_array *)XT_GET_PTR(value))->length);
413
- if (XT_IS_STRING(value)) return xt_number((double)xt_string_length(xt_as_string(value)));
414
- /* Functions expose their arity as `.length`. */
415
- if (XT_IS_FUNCTION(value)) {
416
- int32_t arity = ((xt_function *)XT_GET_PTR(value))->arity;
417
- return xt_number(arity >= 0 ? (double)arity : 0.0);
418
- }
419
- /* Objects such as Buffers expose a `length` property of their own. */
420
- if (XT_IS_OBJECT(value)) return xt_object_get_cstr(value, "length");
421
- return XT_UNDEFINED;
422
- }
423
-
424
- xt_value xt_array_spread(xt_value target, xt_value source) {
425
- if (!XT_IS_ARRAY(target)) return target;
426
- if (XT_IS_ARRAY(source)) {
427
- xt_array *dst = (xt_array *)XT_GET_PTR(target);
428
- xt_array *src = (xt_array *)XT_GET_PTR(source);
429
- xt_array_reserve(dst, dst->length + src->length);
430
- for (uint32_t i = 0; i < src->length; i++) dst->items[dst->length++] = src->items[i];
431
- return target;
432
- }
433
- /* Spreading a string/Map/Set/iterable iterates exactly like `for...of`. */
434
- source = xt_iter_open(source);
435
- for (int32_t i = 0; xt_truthy(xt_iter_has(source, xt_number((double)i))); i++) {
436
- xt_array_push(target, xt_iter_value(source, xt_number((double)i)));
437
- }
438
- return target;
439
- }
440
-
441
- int32_t xt_array_size(xt_value value) {
442
- if (!XT_IS_ARRAY(value)) return 0;
443
- return (int32_t)((xt_array *)XT_GET_PTR(value))->length;
444
- }
445
-
446
- xt_value *xt_array_items(xt_value value) {
447
- if (!XT_IS_ARRAY(value)) return NULL;
448
- return ((xt_array *)XT_GET_PTR(value))->items;
449
- }
450
-
451
-
452
- /* ------------------------------------------------------------------------- */
453
- /* Generic member access */
454
- /* ------------------------------------------------------------------------- */
455
-
456
- /*
457
- * Reading a property of `null` / `undefined` is a TypeError in JavaScript.
458
- * Short-circuiting `?.` guards forbid reaching this point for a nullish
459
- * receiver, so a non-optional access on a nullish base is a genuine bug in
460
- * the compiled program (e.g. `o?.a.b` where `o.a` is null).
461
- */
462
- static void xt_throw_read_of_nullish(xt_value target, xt_value key) {
463
- const char *base = target == XT_NULL ? "null" : "undefined";
464
- char keybuf[128];
465
- xt_string *k = XT_IS_STRING(key) ? xt_as_string(key) : xt_as_string(xt_to_string(key));
466
- uint32_t n = k->length < sizeof(keybuf) - 1 ? k->length : (uint32_t)(sizeof(keybuf) - 1);
467
- memcpy(keybuf, k->data, n);
468
- keybuf[n] = 0;
469
- char message[256];
470
- snprintf(message, sizeof(message),
471
- "TypeError: Cannot read properties of %s (reading '%s')", base, keybuf);
472
- xt_throw(xt_string_from_cstr(message));
473
- }
474
-
475
- xt_value xt_get(xt_value target, xt_value key) {
476
- if (target == XT_UNDEFINED || target == XT_NULL) xt_throw_read_of_nullish(target, key);
477
- if (XT_IS_ARRAY(target)) {
478
- /* `arr.length` must read the array's length, never an element. */
479
- if (XT_IS_STRING(key)) {
480
- xt_string *k = xt_as_string(key);
481
- if (k->length == 6 && memcmp(k->data, "length", 6) == 0)
482
- return xt_number((double)((xt_array *)XT_GET_PTR(target))->length);
483
- /* Named (non-index) properties such as `raw`/`index`/`input`. */
484
- uint32_t ignored = 0;
485
- if (!xt_key_is_array_index(k, &ignored)) {
486
- xt_value extra = xt_array_extra((xt_array *)XT_GET_PTR(target), 0);
487
- if (extra != XT_UNDEFINED) {
488
- xt_value value = xt_object_get(extra, key);
489
- if (value != XT_UNDEFINED) return value;
490
- }
491
- /* Fall back to first-class built-in methods (`arr.map`). */
492
- return xt_method_value(target, key);
493
- }
494
- return xt_array_get(target, key);
495
- }
496
- /* Symbol-keyed properties live in the side object too. */
497
- if (xt_is_symbol(key)) {
498
- xt_value extra = xt_array_extra((xt_array *)XT_GET_PTR(target), 0);
499
- if (extra != XT_UNDEFINED) {
500
- xt_value value = xt_object_get(extra, key);
501
- if (value != XT_UNDEFINED) return value;
502
- }
503
- return xt_method_value(target, key);
504
- }
505
- return xt_array_get(target, key);
506
- }
507
- if (XT_IS_FUNCTION(target)) {
508
- /* Functions expose own `name` / `length` (arity) properties. */
509
- if (XT_IS_STRING(key)) {
510
- xt_string *k = xt_as_string(key);
511
- if (k->length == 6 && memcmp(k->data, "length", 6) == 0) {
512
- int32_t arity = ((xt_function *)XT_GET_PTR(target))->arity;
513
- return xt_number(arity >= 0 ? (double)arity : 0.0);
514
- }
515
- if (k->length == 4 && memcmp(k->data, "name", 4) == 0) {
516
- xt_string *name = ((xt_function *)XT_GET_PTR(target))->name;
517
- return name ? XT_FROM_PTR(XT_TAG_STRING, name) : xt_string_from_cstr("");
518
- }
519
- }
520
- {
521
- xt_value value = xt_object_get(target, key);
522
- if (value != XT_UNDEFINED) return value;
523
- return xt_method_value(target, key);
524
- }
525
- }
526
- if (XT_IS_OBJECT(target)) {
527
- /* Map/Set expose `.size`; promises, dates and regexps have their own
528
- * getters implemented in the standard library. */
529
- xt_object *obj = (xt_object *)XT_GET_PTR(target);
530
- if (obj->header.kind == XT_OBJECT_KIND_SYMBOL) {
531
- if (XT_IS_STRING(key)) {
532
- xt_string *k = xt_as_string(key);
533
- if (k->length == 11 && memcmp(k->data, "description", 11) == 0) {
534
- return xt_symbol_description(target);
535
- }
536
- }
537
- return xt_method_value(target, key);
538
- }
539
- if (obj->header.kind == XT_OBJECT_KIND_MAP || obj->header.kind == XT_OBJECT_KIND_SET) {
540
- if (XT_IS_STRING(key)) {
541
- xt_string *k = xt_as_string(key);
542
- if (k->length == 4 && memcmp(k->data, "size", 4) == 0) {
543
- int32_t size = obj->header.kind == XT_OBJECT_KIND_MAP ? xt_map_size(target) : xt_set_size(target);
544
- return xt_number((double)size);
545
- }
546
- }
547
- }
548
- if (obj->header.kind == XT_OBJECT_KIND_REGEXP) {
549
- xt_value regexpValue = xt_regexp_get_property(target, key);
550
- if (regexpValue != XT_UNDEFINED) return regexpValue;
551
- }
552
- if (obj->header.kind == XT_OBJECT_KIND_ERROR && XT_IS_STRING(key)) {
553
- xt_string *k = xt_as_string(key);
554
- if (k->length == 5 && memcmp(k->data, "stack", 5) == 0) {
555
- xt_value own = xt_object_get(target, key);
556
- return own != XT_UNDEFINED ? own : xt_error_to_string(target);
557
- }
558
- }
559
- {
560
- xt_value value = xt_object_get(target, key);
561
- if (value != XT_UNDEFINED) return value;
562
- return xt_method_value(target, key);
563
- }
564
- }
565
- if (XT_IS_STRING(target)) {
566
- /* Property access on a string: `.length`, numeric indexing and built-in
567
- * methods. */
568
- xt_string *s = xt_as_string(target);
569
- if (XT_IS_STRING(key)) {
570
- xt_string *k = xt_as_string(key);
571
- if (k->length == 6 && memcmp(k->data, "length", 6) == 0) return xt_number((double)s->length);
572
- uint32_t index = 0;
573
- if (xt_key_is_array_index(k, &index) && index < s->length) {
574
- return xt_string_new(s->data + index, 1);
575
- }
576
- return xt_method_value(target, key);
577
- }
578
- if (XT_IS_NUMBER(key)) {
579
- int32_t index = xt_to_int32(key);
580
- if (index >= 0 && (uint32_t)index < s->length) return xt_string_new(s->data + index, 1);
581
- }
582
- return XT_UNDEFINED;
583
- }
584
- if (XT_IS_STRING(key) &&
585
- (XT_IS_NUMBER(target) || XT_IS_BIGINT(target) || target == XT_TRUE || target == XT_FALSE)) {
586
- return xt_method_value(target, key);
587
- }
588
- return XT_UNDEFINED;
589
- }
590
-
591
- xt_value xt_set(xt_value target, xt_value key, xt_value value) {
592
- if (XT_IS_ARRAY(target)) {
593
- /* Assigning `arr.length` truncates or extends the array. */
594
- if (XT_IS_STRING(key)) {
595
- xt_string *k = xt_as_string(key);
596
- if (k->length == 6 && memcmp(k->data, "length", 6) == 0) {
597
- xt_array *array = (xt_array *)XT_GET_PTR(target);
598
- int32_t n = xt_to_int32(value);
599
- if (n < 0) n = 0;
600
- xt_array_reserve(array, (uint32_t)n);
601
- for (uint32_t j = array->length; j < (uint32_t)n; j++) array->items[j] = XT_UNDEFINED;
602
- array->length = (uint32_t)n;
603
- return value;
604
- }
605
- uint32_t ignored = 0;
606
- if (!xt_key_is_array_index(k, &ignored)) {
607
- return xt_object_set(xt_array_extra((xt_array *)XT_GET_PTR(target), 1), key, value);
608
- }
609
- return xt_array_set(target, key, value);
610
- }
611
- if (xt_is_symbol(key)) {
612
- return xt_object_set(xt_array_extra((xt_array *)XT_GET_PTR(target), 1), key, value);
613
- }
614
- return xt_array_set(target, key, value);
615
- }
616
- if (XT_IS_FUNCTION(target)) return xt_object_set(target, key, value);
617
- if (XT_IS_OBJECT(target)) return xt_object_set(target, key, value);
618
- return value;
619
- }
620
-
621
- /* ------------------------------------------------------------------------- */
622
- /* Boxes */
623
- /* ------------------------------------------------------------------------- */
624
-
625
- xt_value xt_box_new(xt_value value) { return xt_array_new(1, &value); }
626
-
627
- xt_value xt_box_get(xt_value box) { return xt_array_get(box, xt_number(0)); }
628
-
629
- xt_value xt_box_set(xt_value box, xt_value value) { return xt_array_set(box, xt_number(0), value); }
630
-
631
- xt_value xt_is_nullish(xt_value value) { return xt_bool(value == XT_UNDEFINED || value == XT_NULL); }
632
-
19
+ #include "xt_containers/objects.inc"
20
+ #include "xt_containers/arrays.inc"
21
+ #include "xt_containers/access.inc"
22
+ #include "xt_containers/boxes.inc"
package/runtime/xt_ext.h CHANGED
@@ -20,7 +20,6 @@
20
20
  * runtime directory on the include path:
21
21
  *
22
22
  * clang++ -O2 -fPIC -I<runtime> -c mathx.cpp -o mathx.o
23
- * ar rcs libmathx.a mathx.o
24
23
  */
25
24
  #ifndef XT_EXT_H
26
25
  #define XT_EXT_H