Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Make Scala.js Wasm backend suitable for standalone Wasm VMs (a.k.a. support "server-side Wasm") #4991

Open
@tanishiking

Description

@tanishiking

Kinda moved from tanishiking/scala-wasm#117

This issue is created as a meta issue to discuss supporting standalone Wasm and the overall approach. For the design and implementation of individual components, separate issues will be created, and the details will be discussed in those respective issues.

The current Scala.js Wasm backend implementation generates a Wasm binary that runs on JavaScript environments such as browsers, Node.js, Deno, and Cloudflare Workers (V8 isolate). However, it does not work on standalone Wasm runtimes such as WasmEdge and wasmtime. Supporting standalone Wasm runtimes would be important to enable Scala to run on Wasm-based cloud/edge computing services, container environments like runwasi, and so on.


To support standalone Wasm runtimes in Scala.js, the following points need to be addressed:

  • Conditional Linking: Introduce a link-time condition or mechanism to allow libraries to switch their implementation based on whether the target is JavaScript Wasm or standalone Wasm.
    • Alternatively, create a separate Intermediate Representation (IR) specifically for standalone Wasm (let's call it SWIR 😄). This would require libraries to build against standalone Wasm in addition to ScalaJVM, Scala.js, and Scala Native (even if there are no changes needed from the Scala.js version). I'm not sure it's a good idea.
  • WASI Support: Implement support for the WASI (at least preview 1 for now) in the scala.scalajs.wasm package.
  • Avoid JavaScript Interop in the Backend: When the target is standalone Wasm, the Wasm backend should avoid using JavaScript interop. This will require changes to various parts of the compiler, such as:
    • String (and some primitive types) implementation needs to be re-implement in pure-wasm, and re-implement box/unbox/typeTest operations. _JSStringOps.
    • Handling of fmod, undefined values, Object.is comparison, makeExportDef function, and closures and so on.
  • Re-implement Libraries: Some parts of the javalib and scalalib need to be re-implemented using pure Scala and Wasm/WASI intrinsics. For example:
    • Math package could be developed using a pure Scala implementation of the fdlibm, similar to how Kotlin/Wasm implemented their math package
    • Regular Expressions: Scala Native has a pure Scala implementation of regular expressions (a port of re2j for Scala), which could be copied or adapted for standalone Wasm in Scala.js?
    • ExecutionContext: Scala.js impl relies on Promise or setTimeout, but we need to re-implement in Wasm.
      • It may not be necessary to support it initially in our stand-alone Wasm backend, until WASI provides more building-blocks in future. ref [Designing an Async Runtime for WASI 0.2 https://blog.yoshuawuyts.com/building-an-async-runtime-for-wasi/]
    • System:
      • PrintStream should be replaced with WASI's fd_write and fd_read functions.
      • currentTimeMillis can be implemented using WASI's lock_time_get function.
      • and so on.
    • There should be much more to consider and re-implement...

Ref


For non-JS hosts, the benefit for users is to target an entirely new ecosystem. In that scenario, we will want to introduce interop features for at least the Component Model of Wasm, and instead remove the JS interop semantics. In that case, we definitely need IR changes. More critically, we will need a link-time way to reliably (i.e., from a reachability point of view) use one path or another. Either we do this with an entirely different ecosystem and IR (SWIR?), or we amend the Scala.js IR. If amending the Scala.js IR is not too disruptive, this would help adoption of Scala-to-Wasm, as the majority of the Scala.js ecosystem of libraries could be reused as is. We would avoid the slow bootstrap problem entirely.

We discussed one possible link-time dispatch mechanism that would fit in the Scala.js IR: a "link-time if-else". Its conditions would be restricted to a few elementary operations, based on a config dictionary of String->Int. For example it might contain "host"->0 for a JS host and "host"->1 for a WASI host. Or a "isWasm"->0/1, which could be used for code paths known to be better for Wasm than for JS (e.g., manipulating Longs more aggressively, or bit-casting between ints and floats, etc.)

#4928 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementFeature request (that does not concern language semantics, see "language")languageAffects language semantics.wasmApplies to the WebAssembly backend only

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions