Skip to content

Commit

Permalink
Ensure we await for the wasm module to load (#11995)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Hinton authored Nov 14, 2024
1 parent 5da5c88 commit ef127fd
Showing 1 changed file with 31 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,28 @@ const supported = (() => {
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.
if (BrowserApi.isManifestVersion(3)) {
if (supported) {
// eslint-disable-next-line no-console
console.debug("WebAssembly is supported in this environment");
import("./wasm");
loadingPromise = import("./wasm");
} else {
// eslint-disable-next-line no-console
console.debug("WebAssembly is not supported in this environment");
import("./fallback");
loadingPromise = import("./fallback");
}
}

// Manifest v2 expects dynamic imports to prevent timing issues.
async function load() {
if (BrowserApi.isManifestVersion(3)) {
// Ensure we have loaded the module
await loadingPromise;
return;
}

Expand All @@ -59,8 +65,30 @@ export class BrowserSdkClientFactory implements SdkClientFactory {
async createSdkClient(
...args: ConstructorParameters<typeof 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));
}
}

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);
});
});
};

0 comments on commit ef127fd

Please sign in to comment.