Just reporting two libs I tried to use that didn't work for me 😉 (elkjs & netlistsvg)
Describe the bug
I wanted to try if I could use boa in my statically generated blog, to render circuit diagrams using two open-source JS libs (netlistsvg + elkjs), which IIUC seem quite self-contained when taken as a pair. I'm not sure how to do this with the CLI, and also at least one of them seems to throw an error.
To Reproduce
$ cargo install --version 0.20.0 boa_cli
$ curl -O https://unpkg.com/[email protected]/built/netlistsvg.bundle.js
$ curl -O https://unpkg.com/[email protected]/lib/elk.bundled.js
$ boa elk.bundled.js
undefined
$ # ok, this seemed to kinda work; can I use it as a module? is this the way?
$ boa -m elk.bundled.js
Uncaught TypeError: cannot convert 'null' or 'undefined' to object
$ # uh, this didn't seem to go well :( let's see what happens if I try netlistsvg:
$ boa netlistsvg.bundle.js
Uncaught TypeError: not a constructor
$ # oops, this didn't seem to work even without -m :(
$ # also, how can I then use those from a non-module script? should I use -m or not use -m?
Expected behavior
-
no
Uncaught TypeErrorlines -
some example in
--helphow can I run a simple script with those libraries - for example, I could imagine something like:$ boa --require elk=elk.bundled.js --require netlistsvg=netlistsvg.bundle.js --expression "netlistsvg.render(netlistsvg.digitalSkin, netlistsvg.exampleDigital, (err, result) => console.log(result));"
Build environment (please complete the following information):
- OS: Windows
- Version: 10
- Target triple: ?
- Rustc version: rustc 1.85.0 (4d91de4e4 2025-02-17)
Additional context
netlistsvg simple call example via script tag: https://github.com/nturley/netlistsvg?tab=readme-ov-file#web-bundle
<script type="text/javascript" src="https://nturley.github.io/netlistsvg/elk.bundled.js"></script>
<script type="text/javascript" src="https://nturley.github.io/netlistsvg/built/netlistsvg.bundle.js"></script>
netlistsvg.render(netlistsvg.digitalSkin, netlistsvg.exampleDigital, (err, result) => console.log(result));
For starters, could you help me maybe is there a way how could I try to get some more details about the error if I wanted to check if I can attempt to fix it?
Hi! Thanks for letting us know. Unfortunately, to get more information from errors, we'd need to implement backtraces and span nodes (we have open issues for these topics, but haven't implemented them just yet), which would be really great in this use case.
I'm not exactly familiar with the above packages. At a quick glance, it looks like these may be using some runtime features, which may be where the error is coming from. Boa is an engine / interpreter, not a runtime. While we implement some runtime features, some functionality that is provided by Nodejs and browsers, may not be available when using the engine directly.
Thanks! So, that would be #3726 and #300 respectively, yes?
As to the libs, I would think they should not need runtime features; but I may be wrong (though I wonder what would they need them for? 🤔)
elk needs to provide a worker when running, llrt and txiki.js including boa cannot run
if (!optionsClone.workerFactory) {
var _require = require('./elk-worker.min.js'),
_Worker = _require.Worker;
optionsClone.workerFactory = function (url) {
return new _Worker(url);
};
}
const ELK = require("./elk.bundled.js")
globalThis.ELK = ELK
const netlistsvg = require("./netlistsvg.bundle.js")
netlistsvg.render(netlistsvg.digitalSkin, netlistsvg.exampleDigital, (err, result) => console.log(result));
https://github.com/boa-dev/boa/pull/4292 is in full swing, and i see you've raised https://github.com/boa-dev/boa/issues/4280, although i should point out this issue is more of a runtime issue than an engine one, you could try and have a go implementing it as our runtime is very thin so far.
Are there any other runtime issues to report or are we waiting for the span errors PR to see what is happening.
$ # uh, this didn't seem to go well :( let's see what happens if I try netlistsvg: $ boa netlistsvg.bundle.js Uncaught TypeError: not a constructor
This is because you're running this library standalone and ELK doesn't exist (new ELK()) so this failure is expected.
Are there any other runtime issues to report or are we waiting for the span errors PR to see what is happening[?]
@jasonwilliams FWIW, assuming this is a question, I'm still not sure what's the proper way "how can I run a simple script with those libraries" (quote from Expected Behavior point 2 in the ticket above). (Please note my knowledge of JS is very low.) In #4280, and above, @ahaoboy proposes the following script:
const ELK = require("./elk.bundled.js")
globalThis.ELK = ELK
const netlistsvg = require("./netlistsvg.bundle.js")
netlistsvg.render(netlistsvg.digitalSkin, netlistsvg.exampleDigital, (err, result) => console.log(result));
but when I pasted it to a test.js file and tried to run it, I got:
$ boa test.js
Uncaught ReferenceError: require is not defined
Should I use the -m option, like maybe boa -m elk.bundled.js -m netlistsvg.bundle.js test.js? But in such case, how do I reference the modules afterwards in test.js? are they predefined in some global variables after being imported with -m? In the test.js proposal above from @ahaoboy , there's a globalThis.ELK = ELK done before importing netlistsvg.bundle.js - is there a way I could do this in boa between the -ms? Or, is the only option to somehow paste both bundled js files into test.js as closures, to make it a single huge js amalgam file, and then pass this file to boa?
In other words:
This is because you're running this library standalone and ELK doesn't exist (
new ELK()) so this failure is expected.
Ok, but in boa, how do I do this - how do I define/run new ELK() before running netlistsvg.bundle.js?
Yeah require won’t exist as that’s a nodejs thing, at the very least you’re going to need ESM syntax.
Paging @hansl who deals with the runtime side of things.
You can evaluate multiple files at the same time
boa elk.bundled.js netlistsvg.bundled.js main.js
Bundle files are just meant to be run as simple scripts, and the bundle should automatically insert its exports into the global object. Still don't know if this will work without Workers though
We might be able to implement require at some point but it hasn't been a priority. You can use a bundler like webpack/rollup/esbuild (or other) to remove the require calls.
I can look at it sometimes next week and give you some instructions. I have used many packages from NPM in boa with success, including native node apis (caveat: with their poly fills). This should definitely be possible.