@scriptc/compiler 0.0.25 → 0.0.26
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/ambient/scriptc-node-fallback.d.ts +15 -7
- package/dist/backend/cc.d.ts +3 -0
- package/dist/backend/cc.js +37 -4
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +81 -10
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +14 -1
- package/dist/backend/emission/emitter.js +117 -11
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/emission/may-throw.js +11 -1
- package/dist/backend/emission/may-throw.js.map +1 -1
- package/dist/backend/ffi-callbacks.d.ts +11 -0
- package/dist/backend/ffi-callbacks.js +33 -0
- package/dist/backend/ffi-callbacks.js.map +1 -0
- package/dist/backend/llvm/classes.js +21 -21
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +7 -4
- package/dist/backend/llvm/dyn.js +145 -141
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +7 -1
- package/dist/backend/llvm/emitter.js +950 -300
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/shapes.d.ts +4 -0
- package/dist/backend/llvm/shapes.js +26 -24
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/unsupported.js +1 -1
- package/dist/backend/llvm/unsupported.js.map +1 -1
- package/dist/backend/llvm/walkers.d.ts +2 -0
- package/dist/backend/llvm/walkers.js +50 -46
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/coverage/surface-manifest.js +1 -1
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +1 -1
- package/dist/diagnostics/diagnostic.js +3 -2
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/ffi/profile.d.ts +20 -2
- package/dist/ffi/profile.js +130 -6
- package/dist/ffi/profile.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +58 -22
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +17 -7
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +5 -0
- package/dist/frontend/lowering/lower-server.js +129 -37
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +8 -1
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +3 -2
- package/dist/frontend/lowering/surfaces.js +4 -3
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm.d.ts +16 -0
- package/dist/frontend/npm.js +257 -0
- package/dist/frontend/npm.js.map +1 -1
- package/dist/index.d.ts +7 -4
- package/dist/index.js +152 -5
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +48 -13
- package/dist/ir/nodes.js +49 -7
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +10 -22
- package/dist/ir/validate.js.map +1 -1
- package/dist/wasi-paths.d.ts +5 -0
- package/dist/wasi-paths.js +22 -0
- package/dist/wasi-paths.js.map +1 -0
- package/package.json +2 -2
- package/surface-manifest.json +2 -2
|
@@ -31,6 +31,11 @@ export declare function lowerServerCloseOverrideAssignment(L: Lowerer, left: ts.
|
|
|
31
31
|
* routed from lower-stmts' property-assignment path beside the
|
|
32
32
|
* close-override hook. Null when the target isn't one of the two. */
|
|
33
33
|
export declare function lowerHttpResPropertyAssignment(L: Lowerer, left: ts.Expression, right: ts.Expression, loc: SrcLoc): IrStmt | null;
|
|
34
|
+
/** `server.timeout = n` and the four HTTP parser/keep-alive timeout
|
|
35
|
+
* siblings. These are ordinary writable number properties in Node: the
|
|
36
|
+
* runtime stores their exact value per server; active timeout behavior is
|
|
37
|
+
* a separate protocol concern. */
|
|
38
|
+
export declare function lowerHttpServerTimeoutAssignment(L: Lowerer, left: ts.Expression, right: ts.Expression, loc: SrcLoc): IrStmt | null;
|
|
34
39
|
/** The method-call dispatch for both server-surface receiver kinds — one
|
|
35
40
|
* entry in lower-calls.ts's intrinsic chain (the lowerChildMethodCall
|
|
36
41
|
* slot). Null when the receiver is neither. */
|
|
@@ -23,6 +23,19 @@ export const NET_MODULE_FNS = new Set([
|
|
|
23
23
|
"createConnection",
|
|
24
24
|
]);
|
|
25
25
|
const NARROW_DATA_HINT = 'write/end take one string or one Uint8Array/Buffer value (narrow unions first)';
|
|
26
|
+
/** The writable numeric http.Server timeout fields. The selector is an
|
|
27
|
+
* internal runtime ABI shared by the get/set libCalls (kept here beside
|
|
28
|
+
* the only two construction/lowering paths that can mint the accesses). */
|
|
29
|
+
function httpServerTimeoutField(name) {
|
|
30
|
+
switch (name) {
|
|
31
|
+
case "timeout": return 0;
|
|
32
|
+
case "keepAliveTimeout": return 1;
|
|
33
|
+
case "headersTimeout": return 2;
|
|
34
|
+
case "requestTimeout": return 3;
|
|
35
|
+
case "keepAliveTimeoutBuffer": return 4;
|
|
36
|
+
default: return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
26
39
|
/** VOID-result server/socket calls are usable as statements and as concise
|
|
27
40
|
* arrow bodies (`socket.on("error", () => socket.destroy())` — the shape
|
|
28
41
|
* portless is made of); anything that would CONSUME the result (Node
|
|
@@ -812,6 +825,29 @@ export function lowerHttpResPropertyAssignment(L, left, right, loc) {
|
|
|
812
825
|
loc,
|
|
813
826
|
};
|
|
814
827
|
}
|
|
828
|
+
/** `server.timeout = n` and the four HTTP parser/keep-alive timeout
|
|
829
|
+
* siblings. These are ordinary writable number properties in Node: the
|
|
830
|
+
* runtime stores their exact value per server; active timeout behavior is
|
|
831
|
+
* a separate protocol concern. */
|
|
832
|
+
export function lowerHttpServerTimeoutAssignment(L, left, right, loc) {
|
|
833
|
+
if (!ts.isPropertyAccessExpression(left) || left.questionDotToken)
|
|
834
|
+
return null;
|
|
835
|
+
const field = httpServerTimeoutField(left.name.text);
|
|
836
|
+
if (field === null)
|
|
837
|
+
return null;
|
|
838
|
+
if (L.mapTypeOf(L.typeOf(left.expression))?.kind !== "netServer")
|
|
839
|
+
return null;
|
|
840
|
+
if (!L.isStdlibMember(left))
|
|
841
|
+
return null;
|
|
842
|
+
const receiver = handleReceiver(L, left.expression, NETSERVER_T);
|
|
843
|
+
const selector = { kind: "numLit", value: field, type: F64, loc };
|
|
844
|
+
const value = L.lowerExprExpecting(right, F64);
|
|
845
|
+
return {
|
|
846
|
+
kind: "exprStmt",
|
|
847
|
+
expr: { kind: "libCall", fn: "http.serverTimeoutSet", args: [receiver, selector, value], type: VOID, loc },
|
|
848
|
+
loc,
|
|
849
|
+
};
|
|
850
|
+
}
|
|
815
851
|
/** Method calls on net.Server receivers: listen(port[, cb]), close([cb]),
|
|
816
852
|
* on/once("connection" | "error" | "close", cb). address() alone fences
|
|
817
853
|
* toward the composed address().port read. Null for other receivers. */
|
|
@@ -1714,12 +1750,20 @@ function lowerH2StreamMethodCall(L, call, access) {
|
|
|
1714
1750
|
* the two reads never materializes; the runtime answers the bound port
|
|
1715
1751
|
* directly. Null for every other property shape. */
|
|
1716
1752
|
export function lowerServerProperty(L, expr) {
|
|
1717
|
-
if (expr.questionDotToken)
|
|
1753
|
+
if (expr.questionDotToken && !L.chainHandled.has(expr))
|
|
1718
1754
|
return null;
|
|
1719
1755
|
const loc = locOf(expr);
|
|
1720
1756
|
// req.url / req.method — always-present strings on server requests;
|
|
1721
1757
|
// req.headers.NAME — the `string | undefined` union (envGet's type).
|
|
1722
1758
|
const recvKind = L.mapTypeOf(L.typeOf(expr.expression))?.kind;
|
|
1759
|
+
if (recvKind === "netServer" && L.isStdlibMember(expr)) {
|
|
1760
|
+
const field = httpServerTimeoutField(expr.name.text);
|
|
1761
|
+
if (field !== null) {
|
|
1762
|
+
const receiver = handleReceiver(L, expr.expression, NETSERVER_T);
|
|
1763
|
+
const selector = { kind: "numLit", value: field, type: F64, loc };
|
|
1764
|
+
return { kind: "libCall", fn: "http.serverTimeoutGet", args: [receiver, selector], type: F64, loc };
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1723
1767
|
if (recvKind === "httpReq" && L.isStdlibMember(expr)) {
|
|
1724
1768
|
const name = expr.name.text;
|
|
1725
1769
|
if (name === "url" || name === "method") {
|
|
@@ -1979,17 +2023,17 @@ function lowerRequestHandlerArg(L, node) {
|
|
|
1979
2023
|
return voidizedCallback(L, cb, locOf(node));
|
|
1980
2024
|
}
|
|
1981
2025
|
/** The http.createServer / http.Server options object — { requireHostHeader?,
|
|
1982
|
-
* joinDuplicateHeaders?, ... }
|
|
1983
|
-
* parser
|
|
1984
|
-
*
|
|
1985
|
-
*
|
|
1986
|
-
*
|
|
1987
|
-
* Node drops them. Answers whether joinDuplicateHeaders was requested. */
|
|
2026
|
+
* joinDuplicateHeaders?, keepAliveTimeoutBuffer?, ... }. The first two
|
|
2027
|
+
* select parser behavior; keepAliveTimeoutBuffer initializes the matching
|
|
2028
|
+
* writable server field after Node's non-negative-safe-integer validation.
|
|
2029
|
+
* Other documented keys fence by name; unknown keys drop like Node drops
|
|
2030
|
+
* them. */
|
|
1988
2031
|
function lowerHttpServerOptions(L, node, what) {
|
|
1989
2032
|
if (!ts.isObjectLiteralExpression(node)) {
|
|
1990
2033
|
L.noLowering(`${what} with a non-literal options argument`, node, "pass the options as an object literal: { requireHostHeader?, joinDuplicateHeaders? }");
|
|
1991
2034
|
}
|
|
1992
2035
|
let joinDup = false;
|
|
2036
|
+
let keepAliveTimeoutBuffer = null;
|
|
1993
2037
|
for (const prop of node.properties) {
|
|
1994
2038
|
let initializer;
|
|
1995
2039
|
if (ts.isPropertyAssignment(prop) &&
|
|
@@ -2025,16 +2069,35 @@ function lowerHttpServerOptions(L, node, what) {
|
|
|
2025
2069
|
}
|
|
2026
2070
|
L.noLowering(`${what} with a non-literal joinDuplicateHeaders option`, prop, "the lowered forms are the literals joinDuplicateHeaders: true (repeats join \", \") and false (the keep-first default)");
|
|
2027
2071
|
}
|
|
2028
|
-
|
|
2072
|
+
if (key === "keepAliveTimeoutBuffer") {
|
|
2073
|
+
if (keepAliveTimeoutBuffer !== null) {
|
|
2074
|
+
L.noLowering(`${what} with duplicate keepAliveTimeoutBuffer options`, prop, "write keepAliveTimeoutBuffer once in the options literal");
|
|
2075
|
+
}
|
|
2076
|
+
const raw = initializer !== null
|
|
2077
|
+
? L.lowerExpr(initializer)
|
|
2078
|
+
: L.lowerShorthandValue(prop);
|
|
2079
|
+
const value = L.coerceToExpected(raw, DYN);
|
|
2080
|
+
if (value.type.kind !== "dyn") {
|
|
2081
|
+
L.noLowering(`${what} with a keepAliveTimeoutBuffer value that cannot cross the runtime option boundary`, prop, "keepAliveTimeoutBuffer is a number or undefined");
|
|
2082
|
+
}
|
|
2083
|
+
// Preserve the optional field's undefined arm until runtime: Node
|
|
2084
|
+
// treats it as absent, while numbers take the constructor-only
|
|
2085
|
+
// integer/range ladder and dynamic non-numbers get its named type
|
|
2086
|
+
// error. Coercing eagerly to F64 would reject the valid explicit-
|
|
2087
|
+
// undefined spelling before the option helper sees it.
|
|
2088
|
+
keepAliveTimeoutBuffer = value;
|
|
2089
|
+
continue;
|
|
2090
|
+
}
|
|
2091
|
+
fenceOrDropOptionKey(L, prop, key, what, HTTP_SERVER_DOCUMENTED_OPTIONS, "requireHostHeader: false, joinDuplicateHeaders, and keepAliveTimeoutBuffer are the supported options");
|
|
2029
2092
|
// An undocumented key, dropped like Node drops it.
|
|
2030
2093
|
}
|
|
2031
|
-
return { joinDup };
|
|
2094
|
+
return { joinDup, keepAliveTimeoutBuffer };
|
|
2032
2095
|
}
|
|
2033
2096
|
/** The shared createServer([options][, handler]) shapes behind
|
|
2034
2097
|
* http.createServer, http.Server, and `new http.Server`: no arguments
|
|
2035
2098
|
* (the on("request") route), a lone handler, a lone options object, and
|
|
2036
|
-
* (options, handler).
|
|
2037
|
-
*
|
|
2099
|
+
* (options, handler). Modeled option values wrap the construction in an
|
|
2100
|
+
* interned option-setting helper. */
|
|
2038
2101
|
function lowerHttpCreateServerForms(L, expr, what, loc) {
|
|
2039
2102
|
const args = expr.arguments ?? [];
|
|
2040
2103
|
if (args.length > 2) {
|
|
@@ -2052,37 +2115,63 @@ function lowerHttpCreateServerForms(L, expr, what, loc) {
|
|
|
2052
2115
|
else
|
|
2053
2116
|
handlerNode = args[0];
|
|
2054
2117
|
}
|
|
2055
|
-
const
|
|
2118
|
+
const opts = optsNode !== null
|
|
2119
|
+
? lowerHttpServerOptions(L, optsNode, what)
|
|
2120
|
+
: { joinDup: false, keepAliveTimeoutBuffer: null };
|
|
2056
2121
|
const server = handlerNode !== null
|
|
2057
2122
|
? { kind: "libCall", fn: "http.createServer", args: [lowerRequestHandlerArg(L, handlerNode)], type: NETSERVER_T, loc }
|
|
2058
2123
|
: { kind: "libCall", fn: "http.createServerEmpty", args: [], type: NETSERVER_T, loc };
|
|
2059
|
-
if (!joinDup)
|
|
2124
|
+
if (!opts.joinDup && opts.keepAliveTimeoutBuffer === null)
|
|
2060
2125
|
return server;
|
|
2061
|
-
// The
|
|
2062
|
-
//
|
|
2063
|
-
|
|
2126
|
+
// The option-setting composition: an interned helper takes the option
|
|
2127
|
+
// values first (preserving Node's options-before-handler evaluation
|
|
2128
|
+
// order), then the fresh server, applies the modeled fields, and answers
|
|
2129
|
+
// the server as the constructor/factory result.
|
|
2130
|
+
const hasBuffer = opts.keepAliveTimeoutBuffer !== null;
|
|
2131
|
+
const key = `server.opts:${opts.joinDup ? 1 : 0}:${hasBuffer ? 1 : 0}`;
|
|
2064
2132
|
const existing = L.arrHofHelpers.get(key);
|
|
2065
|
-
const name = existing ?? `%server.
|
|
2133
|
+
const name = existing ?? `%server.opts.${L.arrHofHelpers.size}`;
|
|
2066
2134
|
if (!existing) {
|
|
2067
2135
|
L.arrHofHelpers.set(key, name);
|
|
2136
|
+
const params = [
|
|
2137
|
+
...(hasBuffer ? [{ localId: "b.0", name: "buffer", type: DYN }] : []),
|
|
2138
|
+
{ localId: "s.0", name: "s", type: NETSERVER_T },
|
|
2139
|
+
];
|
|
2068
2140
|
const ref = { kind: "varRef", localId: "s.0", type: NETSERVER_T, loc };
|
|
2141
|
+
const body = [];
|
|
2142
|
+
if (hasBuffer) {
|
|
2143
|
+
const selector = { kind: "numLit", value: 4, type: F64, loc };
|
|
2144
|
+
const value = { kind: "varRef", localId: "b.0", type: DYN, loc };
|
|
2145
|
+
body.push({
|
|
2146
|
+
kind: "exprStmt",
|
|
2147
|
+
expr: { kind: "libCall", fn: "http.serverTimeoutOptionSet", args: [ref, selector, value], type: VOID, loc },
|
|
2148
|
+
loc,
|
|
2149
|
+
});
|
|
2150
|
+
}
|
|
2151
|
+
if (opts.joinDup) {
|
|
2152
|
+
body.push({
|
|
2153
|
+
kind: "exprStmt",
|
|
2154
|
+
expr: { kind: "libCall", fn: "http.serverJoinDupHeaders", args: [ref], type: VOID, loc },
|
|
2155
|
+
loc,
|
|
2156
|
+
});
|
|
2157
|
+
}
|
|
2158
|
+
body.push({ kind: "return", value: ref, loc });
|
|
2069
2159
|
L.liftedFns.push({
|
|
2070
2160
|
name,
|
|
2071
|
-
params
|
|
2161
|
+
params,
|
|
2072
2162
|
returnType: NETSERVER_T,
|
|
2073
|
-
locals:
|
|
2074
|
-
body
|
|
2075
|
-
{
|
|
2076
|
-
kind: "exprStmt",
|
|
2077
|
-
expr: { kind: "libCall", fn: "http.serverJoinDupHeaders", args: [ref], type: VOID, loc },
|
|
2078
|
-
loc,
|
|
2079
|
-
},
|
|
2080
|
-
{ kind: "return", value: ref, loc },
|
|
2081
|
-
],
|
|
2163
|
+
locals: params.map((p) => ({ id: p.localId, name: p.name, type: p.type, mutable: false })),
|
|
2164
|
+
body,
|
|
2082
2165
|
loc,
|
|
2083
2166
|
});
|
|
2084
2167
|
}
|
|
2085
|
-
return {
|
|
2168
|
+
return {
|
|
2169
|
+
kind: "call",
|
|
2170
|
+
callee: name,
|
|
2171
|
+
args: [...(opts.keepAliveTimeoutBuffer !== null ? [opts.keepAliveTimeoutBuffer] : []), server],
|
|
2172
|
+
type: NETSERVER_T,
|
|
2173
|
+
loc,
|
|
2174
|
+
};
|
|
2086
2175
|
}
|
|
2087
2176
|
/** `new http.Server([options][, handler])` — the constructor spelling of
|
|
2088
2177
|
* createServer (Node's Server class IS the factory's product); called
|
|
@@ -2316,17 +2405,20 @@ const TLS_VALIDATED_OPTIONS = new Set([
|
|
|
2316
2405
|
"minVersion", "maxVersion", "handshakeTimeout", "keepAliveInitialDelay",
|
|
2317
2406
|
"sessionTimeout", "ticketKeys",
|
|
2318
2407
|
]);
|
|
2319
|
-
/** True when a literal options bag
|
|
2320
|
-
* the
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2408
|
+
/** True when a literal options bag must ride the runtime walker: JS uses
|
|
2409
|
+
* it for the typed TLS validation ladders, and HTTPS uses it for
|
|
2410
|
+
* keepAliveTimeoutBuffer so the HTTP option is consumed without losing
|
|
2411
|
+
* the literal's evaluation order. */
|
|
2412
|
+
function tlsLiteralNeedsRuntimeWalk(node, includeHttpTimeoutOptions = false) {
|
|
2413
|
+
const jsSource = isJsSourceFile(node.getSourceFile());
|
|
2324
2414
|
return node.properties.some((p) => (ts.isPropertyAssignment(p) || ts.isShorthandPropertyAssignment(p)) &&
|
|
2325
2415
|
(ts.isIdentifier(p.name) || ts.isStringLiteral(p.name)) &&
|
|
2326
|
-
|
|
2416
|
+
((includeHttpTimeoutOptions && p.name.text === "keepAliveTimeoutBuffer") ||
|
|
2417
|
+
(jsSource && TLS_VALIDATED_OPTIONS.has(p.name.text))));
|
|
2327
2418
|
}
|
|
2328
|
-
function lowerTlsServerOptionsOrDyn(L, node, what) {
|
|
2329
|
-
if (ts.isObjectLiteralExpression(node) &&
|
|
2419
|
+
function lowerTlsServerOptionsOrDyn(L, node, what, includeHttpTimeoutOptions = false) {
|
|
2420
|
+
if (ts.isObjectLiteralExpression(node) &&
|
|
2421
|
+
!tlsLiteralNeedsRuntimeWalk(node, includeHttpTimeoutOptions)) {
|
|
2330
2422
|
return lowerTlsServerOptions(L, node, what);
|
|
2331
2423
|
}
|
|
2332
2424
|
const v = L.lowerExpr(node);
|
|
@@ -2669,7 +2761,7 @@ function lowerHttpsModuleCall(L, expr, bi, loc) {
|
|
|
2669
2761
|
if (args.length < 1 || args.length > 2) {
|
|
2670
2762
|
L.noLowering(`createServer with ${args.length} arguments`, expr, "the supported form is createServer({ cert, key }, (req, res) => ...)");
|
|
2671
2763
|
}
|
|
2672
|
-
const opts = lowerTlsServerOptionsOrDyn(L, args[0], "https.createServer");
|
|
2764
|
+
const opts = lowerTlsServerOptionsOrDyn(L, args[0], "https.createServer", true);
|
|
2673
2765
|
if (args.length === 1) {
|
|
2674
2766
|
// The handler-less form: 'request' listeners arrive later via
|
|
2675
2767
|
// server.on("request", ...) — the createSecureServer emission's
|