@scriptc/compiler 0.0.9 → 0.0.11

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 +54 -9
  2. package/dist/backend/emission/emit-exprs.js +170 -14
  3. package/dist/backend/emission/emit-exprs.js.map +1 -1
  4. package/dist/backend/emission/emit-walkers.js +29 -2
  5. package/dist/backend/emission/emit-walkers.js.map +1 -1
  6. package/dist/backend/emission/emitter.js +25 -1
  7. package/dist/backend/emission/emitter.js.map +1 -1
  8. package/dist/backend/llvm/dyn.d.ts +1 -0
  9. package/dist/backend/llvm/dyn.js +83 -1
  10. package/dist/backend/llvm/dyn.js.map +1 -1
  11. package/dist/backend/llvm/emitter.js +210 -13
  12. package/dist/backend/llvm/emitter.js.map +1 -1
  13. package/dist/coverage/surface-manifest.js +16 -2
  14. package/dist/coverage/surface-manifest.js.map +1 -1
  15. package/dist/diagnostics/diagnostic.d.ts +41 -14
  16. package/dist/diagnostics/diagnostic.js +79 -27
  17. package/dist/diagnostics/diagnostic.js.map +1 -1
  18. package/dist/diagnostics/render.js +8 -0
  19. package/dist/diagnostics/render.js.map +1 -1
  20. package/dist/frontend/lowering/lib-boundary.js +11 -1
  21. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  22. package/dist/frontend/lowering/lower-builtins.d.ts +69 -0
  23. package/dist/frontend/lowering/lower-builtins.js +380 -4
  24. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  25. package/dist/frontend/lowering/lower-calls.d.ts +41 -0
  26. package/dist/frontend/lowering/lower-calls.js +559 -11
  27. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  28. package/dist/frontend/lowering/lower-classes.d.ts +7 -0
  29. package/dist/frontend/lowering/lower-classes.js +51 -1
  30. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  31. package/dist/frontend/lowering/lower-containers.d.ts +21 -0
  32. package/dist/frontend/lowering/lower-containers.js +262 -17
  33. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  34. package/dist/frontend/lowering/lower-dgram.js +92 -17
  35. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  36. package/dist/frontend/lowering/lower-emitter.d.ts +70 -3
  37. package/dist/frontend/lowering/lower-emitter.js +436 -29
  38. package/dist/frontend/lowering/lower-emitter.js.map +1 -1
  39. package/dist/frontend/lowering/lower-exprs.d.ts +80 -5
  40. package/dist/frontend/lowering/lower-exprs.js +651 -23
  41. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  42. package/dist/frontend/lowering/lower-modules.d.ts +8 -5
  43. package/dist/frontend/lowering/lower-modules.js +144 -19
  44. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  45. package/dist/frontend/lowering/lower-namespaces.d.ts +39 -11
  46. package/dist/frontend/lowering/lower-namespaces.js +166 -24
  47. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  48. package/dist/frontend/lowering/lower-server.js +211 -4
  49. package/dist/frontend/lowering/lower-server.js.map +1 -1
  50. package/dist/frontend/lowering/lower-stmts.d.ts +1 -5
  51. package/dist/frontend/lowering/lower-stmts.js +293 -10
  52. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  53. package/dist/frontend/lowering/lower-stream.js +178 -10
  54. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  55. package/dist/frontend/lowering/lowerer.d.ts +53 -1
  56. package/dist/frontend/lowering/lowerer.js +210 -19
  57. package/dist/frontend/lowering/lowerer.js.map +1 -1
  58. package/dist/frontend/lowering/surfaces.d.ts +44 -0
  59. package/dist/frontend/lowering/surfaces.js +234 -3
  60. package/dist/frontend/lowering/surfaces.js.map +1 -1
  61. package/dist/frontend/npm.d.ts +12 -0
  62. package/dist/frontend/npm.js +30 -0
  63. package/dist/frontend/npm.js.map +1 -1
  64. package/dist/frontend/program.d.ts +25 -0
  65. package/dist/frontend/program.js +144 -135
  66. package/dist/frontend/program.js.map +1 -1
  67. package/dist/frontend/shared.d.ts +1 -1
  68. package/dist/frontend/shared.js +1 -1
  69. package/dist/frontend/shared.js.map +1 -1
  70. package/dist/frontend/types.d.ts +13 -0
  71. package/dist/frontend/types.js +84 -7
  72. package/dist/frontend/types.js.map +1 -1
  73. package/dist/index.d.ts +2 -1
  74. package/dist/index.js +157 -12
  75. package/dist/index.js.map +1 -1
  76. package/dist/ir/nodes.d.ts +163 -13
  77. package/dist/ir/nodes.js +65 -6
  78. package/dist/ir/nodes.js.map +1 -1
  79. package/dist/ir/validate.js +64 -5
  80. package/dist/ir/validate.js.map +1 -1
  81. package/dist/library/fence-eval.d.ts +77 -0
  82. package/dist/library/fence-eval.js +395 -0
  83. package/dist/library/fence-eval.js.map +1 -0
  84. package/dist/library/int-infer.d.ts +119 -0
  85. package/dist/library/int-infer.js +1301 -0
  86. package/dist/library/int-infer.js.map +1 -0
  87. package/dist/library/int-infer.test.d.ts +1 -0
  88. package/dist/library/int-infer.test.js +279 -0
  89. package/dist/library/int-infer.test.js.map +1 -0
  90. package/dist/library/profile.d.ts +43 -6
  91. package/dist/library/profile.js +179 -31
  92. package/dist/library/profile.js.map +1 -1
  93. package/dist/library/sidecar.d.ts +23 -0
  94. package/dist/library/sidecar.js +150 -16
  95. package/dist/library/sidecar.js.map +1 -1
  96. package/package.json +2 -2
  97. package/surface-manifest.json +208 -10
@@ -197,6 +197,11 @@ const LIB_FN_SYMS = {
197
197
  "bytes.compareChk": "scr_bytes_compare_chk",
198
198
  "buffer.newStringFail": "scr_buffer_new_string_fail",
199
199
  "fs.toUnixTimestamp": "scr_fs_to_unix_timestamp",
200
+ "fs.existsChk": "scr_fs_exists_async",
201
+ "fs.mkdtempSyncChk": "scr_fs_mkdtemp_sync_chk",
202
+ "net.connectAttempt": "scr_net_connect_attempt",
203
+ "fs.lchmodSyncChk": "scr_fs_lchmod_sync_chk",
204
+ "fsp.lchmodChk": "scr_fsp_lchmod_chk",
200
205
  "fs.readFileSyncBuf": "scr_fs_read_file_bytes",
201
206
  "fs.readFileSyncBytes": "scr_fs_read_file_bytes",
202
207
  "fs.writeFileSyncBytes": "scr_fs_write_file_bytes",
@@ -342,9 +347,10 @@ const LIB_FN_SYMS = {
342
347
  // ambient-this read never throw. The fs dyn read is the sync-fs story.
343
348
  "json.parse": "scr_json_parse",
344
349
  "dyn.keySet": "scr_dyn_key_set",
350
+ "dyn.iterPack": "scr_dyn_iter_pack",
345
351
  "dyn.defineProps": "scr_dyn_define_props",
346
352
  "dyn.typeof": "scr_dyn_typeof",
347
- "dyn.toString": "scr_dyn_to_string",
353
+ "dyn.toString": "scr_dyn_to_string_method",
348
354
  "dyn.this": "scr_dyn_this_get",
349
355
  "insp.dyn": "scr_insp_dyn",
350
356
  "insp.dynS": "scr_insp_dyn_s",
@@ -397,6 +403,8 @@ const LIB_FN_SYMS = {
397
403
  // generic pending check; loop liveness rides USES_TIMERS_LIB_FNS.
398
404
  "readable.push": "scr_stream_push",
399
405
  "readable.pushStr": "scr_stream_push_str",
406
+ "readable.pushStrEnc": "scr_stream_push_str_enc",
407
+ "readable.pushEncoding": "scr_stream_set_push_encoding",
400
408
  "readable.pushNull": "scr_stream_push_null",
401
409
  "readable.pushDyn": "scr_stream_push_dyn",
402
410
  "readable.unshift": "scr_stream_unshift",
@@ -498,6 +506,11 @@ const LIB_FN_SYMS = {
498
506
  // stream/promises' finished form (+1 promise; may-throw pending check;
499
507
  // the pipeline form needs the stream-array compound and emits below).
500
508
  "sp.finished": "scr_sp_finished",
509
+ // stream/consumers' promise consumers (+1 promises; may-throw pending
510
+ // check — the 'newListener' meta emit can run user code).
511
+ "sc.text": "scr_sc_text",
512
+ "sc.json": "scr_sc_json",
513
+ "sc.buffer": "scr_sc_buffer",
501
514
  "dc.channel": "scr_dc_channel",
502
515
  "dc.subscribe": "scr_dc_subscribe",
503
516
  "dc.unsubscribe": "scr_dc_unsubscribe",
@@ -559,6 +572,14 @@ const LIB_FN_SYMS = {
559
572
  "dyn.objKeys": "scr_dyn_obj_keys",
560
573
  "dyn.hasOwn": "scr_dyn_has_own",
561
574
  "dyn.assign": "scr_dyn_assign",
575
+ // variadic Object.assign: the source pack (push never throws; the
576
+ // spread flatten throws V8's spread-call TypeErrors) and the final
577
+ // left-to-right copy (ToObject TypeError on a nullish target).
578
+ "dyn.packPush": "scr_dyn_pack_push",
579
+ "dyn.packPushSpread": "scr_dyn_pack_push_spread",
580
+ "dyn.packPushSpreadIter": "scr_dyn_pack_push_spread_iter",
581
+ "dyn.assignAll": "scr_dyn_assign_all",
582
+ "dyn.objCreateNullProto": "scr_dyn_new_obj_null_proto",
562
583
  "dyn.objValues": "scr_dyn_obj_values",
563
584
  "dyn.objEntries": "scr_dyn_obj_entries",
564
585
  "dyn.structuredClone": "scr_structured_clone",
@@ -590,7 +611,8 @@ const USES_TIMERS_LIB_FNS = new Set([
590
611
  "readable.init", "writable.init", "duplex.init", "transform.init", "passthrough.init",
591
612
  "readable.newDyn", "writable.newDyn", "duplex.newDyn", "transform.newDyn", "passthrough.newDyn",
592
613
  "readable.initDyn", "writable.initDyn", "duplex.initDyn", "transform.initDyn", "passthrough.initDyn",
593
- "readable.push", "readable.pushStr", "readable.pushNull", "readable.pushU", "readable.pushDyn",
614
+ "readable.push", "readable.pushStr", "readable.pushStrEnc", "readable.pushEncoding",
615
+ "readable.pushNull", "readable.pushU", "readable.pushDyn",
594
616
  "readable.unshift", "readable.unshiftStr", "readable.read", "readable.setEncoding",
595
617
  "readable.nextChunk", "readable.nextChunkDyn", "readable.fromArr", "readable.resume",
596
618
  "readable.pipe", "readable.unpipe",
@@ -602,8 +624,10 @@ const USES_TIMERS_LIB_FNS = new Set([
602
624
  "process.activeResources",
603
625
  "stream.finished", "stream.finishedDyn", "stream.pipeline", "stream.pipelineDyn",
604
626
  "sp.finished", "sp.pipeline",
627
+ "sc.text", "sc.json", "sc.buffer",
605
628
  "net.listen", "net.listenCb", "net.listenOpts", "net.listenOptsCb",
606
- "net.connect", "net.connectCb", "net.connectLookup",
629
+ "net.connect", "net.connectCb", "net.connectLookup", "net.connectAttempt",
630
+ "fs.existsChk",
607
631
  "http.createServer", "http.createServerEmpty",
608
632
  "http.request", "http.requestCb", "http.requestUrl", "http.requestUrlCb",
609
633
  "http.requestConn", "http.requestConnCb",
@@ -1055,6 +1079,12 @@ class LlEmitter {
1055
1079
  if (this.mod.lib.exports.some((e) => e.params.includes("bytes"))) {
1056
1080
  this.declare(`declare ptr @scr_library_bytes_in(ptr, i64, ptr)`);
1057
1081
  }
1082
+ if (this.mod.lib.exports.some((e) => e.params.includes("i64"))) {
1083
+ this.declare(`declare double @scr_library_i64_in(i64, ptr)`);
1084
+ }
1085
+ if (this.mod.lib.exports.some((e) => e.params.includes("u64"))) {
1086
+ this.declare(`declare double @scr_library_u64_in(i64, ptr)`);
1087
+ }
1058
1088
  if (this.mod.lib.exports.some((e) => e.returns === "string")) {
1059
1089
  this.declare(`declare void @scr_library_str_out(ptr, ptr, ptr)`);
1060
1090
  }
@@ -1363,6 +1393,14 @@ class LlEmitter {
1363
1393
  const trapBytes = Buffer.byteLength(e.inboundBytesTrap, "utf8");
1364
1394
  out.push(`@sc_lib_bytes_trap_${e.symbol} = internal constant [${trapBytes + 1} x i8] c"${llStrBytes(e.inboundBytesTrap)}"`, ``);
1365
1395
  }
1396
+ if (e.inboundIntTrap !== undefined) {
1397
+ // The i64/u64-in helpers' host-contract trap message (ask 4): an
1398
+ // inbound integer past ±(2^53−1) cannot ride f64 exactly. Same
1399
+ // assembled structured form, same SC4012 code, same
1400
+ // emission-invariance argument as the bytes trap.
1401
+ const trapBytes = Buffer.byteLength(e.inboundIntTrap, "utf8");
1402
+ out.push(`@sc_lib_int_trap_${e.symbol} = internal constant [${trapBytes + 1} x i8] c"${llStrBytes(e.inboundIntTrap)}"`, ``);
1403
+ }
1366
1404
  e.params.forEach((cls, i) => {
1367
1405
  switch (cls) {
1368
1406
  case "f64":
@@ -1389,6 +1427,19 @@ class LlEmitter {
1389
1427
  body.push(` %c${i} = sitofp i32 %a${i} to double`);
1390
1428
  args.push(`double %c${i}`);
1391
1429
  break;
1430
+ case "i64":
1431
+ // Inbound declared-integer edge (ask 4): the helper converts
1432
+ // exactly or delivers the host-contract trap (past ±(2^53−1)
1433
+ // the value cannot ride f64 without silent rounding).
1434
+ params.push(`i64 %a${i}`);
1435
+ body.push(` %c${i} = call double @scr_library_i64_in(i64 %a${i}, ptr @sc_lib_int_trap_${e.symbol})`);
1436
+ args.push(`double %c${i}`);
1437
+ break;
1438
+ case "u64":
1439
+ params.push(`i64 %a${i}`);
1440
+ body.push(` %c${i} = call double @scr_library_u64_in(i64 %a${i}, ptr @sc_lib_int_trap_${e.symbol})`);
1441
+ args.push(`double %c${i}`);
1442
+ break;
1392
1443
  case "string":
1393
1444
  params.push(`ptr %a${i}_ptr`, `i64 %a${i}_len`);
1394
1445
  body.push(` %c${i} = call ptr @scr_library_str_in(ptr %a${i}_ptr, i64 %a${i}_len)`);
@@ -1415,6 +1466,16 @@ class LlEmitter {
1415
1466
  retType = "double";
1416
1467
  body.push(` %r = call double ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` ret double %r`);
1417
1468
  break;
1469
+ case "i64":
1470
+ case "u64":
1471
+ // The outbound declared-integer edge (ask 4): every value
1472
+ // reaching this return was PROVEN whole and inside the class's
1473
+ // range at compile time, so the fp-to-int conversion is exact
1474
+ // by construction — the crossing carries the mathematically
1475
+ // exact integer the f64 held.
1476
+ retType = "i64";
1477
+ 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`);
1478
+ break;
1418
1479
  case "bool":
1419
1480
  retType = "i8";
1420
1481
  body.push(` %r = call i1 ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` %z = zext i1 %r to i8`, ` ret i8 %z`);
@@ -4178,6 +4239,33 @@ class LlEmitter {
4178
4239
  B.line(`${t} = load ptr, ptr ${slot}`);
4179
4240
  return this.own({ name: t, type: e.type });
4180
4241
  }
4242
+ if (e.left.type.kind === "dyn") {
4243
+ // The checked-dynamic form: the runtime kind decides (UNDEF/
4244
+ // NULL take the default; a wrapped island value asks the
4245
+ // engine); the right runs lazily in its branch (already dyn).
4246
+ const l = this.emitExpr(e.left);
4247
+ this.moveTemp(l);
4248
+ this.declare(`declare zeroext i1 @scr_dyn_is_nullish(ptr)`);
4249
+ const slot = B.slot();
4250
+ B.entryAllocas.push(`${slot} = alloca ptr`);
4251
+ const isN = B.tmp();
4252
+ B.line(`${isN} = call zeroext i1 @scr_dyn_is_nullish(ptr ${l.name})`);
4253
+ const lu = B.newLabel("nuld.u");
4254
+ const lv = B.newLabel("nuld.v");
4255
+ const lj = B.newLabel("nuld.j");
4256
+ B.condBr(isN, lu, lv);
4257
+ B.startBlock(lu);
4258
+ this.releaseValue(l.name, e.left.type);
4259
+ this.emitBranchInto(slot, e.right);
4260
+ B.br(lj);
4261
+ B.startBlock(lv);
4262
+ B.line(`store ptr ${l.name}, ptr ${slot}`);
4263
+ B.br(lj);
4264
+ B.startBlock(lj);
4265
+ const t = B.tmp();
4266
+ B.line(`${t} = load ptr, ptr ${slot}`);
4267
+ return this.own({ name: t, type: e.type });
4268
+ }
4181
4269
  if (e.left.type.kind !== "union")
4182
4270
  throw new Error("llvm emitter bug: nullish left is not a union");
4183
4271
  const def = this.unionsById.get(e.left.type.unionId);
@@ -5500,6 +5588,16 @@ class LlEmitter {
5500
5588
  B.line(`${t} = call ptr @${conv}(${valTy} ${v.name})`);
5501
5589
  return this.own({ name: t, type: e.type });
5502
5590
  }
5591
+ 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
5594
+ // kinds at wrap time). Operand borrowed, result +1, never throws.
5595
+ const v = this.emitExpr(e.value);
5596
+ this.declare(`declare ptr @scr_dyn_from_jsval(ptr)`);
5597
+ const t = B.tmp();
5598
+ B.line(`${t} = call ptr @scr_dyn_from_jsval(ptr ${v.name})`);
5599
+ return this.own({ name: t, type: e.type });
5600
+ }
5503
5601
  case "caughtToDyn": {
5504
5602
  // A catch binding flowing into an `unknown` slot: the snapshot's
5505
5603
  // runtime kind converts through the interned helper (+1 fresh
@@ -5681,7 +5779,8 @@ class LlEmitter {
5681
5779
  B.startBlock(lNotObj);
5682
5780
  const isArr = B.tmp();
5683
5781
  B.line(`${isArr} = icmp eq i32 ${kd}, ${DK.ARR}`);
5684
- B.condBr(isArr, lArr, lj);
5782
+ const lNotArr = B.newLabel("dhk.na");
5783
+ B.condBr(isArr, lArr, lNotArr);
5685
5784
  B.startBlock(lArr);
5686
5785
  if (e.key === "length") {
5687
5786
  B.line(`store i1 true, ptr ${slot}`);
@@ -5696,9 +5795,20 @@ class LlEmitter {
5696
5795
  B.line(`store i1 ${inR}, ptr ${slot}`);
5697
5796
  }
5698
5797
  B.br(lj);
5798
+ // An ISLAND-held receiver fences loudly (Node asks the real
5799
+ // engine object — `false` would be a silent wrong answer); the
5800
+ // helper answers false for every other kind, so this arm is a
5801
+ // plain unconditional call.
5802
+ B.startBlock(lNotArr);
5803
+ this.declare(`declare zeroext i1 @scr_dyn_isl_fence(ptr, ptr)`);
5804
+ const fenced = B.tmp();
5805
+ B.line(`${fenced} = call zeroext i1 @scr_dyn_isl_fence(ptr ${d.name}, ptr ${this.cstr("'in'")})`);
5806
+ B.line(`store i1 ${fenced}, ptr ${slot}`);
5807
+ B.br(lj);
5699
5808
  B.startBlock(lj);
5700
5809
  const raw = B.tmp();
5701
5810
  B.line(`${raw} = load i1, ptr ${slot}`);
5811
+ this.emitPendingCheck();
5702
5812
  if (!e.negated)
5703
5813
  return { name: raw, type: e.type };
5704
5814
  const neg = B.tmp();
@@ -5778,13 +5888,18 @@ class LlEmitter {
5778
5888
  }
5779
5889
  else if (e.test === "error") {
5780
5890
  // `u instanceof Error`: the DOM's error encoding — an object
5781
- // carrying the reserved "%error" marker key.
5891
+ // carrying the reserved "%error" marker key — or a real engine
5892
+ // Error held by reference (the isl helper answers false for
5893
+ // every non-JSVAL kind, so the call is unconditional).
5782
5894
  const kd = this.dynKind(d.name);
5783
5895
  const isObj = B.tmp();
5784
5896
  B.line(`${isObj} = icmp eq i32 ${kd}, ${DK.OBJ}`);
5785
5897
  const slot = B.slot();
5786
5898
  B.entryAllocas.push(`${slot} = alloca i1`);
5787
- B.line(`store i1 false, ptr ${slot}`);
5899
+ this.declare(`declare zeroext i1 @scr_dyn_isl_is_error(ptr)`);
5900
+ const isl = B.tmp();
5901
+ B.line(`${isl} = call zeroext i1 @scr_dyn_isl_is_error(ptr ${d.name})`);
5902
+ B.line(`store i1 ${isl}, ptr ${slot}`);
5788
5903
  const lObj = B.newLabel("dts.o");
5789
5904
  const lj = B.newLabel("dts.j");
5790
5905
  B.condBr(isObj, lObj, lj);
@@ -5818,13 +5933,33 @@ class LlEmitter {
5818
5933
  }
5819
5934
  return acc;
5820
5935
  };
5936
+ // ISLAND-held nodes route the tests that depend on the engine's
5937
+ // answer through the scr_dyn_isl_* helpers (false on every
5938
+ // other kind — the calls stay unconditional and branch-free).
5939
+ const orIsl = (acc, helper, arg) => {
5940
+ this.declare(`declare zeroext i1 @${helper}(ptr${arg !== undefined ? ", ptr" : ""})`);
5941
+ const c = B.tmp();
5942
+ B.line(`${c} = call zeroext i1 @${helper}(ptr ${d.name}${arg !== undefined ? `, ptr ${arg}` : ""})`);
5943
+ const o = B.tmp();
5944
+ B.line(`${o} = or i1 ${acc}, ${c}`);
5945
+ return o;
5946
+ };
5821
5947
  if (e.test === "nullish") {
5822
5948
  test = oneOf([DK.UNDEF, DK.NULL]);
5823
5949
  }
5824
5950
  else if (e.test === "object") {
5825
5951
  // `typeof v === "object"`: objects, arrays, bytes, native
5826
- // handles, promises, AND null.
5827
- test = oneOf([DK.OBJ, DK.ARR, DK.BYTES, DK.HANDLE, DK.PROMISE, DK.NULL]);
5952
+ // handles, promises, AND null — engine-held objects by the
5953
+ // engine's own typeof.
5954
+ test = orIsl(oneOf([DK.OBJ, DK.ARR, DK.BYTES, DK.HANDLE, DK.PROMISE, DK.NULL]), "scr_dyn_isl_typeof_is", this.cstr("object"));
5955
+ }
5956
+ else if (e.test === "array") {
5957
+ // Array.isArray: the DOM's array kind, or the engine's own
5958
+ // answer for an engine-held value.
5959
+ test = orIsl(oneOf([DK.ARR]), "scr_dyn_isl_is_array");
5960
+ }
5961
+ else if (e.test === "function") {
5962
+ test = orIsl(oneOf([DK.FUNC]), "scr_dyn_isl_typeof_is", this.cstr("function"));
5828
5963
  }
5829
5964
  else {
5830
5965
  const kindOf = {
@@ -5834,8 +5969,6 @@ class LlEmitter {
5834
5969
  undefined: DK.UNDEF,
5835
5970
  null: DK.NULL,
5836
5971
  bytes: DK.BYTES,
5837
- array: DK.ARR,
5838
- function: DK.FUNC,
5839
5972
  };
5840
5973
  test = oneOf([kindOf[e.test]]);
5841
5974
  }
@@ -5947,6 +6080,13 @@ class LlEmitter {
5947
6080
  return simple("scr_jsval_from_bool", "i1", false);
5948
6081
  case "string":
5949
6082
  return simple("scr_jsval_from_str", "ptr", false);
6083
+ case "dyn":
6084
+ // A CHECKED-DYNAMIC (DOM) value entering the island: deep copy,
6085
+ // data kinds only — boxed functions/handles/promises throw the
6086
+ // catchable TypeError in the runtime, and a wrapped island value
6087
+ // unwraps to the SAME engine value (the identity round trip).
6088
+ // The C emitter's rule, mirrored.
6089
+ return simple("scr_jsval_from_dyn", "ptr", true);
5950
6090
  case "bytes":
5951
6091
  // A typed array crossing IN: a COPY (the boundary's copy stance).
5952
6092
  return simple("scr_jsval_from_bytes", "ptr", true);
@@ -8161,6 +8301,10 @@ class LlEmitter {
8161
8301
  return call("scr_bytes_get", "double (ptr, double)", `ptr ${r.name}, double ${args[0].name}`, false, false);
8162
8302
  case "slice":
8163
8303
  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);
8304
+ case "subarray":
8305
+ // A +1 VIEW aliasing the receiver's storage (subarray / Buffer's
8306
+ // slice); same index defaults as slice.
8307
+ 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);
8164
8308
  case "setFrom":
8165
8309
  // dst.set(src, offset?) — void; throws Node's RangeError on
8166
8310
  // overflow.
@@ -8214,6 +8358,10 @@ class LlEmitter {
8214
8358
  B.line(`${t} = fcmp one double ${idx.name}, ${f64Lit(-1)}`);
8215
8359
  return { name: t, type: e.type };
8216
8360
  }
8361
+ case "fillElem":
8362
+ // Per-element TypedArray fill (non-u8): slice-style index
8363
+ // defaults, never throws; the receiver comes back +1.
8364
+ 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);
8217
8365
  case "fill":
8218
8366
  case "fillNum": {
8219
8367
  const sym = method === "fill" ? "scr_bytes_fill" : "scr_bytes_fill_num";
@@ -8666,6 +8814,54 @@ class LlEmitter {
8666
8814
  this.emitPendingCheck();
8667
8815
  return out;
8668
8816
  }
8817
+ if (e.fn === "error.propTypeThrow") {
8818
+ // The property flavor of argTypeThrow — same always-throw shape.
8819
+ const an = this.emitExpr(e.args[0]);
8820
+ const ex = this.emitExpr(e.args[1]);
8821
+ const got = this.emitExpr(e.args[2]);
8822
+ this.declare(`declare void @scr_throw_prop_type(ptr, ptr, ptr)`);
8823
+ B.line(`call void @scr_throw_prop_type(ptr ${an.name}, ptr ${ex.name}, ptr ${got.name})`);
8824
+ const ty = this.llType(e.type);
8825
+ if (ty === "void") {
8826
+ this.emitPendingCheck();
8827
+ return { name: "", type: e.type };
8828
+ }
8829
+ const dummy = ty === "double" ? f64Lit(0) : ty === "i1" ? "false" : "null";
8830
+ const out = this.own({ name: dummy, type: e.type });
8831
+ this.emitPendingCheck();
8832
+ return out;
8833
+ }
8834
+ {
8835
+ // The fs validation-ladder Chk forms that ALWAYS throw (a
8836
+ // validation error or the trailing compiler-rendered fence): every
8837
+ // argument is a ptr (dyns + the fence string), and the typed dummy
8838
+ // is abandoned by the pending check's unwind.
8839
+ const FS_CHK_THROW_SYMS = {
8840
+ "fs.mkdtempChk": "scr_fs_mkdtemp_chk",
8841
+ "fs.readFileChk": "scr_fs_read_file_chk",
8842
+ "fs.opendirChk": "scr_fs_opendir_chk",
8843
+ "fs.watchFileChk": "scr_fs_watch_file_chk",
8844
+ "fs.lchmodChk": "scr_fs_lchmod_chk",
8845
+ "fs.readChk": "scr_fs_read_chk",
8846
+ "fs.streamOptsChk": "scr_fs_stream_opts_chk",
8847
+ "net.connectOptsChk": "scr_net_connect_opts_chk",
8848
+ };
8849
+ const sym = FS_CHK_THROW_SYMS[e.fn];
8850
+ if (sym !== undefined) {
8851
+ const args = e.args.map((a) => this.emitExpr(a));
8852
+ this.declare(`declare void @${sym}(${args.map(() => "ptr").join(", ")})`);
8853
+ B.line(`call void @${sym}(${args.map((a) => `ptr ${a.name}`).join(", ")})`);
8854
+ const ty = this.llType(e.type);
8855
+ if (ty === "void") {
8856
+ this.emitPendingCheck();
8857
+ return { name: "", type: e.type };
8858
+ }
8859
+ const dummy = ty === "double" ? f64Lit(0) : ty === "i1" ? "false" : "null";
8860
+ const out = this.own({ name: dummy, type: e.type });
8861
+ this.emitPendingCheck();
8862
+ return out;
8863
+ }
8864
+ }
8669
8865
  if (e.fn === "error.nodeThrow") {
8670
8866
  // The compiler-resolved Node-parity throw (always throws — the
8671
8867
  // typed dummy is abandoned by the pending check's unwind).
@@ -10417,11 +10613,12 @@ class LlEmitter {
10417
10613
  if (MAY_THROW_LIB_FNS.has(e.fn) && LIB_FN_SYMS[e.fn] === undefined) {
10418
10614
  throw new LlvmUnsupportedError(`libCall:${e.fn}`, e.loc);
10419
10615
  }
10420
- if (e.fn === "math.floor") {
10616
+ if (e.fn === "math.floor" || e.fn === "math.trunc" || e.fn === "math.ceil") {
10617
+ const intr = e.fn === "math.floor" ? "floor" : e.fn === "math.trunc" ? "trunc" : "ceil";
10421
10618
  const v = this.emitExpr(e.args[0]);
10422
- this.declare(`declare double @llvm.floor.f64(double)`);
10619
+ this.declare(`declare double @llvm.${intr}.f64(double)`);
10423
10620
  const t = B.tmp();
10424
- B.line(`${t} = call double @llvm.floor.f64(double ${v.name})`);
10621
+ B.line(`${t} = call double @llvm.${intr}.f64(double ${v.name})`);
10425
10622
  return { name: t, type: e.type };
10426
10623
  }
10427
10624
  if (e.fn === "math.abs") {