wasmer 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +100 -0
- data/.gitignore +3 -1
- data/CHANGELOG.md +147 -0
- data/Cargo.lock +302 -840
- data/Cargo.toml +4 -5
- data/LICENSE +21 -0
- data/README.md +30 -3
- data/bors.toml +3 -1
- data/lib/wasmer/version.rb +1 -1
- data/src/{instance.rs → instance/exports.rs} +16 -112
- data/src/instance/globals.rs +234 -0
- data/src/instance/mod.rs +141 -0
- data/src/lib.rs +40 -2
- data/src/memory/mod.rs +1 -2
- data/wasmer.gemspec +4 -4
- metadata +16 -12
- data/.circleci/config.yml +0 -72
data/Cargo.toml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
[package]
|
2
2
|
publish = false
|
3
3
|
name = "ruby-ext-wasm"
|
4
|
-
version = "0.
|
4
|
+
version = "0.4.0"
|
5
5
|
authors = ["Ivan Enderlin <ivan.enderlin@hoa-project.net>"]
|
6
6
|
edition = "2018"
|
7
7
|
description = "Ruby extension to run WebAssembly binaries"
|
@@ -15,7 +15,6 @@ name = "wasmer"
|
|
15
15
|
crate-type = ["dylib"]
|
16
16
|
|
17
17
|
[dependencies]
|
18
|
-
wasmer-runtime = "0.
|
19
|
-
|
20
|
-
|
21
|
-
lazy_static = "1.3.0"
|
18
|
+
wasmer-runtime = "0.14"
|
19
|
+
rutie = "0.7"
|
20
|
+
lazy_static = "1.4"
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2019-present Wasmer, Inc. and its affiliates.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<p align="center">
|
2
|
-
<a href="https://wasmer.io" target="_blank" rel="noopener
|
3
|
-
<img width="
|
2
|
+
<a href="https://wasmer.io" target="_blank" rel="noopener">
|
3
|
+
<img width="300" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/assets/logo.png" alt="Wasmer logo">
|
4
4
|
</a>
|
5
5
|
</p>
|
6
6
|
|
@@ -76,7 +76,8 @@ $ ruby simple.rb
|
|
76
76
|
|
77
77
|
## The `Instance` class
|
78
78
|
|
79
|
-
Instantiates a WebAssembly module represented by bytes, and calls
|
79
|
+
Instantiates a WebAssembly module represented by bytes, and calls
|
80
|
+
exported functions on it:
|
80
81
|
|
81
82
|
```ruby
|
82
83
|
require "wasmer"
|
@@ -93,10 +94,14 @@ result = instance.exports.sum 1, 2
|
|
93
94
|
puts result # 3
|
94
95
|
```
|
95
96
|
|
97
|
+
### Exported functions
|
98
|
+
|
96
99
|
All exported functions are accessible on the `exports`
|
97
100
|
getter. Arguments of these functions are automatically casted to
|
98
101
|
WebAssembly values.
|
99
102
|
|
103
|
+
### Exported memory
|
104
|
+
|
100
105
|
The `memory` getter exposes the `Memory` class representing the memory
|
101
106
|
of that particular instance, e.g.:
|
102
107
|
|
@@ -104,8 +109,30 @@ of that particular instance, e.g.:
|
|
104
109
|
view = instance.memory.uint8_view
|
105
110
|
```
|
106
111
|
|
112
|
+
`Instance.memory` throws an exception if no memory is exported.
|
113
|
+
|
107
114
|
See below for more information.
|
108
115
|
|
116
|
+
### Exported globals
|
117
|
+
|
118
|
+
The `globals` getter exposes the `ExportedGlobal` class represented an
|
119
|
+
exported global variable, e.g.:
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
# Get the `x` global.
|
123
|
+
x = instance.globals.x
|
124
|
+
|
125
|
+
# Check whether the global is mutable.
|
126
|
+
assert x.mutable
|
127
|
+
assert_equal x.value, 7
|
128
|
+
|
129
|
+
# Update its value.
|
130
|
+
x.value = 42
|
131
|
+
|
132
|
+
# Tada!
|
133
|
+
assert_equal x.value, 42
|
134
|
+
```
|
135
|
+
|
109
136
|
## The `Memory` class
|
110
137
|
|
111
138
|
A WebAssembly instance has its own memory, represented by the `Memory`
|
data/bors.toml
CHANGED
data/lib/wasmer/version.rb
CHANGED
@@ -1,21 +1,17 @@
|
|
1
|
-
//! The `
|
1
|
+
//! The `ExportedFunctions` WebAssembly class.
|
2
2
|
|
3
|
-
use crate::
|
4
|
-
error::unwrap_or_raise,
|
5
|
-
memory::{Memory, RubyMemory, MEMORY_WRAPPER},
|
6
|
-
};
|
3
|
+
use crate::error::unwrap_or_raise;
|
7
4
|
use lazy_static::lazy_static;
|
8
5
|
use rutie::{
|
9
6
|
class, methods,
|
10
7
|
rubysys::{class, value::ValueType},
|
11
8
|
types::{Argc, Value},
|
12
9
|
util::str_to_cstring,
|
13
|
-
wrappable_struct, AnyException, AnyObject, Array, Boolean, Exception, Fixnum, Float,
|
14
|
-
|
10
|
+
wrappable_struct, AnyException, AnyObject, Array, Boolean, Exception, Fixnum, Float, NilClass,
|
11
|
+
Object, Symbol,
|
15
12
|
};
|
16
|
-
use std::
|
17
|
-
use wasmer_runtime::{self as runtime,
|
18
|
-
use wasmer_runtime_core::types::Type;
|
13
|
+
use std::rc::Rc;
|
14
|
+
use wasmer_runtime::{self as runtime, types::Type};
|
19
15
|
|
20
16
|
/// The `ExportedFunctions` Ruby class.
|
21
17
|
pub struct ExportedFunctions {
|
@@ -150,12 +146,18 @@ impl ExportedFunctions {
|
|
150
146
|
.call(function_arguments.as_slice())
|
151
147
|
.map_err(|e| AnyException::new("RuntimeError", Some(&format!("{}", e))))?;
|
152
148
|
|
153
|
-
if results.
|
149
|
+
if !results.is_empty() {
|
154
150
|
Ok(match results[0] {
|
155
151
|
runtime::Value::I32(result) => Fixnum::new(result as i64).into(),
|
156
152
|
runtime::Value::I64(result) => Fixnum::new(result).into(),
|
157
153
|
runtime::Value::F32(result) => Float::new(result as f64).into(),
|
158
154
|
runtime::Value::F64(result) => Float::new(result).into(),
|
155
|
+
runtime::Value::V128(_result) => {
|
156
|
+
return Err(AnyException::new(
|
157
|
+
"RuntimeError",
|
158
|
+
Some("Type `V128` isn't supported yet."),
|
159
|
+
))
|
160
|
+
}
|
159
161
|
})
|
160
162
|
} else {
|
161
163
|
Ok(NilClass::new().into())
|
@@ -180,9 +182,9 @@ methods!(
|
|
180
182
|
fn ruby_exported_functions_method_exists(symbol: Symbol, _include_private: Boolean) -> Boolean {
|
181
183
|
unwrap_or_raise(|| {
|
182
184
|
let symbol = symbol?;
|
183
|
-
let
|
185
|
+
let exported_functions = itself.get_data(&*EXPORTED_FUNCTIONS_WRAPPER);
|
184
186
|
|
185
|
-
Ok(Boolean::new(
|
187
|
+
Ok(Boolean::new(exported_functions.respond_to_missing(symbol.to_str())))
|
186
188
|
})
|
187
189
|
}
|
188
190
|
);
|
@@ -197,7 +199,7 @@ pub extern "C" fn ruby_exported_functions_method_missing(
|
|
197
199
|
let arguments = Value::from(0);
|
198
200
|
|
199
201
|
unsafe {
|
200
|
-
let argv_pointer
|
202
|
+
let argv_pointer = argv as *const Value;
|
201
203
|
|
202
204
|
class::rb_scan_args(argc, argv_pointer, str_to_cstring("*").as_ptr(), &arguments)
|
203
205
|
};
|
@@ -211,101 +213,3 @@ pub extern "C" fn ruby_exported_functions_method_missing(
|
|
211
213
|
.method_missing(method_name, arguments)
|
212
214
|
})
|
213
215
|
}
|
214
|
-
|
215
|
-
/// The `Instance` Ruby class.
|
216
|
-
pub struct Instance {
|
217
|
-
/// The WebAssembly instance.
|
218
|
-
instance: Rc<runtime::Instance>,
|
219
|
-
}
|
220
|
-
|
221
|
-
impl Instance {
|
222
|
-
/// Create a new instance of the `Instance` Ruby class.
|
223
|
-
/// The constructor receives bytes from a string.
|
224
|
-
pub fn new(bytes: &[u8]) -> Result<Self, AnyException> {
|
225
|
-
let import_object = imports! {};
|
226
|
-
|
227
|
-
Ok(Self {
|
228
|
-
instance: Rc::new(runtime::instantiate(bytes, &import_object).map_err(|e| {
|
229
|
-
AnyException::new(
|
230
|
-
"RuntimeError",
|
231
|
-
Some(&format!("Failed to instantiate the module:\n {}", e)),
|
232
|
-
)
|
233
|
-
})?),
|
234
|
-
})
|
235
|
-
}
|
236
|
-
}
|
237
|
-
|
238
|
-
wrappable_struct!(Instance, InstanceWrapper, INSTANCE_WRAPPER);
|
239
|
-
|
240
|
-
class!(RubyInstance);
|
241
|
-
|
242
|
-
#[rustfmt::skip]
|
243
|
-
methods!(
|
244
|
-
RubyInstance,
|
245
|
-
_itself,
|
246
|
-
|
247
|
-
// Glue code to call the `Instance.new` method.
|
248
|
-
fn ruby_instance_new(bytes: RString) -> AnyObject {
|
249
|
-
unwrap_or_raise(|| {
|
250
|
-
let instance = Instance::new(
|
251
|
-
bytes
|
252
|
-
.map_err(|_| {
|
253
|
-
AnyException::new(
|
254
|
-
"ArgumentError",
|
255
|
-
Some("WebAssembly module must be represented by Ruby bytes only."),
|
256
|
-
)
|
257
|
-
})?
|
258
|
-
.to_bytes_unchecked(),
|
259
|
-
)?;
|
260
|
-
let exported_functions = ExportedFunctions::new(instance.instance.clone());
|
261
|
-
|
262
|
-
let memory = instance
|
263
|
-
.instance
|
264
|
-
.exports()
|
265
|
-
.find_map(|(_, export)| match export {
|
266
|
-
Export::Memory(memory) => Some(Memory::new(Rc::new(memory))),
|
267
|
-
_ => None,
|
268
|
-
})
|
269
|
-
.ok_or_else(|| {
|
270
|
-
AnyException::new(
|
271
|
-
"RuntimeError",
|
272
|
-
Some("The WebAssembly module has no exported memory."),
|
273
|
-
)
|
274
|
-
})?;
|
275
|
-
|
276
|
-
let wasmer_module = Module::from_existing("Wasmer");
|
277
|
-
|
278
|
-
let mut ruby_instance: AnyObject = wasmer_module
|
279
|
-
.get_nested_class("Instance")
|
280
|
-
.wrap_data(instance, &*INSTANCE_WRAPPER);
|
281
|
-
|
282
|
-
let ruby_exported_functions: RubyExportedFunctions = wasmer_module
|
283
|
-
.get_nested_class("ExportedFunctions")
|
284
|
-
.wrap_data(exported_functions, &*EXPORTED_FUNCTIONS_WRAPPER);
|
285
|
-
|
286
|
-
ruby_instance.instance_variable_set("@exports", ruby_exported_functions);
|
287
|
-
|
288
|
-
let ruby_memory: RubyMemory = wasmer_module
|
289
|
-
.get_nested_class("Memory")
|
290
|
-
.wrap_data(memory, &*MEMORY_WRAPPER);
|
291
|
-
|
292
|
-
ruby_instance.instance_variable_set("@memory", ruby_memory);
|
293
|
-
|
294
|
-
Ok(ruby_instance)
|
295
|
-
})
|
296
|
-
}
|
297
|
-
|
298
|
-
// Glue code to call the `Instance.exports` getter method.
|
299
|
-
fn ruby_instance_exported_functions() -> RubyExportedFunctions {
|
300
|
-
unsafe {
|
301
|
-
_itself
|
302
|
-
.instance_variable_get("@exports")
|
303
|
-
.to::<RubyExportedFunctions>()
|
304
|
-
}
|
305
|
-
}
|
306
|
-
|
307
|
-
// Glue code to call the `Instance.memory` getter method.
|
308
|
-
fn ruby_instance_memory() -> RubyMemory {
|
309
|
-
unsafe { _itself.instance_variable_get("@memory").to::<RubyMemory>() }
|
310
|
-
}
|
311
|
-
);
|
@@ -0,0 +1,234 @@
|
|
1
|
+
//! The `ExportedGlobals` WebAssembly class.
|
2
|
+
|
3
|
+
use crate::error::unwrap_or_raise;
|
4
|
+
use lazy_static::lazy_static;
|
5
|
+
use rutie::{
|
6
|
+
class, methods,
|
7
|
+
rubysys::class,
|
8
|
+
types::{Argc, Value},
|
9
|
+
util::str_to_cstring,
|
10
|
+
wrappable_struct, AnyException, AnyObject, Array, Boolean, Exception, Fixnum, Float, Module,
|
11
|
+
NilClass, Object, Symbol,
|
12
|
+
};
|
13
|
+
use std::rc::Rc;
|
14
|
+
use wasmer_runtime::{
|
15
|
+
self as runtime, types::Type as WasmType, Export, Global, Value as WasmValue,
|
16
|
+
};
|
17
|
+
|
18
|
+
/// The `ExportedGlobals` Ruby class.
|
19
|
+
pub struct ExportedGlobals {
|
20
|
+
/// The WebAssembly runtime.
|
21
|
+
instance: Rc<runtime::Instance>,
|
22
|
+
}
|
23
|
+
|
24
|
+
impl ExportedGlobals {
|
25
|
+
/// Create a new instance of the `ExportedGlobals` Ruby class.
|
26
|
+
pub fn new(instance: Rc<runtime::Instance>) -> Self {
|
27
|
+
Self { instance }
|
28
|
+
}
|
29
|
+
|
30
|
+
/// Check that an exported function exists.
|
31
|
+
pub fn respond_to_missing(&self, method_name: &str) -> bool {
|
32
|
+
self.instance
|
33
|
+
.exports()
|
34
|
+
.any(|(export_name, export)| match export {
|
35
|
+
Export::Global(_) if export_name == method_name => true,
|
36
|
+
_ => false,
|
37
|
+
})
|
38
|
+
}
|
39
|
+
|
40
|
+
/// Call an exported function on the given WebAssembly instance.
|
41
|
+
pub fn method_missing(
|
42
|
+
&self,
|
43
|
+
method_name: &str,
|
44
|
+
_arguments: Array,
|
45
|
+
) -> Result<ExportedGlobal, AnyException> {
|
46
|
+
let global = self
|
47
|
+
.instance
|
48
|
+
.exports()
|
49
|
+
.find_map(|(export_name, export)| match export {
|
50
|
+
Export::Global(global) if export_name == method_name => Some(global),
|
51
|
+
_ => None,
|
52
|
+
})
|
53
|
+
.ok_or_else(|| {
|
54
|
+
AnyException::new(
|
55
|
+
"RuntimeError",
|
56
|
+
Some(&format!("Global `{}` does not exist.", method_name)),
|
57
|
+
)
|
58
|
+
})?;
|
59
|
+
|
60
|
+
Ok(ExportedGlobal {
|
61
|
+
global_name: method_name.to_string(),
|
62
|
+
global: Rc::new(global),
|
63
|
+
})
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
wrappable_struct!(
|
68
|
+
ExportedGlobals,
|
69
|
+
ExportedGlobalsWrapper,
|
70
|
+
EXPORTED_GLOBALS_WRAPPER
|
71
|
+
);
|
72
|
+
|
73
|
+
class!(RubyExportedGlobals);
|
74
|
+
|
75
|
+
#[rustfmt::skip]
|
76
|
+
methods!(
|
77
|
+
RubyExportedGlobals,
|
78
|
+
itself,
|
79
|
+
|
80
|
+
// Glue code to call the `Exportedglobals.respond_to` method.
|
81
|
+
fn ruby_exported_globals_method_exists(symbol: Symbol, _include_private: Boolean) -> Boolean {
|
82
|
+
unwrap_or_raise(|| {
|
83
|
+
let symbol = symbol?;
|
84
|
+
let exported_globals = itself.get_data(&*EXPORTED_GLOBALS_WRAPPER);
|
85
|
+
|
86
|
+
Ok(Boolean::new(exported_globals.respond_to_missing(symbol.to_str())))
|
87
|
+
})
|
88
|
+
}
|
89
|
+
);
|
90
|
+
|
91
|
+
/// Glue code to call the `ExportedGlobals.method_missing` method.
|
92
|
+
pub extern "C" fn ruby_exported_globals_method_missing(
|
93
|
+
argc: Argc,
|
94
|
+
argv: *const AnyObject,
|
95
|
+
itself: RubyExportedGlobals,
|
96
|
+
) -> RubyExportedGlobal {
|
97
|
+
unwrap_or_raise(|| {
|
98
|
+
let arguments = Value::from(0);
|
99
|
+
|
100
|
+
unsafe {
|
101
|
+
let argv_pointer = argv as *const Value;
|
102
|
+
|
103
|
+
class::rb_scan_args(argc, argv_pointer, str_to_cstring("*").as_ptr(), &arguments)
|
104
|
+
};
|
105
|
+
|
106
|
+
let mut arguments = Array::from(arguments);
|
107
|
+
let method_name = unsafe { arguments.shift().to::<Symbol>() };
|
108
|
+
let method_name = method_name.to_str();
|
109
|
+
|
110
|
+
Ok(Module::from_existing("Wasmer")
|
111
|
+
.get_nested_class("ExportedGlobal")
|
112
|
+
.wrap_data(
|
113
|
+
itself
|
114
|
+
.get_data(&*EXPORTED_GLOBALS_WRAPPER)
|
115
|
+
.method_missing(method_name, arguments)?,
|
116
|
+
&*EXPORTED_GLOBAL_WRAPPER,
|
117
|
+
))
|
118
|
+
})
|
119
|
+
}
|
120
|
+
|
121
|
+
#[allow(unused)]
|
122
|
+
/// The `ExportedGlobal` Ruby class.
|
123
|
+
pub struct ExportedGlobal {
|
124
|
+
/// The exported global name from the WebAssembly instance.
|
125
|
+
global_name: String,
|
126
|
+
|
127
|
+
/// The exported global from the WebAssembly instance.
|
128
|
+
global: Rc<Global>,
|
129
|
+
}
|
130
|
+
|
131
|
+
impl ExportedGlobal {
|
132
|
+
pub fn get_value(&self) -> WasmValue {
|
133
|
+
self.global.get()
|
134
|
+
}
|
135
|
+
|
136
|
+
pub fn set_value(&self, value: WasmValue) {
|
137
|
+
self.global.set(value);
|
138
|
+
}
|
139
|
+
|
140
|
+
pub fn mutable(&self) -> bool {
|
141
|
+
self.global.descriptor().mutable
|
142
|
+
}
|
143
|
+
|
144
|
+
fn ty(&self) -> WasmType {
|
145
|
+
self.global.descriptor().ty
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
wrappable_struct!(
|
150
|
+
ExportedGlobal,
|
151
|
+
ExportedGlobalWrapper,
|
152
|
+
EXPORTED_GLOBAL_WRAPPER
|
153
|
+
);
|
154
|
+
|
155
|
+
class!(RubyExportedGlobal);
|
156
|
+
|
157
|
+
#[rustfmt::skip]
|
158
|
+
methods!(
|
159
|
+
RubyExportedGlobal,
|
160
|
+
itself,
|
161
|
+
|
162
|
+
// Glue code to call the `ExportedGlobal.get_value` method.
|
163
|
+
fn ruby_exported_global_get_value() -> AnyObject {
|
164
|
+
unwrap_or_raise(|| {
|
165
|
+
let exported_global = itself.get_data(&*EXPORTED_GLOBAL_WRAPPER);
|
166
|
+
|
167
|
+
Ok(match exported_global.get_value() {
|
168
|
+
WasmValue::I32(result) => Fixnum::new(result as i64).to_any_object(),
|
169
|
+
WasmValue::I64(result) => Fixnum::new(result).to_any_object(),
|
170
|
+
WasmValue::F32(result) => Float::new(result as f64).to_any_object(),
|
171
|
+
WasmValue::F64(result) => Float::new(result).to_any_object(),
|
172
|
+
WasmValue::V128(_result) => {
|
173
|
+
return Err(AnyException::new(
|
174
|
+
"RuntimeError",
|
175
|
+
Some("Type `V128` isn't supported yet."),
|
176
|
+
))
|
177
|
+
}
|
178
|
+
})
|
179
|
+
})
|
180
|
+
}
|
181
|
+
|
182
|
+
// Glue code to call the `ExportedGlobal.set_value` method.
|
183
|
+
fn ruby_exported_global_set_value(value: AnyObject) -> NilClass {
|
184
|
+
unwrap_or_raise(|| {
|
185
|
+
let exported_global = itself.get_data(&*EXPORTED_GLOBAL_WRAPPER);
|
186
|
+
|
187
|
+
if !exported_global.mutable() {
|
188
|
+
return Err(AnyException::new(
|
189
|
+
"RuntimeError",
|
190
|
+
Some(&format!(
|
191
|
+
"The global variable `{}` is not mutable, cannot set a new value.",
|
192
|
+
exported_global.global_name
|
193
|
+
)),
|
194
|
+
));
|
195
|
+
}
|
196
|
+
|
197
|
+
let value = value?;
|
198
|
+
|
199
|
+
let wasm_type = exported_global.ty();
|
200
|
+
let wasm_value = match wasm_type {
|
201
|
+
WasmType::I32 if value.is_fixnum() => {
|
202
|
+
WasmValue::I32(unsafe { value.to::<Fixnum>().to_i32() })
|
203
|
+
}
|
204
|
+
WasmType::I64 if value.is_fixnum() => {
|
205
|
+
WasmValue::I64(unsafe { value.to::<Fixnum>().to_i64() })
|
206
|
+
}
|
207
|
+
WasmType::F32 if value.is_flonum() => {
|
208
|
+
WasmValue::F32(unsafe { value.to::<Float>().to_f64() as f32 })
|
209
|
+
}
|
210
|
+
WasmType::F64 if value.is_flonum() => {
|
211
|
+
WasmValue::F64(unsafe { value.to::<Float>().to_f64() })
|
212
|
+
}
|
213
|
+
_ => {
|
214
|
+
return Err(AnyException::new(
|
215
|
+
"TypeError",
|
216
|
+
Some(&format!(
|
217
|
+
"Failed to set `{:?}` to the global `{}` (with type `{}`).",
|
218
|
+
value, exported_global.global_name, wasm_type
|
219
|
+
)),
|
220
|
+
))
|
221
|
+
}
|
222
|
+
};
|
223
|
+
|
224
|
+
exported_global.set_value(wasm_value);
|
225
|
+
|
226
|
+
Ok(NilClass::new())
|
227
|
+
})
|
228
|
+
}
|
229
|
+
|
230
|
+
// Glue code to call the `ExportedGlobal.mutable` getter.
|
231
|
+
fn ruby_exported_global_mutable() -> Boolean {
|
232
|
+
Boolean::new(itself.get_data(&*EXPORTED_GLOBAL_WRAPPER).mutable())
|
233
|
+
}
|
234
|
+
);
|