Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revamp documentation #752

Merged
merged 8 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
227 changes: 12 additions & 215 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,69 +10,23 @@
<p>
<a href="https://github.com/bytecodealliance/javy/actions/workflows/ci.yml"><img alt="Build status" src="https://github.com/bytecodealliance/javy/actions/workflows/ci.yml/badge.svg?branch=main" /></a>
<a href="https://bytecodealliance.zulipchat.com/#narrow/stream/370816-javy"><img src="https://img.shields.io/badge/zulip-join_chat-brightgreen.svg" alt="zulip chat" /></a>
</p>
</p>
saulecabrera marked this conversation as resolved.
Show resolved Hide resolved
</div>

## About this repo

**Introduction**: Run your JavaScript on WebAssembly. Javy takes your JavaScript code, and executes it in a WebAssembly embedded JavaScript runtime. Javy can create _very_ small Wasm modules in the 1 to 16 KB range with use of dynamic linking. The default static linking produces modules that are at least 869 KB in size.

## Runtime requirements

When running the official Javy binary on Linux, `glibc` 2.31 or greater must be available. You may need to update the version of your operating system if you are using an older version of `glibc`.

## Extending Javy

If you would like to use Javy for your own project but need to make some changes, read the [extending Javy documentation](docs/extending.md) for one approach to consider.

## Contributing

We welcome feedback, bug reports and bug fixes. We're also happy to discuss feature development but please discuss the features in an issue before contributing.
**Introduction**: Run your JavaScript on WebAssembly. Javy takes your JavaScript
code, and executes it in a WebAssembly embedded JavaScript runtime. Javy can
create _very_ small Wasm modules in the 1 to 16 KB range with use of dynamic
linking. The default static linking produces modules that are at least 869 KB in
size.

Read our [contribution documentation](docs/contributing.md) for additional information on contributing to Javy.
## Installation

## Requirements to build
Pre-compiled binaries of the Javy CLI can be found on [the releases
page](https://github.com/bytecodealliance/javy/releases).

- On Ubuntu, `sudo apt-get install curl pkg-config libssl-dev clang`
- [rustup](https://rustup.rs/)
- Stable Rust, installed via `rustup install stable && rustup default stable`
- wasm32-wasi, can be installed via `rustup target add wasm32-wasi`
- cmake, depending on your operating system and architecture, it might not be
installed by default. On MacOS it can be installed with `homebrew` via `brew
install cmake`. On Ubuntu, `sudo apt-get install cmake`.
- Rosetta 2 if running MacOS on Apple Silicon, can be installed via
`softwareupdate --install-rosetta`

## Development requirements

- wasmtime-cli, can be installed via `cargo install wasmtime-cli` (required for
`cargo-wasi`)
- cargo-wasi, can be installed via `cargo install cargo-wasi`
- cargo-hack, can be installed via `cargo +stable install cargo-hack --locked`

## How to build

Inside the Javy repository, run:
```
$ cargo build -p javy-core --target=wasm32-wasi -r
$ cargo build -p javy-cli -r
```

Alternatively if you want to install the Javy CLI globally, inside the Javy repository run:
```
$ cargo build -p javy-core --target=wasm32-wasi -r
$ cargo install --path crates/cli
```

If you are going to recompile frequently, you may want to prepend `CARGO_PROFILE_RELEASE_LTO=off` to cargo build for the CLI to speed up the build.

## Using Javy

Pre-compiled binaries of the Javy CLI can be found on [the releases page](https://github.com/bytecodealliance/javy/releases).

Javy supports ES2023 JavaScript. Javy does _not_ provide support for NodeJS or CommonJS APIs.

### Compiling to WebAssembly
## Example

Define your JavaScript like:

Expand Down Expand Up @@ -144,163 +98,6 @@ $ echo '{ "n": 2, "bar": "baz" }' | wasmtime index.wasm
{"foo":3,"newBar":"baz!"}%
```

If you have a lot of JavaScript and you want to reduce compile times, try using the `--no-source-compression` flag. It will skip compressing the JavaScript source code when generating the Wasm module but will result in the Wasm module being larger.

```bash
javy build index.js -o destination/index.wasm -C source-compression=n
```

### Exporting functions

To export exported JavaScript functions, you can pass a WIT file and WIT world when running `javy build`. Only ESM exports are supported (that is, Node.js/CommonJS exports are _not_ supported). For each exported JavaScript function, Javy will add an additional function export to the WebAssembly module. Exported functions with arguments and generators are not supported. Return values will also be dropped and not returned. The Wasm module generated is a core Wasm module, **not** a Wasm component.

An example looks like:

`index.js`:
```javascript
export function foo() {
console.log("Hello from foo!");
}

console.log("Hello world!");
```

`index.wit`:
```
package local:main;

world index-world {
export foo: func();
}
```

In the terminal:
```bash
$ javy build index.js -C wit=index.wit -C wit-world=index-world -o index.wasm
$ wasmtime run --invoke foo index.wasm
Hello world!
Hello from foo!
```

The WIT package name and WIT world name do not matter as long as they are present and syntactically correct WIT (that is, it needs to be two names separated by a `:`). The name of the WIT world (that is, the value after `world` and before `{`) must be passed as the `-n` argument. The `-n` argument identifies the WIT world in the WIT file for the Wasm module generated by `javy build`.

#### Exports with multiple words

Exported function names with multiple words have to written in kebab-case in the WIT file (that is a restriction imposed by WIT), they are exported from the Wasm module as kebab-case to match the WIT, and Javy will match the WIT export to a JS export with the same name but in camel-case.

`index.js`:
```javascript
export function fooBar() {
console.log("In foo-bar");
}
```

`index.wit`:
```
package local:main;

world index {
export foo-bar: func();
}
```

In the terminal:
```bash
$ javy build index.js -C wit=index.wit -C wit-world=index -o index.wasm
$ wasmtime run --invoke foo-bar index.wasm
In foo-bar
```

#### Exporting a default function

Exporting a function named `default` in the WIT world exports a function named `default` on the Wasm module and corresponds to either an exported default function or exported default arrow function in JS.

`index.js`:
```javascript
export default function () {
console.log("In default");
}
```

`index.wit`:
```
package local:main;

world index {
export default: func();
}
```

In the terminal:
```bash
$ javy build index.js -C wit=index.wit -C wit-world=index -o index.wasm
$ wasmtime run --invoke default index.wasm
In default
```

You can also export a default function by writing:
```javascript
export default () => {
console.log("default");
}
```

### Invoking Javy-generated modules programatically
## Documentation

Javy-generated modules are by design WASI only and follow the [command pattern](https://github.com/WebAssembly/WASI/blob/snapshot-01/design/application-abi.md#current-unstable-abi). Any input must be passed via `stdin` and any output will be placed in `stdout`. This is especially important when invoking Javy modules from a custom embedding.

In a runtime like Wasmtime, [wasmtime-wasi](
https://docs.rs/wasmtime-wasi/latest/wasmtime_wasi/struct.WasiCtx.html#method.set_stdin)
can be used to set the input and retrieve the output.

To embed Javy in a Node.js application see this [example](docs/nodejs-embedding.md).

### Creating and using dynamically linked modules

An important use for Javy is for when you may want or need to generate much smaller Wasm modules. Using the `-d` flag when invoking Javy will create a dynamically linked module which will have a much smaller file size than a statically linked module. Statically linked modules embed the JS engine inside the module while dynamically linked modules rely on Wasm imports to provide the JS engine. Dynamically linked modules have special requirements that statically linked modules do not and will not execute in WebAssembly runtimes that do not meet these requirements.

To successfully instantiate and run a dynamically linked Javy module, the execution environment must provide a `javy_quickjs_provider_v2` namespace for importing that links to the exports provided by the `javy_quickjs_provider.wasm` module. Dynamically linked modules **cannot** be instantiated in environments that do not provide this import.

Dynamically linked Javy modules are tied to QuickJS since they use QuickJS's bytecode representation.

#### Obtaining the QuickJS provider module

The `javy_quickjs_provider.wasm` module is available as an asset on the Javy release you are using. It can also be obtained by running `javy emit-provider -o <path>` to write the module into `<path>`.

#### Creating and running a dynamically linked module on the CLI

```
$ echo 'console.log("hello world!");' > my_code.js
$ javy build -C dynamic -o my_code.wasm my_code.js
$ javy emit-provider -o provider.wasm
$ wasmtime run --preload javy_quickjs_provider_v2=provider.wasm my_code.wasm
hello world!
```

## Releasing

1. Update the root `Cargo.toml` with the new version
2. Create a tag for the new version like `v0.2.0`
```
git tag v0.2.0
git push origin --tags
```
3. Create a new release from the new tag in github [here](https://github.com/bytecodealliance/javy/releases/new).
4. A GitHub Action will trigger for `publish.yml` when a release is published ([i.e. it doesn't run on drafts](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#:~:text=created%2C%20edited%2C%20or%20deleted%20activity%20types%20for%20draft%20releases)), creating the artifacts for downloading.

## Testing locally

1. Clone submodules
```
git submodules init
git submodules update
```
2. Install cargo hack
```
cargo +stable install cargo-hack --locked
```
3. Run tests, eg:
```
cargo +stable install cargo-hack --locked
```
CARGO_TARGET_WASM32_WASI_RUNNER="wasmtime --dir=." cargo hack wasi test --workspace --exclude=javy-cli --exclude=javy-config --each-feature -- --nocapture
Read the documentation [here](./docs/index.md)
111 changes: 0 additions & 111 deletions docs/contributing-architecture.md

This file was deleted.

29 changes: 0 additions & 29 deletions docs/contributing.md

This file was deleted.

Loading
Loading