Encode the WASM as base64

Some nasty hackery to get around the nastiness of the JS ecosystem
This commit is contained in:
Richard van der Hoff
2022-10-31 22:29:38 +00:00
parent 471ac07c88
commit 093856671a
3 changed files with 82 additions and 5 deletions

View File

@@ -37,12 +37,9 @@
"node": ">= 10"
},
"scripts": {
"build": "cross-env RUSTFLAGS='-C opt-level=z' WASM_BINDGEN_WEAKREF=1 wasm-pack build --release --target nodejs --scope matrix-org --out-dir ./pkg",
"build": "./scripts/build.sh",
"test": "jest --verbose",
"doc": "typedoc --tsconfig .",
"prepack": "npm run build && npm run test",
"pack": "wasm-pack pack",
"prepublish": "npm run pack",
"publish": "wasm-pack publish"
"prepack": "npm run build && npm run test"
}
}

View File

@@ -0,0 +1,32 @@
#!/bin/bash
#
# Build the javascript modules
#
# This script is really a workaround for https://github.com/rustwasm/wasm-pack/issues/1074.
#
# Currently, the only reliable way to load webassembly in all the JS
# environments we want to target (web-via-webpack, web-via-browserify, jest)
# seems to be to pack the WASM into base64, and then unpack it and instantiate
# it at runtime.
#
# Hopefully one day, https://github.com/rustwasm/wasm-pack/issues/1074 will be
# fixed and this will be unnecessary.
set -e
RUSTFLAGS='-C opt-level=z' WASM_BINDGEN_WEAKREF=1 wasm-pack build --release --target nodejs --scope matrix-org --out-dir ./pkg
# convert the wasm into a js file that exports the b64'ed wasm
{
echo 'module.exports = `'
base64 pkg/matrix_sdk_crypto_js_bg.wasm
echo '`;'
} > pkg/matrix_sdk_crypto_js_bg.wasm.js
# In the javascript:
# 1. replace the lines that load the wasm
# 2. remove the imports of TextDecoder and TextEncoder. We rely on the global defaults.
loadwasm='const bytes = require("../unbase64.js")(require("./matrix_sdk_crypto_js_bg.wasm.js"));'
sed -i -e "/^const path = /,+1 c$loadwasm" \
-e '/= require(`util`)/d' \
pkg/matrix_sdk_crypto_js.js

View File

@@ -0,0 +1,48 @@
// Javascript module which exports a function which will un-base64 a string
//
// From the code at https://developer.mozilla.org/en-US/docs/Glossary/Base64#solution_2_%E2%80%93_rewriting_atob_and_btoa_using_typedarrays_and_utf-8
function b64ToUint6(nChr) {
return nChr > 64 && nChr < 91
? nChr - 65
: nChr > 96 && nChr < 123
? nChr - 71
: nChr > 47 && nChr < 58
? nChr + 4
: nChr === 43
? 62
: nChr === 47
? 63
: 0;
}
function base64DecToArr(sBase64, nBlocksSize) {
const sB64Enc = sBase64.replace(/[^A-Za-z0-9+/]/g, "");
const nInLen = sB64Enc.length;
const nOutLen = nBlocksSize
? Math.ceil(((nInLen * 3 + 1) >> 2) / nBlocksSize) * nBlocksSize
: (nInLen * 3 + 1) >> 2;
const taBytes = new Uint8Array(nOutLen);
let nMod3;
let nMod4;
let nUint24 = 0;
let nOutIdx = 0;
for (let nInIdx = 0; nInIdx < nInLen; nInIdx++) {
nMod4 = nInIdx & 3;
nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << (6 * (3 - nMod4));
if (nMod4 === 3 || nInLen - nInIdx === 1) {
nMod3 = 0;
while (nMod3 < 3 && nOutIdx < nOutLen) {
taBytes[nOutIdx] = (nUint24 >>> ((16 >>> nMod3) & 24)) & 255;
nMod3++;
nOutIdx++;
}
nUint24 = 0;
}
}
return taBytes;
}
module.exports = base64DecToArr;