Skip to content

Commit

Permalink
Merge pull request #4192 from wasmerio/wasmer-js-fixes
Browse files Browse the repository at this point in the history
More fixes to support Wasmer JS
  • Loading branch information
syrusakbary authored Oct 30, 2023
2 parents 7cb550d + c0a695d commit 448a557
Show file tree
Hide file tree
Showing 29 changed files with 658 additions and 408 deletions.
24 changes: 0 additions & 24 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ required-features = ["backend"]
[[example]]
name = "errors"
path = "examples/errors.rs"
required-features = ["sys"]
required-features = ["backend"]

[[example]]
name = "imported-function-env"
Expand Down
3 changes: 0 additions & 3 deletions lib/api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ wasmer-compiler-llvm = { path = "../compiler-llvm", version = "=4.2.3", optional
wasm-bindgen = { version = "0.2.74", optional = true }
js-sys = { version = "0.3.51", optional = true }
rusty_jsc = { version = "0.1.0", optional = true }
# rusty_jsc = { path="../../../rusty_jsc", optional = true }
wasmparser = { version = "0.83", default-features = false, optional = true }

# - Mandatory dependencies for `sys` on Windows.
Expand All @@ -70,9 +69,7 @@ macro-wasmer-universal-test = { version = "4.2.3", path = "./macro-wasmer-univer
# - Mandatory dependencies for `js`.
wasmer-types = { path = "../types", version = "=4.2.3", default-features = false, features = ["std"] }
wasm-bindgen = "0.2.74"
wasm-bindgen-downcast = { version = "0.1.1" }
js-sys = "0.3.51"
#web-sys = { version = "0.3.51", features = [ "console" ] }
wasmer-derive = { path = "../derive", version = "=4.2.3" }
# - Optional dependencies for `js`.
wasmparser = { version = "0.95", default-features = false, optional = true }
Expand Down
2 changes: 1 addition & 1 deletion lib/api/src/externals/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl Memory {
/// Creates a new host `Memory` from the provided [`MemoryType`].
///
/// This function will construct the `Memory` using the store
/// [`BaseTunables`][crate::sys::BaseTunables].
/// `BaseTunables`.
///
/// # Example
///
Expand Down
3 changes: 1 addition & 2 deletions lib/api/src/externals/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ impl Table {
///
/// All the elements in the table will be set to the `init` value.
///
/// This function will construct the `Table` using the store
/// [`BaseTunables`][crate::sys::BaseTunables].
/// This function will construct the `Table` using the store `BaseTunables`.
pub fn new(
store: &mut impl AsStoreMut,
ty: TableType,
Expand Down
7 changes: 2 additions & 5 deletions lib/api/src/js/as_js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,13 +232,10 @@ impl AsJs for Memory {
memory_type: &Self::DefinitionType,
value: &JsValue,
) -> Result<Self, JsError> {
if value.is_instance_of::<JsMemory>() {
if let Some(memory) = value.dyn_ref::<JsMemory>() {
Ok(Memory::from_vm_extern(
store,
VMMemory::new(
value.clone().unchecked_into::<JsMemory>(),
memory_type.clone(),
),
VMMemory::new(memory.clone(), memory_type.clone()),
))
} else {
Err(JsError::new(&format!(
Expand Down
24 changes: 22 additions & 2 deletions lib/api/src/js/externals/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,16 @@ impl Memory {
js_sys::Reflect::set(&descriptor, &"shared".into(), &ty.shared.into()).unwrap();
}

let js_memory = js_sys::WebAssembly::Memory::new(&descriptor)
.map_err(|_e| MemoryError::Generic("Error while creating the memory".to_owned()))?;
let js_memory = js_sys::WebAssembly::Memory::new(&descriptor).map_err(|e| {
let error_message = if let Some(s) = e.as_string() {
s
} else if let Some(obj) = e.dyn_ref::<js_sys::Object>() {
obj.to_string().into()
} else {
"Error while creating the memory".to_string()
};
MemoryError::Generic(error_message)
})?;

Ok(js_memory)
}
Expand Down Expand Up @@ -164,6 +172,18 @@ impl std::cmp::PartialEq for Memory {
}
}

impl From<Memory> for crate::Memory {
fn from(value: Memory) -> Self {
crate::Memory(value)
}
}

impl From<crate::Memory> for Memory {
fn from(value: crate::Memory) -> Self {
value.0
}
}

/// Underlying buffer for a memory.
#[derive(Copy, Clone, Debug)]
pub(crate) struct MemoryBuffer<'a> {
Expand Down
82 changes: 43 additions & 39 deletions lib/api/src/js/js_handle.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use std::ops::{Deref, DerefMut};
use std::{
ops::{Deref, DerefMut},
sync::atomic::{AtomicU32, Ordering},
};

use js_sys::Symbol;
use wasm_bindgen::JsValue;

use self::integrity_check::IntegrityCheck;
Expand Down Expand Up @@ -101,14 +105,9 @@ mod integrity_check {

#[cfg(debug_assertions)]
mod integrity_check {
use std::{
fmt::Write as _,
panic::Location,
sync::atomic::{AtomicU32, Ordering},
};
use std::{fmt::Write as _, panic::Location};

use js_sys::{JsString, Symbol};
use wasm_bindgen::JsValue;
use js_sys::JsString;

#[derive(Debug, Clone, PartialEq)]
pub(crate) struct IntegrityCheck {
Expand All @@ -122,7 +121,7 @@ mod integrity_check {
#[track_caller]
pub(crate) fn new(type_name: &'static str) -> Self {
IntegrityCheck {
original_thread: current_thread_id(),
original_thread: super::current_thread_id(),
created: Location::caller(),
type_name,
backtrace: record_backtrace(),
Expand All @@ -131,7 +130,7 @@ mod integrity_check {

#[track_caller]
pub(crate) fn check(&self) {
let current_thread = current_thread_id();
let current_thread = super::current_thread_id();

if current_thread != self.original_thread {
let IntegrityCheck {
Expand Down Expand Up @@ -177,35 +176,6 @@ mod integrity_check {
}
}

/// Get a unique ID for the current "thread" (i.e. web worker or the main
/// thread).
///
/// This works by creating a `$WASMER_THREAD_ID` symbol and setting it on
/// the global object.
fn current_thread_id() -> u32 {
static NEXT_ID: AtomicU32 = AtomicU32::new(0);

let global = js_sys::global();
let thread_id_symbol = Symbol::for_("$WASMER_THREAD_ID");

if let Some(v) = js_sys::Reflect::get(&global, &thread_id_symbol)
.ok()
.and_then(|v| v.as_f64())
{
// Note: we use a symbol so we know for sure that nobody else created
// this field.
return v as u32;
}

// Looks like we haven't set the thread ID yet.
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);

js_sys::Reflect::set(&global, &thread_id_symbol, &JsValue::from(id))
.expect("Setting a field on the global object should never fail");

id
}

fn record_backtrace() -> Option<String> {
let err = js_sys::Error::new("");
let stack = JsString::from(wasm_bindgen::intern("stack"));
Expand All @@ -215,3 +185,37 @@ mod integrity_check {
.and_then(|v| v.as_string())
}
}

/// A browser polyfill for [`std::thread::ThreadId`] [`std::thread::current()`].
///
/// This works by creating a `$WASMER_THREAD_ID` symbol and setting it on
/// the global object. As long as they use the same `SharedArrayBuffer` for
/// their linear memory, each thread (i.e. web worker or the UI thread) is
/// guaranteed to get a unique ID.
///
/// This is mainly intended for use in `wasmer-wasix` and `wasmer-js`, and may
/// go away in the future.
#[doc(hidden)]
pub fn current_thread_id() -> u32 {
static NEXT_ID: AtomicU32 = AtomicU32::new(0);

let global = js_sys::global();
let thread_id_symbol = Symbol::for_("$WASMER_THREAD_ID");

if let Some(v) = js_sys::Reflect::get(&global, &thread_id_symbol)
.ok()
.and_then(|v| v.as_f64())
{
// Note: we use a symbol so we know for sure that nobody else created
// this field.
return v as u32;
}

// Looks like we haven't set the thread ID yet.
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);

js_sys::Reflect::set(&global, &thread_id_symbol, &JsValue::from(id))
.expect("Setting a field on the global object should never fail");

id
}
3 changes: 1 addition & 2 deletions lib/api/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,4 @@ pub(crate) mod typed_function;
pub(crate) mod vm;
mod wasm_bindgen_polyfill;

pub use crate::js::as_js::AsJs;
pub use crate::js::module::ModuleTypeHints;
pub use self::{as_js::AsJs, js_handle::current_thread_id, module::ModuleTypeHints};
9 changes: 7 additions & 2 deletions lib/api/src/js/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ use wasmer_types::{
///
/// This should be fixed once the JS-Types Wasm proposal is adopted
/// by the browsers:
/// https://github.com/WebAssembly/js-types/blob/master/proposals/js-types/Overview.md
/// <https://github.com/WebAssembly/js-types/blob/master/proposals/js-types/Overview.md>
///
/// Until that happens, we annotate the module with the expected
/// types so we can built on top of them at runtime.
#[derive(Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ModuleTypeHints {
/// The type hints for the imported types
pub imports: Vec<ExternType>,
Expand Down Expand Up @@ -474,3 +474,8 @@ impl From<WebAssembly::Module> for crate::module::Module {
crate::module::Module(module.into())
}
}
impl From<crate::module::Module> for WebAssembly::Module {
fn from(value: crate::module::Module) -> Self {
value.0.module.into_inner()
}
}
4 changes: 2 additions & 2 deletions lib/api/src/js/module_info_polyfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
//!
//! This shall not be needed once the JS type reflection API is available
//! for the Wasm imports and exports.
//!
//! https://github.com/WebAssembly/js-types/blob/master/proposals/js-types/Overview.md
//!
//! <https://github.com/WebAssembly/js-types/blob/master/proposals/js-types/Overview.md>
use core::convert::TryFrom;
use std::vec::Vec;
use wasmer_types::entity::EntityRef;
Expand Down
Loading

0 comments on commit 448a557

Please sign in to comment.