@scriptc/runtime 0.0.22 → 0.0.24
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/package.json +1 -1
- package/src/scr_array.c +65 -0
- package/src/scr_async.c +291 -7
- package/src/scr_bytes.c +634 -4
- package/src/scr_bytes_io.c +4 -2
- package/src/scr_cycle.c +403 -62
- package/src/scr_fetch.c +652 -77
- package/src/scr_file_handle.c +491 -0
- package/src/scr_island.c +10 -0
- package/src/scr_json.c +137 -21
- package/src/scr_lib.c +957 -48
- package/src/scr_number.c +9 -0
- package/src/scr_regex.c +12 -1
- package/src/scr_runtime.h +189 -19
- package/src/scr_string.c +13 -2
- package/src/scr_text_decoder_data.h +7389 -0
- package/src/scr_util.c +984 -0
- package/src/scr_win_stats.h +23 -0
package/src/scr_number.c
CHANGED
|
@@ -24,6 +24,15 @@
|
|
|
24
24
|
* unchanged. Provides d2d(), d2d_small_int(), decimalLength17(), div10(). */
|
|
25
25
|
#include "../vendor/ryu/d2s.c"
|
|
26
26
|
|
|
27
|
+
/* ECMA ToUint32, shared by bitwise operators and split's limit: non-finite
|
|
28
|
+
* values become zero, finite values truncate toward zero and wrap mod 2^32. */
|
|
29
|
+
uint32_t scr_to_uint32(double d) {
|
|
30
|
+
if (!isfinite(d)) return 0;
|
|
31
|
+
double t = fmod(trunc(d), 4294967296.0);
|
|
32
|
+
if (t < 0) t += 4294967296.0;
|
|
33
|
+
return (uint32_t)t;
|
|
34
|
+
}
|
|
35
|
+
|
|
27
36
|
/* The Ryū digit core, shared by the ECMA placement below and the Intl
|
|
28
37
|
* en-US number formatter (scr_lib.c): the shortest round-tripping digit
|
|
29
38
|
* string for a positive finite double — value = 0.digits × 10^n with no
|
package/src/scr_regex.c
CHANGED
|
@@ -624,8 +624,10 @@ ScrStr *scr_regex_replace_all(ScrStr *s, ScrRegex *re, ScrStr *rep) {
|
|
|
624
624
|
|
|
625
625
|
/* ── split ────────────────────────────────────────────────────────────── */
|
|
626
626
|
|
|
627
|
-
ScrArr *
|
|
627
|
+
ScrArr *scr_regex_split_limit(ScrStr *s, ScrRegex *re, double limit_num) {
|
|
628
628
|
uint8_t *bc = scr_regex_bc(re);
|
|
629
|
+
uint32_t limit = scr_to_uint32(limit_num);
|
|
630
|
+
if (limit == 0) return scr_arr_new(SCR_ELEM_STR, 0);
|
|
629
631
|
if (lre_get_capture_count(bc) > 1) {
|
|
630
632
|
/* JS splices every capture group's value into the result between the
|
|
631
633
|
* pieces, changing the array's SHAPE per match — not modeled this
|
|
@@ -675,6 +677,11 @@ ScrArr *scr_regex_split(ScrStr *s, ScrRegex *re) {
|
|
|
675
677
|
q = scr_advance(u, len, start, unicode);
|
|
676
678
|
} else {
|
|
677
679
|
scr_arr_push_ref(out, scr_str_from_utf16(u, p, start));
|
|
680
|
+
if (out->len == limit) {
|
|
681
|
+
free(capture);
|
|
682
|
+
free(u);
|
|
683
|
+
return out;
|
|
684
|
+
}
|
|
678
685
|
p = end;
|
|
679
686
|
q = p;
|
|
680
687
|
}
|
|
@@ -685,6 +692,10 @@ ScrArr *scr_regex_split(ScrStr *s, ScrRegex *re) {
|
|
|
685
692
|
return out;
|
|
686
693
|
}
|
|
687
694
|
|
|
695
|
+
ScrArr *scr_regex_split(ScrStr *s, ScrRegex *re) {
|
|
696
|
+
return scr_regex_split_limit(s, re, 4294967295.0);
|
|
697
|
+
}
|
|
698
|
+
|
|
688
699
|
/* ── String.prototype.toLowerCase / toUpperCase (the static path) ──────
|
|
689
700
|
* ECMA-262 Default Case Conversion via the vendored libunicode's
|
|
690
701
|
* lre_case_conv — the exact tables and algorithm the engine's own
|
package/src/scr_runtime.h
CHANGED
|
@@ -197,9 +197,15 @@ void scr_library_bytes_out(ScrBytes *b, const uint8_t **out, size_t *out_len);
|
|
|
197
197
|
* collection walks the buffer (markGray: trial-decrement internal edges;
|
|
198
198
|
* scan: restore externally-referenced subgraphs; collectWhite: free the
|
|
199
199
|
* dead cycle members, releasing only edges that LEAVE the white set).
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
200
|
+
* It is GENERATIONAL: each header carries a generation, a pass names the
|
|
201
|
+
* oldest one it will walk, and objects that survive a pass are promoted out
|
|
202
|
+
* of the nursery so later nursery passes never re-walk them. That is what
|
|
203
|
+
* keeps a pass proportional to recent allocation rather than to the whole
|
|
204
|
+
* live heap — see the generation note in scr_cycle.c for the soundness
|
|
205
|
+
* argument and the schedule. Collection points: program exit (before the RC
|
|
206
|
+
* audit), event-loop quiescence, and the per-generation triggers.
|
|
207
|
+
* SCR_CYCLE_THRESHOLD pins the nursery trigger to a fixed candidate count.
|
|
208
|
+
* There is no concurrent or incremental collection.
|
|
203
209
|
*
|
|
204
210
|
* Contract for trace/teardown pairs (the compiler emits them for shapes,
|
|
205
211
|
* the runtime owns its own): trace(obj) visits exactly the strong
|
|
@@ -214,16 +220,44 @@ typedef void (*ScrTraceVisit)(void *child, void *ctx);
|
|
|
214
220
|
typedef void (*ScrTraceFn)(void *obj, ScrTraceVisit visit, void *ctx);
|
|
215
221
|
typedef void (*ScrCycFreeFn)(void *obj);
|
|
216
222
|
|
|
217
|
-
|
|
223
|
+
/* DOOMED is WHITE that collectWhite has already gathered: it stops the
|
|
224
|
+
* gather recursing twice, and distinguishes "about to be freed" from a
|
|
225
|
+
* survivor for the re-buffering step (see scr_cycle.c). */
|
|
226
|
+
enum {
|
|
227
|
+
SCR_CYC_BLACK = 0, SCR_CYC_PURPLE = 1, SCR_CYC_GRAY = 2, SCR_CYC_WHITE = 3,
|
|
228
|
+
SCR_CYC_DOOMED = 4
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/* Generations. A candidate sits in the buffer named by its own `gen`, and a
|
|
232
|
+
* pass walks only objects at or below the generation it collects. */
|
|
233
|
+
enum { SCR_CYC_NURSERY = 0, SCR_CYC_MATURE = 1, SCR_CYC_NGENS = 2 };
|
|
218
234
|
|
|
219
235
|
typedef struct ScrCycHdr {
|
|
220
236
|
ScrTraceFn trace;
|
|
221
237
|
ScrCycFreeFn free_fn;
|
|
222
238
|
uint32_t color; /* SCR_CYC_* */
|
|
223
|
-
|
|
239
|
+
uint16_t buffered; /* 1 = sitting in its generation's candidate buffer */
|
|
240
|
+
uint16_t gen; /* SCR_CYC_NURSERY..SCR_CYC_MATURE (the walk filter) */
|
|
224
241
|
size_t buf_index; /* position there (O(1) removal when rc hits 0) */
|
|
225
242
|
} ScrCycHdr;
|
|
226
243
|
|
|
244
|
+
/* This layout is an ABI, not an implementation detail: the LLVM backend
|
|
245
|
+
* inlines scr_cyc_mark_live as a raw `store i32 0` at obj-16 (it is a
|
|
246
|
+
* static inline here, so there is no symbol to call) and reaches the header
|
|
247
|
+
* at obj-32. Three sites emit it — llvm/shapes.ts, llvm/classes.ts,
|
|
248
|
+
* llvm/emitter.ts. Nothing but `color` may share those four bytes: a field
|
|
249
|
+
* placed in them is silently zeroed by every retain, which is invisible to
|
|
250
|
+
* the type system and to the C compiler. Hence the assertions. */
|
|
251
|
+
_Static_assert(sizeof(ScrCycHdr) == 32, "LLVM backend reads the header at obj-32");
|
|
252
|
+
_Static_assert(offsetof(ScrCycHdr, color) == 16,
|
|
253
|
+
"LLVM backend's inlined mark-live stores i32 0 at obj-16");
|
|
254
|
+
_Static_assert(sizeof(((ScrCycHdr *)0)->color) == 4,
|
|
255
|
+
"mark-live is an i32 store: color must own all four bytes");
|
|
256
|
+
_Static_assert(SCR_CYC_BLACK == 0,
|
|
257
|
+
"the emitted mark-live stores the LITERAL 0, not the enumerator "
|
|
258
|
+
"— reordering the colors would make every compiled retain write "
|
|
259
|
+
"the wrong one");
|
|
260
|
+
|
|
227
261
|
static inline ScrCycHdr *scr_cyc_hdr(void *obj) { return (ScrCycHdr *)obj - 1; }
|
|
228
262
|
|
|
229
263
|
/* Zeroed allocation with a cycle header in front; returns the OBJECT
|
|
@@ -243,9 +277,18 @@ static inline void scr_cyc_mark_live(void *obj) {
|
|
|
243
277
|
scr_cyc_hdr(obj)->color = SCR_CYC_BLACK;
|
|
244
278
|
}
|
|
245
279
|
|
|
246
|
-
/*
|
|
280
|
+
/* Full sweep: trial-deletion passes over EVERY generation, to a fixpoint.
|
|
281
|
+
* This is the exit / session-reset entry point (the RC audit runs straight
|
|
282
|
+
* after and wants nothing reclaimable left), and it costs a walk of the
|
|
283
|
+
* live heap — do not put it on a per-turn path. */
|
|
247
284
|
void scr_collect_cycles(void);
|
|
248
285
|
|
|
286
|
+
/* One pass on the normal generational schedule, for callers that reach a
|
|
287
|
+
* natural collection point rather than a threshold (the event loop between
|
|
288
|
+
* turns). Cheap: usually a nursery pass; a waiting mature backlog ages into
|
|
289
|
+
* a bounded full pass so sparse roots cannot float forever. */
|
|
290
|
+
void scr_cyc_collect_scheduled(void);
|
|
291
|
+
|
|
249
292
|
/* ── class hierarchies (single inheritance) ───────────────────────────
|
|
250
293
|
* Classes in an `extends` hierarchy share a two-word object prefix: the
|
|
251
294
|
* usual `size_t rc`, then a pointer to the class's static vtable (emitted
|
|
@@ -569,12 +612,14 @@ ScrStr *scr_str_cp_at(ScrStr *s, double i);
|
|
|
569
612
|
ScrStr *scr_str_trim_start(ScrStr *s);
|
|
570
613
|
ScrStr *scr_str_trim_end(ScrStr *s);
|
|
571
614
|
|
|
572
|
-
/* split(separator) with a STRING separator
|
|
615
|
+
/* split(separator[, limit]) with a STRING separator: limit uses ToUint32;
|
|
616
|
+
* the no-limit wrapper supplies 2^32-1. Empty separator
|
|
573
617
|
* splits into single UTF-16 code units (each half of an astral char is
|
|
574
618
|
* U+FFFD — divergence, see above); otherwise splits on every occurrence,
|
|
575
619
|
* empty pieces kept. Borrows both; returns a +1 string[] (SCR_ELEM_STR). */
|
|
576
620
|
struct ScrArr;
|
|
577
621
|
struct ScrArr *scr_str_split(ScrStr *s, ScrStr *sep);
|
|
622
|
+
struct ScrArr *scr_str_split_limit(ScrStr *s, ScrStr *sep, double limit);
|
|
578
623
|
|
|
579
624
|
/* padStart(maxLength, fill)/padEnd — ECMA StringPad, UTF-16 unit counts.
|
|
580
625
|
* Target at or below the length (or empty fill) returns the receiver
|
|
@@ -677,6 +722,12 @@ void scr_qs_parse_into(ScrMap *out, const ScrStr *qs, const ScrStr *sep,
|
|
|
677
722
|
const ScrStr *eq, double max_keys, uint32_t str_tag,
|
|
678
723
|
uint32_t arr_tag);
|
|
679
724
|
|
|
725
|
+
/* node:util.parseArgs — the static checked-dynamic boundary. `config` is
|
|
726
|
+
* the documented JSON-safe configuration object; the returned dyn tree is
|
|
727
|
+
* a fresh ParsedResults object whose `values` child has null prototype.
|
|
728
|
+
* Borrows config; returns +1, or NULL with a Node-coded TypeError pending. */
|
|
729
|
+
struct ScrDyn *scr_util_parse_args(const struct ScrDyn *config);
|
|
730
|
+
|
|
680
731
|
/* querystring.stringify — Node's stringify over a borrowed dyn value (the
|
|
681
732
|
* frontend dynFroms the typed record; JS-world dyn values pass straight
|
|
682
733
|
* through). Non-object dyn values answer "" like Node; object keys iterate in
|
|
@@ -837,6 +888,15 @@ double scr_arr_push_f64(ScrArr *a, double v);
|
|
|
837
888
|
double scr_arr_push_bool(ScrArr *a, bool v);
|
|
838
889
|
double scr_arr_push_ref(ScrArr *a, void *v);
|
|
839
890
|
|
|
891
|
+
/* unshift returns the new length and _ref takes ownership. The spread form
|
|
892
|
+
* borrows a same-element-kind source, retains copied refs, and snapshots
|
|
893
|
+
* self-spread. reverse mutates in place and returns the receiver at +1. */
|
|
894
|
+
double scr_arr_unshift_f64(ScrArr *a, double v);
|
|
895
|
+
double scr_arr_unshift_bool(ScrArr *a, bool v);
|
|
896
|
+
double scr_arr_unshift_ref(ScrArr *a, void *v);
|
|
897
|
+
double scr_arr_unshift_spread(ScrArr *a, const ScrArr *src);
|
|
898
|
+
ScrArr *scr_arr_reverse(ScrArr *a);
|
|
899
|
+
|
|
840
900
|
/* pop traps on an empty array; _ref transfers ownership out (+1 to the
|
|
841
901
|
* caller, no release). */
|
|
842
902
|
double scr_arr_pop_f64(ScrArr *a);
|
|
@@ -940,8 +1000,10 @@ ScrStr *scr_regex_flags(ScrRegex *re); /* +1 */
|
|
|
940
1000
|
ScrStr *scr_regex_replace(ScrStr *s, ScrRegex *re, ScrStr *rep);
|
|
941
1001
|
/* replaceAll: throws Node's TypeError when /g is missing (may-throw). */
|
|
942
1002
|
ScrStr *scr_regex_replace_all(ScrStr *s, ScrRegex *re, ScrStr *rep);
|
|
943
|
-
/* split: capture-free patterns only — capture groups throw (may-throw).
|
|
1003
|
+
/* split: capture-free patterns only — capture groups throw (may-throw).
|
|
1004
|
+
* limit uses ToUint32; the no-limit wrapper supplies 2^32-1. */
|
|
944
1005
|
ScrArr *scr_regex_split(ScrStr *s, ScrRegex *re);
|
|
1006
|
+
ScrArr *scr_regex_split_limit(ScrStr *s, ScrRegex *re, double limit);
|
|
945
1007
|
/* matchAll drained eagerly: +1 string[][] of honest match slices; throws
|
|
946
1008
|
* Node's TypeError on a non-global regex (catchable). */
|
|
947
1009
|
ScrArr *scr_regex_match_all(ScrStr *s, ScrRegex *re);
|
|
@@ -2004,6 +2066,11 @@ void scr_fs_chmod(ScrStr *path, double mode);
|
|
|
2004
2066
|
void scr_fs_chown(ScrStr *path, double uid, double gid);
|
|
2005
2067
|
void scr_fs_copyfile(ScrStr *src, ScrStr *dest);
|
|
2006
2068
|
void scr_fs_rename(ScrStr *oldpath, ScrStr *newpath);
|
|
2069
|
+
/* The callback rename worker uses the non-throwing syscall seam off the
|
|
2070
|
+
* runtime thread, then materializes any Node-shaped Error back on the main
|
|
2071
|
+
* thread. raw returns 0 on success or a positive errno value on failure. */
|
|
2072
|
+
int scr_fs_rename_raw(const ScrStr *oldpath, const ScrStr *newpath);
|
|
2073
|
+
void scr_fs_rename_error(int error, const ScrStr *oldpath, const ScrStr *newpath);
|
|
2007
2074
|
void scr_fs_write_file_mode(ScrStr *path, ScrStr *data, double mode);
|
|
2008
2075
|
void scr_fs_mkdir_mode(ScrStr *path, double mode);
|
|
2009
2076
|
void scr_fs_mkdir_recursive_mode(ScrStr *path, double mode);
|
|
@@ -2036,6 +2103,7 @@ double scr_process_columns(double fd);
|
|
|
2036
2103
|
* stat(2) — follows symlinks, like Node's stat family. scr_fs_stat
|
|
2037
2104
|
* THROWS like the other sync calls. */
|
|
2038
2105
|
typedef struct ScrStats ScrStats;
|
|
2106
|
+
typedef struct ScrFileHandle ScrFileHandle;
|
|
2039
2107
|
typedef struct ScrPromise ScrPromise; /* full section further down */
|
|
2040
2108
|
|
|
2041
2109
|
ScrStats *scr_fs_stat(ScrStr *path); /* +1, or throws */
|
|
@@ -2048,6 +2116,9 @@ bool scr_stats_is_file(ScrStats *s);
|
|
|
2048
2116
|
bool scr_stats_is_dir(ScrStats *s);
|
|
2049
2117
|
bool scr_stats_is_symlink(ScrStats *s); /* lstat snapshots only */
|
|
2050
2118
|
double scr_stats_size(ScrStats *s);
|
|
2119
|
+
double scr_stats_blocks(ScrStats *s); /* allocated size in 512-byte units */
|
|
2120
|
+
double scr_stats_nlink(ScrStats *s);
|
|
2121
|
+
double scr_stats_atime_ms(ScrStats *s); /* ms with the sub-second fraction */
|
|
2051
2122
|
double scr_stats_mtime_ms(ScrStats *s); /* ms with the ns fraction */
|
|
2052
2123
|
|
|
2053
2124
|
/* fs/promises: the SAME sync operations, minting an already-settled
|
|
@@ -2058,6 +2129,7 @@ double scr_stats_mtime_ms(ScrStats *s); /* ms with the ns fraction */
|
|
|
2058
2129
|
* scr_lib.c without the fiber slice). */
|
|
2059
2130
|
ScrPromise *scr_fsp_read_file(ScrStr *path);
|
|
2060
2131
|
ScrPromise *scr_fsp_write_file(ScrStr *path, ScrStr *data);
|
|
2132
|
+
ScrPromise *scr_fsp_write_file_mode(ScrStr *path, ScrStr *data, double mode);
|
|
2061
2133
|
ScrPromise *scr_fsp_mkdir(ScrStr *path);
|
|
2062
2134
|
ScrPromise *scr_fsp_mkdir_mode(ScrStr *path, double mode);
|
|
2063
2135
|
ScrPromise *scr_fsp_mkdir_recursive(ScrStr *path);
|
|
@@ -2067,6 +2139,24 @@ ScrPromise *scr_fsp_chmod(ScrStr *path, double mode);
|
|
|
2067
2139
|
ScrPromise *scr_fsp_readdir(ScrStr *path);
|
|
2068
2140
|
ScrPromise *scr_fsp_rm(ScrStr *path);
|
|
2069
2141
|
ScrPromise *scr_fsp_stat(ScrStr *path);
|
|
2142
|
+
ScrPromise *scr_fsp_rename(ScrStr *oldpath, ScrStr *newpath);
|
|
2143
|
+
ScrPromise *scr_fsp_open(ScrStr *path, ScrStr *flags, double mode);
|
|
2144
|
+
ScrPromise *scr_file_handle_close_promise(ScrFileHandle *h);
|
|
2145
|
+
ScrPromise *scr_file_handle_read_file_promise(ScrFileHandle *h, ScrStr *encoding);
|
|
2146
|
+
ScrPromise *scr_file_handle_read_file_bytes_promise(ScrFileHandle *h, ScrStr *encoding);
|
|
2147
|
+
ScrPromise *scr_file_handle_write_file_promise(ScrFileHandle *h, ScrStr *data, ScrStr *encoding);
|
|
2148
|
+
ScrPromise *scr_file_handle_write_file_bytes_promise(ScrFileHandle *h, ScrBytes *data, ScrStr *encoding);
|
|
2149
|
+
ScrPromise *scr_file_handle_stat_promise(ScrFileHandle *h);
|
|
2150
|
+
|
|
2151
|
+
/* fs.rename: the syscall is submitted to a native worker immediately and
|
|
2152
|
+
* its error-first callback fires on a later event-loop turn through an
|
|
2153
|
+
* emitted, program-shaped adapter. Both paths and the callback are borrowed
|
|
2154
|
+
* at entry; the callback MOVES into the operation. err is borrowed and NULL
|
|
2155
|
+
* on success. */
|
|
2156
|
+
typedef void (*ScrFsRenameFn)(ScrClosure *cb, ScrError *err);
|
|
2157
|
+
void scr_fs_rename_async(ScrStr *oldpath, ScrStr *newpath,
|
|
2158
|
+
ScrClosure *cb /*moves*/, ScrFsRenameFn fn);
|
|
2159
|
+
void scr_fs_rename_thunk0(ScrClosure *cb, ScrError *err);
|
|
2070
2160
|
|
|
2071
2161
|
/* ── node:timers/promises (scr_async.c) ──────────────────────────────
|
|
2072
2162
|
* The promisified pair: a PENDING void promise a one-shot heap timer /
|
|
@@ -2416,7 +2506,36 @@ ScrStr *scr_path_win32_to_namespaced_path(ScrStr *path);
|
|
|
2416
2506
|
* (failure throws the path-less "EBADF: bad file descriptor, close").
|
|
2417
2507
|
* The pair behind spawn's fd-stdio form. */
|
|
2418
2508
|
double scr_fs_open(ScrStr *path, ScrStr *flags);
|
|
2419
|
-
|
|
2509
|
+
ScrFileHandle *scr_file_handle_open(ScrStr *path, ScrStr *flags, double mode);
|
|
2510
|
+
ScrFileHandle *scr_file_handle_retain(ScrFileHandle *h);
|
|
2511
|
+
void scr_file_handle_release(ScrFileHandle *h);
|
|
2512
|
+
void *scr_file_handle_retain_v(void *p);
|
|
2513
|
+
void scr_file_handle_release_v(void *p);
|
|
2514
|
+
double scr_file_handle_fd(ScrFileHandle *h);
|
|
2515
|
+
void scr_file_handle_close(ScrFileHandle *h);
|
|
2516
|
+
double scr_file_handle_read(ScrFileHandle *h, ScrBytes *buf, double offset,
|
|
2517
|
+
double length, double position, bool length_default);
|
|
2518
|
+
double scr_file_handle_write_bytes(ScrFileHandle *h, ScrBytes *buf,
|
|
2519
|
+
double offset, double length,
|
|
2520
|
+
double position, bool length_default);
|
|
2521
|
+
double scr_file_handle_write_str(ScrFileHandle *h, ScrStr *data,
|
|
2522
|
+
double position, ScrStr *encoding);
|
|
2523
|
+
ScrStr *scr_file_handle_read_file(ScrFileHandle *h);
|
|
2524
|
+
ScrBytes *scr_file_handle_read_file_bytes(ScrFileHandle *h);
|
|
2525
|
+
void scr_file_handle_write_file(ScrFileHandle *h, ScrStr *data);
|
|
2526
|
+
void scr_file_handle_write_file_bytes(ScrFileHandle *h, ScrBytes *data);
|
|
2527
|
+
ScrStats *scr_file_handle_stat(ScrFileHandle *h);
|
|
2528
|
+
/* position == -1 reads from and advances the descriptor's current offset;
|
|
2529
|
+
* nonnegative positions leave that offset unchanged (pread/ReadFile seam). */
|
|
2530
|
+
double scr_fs_read_sync(double fd, ScrBytes *buf, double offset, double length,
|
|
2531
|
+
double position);
|
|
2532
|
+
/* writeSync's classic Buffer window and utf8 string forms. position -1 (or
|
|
2533
|
+
* any other non-safe/nonnegative-integer value) writes at and advances the
|
|
2534
|
+
* current descriptor offset; safe nonnegative positions leave it unchanged. */
|
|
2535
|
+
double scr_fs_write_sync(double fd, ScrBytes *buf, double offset, double length,
|
|
2536
|
+
double position);
|
|
2537
|
+
double scr_fs_write_str_sync(double fd, ScrStr *data, double position,
|
|
2538
|
+
ScrStr *encoding);
|
|
2420
2539
|
void scr_fs_close(double fd);
|
|
2421
2540
|
|
|
2422
2541
|
/* ── WHATWG URL (scr_url.c) ──────────────────────────────────────────
|
|
@@ -2714,6 +2833,7 @@ typedef enum {
|
|
|
2714
2833
|
SCR_DYNH_FETCH_RESPONSE, /* native static-fetch Response */
|
|
2715
2834
|
SCR_DYNH_FETCH_HEADERS, /* native static-fetch response Headers */
|
|
2716
2835
|
SCR_DYNH_EVENT, /* native static-fetch abort Event */
|
|
2836
|
+
SCR_DYNH_ABORT_CONTROLLER, /* native static-fetch AbortController */
|
|
2717
2837
|
SCR_DYNH_COUNT,
|
|
2718
2838
|
} ScrDynHandleTag;
|
|
2719
2839
|
|
|
@@ -2980,6 +3100,7 @@ ScrStr *scr_dyn_string_coerce(const ScrDyn *d);
|
|
|
2980
3100
|
* called, their throws propagating) — the WHATWG USVString conversions.
|
|
2981
3101
|
* Borrows; +1 or NULL with the exception pending. */
|
|
2982
3102
|
ScrStr *scr_dyn_string_coerce_js(const ScrDyn *d);
|
|
3103
|
+
bool scr_dyn_number_coerce_js(const ScrDyn *d, double *out);
|
|
2983
3104
|
|
|
2984
3105
|
/* `d instanceof TypeError` (and the other builtin error classes) on a
|
|
2985
3106
|
* checked-dynamic value: the from_error cache resolves the dyn encoding
|
|
@@ -3349,6 +3470,8 @@ typedef struct {
|
|
|
3349
3470
|
} ScrJsonBuf;
|
|
3350
3471
|
|
|
3351
3472
|
void scr_jb_init(ScrJsonBuf *b);
|
|
3473
|
+
/* Append one borrowed runtime string verbatim (no JSON quoting). */
|
|
3474
|
+
void scr_jb_put_str(ScrJsonBuf *b, const ScrStr *s);
|
|
3352
3475
|
/* Push a container onto the circular-detection stack before serializing
|
|
3353
3476
|
* its members. If `v` is already ON the stack, throws V8's exact
|
|
3354
3477
|
* "Converting circular structure to JSON" TypeError (the --> starting at /
|
|
@@ -3664,6 +3787,10 @@ bool scr_immediate_has_ref(double handle);
|
|
|
3664
3787
|
* teardown (they must never run yet must not leak). cb ownership moves
|
|
3665
3788
|
* in. */
|
|
3666
3789
|
void scr_next_tick(ScrClosure *cb);
|
|
3790
|
+
/* A successful process.stdout/stderr.write completion on that same queue.
|
|
3791
|
+
* The callback and its program-shaped Error | null adapter both MOVE into
|
|
3792
|
+
* the entry; the adapter is invoked with NULL (Node's success argument). */
|
|
3793
|
+
void scr_process_write_callback(ScrClosure *cb, ScrFsRenameFn fn);
|
|
3667
3794
|
/* A raw C-hook entry on the SAME queue: the stream unit enqueues one
|
|
3668
3795
|
* marker per deferred stream emission, so stream ticks and user
|
|
3669
3796
|
* nextTicks run in true FIFO order (in Node they are the same queue).
|
|
@@ -3907,9 +4034,11 @@ long scr_promise_live_count(void);
|
|
|
3907
4034
|
* emitted main calls scr_fetch_install in either form. */
|
|
3908
4035
|
void scr_fetch_install(void);
|
|
3909
4036
|
ScrPromise *scr_fetch_static(ScrStr *url, ScrDyn *init); /* +1 promise<Response handle> */
|
|
4037
|
+
ScrDyn *scr_fetch_response_new(ScrDyn *body, ScrDyn *init); /* borrowed args; +1 Response handle or NULL pending */
|
|
3910
4038
|
ScrPromise *scr_fetch_response_json(ScrDyn *response); /* +1 promise<dyn> */
|
|
3911
4039
|
ScrPromise *scr_fetch_response_text(ScrDyn *response); /* +1 promise<dyn> */
|
|
3912
4040
|
ScrPromise *scr_fetch_response_bytes(ScrDyn *response); /* +1 promise<dyn> */
|
|
4041
|
+
ScrDyn *scr_fetch_abort_controller_new(void); /* +1 AbortController handle */
|
|
3913
4042
|
/* Borrowed number; +1 AbortSignal handle or NULL pending. */
|
|
3914
4043
|
ScrDyn *scr_fetch_abort_timeout(ScrDyn *delay);
|
|
3915
4044
|
ScrDyn *scr_fetch_abort_now(ScrDyn *reason); /* borrowed reason; +1 handle */
|
|
@@ -4398,10 +4527,13 @@ bool scr_num_same_value(double a, double b);
|
|
|
4398
4527
|
* en-US is the one embedded locale. Result +1; never throws. */
|
|
4399
4528
|
ScrStr *scr_intl_num_format_en_us(double x);
|
|
4400
4529
|
|
|
4401
|
-
/* ── Date, the
|
|
4402
|
-
* Date
|
|
4403
|
-
*
|
|
4530
|
+
/* ── Date, the read-only value slice (scr_lib.c) ──────────────────────
|
|
4531
|
+
* A Date value is its TimeClip'd epoch-millisecond scalar. Identity and
|
|
4532
|
+
* mutation are frontend-fenced; construction, storage, getters, and ISO
|
|
4533
|
+
* formatting are exact over this representation. */
|
|
4404
4534
|
double scr_date_now(void); /* integer ms since epoch, like Node */
|
|
4535
|
+
double scr_date_new_ms(double ms); /* TimeClip (NaN when invalid) */
|
|
4536
|
+
double scr_date_get_time(double ms);
|
|
4405
4537
|
/* Node's exact ISO 8601 UTC format (expanded ±YYYYYY years outside
|
|
4406
4538
|
* 0–9999). THROWS Node's "Invalid time value" RangeError on NaN or
|
|
4407
4539
|
* |ms| > 8.64e15 and returns NULL; +1 otherwise. */
|
|
@@ -4415,13 +4547,39 @@ double scr_date_parse_get_time(ScrStr *s);
|
|
|
4415
4547
|
* and years past V8's ±1e6 MakeDay bound. Never throws. */
|
|
4416
4548
|
double scr_date_utc(double y, double mo, double d,
|
|
4417
4549
|
double h, double mi, double s, double ms);
|
|
4418
|
-
|
|
4419
|
-
|
|
4550
|
+
double scr_date_get_full_year(double ms, bool utc);
|
|
4551
|
+
double scr_date_get_month(double ms, bool utc);
|
|
4552
|
+
double scr_date_get_date(double ms, bool utc);
|
|
4553
|
+
double scr_date_get_day(double ms, bool utc);
|
|
4554
|
+
double scr_date_get_hours(double ms, bool utc);
|
|
4555
|
+
double scr_date_get_minutes(double ms, bool utc);
|
|
4556
|
+
double scr_date_get_seconds(double ms, bool utc);
|
|
4557
|
+
double scr_date_get_milliseconds(double ms);
|
|
4558
|
+
double scr_date_get_timezone_offset(double ms);
|
|
4559
|
+
/* One-argument ABI wrappers used by the LLVM lib-call table. */
|
|
4560
|
+
double scr_date_get_full_year_local(double ms);
|
|
4561
|
+
double scr_date_get_full_year_utc(double ms);
|
|
4562
|
+
double scr_date_get_month_local(double ms);
|
|
4563
|
+
double scr_date_get_month_utc(double ms);
|
|
4564
|
+
double scr_date_get_date_local(double ms);
|
|
4565
|
+
double scr_date_get_date_utc(double ms);
|
|
4566
|
+
double scr_date_get_day_local(double ms);
|
|
4567
|
+
double scr_date_get_day_utc(double ms);
|
|
4568
|
+
double scr_date_get_hours_local(double ms);
|
|
4569
|
+
double scr_date_get_hours_utc(double ms);
|
|
4570
|
+
double scr_date_get_minutes_local(double ms);
|
|
4571
|
+
double scr_date_get_minutes_utc(double ms);
|
|
4572
|
+
double scr_date_get_seconds_local(double ms);
|
|
4573
|
+
double scr_date_get_seconds_utc(double ms);
|
|
4574
|
+
|
|
4575
|
+
/* ── numeric coercion + bitwise operators ─────────────────────────────
|
|
4420
4576
|
* JS-exact ToInt32/ToUint32 semantics: NaN/±Infinity → 0, truncation
|
|
4421
4577
|
* toward zero, modular wrap into 32 bits; the operation runs in 32-bit
|
|
4422
4578
|
* space (shift counts mask to 5 bits, `>>` is an arithmetic shift spelled
|
|
4423
4579
|
* portably — no C UB/implementation-defined shifts) and the result
|
|
4424
|
-
* returns to f64: `>>>` as Uint32, everything else as Int32.
|
|
4580
|
+
* returns to f64: `>>>` as Uint32, everything else as Int32.
|
|
4581
|
+
* scr_to_uint32 lives in scr_number.c; the bitwise operations in scr_lib.c. */
|
|
4582
|
+
uint32_t scr_to_uint32(double d);
|
|
4425
4583
|
double scr_bit_and(double a, double b);
|
|
4426
4584
|
double scr_bit_or(double a, double b);
|
|
4427
4585
|
double scr_bit_xor(double a, double b);
|
|
@@ -4618,12 +4776,22 @@ void scr_bytes_set_from(ScrBytes *dst, const ScrBytes *src, double offset);
|
|
|
4618
4776
|
* compiler fences other encodings). */
|
|
4619
4777
|
ScrStr *scr_bytes_to_str(const ScrBytes *b, const ScrStr *enc);
|
|
4620
4778
|
ScrStr *scr_bytes_to_str_range(const ScrBytes *b, const ScrStr *enc, double start, double end);
|
|
4779
|
+
/* Runtime-valued Buffer.toString encoding: aliases/case canonicalize;
|
|
4780
|
+
* unknown names throw ERR_UNKNOWN_ENCODING. +1, or NULL when throwing. */
|
|
4781
|
+
ScrStr *scr_bytes_to_str_checked(const ScrBytes *b, const ScrStr *enc);
|
|
4782
|
+
ScrStr *scr_bytes_to_str_checked_range(const ScrBytes *b, const ScrStr *enc, double start, double end);
|
|
4621
4783
|
|
|
4622
4784
|
/* WHATWG TextDecoder.decode over u8 bytes (utf-8, default options): the
|
|
4623
4785
|
* same replacement decode as toString("utf8") with the leading BOM
|
|
4624
4786
|
* stripped. Borrows; +1; never throws. */
|
|
4625
4787
|
ScrStr *scr_text_decode(const ScrBytes *b);
|
|
4626
4788
|
|
|
4789
|
+
/* TextDecoder with a compile-time WHATWG legacy-encoding id. The frontend
|
|
4790
|
+
* owns label canonicalization and emits only the ids understood by
|
|
4791
|
+
* scr_bytes.c; keeping this separate from scr_text_decode means default
|
|
4792
|
+
* UTF-8 users do not retain the legacy mapping tables. Borrows; +1. */
|
|
4793
|
+
ScrStr *scr_text_decode_legacy(const ScrBytes *b, double encoding);
|
|
4794
|
+
|
|
4627
4795
|
/* Buffer.from(string, enc): "utf8" copies the bytes; "hex" parses pairs
|
|
4628
4796
|
* and stops at the first invalid/odd tail (Node-lenient); "base64" and
|
|
4629
4797
|
* "base64url" decode the standard AND url-safe alphabets, skipping
|
|
@@ -4818,10 +4986,12 @@ ScrPromise *scr_fsp_read_file_bytes(ScrStr *path); /* +1 */
|
|
|
4818
4986
|
* RangeError catchably (same check as scr_crypto_random_string). */
|
|
4819
4987
|
ScrBytes *scr_crypto_random_bytes(double n); /* +1 */
|
|
4820
4988
|
|
|
4821
|
-
/* process.stdout/stderr.write(buf): the raw byte writes' Buffer
|
|
4822
|
-
* (same streams and buffering as the string forms).
|
|
4823
|
-
|
|
4824
|
-
|
|
4989
|
+
/* process.stdout/stderr.write(buf[, encoding]): the raw byte writes' Buffer
|
|
4990
|
+
* overloads (same streams and buffering as the string forms). The encoding
|
|
4991
|
+
* is evaluated by the caller and ignored here, as Node does for bytes.
|
|
4992
|
+
* Constantly true. */
|
|
4993
|
+
bool scr_process_stdout_write_bytes(const ScrBytes *b, const ScrStr *encoding);
|
|
4994
|
+
bool scr_process_stderr_write_bytes(const ScrBytes *b, const ScrStr *encoding);
|
|
4825
4995
|
|
|
4826
4996
|
/* The Node-shaped fs error thrower (scr_lib.c): formats "ENOENT: no such
|
|
4827
4997
|
* file or directory, open 'x'" and throws it catchably. Shared with
|
package/src/scr_string.c
CHANGED
|
@@ -678,7 +678,9 @@ ScrStr *scr_str_trim_end(ScrStr *s) {
|
|
|
678
678
|
static const struct { size_t rc; size_t len; size_t cap; char data[4]; }
|
|
679
679
|
scr_lit_fffd = {SIZE_MAX, 3, 3, "\xEF\xBF\xBD"};
|
|
680
680
|
|
|
681
|
-
/* split(separator) with a STRING separator
|
|
681
|
+
/* split(separator, limit) with a STRING separator (ECMA-262 22.1.3.23):
|
|
682
|
+
* limit is ToUint32'd; zero returns [] and reaching the limit stops before
|
|
683
|
+
* any later separator probes. The no-limit wrapper supplies 2^32-1.
|
|
682
684
|
* an empty separator splits into single UTF-16 code units ("".split("") is
|
|
683
685
|
* [] — no probe matches nothing); a non-empty separator splits on every
|
|
684
686
|
* byte-level occurrence (well-formed UTF-8 is self-synchronizing, so byte
|
|
@@ -688,8 +690,10 @@ static const struct { size_t rc; size_t len; size_t cap; char data[4]; }
|
|
|
688
690
|
* yield the two lone surrogate halves, each half is U+FFFD here
|
|
689
691
|
* (divergence 2 — the same substitution the island's boundary marshal
|
|
690
692
|
* applied). Borrows both; returns a +1 string[]. */
|
|
691
|
-
ScrArr *
|
|
693
|
+
ScrArr *scr_str_split_limit(ScrStr *s, ScrStr *sep, double limit_num) {
|
|
692
694
|
ScrArr *out = scr_arr_new(SCR_ELEM_STR, 0);
|
|
695
|
+
uint32_t limit = scr_to_uint32(limit_num);
|
|
696
|
+
if (limit == 0) return out;
|
|
693
697
|
if (sep->len == 0) {
|
|
694
698
|
size_t i = 0;
|
|
695
699
|
while (i < s->len) {
|
|
@@ -697,10 +701,12 @@ ScrArr *scr_str_split(ScrStr *s, ScrStr *sep) {
|
|
|
697
701
|
uint32_t cp = scr_utf8_decode(s->data + i, &adv);
|
|
698
702
|
if (cp >= 0x10000) { /* two units in JS: both halves become U+FFFD */
|
|
699
703
|
scr_arr_push_ref(out, scr_str_retain((ScrStr *)&scr_lit_fffd));
|
|
704
|
+
if (out->len == limit) return out;
|
|
700
705
|
scr_arr_push_ref(out, scr_str_retain((ScrStr *)&scr_lit_fffd));
|
|
701
706
|
} else {
|
|
702
707
|
scr_arr_push_ref(out, scr_str_from_span(s->data + i, adv));
|
|
703
708
|
}
|
|
709
|
+
if (out->len == limit) return out;
|
|
704
710
|
i += adv;
|
|
705
711
|
}
|
|
706
712
|
return out;
|
|
@@ -712,12 +718,17 @@ ScrArr *scr_str_split(ScrStr *s, ScrStr *sep) {
|
|
|
712
718
|
if (!found) break;
|
|
713
719
|
size_t at = (size_t)(found - s->data);
|
|
714
720
|
scr_arr_push_ref(out, scr_str_from_span(s->data + start, at - start));
|
|
721
|
+
if (out->len == limit) return out;
|
|
715
722
|
start = at + sep->len;
|
|
716
723
|
}
|
|
717
724
|
scr_arr_push_ref(out, scr_str_from_span(s->data + start, s->len - start));
|
|
718
725
|
return out;
|
|
719
726
|
}
|
|
720
727
|
|
|
728
|
+
ScrArr *scr_str_split(ScrStr *s, ScrStr *sep) {
|
|
729
|
+
return scr_str_split_limit(s, sep, 4294967295.0);
|
|
730
|
+
}
|
|
731
|
+
|
|
721
732
|
/* StringPad (ECMA-262 22.1.3.16/17): target length in UTF-16 units, the
|
|
722
733
|
* filler built from whole repetitions of `fill` plus a truncated prefix.
|
|
723
734
|
* A target at or below the length (or an empty fill) returns the receiver
|