boa icon indicating copy to clipboard operation
boa copied to clipboard

Just reporting two libs I tried to use that didn't work for me 😉 (elkjs & netlistsvg)

Open akavel opened this issue 9 months ago • 10 comments

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

  1. no Uncaught TypeError lines

  2. some example in --help how 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));

akavel avatar Mar 22 '25 10:03 akavel

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?

akavel avatar Mar 29 '25 13:03 akavel

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.

nekevss avatar Mar 29 '25 14:03 nekevss

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

akavel avatar Mar 30 '25 00:03 akavel

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));

ahaoboy avatar Jun 10 '25 13:06 ahaoboy

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.

jasonwilliams avatar Jun 25 '25 20:06 jasonwilliams

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?

akavel avatar Jun 26 '25 09:06 akavel

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.

jasonwilliams avatar Jun 26 '25 09:06 jasonwilliams

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

jedel1043 avatar Jun 26 '25 13:06 jedel1043

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.

hansl avatar Jun 26 '25 18:06 hansl

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.

hansl avatar Jun 26 '25 18:06 hansl