xbintsc 0.3.35 → 0.3.46
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/README.md +6 -3
- package/dist/src/codegen/generator/module.js +10 -0
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/state.js +4 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/tests/e2e/gc.test.d.ts +1 -0
- package/dist/tests/e2e/gc.test.js +168 -0
- package/dist/tests/e2e/gc.test.js.map +1 -0
- package/dist/tests/e2e/harness.d.ts +2 -0
- package/dist/tests/e2e/harness.js +1 -0
- package/dist/tests/e2e/harness.js.map +1 -1
- package/package.json +3 -2
- package/runtime/ext_gui/dom_api_proto.cpp +5 -0
- package/runtime/ext_gui/window.cpp +1 -0
- package/runtime/ext_node/buffer/parts/prototype.inc +1 -0
- package/runtime/ext_node/dgram/dgram.c +1 -0
- package/runtime/ext_node/events/events.c +1 -0
- package/runtime/ext_node/fs/fs_ops.c +10 -25
- package/runtime/ext_node/fs/glob.c +13 -30
- package/runtime/ext_node/fs/promises.c +1 -0
- package/runtime/ext_node/http/parts/prototypes.inc +5 -0
- package/runtime/ext_node/net/parts/prototypes.inc +2 -0
- package/runtime/ext_node/process/process.c +9 -7
- package/runtime/ext_node/stream/stream.c +1 -0
- package/runtime/ext_node/util/util.c +6 -6
- package/runtime/rt.h +10 -0
- package/runtime/rt_internal.h +63 -2
- package/runtime/xt_alloc.c +442 -5
- package/runtime/xt_generator.c +95 -1
- package/runtime/xt_loop.c +35 -1
- package/runtime/xt_promise.c +46 -0
- package/runtime/xt_stdlib2/error.inc +1 -0
- package/runtime/xt_stdlib2/regexp-match.inc +8 -7
- package/runtime/xt_symbol.c +2 -0
- package/runtime/xt_typed_array/construction.inc +142 -0
- package/runtime/xt_typed_array/elements.inc +92 -0
- package/runtime/xt_typed_array/methods.inc +329 -0
- package/runtime/xt_typed_array.c +6 -548
- package/runtime/xt_values/number-format.inc +26 -0
- package/scripts/check-file-length.ts +85 -0
- package/src/codegen/generator/module.ts +10 -0
- package/src/codegen/generator/state.ts +4 -0
package/runtime/xt_typed_array.c
CHANGED
|
@@ -37,78 +37,6 @@ static const int xt_ta_bytes[XT_TA_KIND_COUNT] = {1, 1, 1, 2, 2, 4, 4, 4, 8};
|
|
|
37
37
|
|
|
38
38
|
static xt_value xt_ta_protos[XT_TA_KIND_COUNT];
|
|
39
39
|
|
|
40
|
-
/* -- element conversion --------------------------------------------------- */
|
|
41
|
-
|
|
42
|
-
/* ECMAScript `ToUintN` / `ToIntN`: truncate, then wrap modulo 2^N. */
|
|
43
|
-
static double xt_ta_wrap(double value, double modulus) {
|
|
44
|
-
if (isnan(value) || isinf(value)) return 0;
|
|
45
|
-
double result = fmod(trunc(value), modulus);
|
|
46
|
-
if (result < 0) result += modulus;
|
|
47
|
-
return result;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
double xt_typed_array_coerce(int kind, double value) {
|
|
51
|
-
switch (kind) {
|
|
52
|
-
case XT_TA_U8:
|
|
53
|
-
return xt_ta_wrap(value, 256.0);
|
|
54
|
-
case XT_TA_I8: {
|
|
55
|
-
double wrapped = xt_ta_wrap(value, 256.0);
|
|
56
|
-
return wrapped >= 128.0 ? wrapped - 256.0 : wrapped;
|
|
57
|
-
}
|
|
58
|
-
case XT_TA_U8C:
|
|
59
|
-
if (isnan(value) || value <= 0) return 0;
|
|
60
|
-
if (value >= 255) return 255;
|
|
61
|
-
return rint(value);
|
|
62
|
-
case XT_TA_U16:
|
|
63
|
-
return xt_ta_wrap(value, 65536.0);
|
|
64
|
-
case XT_TA_I16: {
|
|
65
|
-
double wrapped = xt_ta_wrap(value, 65536.0);
|
|
66
|
-
return wrapped >= 32768.0 ? wrapped - 65536.0 : wrapped;
|
|
67
|
-
}
|
|
68
|
-
case XT_TA_U32:
|
|
69
|
-
return xt_ta_wrap(value, 4294967296.0);
|
|
70
|
-
case XT_TA_I32: {
|
|
71
|
-
double wrapped = xt_ta_wrap(value, 4294967296.0);
|
|
72
|
-
return wrapped >= 2147483648.0 ? wrapped - 4294967296.0 : wrapped;
|
|
73
|
-
}
|
|
74
|
-
case XT_TA_F32:
|
|
75
|
-
return (double)(float)value;
|
|
76
|
-
case XT_TA_F64:
|
|
77
|
-
default:
|
|
78
|
-
return value;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
int xt_typed_array_kind_of(xt_value value) {
|
|
83
|
-
if (!XT_IS_OBJECT(value)) return -1;
|
|
84
|
-
xt_object *object = (xt_object *)XT_GET_PTR(value);
|
|
85
|
-
if (object->header.kind != XT_OBJECT_KIND_OBJECT) return -1;
|
|
86
|
-
for (int kind = 0; kind < XT_TA_KIND_COUNT; kind++) {
|
|
87
|
-
if (xt_ta_protos[kind] && object->prototype == xt_ta_protos[kind]) return kind;
|
|
88
|
-
}
|
|
89
|
-
return -1;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/* -- element storage ------------------------------------------------------ */
|
|
93
|
-
|
|
94
|
-
static uint32_t xt_ta_length(xt_value array) {
|
|
95
|
-
double length = xt_to_number(xt_object_get_cstr(array, "length"));
|
|
96
|
-
if (!(length > 0)) return 0;
|
|
97
|
-
return (uint32_t)length;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
static xt_value xt_ta_element(xt_value array, uint32_t index) {
|
|
101
|
-
char key[24];
|
|
102
|
-
snprintf(key, sizeof(key), "%u", index);
|
|
103
|
-
return xt_object_get_cstr(array, key);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
static void xt_ta_store(xt_value array, int kind, uint32_t index, double value) {
|
|
107
|
-
char key[24];
|
|
108
|
-
snprintf(key, sizeof(key), "%u", index);
|
|
109
|
-
xt_object_set(array, xt_string_from_cstr(key), xt_number(xt_typed_array_coerce(kind, value)));
|
|
110
|
-
}
|
|
111
|
-
|
|
112
40
|
/* -- forward declarations ------------------------------------------------- */
|
|
113
41
|
|
|
114
42
|
static xt_value xt_ta_method_fill(xt_value, xt_value, int32_t, xt_value *);
|
|
@@ -135,480 +63,10 @@ static xt_value xt_ta_method_keys(xt_value, xt_value, int32_t, xt_value *);
|
|
|
135
63
|
static xt_value xt_ta_method_values(xt_value, xt_value, int32_t, xt_value *);
|
|
136
64
|
static xt_value xt_ta_method_entries(xt_value, xt_value, int32_t, xt_value *);
|
|
137
65
|
|
|
138
|
-
/*
|
|
139
|
-
|
|
140
|
-
static
|
|
141
|
-
xt_object_set(proto, xt_string_from_cstr(name), xt_closure_new(fn, 0, NULL));
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
static xt_value xt_ta_proto(int kind) {
|
|
145
|
-
if (kind < 0 || kind >= XT_TA_KIND_COUNT) return XT_UNDEFINED;
|
|
146
|
-
if (xt_ta_protos[kind]) return xt_ta_protos[kind];
|
|
147
|
-
xt_value proto = xt_object_new();
|
|
148
|
-
xt_ta_protos[kind] = proto;
|
|
149
|
-
xt_object_set(proto, xt_string_from_cstr("BYTES_PER_ELEMENT"), xt_number((double)xt_ta_bytes[kind]));
|
|
150
|
-
xt_ta_define(proto, "fill", (void *)xt_ta_method_fill);
|
|
151
|
-
xt_ta_define(proto, "set", (void *)xt_ta_method_set);
|
|
152
|
-
xt_ta_define(proto, "slice", (void *)xt_ta_method_slice);
|
|
153
|
-
xt_ta_define(proto, "subarray", (void *)xt_ta_method_slice);
|
|
154
|
-
xt_ta_define(proto, "join", (void *)xt_ta_method_join);
|
|
155
|
-
xt_ta_define(proto, "toString", (void *)xt_ta_method_to_string);
|
|
156
|
-
xt_ta_define(proto, "toLocaleString", (void *)xt_ta_method_to_string);
|
|
157
|
-
xt_ta_define(proto, "indexOf", (void *)xt_ta_method_index_of);
|
|
158
|
-
xt_ta_define(proto, "lastIndexOf", (void *)xt_ta_method_last_index_of);
|
|
159
|
-
xt_ta_define(proto, "includes", (void *)xt_ta_method_includes);
|
|
160
|
-
xt_ta_define(proto, "forEach", (void *)xt_ta_method_for_each);
|
|
161
|
-
xt_ta_define(proto, "map", (void *)xt_ta_method_map);
|
|
162
|
-
xt_ta_define(proto, "filter", (void *)xt_ta_method_filter);
|
|
163
|
-
xt_ta_define(proto, "every", (void *)xt_ta_method_every);
|
|
164
|
-
xt_ta_define(proto, "some", (void *)xt_ta_method_some);
|
|
165
|
-
xt_ta_define(proto, "find", (void *)xt_ta_method_find);
|
|
166
|
-
xt_ta_define(proto, "findIndex", (void *)xt_ta_method_find_index);
|
|
167
|
-
xt_ta_define(proto, "reduce", (void *)xt_ta_method_reduce);
|
|
168
|
-
xt_ta_define(proto, "reverse", (void *)xt_ta_method_reverse);
|
|
169
|
-
xt_ta_define(proto, "sort", (void *)xt_ta_method_sort);
|
|
170
|
-
xt_ta_define(proto, "copyWithin", (void *)xt_ta_method_copy_within);
|
|
171
|
-
xt_ta_define(proto, "at", (void *)xt_ta_method_at);
|
|
172
|
-
xt_ta_define(proto, "keys", (void *)xt_ta_method_keys);
|
|
173
|
-
xt_ta_define(proto, "values", (void *)xt_ta_method_values);
|
|
174
|
-
xt_ta_define(proto, "entries", (void *)xt_ta_method_entries);
|
|
175
|
-
return proto;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
static xt_value xt_ta_new(int kind, uint32_t length) {
|
|
179
|
-
xt_value array = xt_object_new_with_proto(xt_ta_proto(kind));
|
|
180
|
-
xt_object_set(array, xt_string_from_cstr("length"), xt_number((double)length));
|
|
181
|
-
xt_object_set(array, xt_string_from_cstr("byteLength"), xt_number((double)length * xt_ta_bytes[kind]));
|
|
182
|
-
xt_object_set(array, xt_string_from_cstr("byteOffset"), xt_number(0));
|
|
183
|
-
for (uint32_t i = 0; i < length; i++) xt_ta_store(array, kind, i, 0);
|
|
184
|
-
return array;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/* Length of any value a typed array can be built from, or 0 when it is not
|
|
188
|
-
* array-like (strings/iterables are intentionally not treated as element
|
|
189
|
-
* sources yet). */
|
|
190
|
-
static int xt_ta_length_of(xt_value value, uint32_t *out) {
|
|
191
|
-
if (XT_IS_ARRAY(value)) {
|
|
192
|
-
*out = (uint32_t)xt_to_number(xt_array_length(value));
|
|
193
|
-
return 1;
|
|
194
|
-
}
|
|
195
|
-
if (XT_IS_STRING(value)) {
|
|
196
|
-
*out = xt_as_string(value)->length;
|
|
197
|
-
return 1;
|
|
198
|
-
}
|
|
199
|
-
if (xt_typed_array_kind_of(value) >= 0) {
|
|
200
|
-
*out = xt_ta_length(value);
|
|
201
|
-
return 1;
|
|
202
|
-
}
|
|
203
|
-
if (XT_IS_OBJECT(value)) {
|
|
204
|
-
xt_value length = xt_object_get_cstr(value, "length");
|
|
205
|
-
if (length != XT_UNDEFINED) {
|
|
206
|
-
double size = xt_to_number(length);
|
|
207
|
-
*out = size > 0 ? (uint32_t)size : 0;
|
|
208
|
-
return 1;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
return 0;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
static xt_value xt_ta_from_value(int kind, xt_value value, xt_value mapFn, xt_value thisArg, int haveMap) {
|
|
215
|
-
uint32_t length = 0;
|
|
216
|
-
if (!xt_ta_length_of(value, &length)) length = 0;
|
|
217
|
-
xt_value array = xt_ta_new(kind, length);
|
|
218
|
-
for (uint32_t i = 0; i < length; i++) {
|
|
219
|
-
xt_value item = xt_get(value, xt_number((double)i));
|
|
220
|
-
if (haveMap) {
|
|
221
|
-
xt_value args[3] = {item, xt_number((double)i), array};
|
|
222
|
-
item = xt_call_with_this(mapFn, thisArg, 3, args);
|
|
223
|
-
}
|
|
224
|
-
xt_ta_store(array, kind, i, xt_to_number(item));
|
|
225
|
-
}
|
|
226
|
-
return array;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
static xt_value xt_ta_ctor_impl(int kind, int32_t argc, xt_value *argv) {
|
|
230
|
-
if (argc == 0) return xt_ta_new(kind, 0);
|
|
231
|
-
xt_value argument = argv[0];
|
|
232
|
-
/* Objects (arrays / typed arrays / array-likes / iterables) are copied
|
|
233
|
-
* element-wise; every other argument is a length via `ToIndex`. */
|
|
234
|
-
if (XT_IS_ARRAY(argument) || XT_IS_OBJECT(argument)) {
|
|
235
|
-
return xt_ta_from_value(kind, argument, XT_UNDEFINED, XT_UNDEFINED, 0);
|
|
236
|
-
}
|
|
237
|
-
double size = xt_to_number(argument);
|
|
238
|
-
return xt_ta_new(kind, size > 0 ? (uint32_t)trunc(size) : 0);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
static xt_value xt_ta_static_impl(int kind, xt_value name, int32_t argc, xt_value *argv) {
|
|
242
|
-
const char *method = xt_string_data(name);
|
|
243
|
-
if (!method) return XT_UNDEFINED;
|
|
244
|
-
if (strcmp(method, "from") == 0) {
|
|
245
|
-
int haveMap = argc > 1 && XT_IS_FUNCTION(argv[1]);
|
|
246
|
-
return xt_ta_from_value(kind, xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1), xt_arg_at(argc, argv, 2), haveMap);
|
|
247
|
-
}
|
|
248
|
-
if (strcmp(method, "of") == 0) {
|
|
249
|
-
xt_value array = xt_ta_new(kind, (uint32_t)argc);
|
|
250
|
-
for (int32_t i = 0; i < argc; i++) xt_ta_store(array, kind, (uint32_t)i, xt_to_number(argv[i]));
|
|
251
|
-
return array;
|
|
252
|
-
}
|
|
253
|
-
return XT_UNDEFINED;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
#define XT_TA_CTOR(suffix, kind) \
|
|
257
|
-
xt_value xt_ta_##suffix##_ctor(int32_t argc, xt_value *argv) { return xt_ta_ctor_impl(kind, argc, argv); } \
|
|
258
|
-
xt_value xt_ta_##suffix##_static(xt_value name, int32_t argc, xt_value *argv) { \
|
|
259
|
-
return xt_ta_static_impl(kind, name, argc, argv); \
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
XT_TA_CTOR(u8, XT_TA_U8)
|
|
263
|
-
XT_TA_CTOR(i8, XT_TA_I8)
|
|
264
|
-
XT_TA_CTOR(u8c, XT_TA_U8C)
|
|
265
|
-
XT_TA_CTOR(u16, XT_TA_U16)
|
|
266
|
-
XT_TA_CTOR(i16, XT_TA_I16)
|
|
267
|
-
XT_TA_CTOR(u32, XT_TA_U32)
|
|
268
|
-
XT_TA_CTOR(i32, XT_TA_I32)
|
|
269
|
-
XT_TA_CTOR(f32, XT_TA_F32)
|
|
270
|
-
XT_TA_CTOR(f64, XT_TA_F64)
|
|
271
|
-
|
|
272
|
-
/* -- helpers -------------------------------------------------------------- */
|
|
273
|
-
|
|
274
|
-
static int32_t xt_ta_relative(int32_t index, int32_t length) {
|
|
275
|
-
if (index < 0) index += length;
|
|
276
|
-
if (index < 0) index = 0;
|
|
277
|
-
if (index > length) index = length;
|
|
278
|
-
return index;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
static xt_value xt_ta_append(xt_value array, int kind, xt_value value) {
|
|
282
|
-
uint32_t length = xt_ta_length(array);
|
|
283
|
-
xt_object_set(array, xt_string_from_cstr("length"), xt_number((double)(length + 1)));
|
|
284
|
-
xt_object_set(array, xt_string_from_cstr("byteLength"), xt_number((double)(length + 1) * xt_ta_bytes[kind]));
|
|
285
|
-
xt_ta_store(array, kind, length, xt_to_number(value));
|
|
286
|
-
return array;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/* -- methods -------------------------------------------------------------- */
|
|
290
|
-
|
|
291
|
-
static xt_value xt_ta_method_fill(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
292
|
-
(void)env;
|
|
293
|
-
int kind = xt_typed_array_kind_of(self);
|
|
294
|
-
if (kind < 0) return self;
|
|
295
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
296
|
-
int32_t start = xt_ta_relative(argc > 1 ? xt_to_int32(argv[1]) : 0, length);
|
|
297
|
-
int32_t end = xt_ta_relative(argc > 2 && argv[2] != XT_UNDEFINED ? xt_to_int32(argv[2]) : length, length);
|
|
298
|
-
double value = xt_to_number(xt_arg_at(argc, argv, 0));
|
|
299
|
-
for (int32_t i = start; i < end; i++) xt_ta_store(self, kind, (uint32_t)i, value);
|
|
300
|
-
return self;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
static xt_value xt_ta_method_set(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
304
|
-
(void)env;
|
|
305
|
-
int kind = xt_typed_array_kind_of(self);
|
|
306
|
-
if (kind < 0) return XT_UNDEFINED;
|
|
307
|
-
xt_value source = xt_arg_at(argc, argv, 0);
|
|
308
|
-
uint32_t sourceLength = 0;
|
|
309
|
-
if (!xt_ta_length_of(source, &sourceLength)) return XT_UNDEFINED;
|
|
310
|
-
int32_t offset = argc > 1 ? xt_to_int32(argv[1]) : 0;
|
|
311
|
-
if (offset < 0 || offset + (int32_t)sourceLength > (int32_t)xt_ta_length(self)) {
|
|
312
|
-
xt_throw(xt_string_from_cstr("RangeError: offset is out of bounds"));
|
|
313
|
-
return XT_UNDEFINED;
|
|
314
|
-
}
|
|
315
|
-
for (uint32_t i = 0; i < sourceLength; i++) {
|
|
316
|
-
xt_value item = xt_get(source, xt_number((double)i));
|
|
317
|
-
xt_ta_store(self, kind, (uint32_t)(offset + (int32_t)i), xt_to_number(item));
|
|
318
|
-
}
|
|
319
|
-
return XT_UNDEFINED;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
static xt_value xt_ta_method_slice(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
323
|
-
(void)env;
|
|
324
|
-
int kind = xt_typed_array_kind_of(self);
|
|
325
|
-
if (kind < 0) return XT_UNDEFINED;
|
|
326
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
327
|
-
int32_t start = xt_ta_relative(argc > 0 && argv[0] != XT_UNDEFINED ? xt_to_int32(argv[0]) : 0, length);
|
|
328
|
-
int32_t end = xt_ta_relative(argc > 1 && argv[1] != XT_UNDEFINED ? xt_to_int32(argv[1]) : length, length);
|
|
329
|
-
if (end < start) end = start;
|
|
330
|
-
xt_value out = xt_ta_new(kind, (uint32_t)(end - start));
|
|
331
|
-
for (int32_t i = start; i < end; i++) xt_ta_store(out, kind, (uint32_t)(i - start), xt_to_number(xt_ta_element(self, (uint32_t)i)));
|
|
332
|
-
return out;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
static xt_value xt_ta_method_join(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
336
|
-
(void)env;
|
|
337
|
-
xt_value separator = argc > 0 && argv[0] != XT_UNDEFINED ? xt_to_string(argv[0]) : xt_string_from_cstr(",");
|
|
338
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
339
|
-
xt_value result = xt_string_from_cstr("");
|
|
340
|
-
for (int32_t i = 0; i < length; i++) {
|
|
341
|
-
if (i > 0) result = xt_add(result, separator);
|
|
342
|
-
result = xt_add(result, xt_to_string(xt_ta_element(self, (uint32_t)i)));
|
|
343
|
-
}
|
|
344
|
-
return result;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
static xt_value xt_ta_method_to_string(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
348
|
-
(void)argc;
|
|
349
|
-
return xt_ta_method_join(self, env, 0, argv);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
static xt_value xt_ta_method_index_of(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
353
|
-
(void)env;
|
|
354
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
355
|
-
xt_value needle = xt_arg_at(argc, argv, 0);
|
|
356
|
-
int32_t from = argc > 1 && argv[1] != XT_UNDEFINED ? xt_to_int32(argv[1]) : 0;
|
|
357
|
-
if (from < 0) from += length;
|
|
358
|
-
if (from < 0) from = 0;
|
|
359
|
-
for (int32_t i = from; i < length; i++) {
|
|
360
|
-
if (xt_value_equals(xt_ta_element(self, (uint32_t)i), needle)) return xt_number((double)i);
|
|
361
|
-
}
|
|
362
|
-
return xt_number(-1);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
static xt_value xt_ta_method_last_index_of(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
366
|
-
(void)env;
|
|
367
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
368
|
-
xt_value needle = xt_arg_at(argc, argv, 0);
|
|
369
|
-
int32_t from = argc > 1 && argv[1] != XT_UNDEFINED ? xt_to_int32(argv[1]) : length - 1;
|
|
370
|
-
if (from < 0) from += length;
|
|
371
|
-
if (from >= length) from = length - 1;
|
|
372
|
-
for (int32_t i = from; i >= 0; i--) {
|
|
373
|
-
if (xt_value_equals(xt_ta_element(self, (uint32_t)i), needle)) return xt_number((double)i);
|
|
374
|
-
}
|
|
375
|
-
return xt_number(-1);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
static xt_value xt_ta_method_includes(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
379
|
-
(void)env;
|
|
380
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
381
|
-
xt_value needle = xt_arg_at(argc, argv, 0);
|
|
382
|
-
int32_t from = argc > 1 && argv[1] != XT_UNDEFINED ? xt_to_int32(argv[1]) : 0;
|
|
383
|
-
if (from < 0) from += length;
|
|
384
|
-
if (from < 0) from = 0;
|
|
385
|
-
for (int32_t i = from; i < length; i++) {
|
|
386
|
-
if (xt_value_equals(xt_ta_element(self, (uint32_t)i), needle)) return XT_TRUE;
|
|
387
|
-
}
|
|
388
|
-
return XT_FALSE;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
static xt_value xt_ta_method_for_each(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
392
|
-
(void)env;
|
|
393
|
-
xt_value callback = xt_arg_at(argc, argv, 0);
|
|
394
|
-
xt_value thisArg = xt_arg_at(argc, argv, 1);
|
|
395
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
396
|
-
for (int32_t i = 0; i < length; i++) {
|
|
397
|
-
xt_value args[3] = {xt_ta_element(self, (uint32_t)i), xt_number((double)i), self};
|
|
398
|
-
xt_call_with_this(callback, thisArg, 3, args);
|
|
399
|
-
}
|
|
400
|
-
return XT_UNDEFINED;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
static xt_value xt_ta_method_map(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
404
|
-
(void)env;
|
|
405
|
-
int kind = xt_typed_array_kind_of(self);
|
|
406
|
-
if (kind < 0) return XT_UNDEFINED;
|
|
407
|
-
xt_value callback = xt_arg_at(argc, argv, 0);
|
|
408
|
-
xt_value thisArg = xt_arg_at(argc, argv, 1);
|
|
409
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
410
|
-
xt_value out = xt_ta_new(kind, (uint32_t)length);
|
|
411
|
-
for (int32_t i = 0; i < length; i++) {
|
|
412
|
-
xt_value args[3] = {xt_ta_element(self, (uint32_t)i), xt_number((double)i), self};
|
|
413
|
-
xt_ta_store(out, kind, (uint32_t)i, xt_to_number(xt_call_with_this(callback, thisArg, 3, args)));
|
|
414
|
-
}
|
|
415
|
-
return out;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
static xt_value xt_ta_method_filter(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
419
|
-
(void)env;
|
|
420
|
-
int kind = xt_typed_array_kind_of(self);
|
|
421
|
-
if (kind < 0) return XT_UNDEFINED;
|
|
422
|
-
xt_value callback = xt_arg_at(argc, argv, 0);
|
|
423
|
-
xt_value thisArg = xt_arg_at(argc, argv, 1);
|
|
424
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
425
|
-
xt_value out = xt_ta_new(kind, 0);
|
|
426
|
-
for (int32_t i = 0; i < length; i++) {
|
|
427
|
-
xt_value args[3] = {xt_ta_element(self, (uint32_t)i), xt_number((double)i), self};
|
|
428
|
-
if (xt_truthy(xt_call_with_this(callback, thisArg, 3, args))) {
|
|
429
|
-
xt_ta_append(out, kind, xt_ta_element(self, (uint32_t)i));
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
return out;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
static xt_value xt_ta_method_every(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
436
|
-
(void)env;
|
|
437
|
-
xt_value callback = xt_arg_at(argc, argv, 0);
|
|
438
|
-
xt_value thisArg = xt_arg_at(argc, argv, 1);
|
|
439
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
440
|
-
for (int32_t i = 0; i < length; i++) {
|
|
441
|
-
xt_value args[3] = {xt_ta_element(self, (uint32_t)i), xt_number((double)i), self};
|
|
442
|
-
if (!xt_truthy(xt_call_with_this(callback, thisArg, 3, args))) return XT_FALSE;
|
|
443
|
-
}
|
|
444
|
-
return XT_TRUE;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
static xt_value xt_ta_method_some(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
448
|
-
(void)env;
|
|
449
|
-
xt_value callback = xt_arg_at(argc, argv, 0);
|
|
450
|
-
xt_value thisArg = xt_arg_at(argc, argv, 1);
|
|
451
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
452
|
-
for (int32_t i = 0; i < length; i++) {
|
|
453
|
-
xt_value args[3] = {xt_ta_element(self, (uint32_t)i), xt_number((double)i), self};
|
|
454
|
-
if (xt_truthy(xt_call_with_this(callback, thisArg, 3, args))) return XT_TRUE;
|
|
455
|
-
}
|
|
456
|
-
return XT_FALSE;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
static xt_value xt_ta_method_find(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
460
|
-
(void)env;
|
|
461
|
-
xt_value callback = xt_arg_at(argc, argv, 0);
|
|
462
|
-
xt_value thisArg = xt_arg_at(argc, argv, 1);
|
|
463
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
464
|
-
for (int32_t i = 0; i < length; i++) {
|
|
465
|
-
xt_value element = xt_ta_element(self, (uint32_t)i);
|
|
466
|
-
xt_value args[3] = {element, xt_number((double)i), self};
|
|
467
|
-
if (xt_truthy(xt_call_with_this(callback, thisArg, 3, args))) return element;
|
|
468
|
-
}
|
|
469
|
-
return XT_UNDEFINED;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
static xt_value xt_ta_method_find_index(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
473
|
-
(void)env;
|
|
474
|
-
xt_value callback = xt_arg_at(argc, argv, 0);
|
|
475
|
-
xt_value thisArg = xt_arg_at(argc, argv, 1);
|
|
476
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
477
|
-
for (int32_t i = 0; i < length; i++) {
|
|
478
|
-
xt_value args[3] = {xt_ta_element(self, (uint32_t)i), xt_number((double)i), self};
|
|
479
|
-
if (xt_truthy(xt_call_with_this(callback, thisArg, 3, args))) return xt_number((double)i);
|
|
480
|
-
}
|
|
481
|
-
return xt_number(-1);
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
static xt_value xt_ta_method_reduce(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
485
|
-
(void)env;
|
|
486
|
-
xt_value callback = xt_arg_at(argc, argv, 0);
|
|
487
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
488
|
-
int32_t index = 0;
|
|
489
|
-
xt_value accumulator;
|
|
490
|
-
if (argc > 1) {
|
|
491
|
-
accumulator = argv[1];
|
|
492
|
-
} else if (length > 0) {
|
|
493
|
-
accumulator = xt_ta_element(self, 0);
|
|
494
|
-
index = 1;
|
|
495
|
-
} else {
|
|
496
|
-
xt_throw(xt_string_from_cstr("TypeError: Reduce of empty array with no initial value"));
|
|
497
|
-
return XT_UNDEFINED;
|
|
498
|
-
}
|
|
499
|
-
for (; index < length; index++) {
|
|
500
|
-
xt_value args[4] = {accumulator, xt_ta_element(self, (uint32_t)index), xt_number((double)index), self};
|
|
501
|
-
accumulator = xt_call_with_this(callback, XT_UNDEFINED, 4, args);
|
|
502
|
-
}
|
|
503
|
-
return accumulator;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
static xt_value xt_ta_method_reverse(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
507
|
-
(void)env;
|
|
508
|
-
(void)argc;
|
|
509
|
-
(void)argv;
|
|
510
|
-
int kind = xt_typed_array_kind_of(self);
|
|
511
|
-
if (kind < 0) return self;
|
|
512
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
513
|
-
for (int32_t i = 0; i < length / 2; i++) {
|
|
514
|
-
double left = xt_to_number(xt_ta_element(self, (uint32_t)i));
|
|
515
|
-
double right = xt_to_number(xt_ta_element(self, (uint32_t)(length - 1 - i)));
|
|
516
|
-
xt_ta_store(self, kind, (uint32_t)i, right);
|
|
517
|
-
xt_ta_store(self, kind, (uint32_t)(length - 1 - i), left);
|
|
518
|
-
}
|
|
519
|
-
return self;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
static int xt_ta_compare(xt_value comparator, xt_value a, xt_value b) {
|
|
523
|
-
if (XT_IS_FUNCTION(comparator)) {
|
|
524
|
-
xt_value args[2] = {a, b};
|
|
525
|
-
double result = xt_to_number(xt_call_with_this(comparator, XT_UNDEFINED, 2, args));
|
|
526
|
-
return result < 0 ? -1 : result > 0 ? 1 : 0;
|
|
527
|
-
}
|
|
528
|
-
double x = xt_to_number(a);
|
|
529
|
-
double y = xt_to_number(b);
|
|
530
|
-
if (isnan(x)) return isnan(y) ? 0 : 1;
|
|
531
|
-
if (isnan(y)) return -1;
|
|
532
|
-
return x < y ? -1 : x > y ? 1 : 0;
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
static xt_value xt_ta_method_sort(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
536
|
-
(void)env;
|
|
537
|
-
int kind = xt_typed_array_kind_of(self);
|
|
538
|
-
if (kind < 0) return self;
|
|
539
|
-
xt_value comparator = xt_arg_at(argc, argv, 0);
|
|
540
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
541
|
-
for (int32_t i = 1; i < length; i++) {
|
|
542
|
-
xt_value key = xt_ta_element(self, (uint32_t)i);
|
|
543
|
-
int32_t j = i - 1;
|
|
544
|
-
while (j >= 0 && xt_ta_compare(comparator, xt_ta_element(self, (uint32_t)j), key) > 0) {
|
|
545
|
-
xt_ta_store(self, kind, (uint32_t)(j + 1), xt_to_number(xt_ta_element(self, (uint32_t)j)));
|
|
546
|
-
j--;
|
|
547
|
-
}
|
|
548
|
-
xt_ta_store(self, kind, (uint32_t)(j + 1), xt_to_number(key));
|
|
549
|
-
}
|
|
550
|
-
return self;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
static xt_value xt_ta_method_copy_within(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
554
|
-
(void)env;
|
|
555
|
-
int kind = xt_typed_array_kind_of(self);
|
|
556
|
-
if (kind < 0) return self;
|
|
557
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
558
|
-
int32_t target = xt_ta_relative(xt_to_int32(xt_arg_at(argc, argv, 0)), length);
|
|
559
|
-
int32_t start = xt_ta_relative(argc > 1 && argv[1] != XT_UNDEFINED ? xt_to_int32(argv[1]) : 0, length);
|
|
560
|
-
int32_t end = xt_ta_relative(argc > 2 && argv[2] != XT_UNDEFINED ? xt_to_int32(argv[2]) : length, length);
|
|
561
|
-
int32_t count = end - start;
|
|
562
|
-
if (count > length - target) count = length - target;
|
|
563
|
-
if (count <= 0 || target == start) return self;
|
|
564
|
-
xt_value *temporary = (xt_value *)malloc(sizeof(xt_value) * (size_t)count);
|
|
565
|
-
if (!temporary) return self;
|
|
566
|
-
for (int32_t i = 0; i < count; i++) temporary[i] = xt_ta_element(self, (uint32_t)(start + i));
|
|
567
|
-
for (int32_t i = 0; i < count; i++) xt_ta_store(self, kind, (uint32_t)(target + i), xt_to_number(temporary[i]));
|
|
568
|
-
free(temporary);
|
|
569
|
-
return self;
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
static xt_value xt_ta_method_at(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
573
|
-
(void)env;
|
|
574
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
575
|
-
int32_t index = xt_to_int32(xt_arg_at(argc, argv, 0));
|
|
576
|
-
if (index < 0) index += length;
|
|
577
|
-
if (index < 0 || index >= length) return XT_UNDEFINED;
|
|
578
|
-
return xt_ta_element(self, (uint32_t)index);
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
static xt_value xt_ta_method_keys(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
582
|
-
(void)env;
|
|
583
|
-
(void)argc;
|
|
584
|
-
(void)argv;
|
|
585
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
586
|
-
xt_value out = xt_array_new(0, NULL);
|
|
587
|
-
for (int32_t i = 0; i < length; i++) xt_array_push(out, xt_number((double)i));
|
|
588
|
-
return out;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
static xt_value xt_ta_method_values(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
592
|
-
(void)env;
|
|
593
|
-
(void)argc;
|
|
594
|
-
(void)argv;
|
|
595
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
596
|
-
xt_value out = xt_array_new(0, NULL);
|
|
597
|
-
for (int32_t i = 0; i < length; i++) xt_array_push(out, xt_ta_element(self, (uint32_t)i));
|
|
598
|
-
return out;
|
|
599
|
-
}
|
|
66
|
+
/* The implementation is grouped by functional area under `xt_typed_array/`
|
|
67
|
+
* and `#include`d here as a single translation unit, so the internal helpers
|
|
68
|
+
* stay `static` while each file stays focused on one area. */
|
|
600
69
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
(void)argv;
|
|
605
|
-
int32_t length = (int32_t)xt_ta_length(self);
|
|
606
|
-
xt_value out = xt_array_new(0, NULL);
|
|
607
|
-
for (int32_t i = 0; i < length; i++) {
|
|
608
|
-
xt_value pair = xt_array_new(0, NULL);
|
|
609
|
-
xt_array_push(pair, xt_number((double)i));
|
|
610
|
-
xt_array_push(pair, xt_ta_element(self, (uint32_t)i));
|
|
611
|
-
xt_array_push(out, pair);
|
|
612
|
-
}
|
|
613
|
-
return out;
|
|
614
|
-
}
|
|
70
|
+
#include "xt_typed_array/elements.inc"
|
|
71
|
+
#include "xt_typed_array/construction.inc"
|
|
72
|
+
#include "xt_typed_array/methods.inc"
|
|
@@ -64,6 +64,32 @@ void xt_number_to_js_string(double d, char *buffer, size_t size) {
|
|
|
64
64
|
}
|
|
65
65
|
int negative = d < 0;
|
|
66
66
|
double x = negative ? -d : d;
|
|
67
|
+
|
|
68
|
+
/* Integers up to 2^53 have a unique shortest round-tripping representation:
|
|
69
|
+
* themselves. Emit them with pure integer arithmetic so we never touch the
|
|
70
|
+
* `%e` + `strtod` loop below, whose libc conversion is mis-rounded for some
|
|
71
|
+
* inputs on the Windows ARM64 UCRT (12502500 used to come out as
|
|
72
|
+
* 12502500.000000002). Values above 2^53 can have a shorter neighbour, so
|
|
73
|
+
* they keep using the general path. */
|
|
74
|
+
if (x <= 9007199254740992.0) {
|
|
75
|
+
uint64_t n = (uint64_t)x;
|
|
76
|
+
if ((double)n == x) {
|
|
77
|
+
char digits[20];
|
|
78
|
+
int nd = 0;
|
|
79
|
+
do {
|
|
80
|
+
digits[nd++] = (char)('0' + (int)(n % 10u));
|
|
81
|
+
n /= 10u;
|
|
82
|
+
} while (n > 0);
|
|
83
|
+
for (int i = 0; i < nd / 2; i++) {
|
|
84
|
+
char tmp = digits[i];
|
|
85
|
+
digits[i] = digits[nd - 1 - i];
|
|
86
|
+
digits[nd - 1 - i] = tmp;
|
|
87
|
+
}
|
|
88
|
+
xt_render_decimal(negative, digits, nd, nd - 1, 0, buffer, size);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
67
93
|
char sci[64];
|
|
68
94
|
for (int p = 1; p <= 17; p++) {
|
|
69
95
|
snprintf(sci, sizeof(sci), "%.*e", p - 1, x);
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Enforce the per-file line budget for code ESLint cannot parse.
|
|
4
|
+
*
|
|
5
|
+
* ESLint's `max-lines` rule already caps the TypeScript/JavaScript sources at
|
|
6
|
+
* 600 lines (see `eslint.config.js`). This script applies the same budget to
|
|
7
|
+
* the runtime's C, C++, Rust and `#include`d `.inc` fragments plus shell
|
|
8
|
+
* scripts, so *every* code file stays focused and small.
|
|
9
|
+
*
|
|
10
|
+
* Vendored third-party sources that must ship verbatim (notably the
|
|
11
|
+
* single-header `stb_image.h`) are exempt: they are not ours to split.
|
|
12
|
+
*
|
|
13
|
+
* Run via `npm run lint` (or `tsx scripts/check-file-length.ts`).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
17
|
+
import { join, relative, resolve } from "node:path";
|
|
18
|
+
import { fileURLToPath } from "node:url";
|
|
19
|
+
|
|
20
|
+
const root = resolve(fileURLToPath(new URL(".", import.meta.url)), "..");
|
|
21
|
+
|
|
22
|
+
/** Maximum number of lines allowed in a single code file. */
|
|
23
|
+
const MAX_LINES = 600;
|
|
24
|
+
|
|
25
|
+
const CODE_EXTENSIONS = new Set([".c", ".h", ".cc", ".cpp", ".hpp", ".rs", ".inc", ".sh"]);
|
|
26
|
+
|
|
27
|
+
const IGNORED_DIRECTORIES = new Set([
|
|
28
|
+
".git",
|
|
29
|
+
"build",
|
|
30
|
+
"coverage",
|
|
31
|
+
"dist",
|
|
32
|
+
"node_modules",
|
|
33
|
+
"scratch",
|
|
34
|
+
"target",
|
|
35
|
+
"vendor",
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
/** Vendored third-party sources that ship verbatim and are not ours to split. */
|
|
39
|
+
const VENDORED_FILES = new Set([join("runtime", "ext_gui", "stb_image.h")]);
|
|
40
|
+
|
|
41
|
+
interface Offense {
|
|
42
|
+
file: string;
|
|
43
|
+
lines: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function countLines(path: string): number {
|
|
47
|
+
const content = readFileSync(path, "utf8");
|
|
48
|
+
if (content.length === 0) return 0;
|
|
49
|
+
// A trailing newline terminates the last line instead of starting a new one.
|
|
50
|
+
const lines = content.split("\n");
|
|
51
|
+
return content.endsWith("\n") ? lines.length - 1 : lines.length;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function collect(dir: string, offenses: Offense[]): void {
|
|
55
|
+
for (const entry of readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
56
|
+
const full = join(dir, entry.name);
|
|
57
|
+
if (entry.isDirectory()) {
|
|
58
|
+
if (IGNORED_DIRECTORIES.has(entry.name)) continue;
|
|
59
|
+
// `runtime/lib` holds prebuilt archives, never sources.
|
|
60
|
+
if (relative(root, full) === join("runtime", "lib")) continue;
|
|
61
|
+
collect(full, offenses);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (!entry.isFile()) continue;
|
|
65
|
+
const dot = entry.name.lastIndexOf(".");
|
|
66
|
+
if (dot < 0 || !CODE_EXTENSIONS.has(entry.name.slice(dot))) continue;
|
|
67
|
+
const file = relative(root, full);
|
|
68
|
+
if (VENDORED_FILES.has(file)) continue;
|
|
69
|
+
const lines = countLines(full);
|
|
70
|
+
if (lines > MAX_LINES) offenses.push({ file, lines });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const offenses: Offense[] = [];
|
|
75
|
+
collect(root, offenses);
|
|
76
|
+
|
|
77
|
+
if (offenses.length > 0) {
|
|
78
|
+
console.error(`xbintsc: code files must stay under ${MAX_LINES} lines - split them by responsibility:`);
|
|
79
|
+
for (const offense of offenses.sort((a, b) => b.lines - a.lines)) {
|
|
80
|
+
console.error(` ${offense.file}: ${offense.lines} lines`);
|
|
81
|
+
}
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
console.log(`xbintsc: all code files are within ${MAX_LINES} lines`);
|