@scriptc/runtime 0.0.7 → 0.0.9
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_bytes.c +58 -12
- package/src/scr_bytes_io.c +97 -1
- package/src/scr_dyn_handle.c +8 -66
- package/src/scr_error.c +15 -0
- package/src/scr_events_emitter.c +34 -0
- package/src/scr_exception.c +24 -1
- package/src/scr_island.c +109 -6
- package/src/scr_json.c +218 -0
- package/src/scr_lib.c +101 -3
- package/src/scr_library.c +119 -5
- package/src/scr_number.c +29 -19
- package/src/scr_object.c +18 -0
- package/src/scr_runtime.h +173 -7
- package/src/scr_stream.c +49 -2
package/src/scr_runtime.h
CHANGED
|
@@ -48,8 +48,10 @@ void scr_init(void);
|
|
|
48
48
|
* the host-registered panic sink and abort only as the last resort: before
|
|
49
49
|
* registration, or if the sink returns (the ruled host-contract violation —
|
|
50
50
|
* a conforming sink longjmps to a host frame BELOW the entry, never back
|
|
51
|
-
* into library frames). Messages keep their trailing newline in both lanes
|
|
52
|
-
* the funnel
|
|
51
|
+
* into library frames). Messages keep their trailing newline in both lanes;
|
|
52
|
+
* the library funnel additionally assembles every DETECTED trap into the
|
|
53
|
+
* structured trap-teaching form before delivery (a message that already
|
|
54
|
+
* begins with the 0x01 marker passes verbatim) — see ScrLibSinkFn below. */
|
|
53
55
|
_Noreturn void scr_trap(const char *msg);
|
|
54
56
|
_Noreturn void scr_trap_fmt(const char *fmt, ...);
|
|
55
57
|
|
|
@@ -67,7 +69,32 @@ typedef struct ScrBytes ScrBytes;
|
|
|
67
69
|
* call; address is the trap site's return address (0 when the toolchain
|
|
68
70
|
* cannot supply one); ctx is the registration's opaque pointer. The sink
|
|
69
71
|
* must not call back into any library entry and must not unwind or longjmp
|
|
70
|
-
* back into library frames.
|
|
72
|
+
* back into library frames.
|
|
73
|
+
*
|
|
74
|
+
* Message shape (the ratified structured trap-teaching encoding): a
|
|
75
|
+
* BASELINE message is plain text whose first byte is printable (>= 0x20) —
|
|
76
|
+
* no emitter path ever produces an unstructured message starting below
|
|
77
|
+
* 0x20. A STRUCTURED message begins with the marker byte 0x01 followed by
|
|
78
|
+
* the human teaching text and 0x1F-separated fields:
|
|
79
|
+
*
|
|
80
|
+
* 0x01 text 0x1F code 0x1F symbol [ 0x1F remediation ]
|
|
81
|
+
*
|
|
82
|
+
* so msg_len > 0 && msg[0] == 0x01 is the one version test. Parse: split
|
|
83
|
+
* the bytes after the marker on 0x1F — field 0 is the human text, 1 the
|
|
84
|
+
* diagnostic code, 2 the trapping symbol as the host linked it, 3 the
|
|
85
|
+
* remediation; a missing or empty field means none; ignore any field past
|
|
86
|
+
* the fourth. Fields are (pointer, length) — never assume NUL termination.
|
|
87
|
+
* A plain-text host may print the whole buffer: the teaching leads it.
|
|
88
|
+
*
|
|
89
|
+
* Every trap the runtime DETECTS arrives structured: the funnel assembles
|
|
90
|
+
* the baseline human line into field 0 unchanged, a stable code for the
|
|
91
|
+
* trap kind (the compiler registry's SC4013–SC4019 runtime family,
|
|
92
|
+
* classified in scr_library.c), the entry symbol recorded by the trapping
|
|
93
|
+
* entry's prologue, and the profile's remediation for that code when the
|
|
94
|
+
* program TU's overlay table declares one (the whole fourth field is
|
|
95
|
+
* absent otherwise). A message that already begins with the marker — a
|
|
96
|
+
* facade-authored structured throw, or the wrapper's compile-time-
|
|
97
|
+
* assembled SC4012 contract trap — passes through byte-for-byte. */
|
|
71
98
|
typedef void (*ScrLibSinkFn)(void *ctx, const uint8_t *msg, size_t msg_len,
|
|
72
99
|
uint64_t address);
|
|
73
100
|
void scr_library_set_sink(ScrLibSinkFn fn, void *ctx); /* latest wins */
|
|
@@ -75,8 +102,15 @@ void scr_library_set_sink(ScrLibSinkFn fn, void *ctx); /* latest wins */
|
|
|
75
102
|
/* Entry prologue: aborts deterministically when the library is poisoned (a
|
|
76
103
|
* trap already fired — no profile entry may run again; recovery is process
|
|
77
104
|
* restart). reset_arena additionally drops the result arena (the
|
|
78
|
-
* auto-reset posture, and the reset/collect entries' shared body).
|
|
79
|
-
|
|
105
|
+
* auto-reset posture, and the reset/collect entries' shared body).
|
|
106
|
+
* entry_symbol is the generated entry's external symbol exactly as the
|
|
107
|
+
* host linked it (a static string in the program TU): the prologue records
|
|
108
|
+
* it in the funnel's current-entry slot so a detected trap's structured
|
|
109
|
+
* message can name the trapping entry — sound as a single static slot
|
|
110
|
+
* because exactly one core is ever live and entries never nest. Init and
|
|
111
|
+
* the mode entries (reset, collect) record theirs too; the identity
|
|
112
|
+
* getters and sink registration touch no runtime and never trap. */
|
|
113
|
+
void scr_library_entry(bool reset_arena, const char *entry_symbol);
|
|
80
114
|
void scr_library_arena_reset(void);
|
|
81
115
|
/* The mode-provided collect entry's body: arena reset + a full cycle
|
|
82
116
|
* collection (snapshot-invariant by construction — collection frees only
|
|
@@ -96,16 +130,39 @@ void scr_library_register_reset(void (*fn)(void));
|
|
|
96
130
|
/* An escaped exception at an entry boundary: renders the same "Uncaught
|
|
97
131
|
* ..." text the executable epilogue prints, releases the payload, and
|
|
98
132
|
* routes the text through the trap funnel. No-op when nothing is pending.
|
|
99
|
-
*
|
|
133
|
+
* The ratified verbatim rule: a thrown message that ALREADY begins with the
|
|
134
|
+
* structured marker 0x01 (a thrown string, or an Error whose .message
|
|
135
|
+
* starts with it) is delivered byte-for-byte — no "Uncaught " prefix, no
|
|
136
|
+
* added newline — which is how facade-authored structured teachings ride
|
|
137
|
+
* the throw channel to the sink. Defined in scr_exception.c (it owns the
|
|
138
|
+
* cell). */
|
|
100
139
|
void scr_library_check_exc(void);
|
|
101
140
|
|
|
141
|
+
/* The length-taking funnel entry (library lane only): delivers exactly the
|
|
142
|
+
* given bytes to the sink — the verbatim path above needs it because a
|
|
143
|
+
* structured message is length-delimited, never NUL-scanned. */
|
|
144
|
+
_Noreturn void scr_trap_len(const char *msg, size_t len);
|
|
145
|
+
|
|
146
|
+
/* The runtime-trap overlay table, DEFINED by the generated program TU
|
|
147
|
+
* (both emissions emit identical data) and consumed by the funnel when it
|
|
148
|
+
* assembles a detected trap's structured message: flat triples of
|
|
149
|
+
* (code, teaching-or-NULL, remediation-or-NULL), one per runtime trap code
|
|
150
|
+
* (SC4013–SC4019 family) the profile declares text for; _len counts
|
|
151
|
+
* triples. A declared teaching replaces the baseline human line as field 0;
|
|
152
|
+
* a declared remediation becomes the optional fourth field. */
|
|
153
|
+
extern const char *const scr_library_trap_overlays[];
|
|
154
|
+
extern const size_t scr_library_trap_overlays_len;
|
|
155
|
+
|
|
102
156
|
/* Marshalling helpers the generated wrappers call (both emissions share
|
|
103
157
|
* these bodies, which is how the two lanes stay identical by
|
|
104
158
|
* construction). Inbound is borrowed-and-copied; outbound values MOVE into
|
|
105
159
|
* the result arena and stay valid until the next arena reset. String
|
|
106
160
|
* results are NUL-terminated after *out_len bytes (ScrStr's layout). */
|
|
107
161
|
ScrStr *scr_library_str_in(const uint8_t *p, size_t len); /* +1 */
|
|
108
|
-
|
|
162
|
+
/* trap_msg is the wrapper's compiler-assembled host-contract trap message
|
|
163
|
+
* (structured trap-teaching bytes naming this entry's symbol), delivered
|
|
164
|
+
* through the funnel when len falls outside the marshalling class. */
|
|
165
|
+
ScrBytes *scr_library_bytes_in(const uint8_t *p, size_t len, const char *trap_msg); /* +1, u8 */
|
|
109
166
|
void scr_library_str_out(ScrStr *s, const uint8_t **out, size_t *out_len);
|
|
110
167
|
void scr_library_bytes_out(ScrBytes *b, const uint8_t **out, size_t *out_len);
|
|
111
168
|
|
|
@@ -287,6 +344,10 @@ void *scr_classobj_retain_v(void *c);
|
|
|
287
344
|
void scr_classobj_release_v(void *c);
|
|
288
345
|
/* `X.name` (+1 — a no-op retain on the interned immortal). */
|
|
289
346
|
ScrStr *scr_classobj_name(ScrClassObj *c);
|
|
347
|
+
/* The keyed-write miss on a fixed-shape record: throws the catchable
|
|
348
|
+
* TypeError naming the key (JS would add the property — the documented
|
|
349
|
+
* monomorphic-struct divergence). scr_object.c. */
|
|
350
|
+
void scr_record_key_miss(ScrStr *k);
|
|
290
351
|
|
|
291
352
|
/* ── error objects (scr_error.c) ──────────────────────────────────────
|
|
292
353
|
* `Error` and its lib subclasses (TypeError/RangeError/SyntaxError) are a
|
|
@@ -417,6 +478,9 @@ void scr_undef_global_read(ScrStr *name);
|
|
|
417
478
|
void scr_error_set_code(ScrError *e, const char *code);
|
|
418
479
|
ScrStr *scr_error_code(ScrError *e);
|
|
419
480
|
void scr_throw_error_msg_code(int kind, const char *message, size_t len, const char *code);
|
|
481
|
+
/* The compiler-resolved Node-parity throw (error.nodeThrow): builtin
|
|
482
|
+
* error of `kind`, `code` stamped when non-empty. Borrows both. */
|
|
483
|
+
void scr_throw_node_coded(double kind, const ScrStr *code, const ScrStr *msg);
|
|
420
484
|
|
|
421
485
|
/* ── string methods ─────────────────────────────────────────────────
|
|
422
486
|
* ECMA-262 observable semantics (UTF-16 code units) computed over the
|
|
@@ -1520,6 +1584,13 @@ bool scr_stream_push_dyn(ScrStream *s, const ScrDyn *d); /* borrows d; tag
|
|
|
1520
1584
|
bool scr_stream_write_dyn(ScrStream *s, const ScrDyn *d, ScrClosure *cb); /* cb moves */
|
|
1521
1585
|
ScrPromise *scr_stream_next_chunk(ScrStream *s);
|
|
1522
1586
|
ScrPromise *scr_stream_next_chunk_dyn(ScrStream *s);
|
|
1587
|
+
/* node:stream/promises — the promise forms over the finished/pipeline
|
|
1588
|
+
* machinery above: a pending void promise the terminal watcher settles
|
|
1589
|
+
* (fulfilled on a clean finish, rejected with the finish status
|
|
1590
|
+
* otherwise — the stream's error or ERR_STREAM_PREMATURE_CLOSE).
|
|
1591
|
+
* Streams borrowed; +1 promises. */
|
|
1592
|
+
ScrPromise *scr_sp_finished(ScrStream *s);
|
|
1593
|
+
ScrPromise *scr_sp_pipeline(double n, ScrStream **streams);
|
|
1523
1594
|
/* Readable.from(array): +1 fully-seeded object-entry stream (one WHOLE
|
|
1524
1595
|
* chunk per element — strings or Buffers per the flag; hwm 1, already
|
|
1525
1596
|
* EOF'd). Borrows arr. */
|
|
@@ -2640,6 +2711,13 @@ ScrDyn *scr_dyn_obj_get(const ScrDyn *d, const char *key, size_t key_len);
|
|
|
2640
2711
|
* member nodes. null/undefined receivers throw Node's catchable
|
|
2641
2712
|
* TypeError. */
|
|
2642
2713
|
ScrDyn *scr_dyn_obj_keys(const ScrDyn *v);
|
|
2714
|
+
/* Object.hasOwn over a DOM receiver: OBJ member presence, ARR index
|
|
2715
|
+
* bounds ("length" included); nullish receivers throw Node's ToObject
|
|
2716
|
+
* TypeError; every other kind answers false. */
|
|
2717
|
+
bool scr_dyn_has_own(const ScrDyn *v, const ScrStr *key);
|
|
2718
|
+
/* Object.assign over DOM values (+1 target back; ToObject TypeError on a
|
|
2719
|
+
* nullish target). */
|
|
2720
|
+
ScrDyn *scr_dyn_assign(ScrDyn *target, const ScrDyn *src);
|
|
2643
2721
|
ScrDyn *scr_dyn_obj_values(const ScrDyn *v);
|
|
2644
2722
|
ScrDyn *scr_dyn_obj_entries(const ScrDyn *v);
|
|
2645
2723
|
|
|
@@ -2667,6 +2745,14 @@ ScrDyn *scr_dyn_new_buffer_copy(const ScrBytes *b);
|
|
|
2667
2745
|
* extraction (`u as Uint8Array`). */
|
|
2668
2746
|
ScrBytes *scr_dyn_bytes_copy_out(const ScrDyn *d);
|
|
2669
2747
|
void scr_dyn_arr_push(ScrDyn *arr, ScrDyn *item);
|
|
2748
|
+
/* Spread completion for a runtime-arity argument list (`f(...xs)` in the
|
|
2749
|
+
* checked-dynamic tier): flattens `src` into `arr` per JS's spread over the
|
|
2750
|
+
* DOM's iterable kinds — arrays element-by-element (retained), strings by
|
|
2751
|
+
* code POINT (the string iterator), bytes by byte — and throws V8's exact
|
|
2752
|
+
* SPREAD-CALL TypeError for every other kind (pending; callers check):
|
|
2753
|
+
* nullish sources spell the spread expression (`what`), everything else is
|
|
2754
|
+
* the generic "Spread syntax requires ..." text. Borrows src. */
|
|
2755
|
+
void scr_dyn_arr_push_spread(ScrDyn *arr, const ScrDyn *src, const char *what);
|
|
2670
2756
|
void scr_dyn_obj_set(ScrDyn *obj, const char *key, size_t key_len, ScrDyn *value);
|
|
2671
2757
|
/* The checked-dynamic keyed WRITE (`h.k = v` on a dyn receiver): OBJ sets
|
|
2672
2758
|
* the member (JS: later writes win, insertion order); undefined/null and
|
|
@@ -2683,6 +2769,10 @@ ScrStr *scr_dyn_to_string(const ScrDyn *d, const ScrStr *enc);
|
|
|
2683
2769
|
/* JS String() over the DOM kind (units render "null"/"undefined" where
|
|
2684
2770
|
* scr_dyn_to_string throws) — the web globals' WebIDL ToString. +1. */
|
|
2685
2771
|
ScrStr *scr_dyn_string_coerce(const ScrDyn *d);
|
|
2772
|
+
/* JS ToString WITH the object protocol (user toString/valueOf members
|
|
2773
|
+
* called, their throws propagating) — the WHATWG USVString conversions.
|
|
2774
|
+
* Borrows; +1 or NULL with the exception pending. */
|
|
2775
|
+
ScrStr *scr_dyn_string_coerce_js(const ScrDyn *d);
|
|
2686
2776
|
|
|
2687
2777
|
/* `d instanceof TypeError` (and the other builtin error classes) on a
|
|
2688
2778
|
* checked-dynamic value: the from_error cache resolves the DOM encoding
|
|
@@ -2753,6 +2843,10 @@ ScrDyn *scr_dyn_new_func(ScrClosure *clo, ScrDynThunk thunk, uint32_t arity, con
|
|
|
2753
2843
|
* boxed thunk (per-arg checks live there). `args` entries are BORROWED;
|
|
2754
2844
|
* the result is owned (+1), or NULL with the exception pending. */
|
|
2755
2845
|
ScrDyn *scr_dyn_call(const ScrDyn *d, ScrDyn *const *args, size_t argc, const char *what);
|
|
2846
|
+
/* scr_dyn_call over a DOM ARRAY's elements (the spread-application form —
|
|
2847
|
+
* `f(...args)` after the emitted argument array is built): argv IS the
|
|
2848
|
+
* array's items. Borrows both; result owned (+1), or NULL pending. */
|
|
2849
|
+
ScrDyn *scr_dyn_apply(const ScrDyn *d, const ScrDyn *args, const char *what);
|
|
2756
2850
|
|
|
2757
2851
|
/* Path spine for dynCheck error messages — a compile-time-shaped linked
|
|
2758
2852
|
* list the emitted builders stack-allocate per recursion level: `key`
|
|
@@ -2893,6 +2987,9 @@ void scr_dyn_check_listener(const ScrDyn *cb, const char *argname);
|
|
|
2893
2987
|
* generic ERR_INVALID_ARG_TYPE thrower over it (`expected` is the whole
|
|
2894
2988
|
* "of type ..." clause). The handle dispatchers' per-arg gates. */
|
|
2895
2989
|
const char *scr_dyn_specific_type(const ScrDyn *v, char *buf, size_t cap);
|
|
2990
|
+
/* ERR_INVALID_ARG_TYPE with the runtime-rendered Received tail (the
|
|
2991
|
+
* error.argTypeThrow libCall). Borrows all three; always throws. */
|
|
2992
|
+
void scr_throw_arg_type(const ScrStr *argname, const ScrStr *expected, const ScrDyn *got);
|
|
2896
2993
|
void scr_dyn_arg_type_fail(const char *argname, const char *expected, const ScrDyn *got);
|
|
2897
2994
|
/* Listener-closure builders for the handle dispatchers' .on(...) paths:
|
|
2898
2995
|
* a runtime-built ScrClosure whose capture is the boxed dyn listener and
|
|
@@ -3681,6 +3778,13 @@ ScrJsval *scr_jsval_call_method(ScrJsval *o, const ScrStr *name, int argc, ScrJs
|
|
|
3681
3778
|
* anything else calls with this = o (non-callables throw in the engine). */
|
|
3682
3779
|
ScrJsval *scr_jsval_opt_call_method(ScrJsval *o, const ScrStr *name, int argc, ScrJsval **argv);
|
|
3683
3780
|
ScrJsval *scr_jsval_call(ScrJsval *f, int argc, ScrJsval **argv);
|
|
3781
|
+
/* Spread application on an island callee — `f(...pre, ...spread)` through
|
|
3782
|
+
* the prelude helper's REAL spread syntax (iterator protocols are the
|
|
3783
|
+
* engine's own; the guards front-run V8's exact spread-call TypeError
|
|
3784
|
+
* texts). `pre` is the engine array of leading fixed arguments; `what` the
|
|
3785
|
+
* spread expression's source spelling (the nullish text spells it).
|
|
3786
|
+
* Borrows everything; +1 out, or NULL with the exception bridged. */
|
|
3787
|
+
ScrJsval *scr_jsval_call_spread(ScrJsval *f, ScrJsval *pre, ScrJsval *spread, const ScrStr *what);
|
|
3684
3788
|
/* `new X(...)` on an island callee (jsOp construct) — JS_CallConstructor.
|
|
3685
3789
|
* Borrows everything; +1 out, or NULL with the exception bridged. */
|
|
3686
3790
|
ScrJsval *scr_jsval_construct(ScrJsval *f, int argc, ScrJsval **argv);
|
|
@@ -3765,6 +3869,16 @@ ScrPromise *scr_jsval_bridge_promise(ScrJsval *v, int payload);
|
|
|
3765
3869
|
* marshaled strings) or an array from elements. Borrow argv; +1 out.
|
|
3766
3870
|
* Cannot fail (allocation failure aborts, like every runtime OOM). */
|
|
3767
3871
|
ScrJsval *scr_jsval_obj_lit(int npairs, ScrJsval **kv);
|
|
3872
|
+
/* Getter completion for an island literal: defines `key` on `obj` as an
|
|
3873
|
+
* engine getter invoking `fn`; answers the object retained (+1). */
|
|
3874
|
+
ScrJsval *scr_jsval_define_getter(ScrJsval *obj, ScrJsval *key, ScrJsval *fn);
|
|
3875
|
+
/* The engine TemplateStringsArray for an island tag call: n cooked then n
|
|
3876
|
+
* raw strings; the result array carries `.raw` (+1). */
|
|
3877
|
+
ScrJsval *scr_jsval_tpl_strings(int n, ScrJsval **kv);
|
|
3878
|
+
/* Spread completion for an island literal: engine CopyDataProperties of
|
|
3879
|
+
* `src` onto `obj`; answers the target (+1), NULL + pending on a getter
|
|
3880
|
+
* throw. */
|
|
3881
|
+
ScrJsval *scr_jsval_obj_spread(ScrJsval *obj, ScrJsval *src);
|
|
3768
3882
|
ScrJsval *scr_jsval_arr_lit(int n, ScrJsval **elems);
|
|
3769
3883
|
|
|
3770
3884
|
/* Marshal out (island → static): validated, STRICT extraction — a
|
|
@@ -3818,6 +3932,12 @@ void scr_jsval_cast_fail(ScrJsval *v, const ScrStr *target);
|
|
|
3818
3932
|
*/
|
|
3819
3933
|
size_t scr_f64_to_str(double x, char *buf);
|
|
3820
3934
|
|
|
3935
|
+
/* The Ryū digit core (scr_number.c), shared with the Intl en-US number
|
|
3936
|
+
* formatter: the shortest round-tripping digits of a POSITIVE finite
|
|
3937
|
+
* double — value = 0.digits × 10^n, no trailing zeros, NUL-terminated.
|
|
3938
|
+
* Returns k, the digit count (≤ 17). */
|
|
3939
|
+
int scr_f64_digits(double x, char digits[18], int *n_out);
|
|
3940
|
+
|
|
3821
3941
|
/* ToString for template literals / string coercion. Returns +1. */
|
|
3822
3942
|
ScrStr *scr_f64_to_scrstr(double x);
|
|
3823
3943
|
ScrStr *scr_bool_to_scrstr(bool b); /* interned "true"/"false" */
|
|
@@ -3849,6 +3969,18 @@ bool scr_num_is_safe_integer(double x);
|
|
|
3849
3969
|
ScrStr *scr_num_to_exponential(double x);
|
|
3850
3970
|
ScrStr *scr_num_to_fixed0(double x);
|
|
3851
3971
|
|
|
3972
|
+
/* Object.is over two numbers — the spec's SameValue on doubles: NaN
|
|
3973
|
+
* equals NaN, +0 differs from -0, everything else is ==. Never throws. */
|
|
3974
|
+
bool scr_num_same_value(double a, double b);
|
|
3975
|
+
|
|
3976
|
+
/* Intl.NumberFormat("en-US").format(x) / x.toLocaleString("en-US") with
|
|
3977
|
+
* default options: decimal notation, 0–3 fraction digits rounded half-up
|
|
3978
|
+
* on the shortest round-tripping decimal (ICU's rounding input — NOT
|
|
3979
|
+
* toFixed's exact-value rounding), "," grouping every three integer
|
|
3980
|
+
* digits, "∞"/"NaN" texts, "-0" for negative inputs rounding to zero.
|
|
3981
|
+
* en-US is the one embedded locale. Result +1; never throws. */
|
|
3982
|
+
ScrStr *scr_intl_num_format_en_us(double x);
|
|
3983
|
+
|
|
3852
3984
|
/* ── Date, the composed slice (scr_lib.c) ─────────────────────────────
|
|
3853
3985
|
* Date values have no representation; the runtime surface is exactly
|
|
3854
3986
|
* Date.now() and toISOString over a millisecond time value. */
|
|
@@ -4003,6 +4135,14 @@ typedef enum ScrDataViewGet {
|
|
|
4003
4135
|
} ScrDataViewGet;
|
|
4004
4136
|
double scr_dataview_get(const ScrBytes *b, double byte_off, ScrDataViewGet kind, bool le);
|
|
4005
4137
|
|
|
4138
|
+
/* DataView setters (the integer/float kinds only — the BIG kinds never
|
|
4139
|
+
* lower: bigint arguments have no representation). Values coerce
|
|
4140
|
+
* JS-exactly: the integer kinds by modular truncation (ToUint32's residue
|
|
4141
|
+
* — the narrower widths store its low bytes, the same 2^width residue),
|
|
4142
|
+
* F32 by double→float round-to-nearest-even. Offsets go through ToIndex
|
|
4143
|
+
* with the getters' one RangeError. */
|
|
4144
|
+
void scr_dataview_set(ScrBytes *b, double byte_off, double value, ScrDataViewGet kind, bool le);
|
|
4145
|
+
|
|
4006
4146
|
/* Element read/write. Any invalid index — negative, fractional, NaN, or
|
|
4007
4147
|
* out of bounds — TRAPS like the array runtime (SEMANTICS.md documents
|
|
4008
4148
|
* the divergence from JS's undefined-read/ignored-write). Writes coerce
|
|
@@ -4073,6 +4213,32 @@ bool scr_bytes_is_encoding(const ScrStr *s);
|
|
|
4073
4213
|
bool scr_bytes_equals(const ScrBytes *a, const ScrBytes *b);
|
|
4074
4214
|
double scr_bytes_compare(const ScrBytes *src, const ScrBytes *target, double nargs,
|
|
4075
4215
|
double ts, double te, double ss, double se);
|
|
4216
|
+
/* Node's validateOffset ladder (buffer.js): non-integers (±Infinity and
|
|
4217
|
+
* NaN included) throw the 'an integer' ERR_OUT_OF_RANGE RangeError, the
|
|
4218
|
+
* rest the '>= 0 && <= max' render; max < 0 drops the upper bound.
|
|
4219
|
+
* Returns false after arming the pending throw. */
|
|
4220
|
+
bool scr_bytes_validate_off(const char *name, double value, double max);
|
|
4221
|
+
/* The checked-dynamic compare/equals validators (scr_bytes_io.c): Node's
|
|
4222
|
+
* argument ladder over DOM-boxed arguments — a non-bytes value throws
|
|
4223
|
+
* ERR_INVALID_ARG_TYPE with the API's own argument name ("buf1"/"buf2",
|
|
4224
|
+
* "otherBuffer", "target"), non-number offsets ERR_INVALID_ARG_TYPE
|
|
4225
|
+
* "of type number", out-of-range numbers the validateOffset RangeError;
|
|
4226
|
+
* an undefined offset takes its Node default. All arguments BORROWED. */
|
|
4227
|
+
double scr_buffer_compare_chk(const ScrDyn *a, const ScrDyn *b);
|
|
4228
|
+
bool scr_bytes_equals_chk(const ScrBytes *recv, const ScrDyn *other);
|
|
4229
|
+
double scr_bytes_compare_chk(const ScrBytes *src, const ScrDyn *target,
|
|
4230
|
+
const ScrDyn *ts, const ScrDyn *te,
|
|
4231
|
+
const ScrDyn *ss, const ScrDyn *se);
|
|
4232
|
+
/* new Buffer(number, encoding)'s string-arm type error (always throws;
|
|
4233
|
+
* borrowed). */
|
|
4234
|
+
ScrBytes *scr_buffer_new_string_fail(const ScrDyn *got);
|
|
4235
|
+
/* fs._toUnixTimestamp over a DOM time value: numeric strings and finite
|
|
4236
|
+
* numbers coerce (negatives answer now/1000), the rest throw Node's
|
|
4237
|
+
* ERR_INVALID_ARG_TYPE. Borrowed. */
|
|
4238
|
+
double scr_fs_to_unix_timestamp(const ScrDyn *t);
|
|
4239
|
+
/* The checked-dynamic max-listeners ladders (scr_events_emitter.c). */
|
|
4240
|
+
ScrEmitter *scr_emitter_set_max_chk(ScrEmitter *em, const ScrDyn *n);
|
|
4241
|
+
void scr_emitter_set_default_max_chk(const ScrDyn *n, const ScrStr *name);
|
|
4076
4242
|
double scr_bytes_index_of(const ScrBytes *b, const ScrBytes *needle, double off, double align, bool fwd);
|
|
4077
4243
|
double scr_bytes_index_of_num(const ScrBytes *b, double v, double off, bool fwd);
|
|
4078
4244
|
ScrBytes *scr_bytes_fill(ScrBytes *b, const ScrBytes *pattern, double nargs, double offset, double end);
|
package/src/scr_stream.c
CHANGED
|
@@ -683,7 +683,9 @@ static void *scr_stream_read_n(ScrStream *s, double size) {
|
|
|
683
683
|
st->r.hwm = h;
|
|
684
684
|
}
|
|
685
685
|
}
|
|
686
|
-
|
|
686
|
+
/* Node's read(): `if (n !== 0) state.emittedReadable = false` — the
|
|
687
|
+
* absent form is NaN there, which also clears; only read(0) keeps it. */
|
|
688
|
+
if (absent || n != 0) st->r.emitted_readable = false;
|
|
687
689
|
if (!absent && n == 0 && st->r.need_readable &&
|
|
688
690
|
(st->r.length >= st->r.hwm || st->r.ended)) {
|
|
689
691
|
if (st->r.length == 0 && st->r.ended) scr_stream_end_readable(s);
|
|
@@ -2148,6 +2150,49 @@ ScrStream *scr_stream_pipeline(double n_d, ScrStream **streams /*borrowed*/,
|
|
|
2148
2150
|
return scr_stream_retain(streams[n - 1]);
|
|
2149
2151
|
}
|
|
2150
2152
|
|
|
2153
|
+
/* ── node:stream/promises ─────────────────────────────────────────────
|
|
2154
|
+
* The promise forms ride the callback machinery above with a settling
|
|
2155
|
+
* watcher: caps[0] boxes the pending promise; the terminal status
|
|
2156
|
+
* fulfills (NULL) or rejects (the error moves through the exception
|
|
2157
|
+
* cell, the reject-pending pattern). */
|
|
2158
|
+
|
|
2159
|
+
static void scr_sp_settle_inv(ScrClosure *cb, ScrStream *s, ScrError *err) {
|
|
2160
|
+
(void)s;
|
|
2161
|
+
ScrPromise *p = scr_box_get_ref(cb->caps[0]); /* +1 */
|
|
2162
|
+
if (err != NULL) {
|
|
2163
|
+
scr_throw_obj(scr_error_retain(err), &scr_error_retain_v, &scr_error_release_v,
|
|
2164
|
+
scr_error_trace_arg());
|
|
2165
|
+
scr_promise_reject_pending(p);
|
|
2166
|
+
} else {
|
|
2167
|
+
scr_promise_fulfill_void(p);
|
|
2168
|
+
}
|
|
2169
|
+
scr_promise_release(p);
|
|
2170
|
+
}
|
|
2171
|
+
|
|
2172
|
+
static ScrClosure *scr_sp_watcher(ScrPromise *p /*borrowed*/) {
|
|
2173
|
+
ScrClosure *w = scr_closure_new((void *)&scr_sp_settle_inv, 1);
|
|
2174
|
+
w->caps[0] = scr_box_new_obj(scr_promise_retain_v, scr_promise_release_v, scr_promise_trace_v);
|
|
2175
|
+
scr_box_set_ref(w->caps[0], scr_promise_retain(p));
|
|
2176
|
+
return w;
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
ScrPromise *scr_sp_finished(ScrStream *s) {
|
|
2180
|
+
ScrPromise *p = scr_promise_new();
|
|
2181
|
+
/* The cleanup closure is the callback form's return value; the promise
|
|
2182
|
+
* form exposes no unhook, so it drops here (the watcher stays parked —
|
|
2183
|
+
* scr_stream_finished retained it into the stream's list). */
|
|
2184
|
+
ScrClosure *cleanup = scr_stream_finished(s, scr_sp_watcher(p), &scr_sp_settle_inv);
|
|
2185
|
+
scr_closure_release(cleanup);
|
|
2186
|
+
return p;
|
|
2187
|
+
}
|
|
2188
|
+
|
|
2189
|
+
ScrPromise *scr_sp_pipeline(double n, ScrStream **streams) {
|
|
2190
|
+
ScrPromise *p = scr_promise_new();
|
|
2191
|
+
ScrStream *dst = scr_stream_pipeline(n, streams, scr_sp_watcher(p), &scr_sp_settle_inv);
|
|
2192
|
+
scr_stream_release(dst);
|
|
2193
|
+
return p;
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2151
2196
|
/* ── the readable surface ─────────────────────────────────────────────── */
|
|
2152
2197
|
|
|
2153
2198
|
bool scr_stream_push(ScrStream *s, ScrBytes *chunk) {
|
|
@@ -2664,10 +2709,12 @@ double scr_stream_prop(ScrStream *s, const char *name) {
|
|
|
2664
2709
|
* arrives outside a _read call). */
|
|
2665
2710
|
static void scr_stream_emit_readable_now(ScrStream *s) {
|
|
2666
2711
|
ScrStreamState *st = s->st;
|
|
2667
|
-
|
|
2712
|
+
/* Node's emitReadable_ clears emittedReadable AFTER the emit (a
|
|
2713
|
+
* 'readable' listener observes true) and only when it really fired. */
|
|
2668
2714
|
if (!st->destroyed && !st->errored && (st->r.length > 0 || st->r.ended)) {
|
|
2669
2715
|
scr_stream_emit0(s, "readable");
|
|
2670
2716
|
if (scr_exc_pending()) return;
|
|
2717
|
+
st->r.emitted_readable = false;
|
|
2671
2718
|
}
|
|
2672
2719
|
st->r.need_readable = st->r.flowing != 1 && !st->r.ended &&
|
|
2673
2720
|
st->r.length <= st->r.hwm;
|