watr 4.3.1 → 4.3.4

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
@@ -14,7 +14,8 @@ __export(encode_exports, {
14
14
  i64: () => i64,
15
15
  i8: () => i8,
16
16
  uleb: () => uleb,
17
- uleb5: () => uleb5
17
+ uleb5: () => uleb5,
18
+ v128: () => v128
18
19
  });
19
20
 
20
21
  // src/util.js
@@ -116,7 +117,8 @@ i32.parse = (n) => {
116
117
  };
117
118
  function i64(n, buffer = []) {
118
119
  if (typeof n === "string") n = i64.parse(n);
119
- else if (typeof n === "bigint" && n > 0x7fffffffffffffffn) {
120
+ else if (typeof n === "number") n = BigInt(n);
121
+ if (typeof n === "bigint" && n > 0x7fffffffffffffffn) {
120
122
  n = n - 0x10000000000000000n;
121
123
  }
122
124
  while (true) {
@@ -130,14 +132,19 @@ function i64(n, buffer = []) {
130
132
  }
131
133
  return buffer;
132
134
  }
135
+ var _buf = new ArrayBuffer(8);
136
+ var _u8 = new Uint8Array(_buf);
137
+ var _i32 = new Int32Array(_buf);
138
+ var _f32 = new Float32Array(_buf);
139
+ var _f64 = new Float64Array(_buf);
140
+ var _i64 = new BigInt64Array(_buf);
133
141
  i64.parse = (n) => {
134
142
  n = cleanInt(n);
135
143
  n = n[0] === "-" ? -BigInt(n.slice(1)) : BigInt(n);
136
144
  if (n < -0x8000000000000000n || n > 0xffffffffffffffffn) err(`i64 constant out of range`);
137
- byteView.setBigInt64(0, n);
138
- return byteView.getBigInt64(0);
145
+ _i64[0] = n;
146
+ return _i64[0];
139
147
  };
140
- var byteView = new DataView(new Float64Array(1).buffer);
141
148
  var F32_SIGN = 2147483648;
142
149
  var F32_NAN = 2139095040;
143
150
  function f32(input, value, idx) {
@@ -145,17 +152,12 @@ function f32(input, value, idx) {
145
152
  value = i32.parse(input.slice(idx + 4));
146
153
  value |= F32_NAN;
147
154
  if (input[0] === "-") value |= F32_SIGN;
148
- byteView.setInt32(0, value);
155
+ _i32[0] = value;
149
156
  } else {
150
157
  value = typeof input === "string" ? f32.parse(input) : input;
151
- byteView.setFloat32(0, value);
158
+ _f32[0] = value;
152
159
  }
153
- return [
154
- byteView.getUint8(3),
155
- byteView.getUint8(2),
156
- byteView.getUint8(1),
157
- byteView.getUint8(0)
158
- ];
160
+ return [_u8[0], _u8[1], _u8[2], _u8[3]];
159
161
  }
160
162
  var F64_SIGN = 0x8000000000000000n;
161
163
  var F64_NAN = 0x7ff0000000000000n;
@@ -164,21 +166,12 @@ function f64(input, value, idx) {
164
166
  value = i64.parse(input.slice(idx + 4));
165
167
  value |= F64_NAN;
166
168
  if (input[0] === "-") value |= F64_SIGN;
167
- byteView.setBigInt64(0, value);
169
+ _i64[0] = value;
168
170
  } else {
169
171
  value = typeof input === "string" ? f64.parse(input) : input;
170
- byteView.setFloat64(0, value);
172
+ _f64[0] = value;
171
173
  }
172
- return [
173
- byteView.getUint8(7),
174
- byteView.getUint8(6),
175
- byteView.getUint8(5),
176
- byteView.getUint8(4),
177
- byteView.getUint8(3),
178
- byteView.getUint8(2),
179
- byteView.getUint8(1),
180
- byteView.getUint8(0)
181
- ];
174
+ return [_u8[0], _u8[1], _u8[2], _u8[3], _u8[4], _u8[5], _u8[6], _u8[7]];
182
175
  }
183
176
  f64.parse = (input, max = Number.MAX_VALUE) => {
184
177
  input = input.replaceAll("_", "");
@@ -202,6 +195,12 @@ f64.parse = (input, max = Number.MAX_VALUE) => {
202
195
  return sign * parseFloat(input);
203
196
  };
204
197
  f32.parse = (input) => f64.parse(input, 34028234663852886e22);
198
+ var v128 = (input) => {
199
+ let n = typeof input === "string" ? BigInt(input.replaceAll("_", "")) : BigInt(input);
200
+ let arr = new Uint8Array(16);
201
+ for (let i = 0; i < 16; i++) arr[i] = Number(n & 0xffn), n >>= 8n;
202
+ return [...arr];
203
+ };
205
204
 
206
205
  // src/const.js
207
206
  var INSTR = [
@@ -1765,7 +1764,7 @@ var IMM = {
1765
1764
  i64: (n) => i64(n.shift()),
1766
1765
  f32: (n) => f32(n.shift()),
1767
1766
  f64: (n) => f64(n.shift()),
1768
- v128: (n) => (void 0)(n.shift()),
1767
+ v128: (n) => v128(n.shift()),
1769
1768
  // Combinations
1770
1769
  typeidx_field: (n, c) => {
1771
1770
  let typeId = id(n.shift(), c.type);
@@ -3085,6 +3084,7 @@ var treeshake = (ast) => {
3085
3084
  }
3086
3085
  return result;
3087
3086
  };
3087
+ var roundEven = (x) => x - Math.floor(x) !== 0.5 ? Math.round(x) : 2 * Math.round(x / 2);
3088
3088
  var FOLDABLE = {
3089
3089
  // i32
3090
3090
  "i32.add": (a, b) => a + b | 0,
@@ -3168,7 +3168,7 @@ var FOLDABLE = {
3168
3168
  "f32.ceil": (a) => Math.fround(Math.ceil(a)),
3169
3169
  "f32.floor": (a) => Math.fround(Math.floor(a)),
3170
3170
  "f32.trunc": (a) => Math.fround(Math.trunc(a)),
3171
- "f32.nearest": (a) => Math.fround(Math.round(a)),
3171
+ "f32.nearest": (a) => Math.fround(roundEven(a)),
3172
3172
  "f64.add": (a, b) => a + b,
3173
3173
  "f64.sub": (a, b) => a - b,
3174
3174
  "f64.mul": (a, b) => a * b,
@@ -3179,7 +3179,7 @@ var FOLDABLE = {
3179
3179
  "f64.ceil": (a) => Math.ceil(a),
3180
3180
  "f64.floor": (a) => Math.floor(a),
3181
3181
  "f64.trunc": (a) => Math.trunc(a),
3182
- "f64.nearest": (a) => Math.round(a)
3182
+ "f64.nearest": roundEven
3183
3183
  };
3184
3184
  var getConst = (node) => {
3185
3185
  if (!Array.isArray(node) || node.length !== 2) return null;
@@ -3489,7 +3489,7 @@ var localReuse = (ast) => {
3489
3489
  const sub = node[i];
3490
3490
  if (!Array.isArray(sub)) continue;
3491
3491
  if (sub[0] === "local") {
3492
- localDecls.push({ idx: i, node: sub });
3492
+ localDecls.push({ node: sub, idx: i });
3493
3493
  if (typeof sub[1] === "string" && sub[1][0] === "$") {
3494
3494
  localTypes.set(sub[1], sub[2]);
3495
3495
  }
@@ -3519,55 +3519,101 @@ var localReuse = (ast) => {
3519
3519
  });
3520
3520
  return result;
3521
3521
  };
3522
+ var isPure = (node) => {
3523
+ if (!Array.isArray(node)) return true;
3524
+ const op = node[0];
3525
+ if (typeof op !== "string") return false;
3526
+ if (op === "call" || op === "call_indirect" || op === "return_call" || op === "return_call_indirect") return false;
3527
+ if (op.includes(".store") || op.includes(".load") || op.includes("memory.")) return false;
3528
+ if (op === "global.set") return false;
3529
+ for (let i = 1; i < node.length; i++) if (Array.isArray(node[i]) && !isPure(node[i])) return false;
3530
+ return true;
3531
+ };
3532
+ var countLocalUses = (node) => {
3533
+ const counts = /* @__PURE__ */ new Map();
3534
+ const ensure = (name2) => {
3535
+ if (!counts.has(name2)) counts.set(name2, { gets: 0, sets: 0, tees: 0 });
3536
+ return counts.get(name2);
3537
+ };
3538
+ walk2(node, (n) => {
3539
+ if (!Array.isArray(n) || n.length < 2 || typeof n[1] !== "string") return;
3540
+ if (n[0] === "local.get") ensure(n[1]).gets++;
3541
+ else if (n[0] === "local.set") ensure(n[1]).sets++;
3542
+ else if (n[0] === "local.tee") ensure(n[1]).tees++;
3543
+ });
3544
+ return counts;
3545
+ };
3546
+ var canSubst = (k) => getConst(k.val) || k.pure && k.singleUse;
3547
+ var substGets = (node, known) => walkPost2(node, (n) => {
3548
+ if (!Array.isArray(n) || n[0] !== "local.get" || n.length !== 2) return;
3549
+ const k = typeof n[1] === "string" && known.get(n[1]);
3550
+ if (k && canSubst(k)) return clone2(k.val);
3551
+ });
3522
3552
  var propagate = (ast) => {
3523
3553
  const result = clone2(ast);
3524
- walk2(result, (node) => {
3525
- if (!Array.isArray(node) || node[0] !== "func") return;
3526
- const constLocals = /* @__PURE__ */ new Map();
3527
- const processBlock = (block, startIdx = 1) => {
3528
- for (let i = startIdx; i < block.length; i++) {
3529
- const instr2 = block[i];
3554
+ walk2(result, (funcNode) => {
3555
+ if (!Array.isArray(funcNode) || funcNode[0] !== "func") return;
3556
+ const params = /* @__PURE__ */ new Set();
3557
+ for (const sub of funcNode)
3558
+ if (Array.isArray(sub) && sub[0] === "param" && typeof sub[1] === "string") params.add(sub[1]);
3559
+ for (let pass = 0; pass < 4; pass++) {
3560
+ let changed = false;
3561
+ const uses = countLocalUses(funcNode);
3562
+ const getUses = (name2) => uses.get(name2) || { gets: 0, sets: 0, tees: 0 };
3563
+ const known = /* @__PURE__ */ new Map();
3564
+ for (let i = 1; i < funcNode.length; i++) {
3565
+ const instr2 = funcNode[i];
3530
3566
  if (!Array.isArray(instr2)) continue;
3531
3567
  const op = instr2[0];
3532
- if (op === "local.set" && instr2.length === 3) {
3533
- const local = instr2[1];
3534
- const val = instr2[2];
3535
- const c = getConst(val);
3536
- if (c && typeof local === "string") {
3537
- constLocals.set(local, val);
3538
- } else if (typeof local === "string") {
3539
- constLocals.delete(local);
3540
- }
3541
- } else if (op === "local.tee" && instr2.length === 3) {
3542
- const local = instr2[1];
3543
- const val = instr2[2];
3544
- const c = getConst(val);
3545
- if (c && typeof local === "string") {
3546
- constLocals.set(local, val);
3547
- } else if (typeof local === "string") {
3548
- constLocals.delete(local);
3549
- }
3550
- } else if (op === "local.get" && instr2.length === 2) {
3551
- const local = instr2[1];
3552
- if (typeof local === "string" && constLocals.has(local)) {
3553
- const constVal = constLocals.get(local);
3568
+ if (op === "param" || op === "result" || op === "local" || op === "type" || op === "export") continue;
3569
+ if (op === "local.set" && instr2.length === 3 && typeof instr2[1] === "string") {
3570
+ substGets(instr2[2], known);
3571
+ const u = getUses(instr2[1]);
3572
+ known.set(instr2[1], {
3573
+ val: instr2[2],
3574
+ pure: isPure(instr2[2]),
3575
+ singleUse: u.gets <= 1 && u.sets <= 1 && u.tees === 0
3576
+ });
3577
+ continue;
3578
+ }
3579
+ if (op === "block" || op === "loop" || op === "if") known.clear();
3580
+ if (op === "call" || op === "call_indirect" || op === "return_call" || op === "return_call_indirect") {
3581
+ for (const [k, v] of known) if (!getConst(v.val)) known.delete(k);
3582
+ }
3583
+ if (op === "local.get" && instr2.length === 2 && typeof instr2[1] === "string") {
3584
+ const k = known.get(instr2[1]);
3585
+ if (k && canSubst(k)) {
3586
+ const r = clone2(k.val);
3554
3587
  instr2.length = 0;
3555
- instr2.push(...clone2(constVal));
3588
+ instr2.push(...Array.isArray(r) ? r : [r]);
3589
+ changed = true;
3590
+ continue;
3556
3591
  }
3557
- } else if (op === "block" || op === "loop" || op === "if" || op === "call" || op === "call_indirect") {
3558
- constLocals.clear();
3559
3592
  }
3560
- walkPost2(instr2, (n) => {
3561
- if (!Array.isArray(n) || n[0] !== "local.get" || n.length !== 2) return;
3562
- const local = n[1];
3563
- if (typeof local === "string" && constLocals.has(local)) {
3564
- const constVal = constLocals.get(local);
3565
- return clone2(constVal);
3566
- }
3567
- });
3593
+ if (op !== "block" && op !== "loop" && op !== "if") {
3594
+ const prev = JSON.stringify(instr2);
3595
+ substGets(instr2, known);
3596
+ if (JSON.stringify(instr2) !== prev) changed = true;
3597
+ }
3568
3598
  }
3569
- };
3570
- processBlock(node);
3599
+ const postUses = countLocalUses(funcNode);
3600
+ const pu = (name2) => postUses.get(name2) || { gets: 0, sets: 0, tees: 0 };
3601
+ for (let i = funcNode.length - 1; i >= 1; i--) {
3602
+ const sub = funcNode[i];
3603
+ if (!Array.isArray(sub)) continue;
3604
+ const name2 = typeof sub[1] === "string" ? sub[1] : null;
3605
+ if (!name2 || params.has(name2)) continue;
3606
+ const u = pu(name2);
3607
+ if (sub[0] === "local.set" && u.gets === 0 && u.tees === 0 && isPure(sub[2])) {
3608
+ funcNode.splice(i, 1);
3609
+ changed = true;
3610
+ } else if (sub[0] === "local" && name2[0] === "$" && u.gets === 0 && u.sets === 0 && u.tees === 0) {
3611
+ funcNode.splice(i, 1);
3612
+ changed = true;
3613
+ }
3614
+ }
3615
+ if (!changed) break;
3616
+ }
3571
3617
  });
3572
3618
  return result;
3573
3619
  };
@@ -3718,7 +3764,7 @@ function genImports(imports) {
3718
3764
  }
3719
3765
  function compile2(source, ...values) {
3720
3766
  let opts = {};
3721
- if (!Array.isArray(source) && values.length && typeof values[values.length - 1] === "object" && values[values.length - 1] !== null && !(values[values.length - 1] instanceof Uint8Array)) {
3767
+ if (!Array.isArray(source) && values.length && typeof values[values.length - 1] === "object" && values[values.length - 1] !== null && !values[values.length - 1].byteLength) {
3722
3768
  opts = values.pop();
3723
3769
  }
3724
3770
  if (Array.isArray(source) && source.raw) {
@@ -3743,7 +3789,7 @@ function compile2(source, ...values) {
3743
3789
  }
3744
3790
  return parsed;
3745
3791
  }
3746
- if (value instanceof Uint8Array) return [...value];
3792
+ if (value.byteLength !== void 0) return [...value];
3747
3793
  return value;
3748
3794
  }
3749
3795
  return node;