watr 4.6.6 → 4.6.8

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
@@ -56,6 +56,17 @@ var str = (s) => {
56
56
  return bytes;
57
57
  };
58
58
  var unescape = (s) => tdec.decode(new Uint8Array(str(s)));
59
+ var clone = (node) => Array.isArray(node) ? node.map(clone) : node;
60
+ var walk = (node, fn, parent, idx) => {
61
+ fn(node, parent, idx);
62
+ if (Array.isArray(node)) for (let i = 0; i < node.length; i++) walk(node[i], fn, node, i);
63
+ };
64
+ var walkPost = (node, fn, parent, idx) => {
65
+ if (Array.isArray(node)) for (let i = 0; i < node.length; i++) walkPost(node[i], fn, node, i);
66
+ const result = fn(node, parent, idx);
67
+ if (result !== void 0 && parent) parent[idx] = result;
68
+ return result !== void 0 ? result : node;
69
+ };
59
70
 
60
71
  // src/encode.js
61
72
  var uleb = (n, buffer = []) => {
@@ -141,7 +152,7 @@ var _i64 = new BigInt64Array(_buf);
141
152
  i64.parse = (n) => {
142
153
  n = cleanInt(n);
143
154
  const neg = n[0] === "-";
144
- const body = neg ? n.slice(1) : n;
155
+ const body = neg || n[0] === "+" ? n.slice(1) : n;
145
156
  let max;
146
157
  if (body[0] === "0" && (body[1] === "x" || body[1] === "X")) {
147
158
  const hex = body.slice(2).replace(/^0+/, "") || "0";
@@ -1243,6 +1254,17 @@ var INSTR = [
1243
1254
  "i64.atomic.rmw32.cmpxchg_u memarg"
1244
1255
  ]
1245
1256
  ];
1257
+ var resultType = (op) => {
1258
+ if (typeof op !== "string") return null;
1259
+ const dot = op.indexOf(".");
1260
+ if (dot < 0) return null;
1261
+ const prefix = op.slice(0, dot);
1262
+ const scalar = prefix === "i32" || prefix === "i64" || prefix === "f32" || prefix === "f64";
1263
+ if (scalar && /^(eqz?|ne|[lg][te])(_[su])?$/.test(op.slice(dot + 1))) return "i32";
1264
+ if (scalar || prefix === "v128") return prefix;
1265
+ if (op === "memory.size" || op === "memory.grow") return "i32";
1266
+ return null;
1267
+ };
1246
1268
  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 };
1247
1269
  var TYPE = {
1248
1270
  // Value types
@@ -2177,91 +2199,6 @@ function print(tree, options = {}) {
2177
2199
  }
2178
2200
 
2179
2201
  // src/polyfill.js
2180
- var FEATURES = {
2181
- funcref: ["ref.func", "call_ref", "return_call_ref"],
2182
- sign_ext: ["i32.extend8_s", "i32.extend16_s", "i64.extend8_s", "i64.extend16_s", "i64.extend32_s"],
2183
- nontrapping: [
2184
- "i32.trunc_sat_f32_s",
2185
- "i32.trunc_sat_f32_u",
2186
- "i32.trunc_sat_f64_s",
2187
- "i32.trunc_sat_f64_u",
2188
- "i64.trunc_sat_f32_s",
2189
- "i64.trunc_sat_f32_u",
2190
- "i64.trunc_sat_f64_s",
2191
- "i64.trunc_sat_f64_u"
2192
- ],
2193
- bulk_memory: ["memory.copy", "memory.fill"],
2194
- return_call: ["return_call", "return_call_indirect"],
2195
- i31ref: ["ref.i31", "i31.get_s", "i31.get_u"],
2196
- extended_const: ["global.get"],
2197
- // in const context - detected specially
2198
- multi_value: [],
2199
- // detected by result count
2200
- gc: [
2201
- "struct.new",
2202
- "struct.get",
2203
- "struct.set",
2204
- "array.new",
2205
- "array.get",
2206
- "array.set",
2207
- "array.len",
2208
- "struct.new_default",
2209
- "array.new_default",
2210
- "array.new_fixed",
2211
- "array.copy"
2212
- ],
2213
- ref_cast: ["ref.test", "ref.cast", "br_on_cast", "br_on_cast_fail"]
2214
- };
2215
- var ALL = Object.keys(FEATURES);
2216
- var normalize2 = (opts) => {
2217
- if (opts === true) return Object.fromEntries(ALL.map((f) => [f, true]));
2218
- if (opts === false) return {};
2219
- if (typeof opts === "string") {
2220
- const set = new Set(opts.split(/\s+/).filter(Boolean));
2221
- return Object.fromEntries(ALL.map((f) => [f, set.has(f) || set.has("all")]));
2222
- }
2223
- return { ...opts };
2224
- };
2225
- var walk = (node, fn, parent, idx) => {
2226
- fn(node, parent, idx);
2227
- if (Array.isArray(node)) for (let i = 0; i < node.length; i++) walk(node[i], fn, node, i);
2228
- };
2229
- var walkPost = (node, fn, parent, idx) => {
2230
- if (Array.isArray(node)) for (let i = 0; i < node.length; i++) walkPost(node[i], fn, node, i);
2231
- fn(node, parent, idx);
2232
- };
2233
- var detect = (ast) => {
2234
- const used = /* @__PURE__ */ new Set();
2235
- walk(ast, (node) => {
2236
- if (typeof node !== "string") return;
2237
- for (const [feat, ops] of Object.entries(FEATURES)) {
2238
- if (ops.some((op) => node === op || node.startsWith(op + " "))) used.add(feat);
2239
- }
2240
- });
2241
- walk(ast, (node) => {
2242
- if (!Array.isArray(node) || node[0] !== "global") return;
2243
- for (const init of node) {
2244
- if (!Array.isArray(init)) continue;
2245
- if (init[0] === "i32.add" || init[0] === "i32.sub" || init[0] === "i32.mul" || init[0] === "i64.add" || init[0] === "i64.sub" || init[0] === "i64.mul") {
2246
- walk(init, (inner) => {
2247
- if (Array.isArray(inner) && inner[0] === "global.get") used.add("extended_const");
2248
- });
2249
- }
2250
- }
2251
- });
2252
- walk(ast, (node) => {
2253
- if (!Array.isArray(node) || node[0] !== "func") return;
2254
- let resultCount = 0;
2255
- for (const part of node) {
2256
- if (Array.isArray(part) && part[0] === "result") {
2257
- resultCount += part.length - 1;
2258
- }
2259
- }
2260
- if (resultCount > 1) used.add("multi_value");
2261
- });
2262
- return used;
2263
- };
2264
- var clone = (node) => Array.isArray(node) ? node.map(clone) : node;
2265
2202
  var findNodes = (ast, kind) => {
2266
2203
  const nodes = [];
2267
2204
  const start = ast[0] === "module" ? 1 : 0;
@@ -2319,7 +2256,6 @@ var funcref = (ast, ctx) => {
2319
2256
  });
2320
2257
  return ast;
2321
2258
  };
2322
- var transforms = { funcref };
2323
2259
  var SIGN_EXT_SHIFTS = {
2324
2260
  "i32.extend8_s": ["i32", 24],
2325
2261
  "i32.extend16_s": ["i32", 16],
@@ -2342,7 +2278,6 @@ var sign_ext = (ast, ctx) => {
2342
2278
  });
2343
2279
  return ast;
2344
2280
  };
2345
- transforms.sign_ext = sign_ext;
2346
2281
  var TRUNC_SAT_INFO = {
2347
2282
  "i32.trunc_sat_f32_s": { itype: "i32", ftype: "f32", signed: true, min: -2147483648, max: 2147483647 },
2348
2283
  "i32.trunc_sat_f32_u": { itype: "i32", ftype: "f32", signed: false, min: 0, max: 4294967295 },
@@ -2410,7 +2345,6 @@ var nontrapping = (ast, ctx) => {
2410
2345
  });
2411
2346
  return ast;
2412
2347
  };
2413
- transforms.nontrapping = nontrapping;
2414
2348
  var bulk_memory = (ast, ctx) => {
2415
2349
  const needsCopy = /* @__PURE__ */ new Set(), needsFill = /* @__PURE__ */ new Set();
2416
2350
  walk(ast, (node) => {
@@ -2502,7 +2436,6 @@ var bulk_memory = (ast, ctx) => {
2502
2436
  });
2503
2437
  return ast;
2504
2438
  };
2505
- transforms.bulk_memory = bulk_memory;
2506
2439
  var return_call_transform = (ast, ctx) => {
2507
2440
  let hasAnyTailCall = false;
2508
2441
  walk(ast, (node) => {
@@ -2522,7 +2455,6 @@ var return_call_transform = (ast, ctx) => {
2522
2455
  });
2523
2456
  return ast;
2524
2457
  };
2525
- transforms.return_call = return_call_transform;
2526
2458
  var i31ref = (ast, ctx) => {
2527
2459
  walkPost(ast, (node, parent, idx) => {
2528
2460
  if (!Array.isArray(node) || !parent) return;
@@ -2539,7 +2471,6 @@ var i31ref = (ast, ctx) => {
2539
2471
  });
2540
2472
  return ast;
2541
2473
  };
2542
- transforms.i31ref = i31ref;
2543
2474
  var extended_const = (ast, ctx) => {
2544
2475
  const globals2 = {};
2545
2476
  walk(ast, (node) => {
@@ -2602,7 +2533,6 @@ var extended_const = (ast, ctx) => {
2602
2533
  });
2603
2534
  return ast;
2604
2535
  };
2605
- transforms.extended_const = extended_const;
2606
2536
  var multi_value = (ast, ctx) => {
2607
2537
  const multiResultFuncs = /* @__PURE__ */ new Map();
2608
2538
  const returnGlobals = [];
@@ -2651,7 +2581,6 @@ var multi_value = (ast, ctx) => {
2651
2581
  });
2652
2582
  return ast;
2653
2583
  };
2654
- transforms.multi_value = multi_value;
2655
2584
  var TYPE_SIZES = { i32: 4, i64: 8, f32: 4, f64: 8 };
2656
2585
  var gc = (ast, ctx) => {
2657
2586
  const types = /* @__PURE__ */ new Map();
@@ -2895,7 +2824,6 @@ var gc = (ast, ctx) => {
2895
2824
  });
2896
2825
  return ast;
2897
2826
  };
2898
- transforms.gc = gc;
2899
2827
  var ref_cast = (ast, ctx) => {
2900
2828
  const typeIndices = /* @__PURE__ */ new Map();
2901
2829
  let typeIdx = 1;
@@ -3039,77 +2967,94 @@ var ref_cast = (ast, ctx) => {
3039
2967
  });
3040
2968
  return ast;
3041
2969
  };
3042
- transforms.ref_cast = ref_cast;
2970
+ var POLYFILLS = [
2971
+ ["funcref", ["ref.func", "call_ref", "return_call_ref"], funcref],
2972
+ ["sign_ext", ["i32.extend8_s", "i32.extend16_s", "i64.extend8_s", "i64.extend16_s", "i64.extend32_s"], sign_ext],
2973
+ ["nontrapping", [
2974
+ "i32.trunc_sat_f32_s",
2975
+ "i32.trunc_sat_f32_u",
2976
+ "i32.trunc_sat_f64_s",
2977
+ "i32.trunc_sat_f64_u",
2978
+ "i64.trunc_sat_f32_s",
2979
+ "i64.trunc_sat_f32_u",
2980
+ "i64.trunc_sat_f64_s",
2981
+ "i64.trunc_sat_f64_u"
2982
+ ], nontrapping],
2983
+ ["bulk_memory", ["memory.copy", "memory.fill"], bulk_memory],
2984
+ ["return_call", ["return_call", "return_call_indirect"], return_call_transform],
2985
+ ["i31ref", ["ref.i31", "i31.get_s", "i31.get_u"], i31ref],
2986
+ ["extended_const", ["global.get"], extended_const],
2987
+ // global.get in a const initializer — also detected specially
2988
+ ["multi_value", [], multi_value],
2989
+ // functions with >1 result — detected by result count
2990
+ ["gc", [
2991
+ "struct.new",
2992
+ "struct.get",
2993
+ "struct.set",
2994
+ "array.new",
2995
+ "array.get",
2996
+ "array.set",
2997
+ "array.len",
2998
+ "struct.new_default",
2999
+ "array.new_default",
3000
+ "array.new_fixed",
3001
+ "array.copy"
3002
+ ], gc],
3003
+ ["ref_cast", ["ref.test", "ref.cast", "br_on_cast", "br_on_cast_fail"], ref_cast]
3004
+ ];
3005
+ var FEATURES = Object.fromEntries(POLYFILLS.map((p) => [p[0], p[1]]));
3006
+ var normalize2 = (opts) => {
3007
+ if (opts === false) return {};
3008
+ if (opts !== true && typeof opts !== "string") return { ...opts };
3009
+ const set = typeof opts === "string" ? new Set(opts.split(/\s+/).filter(Boolean)) : null;
3010
+ const m = {};
3011
+ for (const p of POLYFILLS) m[p[0]] = set ? set.has("all") || set.has(p[0]) : true;
3012
+ return m;
3013
+ };
3014
+ var detect = (ast) => {
3015
+ const used = /* @__PURE__ */ new Set();
3016
+ walk(ast, (node) => {
3017
+ if (typeof node !== "string") return;
3018
+ for (const p of POLYFILLS) {
3019
+ const ops = p[1];
3020
+ if (ops.some((op) => node === op || node.startsWith(op + " "))) used.add(p[0]);
3021
+ }
3022
+ });
3023
+ walk(ast, (node) => {
3024
+ if (!Array.isArray(node) || node[0] !== "global") return;
3025
+ for (const init of node) {
3026
+ if (!Array.isArray(init)) continue;
3027
+ if (init[0] === "i32.add" || init[0] === "i32.sub" || init[0] === "i32.mul" || init[0] === "i64.add" || init[0] === "i64.sub" || init[0] === "i64.mul") {
3028
+ walk(init, (inner) => {
3029
+ if (Array.isArray(inner) && inner[0] === "global.get") used.add("extended_const");
3030
+ });
3031
+ }
3032
+ }
3033
+ });
3034
+ walk(ast, (node) => {
3035
+ if (!Array.isArray(node) || node[0] !== "func") return;
3036
+ let resultCount = 0;
3037
+ for (const part of node) {
3038
+ if (Array.isArray(part) && part[0] === "result") resultCount += part.length - 1;
3039
+ }
3040
+ if (resultCount > 1) used.add("multi_value");
3041
+ });
3042
+ return used;
3043
+ };
3043
3044
  function polyfill(ast, opts = true) {
3044
3045
  if (typeof ast === "string") ast = parse_default(ast);
3045
3046
  ast = clone(ast);
3046
3047
  opts = normalize2(opts);
3047
3048
  const used = detect(ast);
3048
3049
  const ctx = { uid: 0 };
3049
- for (const feat of ALL) {
3050
- if (used.has(feat) && opts[feat] !== false && transforms[feat]) {
3051
- ast = transforms[feat](ast, ctx);
3052
- }
3050
+ for (const p of POLYFILLS) {
3051
+ const fn = p[2];
3052
+ if (used.has(p[0]) && opts[p[0]] !== false) ast = fn(ast, ctx);
3053
3053
  }
3054
3054
  return ast;
3055
3055
  }
3056
3056
 
3057
3057
  // src/optimize.js
3058
- var OPTS = {
3059
- treeshake: true,
3060
- // remove unused funcs/globals/types/tables
3061
- fold: true,
3062
- // constant folding
3063
- deadcode: true,
3064
- // eliminate dead code after unreachable/br/return
3065
- locals: true,
3066
- // remove unused locals
3067
- identity: true,
3068
- // remove identity ops (x + 0 → x)
3069
- strength: true,
3070
- // strength reduction (x * 2 → x << 1)
3071
- branch: true,
3072
- // simplify constant branches
3073
- propagate: true,
3074
- // forward-propagate single-use locals & tiny consts (never inflates)
3075
- inline: false,
3076
- // inline tiny functions — can duplicate bodies
3077
- inlineOnce: true,
3078
- // inline single-call functions into their lone caller (never duplicates)
3079
- vacuum: true,
3080
- // remove nops, drop-of-pure, empty branches
3081
- mergeBlocks: true,
3082
- // unwrap `(block $L …)` whose label is never targeted
3083
- coalesce: true,
3084
- // share local slots between same-type non-overlapping locals
3085
- peephole: true,
3086
- // x-x→0, x&0→0, etc.
3087
- globals: true,
3088
- // propagate immutable global constants
3089
- offset: true,
3090
- // fold add+const into load/store offset
3091
- unbranch: true,
3092
- // remove redundant br at end of own block
3093
- loopify: true,
3094
- // collapse block+loop+brif while-idiom into loop+if
3095
- stripmut: true,
3096
- // strip mut from never-written globals
3097
- brif: true,
3098
- // if-then-br → br_if
3099
- foldarms: false,
3100
- // merge identical trailing if arms — can add block wrapper
3101
- dedupe: true,
3102
- // eliminate duplicate functions
3103
- reorder: false,
3104
- // put hot functions first — no AST reduction
3105
- dedupTypes: true,
3106
- // merge identical type definitions
3107
- packData: true,
3108
- // trim trailing zeros, merge adjacent data segments
3109
- minifyImports: false
3110
- // shorten import names — enable only when you control the host
3111
- };
3112
- var ALL2 = Object.keys(OPTS);
3113
3058
  var binarySize = (ast) => {
3114
3059
  try {
3115
3060
  return compile(ast).length;
@@ -3126,34 +3071,6 @@ var equal = (a, b) => {
3126
3071
  for (let i = 0; i < a.length; i++) if (!equal(a[i], b[i])) return false;
3127
3072
  return true;
3128
3073
  };
3129
- var normalize3 = (opts) => {
3130
- if (opts === true) return { ...OPTS };
3131
- if (opts === false) return {};
3132
- if (typeof opts === "string") {
3133
- const set = new Set(opts.split(/\s+/).filter(Boolean));
3134
- if (set.has("all")) return Object.fromEntries(ALL2.map((f) => [f, true]));
3135
- return Object.fromEntries(ALL2.map((f) => [f, set.has(f)]));
3136
- }
3137
- return { ...OPTS, ...opts };
3138
- };
3139
- var clone2 = (node) => {
3140
- if (!Array.isArray(node)) return node;
3141
- return node.map(clone2);
3142
- };
3143
- var walk2 = (node, fn, parent, idx) => {
3144
- fn(node, parent, idx);
3145
- if (Array.isArray(node)) for (let i = 0; i < node.length; i++) walk2(node[i], fn, node, i);
3146
- };
3147
- var walkPost2 = (node, fn, parent, idx) => {
3148
- if (Array.isArray(node)) {
3149
- for (let i = 0; i < node.length; i++) {
3150
- const result2 = walkPost2(node[i], fn, node, i);
3151
- if (result2 !== void 0) node[i] = result2;
3152
- }
3153
- }
3154
- const result = fn(node, parent, idx);
3155
- return result !== void 0 ? result : node;
3156
- };
3157
3074
  var parseIf = (node) => {
3158
3075
  let condIdx = 1;
3159
3076
  while (condIdx < node.length) {
@@ -3254,7 +3171,7 @@ var treeshake = (ast) => {
3254
3171
  markFunc(ref);
3255
3172
  }
3256
3173
  for (const elem of elems) {
3257
- walk2(elem, (n) => {
3174
+ walk(elem, (n) => {
3258
3175
  if (Array.isArray(n) && n[0] === "ref.func") markFunc(n[1]);
3259
3176
  else if (typeof n === "string" && n[0] === "$") markFunc(n);
3260
3177
  });
@@ -3276,7 +3193,7 @@ var treeshake = (ast) => {
3276
3193
  if (entry.scanned) continue;
3277
3194
  entry.scanned = true;
3278
3195
  if (entry.isImport) continue;
3279
- walk2(entry.node, (n) => {
3196
+ walk(entry.node, (n) => {
3280
3197
  if (!Array.isArray(n)) {
3281
3198
  if (typeof n === "string" && n[0] === "$") markFunc(n);
3282
3199
  return;
@@ -3348,120 +3265,120 @@ var i64c = (fn) => (a, b) => fn(a, b) ? 1 : 0;
3348
3265
  var u64c = (fn) => (a, b) => fn(BigInt.asUintN(64, a), BigInt.asUintN(64, b)) ? 1 : 0;
3349
3266
  var FOLDABLE = {
3350
3267
  // i32 arithmetic
3351
- "i32.add": [(a, b) => a + b | 0, "i32"],
3352
- "i32.sub": [(a, b) => a - b | 0, "i32"],
3353
- "i32.mul": [(a, b) => Math.imul(a, b), "i32"],
3354
- "i32.div_s": [(a, b) => b !== 0 ? a / b | 0 : null, "i32"],
3355
- "i32.div_u": [(a, b) => b !== 0 ? (a >>> 0) / (b >>> 0) | 0 : null, "i32"],
3356
- "i32.rem_s": [(a, b) => b !== 0 ? a % b | 0 : null, "i32"],
3357
- "i32.rem_u": [(a, b) => b !== 0 ? (a >>> 0) % (b >>> 0) | 0 : null, "i32"],
3358
- "i32.and": [(a, b) => a & b, "i32"],
3359
- "i32.or": [(a, b) => a | b, "i32"],
3360
- "i32.xor": [(a, b) => a ^ b, "i32"],
3361
- "i32.shl": [(a, b) => a << (b & 31), "i32"],
3362
- "i32.shr_s": [(a, b) => a >> (b & 31), "i32"],
3363
- "i32.shr_u": [(a, b) => a >>> (b & 31), "i32"],
3364
- "i32.rotl": [(a, b) => {
3268
+ "i32.add": (a, b) => a + b | 0,
3269
+ "i32.sub": (a, b) => a - b | 0,
3270
+ "i32.mul": (a, b) => Math.imul(a, b),
3271
+ "i32.div_s": (a, b) => b !== 0 ? a / b | 0 : null,
3272
+ "i32.div_u": (a, b) => b !== 0 ? (a >>> 0) / (b >>> 0) | 0 : null,
3273
+ "i32.rem_s": (a, b) => b !== 0 ? a % b | 0 : null,
3274
+ "i32.rem_u": (a, b) => b !== 0 ? (a >>> 0) % (b >>> 0) | 0 : null,
3275
+ "i32.and": (a, b) => a & b,
3276
+ "i32.or": (a, b) => a | b,
3277
+ "i32.xor": (a, b) => a ^ b,
3278
+ "i32.shl": (a, b) => a << (b & 31),
3279
+ "i32.shr_s": (a, b) => a >> (b & 31),
3280
+ "i32.shr_u": (a, b) => a >>> (b & 31),
3281
+ "i32.rotl": (a, b) => {
3365
3282
  b &= 31;
3366
3283
  return a << b | a >>> 32 - b | 0;
3367
- }, "i32"],
3368
- "i32.rotr": [(a, b) => {
3284
+ },
3285
+ "i32.rotr": (a, b) => {
3369
3286
  b &= 31;
3370
3287
  return a >>> b | a << 32 - b | 0;
3371
- }, "i32"],
3372
- "i32.eq": [i32c((a, b) => a === b), "i32"],
3373
- "i32.ne": [i32c((a, b) => a !== b), "i32"],
3374
- "i32.lt_s": [i32c((a, b) => a < b), "i32"],
3375
- "i32.lt_u": [u32c((a, b) => a < b), "i32"],
3376
- "i32.gt_s": [i32c((a, b) => a > b), "i32"],
3377
- "i32.gt_u": [u32c((a, b) => a > b), "i32"],
3378
- "i32.le_s": [i32c((a, b) => a <= b), "i32"],
3379
- "i32.le_u": [u32c((a, b) => a <= b), "i32"],
3380
- "i32.ge_s": [i32c((a, b) => a >= b), "i32"],
3381
- "i32.ge_u": [u32c((a, b) => a >= b), "i32"],
3382
- "i32.eqz": [(a) => a === 0 ? 1 : 0, "i32"],
3383
- "i32.clz": [(a) => Math.clz32(a), "i32"],
3384
- "i32.ctz": [(a) => a === 0 ? 32 : 31 - Math.clz32(a & -a), "i32"],
3385
- "i32.popcnt": [(a) => {
3288
+ },
3289
+ "i32.eq": i32c((a, b) => a === b),
3290
+ "i32.ne": i32c((a, b) => a !== b),
3291
+ "i32.lt_s": i32c((a, b) => a < b),
3292
+ "i32.lt_u": u32c((a, b) => a < b),
3293
+ "i32.gt_s": i32c((a, b) => a > b),
3294
+ "i32.gt_u": u32c((a, b) => a > b),
3295
+ "i32.le_s": i32c((a, b) => a <= b),
3296
+ "i32.le_u": u32c((a, b) => a <= b),
3297
+ "i32.ge_s": i32c((a, b) => a >= b),
3298
+ "i32.ge_u": u32c((a, b) => a >= b),
3299
+ "i32.eqz": (a) => a === 0 ? 1 : 0,
3300
+ "i32.clz": (a) => Math.clz32(a),
3301
+ "i32.ctz": (a) => a === 0 ? 32 : 31 - Math.clz32(a & -a),
3302
+ "i32.popcnt": (a) => {
3386
3303
  let c = 0;
3387
3304
  while (a) {
3388
3305
  c += a & 1;
3389
3306
  a >>>= 1;
3390
3307
  }
3391
3308
  return c;
3392
- }, "i32"],
3393
- "i32.wrap_i64": [(a) => Number(BigInt.asIntN(32, a)), "i32"],
3394
- "i32.extend8_s": [(a) => a << 24 >> 24, "i32"],
3395
- "i32.extend16_s": [(a) => a << 16 >> 16, "i32"],
3309
+ },
3310
+ "i32.wrap_i64": (a) => Number(BigInt.asIntN(32, a)),
3311
+ "i32.extend8_s": (a) => a << 24 >> 24,
3312
+ "i32.extend16_s": (a) => a << 16 >> 16,
3396
3313
  // i64 (using BigInt)
3397
- "i64.add": [(a, b) => BigInt.asIntN(64, a + b), "i64"],
3398
- "i64.sub": [(a, b) => BigInt.asIntN(64, a - b), "i64"],
3399
- "i64.mul": [(a, b) => BigInt.asIntN(64, a * b), "i64"],
3400
- "i64.div_s": [(a, b) => b !== 0n ? BigInt.asIntN(64, a / b) : null, "i64"],
3401
- "i64.div_u": [(a, b) => b !== 0n ? BigInt.asUintN(64, BigInt.asUintN(64, a) / BigInt.asUintN(64, b)) : null, "i64"],
3402
- "i64.rem_s": [(a, b) => b !== 0n ? BigInt.asIntN(64, a % b) : null, "i64"],
3403
- "i64.rem_u": [(a, b) => b !== 0n ? BigInt.asUintN(64, BigInt.asUintN(64, a) % BigInt.asUintN(64, b)) : null, "i64"],
3404
- "i64.and": [(a, b) => BigInt.asIntN(64, a & b), "i64"],
3405
- "i64.or": [(a, b) => BigInt.asIntN(64, a | b), "i64"],
3406
- "i64.xor": [(a, b) => BigInt.asIntN(64, a ^ b), "i64"],
3407
- "i64.shl": [(a, b) => BigInt.asIntN(64, a << (b & 63n)), "i64"],
3408
- "i64.shr_s": [(a, b) => BigInt.asIntN(64, a >> (b & 63n)), "i64"],
3409
- "i64.shr_u": [(a, b) => BigInt.asUintN(64, BigInt.asUintN(64, a) >> (b & 63n)), "i64"],
3410
- "i64.eq": [i64c((a, b) => a === b), "i32"],
3411
- "i64.ne": [i64c((a, b) => a !== b), "i32"],
3412
- "i64.lt_s": [i64c((a, b) => a < b), "i32"],
3413
- "i64.lt_u": [u64c((a, b) => a < b), "i32"],
3414
- "i64.gt_s": [i64c((a, b) => a > b), "i32"],
3415
- "i64.gt_u": [u64c((a, b) => a > b), "i32"],
3416
- "i64.le_s": [i64c((a, b) => a <= b), "i32"],
3417
- "i64.le_u": [u64c((a, b) => a <= b), "i32"],
3418
- "i64.ge_s": [i64c((a, b) => a >= b), "i32"],
3419
- "i64.ge_u": [u64c((a, b) => a >= b), "i32"],
3420
- "i64.eqz": [(a) => a === 0n ? 1 : 0, "i32"],
3421
- "i64.extend_i32_s": [(a) => BigInt(a), "i64"],
3422
- "i64.extend_i32_u": [(a) => BigInt(a >>> 0), "i64"],
3423
- "i64.extend8_s": [(a) => BigInt.asIntN(64, BigInt.asIntN(8, a)), "i64"],
3424
- "i64.extend16_s": [(a) => BigInt.asIntN(64, BigInt.asIntN(16, a)), "i64"],
3425
- "i64.extend32_s": [(a) => BigInt.asIntN(64, BigInt.asIntN(32, a)), "i64"],
3314
+ "i64.add": (a, b) => BigInt.asIntN(64, a + b),
3315
+ "i64.sub": (a, b) => BigInt.asIntN(64, a - b),
3316
+ "i64.mul": (a, b) => BigInt.asIntN(64, a * b),
3317
+ "i64.div_s": (a, b) => b !== 0n ? BigInt.asIntN(64, a / b) : null,
3318
+ "i64.div_u": (a, b) => b !== 0n ? BigInt.asUintN(64, BigInt.asUintN(64, a) / BigInt.asUintN(64, b)) : null,
3319
+ "i64.rem_s": (a, b) => b !== 0n ? BigInt.asIntN(64, a % b) : null,
3320
+ "i64.rem_u": (a, b) => b !== 0n ? BigInt.asUintN(64, BigInt.asUintN(64, a) % BigInt.asUintN(64, b)) : null,
3321
+ "i64.and": (a, b) => BigInt.asIntN(64, a & b),
3322
+ "i64.or": (a, b) => BigInt.asIntN(64, a | b),
3323
+ "i64.xor": (a, b) => BigInt.asIntN(64, a ^ b),
3324
+ "i64.shl": (a, b) => BigInt.asIntN(64, a << (b & 63n)),
3325
+ "i64.shr_s": (a, b) => BigInt.asIntN(64, a >> (b & 63n)),
3326
+ "i64.shr_u": (a, b) => BigInt.asUintN(64, BigInt.asUintN(64, a) >> (b & 63n)),
3327
+ "i64.eq": i64c((a, b) => a === b),
3328
+ "i64.ne": i64c((a, b) => a !== b),
3329
+ "i64.lt_s": i64c((a, b) => a < b),
3330
+ "i64.lt_u": u64c((a, b) => a < b),
3331
+ "i64.gt_s": i64c((a, b) => a > b),
3332
+ "i64.gt_u": u64c((a, b) => a > b),
3333
+ "i64.le_s": i64c((a, b) => a <= b),
3334
+ "i64.le_u": u64c((a, b) => a <= b),
3335
+ "i64.ge_s": i64c((a, b) => a >= b),
3336
+ "i64.ge_u": u64c((a, b) => a >= b),
3337
+ "i64.eqz": (a) => a === 0n ? 1 : 0,
3338
+ "i64.extend_i32_s": (a) => BigInt(a),
3339
+ "i64.extend_i32_u": (a) => BigInt(a >>> 0),
3340
+ "i64.extend8_s": (a) => BigInt.asIntN(64, BigInt.asIntN(8, a)),
3341
+ "i64.extend16_s": (a) => BigInt.asIntN(64, BigInt.asIntN(16, a)),
3342
+ "i64.extend32_s": (a) => BigInt.asIntN(64, BigInt.asIntN(32, a)),
3426
3343
  // f32/f64 (NaN/precision-aware via Math.fround)
3427
- "f32.add": [(a, b) => Math.fround(a + b), "f32"],
3428
- "f32.sub": [(a, b) => Math.fround(a - b), "f32"],
3429
- "f32.mul": [(a, b) => Math.fround(a * b), "f32"],
3430
- "f32.div": [(a, b) => Math.fround(a / b), "f32"],
3431
- "f32.neg": [(a) => Math.fround(-a), "f32"],
3432
- "f32.abs": [(a) => Math.fround(Math.abs(a)), "f32"],
3433
- "f32.sqrt": [(a) => Math.fround(Math.sqrt(a)), "f32"],
3434
- "f32.ceil": [(a) => Math.fround(Math.ceil(a)), "f32"],
3435
- "f32.floor": [(a) => Math.fround(Math.floor(a)), "f32"],
3436
- "f32.trunc": [(a) => Math.fround(Math.trunc(a)), "f32"],
3437
- "f32.nearest": [(a) => Math.fround(roundEven(a)), "f32"],
3438
- "f64.add": [(a, b) => a + b, "f64"],
3439
- "f64.sub": [(a, b) => a - b, "f64"],
3440
- "f64.mul": [(a, b) => a * b, "f64"],
3441
- "f64.div": [(a, b) => a / b, "f64"],
3442
- "f64.neg": [(a) => -a, "f64"],
3443
- "f64.abs": [Math.abs, "f64"],
3444
- "f64.sqrt": [Math.sqrt, "f64"],
3445
- "f64.ceil": [Math.ceil, "f64"],
3446
- "f64.floor": [Math.floor, "f64"],
3447
- "f64.trunc": [Math.trunc, "f64"],
3448
- "f64.nearest": [roundEven, "f64"],
3344
+ "f32.add": (a, b) => Math.fround(a + b),
3345
+ "f32.sub": (a, b) => Math.fround(a - b),
3346
+ "f32.mul": (a, b) => Math.fround(a * b),
3347
+ "f32.div": (a, b) => Math.fround(a / b),
3348
+ "f32.neg": (a) => Math.fround(-a),
3349
+ "f32.abs": (a) => Math.fround(Math.abs(a)),
3350
+ "f32.sqrt": (a) => Math.fround(Math.sqrt(a)),
3351
+ "f32.ceil": (a) => Math.fround(Math.ceil(a)),
3352
+ "f32.floor": (a) => Math.fround(Math.floor(a)),
3353
+ "f32.trunc": (a) => Math.fround(Math.trunc(a)),
3354
+ "f32.nearest": (a) => Math.fround(roundEven(a)),
3355
+ "f64.add": (a, b) => a + b,
3356
+ "f64.sub": (a, b) => a - b,
3357
+ "f64.mul": (a, b) => a * b,
3358
+ "f64.div": (a, b) => a / b,
3359
+ "f64.neg": (a) => -a,
3360
+ "f64.abs": Math.abs,
3361
+ "f64.sqrt": Math.sqrt,
3362
+ "f64.ceil": Math.ceil,
3363
+ "f64.floor": Math.floor,
3364
+ "f64.trunc": Math.trunc,
3365
+ "f64.nearest": roundEven,
3449
3366
  // Bit-exact reinterprets (preserve NaN payloads)
3450
- "i32.reinterpret_f32": [i32FromF32, "i32"],
3451
- "f32.reinterpret_i32": [f32FromI32, "f32"],
3452
- "i64.reinterpret_f64": [i64FromF64, "i64"],
3453
- "f64.reinterpret_i64": [f64FromI64, "f64"],
3367
+ "i32.reinterpret_f32": i32FromF32,
3368
+ "f32.reinterpret_i32": f32FromI32,
3369
+ "i64.reinterpret_f64": i64FromF64,
3370
+ "f64.reinterpret_i64": f64FromI64,
3454
3371
  // Numeric conversions (value-preserving where representable)
3455
- "f32.convert_i32_s": [(a) => Math.fround(a | 0), "f32"],
3456
- "f32.convert_i32_u": [(a) => Math.fround(a >>> 0), "f32"],
3457
- "f32.convert_i64_s": [(a) => Math.fround(Number(BigInt.asIntN(64, a))), "f32"],
3458
- "f32.convert_i64_u": [(a) => Math.fround(Number(BigInt.asUintN(64, a))), "f32"],
3459
- "f64.convert_i32_s": [(a) => a | 0, "f64"],
3460
- "f64.convert_i32_u": [(a) => a >>> 0, "f64"],
3461
- "f64.convert_i64_s": [(a) => Number(BigInt.asIntN(64, a)), "f64"],
3462
- "f64.convert_i64_u": [(a) => Number(BigInt.asUintN(64, a)), "f64"],
3463
- "f32.demote_f64": [(a) => Math.fround(a), "f32"],
3464
- "f64.promote_f32": [(a) => Math.fround(a), "f64"]
3372
+ "f32.convert_i32_s": (a) => Math.fround(a | 0),
3373
+ "f32.convert_i32_u": (a) => Math.fround(a >>> 0),
3374
+ "f32.convert_i64_s": (a) => Math.fround(Number(BigInt.asIntN(64, a))),
3375
+ "f32.convert_i64_u": (a) => Math.fround(Number(BigInt.asUintN(64, a))),
3376
+ "f64.convert_i32_s": (a) => a | 0,
3377
+ "f64.convert_i32_u": (a) => a >>> 0,
3378
+ "f64.convert_i64_s": (a) => Number(BigInt.asIntN(64, a)),
3379
+ "f64.convert_i64_u": (a) => Number(BigInt.asUintN(64, a)),
3380
+ "f32.demote_f64": (a) => Math.fround(a),
3381
+ "f64.promote_f32": (a) => Math.fround(a)
3465
3382
  };
3466
3383
  var _parseNanF64 = (s, i = s?.indexOf?.("nan")) => {
3467
3384
  if (i < 0 || i == null) return null;
@@ -3478,8 +3395,8 @@ var _parseNanF32 = (s, i = s?.indexOf?.("nan")) => {
3478
3395
  var getConst = (node) => {
3479
3396
  if (!Array.isArray(node) || node.length !== 2) return null;
3480
3397
  const [op, val] = node;
3481
- if (op === "i32.const") return { type: "i32", value: Number(val) | 0 };
3482
- if (op === "i64.const") return { type: "i64", value: BigInt(val) };
3398
+ if (op === "i32.const") return { type: "i32", value: (typeof val === "string" ? i32.parse(val) : val) | 0 };
3399
+ if (op === "i64.const") return { type: "i64", value: typeof val === "string" ? i64.parse(val) : BigInt(val) };
3483
3400
  if (op === "f32.const") {
3484
3401
  const n = _parseNanF32(val);
3485
3402
  return { type: "f32", value: n !== null ? n : Math.fround(Number(val)) };
@@ -3498,24 +3415,23 @@ var makeConst = (type, value) => {
3498
3415
  return null;
3499
3416
  };
3500
3417
  var fold = (ast) => {
3501
- return walkPost2(ast, (node) => {
3418
+ return walkPost(ast, (node) => {
3502
3419
  if (!Array.isArray(node)) return;
3503
- const entry = FOLDABLE[node[0]];
3504
- if (!entry) return;
3505
- const [fn, t] = entry;
3420
+ const fn = FOLDABLE[node[0]];
3421
+ if (!fn) return;
3506
3422
  if (fn.length === 1 && node.length === 2) {
3507
3423
  const a = getConst(node[1]);
3508
3424
  if (!a) return;
3509
3425
  const r = fn(a.value);
3510
3426
  if (r === null) return;
3511
- return makeConst(t, r);
3427
+ return makeConst(resultType(node[0]), r);
3512
3428
  }
3513
3429
  if (fn.length === 2 && node.length === 3) {
3514
3430
  const a = getConst(node[1]), b = getConst(node[2]);
3515
3431
  if (!a || !b) return;
3516
3432
  const r = fn(a.value, b.value);
3517
3433
  if (r === null) return;
3518
- return makeConst(t, r);
3434
+ return makeConst(resultType(node[0]), r);
3519
3435
  }
3520
3436
  });
3521
3437
  };
@@ -3561,7 +3477,7 @@ var IDENTITIES = {
3561
3477
  // f * 1 → x (careful with NaN, skip for floats)
3562
3478
  };
3563
3479
  var identity = (ast) => {
3564
- return walkPost2(ast, (node) => {
3480
+ return walkPost(ast, (node) => {
3565
3481
  if (!Array.isArray(node) || node.length !== 3) return;
3566
3482
  const fn = IDENTITIES[node[0]];
3567
3483
  if (!fn) return;
@@ -3571,7 +3487,7 @@ var identity = (ast) => {
3571
3487
  });
3572
3488
  };
3573
3489
  var strength = (ast) => {
3574
- return walkPost2(ast, (node) => {
3490
+ return walkPost(ast, (node) => {
3575
3491
  if (!Array.isArray(node) || node.length !== 3) return;
3576
3492
  const [op, a, b] = node;
3577
3493
  if (op === "i32.mul") {
@@ -3627,7 +3543,7 @@ var strength = (ast) => {
3627
3543
  });
3628
3544
  };
3629
3545
  var branch = (ast) => {
3630
- return walkPost2(ast, (node) => {
3546
+ return walkPost(ast, (node) => {
3631
3547
  if (!Array.isArray(node)) return;
3632
3548
  const op = node[0];
3633
3549
  if (op === "if") {
@@ -3659,7 +3575,7 @@ var branch = (ast) => {
3659
3575
  };
3660
3576
  var TERMINATORS = /* @__PURE__ */ new Set(["unreachable", "return", "br", "br_table"]);
3661
3577
  var deadcode = (ast) => {
3662
- walk2(ast, (node) => {
3578
+ walk(ast, (node) => {
3663
3579
  if (!Array.isArray(node)) return;
3664
3580
  const kind = node[0];
3665
3581
  if (kind === "func" || kind === "block" || kind === "loop") {
@@ -3705,7 +3621,7 @@ var eliminateDeadInBlock = (block) => {
3705
3621
  }
3706
3622
  };
3707
3623
  var localReuse = (ast) => {
3708
- walk2(ast, (node) => {
3624
+ walk(ast, (node) => {
3709
3625
  if (!Array.isArray(node) || node[0] !== "func") return;
3710
3626
  const localDecls = [];
3711
3627
  const localTypes = /* @__PURE__ */ new Map();
@@ -3726,7 +3642,7 @@ var localReuse = (ast) => {
3726
3642
  }
3727
3643
  }
3728
3644
  }
3729
- walk2(node, (n) => {
3645
+ walk(node, (n) => {
3730
3646
  if (!Array.isArray(n)) return;
3731
3647
  const op = n[0];
3732
3648
  if (op === "local.get" || op === "local.set" || op === "local.tee") {
@@ -3799,7 +3715,7 @@ var countLocalUses = (node) => {
3799
3715
  if (!counts.has(name2)) counts.set(name2, { gets: 0, sets: 0, tees: 0 });
3800
3716
  return counts.get(name2);
3801
3717
  };
3802
- walk2(node, (n) => {
3718
+ walk(node, (n) => {
3803
3719
  if (!Array.isArray(n) || n.length < 2 || typeof n[1] !== "string") return;
3804
3720
  if (n[0] === "local.get") ensure(n[1]).gets++;
3805
3721
  else if (n[0] === "local.set") ensure(n[1]).sets++;
@@ -3824,7 +3740,7 @@ var canSubst = (k) => k.pure && k.singleUse || isTinyConst(k.val);
3824
3740
  var purgeRefs = (known, name2) => {
3825
3741
  for (const [key, tracked] of known) {
3826
3742
  let refs = false;
3827
- walk2(tracked.val, (n) => {
3743
+ walk(tracked.val, (n) => {
3828
3744
  if (Array.isArray(n) && (n[0] === "local.get" || n[0] === "local.tee") && n[1] === name2) refs = true;
3829
3745
  });
3830
3746
  if (refs) known.delete(key);
@@ -3854,13 +3770,13 @@ var substGets = (node, known) => {
3854
3770
  const op = node[0];
3855
3771
  if (op === "local.get" && node.length === 2) {
3856
3772
  const k = typeof node[1] === "string" && known.get(node[1]);
3857
- if (k && canSubst(k)) return clone2(k.val);
3773
+ if (k && canSubst(k)) return clone(k.val);
3858
3774
  return node;
3859
3775
  }
3860
3776
  let inner = known;
3861
3777
  if (op === "block" || op === "loop" || op === "if") {
3862
3778
  let cloned = null;
3863
- walk2(node, (n) => {
3779
+ walk(node, (n) => {
3864
3780
  if (!Array.isArray(n)) return;
3865
3781
  if ((n[0] === "local.set" || n[0] === "local.tee") && typeof n[1] === "string" && known.has(n[1])) {
3866
3782
  if (!cloned) cloned = new Map(known);
@@ -3873,7 +3789,7 @@ var substGets = (node, known) => {
3873
3789
  const r = substGets(node[i], inner);
3874
3790
  if (r !== node[i]) node[i] = r;
3875
3791
  if (i + 1 < node.length && Array.isArray(node[i])) {
3876
- walk2(node[i], (n) => {
3792
+ walk(node[i], (n) => {
3877
3793
  if (!Array.isArray(n)) return;
3878
3794
  if ((n[0] === "local.set" || n[0] === "local.tee") && typeof n[1] === "string") {
3879
3795
  if (inner === known) inner = new Map(known);
@@ -3920,7 +3836,7 @@ var forwardPropagate = (funcNode, params, useCounts) => {
3920
3836
  if (op === "local.get" && instr2.length === 2 && typeof instr2[1] === "string") {
3921
3837
  const tracked = known.get(instr2[1]);
3922
3838
  if (tracked && canSubst(tracked)) {
3923
- const replacement = clone2(tracked.val);
3839
+ const replacement = clone(tracked.val);
3924
3840
  instr2.length = 0;
3925
3841
  instr2.push(...Array.isArray(replacement) ? replacement : [replacement]);
3926
3842
  changed = true;
@@ -3928,10 +3844,10 @@ var forwardPropagate = (funcNode, params, useCounts) => {
3928
3844
  }
3929
3845
  }
3930
3846
  if (op !== "block" && op !== "loop" && op !== "if") {
3931
- const prev = clone2(instr2);
3847
+ const prev = clone(instr2);
3932
3848
  substGets(instr2, known);
3933
3849
  if (!equal(prev, instr2)) changed = true;
3934
- walk2(instr2, (n) => {
3850
+ walk(instr2, (n) => {
3935
3851
  if (Array.isArray(n) && (n[0] === "local.set" || n[0] === "local.tee") && typeof n[1] === "string") {
3936
3852
  known.delete(n[1]);
3937
3853
  purgeRefs(known, n[1]);
@@ -3955,7 +3871,7 @@ var eliminateSetGetPairs = (funcNode, params, useCounts) => {
3955
3871
  if (getNode[1] !== name2 || params.has(name2)) continue;
3956
3872
  const uses = useCounts.get(name2) || { gets: 0, sets: 0, tees: 0 };
3957
3873
  if (uses.sets !== 1 || uses.gets !== 1 || uses.tees !== 0) continue;
3958
- const expr2 = clone2(setNode[2]);
3874
+ const expr2 = clone(setNode[2]);
3959
3875
  funcNode.splice(i, 2, ...Array.isArray(expr2) ? [expr2] : [expr2]);
3960
3876
  changed = true;
3961
3877
  i--;
@@ -3973,7 +3889,7 @@ var createLocalTees = (funcNode, params, useCounts) => {
3973
3889
  if (getNode[1] !== name2 || params.has(name2)) continue;
3974
3890
  const uses = useCounts.get(name2) || { gets: 0, sets: 0, tees: 0 };
3975
3891
  if (uses.sets + uses.gets + uses.tees <= 2) continue;
3976
- funcNode.splice(i, 2, ["local.tee", name2, clone2(setNode[2])]);
3892
+ funcNode.splice(i, 2, ["local.tee", name2, clone(setNode[2])]);
3977
3893
  changed = true;
3978
3894
  }
3979
3895
  return changed;
@@ -4006,13 +3922,13 @@ var eliminateDeadStores = (funcNode, params, useCounts) => {
4006
3922
  };
4007
3923
  var isScopeNode = (n) => Array.isArray(n) && (n[0] === "func" || n[0] === "block" || n[0] === "loop" || n[0] === "then" || n[0] === "else");
4008
3924
  var propagate = (ast) => {
4009
- walk2(ast, (funcNode) => {
3925
+ walk(ast, (funcNode) => {
4010
3926
  if (!Array.isArray(funcNode) || funcNode[0] !== "func") return;
4011
3927
  const params = /* @__PURE__ */ new Set();
4012
3928
  for (const sub of funcNode)
4013
3929
  if (Array.isArray(sub) && sub[0] === "param" && typeof sub[1] === "string") params.add(sub[1]);
4014
3930
  const scopes = [];
4015
- walkPost2(funcNode, (n) => {
3931
+ walkPost(funcNode, (n) => {
4016
3932
  if (isScopeNode(n)) scopes.push(n);
4017
3933
  });
4018
3934
  for (let round = 0; round < 6; round++) {
@@ -4062,7 +3978,7 @@ var inline = (ast) => {
4062
3978
  const paramNames = new Set(params.map((p) => p.name));
4063
3979
  let mutatesParam = false;
4064
3980
  let hasReturn = false;
4065
- walk2(body[0], (n) => {
3981
+ walk(body[0], (n) => {
4066
3982
  if (!Array.isArray(n)) return;
4067
3983
  if ((n[0] === "local.set" || n[0] === "local.tee") && paramNames.has(n[1])) {
4068
3984
  mutatesParam = true;
@@ -4077,22 +3993,21 @@ var inline = (ast) => {
4077
3993
  }
4078
3994
  }
4079
3995
  if (inlinable.size === 0) return ast;
4080
- walkPost2(ast, (node) => {
3996
+ walkPost(ast, (node) => {
4081
3997
  if (!Array.isArray(node) || node[0] !== "call") return;
4082
3998
  const fname = node[1];
4083
3999
  if (!inlinable.has(fname)) return;
4084
4000
  const { body, params } = inlinable.get(fname);
4085
4001
  const args = node.slice(2);
4086
4002
  if (params.length === 0) {
4087
- return clone2(body);
4003
+ return clone(body);
4088
4004
  }
4089
- const substituted = clone2(body);
4090
- walkPost2(substituted, (n) => {
4005
+ const substituted = walkPost(clone(body), (n) => {
4091
4006
  if (!Array.isArray(n) || n[0] !== "local.get") return;
4092
4007
  const local = n[1];
4093
4008
  const paramIdx = params.findIndex((p) => p.name === local);
4094
4009
  if (paramIdx !== -1 && args[paramIdx]) {
4095
- return clone2(args[paramIdx]);
4010
+ return clone(args[paramIdx]);
4096
4011
  }
4097
4012
  });
4098
4013
  return substituted;
@@ -4231,13 +4146,13 @@ var inlineOnce = (ast) => {
4231
4146
  if (!calleeName) break;
4232
4147
  const callee = funcByName.get(calleeName);
4233
4148
  const params = [], locals = [];
4234
- let resultType = null;
4149
+ let inlResult = null;
4235
4150
  for (let i = 2; i < callee.length; i++) {
4236
4151
  const c = callee[i];
4237
4152
  if (typeof c === "string" || !Array.isArray(c)) continue;
4238
4153
  if (c[0] === "param") params.push({ name: c[1], type: c[2] });
4239
4154
  else if (c[0] === "result") {
4240
- if (c.length > 1) resultType = c[1];
4155
+ if (c.length > 1) inlResult = c[1];
4241
4156
  } else if (c[0] === "local") locals.push({ name: c[1], type: c[2] });
4242
4157
  else if (c[0] === "export" || c[0] === "type") continue;
4243
4158
  else break;
@@ -4273,7 +4188,7 @@ var inlineOnce = (ast) => {
4273
4188
  if (fn === callee || done) continue;
4274
4189
  const start = bodyStart(fn);
4275
4190
  for (let i = start; i < fn.length; i++) {
4276
- const replaced = walkPost2(fn[i], (n) => {
4191
+ const replaced = walkPost(fn[i], (n) => {
4277
4192
  if (done || !Array.isArray(n) || n[0] !== "call" || n[1] !== calleeName) return;
4278
4193
  const args = n.slice(2);
4279
4194
  if (args.length !== params.length) return;
@@ -4281,7 +4196,7 @@ var inlineOnce = (ast) => {
4281
4196
  const resets = locals.filter((l) => needsReset(cBody, l.name)).map((l) => ["local.set", rename.get(l.name), zeroFor(l.type)]);
4282
4197
  const inner = cBody.map(sub);
4283
4198
  done = true;
4284
- return resultType ? ["block", exit, ["result", resultType], ...setup, ...resets, ...inner] : ["block", exit, ...setup, ...resets, ...inner];
4199
+ return inlResult ? ["block", exit, ["result", inlResult], ...setup, ...resets, ...inner] : ["block", exit, ...setup, ...resets, ...inner];
4285
4200
  });
4286
4201
  if (replaced !== fn[i]) fn[i] = replaced;
4287
4202
  if (done) {
@@ -4338,7 +4253,7 @@ var targetsLabel = (body, label) => {
4338
4253
  return found;
4339
4254
  };
4340
4255
  var mergeBlocks = (ast) => {
4341
- walkPost2(ast, (node) => {
4256
+ walkPost(ast, (node) => {
4342
4257
  if (!Array.isArray(node) || node[0] !== "block") return;
4343
4258
  let bi = 1, label = null;
4344
4259
  if (typeof node[1] === "string" && node[1][0] === "$") {
@@ -4367,7 +4282,7 @@ var mergeBlocks = (ast) => {
4367
4282
  node.length = 0;
4368
4283
  for (const tok of only) node.push(tok);
4369
4284
  });
4370
- walk2(ast, (node) => {
4285
+ walk(ast, (node) => {
4371
4286
  if (!isScopeNode(node)) return;
4372
4287
  let i = 1;
4373
4288
  while (i < node.length) {
@@ -4441,7 +4356,7 @@ var mergeBlocks = (ast) => {
4441
4356
  return ast;
4442
4357
  };
4443
4358
  var coalesceLocals = (ast) => {
4444
- walk2(ast, (funcNode) => {
4359
+ walk(ast, (funcNode) => {
4445
4360
  if (!Array.isArray(funcNode) || funcNode[0] !== "func") return;
4446
4361
  const decls = /* @__PURE__ */ new Map();
4447
4362
  for (const sub of funcNode) {
@@ -4513,7 +4428,7 @@ var coalesceLocals = (ast) => {
4513
4428
  } else slots.push({ primary: name2, type, end: range.end });
4514
4429
  }
4515
4430
  if (rename.size === 0) return;
4516
- walk2(funcNode, (n) => {
4431
+ walk(funcNode, (n) => {
4517
4432
  if (Array.isArray(n) && (n[0] === "local.get" || n[0] === "local.set" || n[0] === "local.tee") && rename.has(n[1])) {
4518
4433
  n[1] = rename.get(n[1]);
4519
4434
  }
@@ -4522,7 +4437,7 @@ var coalesceLocals = (ast) => {
4522
4437
  return ast;
4523
4438
  };
4524
4439
  var vacuum = (ast) => {
4525
- return walkPost2(ast, (node) => {
4440
+ return walkPost(ast, (node) => {
4526
4441
  if (!Array.isArray(node)) return;
4527
4442
  const op = node[0];
4528
4443
  if (op === "nop") return ["nop"];
@@ -4562,10 +4477,6 @@ var PEEPHOLE = {
4562
4477
  "i64.sub": (a, b) => equal(a, b) ? ["i64.const", 0n] : null,
4563
4478
  "i32.xor": (a, b) => equal(a, b) ? ["i32.const", 0] : null,
4564
4479
  "i64.xor": (a, b) => equal(a, b) ? ["i64.const", 0n] : null,
4565
- "i32.and": (a, b) => equal(a, b) ? a : null,
4566
- "i64.and": (a, b) => equal(a, b) ? a : null,
4567
- "i32.or": (a, b) => equal(a, b) ? a : null,
4568
- "i64.or": (a, b) => equal(a, b) ? a : null,
4569
4480
  "i32.eq": (a, b) => equal(a, b) ? ["i32.const", 1] : null,
4570
4481
  "i64.eq": (a, b) => equal(a, b) ? ["i32.const", 1] : null,
4571
4482
  "i32.ne": (a, b) => equal(a, b) ? ["i32.const", 0] : null,
@@ -4598,21 +4509,25 @@ var PEEPHOLE = {
4598
4509
  return null;
4599
4510
  },
4600
4511
  "i32.and": (a, b) => {
4512
+ if (equal(a, b)) return a;
4601
4513
  const ca = getConst(a), cb = getConst(b);
4602
4514
  if (ca?.value === 0 || cb?.value === 0) return ["i32.const", 0];
4603
4515
  return null;
4604
4516
  },
4605
4517
  "i64.and": (a, b) => {
4518
+ if (equal(a, b)) return a;
4606
4519
  const ca = getConst(a), cb = getConst(b);
4607
4520
  if (ca?.value === 0n || cb?.value === 0n) return ["i64.const", 0n];
4608
4521
  return null;
4609
4522
  },
4610
4523
  "i32.or": (a, b) => {
4524
+ if (equal(a, b)) return a;
4611
4525
  const ca = getConst(a), cb = getConst(b);
4612
4526
  if (ca?.value === -1 || cb?.value === -1) return ["i32.const", -1];
4613
4527
  return null;
4614
4528
  },
4615
4529
  "i64.or": (a, b) => {
4530
+ if (equal(a, b)) return a;
4616
4531
  const ca = getConst(a), cb = getConst(b);
4617
4532
  if (ca?.value === -1n || cb?.value === -1n) return ["i64.const", -1n];
4618
4533
  return null;
@@ -4621,7 +4536,7 @@ var PEEPHOLE = {
4621
4536
  "local.set": (a, b) => Array.isArray(b) && b[0] === "local.get" && b[1] === a ? ["nop"] : null
4622
4537
  };
4623
4538
  var peephole = (ast) => {
4624
- return walkPost2(ast, (node) => {
4539
+ return walkPost(ast, (node) => {
4625
4540
  if (!Array.isArray(node) || node.length !== 3) return;
4626
4541
  const fn = PEEPHOLE[node[0]];
4627
4542
  if (!fn) return;
@@ -4678,7 +4593,7 @@ var globals = (ast) => {
4678
4593
  }
4679
4594
  if (constGlobals.size === 0) return ast;
4680
4595
  const reads = /* @__PURE__ */ new Map();
4681
- walk2(ast, (n) => {
4596
+ walk(ast, (n) => {
4682
4597
  if (!Array.isArray(n)) return;
4683
4598
  const ref = n[1];
4684
4599
  if (typeof ref !== "string" || ref[0] !== "$") return;
@@ -4696,9 +4611,9 @@ var globals = (ast) => {
4696
4611
  if (after <= before) propagate2.add(name2);
4697
4612
  }
4698
4613
  if (propagate2.size === 0) return ast;
4699
- walkPost2(ast, (node) => {
4614
+ walkPost(ast, (node) => {
4700
4615
  if (!Array.isArray(node) || node[0] !== "global.get" || node.length !== 2) return;
4701
- if (propagate2.has(node[1])) return clone2(constGlobals.get(node[1]));
4616
+ if (propagate2.has(node[1])) return clone(constGlobals.get(node[1]));
4702
4617
  });
4703
4618
  for (let i = ast.length - 1; i >= 1; i--) {
4704
4619
  const n = ast[i];
@@ -4707,7 +4622,7 @@ var globals = (ast) => {
4707
4622
  return ast;
4708
4623
  };
4709
4624
  var offset = (ast) => {
4710
- return walkPost2(ast, (node) => {
4625
+ return walkPost(ast, (node) => {
4711
4626
  if (!Array.isArray(node)) return;
4712
4627
  const op = node[0];
4713
4628
  if (typeof op !== "string" || !op.endsWith("load") && !op.endsWith("store")) return;
@@ -4758,7 +4673,7 @@ var offset = (ast) => {
4758
4673
  });
4759
4674
  };
4760
4675
  var unbranch = (ast) => {
4761
- walk2(ast, (node) => {
4676
+ walk(ast, (node) => {
4762
4677
  if (!Array.isArray(node)) return;
4763
4678
  const op = node[0];
4764
4679
  if (op !== "block") return;
@@ -4790,7 +4705,7 @@ var unbranch = (ast) => {
4790
4705
  return ast;
4791
4706
  };
4792
4707
  var loopify = (ast) => {
4793
- walk2(ast, (node) => {
4708
+ walk(ast, (node) => {
4794
4709
  if (!Array.isArray(node) || node[0] !== "block") return;
4795
4710
  let bi = 1, label = null;
4796
4711
  if (typeof node[1] === "string" && node[1][0] === "$") {
@@ -4849,10 +4764,10 @@ var loopify = (ast) => {
4849
4764
  var stripmut = (ast) => {
4850
4765
  if (!Array.isArray(ast) || ast[0] !== "module") return ast;
4851
4766
  const written = /* @__PURE__ */ new Set();
4852
- walk2(ast, (n) => {
4767
+ walk(ast, (n) => {
4853
4768
  if (Array.isArray(n) && n[0] === "global.set" && typeof n[1] === "string") written.add(n[1]);
4854
4769
  });
4855
- return walkPost2(ast, (node) => {
4770
+ return walkPost(ast, (node) => {
4856
4771
  if (!Array.isArray(node) || node[0] !== "global") return;
4857
4772
  const name2 = typeof node[1] === "string" && node[1][0] === "$" ? node[1] : null;
4858
4773
  if (!name2 || written.has(name2)) return;
@@ -4866,7 +4781,7 @@ var stripmut = (ast) => {
4866
4781
  });
4867
4782
  };
4868
4783
  var brif = (ast) => {
4869
- return walkPost2(ast, (node) => {
4784
+ return walkPost(ast, (node) => {
4870
4785
  if (!Array.isArray(node) || node[0] !== "if") return;
4871
4786
  const { cond, thenBranch, elseBranch } = parseIf(node);
4872
4787
  const thenEmpty = !thenBranch || thenBranch.length <= 1;
@@ -4882,7 +4797,7 @@ var brif = (ast) => {
4882
4797
  });
4883
4798
  };
4884
4799
  var foldarms = (ast) => {
4885
- return walkPost2(ast, (node) => {
4800
+ return walkPost(ast, (node) => {
4886
4801
  if (!Array.isArray(node) || node[0] !== "if") return;
4887
4802
  const { thenBranch, elseBranch } = parseIf(node);
4888
4803
  if (!thenBranch || !elseBranch) return;
@@ -4955,7 +4870,7 @@ var dedupe = (ast) => {
4955
4870
  if (!name2) continue;
4956
4871
  const localNames = /* @__PURE__ */ new Set();
4957
4872
  if (typeof node[1] === "string" && node[1][0] === "$") localNames.add(node[1]);
4958
- walk2(node, (n) => {
4873
+ walk(node, (n) => {
4959
4874
  if (!Array.isArray(n) || typeof n[1] !== "string" || n[1][0] !== "$") return;
4960
4875
  const op = n[0];
4961
4876
  if (op === "param" || op === "local" || op === "block" || op === "loop" || op === "if") {
@@ -4970,7 +4885,7 @@ var dedupe = (ast) => {
4970
4885
  }
4971
4886
  }
4972
4887
  if (redirects.size === 0) return ast;
4973
- walkPost2(ast, (node) => {
4888
+ walkPost(ast, (node) => {
4974
4889
  if (!Array.isArray(node)) return;
4975
4890
  const op = node[0];
4976
4891
  if ((op === "call" || op === "return_call") && redirects.has(node[1])) {
@@ -5017,7 +4932,7 @@ var dedupTypes = (ast) => {
5017
4932
  if (name2 && redirects.has(name2)) ast.splice(i, 1);
5018
4933
  }
5019
4934
  }
5020
- walkPost2(ast, (node) => {
4935
+ walkPost(ast, (node) => {
5021
4936
  if (!Array.isArray(node)) return;
5022
4937
  const op = node[0];
5023
4938
  if (op === "func") {
@@ -5244,7 +5159,7 @@ var minifyImports = (ast) => {
5244
5159
  };
5245
5160
  var reorderSafe = (ast) => {
5246
5161
  let safe = true;
5247
- walk2(ast, (n) => {
5162
+ walk(ast, (n) => {
5248
5163
  if (!safe || !Array.isArray(n)) return;
5249
5164
  const op = n[0];
5250
5165
  if (op === "func" && (typeof n[1] !== "string" || n[1][0] !== "$")) safe = false;
@@ -5269,7 +5184,7 @@ var reorder = (ast) => {
5269
5184
  if (!Array.isArray(ast) || ast[0] !== "module") return ast;
5270
5185
  if (!reorderSafe(ast)) return ast;
5271
5186
  const callCounts = /* @__PURE__ */ new Map();
5272
- walk2(ast, (n) => {
5187
+ walk(ast, (n) => {
5273
5188
  if (!Array.isArray(n)) return;
5274
5189
  if (n[0] === "call" || n[0] === "return_call") {
5275
5190
  callCounts.set(n[1], (callCounts.get(n[1]) || 0) + 1);
@@ -5288,6 +5203,47 @@ var reorder = (ast) => {
5288
5203
  funcs.sort((a, b) => (callCounts.get(b[1]) || 0) - (callCounts.get(a[1]) || 0));
5289
5204
  return ["module", ...imports, ...funcs, ...others];
5290
5205
  };
5206
+ var PASSES = [
5207
+ ["stripmut", stripmut, true, "strip mut from never-written globals"],
5208
+ ["globals", globals, true, "propagate immutable global constants"],
5209
+ ["fold", fold, true, "constant folding"],
5210
+ ["identity", identity, true, "remove identity ops (x + 0 \u2192 x)"],
5211
+ ["peephole", peephole, true, "x-x\u21920, x&0\u21920, etc."],
5212
+ ["strength", strength, true, "strength reduction (x * 2 \u2192 x << 1)"],
5213
+ ["branch", branch, true, "simplify constant branches"],
5214
+ ["propagate", propagate, true, "forward-propagate single-use locals & tiny consts (never inflates)"],
5215
+ ["inlineOnce", inlineOnce, true, "inline single-call functions into their lone caller (never duplicates)"],
5216
+ ["inline", inline, false, "inline tiny functions \u2014 can duplicate bodies"],
5217
+ ["offset", offset, true, "fold add+const into load/store offset"],
5218
+ ["unbranch", unbranch, true, "remove redundant br at end of own block"],
5219
+ ["loopify", loopify, true, "collapse block+loop+brif while-idiom into loop+if"],
5220
+ ["brif", brif, true, "if-then-br \u2192 br_if"],
5221
+ ["foldarms", foldarms, false, "merge identical trailing if arms \u2014 can add block wrapper"],
5222
+ ["deadcode", deadcode, true, "eliminate dead code after unreachable/br/return"],
5223
+ ["vacuum", vacuum, true, "remove nops, drop-of-pure, empty branches"],
5224
+ ["mergeBlocks", mergeBlocks, true, "unwrap `(block $L \u2026)` whose label is never targeted"],
5225
+ ["coalesce", coalesceLocals, true, "share local slots between same-type non-overlapping locals"],
5226
+ ["locals", localReuse, true, "remove unused locals"],
5227
+ ["dedupe", dedupe, true, "eliminate duplicate functions"],
5228
+ ["dedupTypes", dedupTypes, true, "merge identical type definitions"],
5229
+ ["packData", packData, true, "trim trailing zeros, merge adjacent data segments"],
5230
+ ["reorder", reorder, false, "put hot functions first \u2014 no AST reduction"],
5231
+ ["treeshake", treeshake, true, "remove unused funcs/globals/types/tables"],
5232
+ ["minifyImports", minifyImports, false, "shorten import names \u2014 enable only when you control the host"]
5233
+ ];
5234
+ var OPTS = Object.fromEntries(PASSES.map((p) => [p[0], p[2]]));
5235
+ var normalize3 = (opts) => {
5236
+ if (opts === false) return {};
5237
+ if (opts !== true && typeof opts !== "string") {
5238
+ const m2 = { ...opts };
5239
+ for (const p of PASSES) if (m2[p[0]] === void 0) m2[p[0]] = p[2];
5240
+ return m2;
5241
+ }
5242
+ const set = typeof opts === "string" ? new Set(opts.split(/\s+/).filter(Boolean)) : null;
5243
+ const m = {};
5244
+ for (const p of PASSES) m[p[0]] = set ? set.has("all") || set.has(p[0]) : p[2];
5245
+ return m;
5246
+ };
5291
5247
  function optimize(ast, opts = true) {
5292
5248
  if (typeof ast === "string") ast = parse_default(ast);
5293
5249
  const strictGuard = opts === true;
@@ -5295,37 +5251,12 @@ function optimize(ast, opts = true) {
5295
5251
  const log = opts.log ? (msg, delta) => opts.log(msg, delta) : () => {
5296
5252
  };
5297
5253
  const verbose = opts.verbose || opts.log;
5298
- ast = clone2(ast);
5254
+ ast = clone(ast);
5299
5255
  let beforeRound = null;
5300
5256
  for (let round = 0; round < 3; round++) {
5301
- beforeRound = clone2(ast);
5257
+ beforeRound = clone(ast);
5302
5258
  const sizeBefore = binarySize(ast);
5303
- if (opts.stripmut) ast = stripmut(ast);
5304
- if (opts.globals) ast = globals(ast);
5305
- if (opts.fold) ast = fold(ast);
5306
- if (opts.identity) ast = identity(ast);
5307
- if (opts.peephole) ast = peephole(ast);
5308
- if (opts.strength) ast = strength(ast);
5309
- if (opts.branch) ast = branch(ast);
5310
- if (opts.propagate) ast = propagate(ast);
5311
- if (opts.inlineOnce) ast = inlineOnce(ast);
5312
- if (opts.inline) ast = inline(ast);
5313
- if (opts.offset) ast = offset(ast);
5314
- if (opts.unbranch) ast = unbranch(ast);
5315
- if (opts.loopify) ast = loopify(ast);
5316
- if (opts.brif) ast = brif(ast);
5317
- if (opts.foldarms) ast = foldarms(ast);
5318
- if (opts.deadcode) ast = deadcode(ast);
5319
- if (opts.vacuum) ast = vacuum(ast);
5320
- if (opts.mergeBlocks) ast = mergeBlocks(ast);
5321
- if (opts.coalesce) ast = coalesceLocals(ast);
5322
- if (opts.locals) ast = localReuse(ast);
5323
- if (opts.dedupe) ast = dedupe(ast);
5324
- if (opts.dedupTypes) ast = dedupTypes(ast);
5325
- if (opts.packData) ast = packData(ast);
5326
- if (opts.reorder) ast = reorder(ast);
5327
- if (opts.treeshake) ast = treeshake(ast);
5328
- if (opts.minifyImports) ast = minifyImports(ast);
5259
+ for (const [key, fn] of PASSES) if (opts[key]) ast = fn(ast);
5329
5260
  if (opts.propagate && (opts.inlineOnce || opts.inline)) ast = propagate(ast);
5330
5261
  const sizeAfter = binarySize(ast);
5331
5262
  const delta = sizeAfter - sizeBefore;
@@ -5343,32 +5274,25 @@ function optimize(ast, opts = true) {
5343
5274
  return ast;
5344
5275
  }
5345
5276
 
5346
- // watr.js
5277
+ // src/template.js
5347
5278
  var PUA = "\uE000";
5348
- var instrType = (op) => {
5349
- if (!op || typeof op !== "string") return null;
5350
- const prefix = op.split(".")[0];
5351
- if (/^[if](32|64)|v128/.test(prefix)) return prefix;
5352
- if (/\.(eq|ne|[lg][te]|eqz)/.test(op)) return "i32";
5353
- if (op === "memory.size" || op === "memory.grow") return "i32";
5354
- return null;
5355
- };
5356
5279
  var exprType = (node, ctx = {}) => {
5357
5280
  if (!Array.isArray(node)) {
5358
5281
  if (typeof node === "string" && node[0] === "$" && ctx.locals?.[node]) return ctx.locals[node];
5359
5282
  return null;
5360
5283
  }
5361
5284
  const [op, ...args] = node;
5362
- if (instrType(op)) return instrType(op);
5285
+ const rt = resultType(op);
5286
+ if (rt) return rt;
5363
5287
  if (op === "local.get" && ctx.locals?.[args[0]]) return ctx.locals[args[0]];
5364
5288
  if (op === "call" && ctx.funcs?.[args[0]]) return ctx.funcs[args[0]].result?.[0];
5365
5289
  return null;
5366
5290
  };
5367
- function walk3(node, fn) {
5291
+ function walk2(node, fn) {
5368
5292
  node = fn(node);
5369
5293
  if (Array.isArray(node)) {
5370
5294
  for (let i = 0; i < node.length; i++) {
5371
- let child = walk3(node[i], fn);
5295
+ let child = walk2(node[i], fn);
5372
5296
  if (child?._splice) node.splice(i, 1, ...child), i += child.length - 1;
5373
5297
  else node[i] = child;
5374
5298
  }
@@ -5378,7 +5302,7 @@ function walk3(node, fn) {
5378
5302
  function inferImports(ast, funcs) {
5379
5303
  const imports = [];
5380
5304
  const importMap = /* @__PURE__ */ new Map();
5381
- walk3(ast, (node) => {
5305
+ walk2(ast, (node) => {
5382
5306
  if (!Array.isArray(node)) return node;
5383
5307
  if (node[0] === "call" && typeof node[1] === "function") {
5384
5308
  const fn = node[1];
@@ -5405,7 +5329,8 @@ function genImports(imports) {
5405
5329
  ({ name: name2, params }) => ["import", '"env"', `"${name2.slice(1)}"`, ["func", name2, ...params.map((t) => ["param", t])]]
5406
5330
  );
5407
5331
  }
5408
- function compile2(source, ...values) {
5332
+ function compile2(backend2, source, values) {
5333
+ const { parse, compile: emit, optimize: optimize2, polyfill: polyfill2 } = backend2;
5409
5334
  let opts = {};
5410
5335
  if (!Array.isArray(source) && values.length && typeof values[values.length - 1] === "object" && values[values.length - 1] !== null && !values[values.length - 1].byteLength) {
5411
5336
  opts = values.pop();
@@ -5415,10 +5340,10 @@ function compile2(source, ...values) {
5415
5340
  for (let i = 0; i < values.length; i++) {
5416
5341
  src += PUA + source[i + 1];
5417
5342
  }
5418
- let ast = parse_default(src);
5343
+ let ast = parse(src);
5419
5344
  const funcsToImport = [];
5420
5345
  let idx = 0;
5421
- ast = walk3(ast, (node) => {
5346
+ ast = walk2(ast, (node) => {
5422
5347
  if (node === PUA) {
5423
5348
  const value = values[idx++];
5424
5349
  if (typeof value === "function") {
@@ -5426,13 +5351,14 @@ function compile2(source, ...values) {
5426
5351
  return value;
5427
5352
  }
5428
5353
  if (typeof value === "string" && (value[0] === "(" || /^\s*\(/.test(value))) {
5429
- const parsed = parse_default(value);
5354
+ const parsed = parse(value);
5430
5355
  if (Array.isArray(parsed) && Array.isArray(parsed[0])) {
5431
5356
  parsed._splice = true;
5432
5357
  }
5433
5358
  return parsed;
5434
5359
  }
5435
- if (value.byteLength !== void 0) return [...value];
5360
+ if (value?.byteLength !== void 0) return [...value];
5361
+ if (typeof value === "bigint") return value.toString();
5436
5362
  return value;
5437
5363
  }
5438
5364
  return node;
@@ -5455,33 +5381,42 @@ function compile2(source, ...values) {
5455
5381
  }
5456
5382
  }
5457
5383
  }
5458
- if (opts.polyfill) ast = polyfill(ast, opts.polyfill);
5459
- if (opts.optimize) ast = optimize(ast, opts.optimize);
5460
- const binary = compile(ast);
5384
+ if (opts.polyfill) ast = polyfill2(ast, opts.polyfill);
5385
+ if (opts.optimize) ast = optimize2(ast, opts.optimize);
5386
+ const binary = emit(ast);
5461
5387
  if (importObjs) binary._imports = importObjs;
5462
5388
  return binary;
5463
5389
  }
5464
5390
  if (opts.polyfill || opts.optimize) {
5465
- let ast = typeof source === "string" ? parse_default(source) : source;
5466
- if (opts.polyfill) ast = polyfill(ast, opts.polyfill);
5467
- if (opts.optimize) ast = optimize(ast, opts.optimize);
5468
- return compile(ast);
5391
+ let ast = typeof source === "string" ? parse(source) : source;
5392
+ if (opts.polyfill) ast = polyfill2(ast, opts.polyfill);
5393
+ if (opts.optimize) ast = optimize2(ast, opts.optimize);
5394
+ return emit(ast);
5469
5395
  }
5470
- return compile(source);
5396
+ return emit(source);
5471
5397
  }
5472
- function watr(strings, ...values) {
5473
- const binary = compile2(strings, ...values);
5398
+ function watr(backend2, source, values) {
5399
+ const binary = compile2(backend2, source, values);
5474
5400
  const module = new WebAssembly.Module(binary);
5475
5401
  const instance = new WebAssembly.Instance(module, binary._imports);
5476
5402
  return instance.exports;
5477
5403
  }
5478
- var watr_default = watr;
5404
+
5405
+ // watr.js
5406
+ var backend = { parse: parse_default, compile, optimize, polyfill };
5407
+ function compile3(source, ...values) {
5408
+ return compile2(backend, source, values);
5409
+ }
5410
+ function watr2(source, ...values) {
5411
+ return watr(backend, source, values);
5412
+ }
5413
+ var watr_default = watr2;
5479
5414
  export {
5480
- compile2 as compile,
5415
+ compile3 as compile,
5481
5416
  watr_default as default,
5482
5417
  optimize,
5483
5418
  parse_default as parse,
5484
5419
  polyfill,
5485
5420
  print,
5486
- watr
5421
+ watr2 as watr
5487
5422
  };