@scriptc/compiler 0.1.2 → 0.1.4

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 (206) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +258 -64
  2. package/dist/backend/c/async.d.ts +30 -0
  3. package/dist/backend/c/async.js +224 -0
  4. package/dist/backend/c/async.js.map +1 -1
  5. package/dist/backend/c/c-emitter.d.ts +13 -0
  6. package/dist/backend/c/c-emitter.js +28 -9
  7. package/dist/backend/c/c-emitter.js.map +1 -1
  8. package/dist/backend/c/exprs.d.ts +8 -1
  9. package/dist/backend/c/exprs.js +445 -60
  10. package/dist/backend/c/exprs.js.map +1 -1
  11. package/dist/backend/c/shapes.js +15 -13
  12. package/dist/backend/c/shapes.js.map +1 -1
  13. package/dist/backend/c/types.d.ts +4 -0
  14. package/dist/backend/c/types.js +20 -1
  15. package/dist/backend/c/types.js.map +1 -1
  16. package/dist/backend/c/types.test.js +8 -1
  17. package/dist/backend/c/types.test.js.map +1 -1
  18. package/dist/backend/c/walkers.js +32 -11
  19. package/dist/backend/c/walkers.js.map +1 -1
  20. package/dist/backend/json-literal.d.ts +7 -0
  21. package/dist/backend/json-literal.js +17 -0
  22. package/dist/backend/json-literal.js.map +1 -0
  23. package/dist/backend/json-literal.test.d.ts +1 -0
  24. package/dist/backend/json-literal.test.js +17 -0
  25. package/dist/backend/json-literal.test.js.map +1 -0
  26. package/dist/backend/link-plan.d.ts +2 -1
  27. package/dist/backend/link-plan.js +6 -1
  28. package/dist/backend/link-plan.js.map +1 -1
  29. package/dist/backend/llvm/classes.js +8 -7
  30. package/dist/backend/llvm/classes.js.map +1 -1
  31. package/dist/backend/llvm/common.d.ts +4 -0
  32. package/dist/backend/llvm/common.js +6 -0
  33. package/dist/backend/llvm/common.js.map +1 -1
  34. package/dist/backend/llvm/common.test.d.ts +1 -0
  35. package/dist/backend/llvm/common.test.js +9 -0
  36. package/dist/backend/llvm/common.test.js.map +1 -0
  37. package/dist/backend/llvm/dyn.d.ts +4 -0
  38. package/dist/backend/llvm/dyn.js +24 -13
  39. package/dist/backend/llvm/dyn.js.map +1 -1
  40. package/dist/backend/llvm/emitter.js +54 -12
  41. package/dist/backend/llvm/emitter.js.map +1 -1
  42. package/dist/backend/llvm/expr-bytes.d.ts +1 -1
  43. package/dist/backend/llvm/expr-bytes.js +8 -8
  44. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  45. package/dist/backend/llvm/expr-callbacks.d.ts +9 -0
  46. package/dist/backend/llvm/expr-callbacks.js +125 -0
  47. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  48. package/dist/backend/llvm/expr-context.d.ts +18 -2
  49. package/dist/backend/llvm/expr-dispatch.js +1 -0
  50. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  51. package/dist/backend/llvm/expr-dynamic.js +9 -0
  52. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  53. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  54. package/dist/backend/llvm/expr-primitives.js +38 -9
  55. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  56. package/dist/backend/llvm/expr-primitives.test.d.ts +1 -0
  57. package/dist/backend/llvm/expr-primitives.test.js +38 -0
  58. package/dist/backend/llvm/expr-primitives.test.js.map +1 -0
  59. package/dist/backend/llvm/expr-records.js +3 -3
  60. package/dist/backend/llvm/expr-records.js.map +1 -1
  61. package/dist/backend/llvm/expr-stream-bridges.js +2 -1
  62. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  63. package/dist/backend/llvm/expr-stream-callbacks.d.ts +6 -0
  64. package/dist/backend/llvm/expr-stream-callbacks.js +122 -0
  65. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  66. package/dist/backend/llvm/lib-dispatch.js +22 -0
  67. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  68. package/dist/backend/llvm/lib-filesystem.js +68 -10
  69. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  70. package/dist/backend/llvm/lib-network.js +18 -2
  71. package/dist/backend/llvm/lib-network.js.map +1 -1
  72. package/dist/backend/llvm/lib-process.js +206 -11
  73. package/dist/backend/llvm/lib-process.js.map +1 -1
  74. package/dist/backend/llvm/lib-shared.js +82 -0
  75. package/dist/backend/llvm/lib-shared.js.map +1 -1
  76. package/dist/backend/llvm/lib-stream.js +23 -0
  77. package/dist/backend/llvm/lib-stream.js.map +1 -1
  78. package/dist/backend/llvm/shapes.js +10 -8
  79. package/dist/backend/llvm/shapes.js.map +1 -1
  80. package/dist/backend/llvm/walkers.js +7 -5
  81. package/dist/backend/llvm/walkers.js.map +1 -1
  82. package/dist/backend/native-link-info.d.ts +2 -1
  83. package/dist/backend/native-link-info.js +4 -0
  84. package/dist/backend/native-link-info.js.map +1 -1
  85. package/dist/backend/native-link-info.test.js +24 -1
  86. package/dist/backend/native-link-info.test.js.map +1 -1
  87. package/dist/backend/native-toolchain.d.ts +11 -6
  88. package/dist/backend/native-toolchain.js +30 -13
  89. package/dist/backend/native-toolchain.js.map +1 -1
  90. package/dist/backend/native-toolchain.test.js +36 -1
  91. package/dist/backend/native-toolchain.test.js.map +1 -1
  92. package/dist/backend/runtime-pack-targets.test.js +1 -1
  93. package/dist/backend/runtime-pack-targets.test.js.map +1 -1
  94. package/dist/backend/runtime-pack.test.js +29 -10
  95. package/dist/backend/runtime-pack.test.js.map +1 -1
  96. package/dist/backend/targets.d.ts +9 -0
  97. package/dist/backend/targets.js +22 -0
  98. package/dist/backend/targets.js.map +1 -1
  99. package/dist/backend/targets.test.js +13 -1
  100. package/dist/backend/targets.test.js.map +1 -1
  101. package/dist/coverage/surface-manifest.js +9 -0
  102. package/dist/coverage/surface-manifest.js.map +1 -1
  103. package/dist/diagnostics/diagnostic.js +4 -4
  104. package/dist/diagnostics/diagnostic.js.map +1 -1
  105. package/dist/executable/executable-cache.d.ts +3 -0
  106. package/dist/executable/executable-cache.js +4 -0
  107. package/dist/executable/executable-cache.js.map +1 -1
  108. package/dist/executable/executable-cache.test.js +1 -0
  109. package/dist/executable/executable-cache.test.js.map +1 -1
  110. package/dist/frontend/fork-target.d.ts +17 -0
  111. package/dist/frontend/fork-target.js +256 -0
  112. package/dist/frontend/fork-target.js.map +1 -0
  113. package/dist/frontend/lowering/abstract-equality.d.ts +6 -0
  114. package/dist/frontend/lowering/abstract-equality.js +250 -0
  115. package/dist/frontend/lowering/abstract-equality.js.map +1 -0
  116. package/dist/frontend/lowering/containers/bytes.d.ts +0 -4
  117. package/dist/frontend/lowering/containers/bytes.js +112 -28
  118. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  119. package/dist/frontend/lowering/lower-assert.js +87 -12
  120. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  121. package/dist/frontend/lowering/lower-builtins.d.ts +72 -44
  122. package/dist/frontend/lowering/lower-builtins.js +1323 -165
  123. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  124. package/dist/frontend/lowering/lower-calls.d.ts +37 -27
  125. package/dist/frontend/lowering/lower-calls.js +682 -132
  126. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  127. package/dist/frontend/lowering/lower-classes.js +39 -8
  128. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  129. package/dist/frontend/lowering/lower-containers.js +162 -8
  130. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  131. package/dist/frontend/lowering/lower-event-emitter.js +212 -21
  132. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  133. package/dist/frontend/lowering/lower-exprs.js +238 -87
  134. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  135. package/dist/frontend/lowering/lower-inspect.d.ts +4 -0
  136. package/dist/frontend/lowering/lower-inspect.js +8 -1
  137. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  138. package/dist/frontend/lowering/lower-island.d.ts +6 -3
  139. package/dist/frontend/lowering/lower-island.js +165 -6
  140. package/dist/frontend/lowering/lower-island.js.map +1 -1
  141. package/dist/frontend/lowering/lower-modules.d.ts +6 -0
  142. package/dist/frontend/lowering/lower-modules.js +192 -38
  143. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  144. package/dist/frontend/lowering/lower-namespaces.js +7 -0
  145. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  146. package/dist/frontend/lowering/lower-server.d.ts +1 -1
  147. package/dist/frontend/lowering/lower-server.js +130 -27
  148. package/dist/frontend/lowering/lower-server.js.map +1 -1
  149. package/dist/frontend/lowering/lower-stmts.d.ts +5 -4
  150. package/dist/frontend/lowering/lower-stmts.js +141 -21
  151. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  152. package/dist/frontend/lowering/lower-stream.d.ts +3 -0
  153. package/dist/frontend/lowering/lower-stream.js +7 -0
  154. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  155. package/dist/frontend/lowering/lowerer.d.ts +90 -13
  156. package/dist/frontend/lowering/lowerer.js +416 -76
  157. package/dist/frontend/lowering/lowerer.js.map +1 -1
  158. package/dist/frontend/lowering/surfaces.d.ts +31 -3
  159. package/dist/frontend/lowering/surfaces.js +173 -90
  160. package/dist/frontend/lowering/surfaces.js.map +1 -1
  161. package/dist/frontend/npm-static-declarations.d.ts +4 -0
  162. package/dist/frontend/npm-static-declarations.js +83 -14
  163. package/dist/frontend/npm-static-declarations.js.map +1 -1
  164. package/dist/frontend/npm-static-declarations.test.js +33 -2
  165. package/dist/frontend/npm-static-declarations.test.js.map +1 -1
  166. package/dist/frontend/npm-static.js +6 -5
  167. package/dist/frontend/npm-static.js.map +1 -1
  168. package/dist/frontend/npm.d.ts +15 -3
  169. package/dist/frontend/npm.js +80 -8
  170. package/dist/frontend/npm.js.map +1 -1
  171. package/dist/frontend/npm.test.js +76 -9
  172. package/dist/frontend/npm.test.js.map +1 -1
  173. package/dist/frontend/program.js +110 -12
  174. package/dist/frontend/program.js.map +1 -1
  175. package/dist/frontend/resolve.d.ts +28 -7
  176. package/dist/frontend/resolve.js +90 -26
  177. package/dist/frontend/resolve.js.map +1 -1
  178. package/dist/frontend/resolve.test.js +21 -1
  179. package/dist/frontend/resolve.test.js.map +1 -1
  180. package/dist/frontend/type-mapper.d.ts +5 -0
  181. package/dist/frontend/type-mapper.js +115 -33
  182. package/dist/frontend/type-mapper.js.map +1 -1
  183. package/dist/index.d.ts +5 -0
  184. package/dist/index.js +30 -3
  185. package/dist/index.js.map +1 -1
  186. package/dist/ir/analysis.js +1 -0
  187. package/dist/ir/analysis.js.map +1 -1
  188. package/dist/ir/ir.d.ts +155 -66
  189. package/dist/ir/ir.js +143 -6
  190. package/dist/ir/ir.js.map +1 -1
  191. package/dist/ir/ir.test.js +14 -1
  192. package/dist/ir/ir.test.js.map +1 -1
  193. package/dist/ir/serialize.d.ts +1 -1
  194. package/dist/ir/serialize.js +1 -1
  195. package/dist/ir/serialize.js.map +1 -1
  196. package/dist/ir/validate.js +242 -18
  197. package/dist/ir/validate.js.map +1 -1
  198. package/dist/library/int-infer.test.js +4 -4
  199. package/dist/library/int-infer.test.js.map +1 -1
  200. package/dist/library/library-cache.d.ts +1 -0
  201. package/dist/library/library-cache.js +1 -0
  202. package/dist/library/library-cache.js.map +1 -1
  203. package/dist/library/library-cache.test.js +18 -5
  204. package/dist/library/library-cache.test.js.map +1 -1
  205. package/package.json +17 -17
  206. package/surface-manifest.json +163 -54
@@ -1517,6 +1517,14 @@ function headersSnapshotHelper(lowerer, shapeId, loc) {
1517
1517
  callArgs: [varRef("r.0", HTTPREQ_T, loc)],
1518
1518
  });
1519
1519
  }
1520
+ function trailersSnapshotHelper(lowerer, shapeId, loc) {
1521
+ return pairsSnapshotHelper(lowerer, shapeId, loc, {
1522
+ keyPrefix: "trailers",
1523
+ libCall: "http.reqTrailerPairs",
1524
+ params: [{ localId: "r.0", name: "r", type: HTTPREQ_T }],
1525
+ callArgs: [varRef("r.0", HTTPREQ_T, loc)],
1526
+ });
1527
+ }
1520
1528
  /** The `endStream` boolean of an h2 options object literal, as a literal
1521
1529
  * bool. Returns undefined when absent (or the arg is absent). Fences on
1522
1530
  * a non-literal endStream value or unknown keys that would matter. */
@@ -1829,11 +1837,12 @@ export function lowerServerProperty(lowerer, expr) {
1829
1837
  const fn = name === "aborted" ? "http.reqAborted" : "http.reqComplete";
1830
1838
  return { kind: "libCall", fn, args: [receiver], type: BOOL, loc };
1831
1839
  }
1832
- if (name === "rawHeaders") {
1840
+ if (name === "rawHeaders" || name === "rawTrailers") {
1833
1841
  // [name, value, name, value, ...] in arrival order, names in their
1834
1842
  // ORIGINAL case — Node's shape; a fresh string[] per read.
1835
1843
  const receiver = coerceToHandle(lowerer, expr.expression, HTTPREQ_T);
1836
- return { kind: "libCall", fn: "http.reqRawHeaders", args: [receiver], type: arrayOf(STRING), loc };
1844
+ const fn = name === "rawHeaders" ? "http.reqRawHeaders" : "http.reqRawTrailers";
1845
+ return { kind: "libCall", fn, args: [receiver], type: arrayOf(STRING), loc };
1837
1846
  }
1838
1847
  if (name === "statusMessage") {
1839
1848
  // `string | undefined` — the reason phrase on client responses (""
@@ -1870,19 +1879,24 @@ export function lowerServerProperty(lowerer, expr) {
1870
1879
  // guarded-no-op / unguarded-TypeError stance; other reads fence.
1871
1880
  lowerer.noLowering(`reading '${name}' (an HTTP/2-only member) from a request`, expr, "compatibility requests do not expose their backing h2 stream/session yet; guarded method calls no-op and other reads have no lowering");
1872
1881
  }
1873
- if (name === "headers") {
1882
+ if (name === "headers" || name === "trailers") {
1874
1883
  // `req.headers` as a VALUE — the `{ ...req.headers }` spread and
1875
1884
  // record flows: a fresh snapshot record per read (Node's spread
1876
1885
  // copies too; the per-name READS keep their direct lowerings).
1877
1886
  const mapped = lowerer.mapTypeOf(lowerer.typeOf(expr));
1878
1887
  if (mapped?.kind === "record") {
1879
- const helper = headersSnapshotHelper(lowerer, mapped.shapeId, loc);
1888
+ const helper = name === "headers"
1889
+ ? headersSnapshotHelper(lowerer, mapped.shapeId, loc)
1890
+ : trailersSnapshotHelper(lowerer, mapped.shapeId, loc);
1880
1891
  if (helper !== null) {
1881
1892
  const receiver = coerceToHandle(lowerer, expr.expression, HTTPREQ_T);
1882
1893
  return { kind: "call", callee: helper, args: [receiver], type: mapped, loc };
1883
1894
  }
1884
1895
  }
1885
- lowerer.unsupported("SC1090", expr, "req.headers as a value of this type (read one header: req.headers.name or req.headers[name])");
1896
+ lowerer.unsupported("SC1090", expr, `req.${name} as a value of this type (read one field: req.${name}.name or req.${name}[name])`);
1897
+ }
1898
+ if (name === "headersDistinct" || name === "trailersDistinct") {
1899
+ lowerer.unsupported("SC1090", expr, `req.${name} as a value (read one name with req.${name}[name])`);
1886
1900
  }
1887
1901
  }
1888
1902
  if (recvKind === "httpRes" && lowerer.isStdlibMember(expr) && expr.name.text === "stream") {
@@ -1951,15 +1965,28 @@ export function lowerServerProperty(lowerer, expr) {
1951
1965
  const receiver = coerceToHandle(lowerer, expr.expression, HTTPCLIENTREQ_T);
1952
1966
  return { kind: "libCall", fn: "http.clientDestroyed", args: [receiver], type: BOOL, loc };
1953
1967
  }
1954
- if (isHttpReqHeaders(lowerer, expr.expression)) {
1968
+ if (recvKind === "httpClientReq" && lowerer.isStdlibMember(expr) && expr.name.text === "writableCorked") {
1969
+ const receiver = coerceToHandle(lowerer, expr.expression, HTTPCLIENTREQ_T);
1970
+ return { kind: "libCall", fn: "http.clientWritableCorked", args: [receiver], type: F64, loc };
1971
+ }
1972
+ if (httpReqFieldCollection(lowerer, expr.expression) !== null) {
1973
+ const collection = httpReqFieldCollection(lowerer, expr.expression);
1955
1974
  const receiver = coerceToHandle(lowerer, expr.expression.expression, HTTPREQ_T);
1956
1975
  const key = { kind: "strLit", value: expr.name.text, type: STRING, loc };
1957
- return { kind: "libCall", fn: "http.reqHeader", args: [receiver, key], type: lowerer.envValueType(), loc };
1976
+ const fn = collection === "headers" ? "http.reqHeader"
1977
+ : collection === "trailers" ? "http.reqTrailer"
1978
+ : collection === "headersDistinct" ? "http.reqHeaderValues" : "http.reqTrailerValues";
1979
+ const type = collection.endsWith("Distinct") ? lowerer.withUndefinedArm(arrayOf(STRING)) : lowerer.envValueType();
1980
+ return { kind: "libCall", fn, args: [receiver, key], type, loc };
1958
1981
  }
1959
1982
  if (recvKind === "httpRes" && lowerer.isStdlibMember(expr) && expr.name.text === "headersSent") {
1960
1983
  const receiver = coerceToHandle(lowerer, expr.expression, HTTPRES_T);
1961
1984
  return { kind: "libCall", fn: "http.resHeadersSent", args: [receiver], type: BOOL, loc };
1962
1985
  }
1986
+ if (recvKind === "httpRes" && lowerer.isStdlibMember(expr) && expr.name.text === "writableCorked") {
1987
+ const receiver = coerceToHandle(lowerer, expr.expression, HTTPRES_T);
1988
+ return { kind: "libCall", fn: "http.resWritableCorked", args: [receiver], type: F64, loc };
1989
+ }
1963
1990
  if (recvKind === "httpRes" && lowerer.isStdlibMember(expr) && expr.name.text === "statusCode") {
1964
1991
  // 200 until assigned — Node's fresh-response default; the assignment
1965
1992
  // twin lives in lowerHttpResPropertyAssignment.
@@ -2084,6 +2111,7 @@ function lowerHttpServerOptions(lowerer, node, what) {
2084
2111
  lowerer.noLowering(`${what} with a non-literal options argument`, node, "pass the options as an object literal: { requireHostHeader?, joinDuplicateHeaders? }");
2085
2112
  }
2086
2113
  let joinDup = false;
2114
+ let allowMissingHost = false;
2087
2115
  let keepAliveTimeoutBuffer = null;
2088
2116
  for (const prop of node.properties) {
2089
2117
  let initializer;
@@ -2099,13 +2127,15 @@ function lowerHttpServerOptions(lowerer, node, what) {
2099
2127
  }
2100
2128
  const key = prop.name.text;
2101
2129
  if (key === "requireHostHeader") {
2102
- // The literal `false` only: it asks for exactly this parser's
2103
- // behavior (requests without Host are served). Node's default
2104
- // (true: answer 400) is the behavior this slice does not have, so
2105
- // `true`/dynamic values fence instead of silently not enforcing.
2106
- if (initializer === null || initializer.kind !== ts.SyntaxKind.FalseKeyword) {
2107
- lowerer.noLowering(`${what} with a non-\`false\` requireHostHeader option`, prop, "this parser never answers 400 for a missing Host header — requireHostHeader: false is the honest (and only) lowered value");
2130
+ if (initializer !== null && initializer.kind === ts.SyntaxKind.FalseKeyword) {
2131
+ allowMissingHost = true;
2132
+ continue;
2108
2133
  }
2134
+ if (initializer !== null && initializer.kind === ts.SyntaxKind.TrueKeyword) {
2135
+ allowMissingHost = false;
2136
+ continue;
2137
+ }
2138
+ lowerer.noLowering(`${what} with a non-literal requireHostHeader option`, prop, "the lowered forms are the literals requireHostHeader: true and false");
2109
2139
  continue;
2110
2140
  }
2111
2141
  if (key === "joinDuplicateHeaders") {
@@ -2116,7 +2146,8 @@ function lowerHttpServerOptions(lowerer, node, what) {
2116
2146
  continue;
2117
2147
  }
2118
2148
  if (initializer !== null && initializer.kind === ts.SyntaxKind.FalseKeyword) {
2119
- continue; /* Node's default: repeats keep the first value */
2149
+ joinDup = false; /* Node's default: repeats keep the first value */
2150
+ continue;
2120
2151
  }
2121
2152
  lowerer.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)");
2122
2153
  }
@@ -2139,10 +2170,10 @@ function lowerHttpServerOptions(lowerer, node, what) {
2139
2170
  keepAliveTimeoutBuffer = value;
2140
2171
  continue;
2141
2172
  }
2142
- fenceOrDropOptionKey(lowerer, prop, key, what, HTTP_SERVER_DOCUMENTED_OPTIONS, "requireHostHeader: false, joinDuplicateHeaders, and keepAliveTimeoutBuffer are the supported options");
2173
+ fenceOrDropOptionKey(lowerer, prop, key, what, HTTP_SERVER_DOCUMENTED_OPTIONS, "requireHostHeader, joinDuplicateHeaders, and keepAliveTimeoutBuffer are the supported options");
2143
2174
  // An undocumented key, dropped like Node drops it.
2144
2175
  }
2145
- return { joinDup, keepAliveTimeoutBuffer };
2176
+ return { joinDup, allowMissingHost, keepAliveTimeoutBuffer };
2146
2177
  }
2147
2178
  /** The shared createServer([options][, handler]) shapes behind
2148
2179
  * http.createServer, http.Server, and `new http.Server`: no arguments
@@ -2168,18 +2199,18 @@ function lowerHttpCreateServerForms(lowerer, expr, what, loc) {
2168
2199
  }
2169
2200
  const opts = optsNode !== null
2170
2201
  ? lowerHttpServerOptions(lowerer, optsNode, what)
2171
- : { joinDup: false, keepAliveTimeoutBuffer: null };
2202
+ : { joinDup: false, allowMissingHost: false, keepAliveTimeoutBuffer: null };
2172
2203
  const server = handlerNode !== null
2173
2204
  ? { kind: "libCall", fn: "http.createServer", args: [lowerRequestHandlerArg(lowerer, handlerNode)], type: NETSERVER_T, loc }
2174
2205
  : { kind: "libCall", fn: "http.createServerEmpty", args: [], type: NETSERVER_T, loc };
2175
- if (!opts.joinDup && opts.keepAliveTimeoutBuffer === null)
2206
+ if (!opts.joinDup && !opts.allowMissingHost && opts.keepAliveTimeoutBuffer === null)
2176
2207
  return server;
2177
2208
  // The option-setting composition: an interned helper takes the option
2178
2209
  // values first (preserving Node's options-before-handler evaluation
2179
2210
  // order), then the fresh server, applies the modeled fields, and answers
2180
2211
  // the server as the constructor/factory result.
2181
2212
  const hasBuffer = opts.keepAliveTimeoutBuffer !== null;
2182
- const key = `server.opts:${opts.joinDup ? 1 : 0}:${hasBuffer ? 1 : 0}`;
2213
+ const key = `server.opts:${opts.joinDup ? 1 : 0}:${opts.allowMissingHost ? 1 : 0}:${hasBuffer ? 1 : 0}`;
2183
2214
  const existing = lowerer.arrHofHelpers.get(key);
2184
2215
  const name = existing ?? `%server.opts.${lowerer.arrHofHelpers.size}`;
2185
2216
  if (!existing) {
@@ -2206,6 +2237,13 @@ function lowerHttpCreateServerForms(lowerer, expr, what, loc) {
2206
2237
  loc,
2207
2238
  });
2208
2239
  }
2240
+ if (opts.allowMissingHost) {
2241
+ body.push({
2242
+ kind: "exprStmt",
2243
+ expr: { kind: "libCall", fn: "http.serverAllowMissingHostHeader", args: [ref], type: VOID, loc },
2244
+ loc,
2245
+ });
2246
+ }
2209
2247
  body.push({ kind: "return", value: ref, loc });
2210
2248
  lowerer.liftedFns.push({
2211
2249
  name,
@@ -3593,6 +3631,28 @@ function lowerClientHeadersOption(lowerer, node) {
3593
3631
  }
3594
3632
  return { kind: "call", callee: helper, args: [v], type: arrayOf(STRING), loc };
3595
3633
  }
3634
+ /** OutgoingMessage.addTrailers accepts an object or a pair-list literal.
3635
+ * Flatten the latter in source order; non-literal nested arrays currently
3636
+ * fence rather than reaching the C runtime with the wrong wire shape. */
3637
+ function lowerHttpTrailersOption(lowerer, node) {
3638
+ if (!ts.isArrayLiteralExpression(node))
3639
+ return lowerClientHeadersOption(lowerer, node);
3640
+ const loc = locOf(node);
3641
+ const flat = [];
3642
+ for (const entry of node.elements) {
3643
+ if (!ts.isArrayLiteralExpression(entry) || entry.elements.length !== 2) {
3644
+ lowerer.noLowering("addTrailers pair list", entry, "use an object/Record or literal [name, value] pairs");
3645
+ }
3646
+ const pair = entry;
3647
+ const name = pair.elements[0];
3648
+ const value = pair.elements[1];
3649
+ if (ts.isSpreadElement(name) || ts.isSpreadElement(value)) {
3650
+ lowerer.noLowering("addTrailers pair with spread", entry, "use direct string name/value expressions");
3651
+ }
3652
+ flat.push(lowerer.lowerExprExpecting(name, STRING), lowerer.lowerExprExpecting(value, STRING));
3653
+ }
3654
+ return { kind: "arrayLit", elems: flat, type: arrayOf(STRING), loc };
3655
+ }
3596
3656
  /** Method calls on ClientRequest receivers: write/end/destroy and
3597
3657
  * on/once("response" | "error" | "timeout" | "close"). Null for other
3598
3658
  * receivers. */
@@ -3604,6 +3664,23 @@ function lowerHttpClientMethodCall(lowerer, call, access) {
3604
3664
  const name = access.name.text;
3605
3665
  const loc = locOf(call);
3606
3666
  const args = call.arguments;
3667
+ if (name === "flushHeaders" || name === "cork" || name === "uncork") {
3668
+ requireStatementPosition(lowerer, call, `request.${name}()`);
3669
+ if (args.length !== 0)
3670
+ lowerer.noLowering(`request.${name} with arguments`, call, `${name}() takes no arguments`);
3671
+ const receiver = coerceToHandle(lowerer, access.expression, HTTPCLIENTREQ_T);
3672
+ const fn = name === "flushHeaders" ? "http.clientFlushHeaders"
3673
+ : name === "cork" ? "http.clientCork" : "http.clientUncork";
3674
+ return { kind: "libCall", fn, args: [receiver], type: VOID, loc };
3675
+ }
3676
+ if (name === "addTrailers") {
3677
+ requireStatementPosition(lowerer, call, "request.addTrailers(...)");
3678
+ if (args.length !== 1)
3679
+ lowerer.noLowering("request.addTrailers argument count", call, "pass one trailer object or pair-list literal");
3680
+ const receiver = coerceToHandle(lowerer, access.expression, HTTPCLIENTREQ_T);
3681
+ const pairs = lowerHttpTrailersOption(lowerer, args[0]);
3682
+ return { kind: "libCall", fn: "http.clientAddTrailers", args: [receiver, pairs], type: VOID, loc };
3683
+ }
3607
3684
  if (name === "write" || name === "end") {
3608
3685
  requireStatementPosition(lowerer, call, `request.${name}(...)`);
3609
3686
  const minArgs = name === "write" ? 1 : 0;
@@ -3728,31 +3805,37 @@ export function lowerSocketInstanceOf(lowerer, expr, loc) {
3728
3805
  }
3729
3806
  /** True when `node` reads `.headers` off an IncomingMessage — the
3730
3807
  * receiver shape of both header-read forms. */
3731
- function isHttpReqHeaders(lowerer, node) {
3732
- return (ts.isPropertyAccessExpression(node) &&
3808
+ function httpReqFieldCollection(lowerer, node) {
3809
+ if (ts.isPropertyAccessExpression(node) &&
3733
3810
  !node.questionDotToken &&
3734
- node.name.text === "headers" &&
3811
+ (node.name.text === "headers" || node.name.text === "trailers" ||
3812
+ node.name.text === "headersDistinct" || node.name.text === "trailersDistinct") &&
3735
3813
  lowerer.mapTypeOf(lowerer.typeOf(node.expression))?.kind === "httpReq" &&
3736
- lowerer.isStdlibMember(node));
3814
+ lowerer.isStdlibMember(node))
3815
+ return node.name.text;
3816
+ return null;
3737
3817
  }
3738
3818
  /** `req.headers["x-name"]` — the element twin of the property read below;
3739
3819
  * called from lowerElementAccess (the process.env precedent). Answers the
3740
3820
  * interned `string | undefined` union; names match case-insensitively
3741
3821
  * (the runtime stores them lowercased, like Node). */
3742
3822
  export function lowerHttpHeadersElement(lowerer, expr) {
3743
- if (!isHttpReqHeaders(lowerer, expr.expression))
3823
+ const collection = httpReqFieldCollection(lowerer, expr.expression);
3824
+ if (collection === null)
3744
3825
  return null;
3745
3826
  const recv = expr.expression.expression;
3746
3827
  const key = lowerer.lowerExpr(expr.argumentExpression);
3747
3828
  if (key.type.kind !== "string") {
3748
- lowerer.unsupported("SC1090", expr.argumentExpression, "indexing req.headers with non-string keys");
3829
+ lowerer.unsupported("SC1090", expr.argumentExpression, `indexing req.${collection} with non-string keys`);
3749
3830
  }
3750
3831
  const receiver = lowerer.lowerExpr(recv);
3751
3832
  return {
3752
3833
  kind: "libCall",
3753
- fn: "http.reqHeader",
3834
+ fn: collection === "headers" ? "http.reqHeader"
3835
+ : collection === "trailers" ? "http.reqTrailer"
3836
+ : collection === "headersDistinct" ? "http.reqHeaderValues" : "http.reqTrailerValues",
3754
3837
  args: [receiver, key],
3755
- type: lowerer.envValueType(),
3838
+ type: collection.endsWith("Distinct") ? lowerer.withUndefinedArm(arrayOf(STRING)) : lowerer.envValueType(),
3756
3839
  loc: locOf(expr),
3757
3840
  };
3758
3841
  }
@@ -3848,6 +3931,26 @@ function lowerHttpResMethodCall(lowerer, call, access) {
3848
3931
  const name = access.name.text;
3849
3932
  const loc = locOf(call);
3850
3933
  const args = call.arguments;
3934
+ if (name === "flushHeaders" || name === "cork" || name === "uncork") {
3935
+ requireStatementPosition(lowerer, call, `res.${name}()`);
3936
+ if (args.length !== 0)
3937
+ lowerer.noLowering(`res.${name} with arguments`, call, `${name}() takes no arguments`);
3938
+ const receiver = coerceToHandle(lowerer, access.expression, HTTPRES_T);
3939
+ const fn = name === "flushHeaders" ? "http.resFlushHeaders"
3940
+ : name === "cork" ? "http.resCork" : "http.resUncork";
3941
+ return { kind: "libCall", fn, args: [receiver], type: VOID, loc };
3942
+ }
3943
+ if (name === "addTrailers") {
3944
+ requireStatementPosition(lowerer, call, "res.addTrailers(...)");
3945
+ if (lowerer.typeOf(access.expression).getSymbol()?.name === "Http2ServerResponse") {
3946
+ lowerer.noLowering("Http2ServerResponse.addTrailers", call, "HTTP/2 response trailers are not supported by the static runtime yet");
3947
+ }
3948
+ if (args.length !== 1)
3949
+ lowerer.noLowering("res.addTrailers argument count", call, "pass one trailer object or pair-list literal");
3950
+ const receiver = coerceToHandle(lowerer, access.expression, HTTPRES_T);
3951
+ const pairs = lowerHttpTrailersOption(lowerer, args[0]);
3952
+ return { kind: "libCall", fn: "http.resAddTrailers", args: [receiver, pairs], type: VOID, loc };
3953
+ }
3851
3954
  if (name === "setHeader") {
3852
3955
  requireStatementPosition(lowerer, call, "res.setHeader(...)");
3853
3956
  if (args.length !== 2) {