Adjust init to allow for asm/wasm or combo (#309)
* Additional known secp256k1 test * Fix test * typo * ... one more typo * Adjust init to allow for asm/wasm or combo * Cleanup export, no internal cjs * Adjust sideEffects * CHANGELOG
This commit is contained in:
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,5 +1,15 @@
|
||||
# CHANGELOG
|
||||
|
||||
## master
|
||||
|
||||
- **Breaking change** For users of React Native, you are now required to add `import '@polkadot/wasm-crypto/initOnlyAsm'` at your project top-level to ensure that asm.js is initialized. (Or alternatively `import '@polkadot/wasm-crypto/initWasmAsm'` to future-proof when WASM does become available)
|
||||
- **Breaking change** For users who used to map the `data` and `empty` of the internal `wasm-crypto-{wasm, asmjs}` packages in their bundlers, swap to one of the `init*()` imports to set the type of interfaces you would prefer.
|
||||
|
||||
Changes:
|
||||
|
||||
- Add (optional) `@polkadot/wasm-crypto/init{OnlyAsm, OnlyWasm, WasmAsm}` to allow specific interface types
|
||||
|
||||
|
||||
## 4.6.1 Mar 12, 2022
|
||||
|
||||
Changes:
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"version": "4.6.2-3",
|
||||
"browser": "empty.js",
|
||||
"main": "empty.js",
|
||||
"react-native": "data.js",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.17.7"
|
||||
},
|
||||
|
||||
@@ -3,4 +3,6 @@
|
||||
|
||||
import { asmJsInit as _asmJsInit } from './cjs/data.js';
|
||||
|
||||
export { packageInfo } from './packageInfo';
|
||||
|
||||
export const asmJsInit = _asmJsInit;
|
||||
@@ -1,4 +1,6 @@
|
||||
// Copyright 2019-2022 @polkadot/wasm-crypto-asmjs authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export const asmJsInit = null;
|
||||
import './detectPackage';
|
||||
|
||||
export * from './bundle';
|
||||
@@ -18,9 +18,7 @@
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"version": "4.6.2-3",
|
||||
"browser": "data.js",
|
||||
"main": "data.js",
|
||||
"react-native": "data.js",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.17.7"
|
||||
},
|
||||
|
||||
@@ -5,4 +5,6 @@ import { base64Decode } from './base64';
|
||||
import { bytes, sizeUncompressed } from './bytes';
|
||||
import { unzlibSync } from './fflate';
|
||||
|
||||
export { packageInfo } from './packageInfo';
|
||||
|
||||
export const wasmBytes = unzlibSync(base64Decode(bytes), new Uint8Array(sizeUncompressed));
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2019-2022 @polkadot/wasm-crypto-wasm authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export const bytes = null;
|
||||
import './detectPackage';
|
||||
|
||||
export const sizeCompressed = 0;
|
||||
|
||||
export const sizeUncompressed = 0;
|
||||
export * from './bundle';
|
||||
@@ -17,7 +17,13 @@
|
||||
},
|
||||
"sideEffects": [
|
||||
"./detectPackage.js",
|
||||
"./detectPackage.cjs"
|
||||
"./detectPackage.cjs",
|
||||
"./initOnlyAsm.js",
|
||||
"./initOnlyAsm.cjs",
|
||||
"./initOnlyWasm.js",
|
||||
"./initOnlyWasm.cjs",
|
||||
"./initWasmAsm.js",
|
||||
"./initWasmAsm.cjs"
|
||||
],
|
||||
"type": "module",
|
||||
"version": "4.6.2-3",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import type { AsmCreator, WasmCryptoInstance } from './types';
|
||||
import type { WasmCryptoInstance } from './types';
|
||||
|
||||
import { assert, stringToU8a, u8aToString } from '@polkadot/util';
|
||||
|
||||
@@ -12,56 +12,46 @@ type PopFirst<T extends unknown[]> =
|
||||
? N
|
||||
: [];
|
||||
|
||||
let wasm: WasmCryptoInstance | null = null;
|
||||
let cachegetInt32: Int32Array | null = null;
|
||||
let cachegetUint8: Uint8Array | null = null;
|
||||
|
||||
export async function initWasm (wasmBytes: Uint8Array | null, asmFn: AsmCreator | null, wbg: Record<string, WebAssembly.ImportValue>): Promise<void> {
|
||||
try {
|
||||
assert(typeof WebAssembly !== 'undefined' && wasmBytes && wasmBytes.length, 'WebAssembly is not available in your environment');
|
||||
|
||||
const source = await WebAssembly.instantiate(wasmBytes, { wbg });
|
||||
|
||||
wasm = source.instance.exports as unknown as WasmCryptoInstance;
|
||||
} catch (error) {
|
||||
// if we have a valid supplied asm.js, return that
|
||||
if (asmFn) {
|
||||
wasm = asmFn(wbg);
|
||||
} else {
|
||||
console.error('FATAL: Unable to initialize @polkadot/wasm-crypto');
|
||||
console.error(error);
|
||||
|
||||
wasm = null;
|
||||
}
|
||||
}
|
||||
interface Bridge {
|
||||
cachegetInt32: Int32Array | null;
|
||||
cachegetUint8: Uint8Array | null;
|
||||
wasm: WasmCryptoInstance | null;
|
||||
wasmPromise: Promise<void> | null;
|
||||
}
|
||||
|
||||
export const __bridge: Bridge = {
|
||||
cachegetInt32: null,
|
||||
cachegetUint8: null,
|
||||
wasm: null,
|
||||
wasmPromise: null
|
||||
};
|
||||
|
||||
export function withWasm <T, F extends (wasm: WasmCryptoInstance, ...params: never[]) => T> (fn: F): (...params: PopFirst<Parameters<F>>) => ReturnType<F> {
|
||||
return (...params: PopFirst<Parameters<F>>): ReturnType<F> => {
|
||||
assert(wasm, 'The WASM interface has not been initialized. Ensure that you wait for the initialization Promise with waitReady() from @polkadot/wasm-crypto (or cryptoWaitReady() from @polkadot/util-crypto) before attempting to use WASM-only interfaces.');
|
||||
assert(__bridge.wasm, 'The WASM interface has not been initialized. Ensure that you wait for the initialization Promise with waitReady() from @polkadot/wasm-crypto (or cryptoWaitReady() from @polkadot/util-crypto) before attempting to use WASM-only interfaces.');
|
||||
|
||||
return fn(wasm, ...params) as ReturnType<F>;
|
||||
return fn(__bridge.wasm, ...params) as ReturnType<F>;
|
||||
};
|
||||
}
|
||||
|
||||
export function getWasm (): WasmCryptoInstance {
|
||||
return wasm!;
|
||||
return __bridge.wasm!;
|
||||
}
|
||||
|
||||
export function getInt32 (): Int32Array {
|
||||
if (cachegetInt32 === null || cachegetInt32.buffer !== wasm!.memory.buffer) {
|
||||
cachegetInt32 = new Int32Array(wasm!.memory.buffer);
|
||||
if (__bridge.cachegetInt32 === null || __bridge.cachegetInt32.buffer !== __bridge.wasm!.memory.buffer) {
|
||||
__bridge.cachegetInt32 = new Int32Array(__bridge.wasm!.memory.buffer);
|
||||
}
|
||||
|
||||
return cachegetInt32;
|
||||
return __bridge.cachegetInt32;
|
||||
}
|
||||
|
||||
export function getUint8 (): Uint8Array {
|
||||
if (cachegetUint8 === null || cachegetUint8.buffer !== wasm!.memory.buffer) {
|
||||
cachegetUint8 = new Uint8Array(wasm!.memory.buffer);
|
||||
if (__bridge.cachegetUint8 === null || __bridge.cachegetUint8.buffer !== __bridge.wasm!.memory.buffer) {
|
||||
__bridge.cachegetUint8 = new Uint8Array(__bridge.wasm!.memory.buffer);
|
||||
}
|
||||
|
||||
return cachegetUint8;
|
||||
return __bridge.cachegetUint8;
|
||||
}
|
||||
|
||||
export function getU8a (ptr: number, len: number): Uint8Array {
|
||||
@@ -73,7 +63,7 @@ export function getString (ptr: number, len: number): string {
|
||||
}
|
||||
|
||||
export function allocU8a (arg: Uint8Array): [number, number] {
|
||||
const ptr = wasm!.__wbindgen_malloc(arg.length * 1);
|
||||
const ptr = __bridge.wasm!.__wbindgen_malloc(arg.length * 1);
|
||||
|
||||
getUint8().set(arg, ptr / 1);
|
||||
|
||||
@@ -89,7 +79,7 @@ export function resultU8a (): Uint8Array {
|
||||
const r1 = getInt32()[8 / 4 + 1];
|
||||
const ret = getU8a(r0, r1).slice();
|
||||
|
||||
wasm!.__wbindgen_free(r0, r1 * 1);
|
||||
__bridge.wasm!.__wbindgen_free(r0, r1 * 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
// Copyright 2019-2022 @polkadot/wasm-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { asmJsInit } from '@polkadot/wasm-crypto-asmjs';
|
||||
import { wasmBytes } from '@polkadot/wasm-crypto-wasm';
|
||||
|
||||
import { allocString, allocU8a, getWasm, initWasm, resultString, resultU8a, withWasm } from './bridge';
|
||||
import * as imports from './imports';
|
||||
import { __bridge, allocString, allocU8a, getWasm, resultString, resultU8a, withWasm } from './bridge';
|
||||
import { setWasmOnlyPromise } from './init';
|
||||
|
||||
export { packageInfo } from './packageInfo';
|
||||
|
||||
const wasmPromise = initWasm(wasmBytes, asmJsInit, imports).catch(() => null);
|
||||
|
||||
export const bip39Generate = withWasm((wasm, words: 12 | 15 | 18 | 21 | 24): string => {
|
||||
wasm.ext_bip39_generate(8, words);
|
||||
|
||||
@@ -208,5 +203,9 @@ export function isReady (): boolean {
|
||||
}
|
||||
|
||||
export function waitReady (): Promise<boolean> {
|
||||
return wasmPromise.then(() => isReady());
|
||||
return (
|
||||
__bridge.wasmPromise || setWasmOnlyPromise()
|
||||
)
|
||||
.then(() => isReady())
|
||||
.catch(() => false);
|
||||
}
|
||||
|
||||
40
packages/wasm-crypto/src/init.ts
Normal file
40
packages/wasm-crypto/src/init.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2019-2022 @polkadot/wasm-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { AsmCreator, WasmCryptoInstance } from './types';
|
||||
|
||||
import { assert } from '@polkadot/util';
|
||||
import { wasmBytes } from '@polkadot/wasm-crypto-wasm';
|
||||
|
||||
import { __bridge } from './bridge';
|
||||
import * as imports from './imports';
|
||||
|
||||
async function createPromise (wasmBytes: Uint8Array | null, asmFn: AsmCreator | null): Promise<void> {
|
||||
try {
|
||||
assert(typeof WebAssembly !== 'undefined' && wasmBytes && wasmBytes.length, 'WebAssembly is not available in your environment');
|
||||
|
||||
const source = await WebAssembly.instantiate(wasmBytes, { wbg: imports });
|
||||
|
||||
__bridge.wasm = source.instance.exports as unknown as WasmCryptoInstance;
|
||||
} catch (error) {
|
||||
// if we have a valid supplied asm.js, return that
|
||||
if (asmFn) {
|
||||
__bridge.wasm = asmFn(imports);
|
||||
} else {
|
||||
console.error('FATAL: Unable to initialize @polkadot/wasm-crypto');
|
||||
console.error(error);
|
||||
|
||||
__bridge.wasm = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function setPromise (wasmBytes: Uint8Array | null, asmFn: AsmCreator | null): Promise<void> {
|
||||
__bridge.wasmPromise = createPromise(wasmBytes, asmFn);
|
||||
|
||||
return __bridge.wasmPromise;
|
||||
}
|
||||
|
||||
export function setWasmOnlyPromise (): Promise<void> {
|
||||
return setPromise(wasmBytes, null);
|
||||
}
|
||||
8
packages/wasm-crypto/src/initOnlyAsm.ts
Normal file
8
packages/wasm-crypto/src/initOnlyAsm.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright 2019-2022 @polkadot/wasm-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { asmJsInit } from '@polkadot/wasm-crypto-asmjs';
|
||||
|
||||
import { setPromise } from './init';
|
||||
|
||||
setPromise(null, asmJsInit).catch(() => undefined);
|
||||
6
packages/wasm-crypto/src/initOnlyWasm.ts
Normal file
6
packages/wasm-crypto/src/initOnlyWasm.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
// Copyright 2019-2022 @polkadot/wasm-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { setWasmOnlyPromise } from './init';
|
||||
|
||||
setWasmOnlyPromise().catch(() => undefined);
|
||||
9
packages/wasm-crypto/src/initWasmAsm.ts
Normal file
9
packages/wasm-crypto/src/initWasmAsm.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2019-2022 @polkadot/wasm-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { asmJsInit } from '@polkadot/wasm-crypto-asmjs';
|
||||
import { wasmBytes } from '@polkadot/wasm-crypto-wasm';
|
||||
|
||||
import { setPromise } from './init';
|
||||
|
||||
setPromise(wasmBytes, asmJsInit).catch(() => undefined);
|
||||
@@ -1,8 +1,12 @@
|
||||
// Copyright 2019-2022 @polkadot/wasm-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
const rootIncl = ['@polkadot/wasm-crypto-asmjs', '@polkadot/wasm-crypto-wasm'];
|
||||
const detcIncl = rootIncl.map((p) => `${p}/packageInfo.cjs`);
|
||||
const rootIncl = ['@polkadot/wasm-crypto', '@polkadot/wasm-crypto-asmjs', '@polkadot/wasm-crypto-wasm'];
|
||||
const detcIncl = [
|
||||
...rootIncl.map((p) => `${p}/initOnlyAsm.cjs`),
|
||||
...rootIncl.map((p) => `${p}/initOnlyWasm.cjs`),
|
||||
...rootIncl.map((p) => `${p}/packageInfo.cjs`)
|
||||
];
|
||||
|
||||
require('override-require')(
|
||||
(request) =>
|
||||
@@ -10,6 +14,10 @@ require('override-require')(
|
||||
detcIncl.some((p) => request.endsWith(p)),
|
||||
(request) =>
|
||||
rootIncl.some((p) => request.endsWith(p))
|
||||
? require(`${rootIncl.find((p) => request.endsWith(p))}/build/data.cjs`)
|
||||
: require(`${detcIncl.find((p) => request.endsWith(p)).replace('packageInfo.cjs', 'build/packageInfo.cjs')}`)
|
||||
? require(`${rootIncl.find((p) => request.endsWith(p))}/build/index.cjs`)
|
||||
: require(`${detcIncl.find((p) => request.endsWith(p))
|
||||
.replace('initOnlyAsm.cjs', 'build/initOnlyAsm.cjs')
|
||||
.replace('initOnlyWasm.cjs', 'build/initOnlyWasm.cjs')
|
||||
.replace('packageInfo.cjs', 'build/packageInfo.cjs')
|
||||
}`)
|
||||
);
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
// Copyright 2019-2022 @polkadot/wasm-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
global.WebAssembly = null;
|
||||
|
||||
require('./alias-imports.cjs');
|
||||
require('@polkadot/wasm-crypto/initOnlyAsm.cjs');
|
||||
|
||||
const { runUnassisted } = require('./all/index.cjs');
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
|
||||
// override-require in jest.config.js
|
||||
|
||||
import { beforeAll, tests, wasm } from './all/index.cjs';
|
||||
|
||||
describe('wasm-crypto', () => {
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
"composite": true,
|
||||
"paths": {
|
||||
"@polkadot/wasm-crypto-asmjs/packageInfo": ["wasm-crypto-asmjs/src/packageInfo"],
|
||||
"@polkadot/wasm-crypto-asmjs": ["wasm-crypto-asmjs/src/data"],
|
||||
"@polkadot/wasm-crypto-asmjs": ["wasm-crypto-asmjs/src"],
|
||||
"@polkadot/wasm-crypto-wasm/packageInfo": ["wasm-crypto-wasm/src/packageInfo"],
|
||||
"@polkadot/wasm-crypto-wasm": ["wasm-crypto-wasm/src/data"],
|
||||
"@polkadot/wasm-crypto-wasm": ["wasm-crypto-wasm/src"],
|
||||
"@polkadot/wasm-crypto": ["wasm-crypto/src"]
|
||||
},
|
||||
"skipLibCheck": true
|
||||
|
||||
Reference in New Issue
Block a user