@scriptc/runtime 0.0.4 → 0.0.5
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 +6 -12
- package/src/scr_assert.c +1 -2
- package/src/scr_bytes.c +3 -6
- package/src/scr_bytes_io.c +1 -2
- package/src/scr_closure.c +1 -2
- package/src/scr_console.c +5 -0
- package/src/scr_cycle.c +1 -2
- package/src/scr_error.c +2 -4
- package/src/scr_events_emitter.c +1 -2
- package/src/scr_exception.c +87 -2
- package/src/scr_inspect.c +1 -2
- package/src/scr_json.c +11 -20
- package/src/scr_lib.c +50 -66
- package/src/scr_library.c +222 -0
- package/src/scr_map.c +2 -4
- package/src/scr_path.c +4 -8
- package/src/scr_regex.c +16 -25
- package/src/scr_runtime.h +75 -0
- package/src/scr_string.c +2 -4
- package/src/scr_symbol.c +2 -3
- package/src/scr_url.c +9 -16
- package/src/scr_url_params.c +6 -12
- package/src/scr_zlib.c +1 -2
package/package.json
CHANGED
package/src/scr_array.c
CHANGED
|
@@ -13,8 +13,7 @@ long scr_arr_live_count(void) { return scr_live_arrays; }
|
|
|
13
13
|
#endif
|
|
14
14
|
|
|
15
15
|
static void scr_arr_oom(void) {
|
|
16
|
-
|
|
17
|
-
abort();
|
|
16
|
+
scr_trap("scriptc: out of memory\n");
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
/* JS would return undefined for an OOB read and create holes for a far OOB
|
|
@@ -23,10 +22,8 @@ static void scr_arr_oom(void) {
|
|
|
23
22
|
static void scr_arr_trap_oob(double i, size_t len) {
|
|
24
23
|
char buf[32];
|
|
25
24
|
scr_f64_to_str(i, buf);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
buf, len);
|
|
29
|
-
abort();
|
|
25
|
+
scr_trap_fmt("scriptc: RangeError: array index %s out of bounds (length %zu)\n",
|
|
26
|
+
buf, len);
|
|
30
27
|
}
|
|
31
28
|
|
|
32
29
|
/* Validate i as an element index. limit is a->len for reads, a->len + 1 for
|
|
@@ -264,8 +261,7 @@ double scr_arr_push_ref(ScrArr *a, void *v) {
|
|
|
264
261
|
|
|
265
262
|
static uint64_t scr_arr_pop_slot(ScrArr *a) {
|
|
266
263
|
if (a->len == 0) {
|
|
267
|
-
|
|
268
|
-
abort();
|
|
264
|
+
scr_trap("scriptc: RangeError: pop() on an empty array\n");
|
|
269
265
|
}
|
|
270
266
|
return a->data[--a->len];
|
|
271
267
|
}
|
|
@@ -283,8 +279,7 @@ void *scr_arr_pop_ref(ScrArr *a) { return scr_slot_to_ptr(scr_arr_pop_slot(a));
|
|
|
283
279
|
* ownership moves out to the caller (no retain). */
|
|
284
280
|
static uint64_t scr_arr_shift_slot(ScrArr *a) {
|
|
285
281
|
if (a->len == 0) {
|
|
286
|
-
|
|
287
|
-
abort();
|
|
282
|
+
scr_trap("scriptc: internal error: shift() on an empty array\n");
|
|
288
283
|
}
|
|
289
284
|
uint64_t s = a->data[0];
|
|
290
285
|
a->len--;
|
|
@@ -456,8 +451,7 @@ ScrStr *scr_arr_join(ScrArr *a, ScrStr *sep) {
|
|
|
456
451
|
case SCR_ELEM_BYTES:
|
|
457
452
|
case SCR_ELEM_REF:
|
|
458
453
|
/* The compiler rejects join on ref-element arrays (SC1090). */
|
|
459
|
-
|
|
460
|
-
abort();
|
|
454
|
+
scr_trap("scriptc: internal error: join on a ref-element array\n");
|
|
461
455
|
}
|
|
462
456
|
}
|
|
463
457
|
ScrStr *out = scr_str_new(buf, len);
|
package/src/scr_assert.c
CHANGED
package/src/scr_bytes.c
CHANGED
|
@@ -17,8 +17,7 @@ long scr_bytes_live_count(void) { return scr_live_bytes; }
|
|
|
17
17
|
#endif
|
|
18
18
|
|
|
19
19
|
static void scr_bytes_oom(void) {
|
|
20
|
-
|
|
21
|
-
abort();
|
|
20
|
+
scr_trap("scriptc: out of memory\n");
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
size_t scr_bytes_elem_size(ScrBytesElem elem) {
|
|
@@ -98,10 +97,8 @@ static size_t scr_bytes_check_index(const ScrBytes *b, double i) {
|
|
|
98
97
|
if (!(i >= 0) || i != trunc(i) || i >= (double)b->len) {
|
|
99
98
|
char buf[32];
|
|
100
99
|
scr_f64_to_str(i, buf);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
buf, b->len);
|
|
104
|
-
abort();
|
|
100
|
+
scr_trap_fmt("scriptc: RangeError: typed array index %s out of bounds (length %zu)\n",
|
|
101
|
+
buf, b->len);
|
|
105
102
|
}
|
|
106
103
|
return (size_t)i;
|
|
107
104
|
}
|
package/src/scr_bytes_io.c
CHANGED
package/src/scr_closure.c
CHANGED
|
@@ -146,8 +146,7 @@ void *scr_box_get_ref(ScrBox *b) {
|
|
|
146
146
|
case SCR_BOX_OBJ:
|
|
147
147
|
return b->obj_retain(p);
|
|
148
148
|
default:
|
|
149
|
-
|
|
150
|
-
abort();
|
|
149
|
+
scr_trap("scriptc: internal error: box_get_ref on a scalar box\n");
|
|
151
150
|
}
|
|
152
151
|
}
|
|
153
152
|
|
package/src/scr_console.c
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
static long scr_abandoned_fibers = 0;
|
|
15
15
|
void scr_note_abandoned_fibers(long n) { scr_abandoned_fibers = n; }
|
|
16
16
|
|
|
17
|
+
#ifndef SCR_LIB
|
|
17
18
|
#ifdef SCR_RC_AUDIT
|
|
18
19
|
extern long scr_str_live_count(void); /* scr_string.c */
|
|
19
20
|
extern long scr_arr_live_count(void); /* scr_array.c */
|
|
@@ -96,6 +97,10 @@ void scr_init(void) {
|
|
|
96
97
|
#endif
|
|
97
98
|
atexit(scr_collect_cycles_at_exit);
|
|
98
99
|
}
|
|
100
|
+
#endif /* !SCR_LIB — a library artifact never touches host stdio modes/buffering and
|
|
101
|
+
* registers no atexit handlers: scr_init and its exit hooks (the
|
|
102
|
+
* audit's _Exit(99) included) are executable-lane machinery; the
|
|
103
|
+
* library session reset lives in scr_library.c. */
|
|
99
104
|
|
|
100
105
|
/* ONE formatter for both console streams — console.error/warn print
|
|
101
106
|
* byte-identically to console.log in Node (same inspect rendering), only
|
package/src/scr_cycle.c
CHANGED
|
@@ -39,8 +39,7 @@
|
|
|
39
39
|
#define SCR_RC(obj) (*(size_t *)(obj))
|
|
40
40
|
|
|
41
41
|
static void scr_cyc_oom(void) {
|
|
42
|
-
|
|
43
|
-
abort();
|
|
42
|
+
scr_trap("scriptc: out of memory\n");
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
void *scr_cyc_alloc(size_t size, ScrTraceFn trace, ScrCycFreeFn free_fn) {
|
package/src/scr_error.c
CHANGED
|
@@ -14,8 +14,7 @@
|
|
|
14
14
|
#include <stdlib.h>
|
|
15
15
|
|
|
16
16
|
static void scr_error_oom(void) {
|
|
17
|
-
|
|
18
|
-
abort();
|
|
17
|
+
scr_trap("scriptc: out of memory\n");
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
static bool scr_error_traced = false;
|
|
@@ -247,8 +246,7 @@ void scr_undef_global_read(ScrStr *name) {
|
|
|
247
246
|
size_t len = name->len + sizeof suffix - 1;
|
|
248
247
|
char *msg = malloc(len + 1);
|
|
249
248
|
if (!msg) {
|
|
250
|
-
|
|
251
|
-
abort();
|
|
249
|
+
scr_trap("scriptc: out of memory\n");
|
|
252
250
|
}
|
|
253
251
|
memcpy(msg, name->data, name->len);
|
|
254
252
|
memcpy(msg + name->len, suffix, sizeof suffix);
|
package/src/scr_events_emitter.c
CHANGED
package/src/scr_exception.c
CHANGED
|
@@ -13,6 +13,28 @@
|
|
|
13
13
|
#include <stdio.h>
|
|
14
14
|
#include <stdlib.h>
|
|
15
15
|
|
|
16
|
+
#ifndef SCR_LIB
|
|
17
|
+
/* The trap funnel's EXECUTABLE expansion: exactly the historical
|
|
18
|
+
* fputs/vfprintf-to-stderr + abort every trap site used to open-code — the
|
|
19
|
+
* default lane's bytes and behavior are unchanged by construction. Library
|
|
20
|
+
* builds (-DSCR_LIB) get the sink-routing definitions from scr_library.c
|
|
21
|
+
* instead; this pair compiles out there. Lives HERE (the failure-channel
|
|
22
|
+
* unit, present in every link including the runtime's own unit-test
|
|
23
|
+
* subsets) rather than in the console unit. */
|
|
24
|
+
_Noreturn void scr_trap(const char *msg) {
|
|
25
|
+
fputs(msg, stderr);
|
|
26
|
+
abort();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
_Noreturn void scr_trap_fmt(const char *fmt, ...) {
|
|
30
|
+
va_list ap;
|
|
31
|
+
va_start(ap, fmt);
|
|
32
|
+
vfprintf(stderr, fmt, ap);
|
|
33
|
+
va_end(ap);
|
|
34
|
+
abort();
|
|
35
|
+
}
|
|
36
|
+
#endif /* !SCR_LIB */
|
|
37
|
+
|
|
16
38
|
static ScrExcCell scr_main_exc; /* fiber zero (the main stack) */
|
|
17
39
|
static ScrExcCell *scr_cur = &scr_main_exc;
|
|
18
40
|
|
|
@@ -60,8 +82,7 @@ void scr_exc_clear(void) { scr_exc_reset(); }
|
|
|
60
82
|
ScrCaught *scr_exc_take(void) {
|
|
61
83
|
ScrCaught *c = calloc(1, sizeof *c);
|
|
62
84
|
if (!c) {
|
|
63
|
-
|
|
64
|
-
abort();
|
|
85
|
+
scr_trap("scriptc: out of memory\n");
|
|
65
86
|
}
|
|
66
87
|
c->rc = 1;
|
|
67
88
|
c->kind = scr_exc_kind;
|
|
@@ -154,6 +175,70 @@ ScrStr *scr_caught_to_string(const ScrCaught *c) {
|
|
|
154
175
|
return scr_str_new("", 0);
|
|
155
176
|
}
|
|
156
177
|
|
|
178
|
+
#ifdef SCR_LIB
|
|
179
|
+
/* An exception that escaped user code into a generated entry wrapper: the
|
|
180
|
+
* host contract is that declared entries do not throw, so an escape is a
|
|
181
|
+
* contract-shaped failure exactly like a trap. Render the same "Uncaught
|
|
182
|
+
* ..." first line the executable epilogue prints (scr_exc_print_uncaught's
|
|
183
|
+
* arms, buffer-writing), release the payload, and route the text through
|
|
184
|
+
* the trap funnel — one failure channel at the boundary. */
|
|
185
|
+
void scr_library_check_exc(void) {
|
|
186
|
+
if (!scr_exc_pending()) return;
|
|
187
|
+
static char buf[1024]; /* the message is copied out before the payload dies */
|
|
188
|
+
size_t n = 0;
|
|
189
|
+
const char prefix[] = "Uncaught ";
|
|
190
|
+
memcpy(buf, prefix, sizeof prefix - 1);
|
|
191
|
+
n = sizeof prefix - 1;
|
|
192
|
+
const size_t cap = sizeof buf - 2; /* room for '\n' + NUL */
|
|
193
|
+
switch (scr_exc_kind) {
|
|
194
|
+
case SCR_EXC_F64:
|
|
195
|
+
n += scr_f64_to_str(scr_exc_f64, buf + n);
|
|
196
|
+
break;
|
|
197
|
+
case SCR_EXC_BOOL: {
|
|
198
|
+
const char *b = scr_exc_bool ? "true" : "false";
|
|
199
|
+
size_t bl = strlen(b);
|
|
200
|
+
memcpy(buf + n, b, bl);
|
|
201
|
+
n += bl;
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
case SCR_EXC_STR: {
|
|
205
|
+
const ScrStr *s = (const ScrStr *)scr_exc_payload;
|
|
206
|
+
size_t take = s->len > cap - n ? cap - n : s->len;
|
|
207
|
+
memcpy(buf + n, s->data, take);
|
|
208
|
+
n += take;
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
case SCR_EXC_OBJ:
|
|
212
|
+
if (scr_error_is(scr_exc_payload)) {
|
|
213
|
+
ScrStr *s = scr_error_to_string((ScrError *)scr_exc_payload);
|
|
214
|
+
size_t take = s->len > cap - n ? cap - n : s->len;
|
|
215
|
+
memcpy(buf + n, s->data, take);
|
|
216
|
+
n += take;
|
|
217
|
+
scr_str_release(s);
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
/* fall through: non-Error hierarchy objects render like other refs */
|
|
221
|
+
case SCR_EXC_REF: {
|
|
222
|
+
const char obj[] = "[object]";
|
|
223
|
+
memcpy(buf + n, obj, sizeof obj - 1);
|
|
224
|
+
n += sizeof obj - 1;
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
case SCR_EXC_NONE:
|
|
228
|
+
case SCR_EXC_GENRET: { /* unreachable through the pending() gate */
|
|
229
|
+
const char none[] = "(no exception)";
|
|
230
|
+
memcpy(buf + n, none, sizeof none - 1);
|
|
231
|
+
n += sizeof none - 1;
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
buf[n++] = '\n';
|
|
236
|
+
buf[n] = '\0';
|
|
237
|
+
scr_exc_reset(); /* the payload is released before the funnel poisons */
|
|
238
|
+
scr_trap(buf);
|
|
239
|
+
}
|
|
240
|
+
#endif /* SCR_LIB */
|
|
241
|
+
|
|
157
242
|
void scr_throw_f64(double v) {
|
|
158
243
|
scr_exc_reset();
|
|
159
244
|
scr_exc_kind = SCR_EXC_F64;
|
package/src/scr_inspect.c
CHANGED
package/src/scr_json.c
CHANGED
|
@@ -36,8 +36,7 @@ long scr_dyn_live_count(void) { return scr_live_dyns; }
|
|
|
36
36
|
#endif
|
|
37
37
|
|
|
38
38
|
static void scr_json_oom(void) {
|
|
39
|
-
|
|
40
|
-
abort();
|
|
39
|
+
scr_trap("scriptc: out of memory\n");
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
/* ── output buffer ─────────────────────────────────────────────────────
|
|
@@ -421,8 +420,7 @@ void scr_dyn_handle_install(ScrDynHandleTag tag, const ScrDynHandleOps *ops) {
|
|
|
421
420
|
static const ScrDynHandleOps *scr_dyn_handle_ops(ScrDynHandleTag tag) {
|
|
422
421
|
const ScrDynHandleOps *ops = scr_dynh_ops[tag];
|
|
423
422
|
if (!ops) {
|
|
424
|
-
|
|
425
|
-
abort();
|
|
423
|
+
scr_trap("scriptc: internal error: dyn handle ops not installed\n");
|
|
426
424
|
}
|
|
427
425
|
return ops;
|
|
428
426
|
}
|
|
@@ -501,8 +499,7 @@ static ScrDynThisEnt *scr_dyn_this_grow(void) {
|
|
|
501
499
|
size_t cap = scr_dyn_this_cap ? scr_dyn_this_cap * 2 : 8;
|
|
502
500
|
ScrDynThisEnt *s = realloc(scr_dyn_this_stack, cap * sizeof *s);
|
|
503
501
|
if (!s) {
|
|
504
|
-
|
|
505
|
-
abort();
|
|
502
|
+
scr_trap("scriptc: out of memory\n");
|
|
506
503
|
}
|
|
507
504
|
scr_dyn_this_stack = s;
|
|
508
505
|
scr_dyn_this_cap = cap;
|
|
@@ -526,8 +523,7 @@ void scr_dyn_this_push_dyn(const ScrDyn *v) {
|
|
|
526
523
|
|
|
527
524
|
void scr_dyn_this_pop(void) {
|
|
528
525
|
if (scr_dyn_this_n == 0) {
|
|
529
|
-
|
|
530
|
-
abort();
|
|
526
|
+
scr_trap("scriptc: internal error: receiver stack underflow\n");
|
|
531
527
|
}
|
|
532
528
|
ScrDynThisEnt *e = &scr_dyn_this_stack[--scr_dyn_this_n];
|
|
533
529
|
if (e->dv) scr_dyn_release(e->dv);
|
|
@@ -763,13 +759,12 @@ ScrDyn *scr_dyn_from_error(const ScrError *e) {
|
|
|
763
759
|
scr_errdyn_cap = scr_errdyn_cap ? scr_errdyn_cap * 2 : 8;
|
|
764
760
|
scr_errdyn_cache = realloc(scr_errdyn_cache, scr_errdyn_cap * sizeof *scr_errdyn_cache);
|
|
765
761
|
if (!scr_errdyn_cache) {
|
|
766
|
-
|
|
767
|
-
abort();
|
|
762
|
+
scr_trap("scriptc: out of memory\n");
|
|
768
763
|
}
|
|
769
764
|
}
|
|
770
765
|
if (!scr_errdyn_teardown_registered) {
|
|
771
766
|
scr_errdyn_teardown_registered = true;
|
|
772
|
-
|
|
767
|
+
scr_atexit(scr_errdyn_teardown);
|
|
773
768
|
}
|
|
774
769
|
scr_errdyn_cache[scr_errdyn_n].err = scr_error_retain((ScrError *)e);
|
|
775
770
|
scr_errdyn_cache[scr_errdyn_n].dyn = scr_dyn_retain(d);
|
|
@@ -824,13 +819,12 @@ void scr_errdyn_put(ScrError *e, ScrDyn *d) {
|
|
|
824
819
|
scr_errdyn_cap = scr_errdyn_cap ? scr_errdyn_cap * 2 : 8;
|
|
825
820
|
scr_errdyn_cache = realloc(scr_errdyn_cache, scr_errdyn_cap * sizeof *scr_errdyn_cache);
|
|
826
821
|
if (!scr_errdyn_cache) {
|
|
827
|
-
|
|
828
|
-
abort();
|
|
822
|
+
scr_trap("scriptc: out of memory\n");
|
|
829
823
|
}
|
|
830
824
|
}
|
|
831
825
|
if (!scr_errdyn_teardown_registered) {
|
|
832
826
|
scr_errdyn_teardown_registered = true;
|
|
833
|
-
|
|
827
|
+
scr_atexit(scr_errdyn_teardown);
|
|
834
828
|
}
|
|
835
829
|
scr_errdyn_cache[scr_errdyn_n].err = scr_error_retain(e);
|
|
836
830
|
scr_errdyn_cache[scr_errdyn_n].dyn = scr_dyn_retain(d);
|
|
@@ -1035,8 +1029,7 @@ void scr_jb_put_dyn(ScrJsonBuf *b, const ScrDyn *d) {
|
|
|
1035
1029
|
return;
|
|
1036
1030
|
}
|
|
1037
1031
|
}
|
|
1038
|
-
|
|
1039
|
-
abort();
|
|
1032
|
+
scr_trap("scriptc: internal error: invalid dyn kind\n");
|
|
1040
1033
|
}
|
|
1041
1034
|
|
|
1042
1035
|
/* ── dynCheck failure path ─────────────────────────────────────────────── */
|
|
@@ -1750,8 +1743,7 @@ static ScrDyn *scr_sc_clone(const ScrDyn *v, const ScrScParent *up) {
|
|
|
1750
1743
|
size_t len = what->len + sizeof suffix - 1;
|
|
1751
1744
|
char *msg = malloc(len + 1);
|
|
1752
1745
|
if (!msg) {
|
|
1753
|
-
|
|
1754
|
-
abort();
|
|
1746
|
+
scr_trap("scriptc: out of memory\n");
|
|
1755
1747
|
}
|
|
1756
1748
|
memcpy(msg, what->data, what->len);
|
|
1757
1749
|
memcpy(msg + what->len, suffix, sizeof suffix);
|
|
@@ -1860,8 +1852,7 @@ static ScrDyn *scr_dyn_objwalk(const ScrDyn *v, ScrObjWalk mode) {
|
|
|
1860
1852
|
bool *is_index = malloc(n ? n * sizeof *is_index : 1);
|
|
1861
1853
|
double *idx = malloc(n ? n * sizeof *idx : 1);
|
|
1862
1854
|
if (!is_index || !idx) {
|
|
1863
|
-
|
|
1864
|
-
abort();
|
|
1855
|
+
scr_trap("scriptc: out of memory\n");
|
|
1865
1856
|
}
|
|
1866
1857
|
size_t index_count = 0;
|
|
1867
1858
|
for (size_t i = 0; i < n; i++) {
|