From 059dd8e84ecf23bfd088500022f71d24904da133 Mon Sep 17 00:00:00 2001 From: 0x009922 <43530070+0x009922@users.noreply.github.com> Date: Thu, 13 Mar 2025 10:35:12 +0900 Subject: [PATCH] fix(core): inline .wasm Signed-off-by: 0x009922 <43530070+0x009922@users.noreply.github.com> --- crypto-wasm/Cargo.lock | 1 - crypto-wasm/Cargo.toml | 15 ++++------- crypto-wasm/src/lib.rs | 11 ++++---- crypto-wasm/src/utils.rs | 11 -------- etc/task-prep-crypto-wasm.ts | 22 +++++++++++++--- packages/core/crypto/mod.ts | 2 +- packages/core/crypto/util.ts | 2 +- packages/core/crypto/wasm.js | 51 ------------------------------------ 8 files changed, 31 insertions(+), 84 deletions(-) delete mode 100644 packages/core/crypto/wasm.js diff --git a/crypto-wasm/Cargo.lock b/crypto-wasm/Cargo.lock index cbb5e7f6..365bc32e 100644 --- a/crypto-wasm/Cargo.lock +++ b/crypto-wasm/Cargo.lock @@ -717,7 +717,6 @@ dependencies = [ name = "iroha_crypto_wasm" version = "0.2.0" dependencies = [ - "console_error_panic_hook", "getrandom", "hex", "iroha_crypto", diff --git a/crypto-wasm/Cargo.toml b/crypto-wasm/Cargo.toml index cfd7a7ae..87faed18 100644 --- a/crypto-wasm/Cargo.toml +++ b/crypto-wasm/Cargo.toml @@ -7,9 +7,6 @@ edition = "2021" [lib] crate-type = ["cdylib", "rlib"] -[features] -default = ["console_error_panic_hook"] - [dependencies] # iroha_crypto = { path = "../.iroha/crates/iroha_crypto", default-features = false, features = ["rand"] } iroha_crypto = { git = "https://github.com/hyperledger-iroha/iroha.git", rev = "daa2d50fbe288aed1231c6f45c853698435477d6", default-features = false, features = ["rand"] } @@ -21,18 +18,16 @@ serde = { version = "1", default-features = false, features = ["derive"] } serde-wasm-bindgen = "0.6" hex = { version = "0.4", default-features = false, features = ["alloc"] } -# The `console_error_panic_hook` crate provides better debugging of panics by -# logging them with `console.error`. This is great for development, but requires -# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for -# code size when deploying. -console_error_panic_hook = { version = "0.1", optional = true } - # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size # compared to the default allocator's ~10K. It is slower than the default # allocator, however. # # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. -wee_alloc = { version = "0.4.5", optional = true } +wee_alloc = { version = "0.4.5" } + +[profile.release] +opt-level = "z" +lto = true [dev-dependencies] wasm-bindgen-test = "0.3.13" diff --git a/crypto-wasm/src/lib.rs b/crypto-wasm/src/lib.rs index e88f1191..eb2f2e7d 100644 --- a/crypto-wasm/src/lib.rs +++ b/crypto-wasm/src/lib.rs @@ -5,6 +5,12 @@ extern crate alloc; +extern crate wee_alloc; + +// Use `wee_alloc` as the global allocator. +#[global_allocator] +static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; + mod utils; use alloc::string::ToString; @@ -327,8 +333,3 @@ impl TryFrom> for VerifyResultJs { Ok(Self { obj: js_value }) } } - -#[wasm_bindgen(start)] -pub fn main_js() { - utils::set_panic_hook(); -} diff --git a/crypto-wasm/src/utils.rs b/crypto-wasm/src/utils.rs index e33b0db1..a4902277 100644 --- a/crypto-wasm/src/utils.rs +++ b/crypto-wasm/src/utils.rs @@ -4,17 +4,6 @@ use core::fmt::Display; use wasm_bindgen::prelude::*; -pub fn set_panic_hook() { - // When the `console_error_panic_hook` feature is enabled, we can call the - // `set_panic_hook` function at least once during initialization, and then - // we will get better error messages if our code ever panics. - // - // For more details see - // https://github.com/rustwasm/console_error_panic_hook#readme - #[cfg(feature = "console_error_panic_hook")] - console_error_panic_hook::set_once(); -} - pub trait JsErrorResultExt { fn wrap_js_error(self) -> Result; } diff --git a/etc/task-prep-crypto-wasm.ts b/etc/task-prep-crypto-wasm.ts index 51d0cf45..063a44b6 100644 --- a/etc/task-prep-crypto-wasm.ts +++ b/etc/task-prep-crypto-wasm.ts @@ -12,13 +12,15 @@ const PREP_DIR = resolveFromRoot('prep/crypto-wasm') console.log(PROJECT_DIR) const CRATE_NAME = 'iroha_crypto_wasm' +const GENERATED_FILES = new Set([`.d.ts`, '.internal.js', '.js'].map((x) => `${CRATE_NAME}${x}`)) + async function buildWasm() { const outDir = PREP_DIR console.log(' ' + colors.yellow(`empty ${pathRel(PREP_DIR)}`)) await emptyDir(PREP_DIR) $.logStep(`Building with @deno/wasmbuild...`) - await $`deno run -A jsr:@deno/wasmbuild --out ${outDir}`.cwd(PROJECT_DIR) + await $`deno run -A jsr:@deno/wasmbuild@0.19.1 --out ${outDir} --inline`.cwd(PROJECT_DIR) console.log(` ${colors.yellow(`write ${pathRel(outDir)}`)}`) } @@ -29,7 +31,7 @@ async function checkBuildReady() { assert(i.isFile) files.add(i.name) } - assertEquals(files, new Set([`.d.ts`, '.internal.js', '.js', '.wasm'].map((x) => `${CRATE_NAME}${x}`))) + assertEquals(files, GENERATED_FILES) return true } catch (err) { $.logWarn('Error whiule checking build artifacts:', err) @@ -37,19 +39,31 @@ async function checkBuildReady() { } } +function patchWasmJsWrapCode(code: string): string { + return code.replace(/(__wbg_set_wasm\(wasm.exports\))/, '$1\nwasm.exports.__wbindgen_start()') +} + +async function patchWasmJsWrap(file: string) { + const content = await Deno.readTextFile(file) + const patched = patchWasmJsWrapCode(content) + await Deno.writeTextFile(file, patched) +} + async function copyOutputs() { const targetDir = resolveFromRoot('packages/core/crypto/wasm') - const files = [`${CRATE_NAME}.d.ts`, `${CRATE_NAME}.wasm`, `${CRATE_NAME}.internal.js`] console.log(' ' + colors.yellow(`empty ${pathRel(targetDir)}`)) await emptyDir(targetDir) - for (const i of files) { + for (const i of GENERATED_FILES) { const src = resolveFromRoot(PREP_DIR, i) const dest = path.join(targetDir, i) console.log(` ${colors.yellow(`write ${pathRel(dest)}`)}`) await copy(src, dest) } + + // https://github.com/denoland/wasmbuild/issues/156 + await patchWasmJsWrap(path.join(targetDir, `${CRATE_NAME}.js`)) } const args = parseArgs(Deno.args, { diff --git a/packages/core/crypto/mod.ts b/packages/core/crypto/mod.ts index 3cd92774..fbe57d6a 100644 --- a/packages/core/crypto/mod.ts +++ b/packages/core/crypto/mod.ts @@ -58,7 +58,7 @@ import { enumCodec, GenCodec, structCodec } from '../codec.ts' import * as scale from '@scale-codec/core' import { assert } from '@std/assert/assert' import { BytesVec } from '../data-model/primitives.ts' -import * as wasm from './wasm.js' +import * as wasm from './wasm/iroha_crypto_wasm.js' export { Bytes } export type VerifyResult = wasm.VerifyResult diff --git a/packages/core/crypto/util.ts b/packages/core/crypto/util.ts index cac4721c..e431ed27 100644 --- a/packages/core/crypto/util.ts +++ b/packages/core/crypto/util.ts @@ -1,5 +1,5 @@ import { decodeHex, encodeHex } from '@std/encoding/hex' -import type { Bytes as WasmBytes } from './wasm.js' +import type { Bytes as WasmBytes } from './wasm/iroha_crypto_wasm.js' /** * Helper to work with binary data passed into the WASM diff --git a/packages/core/crypto/wasm.js b/packages/core/crypto/wasm.js deleted file mode 100644 index 3e768d77..00000000 --- a/packages/core/crypto/wasm.js +++ /dev/null @@ -1,51 +0,0 @@ -// @ts-self-types="./wasm/iroha_crypto_wasm.d.ts" - -export * from './wasm/iroha_crypto_wasm.internal.js' -import * as internal from './wasm/iroha_crypto_wasm.internal.js' - -const imports = { './iroha_crypto_wasm.internal.js': internal } - -let wasm - -try { - wasm = await import('./wasm/iroha_crypto_wasm.wasm') - if (!(typeof wasm === 'object' && typeof wasm.__wbindgen_start === 'function')) { - throw 'not module' - } -} catch (errImport) { - try { - const response = fetch(new URL('./wasm/iroha_crypto_wasm.wasm', import.meta.url)) - const { instance } = await WebAssembly.instantiateStreaming(response, imports) - wasm = instance.exports - } catch (errFetch) { - try { - const fs = await import( - // turn off Vite warning https://vite.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility - /* @vite-ignore */ - 'node' + ':fs' - ) - const bytes = fs.readFileSync(new URL('./wasm/iroha_crypto_wasm.wasm', import.meta.url)) - const wasmModule = new WebAssembly.Module(bytes) - const wasmInstance = new WebAssembly.Instance(wasmModule, imports) - wasm = wasmInstance.exports - } catch (errNodeFs) { - console.error( - 'Unable to import/load `iroha_crypto_wasm.wasm`. There are a few ways to fix it:\n' + - ` - If you are using a bundler such as Vite, consider using "vite-plugin-wasm" to enable direct imports of \`.wasm\` modules. ` + - `This documentation could help: https://vite.dev/guide/features#webassembly\n` + - ` - If you are using importing directly in Browser, consider using https://github.com/guybedford/es-module-shims\n` + - `Below are collected errors:\n`, - ` - when tried import() with .wasm:`, - errImport, - `\n - when tried fetch():`, - errFetch, - `\n - when tried import('node:fs') + readFileSync:`, - errNodeFs, - ) - throw new TypeError('Could not import `iroha_crypto_wasm.wasm`') - } - } -} - -internal.__wbg_set_wasm(wasm) -wasm.__wbindgen_start()