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

Wasmer.sh Demo #330

Merged
merged 13 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
256 changes: 123 additions & 133 deletions Cargo.lock

Large diffs are not rendered by default.

20 changes: 12 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ tracing = { version = "0.1", features = ["log", "release_max_level_info"] }
tracing-futures = { version = "0.2" }
tracing-wasm = { version = "0.2" }
url = "2.4.0"
virtual-net = { version = "0.5.0", default-features = false, features = ["remote"] }
virtual-fs = { version = "0.8.0", default-features = false }
virtual-net = { version = "0.6.0", default-features = false, features = ["remote"] }
virtual-fs = { version = "0.9.0", default-features = false }
wasm-bindgen = { version = "0.2" }
wasm-bindgen-downcast = "0.1"
wasm-bindgen-futures = "0.4"
wasm-bindgen-test = "0.3.37"
wasmer = { version = "4.1", default-features = false, features = ["js", "js-default"] }
wasmer-wasix = { version = "0.13", default-features = false, features = ["js", "js-default"] }
wasmer = { version = "4.2.2", default-features = false, features = ["js", "js-default", "tracing", "wasm-types-polyfill"] }
wasmer-wasix = { version = "0.15", default-features = false, features = ["js", "js-default"] }
wee_alloc = { version = "0.4", optional = true }
webc = "5.3.0"
shared-buffer = "0.1.3"
Expand Down Expand Up @@ -99,7 +99,11 @@ dwarf-debug-info = false
wasm-opt = ["--enable-threads", "--enable-bulk-memory", "-Oz"]

[patch.crates-io]
virtual-net = { git = "https://github.com/wasmerio/wasmer", branch = "wasmer-js-fixes" }
virtual-fs = { git = "https://github.com/wasmerio/wasmer", branch = "wasmer-js-fixes" }
wasmer-wasix = { git = "https://github.com/wasmerio/wasmer", branch = "wasmer-js-fixes" }
wasmer = { git = "https://github.com/wasmerio/wasmer", branch = "wasmer-js-fixes" }
# virtual-net = { git = "https://github.com/wasmerio/wasmer", branch = "wasmer-js-fixes" }
# virtual-fs = { git = "https://github.com/wasmerio/wasmer", branch = "wasmer-js-fixes" }
# wasmer-wasix = { git = "https://github.com/wasmerio/wasmer", branch = "wasmer-js-fixes" }
# wasmer = { git = "https://github.com/wasmerio/wasmer", branch = "wasmer-js-fixes" }
virtual-net = { path = "../wasmer/lib/virtual-net" }
virtual-fs = { path = "../wasmer/lib/virtual-fs" }
wasmer-wasix = { path = "../wasmer/lib/wasix" }
wasmer = { path = "../wasmer/lib/api" }
1 change: 1 addition & 0 deletions examples/wasmer.sh/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.parcel-cache/
15 changes: 15 additions & 0 deletions examples/wasmer.sh/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Python REPL</title>
</head>

<body>
<div id="app"></div>
<script type="module" src="index.ts"></script>
</body>

</html>
66 changes: 66 additions & 0 deletions examples/wasmer.sh/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import "xterm/css/xterm.css";

import { SpawnConfig, Wasmer, init } from "@wasmer/wasix";
import { Terminal } from "xterm";

const encoder = new TextEncoder();

const packageName = "sharrattj/bash";
const args: string[] = [];
const uses: string[] = ["sharrattj/coreutils"];

async function main() {
console.log("Initializing");
await init();

const term = new Terminal();

const element = document.getElementById("app")!;
term.open(element);

term.writeln("Starting...");
const wasmer = new Wasmer();

while (true) {
console.log("Starting instance");
await runInstance(term, wasmer, packageName, { args, uses });
console.log("Rebooting...");
term.writeln("Rebooting...");
}
}

async function runInstance(term: Terminal, wasmer: Wasmer, packageName: string, config: SpawnConfig) {
const instance = await wasmer.spawn(packageName, config);
term.clear();

const stdin: WritableStreamDefaultWriter<Uint8Array> = instance.stdin!.getWriter();
term.onData(line => { stdin.write(encoder.encode(line)); });

const stdout: ReadableStreamDefaultReader<Uint8Array> = instance.stdout.getReader();
copyStream(stdout, line => term.write(line));

const stderr: ReadableStreamDefaultReader<Uint8Array> = instance.stderr.getReader();
copyStream(stderr, line => term.write(line));

const { code } = await instance.wait();

if (code != 0) {
term.writeln(`\nExit code: ${code}`);
}
}

async function copyStream(reader: ReadableStreamDefaultReader<Uint8Array>, cb: (line: string) => void) {
const decoder = new TextDecoder("utf-8");

while(true) {
const {done, value} = await reader.read();

if (done || !value) {
break;
}
const chunk = decoder.decode(value);
cb(chunk);
}
}

addEventListener("DOMContentLoaded", () => main());
24 changes: 24 additions & 0 deletions examples/wasmer.sh/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "@wasmer/shell",
"version": "1.0.0",
"description": "A Bash terminal in your browser, powered by WebAssembly and WASIX.",
"scripts": {
"dev": "rollup -c -w",
"build": "rollup -c"
},
"dependencies": {
"@wasmer/wasix": "file:../..",
"xterm": "4.19"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.4",
"@rollup/plugin-node-resolve": "^15.2.1",
"@rollup/plugin-typescript": "^11.1.4",
"@rollup/plugin-url": "^8.0.1",
"@web/rollup-plugin-html": "^2.0.1",
"rollup": "^3.29.3",
"rollup-plugin-import-css": "^3.3.4",
"rollup-plugin-serve": "^2.0.2"
},
"browserslist": "> 0.5%, last 2 versions, not dead"
}
37 changes: 37 additions & 0 deletions examples/wasmer.sh/rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { rollupPluginHTML as html } from "@web/rollup-plugin-html";
import typescript from "@rollup/plugin-typescript";
import commonjs from "@rollup/plugin-commonjs";
import { nodeResolve } from "@rollup/plugin-node-resolve";
import url from "@rollup/plugin-url";
import serve from "rollup-plugin-serve";
import css from "rollup-plugin-import-css";

export default function configure() {
const config = {
input: "index.html",
output: { dir: "dist" },
plugins: [
html(),
typescript(),
nodeResolve(),
commonjs(),
url({
include: ["**/*.wasm"],
limit: 1 * 1024 * 1024,
}),
css(),
],
};

if (process.env.ROLLUP_WATCH) {
config.plugins.push(serve({
contentBase: "dist",
headers: {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
}
}));
}

return config;
}
94 changes: 93 additions & 1 deletion lib.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,94 @@
// @deno-types="./pkg/wasmer_wasix_js.d.ts"
import { Buffer } from "buffer";
export * from "./pkg/wasmer_wasix_js";
// @ts-ignore
import load, { WorkerState } from "./pkg/wasmer_wasix_js";
import wasm_bytes from "./pkg/wasmer_wasix_js_bg.wasm";

interface MimeBuffer extends Buffer {
type: string;
typeFull: string;
charset: string;
}

/**
* Returns a `Buffer` instance from the given data URI `uri`.
*
* @param {String} uri Data URI to turn into a Buffer instance
* @returns {Buffer} Buffer instance from Data URI
* @api public
*/
function dataUriToBuffer(uri: string): MimeBuffer {
if (!/^data:/i.test(uri)) {
throw new TypeError(
'`uri` does not appear to be a Data URI (must begin with "data:")'
);
}

// strip newlines
uri = uri.replace(/\r?\n/g, '');

// split the URI up into the "metadata" and the "data" portions
const firstComma = uri.indexOf(',');
if (firstComma === -1 || firstComma <= 4) {
throw new TypeError('malformed data: URI');
}

// remove the "data:" scheme and parse the metadata
const meta = uri.substring(5, firstComma).split(';');

let charset = '';
let base64 = false;
const type = meta[0] || 'text/plain';
let typeFull = type;
for (let i = 1; i < meta.length; i++) {
if (meta[i] === 'base64') {
base64 = true;
} else {
typeFull += `;${ meta[i]}`;
if (meta[i].indexOf('charset=') === 0) {
charset = meta[i].substring(8);
}
}
}
// defaults to US-ASCII only if type is not provided
if (!meta[0] && !charset.length) {
typeFull += ';charset=US-ASCII';
charset = 'US-ASCII';
}

// get the encoded data portion and decode URI-encoded chars
const encoding = base64 ? 'base64' : 'ascii';
const data = unescape(uri.substring(firstComma + 1));
const buffer = Buffer.from(data, encoding) as MimeBuffer;

// set `.type` and `.typeFull` properties to MIME type
buffer.type = type;
buffer.typeFull = typeFull;

// set the `.charset` property
buffer.charset = charset;

return buffer;
}

export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;

let inited: Promise<any> | null = null;

/**
* Initialize the underlying WebAssembly module.
*/
export const init = async (input?: InitInput | Promise<InitInput>, maybe_memory?: WebAssembly.Memory, force?: boolean) => {
if (inited === null || force === true) {
if (!input) {
input = await WebAssembly.compile(dataUriToBuffer(wasm_bytes as any as string));
}
inited = load(input, maybe_memory);
}
await inited;
}

// HACK: We save these to the global scope because it's the most reliable way to
// make sure worker.js gets access to them. Normal exports are removed when
// using a bundler.
(globalThis as any)["__WASMER_INTERNALS__"] = { WorkerState, init };
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
{
"name": "@wasmer/wasi",
"version": "1.2.2",
"name": "@wasmer/wasix",
"version": "0.1.0",
"main": "dist/Library.cjs.min.js",
"module": "dist/Library.esm.min.js",
"unpkg": "dist/Library.umd.min.js",
"types": "dist/lib.d.ts",
"keywords": [
"webassembly",
"wasm",
"wasi"
"wasi",
"wasix"
],
"description": "Isomorphic Javascript library for interacting with WASI Modules in Node.js and the Browser.",
"author": "Wasmer Engineering Team <[email protected]>",
Expand All @@ -25,7 +26,7 @@
"access": "public"
},
"scripts": {
"build": "wasm-pack build --release --target=web --weak-refs && wasm-opt pkg/wasmer_wasix_js_bg.wasm -O2 -o pkg/wasmer_wasix_js_bg.wasm && wasm-strip pkg/wasmer_wasix_js_bg.wasm && rollup -c --environment BUILD:production",
"build": "wasm-pack build --release --target=web --weak-refs && wasm-opt pkg/wasmer_wasix_js_bg.wasm -O2 -o pkg/wasmer_wasix_js_bg.wasm && rollup -c --environment BUILD:production",
"build:dev": "wasm-pack build --dev --target=web --weak-refs && rollup -c --environment BUILD:development",
"dev": "rollup -c -w",
"test": "web-test-runner 'tests/**/*.test.ts' --node-resolve --esbuild-target auto --config ./web-dev-server.config.mjs",
Expand All @@ -44,6 +45,7 @@
"rimraf": "~3.0.2",
"rollup": "~3.5.1",
"rollup-plugin-dts": "^5.0.0",
"rollup-plugin-node-polyfills": "^0.2.1",
"rollup-plugin-typescript2": "^0.34.1",
"ts-loader": "^9.2.6",
"tslib": "^2.3.1",
Expand Down
4 changes: 3 additions & 1 deletion rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// ],
// };

import nodePolyfills from 'rollup-plugin-node-polyfills';
import terser from '@rollup/plugin-terser';
import pkg from './package.json' assert { type: 'json' };
import dts from "rollup-plugin-dts";
Expand Down Expand Up @@ -68,8 +69,9 @@ const makeConfig = (env = 'development') => {
typescript(),
url({
include: ['**/*.wasm'],
limit: 1 * 1024 * 1024,
limit: 100 * 1000 * 1000,
}),
nodePolyfills(),
]
};

Expand Down
Loading
Loading