wasmtime 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Cargo.lock +941 -627
- data/Cargo.toml +2 -14
- data/LICENSE +23 -21
- data/README.md +47 -118
- data/ext/Cargo.toml +17 -0
- data/ext/extconf.rb +6 -0
- data/ext/src/helpers/mod.rs +3 -0
- data/ext/src/helpers/wrapped_struct.rs +84 -0
- data/ext/src/lib.rs +9 -0
- data/ext/src/ruby_api/config.rs +68 -0
- data/ext/src/ruby_api/convert.rs +92 -0
- data/ext/src/ruby_api/engine.rs +66 -0
- data/ext/src/ruby_api/errors.rs +56 -0
- data/ext/src/ruby_api/externals.rs +113 -0
- data/ext/src/ruby_api/func.rs +388 -0
- data/ext/src/ruby_api/func_type.rs +139 -0
- data/ext/src/ruby_api/instance.rs +174 -0
- data/ext/src/ruby_api/linker.rs +296 -0
- data/ext/src/ruby_api/macros.rs +12 -0
- data/ext/src/ruby_api/memory.rs +142 -0
- data/ext/src/ruby_api/memory_type.rs +56 -0
- data/ext/src/ruby_api/mod.rs +48 -0
- data/ext/src/ruby_api/module.rs +107 -0
- data/ext/src/ruby_api/params.rs +42 -0
- data/ext/src/ruby_api/static_id.rs +57 -0
- data/ext/src/ruby_api/store.rs +182 -0
- data/ext/src/ruby_api/trap.rs +135 -0
- data/lib/wasmtime/version.rb +1 -1
- data/lib/wasmtime.rb +29 -4
- metadata +54 -30
- data/.cargo/config +0 -4
- data/CHANGELOG.md +0 -27
- data/ext/wasmtime/Makefile +0 -5
- data/ext/wasmtime/Rakefile +0 -3
- data/ext/wasmtime/extconf.rb +0 -5
- data/lib/tasks/compile.rake +0 -27
- data/lib/wasmtime/refinements.rb +0 -20
- data/lib/wasmtime/require.rb +0 -72
- data/src/export.rs +0 -19
- data/src/func.rs +0 -175
- data/src/instance.rs +0 -93
- data/src/lib.rs +0 -22
- data/src/memory.rs +0 -48
- data/src/ruby_type.rs +0 -32
- data/src/vm.rs +0 -6
@@ -0,0 +1,139 @@
|
|
1
|
+
use super::root;
|
2
|
+
use crate::{define_rb_intern, err};
|
3
|
+
use magnus::{function, method, Error, Module as _, Object, RArray, Symbol, Value};
|
4
|
+
use wasmtime::{FuncType as FuncTypeImpl, ValType};
|
5
|
+
|
6
|
+
define_rb_intern!(
|
7
|
+
I32 => "i32",
|
8
|
+
I64 => "i64",
|
9
|
+
F32 => "f32",
|
10
|
+
F64 => "f64",
|
11
|
+
V128 => "v128",
|
12
|
+
FUNCREF => "funcref",
|
13
|
+
EXTERNREF => "externref",
|
14
|
+
);
|
15
|
+
|
16
|
+
/// @yard
|
17
|
+
/// Represents a Func's signature.
|
18
|
+
/// @see https://docs.rs/wasmtime/latest/wasmtime/struct.FuncType.html Wasmtime's Rust doc
|
19
|
+
#[derive(Clone, Debug)]
|
20
|
+
#[magnus::wrap(class = "Wasmtime::FuncType")]
|
21
|
+
pub struct FuncType {
|
22
|
+
inner: FuncTypeImpl,
|
23
|
+
}
|
24
|
+
|
25
|
+
impl FuncType {
|
26
|
+
pub fn get(&self) -> &FuncTypeImpl {
|
27
|
+
&self.inner
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
impl FuncType {
|
32
|
+
/// @yard
|
33
|
+
/// A descriptor for a function in a WebAssembly module.
|
34
|
+
/// WebAssembly functions can have 0 or more parameters and results. Each param
|
35
|
+
/// must be a valid WebAssembly type represented as a symbol. The valid symbols are:
|
36
|
+
/// +:i32+, +:i64+, +:f32+, +:f64+, +:v128+, +:funcref+, +:externref+.
|
37
|
+
///
|
38
|
+
/// @def new(params, results)
|
39
|
+
/// @param params [Array<Symbol>] The function's parameter types.
|
40
|
+
/// @param results [Array<Symbol>] The function's result types.
|
41
|
+
/// @return [FuncType]
|
42
|
+
///
|
43
|
+
/// @example +FuncType+ that takes 2 +i32+s and returns 1 +i32+:
|
44
|
+
/// FuncType.new([:i32, :i32], [:i32])
|
45
|
+
pub fn new(params: RArray, results: RArray) -> Result<Self, Error> {
|
46
|
+
let inner = FuncTypeImpl::new(params.to_val_type_vec()?, results.to_val_type_vec()?);
|
47
|
+
Ok(Self { inner })
|
48
|
+
}
|
49
|
+
|
50
|
+
/// @yard
|
51
|
+
/// @return [Array<Symbol>] The function's parameter types.
|
52
|
+
pub fn params(&self) -> Vec<Symbol> {
|
53
|
+
self.get().params().map(ToSym::to_sym).collect()
|
54
|
+
}
|
55
|
+
|
56
|
+
/// @yard
|
57
|
+
/// @return [Array<Symbol>] The function's result types.
|
58
|
+
pub fn results(&self) -> Vec<Symbol> {
|
59
|
+
self.get().results().map(ToSym::to_sym).collect()
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
trait ToValType {
|
64
|
+
fn to_val_type(&self) -> Result<ValType, Error>;
|
65
|
+
}
|
66
|
+
|
67
|
+
impl ToValType for Value {
|
68
|
+
fn to_val_type(&self) -> Result<ValType, Error> {
|
69
|
+
if let Ok(symbol) = self.try_convert::<Symbol>() {
|
70
|
+
if let Ok(true) = symbol.equal(Symbol::from(*I32)) {
|
71
|
+
return Ok(ValType::I32);
|
72
|
+
}
|
73
|
+
if let Ok(true) = symbol.equal(Symbol::from(*I64)) {
|
74
|
+
return Ok(ValType::I64);
|
75
|
+
}
|
76
|
+
if let Ok(true) = symbol.equal(Symbol::from(*F32)) {
|
77
|
+
return Ok(ValType::F32);
|
78
|
+
}
|
79
|
+
if let Ok(true) = symbol.equal(Symbol::from(*F64)) {
|
80
|
+
return Ok(ValType::F64);
|
81
|
+
}
|
82
|
+
if let Ok(true) = symbol.equal(Symbol::from(*V128)) {
|
83
|
+
return Ok(ValType::V128);
|
84
|
+
}
|
85
|
+
if let Ok(true) = symbol.equal(Symbol::from(*FUNCREF)) {
|
86
|
+
return Ok(ValType::FuncRef);
|
87
|
+
}
|
88
|
+
if let Ok(true) = symbol.equal(Symbol::from(*EXTERNREF)) {
|
89
|
+
return Ok(ValType::ExternRef);
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
err!(
|
94
|
+
"invalid Webassembly type, expected one of [:i32, :i64, :f32, :f64, :v128, :funcref, :externref], got {:}",
|
95
|
+
self.inspect()
|
96
|
+
)
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
trait ToValTypeVec {
|
101
|
+
fn to_val_type_vec(&self) -> Result<Vec<ValType>, Error>;
|
102
|
+
}
|
103
|
+
|
104
|
+
impl ToValTypeVec for RArray {
|
105
|
+
fn to_val_type_vec(&self) -> Result<Vec<ValType>, Error> {
|
106
|
+
unsafe { self.as_slice() }
|
107
|
+
.iter()
|
108
|
+
.map(ToValType::to_val_type)
|
109
|
+
.collect::<Result<Vec<ValType>, Error>>()
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
trait ToSym {
|
114
|
+
fn to_sym(self) -> Symbol;
|
115
|
+
}
|
116
|
+
|
117
|
+
impl ToSym for ValType {
|
118
|
+
fn to_sym(self) -> Symbol {
|
119
|
+
match self {
|
120
|
+
ValType::I32 => Symbol::from(*I32),
|
121
|
+
ValType::I64 => Symbol::from(*I64),
|
122
|
+
ValType::F32 => Symbol::from(*F32),
|
123
|
+
ValType::F64 => Symbol::from(*F64),
|
124
|
+
ValType::V128 => Symbol::from(*V128),
|
125
|
+
ValType::FuncRef => Symbol::from(*FUNCREF),
|
126
|
+
ValType::ExternRef => Symbol::from(*EXTERNREF),
|
127
|
+
}
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
pub fn init() -> Result<(), Error> {
|
132
|
+
let class = root().define_class("FuncType", Default::default())?;
|
133
|
+
|
134
|
+
class.define_singleton_method("new", function!(FuncType::new, 2))?;
|
135
|
+
class.define_method("params", method!(FuncType::params, 0))?;
|
136
|
+
class.define_method("results", method!(FuncType::results, 0))?;
|
137
|
+
|
138
|
+
Ok(())
|
139
|
+
}
|
@@ -0,0 +1,174 @@
|
|
1
|
+
use super::{
|
2
|
+
convert::{ToExtern, WrapWasmtimeType},
|
3
|
+
func::Func,
|
4
|
+
module::Module,
|
5
|
+
root,
|
6
|
+
store::{Store, StoreContextValue, StoreData},
|
7
|
+
};
|
8
|
+
use crate::{err, helpers::WrappedStruct};
|
9
|
+
use magnus::{
|
10
|
+
function, method, scan_args, DataTypeFunctions, Error, Module as _, Object, RArray, RHash,
|
11
|
+
RString, TypedData, Value,
|
12
|
+
};
|
13
|
+
use wasmtime::{Extern, Instance as InstanceImpl, StoreContextMut};
|
14
|
+
|
15
|
+
/// @yard
|
16
|
+
/// Represents a WebAssembly instance.
|
17
|
+
/// @see https://docs.rs/wasmtime/latest/wasmtime/struct.Instance.html Wasmtime's Rust doc
|
18
|
+
#[derive(Clone, Debug, TypedData)]
|
19
|
+
#[magnus(class = "Wasmtime::Instance", mark, free_immediatly)]
|
20
|
+
pub struct Instance {
|
21
|
+
inner: InstanceImpl,
|
22
|
+
store: WrappedStruct<Store>,
|
23
|
+
}
|
24
|
+
|
25
|
+
unsafe impl Send for Instance {}
|
26
|
+
|
27
|
+
impl DataTypeFunctions for Instance {
|
28
|
+
fn mark(&self) {
|
29
|
+
self.store.mark()
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
impl Instance {
|
34
|
+
/// @yard
|
35
|
+
/// @def new(store, mod, imports = [])
|
36
|
+
/// @param store [Store] The store to instantiate the module in.
|
37
|
+
/// @param mod [Module] The module to instantiate.
|
38
|
+
/// @param imports [Array<Func, Memory>]
|
39
|
+
/// The module's import, in orders that that they show up in the module.
|
40
|
+
/// @return [Instance]
|
41
|
+
pub fn new(args: &[Value]) -> Result<Self, Error> {
|
42
|
+
let args =
|
43
|
+
scan_args::scan_args::<(Value, &Module), (Option<Value>,), (), (), (), ()>(args)?;
|
44
|
+
let (s, module) = args.required;
|
45
|
+
let wrapped_store: WrappedStruct<Store> = s.try_convert()?;
|
46
|
+
let store = wrapped_store.get()?;
|
47
|
+
let context = store.context_mut();
|
48
|
+
let imports = args
|
49
|
+
.optional
|
50
|
+
.0
|
51
|
+
.and_then(|v| if v.is_nil() { None } else { Some(v) });
|
52
|
+
|
53
|
+
let imports: Vec<Extern> = match imports {
|
54
|
+
Some(arr) => {
|
55
|
+
let arr: RArray = arr.try_convert()?;
|
56
|
+
let mut imports = Vec::with_capacity(arr.len());
|
57
|
+
for import in arr.each() {
|
58
|
+
let import = import?;
|
59
|
+
store.retain(import);
|
60
|
+
imports.push(import.to_extern()?);
|
61
|
+
}
|
62
|
+
imports
|
63
|
+
}
|
64
|
+
None => vec![],
|
65
|
+
};
|
66
|
+
|
67
|
+
let module = module.get();
|
68
|
+
let inner = InstanceImpl::new(context, module, &imports)
|
69
|
+
.map_err(|e| StoreContextValue::from(wrapped_store).handle_wasm_error(e))?;
|
70
|
+
|
71
|
+
Ok(Self {
|
72
|
+
inner,
|
73
|
+
store: wrapped_store,
|
74
|
+
})
|
75
|
+
}
|
76
|
+
|
77
|
+
pub fn get(&self) -> InstanceImpl {
|
78
|
+
self.inner
|
79
|
+
}
|
80
|
+
|
81
|
+
pub fn from_inner(store: WrappedStruct<Store>, inner: InstanceImpl) -> Self {
|
82
|
+
Self { inner, store }
|
83
|
+
}
|
84
|
+
|
85
|
+
/// @yard
|
86
|
+
/// Returns a +Hash+ of exports where keys are export names as +String+s
|
87
|
+
/// and values are {Extern}s.
|
88
|
+
///
|
89
|
+
/// @def exports
|
90
|
+
/// @return [Hash{String => Extern}]
|
91
|
+
pub fn exports(&self) -> Result<RHash, Error> {
|
92
|
+
let store = self.store.get()?;
|
93
|
+
let mut ctx = store.context_mut();
|
94
|
+
let hash = RHash::new();
|
95
|
+
|
96
|
+
for export in self.inner.exports(&mut ctx) {
|
97
|
+
let export_name: RString = export.name().into();
|
98
|
+
let wrapped_store = self.store;
|
99
|
+
let wrapped_export = export
|
100
|
+
.into_extern()
|
101
|
+
.wrap_wasmtime_type(wrapped_store.into())?;
|
102
|
+
hash.aset(export_name, wrapped_export)?;
|
103
|
+
}
|
104
|
+
|
105
|
+
Ok(hash)
|
106
|
+
}
|
107
|
+
|
108
|
+
/// @yard
|
109
|
+
/// Get an export by name.
|
110
|
+
///
|
111
|
+
/// @def export(name)
|
112
|
+
/// @param name [String]
|
113
|
+
/// @return [Extern, nil] The export if it exists, nil otherwise.
|
114
|
+
pub fn export(&self, str: RString) -> Result<Option<super::externals::Extern>, Error> {
|
115
|
+
let store = self.store.get()?;
|
116
|
+
let export = self
|
117
|
+
.inner
|
118
|
+
.get_export(store.context_mut(), unsafe { str.as_str()? });
|
119
|
+
match export {
|
120
|
+
Some(export) => export.wrap_wasmtime_type(self.store.into()).map(Some),
|
121
|
+
None => Ok(None),
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
/// @yard
|
126
|
+
/// Retrieves a Wasm function from the instance and calls it.
|
127
|
+
/// Essentially a shortcut for +instance.export(name).call(...)+.
|
128
|
+
///
|
129
|
+
/// @def invoke(name, *args)
|
130
|
+
/// @param name [String] The name of function to run.
|
131
|
+
/// @param (see Func#call)
|
132
|
+
/// @return (see Func#call)
|
133
|
+
/// @see Func#call
|
134
|
+
pub fn invoke(&self, args: &[Value]) -> Result<Value, Error> {
|
135
|
+
let name: RString = args
|
136
|
+
.get(0)
|
137
|
+
.ok_or_else(|| {
|
138
|
+
Error::new(
|
139
|
+
magnus::exception::type_error(),
|
140
|
+
"wrong number of arguments (given 0, expected 1+)",
|
141
|
+
)
|
142
|
+
})?
|
143
|
+
.try_convert()?;
|
144
|
+
|
145
|
+
let store: &Store = self.store.try_convert()?;
|
146
|
+
let func = self.get_func(store.context_mut(), unsafe { name.as_str()? })?;
|
147
|
+
Func::invoke(&self.store.into(), &func, &args[1..]).map_err(|e| e.into())
|
148
|
+
}
|
149
|
+
|
150
|
+
fn get_func(
|
151
|
+
&self,
|
152
|
+
context: StoreContextMut<'_, StoreData>,
|
153
|
+
name: &str,
|
154
|
+
) -> Result<wasmtime::Func, Error> {
|
155
|
+
let instance = self.inner;
|
156
|
+
|
157
|
+
if let Some(func) = instance.get_func(context, name) {
|
158
|
+
Ok(func)
|
159
|
+
} else {
|
160
|
+
err!("function \"{}\" not found", name)
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
pub fn init() -> Result<(), Error> {
|
166
|
+
let class = root().define_class("Instance", Default::default())?;
|
167
|
+
|
168
|
+
class.define_singleton_method("new", function!(Instance::new, -1))?;
|
169
|
+
class.define_method("invoke", method!(Instance::invoke, -1))?;
|
170
|
+
class.define_method("exports", method!(Instance::exports, 0))?;
|
171
|
+
class.define_method("export", method!(Instance::export, 1))?;
|
172
|
+
|
173
|
+
Ok(())
|
174
|
+
}
|
@@ -0,0 +1,296 @@
|
|
1
|
+
use super::{
|
2
|
+
convert::WrapWasmtimeType,
|
3
|
+
engine::Engine,
|
4
|
+
externals::Extern,
|
5
|
+
func::{self, Func},
|
6
|
+
func_type::FuncType,
|
7
|
+
instance::Instance,
|
8
|
+
module::Module,
|
9
|
+
root,
|
10
|
+
store::{Store, StoreContextValue, StoreData},
|
11
|
+
};
|
12
|
+
use crate::{error, helpers::WrappedStruct, ruby_api::convert::ToExtern};
|
13
|
+
use magnus::{
|
14
|
+
block::Proc, function, gc, method, scan_args::scan_args, DataTypeFunctions, Error, Module as _,
|
15
|
+
Object, RHash, RString, TypedData, Value,
|
16
|
+
};
|
17
|
+
use std::cell::RefCell;
|
18
|
+
use wasmtime::Linker as LinkerImpl;
|
19
|
+
|
20
|
+
/// @yard
|
21
|
+
/// @see https://docs.rs/wasmtime/latest/wasmtime/struct.Linker.html Wasmtime's Rust doc
|
22
|
+
#[derive(TypedData)]
|
23
|
+
#[magnus(class = "Wasmtime::Linker", size, mark, free_immediatly)]
|
24
|
+
pub struct Linker {
|
25
|
+
inner: RefCell<LinkerImpl<StoreData>>,
|
26
|
+
refs: RefCell<Vec<Value>>,
|
27
|
+
}
|
28
|
+
|
29
|
+
unsafe impl Send for Linker {}
|
30
|
+
|
31
|
+
impl DataTypeFunctions for Linker {
|
32
|
+
fn mark(&self) {
|
33
|
+
self.refs.borrow().iter().for_each(gc::mark);
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
impl Linker {
|
38
|
+
/// @yard
|
39
|
+
/// @def new(engine)
|
40
|
+
/// @param engine [Engine]
|
41
|
+
/// @return [Linker]
|
42
|
+
pub fn new(engine: &Engine) -> Result<Self, Error> {
|
43
|
+
Ok(Self {
|
44
|
+
inner: RefCell::new(LinkerImpl::new(engine.get())),
|
45
|
+
refs: Default::default(),
|
46
|
+
})
|
47
|
+
}
|
48
|
+
|
49
|
+
/// @yard
|
50
|
+
/// Allow shadowing.
|
51
|
+
/// @def allow_shadowing=(val)
|
52
|
+
/// @param val [Boolean]
|
53
|
+
pub fn set_allow_shadowing(&self, val: bool) {
|
54
|
+
self.inner.borrow_mut().allow_shadowing(val);
|
55
|
+
}
|
56
|
+
|
57
|
+
/// @yard
|
58
|
+
/// Allow unknown exports.
|
59
|
+
/// @def allow_unknown_exports=(val)
|
60
|
+
/// @param val [Boolean]
|
61
|
+
pub fn set_allow_unknown_exports(&self, val: bool) {
|
62
|
+
self.inner.borrow_mut().allow_unknown_exports(val);
|
63
|
+
}
|
64
|
+
|
65
|
+
/// @yard
|
66
|
+
/// Define unknown (unresolved) imports as functions which trap.
|
67
|
+
/// @def define_unknown_imports_as_traps(mod)
|
68
|
+
/// @param mod [Module]
|
69
|
+
/// @return [void]
|
70
|
+
pub fn define_unknown_imports_as_traps(&self, module: &Module) -> Result<(), Error> {
|
71
|
+
self.inner
|
72
|
+
.borrow_mut()
|
73
|
+
.define_unknown_imports_as_traps(module.get())
|
74
|
+
.map_err(|e| error!("{}", e))
|
75
|
+
}
|
76
|
+
|
77
|
+
/// @yard
|
78
|
+
/// Define an item in this linker.
|
79
|
+
/// @def define(mod, name, item)
|
80
|
+
/// @param mod [String] Module name
|
81
|
+
/// @param name [String] Import name
|
82
|
+
/// @param item [Func, Memory] The item to define.
|
83
|
+
/// @return [void]
|
84
|
+
pub fn define(&self, module: RString, name: RString, item: Value) -> Result<(), Error> {
|
85
|
+
let item = item.to_extern()?;
|
86
|
+
|
87
|
+
self.inner
|
88
|
+
.borrow_mut()
|
89
|
+
.define(unsafe { module.as_str()? }, unsafe { name.as_str()? }, item)
|
90
|
+
.map(|_| ())
|
91
|
+
.map_err(|e| error!("{}", e))
|
92
|
+
}
|
93
|
+
|
94
|
+
/// @yard
|
95
|
+
/// Define a function in this linker.
|
96
|
+
///
|
97
|
+
/// @def func_new(mod, name, type, &block)
|
98
|
+
///
|
99
|
+
/// @param mod [String] Module name
|
100
|
+
/// @param name [String] Import name
|
101
|
+
/// @param type [FuncType]
|
102
|
+
/// @param block [Block] See {Func.new} for block argument details.
|
103
|
+
/// @return [void]
|
104
|
+
/// @see Func.new
|
105
|
+
pub fn func_new(&self, args: &[Value]) -> Result<(), Error> {
|
106
|
+
let args = scan_args::<(RString, RString, &FuncType), (), (), (), RHash, Proc>(args)?;
|
107
|
+
let (module, name, ty) = args.required;
|
108
|
+
let callable = args.block;
|
109
|
+
let func_closure = func::make_func_closure(ty.get(), callable);
|
110
|
+
|
111
|
+
self.refs.borrow_mut().push(callable.into());
|
112
|
+
|
113
|
+
self.inner
|
114
|
+
.borrow_mut()
|
115
|
+
.func_new(
|
116
|
+
unsafe { module.as_str() }?,
|
117
|
+
unsafe { name.as_str() }?,
|
118
|
+
ty.get().clone(),
|
119
|
+
func_closure,
|
120
|
+
)
|
121
|
+
.map_err(|e| error!("{}", e))
|
122
|
+
.map(|_| ())
|
123
|
+
}
|
124
|
+
|
125
|
+
/// @yard
|
126
|
+
/// Looks up a previously defined item in this linker.
|
127
|
+
///
|
128
|
+
/// @def get(store, mod, name)
|
129
|
+
/// @param store [Store]
|
130
|
+
/// @param mod [String] Module name
|
131
|
+
/// @param name [String] Import name
|
132
|
+
/// @return [Extern, nil] The item if it exists, nil otherwise.
|
133
|
+
pub fn get(
|
134
|
+
&self,
|
135
|
+
s: WrappedStruct<Store>,
|
136
|
+
module: RString,
|
137
|
+
name: RString,
|
138
|
+
) -> Result<Option<Extern>, Error> {
|
139
|
+
let store: &Store = s.try_convert()?;
|
140
|
+
let ext =
|
141
|
+
self.inner
|
142
|
+
.borrow()
|
143
|
+
.get(store.context_mut(), unsafe { module.as_str() }?, unsafe {
|
144
|
+
name.as_str()?
|
145
|
+
});
|
146
|
+
|
147
|
+
match ext {
|
148
|
+
None => Ok(None),
|
149
|
+
Some(ext) => ext.wrap_wasmtime_type(s.into()).map(Some),
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
/// @yard
|
154
|
+
/// Defines an entire {Instance} in this linker.
|
155
|
+
///
|
156
|
+
/// @def instance(store, mod, instance)
|
157
|
+
/// @param store [Store]
|
158
|
+
/// @param mod [String] Module name
|
159
|
+
/// @param instance [Instance]
|
160
|
+
/// @return [void]
|
161
|
+
pub fn instance(
|
162
|
+
&self,
|
163
|
+
store: &Store,
|
164
|
+
module: RString,
|
165
|
+
instance: &Instance,
|
166
|
+
) -> Result<(), Error> {
|
167
|
+
self.inner
|
168
|
+
.borrow_mut()
|
169
|
+
.instance(
|
170
|
+
store.context_mut(),
|
171
|
+
unsafe { module.as_str() }?,
|
172
|
+
instance.get(),
|
173
|
+
)
|
174
|
+
.map_err(|e| error!("{}", e))
|
175
|
+
.map(|_| ())
|
176
|
+
}
|
177
|
+
|
178
|
+
/// @yard
|
179
|
+
/// Defines automatic instantiation of a {Module} in this linker.
|
180
|
+
///
|
181
|
+
/// @def module(store, name, mod)
|
182
|
+
/// @param store [Store]
|
183
|
+
/// @param name [String] Module name
|
184
|
+
/// @param mod [Module]
|
185
|
+
/// @return [void]
|
186
|
+
pub fn module(&self, store: &Store, name: RString, module: &Module) -> Result<(), Error> {
|
187
|
+
self.inner
|
188
|
+
.borrow_mut()
|
189
|
+
.module(store.context_mut(), unsafe { name.as_str()? }, module.get())
|
190
|
+
.map(|_| ())
|
191
|
+
.map_err(|e| error!("{}", e))
|
192
|
+
}
|
193
|
+
|
194
|
+
/// @yard
|
195
|
+
/// Aliases one item’s name as another.
|
196
|
+
///
|
197
|
+
/// @def alias(mod, name, as_mod, as_name)
|
198
|
+
/// @param mod [String] The source module name.
|
199
|
+
/// @param name [String] The source item name.
|
200
|
+
/// @param as_mod [String] The destination module name.
|
201
|
+
/// @param as_name [String] The destination item name.
|
202
|
+
/// @return [void]
|
203
|
+
pub fn alias(
|
204
|
+
&self,
|
205
|
+
module: RString,
|
206
|
+
name: RString,
|
207
|
+
as_module: RString,
|
208
|
+
as_name: RString,
|
209
|
+
) -> Result<(), Error> {
|
210
|
+
self.inner
|
211
|
+
.borrow_mut()
|
212
|
+
.alias(
|
213
|
+
unsafe { module.as_str() }?,
|
214
|
+
unsafe { name.as_str() }?,
|
215
|
+
unsafe { as_module.as_str() }?,
|
216
|
+
unsafe { as_name.as_str() }?,
|
217
|
+
)
|
218
|
+
.map_err(|e| error!("{}", e))
|
219
|
+
.map(|_| ())
|
220
|
+
}
|
221
|
+
|
222
|
+
/// @yard
|
223
|
+
/// Aliases one module’s name as another.
|
224
|
+
///
|
225
|
+
/// @def alias(mod, as_mod)
|
226
|
+
/// @param mod [String] Source module name
|
227
|
+
/// @param as_mod [String] Destination module name
|
228
|
+
/// @return [void]
|
229
|
+
pub fn alias_module(&self, module: RString, as_module: RString) -> Result<(), Error> {
|
230
|
+
self.inner
|
231
|
+
.borrow_mut()
|
232
|
+
.alias_module(unsafe { module.as_str() }?, unsafe { as_module.as_str() }?)
|
233
|
+
.map_err(|e| error!("{}", e))
|
234
|
+
.map(|_| ())
|
235
|
+
}
|
236
|
+
|
237
|
+
/// @yard
|
238
|
+
/// Instantiates a {Module} in a {Store} using the defined imports in the linker.
|
239
|
+
/// @def instantiate(store, mod)
|
240
|
+
/// @param store [Store]
|
241
|
+
/// @param mod [Module]
|
242
|
+
/// @return [Instance]
|
243
|
+
pub fn instantiate(&self, s: WrappedStruct<Store>, module: &Module) -> Result<Instance, Error> {
|
244
|
+
let wrapped_store: WrappedStruct<Store> = s.try_convert()?;
|
245
|
+
let store = wrapped_store.get()?;
|
246
|
+
self.inner
|
247
|
+
.borrow_mut()
|
248
|
+
.instantiate(store.context_mut(), module.get())
|
249
|
+
.map_err(|e| StoreContextValue::from(wrapped_store).handle_wasm_error(e))
|
250
|
+
.map(|instance| {
|
251
|
+
self.refs.borrow().iter().for_each(|val| store.retain(*val));
|
252
|
+
Instance::from_inner(s, instance)
|
253
|
+
})
|
254
|
+
}
|
255
|
+
|
256
|
+
/// @yard
|
257
|
+
/// Returns the “default export” of a module.
|
258
|
+
/// @def get_default(store, mod)
|
259
|
+
/// @param store [Store]
|
260
|
+
/// @param mod [String] Module name
|
261
|
+
/// @return [Func]
|
262
|
+
pub fn get_default(&self, s: WrappedStruct<Store>, module: RString) -> Result<Func, Error> {
|
263
|
+
let store = s.get()?;
|
264
|
+
|
265
|
+
self.inner
|
266
|
+
.borrow()
|
267
|
+
.get_default(store.context_mut(), unsafe { module.as_str() }?)
|
268
|
+
.map(|func| Func::from_inner(s.into(), func))
|
269
|
+
.map_err(|e| error!("{}", e))
|
270
|
+
}
|
271
|
+
}
|
272
|
+
|
273
|
+
pub fn init() -> Result<(), Error> {
|
274
|
+
let class = root().define_class("Linker", Default::default())?;
|
275
|
+
class.define_singleton_method("new", function!(Linker::new, 1))?;
|
276
|
+
class.define_method("allow_shadowing=", method!(Linker::set_allow_shadowing, 1))?;
|
277
|
+
class.define_method(
|
278
|
+
"allow_unknown_exports=",
|
279
|
+
method!(Linker::set_allow_unknown_exports, 1),
|
280
|
+
)?;
|
281
|
+
class.define_method(
|
282
|
+
"define_unknown_imports_as_traps",
|
283
|
+
method!(Linker::define_unknown_imports_as_traps, 1),
|
284
|
+
)?;
|
285
|
+
class.define_method("define", method!(Linker::define, 3))?;
|
286
|
+
class.define_method("func_new", method!(Linker::func_new, -1))?;
|
287
|
+
class.define_method("get", method!(Linker::get, 3))?;
|
288
|
+
class.define_method("instance", method!(Linker::instance, 3))?;
|
289
|
+
class.define_method("module", method!(Linker::module, 3))?;
|
290
|
+
class.define_method("alias", method!(Linker::alias, 4))?;
|
291
|
+
class.define_method("alias_module", method!(Linker::alias_module, 2))?;
|
292
|
+
class.define_method("instantiate", method!(Linker::instantiate, 2))?;
|
293
|
+
class.define_method("get_default", method!(Linker::get_default, 2))?;
|
294
|
+
|
295
|
+
Ok(())
|
296
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
/// A macro to define a new `Id` const for a given string.
|
2
|
+
#[macro_export]
|
3
|
+
macro_rules! define_rb_intern {
|
4
|
+
($($name:ident => $id:expr,)*) => {
|
5
|
+
$(
|
6
|
+
lazy_static::lazy_static! {
|
7
|
+
/// Define a Ruby internal `Id`. Equivalent to `rb_intern("$name")`
|
8
|
+
pub static ref $name: $crate::ruby_api::static_id::StaticId = $crate::ruby_api::static_id::StaticId::intern_str($id);
|
9
|
+
}
|
10
|
+
)*
|
11
|
+
};
|
12
|
+
}
|