watr 4.2.1 → 4.3.1

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.
package/dist/watr.js CHANGED
@@ -447,13 +447,14 @@ var INSTR = [
447
447
  ,
448
448
  ,
449
449
  ,
450
- ,
451
- ,
452
- ,
453
- ,
454
- ,
455
- ,
456
- ,
450
+ // 0xe0-0xe6: stack switching (Phase 3)
451
+ "cont.new typeidx",
452
+ "cont.bind cont_bind",
453
+ "suspend tagidx",
454
+ "resume resume",
455
+ "resume_throw resume_throw",
456
+ "resume_throw_ref resume_throw_ref",
457
+ "switch switch_cont",
457
458
  ,
458
459
  ,
459
460
  ,
@@ -506,7 +507,165 @@ var INSTR = [
506
507
  "extern.convert_any",
507
508
  "ref.i31",
508
509
  "i31.get_s",
509
- "i31.get_u"
510
+ "i31.get_u",
511
+ ,
512
+ "struct.new_desc typeidx",
513
+ "struct.new_default_desc typeidx",
514
+ "ref.get_desc typeidx",
515
+ "ref.cast_desc_eq reftype",
516
+ ,
517
+ "br_on_cast_desc_eq reftype2",
518
+ "br_on_cast_desc_eq_fail reftype2",
519
+ ,
520
+ ,
521
+ ,
522
+ ,
523
+ ,
524
+ ,
525
+ ,
526
+ ,
527
+ ,
528
+ ,
529
+ ,
530
+ ,
531
+ ,
532
+ ,
533
+ ,
534
+ ,
535
+ ,
536
+ ,
537
+ ,
538
+ ,
539
+ ,
540
+ ,
541
+ ,
542
+ ,
543
+ ,
544
+ ,
545
+ ,
546
+ ,
547
+ ,
548
+ ,
549
+ ,
550
+ ,
551
+ ,
552
+ ,
553
+ ,
554
+ ,
555
+ ,
556
+ ,
557
+ ,
558
+ ,
559
+ ,
560
+ ,
561
+ ,
562
+ ,
563
+ ,
564
+ ,
565
+ ,
566
+ ,
567
+ ,
568
+ ,
569
+ ,
570
+ ,
571
+ ,
572
+ ,
573
+ ,
574
+ ,
575
+ ,
576
+ ,
577
+ ,
578
+ ,
579
+ ,
580
+ ,
581
+ ,
582
+ ,
583
+ ,
584
+ ,
585
+ ,
586
+ ,
587
+ ,
588
+ ,
589
+ ,
590
+ ,
591
+ ,
592
+ ,
593
+ ,
594
+ ,
595
+ ,
596
+ ,
597
+ ,
598
+ ,
599
+ ,
600
+ ,
601
+ ,
602
+ ,
603
+ ,
604
+ ,
605
+ ,
606
+ ,
607
+ ,
608
+ // stringref: 0xFB 0x80-0xB7
609
+ "string.new_utf8 memoryidx?",
610
+ "string.new_wtf16 memoryidx?",
611
+ "string.const stringidx",
612
+ "string.measure_utf8",
613
+ "string.measure_wtf8",
614
+ "string.measure_wtf16",
615
+ "string.encode_utf8 memoryidx?",
616
+ "string.encode_wtf16 memoryidx?",
617
+ "string.concat",
618
+ "string.eq",
619
+ "string.is_usv_sequence",
620
+ "string.new_lossy_utf8 memoryidx?",
621
+ "string.new_wtf8 memoryidx?",
622
+ "string.encode_lossy_utf8 memoryidx?",
623
+ "string.encode_wtf8 memoryidx?",
624
+ ,
625
+ // 0x8F
626
+ "string.as_wtf8",
627
+ "stringview_wtf8.advance",
628
+ "stringview_wtf8.encode_utf8 memoryidx?",
629
+ "stringview_wtf8.slice",
630
+ "stringview_wtf8.encode_lossy_utf8 memoryidx?",
631
+ "stringview_wtf8.encode_wtf8 memoryidx?",
632
+ ,
633
+ ,
634
+ // 0x96-0x97
635
+ "string.as_wtf16",
636
+ "stringview_wtf16.length",
637
+ "stringview_wtf16.get_codeunit",
638
+ "stringview_wtf16.encode memoryidx?",
639
+ "stringview_wtf16.slice",
640
+ ,
641
+ ,
642
+ ,
643
+ // 0x9D-0x9F
644
+ "string.as_iter",
645
+ "stringview_iter.next",
646
+ "stringview_iter.advance",
647
+ "stringview_iter.rewind",
648
+ "stringview_iter.slice",
649
+ ,
650
+ ,
651
+ ,
652
+ ,
653
+ ,
654
+ ,
655
+ ,
656
+ ,
657
+ ,
658
+ ,
659
+ ,
660
+ // 0xA5-0xAF
661
+ "string.new_utf8_array",
662
+ "string.new_wtf16_array",
663
+ "string.encode_utf8_array",
664
+ "string.encode_wtf16_array",
665
+ "string.new_lossy_utf8_array",
666
+ "string.new_wtf8_array",
667
+ "string.encode_lossy_utf8_array",
668
+ "string.encode_wtf8_array"
510
669
  ],
511
670
  // 0xfc: Bulk memory/table operations (nested array)
512
671
  [
@@ -896,7 +1055,7 @@ var INSTR = [
896
1055
  "i64.atomic.rmw32.cmpxchg_u memarg"
897
1056
  ]
898
1057
  ];
899
- var SECTION = { custom: 0, type: 1, import: 2, func: 3, table: 4, memory: 5, tag: 13, global: 6, export: 7, start: 8, elem: 9, datacount: 12, code: 10, data: 11 };
1058
+ var SECTION = { custom: 0, type: 1, import: 2, func: 3, table: 4, memory: 5, tag: 13, strings: 14, global: 6, export: 7, start: 8, elem: 9, datacount: 12, code: 10, data: 11 };
900
1059
  var TYPE = {
901
1060
  // Value types
902
1061
  i8: 120,
@@ -920,6 +1079,14 @@ var TYPE = {
920
1079
  i31: 108,
921
1080
  struct: 107,
922
1081
  array: 106,
1082
+ cont: 104,
1083
+ nocont: 117,
1084
+ // stack switching (Phase 3)
1085
+ string: 103,
1086
+ stringview_wtf8: 102,
1087
+ stringview_wtf16: 96,
1088
+ stringview_iter: 97,
1089
+ // stringref
923
1090
  // Reference type abbreviations (absheaptype abbrs)
924
1091
  nullfuncref: 115,
925
1092
  nullexternref: 114,
@@ -933,6 +1100,11 @@ var TYPE = {
933
1100
  i31ref: 108,
934
1101
  structref: 107,
935
1102
  arrayref: 106,
1103
+ contref: 104,
1104
+ nocontref: 117,
1105
+ // stack switching abbreviations
1106
+ stringref: 103,
1107
+ // stringref abbreviation
936
1108
  // ref, refnull
937
1109
  ref: 100,
938
1110
  // -0x1c
@@ -943,7 +1115,7 @@ var TYPE = {
943
1115
  subfinal: 79,
944
1116
  rec: 78
945
1117
  };
946
- var DEFTYPE = { func: 96, struct: 95, array: 94, sub: 80, subfinal: 79, rec: 78 };
1118
+ var DEFTYPE = { func: 96, struct: 95, array: 94, cont: 93, sub: 80, subfinal: 79, rec: 78 };
947
1119
  var KIND = { func: 0, table: 1, memory: 2, global: 3, tag: 4 };
948
1120
 
949
1121
  // src/parse.js
@@ -962,10 +1134,10 @@ var parse_default = (str2) => {
962
1134
  buf += str2[i++]
963
1135
  )
964
1136
  );
965
- else if (q < 0) c === 10 || c === 13 ? (buf += str2[i++], commit(), q = 0) : buf += str2[i++];
1137
+ else if (q < 0) c === 10 || c === 13 ? (buf += str2[i++], commit(), q = 0) : q === -2 && c === 41 ? (commit(), q = 0) : buf += str2[i++];
966
1138
  else if (c === 34) buf !== "$" && commit(), q = 34, buf += str2[i++];
967
1139
  else if (c === 40 && str2.charCodeAt(i + 1) === 59) commit(), q = 60, buf = str2[i++] + str2[i++];
968
- else if (c === 59 && str2.charCodeAt(i + 1) === 59) commit(), q = -1, buf = str2[i++] + str2[i++];
1140
+ else if (c === 59 && str2.charCodeAt(i + 1) === 59) commit(), q = str2.indexOf("\n", i) < 0 ? -2 : -1, buf = str2[i++] + str2[i++];
969
1141
  else if (c === 40 && str2.charCodeAt(i + 1) === 64) commit(), p = i, i += 2, buf = "@", depth++, (root = level).push(level = []), parseLevel(p), level = root;
970
1142
  else if (c === 40) commit(), p = i++, depth++, (root = level).push(level = []), parseLevel(p), level = root;
971
1143
  else if (c === 41) return commit(), i++, depth--;
@@ -1010,6 +1182,17 @@ function compile(nodes) {
1010
1182
  else if (typeof nodes[0] === "string") nodes = [nodes];
1011
1183
  if (nodes[idx] === "binary") return Uint8Array.from(nodes.slice(++idx).flat());
1012
1184
  if (nodes[idx] === "quote") return compile(nodes.slice(++idx).map((v) => v.valueOf().slice(1, -1)).flat().join(""));
1185
+ nodes = nodes.flatMap((n, i) => {
1186
+ if (i < idx || !Array.isArray(n) || n[0] !== "import") return [n];
1187
+ const [, mod, ...rest] = n;
1188
+ if (!rest.some((r) => Array.isArray(r) && r[0] === "item")) return [n];
1189
+ const lastIsType = Array.isArray(rest.at(-1)) && rest.at(-1)[0] !== "item";
1190
+ if (lastIsType) {
1191
+ const type = rest.at(-1);
1192
+ return rest.slice(0, -1).filter((r) => r[0] === "item").map(([, nm]) => ["import", mod, nm, type]);
1193
+ }
1194
+ return rest.filter((r) => r[0] === "item").map(([, nm, type]) => ["import", mod, nm, type]);
1195
+ });
1013
1196
  const ctx = [];
1014
1197
  for (let kind in SECTION) (ctx[SECTION[kind]] = ctx[kind] = []).name = kind;
1015
1198
  ctx.metadata = {};
@@ -1040,12 +1223,19 @@ function compile(nodes) {
1040
1223
  for (let i = 0; i < node.length; i++) {
1041
1224
  let [, ...subnode] = node[i];
1042
1225
  name(subnode, ctx.type);
1226
+ const tdesc = [];
1227
+ while (subnode[0]?.[0] === "descriptor" || subnode[0]?.[0] === "describes") tdesc.push(subnode.shift());
1043
1228
  (subnode = typedef(subnode, ctx)).push(i ? true : [ctx.type.length, node.length]);
1229
+ if (tdesc.length) subnode.desc = subnode.desc ? [...tdesc, ...subnode.desc] : tdesc;
1044
1230
  ctx.type.push(subnode);
1045
1231
  }
1046
1232
  } else if (kind === "type") {
1047
1233
  name(node, ctx.type);
1048
- ctx.type.push(typedef(node, ctx));
1234
+ const tdesc = [];
1235
+ while (node[0]?.[0] === "descriptor" || node[0]?.[0] === "describes") tdesc.push(node.shift());
1236
+ const td = typedef(node, ctx);
1237
+ if (tdesc.length) td.desc = td.desc ? [...tdesc, ...td.desc] : tdesc;
1238
+ ctx.type.push(td);
1049
1239
  } else if (kind === "start" || kind === "export") ctx[kind].push(node);
1050
1240
  else return true;
1051
1241
  }).forEach((n) => {
@@ -1068,7 +1258,8 @@ function compile(nodes) {
1068
1258
  } else if (kind === "memory") {
1069
1259
  const is64 = node[0] === "i64", idx2 = is64 ? 1 : 0;
1070
1260
  if (node[idx2]?.[0] === "data") {
1071
- let [, ...data] = node.splice(idx2, 1)[0], m = "" + Math.ceil(data.reduce((s, d) => s + d.length, 0) / 65536);
1261
+ const ps = node.find((n2) => Array.isArray(n2) && n2[0] === "pagesize")?.[1] ?? 65536;
1262
+ let [, ...data] = node.splice(idx2, 1)[0], m = "" + Math.ceil(data.reduce((s, d) => s + d.length, 0) / ps);
1072
1263
  ctx.data.push([["memory", items.length], [is64 ? "i64.const" : "i32.const", is64 ? 0n : 0], ...data]);
1073
1264
  node = is64 ? ["i64", m, m] : [m, m];
1074
1265
  }
@@ -1101,6 +1292,12 @@ function compile(nodes) {
1101
1292
  }
1102
1293
  return sections;
1103
1294
  };
1295
+ const globalSection = bin(SECTION.global);
1296
+ const elemSection = bin(SECTION.elem);
1297
+ const codeSection = bin(SECTION.code);
1298
+ const metaSection = binMeta();
1299
+ const dataSection = bin(SECTION.data);
1300
+ const stringsSection = ctx.strings.length ? [SECTION.strings, ...vec([0, ...vec(ctx.strings.map((s) => vec(s)))])] : [];
1104
1301
  return Uint8Array.from([
1105
1302
  0,
1106
1303
  97,
@@ -1119,14 +1316,15 @@ function compile(nodes) {
1119
1316
  ...bin(SECTION.table),
1120
1317
  ...bin(SECTION.memory),
1121
1318
  ...bin(SECTION.tag),
1122
- ...bin(SECTION.global),
1319
+ ...stringsSection,
1320
+ ...globalSection,
1123
1321
  ...bin(SECTION.export),
1124
1322
  ...bin(SECTION.start, false),
1125
- ...bin(SECTION.elem),
1323
+ ...elemSection,
1126
1324
  ...bin(SECTION.datacount, false),
1127
- ...bin(SECTION.code),
1128
- ...binMeta(),
1129
- ...bin(SECTION.data)
1325
+ ...codeSection,
1326
+ ...metaSection,
1327
+ ...dataSection
1130
1328
  ]);
1131
1329
  }
1132
1330
  var isIdx = (n) => n?.[0] === "$" || !isNaN(n);
@@ -1195,7 +1393,7 @@ function normalize(nodes, ctx) {
1195
1393
  out.push(...normalize(parts, ctx), "end");
1196
1394
  } else {
1197
1395
  const imm = [];
1198
- while (parts.length && (!Array.isArray(parts[0]) || "type,param,result,ref".includes(parts[0][0]))) imm.push(parts.shift());
1396
+ while (parts.length && (!Array.isArray(parts[0]) || parts[0].valueOf !== Array.prototype.valueOf || "type,param,result,ref,exact,on".includes(parts[0][0]))) imm.push(parts.shift());
1199
1397
  out.push(...normalize(parts, ctx), op, ...imm);
1200
1398
  nodes.unshift(...out.splice(out.length - 1 - imm.length));
1201
1399
  }
@@ -1240,16 +1438,19 @@ var name = (node, list) => {
1240
1438
  return nm;
1241
1439
  };
1242
1440
  var typedef = ([dfn], ctx) => {
1243
- let subkind = "subfinal", supertypes = [], compkind;
1441
+ let subkind = "subfinal", supertypes = [], compkind, desc = [];
1244
1442
  if (dfn[0] === "sub") {
1245
1443
  subkind = dfn.shift(), dfn[0] === "final" && (subkind += dfn.shift());
1246
1444
  dfn = (supertypes = dfn).pop();
1445
+ supertypes = supertypes.filter((n) => Array.isArray(n) && (n[0] === "descriptor" || n[0] === "describes") ? (desc.push(n), false) : true);
1247
1446
  }
1248
1447
  [compkind, ...dfn] = dfn;
1249
1448
  if (compkind === "func") dfn = paramres(dfn), ctx.type["$" + dfn.join(">")] ??= ctx.type.length;
1250
1449
  else if (compkind === "struct") dfn = fieldseq(dfn, "field");
1251
1450
  else if (compkind === "array") [dfn] = dfn;
1252
- return [compkind, dfn, subkind, supertypes];
1451
+ const result = [compkind, dfn, subkind, supertypes];
1452
+ if (desc.length) result.desc = desc;
1453
+ return result;
1253
1454
  };
1254
1455
  var build = [
1255
1456
  // (@custom "name" placement? data) - custom section builder
@@ -1264,29 +1465,37 @@ var build = [
1264
1465
  // (func params result)
1265
1466
  // (array i8)
1266
1467
  // (struct ...fields)
1267
- ([kind, fields, subkind, supertypes, rec], ctx) => {
1468
+ // (cont $ft) - stack switching (Phase 3)
1469
+ (node, ctx) => {
1470
+ const [kind, fields, subkind, supertypes, rec] = node;
1268
1471
  if (rec === true) return;
1269
- let details;
1472
+ const descPfx = (node.desc ?? []).flatMap(([clause, ref]) => [clause === "descriptor" ? 77 : 76, ...uleb(id(ref, ctx.type))]);
1473
+ const comptype = (k, f) => {
1474
+ if (k === "func") return [DEFTYPE.func, ...vec(f[0].map((t) => reftype(t, ctx))), ...vec(f[1].map((t) => reftype(t, ctx)))];
1475
+ if (k === "array") return [DEFTYPE.array, ...fieldtype(f, ctx)];
1476
+ if (k === "struct") return [DEFTYPE.struct, ...vec(f.map((t) => fieldtype(t, ctx)))];
1477
+ if (k === "cont") return [DEFTYPE.cont, ...uleb(id(f[0] ?? f, ctx.type))];
1478
+ return [DEFTYPE[k]];
1479
+ };
1270
1480
  if (rec) {
1271
- kind = "rec";
1272
- let [from, length] = rec, subtypes = Array.from({ length }, (_, i) => build[SECTION.type](ctx.type[from + i].slice(0, 4), ctx));
1273
- details = vec(subtypes);
1481
+ let [from, length] = rec;
1482
+ const subtypes = Array.from({ length }, (_, i) => {
1483
+ const t = ctx.type[from + i], sub = t.slice(0, 4);
1484
+ if (t.desc) sub.desc = t.desc;
1485
+ return build[SECTION.type](sub, ctx);
1486
+ });
1487
+ return [DEFTYPE.rec, ...vec(subtypes)];
1274
1488
  } else if (subkind === "sub" || supertypes?.length) {
1275
- details = [...vec(supertypes.map((n) => id(n, ctx.type))), ...build[SECTION.type]([kind, fields], ctx)];
1276
- kind = subkind;
1277
- } else if (kind === "func") {
1278
- details = [...vec(fields[0].map((t) => reftype(t, ctx))), ...vec(fields[1].map((t) => reftype(t, ctx)))];
1279
- } else if (kind === "array") {
1280
- details = fieldtype(fields, ctx);
1281
- } else if (kind === "struct") {
1282
- details = vec(fields.map((t) => fieldtype(t, ctx)));
1489
+ return [DEFTYPE[subkind], ...vec(supertypes.map((n) => id(n, ctx.type))), ...descPfx, ...comptype(kind, fields)];
1283
1490
  }
1284
- return [DEFTYPE[kind], ...details];
1491
+ return [...descPfx, ...comptype(kind, fields)];
1285
1492
  },
1286
1493
  // (import "math" "add" (func|table|global|memory|tag dfn?))
1287
1494
  ([mod, field, [kind, ...dfn]], ctx) => {
1288
- let details;
1495
+ let details, kindByte = KIND[kind];
1289
1496
  if (kind === "func") {
1497
+ const isExact = dfn[0] === "exact" && dfn.shift();
1498
+ if (isExact) kindByte = 32;
1290
1499
  let [[, typeidx]] = dfn;
1291
1500
  details = uleb(id(typeidx, ctx.type));
1292
1501
  } else if (kind === "tag") {
@@ -1299,7 +1508,7 @@ var build = [
1299
1508
  } else if (kind === "table") {
1300
1509
  details = [...reftype(dfn.pop(), ctx), ...limits(dfn)];
1301
1510
  } else err(`Unknown kind ${kind}`);
1302
- return [...vec(mod), ...vec(field), KIND[kind], ...details];
1511
+ return [...vec(mod), ...vec(field), kindByte, ...details];
1303
1512
  },
1304
1513
  // (func $name? ...params result ...body)
1305
1514
  ([[, typeidx]], ctx) => uleb(id(typeidx, ctx.type)),
@@ -1413,6 +1622,7 @@ var build = [
1413
1622
  // (data (i32.const 0) "\aa" "\bb"?)
1414
1623
  // (data (memory ref) (offset (i32.const 0)) "\aa" "\bb"?)
1415
1624
  // (data (global.get $x) "\aa" "\bb"?)
1625
+ // (data (i8 1 2 3) ...) numeric values (WAT numeric values, Phase 2)
1416
1626
  (inits, ctx) => {
1417
1627
  let offset, memidx = 0;
1418
1628
  if (inits[0]?.[0] === "memory") {
@@ -1435,7 +1645,7 @@ var build = [
1435
1645
  [1]
1436
1646
  )
1437
1647
  ),
1438
- ...vec(inits.flat())
1648
+ ...vec(inits.flatMap((item) => numdata(item) ?? [...item]))
1439
1649
  ];
1440
1650
  },
1441
1651
  // datacount
@@ -1443,7 +1653,13 @@ var build = [
1443
1653
  // (tag $name? (type idx))
1444
1654
  ([[, typeidx]], ctx) => [0, ...uleb(id(typeidx, ctx.type))]
1445
1655
  ];
1446
- var reftype = (t, ctx) => t[0] === "ref" ? t[1] == "null" ? TYPE[t[2]] ? [TYPE[t[2]]] : [TYPE.refnull, ...uleb(id(t[t.length - 1], ctx.type))] : [TYPE.ref, ...uleb(TYPE[t[t.length - 1]] || id(t[t.length - 1], ctx.type))] : (
1656
+ var reftype = (t, ctx) => t[0] === "ref" ? t[1] == "null" ? (
1657
+ // (ref null (exact $T)) - exact nullable ref
1658
+ Array.isArray(t[2]) && t[2][0] === "exact" ? [TYPE.refnull, 98, ...uleb(id(t[2][1], ctx.type))] : TYPE[t[2]] ? [TYPE[t[2]]] : [TYPE.refnull, ...uleb(id(t[t.length - 1], ctx.type))]
1659
+ ) : (
1660
+ // (ref (exact $T)) - exact non-null ref
1661
+ Array.isArray(t[1]) && t[1][0] === "exact" ? [TYPE.ref, 98, ...uleb(id(t[1][1], ctx.type))] : [TYPE.ref, ...uleb(TYPE[t[t.length - 1]] || id(t[t.length - 1], ctx.type))]
1662
+ ) : (
1447
1663
  // abbrs
1448
1664
  [TYPE[t] ?? err(`Unknown type ${t}`)]
1449
1665
  );
@@ -1491,7 +1707,7 @@ var IMM = {
1491
1707
  },
1492
1708
  ref_null: (n, c) => {
1493
1709
  let t = n.shift();
1494
- return TYPE[t] ? [TYPE[t]] : uleb(id(t, c.type));
1710
+ return Array.isArray(t) && t[0] === "exact" ? [98, ...uleb(id(t[1], c.type))] : TYPE[t] ? [TYPE[t]] : uleb(id(t, c.type));
1495
1711
  },
1496
1712
  memarg: (n, c, op) => memargEnc(n, op, isIdx(n[0]) && !isMemParam(n[0]) ? id(n.shift(), c.memory) : 0),
1497
1713
  opt_memory: (n, c) => uleb(id(isIdx(n[0]) ? n.shift() : 0, c.memory)),
@@ -1500,8 +1716,8 @@ var IMM = {
1500
1716
  return ht.length > 1 ? ht.slice(1) : ht;
1501
1717
  },
1502
1718
  reftype2: (n, c) => {
1503
- let b = blockid(n.shift(), c.block), h1 = reftype(n.shift(), c), h2 = reftype(n.shift(), c);
1504
- return [(h2[0] !== TYPE.ref) << 1 | h1[0] !== TYPE.ref, ...uleb(b), h1.pop(), h2.pop()];
1719
+ let b = blockid(n.shift(), c.block), h1 = reftype(n.shift(), c), h2 = reftype(n.shift(), c), ht = (h) => h.length > 1 ? h.slice(1) : h;
1720
+ return [(h2[0] !== TYPE.ref) << 1 | h1[0] !== TYPE.ref, ...uleb(b), ...ht(h1), ...ht(h2)];
1505
1721
  },
1506
1722
  v128const: (n) => {
1507
1723
  let [t, num] = n.shift().split("x"), bits = +t.slice(1), stride = bits >>> 3;
@@ -1539,6 +1755,11 @@ var IMM = {
1539
1755
  elemidx: (n, c) => uleb(id(n.shift(), c.elem)),
1540
1756
  tagidx: (n, c) => uleb(id(n.shift(), c.tag)),
1541
1757
  "memoryidx?": (n, c) => uleb(id(isIdx(n[0]) ? n.shift() : 0, c.memory)),
1758
+ stringidx: (n, c) => {
1759
+ let s = n.shift(), key = s.valueOf(), idx = c.strings.findIndex((x) => x.valueOf() === key);
1760
+ if (idx < 0) idx = c.strings.push(s) - 1;
1761
+ return uleb(idx);
1762
+ },
1542
1763
  // Value type
1543
1764
  i32: (n) => i32(n.shift()),
1544
1765
  i64: (n) => i64(n.shift()),
@@ -1556,7 +1777,47 @@ var IMM = {
1556
1777
  typeidx_typeidx: (n, c) => [...uleb(id(n.shift(), c.type)), ...uleb(id(n.shift(), c.type))],
1557
1778
  dataidx_memoryidx: (n, c) => [...uleb(id(n.shift(), c.data)), ...uleb(id(n.shift(), c.memory))],
1558
1779
  memoryidx_memoryidx: (n, c) => [...uleb(id(n.shift(), c.memory)), ...uleb(id(n.shift(), c.memory))],
1559
- tableidx_tableidx: (n, c) => [...uleb(id(n.shift(), c.table)), ...uleb(id(n.shift(), c.table))]
1780
+ tableidx_tableidx: (n, c) => [...uleb(id(n.shift(), c.table)), ...uleb(id(n.shift(), c.table))],
1781
+ // stack switching handlers (Phase 3)
1782
+ cont_bind: (n, c) => [...uleb(id(n.shift(), c.type)), ...uleb(id(n.shift(), c.type))],
1783
+ switch_cont: (n, c) => [...uleb(id(n.shift(), c.type)), ...uleb(id(n.shift(), c.tag))],
1784
+ resume: (n, c) => {
1785
+ const typeidx = uleb(id(n.shift(), c.type));
1786
+ const handlers = [];
1787
+ let cnt = 0;
1788
+ while (n[0]?.[0] === "on") {
1789
+ const [, tag, label] = n.shift();
1790
+ if (label === "switch") handlers.push(1, ...uleb(id(tag, c.tag)));
1791
+ else handlers.push(0, ...uleb(id(tag, c.tag)), ...uleb(blockid(label, c.block)));
1792
+ cnt++;
1793
+ }
1794
+ return [...typeidx, ...uleb(cnt), ...handlers];
1795
+ },
1796
+ resume_throw: (n, c) => {
1797
+ const typeidx = uleb(id(n.shift(), c.type));
1798
+ const exnidx = uleb(id(n.shift(), c.tag));
1799
+ const handlers = [];
1800
+ let cnt = 0;
1801
+ while (n[0]?.[0] === "on") {
1802
+ const [, tag, label] = n.shift();
1803
+ if (label === "switch") handlers.push(1, ...uleb(id(tag, c.tag)));
1804
+ else handlers.push(0, ...uleb(id(tag, c.tag)), ...uleb(blockid(label, c.block)));
1805
+ cnt++;
1806
+ }
1807
+ return [...typeidx, ...exnidx, ...uleb(cnt), ...handlers];
1808
+ },
1809
+ resume_throw_ref: (n, c) => {
1810
+ const typeidx = uleb(id(n.shift(), c.type));
1811
+ const handlers = [];
1812
+ let cnt = 0;
1813
+ while (n[0]?.[0] === "on") {
1814
+ const [, tag, label] = n.shift();
1815
+ if (label === "switch") handlers.push(1, ...uleb(id(tag, c.tag)));
1816
+ else handlers.push(0, ...uleb(id(tag, c.tag)), ...uleb(blockid(label, c.block)));
1817
+ cnt++;
1818
+ }
1819
+ return [...typeidx, ...uleb(cnt), ...handlers];
1820
+ }
1560
1821
  };
1561
1822
  var HANDLER = {};
1562
1823
  (function populate(items, pre) {
@@ -1616,17 +1877,36 @@ var align = (op) => {
1616
1877
  let k = op[i] === "l" ? i + 4 : i + 5, m = op.slice(k).match(/(\d+)(x|_|$)/);
1617
1878
  return Math.log2(m ? m[2] === "x" ? 8 : m[1] / 8 : +group / 8);
1618
1879
  };
1880
+ var numdata = (item) => {
1881
+ if (!Array.isArray(item)) return null;
1882
+ const [t, ...vs] = item;
1883
+ if (t !== "i8" && t !== "i16" && t !== "i32" && t !== "i64" && t !== "f32" && t !== "f64") return null;
1884
+ const out = [], dv = new DataView(new ArrayBuffer(8));
1885
+ for (const v of vs) {
1886
+ if (t === "i8") out.push(i32.parse(v) & 255 + 256 & 255);
1887
+ else if (t === "i16") dv.setInt16(0, i32.parse(v), true), out.push(...new Uint8Array(dv.buffer, 0, 2));
1888
+ else if (t === "i32") dv.setInt32(0, i32.parse(v), true), out.push(...new Uint8Array(dv.buffer, 0, 4));
1889
+ else if (t === "i64") dv.setBigInt64(0, BigInt(v), true), out.push(...new Uint8Array(dv.buffer, 0, 8));
1890
+ else if (t === "f32") out.push(...f32(v));
1891
+ else if (t === "f64") out.push(...f64(v));
1892
+ }
1893
+ return out;
1894
+ };
1619
1895
  var limits = (node) => {
1620
1896
  const is64 = node[0] === "i64" && node.shift();
1621
1897
  const shared = node[node.length - 1] === "shared" && node.pop();
1898
+ const psIdx = node.findIndex((n) => Array.isArray(n) && n[0] === "pagesize");
1899
+ let psLog2 = -1;
1900
+ if (psIdx >= 0) psLog2 = Math.log2(+node.splice(psIdx, 1)[0][1]);
1622
1901
  const hasMax = !isNaN(parseInt(node[1]));
1623
- const flag = (is64 ? 4 : 0) | (shared ? 2 : 0) | (hasMax ? 1 : 0);
1902
+ const flag = (psLog2 >= 0 ? 8 : 0) | (is64 ? 4 : 0) | (shared ? 2 : 0) | (hasMax ? 1 : 0);
1624
1903
  const parse = is64 ? (v) => {
1625
1904
  if (typeof v === "bigint") return v;
1626
1905
  const str2 = typeof v === "string" ? v.replaceAll("_", "") : String(v);
1627
1906
  return BigInt(str2);
1628
1907
  } : parseUint;
1629
- return hasMax ? [flag, ...uleb(parse(node.shift())), ...uleb(parse(node.shift()))] : [flag, ...uleb(parse(node.shift()))];
1908
+ const ps = psLog2 >= 0 ? uleb(psLog2) : [];
1909
+ return hasMax ? [flag, ...uleb(parse(node.shift())), ...uleb(parse(node.shift())), ...ps] : [flag, ...uleb(parse(node.shift())), ...ps];
1630
1910
  };
1631
1911
  var parseUint = (v, max = 4294967295) => {
1632
1912
  const n = typeof v === "string" && v[0] !== "+" ? i32.parse(v) : typeof v === "number" ? v : err(`Bad int ${v}`);