@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scriptc/runtime",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "scriptc native runtime — C sources, compiled into every scriptc binary",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://scriptc.dev",
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
- fputs("scriptc: out of memory\n", stderr);
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
- fprintf(stderr,
27
- "scriptc: RangeError: array index %s out of bounds (length %zu)\n",
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
- fputs("scriptc: RangeError: pop() on an empty array\n", stderr);
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
- fputs("scriptc: internal error: shift() on an empty array\n", stderr);
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
- fputs("scriptc: internal error: join on a ref-element array\n", stderr);
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
@@ -32,8 +32,7 @@
32
32
  #include <string.h>
33
33
 
34
34
  static void scr_assert_oom(void) {
35
- fputs("scriptc: out of memory\n", stderr);
36
- abort();
35
+ scr_trap("scriptc: out of memory\n");
37
36
  }
38
37
 
39
38
  /* ── a tiny append-only byte buffer for message assembly ─────────────── */
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
- fputs("scriptc: out of memory\n", stderr);
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
- fprintf(stderr,
102
- "scriptc: RangeError: typed array index %s out of bounds (length %zu)\n",
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
  }
@@ -12,8 +12,7 @@
12
12
  #include <string.h>
13
13
 
14
14
  static void scr_bytes_io_oom(void) {
15
- fputs("scriptc: out of memory\n", stderr);
16
- abort();
15
+ scr_trap("scriptc: out of memory\n");
17
16
  }
18
17
 
19
18
  /* ── fs (the Buffer forms of scr_lib.c's utf8 pair) ────────────────────── */
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
- fputs("scriptc: internal error: box_get_ref on a scalar box\n", stderr);
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
- fputs("scriptc: out of memory\n", stderr);
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
- fputs("scriptc: out of memory\n", stderr);
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
- fputs("scriptc: out of memory\n", stderr);
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);
@@ -54,8 +54,7 @@
54
54
  #endif
55
55
 
56
56
  static void scr_ee_oom(void) {
57
- fputs("scriptc: out of memory\n", stderr);
58
- abort();
57
+ scr_trap("scriptc: out of memory\n");
59
58
  }
60
59
 
61
60
  /* One registered listener. Shared between the live list and emit
@@ -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
- fputs("scriptc: out of memory\n", stderr);
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
@@ -31,8 +31,7 @@
31
31
  #include <string.h>
32
32
 
33
33
  static void insp_oom(void) {
34
- fputs("scriptc: out of memory\n", stderr);
35
- abort();
34
+ scr_trap("scriptc: out of memory\n");
36
35
  }
37
36
 
38
37
  /* ── a tiny append-only byte buffer ──────────────────────────────────── */
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
- fputs("scriptc: out of memory\n", stderr);
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
- fputs("scriptc: internal error: dyn handle ops not installed\n", stderr);
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
- fputs("scriptc: out of memory\n", stderr);
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
- fputs("scriptc: internal error: receiver stack underflow\n", stderr);
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
- fputs("scriptc: out of memory\n", stderr);
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
- atexit(scr_errdyn_teardown);
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
- fputs("scriptc: out of memory\n", stderr);
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
- atexit(scr_errdyn_teardown);
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
- fputs("scriptc: internal error: invalid dyn kind\n", stderr);
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
- fputs("scriptc: out of memory\n", stderr);
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
- fputs("scriptc: out of memory\n", stderr);
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++) {