Skip to content

Commit d468c65

Browse files
committed
feat: make createNamespace sync by moving it into VtkWASMLoader
- this allows one to first load a VTK.wasm binary, then create a namespace using said binary. - see examples/js/simple-app/src/main.js for usage
1 parent 45213af commit d468c65

7 files changed

Lines changed: 45 additions & 35 deletions

File tree

docs/guide/js/bundler.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Modern web development rely on package manager to bring project dependencies. Th
44

55
## Project setup
66

7-
In the simple example we are going to use [Vite](https://vite.dev/) with Vanilla JavaScript. The full code is available for reference [here](https://github.com/Kitware/vtk-wasm/tree/main/examples/js/simple-app).
7+
In the simple example we are going to use [Vite](https://vite.dev/) with Vanilla JavaScript. The full code is available for reference [here](https://github.com/Kitware/vtk-wasm/tree/main/examples/js/simple-app). Please note that you should use a concrete version, or "latest" for the `@kitware/vtk-wasm` package. Here, it uses a relative path to the `vtk-wasm` project root, so that the in source documentation stays relevant.
88

99
::: code-group
1010
<<< ../../../examples/js/simple-app/package.json

examples/js/simple-app/package-lock.json

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/js/simple-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
"vite": "^6.3.5"
1313
},
1414
"dependencies": {
15-
"@kitware/vtk-wasm": "latest"
15+
"@kitware/vtk-wasm": "file:../../.."
1616
}
1717
}

examples/js/simple-app/src/main.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import "./style.css";
2-
import { createNamespace } from "@kitware/vtk-wasm/vtk";
2+
import { VtkWASMLoader } from "@kitware/vtk-wasm/vtk";
33
import { buildWASMScene } from "./example";
44

5-
const VTK_WASM_TARBALL_URL = "https://gitlab.kitware.com/api/v4/projects/13/packages/generic/vtk-wasm32-emscripten/9.5.20251215/vtk-9.5.20251215-wasm32-emscripten.tar.gz";
6-
createNamespace(VTK_WASM_TARBALL_URL).then((vtk) => {
7-
buildWASMScene(vtk, "#app > canvas", "This scene passes the VTK.wasm bundle from GitLab registry to createNamespace()");
8-
});
5+
const loader = new VtkWASMLoader();
6+
await loader.load("https://gitlab.kitware.com/api/v4/projects/13/packages/generic/vtk-wasm32-emscripten/9.5.20251215/vtk-9.5.20251215-wasm32-emscripten.tar.gz");
7+
let vtk = loader.createNamespace();
8+
buildWASMScene(vtk, "#app > canvas", "This scene passes the VTK.wasm bundle from GitLab registry to createNamespace()");

examples/js/simple-app/vite.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export default {
22
base: "./",
33
build: {
4+
target: 'esnext',
45
outDir: "../../../docs/public/demo/simple-app",
56
emptyOutDir: true,
67
},

src/standalone.js

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,9 @@ import { createInstantiatorProxy } from "./core/proxy";
1313
* @returns the vtk namespace for creating VTK objects.
1414
*/
1515
export async function createNamespace(url, config = {}, wasmBaseName = "vtk") {
16-
const vtkProxyCache = new WeakMap();
17-
const idToRef = new Map();
18-
1916
const loader = new VtkWASMLoader();
2017
await loader.load(url || "loaded-module", config, wasmBaseName);
21-
const wasm = loader.createStandaloneSession();
22-
23-
return createInstantiatorProxy(wasm, vtkProxyCache, idToRef);
18+
return loader.createNamespace();
2419
}
2520

2621
/**
@@ -33,18 +28,20 @@ export async function createNamespace(url, config = {}, wasmBaseName = "vtk") {
3328
* - data-config="{ rendering: 'webgl|webgpu', exec: 'sync|async' }" json config for
3429
* WASM module configuration.
3530
*/
36-
const { promise, resolve, reject } = createFuture();
37-
const script = document.querySelector("#vtk-wasm");
38-
if (script) {
39-
const url = script.dataset.url || ".";
40-
const config = JSON.parse(script.dataset.config || "{}");
41-
window.vtkReady = promise;
42-
createNamespace(url, config)
43-
.then((vtk) => {
44-
window.vtk = vtk;
45-
resolve(vtk);
46-
})
47-
.catch(reject);
48-
} else {
49-
reject("Automatic VTK namespace initialization is disabled because no <script id=\"vtk-wasm\"> tag was found. See https://kitware.github.io/vtk-wasm/guide/js/plain.html#defer-wasm-loading-with-annotation'");
31+
if (typeof window !== "undefined") {
32+
const script = document.querySelector("#vtk-wasm");
33+
if (script) {
34+
const { promise, resolve, reject } = createFuture();
35+
const url = script.dataset.url || ".";
36+
const config = JSON.parse(script.dataset.config || "{}");
37+
window.vtkReady = promise;
38+
createNamespace(url, config)
39+
.then((vtk) => {
40+
window.vtk = vtk;
41+
resolve(vtk);
42+
})
43+
.catch(reject);
44+
}
5045
}
46+
47+
export { VtkWASMLoader } from "./wasmLoader";

src/wasmLoader.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { createRemoteSession } from "./core/sessionFactory";
66
import { createFuture } from "./core/future";
77
import { createBlobURL, disposeBlobURL } from "./core/blobURL";
88
import { convertToObj, convertToStr } from "./core/stateDecorators";
9+
import { createInstantiatorProxy } from "./core/proxy";
910

1011
/**
1112
* VtkWASMLoader type definition
@@ -60,12 +61,12 @@ export class VtkWASMLoader {
6061
this.#pendingLoad = promise;
6162

6263
// wait for wasm script to load if any (first priority)
63-
if (!window.createVTKWASM) {
64+
if (typeof window !== 'undefined' && !globalThis.createVTKWASM) {
6465
await loadWebAssemblyModuleFromExistingScript(wasmBaseName);
6566
}
6667

6768
let wasmFile = null;
68-
if (!window.createVTKWASM) {
69+
if (typeof window !== 'undefined' && !globalThis.createVTKWASM) {
6970
if (isGzipBundle(wasmBaseURL)) {
7071
let gzipArrayBuffer;
7172
let javaScriptBlobURL = null;
@@ -101,8 +102,8 @@ export class VtkWASMLoader {
101102
if (scriptURL !== null) {
102103
await loadWebAssemblyModuleFromScript(scriptURL);
103104
}
104-
// if window.createVTKWASM is still not defined, try legacy loader
105-
if (!window.createVTKWASM) {
105+
// if globalThis.createVTKWASM is still not defined, try legacy loader
106+
if (!globalThis.createVTKWASM) {
106107
const legacyScriptURL = await createScriptURL(wasmBaseURL, null, null, true);
107108
await loadWebAssemblyModuleFromScript(legacyScriptURL);
108109
}
@@ -115,9 +116,9 @@ export class VtkWASMLoader {
115116
}
116117

117118
// Load WASM
118-
if (window.createVTKWASM) {
119+
if (globalThis.createVTKWASM) {
119120
try {
120-
this.#wasmInstance = await window.createVTKWASM(createEmscriptenConfig(this.#config, wasmFile));
121+
this.#wasmInstance = await globalThis.createVTKWASM(createEmscriptenConfig(this.#config, wasmFile));
121122
} catch (e) {
122123
reject(e);
123124
this.#pendingLoad = null;
@@ -126,7 +127,7 @@ export class VtkWASMLoader {
126127
this.#loaded = true;
127128
resolve();
128129
this.#pendingLoad = null;
129-
} else if (window.createVTKWasmSceneManager) {
130+
} else if (globalThis.createVTKWasmSceneManager) {
130131
// Legacy API
131132
this.#wasmInstance = null;
132133
this.#loaded = true;
@@ -153,6 +154,13 @@ export class VtkWASMLoader {
153154
}
154155
}
155156

157+
createNamespace() {
158+
const vtkProxyCache = new WeakMap();
159+
const idToRef = new Map();
160+
const wasm = this.createStandaloneSession();
161+
return createInstantiatorProxy(wasm, vtkProxyCache, idToRef);
162+
}
163+
156164
/**
157165
* Create a new remote session and return it regardless of WASM version.
158166
*

0 commit comments

Comments
 (0)