mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-08 13:48:26 +00:00
Added support for Globals
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
use crate::instance::Instance;
|
use crate::instance::Instance;
|
||||||
|
use crate::wasm_bindgen_polyfill::Global;
|
||||||
use crate::WasmerEnv;
|
use crate::WasmerEnv;
|
||||||
use js_sys::Function;
|
use js_sys::Function;
|
||||||
use js_sys::WebAssembly::{Memory, Table};
|
use js_sys::WebAssembly::{Memory, Table};
|
||||||
@@ -7,7 +8,7 @@ use std::fmt;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasm_bindgen::JsCast;
|
use wasm_bindgen::JsCast;
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
use wasmer_types::{ExternType, FunctionType, MemoryType, TableType};
|
use wasmer_types::{ExternType, FunctionType, GlobalType, MemoryType, TableType};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct VMMemory {
|
pub struct VMMemory {
|
||||||
@@ -21,6 +22,18 @@ impl VMMemory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct VMGlobal {
|
||||||
|
pub(crate) global: Global,
|
||||||
|
pub(crate) ty: GlobalType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VMGlobal {
|
||||||
|
pub(crate) fn new(global: Global, ty: GlobalType) -> Self {
|
||||||
|
Self { global, ty }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct VMTable {
|
pub struct VMTable {
|
||||||
pub(crate) table: Table,
|
pub(crate) table: Table,
|
||||||
@@ -85,8 +98,9 @@ pub enum Export {
|
|||||||
|
|
||||||
/// A memory export value.
|
/// A memory export value.
|
||||||
Memory(VMMemory),
|
Memory(VMMemory),
|
||||||
// /// A global export value.
|
|
||||||
// Global(VMGlobal),
|
/// A global export value.
|
||||||
|
Global(VMGlobal),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Export {
|
impl Export {
|
||||||
@@ -95,6 +109,7 @@ impl Export {
|
|||||||
Export::Memory(js_wasm_memory) => js_wasm_memory.memory.as_ref(),
|
Export::Memory(js_wasm_memory) => js_wasm_memory.memory.as_ref(),
|
||||||
Export::Function(js_func) => js_func.function.as_ref(),
|
Export::Function(js_func) => js_func.function.as_ref(),
|
||||||
Export::Table(js_wasm_table) => js_wasm_table.table.as_ref(),
|
Export::Table(js_wasm_table) => js_wasm_table.table.as_ref(),
|
||||||
|
Export::Global(js_wasm_global) => js_wasm_global.global.as_ref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,6 +127,16 @@ impl From<(JsValue, ExternType)> for Export {
|
|||||||
panic!("Extern type doesn't match js value type");
|
panic!("Extern type doesn't match js value type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ExternType::Global(global_type) => {
|
||||||
|
if val.is_instance_of::<Global>() {
|
||||||
|
return Export::Global(VMGlobal::new(
|
||||||
|
val.unchecked_into::<Global>(),
|
||||||
|
global_type,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
panic!("Extern type doesn't match js value type");
|
||||||
|
}
|
||||||
|
}
|
||||||
ExternType::Function(function_type) => {
|
ExternType::Function(function_type) => {
|
||||||
if val.is_instance_of::<Function>() {
|
if val.is_instance_of::<Function>() {
|
||||||
return Export::Function(VMFunction::new(
|
return Export::Function(VMFunction::new(
|
||||||
|
|||||||
100
lib/js-api/src/externals/global.rs
vendored
100
lib/js-api/src/externals/global.rs
vendored
@@ -1,14 +1,16 @@
|
|||||||
|
use crate::export::Export;
|
||||||
|
use crate::export::VMGlobal;
|
||||||
use crate::exports::{ExportError, Exportable};
|
use crate::exports::{ExportError, Exportable};
|
||||||
use crate::externals::Extern;
|
use crate::externals::Extern;
|
||||||
use crate::store::{Store, StoreObject};
|
use crate::store::{Store, StoreObject};
|
||||||
use crate::types::Val;
|
use crate::types::{Val, ValType};
|
||||||
|
use crate::wasm_bindgen_polyfill::Global as JSGlobal;
|
||||||
use crate::GlobalType;
|
use crate::GlobalType;
|
||||||
use crate::Mutability;
|
use crate::Mutability;
|
||||||
use crate::RuntimeError;
|
use crate::RuntimeError;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasmer_engine::Export;
|
use wasm_bindgen::JsValue;
|
||||||
use wasmer_vm::{Global as RuntimeGlobal, VMGlobal};
|
|
||||||
|
|
||||||
/// A WebAssembly `global` instance.
|
/// A WebAssembly `global` instance.
|
||||||
///
|
///
|
||||||
@@ -16,7 +18,10 @@ use wasmer_vm::{Global as RuntimeGlobal, VMGlobal};
|
|||||||
/// It consists of an individual value and a flag indicating whether it is mutable.
|
/// It consists of an individual value and a flag indicating whether it is mutable.
|
||||||
///
|
///
|
||||||
/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#global-instances>
|
/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#global-instances>
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Global {
|
pub struct Global {
|
||||||
|
store: Store,
|
||||||
|
vm_global: VMGlobal,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Global {
|
impl Global {
|
||||||
@@ -56,25 +61,33 @@ impl Global {
|
|||||||
|
|
||||||
/// Create a `Global` with the initial value [`Val`] and the provided [`Mutability`].
|
/// Create a `Global` with the initial value [`Val`] and the provided [`Mutability`].
|
||||||
fn from_value(store: &Store, val: Val, mutability: Mutability) -> Result<Self, RuntimeError> {
|
fn from_value(store: &Store, val: Val, mutability: Mutability) -> Result<Self, RuntimeError> {
|
||||||
if !val.comes_from_same_store(store) {
|
let global_ty = GlobalType {
|
||||||
return Err(RuntimeError::new("cross-`Store` globals are not supported"));
|
|
||||||
}
|
|
||||||
let global = RuntimeGlobal::new(GlobalType {
|
|
||||||
mutability,
|
mutability,
|
||||||
ty: val.ty(),
|
ty: val.ty(),
|
||||||
});
|
|
||||||
unsafe {
|
|
||||||
global
|
|
||||||
.set_unchecked(val.clone())
|
|
||||||
.map_err(|e| RuntimeError::new(format!("create global for {:?}: {}", val, e)))?;
|
|
||||||
};
|
};
|
||||||
|
let descriptor = js_sys::Object::new();
|
||||||
|
let (type_str, value) = match val {
|
||||||
|
Val::I32(i) => ("i32", JsValue::from_f64(i as _)),
|
||||||
|
Val::I64(i) => ("i64", JsValue::from_f64(i as _)),
|
||||||
|
Val::F32(f) => ("f32", JsValue::from_f64(f as _)),
|
||||||
|
Val::F64(f) => ("f64", JsValue::from_f64(f)),
|
||||||
|
_ => unimplemented!("The type is not yet supported in the JS Global API"),
|
||||||
|
};
|
||||||
|
// This is the value type as string, even though is incorrectly called "value"
|
||||||
|
// in the JS API.
|
||||||
|
js_sys::Reflect::set(&descriptor, &"value".into(), &type_str.into());
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&descriptor,
|
||||||
|
&"mutable".into(),
|
||||||
|
&mutability.is_mutable().into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let js_global = JSGlobal::new(&descriptor, &value).unwrap();
|
||||||
|
let global = VMGlobal::new(js_global, global_ty);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
vm_global: VMGlobal {
|
vm_global: global,
|
||||||
from: Arc::new(global),
|
|
||||||
instance_ref: None,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +106,7 @@ impl Global {
|
|||||||
/// assert_eq!(v.ty(), &GlobalType::new(Type::I64, Mutability::Var));
|
/// assert_eq!(v.ty(), &GlobalType::new(Type::I64, Mutability::Var));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn ty(&self) -> &GlobalType {
|
pub fn ty(&self) -> &GlobalType {
|
||||||
self.vm_global.from.ty()
|
&self.vm_global.ty
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the [`Store`] where the `Global` belongs.
|
/// Returns the [`Store`] where the `Global` belongs.
|
||||||
@@ -125,7 +138,13 @@ impl Global {
|
|||||||
/// assert_eq!(g.get(), Value::I32(1));
|
/// assert_eq!(g.get(), Value::I32(1));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn get(&self) -> Val {
|
pub fn get(&self) -> Val {
|
||||||
self.vm_global.from.get(&self.store)
|
match self.vm_global.ty.ty {
|
||||||
|
ValType::I32 => Val::I32(self.vm_global.global.value().as_f64().unwrap() as _),
|
||||||
|
ValType::I64 => Val::I64(self.vm_global.global.value().as_f64().unwrap() as _),
|
||||||
|
ValType::F32 => Val::F32(self.vm_global.global.value().as_f64().unwrap() as _),
|
||||||
|
ValType::F64 => Val::F64(self.vm_global.global.value().as_f64().unwrap()),
|
||||||
|
_ => unimplemented!("The type is not yet supported in the JS Global API"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a custom value [`Val`] to the runtime Global.
|
/// Sets a custom value [`Val`] to the runtime Global.
|
||||||
@@ -170,15 +189,20 @@ impl Global {
|
|||||||
/// g.set(Value::I64(2)).unwrap();
|
/// g.set(Value::I64(2)).unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set(&self, val: Val) -> Result<(), RuntimeError> {
|
pub fn set(&self, val: Val) -> Result<(), RuntimeError> {
|
||||||
if !val.comes_from_same_store(&self.store) {
|
if self.vm_global.ty.mutability == Mutability::Const {
|
||||||
return Err(RuntimeError::new("cross-`Store` values are not supported"));
|
return Err(RuntimeError::from_str("The global is immutable"));
|
||||||
}
|
}
|
||||||
unsafe {
|
if val.ty() != self.vm_global.ty.ty {
|
||||||
self.vm_global
|
return Err(RuntimeError::from_str("The types don't match"));
|
||||||
.from
|
|
||||||
.set(val)
|
|
||||||
.map_err(|e| RuntimeError::new(format!("{}", e)))?;
|
|
||||||
}
|
}
|
||||||
|
let new_value = match val {
|
||||||
|
Val::I32(i) => JsValue::from_f64(i as _),
|
||||||
|
Val::I64(i) => JsValue::from_f64(i as _),
|
||||||
|
Val::F32(f) => JsValue::from_f64(f as _),
|
||||||
|
Val::F64(f) => JsValue::from_f64(f),
|
||||||
|
_ => unimplemented!("The type is not yet supported in the JS Global API"),
|
||||||
|
};
|
||||||
|
self.vm_global.global.set_value(&new_value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,35 +226,13 @@ impl Global {
|
|||||||
/// assert!(g.same(&g));
|
/// assert!(g.same(&g));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn same(&self, other: &Self) -> bool {
|
pub fn same(&self, other: &Self) -> bool {
|
||||||
Arc::ptr_eq(&self.vm_global.from, &other.vm_global.from)
|
self.vm_global == other.vm_global
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for Global {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
let mut vm_global = self.vm_global.clone();
|
|
||||||
vm_global.upgrade_instance_ref().unwrap();
|
|
||||||
|
|
||||||
Self {
|
|
||||||
store: self.store.clone(),
|
|
||||||
vm_global,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Global {
|
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
formatter
|
|
||||||
.debug_struct("Global")
|
|
||||||
.field("ty", &self.ty())
|
|
||||||
.field("value", &self.get())
|
|
||||||
.finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Exportable<'a> for Global {
|
impl<'a> Exportable<'a> for Global {
|
||||||
fn to_export(&self) -> Export {
|
fn to_export(&self) -> Export {
|
||||||
self.vm_global.clone().into()
|
Export::Global(self.vm_global.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
|
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
|
||||||
|
|||||||
3
lib/js-api/src/externals/memory.rs
vendored
3
lib/js-api/src/externals/memory.rs
vendored
@@ -309,8 +309,7 @@ impl Memory {
|
|||||||
|
|
||||||
impl<'a> Exportable<'a> for Memory {
|
impl<'a> Exportable<'a> for Memory {
|
||||||
fn to_export(&self) -> Export {
|
fn to_export(&self) -> Export {
|
||||||
unimplemented!();
|
Export::Memory(self.vm_memory.clone())
|
||||||
// self.vm_memory.clone().into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
|
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
|
||||||
|
|||||||
26
lib/js-api/src/externals/mod.rs
vendored
26
lib/js-api/src/externals/mod.rs
vendored
@@ -1,5 +1,5 @@
|
|||||||
pub(crate) mod function;
|
pub(crate) mod function;
|
||||||
// mod global;
|
mod global;
|
||||||
mod memory;
|
mod memory;
|
||||||
mod table;
|
mod table;
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ pub use self::function::{
|
|||||||
FromToNativeWasmType, Function, HostFunction, WasmTypeList, WithEnv, WithoutEnv,
|
FromToNativeWasmType, Function, HostFunction, WasmTypeList, WithEnv, WithoutEnv,
|
||||||
};
|
};
|
||||||
|
|
||||||
// pub use self::global::Global;
|
pub use self::global::Global;
|
||||||
pub use self::memory::Memory;
|
pub use self::memory::Memory;
|
||||||
pub use self::table::Table;
|
pub use self::table::Table;
|
||||||
|
|
||||||
@@ -25,8 +25,8 @@ use std::fmt;
|
|||||||
pub enum Extern {
|
pub enum Extern {
|
||||||
/// A external [`Function`].
|
/// A external [`Function`].
|
||||||
Function(Function),
|
Function(Function),
|
||||||
// /// A external [`Global`].
|
/// A external [`Global`].
|
||||||
// Global(Global),
|
Global(Global),
|
||||||
/// A external [`Table`].
|
/// A external [`Table`].
|
||||||
Table(Table),
|
Table(Table),
|
||||||
/// A external [`Memory`].
|
/// A external [`Memory`].
|
||||||
@@ -40,7 +40,7 @@ impl Extern {
|
|||||||
Self::Function(ft) => ExternType::Function(ft.ty().clone()),
|
Self::Function(ft) => ExternType::Function(ft.ty().clone()),
|
||||||
Self::Memory(ft) => ExternType::Memory(ft.ty()),
|
Self::Memory(ft) => ExternType::Memory(ft.ty()),
|
||||||
Self::Table(tt) => ExternType::Table(*tt.ty()),
|
Self::Table(tt) => ExternType::Table(*tt.ty()),
|
||||||
// Self::Global(gt) => ExternType::Global(*gt.ty()),
|
Self::Global(gt) => ExternType::Global(*gt.ty()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ impl Extern {
|
|||||||
match export {
|
match export {
|
||||||
Export::Function(f) => Self::Function(Function::from_vm_export(store, f)),
|
Export::Function(f) => Self::Function(Function::from_vm_export(store, f)),
|
||||||
Export::Memory(m) => Self::Memory(Memory::from_vm_export(store, m)),
|
Export::Memory(m) => Self::Memory(Memory::from_vm_export(store, m)),
|
||||||
// Export::Global(g) => Self::Global(Global::from_vm_export(store, g)),
|
Export::Global(g) => Self::Global(Global::from_vm_export(store, g)),
|
||||||
Export::Table(t) => Self::Table(Table::from_vm_export(store, t)),
|
Export::Table(t) => Self::Table(Table::from_vm_export(store, t)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,7 +59,7 @@ impl<'a> Exportable<'a> for Extern {
|
|||||||
fn to_export(&self) -> Export {
|
fn to_export(&self) -> Export {
|
||||||
match self {
|
match self {
|
||||||
Self::Function(f) => f.to_export(),
|
Self::Function(f) => f.to_export(),
|
||||||
// Self::Global(g) => g.to_export(),
|
Self::Global(g) => g.to_export(),
|
||||||
Self::Memory(m) => m.to_export(),
|
Self::Memory(m) => m.to_export(),
|
||||||
Self::Table(t) => t.to_export(),
|
Self::Table(t) => t.to_export(),
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ impl fmt::Debug for Extern {
|
|||||||
"{}",
|
"{}",
|
||||||
match self {
|
match self {
|
||||||
Self::Function(_) => "Function(...)",
|
Self::Function(_) => "Function(...)",
|
||||||
// Self::Global(_) => "Global(...)",
|
Self::Global(_) => "Global(...)",
|
||||||
Self::Memory(_) => "Memory(...)",
|
Self::Memory(_) => "Memory(...)",
|
||||||
Self::Table(_) => "Table(...)",
|
Self::Table(_) => "Table(...)",
|
||||||
}
|
}
|
||||||
@@ -94,11 +94,11 @@ impl From<Function> for Extern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl From<Global> for Extern {
|
impl From<Global> for Extern {
|
||||||
// fn from(r: Global) -> Self {
|
fn from(r: Global) -> Self {
|
||||||
// Self::Global(r)
|
Self::Global(r)
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
impl From<Memory> for Extern {
|
impl From<Memory> for Extern {
|
||||||
fn from(r: Memory) -> Self {
|
fn from(r: Memory) -> Self {
|
||||||
|
|||||||
@@ -294,6 +294,7 @@ mod module;
|
|||||||
#[cfg(feature = "wasm-types-polyfill")]
|
#[cfg(feature = "wasm-types-polyfill")]
|
||||||
mod module_info_polyfill;
|
mod module_info_polyfill;
|
||||||
mod resolver;
|
mod resolver;
|
||||||
|
mod wasm_bindgen_polyfill;
|
||||||
// mod native;
|
// mod native;
|
||||||
mod ptr;
|
mod ptr;
|
||||||
mod store;
|
mod store;
|
||||||
@@ -309,9 +310,7 @@ pub use crate::cell::WasmCell;
|
|||||||
pub use crate::env::{HostEnvInitError, LazyInit, WasmerEnv};
|
pub use crate::env::{HostEnvInitError, LazyInit, WasmerEnv};
|
||||||
pub use crate::exports::{ExportError, Exportable, Exports, ExportsIterator};
|
pub use crate::exports::{ExportError, Exportable, Exports, ExportsIterator};
|
||||||
pub use crate::externals::{
|
pub use crate::externals::{
|
||||||
Extern, FromToNativeWasmType, Function, HostFunction, Memory, Table,
|
Extern, FromToNativeWasmType, Function, Global, HostFunction, Memory, Table, WasmTypeList,
|
||||||
/* Global, */
|
|
||||||
WasmTypeList,
|
|
||||||
};
|
};
|
||||||
pub use crate::import_object::{ImportObject, ImportObjectIterator, LikeNamespace};
|
pub use crate::import_object::{ImportObject, ImportObjectIterator, LikeNamespace};
|
||||||
pub use crate::instance::{Instance, InstantiationError};
|
pub use crate::instance::{Instance, InstantiationError};
|
||||||
|
|||||||
32
lib/js-api/src/wasm_bindgen_polyfill.rs
Normal file
32
lib/js-api/src/wasm_bindgen_polyfill.rs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
use js_sys::Object;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
use wasm_bindgen::JsCast;
|
||||||
|
|
||||||
|
// WebAssembly.Global
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
/// The `WebAssembly.Global()` constructor creates a new `Global` object
|
||||||
|
/// of the given type and value.
|
||||||
|
///
|
||||||
|
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global)
|
||||||
|
#[wasm_bindgen(js_namespace = WebAssembly, extends = Object, typescript_type = "WebAssembly.Global")]
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub type Global;
|
||||||
|
|
||||||
|
/// The `WebAssembly.Global()` constructor creates a new `Global` object
|
||||||
|
/// of the given type and value.
|
||||||
|
///
|
||||||
|
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global)
|
||||||
|
#[wasm_bindgen(constructor, js_namespace = WebAssembly, catch)]
|
||||||
|
pub fn new(global_descriptor: &Object, value: &JsValue) -> Result<Global, JsValue>;
|
||||||
|
|
||||||
|
/// The value prototype property of the `WebAssembly.Global` object
|
||||||
|
/// returns the value of the global.
|
||||||
|
///
|
||||||
|
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global)
|
||||||
|
#[wasm_bindgen(method, getter, structural, js_namespace = WebAssembly)]
|
||||||
|
pub fn value(this: &Global) -> JsValue;
|
||||||
|
|
||||||
|
#[wasm_bindgen(method, setter = value, structural, js_namespace = WebAssembly)]
|
||||||
|
pub fn set_value(this: &Global, value: &JsValue);
|
||||||
|
}
|
||||||
@@ -2,62 +2,56 @@ use wasm_bindgen_test::*;
|
|||||||
// use anyhow::Result;
|
// use anyhow::Result;
|
||||||
use wasmer_js::*;
|
use wasmer_js::*;
|
||||||
|
|
||||||
// #[test]
|
#[wasm_bindgen_test]
|
||||||
// fn global_new() -> Result<()> {
|
fn global_new() {
|
||||||
// let store = Store::default();
|
let store = Store::default();
|
||||||
// let global = Global::new(&store, Value::I32(10));
|
let global = Global::new(&store, Value::I32(10));
|
||||||
// assert_eq!(
|
assert_eq!(
|
||||||
// *global.ty(),
|
*global.ty(),
|
||||||
// GlobalType {
|
GlobalType {
|
||||||
// ty: Type::I32,
|
ty: Type::I32,
|
||||||
// mutability: Mutability::Const
|
mutability: Mutability::Const
|
||||||
// }
|
}
|
||||||
// );
|
);
|
||||||
|
|
||||||
// let global_mut = Global::new_mut(&store, Value::I32(10));
|
let global_mut = Global::new_mut(&store, Value::I32(10));
|
||||||
// assert_eq!(
|
assert_eq!(
|
||||||
// *global_mut.ty(),
|
*global_mut.ty(),
|
||||||
// GlobalType {
|
GlobalType {
|
||||||
// ty: Type::I32,
|
ty: Type::I32,
|
||||||
// mutability: Mutability::Var
|
mutability: Mutability::Var
|
||||||
// }
|
}
|
||||||
// );
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Ok(())
|
#[wasm_bindgen_test]
|
||||||
// }
|
fn global_get() {
|
||||||
|
let store = Store::default();
|
||||||
|
let global_i32 = Global::new(&store, Value::I32(10));
|
||||||
|
assert_eq!(global_i32.get(), Value::I32(10));
|
||||||
|
// let global_i64 = Global::new(&store, Value::I64(20));
|
||||||
|
// assert_eq!(global_i64.get(), Value::I64(20));
|
||||||
|
let global_f32 = Global::new(&store, Value::F32(10.0));
|
||||||
|
assert_eq!(global_f32.get(), Value::F32(10.0));
|
||||||
|
// let global_f64 = Global::new(&store, Value::F64(20.0));
|
||||||
|
// assert_eq!(global_f64.get(), Value::F64(20.0));
|
||||||
|
}
|
||||||
|
|
||||||
// #[test]
|
#[wasm_bindgen_test]
|
||||||
// fn global_get() -> Result<()> {
|
fn global_set() {
|
||||||
// let store = Store::default();
|
let store = Store::default();
|
||||||
// let global_i32 = Global::new(&store, Value::I32(10));
|
let global_i32 = Global::new(&store, Value::I32(10));
|
||||||
// assert_eq!(global_i32.get(), Value::I32(10));
|
// Set on a constant should error
|
||||||
// let global_i64 = Global::new(&store, Value::I64(20));
|
assert!(global_i32.set(Value::I32(20)).is_err());
|
||||||
// assert_eq!(global_i64.get(), Value::I64(20));
|
|
||||||
// let global_f32 = Global::new(&store, Value::F32(10.0));
|
|
||||||
// assert_eq!(global_f32.get(), Value::F32(10.0));
|
|
||||||
// let global_f64 = Global::new(&store, Value::F64(20.0));
|
|
||||||
// assert_eq!(global_f64.get(), Value::F64(20.0));
|
|
||||||
|
|
||||||
// Ok(())
|
let global_i32_mut = Global::new_mut(&store, Value::I32(10));
|
||||||
// }
|
// Set on different type should error
|
||||||
|
assert!(global_i32_mut.set(Value::I64(20)).is_err());
|
||||||
|
|
||||||
// #[test]
|
// Set on same type should succeed
|
||||||
// fn global_set() -> Result<()> {
|
global_i32_mut.set(Value::I32(20)).unwrap();
|
||||||
// let store = Store::default();
|
assert_eq!(global_i32_mut.get(), Value::I32(20));
|
||||||
// let global_i32 = Global::new(&store, Value::I32(10));
|
}
|
||||||
// // Set on a constant should error
|
|
||||||
// assert!(global_i32.set(Value::I32(20)).is_err());
|
|
||||||
|
|
||||||
// let global_i32_mut = Global::new_mut(&store, Value::I32(10));
|
|
||||||
// // Set on different type should error
|
|
||||||
// assert!(global_i32_mut.set(Value::I64(20)).is_err());
|
|
||||||
|
|
||||||
// // Set on same type should succeed
|
|
||||||
// global_i32_mut.set(Value::I32(20))?;
|
|
||||||
// assert_eq!(global_i32_mut.get(), Value::I32(20));
|
|
||||||
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn table_new() {
|
fn table_new() {
|
||||||
|
|||||||
@@ -290,3 +290,57 @@ fn test_imported_function_native_with_wasmer_env() {
|
|||||||
let expected = vec![Val::I32(36)].into_boxed_slice();
|
let expected = vec![Val::I32(36)].into_boxed_slice();
|
||||||
assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected));
|
assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn test_imported_exported_global() {
|
||||||
|
let store = Store::default();
|
||||||
|
let mut module = Module::new(
|
||||||
|
&store,
|
||||||
|
br#"
|
||||||
|
(module
|
||||||
|
(global $mut_i32_import (import "" "global") (mut i32))
|
||||||
|
(func (export "getGlobal") (result i32) (global.get $mut_i32_import))
|
||||||
|
(func (export "incGlobal") (global.set $mut_i32_import (
|
||||||
|
i32.add (i32.const 1) (global.get $mut_i32_import)
|
||||||
|
)))
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
module.set_type_hints(ModuleTypeHints {
|
||||||
|
imports: vec![ExternType::Global(GlobalType::new(
|
||||||
|
ValType::I32,
|
||||||
|
Mutability::Var,
|
||||||
|
))],
|
||||||
|
exports: vec![
|
||||||
|
ExternType::Function(FunctionType::new(vec![], vec![Type::I32])),
|
||||||
|
ExternType::Function(FunctionType::new(vec![], vec![])),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
let mut global = Global::new_mut(&store, Value::I32(0));
|
||||||
|
let import_object = imports! {
|
||||||
|
"" => {
|
||||||
|
"global" => global.clone()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let instance = Instance::new(&module, &import_object).unwrap();
|
||||||
|
|
||||||
|
let get_global = instance.exports.get_function("getGlobal").unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
get_global.call(&[]),
|
||||||
|
Ok(vec![Val::I32(0)].into_boxed_slice())
|
||||||
|
);
|
||||||
|
|
||||||
|
global.set(Value::I32(42));
|
||||||
|
assert_eq!(
|
||||||
|
get_global.call(&[]),
|
||||||
|
Ok(vec![Val::I32(42)].into_boxed_slice())
|
||||||
|
);
|
||||||
|
|
||||||
|
let inc_global = instance.exports.get_function("incGlobal").unwrap();
|
||||||
|
inc_global.call(&[]);
|
||||||
|
assert_eq!(
|
||||||
|
get_global.call(&[]),
|
||||||
|
Ok(vec![Val::I32(43)].into_boxed_slice())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user