Optimize keyed collection and object processing

- Speed up string-keyed collections and wide object property lookup.
- Share scalable numeric-key ordering across typed and checked objects.
- Preserve property, iteration, and ownership behavior across native and WASI targets.
This commit is contained in:
Chris Tate
2026-10-06 11:21:22 -05:00
parent e0bb196a73
commit 1df760beef
9 changed files with 303 additions and 111 deletions
@@ -14354,6 +14354,18 @@
"<repo>/tests/corpus/text-encode-into-boundaries.ts"
],
"diags": []
},
"<repo>/tests/corpus/object-key-indexes.js": {
"order": [
"<repo>/tests/corpus/object-key-indexes.js"
],
"diags": []
},
"<repo>/tests/corpus/record-key-order.ts": {
"order": [
"<repo>/tests/corpus/record-key-order.ts"
],
"diags": []
}
}
}
+104 -52
View File
@@ -22,6 +22,7 @@
* serializers (and the error messages here).
*/
#include "scr_runtime.h"
#include "scr_key.h"
static SCR_TL ScrDyn *scr_builtin_object_prototype;
@@ -709,6 +710,10 @@ static void scr_dyn_handle_release(void *h, ScrDynHandleTag tag);
static bool scr_dyn_to_primitive_result_is_object(const ScrDyn *d);
static void scr_dyn_dispose(ScrDyn *d, bool collected) {
if (d->kind == SCR_DYN_OBJ) {
free(d->v.obj.index);
d->v.obj.index = NULL;
}
if (!collected) scr_dyn_release(d->prototype);
if (!collected) scr_dyn_release(d->symbol_properties);
if (!collected) scr_dyn_release(d->symbol_keys);
@@ -829,6 +834,42 @@ void scr_dyn_release(ScrDyn *d) {
scr_dyn_dispose(d, false);
}
/* Small objects retain their compact linear representation. A wide object
* owns a bucket index of entry positions; entries remain insertion ordered.
* No key/value ownership lives here, and callbacks never retain its slots. */
#define SCR_DYN_OBJECT_INDEX_MIN 32
typedef struct ScrDynObjectIndex {
size_t buckets;
size_t slots[]; /* zero is empty; occupied slots store entry + 1 */
} ScrDynObjectIndex;
static void scr_dyn_index_insert(ScrDynObjectIndex *index, const ScrDynEntry *entry, size_t position) {
size_t slot = scr_key_hash(entry->key, entry->key_len) & (index->buckets - 1);
while (index->slots[slot]) slot = (slot + 1) & (index->buckets - 1);
index->slots[slot] = position + 1;
}
/* Keep index allocation/probing outside compact object insertion and reads. */
static __attribute__((noinline)) void scr_dyn_index_append(ScrDyn *object) {
size_t count = object->v.obj.len;
ScrDynObjectIndex *index = object->v.obj.index;
if (!index || count > index->buckets / 2) {
size_t buckets = index ? index->buckets : 64;
while (count > buckets / 2) {
if (buckets > (SIZE_MAX - sizeof *index) / sizeof(size_t) / 2) scr_json_oom();
buckets *= 2;
}
free(index);
index = calloc(1, sizeof *index + buckets * sizeof(size_t));
if (!index) scr_json_oom();
index->buckets = buckets;
object->v.obj.index = index;
for (size_t i = 0; i < count; i++) scr_dyn_index_insert(index, &object->v.obj.entries[i], i);
} else {
scr_dyn_index_insert(index, &object->v.obj.entries[count - 1], count - 1);
}
}
/* A checked hint avoids repeating a linear walk for recurring property
* names. Slots store indices only, never object/key pointers. Every hit
* checks the current entry, so different shapes, deletion and reordering
@@ -836,22 +877,38 @@ void scr_dyn_release(ScrDyn *d) {
#define SCR_DYN_PROPERTY_HINTS 64
static SCR_TL size_t scr_dyn_property_hints[SCR_DYN_PROPERTY_HINTS];
static ScrDynEntry *scr_dyn_find_linear_entry(const ScrDyn *object, const char *key, size_t length) {
for (size_t i = 0; i < object->v.obj.len; i++) {
ScrDynEntry *entry = &object->v.obj.entries[i];
if (entry->key_len == length && !memcmp(entry->key, key, length)) return entry;
}
return NULL;
}
static __attribute__((noinline)) ScrDynEntry *scr_dyn_find_indexed_entry(
const ScrDyn *object, const char *key, size_t length) {
const ScrDynObjectIndex *index = object->v.obj.index;
size_t slot = scr_key_hash(key, length) & (index->buckets - 1);
while (index->slots[slot]) {
ScrDynEntry *entry = &object->v.obj.entries[index->slots[slot] - 1];
if (entry->key_len == length && !memcmp(entry->key, key, length)) return entry;
slot = (slot + 1) & (index->buckets - 1);
}
return NULL;
}
static ScrDynEntry *scr_dyn_find_entry(const ScrDyn *object, const char *key, size_t length) {
if (object->kind != SCR_DYN_OBJ) return NULL;
if (object->v.obj.index) return scr_dyn_find_indexed_entry(object, key, length);
size_t slot = (length + (length ? (unsigned char)key[0] * 7u : 0)) % SCR_DYN_PROPERTY_HINTS;
size_t hint = scr_dyn_property_hints[slot];
if (hint < object->v.obj.len) {
ScrDynEntry *entry = &object->v.obj.entries[hint];
if (entry->key_len == length && !memcmp(entry->key, key, length)) return entry;
}
for (size_t i = 0; i < object->v.obj.len; i++) {
ScrDynEntry *entry = &object->v.obj.entries[i];
if (entry->key_len == length && !memcmp(entry->key, key, length)) {
scr_dyn_property_hints[slot] = i;
return entry;
}
}
return NULL;
ScrDynEntry *entry = scr_dyn_find_linear_entry(object, key, length);
if (entry) scr_dyn_property_hints[slot] = (size_t)(entry - object->v.obj.entries);
return entry;
}
ScrDyn *scr_dyn_obj_get(const ScrDyn *d, const char *key, size_t key_len) {
@@ -1156,20 +1213,21 @@ ScrDyn *scr_dyn_arr_named_get(const ScrDyn *d, const ScrStr *key) {
* original spelling/storage and insertion position; the later value wins.
* A recycled entry can reuse equal key bytes without a malloc/free pair. */
static void scr_dyn_obj_put(ScrDyn *obj, const char *key, size_t key_len, ScrDyn *value) {
for (size_t i = 0; i < obj->v.obj.len; i++) {
ScrDynEntry *e = &obj->v.obj.entries[i];
if (e->key_len == key_len && memcmp(e->key, key, key_len) == 0) {
if (e->accessor || !e->writable) {
scr_dyn_release(value);
static const char message[] = "Cannot assign to read only property";
scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
return;
}
ScrDyn *old = e->value;
e->value = value;
scr_dyn_release(old);
/* Construction usually appends an absent name. Avoid a read hint that
* repeats comparisons on compact objects; wide objects use their index. */
ScrDynEntry *existing = obj->v.obj.index ? scr_dyn_find_entry(obj, key, key_len)
: scr_dyn_find_linear_entry(obj, key, key_len);
if (existing) {
if (existing->accessor || !existing->writable) {
scr_dyn_release(value);
static const char message[] = "Cannot assign to read only property";
scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
return;
}
ScrDyn *old = existing->value;
existing->value = value;
scr_dyn_release(old);
return;
}
if (obj->non_extensible) {
scr_dyn_release(value);
@@ -1199,6 +1257,7 @@ static void scr_dyn_obj_put(ScrDyn *obj, const char *key, size_t key_len, ScrDyn
e->writable = true;
e->enumerable = true;
e->configurable = true;
if (obj->v.obj.len >= SCR_DYN_OBJECT_INDEX_MIN) scr_dyn_index_append(obj);
}
/* ── dyn construction (compiler-emitted converters & overflow reads) ───── */
@@ -6332,6 +6391,8 @@ static void scr_json_delete_member(ScrDyn *object, const ScrStr *key) {
ScrDynEntry removed = *entry;
memmove(entry, entry + 1, (object->v.obj.len - i - 1) * sizeof *entry);
object->v.obj.len--;
free(object->v.obj.index);
object->v.obj.index = NULL;
/* The moved tail aliases a live entry; spare slots own only their own
* retained key bytes, never a second pointer to a surviving property. */
memset(&object->v.obj.entries[object->v.obj.len], 0, sizeof *entry);
@@ -7371,15 +7432,9 @@ bool scr_dyn_reflect_set(ScrDyn *target, ScrDyn *raw_key, ScrDyn *value, ScrDyn
/* The array-index test (ECMA: a canonical numeric string < 2^32-1). */
static bool scr_dyn_key_is_index(const char *key, size_t len, double *out) {
if (len == 0 || len > 10) return false;
if (key[0] == '0' && len > 1) return false;
double v = 0;
for (size_t i = 0; i < len; i++) {
if (key[i] < '0' || key[i] > '9') return false;
v = v * 10 + (key[i] - '0');
}
if (v > 4294967294.0) return false;
*out = v;
uint32_t index;
if (!scr_key_array_index(key, len, &index)) return false;
*out = index;
return true;
}
@@ -7397,34 +7452,31 @@ static ScrDyn *scr_dyn_objwalk_key(const char *key, size_t key_len) {
ScrDyn *scr_dyn_obj_own_keys(const ScrDyn *v) {
size_t n = v->v.obj.len;
ScrDyn *keys = scr_dyn_new_arr();
bool *is_index = malloc(n ? n * sizeof *is_index : 1);
double *idx = malloc(n ? n * sizeof *idx : 1);
if (!is_index || !idx) scr_trap("scriptc: out of memory\n");
size_t index_count = 0;
ScrKeyIndex *indices = NULL;
size_t count = 0;
for (size_t i = 0; i < n; i++) {
const ScrDynEntry *e = &v->v.obj.entries[i];
is_index[i] = scr_dyn_key_is_index(e->key, e->key_len, &idx[i]);
if (is_index[i]) index_count++;
}
double last = -1;
for (size_t done = 0; done < index_count; done++) {
size_t best = (size_t)-1;
for (size_t i = 0; i < n; i++) {
if (!is_index[i] || idx[i] <= last) continue;
if (best == (size_t)-1 || idx[i] < idx[best]) best = i;
const ScrDynEntry *entry = &v->v.obj.entries[i];
uint32_t index;
if (!scr_key_array_index(entry->key, entry->key_len, &index)) continue;
if (!indices) {
if (n > SIZE_MAX / sizeof *indices) scr_json_oom();
indices = malloc(n * sizeof *indices);
if (!indices) scr_json_oom();
}
if (best == (size_t)-1) break;
last = idx[best];
scr_dyn_arr_push(keys, scr_dyn_objwalk_key(v->v.obj.entries[best].key,
v->v.obj.entries[best].key_len));
indices[count++] = (ScrKeyIndex){index, i};
}
scr_key_index_sort(indices, count);
for (size_t i = 0; i < count; i++) {
const ScrDynEntry *entry = &v->v.obj.entries[indices[i].entry];
scr_dyn_arr_push(keys, scr_dyn_objwalk_key(entry->key, entry->key_len));
}
free(indices);
for (size_t i = 0; i < n; i++) {
if (is_index[i]) continue;
scr_dyn_arr_push(keys, scr_dyn_objwalk_key(v->v.obj.entries[i].key,
v->v.obj.entries[i].key_len));
const ScrDynEntry *entry = &v->v.obj.entries[i];
uint32_t index;
if (!scr_key_array_index(entry->key, entry->key_len, &index))
scr_dyn_arr_push(keys, scr_dyn_objwalk_key(entry->key, entry->key_len));
}
free(is_index);
free(idx);
return keys;
}
+35
View File
@@ -114,6 +114,41 @@ static void checked_storage(void) {
}
scr_dyn_release(object);
}
/* Cross index growth boundaries, invalidate moved entry positions, then
* recreate the index from survivors. Repeat after pool reuse. */
for (int round = 0; round < 4; round++) {
ScrDyn *object = scr_dyn_new_obj();
assert(!object->v.obj.index);
for (int i = 0; i < 129; i++) {
char key[16];
int length = snprintf(key, sizeof key, "key-%d", i);
scr_dyn_obj_set(object, key, (size_t)length, scr_dyn_new_num(i));
assert((object->v.obj.index != NULL) == (i >= 31));
}
for (int i = 0; i < 129; i++) {
char key[16];
int length = snprintf(key, sizeof key, "key-%d", i);
assert(scr_dyn_obj_get(object, key, (size_t)length)->v.num == i);
if (i % 3 == 0) {
ScrStr *name = scr_str_new(key, (size_t)length);
scr_dyn_key_delete(object, name, true);
scr_str_release(name);
assert(!scr_dyn_obj_get(object, key, (size_t)length));
}
}
scr_dyn_obj_set(object, "last", 4, scr_dyn_new_num(129));
assert(object->v.obj.index);
for (int i = 0; i < 129; i++) {
char key[16];
int length = snprintf(key, sizeof key, "key-%d", i);
ScrDyn *value = scr_dyn_obj_get(object, key, (size_t)length);
assert(i % 3 == 0 ? value == NULL : value && value->v.num == i);
}
scr_dyn_obj_set(object, "key-128", 7, scr_dyn_new_num(900));
assert(object->v.obj.len == 87);
assert(scr_dyn_obj_get(object, "key-128", 7)->v.num == 900);
scr_dyn_release(object);
}
/* A direct step is authorized only by the captured builtin method. */
ScrDyn *source = scr_dyn_new_arr();
scr_dyn_arr_push(source, scr_dyn_new_num(7));
+68
View File
@@ -0,0 +1,68 @@
/* Internal key hashing and canonical array-index ordering shared by native
* maps and checked objects. Hashes never escape into JavaScript values. */
#ifndef SCR_KEY_H
#define SCR_KEY_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
static inline uint64_t scr_key_mix(uint64_t value) {
value ^= value >> 30;
value *= UINT64_C(0xbf58476d1ce4e5b9);
value ^= value >> 27;
value *= UINT64_C(0x94d049bb133111eb);
return value ^ (value >> 31);
}
/* Unaligned loads stay inside the input. Hashing is process-local, so host
* byte order is immaterial; equal byte strings always follow the same path. */
static inline uint64_t scr_key_hash(const char *bytes, size_t length) {
uint64_t hash = UINT64_C(0x9e3779b97f4a7c15) ^ length;
size_t i = 0;
while (length - i >= sizeof(uint64_t)) {
uint64_t word;
memcpy(&word, bytes + i, sizeof word);
hash = scr_key_mix(hash ^ word);
i += sizeof word;
}
uint64_t tail = 0;
if (i < length) memcpy(&tail, bytes + i, length - i);
return scr_key_mix(hash ^ tail);
}
static inline bool scr_key_array_index(const char *key, size_t length, uint32_t *out) {
if (length == 0 || length > 10 || (length > 1 && key[0] == '0')) return false;
uint64_t value = 0;
for (size_t i = 0; i < length; i++) {
if (key[i] < '0' || key[i] > '9') return false;
value = value * 10 + (unsigned)(key[i] - '0');
}
if (value >= UINT32_MAX) return false;
*out = (uint32_t)value;
return true;
}
typedef struct {
uint32_t index;
size_t entry;
} ScrKeyIndex;
static inline int scr_key_index_compare(const void *left, const void *right) {
uint32_t a = ((const ScrKeyIndex *)left)->index;
uint32_t b = ((const ScrKeyIndex *)right)->index;
return (a > b) - (a < b);
}
/* Keys are unique. Already ordered inputs need no sort, while arbitrary
* numeric property insertion must not require quadratic enumeration. */
static inline void scr_key_index_sort(ScrKeyIndex *keys, size_t count) {
for (size_t i = 1; i < count; i++) {
if (keys[i - 1].index > keys[i].index) {
qsort(keys, count, sizeof *keys, scr_key_index_compare);
return;
}
}
}
#endif
+27 -59
View File
@@ -15,6 +15,7 @@
* keep the lean 1-word header and never touch the collector.
*/
#include "scr_runtime.h"
#include "scr_key.h"
#include <stdio.h>
#include <stdlib.h>
@@ -46,27 +47,14 @@ static uint64_t scr_map_f64_bits(double k) {
return bits;
}
static uint64_t scr_map_fnv1a(const unsigned char *bytes, size_t n) {
uint64_t h = UINT64_C(0xcbf29ce484222325);
for (size_t i = 0; i < n; i++) {
h ^= bytes[i];
h *= UINT64_C(0x100000001b3);
}
return h;
}
static uint64_t scr_map_hash_str(const ScrStr *k) {
return scr_map_fnv1a((const unsigned char *)k->data, k->len);
return scr_key_hash(k->data, k->len);
}
/* Mix the complete normalized number or identity word. Float exponents
* and aligned pointers need high bits to reach the low bucket-index bits. */
static uint64_t scr_map_hash_word(uint64_t value) {
value ^= value >> 30;
value *= UINT64_C(0xbf58476d1ce4e5b9);
value ^= value >> 27;
value *= UINT64_C(0x94d049bb133111eb);
return value ^ (value >> 31);
return scr_key_mix(value);
}
/* ── slot packing (8-byte slots, like ScrArr) ──────────────────────────── */
@@ -906,59 +894,39 @@ void scr_set_add_all(ScrMap *set, ScrArr *values) {
/* Canonical array index test: "0".."4294967294" — digits only, no leading
* zero (except "0" itself), value <= 2^32 - 2. JS orders these OWN keys
* first, ascending numerically, before every other string key. */
static bool scr_map_key_array_index(const ScrStr *k, uint32_t *out) {
size_t n = k->len;
if (n == 0 || n > 10) return false;
const char *s = k->data;
if (s[0] == '0' && n > 1) return false;
uint64_t v = 0;
for (size_t i = 0; i < n; i++) {
if (s[i] < '0' || s[i] > '9') return false;
v = v * 10 + (uint64_t)(s[i] - '0');
}
if (v > UINT64_C(4294967294)) return false;
*out = (uint32_t)v;
return true;
static bool scr_map_key_array_index(const ScrStr *key, uint32_t *out) {
return scr_key_array_index(key->data, key->len, out);
}
/* The live STRING keys of `m` in JS OWN-KEY ORDER (Object.keys over the
* index-signature overflow): integer-like keys (canonical array indices)
* first in ascending numeric order, then the rest in insertion order.
* Returns a fresh ScrStr* array (+1); the map is borrowed. Insertion sort
* over the integer-like subset — overflow maps are small, and ties are
* impossible (keys are unique). */
/* Enumerate numeric keys in ascending order, then other keys in insertion
* order. Scratch entries refer to stable map indices, not copied strings. */
ScrArr *scr_map_keys_js_order(const ScrMap *m) {
size_t n = m->nentries;
ScrArr *out = scr_arr_new(SCR_ELEM_STR, m->nlive);
size_t nidx = 0;
struct { uint32_t v; ScrStr *k; } *idx = NULL;
for (size_t i = 0; i < n; i++) {
if (m->nlive > SIZE_MAX / sizeof(ScrKeyIndex)) scr_map_oom();
ScrKeyIndex *indices = NULL;
size_t count = 0;
for (size_t i = 0; i < m->nentries; i++) {
if (!m->entries[i].hash) continue;
ScrStr *k = (ScrStr *)scr_map_slot_to_ptr(m->entries[i].key);
uint32_t v;
if (!scr_map_key_array_index(k, &v)) continue;
if (nidx % 16 == 0) {
idx = realloc(idx, (nidx + 16) * sizeof *idx);
if (!idx) scr_map_oom();
ScrStr *key = scr_map_slot_to_ptr(m->entries[i].key);
uint32_t index;
if (!scr_map_key_array_index(key, &index)) continue;
if (!indices) {
indices = malloc(m->nlive * sizeof *indices);
if (!indices) scr_map_oom();
}
size_t j = nidx++;
while (j > 0 && idx[j - 1].v > v) {
idx[j] = idx[j - 1];
j--;
}
idx[j].v = v;
idx[j].k = k;
indices[count++] = (ScrKeyIndex){index, i};
}
for (size_t i = 0; i < nidx; i++) {
scr_arr_push_ref(out, scr_str_retain(idx[i].k));
scr_key_index_sort(indices, count);
for (size_t i = 0; i < count; i++) {
ScrStr *key = scr_map_slot_to_ptr(m->entries[indices[i].entry].key);
scr_arr_push_ref(out, scr_str_retain(key));
}
free(idx);
for (size_t i = 0; i < n; i++) {
free(indices);
for (size_t i = 0; i < m->nentries; i++) {
if (!m->entries[i].hash) continue;
ScrStr *k = (ScrStr *)scr_map_slot_to_ptr(m->entries[i].key);
uint32_t v;
if (scr_map_key_array_index(k, &v)) continue;
scr_arr_push_ref(out, scr_str_retain(k));
ScrStr *key = scr_map_slot_to_ptr(m->entries[i].key);
uint32_t index;
if (!scr_map_key_array_index(key, &index)) scr_arr_push_ref(out, scr_str_retain(key));
}
return out;
}
+1
View File
@@ -3759,6 +3759,7 @@ struct ScrDyn {
* interfaces may request a fresh snapshot with the true arm. */
void *source_identity;
ScrDyn *(*source_access)(void *, bool materialize);
struct ScrDynObjectIndex *index; /* optional wide-object lookup; owns no values */
} obj; /* owned */
/* SCR_DYN_FUNC: the boxed closure (owned) + its call descriptor. `sig`
* and `name` are static compiler-emitted literals (never freed); name
+30
View File
@@ -0,0 +1,30 @@
// Wide checked objects preserve insertion order, descriptor behavior, and
// lookups when entries move after deletion or are replaced by accessors.
const object = JSON.parse("{}");
for (let i = 95; i >= 0; i--) object[String(i)] = i * 3;
for (const key of ["tail", "01", "4294967295", "4294967294", "-0", "", "a\0b", "é😀"]) object[key] = key;
console.log(Object.keys(object).join("|"));
console.log(Object.values(object).join("|"));
for (let i = 0; i < 96; i += 3) delete object[String(i)];
for (let i = 0; i < 96; i += 3) object[String(i)] = -i;
object.tail = "updated";
Object.defineProperty(object, "hidden", { value: 42, enumerable: false, configurable: true });
Object.defineProperty(object, "31", { get() { delete object["32"]; object.added = 123; return "getter"; }, enumerable: true, configurable: true });
console.log(Object.entries(object).map(([key, value]) => key + ":" + value).join("|"));
console.log(Reflect.ownKeys(object).join("|"));
console.log(object.hidden, object.missing, object["a\0b"], object["é😀"]);
for (let i = 0; i < 96; i++) delete object[String(i)];
console.log(Object.keys(object).join("|"));
for (let i = 0; i < 100; i++) object["key-" + i] = i;
Object.freeze(object);
try { object["key-50"] = 0; } catch (error) { console.log(error.name); }
console.log(object["key-50"], Object.keys(object).length);
const duplicates = JSON.parse('{"32":1,"1":2,"32":3,"x":4,"x":5}');
console.log(JSON.stringify(duplicates));
// Recycling and cyclic destruction must discard all index storage.
for (let round = 0; round < 40; round++) {
const cycle = JSON.parse("{}");
for (let i = 0; i < 80; i++) cycle["property-" + i] = round + i;
cycle.self = cycle;
console.log(cycle["property-79"], Object.keys(cycle).length);
}
+24
View File
@@ -0,0 +1,24 @@
const record: Record<string, number> = {};
for (let i = 96; i >= 0; i--) record[String(i)] = i;
for (const key of ["word", "01", "4294967295", "4294967294", "-0", "", "a\0b", "é😀"]) record[key] = 100;
console.log(Object.keys(record).join("|"));
console.log(Object.values(record).join("|"));
console.log(Object.entries(record).map(([key, value]) => key + ":" + value).join("|"));
const map = new Map<string, number>();
for (let length = 0; length <= 40; length++) {
const prefix = "same-prefix-".repeat(length);
for (const tail of ["a", "b", "\0", "é", "😀"]) map.set(prefix + tail, length);
}
let sum = 0;
for (const [key, value] of map) {
const copy = ("!" + key).slice(1);
console.log(map.has(copy), map.get(copy), value);
sum += map.get(copy)!;
}
console.log(map.size, sum);
for (let i = 0; i < 200; i++) {
const key = "churn-" + i;
map.set(key, i);
if (i >= 7) map.delete("churn-" + (i - 7));
}
console.log(Array.from(map.keys()).slice(-7).join("|"));
+2
View File
@@ -146,6 +146,8 @@ describe.skipIf(!zigOnPath())("wasm32-wasi differential", () => {
"uint8array-sort-domains.ts",
"buffer-codec-boundaries.ts",
"text-encode-into-boundaries.ts",
"object-key-indexes.js",
"record-key-order.ts",
"1612-cjs-module-globals.cjs",
"992-fs-roundtrip.ts",
"751-cycle-records-mutual.ts",