@scriptc/runtime 0.0.25 → 0.0.27
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 +1 -1
- package/src/scr_assert.c +4 -4
- package/src/scr_async.c +235 -6
- package/src/scr_bytes.c +1 -1
- package/src/scr_child.c +2 -2
- package/src/scr_closure.c +2 -2
- package/src/scr_console.c +1 -1
- package/src/scr_cycle.c +14 -14
- package/src/scr_error.c +3 -3
- package/src/scr_events.c +48 -2
- package/src/scr_events_emitter.c +7 -7
- package/src/scr_exception.c +22 -12
- package/src/scr_http.c +1 -0
- package/src/scr_inspect.c +10 -10
- package/src/scr_island.c +8 -4
- package/src/scr_json.c +14 -14
- package/src/scr_lib.c +104 -28
- package/src/scr_library.c +33 -13
- package/src/scr_map.c +1 -1
- package/src/scr_musl.c +274 -0
- package/src/scr_net.c +118 -3
- package/src/scr_object.c +1 -1
- package/src/scr_regex.c +2 -2
- package/src/scr_runtime.h +82 -25
- package/src/scr_string.c +4 -4
- package/src/scr_symbol.c +1 -1
- package/src/scr_tls.c +22 -0
- package/src/scr_union.c +1 -1
- package/vendor/README.md +8 -0
package/src/scr_net.c
CHANGED
|
@@ -389,6 +389,16 @@ struct ScrNetServer {
|
|
|
389
389
|
bool closing; /* close() called; 'close' fires when conns drain */
|
|
390
390
|
bool close_emitted; /* settled: off the registry, listeners dropped */
|
|
391
391
|
bool emit_listening;
|
|
392
|
+
/* The writable http.Server timeout property values. Kept on the shared
|
|
393
|
+
* server handle because http/https servers retain that handle identity;
|
|
394
|
+
* plain net servers never expose these fields through the static type
|
|
395
|
+
* surface. Indices match lower-server.ts's selector ABI. */
|
|
396
|
+
double http_timeouts[5];
|
|
397
|
+
/* A dynamic write may store any JS value on these ordinary writable
|
|
398
|
+
* properties. Numeric writes stay in http_timeouts; every other value
|
|
399
|
+
* is retained here so dynamic reads preserve kind and identity. */
|
|
400
|
+
ScrDyn *http_timeout_dyn[5];
|
|
401
|
+
bool http_timeout_surface; /* true only for HTTP/1 and HTTPS servers */
|
|
392
402
|
bool defer_conn; /* TLS: 'connection' fires post-handshake, not at accept */
|
|
393
403
|
bool bound_v6; /* the bound family (address()'s 'IPv6'/'IPv4' split) */
|
|
394
404
|
ScrStr *bound_host; /* the explicit bind host (NULL = the host-less any:
|
|
@@ -556,6 +566,7 @@ void scr_net_server_release(ScrNetServer *s) {
|
|
|
556
566
|
scr_net_ls_drop(&s->close_ls);
|
|
557
567
|
scr_net_ls_drop(&s->listening_cbs);
|
|
558
568
|
scr_closure_release(s->close_override);
|
|
569
|
+
for (size_t i = 0; i < 5; i++) scr_dyn_release(s->http_timeout_dyn[i]);
|
|
559
570
|
scr_str_release(s->bound_host);
|
|
560
571
|
scr_str_release(s->pending_err);
|
|
561
572
|
if (s->fd >= 0) scr_net_close_fd_raw(s->fd);
|
|
@@ -1200,6 +1211,11 @@ static ScrNetServer *scr_net_server_new(void) {
|
|
|
1200
1211
|
s->kind = SCR_NET_K_SERVER;
|
|
1201
1212
|
s->rc = 1;
|
|
1202
1213
|
s->fd = -1;
|
|
1214
|
+
s->http_timeouts[0] = 0; /* timeout */
|
|
1215
|
+
s->http_timeouts[1] = 5000; /* keepAliveTimeout */
|
|
1216
|
+
s->http_timeouts[2] = 60000; /* headersTimeout */
|
|
1217
|
+
s->http_timeouts[3] = 300000; /* requestTimeout */
|
|
1218
|
+
s->http_timeouts[4] = 1000; /* keepAliveTimeoutBuffer */
|
|
1203
1219
|
#ifdef SCR_RC_AUDIT
|
|
1204
1220
|
scr_net_live++;
|
|
1205
1221
|
#endif
|
|
@@ -1378,6 +1394,79 @@ void scr_net_listen_opts(ScrNetServer *s, double port, ScrStr *host /*borrowed*/
|
|
|
1378
1394
|
|
|
1379
1395
|
double scr_net_server_port(ScrNetServer *s) { return (double)s->port; }
|
|
1380
1396
|
|
|
1397
|
+
double scr_net_server_timeout_get(ScrNetServer *s, double field) {
|
|
1398
|
+
static const char *const names[] = {
|
|
1399
|
+
"timeout", "keepAliveTimeout", "headersTimeout", "requestTimeout",
|
|
1400
|
+
"keepAliveTimeoutBuffer",
|
|
1401
|
+
};
|
|
1402
|
+
int i = (int)field;
|
|
1403
|
+
if (i < 0 || i >= 5) abort(); /* compiler/runtime ABI violation */
|
|
1404
|
+
if (s->http_timeout_dyn[i] != NULL) {
|
|
1405
|
+
scr_dyn_arg_type_fail(names[i], "of type number", s->http_timeout_dyn[i]);
|
|
1406
|
+
return 0; /* pending exception; typed reads validate an any-written value */
|
|
1407
|
+
}
|
|
1408
|
+
return s->http_timeouts[i];
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
void scr_net_server_timeout_set(ScrNetServer *s, double field, double value) {
|
|
1412
|
+
int i = (int)field;
|
|
1413
|
+
if (i < 0 || i >= 5) abort(); /* compiler/runtime ABI violation */
|
|
1414
|
+
scr_dyn_release(s->http_timeout_dyn[i]);
|
|
1415
|
+
s->http_timeout_dyn[i] = NULL;
|
|
1416
|
+
s->http_timeouts[i] = value;
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
void scr_net_server_enable_http_timeout_surface(ScrNetServer *s) {
|
|
1420
|
+
s->http_timeout_surface = true;
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
/* Constructor-option validation is intentionally separate from the plain
|
|
1424
|
+
* writable-property setter above. Node validates these option values as
|
|
1425
|
+
* non-negative safe integers, while later property assignments store the
|
|
1426
|
+
* number directly. */
|
|
1427
|
+
bool scr_net_server_timeout_option_check(double field, double value) {
|
|
1428
|
+
static const char *const names[] = {
|
|
1429
|
+
"timeout", "keepAliveTimeout", "headersTimeout", "requestTimeout",
|
|
1430
|
+
"keepAliveTimeoutBuffer",
|
|
1431
|
+
};
|
|
1432
|
+
int i = (int)field;
|
|
1433
|
+
if (i < 0 || i >= 5) abort(); /* compiler/runtime ABI violation */
|
|
1434
|
+
char recv[48], msg[224];
|
|
1435
|
+
if (!(isfinite(value) && trunc(value) == value)) {
|
|
1436
|
+
scr_num_received(value, recv);
|
|
1437
|
+
int len = snprintf(msg, sizeof msg,
|
|
1438
|
+
"The value of \"%s\" is out of range. It must be an integer. Received %s",
|
|
1439
|
+
names[i], recv);
|
|
1440
|
+
scr_throw_error_msg_code(SCR_ERR_RANGE, msg, (size_t)len, "ERR_OUT_OF_RANGE");
|
|
1441
|
+
return false;
|
|
1442
|
+
}
|
|
1443
|
+
if (value < 0 || value > 9007199254740991.0) {
|
|
1444
|
+
scr_num_received(value, recv);
|
|
1445
|
+
int len = snprintf(msg, sizeof msg,
|
|
1446
|
+
"The value of \"%s\" is out of range. It must be >= 0 && <= 9007199254740991. Received %s",
|
|
1447
|
+
names[i], recv);
|
|
1448
|
+
scr_throw_error_msg_code(SCR_ERR_RANGE, msg, (size_t)len, "ERR_OUT_OF_RANGE");
|
|
1449
|
+
return false;
|
|
1450
|
+
}
|
|
1451
|
+
return true;
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
void scr_net_server_timeout_option_set(ScrNetServer *s, double field, const ScrDyn *value) {
|
|
1455
|
+
int i = (int)field;
|
|
1456
|
+
if (i < 0 || i >= 5) abort(); /* compiler/runtime ABI violation */
|
|
1457
|
+
if (value->kind == SCR_DYN_UNDEF) return; /* optional field is absent */
|
|
1458
|
+
if (value->kind != SCR_DYN_NUM) {
|
|
1459
|
+
static const char *const names[] = {
|
|
1460
|
+
"timeout", "keepAliveTimeout", "headersTimeout", "requestTimeout",
|
|
1461
|
+
"keepAliveTimeoutBuffer",
|
|
1462
|
+
};
|
|
1463
|
+
scr_dyn_arg_type_fail(names[i], "of type number", value);
|
|
1464
|
+
return;
|
|
1465
|
+
}
|
|
1466
|
+
if (!scr_net_server_timeout_option_check(field, value->v.num)) return;
|
|
1467
|
+
scr_net_server_timeout_set(s, field, value->v.num);
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1381
1470
|
/* address()'s other two fields — the bound host ('::'/'0.0.0.0' for the
|
|
1382
1471
|
* host-less any, the normalized explicit host otherwise) and the family
|
|
1383
1472
|
* string. Answer the any-form defaults before listen (Node answers null
|
|
@@ -3299,13 +3388,28 @@ static ScrDyn *scr_net_dynh_srv_invoke(void *h, ScrDyn *self, const char *method
|
|
|
3299
3388
|
return NULL;
|
|
3300
3389
|
}
|
|
3301
3390
|
|
|
3391
|
+
static int scr_net_dynh_srv_timeout_field(const char *key) {
|
|
3392
|
+
if (strcmp(key, "timeout") == 0) return 0;
|
|
3393
|
+
if (strcmp(key, "keepAliveTimeout") == 0) return 1;
|
|
3394
|
+
if (strcmp(key, "headersTimeout") == 0) return 2;
|
|
3395
|
+
if (strcmp(key, "requestTimeout") == 0) return 3;
|
|
3396
|
+
if (strcmp(key, "keepAliveTimeoutBuffer") == 0) return 4;
|
|
3397
|
+
return -1;
|
|
3398
|
+
}
|
|
3399
|
+
|
|
3302
3400
|
static ScrDyn *scr_net_dynh_srv_get(void *h, const char *key, size_t key_len) {
|
|
3303
3401
|
ScrNetServer *s = (ScrNetServer *)h;
|
|
3304
3402
|
(void)key_len;
|
|
3305
3403
|
if (strcmp(key, "listening") == 0) return scr_dyn_new_bool(s->listening);
|
|
3404
|
+
int timeout_field = scr_net_dynh_srv_timeout_field(key);
|
|
3405
|
+
if (timeout_field >= 0 && s->http_timeout_surface) {
|
|
3406
|
+
if (s->http_timeout_dyn[timeout_field] != NULL) {
|
|
3407
|
+
return scr_dyn_retain(s->http_timeout_dyn[timeout_field]);
|
|
3408
|
+
}
|
|
3409
|
+
return scr_dyn_new_num(scr_net_server_timeout_get(s, (double)timeout_field));
|
|
3410
|
+
}
|
|
3306
3411
|
{
|
|
3307
|
-
static const char *const known[] = { "maxConnections", "connections", "maxHeadersCount",
|
|
3308
|
-
"timeout", "keepAliveTimeout", "headersTimeout", "requestTimeout", NULL };
|
|
3412
|
+
static const char *const known[] = { "maxConnections", "connections", "maxHeadersCount", NULL };
|
|
3309
3413
|
for (size_t i = 0; known[i]; i++) {
|
|
3310
3414
|
if (strcmp(key, known[i]) == 0) {
|
|
3311
3415
|
scr_net_dynh_srv_unsupported(key, NULL);
|
|
@@ -3317,7 +3421,18 @@ static ScrDyn *scr_net_dynh_srv_get(void *h, const char *key, size_t key_len) {
|
|
|
3317
3421
|
}
|
|
3318
3422
|
|
|
3319
3423
|
static bool scr_net_dynh_srv_set(void *h, const char *key, size_t key_len, const ScrDyn *value) {
|
|
3320
|
-
|
|
3424
|
+
ScrNetServer *s = (ScrNetServer *)h;
|
|
3425
|
+
(void)key_len;
|
|
3426
|
+
int timeout_field = scr_net_dynh_srv_timeout_field(key);
|
|
3427
|
+
if (timeout_field >= 0 && s->http_timeout_surface) {
|
|
3428
|
+
if (value->kind == SCR_DYN_NUM) {
|
|
3429
|
+
scr_net_server_timeout_set(s, (double)timeout_field, value->v.num);
|
|
3430
|
+
} else {
|
|
3431
|
+
scr_dyn_release(s->http_timeout_dyn[timeout_field]);
|
|
3432
|
+
s->http_timeout_dyn[timeout_field] = scr_dyn_retain((ScrDyn *)value);
|
|
3433
|
+
}
|
|
3434
|
+
return true;
|
|
3435
|
+
}
|
|
3321
3436
|
return false;
|
|
3322
3437
|
}
|
|
3323
3438
|
|
package/src/scr_object.c
CHANGED
|
@@ -33,7 +33,7 @@ void scr_record_key_miss(ScrStr *k) {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
#ifdef SCR_RC_AUDIT
|
|
36
|
-
static long scr_live_objects = 0;
|
|
36
|
+
static SCR_TL long scr_live_objects = 0;
|
|
37
37
|
long scr_obj_live_count(void) { return scr_live_objects; }
|
|
38
38
|
void scr_obj_alloc_note(void) { scr_live_objects++; }
|
|
39
39
|
void scr_obj_free_note(void) { scr_live_objects--; }
|
package/src/scr_regex.c
CHANGED
|
@@ -82,8 +82,8 @@ void *lre_realloc(void *opaque, void *ptr, size_t size) {
|
|
|
82
82
|
* allocation audit sees the bytecode gone).
|
|
83
83
|
*/
|
|
84
84
|
|
|
85
|
-
static ScrRegex **scr_compiled = NULL;
|
|
86
|
-
static size_t scr_compiled_len = 0, scr_compiled_cap = 0;
|
|
85
|
+
static SCR_TL ScrRegex **scr_compiled = NULL;
|
|
86
|
+
static SCR_TL size_t scr_compiled_len = 0, scr_compiled_cap = 0;
|
|
87
87
|
|
|
88
88
|
static void scr_regex_free_bytecodes(void) {
|
|
89
89
|
for (size_t i = 0; i < scr_compiled_len; i++) {
|
package/src/scr_runtime.h
CHANGED
|
@@ -15,22 +15,36 @@
|
|
|
15
15
|
#include <string.h> /* memcpy in the inline slot accessors */
|
|
16
16
|
#include <sys/types.h> /* ssize_t in the transport ops table */
|
|
17
17
|
|
|
18
|
-
/* ──
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* underneath), gmtime_r (scr_http.c's Date header; the CRT's gmtime is
|
|
23
|
-
* already per-thread), and strcasestr (scr_http.c's token scan).
|
|
24
|
-
* scr_win.c — compiled into win32-target builds only (cc.ts) —
|
|
25
|
-
* implements all of them. Declared here so every TU that calls them
|
|
26
|
-
* through scr_runtime.h compiles unchanged; POSIX hosts never see
|
|
27
|
-
* these. */
|
|
18
|
+
/* ── libc shims ─────────────────────────────────────────────────────────
|
|
19
|
+
* Win32's missing POSIX/BSD functions live in scr_win.c. Zig's musl sysroot
|
|
20
|
+
* additionally lacks arc4random_buf; scr_musl.c supplies it from Linux's
|
|
21
|
+
* getrandom syscall. Both files are selected by cc.ts only for their target. */
|
|
28
22
|
#ifdef _WIN32
|
|
29
23
|
#include <time.h> /* time_t / struct tm for the gmtime_r shim */
|
|
30
24
|
char *stpcpy(char *dst, const char *src);
|
|
31
25
|
void arc4random_buf(void *buf, size_t n);
|
|
32
26
|
struct tm *gmtime_r(const time_t *t, struct tm *out);
|
|
33
27
|
char *strcasestr(const char *hay, const char *needle);
|
|
28
|
+
#elif defined(SCR_MUSL)
|
|
29
|
+
void arc4random_buf(void *buf, size_t n);
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
/* ── thread-instanced library state ─────────────────────────────────────
|
|
33
|
+
* Archives built under the profile's abi.instance_per_thread compile every
|
|
34
|
+
* TU with -DSCR_THREAD_INSTANCES, and SCR_TL moves each unit's mutable
|
|
35
|
+
* state — and the emitted program's globals — into thread-local storage.
|
|
36
|
+
* A thread that calls the profile's init entry then owns a complete,
|
|
37
|
+
* independent instance: its own collector, result arena, panic-sink
|
|
38
|
+
* registration, poison flag, and program state. The instance's lifetime is
|
|
39
|
+
* the thread's; the one-thread-per-instance contract (an instance is never
|
|
40
|
+
* entered from two threads) is unchanged — this mode adds instances, not
|
|
41
|
+
* thread awareness. Expands to nothing everywhere else, so executable
|
|
42
|
+
* builds and classic library builds carry the exact bytes they always
|
|
43
|
+
* carried. Truly immutable tables (static const data) stay shared. */
|
|
44
|
+
#if defined(SCR_LIB) && defined(SCR_THREAD_INSTANCES)
|
|
45
|
+
#define SCR_TL _Thread_local
|
|
46
|
+
#else
|
|
47
|
+
#define SCR_TL
|
|
34
48
|
#endif
|
|
35
49
|
|
|
36
50
|
/* ── process ──────────────────────────────────────────────────────────── */
|
|
@@ -241,16 +255,22 @@ typedef struct ScrCycHdr {
|
|
|
241
255
|
size_t buf_index; /* position there (O(1) removal when rc hits 0) */
|
|
242
256
|
} ScrCycHdr;
|
|
243
257
|
|
|
244
|
-
/* This layout is an ABI, not an implementation detail
|
|
245
|
-
* inlines scr_cyc_mark_live as a raw `store i32 0
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
|
|
258
|
+
/* This layout is an ABI, not an implementation detail. The LLVM backend
|
|
259
|
+
* inlines scr_cyc_mark_live as a raw `store i32 0`: color is at obj-16 on
|
|
260
|
+
* 64-bit targets and obj-12 on wasm32. Three sites emit it —
|
|
261
|
+
* llvm/shapes.ts, llvm/classes.ts, and llvm/emitter.ts. Nothing but `color`
|
|
262
|
+
* may share those four bytes: a field placed in them is silently zeroed by
|
|
263
|
+
* every retain, which is invisible to the type system and to the C
|
|
264
|
+
* compiler. Hence the target-width assertions. */
|
|
265
|
+
#if UINTPTR_MAX == UINT64_MAX
|
|
266
|
+
_Static_assert(sizeof(ScrCycHdr) == 32, "LLVM backend expects a 32-byte cycle header");
|
|
252
267
|
_Static_assert(offsetof(ScrCycHdr, color) == 16,
|
|
253
268
|
"LLVM backend's inlined mark-live stores i32 0 at obj-16");
|
|
269
|
+
#elif UINTPTR_MAX == UINT32_MAX
|
|
270
|
+
_Static_assert(sizeof(ScrCycHdr) == 20, "LLVM backend expects a 20-byte cycle header");
|
|
271
|
+
_Static_assert(offsetof(ScrCycHdr, color) == 8,
|
|
272
|
+
"LLVM backend's inlined mark-live stores i32 0 at obj-12");
|
|
273
|
+
#endif
|
|
254
274
|
_Static_assert(sizeof(((ScrCycHdr *)0)->color) == 4,
|
|
255
275
|
"mark-live is an i32 store: color must own all four bytes");
|
|
256
276
|
_Static_assert(SCR_CYC_BLACK == 0,
|
|
@@ -443,7 +463,7 @@ enum {
|
|
|
443
463
|
SCR_ERR_DOMEX = 4, /* DOMException — ScrDomException, the wider layout */
|
|
444
464
|
};
|
|
445
465
|
|
|
446
|
-
extern ScrVt scr_error_vts[5]; /* indexed by SCR_ERR_*; main() stamps pre/post */
|
|
466
|
+
extern SCR_TL ScrVt scr_error_vts[5]; /* indexed by SCR_ERR_*; main() stamps pre/post */
|
|
447
467
|
|
|
448
468
|
struct ScrDyn; /* full declaration below (the checked-dynamic tree section) */
|
|
449
469
|
|
|
@@ -1371,8 +1391,8 @@ typedef struct ScrEmitter {
|
|
|
1371
1391
|
const char *cls; /* display name for the leak warning ("EventEmitter") */
|
|
1372
1392
|
} ScrEmitter;
|
|
1373
1393
|
|
|
1374
|
-
extern ScrVt scr_emitter_vt; /* main() stamps pre/post */
|
|
1375
|
-
extern double scr_emitter_default_max;
|
|
1394
|
+
extern SCR_TL ScrVt scr_emitter_vt; /* main() stamps pre/post */
|
|
1395
|
+
extern SCR_TL double scr_emitter_default_max;
|
|
1376
1396
|
|
|
1377
1397
|
ScrEmitter *scr_emitter_new(void); /* +1, collector-headered */
|
|
1378
1398
|
void scr_emitter_init(void *obj); /* super() into the prefix (no-op today) */
|
|
@@ -1421,9 +1441,10 @@ ScrEmitter *scr_emitter_on_via(ScrEmitter *em, ScrStr *name, ScrClosure *orig /*
|
|
|
1421
1441
|
* slots off the emit tuple and calls cb->fn behind the fixed signature
|
|
1422
1442
|
* `void (ScrClosure *, void * ×k)` — the fixed-signature adapter the
|
|
1423
1443
|
* backend provides. Such backends pass every user tuple argument
|
|
1424
|
-
* pointer-classed at the emit site
|
|
1425
|
-
*
|
|
1426
|
-
* pointers only, so the shims read every
|
|
1444
|
+
* pointer-classed at the emit site: scalar values point at call-lived
|
|
1445
|
+
* typed stack slots and reference values ride directly. The runtime's own
|
|
1446
|
+
* emits (data/error/pipe/meta) carry pointers only, so the shims read every
|
|
1447
|
+
* tuple either lane produces on 32- and 64-bit targets.
|
|
1427
1448
|
* SCR_EE_FIXED_MAX is the registry's audited arity ceiling — backends
|
|
1428
1449
|
* refuse listeners past it rather than guess. */
|
|
1429
1450
|
#define SCR_EE_FIXED_MAX 4
|
|
@@ -1973,7 +1994,7 @@ bool scr_process_kill_named(double pid, const ScrStr *signal);
|
|
|
1973
1994
|
void scr_process_exit(double code);
|
|
1974
1995
|
/* process._exiting: true once the exit sequence began (process.exit or
|
|
1975
1996
|
* the exit-listener runner set the flag). Never throws. */
|
|
1976
|
-
extern bool scr_process_in_exit;
|
|
1997
|
+
extern SCR_TL bool scr_process_in_exit;
|
|
1977
1998
|
bool scr_process_exiting(void);
|
|
1978
1999
|
/* umask(2): mask < 0 reads without setting; otherwise sets and answers
|
|
1979
2000
|
* the previous mask. Never throws. */
|
|
@@ -3548,6 +3569,28 @@ void scr_promise_release_v(void *p);
|
|
|
3548
3569
|
typedef struct ScrFiber ScrFiber;
|
|
3549
3570
|
/* Spawn + run eagerly to the first suspension; returns the promise, +1. */
|
|
3550
3571
|
ScrPromise *scr_async_spawn(void (*entry)(ScrFiber *, void *), void *argpack);
|
|
3572
|
+
/* Runtime-authored C waiters cannot themselves become LLVM switched
|
|
3573
|
+
* coroutines on wasm32. Spawn after `dependency` settles so their first
|
|
3574
|
+
* (and only) await is extraction from an already-settled promise, while
|
|
3575
|
+
* retaining the ordinary promise-job hop on every target. +1. */
|
|
3576
|
+
ScrPromise *scr_async_spawn_after(ScrPromise *dependency,
|
|
3577
|
+
void (*entry)(ScrFiber *, void *),
|
|
3578
|
+
void *argpack);
|
|
3579
|
+
|
|
3580
|
+
/* wasm32-wasi lowers async functions and generators through LLVM switched
|
|
3581
|
+
* coroutines instead of the native stack-switching implementations. The
|
|
3582
|
+
* first two adapters are emitted into the program module; the remaining
|
|
3583
|
+
* helpers let scr_async.c register, queue, and finish those coroutine
|
|
3584
|
+
* frames through the same ScrFiber scheduler. These declarations are part
|
|
3585
|
+
* of the LLVM/runtime ABI even though native targets never call them. */
|
|
3586
|
+
void scr_wasi_coro_resume(void *handle);
|
|
3587
|
+
void scr_wasi_coro_destroy(void *handle);
|
|
3588
|
+
void scr_wasi_coro_started(void *handle);
|
|
3589
|
+
void scr_wasi_await_prepare(ScrFiber *self, ScrPromise *p);
|
|
3590
|
+
void scr_wasi_await_hop_prepare(ScrFiber *self);
|
|
3591
|
+
bool scr_wasi_module_await_prepare(ScrFiber *self, ScrPromise *p);
|
|
3592
|
+
void scr_wasi_async_finish(ScrFiber *self);
|
|
3593
|
+
void scr_wasi_gen_finish(ScrFiber *self);
|
|
3551
3594
|
|
|
3552
3595
|
double scr_await_f64(ScrPromise *p); /* rejected promises re-throw */
|
|
3553
3596
|
bool scr_await_bool(ScrPromise *p);
|
|
@@ -5113,6 +5156,20 @@ void scr_net_listen(ScrNetServer *s, double port, ScrClosure *cb /*moves, nullab
|
|
|
5113
5156
|
void scr_net_listen_opts(ScrNetServer *s, double port, ScrStr *host /*borrowed*/,
|
|
5114
5157
|
bool ipv6_only, ScrClosure *cb /*moves, nullable*/);
|
|
5115
5158
|
double scr_net_server_port(ScrNetServer *s); /* address().port */
|
|
5159
|
+
/* Writable http.Server timeout property storage. `field` is the compiler
|
|
5160
|
+
* ABI selector: timeout, keepAliveTimeout, headersTimeout, requestTimeout,
|
|
5161
|
+
* keepAliveTimeoutBuffer. Typed reads validate that no dynamic write left
|
|
5162
|
+
* a non-number in the ordinary JS property slot. */
|
|
5163
|
+
double scr_net_server_timeout_get(ScrNetServer *s, double field);
|
|
5164
|
+
void scr_net_server_timeout_set(ScrNetServer *s, double field, double value);
|
|
5165
|
+
/* Marks the shared net-server handle as an HTTP/1 or HTTPS server. The
|
|
5166
|
+
* dynamic handle uses this to keep HTTP-only fields off net/TLS/H2. */
|
|
5167
|
+
void scr_net_server_enable_http_timeout_surface(ScrNetServer *s);
|
|
5168
|
+
/* Constructor-option twin: undefined is absent; otherwise validates type
|
|
5169
|
+
* and a non-negative safe integer before storing, matching Node's option
|
|
5170
|
+
* ladder (plain property writes do not validate). */
|
|
5171
|
+
bool scr_net_server_timeout_option_check(double field, double value);
|
|
5172
|
+
void scr_net_server_timeout_option_set(ScrNetServer *s, double field, const struct ScrDyn *value);
|
|
5116
5173
|
ScrStr *scr_net_server_addr_ip(ScrNetServer *s); /* +1 — address().address */
|
|
5117
5174
|
ScrStr *scr_net_server_addr_family(ScrNetServer *s); /* +1 — address().family */
|
|
5118
5175
|
void scr_net_server_close(ScrNetServer *s, ScrClosure *cb /*moves, nullable*/);
|
package/src/scr_string.c
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* leaks nothing and frees nothing twice (double-free shows up as ASan
|
|
11
11
|
* use-after-free on the rc field or a negative count here). */
|
|
12
12
|
#ifdef SCR_RC_AUDIT
|
|
13
|
-
static long scr_live_strings = 0;
|
|
13
|
+
static SCR_TL long scr_live_strings = 0;
|
|
14
14
|
long scr_str_live_count(void) { return scr_live_strings; }
|
|
15
15
|
#endif
|
|
16
16
|
|
|
@@ -41,8 +41,8 @@ typedef struct {
|
|
|
41
41
|
size_t u16len; /* SCR_U16_UNKNOWN until computed */
|
|
42
42
|
size_t cu, cb; /* cursor: byte offset cb starts the char at unit cu */
|
|
43
43
|
} ScrSidx;
|
|
44
|
-
static ScrSidx scr_sidx_tab[SCR_SIDX_N];
|
|
45
|
-
static unsigned scr_sidx_clock;
|
|
44
|
+
static SCR_TL ScrSidx scr_sidx_tab[SCR_SIDX_N];
|
|
45
|
+
static SCR_TL unsigned scr_sidx_clock;
|
|
46
46
|
|
|
47
47
|
static void scr_sidx_purge(const ScrStr *s) {
|
|
48
48
|
for (int i = 0; i < SCR_SIDX_N; i++) {
|
|
@@ -90,7 +90,7 @@ ScrStr *scr_str_new(const char *bytes, size_t len) {
|
|
|
90
90
|
* blocks instead of paging in fresh zero-filled memory 40k times. Disabled
|
|
91
91
|
* in the audit lane so ASan sees every logical free as a real free. */
|
|
92
92
|
#ifndef SCR_RC_AUDIT
|
|
93
|
-
static ScrStr *scr_str_spare;
|
|
93
|
+
static SCR_TL ScrStr *scr_str_spare;
|
|
94
94
|
#endif
|
|
95
95
|
|
|
96
96
|
/* A spare-block reuse must not waste grossly (cap <= 4x the need) and only
|
package/src/scr_symbol.c
CHANGED
|
@@ -55,7 +55,7 @@ ScrSym *scr_sym_new(ScrStr *desc) {
|
|
|
55
55
|
|
|
56
56
|
/* ── the Symbol.for global registry ──────────────────────────────────── */
|
|
57
57
|
|
|
58
|
-
static ScrSym *g_sym_registry = NULL;
|
|
58
|
+
static SCR_TL ScrSym *g_sym_registry = NULL;
|
|
59
59
|
|
|
60
60
|
static void scr_sym_registry_cleanup(void) {
|
|
61
61
|
ScrSym *s = g_sym_registry;
|
package/src/scr_tls.c
CHANGED
|
@@ -1415,6 +1415,27 @@ ScrNetServer *scr_tls_create_server_dyn(const ScrDyn *opts /*borrowed*/,
|
|
|
1415
1415
|
ScrNetServer *scr_https_create_server_dyn(const ScrDyn *opts /*borrowed*/,
|
|
1416
1416
|
ScrClosure *handler /*moves, nullable*/,
|
|
1417
1417
|
ScrHttpReqFn fn) {
|
|
1418
|
+
/* HTTPS ServerOptions extends http.ServerOptions. Consume the one HTTP
|
|
1419
|
+
* constructor field this runtime models before the shared TLS walker;
|
|
1420
|
+
* that walker deliberately owns only the TLS-side option surface. */
|
|
1421
|
+
bool has_timeout_buffer = false;
|
|
1422
|
+
double timeout_buffer = 0;
|
|
1423
|
+
if (opts != NULL && opts->kind == SCR_DYN_OBJ) {
|
|
1424
|
+
const ScrDyn *v = scr_dyn_obj_get(opts, "keepAliveTimeoutBuffer", 22);
|
|
1425
|
+
if (v != NULL && v->kind != SCR_DYN_UNDEF) {
|
|
1426
|
+
if (v->kind != SCR_DYN_NUM) {
|
|
1427
|
+
scr_dyn_arg_type_fail("keepAliveTimeoutBuffer", "of type number", v);
|
|
1428
|
+
scr_closure_release(handler);
|
|
1429
|
+
return NULL;
|
|
1430
|
+
}
|
|
1431
|
+
timeout_buffer = v->v.num;
|
|
1432
|
+
if (!scr_net_server_timeout_option_check(4, timeout_buffer)) {
|
|
1433
|
+
scr_closure_release(handler);
|
|
1434
|
+
return NULL;
|
|
1435
|
+
}
|
|
1436
|
+
has_timeout_buffer = true;
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1418
1439
|
ScrBytes *cert, *key;
|
|
1419
1440
|
if (!scr_tls_srv_opts_walk(opts, "https.createServer", &cert, &key)) {
|
|
1420
1441
|
scr_closure_release(handler);
|
|
@@ -1422,6 +1443,7 @@ ScrNetServer *scr_https_create_server_dyn(const ScrDyn *opts /*borrowed*/,
|
|
|
1422
1443
|
}
|
|
1423
1444
|
ScrNetServer *s = scr_https_create_server((const char *)cert->data, cert->len,
|
|
1424
1445
|
(const char *)key->data, key->len, handler, fn);
|
|
1446
|
+
if (has_timeout_buffer) scr_net_server_timeout_set(s, 4, timeout_buffer);
|
|
1425
1447
|
scr_bytes_release(cert);
|
|
1426
1448
|
scr_bytes_release(key);
|
|
1427
1449
|
return s;
|
package/src/scr_union.c
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
/* Live union count for the RC audit lane (-DSCR_RC_AUDIT); same contract
|
|
16
16
|
* as scr_str_live_count in scr_string.c. */
|
|
17
17
|
#ifdef SCR_RC_AUDIT
|
|
18
|
-
static long scr_live_unions = 0;
|
|
18
|
+
static SCR_TL long scr_live_unions = 0;
|
|
19
19
|
long scr_union_live_count(void) { return scr_live_unions; }
|
|
20
20
|
#endif
|
|
21
21
|
|
package/vendor/README.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Vendored third-party code
|
|
2
2
|
|
|
3
|
+
## libucontext (derived source)
|
|
4
|
+
|
|
5
|
+
- Project: https://github.com/kaniini/libucontext
|
|
6
|
+
- Commit: 49e671dd52ff6791295d8161ad3b6da7dc5f6f9d
|
|
7
|
+
- License: ISC (copyright and permission notice reproduced in `src/scr_musl.c`)
|
|
8
|
+
|
|
9
|
+
The x86_64 register-save/restore and `makecontext` logic is adapted into `src/scr_musl.c`, rather than carried as a separate library, to supply the legacy `ucontext` functions that musl declares but does not implement. It is compiled only for the explicit `x86_64-linux-musl` target and uses musl's public `ucontext_t` layout. The signal-mask compatibility wrapper is deliberately not included: scriptc fibers perform user-space register swaps and do not change a per-fiber signal mask.
|
|
10
|
+
|
|
3
11
|
## ryu/
|
|
4
12
|
|
|
5
13
|
- Project: https://github.com/ulfjack/ryu
|