xbintsc 0.3.81 → 0.5.6

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 (188) hide show
  1. package/AGENTS.md +8 -4
  2. package/README.md +16 -5
  3. package/README.zh-CN.md +14 -6
  4. package/dist/src/ast/common.d.ts +23 -0
  5. package/dist/src/cli/main.js +68 -24
  6. package/dist/src/cli/main.js.map +1 -1
  7. package/dist/src/codegen/generator/calls/access.js +6 -2
  8. package/dist/src/codegen/generator/calls/access.js.map +1 -1
  9. package/dist/src/codegen/generator/calls/closures.js +4 -0
  10. package/dist/src/codegen/generator/calls/closures.js.map +1 -1
  11. package/dist/src/codegen/generator/calls/invocation.js +9 -4
  12. package/dist/src/codegen/generator/calls/invocation.js.map +1 -1
  13. package/dist/src/codegen/generator/context.d.ts +50 -0
  14. package/dist/src/codegen/generator/context.js +124 -13
  15. package/dist/src/codegen/generator/context.js.map +1 -1
  16. package/dist/src/codegen/generator/debug.d.ts +33 -0
  17. package/dist/src/codegen/generator/debug.js +97 -0
  18. package/dist/src/codegen/generator/debug.js.map +1 -0
  19. package/dist/src/codegen/generator/expressions/assignment.js +9 -5
  20. package/dist/src/codegen/generator/expressions/assignment.js.map +1 -1
  21. package/dist/src/codegen/generator/expressions/operators.js +35 -9
  22. package/dist/src/codegen/generator/expressions/operators.js.map +1 -1
  23. package/dist/src/codegen/generator/expressions/primary.js +11 -3
  24. package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
  25. package/dist/src/codegen/generator/generator.d.ts +3 -1
  26. package/dist/src/codegen/generator/generator.js +3 -1
  27. package/dist/src/codegen/generator/generator.js.map +1 -1
  28. package/dist/src/codegen/generator/module.d.ts +1 -1
  29. package/dist/src/codegen/generator/module.js +82 -12
  30. package/dist/src/codegen/generator/module.js.map +1 -1
  31. package/dist/src/codegen/generator/numeric.d.ts +26 -0
  32. package/dist/src/codegen/generator/numeric.js +127 -0
  33. package/dist/src/codegen/generator/numeric.js.map +1 -0
  34. package/dist/src/codegen/generator/state.d.ts +17 -0
  35. package/dist/src/codegen/generator/state.js +9 -0
  36. package/dist/src/codegen/generator/state.js.map +1 -1
  37. package/dist/src/codegen/generator/statements/control-flow.js +2 -4
  38. package/dist/src/codegen/generator/statements/control-flow.js.map +1 -1
  39. package/dist/src/codegen/generator/statements/dispatch.js +3 -0
  40. package/dist/src/codegen/generator/statements/dispatch.js.map +1 -1
  41. package/dist/src/codegen/generator/statements/variables.js +8 -2
  42. package/dist/src/codegen/generator/statements/variables.js.map +1 -1
  43. package/dist/src/codegen/generator/tables.d.ts +16 -0
  44. package/dist/src/codegen/generator/tables.js +99 -2
  45. package/dist/src/codegen/generator/tables.js.map +1 -1
  46. package/dist/src/driver/bundler/merge.js +41 -5
  47. package/dist/src/driver/bundler/merge.js.map +1 -1
  48. package/dist/src/driver/compiler.d.ts +23 -4
  49. package/dist/src/driver/compiler.js +46 -57
  50. package/dist/src/driver/compiler.js.map +1 -1
  51. package/dist/src/driver/fingerprint.d.ts +27 -0
  52. package/dist/src/driver/fingerprint.js +88 -0
  53. package/dist/src/driver/fingerprint.js.map +1 -0
  54. package/dist/src/driver/toolchain-provider.d.ts +9 -2
  55. package/dist/src/driver/toolchain-provider.js +15 -15
  56. package/dist/src/driver/toolchain-provider.js.map +1 -1
  57. package/dist/src/driver/toolchain.d.ts +58 -1
  58. package/dist/src/driver/toolchain.js +169 -22
  59. package/dist/src/driver/toolchain.js.map +1 -1
  60. package/dist/src/parser/expressions.js +20 -1
  61. package/dist/src/parser/expressions.js.map +1 -1
  62. package/dist/tests/cli/main.test.js +41 -1
  63. package/dist/tests/cli/main.test.js.map +1 -1
  64. package/dist/tests/codegen/closures.test.js +8 -0
  65. package/dist/tests/codegen/closures.test.js.map +1 -1
  66. package/dist/tests/codegen/expressions.test.js +14 -3
  67. package/dist/tests/codegen/expressions.test.js.map +1 -1
  68. package/dist/tests/codegen/llvm.test.js +23 -0
  69. package/dist/tests/codegen/llvm.test.js.map +1 -1
  70. package/dist/tests/driver/toolchain-provider.test.js +49 -2
  71. package/dist/tests/driver/toolchain-provider.test.js.map +1 -1
  72. package/dist/tests/driver/toolchain.test.js +62 -3
  73. package/dist/tests/driver/toolchain.test.js.map +1 -1
  74. package/dist/tests/e2e/async-await.test.d.ts +10 -0
  75. package/dist/tests/e2e/async-await.test.js +247 -0
  76. package/dist/tests/e2e/async-await.test.js.map +1 -0
  77. package/dist/tests/e2e/child-process.test.d.ts +10 -0
  78. package/dist/tests/e2e/child-process.test.js +59 -0
  79. package/dist/tests/e2e/child-process.test.js.map +1 -0
  80. package/dist/tests/e2e/compile-objects-classes.test.js +47 -0
  81. package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
  82. package/dist/tests/e2e/error-stack.test.d.ts +9 -0
  83. package/dist/tests/e2e/error-stack.test.js +94 -0
  84. package/dist/tests/e2e/error-stack.test.js.map +1 -0
  85. package/dist/tests/e2e/runtime-coverage-globals.test.js +46 -0
  86. package/dist/tests/e2e/runtime-coverage-globals.test.js.map +1 -1
  87. package/dist/tests/e2e/string-concat.test.d.ts +9 -0
  88. package/dist/tests/e2e/string-concat.test.js +102 -0
  89. package/dist/tests/e2e/string-concat.test.js.map +1 -0
  90. package/dist/tests/e2e/string-utf16.test.d.ts +6 -0
  91. package/dist/tests/e2e/string-utf16.test.js +133 -0
  92. package/dist/tests/e2e/string-utf16.test.js.map +1 -0
  93. package/dist/tests/helpers.d.ts +9 -0
  94. package/dist/tests/helpers.js +26 -3
  95. package/dist/tests/helpers.js.map +1 -1
  96. package/dist/tests/parser/expressions.test.js +7 -0
  97. package/dist/tests/parser/expressions.test.js.map +1 -1
  98. package/dist/tests/version.test.d.ts +1 -0
  99. package/dist/tests/version.test.js +24 -0
  100. package/dist/tests/version.test.js.map +1 -0
  101. package/doc/DESIGN.md +20 -12
  102. package/doc/ai/cli.md +2 -0
  103. package/doc/ai/contributing.md +16 -8
  104. package/doc/ai/extensions.md +3 -2
  105. package/doc/ai/language-support.md +15 -12
  106. package/doc/ai/troubleshooting.md +43 -5
  107. package/doc/ai/zh-CN/cli.md +2 -0
  108. package/doc/ai/zh-CN/contributing.md +11 -7
  109. package/doc/ai/zh-CN/extensions.md +2 -1
  110. package/doc/ai/zh-CN/language-support.md +15 -12
  111. package/doc/ai/zh-CN/troubleshooting.md +38 -4
  112. package/doc/implemented.md +16 -13
  113. package/doc/requirements.md +13 -4
  114. package/doc/unimplemented.md +20 -18
  115. package/doc/zh-CN/DESIGN.md +15 -9
  116. package/doc/zh-CN/implemented.md +15 -12
  117. package/doc/zh-CN/requirements.md +12 -3
  118. package/doc/zh-CN/unimplemented.md +19 -17
  119. package/package.json +3 -1
  120. package/runtime/ext_node/buffer/parts/construction.inc +2 -2
  121. package/runtime/ext_node/buffer/parts/methods.inc +1 -1
  122. package/runtime/ext_node/buffer/parts/search.inc +1 -1
  123. package/runtime/ext_node/child_process/child_process.c +25 -0
  124. package/runtime/ext_node/fs/fd_ops.c +1 -1
  125. package/runtime/rt.h +49 -1
  126. package/runtime/rt_internal.h +136 -4
  127. package/runtime/xt_alloc.c +20 -2
  128. package/runtime/xt_async.c +197 -0
  129. package/runtime/xt_bigint/conversions.inc +1 -1
  130. package/runtime/xt_builtins.c +169 -43
  131. package/runtime/xt_constructors.c +389 -0
  132. package/runtime/xt_containers/access.inc +61 -24
  133. package/runtime/xt_containers/arrays.inc +26 -2
  134. package/runtime/xt_containers/objects.inc +206 -8
  135. package/runtime/xt_coroutine.c +212 -0
  136. package/runtime/xt_generator.c +31 -162
  137. package/runtime/xt_io/exception.inc +171 -2
  138. package/runtime/xt_io/inspect.inc +48 -13
  139. package/runtime/xt_io.c +5 -0
  140. package/runtime/xt_promise.c +62 -17
  141. package/runtime/xt_stdlib/arrays.inc +2 -2
  142. package/runtime/xt_stdlib/dispatch.inc +20 -4
  143. package/runtime/xt_stdlib/strings.inc +98 -29
  144. package/runtime/xt_stdlib2/array-statics.inc +3 -2
  145. package/runtime/xt_stdlib2/arrays.inc +1 -1
  146. package/runtime/xt_stdlib2/error.inc +33 -6
  147. package/runtime/xt_stdlib2/json.inc +46 -16
  148. package/runtime/xt_stdlib2/number-string-statics.inc +24 -13
  149. package/runtime/xt_stdlib2/objects.inc +1 -1
  150. package/runtime/xt_stdlib2/regexp-match.inc +50 -35
  151. package/runtime/xt_stdlib2/set.inc +6 -0
  152. package/runtime/xt_stdlib2/strings.inc +81 -42
  153. package/runtime/xt_symbol.c +1 -1
  154. package/runtime/xt_typed_array/construction.inc +43 -2
  155. package/runtime/xt_typed_array.c +4 -0
  156. package/runtime/xt_values/comparison.inc +2 -2
  157. package/runtime/xt_values/constructors.inc +18 -5
  158. package/runtime/xt_values/conversions.inc +4 -3
  159. package/runtime/xt_values/strings.inc +94 -4
  160. package/runtime/xt_values/utf16.inc +340 -0
  161. package/runtime/xt_values.c +1 -0
  162. package/scripts/bench.ts +172 -0
  163. package/scripts/build-runtime.ts +2 -1
  164. package/scripts/check-version.ts +53 -0
  165. package/src/ast/common.ts +23 -0
  166. package/src/cli/main.ts +68 -26
  167. package/src/codegen/generator/calls/access.ts +7 -2
  168. package/src/codegen/generator/calls/closures.ts +3 -0
  169. package/src/codegen/generator/calls/invocation.ts +9 -3
  170. package/src/codegen/generator/context.ts +129 -18
  171. package/src/codegen/generator/debug.ts +132 -0
  172. package/src/codegen/generator/expressions/assignment.ts +9 -5
  173. package/src/codegen/generator/expressions/operators.ts +47 -8
  174. package/src/codegen/generator/expressions/primary.ts +11 -3
  175. package/src/codegen/generator/generator.ts +18 -2
  176. package/src/codegen/generator/module.ts +83 -13
  177. package/src/codegen/generator/numeric.ts +158 -0
  178. package/src/codegen/generator/state.ts +26 -0
  179. package/src/codegen/generator/statements/control-flow.ts +2 -3
  180. package/src/codegen/generator/statements/dispatch.ts +3 -0
  181. package/src/codegen/generator/statements/variables.ts +8 -2
  182. package/src/codegen/generator/tables.ts +110 -2
  183. package/src/driver/bundler/merge.ts +39 -5
  184. package/src/driver/compiler.ts +65 -55
  185. package/src/driver/fingerprint.ts +85 -0
  186. package/src/driver/toolchain-provider.ts +17 -16
  187. package/src/driver/toolchain.ts +210 -21
  188. package/src/parser/expressions.ts +20 -1
@@ -18,23 +18,22 @@
18
18
 
19
19
  xt_value xt_object_values(xt_value value) {
20
20
  xt_value result = xt_array_new(0, NULL);
21
- if (!XT_IS_OBJECT(value)) return result;
22
- xt_object *obj = (xt_object *)XT_GET_PTR(value);
23
- for (uint32_t i = 0; i < obj->count; i++) {
24
- if (XT_IS_STRING(obj->properties[i].key)) xt_array_push(result, obj->properties[i].value);
25
- }
21
+ xt_value keys = xt_object_keys(value);
22
+ xt_array *array = xt_as_array(keys);
23
+ if (!array) return result;
24
+ for (uint32_t i = 0; i < array->length; i++) xt_array_push(result, xt_get(value, array->items[i]));
26
25
  return result;
27
26
  }
28
27
 
29
28
  xt_value xt_object_entries(xt_value value) {
30
29
  xt_value result = xt_array_new(0, NULL);
31
- if (!XT_IS_OBJECT(value)) return result;
32
- xt_object *obj = (xt_object *)XT_GET_PTR(value);
33
- for (uint32_t i = 0; i < obj->count; i++) {
34
- if (!XT_IS_STRING(obj->properties[i].key)) continue;
30
+ xt_value keys = xt_object_keys(value);
31
+ xt_array *array = xt_as_array(keys);
32
+ if (!array) return result;
33
+ for (uint32_t i = 0; i < array->length; i++) {
35
34
  xt_value pair = xt_array_new(0, NULL);
36
- xt_array_push(pair, obj->properties[i].key);
37
- xt_array_push(pair, obj->properties[i].value);
35
+ xt_array_push(pair, array->items[i]);
36
+ xt_array_push(pair, xt_get(value, array->items[i]));
38
37
  xt_array_push(result, pair);
39
38
  }
40
39
  return result;
@@ -45,8 +44,11 @@ xt_value xt_object_assign(int32_t argc, xt_value *argv) {
45
44
  xt_value target = argv[0];
46
45
  if (!XT_IS_OBJECT(target)) return target;
47
46
  for (int32_t i = 1; i < argc; i++) {
48
- if (!XT_IS_OBJECT(argv[i])) continue;
49
- xt_object *source = (xt_object *)XT_GET_PTR(argv[i]);
47
+ if (!XT_IS_OBJECT(argv[i]) && !XT_IS_ARRAY(argv[i]) && !XT_IS_STRING(argv[i])) continue;
48
+ /* Arrays and strings contribute their index properties, exactly like
49
+ * `{ ..."ab" }` / `Object.assign({}, [1, 2])` in ECMAScript. */
50
+ xt_value properties = xt_object_rest(argv[i], 0, NULL);
51
+ xt_object *source = (xt_object *)XT_GET_PTR(properties);
50
52
  for (uint32_t j = 0; j < source->count; j++) {
51
53
  xt_object_set(target, source->properties[j].key, source->properties[j].value);
52
54
  }
@@ -62,9 +64,77 @@ xt_value xt_object_spread(xt_value target, xt_value source) {
62
64
  return xt_object_assign(2, args);
63
65
  }
64
66
 
67
+ /* True when `key` is one of the explicitly destructured properties. */
68
+ static int xt_object_rest_excludes(xt_value key, int32_t argc, xt_value *argv) {
69
+ for (int32_t i = 0; i < argc; i++) {
70
+ if (xt_property_key_equals(key, argv[i])) return 1;
71
+ }
72
+ return 0;
73
+ }
74
+
75
+ static void xt_object_rest_copy(xt_value target, xt_value key, xt_value value, int32_t argc, xt_value *argv) {
76
+ if (xt_object_rest_excludes(key, argc, argv)) return;
77
+ xt_object_set(target, key, value);
78
+ }
79
+
80
+ /*
81
+ * `const { a, ...rest } = source` (and the assignment / parameter forms).
82
+ *
83
+ * Copies the *own enumerable* properties that the pattern did not name, in
84
+ * insertion order. Arrays and strings contribute their index properties, like
85
+ * ECMAScript; accessor properties are read through their getter, with the
86
+ * source as the receiver.
87
+ */
88
+ xt_value xt_object_rest(xt_value source, int32_t argc, xt_value *argv) {
89
+ if (source == XT_UNDEFINED || source == XT_NULL) {
90
+ xt_throw(xt_string_from_cstr("TypeError: Cannot destructure null or undefined"));
91
+ return XT_UNDEFINED;
92
+ }
93
+ xt_value result = xt_object_new();
94
+
95
+ if (XT_IS_ARRAY(source)) {
96
+ xt_array *array = (xt_array *)XT_GET_PTR(source);
97
+ for (uint32_t i = 0; i < array->length; i++) {
98
+ char buffer[16];
99
+ snprintf(buffer, sizeof(buffer), "%u", i);
100
+ xt_object_rest_copy(result, xt_string_from_cstr(buffer), array->items[i], argc, argv);
101
+ }
102
+ return result;
103
+ }
104
+
105
+ if (XT_IS_STRING(source)) {
106
+ xt_string *string = (xt_string *)XT_GET_PTR(source);
107
+ uint32_t units = xt_string_utf16_length(string);
108
+ for (uint32_t i = 0; i < units; i++) {
109
+ char buffer[16];
110
+ snprintf(buffer, sizeof(buffer), "%u", i);
111
+ xt_object_rest_copy(result, xt_string_from_cstr(buffer), xt_string_unit_value(string, (int32_t)i), argc, argv);
112
+ }
113
+ return result;
114
+ }
115
+
116
+ if (!XT_IS_OBJECT(source) && !XT_IS_FUNCTION(source)) return result;
117
+ xt_object *object = xt_as_object(source);
118
+ if (!object) return result;
119
+ if (object->header.kind != XT_OBJECT_KIND_OBJECT && object->header.kind != XT_OBJECT_KIND_ERROR) {
120
+ /* Map/Set/Date/RegExp/Promise have no own enumerable string properties. */
121
+ return result;
122
+ }
123
+ for (uint32_t i = 0; i < object->count; i++) {
124
+ xt_property *property = &object->properties[i];
125
+ if (xt_object_rest_excludes(property->key, argc, argv)) continue;
126
+ xt_value value = property->value;
127
+ if (property->getter != XT_UNDEFINED && XT_IS_FUNCTION(property->getter)) {
128
+ value = xt_call_with_this(property->getter, source, 0, NULL);
129
+ }
130
+ xt_object_set(result, property->key, value);
131
+ }
132
+ return result;
133
+ }
134
+
65
135
  xt_value xt_parse_int(int32_t argc, xt_value *argv) {
66
136
  xt_string *s = xt_as_string(xt_to_string(xt_arg_at(argc, argv, 0)));
67
- const char *p = s->data;
137
+ const char *p = xt_string_bytes(s);
68
138
  /* JavaScript `parseInt` semantics: skip leading whitespace, accept an
69
139
  optional sign, pick the radix (auto-detecting a `0x` prefix), read the
70
140
  longest run of valid digits and accumulate into a double. Accumulating as
@@ -107,9 +177,10 @@ xt_value xt_parse_int(int32_t argc, xt_value *argv) {
107
177
 
108
178
  xt_value xt_parse_float(int32_t argc, xt_value *argv) {
109
179
  xt_string *s = xt_as_string(xt_to_string(xt_arg_at(argc, argv, 0)));
180
+ const char *bytes = xt_string_bytes(s);
110
181
  char *end = NULL;
111
- double value = strtod(s->data, &end);
112
- if (end == s->data) return xt_number(NAN);
182
+ double value = strtod(bytes, &end);
183
+ if (end == bytes) return xt_number(NAN);
113
184
  return xt_number(value);
114
185
  }
115
186
 
@@ -140,6 +211,7 @@ static int xt_uri_is_kept(const char *allowed, unsigned char c) {
140
211
 
141
212
  static xt_value xt_uri_encode(xt_value input, const char *allowed) {
142
213
  xt_string *s = xt_as_string(xt_to_string(input));
214
+ const char *bytes = xt_string_bytes(s);
143
215
  static const char hex[] = "0123456789ABCDEF";
144
216
  char *out = (char *)malloc((size_t)s->length * 3 + 1);
145
217
  if (!out) {
@@ -148,7 +220,7 @@ static xt_value xt_uri_encode(xt_value input, const char *allowed) {
148
220
  }
149
221
  size_t written = 0;
150
222
  for (uint32_t i = 0; i < s->length; i++) {
151
- unsigned char c = (unsigned char)s->data[i];
223
+ unsigned char c = (unsigned char)bytes[i];
152
224
  if (xt_uri_is_kept(allowed, c)) {
153
225
  out[written++] = (char)c;
154
226
  } else {
@@ -173,6 +245,7 @@ static int xt_hex_value(int c) {
173
245
  * escapes for reserved characters are copied through unchanged. */
174
246
  static xt_value xt_uri_decode(xt_value input, int component) {
175
247
  xt_string *s = xt_as_string(xt_to_string(input));
248
+ const char *bytes = xt_string_bytes(s);
176
249
  char *out = (char *)malloc((size_t)s->length + 1);
177
250
  if (!out) {
178
251
  fprintf(stderr, "xbintsc: out of memory\n");
@@ -181,22 +254,22 @@ static xt_value xt_uri_decode(xt_value input, int component) {
181
254
  size_t written = 0;
182
255
  uint32_t i = 0;
183
256
  while (i < s->length) {
184
- unsigned char c = (unsigned char)s->data[i];
257
+ unsigned char c = (unsigned char)bytes[i];
185
258
  if (c != '%') {
186
259
  out[written++] = (char)c;
187
260
  i++;
188
261
  continue;
189
262
  }
190
263
  if (i + 2 >= s->length) xt_throw_uri_error("URI malformed");
191
- int h1 = xt_hex_value((unsigned char)s->data[i + 1]);
192
- int h2 = xt_hex_value((unsigned char)s->data[i + 2]);
264
+ int h1 = xt_hex_value((unsigned char)bytes[i + 1]);
265
+ int h2 = xt_hex_value((unsigned char)bytes[i + 2]);
193
266
  if (h1 < 0 || h2 < 0) xt_throw_uri_error("URI malformed");
194
267
  unsigned char b = (unsigned char)((h1 << 4) | h2);
195
268
  if (b < 0x80) {
196
269
  if (!component && xt_uri_is_kept(";/?:@&=+$,#", b)) {
197
- out[written++] = s->data[i];
198
- out[written++] = s->data[i + 1];
199
- out[written++] = s->data[i + 2];
270
+ out[written++] = bytes[i];
271
+ out[written++] = bytes[i + 1];
272
+ out[written++] = bytes[i + 2];
200
273
  } else {
201
274
  out[written++] = (char)b;
202
275
  }
@@ -213,9 +286,9 @@ static xt_value xt_uri_decode(xt_value input, int component) {
213
286
  for (int k = 1; k <= extra; k++) {
214
287
  uint32_t pos = i + (uint32_t)k * 3;
215
288
  if (pos + 2 >= s->length) xt_throw_uri_error("URI malformed");
216
- if (s->data[pos] != '%') xt_throw_uri_error("URI malformed");
217
- int c1 = xt_hex_value((unsigned char)s->data[pos + 1]);
218
- int c2 = xt_hex_value((unsigned char)s->data[pos + 2]);
289
+ if (bytes[pos] != '%') xt_throw_uri_error("URI malformed");
290
+ int c1 = xt_hex_value((unsigned char)bytes[pos + 1]);
291
+ int c2 = xt_hex_value((unsigned char)bytes[pos + 2]);
219
292
  if (c1 < 0 || c2 < 0) xt_throw_uri_error("URI malformed");
220
293
  unsigned char cb = (unsigned char)((c1 << 4) | c2);
221
294
  if ((cb & 0xC0) != 0x80) xt_throw_uri_error("URI malformed");
@@ -322,9 +395,9 @@ xt_value xt_in(xt_value key, xt_value value) {
322
395
  if (xt_is_symbol(key)) return XT_FALSE;
323
396
  xt_string *s = xt_as_string(value);
324
397
  xt_string *k = xt_as_string(xt_to_string(key));
325
- if (k->length == 6 && memcmp(k->data, "length", 6) == 0) return XT_TRUE;
398
+ if (k->length == 6 && memcmp(xt_string_bytes(k), "length", 6) == 0) return XT_TRUE;
326
399
  int32_t index = xt_to_int32(key);
327
- return xt_bool(index >= 0 && (uint32_t)index < s->length);
400
+ return xt_bool(index >= 0 && (uint32_t)index < xt_string_utf16_length(s));
328
401
  }
329
402
  return XT_FALSE;
330
403
  }
@@ -375,6 +448,9 @@ xt_value xt_closure_new(void *fn, int32_t env_count, xt_value *env) {
375
448
  function->properties = NULL;
376
449
  function->environment = NULL;
377
450
  function->prototype = XT_UNDEFINED;
451
+ function->is_generator = 0;
452
+ function->is_async = 0;
453
+ function->builtin_name = NULL;
378
454
  if (env_count > 0) {
379
455
  function->environment = (xt_value *)malloc(sizeof(xt_value) * (size_t)env_count);
380
456
  for (int32_t i = 0; i < env_count; i++) function->environment[i] = env[i];
@@ -395,6 +471,9 @@ xt_value xt_call_with_this(xt_value value, xt_value thisValue, int32_t argc, xt_
395
471
  /* Calling a generator function returns a suspended generator instead of
396
472
  * running the body. */
397
473
  if (function->is_generator) return xt_generator_new(value, thisValue, argc, argv);
474
+ /* An `async` function runs its body on a coroutine and returns a promise,
475
+ * which may already be settled or may resolve after an event-loop turn. */
476
+ if (function->is_async) return xt_async_call(value, thisValue, argc, argv);
398
477
  /* The closure value itself is threaded through as `env` so the callee can
399
478
  * read its captures with xt_closure_env(env, i). */
400
479
  return function->code(thisValue, value, argc, argv);
@@ -407,11 +486,6 @@ xt_value xt_function_set_prototype(xt_value value, xt_value proto) {
407
486
  return value;
408
487
  }
409
488
 
410
- xt_value xt_function_set_generator(xt_value value) {
411
- if (XT_IS_FUNCTION(value)) ((xt_function *)XT_GET_PTR(value))->is_generator = 1;
412
- return value;
413
- }
414
-
415
489
  xt_value xt_function_get_prototype(xt_value value) {
416
490
  if (XT_IS_FUNCTION(value)) return ((xt_function *)XT_GET_PTR(value))->prototype;
417
491
  return XT_UNDEFINED;
@@ -426,26 +500,78 @@ xt_value xt_new(xt_value ctor, int32_t argc, xt_value *argv) {
426
500
  xt_value proto = function->prototype;
427
501
  xt_value instance = xt_object_new_with_proto(XT_IS_OBJECT(proto) ? proto : XT_UNDEFINED);
428
502
  xt_value result = function->code(instance, ctor, argc, argv);
429
- if (XT_IS_OBJECT(result) || XT_IS_ARRAY(result)) return result;
503
+ if (XT_IS_OBJECT(result) || XT_IS_ARRAY(result) || XT_IS_FUNCTION(result)) return result;
430
504
  return instance;
431
505
  }
432
506
 
433
507
  xt_value xt_instance_of(xt_value value, xt_value ctor) {
434
508
  if (!XT_IS_FUNCTION(ctor)) return XT_FALSE;
435
509
  xt_value proto = ((xt_function *)XT_GET_PTR(ctor))->prototype;
436
- if (!XT_IS_OBJECT(proto)) return XT_FALSE;
437
- if (!XT_IS_OBJECT(value)) return XT_FALSE;
438
- xt_object *cur = (xt_object *)XT_GET_PTR(value);
439
- xt_object *target = (xt_object *)XT_GET_PTR(proto);
440
- cur = (xt_object *)XT_GET_PTR(XT_IS_OBJECT(cur->prototype) ? cur->prototype : XT_UNDEFINED);
441
- while (cur) {
442
- if (cur == target) return XT_TRUE;
443
- if (!XT_IS_OBJECT(cur->prototype)) break;
444
- cur = (xt_object *)XT_GET_PTR(cur->prototype);
510
+ if (XT_IS_OBJECT(proto) || XT_IS_ARRAY(proto) || XT_IS_FUNCTION(proto)) {
511
+ /* Walk the value's [[Prototype]] chain. `xt_object_get_prototype` knows the
512
+ * layout of every kind (arrays carry a prototype field; Map/Set/Date/... use
513
+ * their built-in prototype), so this is safe for containers too. */
514
+ xt_value cursor = xt_object_get_prototype(value);
515
+ while (cursor != XT_UNDEFINED && cursor != XT_NULL) {
516
+ if (cursor == proto) return XT_TRUE;
517
+ cursor = xt_object_get_prototype(cursor);
518
+ }
445
519
  }
446
520
  return XT_FALSE;
447
521
  }
448
522
 
523
+ /*
524
+ * `value instanceof Array` (and the rest of the built-in constructors).
525
+ *
526
+ * The codegen recognises the direct spelling and asks this helper instead of
527
+ * materialising the constructor value; an alias (`const A = Array`) goes
528
+ * through the ordinary prototype chain in `xt_instance_of`. Ids match
529
+ * `BUILTIN_INSTANCEOF` in `src/codegen/generator/tables.ts`; 16..24 map onto
530
+ * the runtime's `XT_TA_*` order (Uint8Array first).
531
+ */
532
+ enum {
533
+ XT_INSTANCE_ARRAY = 0,
534
+ XT_INSTANCE_OBJECT = 1,
535
+ XT_INSTANCE_FUNCTION = 2,
536
+ XT_INSTANCE_MAP = 3,
537
+ XT_INSTANCE_SET = 4,
538
+ XT_INSTANCE_DATE = 5,
539
+ XT_INSTANCE_REGEXP = 6,
540
+ XT_INSTANCE_PROMISE = 7,
541
+ XT_INSTANCE_TYPED_ARRAY_FIRST = 16,
542
+ XT_INSTANCE_TYPED_ARRAY_LAST = 24
543
+ };
544
+
545
+ static int xt_value_has_kind(xt_value value, uint8_t kind) {
546
+ return XT_IS_OBJECT(value) && ((xt_object *)XT_GET_PTR(value))->header.kind == kind;
547
+ }
548
+
549
+ xt_value xt_instance_of_builtin(xt_value value, int32_t id) {
550
+ switch (id) {
551
+ case XT_INSTANCE_ARRAY:
552
+ return xt_bool(XT_IS_ARRAY(value));
553
+ case XT_INSTANCE_OBJECT:
554
+ return xt_bool(XT_IS_OBJECT(value) || XT_IS_ARRAY(value) || XT_IS_FUNCTION(value));
555
+ case XT_INSTANCE_FUNCTION:
556
+ return xt_bool(XT_IS_FUNCTION(value));
557
+ case XT_INSTANCE_MAP:
558
+ return xt_bool(xt_value_has_kind(value, XT_OBJECT_KIND_MAP));
559
+ case XT_INSTANCE_SET:
560
+ return xt_bool(xt_value_has_kind(value, XT_OBJECT_KIND_SET));
561
+ case XT_INSTANCE_DATE:
562
+ return xt_bool(xt_value_has_kind(value, XT_OBJECT_KIND_DATE));
563
+ case XT_INSTANCE_REGEXP:
564
+ return xt_bool(xt_value_has_kind(value, XT_OBJECT_KIND_REGEXP));
565
+ case XT_INSTANCE_PROMISE:
566
+ return xt_bool(xt_value_has_kind(value, XT_OBJECT_KIND_PROMISE));
567
+ default:
568
+ if (id >= XT_INSTANCE_TYPED_ARRAY_FIRST && id <= XT_INSTANCE_TYPED_ARRAY_LAST) {
569
+ return xt_bool(xt_typed_array_kind_of(value) == id - XT_INSTANCE_TYPED_ARRAY_FIRST);
570
+ }
571
+ return XT_FALSE;
572
+ }
573
+ }
574
+
449
575
  xt_value xt_closure_env(xt_value value, int32_t index) {
450
576
  if (!XT_IS_FUNCTION(value)) return XT_UNDEFINED;
451
577
  xt_function *function = (xt_function *)XT_GET_PTR(value);