Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using viz.js in web browser with Parcel bundler: render.browser.js throws "Y.startsWith is not a function", fix by adding Y.toString() #27

Closed
pfroud opened this issue Aug 2, 2022 · 2 comments

Comments

@pfroud
Copy link

pfroud commented Aug 2, 2022

Hi, I'm trying to use viz.js in a web browser using the Parcel bundler.

Directory structure of my test project:

vizjs-parcel-test/
├── node_modules
├── src/
│   ├── index.html
│   ├── main.js
│   └── worker.js
└── package.json

Contents of file package.json:

{
  "devDependencies": {
    "@aduh95/viz.js": "^3.7.0",
    "parcel": "^2.6.2"
  }
}

Contents of file index.html:

<html><body><script type="module" src="main.js"></script></body></html>

The Parcel bundler does not support package.json#exports and does not have a file-loader plugin. So the main.js and worker.js files are both taken from https://github.com/aduh95/viz.js/blob/master/README.md#using-a-bundler.

Contents of file main.js:

import Viz from "@aduh95/viz.js";
const viz = new Viz({ worker: new Worker(new URL("./worker.js", import.meta.url), { type: "module" }) });
viz.renderString("digraph{1 -> 2 }")
    .then(svgString => console.log(svgString))
    .catch(error => console.error(error))
    .finally(() => viz.terminateWorker());

Contents of file worker.js:

import initWASM from "../node_modules/@aduh95/viz.js/dist/render.browser.js";
const wasmURL = new URL("../node_modules/@aduh95/viz.js/dist/render.wasm", import.meta.url);
initWASM({ locateFile() { return wasmURL; } });

Running Parcel and starting a web server:

> npx parcel serve src/index.html
Server running at http://localhost:1234
✨ Built in 11ms

The web browser I'm using is Chrome version 103.0.5060.13 on Windows 10 64-bit. Opening the Chrome console shows this error:

TypeError: Y.startsWith is not a function
    at L (worker.7fe67360.js:720:18)
    at worker.7fe67360.js:2413:73
    at n (worker.7fe67360.js:2420:6)
    at async worker.7fe67360.js:2491:41

Attached file: worker.7fe67360.js.txt. It is the contents of node_modules/@aduh95/viz.js/dist/render.browser.js with some stuff added by Parcel.

Here's the code where the error happens:

/* 719 */ function L() {
/* 720 */    return Y.startsWith("data:application/octet-stream;base64,");
/* 721 */ }

Here's what happening at the second stack frame:

/* 2413 */ (s1 || "function" != typeof WebAssembly.instantiateStreaming || L() || "function" != typeof fetch ? a49(e96) : fetch(Y, {
/* 2414 */     credentials: "same-origin"
/* 2415 */ }).then(function(n252) {
/* 2416 */     return WebAssembly.instantiateStreaming(n252, i).then(e96, function(n253) {
/* 2417 */         return l1("wasm streaming compile failed: " + n253), l1("falling back to ArrayBuffer instantiation"), a49(e96);
/* 2418 */     });
/* 2419 */ })).catch(t1);

I debug this issue, I edited render.browser.js to add a debugger statement before the error happens to see what's happening:

function L(){debugger; return Y.startsWith("data:application/octet-stream;base64,")}

When you edit render.browser.js, the Parcel web server will automatically re-build, then you need to refresh the page in Chrome.

The L function is called twice:

  • The first time L is called, Y is the string "render.wasm".
  • The second time L is called, Y is a URL object, and Y.toString() returns "http://localhost:1234/render.fc4f61f3.wasm?1659397387600". URL objects do not have a startsWith method!

If I edit render.browser.js to have:

function L(){return Y.toString().startsWith("data:application/octet-stream;base64,")}

Then everything works correctly, and the Chrome console shows an SVG XML file as a string.

Is this a bug in Emscripten??

@aduh95
Copy link
Owner

aduh95 commented Aug 2, 2022

initWASM({ locateFile() { return wasmURL; } });

Did you try to change your locateFile to return String(wasmURL)? I wonder if that would be an easier workaround than changing the emscripten generated file.

Is this a bug in Emscripten??

It could be, it's one of their function, and it looks like it could be improved by adding URL support.

@pfroud
Copy link
Author

pfroud commented Aug 2, 2022

Did you try to change your locateFile to return String(wasmURL)?

I did not try that, good idea, it works, thank you!!!

I think that should be added to the viz.js readme, I submitted a pull request (#28).

pfroud added a commit to pfroud/viz.js that referenced this issue Aug 5, 2022
@pfroud pfroud closed this as completed Aug 5, 2022
pfroud added a commit to pfroud/jeopardy that referenced this issue Aug 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants