mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
fix(markdown): compile the parser wasm asynchronously (#2900)
This commit is contained in:
@@ -47,11 +47,19 @@ const lenientTextDecoder = new TextDecoder('utf-8', {ignoreBOM: true, fatal: fal
|
||||
|
||||
let textDecoder = new TextDecoder('utf-8', {ignoreBOM: true, fatal: true});
|
||||
let wasm: WasmExports | null = null;
|
||||
let wasmModule: unknown = null;
|
||||
let cachedMemory: Uint8Array | null = null;
|
||||
let replacingOversizedInstance = false;
|
||||
|
||||
interface WasmInstance {
|
||||
exports: Record<string, unknown>;
|
||||
}
|
||||
|
||||
declare const WebAssembly: {
|
||||
Module: new (bytes: Uint8Array) => unknown;
|
||||
Instance: new (module: unknown, imports?: Record<string, unknown>) => {exports: Record<string, unknown>};
|
||||
Instance: new (module: unknown, imports?: Record<string, unknown>) => WasmInstance;
|
||||
compile(bytes: Uint8Array): Promise<unknown>;
|
||||
instantiate(module: unknown, imports?: Record<string, unknown>): Promise<WasmInstance>;
|
||||
};
|
||||
|
||||
function getWasmMemory(exports: Record<string, unknown>): WasmExports['memory'] {
|
||||
@@ -94,22 +102,39 @@ function decodeBase64(value: string): Uint8Array {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function getWasm(): WasmExports {
|
||||
if (!wasm) {
|
||||
const module = new WebAssembly.Module(decodeBase64(MARKDOWN_PARSER_WASM_BASE64));
|
||||
const instance = new WebAssembly.Instance(module, {});
|
||||
wasm = createWasmExports(instance.exports);
|
||||
cachedMemory = null;
|
||||
}
|
||||
function setWasmInstance(instance: WasmInstance): WasmExports {
|
||||
wasm = createWasmExports(instance.exports);
|
||||
cachedMemory = null;
|
||||
return wasm;
|
||||
}
|
||||
|
||||
export async function preloadMarkdownParserWasm(): Promise<void> {
|
||||
if (wasm) return;
|
||||
wasmModule ??= await WebAssembly.compile(decodeBase64(MARKDOWN_PARSER_WASM_BASE64));
|
||||
const instance = await WebAssembly.instantiate(wasmModule, {});
|
||||
if (!wasm) setWasmInstance(instance);
|
||||
}
|
||||
|
||||
function getWasm(): WasmExports {
|
||||
if (wasm) return wasm;
|
||||
wasmModule ??= new WebAssembly.Module(decodeBase64(MARKDOWN_PARSER_WASM_BASE64));
|
||||
return setWasmInstance(new WebAssembly.Instance(wasmModule, {}));
|
||||
}
|
||||
|
||||
function releaseOversizedWasmMemory(): void {
|
||||
if ((wasm?.memory.buffer.byteLength ?? 0) <= MAX_RETAINED_WASM_MEMORY_BYTES) {
|
||||
if (replacingOversizedInstance || (wasm?.memory.buffer.byteLength ?? 0) <= MAX_RETAINED_WASM_MEMORY_BYTES) {
|
||||
return;
|
||||
}
|
||||
wasm = null;
|
||||
cachedMemory = null;
|
||||
const oversized = wasm;
|
||||
replacingOversizedInstance = true;
|
||||
WebAssembly.instantiate(wasmModule, {})
|
||||
.then((instance) => {
|
||||
if (wasm === oversized) setWasmInstance(instance);
|
||||
})
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
replacingOversizedInstance = false;
|
||||
});
|
||||
}
|
||||
|
||||
function memoryU8(): Uint8Array {
|
||||
|
||||
@@ -86,7 +86,19 @@ async function logClientInfo(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
async function preloadMarkdownParser(): Promise<void> {
|
||||
try {
|
||||
const {preloadMarkdownParserWasm} = await loadLazyModule(
|
||||
() => import('@app/features/messaging/utils/markdown/parser/MarkdownParserWasm'),
|
||||
);
|
||||
await preloadMarkdownParserWasm();
|
||||
} catch (error) {
|
||||
logger.warn('Failed to preload markdown parser:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function bootstrapThemeStudio(): Promise<void> {
|
||||
const markdownParserReady = preloadMarkdownParser();
|
||||
const [{ThemeStudioStandaloneApp}, {setupHttp}, {default: AccountManager}] = await Promise.all([
|
||||
loadLazyModule(() => import('@app/features/theme_studio/ThemeStudioStandaloneApp')),
|
||||
loadLazyModule(() => import('@app/app/SetupHttp')),
|
||||
@@ -94,6 +106,7 @@ async function bootstrapThemeStudio(): Promise<void> {
|
||||
]);
|
||||
await AccountManager.bootstrap();
|
||||
setupHttp();
|
||||
await markdownParserReady;
|
||||
mountRoot(
|
||||
<AppI18nProvider i18n={i18n}>
|
||||
<ThemeStudioStandaloneApp data-flx="index.render-theme-studio.theme-studio-standalone-app" />
|
||||
@@ -103,6 +116,7 @@ async function bootstrapThemeStudio(): Promise<void> {
|
||||
}
|
||||
|
||||
async function bootstrapApp(): Promise<void> {
|
||||
const markdownParserReady = preloadMarkdownParser();
|
||||
const [
|
||||
{App},
|
||||
{setupHttp},
|
||||
@@ -148,6 +162,7 @@ async function bootstrapApp(): Promise<void> {
|
||||
await AccountManager.bootstrap();
|
||||
setupHttp();
|
||||
initializeEmojiParser();
|
||||
await markdownParserReady;
|
||||
mountRoot(<App data-flx="index.bootstrap.app" />, 'index.bootstrap');
|
||||
QuickSwitcher.preloadModal();
|
||||
registerServiceWorker();
|
||||
|
||||
Reference in New Issue
Block a user