Skip to content

Commit 2d7862a

Browse files
committed
fix: fix lazy loading of JavaScript and WebAssembly modules
Previously, a number of JavaScript and WebAssembly modules were incorrectly loaded eagerly when not actually needed.
1 parent 3b385a5 commit 2d7862a

File tree

7 files changed

+69
-51
lines changed

7 files changed

+69
-51
lines changed

src/async_computation/decode_gzip.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@
1414
* limitations under the License.
1515
*/
1616

17-
import pako from "pako";
1817
import { decodeGzip } from "#src/async_computation/decode_gzip_request.js";
1918
import { registerAsyncComputation } from "#src/async_computation/handler.js";
2019

2120
registerAsyncComputation(decodeGzip, async (data: Uint8Array) => {
22-
const result = pako.inflate(data);
21+
const result = (await import("pako")).inflate(data);
2322
return { value: result, transfer: [result.buffer] };
2423
});

src/async_computation/obj_mesh.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { Uint32ArrayBuilder } from "#src/util/uint32array_builder.js";
2424
registerAsyncComputation(
2525
parseOBJFromArrayBuffer,
2626
async (buffer: ArrayBuffer) => {
27-
buffer = maybeDecompressGzip(buffer);
27+
buffer = await maybeDecompressGzip(buffer);
2828
let text = new TextDecoder().decode(buffer);
2929
// Strip comments
3030
text = text.replace(/#.*/g, "");

src/async_computation/vtk_mesh.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { maybeDecompressGzip } from "#src/util/gzip.js";
2222
registerAsyncComputation(
2323
parseVTKFromArrayBuffer,
2424
async (buffer: ArrayBuffer) => {
25-
const mesh = parseVTK(maybeDecompressGzip(buffer));
25+
const mesh = parseVTK(await maybeDecompressGzip(buffer));
2626
return {
2727
value: { data: mesh, size: getTriangularMeshSize(mesh) },
2828
transfer: [

src/mesh/draco/index.ts

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,26 +60,33 @@ const libraryEnv = {
6060
throw `proc exit: ${code}`;
6161
},
6262
};
63-
const dracoModulePromise = (async () => {
64-
const m = (wasmModule = (
65-
await WebAssembly.instantiateStreaming(
66-
fetch(new URL("./neuroglancer_draco.wasm", import.meta.url)),
67-
{
68-
env: libraryEnv,
69-
wasi_snapshot_preview1: libraryEnv,
70-
},
71-
)
72-
).instance);
73-
(m.exports._initialize as Function)();
74-
return m;
75-
})();
63+
let dracoModulePromise: Promise<WebAssembly.Instance> | undefined;
64+
65+
function getDracoModulePromise() {
66+
if (dracoModulePromise == undefined) {
67+
dracoModulePromise = (async () => {
68+
const m = (wasmModule = (
69+
await WebAssembly.instantiateStreaming(
70+
fetch(new URL("./neuroglancer_draco.wasm", import.meta.url)),
71+
{
72+
env: libraryEnv,
73+
wasi_snapshot_preview1: libraryEnv,
74+
},
75+
)
76+
).instance);
77+
(m.exports._initialize as Function)();
78+
return m;
79+
})();
80+
}
81+
return dracoModulePromise;
82+
}
7683

7784
export async function decodeDracoPartitioned(
7885
buffer: Uint8Array,
7986
vertexQuantizationBits: number,
8087
partition: boolean,
8188
): Promise<RawPartitionedMeshData> {
82-
const m = await dracoModulePromise;
89+
const m = await getDracoModulePromise();
8390
const offset = (m.exports.malloc as Function)(buffer.byteLength);
8491
const heap = new Uint8Array((m.exports.memory as WebAssembly.Memory).buffer);
8592
heap.set(buffer, offset);
@@ -101,7 +108,7 @@ export async function decodeDracoPartitioned(
101108
}
102109

103110
export async function decodeDraco(buffer: Uint8Array): Promise<RawMeshData> {
104-
const m = await dracoModulePromise;
111+
const m = await getDracoModulePromise();
105112
const offset = (m.exports.malloc as Function)(buffer.byteLength);
106113
const heap = new Uint8Array((m.exports.memory as WebAssembly.Memory).buffer);
107114
heap.set(buffer, offset);

src/sliceview/compresso/index.ts

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,26 @@ const libraryEnv = {
2121
},
2222
};
2323

24-
const compressoModulePromise = (async () => {
25-
const m = (
26-
await WebAssembly.instantiateStreaming(
27-
fetch(new URL("./compresso.wasm", import.meta.url)),
28-
{
29-
env: libraryEnv,
30-
wasi_snapshot_preview1: libraryEnv,
31-
},
32-
)
33-
).instance;
34-
(m.exports._initialize as Function)();
35-
return m;
36-
})();
24+
let compressoModulePromise: Promise<WebAssembly.Instance> | undefined;
25+
26+
function getCompressoModulePromise() {
27+
if (compressoModulePromise === undefined) {
28+
compressoModulePromise = (async () => {
29+
const m = (
30+
await WebAssembly.instantiateStreaming(
31+
fetch(new URL("./compresso.wasm", import.meta.url)),
32+
{
33+
env: libraryEnv,
34+
wasi_snapshot_preview1: libraryEnv,
35+
},
36+
)
37+
).instance;
38+
(m.exports._initialize as Function)();
39+
return m;
40+
})();
41+
}
42+
return compressoModulePromise;
43+
}
3744

3845
// not a full implementation of read header, just the parts we need
3946
function readHeader(buffer: Uint8Array): {
@@ -69,7 +76,7 @@ function readHeader(buffer: Uint8Array): {
6976
export async function decompressCompresso(
7077
buffer: Uint8Array,
7178
): Promise<Uint8Array> {
72-
const m = await compressoModulePromise;
79+
const m = await getCompressoModulePromise();
7380

7481
const { sx, sy, sz, dataWidth } = readHeader(buffer);
7582
const voxels = sx * sy * sz;

src/sliceview/png/index.ts

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,26 @@ const libraryEnv = {
2323
},
2424
};
2525

26-
const pngModulePromise = (async () => {
27-
const m = (
28-
await WebAssembly.instantiateStreaming(
29-
fetch(new URL("./libpng.wasm", import.meta.url)),
30-
{
31-
env: libraryEnv,
32-
wasi_snapshot_preview1: libraryEnv,
33-
},
34-
)
35-
).instance;
36-
(m.exports._initialize as Function)();
37-
return m;
38-
})();
26+
let pngModulePromise: Promise<WebAssembly.Instance> | undefined;
27+
28+
function getPngModulePromise() {
29+
if (pngModulePromise === undefined) {
30+
pngModulePromise = (async () => {
31+
const m = (
32+
await WebAssembly.instantiateStreaming(
33+
fetch(new URL("./libpng.wasm", import.meta.url)),
34+
{
35+
env: libraryEnv,
36+
wasi_snapshot_preview1: libraryEnv,
37+
},
38+
)
39+
).instance;
40+
(m.exports._initialize as Function)();
41+
return m;
42+
})();
43+
}
44+
return pngModulePromise;
45+
}
3946

4047
enum PngColorSpace {
4148
GRAYSCALE = 0,
@@ -169,7 +176,7 @@ export async function decompressPng(
169176
bytesPerPixel: number,
170177
convertToGrayscale: boolean,
171178
): Promise<DecodedImage> {
172-
const m = await pngModulePromise;
179+
const m = await getPngModulePromise();
173180
let { sx, sy, dataWidth, numChannels } = readHeader(buffer);
174181

175182
if (convertToGrayscale) {

src/util/gzip.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
* limitations under the License.
1515
*/
1616

17-
import pako from "pako";
18-
1917
/**
2018
* Detects gzip format based on the 2 magic bytes at the start.
2119
*/
@@ -27,15 +25,15 @@ export function isGzipFormat(data: ArrayBufferView) {
2725
/**
2826
* Decompress `data` if it is in gzip format, otherwise just return it.
2927
*/
30-
export function maybeDecompressGzip(data: ArrayBuffer | ArrayBufferView) {
28+
export async function maybeDecompressGzip(data: ArrayBuffer | ArrayBufferView) {
3129
let byteView: Uint8Array;
3230
if (data instanceof ArrayBuffer) {
3331
byteView = new Uint8Array(data);
3432
} else {
3533
byteView = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
3634
}
3735
if (isGzipFormat(byteView)) {
38-
return pako.inflate(byteView);
36+
return (await import("pako")).inflate(byteView);
3937
}
4038
return byteView;
4139
}

0 commit comments

Comments
 (0)