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

Support wasm-pack backend #706

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
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
19 changes: 19 additions & 0 deletions compiler/wasm-pack/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "hello_world"
version = "0.1.0"
authors = ["The wasm-bindgen Developers"]
edition = "2018"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "^0.2"
web-sys = "^0.3"
js-sys = "^0.3"
wasm-bindgen-futures = "^0.4"
yew = "0.17"
seed = "0.8.0"

[package.metadata.wasm-pack.profile.release]
wasm-opt = false
17 changes: 17 additions & 0 deletions compiler/wasm-pack/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# syntax = docker/dockerfile:experimental

# fetch dependencies to local
FROM shepmaster/rust-nightly as sources
RUN cargo install wasm-pack
ADD --chown=playground src/lib.rs /playground/src/lib.rs
# TODO support top 100 crates
ADD --chown=playground Cargo.toml /playground/Cargo.toml
RUN cargo fetch

# build dependencies
FROM sources
RUN wasm-pack build --target web --out-name package --dev
RUN rm src/*.rs

ADD --chown=playground cargo-pack /playground/.cargo/bin/
ENTRYPOINT ["/playground/tools/entrypoint.sh"]
28 changes: 28 additions & 0 deletions compiler/wasm-pack/cargo-pack
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash

set -eu

# Rewrite our arguments to be `cargo build` instead of `cargo wasm`;
# this assumes that the command will always be `cargo wasm ...`. We
# capture the output directory in order to place the result file.
shift # Ignore "wasm"
args=()
while (( "$#" )); do
if [[ "$1" == "--" ]] ; then
: # Ignore
elif [[ "$1" == "-o" ]] ; then
shift
output="$1"
else
args+="$1"
fi

shift
done
# Greatly inspired from https://gitlab.com/strwrite/seed-playground
# --dev flag disables the wasm-opt for optimization downloaded from networks
wasm-pack build --target web --out-name package --dev

cat pkg/package_bg.wasm | base64 > "${output}.wasm"
cat pkg/package.js | base64 > "${output}.js"

19 changes: 19 additions & 0 deletions compiler/wasm-pack/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use wasm_bindgen::prelude::*;

// Called by our JS entry point to run the example
#[wasm_bindgen(start)]
pub fn run() -> Result<(), JsValue> {
// Use `web_sys`'s global `window` function to get a handle on the global
// window object.
let window = web_sys::window().expect("no global `window` exists");
let document = window.document().expect("should have a document on window");
let body = document.body().expect("document should have a body");

// Manufacture the element we're gonna append
let val = document.create_element("p")?;
val.set_text_content(Some("Hello from Rust!"));

body.append_child(&val)?;

Ok(())
}
2 changes: 0 additions & 2 deletions ui/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions ui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ fn main() {
mount.mount("/meta/version/miri", meta_version_miri);
mount.mount("/meta/gist", gist_router);
mount.mount("/evaluate.json", evaluate);
mount.mount("/wasm-pack", wasm_pack);

let mut chain = Chain::new(mount);
let file_logger = FileLogger::new(logfile).expect("Unable to create file logger");
Expand Down Expand Up @@ -281,6 +282,16 @@ fn evaluate(req: &mut Request<'_, '_>) -> IronResult<Response> {
})
}

fn wasm_pack(req: &mut Request<'_, '_>) -> IronResult<Response>{
with_sandbox(req, |sandbox, req: WasmPackRequest| {
let req = req.try_into()?;
sandbox
.wasm_pack(&req)
.map(WasmPackResponse::from)
.context(WasmPack)
})
}

fn with_sandbox<Req, Resp, F>(req: &mut Request<'_, '_>, f: F) -> IronResult<Response>
where
F: FnOnce(Sandbox, Req) -> Result<Resp>,
Expand Down Expand Up @@ -488,6 +499,8 @@ pub enum Error {
Execution { source: sandbox::Error },
#[snafu(display("Evaluation operation failed: {}", source))]
Evaluation { source: sandbox::Error },
#[snafu(display("wasm-pack operation failed: {}", source))]
WasmPack { source: sandbox::Error },
#[snafu(display("Linting operation failed: {}", source))]
Linting { source: sandbox::Error },
#[snafu(display("Expansion operation failed: {}", source))]
Expand Down Expand Up @@ -691,6 +704,20 @@ struct EvaluateResponse {
error: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
struct WasmPackRequest {
code: String
}

#[derive(Debug, Clone, Serialize)]
struct WasmPackResponse {
success: bool,
wasm_js: String,
wasm_bg: String,
stdout: String,
stderr: String,
}

impl TryFrom<CompileRequest> for sandbox::CompileRequest {
type Error = Error;

Expand Down Expand Up @@ -927,6 +954,29 @@ impl From<sandbox::ExecuteResponse> for EvaluateResponse {
}
}

impl TryFrom<WasmPackRequest> for sandbox::WasmPackRequest {
type Error = Error;

fn try_from(me: WasmPackRequest) -> Result<Self> {
Ok(sandbox::WasmPackRequest {
code: me.code,
..sandbox::WasmPackRequest::default()
})
}
}

impl From<sandbox::WasmPackResponse> for WasmPackResponse {
fn from(me: sandbox::WasmPackResponse) -> Self {
WasmPackResponse {
success: me.success,
wasm_bg: me.wasm_bg,
wasm_js: me.wasm_js,
stdout: me.stdout,
stderr: me.stderr,
}
}
}

fn parse_target(s: &str) -> Result<sandbox::CompileTarget> {
Ok(match s {
"asm" => sandbox::CompileTarget::Assembly(sandbox::AssemblyFlavor::Att,
Expand Down
82 changes: 80 additions & 2 deletions ui/src/sandbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,43 @@ impl Sandbox {
})
}

// Greatly inspired from https://gitlab.com/strwrite/seed-playground
pub fn wasm_pack(&self, req: &WasmPackRequest) -> Result<WasmPackResponse> {
use CompileTarget::*;
use CrateType::*;

let compile_req = CompileRequest{
backtrace: false,
channel: Channel::WasmPack,
code: req.code.clone(),
crate_type: Library(LibraryType::Cdylib),
edition: Some(Edition::Rust2018),
mode: Mode::Debug,
target: WasmPack,
tests: false,
};
let res = self.compile(&compile_req)?;
let js_file =
fs::read_dir(&self.output_dir)
.context(UnableToReadOutput)?
.flat_map(|entry| entry)
.map(|entry| entry.path())
.find(|path| path.extension() == Some(OsStr::new("js")));

let js_code = match js_file {
Some(file) => read(&file)?.unwrap_or_else(String::new),
None => String::new() // TODO: return proper error?
};

Ok(WasmPackResponse {
success: res.success,
stdout: res.stdout,
stderr: res.stderr,
wasm_bg: res.code,
wasm_js: js_code
})
}

pub fn format(&self, req: &FormatRequest) -> Result<FormatResponse> {
self.write_source_code(&req.code)?;
let command = self.format_command(req);
Expand Down Expand Up @@ -419,10 +456,14 @@ impl Sandbox {
mount_output_dir.push(":");
mount_output_dir.push("/playground-result");

// let mut mount_output_wasm = self.scratch.as_path().join("pkg").as_os_str().to_os_string();
// mount_output_wasm.push(":");
// mount_output_wasm.push("/playground/pkg");
let mut cmd = basic_secure_docker_command();

cmd
.arg("--volume").arg(&mount_input_file)
// .arg("--volume").arg(&mount_output_wasm)
.arg("--volume").arg(&mount_output_dir);

cmd
Expand Down Expand Up @@ -469,6 +510,7 @@ fn build_execution_command(target: Option<CompileTarget>, channel: Channel, mode
let mut cmd = vec!["cargo"];

match (target, req.crate_type(), tests) {
(Some(WasmPack), _, _) => cmd.push("pack"),
(Some(Wasm), _, _) => cmd.push("wasm"),
(Some(_), _, _) => cmd.push("rustc"),
(_, _, true) => cmd.push("test"),
Expand Down Expand Up @@ -511,12 +553,14 @@ fn build_execution_command(target: Option<CompileTarget>, channel: Channel, mode
Mir => cmd.push("--emit=mir"),
Hir => cmd.push("-Zunpretty=hir"),
Wasm => { /* handled by cargo-wasm wrapper */ },
WasmPack => { /* handled by cargo-wasmpack wrapper */ },
}
}

}
log::debug!("{:?}", &cmd);
cmd
}


fn set_execution_environment(cmd: &mut Command, target: Option<CompileTarget>, req: impl CrateTypeRequest + EditionRequest + BacktraceRequest) {
use self::CompileTarget::*;

Expand Down Expand Up @@ -623,6 +667,7 @@ pub enum CompileTarget {
Mir,
Hir,
Wasm,
WasmPack,
}

impl CompileTarget {
Expand All @@ -633,6 +678,7 @@ impl CompileTarget {
CompileTarget::Mir => "mir",
CompileTarget::Hir => "hir",
CompileTarget::Wasm => "wat",
CompileTarget::WasmPack => "wasm",
};
OsStr::new(ext)
}
Expand All @@ -648,6 +694,7 @@ impl fmt::Display for CompileTarget {
Mir => "Rust MIR".fmt(f),
Hir => "Rust HIR".fmt(f),
Wasm => "WebAssembly".fmt(f),
WasmPack => "WasmPack".fmt(f),
}
}
}
Expand All @@ -657,6 +704,7 @@ pub enum Channel {
Stable,
Beta,
Nightly,
WasmPack,
}

impl Channel {
Expand All @@ -667,6 +715,7 @@ impl Channel {
Stable => "rust-stable",
Beta => "rust-beta",
Nightly => "rust-nightly",
WasmPack => "rust-wasm-pack",
}
}
}
Expand Down Expand Up @@ -924,6 +973,35 @@ pub struct MacroExpansionResponse {
pub stderr: String,
}

#[derive(Debug, Clone)]
pub struct WasmPackRequest {
pub code: String,
pub crate_type: CrateType,
pub output_name: String,
}

impl Default for WasmPackRequest {
fn default() -> Self {
WasmPackRequest {
code: String::from(""),
crate_type: CrateType::Library(LibraryType::Rlib),
output_name: "wasm".to_string(),
}
}
}

impl CrateTypeRequest for WasmPackRequest {
fn crate_type(&self) -> CrateType { self.crate_type }
}

#[derive(Debug, Clone)]
pub struct WasmPackResponse {
pub wasm_js: String,
pub wasm_bg: String,
pub success: bool,
pub stdout: String,
pub stderr: String,
}
#[cfg(test)]
mod test {
use super::*;
Expand Down