@scriptc/compiler 0.0.10 → 0.0.12

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 (111) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +63 -15
  2. package/ambient/scriptc.d.ts +2 -2
  3. package/dist/backend/cc.d.ts +2 -2
  4. package/dist/backend/emission/emit-async.js +1 -1
  5. package/dist/backend/emission/emit-exprs.js +131 -54
  6. package/dist/backend/emission/emit-exprs.js.map +1 -1
  7. package/dist/backend/emission/emit-island.js +1 -1
  8. package/dist/backend/emission/emit-shapes.js +1 -1
  9. package/dist/backend/emission/emit-walkers.d.ts +14 -14
  10. package/dist/backend/emission/emit-walkers.js +44 -44
  11. package/dist/backend/emission/emit-walkers.js.map +1 -1
  12. package/dist/backend/emission/emitter.d.ts +3 -3
  13. package/dist/backend/emission/emitter.js +33 -9
  14. package/dist/backend/emission/emitter.js.map +1 -1
  15. package/dist/backend/emission/may-throw.js +1 -1
  16. package/dist/backend/llvm/dyn.d.ts +10 -10
  17. package/dist/backend/llvm/dyn.js +26 -26
  18. package/dist/backend/llvm/dyn.js.map +1 -1
  19. package/dist/backend/llvm/emitter.js +156 -47
  20. package/dist/backend/llvm/emitter.js.map +1 -1
  21. package/dist/backend/llvm/shapes.js +1 -1
  22. package/dist/backend/llvm/walkers.js +2 -2
  23. package/dist/backend/llvm/walkers.js.map +1 -1
  24. package/dist/coverage/surface-manifest.js +16 -2
  25. package/dist/coverage/surface-manifest.js.map +1 -1
  26. package/dist/diagnostics/diagnostic.d.ts +21 -8
  27. package/dist/diagnostics/diagnostic.js +48 -14
  28. package/dist/diagnostics/diagnostic.js.map +1 -1
  29. package/dist/frontend/lowering/lib-boundary.js +5 -5
  30. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  31. package/dist/frontend/lowering/lower-assert.js +12 -12
  32. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  33. package/dist/frontend/lowering/lower-builtins.d.ts +63 -7
  34. package/dist/frontend/lowering/lower-builtins.js +327 -35
  35. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  36. package/dist/frontend/lowering/lower-calls.d.ts +4 -4
  37. package/dist/frontend/lowering/lower-calls.js +104 -70
  38. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  39. package/dist/frontend/lowering/lower-classes.d.ts +7 -0
  40. package/dist/frontend/lowering/lower-classes.js +82 -6
  41. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  42. package/dist/frontend/lowering/lower-containers.d.ts +9 -5
  43. package/dist/frontend/lowering/lower-containers.js +88 -26
  44. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  45. package/dist/frontend/lowering/lower-emitter.d.ts +70 -3
  46. package/dist/frontend/lowering/lower-emitter.js +438 -31
  47. package/dist/frontend/lowering/lower-emitter.js.map +1 -1
  48. package/dist/frontend/lowering/lower-exprs.d.ts +87 -12
  49. package/dist/frontend/lowering/lower-exprs.js +630 -125
  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.d.ts +8 -5
  56. package/dist/frontend/lowering/lower-modules.js +157 -63
  57. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  58. package/dist/frontend/lowering/lower-namespaces.d.ts +24 -0
  59. package/dist/frontend/lowering/lower-namespaces.js +158 -16
  60. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  61. package/dist/frontend/lowering/lower-server.js +11 -11
  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 +271 -36
  65. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  66. package/dist/frontend/lowering/lower-stream.js +171 -20
  67. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  68. package/dist/frontend/lowering/lowerer.d.ts +27 -10
  69. package/dist/frontend/lowering/lowerer.js +156 -54
  70. package/dist/frontend/lowering/lowerer.js.map +1 -1
  71. package/dist/frontend/lowering/surfaces.d.ts +44 -0
  72. package/dist/frontend/lowering/surfaces.js +236 -5
  73. package/dist/frontend/lowering/surfaces.js.map +1 -1
  74. package/dist/frontend/npm.d.ts +12 -0
  75. package/dist/frontend/npm.js +30 -0
  76. package/dist/frontend/npm.js.map +1 -1
  77. package/dist/frontend/program.d.ts +25 -0
  78. package/dist/frontend/program.js +145 -136
  79. package/dist/frontend/program.js.map +1 -1
  80. package/dist/frontend/shared.d.ts +1 -1
  81. package/dist/frontend/shared.js +8 -8
  82. package/dist/frontend/shared.js.map +1 -1
  83. package/dist/frontend/types.d.ts +2 -2
  84. package/dist/frontend/types.js +15 -15
  85. package/dist/frontend/types.js.map +1 -1
  86. package/dist/index.d.ts +2 -1
  87. package/dist/index.js +169 -5
  88. package/dist/index.js.map +1 -1
  89. package/dist/ir/nodes.d.ts +174 -106
  90. package/dist/ir/nodes.js +69 -24
  91. package/dist/ir/nodes.js.map +1 -1
  92. package/dist/ir/validate.js +55 -36
  93. package/dist/ir/validate.js.map +1 -1
  94. package/dist/library/fence-eval.js +12 -2
  95. package/dist/library/fence-eval.js.map +1 -1
  96. package/dist/library/int-infer.d.ts +119 -0
  97. package/dist/library/int-infer.js +1314 -0
  98. package/dist/library/int-infer.js.map +1 -0
  99. package/dist/library/int-infer.test.d.ts +1 -0
  100. package/dist/library/int-infer.test.js +279 -0
  101. package/dist/library/int-infer.test.js.map +1 -0
  102. package/dist/library/profile.d.ts +34 -5
  103. package/dist/library/profile.js +77 -13
  104. package/dist/library/profile.js.map +1 -1
  105. package/dist/library/sidecar-validate.js +1 -1
  106. package/dist/library/sidecar-validate.js.map +1 -1
  107. package/dist/library/sidecar.d.ts +24 -1
  108. package/dist/library/sidecar.js +163 -16
  109. package/dist/library/sidecar.js.map +1 -1
  110. package/package.json +2 -2
  111. package/surface-manifest.json +210 -12
@@ -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";
@@ -340,7 +340,7 @@ const LIB_FN_SYMS = {
340
340
  "sym.toString": "scr_sym_to_string",
341
341
  "error.toString": "scr_error_to_string",
342
342
  "class.name": "scr_classobj_name",
343
- // The dyn (ScrDyn DOM) surface (scr_json.c / scr_dyn_invoke.c):
343
+ // The dyn (ScrDyn dyn) surface (scr_json.c / scr_dyn_invoke.c):
344
344
  // json.parse throws the catchable SyntaxError; keySet/toString/
345
345
  // defineProps throw Node's TypeErrors (all in the may-throw seed set —
346
346
  // the generic path emits the standard pending check). typeof and the
@@ -348,6 +348,8 @@ const LIB_FN_SYMS = {
348
348
  "json.parse": "scr_json_parse",
349
349
  "dyn.keySet": "scr_dyn_key_set",
350
350
  "dyn.iterPack": "scr_dyn_iter_pack",
351
+ "dyn.arrLen": "scr_dyn_arr_len",
352
+ "dyn.arrAt": "scr_dyn_arr_at",
351
353
  "dyn.defineProps": "scr_dyn_define_props",
352
354
  "dyn.typeof": "scr_dyn_typeof",
353
355
  "dyn.toString": "scr_dyn_to_string_method",
@@ -403,6 +405,8 @@ const LIB_FN_SYMS = {
403
405
  // generic pending check; loop liveness rides USES_TIMERS_LIB_FNS.
404
406
  "readable.push": "scr_stream_push",
405
407
  "readable.pushStr": "scr_stream_push_str",
408
+ "readable.pushStrEnc": "scr_stream_push_str_enc",
409
+ "readable.pushEncoding": "scr_stream_set_push_encoding",
406
410
  "readable.pushNull": "scr_stream_push_null",
407
411
  "readable.pushDyn": "scr_stream_push_dyn",
408
412
  "readable.unshift": "scr_stream_unshift",
@@ -504,6 +508,11 @@ const LIB_FN_SYMS = {
504
508
  // stream/promises' finished form (+1 promise; may-throw pending check;
505
509
  // the pipeline form needs the stream-array compound and emits below).
506
510
  "sp.finished": "scr_sp_finished",
511
+ // stream/consumers' promise consumers (+1 promises; may-throw pending
512
+ // check — the 'newListener' meta emit can run user code).
513
+ "sc.text": "scr_sc_text",
514
+ "sc.json": "scr_sc_json",
515
+ "sc.buffer": "scr_sc_buffer",
507
516
  "dc.channel": "scr_dc_channel",
508
517
  "dc.subscribe": "scr_dc_subscribe",
509
518
  "dc.unsubscribe": "scr_dc_unsubscribe",
@@ -528,7 +537,7 @@ const LIB_FN_SYMS = {
528
537
  "dc.tcTraceCallback": "scr_dc_tc_trace_callback",
529
538
  "dc.tcTracePromise": "scr_dc_tc_trace_promise",
530
539
  // AsyncLocalStorage (scr_async_dyn.c): store ids are doubles, values
531
- // ride the DOM; run/exitRun dispatch user callbacks (may-throw).
540
+ // ride the checked-dynamic tree; run/exitRun dispatch user callbacks (may-throw).
532
541
  // The dc bind-store trio shares the als id space.
533
542
  "als.new": "scr_als_new",
534
543
  "als.get": "scr_als_get",
@@ -540,7 +549,7 @@ const LIB_FN_SYMS = {
540
549
  "dc.chanUnbindStore": "scr_dc_chan_unbind_store",
541
550
  "dc.chanRunStores": "scr_dc_chan_run_stores",
542
551
  // process warning/rejection events (scr_lib.c / scr_async_dyn.c):
543
- // DOM listeners are borrowed (the runtime retains its copy);
552
+ // dyn listeners are borrowed (the runtime retains its copy);
544
553
  // onUnhandledRejection marks the loop live (the loop-end report
545
554
  // dispatches the listeners).
546
555
  "process.onWarning": "scr_process_on_warning",
@@ -561,7 +570,7 @@ const LIB_FN_SYMS = {
561
570
  "regexp.escape": "scr_regexp_escape",
562
571
  // The dyn Object walks (throw on nullish receivers), structuredClone
563
572
  // (option/DataClone/cycle errors), and new RegExp's eager compile
564
- // (catchable SyntaxError) — all may-throw generics over the DOM.
573
+ // (catchable SyntaxError) — all may-throw generics over the checked-dynamic tree.
565
574
  "dyn.objKeys": "scr_dyn_obj_keys",
566
575
  "dyn.hasOwn": "scr_dyn_has_own",
567
576
  "dyn.assign": "scr_dyn_assign",
@@ -604,7 +613,8 @@ const USES_TIMERS_LIB_FNS = new Set([
604
613
  "readable.init", "writable.init", "duplex.init", "transform.init", "passthrough.init",
605
614
  "readable.newDyn", "writable.newDyn", "duplex.newDyn", "transform.newDyn", "passthrough.newDyn",
606
615
  "readable.initDyn", "writable.initDyn", "duplex.initDyn", "transform.initDyn", "passthrough.initDyn",
607
- "readable.push", "readable.pushStr", "readable.pushNull", "readable.pushU", "readable.pushDyn",
616
+ "readable.push", "readable.pushStr", "readable.pushStrEnc", "readable.pushEncoding",
617
+ "readable.pushNull", "readable.pushU", "readable.pushDyn",
608
618
  "readable.unshift", "readable.unshiftStr", "readable.read", "readable.setEncoding",
609
619
  "readable.nextChunk", "readable.nextChunkDyn", "readable.fromArr", "readable.resume",
610
620
  "readable.pipe", "readable.unpipe",
@@ -616,6 +626,7 @@ const USES_TIMERS_LIB_FNS = new Set([
616
626
  "process.activeResources",
617
627
  "stream.finished", "stream.finishedDyn", "stream.pipeline", "stream.pipelineDyn",
618
628
  "sp.finished", "sp.pipeline",
629
+ "sc.text", "sc.json", "sc.buffer",
619
630
  "net.listen", "net.listenCb", "net.listenOpts", "net.listenOptsCb",
620
631
  "net.connect", "net.connectCb", "net.connectLookup", "net.connectAttempt",
621
632
  "fs.existsChk",
@@ -710,7 +721,7 @@ class LlEmitter {
710
721
  * rewriter, union ToString/join) — interned per typeKey/unionId, defs
711
722
  * flushed with the shape helpers. */
712
723
  walkers = new LlWalkers(this);
713
- /** The dyn (ScrDyn DOM) helper registry — dyn.ts's interned ports of
724
+ /** The dyn (ScrDyn dyn) helper registry — dyn.ts's interned ports of
714
725
  * emit-walkers.ts's dyn slice. */
715
726
  dyn = new LlDyn(this);
716
727
  /** External declarations, in first-use order. */
@@ -1070,6 +1081,12 @@ class LlEmitter {
1070
1081
  if (this.mod.lib.exports.some((e) => e.params.includes("bytes"))) {
1071
1082
  this.declare(`declare ptr @scr_library_bytes_in(ptr, i64, ptr)`);
1072
1083
  }
1084
+ if (this.mod.lib.exports.some((e) => e.params.includes("i64"))) {
1085
+ this.declare(`declare double @scr_library_i64_in(i64, ptr)`);
1086
+ }
1087
+ if (this.mod.lib.exports.some((e) => e.params.includes("u64"))) {
1088
+ this.declare(`declare double @scr_library_u64_in(i64, ptr)`);
1089
+ }
1073
1090
  if (this.mod.lib.exports.some((e) => e.returns === "string")) {
1074
1091
  this.declare(`declare void @scr_library_str_out(ptr, ptr, ptr)`);
1075
1092
  }
@@ -1378,6 +1395,14 @@ class LlEmitter {
1378
1395
  const trapBytes = Buffer.byteLength(e.inboundBytesTrap, "utf8");
1379
1396
  out.push(`@sc_lib_bytes_trap_${e.symbol} = internal constant [${trapBytes + 1} x i8] c"${llStrBytes(e.inboundBytesTrap)}"`, ``);
1380
1397
  }
1398
+ if (e.inboundIntTrap !== undefined) {
1399
+ // The i64/u64-in helpers' host-contract trap message (ask 4): an
1400
+ // inbound integer past ±(2^53−1) cannot ride f64 exactly. Same
1401
+ // assembled structured form, same SC4012 code, same
1402
+ // emission-invariance argument as the bytes trap.
1403
+ const trapBytes = Buffer.byteLength(e.inboundIntTrap, "utf8");
1404
+ out.push(`@sc_lib_int_trap_${e.symbol} = internal constant [${trapBytes + 1} x i8] c"${llStrBytes(e.inboundIntTrap)}"`, ``);
1405
+ }
1381
1406
  e.params.forEach((cls, i) => {
1382
1407
  switch (cls) {
1383
1408
  case "f64":
@@ -1404,6 +1429,19 @@ class LlEmitter {
1404
1429
  body.push(` %c${i} = sitofp i32 %a${i} to double`);
1405
1430
  args.push(`double %c${i}`);
1406
1431
  break;
1432
+ case "i64":
1433
+ // Inbound declared-integer edge (ask 4): the helper converts
1434
+ // exactly or delivers the host-contract trap (past ±(2^53−1)
1435
+ // the value cannot ride f64 without silent rounding).
1436
+ params.push(`i64 %a${i}`);
1437
+ body.push(` %c${i} = call double @scr_library_i64_in(i64 %a${i}, ptr @sc_lib_int_trap_${e.symbol})`);
1438
+ args.push(`double %c${i}`);
1439
+ break;
1440
+ case "u64":
1441
+ params.push(`i64 %a${i}`);
1442
+ body.push(` %c${i} = call double @scr_library_u64_in(i64 %a${i}, ptr @sc_lib_int_trap_${e.symbol})`);
1443
+ args.push(`double %c${i}`);
1444
+ break;
1407
1445
  case "string":
1408
1446
  params.push(`ptr %a${i}_ptr`, `i64 %a${i}_len`);
1409
1447
  body.push(` %c${i} = call ptr @scr_library_str_in(ptr %a${i}_ptr, i64 %a${i}_len)`);
@@ -1430,6 +1468,16 @@ class LlEmitter {
1430
1468
  retType = "double";
1431
1469
  body.push(` %r = call double ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` ret double %r`);
1432
1470
  break;
1471
+ case "i64":
1472
+ case "u64":
1473
+ // The outbound declared-integer edge (ask 4): every value
1474
+ // reaching this return was PROVEN whole and inside the class's
1475
+ // range at compile time, so the fp-to-int conversion is exact
1476
+ // by construction — the crossing carries the mathematically
1477
+ // exact integer the f64 held.
1478
+ retType = "i64";
1479
+ body.push(` %r = call double ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` %z = ${e.returns === "i64" ? "fptosi" : "fptoui"} double %r to i64`, ` ret i64 %z`);
1480
+ break;
1433
1481
  case "bool":
1434
1482
  retType = "i8";
1435
1483
  body.push(` %r = call i1 ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` %z = zext i1 %r to i8`, ` ret i8 %z`);
@@ -1990,7 +2038,7 @@ class LlEmitter {
1990
2038
  return t;
1991
2039
  }
1992
2040
  case "dyn": {
1993
- // ToBoolean over the DOM kind (scr_dyn_truthy — JS-exact for
2041
+ // ToBoolean over the dyn kind (scr_dyn_truthy — JS-exact for
1994
2042
  // every kind; borrowed, never throws): `v || dflt` and condition
1995
2043
  // descent on checked-dynamic values.
1996
2044
  this.declare(`declare zeroext i1 @scr_dyn_truthy(ptr)`);
@@ -3668,7 +3716,7 @@ class LlEmitter {
3668
3716
  return this.own({ name: t, type: e.type });
3669
3717
  }
3670
3718
  if (v.type.kind === "dyn") {
3671
- // String(unknown): dispatch over the DOM kind (dyn.ts's sc_ds —
3719
+ // String(unknown): dispatch over the dyn kind (dyn.ts's sc_ds —
3672
3720
  // Node's String() incl. arrays-join and "[object Object]").
3673
3721
  const helper = this.dyn.dynToStrHelper();
3674
3722
  const t = B.tmp();
@@ -3969,7 +4017,7 @@ class LlEmitter {
3969
4017
  this.unionTagSwitch(u.name, def, (arm) => {
3970
4018
  if (isUnitType(arm)) {
3971
4019
  if (e.type.kind === "dyn") {
3972
- // A dyn-typed chain: the unit path is the undefined DOM
4020
+ // A dyn-typed chain: the unit path is the undefined dyn
3973
4021
  // value — dyn represents undefined directly.
3974
4022
  this.declare(`declare ptr @scr_dyn_undefined()`);
3975
4023
  this.declare(`declare ptr @scr_dyn_retain_v(ptr)`);
@@ -4265,9 +4313,9 @@ class LlEmitter {
4265
4313
  // the frame's release is a no-op) and the body reads it through
4266
4314
  // chainRecv.
4267
4315
  if (e.receiver.type.kind === "dyn") {
4268
- // A dyn (DOM) receiver — the `rawName?.match(re)` step: the
4316
+ // A dyn (dyn) receiver — the `rawName?.match(re)` step: the
4269
4317
  // nullish test reads the node's kind tag; the unit path is the
4270
- // undefined DOM singleton (dyn results) or nothing (void
4318
+ // undefined dyn singleton (dyn results) or nothing (void
4271
4319
  // bodies), the body runs over the bound receiver otherwise.
4272
4320
  const r = this.emitExpr(e.receiver);
4273
4321
  const kd = this.dynKind(r.name);
@@ -4419,7 +4467,7 @@ class LlEmitter {
4419
4467
  }
4420
4468
  if (e.type.kind === "dyn") {
4421
4469
  // A dyn-typed chain (`pricing?.[key]` over an unknown-valued
4422
- // index signature): the unit path is the undefined DOM value —
4470
+ // index signature): the unit path is the undefined dyn value —
4423
4471
  // dyn represents undefined directly, no union wrapper exists.
4424
4472
  const slotD = B.slot();
4425
4473
  B.entryAllocas.push(`${slotD} = alloca ptr`);
@@ -4866,14 +4914,14 @@ class LlEmitter {
4866
4914
  }
4867
4915
  case "jsonStringify": {
4868
4916
  // Type-directed serialization: the STATIC type picks an emitted
4869
- // serializer (interned per typeKey) — no DOM, no runtime dispatch.
4917
+ // serializer (interned per typeKey) — no dyn, no runtime dispatch.
4870
4918
  // The value temp is BORROWED (released with this statement's
4871
4919
  // frame); the result string is owned (+1). Never throws — except
4872
4920
  // the dyn root below.
4873
4921
  const v = this.emitExpr(e.value);
4874
4922
  let compact;
4875
4923
  if (e.value.type.kind === "dyn") {
4876
- // A dyn root: the runtime's DOM walker (scr_dyn_format_j — the
4924
+ // A dyn root: the runtime's dyn walker (scr_dyn_format_j — the
4877
4925
  // C backend's dispatch exactly): number/string/bool/null/array/
4878
4926
  // object exact, dropped members omitted, and a dropped ROOT
4879
4927
  // becomes the TEXT "undefined" (JSON.stringify(undefined) is
@@ -5038,7 +5086,7 @@ class LlEmitter {
5038
5086
  if (e.arg === null) {
5039
5087
  if (genT.nextT.kind === "dyn") {
5040
5088
  // Valueless resume on a dyn channel: JS's undefined — the
5041
- // DOM singleton rides the IN slot (+1 moves in).
5089
+ // dyn singleton rides the IN slot (+1 moves in).
5042
5090
  this.declare(`declare ptr @scr_dyn_undefined()`);
5043
5091
  this.declare(`declare ptr @scr_dyn_retain_v(ptr)`);
5044
5092
  this.declare(`declare void @scr_dyn_release_v(ptr)`);
@@ -5506,10 +5554,10 @@ class LlEmitter {
5506
5554
  return { name: "", type: e.type };
5507
5555
  }
5508
5556
  case "dynFrom": {
5509
- // Static value → fresh DOM tree (+1) through the interned per-type
5557
+ // Static value → fresh dyn tree (+1) through the interned per-type
5510
5558
  // converter; the operand stays borrowed (frame-released as usual).
5511
5559
  // Bare unit literals (an `undefined`/`null` stored under an
5512
- // `unknown` index signature) are the DOM unit values directly.
5560
+ // `unknown` index signature) are the dyn unit values directly.
5513
5561
  if (e.value.kind === "unitLit") {
5514
5562
  const t = B.tmp();
5515
5563
  if (e.value.unit === "undefined") {
@@ -5527,7 +5575,7 @@ class LlEmitter {
5527
5575
  }
5528
5576
  const v = this.emitExpr(e.value);
5529
5577
  if (v.type.kind === "func") {
5530
- // A closure boxes as the DOM's function kind: retained closure +
5578
+ // A closure boxes as the checked-dynamic tree's function kind: retained closure +
5531
5579
  // the per-signature call thunk + the interned signature key. The
5532
5580
  // best-effort name rides along (null when the lowering had none).
5533
5581
  const name = e.fnName !== undefined && e.fnName !== "" ? this.cstr(e.fnName) : "null";
@@ -5543,8 +5591,8 @@ class LlEmitter {
5543
5591
  return this.own({ name: t, type: e.type });
5544
5592
  }
5545
5593
  case "dynFromJsval": {
5546
- // Island value → DOM: the by-reference wrap (scr_dyn_from_jsval
5547
- // retains the cell in; engine scalars normalize to native DOM
5594
+ // Island value → dyn: the by-reference wrap (scr_dyn_from_jsval
5595
+ // retains the cell in; engine scalars normalize to native dyn
5548
5596
  // kinds at wrap time). Operand borrowed, result +1, never throws.
5549
5597
  const v = this.emitExpr(e.value);
5550
5598
  this.declare(`declare ptr @scr_dyn_from_jsval(ptr)`);
@@ -5563,7 +5611,7 @@ class LlEmitter {
5563
5611
  return this.own({ name: t, type: e.type });
5564
5612
  }
5565
5613
  case "dynCheck": {
5566
- // The dynamic boundary: validate the DOM against the target type
5614
+ // The dynamic boundary: validate the checked-dynamic tree against the target type
5567
5615
  // and BUILD the typed value (+1) — or throw the catchable
5568
5616
  // path-annotated TypeError. The dyn temp is BORROWED; the result
5569
5617
  // joins the frame BEFORE the pending check so an unwind releases
@@ -5584,11 +5632,11 @@ class LlEmitter {
5584
5632
  // spelling rides along for Node's "<name> is not a function".
5585
5633
  const callee = this.emitExpr(e.callee);
5586
5634
  if (e.spreads !== undefined && e.spreads.length > 0) {
5587
- // The RUNTIME-ARITY form (`f(...args)`): one fresh DOM array
5635
+ // The RUNTIME-ARITY form (`f(...args)`): one fresh dyn array
5588
5636
  // collects the arguments left-to-right — plain args move in
5589
5637
  // (push takes ownership), spread args FLATTEN (push_spread
5590
5638
  // retains elements in and throws V8's spread-call TypeError for
5591
- // non-iterable DOM kinds, checked per spread — JS's
5639
+ // non-iterable dyn kinds, checked per spread — JS's
5592
5640
  // ArgumentListEvaluation order) — then apply calls through the
5593
5641
  // array's elements (borrowed, exactly scr_dyn_call).
5594
5642
  this.declare(`declare ptr @scr_dyn_new_arr()`);
@@ -5661,7 +5709,7 @@ class LlEmitter {
5661
5709
  return out;
5662
5710
  }
5663
5711
  case "dynArrLit": {
5664
- // A DOM array built element-by-element: ownership of each dyn
5712
+ // A dyn array built element-by-element: ownership of each dyn
5665
5713
  // element MOVES into the array (scr_dyn_arr_push's contract).
5666
5714
  this.declare(`declare ptr @scr_dyn_new_arr()`);
5667
5715
  this.declare(`declare void @scr_dyn_arr_push(ptr, ptr)`);
@@ -5676,7 +5724,7 @@ class LlEmitter {
5676
5724
  return out;
5677
5725
  }
5678
5726
  case "dynObjLit": {
5679
- // A DOM object built member-by-member: key then value, source
5727
+ // A dyn object built member-by-member: key then value, source
5680
5728
  // order. scr_dyn_key_set BORROWS all three (the member retains the
5681
5729
  // value in); the receiver is a fresh OBJ, so the non-object throw
5682
5730
  // paths are unreachable here.
@@ -5693,7 +5741,7 @@ class LlEmitter {
5693
5741
  return out;
5694
5742
  }
5695
5743
  case "dynKeyGet": {
5696
- // Keyed read on the DOM through the one interned helper — the
5744
+ // Keyed read on the checked-dynamic tree through the one interned helper — the
5697
5745
  // non-optional form throws JS's TypeError on an undefined/null
5698
5746
  // receiver, and HANDLE receivers can throw the loud unmodeled-
5699
5747
  // property ladder on EITHER form; the result is owned (+1).
@@ -5778,7 +5826,7 @@ class LlEmitter {
5778
5826
  const [d, s, st] = e.left.type.kind === "dyn" ? [l, r, e.right.type] : [r, l, e.left.type];
5779
5827
  let test;
5780
5828
  if (st.kind === "dyn") {
5781
- // dyn vs dyn: whole-DOM strict equality.
5829
+ // dyn vs dyn: whole-dyn strict equality.
5782
5830
  this.declare(`declare zeroext i1 @scr_dyn_strict_eq(ptr, ptr)`);
5783
5831
  test = B.tmp();
5784
5832
  B.line(`${test} = call zeroext i1 @scr_dyn_strict_eq(ptr ${l.name}, ptr ${r.name})`);
@@ -5831,7 +5879,7 @@ class LlEmitter {
5831
5879
  return { name: neg, type: e.type };
5832
5880
  }
5833
5881
  case "dynTest": {
5834
- // A pure kind compare on the DOM node — borrowed; only the truthy
5882
+ // A pure kind compare on the dyn node — borrowed; only the truthy
5835
5883
  // form also reads a scalar payload (the runtime's ToBoolean).
5836
5884
  const d = this.emitExpr(e.value);
5837
5885
  let test;
@@ -5841,7 +5889,7 @@ class LlEmitter {
5841
5889
  B.line(`${test} = call zeroext i1 @scr_dyn_truthy(ptr ${d.name})`);
5842
5890
  }
5843
5891
  else if (e.test === "error") {
5844
- // `u instanceof Error`: the DOM's error encoding — an object
5892
+ // `u instanceof Error`: the checked-dynamic tree's error encoding — an object
5845
5893
  // carrying the reserved "%error" marker key — or a real engine
5846
5894
  // Error held by reference (the isl helper answers false for
5847
5895
  // every non-JSVAL kind, so the call is unconditional).
@@ -5908,7 +5956,7 @@ class LlEmitter {
5908
5956
  test = orIsl(oneOf([DK.OBJ, DK.ARR, DK.BYTES, DK.HANDLE, DK.PROMISE, DK.NULL]), "scr_dyn_isl_typeof_is", this.cstr("object"));
5909
5957
  }
5910
5958
  else if (e.test === "array") {
5911
- // Array.isArray: the DOM's array kind, or the engine's own
5959
+ // Array.isArray: the checked-dynamic tree's array kind, or the engine's own
5912
5960
  // answer for an engine-held value.
5913
5961
  test = orIsl(oneOf([DK.ARR]), "scr_dyn_isl_is_array");
5914
5962
  }
@@ -5934,7 +5982,7 @@ class LlEmitter {
5934
5982
  return { name: neg, type: e.type };
5935
5983
  }
5936
5984
  case "dynDestrCheck": {
5937
- // RequireObjectCoercible with V8's destructuring TypeError. DOM
5985
+ // RequireObjectCoercible with V8's destructuring TypeError. dyn
5938
5986
  // values check in the runtime helper and pass through unchanged
5939
5987
  // (same temp, same ownership); island values check in the engine
5940
5988
  // (a fresh +1 cell for the same value comes back).
@@ -5955,7 +6003,7 @@ class LlEmitter {
5955
6003
  }
5956
6004
  case "dynIterN": {
5957
6005
  // GetIterator + first-N steps as a fresh array (V8's exact
5958
- // not-iterable TypeError on non-iterables): the DOM helper for
6006
+ // not-iterable TypeError on non-iterables): the dyn helper for
5959
6007
  // dyn operands, the engine's real iterator protocol for island
5960
6008
  // ones.
5961
6009
  const v = this.emitExpr(e.value);
@@ -5987,7 +6035,9 @@ class LlEmitter {
5987
6035
  const v = this.emitExpr(e.value);
5988
6036
  const payload = e.type.kind === "promise" && e.type.inner.kind === "void"
5989
6037
  ? 0 // SCR_ISLP_VOID
5990
- : 4; // SCR_ISLP_JSVAL
6038
+ : e.type.kind === "promise" && e.type.inner.kind === "array" && e.type.inner.elem.kind === "jsval"
6039
+ ? 5 // SCR_ISLP_JSVAL_ARR: the Array.isArray-gated by-reference exit at settle
6040
+ : 4; // SCR_ISLP_JSVAL
5991
6041
  this.declare(`declare ptr @scr_jsval_bridge_promise(ptr, i32)`);
5992
6042
  const t = B.tmp();
5993
6043
  B.line(`${t} = call ptr @scr_jsval_bridge_promise(ptr ${v.name}, i32 ${payload})`);
@@ -6035,7 +6085,7 @@ class LlEmitter {
6035
6085
  case "string":
6036
6086
  return simple("scr_jsval_from_str", "ptr", false);
6037
6087
  case "dyn":
6038
- // A CHECKED-DYNAMIC (DOM) value entering the island: deep copy,
6088
+ // A CHECKED-DYNAMIC (dyn) value entering the island: deep copy,
6039
6089
  // data kinds only — boxed functions/handles/promises throw the
6040
6090
  // catchable TypeError in the runtime, and a wrapped island value
6041
6091
  // unwraps to the SAME engine value (the identity round trip).
@@ -6047,6 +6097,25 @@ class LlEmitter {
6047
6097
  case "url":
6048
6098
  // A URL crossing IN: an engine URL instance built from href.
6049
6099
  return simple("scr_jsval_from_url", "ptr", true);
6100
+ case "promise": {
6101
+ // A STATIC promise crossing IN: a real engine thenable settled
6102
+ // when the scriptc promise settles (the async-callback return
6103
+ // bridge). from_promise takes ownership of a +1 — retain past
6104
+ // the borrowed frame temp. The C emitter's rule, mirrored.
6105
+ const tag = islandPromisePayloadTag(e.value.type.inner);
6106
+ if (!tag)
6107
+ throw new Error("llvm emitter bug: jsMarshal of a promise outside the bridge payload domain");
6108
+ const tagN = { void: 0, f64: 1, bool: 2, string: 3, jsval: 4, jsvalArr: 5 }[tag];
6109
+ this.declare(`declare ptr @scr_promise_retain(ptr)`);
6110
+ this.declare(`declare ptr @scr_jsval_from_promise(ptr, i32)`);
6111
+ const pr = B.tmp();
6112
+ B.line(`${pr} = call ptr @scr_promise_retain(ptr ${v.name})`);
6113
+ const t = B.tmp();
6114
+ B.line(`${t} = call ptr @scr_jsval_from_promise(ptr ${pr}, i32 ${tagN})`);
6115
+ const out = this.own({ name: t, type: e.type });
6116
+ this.emitPendingCheck();
6117
+ return out;
6118
+ }
6050
6119
  case "func": {
6051
6120
  // A closure entering the island as a host function: from_closure
6052
6121
  // retains it; the engine's finalizer releases it at teardown. The
@@ -6378,6 +6447,17 @@ class LlEmitter {
6378
6447
  return out;
6379
6448
  }
6380
6449
  default: {
6450
+ // `any[]`-declared slot: Array.isArray-gated, elements BY
6451
+ // REFERENCE (identity crosses; the spine is a snapshot copy).
6452
+ // JSON-safe element types keep the round trip below.
6453
+ if (e.type.kind === "array" && e.type.elem.kind === "jsval") {
6454
+ this.declare(`declare ptr @scr_jsval_exit_jsval_arr(ptr)`);
6455
+ const t = B.tmp();
6456
+ B.line(`${t} = call ptr @scr_jsval_exit_jsval_arr(ptr ${v.name})`);
6457
+ const out = this.own({ name: t, type: e.type });
6458
+ this.emitPendingCheck();
6459
+ return out;
6460
+ }
6381
6461
  // An undefined-armed union target: the engine's undefined takes
6382
6462
  // the undefined arm FIRST (JSON cannot spell it); then null and
6383
6463
  // data ride the round trip into the union's dynCheck like any
@@ -6414,11 +6494,31 @@ class LlEmitter {
6414
6494
  B.br(lj);
6415
6495
  B.startBlock(ld);
6416
6496
  this.frames.push([]);
6417
- const t = roundTrip();
6418
- this.own({ name: t, type: e.type });
6419
- this.emitPendingCheck();
6420
- this.moveTemp({ name: t, type: e.type });
6421
- B.line(`store ptr ${t}, ptr ${slot}`);
6497
+ const unionDef = this.unionsById.get(e.type.unionId);
6498
+ const dataArms = unionDef ? unionDef.arms.flatMap((a, i) => (isUnitType(a) ? [] : [{ a, i }])) : [];
6499
+ const jsvalArr = dataArms.length === 1 && dataArms[0].a.kind === "array" && dataArms[0].a.elem.kind === "jsval" ? dataArms[0] : null;
6500
+ let t;
6501
+ if (jsvalArr) {
6502
+ // The `any[] | undefined` defaulted-parameter spelling: the
6503
+ // engine array exits BY REFERENCE into the data arm.
6504
+ this.declare(`declare ptr @scr_jsval_exit_jsval_arr(ptr)`);
6505
+ this.declare(`declare ptr @scr_union_new_ref(i32, ptr, ptr, ptr, ptr)`);
6506
+ this.declare(`declare ptr @scr_arr_retain_v(ptr)`);
6507
+ this.declare(`declare void @scr_arr_release_v(ptr)`);
6508
+ const arr = B.tmp();
6509
+ B.line(`${arr} = call ptr @scr_jsval_exit_jsval_arr(ptr ${v.name})`);
6510
+ this.emitPendingCheck();
6511
+ t = B.tmp();
6512
+ 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)`);
6513
+ B.line(`store ptr ${t}, ptr ${slot}`);
6514
+ }
6515
+ else {
6516
+ t = roundTrip();
6517
+ this.own({ name: t, type: e.type });
6518
+ this.emitPendingCheck();
6519
+ this.moveTemp({ name: t, type: e.type });
6520
+ B.line(`store ptr ${t}, ptr ${slot}`);
6521
+ }
6422
6522
  this.releaseFrame(this.frames.pop());
6423
6523
  B.br(lj);
6424
6524
  B.startBlock(lj);
@@ -6631,7 +6731,7 @@ class LlEmitter {
6631
6731
  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`);
6632
6732
  break;
6633
6733
  case "dyn":
6634
- // A checked-dynamic (+1 DOM) result: deep copy into the engine
6734
+ // A checked-dynamic (+1 dyn) result: deep copy into the engine
6635
6735
  // (the jsMarshal dyn rule); NULL is the throw-path dummy.
6636
6736
  this.declare(`declare ptr @scr_jsval_from_dyn(ptr)`);
6637
6737
  this.declare(`declare void @scr_dyn_release(ptr)`);
@@ -6662,7 +6762,7 @@ class LlEmitter {
6662
6762
  this.resolveThunkDefs.push(...d);
6663
6763
  return sym;
6664
6764
  }
6665
- /** Loads a DOM node's kind tag (i32 at +8) — the dyn expression tests'
6765
+ /** Loads a dyn node's kind tag (i32 at +8) — the dyn expression tests'
6666
6766
  * shared read. */
6667
6767
  dynKind(d) {
6668
6768
  const B = this.B;
@@ -8255,6 +8355,10 @@ class LlEmitter {
8255
8355
  return call("scr_bytes_get", "double (ptr, double)", `ptr ${r.name}, double ${args[0].name}`, false, false);
8256
8356
  case "slice":
8257
8357
  return call("scr_bytes_slice", "ptr (ptr, double, double)", `ptr ${r.name}, double ${args[0]?.name ?? f64Lit(0)}, double ${args[1]?.name ?? F64_INF}`, true, false);
8358
+ case "subarray":
8359
+ // A +1 VIEW aliasing the receiver's storage (subarray / Buffer's
8360
+ // slice); same index defaults as slice.
8361
+ return call("scr_bytes_subarray", "ptr (ptr, double, double)", `ptr ${r.name}, double ${args[0]?.name ?? f64Lit(0)}, double ${args[1]?.name ?? F64_INF}`, true, false);
8258
8362
  case "setFrom":
8259
8363
  // dst.set(src, offset?) — void; throws Node's RangeError on
8260
8364
  // overflow.
@@ -8308,6 +8412,10 @@ class LlEmitter {
8308
8412
  B.line(`${t} = fcmp one double ${idx.name}, ${f64Lit(-1)}`);
8309
8413
  return { name: t, type: e.type };
8310
8414
  }
8415
+ case "fillElem":
8416
+ // Per-element TypedArray fill (non-u8): slice-style index
8417
+ // defaults, never throws; the receiver comes back +1.
8418
+ return call("scr_bytes_fill_elem", "ptr (ptr, double, double, double)", `ptr ${r.name}, double ${args[0].name}, double ${args[1]?.name ?? f64Lit(0)}, double ${args[2]?.name ?? F64_INF}`, true, false);
8311
8419
  case "fill":
8312
8420
  case "fillNum": {
8313
8421
  const sym = method === "fill" ? "scr_bytes_fill" : "scr_bytes_fill_num";
@@ -8483,7 +8591,7 @@ class LlEmitter {
8483
8591
  // A dyn JOIN (the C helper's `surface` dyn arm): declared hits
8484
8592
  // convert through the per-type toDyn walker (borrowed read → fresh
8485
8593
  // +1 tree), a dyn-valued overflow hit passes through (+1 from the
8486
- // map get), and a miss is JS's undefined — the DOM singleton.
8594
+ // map get), and a miss is JS's undefined — the dyn singleton.
8487
8595
  this.declare(`declare zeroext i1 @scr_str_eq(ptr, ptr)`);
8488
8596
  for (const f of overflowOnly ? [] : shape.fields) {
8489
8597
  const lit = this.internLiteral(f.name);
@@ -8561,7 +8669,7 @@ class LlEmitter {
8561
8669
  B.br(join);
8562
8670
  B.startBlock(ln);
8563
8671
  }
8564
- // The miss path: JS's undefined — the DOM singleton, retained.
8672
+ // The miss path: JS's undefined — the dyn singleton, retained.
8565
8673
  this.declare(`declare ptr @scr_dyn_undefined()`);
8566
8674
  this.declare(`declare ptr @scr_dyn_retain_v(ptr)`);
8567
8675
  const u = B.tmp();
@@ -10559,11 +10667,12 @@ class LlEmitter {
10559
10667
  if (MAY_THROW_LIB_FNS.has(e.fn) && LIB_FN_SYMS[e.fn] === undefined) {
10560
10668
  throw new LlvmUnsupportedError(`libCall:${e.fn}`, e.loc);
10561
10669
  }
10562
- if (e.fn === "math.floor") {
10670
+ if (e.fn === "math.floor" || e.fn === "math.trunc" || e.fn === "math.ceil") {
10671
+ const intr = e.fn === "math.floor" ? "floor" : e.fn === "math.trunc" ? "trunc" : "ceil";
10563
10672
  const v = this.emitExpr(e.args[0]);
10564
- this.declare(`declare double @llvm.floor.f64(double)`);
10673
+ this.declare(`declare double @llvm.${intr}.f64(double)`);
10565
10674
  const t = B.tmp();
10566
- B.line(`${t} = call double @llvm.floor.f64(double ${v.name})`);
10675
+ B.line(`${t} = call double @llvm.${intr}.f64(double ${v.name})`);
10567
10676
  return { name: t, type: e.type };
10568
10677
  }
10569
10678
  if (e.fn === "math.abs") {