@scriptc/runtime 0.0.21 → 0.0.23
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_assert.c +23 -0
- package/src/scr_async.c +5 -2
- package/src/scr_bytes.c +7 -0
- package/src/scr_cycle.c +403 -62
- package/src/scr_dyn_invoke.c +58 -6
- package/src/scr_fetch.c +6200 -124
- package/src/scr_fetch_curl.c +21 -9
- package/src/scr_http.c +13 -0
- package/src/scr_inspect.c +6 -0
- package/src/scr_island.c +19 -0
- package/src/scr_json.c +413 -9
- package/src/scr_lib.c +277 -18
- package/src/scr_runtime.h +211 -27
- package/src/scr_tls.c +15 -11
- package/src/scr_tls_ca.c +35 -8
- package/src/scr_url.c +103 -15
- package/src/scr_web.c +77 -1
- package/vendor/README.md +4 -4
package/src/scr_url.c
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* - scheme lowercasing; "Invalid URL" TypeError on schemeless input
|
|
8
8
|
* - special schemes (http/https/ws/wss/ftp/file): authority parsing with
|
|
9
9
|
* host lowercasing, default-port removal (leading zeros stripped),
|
|
10
|
+
* canonical bracketed IPv6 literals,
|
|
10
11
|
* backslash-as-slash, and any run of leading slashes tolerated
|
|
11
12
|
* (http:foo.com works); file: takes an authority only after exactly
|
|
12
13
|
* "//" (file:/x and file:x are host-less absolute paths, like Node)
|
|
@@ -21,8 +22,8 @@
|
|
|
21
22
|
* path kept verbatim (data:text/plain,hi there)
|
|
22
23
|
*
|
|
23
24
|
* DOCUMENTED DIVERGENCES (SEMANTICS.md): non-ASCII and %-escaped hosts are
|
|
24
|
-
* rejected with "Invalid URL" (no IDNA/punycode),
|
|
25
|
-
*
|
|
25
|
+
* rejected with "Invalid URL" (no IDNA/punycode), and opaque paths skip
|
|
26
|
+
* the spec's C0-encode pass (kept verbatim).
|
|
26
27
|
*
|
|
27
28
|
* Failures THROW catchable TypeErrors through the exception cell with
|
|
28
29
|
* Node's messages; callers are compiler-emitted pending checks. */
|
|
@@ -33,6 +34,12 @@
|
|
|
33
34
|
#include <stdlib.h>
|
|
34
35
|
#include <string.h>
|
|
35
36
|
#include <unistd.h>
|
|
37
|
+
#ifdef _WIN32
|
|
38
|
+
#include <winsock2.h>
|
|
39
|
+
#include <ws2tcpip.h>
|
|
40
|
+
#else
|
|
41
|
+
#include <arpa/inet.h>
|
|
42
|
+
#endif
|
|
36
43
|
|
|
37
44
|
ScrUrl *scr_url_retain(ScrUrl *u) {
|
|
38
45
|
if (u->rc != SIZE_MAX) u->rc++;
|
|
@@ -94,6 +101,65 @@ static ScrStr *ub_take(UrlBuf *b) {
|
|
|
94
101
|
return s;
|
|
95
102
|
}
|
|
96
103
|
|
|
104
|
+
/* WHATWG's IPv6 serializer: lowercase hexadecimal with the first longest
|
|
105
|
+
* run of two-or-more zero pieces compressed. inet_pton supplies the parser,
|
|
106
|
+
* while serializing the eight pieces here also avoids the platform-specific
|
|
107
|
+
* dotted-decimal spelling inet_ntop uses for IPv4-mapped addresses. */
|
|
108
|
+
static bool ub_append_ipv6(UrlBuf *out, const char *raw, size_t len) {
|
|
109
|
+
char *text = malloc(len + 1);
|
|
110
|
+
if (!text) scr_trap("scriptc: out of memory\n");
|
|
111
|
+
memcpy(text, raw, len);
|
|
112
|
+
text[len] = '\0';
|
|
113
|
+
struct in6_addr address;
|
|
114
|
+
bool valid = inet_pton(AF_INET6, text, &address) == 1;
|
|
115
|
+
free(text);
|
|
116
|
+
if (!valid) return false;
|
|
117
|
+
|
|
118
|
+
const unsigned char *bytes = (const unsigned char *)&address;
|
|
119
|
+
uint16_t pieces[8];
|
|
120
|
+
for (size_t i = 0; i < 8; i++) {
|
|
121
|
+
pieces[i] = (uint16_t)(((uint16_t)bytes[i * 2] << 8) |
|
|
122
|
+
bytes[i * 2 + 1]);
|
|
123
|
+
}
|
|
124
|
+
size_t best_start = 0;
|
|
125
|
+
size_t best_len = 0;
|
|
126
|
+
for (size_t i = 0; i < 8;) {
|
|
127
|
+
if (pieces[i] != 0) {
|
|
128
|
+
i++;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
size_t start = i;
|
|
132
|
+
while (i < 8 && pieces[i] == 0) i++;
|
|
133
|
+
size_t run = i - start;
|
|
134
|
+
if (run > best_len) {
|
|
135
|
+
best_start = start;
|
|
136
|
+
best_len = run;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (best_len < 2) best_len = 0;
|
|
140
|
+
|
|
141
|
+
ub_push(out, '[');
|
|
142
|
+
bool first = true;
|
|
143
|
+
size_t compressed_end = best_start + best_len;
|
|
144
|
+
for (size_t i = 0; i < 8;) {
|
|
145
|
+
if (best_len > 0 && i == best_start) {
|
|
146
|
+
ub_append(out, "::", 2);
|
|
147
|
+
first = false;
|
|
148
|
+
i = compressed_end;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (!first && (best_len == 0 || i != compressed_end)) ub_push(out, ':');
|
|
152
|
+
char hex[5];
|
|
153
|
+
int hex_len = snprintf(hex, sizeof hex, "%x", pieces[i]);
|
|
154
|
+
if (hex_len <= 0 || (size_t)hex_len >= sizeof hex) return false;
|
|
155
|
+
ub_append(out, hex, (size_t)hex_len);
|
|
156
|
+
first = false;
|
|
157
|
+
i++;
|
|
158
|
+
}
|
|
159
|
+
ub_push(out, ']');
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
|
|
97
163
|
/* ── percent-encode sets (WHATWG) ────────────────────────────────────── */
|
|
98
164
|
|
|
99
165
|
static bool enc_always(unsigned char c) {
|
|
@@ -273,25 +339,48 @@ static bool parse_authority(const char *raw, size_t len, bool special, bool is_f
|
|
|
273
339
|
*userinfo = ub_take(&ub);
|
|
274
340
|
const char *hp = at >= 0 ? raw + at + 1 : raw;
|
|
275
341
|
size_t hp_len = at >= 0 ? len - (size_t)at - 1 : len;
|
|
276
|
-
/* host[:port]
|
|
342
|
+
/* host[:port], with IPv6 literals bracketed per WHATWG. */
|
|
277
343
|
long colon = -1;
|
|
278
|
-
|
|
279
|
-
|
|
344
|
+
size_t host_len = hp_len;
|
|
345
|
+
bool ipv6 = hp_len > 0 && hp[0] == '[';
|
|
346
|
+
size_t ipv6_end = 0;
|
|
347
|
+
if (ipv6) {
|
|
348
|
+
while (ipv6_end < hp_len && hp[ipv6_end] != ']') ipv6_end++;
|
|
349
|
+
if (ipv6_end == hp_len || ipv6_end == 1) return false;
|
|
350
|
+
host_len = ipv6_end + 1;
|
|
351
|
+
if (host_len < hp_len) {
|
|
352
|
+
if (hp[host_len] != ':') return false;
|
|
353
|
+
colon = (long)host_len;
|
|
354
|
+
}
|
|
355
|
+
} else {
|
|
356
|
+
for (size_t i = 0; i < hp_len; i++) {
|
|
357
|
+
if (hp[i] == ':') colon = (long)i;
|
|
358
|
+
}
|
|
359
|
+
host_len = colon >= 0 ? (size_t)colon : hp_len;
|
|
280
360
|
}
|
|
281
|
-
size_t host_len = colon >= 0 ? (size_t)colon : hp_len;
|
|
282
361
|
/* Validate + lowercase (special) the host. Divergence: non-ASCII and
|
|
283
|
-
* %-escapes (IDNA territory)
|
|
362
|
+
* %-escapes (IDNA territory) are rejected outright. */
|
|
284
363
|
UrlBuf hb;
|
|
285
364
|
ub_init(&hb);
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
if (c >= 0x80 || c == '%' || c == '[' || c == ']' || c <= 0x20 || c == '#' || c == '/' ||
|
|
289
|
-
c == '<' || c == '>' || c == '?' || c == '@' || c == '\\' || c == '^' || c == '|') {
|
|
365
|
+
if (ipv6) {
|
|
366
|
+
if (!ub_append_ipv6(&hb, hp + 1, ipv6_end - 1)) {
|
|
290
367
|
free(hb.data);
|
|
291
368
|
return false;
|
|
292
369
|
}
|
|
293
|
-
|
|
294
|
-
|
|
370
|
+
} else {
|
|
371
|
+
for (size_t i = 0; i < host_len; i++) {
|
|
372
|
+
unsigned char c = (unsigned char)hp[i];
|
|
373
|
+
if (c >= 0x80 || c == '%' || c == ':' || c == '[' || c == ']' ||
|
|
374
|
+
c <= 0x20 || c == '#' || c == '/' || c == '<' || c == '>' ||
|
|
375
|
+
c == '?' || c == '@' || c == '\\' || c == '^' || c == '|') {
|
|
376
|
+
free(hb.data);
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
if (special && c >= 'A' && c <= 'Z') {
|
|
380
|
+
c = (unsigned char)(c - 'A' + 'a');
|
|
381
|
+
}
|
|
382
|
+
ub_push(&hb, (char)c);
|
|
383
|
+
}
|
|
295
384
|
}
|
|
296
385
|
/* file: "localhost" normalizes to "" at parse time (Node). */
|
|
297
386
|
if (is_file && hb.len == 9 && memcmp(hb.data, "localhost", 9) == 0) hb.len = 0;
|
|
@@ -561,8 +650,7 @@ ScrStr *scr_url_host(ScrUrl *u) {
|
|
|
561
650
|
}
|
|
562
651
|
|
|
563
652
|
/* WHATWG hostname getter: the stored port-less host verbatim ("" for
|
|
564
|
-
* authority-less URLs)
|
|
565
|
-
* rejects IPv6 hosts (documented divergence), so none reach this getter. */
|
|
653
|
+
* authority-less URLs); IPv6 literals retain their brackets. */
|
|
566
654
|
ScrStr *scr_url_hostname(ScrUrl *u) { return scr_str_retain(u->host); }
|
|
567
655
|
|
|
568
656
|
ScrStr *scr_url_href(ScrUrl *u) {
|
package/src/scr_web.c
CHANGED
|
@@ -294,6 +294,62 @@ static const char web_prelude[] =
|
|
|
294
294
|
" return it;\n"
|
|
295
295
|
" }\n"
|
|
296
296
|
" [Symbol.asyncIterator](options) { return this.values(options); }\n"
|
|
297
|
+
" static from(iterable) {\n"
|
|
298
|
+
" if (iterable === undefined || iterable === null) {\n"
|
|
299
|
+
" throw new TypeError('ReadableStream.from requires an iterable');\n"
|
|
300
|
+
" }\n"
|
|
301
|
+
" const asyncMethod = iterable[Symbol.asyncIterator];\n"
|
|
302
|
+
" let method;\n"
|
|
303
|
+
" let asyncIterator = false;\n"
|
|
304
|
+
" if (asyncMethod !== undefined && asyncMethod !== null) {\n"
|
|
305
|
+
" if (typeof asyncMethod !== 'function') {\n"
|
|
306
|
+
" throw new TypeError('ReadableStream.from requires an iterable');\n"
|
|
307
|
+
" }\n"
|
|
308
|
+
" method = asyncMethod;\n"
|
|
309
|
+
" asyncIterator = true;\n"
|
|
310
|
+
" } else {\n"
|
|
311
|
+
" method = iterable[Symbol.iterator];\n"
|
|
312
|
+
" if (typeof method !== 'function') {\n"
|
|
313
|
+
" throw new TypeError('ReadableStream.from requires an iterable');\n"
|
|
314
|
+
" }\n"
|
|
315
|
+
" }\n"
|
|
316
|
+
" const iterator = method.call(iterable);\n"
|
|
317
|
+
" if ((typeof iterator !== 'object' || iterator === null) && typeof iterator !== 'function') {\n"
|
|
318
|
+
" throw new TypeError('iterator method must return an object');\n"
|
|
319
|
+
" }\n"
|
|
320
|
+
" const next = iterator.next;\n"
|
|
321
|
+
" let finished = false;\n"
|
|
322
|
+
" let started = false;\n"
|
|
323
|
+
" return new ReadableStream({\n"
|
|
324
|
+
" async pull(controller) {\n"
|
|
325
|
+
" started = true;\n"
|
|
326
|
+
" const result = asyncIterator ? await next.call(iterator) : next.call(iterator);\n"
|
|
327
|
+
" if ((typeof result !== 'object' || result === null) && typeof result !== 'function') {\n"
|
|
328
|
+
" throw new TypeError('iterator result is not an object');\n"
|
|
329
|
+
" }\n"
|
|
330
|
+
" if (result.done) { finished = true; controller.close(); return; }\n"
|
|
331
|
+
" controller.enqueue(asyncIterator ? result.value : await result.value);\n"
|
|
332
|
+
" },\n"
|
|
333
|
+
" async cancel(reason) {\n"
|
|
334
|
+
" if (finished) return;\n"
|
|
335
|
+
" finished = true;\n"
|
|
336
|
+
" if (!started) return;\n"
|
|
337
|
+
" const finish = iterator.return;\n"
|
|
338
|
+
" if (finish === undefined || finish === null) return;\n"
|
|
339
|
+
" if (typeof finish !== 'function') throw new TypeError('iterator return is not a function');\n"
|
|
340
|
+
" const result = finish.call(iterator, reason);\n"
|
|
341
|
+
" if (!asyncIterator && ((typeof result !== 'object' || result === null) && typeof result !== 'function')) {\n"
|
|
342
|
+
" throw new TypeError('iterator result is not an object');\n"
|
|
343
|
+
" }\n"
|
|
344
|
+
" if (asyncIterator) {\n"
|
|
345
|
+
" const awaited = await result;\n"
|
|
346
|
+
" if ((typeof awaited !== 'object' || awaited === null) && typeof awaited !== 'function') {\n"
|
|
347
|
+
" throw new TypeError('iterator result is not an object');\n"
|
|
348
|
+
" }\n"
|
|
349
|
+
" }\n"
|
|
350
|
+
" },\n"
|
|
351
|
+
" });\n"
|
|
352
|
+
" }\n"
|
|
297
353
|
" pipeThrough(transform, options) {\n"
|
|
298
354
|
" if (transform === null || typeof transform !== 'object' || !transform.writable || !transform.readable) {\n"
|
|
299
355
|
" throw new TypeError('pipeThrough requires a { writable, readable } pair');\n"
|
|
@@ -1342,12 +1398,14 @@ static const char web_prelude[] =
|
|
|
1342
1398
|
" this._headers = new g.Headers(input._headers);\n"
|
|
1343
1399
|
" this._body = input._body; // shared bytes; fetch copies\n"
|
|
1344
1400
|
" this._signal = input._signal;\n"
|
|
1401
|
+
" this._redirect = input._redirect;\n"
|
|
1345
1402
|
" } else {\n"
|
|
1346
1403
|
" this._url = String(input);\n"
|
|
1347
1404
|
" this._method = 'GET';\n"
|
|
1348
1405
|
" this._headers = new g.Headers();\n"
|
|
1349
1406
|
" this._body = null;\n"
|
|
1350
1407
|
" this._signal = null;\n"
|
|
1408
|
+
" this._redirect = 'follow';\n"
|
|
1351
1409
|
" }\n"
|
|
1352
1410
|
" if (init.method !== undefined) this._method = normalizeMethod(init.method);\n"
|
|
1353
1411
|
" if (init.headers !== undefined) this._headers = new g.Headers(init.headers);\n"
|
|
@@ -1357,19 +1415,35 @@ static const char web_prelude[] =
|
|
|
1357
1415
|
" }\n"
|
|
1358
1416
|
" this._signal = init.signal;\n"
|
|
1359
1417
|
" }\n"
|
|
1418
|
+
" if (init.redirect !== undefined) {\n"
|
|
1419
|
+
" const redirect = String(init.redirect);\n"
|
|
1420
|
+
" if (redirect !== 'follow' && redirect !== 'error' && redirect !== 'manual') {\n"
|
|
1421
|
+
" throw new TypeError(`undefined: ${redirect} is not an accepted type. Expected one of follow, manual, error.`);\n"
|
|
1422
|
+
" }\n"
|
|
1423
|
+
" this._redirect = redirect;\n"
|
|
1424
|
+
" }\n"
|
|
1360
1425
|
" if (init.body !== undefined && init.body !== null) {\n"
|
|
1361
1426
|
" if (this._method === 'GET' || this._method === 'HEAD') {\n"
|
|
1362
1427
|
" throw new TypeError('Request with GET/HEAD method cannot have body.');\n"
|
|
1363
1428
|
" }\n"
|
|
1364
1429
|
" const [bytes, ct] = coerceBodyBytes(init.body);\n"
|
|
1430
|
+
" if (bytes instanceof g.ReadableStream && init.duplex !== 'half') {\n"
|
|
1431
|
+
" throw new TypeError('RequestInit: duplex option is required when sending a body.');\n"
|
|
1432
|
+
" }\n"
|
|
1365
1433
|
" this._body = bytes;\n"
|
|
1366
1434
|
" if (ct !== null && !this._headers.has('content-type')) this._headers.set('content-type', ct);\n"
|
|
1367
1435
|
" }\n"
|
|
1436
|
+
" // A method override still validates a body inherited from the\n"
|
|
1437
|
+
" // input Request, not only a body supplied by this init.\n"
|
|
1438
|
+
" if (this._body !== null && (this._method === 'GET' || this._method === 'HEAD')) {\n"
|
|
1439
|
+
" throw new TypeError('Request with GET/HEAD method cannot have body.');\n"
|
|
1440
|
+
" }\n"
|
|
1368
1441
|
" this._bodyUsed = false;\n"
|
|
1369
1442
|
" }\n"
|
|
1370
1443
|
" get url() { return this._url; }\n"
|
|
1371
1444
|
" get method() { return this._method; }\n"
|
|
1372
1445
|
" get headers() { return this._headers; }\n"
|
|
1446
|
+
" get redirect() { return this._redirect; }\n"
|
|
1373
1447
|
" /* Node's Request.signal is never null — a request built without one\n"
|
|
1374
1448
|
" * carries an inert signal; mint it lazily on first access. */\n"
|
|
1375
1449
|
" get signal() {\n"
|
|
@@ -1391,6 +1465,7 @@ static const char web_prelude[] =
|
|
|
1391
1465
|
" this._headers = new g.Headers(init.headers);\n"
|
|
1392
1466
|
" this._url = '';\n"
|
|
1393
1467
|
" this._redirected = false;\n"
|
|
1468
|
+
" this._type = 'default';\n"
|
|
1394
1469
|
" this._bodyUsed = false;\n"
|
|
1395
1470
|
" if (body === undefined || body === null) {\n"
|
|
1396
1471
|
" this._body = null;\n"
|
|
@@ -1406,7 +1481,7 @@ static const char web_prelude[] =
|
|
|
1406
1481
|
" get headers() { return this._headers; }\n"
|
|
1407
1482
|
" get url() { return this._url; }\n"
|
|
1408
1483
|
" get redirected() { return this._redirected; }\n"
|
|
1409
|
-
" get type() { return
|
|
1484
|
+
" get type() { return this._type; }\n"
|
|
1410
1485
|
" static json(data, init) {\n"
|
|
1411
1486
|
" const r = new Response(JSON.stringify(data), init);\n"
|
|
1412
1487
|
" r._headers.set('content-type', 'application/json');\n"
|
|
@@ -1425,6 +1500,7 @@ static const char web_prelude[] =
|
|
|
1425
1500
|
" r._headers = headers;\n"
|
|
1426
1501
|
" r._url = url;\n"
|
|
1427
1502
|
" r._redirected = redirected;\n"
|
|
1503
|
+
" r._type = 'basic';\n"
|
|
1428
1504
|
" r._body = bodyStream;\n"
|
|
1429
1505
|
" return r;\n"
|
|
1430
1506
|
" };\n"
|
package/vendor/README.md
CHANGED
|
@@ -19,7 +19,7 @@ The QuickJS-ng JavaScript engine, embedded by the opt-in `--dynamic` build mode
|
|
|
19
19
|
|
|
20
20
|
The tree is a plain snapshot of the upstream commit with directories the library build does not need removed (tests/, docs/, examples/, test262 fixtures, CI config, generator scripts). No vendored file is modified; to update, re-clone upstream at the new commit, delete its .git directory, apply the same trim, and update this file.
|
|
21
21
|
|
|
22
|
-
The engine archive (libqjs.a) is built lazily on the first `--dynamic` compile into `.cache/<commit>-<flavor>/` next to this file — one flavor per lane (plain, asan). The cache directory is gitignored and safe to delete.
|
|
22
|
+
The engine archive (libqjs.a) is built lazily on the first `--dynamic` compile into `.cache/<commit>-<flavor>-<target>-<toolchain>/` next to this file — one flavor per lane (plain, asan), native platform/architecture or explicit cross target, and compiler environment/identity. The cache directory is gitignored and safe to delete.
|
|
23
23
|
|
|
24
24
|
## zlib/
|
|
25
25
|
|
|
@@ -29,7 +29,7 @@ The engine archive (libqjs.a) is built lazily on the first `--dynamic` compile i
|
|
|
29
29
|
|
|
30
30
|
The CROSS-target arm of node:zlib (see packages/runtime/src/scr_zlib.c): host builds keep the historical system `-lz` link (macOS ships libz), but zig's cross sysroots have no libz, so SCRIPTC_TARGET builds compile this vendored copy per target instead. Only the flat `*.c`/`*.h` at the distribution root are vendored (LICENSE beside them) — contrib, tests, build machinery, and docs are not. No vendored file is modified; the gz* file-I/O TUs are vendored for faithfulness but never compiled (nothing references the gzFile API — see ZLIB_SOURCES in packages/compiler/src/backend/cc.ts). To update, re-fetch the release tarball, copy the same flat set, and bump `ZLIB_VERSION` in cc.ts.
|
|
31
31
|
|
|
32
|
-
The objects build lazily on the first zlib-using cross compile into `.cache/zlib-<version>-<flavor>/` next to this file — one flavor per driver/target (the lre-objects pattern). Zlib-free binaries never compile any of this; compressed OUTPUT bytes are zlib-version-dependent, which is why the corpus only compares round-trips and fixed-blob inflation.
|
|
32
|
+
The objects build lazily on the first zlib-using cross compile into `.cache/zlib-<version>-<flavor>-<target>-<toolchain>/` next to this file — one flavor per driver/target and compiler environment/identity (the lre-objects pattern). Zlib-free binaries never compile any of this; compressed OUTPUT bytes are zlib-version-dependent, which is why the corpus only compares round-trips and fixed-blob inflation.
|
|
33
33
|
|
|
34
34
|
## curl/
|
|
35
35
|
|
|
@@ -39,7 +39,7 @@ The objects build lazily on the first zlib-using cross compile into `.cache/zlib
|
|
|
39
39
|
|
|
40
40
|
HEADERS ONLY — no curl C source is vendored and none is ever compiled. These headers now serve ONLY the RETIRED curl reference implementation of fetch (packages/runtime/src/scr_fetch_curl.c, selected by `SCRIPTC_FETCH_CURL=1`; kept compilable for one release as the native flip's reference — see scr_fetch.c, the default, which rides scr_net/scr_tls/scr_http/zlib and touches nothing here). Under the flag: host builds link the system `-lcurl` (macOS ships libcurl), and linux-gnu CROSS builds compile scr_fetch_curl.c against these headers, then link against a generated STUB `libcurl.so` (soname `libcurl.so.4`, empty definitions of exactly the symbols scr_fetch_curl.c calls — see CURL_STUB_SYMBOLS in packages/compiler/src/backend/cc.ts) so the produced binary records a plain `DT_NEEDED libcurl.so.4` that the TARGET system's real libcurl satisfies at load time, the standard cross-link import-stub technique. The 7.88.1 pin is a floor, not a lock: scr_fetch_curl.c's newest requirement is CURLOPT_PROTOCOLS_STR (7.85.0) and the unversioned symbol references bind to any libcurl.so.4. This whole directory leaves with scr_fetch_curl.c when the reference retires for good.
|
|
41
41
|
|
|
42
|
-
The stub builds lazily on the first flag-selected fetch cross compile into `.cache/curl-stub-<
|
|
42
|
+
The stub builds lazily on the first flag-selected fetch cross compile into `.cache/curl-stub-<target>-<toolchain>/` next to this file (the zlib-objects pattern). Default builds never see any of this, and no build ever compiles curl itself.
|
|
43
43
|
|
|
44
44
|
## mbedtls/
|
|
45
45
|
|
|
@@ -49,4 +49,4 @@ The stub builds lazily on the first flag-selected fetch cross compile into `.cac
|
|
|
49
49
|
|
|
50
50
|
The TLS provider behind node:tls/node:https (see the design note atop packages/runtime/src/scr_tls.c for why mbedTLS over SecureTransport/BoringSSL/libtls). Only `include/` and `library/` are vendored (LICENSE beside them) — tests, docs, programs, scripts, and CMake machinery are not. No vendored file is modified and no custom config is applied (the stock `mbedtls_config.h` builds every `library/*.c` standalone with clang); to update, re-fetch the release tarball, copy the same two directories, and bump `MBEDTLS_VERSION` in packages/compiler/src/backend/cc.ts.
|
|
51
51
|
|
|
52
|
-
The archive (libmbedtls.a) is built lazily on the first TLS-using compile into `.cache/mbedtls-<version>-<flavor>/` next to this file — one flavor per lane (plain, asan), the libqjs.a pattern. TLS-free binaries never compile or link any of this.
|
|
52
|
+
The archive (libmbedtls.a) is built lazily on the first TLS-using compile into `.cache/mbedtls-<version>-<flavor>-<target>-<toolchain>/` next to this file — one flavor per lane (plain, asan), native platform/architecture or explicit cross target, and compiler environment/identity, the libqjs.a pattern. TLS-free binaries never compile or link any of this.
|