mirror of
https://github.com/bitwarden/browser
synced 2025-12-12 22:33:35 +00:00
Ensure we await for the wasm module to load (#11995)
Webpack seems to always convert imports to be async. This causes a issue where init_sdk is not always initialized before we call it. To resolve this I added a promise we can await in MV3 mode, and also defined a timeout which throws an error we can use to identify if we have issues loading the module.
This commit is contained in:
@@ -20,22 +20,28 @@ const supported = (() => {
|
|||||||
return false;
|
return false;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// Due to using webpack as bundler, sync imports will return an async module. Since we do support
|
||||||
|
// top level awaits, we define a promise we can await in the `load` function.
|
||||||
|
let loadingPromise: Promise<any> | undefined;
|
||||||
|
|
||||||
// Manifest v3 does not support dynamic imports in the service worker.
|
// Manifest v3 does not support dynamic imports in the service worker.
|
||||||
if (BrowserApi.isManifestVersion(3)) {
|
if (BrowserApi.isManifestVersion(3)) {
|
||||||
if (supported) {
|
if (supported) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.debug("WebAssembly is supported in this environment");
|
console.debug("WebAssembly is supported in this environment");
|
||||||
import("./wasm");
|
loadingPromise = import("./wasm");
|
||||||
} else {
|
} else {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.debug("WebAssembly is not supported in this environment");
|
console.debug("WebAssembly is not supported in this environment");
|
||||||
import("./fallback");
|
loadingPromise = import("./fallback");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manifest v2 expects dynamic imports to prevent timing issues.
|
// Manifest v2 expects dynamic imports to prevent timing issues.
|
||||||
async function load() {
|
async function load() {
|
||||||
if (BrowserApi.isManifestVersion(3)) {
|
if (BrowserApi.isManifestVersion(3)) {
|
||||||
|
// Ensure we have loaded the module
|
||||||
|
await loadingPromise;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,8 +65,30 @@ export class BrowserSdkClientFactory implements SdkClientFactory {
|
|||||||
async createSdkClient(
|
async createSdkClient(
|
||||||
...args: ConstructorParameters<typeof BitwardenClient>
|
...args: ConstructorParameters<typeof BitwardenClient>
|
||||||
): Promise<BitwardenClient> {
|
): Promise<BitwardenClient> {
|
||||||
await load();
|
try {
|
||||||
|
await loadWithTimeout();
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Failed to load: ${error.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
return Promise.resolve((globalThis as any).init_sdk(...args));
|
return Promise.resolve((globalThis as any).init_sdk(...args));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loadWithTimeout = async () => {
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
reject(new Error("Operation timed out after 1 second"));
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
load()
|
||||||
|
.then(() => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user