@scriptc/compiler 0.3.5 → 0.3.6

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 (181) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +278 -32
  2. package/dist/backend/llvm/dyn.js +31 -1
  3. package/dist/backend/llvm/dyn.js.map +1 -1
  4. package/dist/backend/llvm/emitter.d.ts +45 -1
  5. package/dist/backend/llvm/emitter.js +412 -104
  6. package/dist/backend/llvm/emitter.js.map +1 -1
  7. package/dist/backend/llvm/expr-dispatch.js +1 -0
  8. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  9. package/dist/backend/llvm/expr-dynamic.js +25 -1
  10. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  11. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  12. package/dist/backend/llvm/expr-primitives.js +11 -0
  13. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  14. package/dist/backend/llvm/lib-dispatch.js +28 -1
  15. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  16. package/dist/backend/llvm/lib-filesystem.js +61 -1
  17. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  18. package/dist/backend/llvm/lib-network.js +21 -3
  19. package/dist/backend/llvm/lib-network.js.map +1 -1
  20. package/dist/backend/llvm/lib-process.js +10 -0
  21. package/dist/backend/llvm/lib-process.js.map +1 -1
  22. package/dist/backend/llvm/lib-shared.js +43 -0
  23. package/dist/backend/llvm/lib-shared.js.map +1 -1
  24. package/dist/backend/llvm/lib-test.js +16 -3
  25. package/dist/backend/llvm/lib-test.js.map +1 -1
  26. package/dist/backend/llvm/nullable-unions.d.ts +6 -3
  27. package/dist/backend/llvm/nullable-unions.js +2 -0
  28. package/dist/backend/llvm/nullable-unions.js.map +1 -1
  29. package/dist/backend/llvm/record-results.d.ts +1 -1
  30. package/dist/backend/llvm/record-results.js +2 -2
  31. package/dist/backend/llvm/record-results.js.map +1 -1
  32. package/dist/backend/llvm/reference-writes.js +1 -0
  33. package/dist/backend/llvm/reference-writes.js.map +1 -1
  34. package/dist/backend/llvm/shapes.d.ts +3 -0
  35. package/dist/backend/llvm/shapes.js +5 -0
  36. package/dist/backend/llvm/shapes.js.map +1 -1
  37. package/dist/backend/llvm/speculative-integers.d.ts +74 -0
  38. package/dist/backend/llvm/speculative-integers.js +571 -0
  39. package/dist/backend/llvm/speculative-integers.js.map +1 -0
  40. package/dist/backend/llvm/speculative-integers.test.d.ts +1 -0
  41. package/dist/backend/llvm/speculative-integers.test.js +148 -0
  42. package/dist/backend/llvm/speculative-integers.test.js.map +1 -0
  43. package/dist/backend/may-throw.js +2 -0
  44. package/dist/backend/may-throw.js.map +1 -1
  45. package/dist/backend/native/executable.js +3 -0
  46. package/dist/backend/native/executable.js.map +1 -1
  47. package/dist/backend/native/runtime-inputs.d.ts +1 -1
  48. package/dist/backend/native/runtime-inputs.js +1 -0
  49. package/dist/backend/native/runtime-inputs.js.map +1 -1
  50. package/dist/backend/runtime-pack.d.ts +7 -3
  51. package/dist/backend/runtime-pack.js +12 -6
  52. package/dist/backend/runtime-pack.js.map +1 -1
  53. package/dist/backend/runtime-pack.test.js +15 -6
  54. package/dist/backend/runtime-pack.test.js.map +1 -1
  55. package/dist/contracts/check.js +1 -0
  56. package/dist/contracts/check.js.map +1 -1
  57. package/dist/coverage/surface-manifest.js +3 -3
  58. package/dist/coverage/surface-manifest.js.map +1 -1
  59. package/dist/diagnostics/diagnostic.d.ts +1 -1
  60. package/dist/diagnostics/diagnostic.js +6 -2
  61. package/dist/diagnostics/diagnostic.js.map +1 -1
  62. package/dist/frontend/lowering/builtin-calls.js +10 -0
  63. package/dist/frontend/lowering/builtin-calls.js.map +1 -1
  64. package/dist/frontend/lowering/builtins/callable-aliases.js +31 -3
  65. package/dist/frontend/lowering/builtins/callable-aliases.js.map +1 -1
  66. package/dist/frontend/lowering/builtins/compression.d.ts +9 -0
  67. package/dist/frontend/lowering/builtins/compression.js +145 -30
  68. package/dist/frontend/lowering/builtins/compression.js.map +1 -1
  69. package/dist/frontend/lowering/builtins/crypto.js +12 -1
  70. package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
  71. package/dist/frontend/lowering/builtins/errors.js +5 -3
  72. package/dist/frontend/lowering/builtins/errors.js.map +1 -1
  73. package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +4 -0
  74. package/dist/frontend/lowering/builtins/filesystem-calls.js +11 -0
  75. package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
  76. package/dist/frontend/lowering/builtins/filesystem.d.ts +8 -0
  77. package/dist/frontend/lowering/builtins/filesystem.js +139 -2
  78. package/dist/frontend/lowering/builtins/filesystem.js.map +1 -1
  79. package/dist/frontend/lowering/builtins/hash-stream.d.ts +12 -0
  80. package/dist/frontend/lowering/builtins/hash-stream.js +80 -0
  81. package/dist/frontend/lowering/builtins/hash-stream.js.map +1 -0
  82. package/dist/frontend/lowering/builtins/module-calls.js +13 -3
  83. package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
  84. package/dist/frontend/lowering/builtins/process.js +9 -2
  85. package/dist/frontend/lowering/builtins/process.js.map +1 -1
  86. package/dist/frontend/lowering/builtins/readline.d.ts +45 -13
  87. package/dist/frontend/lowering/builtins/readline.js +812 -47
  88. package/dist/frontend/lowering/builtins/readline.js.map +1 -1
  89. package/dist/frontend/lowering/builtins/workers.d.ts +4 -0
  90. package/dist/frontend/lowering/builtins/workers.js +58 -0
  91. package/dist/frontend/lowering/builtins/workers.js.map +1 -1
  92. package/dist/frontend/lowering/class-protocols.d.ts +55 -0
  93. package/dist/frontend/lowering/class-protocols.js +735 -0
  94. package/dist/frontend/lowering/class-protocols.js.map +1 -1
  95. package/dist/frontend/lowering/containers/array-from-async.d.ts +18 -0
  96. package/dist/frontend/lowering/containers/array-from-async.js +282 -0
  97. package/dist/frontend/lowering/containers/array-from-async.js.map +1 -0
  98. package/dist/frontend/lowering/containers/collection-grouping.js +2 -1
  99. package/dist/frontend/lowering/containers/collection-grouping.js.map +1 -1
  100. package/dist/frontend/lowering/containers/collection-methods.js +27 -23
  101. package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
  102. package/dist/frontend/lowering/divergences.js +188 -15
  103. package/dist/frontend/lowering/divergences.js.map +1 -1
  104. package/dist/frontend/lowering/lower-calls.js +71 -22
  105. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  106. package/dist/frontend/lowering/lower-classes.js +39 -1
  107. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  108. package/dist/frontend/lowering/lower-event-emitter.js +10 -1
  109. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  110. package/dist/frontend/lowering/lower-exprs.js +107 -13
  111. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  112. package/dist/frontend/lowering/lower-inspect.js +23 -3
  113. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  114. package/dist/frontend/lowering/lower-mock.d.ts +11 -1
  115. package/dist/frontend/lowering/lower-mock.js +377 -61
  116. package/dist/frontend/lowering/lower-mock.js.map +1 -1
  117. package/dist/frontend/lowering/lower-modules.js +1 -0
  118. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  119. package/dist/frontend/lowering/lower-server.js +161 -16
  120. package/dist/frontend/lowering/lower-server.js.map +1 -1
  121. package/dist/frontend/lowering/lower-stmts.js +48 -7
  122. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  123. package/dist/frontend/lowering/lower-stream.d.ts +1 -3
  124. package/dist/frontend/lowering/lower-stream.js +317 -20
  125. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  126. package/dist/frontend/lowering/lower-test.js +147 -48
  127. package/dist/frontend/lowering/lower-test.js.map +1 -1
  128. package/dist/frontend/lowering/lowerer.d.ts +10 -0
  129. package/dist/frontend/lowering/lowerer.js +8 -0
  130. package/dist/frontend/lowering/lowerer.js.map +1 -1
  131. package/dist/frontend/lowering/null-prototype.d.ts +13 -0
  132. package/dist/frontend/lowering/null-prototype.js +33 -0
  133. package/dist/frontend/lowering/null-prototype.js.map +1 -0
  134. package/dist/frontend/lowering/surfaces.d.ts +3 -3
  135. package/dist/frontend/lowering/surfaces.js +27 -5
  136. package/dist/frontend/lowering/surfaces.js.map +1 -1
  137. package/dist/frontend/mock-shapes.d.ts +5 -0
  138. package/dist/frontend/mock-shapes.js +27 -2
  139. package/dist/frontend/mock-shapes.js.map +1 -1
  140. package/dist/frontend/program.js +5 -4
  141. package/dist/frontend/program.js.map +1 -1
  142. package/dist/frontend/type-mapper.js +95 -4
  143. package/dist/frontend/type-mapper.js.map +1 -1
  144. package/dist/index.js +18 -8
  145. package/dist/index.js.map +1 -1
  146. package/dist/ir/builtin-effects.js +36 -0
  147. package/dist/ir/builtin-effects.js.map +1 -1
  148. package/dist/ir/builtin-signatures.d.ts +1 -1
  149. package/dist/ir/builtin-signatures.js +167 -6
  150. package/dist/ir/builtin-signatures.js.map +1 -1
  151. package/dist/ir/function-references.test.js +1 -0
  152. package/dist/ir/function-references.test.js.map +1 -1
  153. package/dist/ir/int32-slots.js +22 -0
  154. package/dist/ir/int32-slots.js.map +1 -1
  155. package/dist/ir/int32-slots.test.js +28 -0
  156. package/dist/ir/int32-slots.test.js.map +1 -1
  157. package/dist/ir/integer-loop-facts.d.ts +14 -6
  158. package/dist/ir/integer-loop-facts.js +119 -35
  159. package/dist/ir/integer-loop-facts.js.map +1 -1
  160. package/dist/ir/integer-ranges.js +1 -5
  161. package/dist/ir/integer-ranges.js.map +1 -1
  162. package/dist/ir/integer-ranges.test.js +60 -0
  163. package/dist/ir/integer-ranges.test.js.map +1 -1
  164. package/dist/ir/ir.d.ts +13 -0
  165. package/dist/ir/ir.js +4 -0
  166. package/dist/ir/ir.js.map +1 -1
  167. package/dist/ir/runtime-features.d.ts +3 -1
  168. package/dist/ir/runtime-features.js +96 -6
  169. package/dist/ir/runtime-features.js.map +1 -1
  170. package/dist/ir/runtime-features.test.js +62 -0
  171. package/dist/ir/runtime-features.test.js.map +1 -1
  172. package/dist/ir/traverse.js +4 -0
  173. package/dist/ir/traverse.js.map +1 -1
  174. package/dist/ir/validate.js +45 -3
  175. package/dist/ir/validate.js.map +1 -1
  176. package/dist/ir/validate.test.js +38 -0
  177. package/dist/ir/validate.test.js.map +1 -1
  178. package/dist/library/ir-policy.js +5 -0
  179. package/dist/library/ir-policy.js.map +1 -1
  180. package/package.json +20 -20
  181. package/surface-manifest.json +31 -19
@@ -1389,6 +1389,18 @@ function lowerNetServerMethodCall(lowerer, call, access) {
1389
1389
  loc,
1390
1390
  };
1391
1391
  }
1392
+ if (event === "checkContinue" || event === "checkExpectation") {
1393
+ // Expect handling: these listeners take the request instead of
1394
+ // 'request' (checkContinue answers with res.writeContinue()).
1395
+ const cb = lowerRequestHandlerArg(lowerer, args[1]);
1396
+ return {
1397
+ kind: "libCall",
1398
+ fn: "http.serverOnCheck",
1399
+ args: [receiver, cb, once, boolLit(event === "checkExpectation", loc)],
1400
+ type: VOID,
1401
+ loc,
1402
+ };
1403
+ }
1392
1404
  if (event === "request") {
1393
1405
  // The 'request' event — http.createServer(handler)'s event twin, and
1394
1406
  // the way an http2 allowHTTP1 server (created handler-less) gets its
@@ -1522,7 +1534,7 @@ function lowerNetServerMethodCall(lowerer, call, access) {
1522
1534
  loc,
1523
1535
  };
1524
1536
  }
1525
- lowerer.noLowering(`server.${name}(${event === null ? "non-literal event" : `"${event}"`}, ...)`, args[0], '"connection", "request", "drop", "stream", "session", "upgrade", "connect", "error", "close", "listening", and "sessionError" are the supported server events (as literals)');
1537
+ lowerer.noLowering(`server.${name}(${event === null ? "non-literal event" : `"${event}"`}, ...)`, args[0], '"connection", "request", "checkContinue", "checkExpectation", "drop", "stream", "session", "upgrade", "connect", "error", "close", "listening", and "sessionError" are the supported server events (as literals)');
1526
1538
  }
1527
1539
  if (name === "emit") {
1528
1540
  // The demux route: emit("connection", socket) hands an accepted
@@ -3067,6 +3079,7 @@ function lowerHttpServerOptions(lowerer, node, what) {
3067
3079
  let joinDup = false;
3068
3080
  let allowMissingHost = false;
3069
3081
  let keepAliveTimeoutBuffer = null;
3082
+ let maxHeaderSize = null;
3070
3083
  for (const prop of node.properties) {
3071
3084
  let initializer;
3072
3085
  if (ts.isPropertyAssignment(prop) &&
@@ -3105,6 +3118,17 @@ function lowerHttpServerOptions(lowerer, node, what) {
3105
3118
  }
3106
3119
  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)');
3107
3120
  }
3121
+ if (key === "maxHeaderSize") {
3122
+ // The header size bound (Node's validateInteger runs in the runtime).
3123
+ const raw = initializer !== null
3124
+ ? lowerer.lowerExpr(initializer)
3125
+ : lowerer.lowerShorthandValue(prop);
3126
+ if (raw.type.kind !== "f64") {
3127
+ lowerer.noLowering(`${what} with a '${lowerer.fmt(raw.type)}' maxHeaderSize option`, prop, "maxHeaderSize is a number");
3128
+ }
3129
+ maxHeaderSize = raw;
3130
+ continue;
3131
+ }
3108
3132
  if (key === "keepAliveTimeoutBuffer") {
3109
3133
  if (keepAliveTimeoutBuffer !== null) {
3110
3134
  lowerer.noLowering(`${what} with duplicate keepAliveTimeoutBuffer options`, prop, "write keepAliveTimeoutBuffer once in the options literal");
@@ -3124,10 +3148,10 @@ function lowerHttpServerOptions(lowerer, node, what) {
3124
3148
  keepAliveTimeoutBuffer = value;
3125
3149
  continue;
3126
3150
  }
3127
- fenceOrDropOptionKey(lowerer, prop, key, what, HTTP_SERVER_DOCUMENTED_OPTIONS, "requireHostHeader, joinDuplicateHeaders, and keepAliveTimeoutBuffer are the supported options");
3151
+ fenceOrDropOptionKey(lowerer, prop, key, what, HTTP_SERVER_DOCUMENTED_OPTIONS, "requireHostHeader, joinDuplicateHeaders, keepAliveTimeoutBuffer, and maxHeaderSize are the supported options");
3128
3152
  // An undocumented key, dropped like Node drops it.
3129
3153
  }
3130
- return { joinDup, allowMissingHost, keepAliveTimeoutBuffer };
3154
+ return { joinDup, allowMissingHost, keepAliveTimeoutBuffer, maxHeaderSize };
3131
3155
  }
3132
3156
  /** The shared createServer([options][, handler]) shapes behind
3133
3157
  * http.createServer, http.Server, and `new http.Server`: no arguments
@@ -3153,7 +3177,12 @@ function lowerHttpCreateServerForms(lowerer, expr, what, loc) {
3153
3177
  }
3154
3178
  const opts = optsNode !== null
3155
3179
  ? lowerHttpServerOptions(lowerer, optsNode, what)
3156
- : { joinDup: false, allowMissingHost: false, keepAliveTimeoutBuffer: null };
3180
+ : {
3181
+ joinDup: false,
3182
+ allowMissingHost: false,
3183
+ keepAliveTimeoutBuffer: null,
3184
+ maxHeaderSize: null,
3185
+ };
3157
3186
  const server = handlerNode !== null
3158
3187
  ? {
3159
3188
  kind: "libCall",
@@ -3163,20 +3192,25 @@ function lowerHttpCreateServerForms(lowerer, expr, what, loc) {
3163
3192
  loc,
3164
3193
  }
3165
3194
  : { kind: "libCall", fn: "http.createServerEmpty", args: [], type: NETSERVER_T, loc };
3166
- if (!opts.joinDup && !opts.allowMissingHost && opts.keepAliveTimeoutBuffer === null)
3195
+ if (!opts.joinDup &&
3196
+ !opts.allowMissingHost &&
3197
+ opts.keepAliveTimeoutBuffer === null &&
3198
+ opts.maxHeaderSize === null)
3167
3199
  return server;
3168
3200
  // The option-setting composition: an interned helper takes the option
3169
3201
  // values first (preserving Node's options-before-handler evaluation
3170
3202
  // order), then the fresh server, applies the modeled fields, and answers
3171
3203
  // the server as the constructor/factory result.
3172
3204
  const hasBuffer = opts.keepAliveTimeoutBuffer !== null;
3173
- const key = `server.opts:${opts.joinDup ? 1 : 0}:${opts.allowMissingHost ? 1 : 0}:${hasBuffer ? 1 : 0}`;
3205
+ const hasMax = opts.maxHeaderSize !== null;
3206
+ const key = `server.opts:${opts.joinDup ? 1 : 0}:${opts.allowMissingHost ? 1 : 0}:${hasBuffer ? 1 : 0}:${hasMax ? 1 : 0}`;
3174
3207
  const existing = lowerer.arrHofHelpers.get(key);
3175
3208
  const name = existing ?? `%server.opts.${lowerer.arrHofHelpers.size}`;
3176
3209
  if (!existing) {
3177
3210
  lowerer.arrHofHelpers.set(key, name);
3178
3211
  const params = [
3179
3212
  ...(hasBuffer ? [{ localId: "b.0", name: "buffer", type: DYN }] : []),
3213
+ ...(hasMax ? [{ localId: "m.0", name: "maxHeaderSize", type: F64 }] : []),
3180
3214
  { localId: "s.0", name: "s", type: NETSERVER_T },
3181
3215
  ];
3182
3216
  const ref = { kind: "varRef", localId: "s.0", type: NETSERVER_T, loc };
@@ -3196,6 +3230,19 @@ function lowerHttpCreateServerForms(lowerer, expr, what, loc) {
3196
3230
  loc,
3197
3231
  });
3198
3232
  }
3233
+ if (hasMax) {
3234
+ body.push({
3235
+ kind: "exprStmt",
3236
+ expr: {
3237
+ kind: "libCall",
3238
+ fn: "http.serverMaxHeaderSize",
3239
+ args: [ref, { kind: "varRef", localId: "m.0", type: F64, loc }],
3240
+ type: VOID,
3241
+ loc,
3242
+ },
3243
+ loc,
3244
+ });
3245
+ }
3199
3246
  if (opts.joinDup) {
3200
3247
  body.push({
3201
3248
  kind: "exprStmt",
@@ -3229,7 +3276,11 @@ function lowerHttpCreateServerForms(lowerer, expr, what, loc) {
3229
3276
  return {
3230
3277
  kind: "call",
3231
3278
  callee: name,
3232
- args: [...(opts.keepAliveTimeoutBuffer !== null ? [opts.keepAliveTimeoutBuffer] : []), server],
3279
+ args: [
3280
+ ...(opts.keepAliveTimeoutBuffer !== null ? [opts.keepAliveTimeoutBuffer] : []),
3281
+ ...(opts.maxHeaderSize !== null ? [opts.maxHeaderSize] : []),
3282
+ server,
3283
+ ],
3233
3284
  type: NETSERVER_T,
3234
3285
  loc,
3235
3286
  };
@@ -4505,6 +4556,12 @@ function lowerHttpClientCall(lowerer, expr, member, loc, secure = false) {
4505
4556
  let agentClose = null;
4506
4557
  /** agent: <Agent value> — the requestAgent rows thread the handle. */
4507
4558
  let agentVal = null;
4559
+ /** signal: an AbortSignal (checked at runtime) that destroys the request. */
4560
+ let signal = null;
4561
+ /** servername: the TLS name for SNI and certificate verification. */
4562
+ let servername = null;
4563
+ /** maxHeaderSize: the response head's size bound. */
4564
+ let maxHeaderSize = null;
4508
4565
  for (const prop of optsNode.properties) {
4509
4566
  // Shorthand entries ({ port } for { port: port }) are the natural
4510
4567
  // spelling at these call sites — the shorthand's VALUE lowering
@@ -4596,6 +4653,22 @@ function lowerHttpClientCall(lowerer, expr, member, loc, secure = false) {
4596
4653
  case "timeout":
4597
4654
  timeout = lowerVal("f64");
4598
4655
  break;
4656
+ case "maxHeaderSize":
4657
+ maxHeaderSize = lowerVal("f64");
4658
+ break;
4659
+ case "servername":
4660
+ if (!secureish) {
4661
+ lowerer.noLowering(`${member} option 'servername'`, prop, "servername is an https.request option — the plain http client has no TLS layer");
4662
+ }
4663
+ servername = lowerVal("string");
4664
+ break;
4665
+ case "signal": {
4666
+ const v = initializer !== null
4667
+ ? lowerer.lowerExpr(initializer)
4668
+ : lowerer.lowerShorthandValue(prop);
4669
+ signal = lowerer.coerceToExpected(v, DYN);
4670
+ break;
4671
+ }
4599
4672
  case "headers":
4600
4673
  if (initializer === null) {
4601
4674
  lowerer.noLowering(`${member} with a shorthand headers option`, prop, "spell it out: headers: theHeaders");
@@ -4680,8 +4753,8 @@ function lowerHttpClientCall(lowerer, expr, member, loc, secure = false) {
4680
4753
  }
4681
4754
  default:
4682
4755
  fenceOrDropOptionKey(lowerer, prop, key, member, secureish ? HTTPS_CLIENT_DOCUMENTED_OPTIONS : HTTP_CLIENT_DOCUMENTED_OPTIONS, secureish
4683
- ? "hostname/host, port, path, method, timeout, headers, agent, rejectUnauthorized, and ca are the supported options"
4684
- : "hostname/host, port, path, method, timeout, headers, and agent are the supported options");
4756
+ ? "hostname/host, port, path, method, timeout, headers, agent, signal, maxHeaderSize, rejectUnauthorized, ca, and servername are the supported options"
4757
+ : "hostname/host, port, path, method, timeout, headers, agent, signal, and maxHeaderSize are the supported options");
4685
4758
  }
4686
4759
  }
4687
4760
  if (agentClose !== null) {
@@ -4747,19 +4820,69 @@ function lowerHttpClientCall(lowerer, expr, member, loc, secure = false) {
4747
4820
  timeout ??= numLit(0, loc);
4748
4821
  headers ??= { kind: "arrayLit", elems: [], type: arrayOf(STRING), loc };
4749
4822
  const autoEnd = boolLit(member === "get", loc);
4823
+ // Options applied to the built request: servername before the TLS
4824
+ // handshake starts, then options.signal (an already aborted signal
4825
+ // destroys the request at once, like Node's constructor).
4826
+ const withSignal = (request) => {
4827
+ if (signal === null && servername === null && maxHeaderSize === null)
4828
+ return request;
4829
+ const local = lowerer.declareHiddenLocal("%requestOptions", HTTPCLIENTREQ_T);
4830
+ const ref = () => varRef(local.id, HTTPCLIENTREQ_T, loc);
4831
+ const steps = [{ kind: "varDecl", localId: local.id, init: request, loc }];
4832
+ if (maxHeaderSize !== null) {
4833
+ steps.push({
4834
+ kind: "exprStmt",
4835
+ expr: {
4836
+ kind: "libCall",
4837
+ fn: "http.clientMaxHeaderSize",
4838
+ args: [ref(), maxHeaderSize],
4839
+ type: VOID,
4840
+ loc,
4841
+ },
4842
+ loc,
4843
+ });
4844
+ }
4845
+ if (servername !== null) {
4846
+ steps.push({
4847
+ kind: "exprStmt",
4848
+ expr: {
4849
+ kind: "libCall",
4850
+ fn: "https.clientServername",
4851
+ args: [ref(), servername],
4852
+ type: VOID,
4853
+ loc,
4854
+ },
4855
+ loc,
4856
+ });
4857
+ }
4858
+ if (signal !== null) {
4859
+ steps.push({
4860
+ kind: "exprStmt",
4861
+ expr: { kind: "libCall", fn: "http.clientSignal", args: [ref(), signal], type: VOID, loc },
4862
+ loc,
4863
+ });
4864
+ }
4865
+ return { kind: "seqExpr", stmts: steps, result: ref(), type: HTTPCLIENTREQ_T, loc };
4866
+ };
4750
4867
  if (connCb !== null) {
4751
4868
  const base = [connCb, path, method, timeout, headers, autoEnd];
4752
4869
  if (args.length === 1) {
4753
- return { kind: "libCall", fn: "http.requestConn", args: base, type: HTTPCLIENTREQ_T, loc };
4870
+ return withSignal({
4871
+ kind: "libCall",
4872
+ fn: "http.requestConn",
4873
+ args: base,
4874
+ type: HTTPCLIENTREQ_T,
4875
+ loc,
4876
+ });
4754
4877
  }
4755
4878
  const { cb } = lowerCallbackArg(lowerer, args[1], "response callbacks", 1, (p) => p.kind === "httpReq", "use (res) or ()", [HTTPREQ_T]);
4756
- return {
4879
+ return withSignal({
4757
4880
  kind: "libCall",
4758
4881
  fn: "http.requestConnCb",
4759
4882
  args: [...base, cb],
4760
4883
  type: HTTPCLIENTREQ_T,
4761
4884
  loc,
4762
- };
4885
+ });
4763
4886
  }
4764
4887
  const base = [host, port, path, method, timeout, headers, autoEnd];
4765
4888
  if (secureish) {
@@ -4781,7 +4904,7 @@ function lowerHttpClientCall(lowerer, expr, member, loc, secure = false) {
4781
4904
  : agentVal !== null
4782
4905
  ? "http.requestAgent"
4783
4906
  : "http.request";
4784
- return { kind: "libCall", fn, args: base, type: HTTPCLIENTREQ_T, loc };
4907
+ return withSignal({ kind: "libCall", fn, args: base, type: HTTPCLIENTREQ_T, loc });
4785
4908
  }
4786
4909
  const { cb } = lowerCallbackArg(lowerer, args[1], "response callbacks", 1, (p) => p.kind === "httpReq", "use (res) or ()", [HTTPREQ_T]);
4787
4910
  const fn = binding !== null
@@ -4793,7 +4916,7 @@ function lowerHttpClientCall(lowerer, expr, member, loc, secure = false) {
4793
4916
  : agentVal !== null
4794
4917
  ? "http.requestAgentCb"
4795
4918
  : "http.requestCb";
4796
- return { kind: "libCall", fn, args: [...base, cb], type: HTTPCLIENTREQ_T, loc };
4919
+ return withSignal({ kind: "libCall", fn, args: [...base, cb], type: HTTPCLIENTREQ_T, loc });
4797
4920
  }
4798
4921
  /** The headers option of http.request: an object literal with literal
4799
4922
  * keys and string values packs into the flat [k0, v0, k1, v1, ...] pairs
@@ -5009,6 +5132,22 @@ function lowerHttpClientMethodCall(lowerer, call, access) {
5009
5132
  }
5010
5133
  lowerer.noLowering(`${name} of '${lowerer.fmt(data.type)}' data`, args[0] ?? call, NARROW_DATA_HINT);
5011
5134
  }
5135
+ if (name === "destroy" && args.length === 1) {
5136
+ // destroy(err): err is the request's 'error' (an Error value here).
5137
+ requireStatementPosition(lowerer, call, "request.destroy(err)");
5138
+ const receiver = lowerer.lowerExpr(access.expression);
5139
+ const err = lowerer.lowerExpr(args[0]);
5140
+ if (err.type.kind !== "object") {
5141
+ lowerer.noLowering(`destroy with a '${lowerer.fmt(err.type)}' argument`, args[0], "pass an Error value, or call destroy() without one");
5142
+ }
5143
+ return {
5144
+ kind: "libCall",
5145
+ fn: "http.clientDestroyError",
5146
+ args: [receiver, lowerer.coerceToExpected(err, ERROR_T)],
5147
+ type: VOID,
5148
+ loc,
5149
+ };
5150
+ }
5012
5151
  if (name === "destroy" || name === "abort") {
5013
5152
  requireStatementPosition(lowerer, call, `request.${name}()`);
5014
5153
  if (args.length !== 0) {
@@ -5059,7 +5198,11 @@ function lowerHttpClientMethodCall(lowerer, call, access) {
5059
5198
  loc,
5060
5199
  };
5061
5200
  }
5062
- if (event === "timeout" || event === "close" || event === "finish" || event === "abort") {
5201
+ if (event === "timeout" ||
5202
+ event === "close" ||
5203
+ event === "finish" ||
5204
+ event === "abort" ||
5205
+ event === "continue") {
5063
5206
  const { cb } = lowerCallbackArg(lowerer, args[1], `${event} listeners`, 0, () => false, "use ()", []);
5064
5207
  const fn = event === "timeout"
5065
5208
  ? "http.clientOnTimeout"
@@ -5067,7 +5210,9 @@ function lowerHttpClientMethodCall(lowerer, call, access) {
5067
5210
  ? "http.clientOnClose"
5068
5211
  : event === "abort"
5069
5212
  ? "http.clientOnAbort"
5070
- : "http.clientOnFinish";
5213
+ : event === "continue"
5214
+ ? "http.clientOnContinue"
5215
+ : "http.clientOnFinish";
5071
5216
  return { kind: "libCall", fn, args: [receiver, cb, once], type: VOID, loc };
5072
5217
  }
5073
5218
  if (event === "upgrade") {