@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.
Files changed (66) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +15 -7
  2. package/dist/backend/cc.d.ts +3 -0
  3. package/dist/backend/cc.js +37 -4
  4. package/dist/backend/cc.js.map +1 -1
  5. package/dist/backend/emission/emit-exprs.js +81 -10
  6. package/dist/backend/emission/emit-exprs.js.map +1 -1
  7. package/dist/backend/emission/emitter.d.ts +14 -1
  8. package/dist/backend/emission/emitter.js +117 -11
  9. package/dist/backend/emission/emitter.js.map +1 -1
  10. package/dist/backend/emission/may-throw.js +11 -1
  11. package/dist/backend/emission/may-throw.js.map +1 -1
  12. package/dist/backend/ffi-callbacks.d.ts +11 -0
  13. package/dist/backend/ffi-callbacks.js +33 -0
  14. package/dist/backend/ffi-callbacks.js.map +1 -0
  15. package/dist/backend/llvm/classes.js +21 -21
  16. package/dist/backend/llvm/classes.js.map +1 -1
  17. package/dist/backend/llvm/dyn.d.ts +7 -4
  18. package/dist/backend/llvm/dyn.js +145 -141
  19. package/dist/backend/llvm/dyn.js.map +1 -1
  20. package/dist/backend/llvm/emitter.d.ts +7 -1
  21. package/dist/backend/llvm/emitter.js +950 -300
  22. package/dist/backend/llvm/emitter.js.map +1 -1
  23. package/dist/backend/llvm/shapes.d.ts +4 -0
  24. package/dist/backend/llvm/shapes.js +26 -24
  25. package/dist/backend/llvm/shapes.js.map +1 -1
  26. package/dist/backend/llvm/unsupported.js +1 -1
  27. package/dist/backend/llvm/unsupported.js.map +1 -1
  28. package/dist/backend/llvm/walkers.d.ts +2 -0
  29. package/dist/backend/llvm/walkers.js +50 -46
  30. package/dist/backend/llvm/walkers.js.map +1 -1
  31. package/dist/coverage/surface-manifest.js +1 -1
  32. package/dist/coverage/surface-manifest.js.map +1 -1
  33. package/dist/diagnostics/diagnostic.d.ts +1 -1
  34. package/dist/diagnostics/diagnostic.js +3 -2
  35. package/dist/diagnostics/diagnostic.js.map +1 -1
  36. package/dist/ffi/profile.d.ts +20 -2
  37. package/dist/ffi/profile.js +130 -6
  38. package/dist/ffi/profile.js.map +1 -1
  39. package/dist/frontend/lowering/lower-calls.js +58 -22
  40. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  41. package/dist/frontend/lowering/lower-exprs.js +17 -7
  42. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  43. package/dist/frontend/lowering/lower-server.d.ts +5 -0
  44. package/dist/frontend/lowering/lower-server.js +129 -37
  45. package/dist/frontend/lowering/lower-server.js.map +1 -1
  46. package/dist/frontend/lowering/lower-stmts.js +8 -1
  47. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  48. package/dist/frontend/lowering/surfaces.d.ts +3 -2
  49. package/dist/frontend/lowering/surfaces.js +4 -3
  50. package/dist/frontend/lowering/surfaces.js.map +1 -1
  51. package/dist/frontend/npm.d.ts +16 -0
  52. package/dist/frontend/npm.js +257 -0
  53. package/dist/frontend/npm.js.map +1 -1
  54. package/dist/index.d.ts +7 -4
  55. package/dist/index.js +152 -5
  56. package/dist/index.js.map +1 -1
  57. package/dist/ir/nodes.d.ts +48 -13
  58. package/dist/ir/nodes.js +49 -7
  59. package/dist/ir/nodes.js.map +1 -1
  60. package/dist/ir/validate.js +10 -22
  61. package/dist/ir/validate.js.map +1 -1
  62. package/dist/wasi-paths.d.ts +5 -0
  63. package/dist/wasi-paths.js +22 -0
  64. package/dist/wasi-paths.js.map +1 -0
  65. package/package.json +2 -2
  66. 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?, ... }: the two lowered keys are exactly the
1983
- * parser behaviors this runtime has (requireHostHeader: false IS the
1984
- * parser's stance — it never answers 400 for a missing Host;
1985
- * joinDuplicateHeaders: true joins repeated request-header reads with
1986
- * ", "). Other documented keys fence by name; unknown keys drop like
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
- fenceOrDropOptionKey(L, prop, key, what, HTTP_SERVER_DOCUMENTED_OPTIONS, "requireHostHeader: false and joinDuplicateHeaders are the supported options");
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). joinDuplicateHeaders wraps the construction in the
2037
- * flag-setting helper. */
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 joinDup = optsNode !== null && lowerHttpServerOptions(L, optsNode, what).joinDup;
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 flag-setting composition: an interned helper takes the fresh
2062
- // server, sets the parser flag, and answers it — one expression.
2063
- const key = `server.joindup`;
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.joindup.${L.arrHofHelpers.size}`;
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: [{ localId: "s.0", name: "s", type: NETSERVER_T }],
2161
+ params,
2072
2162
  returnType: NETSERVER_T,
2073
- locals: [{ id: "s.0", name: "s", type: NETSERVER_T, mutable: false }],
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 { kind: "call", callee: name, args: [server], type: NETSERVER_T, loc };
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 carries a runtime-validated key (and
2320
- * the source is JS — TypeScript keeps its compile fences). */
2321
- function tlsLiteralNeedsRuntimeWalk(node) {
2322
- if (!isJsSourceFile(node.getSourceFile()))
2323
- return false;
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
- TLS_VALIDATED_OPTIONS.has(p.name.text));
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) && !tlsLiteralNeedsRuntimeWalk(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