Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add Support for Wasm Component Model and WASIp2 #5121

Open
Labels
wasmApplies to the WebAssembly backend only
@tanishiking

Description

@tanishiking

PoC implementation is going on here:https://github.com/scala-wasm/scala-wasm

Background

This issue is part of#4991 to support "server-side Wasm"

To support "server-side Wasm", we have to remove all the JS dependencies.WASI (WebAssembly System Interface) allows us to implement standard libraries that interact with systems (e.g.println usingget-stdout from WASIp2) without JS.

This issue discusses how do we supportWASI Preview2 (WASIp2) andWasm Component Model in Scala.js Wasm backend.

Wasm Component Model

The Wasm Component Model provides:

  1. Anew binary format calledcomponent that encapsulates traditional Wasm modules.
  2. AWIT (WebAssembly Interface Type) IDL for defining interfaces and types in a language-agnostic way.
  3. ACanonicalABI for standardizing how complex types like strings and structs are represented and exchanged between components.

Once we write a WIT, tools likewit-bindgen would generate bindings for any languages that supports Component Model. (people say "SDKs for free").

Additionally, unlike the traditional interop approach in Wasm, components avoid directly exposing linear memory, and thus it leads reducing the attack surface.

WASI preview2 (WASIp2)

WASI is a set of standardized APIs that allow Wasm modules to interact with system resources (e.g., files, networks, environment variables) in a portable way.WASI Preview2 (WASIp2) is the next version of WASI, designed based on Wasm Component Model.

**Design choice: why WASIp2 instead of WASIp1?**

One of the challenges of adopting WASIp2 is their current immaturity, as not many VMs and tools support them yet1. It might be safer to stick with WASI Preview1 (WASIp1), which is very stable and widely supported by many VMs and tools?

Why we didn't go with WASIp1
Previously, we prototyped server-side Wasm support using WASIp1 inthis issue.
We realized that supporting WASIp1 leads to introducing memory-related APIs (e.g., allocate/free and load/store operations on Wasm linear memory) at Scala.js source level and/or hard-code every WASIp1 functions in standard libraries since we couldn't find clear instruction how the "high-level structs" should be serialized into core Wasm values.

However, we don't like to expose such "unsafe" memory APIs in the Scala.js language, even if the "unsafe" parts of the code would typically be generated by tools likewit-bindgen. At the source language and Scala.js IR level, these low-level details should be abstracted away and handled by the linker backend, rather than being exposed to developers.

WASIp2
The Wasm Component Model provides clear instructions on how high-level interface types should be serialized and deserialized through the Canonical ABI. This allows us to implement the serialization and deserialization logic for linear memory (or on the stack) within the Wasm linker backend, without exposing memory APIs to developers.

We never support WASIp1?
Depending on the future status of WASIp2 support, we might also want to support WASIp1. In that case, we would need to carefully examine the WASIp1witx definitions, and it might be possible to identify high-level types and serialization/deserialization mechanisms similar to those in the Component Model.
https://github.com/WebAssembly/WASI/blob/40019a6181352388397b5b903740f29b26742146/legacy/preview1/witx/wasi_snapshot_preview1.witx

TL;DR: WIP demo

I have a PoC implementation for Wasm Component Model support in the forked repository:scala-wasm#5

packagetanishiking:test@0.0.1;// Scalaworldsocket {importtest;importwasi:cli/stdout@0.2.0;exportwasi:cli/run@0.2.0;}// Rustworldplug {exporttest;}interfacetest {ferris-say:func(content:string,width:u32)->string;}
// Cli.scalaobjectRun {@ComponentExport("wasi:cli/run@0.2.0","run")defrun(): component.Result[Unit,Unit]= {valout=Stdio.getStdout()valferris=Test.ferrisSay("Hello Scala!",80)    out.blockingWriteAndFlush(ferris.getBytes())    component.Ok(())  }}objectTest {@ComponentImport("tanishiking:test/test@0.0.1","ferris-say")defferrisSay(content:String,width:UInt):String= component.native}// Stdio.scalaobjectStdio {@ComponentImport("wasi:cli/stdout@0.2.0","get-stdout")defgetStdout():OutputStream= component.native}@ComponentResourceImport("wasi:io/streams@0.2.0")traitOutputStreamextends component.Resource {@ComponentResourceMethod("blocking-write-and-flush")defblockingWriteAndFlush(contents:Array[UByte]): component.Result[Unit,StreamError]}
#[allow(warnings)]mod bindings;usecrate::bindings::exports::tanishiking::test::test::Guest;use ferris_says::say;structComponent;implGuestforComponent{fnferris_say(content:String,width:u32) ->String{letmut buf =Vec::new();say(content.as_str(), width.try_into().unwrap(),&mut buf).unwrap();returnString::from_utf8(buf).unwrap();}}bindings::export!(Component with_types_in bindings);
$ wasm-tools component embed wit examples/helloworld/.2.12/target/scala-2.12/hello-world-scalajs-example-fastopt/main.wasm -o main.wasm -w socket --encoding utf16$ wasm-tools component new main.wasm -o main.wasm$ wac plug --plug plugin/target/wasm32-wasip1/release/plugin.wasm main.wasm -o out.wasm$ wasmtime -W function-references,gc out.wasm ______________< Hello Scala!> --------------        \         \            _~^~^~_\) /  o o\(/'_   -   _'          /'-----' \

(Note that the wasm-tools, wasmtime, and wac might need to be updated or built from source2.)

Footnotes

  1. wasmtime supports it /WasmEdge is WIP /WAMR seems to be willing to support but not yet /wazero won't support it until it's standardized /WasmKit is WIP

  2. wasmtime needs to be compiled from source or usev30>= in future? forhttps://github.com/bytecodealliance/wasmtime/pull/9952 that includes a fix in wasm-toolshttps://github.com/bytecodealliance/wasm-tools/pull/1968. Andwac also needs to be compiled from source or0.6.2>= forhttps://github.com/bytecodealliance/wac/pull/146

Metadata

Metadata

Assignees

No one assigned

    Labels

    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


      [8]ページ先頭

      ©2009-2025 Movatter.jp