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.
- package/AGENTS.md +8 -4
- package/README.md +16 -5
- package/README.zh-CN.md +14 -6
- package/dist/src/ast/common.d.ts +23 -0
- package/dist/src/cli/main.js +68 -24
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/calls/access.js +6 -2
- package/dist/src/codegen/generator/calls/access.js.map +1 -1
- package/dist/src/codegen/generator/calls/closures.js +4 -0
- package/dist/src/codegen/generator/calls/closures.js.map +1 -1
- package/dist/src/codegen/generator/calls/invocation.js +9 -4
- package/dist/src/codegen/generator/calls/invocation.js.map +1 -1
- package/dist/src/codegen/generator/context.d.ts +50 -0
- package/dist/src/codegen/generator/context.js +124 -13
- package/dist/src/codegen/generator/context.js.map +1 -1
- package/dist/src/codegen/generator/debug.d.ts +33 -0
- package/dist/src/codegen/generator/debug.js +97 -0
- package/dist/src/codegen/generator/debug.js.map +1 -0
- package/dist/src/codegen/generator/expressions/assignment.js +9 -5
- package/dist/src/codegen/generator/expressions/assignment.js.map +1 -1
- package/dist/src/codegen/generator/expressions/operators.js +35 -9
- package/dist/src/codegen/generator/expressions/operators.js.map +1 -1
- package/dist/src/codegen/generator/expressions/primary.js +11 -3
- package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
- package/dist/src/codegen/generator/generator.d.ts +3 -1
- package/dist/src/codegen/generator/generator.js +3 -1
- package/dist/src/codegen/generator/generator.js.map +1 -1
- package/dist/src/codegen/generator/module.d.ts +1 -1
- package/dist/src/codegen/generator/module.js +82 -12
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/numeric.d.ts +26 -0
- package/dist/src/codegen/generator/numeric.js +127 -0
- package/dist/src/codegen/generator/numeric.js.map +1 -0
- package/dist/src/codegen/generator/state.d.ts +17 -0
- package/dist/src/codegen/generator/state.js +9 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/statements/control-flow.js +2 -4
- package/dist/src/codegen/generator/statements/control-flow.js.map +1 -1
- package/dist/src/codegen/generator/statements/dispatch.js +3 -0
- package/dist/src/codegen/generator/statements/dispatch.js.map +1 -1
- package/dist/src/codegen/generator/statements/variables.js +8 -2
- package/dist/src/codegen/generator/statements/variables.js.map +1 -1
- package/dist/src/codegen/generator/tables.d.ts +16 -0
- package/dist/src/codegen/generator/tables.js +99 -2
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/driver/bundler/merge.js +41 -5
- package/dist/src/driver/bundler/merge.js.map +1 -1
- package/dist/src/driver/compiler.d.ts +23 -4
- package/dist/src/driver/compiler.js +46 -57
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/fingerprint.d.ts +27 -0
- package/dist/src/driver/fingerprint.js +88 -0
- package/dist/src/driver/fingerprint.js.map +1 -0
- package/dist/src/driver/toolchain-provider.d.ts +9 -2
- package/dist/src/driver/toolchain-provider.js +15 -15
- package/dist/src/driver/toolchain-provider.js.map +1 -1
- package/dist/src/driver/toolchain.d.ts +58 -1
- package/dist/src/driver/toolchain.js +169 -22
- package/dist/src/driver/toolchain.js.map +1 -1
- package/dist/src/parser/expressions.js +20 -1
- package/dist/src/parser/expressions.js.map +1 -1
- package/dist/tests/cli/main.test.js +41 -1
- package/dist/tests/cli/main.test.js.map +1 -1
- package/dist/tests/codegen/closures.test.js +8 -0
- package/dist/tests/codegen/closures.test.js.map +1 -1
- package/dist/tests/codegen/expressions.test.js +14 -3
- package/dist/tests/codegen/expressions.test.js.map +1 -1
- package/dist/tests/codegen/llvm.test.js +23 -0
- package/dist/tests/codegen/llvm.test.js.map +1 -1
- package/dist/tests/driver/toolchain-provider.test.js +49 -2
- package/dist/tests/driver/toolchain-provider.test.js.map +1 -1
- package/dist/tests/driver/toolchain.test.js +62 -3
- package/dist/tests/driver/toolchain.test.js.map +1 -1
- package/dist/tests/e2e/async-await.test.d.ts +10 -0
- package/dist/tests/e2e/async-await.test.js +247 -0
- package/dist/tests/e2e/async-await.test.js.map +1 -0
- package/dist/tests/e2e/child-process.test.d.ts +10 -0
- package/dist/tests/e2e/child-process.test.js +59 -0
- package/dist/tests/e2e/child-process.test.js.map +1 -0
- package/dist/tests/e2e/compile-objects-classes.test.js +47 -0
- package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
- package/dist/tests/e2e/error-stack.test.d.ts +9 -0
- package/dist/tests/e2e/error-stack.test.js +94 -0
- package/dist/tests/e2e/error-stack.test.js.map +1 -0
- package/dist/tests/e2e/runtime-coverage-globals.test.js +46 -0
- package/dist/tests/e2e/runtime-coverage-globals.test.js.map +1 -1
- package/dist/tests/e2e/string-concat.test.d.ts +9 -0
- package/dist/tests/e2e/string-concat.test.js +102 -0
- package/dist/tests/e2e/string-concat.test.js.map +1 -0
- package/dist/tests/e2e/string-utf16.test.d.ts +6 -0
- package/dist/tests/e2e/string-utf16.test.js +133 -0
- package/dist/tests/e2e/string-utf16.test.js.map +1 -0
- package/dist/tests/helpers.d.ts +9 -0
- package/dist/tests/helpers.js +26 -3
- package/dist/tests/helpers.js.map +1 -1
- package/dist/tests/parser/expressions.test.js +7 -0
- package/dist/tests/parser/expressions.test.js.map +1 -1
- package/dist/tests/version.test.d.ts +1 -0
- package/dist/tests/version.test.js +24 -0
- package/dist/tests/version.test.js.map +1 -0
- package/doc/DESIGN.md +20 -12
- package/doc/ai/cli.md +2 -0
- package/doc/ai/contributing.md +16 -8
- package/doc/ai/extensions.md +3 -2
- package/doc/ai/language-support.md +15 -12
- package/doc/ai/troubleshooting.md +43 -5
- package/doc/ai/zh-CN/cli.md +2 -0
- package/doc/ai/zh-CN/contributing.md +11 -7
- package/doc/ai/zh-CN/extensions.md +2 -1
- package/doc/ai/zh-CN/language-support.md +15 -12
- package/doc/ai/zh-CN/troubleshooting.md +38 -4
- package/doc/implemented.md +16 -13
- package/doc/requirements.md +13 -4
- package/doc/unimplemented.md +20 -18
- package/doc/zh-CN/DESIGN.md +15 -9
- package/doc/zh-CN/implemented.md +15 -12
- package/doc/zh-CN/requirements.md +12 -3
- package/doc/zh-CN/unimplemented.md +19 -17
- package/package.json +3 -1
- package/runtime/ext_node/buffer/parts/construction.inc +2 -2
- package/runtime/ext_node/buffer/parts/methods.inc +1 -1
- package/runtime/ext_node/buffer/parts/search.inc +1 -1
- package/runtime/ext_node/child_process/child_process.c +25 -0
- package/runtime/ext_node/fs/fd_ops.c +1 -1
- package/runtime/rt.h +49 -1
- package/runtime/rt_internal.h +136 -4
- package/runtime/xt_alloc.c +20 -2
- package/runtime/xt_async.c +197 -0
- package/runtime/xt_bigint/conversions.inc +1 -1
- package/runtime/xt_builtins.c +169 -43
- package/runtime/xt_constructors.c +389 -0
- package/runtime/xt_containers/access.inc +61 -24
- package/runtime/xt_containers/arrays.inc +26 -2
- package/runtime/xt_containers/objects.inc +206 -8
- package/runtime/xt_coroutine.c +212 -0
- package/runtime/xt_generator.c +31 -162
- package/runtime/xt_io/exception.inc +171 -2
- package/runtime/xt_io/inspect.inc +48 -13
- package/runtime/xt_io.c +5 -0
- package/runtime/xt_promise.c +62 -17
- package/runtime/xt_stdlib/arrays.inc +2 -2
- package/runtime/xt_stdlib/dispatch.inc +20 -4
- package/runtime/xt_stdlib/strings.inc +98 -29
- package/runtime/xt_stdlib2/array-statics.inc +3 -2
- package/runtime/xt_stdlib2/arrays.inc +1 -1
- package/runtime/xt_stdlib2/error.inc +33 -6
- package/runtime/xt_stdlib2/json.inc +46 -16
- package/runtime/xt_stdlib2/number-string-statics.inc +24 -13
- package/runtime/xt_stdlib2/objects.inc +1 -1
- package/runtime/xt_stdlib2/regexp-match.inc +50 -35
- package/runtime/xt_stdlib2/set.inc +6 -0
- package/runtime/xt_stdlib2/strings.inc +81 -42
- package/runtime/xt_symbol.c +1 -1
- package/runtime/xt_typed_array/construction.inc +43 -2
- package/runtime/xt_typed_array.c +4 -0
- package/runtime/xt_values/comparison.inc +2 -2
- package/runtime/xt_values/constructors.inc +18 -5
- package/runtime/xt_values/conversions.inc +4 -3
- package/runtime/xt_values/strings.inc +94 -4
- package/runtime/xt_values/utf16.inc +340 -0
- package/runtime/xt_values.c +1 -0
- package/scripts/bench.ts +172 -0
- package/scripts/build-runtime.ts +2 -1
- package/scripts/check-version.ts +53 -0
- package/src/ast/common.ts +23 -0
- package/src/cli/main.ts +68 -26
- package/src/codegen/generator/calls/access.ts +7 -2
- package/src/codegen/generator/calls/closures.ts +3 -0
- package/src/codegen/generator/calls/invocation.ts +9 -3
- package/src/codegen/generator/context.ts +129 -18
- package/src/codegen/generator/debug.ts +132 -0
- package/src/codegen/generator/expressions/assignment.ts +9 -5
- package/src/codegen/generator/expressions/operators.ts +47 -8
- package/src/codegen/generator/expressions/primary.ts +11 -3
- package/src/codegen/generator/generator.ts +18 -2
- package/src/codegen/generator/module.ts +83 -13
- package/src/codegen/generator/numeric.ts +158 -0
- package/src/codegen/generator/state.ts +26 -0
- package/src/codegen/generator/statements/control-flow.ts +2 -3
- package/src/codegen/generator/statements/dispatch.ts +3 -0
- package/src/codegen/generator/statements/variables.ts +8 -2
- package/src/codegen/generator/tables.ts +110 -2
- package/src/driver/bundler/merge.ts +39 -5
- package/src/driver/compiler.ts +65 -55
- package/src/driver/fingerprint.ts +85 -0
- package/src/driver/toolchain-provider.ts +17 -16
- package/src/driver/toolchain.ts +210 -21
- package/src/parser/expressions.ts +20 -1
package/runtime/xt_builtins.c
CHANGED
|
@@ -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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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,
|
|
37
|
-
xt_array_push(pair,
|
|
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
|
-
|
|
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
|
|
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(
|
|
112
|
-
if (end ==
|
|
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)
|
|
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)
|
|
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)
|
|
192
|
-
int h2 = xt_hex_value((unsigned char)
|
|
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++] =
|
|
198
|
-
out[written++] =
|
|
199
|
-
out[written++] =
|
|
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 (
|
|
217
|
-
int c1 = xt_hex_value((unsigned char)
|
|
218
|
-
int c2 = xt_hex_value((unsigned char)
|
|
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
|
|
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
|
|
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 (
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
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);
|