forked from wasmerio/wasmer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request wasmerio#357 from wasmerio/michael/sdk-34-updated-…
…wasmersdk-readme Update the README
- Loading branch information
Showing
4 changed files
with
197 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
## Contributing Guide | ||
|
||
### Building | ||
|
||
To build this library you will need to have installed in your system: | ||
|
||
* Node.JS | ||
* [Rust][Rust] | ||
* [wasm-pack][wasm-pack] | ||
* [wabt][wabt] (for `wasm-strip`) | ||
* [binaryen][binaryen] (for `wasm-opt`) | ||
|
||
```sh | ||
npm install | ||
npm run build | ||
``` | ||
|
||
There is also a command for compiling the Rust in debug mode. This tends to be | ||
a lot faster and includes thread-safety checks. | ||
|
||
```sh | ||
npm run build:dev | ||
``` | ||
|
||
### Testing | ||
|
||
Build the package and run the tests: | ||
|
||
```sh | ||
npm run build:dev | ||
npm run test | ||
``` | ||
|
||
### Releasing | ||
|
||
This repository uses [Release Please][release-please] to automate a lot of the | ||
work around creating releases. | ||
|
||
Every time a commit following the [Conventional Commit Style][conv] is merged | ||
into `main`, the [`release-please.yml`](.github/workflows/release-please.yml) | ||
workflow will run and update the "Release PR" to reflect the new changes. | ||
|
||
For commits that just fix bugs (i.e. the message starts with `"fix: "`), the | ||
associated crate will receive a changelog entry and a patch version bump. | ||
Similarly, adding a new feature (i.e. `"feat:"`) does a minor version bump and | ||
adding breaking changes (i.e. `"fix!:"` or `"feat!:"`) will result in a major | ||
version bump. | ||
|
||
When the release PR is merged, the updated changelog and bumped version number | ||
will be merged into the `main` branch, the `release-please.yml` workflow will | ||
automatically generate GitHub Releases, and CI will publish the package to NPM. | ||
|
||
TL;DR: | ||
|
||
1. Use [Conventional Commit Messages][conv] whenever you make a noteworthy change | ||
2. Merge the release PR when ready to release | ||
3. Let the automation do everything else | ||
|
||
[binaryen]: https://github.com/WebAssembly/binaryen | ||
[conv]: https://www.conventionalcommits.org/en/v1.0.0/ | ||
[release-please]: https://github.com/googleapis/release-please | ||
[Rust]: https://www.rust-lang.org/ | ||
[wabt]: https://github.com/WebAssembly/wabt | ||
[wasm-pack]: https://rustwasm.github.io/wasm-pack/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,182 +1,134 @@ | ||
# <img height="48" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/assets/logo.png" alt="Wasmer logo" valign="middle"> Wasmer JS [![Wasmer Slack Channel](https://img.shields.io/static/v1?label=chat&message=on%20Slack&color=green)](https://slack.wasmer.io) | ||
# The Wasmer JavaScript SDK | ||
|
||
This repository consists of multiple packages: | ||
* [Wasmer WASI](#wasmer-wasi) | ||
[![npm (scoped)](https://img.shields.io/npm/v/%40wasmer/sdk)](https://npmjs.org/package/@wasmer/sdk) | ||
[![NPM Downloads](https://img.shields.io/npm/dm/%40wasmer%2Fsdk)](https://npmjs.org/package/@wasmer/sdk) | ||
[![License](https://img.shields.io/npm/l/%40wasmer%2Fsdk)](./LICENSE) | ||
[![Wasmer Discord Channel](https://img.shields.io/discord/1110300506942881873)](https://discord.gg/qBTfsNP7N8) | ||
[![API Docs](https://img.shields.io/badge/API%20Docs-open-blue?link=wasmerio.github.io%2Fwasmer-js%2F)](https://wasmerio.github.io/wasmer-js/) | ||
|
||
# Wasmer WASI | ||
Isomorphic Javascript library for running WASI programs. | ||
|
||
Isomorphic Javascript library for interacting with WASI Modules in Node.js, the Browser and [Deno](https://deno.land/x/wasm). | ||
The Javascript Package supports: | ||
* [X] WASI (with command args, envs and stdio) | ||
* [X] In-Memory filesystem (MemFS) | ||
|
||
### NPM | ||
* [X] WASI support | ||
* [X] Environment variables | ||
* [X] FileSystem access | ||
* [X] Command-line arguments | ||
* [X] Stdio | ||
* [X] WASIX support | ||
* [X] Multi-threading | ||
* [X] Spawning sub-processes | ||
* [ ] Networking | ||
* [X] Mounting directories inside the WASIX instance | ||
* [X] Running packages from the [Wasmer Registry](https://wasmer.io) | ||
* Platforms | ||
* [X] Browser | ||
* [ ] NodeJS | ||
* [ ] Deno | ||
|
||
For instaling `@wasmer/wasi` run this command in your shell: | ||
## Getting Started | ||
|
||
### Install from NPM | ||
|
||
For instaling `@wasmer/sdk`, run this command in your shell: | ||
|
||
```bash | ||
npm install --save @wasmer/wasi | ||
npm install --save @wasmer/sdk | ||
``` | ||
|
||
And then import it in your server or client-side code with: | ||
You can now run WASI packages from the Wasmer registry: | ||
|
||
```js | ||
import { init, WASI } from '@wasmer/wasi'; | ||
``` | ||
|
||
> Check the Node usage examples in https://github.com/wasmerio/wasmer-js/tree/main/examples/node | ||
import { init, Wasmer } from "@wasmer/sdk"; | ||
|
||
### Deno | ||
await init(); | ||
|
||
This package is published in Deno in the `wasm` package, you can import it directly with: | ||
const pkg = await Wasmer.fromRegistry("python/[email protected]"); | ||
const instance = await pkg.entrypoint.run({ | ||
args: ["-c", "print('Hello, World!')"], | ||
}); | ||
|
||
```ts | ||
import { init, WASI } from 'https://deno.land/x/wasm/wasi.ts'; | ||
const { code, stdoutUtf8 } = await instance.wait(); | ||
console.log(`Python exited with ${code}: ${stdoutUtf8}`); | ||
``` | ||
|
||
> Check the Deno usage Examples in https://github.com/wasmerio/wasmer-js/tree/main/examples/deno | ||
### Install from CDN | ||
|
||
## Usage | ||
It is possible to avoid needing to use a bundler by importing `@wasmer/sdk` as | ||
a UMD module. | ||
|
||
```js | ||
// This is needed to load the WASI library first (since is a Wasm module) | ||
await init(); | ||
By adding the following `<script>` tag to your `index.html` file, the library | ||
will be available as the `WasmerSDK` global variable. | ||
|
||
let wasi = new WASI({ | ||
env: { | ||
// 'ENVVAR1': '1', | ||
// 'ENVVAR2': '2' | ||
}, | ||
args: [ | ||
// 'command', 'arg1', 'arg2' | ||
], | ||
}); | ||
|
||
const moduleBytes = fetch("https://deno.land/x/wasm/tests/demo.wasm"); | ||
const module = await WebAssembly.compileStreaming(moduleBytes); | ||
// Instantiate the WASI module | ||
await wasi.instantiate(module, {}); | ||
```html | ||
<script src="https://unpkg.com/@wasmer/sdk@latest"></script> | ||
<script> | ||
const { init, Wasmer } = WasmerSDK; | ||
// Run the start function | ||
let exitCode = wasi.start(); | ||
let stdout = wasi.getStdoutString(); | ||
async function runPython() { | ||
await init(); | ||
// This should print "hello world (exit code: 0)" | ||
console.log(`${stdout}(exit code: ${exitCode})`); | ||
``` | ||
const packageName = "python/[email protected]"; | ||
const pkg = await Wasmer.fromRegistry(packageName); | ||
const instance = await pkg.entrypoint.run({ | ||
args: ["-c", "print('Hello, World!')"], | ||
}); | ||
## API Docs | ||
|
||
<!-- Please check the full API documents here: | ||
https://docs.wasmer.io/integrations/js/reference-api --> | ||
|
||
### Typescript API | ||
|
||
```typescript | ||
export class WASI { | ||
constructor(config: any); | ||
readonly fs: MemFS; | ||
|
||
instantiate(module: any, imports: object): WebAssembly.Instance; | ||
// Start the WASI Instance, it returns the status code when calling the start | ||
// function | ||
start(instance: WebAssembly.Instance): number; | ||
// Get the stdout buffer | ||
// Note: this method flushes the stdout | ||
getStdoutBuffer(): Uint8Array; | ||
// Get the stdout data as a string | ||
// Note: this method flushes the stdout | ||
getStdoutString(): string; | ||
// Get the stderr buffer | ||
// Note: this method flushes the stderr | ||
getStderrBuffer(): Uint8Array; | ||
// Get the stderr data as a string | ||
// Note: this method flushes the stderr | ||
getStderrString(): string; | ||
// Set the stdin buffer | ||
setStdinBuffer(buf: Uint8Array): void; | ||
// Set the stdin data as a string | ||
setStdinString(input: string): void; | ||
} | ||
|
||
export class MemFS { | ||
constructor(); | ||
readDir(path: string): Array<any>; | ||
createDir(path: string): void; | ||
removeDir(path: string): void; | ||
removeFile(path: string): void; | ||
rename(path: string, to: string): void; | ||
metadata(path: string): object; | ||
open(path: string, options: any): JSVirtualFile; | ||
} | ||
|
||
export class JSVirtualFile { | ||
lastAccessed(): BigInt; | ||
lastModified(): BigInt; | ||
createdTime(): BigInt; | ||
size(): BigInt; | ||
setLength(new_size: BigInt): void; | ||
read(): Uint8Array; | ||
readString(): string; | ||
write(buf: Uint8Array): number; | ||
writeString(buf: string): number; | ||
flush(): void; | ||
seek(position: number): number; | ||
} | ||
``` | ||
const { code, stdoutUtf8 } = await instance.wait(); | ||
## Building | ||
console.log(`Python exited with ${code}: ${stdoutUtf8}`); | ||
} | ||
To build this library you will need to have installed in your system: | ||
runPython(); | ||
</script> | ||
``` | ||
|
||
* Node.JS | ||
* [Rust][Rust] | ||
* [wasm-pack][wasm-pack] | ||
* [wabt][wabt] (for `wasm-strip`) | ||
* [binaryen][binaryen] (for `wasm-opt`) | ||
Alternatively, the package can be imported directly from the CDN by turning the | ||
script into a module. | ||
|
||
```sh | ||
npm i | ||
npm run build | ||
``` | ||
```html | ||
<script defer type="module"> | ||
import { init, Wasmer } from "https://unpkg.com/@wasmer/sdk@latest/dist/Library.mjs"; | ||
## Testing | ||
async function runPython() { | ||
await init(); | ||
Build the pkg and run the tests: | ||
... | ||
} | ||
```sh | ||
npm run build | ||
npm run test | ||
runPython(); | ||
</script> | ||
``` | ||
|
||
# What is WebAssembly? | ||
### Cross-Origin Isolation | ||
|
||
Quoting [the WebAssembly site](https://webassembly.org/): | ||
Browsers have implemented security measures to mitigate the Spectre and Meltdown | ||
vulnerabilities. | ||
|
||
> WebAssembly (abbreviated Wasm) is a binary instruction format for a | ||
> stack-based virtual machine. Wasm is designed as a portable target | ||
> for compilation of high-level languages like C/C++/Rust, enabling | ||
> deployment on the web for client and server applications. | ||
These measures restrict the sharing of `SharedArrayBuffer`` objects with Web | ||
Workers unless the execution context is deemed secure. | ||
|
||
About speed: | ||
The `@wasmer/sdk` package uses a threadpool built on Web Workers and requires | ||
sharing the same `SharedArrayBuffer` across multiple workers to enable WASIX | ||
threads to access the same address space. This requirement is crucial even for | ||
running single-threaded WASIX programs because the SDK internals rely on | ||
`SharedArrayBuffer` for communication with Web Workers. | ||
|
||
> WebAssembly aims to execute at native speed by taking advantage of | ||
> [common hardware | ||
> capabilities](https://webassembly.org/docs/portability/#assumptions-for-efficient-execution) | ||
> available on a wide range of platforms. | ||
To avoid Cross-Origin Isolation issues, make sure any web pages using | ||
`@wasmer/sdk` are served over HTTPS and have the following headers set: | ||
|
||
About safety: | ||
```yaml | ||
"Cross-Origin-Opener-Policy": "same-origin" | ||
"Cross-Origin-Embedder-Policy": "require-corp" | ||
``` | ||
> WebAssembly describes a memory-safe, sandboxed [execution | ||
> environment](https://webassembly.org/docs/semantics/#linear-memory) […]. | ||
See the [`SharedArrayBuffer` and Cross-Origin Isolation][coi-docs] section under | ||
the *Troubleshooting Common Problems* docs for more. | ||
|
||
# License | ||
|
||
The entire project is under the MIT License. Please read [the | ||
`LICENSE` file][license]. | ||
|
||
[coi-docs]: https://docs.wasmer.io/javascript-sdk/explainers/troubleshooting#sharedarraybuffer-and-cross-origin-isolation | ||
[license]: https://github.com/wasmerio/wasmer/blob/master/LICENSE | ||
[Rust]: https://www.rust-lang.org/ | ||
[wasm-pack]: https://rustwasm.github.io/wasm-pack/ | ||
[wabt]: https://github.com/WebAssembly/wabt | ||
[binaryen]: https://github.com/WebAssembly/binaryen |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Wasmer JavaScript SDK</title> | ||
<script defer type="module"> | ||
import { init, Wasmer } from "https://unpkg.com/@wasmer/sdk@latest/dist/Library.mjs"; | ||
|
||
async function runPython() { | ||
const status = document.getElementById("status"); | ||
|
||
status.innerHTML = "Initializing..."; | ||
await init(); | ||
|
||
const packageName = "python/[email protected]"; | ||
status.innerHTML = `Fetching ${packageName}...`; | ||
const pkg = await Wasmer.fromRegistry(packageName); | ||
|
||
status.innerHTML = `Starting ${packageName}...`; | ||
const instance = await pkg.entrypoint.run({ | ||
args: ["-c", "print('Hello, World!')"], | ||
}); | ||
|
||
status.innerHTML = `Running ${packageName}...`; | ||
const { code, stdoutUtf8 } = await instance.wait(); | ||
|
||
status.innerHTML = `Exited with status code: ${code}`; | ||
const stdout = document.getElementById("stdout"); | ||
stdout.innerHTML = stdoutUtf8; | ||
} | ||
|
||
runPython(); | ||
</script> | ||
</head> | ||
|
||
<body> | ||
<h1 id="status"></h1> | ||
<pre><code id="stdout"></code></pre> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters