Full Code of Shopify/ruvy for AI

main 425f0ada75d8 cached
45 files
69.0 KB
21.8k tokens
67 symbols
1 requests
Download .txt
Repository: Shopify/ruvy
Branch: main
Commit: 425f0ada75d8
Files: 45
Total size: 69.0 KB

Directory structure:
gitextract_yv2v4z6_/

├── .cargo/
│   └── config.toml
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── config.yml
│   │   ├── feature_request.md
│   │   └── question.md
│   ├── dependabot.yml
│   ├── pull_request_template.md
│   └── workflows/
│       ├── cargo-vet.yml
│       ├── ci.yml
│       └── cla.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE.md
├── Makefile
├── README.md
├── crates/
│   ├── cli/
│   │   ├── Cargo.toml
│   │   ├── benches/
│   │   │   ├── benchmark.rs
│   │   │   └── scripts/
│   │   │       ├── hello_world/
│   │   │       │   └── hello_world.rb
│   │   │       └── transformer/
│   │   │           ├── input.json
│   │   │           ├── preload/
│   │   │           │   └── transformer.rb
│   │   │           ├── ruby_wasm_entry.rb
│   │   │           └── ruvy_entry.rb
│   │   ├── build.rs
│   │   ├── src/
│   │   │   └── main.rs
│   │   └── tests/
│   │       └── integration_test.rs
│   ├── core/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── main.rs
│   │       └── runtime.rs
│   ├── ruby-wasm-assets/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── lib.rs
│   └── wasm-sys/
│       ├── .cargo/
│       │   └── config
│       ├── Cargo.toml
│       ├── build.rs
│       ├── foo.c
│       ├── src/
│       │   └── lib.rs
│       └── wrapper.h
├── prelude/
│   ├── custom_printer.rb
│   └── inspector.rb
├── ruby_examples/
│   ├── hello_world.rb
│   └── use_preludes_and_stdin.rb
├── rust-toolchain.toml
└── supply-chain/
    ├── audits.toml
    └── config.toml

================================================
FILE CONTENTS
================================================

================================================
FILE: .cargo/config.toml
================================================
# Cargo doesn't read directives in individual crates when invoking build
# commands from the workspace root, hence adding it at the workspace root.
# https://doc.rust-lang.org/cargo/reference/config.html.
# Disable reference-types since Wizer (as of version 7.0.0) does not support
# reference-types. Must be combined with "thin" or "fat" LTO.
[target.wasm32-wasip1]
rustflags = ["-C", "target-feature=-reference-types"]
runner = "wasmtime"


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: File a bug report
title:
labels: ["bug"]
assignees:
---

Operating system: ...
Processor architecture: ...
Rust version: ...
Ruvy version (commit hash): ...

## Problem and context

...

## What were you expecting to happen?

...

## What did happen?

...

## Are there steps to reproduce the problem?

...


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: true


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest a feature
title:
labels: ["feature"]
assignees:
---

## Describe your feature

...

## What problem does it solve?

...


================================================
FILE: .github/ISSUE_TEMPLATE/question.md
================================================
---
name: Question
about: Questions about Ruvy
title:
labels: ["question"]
assignees:
---

## What is your question?


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "cargo"
    directory: "/"
    schedule:
      interval: "monthly"
    open-pull-requests-limit: 100
    groups:
      wasmtime:
        patterns:
          - "wasmtime*"
      nonbreaking:
        update-types:
          - "minor"
          - "patch"

  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "monthly"


================================================
FILE: .github/pull_request_template.md
================================================
## Description of the change

## Why am I making this change?


================================================
FILE: .github/workflows/cargo-vet.yml
================================================
name: Cargo vet dependencies
on:
  push:
    branches:
      - main
  pull_request:

jobs:
  cargo-vet:
    name: cargo_vet
    runs-on: ubuntu-latest
    env:
      CARGO_VET_VERSION: 0.9.0
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
      - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
        with:
          path: ${{ runner.tool_cache }}/cargo-vet
          key: cargo-vet-bin-${{ env.CARGO_VET_VERSION }}
      - name: Add the tool cache directory to the search path
        run: echo "${{ runner.tool_cache }}/cargo-vet/bin" >> $GITHUB_PATH
      - name: Ensure that the tool cache is populated with the cargo-vet binary
        run: cargo install --root ${{ runner.tool_cache }}/cargo-vet --version ${{ env.CARGO_VET_VERSION }} cargo-vet
      - name: Invoke cargo-vet
        run: cargo vet --locked


================================================
FILE: .github/workflows/ci.yml
================================================
name: CI

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

      - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

      - name: Install Wasmtime
        env:
          WASMTIME_VERSION: 12.0.2
        run: |
          wget -nv https://github.com/bytecodealliance/wasmtime/releases/download/v${WASMTIME_VERSION}/wasmtime-v${WASMTIME_VERSION}-x86_64-linux.tar.xz -O /tmp/wasmtime.tar.xz
          mkdir /tmp/wasmtime
          tar xvf /tmp/wasmtime.tar.xz --strip-components=1 -C /tmp/wasmtime
          echo "/tmp/wasmtime" >> $GITHUB_PATH

      - name: Compile core
        run: cargo build --package=core --target=wasm32-wasip1 --release

      - name: Test core
        run: cargo test --package=core --target=wasm32-wasip1 --release

      - name: Test CLI
        run: cargo test --package=cli -- --nocapture

      - name: Format checks
        run: |
          cargo fmt -- --check
          cargo clippy --workspace --exclude=cli --exclude=ruby-wasm-assets --target=wasm32-wasip1 --all-targets -- -D clippy::correctness -D clippy::perf -D clippy::suspicious
          cargo clippy --package=cli --package=ruby-wasm-assets --all-targets -- -D clippy::correctness -D clippy::perf -D clippy::suspicious


================================================
FILE: .github/workflows/cla.yml
================================================
name: Contributor License Agreement (CLA)

on:
  pull_request_target:
    types: [opened, synchronize]
  issue_comment:
    types: [created]

jobs:
  cla:
    runs-on: ubuntu-latest
    if: |
      (github.event.issue.pull_request
        && !github.event.issue.pull_request.merged_at
        && contains(github.event.comment.body, 'signed')
      )
      || (github.event.pull_request && !github.event.pull_request.merged)
    steps:
      - uses: Shopify/shopify-cla-action@v1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          cla-token: ${{ secrets.CLA_TOKEN }}


================================================
FILE: .gitignore
================================================
/target
.DS_Store
*.wasm
wasi-sdk
*~
.vscode/


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall
  community

Examples of unacceptable behavior include:

- The use of sexualized language or imagery, and sexual attention or advances of
  any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address,
  without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
opensource@shopify.com.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series of
actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within the
community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].

Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].

For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].

[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Ruvy

Thank you for contributing to Ruvy! Any contributions to Ruvy are appreciated and encouraged.

## Code of conduct

This project and everyone participating in it is govered by the [Code of Conduct document](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behaviour to opensource@shopify.com.

## Creating issues

Before submitting issues, please see if there is an existing open issue. If no related issue is found, then please create a new issue.

## Opening pull requests

If the change is not trivial, we encourage to open a feature request issue to discuss the change you would like to make before creating a pull request. That way we can align on your approach before you start coding it.


================================================
FILE: Cargo.toml
================================================
[workspace]
members = [
  "crates/wasm-sys",
  "crates/core",
  "crates/cli",
  "crates/ruby-wasm-assets",
]

resolver = "2"

[workspace.dependencies]
anyhow = "1.0"

[profile.release]
# Either "thin" or "fat" LTO is required to remove overlong call_indirect table
# indexes which aren't compatible with Wizer.
lto = true


================================================
FILE: LICENSE.md
================================================
MIT License

Copyright 2023-present, Shopify Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: Makefile
================================================
.DEFAULT_GOAL := cli

cli: core
	cargo build --package=cli

core:
	cargo build --package=core --release --target=wasm32-wasip1

tests: test-cli test-core
		
test-cli: cli
	cargo test --package=cli -- --nocapture

test-core:
	cargo test --package=core --target=wasm32-wasip1 -- --nocapture

fmt: fmt-ruby-wasm-assets fmt-wasm-sys fmt-core fmt-cli

fmt-ruby-wasm-assets:
	cargo fmt --package=ruby-wasm-assets -- --check
	cargo clippy --package=ruby-wasm-assets -- -D clippy::correctness -D clippy::perf -D clippy::suspicious

fmt-wasm-sys:
	cargo fmt --package=ruvy-wasm-sys -- --check
	cargo clippy --package=ruvy-wasm-sys --target=wasm32-wasip1 -- -D clippy::correctness -D clippy::perf -D clippy::suspicious

fmt-core:
	cargo fmt --package=core -- --check
	cargo clippy --package=core --target=wasm32-wasip1 --all-targets -- -D clippy::correctness -D clippy::perf -D clippy::suspicious

fmt-cli:
	cargo fmt --package=cli -- --check
	cargo clippy --package=cli --all-targets -- -D clippy::correctness -D clippy::perf -D clippy::suspicious

bench: core
	cargo bench --package=cli


================================================
FILE: README.md
================================================
# Ruvy: A Ruby to WebAssembly toolchain

**This project is no longer maintained**

## About this repo

Ruvy aims to initialize the ruby VM using wizer and execute ruby code passed into the wasm.

## Build

- [rustup](https://rustup.rs/)
- Latest Rust stable version
- wasm32-wasip1, can be installed via `rustup target add wasm32-wasip1`
- cmake, depending on your operating system and architecture, it might not be
  installed by default. On Mac it can be installed with `homebrew` via `brew
install cmake`
- Rosetta 2 if running MacOS on Apple Silicon, can be installed via
  `softwareupdate --install-rosetta`

## Development

- wasmtime-cli, can be installed via `cargo install wasmtime-cli`

### Using a different WASI SDK

The following environment variables allow you to experiment with different WASI SDKs:

- `RUVY_WASM_SYS_WASI_SDK_MAJOR_VERSION` sets the major version of the WASI SDK to use
- `RUVY_WASM_SYS_WASI_SDK_MINOR_VERSION` sets the minor version of the WASI SDK to use
- `RUVY_WASM_SYS_WASI_SDK_PATH` allows you to specify a path to WASI SDK to use

### Using a different ruby.wasm

Set the `RUVY_WASM_SYS_RUBY_PATH` environment variable to a path containing an extracted release asset from https://github.com/ruby/ruby.wasm. The directory the environment variable is set to must contain an `include` and `lib` directory.

## Building

After all the dependencies are installed, run `make`

## Usage

A simple ruby program that prints "Hello world" to stdout

```
$ cargo run --package=cli ruby_examples/hello_world.rb
$ wasmtime index.wasm
Hello world
```

You can preload files by pointing to a directory of ruby files. At the moment, it just naively loads each file 1 by 1.

```
$ cargo run --package=cli -- --preload=prelude/ ruby_examples/use_preludes_and_stdin.rb
$ echo "this is my input" | wasmtime index.wasm
{:discount_input=>"this is my input", :value=>100.0}
```

## Ideas for contributions

Here are some ideas for welcome contributions!

### Compatibility with Shopify Functions

Ruvy is **not** currently compatible with Shopify Functions. This is due to the size of the Wasm modules produced by Ruvy exceeding the maximum size of Wasm modules supported by Shopify Functions.

Here are some ideas for how to make Ruvy compatible with Shopify Functions:

- Shrinking the size of modules by separating the interpreter into an engine Wasm module which exports memory and functions that can be imported by a Wasm module containing Ruby source code. To see an example of implementing this approach, take a look at https://github.com/bytecodealliance/javy, specifically the [core lib.rs](https://github.com/bytecodealliance/javy/blob/3b02858c4a68c830e8e82a1b15b4c3817ad1a64a/crates/core/src/lib.rs) and [the dynamic wasm generator](https://github.com/bytecodealliance/javy/blob/3b02858c4a68c830e8e82a1b15b4c3817ad1a64a/crates/cli/src/wasm_generator/dynamic.rs).
- Investigate and improve performance of Ruvy modules. One approach to consider is using YJIT to output WebAssembly.
- Enable exports of named functions from Wasm that call into named functions in Ruby code so multiple functions can be exported.

### Misc

- Enable using `require` and Ruby gems. At the present time, using code in the preload directory is the only way to add dependencies and large parts of the standard library are not available. It should be possible to enable `require` to work and to load both code from the standard library and from third party gems that are not native gems. A good example of showing this is fixed would be adding a Ruby example that uses the standard library's `json` library to parse and dump JSON.
- Output any error messages from the Ruby VM on the standard error stream.


================================================
FILE: crates/cli/Cargo.toml
================================================
[package]
name = "cli"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
name = "ruvy"
path = "src/main.rs"

[dependencies]
clap = { version = "4.5.53", features = ["derive"] }
anyhow = { workspace = true }
tokio = { version = "1", features = ["macros"] }
wasmtime = "40"
wasmtime-wasi = "40"
wasmtime-wizer = { version = "40", features = ["wasmtime"] }

[dev-dependencies]
criterion = "0.8.1"
ruby-wasm-assets = { path = "../ruby-wasm-assets" }

[build-dependencies]
anyhow = { workspace = true }

[[bench]]
name = "benchmark"
harness = false


================================================
FILE: crates/cli/benches/benchmark.rs
================================================
use std::{
    env::consts,
    ffi::OsStr,
    fmt::{self, Display},
    fs,
    path::{Path, PathBuf},
    process::{Command, ExitStatus},
    str,
};

use anyhow::{bail, Result};
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use wasmtime::{Engine, Linker, Module, Store};
use wasmtime_wasi::{
    p1::WasiP1Ctx,
    p2::pipe::{MemoryInputPipe, MemoryOutputPipe},
    WasiCtxBuilder,
};

pub fn criterion_benchmark(c: &mut Criterion) {
    let engine = Engine::default();
    let cases = vec![
        WasmCase::new(
            BuildStrategy::WasiVFSRubyWasm,
            "benches/scripts/hello_world/hello_world.rb".into(),
        )
        .unwrap(),
        WasmCase::new(
            BuildStrategy::Ruvy(None),
            "benches/scripts/hello_world/hello_world.rb".into(),
        )
        .unwrap(),
        WasmCase::new(
            BuildStrategy::WasiVFSRubyWasm,
            "benches/scripts/transformer/ruby_wasm_entry.rb".into(),
        )
        .unwrap(),
        WasmCase::new(
            BuildStrategy::Ruvy(Some("benches/scripts/transformer/preload".into())),
            "benches/scripts/transformer/ruvy_entry.rb".into(),
        )
        .unwrap(),
    ];
    for case in cases {
        c.bench_with_input(BenchmarkId::new("compile", &case), &case, |b, script| {
            b.iter(|| Module::new(&engine, &script.wasm).unwrap())
        });

        c.bench_with_input(BenchmarkId::new("run", &case), &case, |b, script| {
            b.iter_with_setup(
                || script.setup_for_run(&engine).unwrap(),
                |(linker, module, mut store)| {
                    let instance = linker.instantiate(&mut store, &module).unwrap();
                    let start_func = instance
                        .get_typed_func::<(), ()>(&mut store, "_start")
                        .unwrap();
                    start_func.call(&mut store, ()).unwrap()
                },
            )
        });
    }
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

struct WasmCase {
    name: String,
    wasm: Vec<u8>,
    wasi_args: Vec<String>,
    input: Vec<u8>,
}

impl Display for WasmCase {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.name)
    }
}

impl WasmCase {
    fn new(strategy: BuildStrategy, entrypoint: Entrypoint) -> Result<WasmCase> {
        let name = format!("{}-{}", strategy, entrypoint.parent_dirname);
        let output_path = cargo_target_tmpdir().join(&name).with_extension("wasm");
        let exit_status = strategy.build_wasm(&output_path, &entrypoint)?;
        if !exit_status.success() {
            bail!("Failed to build Wasm module");
        }

        let input_file = &entrypoint.input_path;
        let input = if input_file.exists() {
            fs::read(input_file)?
        } else {
            vec![]
        };

        Ok(Self {
            name,
            wasm: fs::read(output_path)?,
            wasi_args: strategy.wasi_args(&entrypoint),
            input,
        })
    }

    fn setup_for_run(
        &self,
        engine: &Engine,
    ) -> Result<(Linker<WasiP1Ctx>, Module, Store<WasiP1Ctx>)> {
        let mut linker = Linker::new(engine);
        let wasi = WasiCtxBuilder::new()
            .stdin(MemoryInputPipe::new(self.input[..].to_vec()))
            .stdout(MemoryOutputPipe::new(usize::MAX))
            .stderr(MemoryOutputPipe::new(usize::MAX))
            .args(&self.wasi_args)
            .build_p1();
        wasmtime_wasi::p1::add_to_linker_sync(&mut linker, |cx| cx)?;
        let store = Store::new(engine, wasi);
        let module = Module::new(engine, &self.wasm)?;
        Ok((linker, module, store))
    }
}

enum BuildStrategy {
    WasiVFSRubyWasm,
    Ruvy(Option<PathBuf>),
}

impl BuildStrategy {
    fn build_wasm(&self, output_path: &Path, entrypoint: &Entrypoint) -> Result<ExitStatus> {
        match self {
            Self::WasiVFSRubyWasm => {
                let ruby_wasm = ruby_wasm()?;
                let wasi_vfs = wasi_vfs()?;
                Ok(Command::new(wasi_vfs)
                    .arg("pack")
                    .arg(&ruby_wasm)
                    .arg("--mapdir")
                    .arg(format!("/src::{}", entrypoint.parent_path))
                    // Examples online show mapping the `/usr` directory, however this
                    // breaks when using a `minimal` instead of `full` profile of
                    // ruby.wasm, so we don't map that directory here.
                    .arg("-o")
                    .arg(output_path.as_os_str())
                    .status()?)
            }
            Self::Ruvy(preload) => {
                let ruvy = env!("CARGO_BIN_EXE_ruvy");
                let mut args = vec![entrypoint.path, OsStr::new("-o"), output_path.as_os_str()];
                if let Some(preload) = &preload {
                    args.push(OsStr::new("--preload"));
                    args.push(preload.as_os_str());
                }
                Ok(Command::new(ruvy).args(args).status()?)
            }
        }
    }

    fn wasi_args(&self, entrypoint: &Entrypoint) -> Vec<String> {
        match self {
            Self::WasiVFSRubyWasm => vec![
                // Not passing `--disable-gems` results in output about `RubyGems`,
                // `error_highlight`, `did_you_mean`, and `syntax_suggest` not
                // being loaded. We don't want that and we don't use the gems
                // anyway, so I'm disabling them.
                // If we did not want to pass `--disable-gems`, we can use the
                // `full` profile build of ruby.wasm and map the `/usr` directory.
                "--disable-gems".into(),
                PathBuf::from("/src")
                    .join(entrypoint.filename)
                    .to_string_lossy()
                    .to_string(),
            ],
            Self::Ruvy(_) => vec![],
        }
    }
}

impl Display for BuildStrategy {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{}",
            match self {
                Self::WasiVFSRubyWasm => "rubywasm",
                Self::Ruvy(_) => "ruvy",
            }
        )
    }
}

struct Entrypoint<'a> {
    parent_dirname: &'a str,
    parent_path: &'a str,
    filename: &'a OsStr,
    input_path: PathBuf,
    path: &'a OsStr,
}

impl<'a> From<&'a str> for Entrypoint<'a> {
    fn from(value: &'a str) -> Self {
        let value = Path::new(value);
        Entrypoint {
            parent_dirname: value
                .parent()
                .unwrap()
                .file_name()
                .unwrap()
                .to_str()
                .unwrap(),
            parent_path: value.parent().unwrap().to_str().unwrap(),
            filename: value.file_name().unwrap(),
            input_path: value.parent().unwrap().join("input.json"),
            path: value.as_os_str(),
        }
    }
}

fn cargo_target_tmpdir() -> PathBuf {
    PathBuf::from(env!("CARGO_TARGET_TMPDIR"))
}

fn ruby_wasm() -> Result<PathBuf> {
    let tmpdir = cargo_target_tmpdir();
    let ruby_wasm_base = ruby_wasm_assets::ruby_wasm_base_name();
    let ruby_wasm_dir = tmpdir.join(&ruby_wasm_base);
    let ruby_wasm = ruby_wasm_dir.join("usr/local/bin/ruby");
    if ruby_wasm.exists() {
        return Ok(ruby_wasm);
    }
    let archive = tmpdir.join(format!("{ruby_wasm_base}.tar.gz"));
    ruby_wasm_assets::download_ruby_wasm(&archive)?;
    ruby_wasm_assets::extract_tar(&archive, &ruby_wasm_dir, 1)?;
    Ok(ruby_wasm)
}

fn wasi_vfs() -> Result<PathBuf> {
    let tmpdir = cargo_target_tmpdir();
    const VERSION: &str = "0.4.0";
    let wasi_vfs_base = format!("wasi-vfs-{VERSION}");
    let directory = tmpdir.join(&wasi_vfs_base);
    let wasi_vfs = directory.join("wasi-vfs");
    if wasi_vfs.exists() {
        return Ok(wasi_vfs);
    }
    let archive = tmpdir.join(format!("{wasi_vfs_base}.tar.gz"));
    download_wasi_vfs(&archive, VERSION)?;
    extract_wasi_vfs(&archive, &directory)?;
    Ok(wasi_vfs)
}

fn download_wasi_vfs(path: &Path, version: &str) -> Result<()> {
    let file_suffix = match (consts::OS, consts::ARCH) {
        ("linux", "x86_64") => "x86_64-unknown-linux-gnu",
        ("macos", "x86_64") => "x86_64-apple-darwin",
        ("macos", "aarch64") => "aarch64-apple-darwin",
        ("windows", "x86_64") => "x86_64-pc-windows-gnu",
        other => bail!("Unsupported platform tuple {:?}", other),
    };
    ruby_wasm_assets::download(format!("https://github.com/kateinoigakukun/wasi-vfs/releases/download/v{version}/wasi-vfs-cli-{file_suffix}.zip"), path)
}

fn extract_wasi_vfs(archive: &Path, extract_to: &Path) -> Result<()> {
    let output = Command::new("unzip")
        .arg(archive)
        .arg("-d")
        .arg(extract_to)
        .output()?;
    if !output.status.success() {
        bail!(
            "Unpacking wasi-vfs failed: {}",
            String::from_utf8_lossy(&output.stderr)
        );
    }
    Ok(())
}


================================================
FILE: crates/cli/benches/scripts/hello_world/hello_world.rb
================================================
puts "Hello world!"


================================================
FILE: crates/cli/benches/scripts/transformer/input.json
================================================
{ "n": 1 }


================================================
FILE: crates/cli/benches/scripts/transformer/preload/transformer.rb
================================================
class Transformer
  def initialize(input)
    @input = input
  end

  def transform
    @input + '1'
  end
end


================================================
FILE: crates/cli/benches/scripts/transformer/ruby_wasm_entry.rb
================================================
require_relative "preload/transformer.rb"

input = STDIN.gets.strip
transformer = Transformer.new(input)
puts transformer.transform


================================================
FILE: crates/cli/benches/scripts/transformer/ruvy_entry.rb
================================================
input = STDIN.gets.strip
transformer = Transformer::new(input)
puts transformer.transform


================================================
FILE: crates/cli/build.rs
================================================
use std::{env, fs, path::Path};

use anyhow::Result;

fn main() -> Result<()> {
    let destination = Path::new(&env::var("OUT_DIR")?).join("engine.wasm");
    let is_clippy = env::var("CARGO_CFG_FEATURE").is_ok_and(|v| v == "cargo-clippy");
    if is_clippy {
        fs::write(destination, [])?;
        println!("cargo:warning=using stubbed engine.wasm for static analysis");
    } else {
        println!("cargo:rerun-if-changed=build.rs");
        let engine_path = Path::new(env!("CARGO_MANIFEST_DIR"))
            .join("../../target/wasm32-wasip1/release/core.wasm");
        println!("cargo:rerun-if-changed={}", engine_path.to_str().unwrap());
        fs::copy(engine_path, destination)?;
    }
    Ok(())
}


================================================
FILE: crates/cli/src/main.rs
================================================
use anyhow::Result;
use clap::Parser;
use std::{fs, path::PathBuf, process};
use wasmtime::{Config, Engine, Linker, Store};
use wasmtime_wasi::{
    p1::WasiP1Ctx, p2::pipe::MemoryInputPipe, DirPerms, FilePerms, WasiCtxBuilder,
};
use wasmtime_wizer::Wizer;

#[derive(Debug, Parser)]
#[clap(name = "ruvy_cli", about = "Compile ruby code into a Wasm module.")]
struct Opt {
    /// Path of the Ruby input file.
    input: PathBuf,

    /// Path of a directory containing Ruby files to preload to be used by the input file.
    #[arg(long)]
    preload: Option<PathBuf>,

    #[arg(short, default_value = "index.wasm")]
    /// Desired path of the WebAssembly output file.
    output: PathBuf,
}

#[tokio::main]
async fn main() -> Result<()> {
    let opt = Opt::parse();
    let ruby_code = match fs::read_to_string(&opt.input) {
        Ok(code) => code,
        Err(err) => {
            eprintln!("Error reading Ruby file {}: {}", opt.input.display(), err);
            process::exit(1);
        }
    };

    let ruby_engine = include_bytes!(concat!(env!("OUT_DIR"), "/engine.wasm"));
    let user_wasm = wizen(ruby_engine, &ruby_code, opt.preload).await?;

    fs::write(opt.output, user_wasm)?;
    Ok(())
}

async fn wizen(
    ruby_engine: &[u8],
    ruby_code: &str,
    preload_path: Option<PathBuf>,
) -> Result<Vec<u8>> {
    let mut cfg = Config::new();
    cfg.async_support(true);
    let engine = Engine::new(&cfg)?;
    let mut store = Store::new(&engine, wasi(ruby_code, preload_path)?);
    let user_wasm = Wizer::new()
        .run(&mut store, ruby_engine, async |store, module| {
            let engine = store.engine();
            let mut linker = Linker::new(engine);
            wasmtime_wasi::p1::add_to_linker_async(&mut linker, |cx| cx)?;
            let instance = linker.instantiate_async(store, module).await?;
            Ok(instance)
        })
        .await?;
    Ok(user_wasm)
}

fn wasi(ruby_code: &str, preload_path: Option<PathBuf>) -> Result<WasiP1Ctx> {
    let mut wasi_builder = WasiCtxBuilder::new();
    wasi_builder
        .stdin(MemoryInputPipe::new(ruby_code.as_bytes().to_owned()))
        .inherit_stdout()
        .inherit_stderr();
    if let Some(preload_path) = preload_path {
        let guest_preload_path = preload_path.to_string_lossy();
        wasi_builder
            .env("RUVY_PRELOAD_PATH", &guest_preload_path)
            .preopened_dir(
                &preload_path,
                &guest_preload_path,
                DirPerms::READ,
                FilePerms::READ,
            )
            .map(|_| ())?;
    }
    Ok(wasi_builder.build_p1())
}


================================================
FILE: crates/cli/tests/integration_test.rs
================================================
use std::{env, path::Path, process::Command, str};

use anyhow::{bail, Result};
use wasmtime::{Engine, Linker, Module, Store};
use wasmtime_wasi::{
    p1::WasiP1Ctx,
    p2::pipe::{MemoryInputPipe, MemoryOutputPipe},
    WasiCtxBuilder,
};

#[test]
pub fn test_hello_world() -> Result<()> {
    let wasm_path = wasm_path("hello_world");
    run_ruvy(&wasm_path, "../../ruby_examples/hello_world.rb", None)?;
    let output = run_wasm(&wasm_path, "")?;
    assert_eq!("Hello world\n", output);
    Ok(())
}

#[test]
pub fn test_preludes() -> Result<()> {
    let wasm_path = wasm_path("preludes");
    run_ruvy(
        &wasm_path,
        "../../ruby_examples/use_preludes_and_stdin.rb",
        Some("../../prelude"),
    )?;
    let output = run_wasm(&wasm_path, "this is my input")?;
    assert_eq!(
        "{:discount_input=>\"this is my input\", :value=>100.0}\n",
        output
    );
    Ok(())
}

struct Context {
    wasi: WasiP1Ctx,
    out_stream: MemoryOutputPipe,
}

impl Context {
    fn new(input: &[u8]) -> Context {
        let out_stream = MemoryOutputPipe::new(usize::MAX);
        Context {
            wasi: WasiCtxBuilder::new()
                .stdin(MemoryInputPipe::new(input.to_vec()))
                .stdout(out_stream.clone())
                .build_p1(),
            out_stream,
        }
    }
}

fn wasm_path(test_name: &str) -> String {
    format!("{}/{test_name}.wasm", env!("CARGO_TARGET_TMPDIR"))
}

fn run_ruvy(wasm_path: &str, input_path: &str, preload: Option<&str>) -> Result<()> {
    let mut args = vec![format!("-o{wasm_path}")];
    if let Some(preload) = preload {
        args.push(format!("--preload={preload}"));
    }
    args.push(input_path.to_string());

    let status = Command::new(env!("CARGO_BIN_EXE_ruvy"))
        .args(args)
        .status()?;
    if !status.success() {
        bail!("Failed to execute ruvy");
    }
    Ok(())
}

fn run_wasm(wasm_path: impl AsRef<Path>, input: &str) -> Result<String> {
    let engine = Engine::default();
    let mut linker = Linker::new(&engine);
    wasmtime_wasi::p1::add_to_linker_sync(&mut linker, |cx: &mut Context| &mut cx.wasi)?;
    let mut store = Store::new(&engine, Context::new(input.as_bytes()));

    let module = Module::from_file(&engine, wasm_path)?;
    linker
        .instantiate(&mut store, &module)?
        .get_typed_func::<(), ()>(&mut store, "_start")?
        .call(&mut store, ())?;

    let context = store.into_data();
    drop(context.wasi);
    let output = context.out_stream.contents();
    let output = String::from_utf8(output.to_vec())?;

    Ok(output)
}


================================================
FILE: crates/core/Cargo.toml
================================================
[package]
name = "core"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
ruvy-wasm-sys = { path = "../wasm-sys" }
anyhow = { workspace = true }


================================================
FILE: crates/core/src/main.rs
================================================
mod runtime;

use runtime::cleanup_ruby;
use std::{env, io, sync::OnceLock};

static USER_CODE: OnceLock<String> = OnceLock::new();

fn main() {
    let code = USER_CODE.get().unwrap();
    runtime::eval(code).unwrap();
    cleanup_ruby().unwrap();
}

#[export_name = "wizer-initialize"]
pub extern "C" fn load_user_code() {
    let _wasm_ctx = WasmCtx::new();

    runtime::init_ruby();

    if let Ok(preload_path) = env::var("RUVY_PRELOAD_PATH") {
        runtime::preload_files(preload_path);
    }

    let contents = io::read_to_string(io::stdin()).unwrap();
    USER_CODE.set(contents).unwrap();
}

// RAII abstraction for calling Wasm ctors and dtors for exported non-main functions.
struct WasmCtx;

impl WasmCtx {
    #[must_use = "Failing to assign the return value will result in the wasm dtors being run immediately"]
    fn new() -> Self {
        unsafe { __wasm_call_ctors() };
        Self
    }
}

impl Drop for WasmCtx {
    fn drop(&mut self) {
        unsafe { __wasm_call_dtors() };
    }
}

extern "C" {
    // `__wasm_call_ctors` is generated by `wasm-ld` and invokes all of the global constructors.
    // In a Rust bin crate, the `_start` function will invoke this implicitly but no other exported
    // Wasm functions will invoke this.
    // If this is not invoked, access to environment variables and directory preopens will not be
    // available.
    // This should only be invoked at the start of exported Wasm functions that are not the `main`
    // function.
    // References:
    // - [Rust 1.67.0 stopped initializing the WASI environment for exported functions](https://github.com/rust-lang/rust/issues/107635)
    // - [Wizer header in Fastly's JS compute runtime](https://github.com/fastly/js-compute-runtime/blob/main/runtime/js-compute-runtime/third_party/wizer.h#L92)
    fn __wasm_call_ctors();

    fn __wasm_call_dtors();
}


================================================
FILE: crates/core/src/runtime.rs
================================================
use std::fs;

use anyhow::{anyhow, bail, Result};
use ruvy_wasm_sys::{rb_eval_string_protect, ruby_init, ruby_init_loadpath, VALUE};
use std::{ffi::CString, os::raw::c_char};

pub fn init_ruby() {
    unsafe {
        ruby_init();
        ruby_init_loadpath();
    }
}

pub fn eval(code: &str) -> Result<VALUE> {
    let c_code = CString::new(code)?;
    let mut state: i32 = 0;
    let result =
        unsafe { rb_eval_string_protect(c_code.as_ptr() as *const c_char, &mut state as *mut i32) };

    if state == 0 {
        Ok(result)
    } else {
        Err(anyhow!("Error evaluating Ruby code. State: {}", state))
    }
}

pub fn preload_files(path: String) {
    let entries = fs::read_dir(path).unwrap();

    entries
        .map(|r| r.map(|d| d.path()))
        .filter(|r| r.is_ok() && r.as_deref().unwrap().is_file())
        .for_each(|e| {
            let prelude_contents = fs::read_to_string(e.unwrap()).unwrap();
            eval(&prelude_contents).unwrap();
        });
}

pub fn cleanup_ruby() -> Result<()> {
    const EXPECTED_SUCCESS_RET_VAL: i32 = 0;
    // ruby_cleanup expects an integer as an argument that will be returned if it ran successfully.
    let cleanup_status = unsafe { ruvy_wasm_sys::ruby_cleanup(EXPECTED_SUCCESS_RET_VAL) };
    if cleanup_status != EXPECTED_SUCCESS_RET_VAL {
        bail!("ruby_cleanup did not run successfully. Return value: {cleanup_status}");
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use ruvy_wasm_sys::rb_num2int;

    #[test]
    fn test_int() {
        init_ruby();
        let result = unsafe { rb_num2int(eval("1 + 1").unwrap()) };
        assert_eq!(result, 2);
    }
}


================================================
FILE: crates/ruby-wasm-assets/Cargo.toml
================================================
[package]
name = "ruby-wasm-assets"
version = "0.1.0"
edition = "2021"

[dependencies]
anyhow = { workspace = true }
http-body-util = "0.1.3"
hyper = "1.8"
hyper-tls = "0.6.0"
hyper-util = { version = "0.1.19", features = ["http1"] }
lazy_static = "1.5.0"
tokio = { version = "1.48.0", features = ["rt"] }


================================================
FILE: crates/ruby-wasm-assets/src/lib.rs
================================================
use std::{
    fs::{self, File},
    io::Write,
    path::Path,
    process::Command,
};

use anyhow::{anyhow, bail, Error, Result};
use http_body_util::{combinators::BoxBody, BodyExt};
use hyper::{
    body::{Bytes, Incoming},
    Response,
};
use hyper_tls::HttpsConnector;
use hyper_util::{client::legacy::Client, rt::TokioExecutor};
use lazy_static::lazy_static;
use tokio::runtime::Runtime;

const RUBY_WASM_VERSION: &str = "2.1.0";
const RUBY_WASM_RUBY_VERSION: &str = "3_2";
const RUBY_WASM_TARGET: &str = "wasm32-unknown-wasi";
const RUBY_WASM_PROFILE: &str = "minimal";

lazy_static! {
    static ref RT: Runtime = tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()
        .unwrap();
}

pub fn download(uri: String, path: &Path) -> Result<()> {
    RT.block_on(download_async(uri, path))
}

async fn download_async(mut uri: String, path: &Path) -> Result<()> {
    let file_being_downloaded = path.file_name().unwrap().to_str().unwrap();
    if !path.try_exists()? {
        let client = Client::builder(TokioExecutor::new())
            .build::<_, BoxBody<Bytes, Error>>(HttpsConnector::new());
        let mut response: Response<Incoming> = loop {
            let response = client.get(uri.try_into()?).await?;
            let status = response.status();
            if status.is_redirection() {
                uri = response.headers().get("Location").ok_or_else(|| anyhow!("Received redirect without location header when downloading {file_being_downloaded} from GitHub"))?.to_str()?.to_string();
            } else if !status.is_success() {
                bail!("Received {status} when downloading from {file_being_downloaded}");
            } else {
                break response;
            }
        };
        let mut file = File::create(path)?;
        while let Some(next) = response.frame().await {
            let frame = next?;
            if let Some(chunk) = frame.data_ref() {
                file.write_all(chunk.as_ref())?;
            }
        }
    }
    Ok(())
}

pub fn ruby_wasm_base_name() -> String {
    format!(
        "{}-ruby-{}-{}-{}",
        RUBY_WASM_VERSION, RUBY_WASM_RUBY_VERSION, RUBY_WASM_TARGET, RUBY_WASM_PROFILE
    )
}

pub fn download_ruby_wasm(path: &Path) -> Result<()> {
    download(format!("https://github.com/ruby/ruby.wasm/releases/download/{RUBY_WASM_VERSION}/ruby-{RUBY_WASM_RUBY_VERSION}-{RUBY_WASM_TARGET}-{RUBY_WASM_PROFILE}.tar.gz"), path)
}

pub fn extract_tar(archive: &Path, extract_to: &Path, components_to_strip: i32) -> Result<()> {
    if !extract_to.exists() {
        fs::create_dir(extract_to)?;
    }
    let output = Command::new("tar")
        .args([
            "-xf",
            archive.to_str().unwrap(),
            "--strip-components",
            &components_to_strip.to_string(),
        ])
        .current_dir(extract_to)
        .output()?;
    if !output.status.success() {
        bail!(
            "Unpacking {} failed: {}",
            archive.to_string_lossy(),
            String::from_utf8_lossy(&output.stderr)
        );
    }
    Ok(())
}


================================================
FILE: crates/wasm-sys/.cargo/config
================================================
[build]
target = "wasm32-wasip1"

================================================
FILE: crates/wasm-sys/Cargo.toml
================================================
[package]
name = "ruvy-wasm-sys"
version = "0.1.0"
edition = "2021"

[build-dependencies]
anyhow = { workspace = true }
bindgen = "0.72.1"
cc = "1.2"
ruby-wasm-assets = { path = "../ruby-wasm-assets" }


================================================
FILE: crates/wasm-sys/build.rs
================================================
use anyhow::{bail, Result};
use std::{env, fs, path::PathBuf};

const WASI_SDK_VERSION_MAJOR: usize = 20;
const WASI_SDK_VERSION_MINOR: usize = 0;

fn main() -> Result<()> {
    let wasi_sdk_path = wasi_sdk_path()?;
    let wasi_sdk_path = wasi_sdk_path.to_string_lossy();
    let sysroot = format!("--sysroot={}/share/wasi-sysroot", &wasi_sdk_path);
    let sysroot_lib = format!("{}/share/wasi-sysroot/lib/wasm32-wasi", &wasi_sdk_path);

    let ruby_wasm_dir = ruby_wasm_path()?;
    let lib_dir = ruby_wasm_dir.join("lib");
    let include_dir = ruby_wasm_dir.join("include");
    let include_dir = fs::read_dir(include_dir)?
        .find(|e| {
            e.as_ref()
                .unwrap()
                .file_name()
                .to_str()
                .unwrap()
                .starts_with("ruby-")
        })
        .unwrap()?
        .path();
    let include_config_dir = include_dir.join("wasm32-wasi");

    env::set_var("CC", format!("{}/bin/clang", &wasi_sdk_path));
    env::set_var("LD", format!("{}/bin/clang", &wasi_sdk_path));
    env::set_var("AR", format!("{}/bin/ar", &wasi_sdk_path));
    env::set_var("CFLAGS", &sysroot);

    // Ruby lib directory
    println!("cargo:rustc-link-search={}", lib_dir.display());
    // WASI Sysroot directory
    println!("cargo:rustc-link-search={}", sysroot_lib);

    cc::Build::new()
        .file("foo.c")
        .flag_if_supported("-fdeclspec")
        .cargo_metadata(true)
        .include(&include_dir)
        .include(&include_config_dir)
        .target("wasm32-wasip1")
        .compile("ruvy");

    let bindings = bindgen::Builder::default()
        .header("wrapper.h")
        .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
        .clang_args(&[
            "-fvisibility=default",
            "--target=wasm32-wasip1",
            &sysroot,
            &format!("-I{}", include_dir.display()),
            &format!("-I{}", include_config_dir.display()),
        ])
        .generate()
        .unwrap();

    println!("cargo:rustc-link-lib=static=ruby-static");
    println!("cargo:rustc-link-lib=static=m");
    println!("cargo:rustc-link-lib=static=wasi-emulated-signal");
    println!("cargo:rustc-link-lib=static=wasi-emulated-mman");
    println!("cargo:rustc-link-lib=static=wasi-emulated-process-clocks");
    println!("cargo:rustc-link-lib=static=c");
    println!("cargo:rustc-link-lib=static=crypt");
    println!("cargo:rustc-link-lib=static=pthread");
    println!("cargo:rustc-link-lib=static=rt");
    println!("cargo:rustc-link-lib=static=dl");
    println!("cargo:rustc-link-lib=static=resolv");
    println!("cargo:rustc-link-lib=static=util");

    println!("cargo:rerun-if-changed=build.rs");

    let out_dir = PathBuf::from(env::var("OUT_DIR")?);
    bindings.write_to_file(out_dir.join("bindings.rs"))?;
    Ok(())
}

fn wasi_sdk_path() -> Result<PathBuf> {
    const WASI_SDK_PATH_ENV_VAR: &str = "RUVY_WASM_SYS_WASI_SDK_PATH";
    println!("cargo:rerun-if-env-changed={WASI_SDK_PATH_ENV_VAR}");
    if let Ok(path) = env::var(WASI_SDK_PATH_ENV_VAR) {
        return Ok(path.into());
    }
    download_wasi_sdk()
}

fn download_wasi_sdk() -> Result<PathBuf> {
    let mut wasi_sdk_dir: PathBuf = env::var("OUT_DIR")?.into();
    wasi_sdk_dir.push("wasi-sdk");
    fs::create_dir_all(&wasi_sdk_dir)?;

    const MAJOR_VERSION_ENV_VAR: &str = "RUVY_WASM_SYS_WASI_SDK_MAJOR_VERSION";
    const MINOR_VERSION_ENV_VAR: &str = "RUVY_WASM_SYS_WASI_SDK_MINOR_VERSION";
    println!("cargo:rerun-if-env-changed={MAJOR_VERSION_ENV_VAR}");
    println!("cargo:rerun-if-env-changed={MINOR_VERSION_ENV_VAR}");
    let major_version =
        env::var(MAJOR_VERSION_ENV_VAR).unwrap_or(WASI_SDK_VERSION_MAJOR.to_string());
    let minor_version =
        env::var(MINOR_VERSION_ENV_VAR).unwrap_or(WASI_SDK_VERSION_MINOR.to_string());

    let mut archive_path = wasi_sdk_dir.clone();
    archive_path.push(format!("wasi-sdk-{major_version}-{minor_version}.tar.gz"));

    let file_suffix = match (env::consts::OS, env::consts::ARCH) {
        ("linux", "x86") | ("linux", "x86_64") => "linux",
        ("macos", "x86") | ("macos", "x86_64") | ("macos", "aarch64") => "macos",
        ("windows", "x86") => "mingw-x86",
        ("windows", "x86_64") => "mingw",
        other => bail!("Unsupported platform tuple {:?}", other),
    };
    let uri = format!("https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-{major_version}/wasi-sdk-{major_version}.{minor_version}-{file_suffix}.tar.gz");
    ruby_wasm_assets::download(uri, &archive_path)?;
    ruby_wasm_assets::extract_tar(&archive_path, &wasi_sdk_dir, 1)?;

    Ok(wasi_sdk_dir)
}

fn ruby_wasm_path() -> Result<PathBuf> {
    const RUBY_WASM_PATH_ENV_VAR: &str = "RUVY_WASM_SYS_RUBY_PATH";
    println!("cargo:rerun-if-env-changed={RUBY_WASM_PATH_ENV_VAR}");
    if let Ok(path) = env::var(RUBY_WASM_PATH_ENV_VAR) {
        return Ok(path.into());
    }

    println!(
        "cargo:warning=RUVY_WASM_SYS_RUBY_PATH variable was not set. \
        Attempting to download and install default ruby.wasm"
    );
    download_ruby_wasm()
}

fn download_ruby_wasm() -> Result<PathBuf> {
    let mut ruby_wasm_dir: PathBuf = env::var("OUT_DIR")?.into();
    ruby_wasm_dir.push("ruby-wasm");
    fs::create_dir_all(&ruby_wasm_dir)?;
    let mut archive_path = ruby_wasm_dir.clone();
    let ruby_wasm_version = ruby_wasm_assets::ruby_wasm_base_name();
    archive_path.push(&ruby_wasm_version);
    archive_path.set_extension("tar.gz");

    ruby_wasm_assets::download_ruby_wasm(&archive_path)?;
    // Need to strip archive name, `usr`, and `local`.
    ruby_wasm_assets::extract_tar(&archive_path, &ruby_wasm_dir, 3)?;
    println!(
        "cargo:warning={} installed at {}",
        ruby_wasm_version,
        ruby_wasm_dir.display()
    );

    Ok(ruby_wasm_dir)
}


================================================
FILE: crates/wasm-sys/foo.c
================================================
#include "./wrapper.h"
#include <unistd.h>

// XXX https://github.com/WebAssembly/wasi-libc/commit/659ff414560721b1660a19685110e484a081c3d4
pid_t getpid(void) {
    // Return an arbitrary value, greater than 1 which is special.
    return 42;
}

void asyncify_stop_rewind() {
}

void asyncify_start_unwind(int x) {
}


================================================
FILE: crates/wasm-sys/src/lib.rs
================================================
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(warnings)]
#![allow(clippy::all)]

include!(concat!(env!("OUT_DIR"), "/bindings.rs"));


================================================
FILE: crates/wasm-sys/wrapper.h
================================================
#include <ruby.h>


================================================
FILE: prelude/custom_printer.rb
================================================
def custom_print(input)
  puts input
end

================================================
FILE: prelude/inspector.rb
================================================
module Inspector
  class << self
    def inspect(input)
      input.inspect
    end
  end
end


================================================
FILE: ruby_examples/hello_world.rb
================================================
puts "Hello world"

================================================
FILE: ruby_examples/use_preludes_and_stdin.rb
================================================
input = STDIN.gets.strip
class Discount
  attr_reader :input
  def initialize(input)
    @input = input
  end
end

output = {
  discount_input: Discount.new(input).input,
  value: 100.0
}

custom_print(Inspector.inspect(output))

================================================
FILE: rust-toolchain.toml
================================================
[toolchain]
channel = "1.92.0"
components = ["clippy", "rustfmt"]
targets = ["wasm32-wasip1"]
profile = "default"


================================================
FILE: supply-chain/audits.toml
================================================

# cargo-vet audits file

[audits]

[[trusted.aho-corasick]]
criteria = "safe-to-deploy"
user-id = 189 # Andrew Gallant (BurntSushi)
start = "2019-03-28"
end = "2024-10-03"

[[trusted.ambient-authority]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2021-04-14"
end = "2024-09-21"

[[trusted.anstream]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2023-03-16"
end = "2024-12-01"

[[trusted.anstyle]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2022-05-18"
end = "2024-10-03"

[[trusted.anstyle-parse]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2023-03-08"
end = "2024-12-01"

[[trusted.anstyle-query]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2023-04-13"
end = "2024-12-01"

[[trusted.anstyle-wincon]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2023-03-08"
end = "2024-12-01"

[[trusted.anyhow]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-10-05"
end = "2025-11-04"

[[trusted.async-trait]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-07-23"
end = "2026-12-01"

[[trusted.byteorder]]
criteria = "safe-to-deploy"
user-id = 189 # Andrew Gallant (BurntSushi)
start = "2019-06-09"
end = "2024-10-03"

[[trusted.bytes]]
criteria = "safe-to-deploy"
user-id = 6741 # Alice Ryhl (Darksonn)
start = "2021-01-11"
end = "2026-04-07"

[[trusted.cap-fs-ext]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2020-12-11"
end = "2026-03-03"

[[trusted.cap-net-ext]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2023-04-07"
end = "2025-01-03"

[[trusted.cap-primitives]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2020-08-07"
end = "2026-03-03"

[[trusted.cap-rand]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2020-09-24"
end = "2026-03-03"

[[trusted.cap-std]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2020-06-25"
end = "2026-03-03"

[[trusted.cap-time-ext]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2020-09-21"
end = "2026-03-03"

[[trusted.cc]]
criteria = "safe-to-deploy"
user-id = 2915 # Amanieu d'Antras (Amanieu)
start = "2024-02-20"
end = "2025-03-01"

[[trusted.cc]]
criteria = "safe-to-deploy"
user-id = 55123 # rust-lang-owner
start = "2022-10-29"
end = "2026-07-02"

[[trusted.clap]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2021-12-08"
end = "2026-01-06"

[[trusted.clap_builder]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2023-03-28"
end = "2026-12-01"

[[trusted.clap_derive]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2021-12-08"
end = "2026-02-03"

[[trusted.clap_lex]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2022-04-15"
end = "2026-01-06"

[[trusted.cranelift-bitset]]
criteria = "safe-to-deploy"
user-id = 73222 # wasmtime-publish
start = "2024-07-22"
end = "2025-09-16"

[[trusted.cxx]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-12-28"
end = "2025-11-01"

[[trusted.cxx-build]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2020-04-30"
end = "2025-11-01"

[[trusted.cxxbridge-flags]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2020-08-30"
end = "2025-11-01"

[[trusted.cxxbridge-macro]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2020-01-08"
end = "2025-11-01"

[[trusted.equivalent]]
criteria = "safe-to-deploy"
user-id = 539 # Josh Stone (cuviper)
start = "2023-02-05"
end = "2025-01-02"

[[trusted.errno]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2023-08-29"
end = "2025-01-03"

[[trusted.fs-set-times]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2020-09-15"
end = "2026-12-01"

[[trusted.hashbrown]]
criteria = "safe-to-deploy"
user-id = 2915 # Amanieu d'Antras (Amanieu)
start = "2019-04-02"
end = "2025-01-02"

[[trusted.hashbrown]]
criteria = "safe-to-deploy"
user-id = 55123 # rust-lang-owner
start = "2025-04-30"
end = "2026-12-01"

[[trusted.http]]
criteria = "safe-to-deploy"
user-id = 359 # Sean McArthur (seanmonstar)
start = "2019-04-05"
end = "2024-09-21"

[[trusted.http-body-util]]
criteria = "safe-to-deploy"
user-id = 359 # Sean McArthur (seanmonstar)
start = "2022-10-25"
end = "2025-04-01"

[[trusted.httparse]]
criteria = "safe-to-deploy"
user-id = 359 # Sean McArthur (seanmonstar)
start = "2019-07-03"
end = "2026-04-07"

[[trusted.hyper]]
criteria = "safe-to-deploy"
user-id = 359 # Sean McArthur (seanmonstar)
start = "2019-03-01"
end = "2026-04-07"

[[trusted.hyper-tls]]
criteria = "safe-to-deploy"
user-id = 359 # Sean McArthur (seanmonstar)
start = "2019-03-19"
end = "2024-09-21"

[[trusted.hyper-util]]
criteria = "safe-to-deploy"
user-id = 359 # Sean McArthur (seanmonstar)
start = "2022-01-15"
end = "2026-04-07"

[[trusted.indexmap]]
criteria = "safe-to-deploy"
user-id = 539 # Josh Stone (cuviper)
start = "2020-01-15"
end = "2026-12-01"

[[trusted.io-extras]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2021-11-09"
end = "2026-03-03"

[[trusted.io-lifetimes]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2021-06-12"
end = "2024-09-21"

[[trusted.is-terminal]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2022-01-22"
end = "2024-09-21"

[[trusted.itoa]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-05-02"
end = "2024-09-21"

[[trusted.jobserver]]
criteria = "safe-to-deploy"
user-id = 1 # Alex Crichton (alexcrichton)
start = "2019-03-15"
end = "2024-09-21"

[[trusted.js-sys]]
criteria = "safe-to-deploy"
user-id = 1 # Alex Crichton (alexcrichton)
start = "2019-03-04"
end = "2025-01-03"

[[trusted.lazy_static]]
criteria = "safe-to-deploy"
user-id = 539 # Josh Stone (cuviper)
start = "2024-06-21"
end = "2025-07-02"

[[trusted.libc]]
criteria = "safe-to-deploy"
user-id = 51017
start = "2020-03-17"
end = "2025-05-01"

[[trusted.libc]]
criteria = "safe-to-deploy"
user-id = 55123 # rust-lang-owner
start = "2024-08-15"
end = "2026-08-01"

[[trusted.libm]]
criteria = "safe-to-deploy"
user-id = 2915 # Amanieu d'Antras (Amanieu)
start = "2022-02-06"
end = "2025-09-16"

[[trusted.libm]]
criteria = "safe-to-deploy"
user-id = 55123 # rust-lang-owner
start = "2024-10-26"
end = "2026-12-01"

[[trusted.linux-raw-sys]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2021-06-12"
end = "2026-03-03"

[[trusted.memchr]]
criteria = "safe-to-deploy"
user-id = 189 # Andrew Gallant (BurntSushi)
start = "2019-07-07"
end = "2024-10-03"

[[trusted.num_cpus]]
criteria = "safe-to-deploy"
user-id = 359 # Sean McArthur (seanmonstar)
start = "2019-06-10"
end = "2024-09-21"

[[trusted.paste]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-03-19"
end = "2024-09-21"

[[trusted.prettyplease]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2022-01-04"
end = "2024-10-27"

[[trusted.proc-macro2]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-04-23"
end = "2026-12-01"

[[trusted.quote]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-04-09"
end = "2026-12-01"

[[trusted.regex]]
criteria = "safe-to-deploy"
user-id = 189 # Andrew Gallant (BurntSushi)
start = "2019-02-27"
end = "2024-10-03"

[[trusted.regex-automata]]
criteria = "safe-to-deploy"
user-id = 189 # Andrew Gallant (BurntSushi)
start = "2019-02-25"
end = "2024-10-03"

[[trusted.regex-syntax]]
criteria = "safe-to-deploy"
user-id = 189 # Andrew Gallant (BurntSushi)
start = "2019-03-30"
end = "2024-10-03"

[[trusted.rustix]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2021-10-29"
end = "2026-03-03"

[[trusted.rustversion]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-07-08"
end = "2025-11-01"

[[trusted.ryu]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-05-02"
end = "2024-09-21"

[[trusted.scopeguard]]
criteria = "safe-to-deploy"
user-id = 2915 # Amanieu d'Antras (Amanieu)
start = "2020-02-16"
end = "2024-09-21"

[[trusted.scratch]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2020-09-17"
end = "2025-11-01"

[[trusted.semver]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2021-05-25"
end = "2026-12-01"

[[trusted.serde]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-03-01"
end = "2026-03-03"

[[trusted.serde_core]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2025-09-13"
end = "2026-12-01"

[[trusted.serde_derive]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-03-01"
end = "2026-03-03"

[[trusted.serde_json]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-02-28"
end = "2024-09-21"

[[trusted.serde_spanned]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2023-01-20"
end = "2025-05-01"

[[trusted.serde_yaml]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-05-02"
end = "2026-12-01"

[[trusted.slab]]
criteria = "safe-to-deploy"
user-id = 6741 # Alice Ryhl (Darksonn)
start = "2021-10-13"
end = "2026-08-01"

[[trusted.smallvec]]
criteria = "safe-to-deploy"
user-id = 2017 # Matt Brubeck (mbrubeck)
start = "2019-10-28"
end = "2026-03-12"

[[trusted.socket2]]
criteria = "safe-to-deploy"
user-id = 6025 # Thomas de Zeeuw (Thomasdezeeuw)
start = "2020-09-09"
end = "2026-08-01"

[[trusted.syn]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-03-01"
end = "2026-03-03"

[[trusted.system-interface]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2020-10-27"
end = "2026-12-01"

[[trusted.target-lexicon]]
criteria = "safe-to-deploy"
user-id = 6825 # Dan Gohman (sunfishcode)
start = "2019-03-06"
end = "2026-03-03"

[[trusted.termcolor]]
criteria = "safe-to-deploy"
user-id = 189 # Andrew Gallant (BurntSushi)
start = "2019-06-04"
end = "2024-10-03"

[[trusted.thiserror]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-10-09"
end = "2026-09-05"

[[trusted.thiserror-impl]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2019-10-09"
end = "2026-09-05"

[[trusted.tokio]]
criteria = "safe-to-deploy"
user-id = 6741 # Alice Ryhl (Darksonn)
start = "2020-12-25"
end = "2026-02-03"

[[trusted.tokio]]
criteria = "safe-to-deploy"
user-id = 10
start = "2019-03-02"
end = "2025-06-03"

[[trusted.tokio-macros]]
criteria = "safe-to-deploy"
user-id = 6741 # Alice Ryhl (Darksonn)
start = "2020-10-26"
end = "2026-12-01"

[[trusted.toml]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2022-12-14"
end = "2026-12-01"

[[trusted.toml_datetime]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2022-10-21"
end = "2026-12-01"

[[trusted.toml_edit]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2021-09-13"
end = "2025-05-01"

[[trusted.toml_parser]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2025-07-08"
end = "2026-12-01"

[[trusted.toml_writer]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2025-07-08"
end = "2026-12-01"

[[trusted.unicase]]
criteria = "safe-to-deploy"
user-id = 359 # Sean McArthur (seanmonstar)
start = "2019-03-05"
end = "2024-09-21"

[[trusted.unicode-ident]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2021-10-02"
end = "2024-09-21"

[[trusted.unsafe-libyaml]]
criteria = "safe-to-deploy"
user-id = 3618 # David Tolnay (dtolnay)
start = "2022-07-03"
end = "2026-12-01"

[[trusted.walkdir]]
criteria = "safe-to-deploy"
user-id = 189 # Andrew Gallant (BurntSushi)
start = "2019-06-09"
end = "2024-10-03"

[[trusted.want]]
criteria = "safe-to-deploy"
user-id = 359 # Sean McArthur (seanmonstar)
start = "2019-03-19"
end = "2024-09-21"

[[trusted.wasm-bindgen]]
criteria = "safe-to-deploy"
user-id = 1 # Alex Crichton (alexcrichton)
start = "2019-03-04"
end = "2025-01-03"

[[trusted.wasm-bindgen-backend]]
criteria = "safe-to-deploy"
user-id = 1 # Alex Crichton (alexcrichton)
start = "2019-03-04"
end = "2025-01-03"

[[trusted.wasm-bindgen-macro]]
criteria = "safe-to-deploy"
user-id = 1 # Alex Crichton (alexcrichton)
start = "2019-03-04"
end = "2025-01-03"

[[trusted.wasm-bindgen-macro-support]]
criteria = "safe-to-deploy"
user-id = 1 # Alex Crichton (alexcrichton)
start = "2019-03-04"
end = "2025-01-03"

[[trusted.wasm-bindgen-shared]]
criteria = "safe-to-deploy"
user-id = 1 # Alex Crichton (alexcrichton)
start = "2019-03-04"
end = "2025-01-03"

[[trusted.wasm-encoder]]
criteria = "safe-to-deploy"
user-id = 73222 # wasmtime-publish
start = "2024-02-15"
end = "2025-05-01"

[[trusted.wasmparser]]
criteria = "safe-to-deploy"
user-id = 73222 # wasmtime-publish
start = "2024-02-15"
end = "2025-05-01"

[[trusted.wasmprinter]]
criteria = "safe-to-deploy"
user-id = 73222 # wasmtime-publish
start = "2024-02-15"
end = "2025-05-01"

[[trusted.wasmtime-slab]]
criteria = "safe-to-deploy"
user-id = 73222 # wasmtime-publish
start = "2024-03-20"
end = "2025-05-01"

[[trusted.wasmtime-versioned-export-macros]]
criteria = "safe-to-deploy"
user-id = 73222 # wasmtime-publish
start = "2023-08-21"
end = "2026-03-03"

[[trusted.wast]]
criteria = "safe-to-deploy"
user-id = 73222 # wasmtime-publish
start = "2024-02-15"
end = "2025-05-01"

[[trusted.wat]]
criteria = "safe-to-deploy"
user-id = 73222 # wasmtime-publish
start = "2024-02-15"
end = "2025-05-01"

[[trusted.winapi-util]]
criteria = "safe-to-deploy"
user-id = 189 # Andrew Gallant (BurntSushi)
start = "2020-01-11"
end = "2024-10-03"

[[trusted.windows-core]]
criteria = "safe-to-deploy"
user-id = 64539 # Kenny Kerr (kennykerr)
start = "2021-11-15"
end = "2025-01-03"

[[trusted.windows-link]]
criteria = "safe-to-deploy"
user-id = 64539 # Kenny Kerr (kennykerr)
start = "2024-07-17"
end = "2026-09-05"

[[trusted.windows-sys]]
criteria = "safe-to-deploy"
user-id = 64539 # Kenny Kerr (kennykerr)
start = "2021-11-15"
end = "2026-09-05"

[[trusted.windows-targets]]
criteria = "safe-to-deploy"
user-id = 64539 # Kenny Kerr (kennykerr)
start = "2022-09-09"
end = "2026-09-05"

[[trusted.windows_aarch64_gnullvm]]
criteria = "safe-to-deploy"
user-id = 64539 # Kenny Kerr (kennykerr)
start = "2022-09-01"
end = "2026-09-05"

[[trusted.windows_aarch64_msvc]]
criteria = "safe-to-deploy"
user-id = 64539 # Kenny Kerr (kennykerr)
start = "2021-11-05"
end = "2026-09-05"

[[trusted.windows_i686_gnu]]
criteria = "safe-to-deploy"
user-id = 64539 # Kenny Kerr (kennykerr)
start = "2021-10-28"
end = "2026-09-05"

[[trusted.windows_i686_gnullvm]]
criteria = "safe-to-deploy"
user-id = 64539 # Kenny Kerr (kennykerr)
start = "2024-04-02"
end = "2026-03-03"

[[trusted.windows_i686_msvc]]
criteria = "safe-to-deploy"
user-id = 64539 # Kenny Kerr (kennykerr)
start = "2021-10-27"
end = "2026-09-05"

[[trusted.windows_x86_64_gnu]]
criteria = "safe-to-deploy"
user-id = 64539 # Kenny Kerr (kennykerr)
start = "2021-10-28"
end = "2026-09-05"

[[trusted.windows_x86_64_gnullvm]]
criteria = "safe-to-deploy"
user-id = 64539 # Kenny Kerr (kennykerr)
start = "2022-09-01"
end = "2026-09-05"

[[trusted.windows_x86_64_msvc]]
criteria = "safe-to-deploy"
user-id = 64539 # Kenny Kerr (kennykerr)
start = "2021-10-27"
end = "2026-09-05"

[[trusted.winnow]]
criteria = "safe-to-deploy"
user-id = 6743 # Ed Page (epage)
start = "2023-02-22"
end = "2026-12-01"

[[trusted.wit-parser]]
criteria = "safe-to-deploy"
user-id = 73222 # wasmtime-publish
start = "2024-02-15"
end = "2025-05-01"

[[trusted.wizer]]
criteria = "safe-to-deploy"
user-id = 696 # Nick Fitzgerald (fitzgen)
start = "2021-01-07"
end = "2026-03-03"


================================================
FILE: supply-chain/config.toml
================================================

# cargo-vet config file

[cargo-vet]
version = "0.9"

[imports.bytecode-alliance]
url = "https://raw.githubusercontent.com/bytecodealliance/wasmtime/main/supply-chain/audits.toml"

[imports.embark-studios]
url = "https://raw.githubusercontent.com/EmbarkStudios/rust-ecosystem/main/audits.toml"

[imports.google]
url = [
    "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/main/cargo-vet/audits.toml?format=TEXT",
    "https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/third_party/rust_crates/supply-chain/audits.toml?format=TEXT",
]

[imports.isrg]
url = "https://raw.githubusercontent.com/divviup/libprio-rs/main/supply-chain/audits.toml"

[imports.mozilla]
url = "https://raw.githubusercontent.com/mozilla/supply-chain/main/audits.toml"

[[exemptions.addr2line]]
version = "0.19.0"
criteria = "safe-to-deploy"

[[exemptions.bindgen]]
version = "0.72.1"
criteria = "safe-to-deploy"

[[exemptions.bitflags]]
version = "1.3.2"
criteria = "safe-to-deploy"

[[exemptions.bitflags]]
version = "2.10.0"
criteria = "safe-to-deploy"

[[exemptions.block-buffer]]
version = "0.10.4"
criteria = "safe-to-deploy"

[[exemptions.cc]]
version = "1.2.51"
criteria = "safe-to-deploy"

[[exemptions.ciborium]]
version = "0.2.1"
criteria = "safe-to-run"

[[exemptions.ciborium-io]]
version = "0.2.1"
criteria = "safe-to-run"

[[exemptions.ciborium-ll]]
version = "0.2.1"
criteria = "safe-to-run"

[[exemptions.clang-sys]]
version = "1.6.1"
criteria = "safe-to-deploy"

[[exemptions.cpp_demangle]]
version = "0.3.5"
criteria = "safe-to-deploy"

[[exemptions.cpufeatures]]
version = "0.2.9"
criteria = "safe-to-deploy"

[[exemptions.crc32fast]]
version = "1.3.2"
criteria = "safe-to-deploy"

[[exemptions.criterion]]
version = "0.8.0"
criteria = "safe-to-run"

[[exemptions.crossbeam-deque]]
version = "0.8.3"
criteria = "safe-to-deploy"

[[exemptions.crossbeam-epoch]]
version = "0.9.15"
criteria = "safe-to-deploy"

[[exemptions.crossbeam-utils]]
version = "0.8.16"
criteria = "safe-to-deploy"

[[exemptions.digest]]
version = "0.10.7"
criteria = "safe-to-deploy"

[[exemptions.directories-next]]
version = "2.0.0"
criteria = "safe-to-deploy"

[[exemptions.dirs-sys-next]]
version = "0.1.2"
criteria = "safe-to-deploy"

[[exemptions.either]]
version = "1.9.0"
criteria = "safe-to-deploy"

[[exemptions.fallible-iterator]]
version = "0.2.0"
criteria = "safe-to-deploy"

[[exemptions.fd-lock]]
version = "4.0.0"
criteria = "safe-to-deploy"

[[exemptions.find-msvc-tools]]
version = "0.1.6"
criteria = "safe-to-deploy"

[[exemptions.foldhash]]
version = "0.1.4"
criteria = "safe-to-deploy"

[[exemptions.futures-task]]
version = "0.3.21"
criteria = "safe-to-deploy"

[[exemptions.futures-util]]
version = "0.3.21"
criteria = "safe-to-deploy"

[[exemptions.generic-array]]
version = "0.14.7"
criteria = "safe-to-deploy"

[[exemptions.getrandom]]
version = "0.2.10"
criteria = "safe-to-deploy"

[[exemptions.getrandom]]
version = "0.3.4"
criteria = "safe-to-deploy"

[[exemptions.hermit-abi]]
version = "0.3.9"
criteria = "safe-to-deploy"

[[exemptions.im-rc]]
version = "15.1.0"
criteria = "safe-to-deploy"

[[exemptions.ipnet]]
version = "2.8.0"
criteria = "safe-to-deploy"

[[exemptions.itertools]]
version = "0.10.5"
criteria = "safe-to-deploy"

[[exemptions.itertools]]
version = "0.13.0"
criteria = "safe-to-deploy"

[[exemptions.libloading]]
version = "0.7.4"
criteria = "safe-to-deploy"

[[exemptions.litemap]]
version = "0.7.5"
criteria = "safe-to-deploy"

[[exemptions.maybe-owned]]
version = "0.3.4"
criteria = "safe-to-deploy"

[[exemptions.memoffset]]
version = "0.8.0"
criteria = "safe-to-deploy"

[[exemptions.minimal-lexical]]
version = "0.2.1"
criteria = "safe-to-deploy"

[[exemptions.mio]]
version = "0.8.0"
criteria = "safe-to-deploy"

[[exemptions.nom]]
version = "7.1.3"
criteria = "safe-to-deploy"

[[exemptions.object]]
version = "0.36.0"
criteria = "safe-to-deploy"

[[exemptions.once_cell]]
version = "1.18.0"
criteria = "safe-to-deploy"

[[exemptions.oorandom]]
version = "11.1.3"
criteria = "safe-to-run"

[[exemptions.openssl]]
version = "0.10.72"
criteria = "safe-to-deploy"

[[exemptions.openssl-sys]]
version = "0.9.107"
criteria = "safe-to-deploy"

[[exemptions.petgraph]]
version = "0.6.5"
criteria = "safe-to-deploy"

[[exemptions.pkg-config]]
version = "0.3.27"
criteria = "safe-to-deploy"

[[exemptions.plotters]]
version = "0.3.5"
criteria = "safe-to-run"

[[exemptions.plotters-backend]]
version = "0.3.5"
criteria = "safe-to-run"

[[exemptions.plotters-svg]]
version = "0.3.5"
criteria = "safe-to-run"

[[exemptions.ppv-lite86]]
version = "0.2.17"
criteria = "safe-to-deploy"

[[exemptions.r-efi]]
version = "5.3.0"
criteria = "safe-to-deploy"

[[exemptions.rand]]
version = "0.8.5"
criteria = "safe-to-deploy"

[[exemptions.rand_xoshiro]]
version = "0.6.0"
criteria = "safe-to-deploy"

[[exemptions.redox_syscall]]
version = "0.2.16"
criteria = "safe-to-deploy"

[[exemptions.redox_users]]
version = "0.4.3"
criteria = "safe-to-deploy"

[[exemptions.rustc-demangle]]
version = "0.1.23"
criteria = "safe-to-deploy"

[[exemptions.schannel]]
version = "0.1.22"
criteria = "safe-to-deploy"

[[exemptions.security-framework]]
version = "2.9.2"
criteria = "safe-to-deploy"

[[exemptions.security-framework-sys]]
version = "2.9.1"
criteria = "safe-to-deploy"

[[exemptions.sha2]]
version = "0.10.7"
criteria = "safe-to-deploy"

[[exemptions.sized-chunks]]
version = "0.6.5"
criteria = "safe-to-deploy"

[[exemptions.stable_deref_trait]]
version = "1.2.0"
criteria = "safe-to-deploy"

[[exemptions.strsim]]
version = "0.11.0"
criteria = "safe-to-deploy"

[[exemptions.tempfile]]
version = "3.8.0"
criteria = "safe-to-deploy"

[[exemptions.tower-service]]
version = "0.3.2"
criteria = "safe-to-deploy"

[[exemptions.tracing]]
version = "0.1.43"
criteria = "safe-to-deploy"

[[exemptions.tracing-attributes]]
version = "0.1.31"
criteria = "safe-to-deploy"

[[exemptions.tracing-core]]
version = "0.1.35"
criteria = "safe-to-deploy"

[[exemptions.typenum]]
version = "1.16.0"
criteria = "safe-to-deploy"

[[exemptions.uuid]]
version = "1.4.1"
criteria = "safe-to-deploy"

[[exemptions.wasi]]
version = "0.11.0+wasi-snapshot-preview1"
criteria = "safe-to-deploy"

[[exemptions.web-sys]]
version = "0.3.64"
criteria = "safe-to-run"

[[exemptions.winapi]]
version = "0.3.9"
criteria = "safe-to-deploy"

[[exemptions.winapi-i686-pc-windows-gnu]]
version = "0.4.0"
criteria = "safe-to-deploy"

[[exemptions.winapi-x86_64-pc-windows-gnu]]
version = "0.4.0"
criteria = "safe-to-deploy"

[[exemptions.winx]]
version = "0.36.2"
criteria = "safe-to-deploy"

[[exemptions.witx]]
version = "0.9.1"
criteria = "safe-to-deploy"

[[exemptions.zerofrom]]
version = "0.1.6"
criteria = "safe-to-deploy"

[[exemptions.zerofrom-derive]]
version = "0.1.6"
criteria = "safe-to-deploy"

[[exemptions.zstd]]
version = "0.13.1"
criteria = "safe-to-deploy"

[[exemptions.zstd-safe]]
version = "7.1.0"
criteria = "safe-to-deploy"

[[exemptions.zstd-sys]]
version = "2.0.10+zstd.1.5.6"
criteria = "safe-to-deploy"
Download .txt
gitextract_yv2v4z6_/

├── .cargo/
│   └── config.toml
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── config.yml
│   │   ├── feature_request.md
│   │   └── question.md
│   ├── dependabot.yml
│   ├── pull_request_template.md
│   └── workflows/
│       ├── cargo-vet.yml
│       ├── ci.yml
│       └── cla.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE.md
├── Makefile
├── README.md
├── crates/
│   ├── cli/
│   │   ├── Cargo.toml
│   │   ├── benches/
│   │   │   ├── benchmark.rs
│   │   │   └── scripts/
│   │   │       ├── hello_world/
│   │   │       │   └── hello_world.rb
│   │   │       └── transformer/
│   │   │           ├── input.json
│   │   │           ├── preload/
│   │   │           │   └── transformer.rb
│   │   │           ├── ruby_wasm_entry.rb
│   │   │           └── ruvy_entry.rb
│   │   ├── build.rs
│   │   ├── src/
│   │   │   └── main.rs
│   │   └── tests/
│   │       └── integration_test.rs
│   ├── core/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── main.rs
│   │       └── runtime.rs
│   ├── ruby-wasm-assets/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── lib.rs
│   └── wasm-sys/
│       ├── .cargo/
│       │   └── config
│       ├── Cargo.toml
│       ├── build.rs
│       ├── foo.c
│       ├── src/
│       │   └── lib.rs
│       └── wrapper.h
├── prelude/
│   ├── custom_printer.rb
│   └── inspector.rb
├── ruby_examples/
│   ├── hello_world.rb
│   └── use_preludes_and_stdin.rb
├── rust-toolchain.toml
└── supply-chain/
    ├── audits.toml
    └── config.toml
Download .txt
SYMBOL INDEX (67 symbols across 13 files)

FILE: crates/cli/benches/benchmark.rs
  function criterion_benchmark (line 20) | pub fn criterion_benchmark(c: &mut Criterion) {
  type WasmCase (line 67) | struct WasmCase {
    method new (line 81) | fn new(strategy: BuildStrategy, entrypoint: Entrypoint) -> Result<Wasm...
    method setup_for_run (line 104) | fn setup_for_run(
  method fmt (line 75) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type BuildStrategy (line 122) | enum BuildStrategy {
    method build_wasm (line 128) | fn build_wasm(&self, output_path: &Path, entrypoint: &Entrypoint) -> R...
    method wasi_args (line 157) | fn wasi_args(&self, entrypoint: &Entrypoint) -> Vec<String> {
  method fmt (line 178) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Entrypoint (line 190) | struct Entrypoint<'a> {
  function from (line 199) | fn from(value: &'a str) -> Self {
  function cargo_target_tmpdir (line 217) | fn cargo_target_tmpdir() -> PathBuf {
  function ruby_wasm (line 221) | fn ruby_wasm() -> Result<PathBuf> {
  function wasi_vfs (line 235) | fn wasi_vfs() -> Result<PathBuf> {
  function download_wasi_vfs (line 250) | fn download_wasi_vfs(path: &Path, version: &str) -> Result<()> {
  function extract_wasi_vfs (line 261) | fn extract_wasi_vfs(archive: &Path, extract_to: &Path) -> Result<()> {

FILE: crates/cli/benches/scripts/transformer/preload/transformer.rb
  class Transformer (line 1) | class Transformer
    method initialize (line 2) | def initialize(input)
    method transform (line 6) | def transform

FILE: crates/cli/build.rs
  function main (line 5) | fn main() -> Result<()> {

FILE: crates/cli/src/main.rs
  type Opt (line 12) | struct Opt {
  function main (line 26) | async fn main() -> Result<()> {
  function wizen (line 43) | async fn wizen(
  function wasi (line 64) | fn wasi(ruby_code: &str, preload_path: Option<PathBuf>) -> Result<WasiP1...

FILE: crates/cli/tests/integration_test.rs
  function test_hello_world (line 12) | pub fn test_hello_world() -> Result<()> {
  function test_preludes (line 21) | pub fn test_preludes() -> Result<()> {
  type Context (line 36) | struct Context {
    method new (line 42) | fn new(input: &[u8]) -> Context {
  function wasm_path (line 54) | fn wasm_path(test_name: &str) -> String {
  function run_ruvy (line 58) | fn run_ruvy(wasm_path: &str, input_path: &str, preload: Option<&str>) ->...
  function run_wasm (line 74) | fn run_wasm(wasm_path: impl AsRef<Path>, input: &str) -> Result<String> {

FILE: crates/core/src/main.rs
  function main (line 8) | fn main() {
  function load_user_code (line 15) | pub extern "C" fn load_user_code() {
  type WasmCtx (line 29) | struct WasmCtx;
    method new (line 33) | fn new() -> Self {
  method drop (line 40) | fn drop(&mut self) {
  function __wasm_call_ctors (line 56) | fn __wasm_call_ctors();
  function __wasm_call_dtors (line 58) | fn __wasm_call_dtors();

FILE: crates/core/src/runtime.rs
  function init_ruby (line 7) | pub fn init_ruby() {
  function eval (line 14) | pub fn eval(code: &str) -> Result<VALUE> {
  function preload_files (line 27) | pub fn preload_files(path: String) {
  function cleanup_ruby (line 39) | pub fn cleanup_ruby() -> Result<()> {
  function test_int (line 55) | fn test_int() {

FILE: crates/ruby-wasm-assets/src/lib.rs
  constant RUBY_WASM_VERSION (line 19) | const RUBY_WASM_VERSION: &str = "2.1.0";
  constant RUBY_WASM_RUBY_VERSION (line 20) | const RUBY_WASM_RUBY_VERSION: &str = "3_2";
  constant RUBY_WASM_TARGET (line 21) | const RUBY_WASM_TARGET: &str = "wasm32-unknown-wasi";
  constant RUBY_WASM_PROFILE (line 22) | const RUBY_WASM_PROFILE: &str = "minimal";
  function download (line 31) | pub fn download(uri: String, path: &Path) -> Result<()> {
  function download_async (line 35) | async fn download_async(mut uri: String, path: &Path) -> Result<()> {
  function ruby_wasm_base_name (line 62) | pub fn ruby_wasm_base_name() -> String {
  function download_ruby_wasm (line 69) | pub fn download_ruby_wasm(path: &Path) -> Result<()> {
  function extract_tar (line 73) | pub fn extract_tar(archive: &Path, extract_to: &Path, components_to_stri...

FILE: crates/wasm-sys/build.rs
  constant WASI_SDK_VERSION_MAJOR (line 4) | const WASI_SDK_VERSION_MAJOR: usize = 20;
  constant WASI_SDK_VERSION_MINOR (line 5) | const WASI_SDK_VERSION_MINOR: usize = 0;
  function main (line 7) | fn main() -> Result<()> {
  function wasi_sdk_path (line 81) | fn wasi_sdk_path() -> Result<PathBuf> {
  function download_wasi_sdk (line 90) | fn download_wasi_sdk() -> Result<PathBuf> {
  function ruby_wasm_path (line 121) | fn ruby_wasm_path() -> Result<PathBuf> {
  function download_ruby_wasm (line 135) | fn download_ruby_wasm() -> Result<PathBuf> {

FILE: crates/wasm-sys/foo.c
  function pid_t (line 5) | pid_t getpid(void) {
  function asyncify_stop_rewind (line 10) | void asyncify_stop_rewind() {
  function asyncify_start_unwind (line 13) | void asyncify_start_unwind(int x) {

FILE: prelude/custom_printer.rb
  function custom_print (line 1) | def custom_print(input)

FILE: prelude/inspector.rb
  type Inspector (line 1) | module Inspector
    function inspect (line 3) | def inspect(input)

FILE: ruby_examples/use_preludes_and_stdin.rb
  class Discount (line 2) | class Discount
    method initialize (line 4) | def initialize(input)
Condensed preview — 45 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (77K chars).
[
  {
    "path": ".cargo/config.toml",
    "chars": 441,
    "preview": "# Cargo doesn't read directives in individual crates when invoking build\n# commands from the workspace root, hence addin"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 335,
    "preview": "---\nname: Bug report\nabout: File a bug report\ntitle:\nlabels: [\"bug\"]\nassignees:\n---\n\nOperating system: ...\nProcessor arc"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 27,
    "preview": "blank_issues_enabled: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 161,
    "preview": "---\nname: Feature request\nabout: Suggest a feature\ntitle:\nlabels: [\"feature\"]\nassignees:\n---\n\n## Describe your feature\n\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.md",
    "chars": 117,
    "preview": "---\nname: Question\nabout: Questions about Ruvy\ntitle:\nlabels: [\"question\"]\nassignees:\n---\n\n## What is your question?\n"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 395,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"cargo\"\n    directory: \"/\"\n    schedule:\n      interval: \"monthly\"\n    open-p"
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 62,
    "preview": "## Description of the change\n\n## Why am I making this change?\n"
  },
  {
    "path": ".github/workflows/cargo-vet.yml",
    "chars": 882,
    "preview": "name: Cargo vet dependencies\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  cargo-vet:\n    name: cargo_"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 1624,
    "preview": "name: CI\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  ci:\n    runs-on: ubuntu-latest\n    steps:\n    "
  },
  {
    "path": ".github/workflows/cla.yml",
    "chars": 591,
    "preview": "name: Contributor License Agreement (CLA)\n\non:\n  pull_request_target:\n    types: [opened, synchronize]\n  issue_comment:\n"
  },
  {
    "path": ".gitignore",
    "chars": 46,
    "preview": "/target\n.DS_Store\n*.wasm\nwasi-sdk\n*~\n.vscode/\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5487,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 773,
    "preview": "# Contributing to Ruvy\n\nThank you for contributing to Ruvy! Any contributions to Ruvy are appreciated and encouraged.\n\n#"
  },
  {
    "path": "Cargo.toml",
    "chars": 322,
    "preview": "[workspace]\nmembers = [\n  \"crates/wasm-sys\",\n  \"crates/core\",\n  \"crates/cli\",\n  \"crates/ruby-wasm-assets\",\n]\n\nresolver ="
  },
  {
    "path": "LICENSE.md",
    "chars": 1074,
    "preview": "MIT License\n\nCopyright 2023-present, Shopify Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining"
  },
  {
    "path": "Makefile",
    "chars": 1079,
    "preview": ".DEFAULT_GOAL := cli\n\ncli: core\n\tcargo build --package=cli\n\ncore:\n\tcargo build --package=core --release --target=wasm32-"
  },
  {
    "path": "README.md",
    "chars": 3708,
    "preview": "# Ruvy: A Ruby to WebAssembly toolchain\n\n**This project is no longer maintained**\n\n## About this repo\n\nRuvy aims to init"
  },
  {
    "path": "crates/cli/Cargo.toml",
    "chars": 635,
    "preview": "[package]\nname = \"cli\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lan"
  },
  {
    "path": "crates/cli/benches/benchmark.rs",
    "chars": 9052,
    "preview": "use std::{\n    env::consts,\n    ffi::OsStr,\n    fmt::{self, Display},\n    fs,\n    path::{Path, PathBuf},\n    process::{C"
  },
  {
    "path": "crates/cli/benches/scripts/hello_world/hello_world.rb",
    "chars": 20,
    "preview": "puts \"Hello world!\"\n"
  },
  {
    "path": "crates/cli/benches/scripts/transformer/input.json",
    "chars": 11,
    "preview": "{ \"n\": 1 }\n"
  },
  {
    "path": "crates/cli/benches/scripts/transformer/preload/transformer.rb",
    "chars": 111,
    "preview": "class Transformer\n  def initialize(input)\n    @input = input\n  end\n\n  def transform\n    @input + '1'\n  end\nend\n"
  },
  {
    "path": "crates/cli/benches/scripts/transformer/ruby_wasm_entry.rb",
    "chars": 132,
    "preview": "require_relative \"preload/transformer.rb\"\n\ninput = STDIN.gets.strip\ntransformer = Transformer.new(input)\nputs transforme"
  },
  {
    "path": "crates/cli/benches/scripts/transformer/ruvy_entry.rb",
    "chars": 90,
    "preview": "input = STDIN.gets.strip\ntransformer = Transformer::new(input)\nputs transformer.transform\n"
  },
  {
    "path": "crates/cli/build.rs",
    "chars": 718,
    "preview": "use std::{env, fs, path::Path};\n\nuse anyhow::Result;\n\nfn main() -> Result<()> {\n    let destination = Path::new(&env::va"
  },
  {
    "path": "crates/cli/src/main.rs",
    "chars": 2618,
    "preview": "use anyhow::Result;\nuse clap::Parser;\nuse std::{fs, path::PathBuf, process};\nuse wasmtime::{Config, Engine, Linker, Stor"
  },
  {
    "path": "crates/cli/tests/integration_test.rs",
    "chars": 2596,
    "preview": "use std::{env, path::Path, process::Command, str};\n\nuse anyhow::{bail, Result};\nuse wasmtime::{Engine, Linker, Module, S"
  },
  {
    "path": "crates/core/Cargo.toml",
    "chars": 244,
    "preview": "[package]\nname = \"core\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-la"
  },
  {
    "path": "crates/core/src/main.rs",
    "chars": 1873,
    "preview": "mod runtime;\n\nuse runtime::cleanup_ruby;\nuse std::{env, io, sync::OnceLock};\n\nstatic USER_CODE: OnceLock<String> = OnceL"
  },
  {
    "path": "crates/core/src/runtime.rs",
    "chars": 1663,
    "preview": "use std::fs;\n\nuse anyhow::{anyhow, bail, Result};\nuse ruvy_wasm_sys::{rb_eval_string_protect, ruby_init, ruby_init_loadp"
  },
  {
    "path": "crates/ruby-wasm-assets/Cargo.toml",
    "chars": 306,
    "preview": "[package]\nname = \"ruby-wasm-assets\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\nanyhow = { workspace = true }\nhtt"
  },
  {
    "path": "crates/ruby-wasm-assets/src/lib.rs",
    "chars": 3082,
    "preview": "use std::{\n    fs::{self, File},\n    io::Write,\n    path::Path,\n    process::Command,\n};\n\nuse anyhow::{anyhow, bail, Err"
  },
  {
    "path": "crates/wasm-sys/.cargo/config",
    "chars": 32,
    "preview": "[build]\ntarget = \"wasm32-wasip1\""
  },
  {
    "path": "crates/wasm-sys/Cargo.toml",
    "chars": 202,
    "preview": "[package]\nname = \"ruvy-wasm-sys\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[build-dependencies]\nanyhow = { workspace = true }\n"
  },
  {
    "path": "crates/wasm-sys/build.rs",
    "chars": 5844,
    "preview": "use anyhow::{bail, Result};\nuse std::{env, fs, path::PathBuf};\n\nconst WASI_SDK_VERSION_MAJOR: usize = 20;\nconst WASI_SDK"
  },
  {
    "path": "crates/wasm-sys/foo.c",
    "chars": 317,
    "preview": "#include \"./wrapper.h\"\n#include <unistd.h>\n\n// XXX https://github.com/WebAssembly/wasi-libc/commit/659ff414560721b1660a1"
  },
  {
    "path": "crates/wasm-sys/src/lib.rs",
    "chars": 188,
    "preview": "#![allow(non_upper_case_globals)]\n#![allow(non_camel_case_types)]\n#![allow(non_snake_case)]\n#![allow(warnings)]\n#![allow"
  },
  {
    "path": "crates/wasm-sys/wrapper.h",
    "chars": 18,
    "preview": "#include <ruby.h>\n"
  },
  {
    "path": "prelude/custom_printer.rb",
    "chars": 40,
    "preview": "def custom_print(input)\n  puts input\nend"
  },
  {
    "path": "prelude/inspector.rb",
    "chars": 94,
    "preview": "module Inspector\n  class << self\n    def inspect(input)\n      input.inspect\n    end\n  end\nend\n"
  },
  {
    "path": "ruby_examples/hello_world.rb",
    "chars": 18,
    "preview": "puts \"Hello world\""
  },
  {
    "path": "ruby_examples/use_preludes_and_stdin.rb",
    "chars": 228,
    "preview": "input = STDIN.gets.strip\nclass Discount\n  attr_reader :input\n  def initialize(input)\n    @input = input\n  end\nend\n\noutpu"
  },
  {
    "path": "rust-toolchain.toml",
    "chars": 114,
    "preview": "[toolchain]\nchannel = \"1.92.0\"\ncomponents = [\"clippy\", \"rustfmt\"]\ntargets = [\"wasm32-wasip1\"]\nprofile = \"default\"\n"
  },
  {
    "path": "supply-chain/audits.toml",
    "chars": 16226,
    "preview": "\n# cargo-vet audits file\n\n[audits]\n\n[[trusted.aho-corasick]]\ncriteria = \"safe-to-deploy\"\nuser-id = 189 # Andrew Gallant "
  },
  {
    "path": "supply-chain/config.toml",
    "chars": 7027,
    "preview": "\n# cargo-vet config file\n\n[cargo-vet]\nversion = \"0.9\"\n\n[imports.bytecode-alliance]\nurl = \"https://raw.githubusercontent."
  }
]

About this extraction

This page contains the full source code of the Shopify/ruvy GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 45 files (69.0 KB), approximately 21.8k tokens, and a symbol index with 67 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!