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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +941 -627
  3. data/Cargo.toml +2 -14
  4. data/LICENSE +23 -21
  5. data/README.md +47 -118
  6. data/ext/Cargo.toml +17 -0
  7. data/ext/extconf.rb +6 -0
  8. data/ext/src/helpers/mod.rs +3 -0
  9. data/ext/src/helpers/wrapped_struct.rs +84 -0
  10. data/ext/src/lib.rs +9 -0
  11. data/ext/src/ruby_api/config.rs +68 -0
  12. data/ext/src/ruby_api/convert.rs +92 -0
  13. data/ext/src/ruby_api/engine.rs +66 -0
  14. data/ext/src/ruby_api/errors.rs +56 -0
  15. data/ext/src/ruby_api/externals.rs +113 -0
  16. data/ext/src/ruby_api/func.rs +388 -0
  17. data/ext/src/ruby_api/func_type.rs +139 -0
  18. data/ext/src/ruby_api/instance.rs +174 -0
  19. data/ext/src/ruby_api/linker.rs +296 -0
  20. data/ext/src/ruby_api/macros.rs +12 -0
  21. data/ext/src/ruby_api/memory.rs +142 -0
  22. data/ext/src/ruby_api/memory_type.rs +56 -0
  23. data/ext/src/ruby_api/mod.rs +48 -0
  24. data/ext/src/ruby_api/module.rs +107 -0
  25. data/ext/src/ruby_api/params.rs +42 -0
  26. data/ext/src/ruby_api/static_id.rs +57 -0
  27. data/ext/src/ruby_api/store.rs +182 -0
  28. data/ext/src/ruby_api/trap.rs +135 -0
  29. data/lib/wasmtime/version.rb +1 -1
  30. data/lib/wasmtime.rb +29 -4
  31. metadata +54 -30
  32. data/.cargo/config +0 -4
  33. data/CHANGELOG.md +0 -27
  34. data/ext/wasmtime/Makefile +0 -5
  35. data/ext/wasmtime/Rakefile +0 -3
  36. data/ext/wasmtime/extconf.rb +0 -5
  37. data/lib/tasks/compile.rake +0 -27
  38. data/lib/wasmtime/refinements.rb +0 -20
  39. data/lib/wasmtime/require.rb +0 -72
  40. data/src/export.rs +0 -19
  41. data/src/func.rs +0 -175
  42. data/src/instance.rs +0 -93
  43. data/src/lib.rs +0 -22
  44. data/src/memory.rs +0 -48
  45. data/src/ruby_type.rs +0 -32
  46. 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
+ }