@scriptc/compiler 0.0.11 → 0.0.13

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 (97) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +153 -24
  2. package/ambient/scriptc.d.ts +2 -2
  3. package/dist/backend/cc.d.ts +10 -2
  4. package/dist/backend/cc.js +12 -0
  5. package/dist/backend/cc.js.map +1 -1
  6. package/dist/backend/emission/emit-async.js +1 -1
  7. package/dist/backend/emission/emit-exprs.js +235 -64
  8. package/dist/backend/emission/emit-exprs.js.map +1 -1
  9. package/dist/backend/emission/emit-island.js +1 -1
  10. package/dist/backend/emission/emit-shapes.js +1 -1
  11. package/dist/backend/emission/emit-walkers.d.ts +14 -14
  12. package/dist/backend/emission/emit-walkers.js +44 -44
  13. package/dist/backend/emission/emit-walkers.js.map +1 -1
  14. package/dist/backend/emission/emitter.d.ts +3 -3
  15. package/dist/backend/emission/emitter.js +8 -8
  16. package/dist/backend/emission/may-throw.js +1 -1
  17. package/dist/backend/llvm/dyn.d.ts +10 -10
  18. package/dist/backend/llvm/dyn.js +26 -26
  19. package/dist/backend/llvm/dyn.js.map +1 -1
  20. package/dist/backend/llvm/emitter.js +140 -49
  21. package/dist/backend/llvm/emitter.js.map +1 -1
  22. package/dist/backend/llvm/shapes.js +1 -1
  23. package/dist/backend/llvm/walkers.js +2 -2
  24. package/dist/backend/llvm/walkers.js.map +1 -1
  25. package/dist/diagnostics/diagnostic.d.ts +1 -1
  26. package/dist/diagnostics/diagnostic.js +4 -3
  27. package/dist/diagnostics/diagnostic.js.map +1 -1
  28. package/dist/frontend/lowering/crypto-tables.d.ts +7 -0
  29. package/dist/frontend/lowering/crypto-tables.js +139 -0
  30. package/dist/frontend/lowering/crypto-tables.js.map +1 -0
  31. package/dist/frontend/lowering/lib-boundary.js +5 -5
  32. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  33. package/dist/frontend/lowering/lower-assert.js +12 -12
  34. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  35. package/dist/frontend/lowering/lower-builtins.d.ts +45 -27
  36. package/dist/frontend/lowering/lower-builtins.js +203 -70
  37. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  38. package/dist/frontend/lowering/lower-calls.d.ts +4 -4
  39. package/dist/frontend/lowering/lower-calls.js +74 -66
  40. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  41. package/dist/frontend/lowering/lower-classes.js +41 -7
  42. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  43. package/dist/frontend/lowering/lower-containers.d.ts +5 -5
  44. package/dist/frontend/lowering/lower-containers.js +19 -19
  45. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  46. package/dist/frontend/lowering/lower-emitter.js +2 -2
  47. package/dist/frontend/lowering/lower-emitter.js.map +1 -1
  48. package/dist/frontend/lowering/lower-exprs.d.ts +7 -7
  49. package/dist/frontend/lowering/lower-exprs.js +227 -119
  50. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  51. package/dist/frontend/lowering/lower-inspect.js +5 -5
  52. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  53. package/dist/frontend/lowering/lower-island.js +12 -3
  54. package/dist/frontend/lowering/lower-island.js.map +1 -1
  55. package/dist/frontend/lowering/lower-modules.js +17 -17
  56. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  57. package/dist/frontend/lowering/lower-namespaces.d.ts +11 -1
  58. package/dist/frontend/lowering/lower-namespaces.js +41 -6
  59. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  60. package/dist/frontend/lowering/lower-server.d.ts +21 -0
  61. package/dist/frontend/lowering/lower-server.js +278 -23
  62. package/dist/frontend/lowering/lower-server.js.map +1 -1
  63. package/dist/frontend/lowering/lower-stmts.d.ts +1 -1
  64. package/dist/frontend/lowering/lower-stmts.js +195 -34
  65. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  66. package/dist/frontend/lowering/lower-stream.js +67 -23
  67. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  68. package/dist/frontend/lowering/lowerer.d.ts +31 -13
  69. package/dist/frontend/lowering/lowerer.js +99 -45
  70. package/dist/frontend/lowering/lowerer.js.map +1 -1
  71. package/dist/frontend/lowering/surfaces.d.ts +6 -0
  72. package/dist/frontend/lowering/surfaces.js +78 -2
  73. package/dist/frontend/lowering/surfaces.js.map +1 -1
  74. package/dist/frontend/program.js +1 -1
  75. package/dist/frontend/shared.js +7 -7
  76. package/dist/frontend/shared.js.map +1 -1
  77. package/dist/frontend/types.d.ts +2 -2
  78. package/dist/frontend/types.js +27 -15
  79. package/dist/frontend/types.js.map +1 -1
  80. package/dist/index.js +44 -8
  81. package/dist/index.js.map +1 -1
  82. package/dist/ir/nodes.d.ts +208 -106
  83. package/dist/ir/nodes.js +100 -22
  84. package/dist/ir/nodes.js.map +1 -1
  85. package/dist/ir/validate.js +96 -38
  86. package/dist/ir/validate.js.map +1 -1
  87. package/dist/library/int-infer.js +13 -0
  88. package/dist/library/int-infer.js.map +1 -1
  89. package/dist/library/profile.d.ts +8 -6
  90. package/dist/library/profile.js.map +1 -1
  91. package/dist/library/sidecar-validate.js +1 -1
  92. package/dist/library/sidecar-validate.js.map +1 -1
  93. package/dist/library/sidecar.d.ts +1 -1
  94. package/dist/library/sidecar.js +20 -7
  95. package/dist/library/sidecar.js.map +1 -1
  96. package/package.json +2 -2
  97. package/surface-manifest.json +289 -4
@@ -1,4 +1,4 @@
1
- import { canMarshalFuncIntoIsland, CAUGHT, DYN, F64, islandCallbackRet, isRefCounted, isUnitType, MAY_THROW_LIB_FNS, moduleUsesDynInvoke, moduleUsesFetch, moduleUsesFsWatch, moduleUsesHttpServer, moduleUsesNet, moduleUsesProcessEvents, moduleUsesStream, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, STRING, typeEquals, typeKey, VOID } from "../../ir/nodes.js";
1
+ import { canMarshalFuncIntoIsland, CAUGHT, DYN, F64, islandCallbackRet, islandPromisePayloadTag, isRefCounted, isUnitType, MAY_THROW_LIB_FNS, moduleUsesDynInvoke, moduleUsesFetch, moduleUsesFsWatch, moduleUsesHttpServer, moduleUsesNet, moduleUsesProcessEvents, moduleUsesStream, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, STRING, typeEquals, typeKey, VOID } from "../../ir/nodes.js";
2
2
  import { computeMayThrow } from "../emission/may-throw.js";
3
3
  import { mangleArgPack, mangleAsyncSpawn, mangleClassNew, mangleClassObj, mangleClassRetain, mangleFnClosure, mangleFunction, mangleGenDrop, mangleGenResThunk, mangleGenSpawn, mangleGlobal, mangleLocal, mangleRecordNew, mangleRecordStruct, mangleResolveThunk, mangleTrampoline, mangleVtStruct, mangleWrapper } from "../mangle.js";
4
4
  import { BlockBuilder } from "./blocks.js";
@@ -226,6 +226,9 @@ const LIB_FN_SYMS = {
226
226
  "text.decode": "scr_text_decode",
227
227
  "zlib.deflateSync": "scr_zlib_deflate",
228
228
  "zlib.inflateSync": "scr_zlib_inflate",
229
+ // The CA-store read (tlsca.get/set are may-throw seeds and refuse by
230
+ // omission — the C fallback carries them).
231
+ "tlsca.root": "scr_tls_ca_root",
229
232
  "crypto.randomBytes": "scr_crypto_random_bytes",
230
233
  "crypto.randomBytesToString": "scr_crypto_random_string",
231
234
  "crypto.randomUUID": "scr_crypto_random_uuid",
@@ -340,7 +343,7 @@ const LIB_FN_SYMS = {
340
343
  "sym.toString": "scr_sym_to_string",
341
344
  "error.toString": "scr_error_to_string",
342
345
  "class.name": "scr_classobj_name",
343
- // The dyn (ScrDyn DOM) surface (scr_json.c / scr_dyn_invoke.c):
346
+ // The dyn (ScrDyn dyn) surface (scr_json.c / scr_dyn_invoke.c):
344
347
  // json.parse throws the catchable SyntaxError; keySet/toString/
345
348
  // defineProps throw Node's TypeErrors (all in the may-throw seed set —
346
349
  // the generic path emits the standard pending check). typeof and the
@@ -348,6 +351,9 @@ const LIB_FN_SYMS = {
348
351
  "json.parse": "scr_json_parse",
349
352
  "dyn.keySet": "scr_dyn_key_set",
350
353
  "dyn.iterPack": "scr_dyn_iter_pack",
354
+ "dyn.arrLen": "scr_dyn_arr_len",
355
+ "dyn.arrAt": "scr_dyn_arr_at",
356
+ "dyn.hasKey": "scr_dyn_has_key",
351
357
  "dyn.defineProps": "scr_dyn_define_props",
352
358
  "dyn.typeof": "scr_dyn_typeof",
353
359
  "dyn.toString": "scr_dyn_to_string_method",
@@ -444,6 +450,12 @@ const LIB_FN_SYMS = {
444
450
  "net.sockSetEncoding": "scr_net_sock_set_encoding",
445
451
  "net.sockSetTimeout": "scr_net_sock_set_timeout",
446
452
  "net.sockUnshift": "scr_net_sock_unshift_bytes",
453
+ "net.sockPause": "scr_net_sock_pause",
454
+ "net.sockResume": "scr_net_sock_resume",
455
+ "net.sockSetNoDelay": "scr_net_sock_set_nodelay",
456
+ "net.sockDestroySoon": "scr_net_sock_destroy_soon",
457
+ "net.sockBytesWritten": "scr_net_sock_bytes_written",
458
+ "net.sockReadable": "scr_net_sock_readable",
447
459
  "net.sockPipeRes": "scr_http_sock_pipe_res",
448
460
  "net.serverEmitConnection": "scr_net_server_emit_connection",
449
461
  "net.getAutoSelTimeout": "scr_net_get_autosel_timeout",
@@ -490,6 +502,7 @@ const LIB_FN_SYMS = {
490
502
  "http.clientDestroy": "scr_http_client_destroy",
491
503
  "http.clientDestroyed": "scr_http_client_destroyed",
492
504
  "http2.streamUndefCall": "scr_http2_stream_undef_call",
505
+ "http.agentNew": "scr_http_agent_new",
493
506
  // The island surface (--dynamic): eval/import bridge catchably (the
494
507
  // may-throw seed's pending check); importDyn answers an engine promise
495
508
  // and never throws itself. insp.jsval throws on composite island
@@ -535,7 +548,7 @@ const LIB_FN_SYMS = {
535
548
  "dc.tcTraceCallback": "scr_dc_tc_trace_callback",
536
549
  "dc.tcTracePromise": "scr_dc_tc_trace_promise",
537
550
  // AsyncLocalStorage (scr_async_dyn.c): store ids are doubles, values
538
- // ride the DOM; run/exitRun dispatch user callbacks (may-throw).
551
+ // ride the checked-dynamic tree; run/exitRun dispatch user callbacks (may-throw).
539
552
  // The dc bind-store trio shares the als id space.
540
553
  "als.new": "scr_als_new",
541
554
  "als.get": "scr_als_get",
@@ -547,13 +560,16 @@ const LIB_FN_SYMS = {
547
560
  "dc.chanUnbindStore": "scr_dc_chan_unbind_store",
548
561
  "dc.chanRunStores": "scr_dc_chan_run_stores",
549
562
  // process warning/rejection events (scr_lib.c / scr_async_dyn.c):
550
- // DOM listeners are borrowed (the runtime retains its copy);
563
+ // dyn listeners are borrowed (the runtime retains its copy);
551
564
  // onUnhandledRejection marks the loop live (the loop-end report
552
565
  // dispatches the listeners).
553
566
  "process.onWarning": "scr_process_on_warning",
554
567
  "process.offWarning": "scr_process_off_warning",
555
568
  "process.emitWarning": "scr_process_emit_warning",
556
569
  "process.onUnhandledRejection": "scr_process_on_unhandled_rejection",
570
+ "process.offUnhandledRejection": "scr_process_off_unhandled_rejection",
571
+ "process.onRejectionHandled": "scr_process_on_rejection_handled",
572
+ "process.offRejectionHandled": "scr_process_off_rejection_handled",
557
573
  // The await lowering's loop hop and the dyn await (both park the
558
574
  // current fiber — USES_TIMERS_LIB_FNS marks the loop live).
559
575
  "async.hop": "scr_await_hop",
@@ -568,7 +584,7 @@ const LIB_FN_SYMS = {
568
584
  "regexp.escape": "scr_regexp_escape",
569
585
  // The dyn Object walks (throw on nullish receivers), structuredClone
570
586
  // (option/DataClone/cycle errors), and new RegExp's eager compile
571
- // (catchable SyntaxError) — all may-throw generics over the DOM.
587
+ // (catchable SyntaxError) — all may-throw generics over the checked-dynamic tree.
572
588
  "dyn.objKeys": "scr_dyn_obj_keys",
573
589
  "dyn.hasOwn": "scr_dyn_has_own",
574
590
  "dyn.assign": "scr_dyn_assign",
@@ -631,12 +647,13 @@ const USES_TIMERS_LIB_FNS = new Set([
631
647
  "http.createServer", "http.createServerEmpty",
632
648
  "http.request", "http.requestCb", "http.requestUrl", "http.requestUrlCb",
633
649
  "http.requestConn", "http.requestConnCb",
650
+ "http.agentNew", "http.requestAgent", "http.requestAgentCb",
634
651
  // The dyn-async slice (emit-exprs.ts's markings): fiber parks, the
635
652
  // microtask/immediate mints, the tracing-promise reaction fiber, and
636
653
  // the loop-end unhandled-rejection report.
637
654
  "async.hop", "async.awaitDyn",
638
655
  "dc.tcTracePromise",
639
- "process.onUnhandledRejection",
656
+ "process.onUnhandledRejection", "process.onRejectionHandled",
640
657
  "timers.queueMicrotaskDyn", "timers.setImmediateFnValue", "timers.immediatePromise",
641
658
  ]);
642
659
  /** ScrBytesElem (scr_runtime.h): U8, U32, F32, I32. */
@@ -719,7 +736,7 @@ class LlEmitter {
719
736
  * rewriter, union ToString/join) — interned per typeKey/unionId, defs
720
737
  * flushed with the shape helpers. */
721
738
  walkers = new LlWalkers(this);
722
- /** The dyn (ScrDyn DOM) helper registry — dyn.ts's interned ports of
739
+ /** The dyn (ScrDyn dyn) helper registry — dyn.ts's interned ports of
723
740
  * emit-walkers.ts's dyn slice. */
724
741
  dyn = new LlDyn(this);
725
742
  /** External declarations, in first-use order. */
@@ -2036,7 +2053,7 @@ class LlEmitter {
2036
2053
  return t;
2037
2054
  }
2038
2055
  case "dyn": {
2039
- // ToBoolean over the DOM kind (scr_dyn_truthy — JS-exact for
2056
+ // ToBoolean over the dyn kind (scr_dyn_truthy — JS-exact for
2040
2057
  // every kind; borrowed, never throws): `v || dflt` and condition
2041
2058
  // descent on checked-dynamic values.
2042
2059
  this.declare(`declare zeroext i1 @scr_dyn_truthy(ptr)`);
@@ -3714,7 +3731,7 @@ class LlEmitter {
3714
3731
  return this.own({ name: t, type: e.type });
3715
3732
  }
3716
3733
  if (v.type.kind === "dyn") {
3717
- // String(unknown): dispatch over the DOM kind (dyn.ts's sc_ds —
3734
+ // String(unknown): dispatch over the dyn kind (dyn.ts's sc_ds —
3718
3735
  // Node's String() incl. arrays-join and "[object Object]").
3719
3736
  const helper = this.dyn.dynToStrHelper();
3720
3737
  const t = B.tmp();
@@ -4015,7 +4032,7 @@ class LlEmitter {
4015
4032
  this.unionTagSwitch(u.name, def, (arm) => {
4016
4033
  if (isUnitType(arm)) {
4017
4034
  if (e.type.kind === "dyn") {
4018
- // A dyn-typed chain: the unit path is the undefined DOM
4035
+ // A dyn-typed chain: the unit path is the undefined dyn
4019
4036
  // value — dyn represents undefined directly.
4020
4037
  this.declare(`declare ptr @scr_dyn_undefined()`);
4021
4038
  this.declare(`declare ptr @scr_dyn_retain_v(ptr)`);
@@ -4197,8 +4214,21 @@ class LlEmitter {
4197
4214
  const lj = B.newLabel("ord.j");
4198
4215
  B.condBr(truthy, lt, lf);
4199
4216
  B.startBlock(lt);
4200
- B.line(`store ${ty} ${this.unionExtract(l.name, e.type)}, ptr ${slot}`);
4201
- this.releaseValue(l.name, e.left.type);
4217
+ if (e.retag !== undefined) {
4218
+ // Retagged shape: the whole box goes to the union→union helper,
4219
+ // which CONSUMES it (callees own their params) — no release on
4220
+ // this side. The store precedes the pending check so an unwind
4221
+ // leaves only the NULL dummy behind, in a slot nothing reads.
4222
+ const t = B.tmp();
4223
+ B.line(`${t} = call ${ty} @${this.callTarget(e.retag)}(${this.llType(e.left.type)} ${l.name})`);
4224
+ B.line(`store ${ty} ${t}, ptr ${slot}`);
4225
+ if (this.mayThrow.has(e.retag))
4226
+ this.emitPendingCheck();
4227
+ }
4228
+ else {
4229
+ B.line(`store ${ty} ${this.unionExtract(l.name, e.type)}, ptr ${slot}`);
4230
+ this.releaseValue(l.name, e.left.type);
4231
+ }
4202
4232
  B.br(lj);
4203
4233
  B.startBlock(lf);
4204
4234
  this.releaseValue(l.name, e.left.type);
@@ -4311,9 +4341,9 @@ class LlEmitter {
4311
4341
  // the frame's release is a no-op) and the body reads it through
4312
4342
  // chainRecv.
4313
4343
  if (e.receiver.type.kind === "dyn") {
4314
- // A dyn (DOM) receiver — the `rawName?.match(re)` step: the
4344
+ // A dyn (dyn) receiver — the `rawName?.match(re)` step: the
4315
4345
  // nullish test reads the node's kind tag; the unit path is the
4316
- // undefined DOM singleton (dyn results) or nothing (void
4346
+ // undefined dyn singleton (dyn results) or nothing (void
4317
4347
  // bodies), the body runs over the bound receiver otherwise.
4318
4348
  const r = this.emitExpr(e.receiver);
4319
4349
  const kd = this.dynKind(r.name);
@@ -4465,7 +4495,7 @@ class LlEmitter {
4465
4495
  }
4466
4496
  if (e.type.kind === "dyn") {
4467
4497
  // A dyn-typed chain (`pricing?.[key]` over an unknown-valued
4468
- // index signature): the unit path is the undefined DOM value —
4498
+ // index signature): the unit path is the undefined dyn value —
4469
4499
  // dyn represents undefined directly, no union wrapper exists.
4470
4500
  const slotD = B.slot();
4471
4501
  B.entryAllocas.push(`${slotD} = alloca ptr`);
@@ -4912,14 +4942,14 @@ class LlEmitter {
4912
4942
  }
4913
4943
  case "jsonStringify": {
4914
4944
  // Type-directed serialization: the STATIC type picks an emitted
4915
- // serializer (interned per typeKey) — no DOM, no runtime dispatch.
4945
+ // serializer (interned per typeKey) — no dyn, no runtime dispatch.
4916
4946
  // The value temp is BORROWED (released with this statement's
4917
4947
  // frame); the result string is owned (+1). Never throws — except
4918
4948
  // the dyn root below.
4919
4949
  const v = this.emitExpr(e.value);
4920
4950
  let compact;
4921
4951
  if (e.value.type.kind === "dyn") {
4922
- // A dyn root: the runtime's DOM walker (scr_dyn_format_j — the
4952
+ // A dyn root: the runtime's dyn walker (scr_dyn_format_j — the
4923
4953
  // C backend's dispatch exactly): number/string/bool/null/array/
4924
4954
  // object exact, dropped members omitted, and a dropped ROOT
4925
4955
  // becomes the TEXT "undefined" (JSON.stringify(undefined) is
@@ -5084,7 +5114,7 @@ class LlEmitter {
5084
5114
  if (e.arg === null) {
5085
5115
  if (genT.nextT.kind === "dyn") {
5086
5116
  // Valueless resume on a dyn channel: JS's undefined — the
5087
- // DOM singleton rides the IN slot (+1 moves in).
5117
+ // dyn singleton rides the IN slot (+1 moves in).
5088
5118
  this.declare(`declare ptr @scr_dyn_undefined()`);
5089
5119
  this.declare(`declare ptr @scr_dyn_retain_v(ptr)`);
5090
5120
  this.declare(`declare void @scr_dyn_release_v(ptr)`);
@@ -5552,10 +5582,10 @@ class LlEmitter {
5552
5582
  return { name: "", type: e.type };
5553
5583
  }
5554
5584
  case "dynFrom": {
5555
- // Static value → fresh DOM tree (+1) through the interned per-type
5585
+ // Static value → fresh dyn tree (+1) through the interned per-type
5556
5586
  // converter; the operand stays borrowed (frame-released as usual).
5557
5587
  // Bare unit literals (an `undefined`/`null` stored under an
5558
- // `unknown` index signature) are the DOM unit values directly.
5588
+ // `unknown` index signature) are the dyn unit values directly.
5559
5589
  if (e.value.kind === "unitLit") {
5560
5590
  const t = B.tmp();
5561
5591
  if (e.value.unit === "undefined") {
@@ -5573,7 +5603,7 @@ class LlEmitter {
5573
5603
  }
5574
5604
  const v = this.emitExpr(e.value);
5575
5605
  if (v.type.kind === "func") {
5576
- // A closure boxes as the DOM's function kind: retained closure +
5606
+ // A closure boxes as the checked-dynamic tree's function kind: retained closure +
5577
5607
  // the per-signature call thunk + the interned signature key. The
5578
5608
  // best-effort name rides along (null when the lowering had none).
5579
5609
  const name = e.fnName !== undefined && e.fnName !== "" ? this.cstr(e.fnName) : "null";
@@ -5589,8 +5619,8 @@ class LlEmitter {
5589
5619
  return this.own({ name: t, type: e.type });
5590
5620
  }
5591
5621
  case "dynFromJsval": {
5592
- // Island value → DOM: the by-reference wrap (scr_dyn_from_jsval
5593
- // retains the cell in; engine scalars normalize to native DOM
5622
+ // Island value → dyn: the by-reference wrap (scr_dyn_from_jsval
5623
+ // retains the cell in; engine scalars normalize to native dyn
5594
5624
  // kinds at wrap time). Operand borrowed, result +1, never throws.
5595
5625
  const v = this.emitExpr(e.value);
5596
5626
  this.declare(`declare ptr @scr_dyn_from_jsval(ptr)`);
@@ -5609,7 +5639,7 @@ class LlEmitter {
5609
5639
  return this.own({ name: t, type: e.type });
5610
5640
  }
5611
5641
  case "dynCheck": {
5612
- // The dynamic boundary: validate the DOM against the target type
5642
+ // The dynamic boundary: validate the checked-dynamic tree against the target type
5613
5643
  // and BUILD the typed value (+1) — or throw the catchable
5614
5644
  // path-annotated TypeError. The dyn temp is BORROWED; the result
5615
5645
  // joins the frame BEFORE the pending check so an unwind releases
@@ -5630,11 +5660,11 @@ class LlEmitter {
5630
5660
  // spelling rides along for Node's "<name> is not a function".
5631
5661
  const callee = this.emitExpr(e.callee);
5632
5662
  if (e.spreads !== undefined && e.spreads.length > 0) {
5633
- // The RUNTIME-ARITY form (`f(...args)`): one fresh DOM array
5663
+ // The RUNTIME-ARITY form (`f(...args)`): one fresh dyn array
5634
5664
  // collects the arguments left-to-right — plain args move in
5635
5665
  // (push takes ownership), spread args FLATTEN (push_spread
5636
5666
  // retains elements in and throws V8's spread-call TypeError for
5637
- // non-iterable DOM kinds, checked per spread — JS's
5667
+ // non-iterable dyn kinds, checked per spread — JS's
5638
5668
  // ArgumentListEvaluation order) — then apply calls through the
5639
5669
  // array's elements (borrowed, exactly scr_dyn_call).
5640
5670
  this.declare(`declare ptr @scr_dyn_new_arr()`);
@@ -5707,7 +5737,7 @@ class LlEmitter {
5707
5737
  return out;
5708
5738
  }
5709
5739
  case "dynArrLit": {
5710
- // A DOM array built element-by-element: ownership of each dyn
5740
+ // A dyn array built element-by-element: ownership of each dyn
5711
5741
  // element MOVES into the array (scr_dyn_arr_push's contract).
5712
5742
  this.declare(`declare ptr @scr_dyn_new_arr()`);
5713
5743
  this.declare(`declare void @scr_dyn_arr_push(ptr, ptr)`);
@@ -5722,7 +5752,7 @@ class LlEmitter {
5722
5752
  return out;
5723
5753
  }
5724
5754
  case "dynObjLit": {
5725
- // A DOM object built member-by-member: key then value, source
5755
+ // A dyn object built member-by-member: key then value, source
5726
5756
  // order. scr_dyn_key_set BORROWS all three (the member retains the
5727
5757
  // value in); the receiver is a fresh OBJ, so the non-object throw
5728
5758
  // paths are unreachable here.
@@ -5739,7 +5769,7 @@ class LlEmitter {
5739
5769
  return out;
5740
5770
  }
5741
5771
  case "dynKeyGet": {
5742
- // Keyed read on the DOM through the one interned helper — the
5772
+ // Keyed read on the checked-dynamic tree through the one interned helper — the
5743
5773
  // non-optional form throws JS's TypeError on an undefined/null
5744
5774
  // receiver, and HANDLE receivers can throw the loud unmodeled-
5745
5775
  // property ladder on EITHER form; the result is owned (+1).
@@ -5824,7 +5854,7 @@ class LlEmitter {
5824
5854
  const [d, s, st] = e.left.type.kind === "dyn" ? [l, r, e.right.type] : [r, l, e.left.type];
5825
5855
  let test;
5826
5856
  if (st.kind === "dyn") {
5827
- // dyn vs dyn: whole-DOM strict equality.
5857
+ // dyn vs dyn: whole-dyn strict equality.
5828
5858
  this.declare(`declare zeroext i1 @scr_dyn_strict_eq(ptr, ptr)`);
5829
5859
  test = B.tmp();
5830
5860
  B.line(`${test} = call zeroext i1 @scr_dyn_strict_eq(ptr ${l.name}, ptr ${r.name})`);
@@ -5877,7 +5907,7 @@ class LlEmitter {
5877
5907
  return { name: neg, type: e.type };
5878
5908
  }
5879
5909
  case "dynTest": {
5880
- // A pure kind compare on the DOM node — borrowed; only the truthy
5910
+ // A pure kind compare on the dyn node — borrowed; only the truthy
5881
5911
  // form also reads a scalar payload (the runtime's ToBoolean).
5882
5912
  const d = this.emitExpr(e.value);
5883
5913
  let test;
@@ -5887,7 +5917,7 @@ class LlEmitter {
5887
5917
  B.line(`${test} = call zeroext i1 @scr_dyn_truthy(ptr ${d.name})`);
5888
5918
  }
5889
5919
  else if (e.test === "error") {
5890
- // `u instanceof Error`: the DOM's error encoding — an object
5920
+ // `u instanceof Error`: the checked-dynamic tree's error encoding — an object
5891
5921
  // carrying the reserved "%error" marker key — or a real engine
5892
5922
  // Error held by reference (the isl helper answers false for
5893
5923
  // every non-JSVAL kind, so the call is unconditional).
@@ -5954,7 +5984,7 @@ class LlEmitter {
5954
5984
  test = orIsl(oneOf([DK.OBJ, DK.ARR, DK.BYTES, DK.HANDLE, DK.PROMISE, DK.NULL]), "scr_dyn_isl_typeof_is", this.cstr("object"));
5955
5985
  }
5956
5986
  else if (e.test === "array") {
5957
- // Array.isArray: the DOM's array kind, or the engine's own
5987
+ // Array.isArray: the checked-dynamic tree's array kind, or the engine's own
5958
5988
  // answer for an engine-held value.
5959
5989
  test = orIsl(oneOf([DK.ARR]), "scr_dyn_isl_is_array");
5960
5990
  }
@@ -5980,7 +6010,7 @@ class LlEmitter {
5980
6010
  return { name: neg, type: e.type };
5981
6011
  }
5982
6012
  case "dynDestrCheck": {
5983
- // RequireObjectCoercible with V8's destructuring TypeError. DOM
6013
+ // RequireObjectCoercible with V8's destructuring TypeError. dyn
5984
6014
  // values check in the runtime helper and pass through unchanged
5985
6015
  // (same temp, same ownership); island values check in the engine
5986
6016
  // (a fresh +1 cell for the same value comes back).
@@ -6001,7 +6031,7 @@ class LlEmitter {
6001
6031
  }
6002
6032
  case "dynIterN": {
6003
6033
  // GetIterator + first-N steps as a fresh array (V8's exact
6004
- // not-iterable TypeError on non-iterables): the DOM helper for
6034
+ // not-iterable TypeError on non-iterables): the dyn helper for
6005
6035
  // dyn operands, the engine's real iterator protocol for island
6006
6036
  // ones.
6007
6037
  const v = this.emitExpr(e.value);
@@ -6033,7 +6063,9 @@ class LlEmitter {
6033
6063
  const v = this.emitExpr(e.value);
6034
6064
  const payload = e.type.kind === "promise" && e.type.inner.kind === "void"
6035
6065
  ? 0 // SCR_ISLP_VOID
6036
- : 4; // SCR_ISLP_JSVAL
6066
+ : e.type.kind === "promise" && e.type.inner.kind === "array" && e.type.inner.elem.kind === "jsval"
6067
+ ? 5 // SCR_ISLP_JSVAL_ARR: the Array.isArray-gated by-reference exit at settle
6068
+ : 4; // SCR_ISLP_JSVAL
6037
6069
  this.declare(`declare ptr @scr_jsval_bridge_promise(ptr, i32)`);
6038
6070
  const t = B.tmp();
6039
6071
  B.line(`${t} = call ptr @scr_jsval_bridge_promise(ptr ${v.name}, i32 ${payload})`);
@@ -6081,7 +6113,7 @@ class LlEmitter {
6081
6113
  case "string":
6082
6114
  return simple("scr_jsval_from_str", "ptr", false);
6083
6115
  case "dyn":
6084
- // A CHECKED-DYNAMIC (DOM) value entering the island: deep copy,
6116
+ // A CHECKED-DYNAMIC (dyn) value entering the island: deep copy,
6085
6117
  // data kinds only — boxed functions/handles/promises throw the
6086
6118
  // catchable TypeError in the runtime, and a wrapped island value
6087
6119
  // unwraps to the SAME engine value (the identity round trip).
@@ -6093,6 +6125,25 @@ class LlEmitter {
6093
6125
  case "url":
6094
6126
  // A URL crossing IN: an engine URL instance built from href.
6095
6127
  return simple("scr_jsval_from_url", "ptr", true);
6128
+ case "promise": {
6129
+ // A STATIC promise crossing IN: a real engine thenable settled
6130
+ // when the scriptc promise settles (the async-callback return
6131
+ // bridge). from_promise takes ownership of a +1 — retain past
6132
+ // the borrowed frame temp. The C emitter's rule, mirrored.
6133
+ const tag = islandPromisePayloadTag(e.value.type.inner);
6134
+ if (!tag)
6135
+ throw new Error("llvm emitter bug: jsMarshal of a promise outside the bridge payload domain");
6136
+ const tagN = { void: 0, f64: 1, bool: 2, string: 3, jsval: 4, jsvalArr: 5 }[tag];
6137
+ this.declare(`declare ptr @scr_promise_retain(ptr)`);
6138
+ this.declare(`declare ptr @scr_jsval_from_promise(ptr, i32)`);
6139
+ const pr = B.tmp();
6140
+ B.line(`${pr} = call ptr @scr_promise_retain(ptr ${v.name})`);
6141
+ const t = B.tmp();
6142
+ B.line(`${t} = call ptr @scr_jsval_from_promise(ptr ${pr}, i32 ${tagN})`);
6143
+ const out = this.own({ name: t, type: e.type });
6144
+ this.emitPendingCheck();
6145
+ return out;
6146
+ }
6096
6147
  case "func": {
6097
6148
  // A closure entering the island as a host function: from_closure
6098
6149
  // retains it; the engine's finalizer releases it at teardown. The
@@ -6424,6 +6475,17 @@ class LlEmitter {
6424
6475
  return out;
6425
6476
  }
6426
6477
  default: {
6478
+ // `any[]`-declared slot: Array.isArray-gated, elements BY
6479
+ // REFERENCE (identity crosses; the spine is a snapshot copy).
6480
+ // JSON-safe element types keep the round trip below.
6481
+ if (e.type.kind === "array" && e.type.elem.kind === "jsval") {
6482
+ this.declare(`declare ptr @scr_jsval_exit_jsval_arr(ptr)`);
6483
+ const t = B.tmp();
6484
+ B.line(`${t} = call ptr @scr_jsval_exit_jsval_arr(ptr ${v.name})`);
6485
+ const out = this.own({ name: t, type: e.type });
6486
+ this.emitPendingCheck();
6487
+ return out;
6488
+ }
6427
6489
  // An undefined-armed union target: the engine's undefined takes
6428
6490
  // the undefined arm FIRST (JSON cannot spell it); then null and
6429
6491
  // data ride the round trip into the union's dynCheck like any
@@ -6460,11 +6522,31 @@ class LlEmitter {
6460
6522
  B.br(lj);
6461
6523
  B.startBlock(ld);
6462
6524
  this.frames.push([]);
6463
- const t = roundTrip();
6464
- this.own({ name: t, type: e.type });
6465
- this.emitPendingCheck();
6466
- this.moveTemp({ name: t, type: e.type });
6467
- B.line(`store ptr ${t}, ptr ${slot}`);
6525
+ const unionDef = this.unionsById.get(e.type.unionId);
6526
+ const dataArms = unionDef ? unionDef.arms.flatMap((a, i) => (isUnitType(a) ? [] : [{ a, i }])) : [];
6527
+ const jsvalArr = dataArms.length === 1 && dataArms[0].a.kind === "array" && dataArms[0].a.elem.kind === "jsval" ? dataArms[0] : null;
6528
+ let t;
6529
+ if (jsvalArr) {
6530
+ // The `any[] | undefined` defaulted-parameter spelling: the
6531
+ // engine array exits BY REFERENCE into the data arm.
6532
+ this.declare(`declare ptr @scr_jsval_exit_jsval_arr(ptr)`);
6533
+ this.declare(`declare ptr @scr_union_new_ref(i32, ptr, ptr, ptr, ptr)`);
6534
+ this.declare(`declare ptr @scr_arr_retain_v(ptr)`);
6535
+ this.declare(`declare void @scr_arr_release_v(ptr)`);
6536
+ const arr = B.tmp();
6537
+ B.line(`${arr} = call ptr @scr_jsval_exit_jsval_arr(ptr ${v.name})`);
6538
+ this.emitPendingCheck();
6539
+ t = B.tmp();
6540
+ B.line(`${t} = call ptr @scr_union_new_ref(i32 ${jsvalArr.i}, ptr ${arr}, ptr @scr_arr_retain_v, ptr @scr_arr_release_v, ptr null)`);
6541
+ B.line(`store ptr ${t}, ptr ${slot}`);
6542
+ }
6543
+ else {
6544
+ t = roundTrip();
6545
+ this.own({ name: t, type: e.type });
6546
+ this.emitPendingCheck();
6547
+ this.moveTemp({ name: t, type: e.type });
6548
+ B.line(`store ptr ${t}, ptr ${slot}`);
6549
+ }
6468
6550
  this.releaseFrame(this.frames.pop());
6469
6551
  B.br(lj);
6470
6552
  B.startBlock(lj);
@@ -6677,7 +6759,7 @@ class LlEmitter {
6677
6759
  d.push(` %r = call ptr %fn(${passed.join(", ")})`, ` %rn = icmp eq ptr %r, null`, ` br i1 %rn, label %snull, label %sok`, `snull:`, ` ret ptr null`, `sok:`, ` %j = call ptr @scr_jsval_from_str(ptr %r)`, ` call void @scr_str_release(ptr %r)`, ` ret ptr %j`);
6678
6760
  break;
6679
6761
  case "dyn":
6680
- // A checked-dynamic (+1 DOM) result: deep copy into the engine
6762
+ // A checked-dynamic (+1 dyn) result: deep copy into the engine
6681
6763
  // (the jsMarshal dyn rule); NULL is the throw-path dummy.
6682
6764
  this.declare(`declare ptr @scr_jsval_from_dyn(ptr)`);
6683
6765
  this.declare(`declare void @scr_dyn_release(ptr)`);
@@ -6708,7 +6790,7 @@ class LlEmitter {
6708
6790
  this.resolveThunkDefs.push(...d);
6709
6791
  return sym;
6710
6792
  }
6711
- /** Loads a DOM node's kind tag (i32 at +8) — the dyn expression tests'
6793
+ /** Loads a dyn node's kind tag (i32 at +8) — the dyn expression tests'
6712
6794
  * shared read. */
6713
6795
  dynKind(d) {
6714
6796
  const B = this.B;
@@ -8537,7 +8619,7 @@ class LlEmitter {
8537
8619
  // A dyn JOIN (the C helper's `surface` dyn arm): declared hits
8538
8620
  // convert through the per-type toDyn walker (borrowed read → fresh
8539
8621
  // +1 tree), a dyn-valued overflow hit passes through (+1 from the
8540
- // map get), and a miss is JS's undefined — the DOM singleton.
8622
+ // map get), and a miss is JS's undefined — the dyn singleton.
8541
8623
  this.declare(`declare zeroext i1 @scr_str_eq(ptr, ptr)`);
8542
8624
  for (const f of overflowOnly ? [] : shape.fields) {
8543
8625
  const lit = this.internLiteral(f.name);
@@ -8615,7 +8697,7 @@ class LlEmitter {
8615
8697
  B.br(join);
8616
8698
  B.startBlock(ln);
8617
8699
  }
8618
- // The miss path: JS's undefined — the DOM singleton, retained.
8700
+ // The miss path: JS's undefined — the dyn singleton, retained.
8619
8701
  this.declare(`declare ptr @scr_dyn_undefined()`);
8620
8702
  this.declare(`declare ptr @scr_dyn_retain_v(ptr)`);
8621
8703
  const u = B.tmp();
@@ -10544,9 +10626,11 @@ class LlEmitter {
10544
10626
  B.line(`call void @${entry}(ptr ${args[0].name}, ptr ${args[1].name}, ptr @${adapter}, i1 ${args[2].name})`);
10545
10627
  return { name: "", type: e.type };
10546
10628
  }
10547
- if (e.fn === "http.request" || e.fn === "http.requestCb" || e.fn === "http.requestUrl" || e.fn === "http.requestUrlCb") {
10629
+ if (e.fn === "http.request" || e.fn === "http.requestCb" || e.fn === "http.requestUrl" || e.fn === "http.requestUrlCb" ||
10630
+ e.fn === "http.requestAgent" || e.fn === "http.requestAgentCb") {
10548
10631
  const isUrl = e.fn.startsWith("http.requestUrl");
10549
- const cbIdx = isUrl ? 3 : 7;
10632
+ const isAgent = e.fn.startsWith("http.requestAgent");
10633
+ const cbIdx = isUrl ? 3 : isAgent ? 8 : 7;
10550
10634
  const hasCb = e.fn.endsWith("Cb");
10551
10635
  const args = e.args.map((a) => this.emitExpr(a));
10552
10636
  let cb = "null";
@@ -10563,7 +10647,7 @@ class LlEmitter {
10563
10647
  }
10564
10648
  const head = args.slice(0, cbIdx);
10565
10649
  const decls = head.map((a) => (this.llType(a.type) === "i1" ? "i1 zeroext" : this.llType(a.type)));
10566
- const entry = isUrl ? "scr_http_request_url" : "scr_http_request";
10650
+ const entry = isUrl ? "scr_http_request_url" : isAgent ? "scr_http_request_agent" : "scr_http_request";
10567
10651
  this.declare(`declare ptr @${entry}(${[...decls, "ptr", "ptr"].join(", ")})`);
10568
10652
  const t = B.tmp();
10569
10653
  B.line(`${t} = call ptr @${entry}(${[...head.map((a) => `${this.llType(a.type)} ${a.name}`), `ptr ${cb}`, `ptr ${adapter}`].join(", ")})`);
@@ -10598,6 +10682,13 @@ class LlEmitter {
10598
10682
  B.line(`call void @scr_http_res_on_finish(ptr ${args[0].name}, ptr ${args[1].name})`);
10599
10683
  return { name: "", type: e.type };
10600
10684
  }
10685
+ if (e.fn === "net.sockOnFinish") {
10686
+ const args = e.args.map((a) => this.emitExpr(a));
10687
+ this.moveTemp(args[1]);
10688
+ this.declare(`declare void @scr_net_sock_on_finish(ptr, ptr)`);
10689
+ B.line(`call void @scr_net_sock_on_finish(ptr ${args[0].name}, ptr ${args[1].name})`);
10690
+ return { name: "", type: e.type };
10691
+ }
10601
10692
  if (e.fn === "island.castFail") {
10602
10693
  // The deferred boundary failure: the island value was evaluated
10603
10694
  // (its side effects are real), the throw is unconditional