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

[dart2wasm] Support non-JS wasm runtimes #53884

Open
eyebrowsoffire opened this issue Oct 27, 2023 · 12 comments
Open

[dart2wasm] Support non-JS wasm runtimes #53884

eyebrowsoffire opened this issue Oct 27, 2023 · 12 comments
Labels
area-dart2wasm Issues for the dart2wasm compiler.

Comments

@eyebrowsoffire
Copy link
Contributor

eyebrowsoffire commented Oct 27, 2023

We eventually may want dart2wasm to actually work in non-JavaScript environments (wasmtime, wasmer, etc). @askeksa had mentioned a list of a few things that would definitly need to be addressed in order to remove the dependency on a JS/browser environment:

We are currently dependent on JS for the following components:

  • Event loop
  • Printing
  • OS-level timer features, such as current time
  • Weak maps, weak references, finalizers
  • Stack traces
  • Conversions between double and String
  • Regexps
  • Math functions (sin, pow, exp, etc.)

For each of these, we'll have to either:

  • (1) implement the feature in Dart (or intrinsically in the compiler),
  • (2) link to an implementation compiled to Wasm, or
  • (3) import an external implementation from the host.
@kripken
Copy link

kripken commented Oct 27, 2023

Can existing JS solutions for those environments help here? That is, Javy and spidermonkey.wasm and similar projects compile a JS VM into wasm, so it can run in a non-JS wasm environment. If that JS happens to use wasm, it seems like that wasm could be bundled alongside the compiled JS VM, and "just work" with some glue (e.g. spidermonkey already has wasm support; it would just need to be "pointed" to the bundled wasm rather than to interpret it).

The wasm would run at full speed, and the JS is apparently fast enough for those environments, so this seems viable. Perhaps someone has already done it?

If that existed, then dart2wasm and other toolchains would not need to do any special work to port to non-JS environments (no more than people wanting to run JS there, which is considered a solved problem).

edit: stack traces would not fully work, but all the other bullet points above should be fine (math, regexes, etc., are all in the compiled JS VM).

@eyebrowsoffire
Copy link
Contributor Author

Yeah I contemplated something like the spidermonkey.wasm might be an interesting idea. Off-hand, it might be even more effective for WasmGC modules with a thin JS support runtime attached, rather than a large blob of JS. I don't know what kind of optimizations are done for the JS VM snapshot build, but a "whole world analysis" on the JS support runtime could probably lead to pruning a lot of code out of the JS VM.

@lrhn lrhn added the area-dart2wasm Issues for the dart2wasm compiler. label Oct 27, 2023
@yjbanov
Copy link

yjbanov commented Nov 1, 2023

  • (4) Exclude the feature, as it may only makes sense within JS environments. For example, the event loop is a very particular type of code execution model that came to most mainstream languages from JS (e.g. Dart, TypeScript, AssemblyScript), which the host will have to support to enable all the event loop type features in Dart (e.g. futures, microtasks, async/await, streams). However, outside the JS environment, there may be sufficiently large categories of programs/libraries that would not need the event loop, and so it may be useful to have a compilation mode that does not rely on it. There's certainly a subset of the Dart language and libraries that don't need it.
  • (5) Add the feature as a standard to either Wasm or WASI. Back to the event loop example, if we recognize that it covers a sufficient set of use-cases (such as how it happened for WasmGC), then it may make sense to standardize for event loop-based languages to be able to target all standalone Wasm runtimes that provide it. Dart may not be the only language wanting it. AssemblyScript seems to want it too, and there may be others.

@askeksa
Copy link
Contributor

askeksa commented Nov 2, 2023

Stack traces could be a good candidate for (5), since it will be difficult to do without support from the engine.

@lesnitsky
Copy link

Add the feature as a standard to either Wasm or WASI

@yjbanov does this remark mean that Dart will support WASI as a compilation target?

@zacharypuulsedev
Copy link

This would be amazing to support better serverless, and general flexible compute, using Dart.

Being able to easily deploy dart applications that are a collection of WASM modules would be revolutionary. Dart is a great language for glueing together libraries quickly, and leveraging existing libraries across languages (esp. rust) that can be compiled to WASM would expand the ecosystem so tremendously.

While this is already possible with https://pub.dev/packages/wasm_run, it would be great to further the interoperability and deployment process. This would be especially useful when trying to deploy cross platform applications that currently use FFI and native compiled libraries for each supported platform. In the highest performance applications, FFI and native code may still be desirable, but for a vast majority of applications, the ease of quickly composing applications and innovating has huge value.

Advantages

  • Easy interop with other WASM modules/cross language support
    • LLMs/Langchains
    • High performance Rust crates
    • Broad library/language support
  • Flexible deployment (Web, Cloud, Native)
  • Architecture interoperability (ex. compiling on arm64 and running on x64)
  • Ability to run on edge networks
  • Faster cold starts (vs docker containers)
  • Lower memory (vs docker containers)
  • Sandboxing and running sandboxed code

Implementation:

  1. SpiderMonkey.wasm (mentioned above seems like a great start)
  2. Use rust crates to implement missing functionality; Either compile with binary, or link via WASM modules if the wasm module boundary doesn't have too high of a performance penalty.
  3. Upstream support into WASM/WASI spec for managed languages (Go, Python, Typescript, etc..)

--

Regardless of approach taken, facilitating the deployment of applications that are collections of Wasm modules seems like the natural evolution of docker containerization, with even greater platform flexibility, and a higher degree of composability into ever larger applications or pipelines (eg. langchains, llms, sandboxed user code, etc)

@bivens-dev
Copy link

I saw some mention of SpiderMonkey from @yjbanov and others. I was wondering if this offshoot helps move things any closer as a possibility at all.

StarlingMonkey is a SpiderMonkey based JS runtime optimized for use in WebAssembly Components. StarlingMonkey's core builtins target WASI 0.2.0 to support a Component Model based event loop and standards-compliant implementations of key web builtins, including the fetch API, WHATWG Streams, text encoding, and others. To support tailoring for specific use cases, it's designed to be highly modular, and can be readily extended with custom builtins and host APIs.

source: https://github.com/bytecodealliance/StarlingMonkey

@iapicca
Copy link

iapicca commented May 9, 2024

I saw some mention of SpiderMonkey from @yjbanov and others. I was wondering if this offshoot helps move things any closer as a possibility at all.

StarlingMonkey is a SpiderMonkey based JS runtime optimized for use in WebAssembly Components. StarlingMonkey's core builtins target WASI 0.2.0 to support a Component Model based event loop and standards-compliant implementations of key web builtins, including the fetch API, WHATWG Streams, text encoding, and others. To support tailoring for specific use cases, it's designed to be highly modular, and can be readily extended with custom builtins and host APIs.

source: https://github.com/bytecodealliance/StarlingMonkey

is there a way to use dart2JS to compile a non-web target?
it would be very useful to use dart in fermyon

@maks
Copy link

maks commented May 9, 2024

Yes 💯 @iapicca I have just run into an almost identical use case myself. For my product, I need to compile Dart to JS to run in a embedded JS engine, initially I'm targeting Duktape. I was actually trying to use the DDC for this but the removal of the ability to use it directly via the dart cli command in favour of webserve is very annoying and the best I've found so far is to use --no-release with the build command.

I'm very open to even some pointers from the Dart team about where to go look for underlying Dart compiler APIs thar could used as ideally I want to be able to just compile sets of stand alone functions from one or several Dart libraries (ie. files) and not use a main() entry point at all.

@sigmundch
Copy link
Member

Yes, Dart supports running the JS generated from Dart in JavaScript engines outside browsers. We use this for testing, some teams use it to run Dart applications in node.js too. Some details:

compiler
We don't recommend using the DDC compiler for that. Our recommended approach to use dart2js via dart compile js --server-mode. The --server-mode flag makes browser based libraries like dart:html inaccessible and allows you to use the output of dart2js more easily in those environments. Technically the flag is not required, but it's good practice.

preambles
Code generated by the compiler requires a couple APIs to be available from the engine (imagine APIs like setTimeout, critical to schedule microtasks and other low-level features in Dart). Some of these APIs are usually found in browsers, but may need to be polyfilled for standalone engines.

For that purpose we require a "preamble" file that is customized for the engine that you will be using. We already provide preambles in the Dart SDK for two common engines js-shell and d8. The community currently maintains a preamble for node.js in package:node_preamble.

examples
sass is written in Dart but runs in node.js and is distributed as a npm package. It is a great example that uses node_preamble.

Our team wrote the generator of package:web to run in node. This program needed very little from the Dart language, so we ended up creating a custom and over-simplified preamble for it. It may not be the best example of a preamble, but it illustrates how it all gets integrated together.

@maks
Copy link

maks commented May 11, 2024

Thanks so much for all that information @sigmundch ! 👍🏻 to say that it is super useful is an understatement!

I didn't know about --server-mode, thats very helpful too. Nor about the preambles, again very useful!

@yanglaolee
Copy link

yanglaolee commented May 15, 2024

We need to run Flutter/Dart code directly on WASI, this is the future.
I prefer method (1)

It has broad application scenarios in the blockchain field. We use wasmer as the smart contract engine of the blockchain. Currently, the assets it manages are billions of dollars.

Once Flutter supports compilation to WASI, we can develop a unified front-end on any device, and the underlying layer is your assets protected by the blockchain.

Can we implement this feature as soon as possible?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-dart2wasm Issues for the dart2wasm compiler.
Projects
None yet
Development

No branches or pull requests