diff --git a/.cargo/config.toml b/.cargo/config.toml index 79d08f1d..d64d61cd 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -2,11 +2,9 @@ runner = 'wasmtime run --dir=.::/cwd --dir=. --dir=/tmp -Sinherit-env=y,inherit-network=y,http=y,tcp=y,udp=y -C native-unwind-info=n' [target.wasm32-wasip2] -# Keep in sync with the RUSTFLAGS overrides in scripts/build-runtime.sh and scripts/build-dylib.sh. rustflags = ["-C", "target-feature=+simd128"] runner = 'wasmtime run --dir=.::/cwd --dir=. --dir=/tmp -Sinherit-env=y,inherit-network=y,http=y,tcp=y,udp=y -C native-unwind-info=n' [target.wasm32-wasip3] -# Keep in sync with the RUSTFLAGS overrides in scripts/build-runtime.sh and scripts/build-dylib.sh. rustflags = ["-C", "target-feature=+simd128"] runner = 'wasmtime run --dir=.::/cwd --dir=. --dir=/tmp -Sinherit-env=y,inherit-network=y,http=y,tcp=y,udp=y -C native-unwind-info=n' diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 1931ac32..cfe0dc66 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0-WITH-LLVM-exception name: Setup build environment -description: Install system deps, Rust toolchain, WASI SDK, wasmtime, and configure sccache. +description: Install system deps, Rust toolchain, WASI SDK, wasmtime, wasm-tools, and configure sccache. inputs: target: @@ -10,19 +10,20 @@ inputs: runs: using: composite steps: + - name: Add the tool versions to the environment + shell: bash + run: grep -v '^#' "${{ github.action_path }}/../../tool-versions.env" >>"$GITHUB_ENV" + - name: Install system dependencies shell: bash run: | sudo apt-get update sudo apt-get install -y build-essential python3 m4 libclang-dev llvm + # `install-tool.sh` checks each download's SHA-256 digest. - name: Install just shell: bash - run: | - mkdir -p "$HOME/.just/bin" - curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh \ - | bash -s -- --to "$HOME/.just/bin" - echo "$HOME/.just/bin" >> "$GITHUB_PATH" + run: ${{ github.action_path }}/install-tool.sh just - name: Install Rust toolchain shell: bash @@ -34,30 +35,30 @@ runs: run: rustup target add wasm32-wasip2 # The pinned toolchain ships no wasm32-wasip3 std, so the justfile builds that target with the - # nightly toolchain `STARLING_NIGHTLY` names. The pinned toolchain is still needed for the + # beta toolchain `STARLING_BETA` names. The pinned toolchain is still needed for the # host-side test harnesses. - - name: Install nightly Rust toolchain with the wasm32-wasip3 target + - name: Install beta Rust toolchain with the wasm32-wasip3 target if: inputs.target == 'wasm32-wasip3' shell: bash run: | - rustup toolchain install "$STARLING_NIGHTLY" --profile minimal --target wasm32-wasip3 - rustc "+$STARLING_NIGHTLY" --version + rustup toolchain install "$STARLING_BETA" --profile minimal --component clippy \ + --target wasm32-wasip3 + rustc "+$STARLING_BETA" --version - name: Install WASI SDK if: inputs.target != 'native' shell: bash - run: | - sudo mkdir -p /opt/wasi-sdk - curl -sSfL "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_VERSION}.0-x86_64-linux.tar.gz" \ - | sudo tar xz --strip-components=1 -C /opt/wasi-sdk - echo "WASI_SDK_PATH=/opt/wasi-sdk" >> "$GITHUB_ENV" + run: ${{ github.action_path }}/install-tool.sh wasi-sdk - name: Install wasmtime if: inputs.target != 'native' shell: bash - run: | - curl -sSf https://wasmtime.dev/install.sh | bash -s -- --version "v$WASMTIME_VERSION" - echo "$HOME/.wasmtime/bin" >> "$GITHUB_PATH" + run: ${{ github.action_path }}/install-tool.sh wasmtime + + - name: Install wasm-tools + if: inputs.target != 'native' + shell: bash + run: ${{ github.action_path }}/install-tool.sh wasm-tools - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.9 + uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11 diff --git a/.github/actions/setup/install-tool.sh b/.github/actions/setup/install-tool.sh new file mode 100755 index 00000000..404c0d87 --- /dev/null +++ b/.github/actions/setup/install-tool.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0-WITH-LLVM-exception +# +# Download the x86_64 Linux release of a tool at the version `.github/tool-versions.env` names, +# check its SHA-256 digest against the digest listed below for that version, install it, and add +# it to `GITHUB_PATH`. The WASI SDK goes to /opt/wasi-sdk, which `WASI_SDK_PATH` is set to in +# `GITHUB_ENV`, and the other tools go to `~/./bin`. A version without a listed digest +# fails. +# +# Usage: +# install-tool.sh + +set -euo pipefail + +TOOL="$1" +# shellcheck source=../../tool-versions.env +. "$(dirname "$0")/../../tool-versions.env" +case "$TOOL" in + just) VERSION="$JUST_VERSION" ;; + wasi-sdk) VERSION="$WASI_SDK_VERSION" ;; + wasmtime) VERSION="$WASMTIME_VERSION" ;; + wasm-tools) VERSION="$WASM_TOOLS_VERSION" ;; + *) echo "unknown tool $TOOL" >&2; exit 1 ;; +esac +GH=https://github.com + +case "$TOOL-$VERSION" in + just-1.58.0) + URL="$GH/casey/just/releases/download/$VERSION/just-$VERSION-x86_64-unknown-linux-musl.tar.gz" + SHA256=4a5cc2f53e6f0f8c59092a6cc38291eb729d46a7dd95d3ae582008881b84931d + ;; + wasi-sdk-34) + URL="$GH/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$VERSION/wasi-sdk-$VERSION.0-x86_64-linux.tar.gz" + SHA256=b761e3a0721dbae9c09a0059e5fdb2bf917d1b4a8a7b430fb3b5aafb0984b2c4 + ;; + wasmtime-50.0.0) + URL="$GH/bytecodealliance/wasmtime/releases/download/v$VERSION/wasmtime-v$VERSION-x86_64-linux.tar.xz" + SHA256=77c19ee0437991f9ac7837b9c269d9c7076744f85dad263fea5214cc2723c7ff + ;; + wasm-tools-1.262.0) + URL="$GH/bytecodealliance/wasm-tools/releases/download/v$VERSION/wasm-tools-$VERSION-x86_64-linux.tar.gz" + SHA256=655b8df67d54c3ef9b52fc237c4e94bbfbb5f5f43825245cb0940a7002a9ed65 + ;; + *) + echo "No SHA-256 digest for $TOOL $VERSION. Add it to $0." >&2 + exit 1 + ;; +esac + +TMP="$(mktemp -d)" +trap 'rm -rf "$TMP"' EXIT +ARCHIVE="$TMP/$(basename "$URL")" +curl --fail --silent --show-error --location -o "$ARCHIVE" "$URL" +ACTUAL="$(sha256sum "$ARCHIVE" | cut -d' ' -f1)" +if [[ "$ACTUAL" != "$SHA256" ]]; then + echo "SHA-256 mismatch for $URL:" >&2 + echo " expected $SHA256" >&2 + echo " got $ACTUAL" >&2 + exit 1 +fi + +case "$TOOL" in + just) + mkdir -p "$HOME/.just/bin" + tar -xzf "$ARCHIVE" -C "$HOME/.just/bin" just + echo "$HOME/.just/bin" >>"$GITHUB_PATH" + ;; + wasi-sdk) + sudo rm -rf /opt/wasi-sdk + sudo mkdir /opt/wasi-sdk + sudo tar -xzf "$ARCHIVE" --no-same-owner --strip-components=1 -C /opt/wasi-sdk + echo "WASI_SDK_PATH=/opt/wasi-sdk" >>"$GITHUB_ENV" + ;; + wasmtime) + mkdir -p "$HOME/.wasmtime/bin" + tar -xJf "$ARCHIVE" --strip-components=1 -C "$HOME/.wasmtime/bin" "wasmtime-v$VERSION-x86_64-linux/wasmtime" + echo "$HOME/.wasmtime/bin" >>"$GITHUB_PATH" + ;; + wasm-tools) + mkdir -p "$HOME/.wasm-tools/bin" + tar -xzf "$ARCHIVE" --strip-components=1 -C "$HOME/.wasm-tools/bin" "wasm-tools-$VERSION-x86_64-linux/wasm-tools" + echo "$HOME/.wasm-tools/bin" >>"$GITHUB_PATH" + ;; +esac diff --git a/.github/tool-versions.env b/.github/tool-versions.env new file mode 100644 index 00000000..d8f62a52 --- /dev/null +++ b/.github/tool-versions.env @@ -0,0 +1,12 @@ +# The tool versions CI and releases install. The setup action adds them to the job's environment, +# and `actions/setup/install-tool.sh` installs the version given here, checking the digest it +# lists for it. A new release changes nothing until these are bumped. +JUST_VERSION=1.58.0 +WASI_SDK_VERSION=34 +# The wasmtime CLI the wasm tests run under, and the wasm-tools CLI `scripts/build-runtime.sh` +# wraps the runtime with, each at the version of the crates `componentize/Cargo.lock` holds. +WASMTIME_VERSION=50.0.0 +WASM_TOOLS_VERSION=1.262.0 +# The beta toolchain wasm32-wasip3 builds use. +STARLING_BETA=beta-2026-10-18 +NODE_VERSION=24.21.0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 693a9305..8c974a0c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,14 +16,13 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: 0 - WASI_SDK_VERSION: "34" - # The wasmtime CLI the wasm tests run under, and the nightly toolchain wasm32-wasip3 builds use. - # Both are pinned, so a new release changes nothing until these are bumped. - WASMTIME_VERSION: "49.0.0" - STARLING_NIGHTLY: nightly-2026-09-24 + # The setup action adds the tool versions of `.github/tool-versions.env`. RUSTC_WRAPPER: sccache CCACHE: sccache # Bump to purge the sccache GHA cache. @@ -37,7 +36,7 @@ jobs: name: Lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: ./.github/actions/setup with: @@ -49,9 +48,33 @@ jobs: - name: Run clippy run: just clippy --all + - name: Run the componentizer's unit tests + run: just test-componentize-unit + + # --------------------------------------------------------------------------- + # The `init` interface between the runtime and the componentizer + # (`starling/wit/init.wit`) changes only with a version not compatible with the latest + # release's, since the componentizer accepts runtimes with a compatible version. + # --------------------------------------------------------------------------- + init-wit: + name: init.wit versioning + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + # The release tags the check compares with. + fetch-depth: 0 + + - name: Install wasm-tools + run: ./.github/actions/setup/install-tool.sh wasm-tools + + - name: Check init.wit's version + run: ./scripts/check-init-wit.sh + # --------------------------------------------------------------------------- # Cargo tests: {native, wasm32-wasip2, wasm32-wasip3} × {debug+debugmozjs, release} - # The wasm recipes also run the serve end-to-end suite (`just test-serve-wasm`). + # The wasm recipes also run the serve end-to-end suite (`just test-serve-wasm`). The debug wasm + # jobs first lint the code each wasm target compiles (`just clippy-wasm`). # --------------------------------------------------------------------------- test: name: Test (${{ matrix.target }}, ${{ matrix.profile }}) @@ -74,12 +97,16 @@ jobs: WASMTIME_BACKTRACE_DETAILS: '1' RUST_BACKTRACE: 'full' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: ./.github/actions/setup with: target: ${{ matrix.target }} + - name: Run clippy for the wasm target + if: matrix.target != 'native' && matrix.profile == 'debug' + run: just clippy-wasm + - name: Run tests run: just ${{ matrix.recipe }} @@ -87,6 +114,43 @@ jobs: if: matrix.target != 'native' run: just ${{ matrix.recipe }} --examples + # --------------------------------------------------------------------------- + # Componentization suites against the debug runtime (`just test-componentize`). + # That recipe builds the runtime for wasm32-wasip3, the target the componentizer + # links against, so this job installs beta and a wasi-sdk with a sysroot for it. + # --------------------------------------------------------------------------- + componentize: + name: Componentize + runs-on: ubuntu-latest + env: + WASMTIME_BACKTRACE_DETAILS: '1' + RUST_BACKTRACE: 'full' + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - uses: ./.github/actions/setup + with: + target: wasm32-wasip3 + + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: ${{ env.NODE_VERSION }} + + # `--tests` includes the `wit_to_ts` suite, which type-checks its output. + - name: Install the TypeScript compiler + run: npm ci + + - name: Build the debug runtime and run the componentization suites + run: just test-componentize + + # Runs scripts and a late-rejecting top level with the debug runtime component itself. + - name: Run scripts with the runtime component + run: just test-runtime + + # Snapshots with `wizer-initialize`, including CLI tools whose `run` export a snapshot calls. + - name: Test Wizer snapshots + run: WASM_TARGET=p3 just test-wizer + # --------------------------------------------------------------------------- # WPT suite: {native, wasm32-wasip2, wasm32-wasip3} # --------------------------------------------------------------------------- @@ -102,15 +166,15 @@ jobs: WASMTIME_BACKTRACE_DETAILS: '1' RUST_BACKTRACE: 'full' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: ./.github/actions/setup with: target: ${{ matrix.target }} - - uses: actions/setup-node@v4 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: - node-version: "lts/*" + node-version: ${{ env.NODE_VERSION }} - name: Clone WPT suite run: ./scripts/clone-wpt.sh @@ -135,25 +199,44 @@ jobs: gc_rooting: name: GC Rooting Checks - strategy: - fail-fast: false runs-on: ubuntu-latest env: RUST_BACKTRACE: full steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + # `just check-gc` also checks the wasm32-wasip2 build, which needs the target's std and the + # WASI SDK, and runs crown's own tests. - uses: ./.github/actions/setup with: - target: native + target: wasm32-wasip2 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: - node-version: "lts/*" + node-version: ${{ env.NODE_VERSION }} - name: Crown static analysis - run: | - ./scripts/check-crown.sh --workspace --examples + run: just check-gc + + # --------------------------------------------------------------------------- + # GC zeal tests of the default `scripts/test-gc-zeal.sh` packages, each shard + # running every third mode of the full set. + # --------------------------------------------------------------------------- + gc_zeal: + name: GC Zeal (${{ matrix.shard }}/3) + strategy: + fail-fast: false + matrix: + shard: [1, 2, 3] + runs-on: ubuntu-latest + env: + RUST_BACKTRACE: full + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - uses: ./.github/actions/setup + with: + target: native - name: GC Zeal tests - run: just gc-zeal --zeal full --examples --workspace \ No newline at end of file + run: just gc-zeal --zeal full --shard ${{ matrix.shard }}/3 \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..b2f7e538 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,238 @@ +# SPDX-License-Identifier: Apache-2.0-WITH-LLVM-exception + +# Release the runtime and `starling-componentize` together, under the workspace's version in the +# repository's `Cargo.toml`, which `componentize/Cargo.toml` repeats. Build the release runtime, +# `starling-componentize` for every platform of `componentize/npm/platforms.json` with that runtime +# embedded, and the npm packages `componentize/npm/package.mjs` assembles from them. The +# assembly fails unless the matrix below built a binary for every platform. +# +# A `v` tag, which must name the workspace's version, publishes the npm packages and +# creates a GitHub release with `starling.wasm`, each platform's `starling-componentize` and a +# `SHA256SUMS` file of their digests. A manual run publishes the npm packages only with `publish` +# set, and otherwise runs `npm publish --dry-run`. Every run uploads the packages' tarballs as the +# `npm-tarballs` artifact. + +name: Release + +on: + push: + tags: ["v*"] + workflow_dispatch: + inputs: + publish: + description: Publish the packages to npm, rather than doing a dry run + type: boolean + default: false + version: + description: >- + The npm packages' version, such as 0.3.0-preview.1. Defaults to the workspace's + version in Cargo.toml + type: string + default: "" + +defaults: + run: + shell: bash + +permissions: + contents: read + +env: + CARGO_TERM_COLOR: always + # The setup action adds the tool versions of `.github/tool-versions.env`. + RUSTC_WRAPPER: sccache + CCACHE: sccache + SCCACHE_GHA_VERSION: 1 + +jobs: + runtime: + name: Build the runtime + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + # The release tags `check-init-wit.sh` compares with. + fetch-depth: 0 + + - uses: ./.github/actions/setup + with: + target: wasm32-wasip3 + + - name: Check the version + run: | + version=$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -1) + componentize=$(sed -n 's/^version = "\(.*\)"$/\1/p' componentize/Cargo.toml | head -1) + if [ "$componentize" != "$version" ]; then + echo "componentize/Cargo.toml has version $componentize, the workspace $version" >&2 + exit 1 + fi + if [ "${GITHUB_REF_TYPE}" = tag ] && [ "${GITHUB_REF_NAME}" != "v$version" ]; then + echo "The tag ${GITHUB_REF_NAME} does not name the workspace's version $version" >&2 + exit 1 + fi + ./scripts/check-init-wit.sh + + - name: Build the release runtime + run: just build-runtime + + - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: runtime + path: target/wasm32-wasip3/release/starling.wasm + if-no-files-found: error + + binaries: + name: Build for ${{ matrix.platform }} + needs: runtime + strategy: + matrix: + include: + # The Linux binaries link musl statically, so they run on any Linux distribution, + # whichever C library it uses. + - { platform: linux-x64, os: ubuntu-latest, target: x86_64-unknown-linux-musl } + - { platform: linux-arm64, os: ubuntu-24.04-arm, target: aarch64-unknown-linux-musl } + - { platform: darwin-arm64, os: macos-latest } + - { platform: darwin-x64, os: macos-15-intel } + - { platform: win32-x64, os: windows-latest } + runs-on: ${{ matrix.os }} + env: + # The per-platform builds share no cache with the runtime build. + RUSTC_WRAPPER: "" + CCACHE: "" + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Install the Rust toolchain + run: rustup show + + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: runtime + path: runtime + + - name: Install musl-gcc + if: matrix.target + run: | + sudo apt-get update + sudo apt-get install -y musl-tools + + - name: Build starling-componentize + working-directory: componentize + env: + STARLING_EMBED_RUNTIME: ${{ github.workspace }}/runtime/starling.wasm + TARGET: ${{ matrix.target }} + run: | + if [ -n "$TARGET" ]; then + rustup target add "$TARGET" + # `musl-gcc` compiles the C dependencies, such as zstd. + export "CC_${TARGET//-/_}=musl-gcc" + cargo build --release --locked --bin starling-componentize --target "$TARGET" + mkdir -p ../target/release + cp "../target/$TARGET/release/starling-componentize" ../target/release/ + else + cargo build --release --locked --bin starling-componentize + fi + + - name: Check the binary runs + run: | + exe=target/release/starling-componentize + if [ "${{ runner.os }}" = Windows ]; then exe="$exe.exe"; fi + "$exe" --version + mkdir -p out + cp "$exe" out/ + + - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: binary-${{ matrix.platform }} + path: out/ + if-no-files-found: error + + publish: + name: Publish the npm packages + needs: binaries + runs-on: ubuntu-latest + permissions: + contents: read + # For npm's provenance statement. + id-token: write + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Add the tool versions to the environment + run: grep -v '^#' .github/tool-versions.env >>"$GITHUB_ENV" + + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: ${{ env.NODE_VERSION }} + registry-url: https://registry.npmjs.org + + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + pattern: binary-* + path: binaries + + - name: Assemble the packages + env: + INPUT_VERSION: ${{ inputs.version }} + run: | + binaries=() + for dir in binaries/binary-*; do + platform=${dir#binaries/binary-} + binaries+=("$platform=$(ls "$dir"/starling-componentize*)") + done + node componentize/npm/package.mjs ${INPUT_VERSION:+--version "$INPUT_VERSION"} \ + --out npm --pack npm-tarballs --all-platforms "${binaries[@]}" + + - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: npm-tarballs + path: npm-tarballs/ + if-no-files-found: error + + - name: Publish + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: | + dry_run=--dry-run + if [ "${GITHUB_REF_TYPE}" = tag ] || [ "${{ inputs.publish }}" = true ]; then + dry_run= + fi + # The platform packages go first, so the package depending on them never + # names an unpublished version. + for dir in npm/starling-componentize-* npm/starling-componentize; do + (cd "$dir" && npm publish --provenance $dry_run) + done + + github-release: + name: Create the GitHub release + if: github.ref_type == 'tag' + needs: publish + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: runtime + path: assets + + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + pattern: binary-* + path: binaries + + - name: Create the release + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + run: | + for dir in binaries/binary-*; do + platform=${dir#binaries/binary-} + for exe in "$dir"/starling-componentize*; do + name=$(basename "$exe") + cp "$exe" "assets/starling-componentize-${platform}${name#starling-componentize}" + done + done + (cd assets && sha256sum -- * > SHA256SUMS) + gh release create "$GITHUB_REF_NAME" --title "StarlingMonkey $GITHUB_REF_NAME" \ + --generate-notes assets/* diff --git a/.gitignore b/.gitignore index 8f54e946..482650a4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target /deps/wpt +/node_modules diff --git a/Cargo.lock b/Cargo.lock index 5d53900c..9e6aa0bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -386,6 +386,8 @@ dependencies = [ "shlex 2.0.1", "tempfile", "tokio", + "url", + "wit-name-mapping", ] [[package]] @@ -408,9 +410,7 @@ name = "cpp-builtins" version = "0.3.0" dependencies = [ "cc", - "core-runtime", "js", - "libstarling", "mozjs", "mozjs_sys", ] @@ -572,7 +572,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -1442,6 +1442,7 @@ dependencies = [ "mozjs_sys", "num-traits", "rustc-hash", + "slab", "smallvec", "starling-macro", ] @@ -1514,6 +1515,7 @@ dependencies = [ "js", "platform", "serve-test-support", + "tempfile", "tokio", "url", "wasip3", @@ -2064,7 +2066,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2243,7 +2245,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2300,7 +2302,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2546,7 +2548,9 @@ dependencies = [ "libstarling", "tempfile", "wasip3", + "web-fetch", "wit-bindgen", + "wit-bridge", ] [[package]] @@ -2639,7 +2643,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3006,7 +3010,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1d0246511d901aacf25d2dc9111f0054947de5e093fe662099e709ff7530dc3" dependencies = [ "leb128fmt", - "wasmparser", + "wasmparser 0.259.0", ] [[package]] @@ -3018,7 +3022,7 @@ dependencies = [ "anyhow", "indexmap", "wasm-encoder", - "wasmparser", + "wasmparser 0.259.0", ] [[package]] @@ -3046,6 +3050,16 @@ dependencies = [ "semver", ] +[[package]] +name = "wasmparser" +version = "0.262.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "974d643b125b272607e2fff8012ea14a8328acd7621e4bafa7afb32500052b1b" +dependencies = [ + "bitflags", + "semver", +] + [[package]] name = "web-fetch" version = "0.3.0" @@ -3086,7 +3100,9 @@ dependencies = [ "core-runtime", "js", "libstarling", + "platform", "smallvec", + "tokio", "web-globals", ] @@ -3136,7 +3152,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3397,6 +3413,21 @@ dependencies = [ "wit-bindgen-rust", ] +[[package]] +name = "wit-bridge" +version = "0.3.0" +dependencies = [ + "core-runtime", + "js", + "platform", + "slab", + "smallvec", + "web-streams", + "wit-bindgen", + "wit-dylib-ffi", + "wit-name-mapping", +] + [[package]] name = "wit-component" version = "0.259.0" @@ -3412,10 +3443,27 @@ dependencies = [ "serde_json", "wasm-encoder", "wasm-metadata", - "wasmparser", + "wasmparser 0.259.0", "wit-parser", ] +[[package]] +name = "wit-dylib-ffi" +version = "0.1.0" +source = "git+https://github.com/bytecodealliance/wasm-tools/?rev=e22db44da4eaf17a0e46ec55b911c7539589a3cc#e22db44da4eaf17a0e46ec55b911c7539589a3cc" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wit-name-mapping" +version = "0.3.0" +dependencies = [ + "heck", + "semver", + "wasmparser 0.262.0", +] + [[package]] name = "wit-parser" version = "0.259.0" @@ -3432,7 +3480,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-ident", - "wasmparser", + "wasmparser 0.259.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 060c7ce6..c3a5c2bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,8 @@ edition = "2021" [workspace] members = [ "starling", + "crates/wit-bridge", + "crates/wit-name-mapping", "crates/platform", "crates/builtins/*", ] @@ -39,14 +41,19 @@ libstarling = { path = "crates/libstarling" } oxc_resolver = "11" platform = { path = "crates/platform" } reqwest = { version = "0.13", default-features = false, features = ["rustls", "stream"] } +semver = "1.0.28" serve-test-support = { path = "crates/serve-test-support" } +slab = "0.4.12" smallvec = "1.16" starling-macro = { path = "crates/starling-macro" } tokio = { version = "1", features = ["rt", "time", "net", "io-util"] } url = "2.5.8" wasip3 = { version = "0.9.0", features = ["http-compat"] } +wasmparser = { version = "0.262", default-features = false, features = ["validate", "component-model"] } # Must equal the `wit-bindgen` version `wasip3` depends on. See `starling/Cargo.toml`. wit-bindgen = { version = "=0.62.0", features = ["macros"] } +wit-bridge = { path = "crates/wit-bridge" } +wit-name-mapping = { path = "crates/wit-name-mapping" } wpt-support = { path = "crates/wpt-support" } # Builtins @@ -57,7 +64,6 @@ web-streams = { path = "crates/builtins/web-streams" } web-url = { path = "crates/builtins/web-url" } cpp-builtins = { path = "crates/builtins/cpp-builtins" } - [profile.release] lto = "thin" strip = "symbols" diff --git a/README.md b/README.md index edc8fd77..104e3c17 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,9 @@ StarlingMonkey is designed to be extensible and provides safe high-level abstractions for defining additional builtins as JS classes, WebIDL interfaces, JS modules, and functions and properties on the global object. +[`starling-componentize`](#componentizing-javascript) builds WebAssembly components from a +JavaScript application and a WIT world. + --- ## Contents @@ -14,6 +17,20 @@ JS modules, and functions and properties on the global object. - [Running JavaScript](#running-javascript) - [Built-in APIs](#built-in-apis) - [CLI Reference](#cli-reference) +- [Componentizing JavaScript](#componentizing-javascript) + - [Installing](#installing) + - [Command line](#command-line) + - [Export names](#export-names) + - [HTTP servers](#http-servers) + - [CLI tools](#cli-tools-wasiclirun) + - [Components that serve and run](#components-that-serve-and-run) + - [Initialization](#initialization) + - [Refused worlds](#refused-worlds) + - [Disabling WASI features](#disabling-wasi-features) + - [The interfaces the runtime imports](#the-interfaces-the-runtime-imports) + - [WIT values in JavaScript](#wit-values-in-javascript) + - [Bundling and build caching](#bundling-and-build-caching) + - [TypeScript declarations for a world](#typescript-declarations-for-a-world) - [Extending with Custom Builtins](#extending-with-custom-builtins) - [`#[jsclass]` / `#[jsmethods]`](#jsclass--jsmethods) - [`#[jsmodule]`](#jsmodule) @@ -25,9 +42,10 @@ JS modules, and functions and properties on the global object. - [Inheritance](#inheritance) - [Promise / Async](#promise--async) - [Building and Testing](#building-and-testing) + - [The runtime component](#the-runtime-component) + - [The componentizer](#the-componentizer) - [Web Platform Tests (WPT)](#web-platform-tests-wpt) - [GC Rooting Checks](#gc-rooting-checks) -- [Key Design Points](#key-design-points) --- @@ -83,18 +101,14 @@ starlingmonkey --legacy-script old-code.js ## Built-in APIs -StarlingMonkey's suite of builtins is a work in progress for now. - ### C++ built-ins -The previous incarnation of StarlingMonkey was written in C++. This one has -support for running built-ins from that version, in the -[crates/builtins/cpp-builtins](crates/builtins/cpp-builtins) crate. Only the old -`console` builtin is added right now. +[crates/builtins/cpp-builtins](crates/builtins/cpp-builtins) runs builtins written for +StarlingMonkey's earlier C++ implementation through a compatibility layer. It provides `console`. Builtins are tested against the [Web Platform Tests](https://github.com/web-platform-tests/wpt) suite running -on both native and `wasm32-wasip2` targets. +on both native and wasm targets. --- @@ -104,44 +118,41 @@ on both native and `wasm32-wasip2` targets. starlingmonkey [OPTIONS] [SCRIPT_PATH] Arguments: - [SCRIPT_PATH] Path to the entry JS/MJS file (default: ./index.js) + [SCRIPT_PATH] Path to the entry JS/MJS file (default: ./index.js) Options: - -e, --eval