Skip to content

Commit 0fe7eda

Browse files
fix: Init WASM modules using Base64 (#2913)
This PR changes the WASM loader slightly to package the WASM source code using Base64 and decode it at runtime. This has multiple effects: - Fixes an obscure OOM bug in Firefox that would only occur on Mac OS (possibly due to extremely large arrays?) - Reduces bundle size for Snaps that leverage WASM - Prevents bundler slowdown due to large arrays needing to be parsed by Babel This adds minor overhead to initializing WASM bundles, but this seems worth it given the effects above.
1 parent 03cd5d6 commit 0fe7eda

File tree

3 files changed

+27
-6
lines changed

3 files changed

+27
-6
lines changed

packages/examples/packages/wasm/snap.manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"url": "https://github.com/MetaMask/snaps.git"
88
},
99
"source": {
10-
"shasum": "1LptzjDvA6o8jrzA9XsE7NYdhh7kx3alSd7pLwiUq0w=",
10+
"shasum": "t4uK/pnTJODpftadTGKumNIEqmSCTP0zb87aMLMqFt8=",
1111
"location": {
1212
"npm": {
1313
"filePath": "dist/bundle.js",

packages/snaps-cli/src/webpack/loaders/wasm.test.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,18 @@ describe('loader', () => {
7373
"
7474
import { add } from "../src/bindings.ts";
7575
76-
const bytes = new Uint8Array([0,97,115,109,1,0,0,0,1,12,2,96,2,127,127,1,127,96,1,127,1,127,2,26,1,18,46,46,47,115,114,99,47,98,105,110,100,105,110,103,115,46,116,115,3,97,100,100,0,0,3,2,1,1,5,3,1,0,0,7,22,2,9,102,105,98,111,110,97,99,99,105,0,1,6,109,101,109,111,114,121,2,0,10,54,1,52,1,3,127,65,1,33,1,32,0,65,0,74,4,64,3,64,32,0,65,1,107,34,0,4,64,32,2,32,1,16,0,33,3,32,1,33,2,32,3,33,1,12,1,11,11,32,1,15,11,65,0,11]);
76+
const b64 = "AGFzbQEAAAABDAJgAn9/AX9gAX8BfwIaARIuLi9zcmMvYmluZGluZ3MudHMDYWRkAAADAgEBBQMBAAAHFgIJZmlib25hY2NpAAEGbWVtb3J5AgAKNgE0AQN/QQEhASAAQQBKBEADQCAAQQFrIgAEQCACIAEQACEDIAEhAiADIQEMAQsLIAEPC0EACw==";
77+
78+
function decode(encoded) {
79+
const str = atob(encoded);
80+
const bytes = new Uint8Array(str.length);
81+
for (let i = 0; i < str.length; i++) {
82+
bytes[i] = str.charCodeAt(i);
83+
}
84+
return bytes;
85+
}
86+
87+
const bytes = decode(b64);
7788
const module = new WebAssembly.Module(bytes);
7889
const instance = new WebAssembly.Instance(module, {
7990
"../src/bindings.ts": { add },

packages/snaps-cli/src/webpack/loaders/wasm.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable no-restricted-globals */
22

3-
import { assert } from '@metamask/utils';
3+
import { assert, bytesToBase64 } from '@metamask/utils';
44
import { dirname, resolve } from 'path';
55
import type { LoaderDefinitionFunction } from 'webpack';
66

@@ -80,8 +80,7 @@ const loader: LoaderDefinitionFunction = async function loader(
8080
) {
8181
assert(source instanceof Uint8Array, 'Expected source to be a Uint8Array.');
8282

83-
const bytes = new Uint8Array(source);
84-
const wasmModule = await WebAssembly.compile(bytes);
83+
const wasmModule = await WebAssembly.compile(source);
8584

8685
// eslint-disable-next-line @typescript-eslint/no-shadow
8786
const exports = WebAssembly.Module.exports(wasmModule);
@@ -104,7 +103,18 @@ const loader: LoaderDefinitionFunction = async function loader(
104103
return `
105104
${getImports(imports)}
106105
107-
const bytes = new Uint8Array(${JSON.stringify(Array.from(source))});
106+
const b64 = ${JSON.stringify(bytesToBase64(source))};
107+
108+
function decode(encoded) {
109+
const str = atob(encoded);
110+
const bytes = new Uint8Array(str.length);
111+
for (let i = 0; i < str.length; i++) {
112+
bytes[i] = str.charCodeAt(i);
113+
}
114+
return bytes;
115+
}
116+
117+
const bytes = decode(b64);
108118
const module = new WebAssembly.Module(bytes);
109119
const instance = new WebAssembly.Instance(module, {
110120
${getModuleImports(imports)}

0 commit comments

Comments
 (0)