Skip to content

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

Description

@pfroud

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??

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions