Skip to content

Commit

Permalink
fix: Init WASM modules using Base64 (#2913)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
FrederikBolding authored Nov 28, 2024
1 parent 03cd5d6 commit 0fe7eda
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 6 deletions.
2 changes: 1 addition & 1 deletion packages/examples/packages/wasm/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
"shasum": "1LptzjDvA6o8jrzA9XsE7NYdhh7kx3alSd7pLwiUq0w=",
"shasum": "t4uK/pnTJODpftadTGKumNIEqmSCTP0zb87aMLMqFt8=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
13 changes: 12 additions & 1 deletion packages/snaps-cli/src/webpack/loaders/wasm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,18 @@ describe('loader', () => {
"
import { add } from "../src/bindings.ts";
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]);
const b64 = "AGFzbQEAAAABDAJgAn9/AX9gAX8BfwIaARIuLi9zcmMvYmluZGluZ3MudHMDYWRkAAADAgEBBQMBAAAHFgIJZmlib25hY2NpAAEGbWVtb3J5AgAKNgE0AQN/QQEhASAAQQBKBEADQCAAQQFrIgAEQCACIAEQACEDIAEhAiADIQEMAQsLIAEPC0EACw==";
function decode(encoded) {
const str = atob(encoded);
const bytes = new Uint8Array(str.length);
for (let i = 0; i < str.length; i++) {
bytes[i] = str.charCodeAt(i);
}
return bytes;
}
const bytes = decode(b64);
const module = new WebAssembly.Module(bytes);
const instance = new WebAssembly.Instance(module, {
"../src/bindings.ts": { add },
Expand Down
18 changes: 14 additions & 4 deletions packages/snaps-cli/src/webpack/loaders/wasm.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable no-restricted-globals */

import { assert } from '@metamask/utils';
import { assert, bytesToBase64 } from '@metamask/utils';
import { dirname, resolve } from 'path';
import type { LoaderDefinitionFunction } from 'webpack';

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

const bytes = new Uint8Array(source);
const wasmModule = await WebAssembly.compile(bytes);
const wasmModule = await WebAssembly.compile(source);

// eslint-disable-next-line @typescript-eslint/no-shadow
const exports = WebAssembly.Module.exports(wasmModule);
Expand All @@ -104,7 +103,18 @@ const loader: LoaderDefinitionFunction = async function loader(
return `
${getImports(imports)}
const bytes = new Uint8Array(${JSON.stringify(Array.from(source))});
const b64 = ${JSON.stringify(bytesToBase64(source))};
function decode(encoded) {
const str = atob(encoded);
const bytes = new Uint8Array(str.length);
for (let i = 0; i < str.length; i++) {
bytes[i] = str.charCodeAt(i);
}
return bytes;
}
const bytes = decode(b64);
const module = new WebAssembly.Module(bytes);
const instance = new WebAssembly.Instance(module, {
${getModuleImports(imports)}
Expand Down

0 comments on commit 0fe7eda

Please sign in to comment.