Skip to content

Commit

Permalink
feat: Rewrote the top-level Wasmer type to represent a package that…
Browse files Browse the repository at this point in the history
… has been loaded and is ready for execution
  • Loading branch information
Michael-F-Bryan committed Nov 27, 2023
1 parent e55dfe7 commit 9f54cb5
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 18 deletions.
7 changes: 2 additions & 5 deletions src/facade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{
Instance, JsRuntime, Runtime, SpawnOptions,
};

/// The entrypoint to the Wasmer SDK.
/// A package from the Wasmer registry.
#[wasm_bindgen]
pub struct Wasmer {
runtime: Arc<Runtime>,
Expand Down Expand Up @@ -70,10 +70,7 @@ impl Wasmer {
let specifier: PackageSpecifier = app_id.parse()?;
let config = config.unwrap_or_default();

let runtime = match config.runtime().as_runtime() {
Some(rt) => Arc::clone(&*rt),
None => Arc::clone(&self.runtime),
};
let runtime = config.runtime().resolve()?.into_inner();

let pkg = BinaryPackage::from_registry(&specifier, &*runtime).await?;
let command_name = config
Expand Down
28 changes: 25 additions & 3 deletions src/js_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use wasm_bindgen::{prelude::wasm_bindgen, JsCast};
use crate::{runtime::Runtime, tasks::ThreadPool, utils::Error};

#[derive(Clone, Debug, wasm_bindgen_derive::TryFromJsValue)]
#[repr(transparent)]
#[wasm_bindgen(js_name = "Runtime")]
pub struct JsRuntime {
// Note: This is just a wrapper around the "real" runtime implementation.
Expand All @@ -18,10 +19,20 @@ pub struct JsRuntime {
rt: Arc<Runtime>,
}

impl JsRuntime {
pub fn new(rt: Arc<Runtime>) -> Self {
JsRuntime { rt }
}

pub fn into_inner(self) -> Arc<Runtime> {
self.rt
}
}

#[wasm_bindgen(js_class = "Runtime")]
impl JsRuntime {
#[wasm_bindgen(constructor)]
pub fn new(options: Option<RuntimeOptions>) -> Result<JsRuntime, Error> {
pub fn js_new(options: Option<RuntimeOptions>) -> Result<JsRuntime, Error> {
let pool_size = options.as_ref().and_then(|options| options.pool_size());

let pool = match pool_size {
Expand All @@ -44,7 +55,11 @@ impl JsRuntime {
rt.set_registry(registry, api_key.as_deref())?;
}

Ok(JsRuntime { rt: Arc::new(rt) })
if let Some(gateway) = options.as_ref().and_then(|opts| opts.network_gateway()) {
rt.set_network_gateway(gateway);
}

Ok(JsRuntime::new(Arc::new(rt)))
}

/// Get a reference to the global runtime, optionally initializing it if
Expand Down Expand Up @@ -77,7 +92,7 @@ impl DerefMut for JsRuntime {

impl From<Arc<Runtime>> for JsRuntime {
fn from(value: Arc<Runtime>) -> Self {
JsRuntime { rt: value }
JsRuntime::new(value)
}
}

Expand Down Expand Up @@ -110,6 +125,10 @@ export type RuntimeOptions = {
* An optional API key to use when sending requests to the Wasmer registry.
*/
apiKey?: string;
/**
* Enable networking (i.e. TCP and UDP) via a gateway server.
*/
networkGateway?: string;
};
"#;

Expand All @@ -127,6 +146,9 @@ extern "C" {
#[wasm_bindgen(method, getter, js_name = "apiKey")]
fn api_key(this: &RuntimeOptions) -> Option<String>;

#[wasm_bindgen(method, getter, js_name = "networkGateway")]
fn network_gateway(this: &RuntimeOptions) -> Option<String>;

#[wasm_bindgen(typescript_type = "string | null | undefined")]
type MaybeRegistryUrl;
}
Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod streams;
mod tasks;
mod utils;
mod ws;
mod wasmer;

use std::sync::Mutex;

Expand Down Expand Up @@ -45,7 +46,7 @@ pub(crate) const DEFAULT_REGISTRY: &str =

#[wasm_bindgen]
pub fn wat2wasm(wat: String) -> Result<js_sys::Uint8Array, utils::Error> {
let wasm = wasmer::wat2wasm(wat.as_bytes())?;
let wasm = ::wasmer::wat2wasm(wat.as_bytes())?;
Ok(wasm.as_ref().into())
}

Expand Down
13 changes: 11 additions & 2 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ use virtual_fs::TmpFileSystem;
use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue, UnwrapThrowExt};
use wasmer_wasix::WasiEnvBuilder;

use crate::{utils::Error, Directory, DirectoryInit, JsRuntime, StringOrBytes};
use crate::{runtime::Runtime, utils::Error, Directory, DirectoryInit, JsRuntime, StringOrBytes};

#[wasm_bindgen]
extern "C" {
/// A proxy for `Option<&Runtime>`.
#[wasm_bindgen]
pub(crate) type OptionalRuntime;
pub type OptionalRuntime;

#[wasm_bindgen]
pub(crate) type OptionalDirectories;
Expand Down Expand Up @@ -239,6 +239,15 @@ impl OptionalRuntime {
Some(rt)
}
}

/// Use [`OptionalRuntime::as_runtime()`] to resolve the instance, getting
/// a reference to the global [`Runtime`] if one wasn't provided.
pub(crate) fn resolve(&self) -> Result<JsRuntime, Error> {
match self.as_runtime() {
Some(rt) => Ok(rt),
None => Runtime::lazily_initialized().map(JsRuntime::from),
}
}
}

#[wasm_bindgen]
Expand Down
9 changes: 2 additions & 7 deletions src/run.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use std::sync::Arc;

use futures::channel::oneshot;
use wasm_bindgen::{prelude::wasm_bindgen, JsCast};
use wasmer_wasix::{Runtime as _, WasiEnvBuilder};

use crate::{instance::ExitCondition, utils::Error, Instance, RunOptions, Runtime};
use crate::{instance::ExitCondition, utils::Error, Instance, RunOptions};

const DEFAULT_PROGRAM_NAME: &str = "wasm";

Expand All @@ -13,10 +11,7 @@ const DEFAULT_PROGRAM_NAME: &str = "wasm";
pub async fn run(wasm_module: WasmModule, config: RunOptions) -> Result<Instance, Error> {
let _span = tracing::debug_span!("run").entered();

let runtime = match config.runtime().as_runtime() {
Some(rt) => Arc::clone(&*rt),
None => Runtime::lazily_initialized()?,
};
let runtime = config.runtime().resolve()?.into_inner();

let program_name = config
.program()
Expand Down
82 changes: 82 additions & 0 deletions src/wasmer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use std::sync::Arc;

use js_sys::{JsString, Reflect};
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
use wasmer_wasix::{bin_factory::BinaryPackage, runtime::resolver::PackageSpecifier};

use crate::{options::OptionalRuntime, runtime::Runtime, utils::Error};

/// A package from the Wasmer registry.
#[derive(Debug, Clone)]
#[wasm_bindgen]
pub struct Wasmer {
/// The package's entrypoint.
#[wasm_bindgen(getter_with_clone)]
pub entrypoint: Option<Command>,
/// A map containing all commands available to the package (including
/// dependencies).
#[wasm_bindgen(getter_with_clone)]
pub commands: Commands,
}

#[wasm_bindgen]
impl Wasmer {
#[wasm_bindgen(js_name = "fromRegistry")]
pub async fn js_from_registry(
specifier: &str,
runtime: OptionalRuntime,
) -> Result<Wasmer, Error> {
Wasmer::from_registry(specifier, runtime).await
}
}

/// The actual impl - with `#[tracing::instrument]` macros.
impl Wasmer {
#[tracing::instrument(skip(runtime))]
async fn from_registry(specifier: &str, runtime: OptionalRuntime) -> Result<Wasmer, Error> {
let specifier = PackageSpecifier::parse(specifier)?;
let runtime = runtime.resolve()?.into_inner();

let pkg = BinaryPackage::from_registry(&specifier, &*runtime).await?;
let pkg = Arc::new(pkg);

let commands = Commands::default();

for cmd in &pkg.commands {
let name = JsString::from(cmd.name());
let value = JsValue::from(Command {
name: name.clone(),
runtime: Arc::clone(&runtime),
pkg: Arc::clone(&pkg),
});
Reflect::set(&commands, &name, &value).map_err(Error::js)?;
}

let entrypoint = pkg.entrypoint_cmd.as_deref().map(|name| Command {
name: name.into(),
pkg: Arc::clone(&pkg),
runtime,
});

Ok(Wasmer {
entrypoint,
commands,
})
}
}

#[derive(Debug, Clone)]
#[wasm_bindgen]
pub struct Command {
#[wasm_bindgen(getter_with_clone)]
pub name: JsString,
pkg: Arc<BinaryPackage>,
runtime: Arc<Runtime>,
}

#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(typescript_type = "Record<string, Command>", extends = js_sys::Object)]
#[derive(Clone, Default, Debug)]
pub type Commands;
}

0 comments on commit 9f54cb5

Please sign in to comment.