ruby_wasm 2.5.0.pre.1 → 2.5.1
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/CONTRIBUTING.md +13 -9
- data/Cargo.lock +705 -451
- data/Gemfile +1 -1
- data/README.md +12 -19
- data/Rakefile +9 -9
- data/benchmarks/vm_deep_call.rb +2 -2
- data/docs/cheat_sheet.md +8 -8
- data/ext/ruby_wasm/Cargo.toml +6 -5
- data/ext/ruby_wasm/src/lib.rs +208 -7
- data/lib/ruby_wasm/build/executor.rb +4 -0
- data/lib/ruby_wasm/build/product/crossruby.rb +57 -23
- data/lib/ruby_wasm/build/product/libyaml.rb +5 -3
- data/lib/ruby_wasm/build/product/openssl.rb +7 -2
- data/lib/ruby_wasm/build/product/product.rb +3 -3
- data/lib/ruby_wasm/build/product/ruby_source.rb +3 -3
- data/lib/ruby_wasm/build/product/wasi_vfs.rb +1 -39
- data/lib/ruby_wasm/build/product/zlib.rb +5 -3
- data/lib/ruby_wasm/build/target.rb +24 -0
- data/lib/ruby_wasm/build/toolchain.rb +1 -1
- data/lib/ruby_wasm/build.rb +7 -3
- data/lib/ruby_wasm/cli.rb +171 -13
- data/lib/ruby_wasm/feature_set.rb +30 -0
- data/lib/ruby_wasm/packager/component_adapter/wasi_snapshot_preview1.command.wasm +0 -0
- data/lib/ruby_wasm/packager/component_adapter/wasi_snapshot_preview1.reactor.wasm +0 -0
- data/lib/ruby_wasm/packager/component_adapter.rb +14 -0
- data/lib/ruby_wasm/packager/core.rb +192 -4
- data/lib/ruby_wasm/packager/file_system.rb +20 -17
- data/lib/ruby_wasm/packager.rb +21 -83
- data/lib/ruby_wasm/rake_task.rb +2 -0
- data/lib/ruby_wasm/version.rb +1 -1
- data/lib/ruby_wasm.rb +2 -0
- data/package-lock.json +410 -133
- data/package.json +3 -3
- data/{tasks → rakelib}/ci.rake +3 -3
- data/{tasks → rakelib}/doc.rake +6 -1
- data/{tasks → rakelib}/format.rake +3 -2
- data/{tasks → rakelib}/gem.rake +4 -1
- data/{tasks → rakelib}/packaging.rake +34 -17
- data/{tasks → rakelib}/version.rake +2 -0
- data/sig/ruby_wasm/build.rbs +36 -31
- data/sig/ruby_wasm/cli.rbs +30 -3
- data/sig/ruby_wasm/ext.rbs +28 -3
- data/sig/ruby_wasm/feature_set.rbs +12 -0
- data/sig/ruby_wasm/packager.rbs +44 -7
- metadata +16 -15
- data/builders/wasm32-unknown-emscripten/Dockerfile +0 -43
- data/builders/wasm32-unknown-emscripten/entrypoint.sh +0 -7
- data/builders/wasm32-unknown-wasi/Dockerfile +0 -47
- data/builders/wasm32-unknown-wasi/entrypoint.sh +0 -7
- data/ruby_wasm.gemspec +0 -32
- /data/{tasks → rakelib}/check.rake +0 -0
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -17,17 +17,17 @@ Try ruby.wasm in [TryRuby](https://try.ruby-lang.org/playground#code=puts+RUBY_D
|
|
17
17
|
- [Complete Examples](https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-wasm-wasi/example)
|
18
18
|
- [Community Showcase](https://github.com/ruby/ruby.wasm/wiki/Showcase)
|
19
19
|
|
20
|
-
## Quick Example: Ruby on browser
|
20
|
+
## Quick Example: Ruby on Web browser
|
21
21
|
|
22
22
|
Create and save `index.html` page with the following contents:
|
23
23
|
|
24
24
|
```html
|
25
25
|
<html>
|
26
|
-
<script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.
|
26
|
+
<script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.1/dist/browser.script.iife.js"></script>
|
27
27
|
<script type="text/ruby">
|
28
28
|
require "js"
|
29
29
|
|
30
|
-
puts RUBY_VERSION #
|
30
|
+
puts RUBY_VERSION # (Printed to the Web browser console)
|
31
31
|
JS.global[:document].write "Hello, world!"
|
32
32
|
</script>
|
33
33
|
</html>
|
@@ -35,25 +35,26 @@ Create and save `index.html` page with the following contents:
|
|
35
35
|
|
36
36
|
## Quick Example: How to package your Ruby application as a WASI application
|
37
37
|
|
38
|
-
Dependencies: [
|
38
|
+
Dependencies: [wasmtime](https://github.com/bytecodealliance/wasmtime)
|
39
39
|
|
40
40
|
```console
|
41
|
+
$ gem install ruby_wasm
|
41
42
|
# Download a prebuilt Ruby release
|
42
|
-
$ curl -LO https://github.com/ruby/ruby.wasm/releases/latest/download/ruby-3.
|
43
|
-
$ tar xfz ruby-3.
|
43
|
+
$ curl -LO https://github.com/ruby/ruby.wasm/releases/latest/download/ruby-3.3-wasm32-unknown-wasip1-full.tar.gz
|
44
|
+
$ tar xfz ruby-3.3-wasm32-unknown-wasip1-full.tar.gz
|
44
45
|
|
45
46
|
# Extract ruby binary not to pack itself
|
46
|
-
$ mv 3.
|
47
|
+
$ mv ruby-3.3-wasm32-unknown-wasip1-full/usr/local/bin/ruby ruby.wasm
|
47
48
|
|
48
49
|
# Put your app code
|
49
50
|
$ mkdir src
|
50
51
|
$ echo "puts 'Hello'" > src/my_app.rb
|
51
52
|
|
52
53
|
# Pack the whole directory under /usr and your app dir
|
53
|
-
$
|
54
|
+
$ rbwasm pack ruby.wasm --dir ./src::/src --dir ./ruby-3.3-wasm32-unknown-wasip1-full/usr::/usr -o my-ruby-app.wasm
|
54
55
|
|
55
56
|
# Run the packed scripts
|
56
|
-
$ wasmtime my-ruby-app.wasm
|
57
|
+
$ wasmtime my-ruby-app.wasm /src/my_app.rb
|
57
58
|
Hello
|
58
59
|
```
|
59
60
|
|
@@ -109,8 +110,8 @@ A _build_ is a combination of ruby version, _profile_, and _target_.
|
|
109
110
|
</thead>
|
110
111
|
<tbody>
|
111
112
|
<tr>
|
112
|
-
<td><code>wasm32-unknown-
|
113
|
-
<td>Targeting WASI
|
113
|
+
<td><code>wasm32-unknown-wasip1</code></td>
|
114
|
+
<td>Targeting <a href="https://github.com/WebAssembly/WASI/tree/main/legacy/preview1">WASI Preview1</a> compatible environments <br>(e.g. Node.js, browsers with polyfill, <a href="https://github.com/bytecodealliance/wasmtime">wasmtime</a>, and so on)</td>
|
114
115
|
</tr>
|
115
116
|
<tr>
|
116
117
|
<td><code>wasm32-unknown-emscripten</code></td>
|
@@ -137,14 +138,6 @@ A _build_ is a combination of ruby version, _profile_, and _target_.
|
|
137
138
|
<td><code>full</code></td>
|
138
139
|
<td>All standard extension libraries</td>
|
139
140
|
</tr>
|
140
|
-
<tr>
|
141
|
-
<td><code>*-js</code></td>
|
142
|
-
<td>Enabled JS interoperability, only usable with npm package</td>
|
143
|
-
</tr>
|
144
|
-
<tr>
|
145
|
-
<td><code>*-debug</code></td>
|
146
|
-
<td>With DWARF info and <a href="https://webassembly.github.io/spec/core/appendix/custom.html#name-section" rel="nofollow"><code>name</code> section</a> for debugging</td>
|
147
|
-
</tr>
|
148
141
|
</tbody>
|
149
142
|
</table>
|
150
143
|
|
data/Rakefile
CHANGED
@@ -7,8 +7,7 @@ $LOAD_PATH << File.join(File.dirname(__FILE__), "lib")
|
|
7
7
|
require "bundler/gem_tasks"
|
8
8
|
require "ruby_wasm/rake_task"
|
9
9
|
require "ruby_wasm/packager"
|
10
|
-
|
11
|
-
Dir.glob("tasks/**.rake").each { |f| import f }
|
10
|
+
require "ruby_wasm/cli"
|
12
11
|
|
13
12
|
BUILD_SOURCES = %w[3.3 3.2 head]
|
14
13
|
BUILD_PROFILES = %w[full minimal]
|
@@ -16,7 +15,7 @@ BUILD_PROFILES = %w[full minimal]
|
|
16
15
|
BUILDS =
|
17
16
|
BUILD_SOURCES
|
18
17
|
.product(BUILD_PROFILES)
|
19
|
-
.map { |src, profile| [src, "wasm32-unknown-
|
18
|
+
.map { |src, profile| [src, "wasm32-unknown-wasip1", profile] } +
|
20
19
|
BUILD_SOURCES.map { |src| [src, "wasm32-unknown-emscripten", "full"] }
|
21
20
|
|
22
21
|
NPM_PACKAGES = [
|
@@ -30,25 +29,26 @@ NPM_PACKAGES = [
|
|
30
29
|
name: "ruby-head-wasm-wasi",
|
31
30
|
ruby_version: "head",
|
32
31
|
gemfile: "packages/npm-packages/ruby-wasm-wasi/Gemfile",
|
33
|
-
target: "wasm32-unknown-
|
32
|
+
target: "wasm32-unknown-wasip1"
|
34
33
|
},
|
35
34
|
{
|
36
35
|
name: "ruby-3.3-wasm-wasi",
|
37
36
|
ruby_version: "3.3",
|
38
37
|
gemfile: "packages/npm-packages/ruby-wasm-wasi/Gemfile",
|
39
|
-
target: "wasm32-unknown-
|
38
|
+
target: "wasm32-unknown-wasip1"
|
40
39
|
},
|
41
40
|
{
|
42
41
|
name: "ruby-3.2-wasm-wasi",
|
43
42
|
ruby_version: "3.2",
|
44
43
|
gemfile: "packages/npm-packages/ruby-wasm-wasi/Gemfile",
|
45
|
-
target: "wasm32-unknown-
|
46
|
-
}
|
44
|
+
target: "wasm32-unknown-wasip1"
|
45
|
+
},
|
46
|
+
{ name: "ruby-wasm-wasi", target: "wasm32-unknown-wasip1" }
|
47
47
|
]
|
48
48
|
|
49
49
|
STANDALONE_PACKAGES = [
|
50
|
-
{ name: "ruby", build: "head-wasm32-unknown-
|
51
|
-
{ name: "irb", build: "head-wasm32-unknown-
|
50
|
+
{ name: "ruby", build: "head-wasm32-unknown-wasip1-full" },
|
51
|
+
{ name: "irb", build: "head-wasm32-unknown-wasip1-full" }
|
52
52
|
]
|
53
53
|
|
54
54
|
LIB_ROOT = File.dirname(__FILE__)
|
data/benchmarks/vm_deep_call.rb
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
#
|
3
3
|
# Example runs
|
4
4
|
# $ ruby vm_deep_call.rb
|
5
|
-
# $ RUBY_EXE="wasmtime run --
|
6
|
-
# $ RUBY_EXE="wasmtime run --env RUBY_FIBER_MACHINE_STACK_SIZE=20971520 --
|
5
|
+
# $ RUBY_EXE="wasmtime run --dir /::/ head-wasm32-unknown-wasi-minimal/usr/local/bin/ruby --" ruby vm_deep_call.rb
|
6
|
+
# $ RUBY_EXE="wasmtime run --env RUBY_FIBER_MACHINE_STACK_SIZE=20971520 --dir /::/ head-wasm32-unknown-wasi-minimal/usr/local/bin/ruby --" ruby vm_deep_call.rb
|
7
7
|
|
8
8
|
def vm_rec n
|
9
9
|
vm_rec n - 1 if n > 0
|
data/docs/cheat_sheet.md
CHANGED
@@ -38,7 +38,7 @@ The easiest way to run Ruby on browser is to use `browser.script.iife.js` script
|
|
38
38
|
|
39
39
|
```html
|
40
40
|
<html>
|
41
|
-
<script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.
|
41
|
+
<script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.1/dist/browser.script.iife.js"></script>
|
42
42
|
<script type="text/ruby">
|
43
43
|
require "js"
|
44
44
|
JS.global[:document].write "Hello, world!"
|
@@ -51,8 +51,8 @@ If you want to control Ruby VM from JavaScript, you can use `@ruby/wasm-wasi` pa
|
|
51
51
|
```html
|
52
52
|
<html>
|
53
53
|
<script type="module">
|
54
|
-
import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.
|
55
|
-
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.
|
54
|
+
import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.5.1/dist/browser/+esm";
|
55
|
+
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.1/dist/ruby+stdlib.wasm");
|
56
56
|
const module = await WebAssembly.compileStreaming(response);
|
57
57
|
const { vm } = await DefaultRubyVM(module);
|
58
58
|
|
@@ -69,11 +69,11 @@ If you want to control Ruby VM from JavaScript, you can use `@ruby/wasm-wasi` pa
|
|
69
69
|
|
70
70
|
```html
|
71
71
|
<html>
|
72
|
-
<script src="https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.
|
72
|
+
<script src="https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.5.1/dist/browser.umd.js"></script>
|
73
73
|
<script>
|
74
74
|
const main = async () => {
|
75
75
|
const { DefaultRubyVM } = window["ruby-wasm-wasi"];
|
76
|
-
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.
|
76
|
+
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.1/dist/ruby+stdlib.wasm");
|
77
77
|
const module = await WebAssembly.compileStreaming(response);
|
78
78
|
const { vm } = await DefaultRubyVM(module);
|
79
79
|
|
@@ -128,7 +128,7 @@ end
|
|
128
128
|
|
129
129
|
```html
|
130
130
|
<html>
|
131
|
-
<script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.
|
131
|
+
<script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.1/dist/browser.script.iife.js"></script>
|
132
132
|
<script type="text/ruby" data-eval="async">
|
133
133
|
require "js"
|
134
134
|
|
@@ -143,8 +143,8 @@ Or using `@ruby/wasm-wasi` package API `RubyVM#evalAsync`:
|
|
143
143
|
```html
|
144
144
|
<html>
|
145
145
|
<script type="module">
|
146
|
-
import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.
|
147
|
-
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.
|
146
|
+
import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.5.1/dist/browser/+esm";
|
147
|
+
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.1/dist/ruby+stdlib.wasm");
|
148
148
|
const module = await WebAssembly.compileStreaming(response);
|
149
149
|
const { vm } = await DefaultRubyVM(module);
|
150
150
|
|
data/ext/ruby_wasm/Cargo.toml
CHANGED
@@ -10,8 +10,9 @@ publish = false
|
|
10
10
|
crate-type = ["cdylib"]
|
11
11
|
|
12
12
|
[dependencies]
|
13
|
-
magnus = "0.6.2"
|
14
|
-
|
15
|
-
|
16
|
-
wasi-
|
17
|
-
|
13
|
+
magnus = { version = "0.6.2", features = ["bytes"] }
|
14
|
+
bytes = "1"
|
15
|
+
wizer = "4.0.0"
|
16
|
+
wasi-vfs-cli = { git = "https://github.com/kateinoigakukun/wasi-vfs/", tag = "0.5.2" }
|
17
|
+
structopt = "0.3.26"
|
18
|
+
wit-component = "0.203.0"
|
data/ext/ruby_wasm/src/lib.rs
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
use std::path::PathBuf;
|
1
|
+
use std::{collections::HashMap, path::PathBuf};
|
2
2
|
|
3
3
|
use magnus::{
|
4
4
|
eval, exception, function, method,
|
@@ -6,12 +6,13 @@ use magnus::{
|
|
6
6
|
value::{self, InnerValue},
|
7
7
|
wrap, Error, ExceptionClass, RModule, Ruby,
|
8
8
|
};
|
9
|
+
use structopt::StructOpt;
|
9
10
|
use wizer::Wizer;
|
10
11
|
|
11
12
|
static RUBY_WASM: value::Lazy<RModule> =
|
12
13
|
value::Lazy::new(|ruby| ruby.define_module("RubyWasmExt").unwrap());
|
13
14
|
|
14
|
-
fn preinit(core_module:
|
15
|
+
fn preinit(core_module: bytes::Bytes) -> Result<bytes::Bytes, Error> {
|
15
16
|
let rbwasm_error = eval("RubyWasmExt::Error")?;
|
16
17
|
let rbwasm_error = ExceptionClass::from_value(rbwasm_error).unwrap();
|
17
18
|
let mut wizer = Wizer::new();
|
@@ -25,6 +26,7 @@ fn preinit(core_module: Vec<u8>) -> Result<Vec<u8>, Error> {
|
|
25
26
|
wizer
|
26
27
|
.run(&core_module)
|
27
28
|
.map_err(|e| Error::new(rbwasm_error, format!("failed to run wizer: {}", e)))
|
29
|
+
.map(|output| output.into())
|
28
30
|
}
|
29
31
|
|
30
32
|
struct WasiVfsInner {
|
@@ -35,22 +37,188 @@ struct WasiVfsInner {
|
|
35
37
|
struct WasiVfs(std::cell::RefCell<WasiVfsInner>);
|
36
38
|
|
37
39
|
impl WasiVfs {
|
40
|
+
fn run_cli(args: Vec<String>) -> Result<(), Error> {
|
41
|
+
wasi_vfs_cli::App::from_iter(args).execute().map_err(|e| {
|
42
|
+
Error::new(
|
43
|
+
exception::standard_error(),
|
44
|
+
format!("failed to run wasi vfs cli: {}", e),
|
45
|
+
)
|
46
|
+
})
|
47
|
+
}
|
48
|
+
|
38
49
|
fn new() -> Self {
|
39
50
|
Self(std::cell::RefCell::new(WasiVfsInner { map_dirs: vec![] }))
|
40
51
|
}
|
41
52
|
|
42
53
|
fn map_dir(&self, guest_dir: String, host_dir: String) {
|
43
|
-
self.0
|
54
|
+
self.0
|
55
|
+
.borrow_mut()
|
56
|
+
.map_dirs
|
57
|
+
.push((guest_dir.into(), host_dir.into()));
|
58
|
+
}
|
59
|
+
|
60
|
+
fn pack(&self, wasm_bytes: bytes::Bytes) -> Result<bytes::Bytes, Error> {
|
61
|
+
let output_bytes = wasi_vfs_cli::pack(&wasm_bytes, self.0.borrow().map_dirs.clone())
|
62
|
+
.map_err(|e| {
|
63
|
+
Error::new(
|
64
|
+
exception::standard_error(),
|
65
|
+
format!("failed to pack wasi vfs: {}", e),
|
66
|
+
)
|
67
|
+
})?;
|
68
|
+
Ok(output_bytes.into())
|
44
69
|
}
|
70
|
+
}
|
45
71
|
|
46
|
-
|
47
|
-
|
72
|
+
#[wrap(class = "RubyWasmExt::ComponentLink")]
|
73
|
+
struct ComponentLink(std::cell::RefCell<Option<wit_component::Linker>>);
|
74
|
+
|
75
|
+
impl ComponentLink {
|
76
|
+
fn new() -> Self {
|
77
|
+
Self(std::cell::RefCell::new(Some(
|
78
|
+
wit_component::Linker::default(),
|
79
|
+
)))
|
80
|
+
}
|
81
|
+
fn linker(
|
82
|
+
&self,
|
83
|
+
body: impl FnOnce(wit_component::Linker) -> Result<wit_component::Linker, Error>,
|
84
|
+
) -> Result<(), Error> {
|
85
|
+
let mut linker = self.0.take().ok_or_else(|| {
|
48
86
|
Error::new(
|
49
87
|
exception::standard_error(),
|
50
|
-
|
88
|
+
"linker is already consumed".to_string(),
|
51
89
|
)
|
52
90
|
})?;
|
53
|
-
|
91
|
+
linker = body(linker)?;
|
92
|
+
self.0.replace(Some(linker));
|
93
|
+
Ok(())
|
94
|
+
}
|
95
|
+
|
96
|
+
fn library(&self, name: String, module: bytes::Bytes, dl_openable: bool) -> Result<(), Error> {
|
97
|
+
self.linker(|linker| {
|
98
|
+
linker.library(&name, &module, dl_openable).map_err(|e| {
|
99
|
+
Error::new(
|
100
|
+
exception::standard_error(),
|
101
|
+
format!("failed to link library: {}", e),
|
102
|
+
)
|
103
|
+
})
|
104
|
+
})
|
105
|
+
}
|
106
|
+
fn adapter(&self, name: String, module: bytes::Bytes) -> Result<(), Error> {
|
107
|
+
self.linker(|linker| {
|
108
|
+
linker.adapter(&name, &module).map_err(|e| {
|
109
|
+
Error::new(
|
110
|
+
exception::standard_error(),
|
111
|
+
format!("failed to link adapter: {}", e),
|
112
|
+
)
|
113
|
+
})
|
114
|
+
})
|
115
|
+
}
|
116
|
+
fn validate(&self, validate: bool) -> Result<(), Error> {
|
117
|
+
self.linker(|linker| Ok(linker.validate(validate)))
|
118
|
+
}
|
119
|
+
fn stack_size(&self, size: u32) -> Result<(), Error> {
|
120
|
+
self.linker(|linker| Ok(linker.stack_size(size)))
|
121
|
+
}
|
122
|
+
fn stub_missing_functions(&self, stub: bool) -> Result<(), Error> {
|
123
|
+
self.linker(|linker| Ok(linker.stub_missing_functions(stub)))
|
124
|
+
}
|
125
|
+
fn use_built_in_libdl(&self, use_libdl: bool) -> Result<(), Error> {
|
126
|
+
self.linker(|linker| Ok(linker.use_built_in_libdl(use_libdl)))
|
127
|
+
}
|
128
|
+
fn encode(&self) -> Result<bytes::Bytes, Error> {
|
129
|
+
// Take the linker out of the cell and consume it
|
130
|
+
let linker = self.0.borrow_mut().take().ok_or_else(|| {
|
131
|
+
Error::new(
|
132
|
+
exception::standard_error(),
|
133
|
+
"linker is already consumed".to_string(),
|
134
|
+
)
|
135
|
+
})?;
|
136
|
+
let encoded = linker.encode().map_err(|e| {
|
137
|
+
Error::new(
|
138
|
+
exception::standard_error(),
|
139
|
+
format!("failed to encode linker: {}", e),
|
140
|
+
)
|
141
|
+
})?;
|
142
|
+
Ok(encoded.into())
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
#[wrap(class = "RubyWasmExt::ComponentEncode")]
|
147
|
+
struct ComponentEncode(std::cell::RefCell<Option<wit_component::ComponentEncoder>>);
|
148
|
+
|
149
|
+
impl ComponentEncode {
|
150
|
+
fn new() -> Self {
|
151
|
+
Self(std::cell::RefCell::new(Some(
|
152
|
+
wit_component::ComponentEncoder::default(),
|
153
|
+
)))
|
154
|
+
}
|
155
|
+
|
156
|
+
fn encoder(
|
157
|
+
&self,
|
158
|
+
body: impl FnOnce(
|
159
|
+
wit_component::ComponentEncoder,
|
160
|
+
) -> Result<wit_component::ComponentEncoder, Error>,
|
161
|
+
) -> Result<(), Error> {
|
162
|
+
let mut encoder = self.0.take().ok_or_else(|| {
|
163
|
+
Error::new(
|
164
|
+
exception::standard_error(),
|
165
|
+
"encoder is already consumed".to_string(),
|
166
|
+
)
|
167
|
+
})?;
|
168
|
+
encoder = body(encoder)?;
|
169
|
+
self.0.replace(Some(encoder));
|
170
|
+
Ok(())
|
171
|
+
}
|
172
|
+
|
173
|
+
fn validate(&self, validate: bool) -> Result<(), Error> {
|
174
|
+
self.encoder(|encoder| Ok(encoder.validate(validate)))
|
175
|
+
}
|
176
|
+
|
177
|
+
fn adapter(&self, name: String, module: bytes::Bytes) -> Result<(), Error> {
|
178
|
+
self.encoder(|encoder| {
|
179
|
+
encoder.adapter(&name, &module).map_err(|e| {
|
180
|
+
Error::new(
|
181
|
+
exception::standard_error(),
|
182
|
+
format!("failed to encode adapter: {}", e),
|
183
|
+
)
|
184
|
+
})
|
185
|
+
})
|
186
|
+
}
|
187
|
+
|
188
|
+
fn module(&self, module: bytes::Bytes) -> Result<(), Error> {
|
189
|
+
self.encoder(|encoder| {
|
190
|
+
encoder.module(&module).map_err(|e| {
|
191
|
+
Error::new(
|
192
|
+
exception::standard_error(),
|
193
|
+
format!("failed to encode module: {}", e),
|
194
|
+
)
|
195
|
+
})
|
196
|
+
})
|
197
|
+
}
|
198
|
+
|
199
|
+
fn realloc_via_memory_grow(&self, realloc: bool) -> Result<(), Error> {
|
200
|
+
self.encoder(|encoder| Ok(encoder.realloc_via_memory_grow(realloc)))
|
201
|
+
}
|
202
|
+
|
203
|
+
fn import_name_map(&self, map: HashMap<String, String>) -> Result<(), Error> {
|
204
|
+
self.encoder(|encoder| Ok(encoder.import_name_map(map)))
|
205
|
+
}
|
206
|
+
|
207
|
+
fn encode(&self) -> Result<bytes::Bytes, Error> {
|
208
|
+
// Take the encoder out of the cell and consume it
|
209
|
+
let encoder = self.0.borrow_mut().take().ok_or_else(|| {
|
210
|
+
Error::new(
|
211
|
+
exception::standard_error(),
|
212
|
+
"encoder is already consumed".to_string(),
|
213
|
+
)
|
214
|
+
})?;
|
215
|
+
let encoded = encoder.encode().map_err(|e| {
|
216
|
+
Error::new(
|
217
|
+
exception::standard_error(),
|
218
|
+
format!("failed to encode component: {}", e),
|
219
|
+
)
|
220
|
+
})?;
|
221
|
+
Ok(encoded.into())
|
54
222
|
}
|
55
223
|
}
|
56
224
|
|
@@ -63,7 +231,40 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
|
|
63
231
|
|
64
232
|
let wasi_vfs = module.define_class("WasiVfs", ruby.class_object())?;
|
65
233
|
wasi_vfs.define_singleton_method("new", function!(WasiVfs::new, 0))?;
|
234
|
+
wasi_vfs.define_singleton_method("run_cli", function!(WasiVfs::run_cli, 1))?;
|
66
235
|
wasi_vfs.define_method("map_dir", method!(WasiVfs::map_dir, 2))?;
|
67
236
|
wasi_vfs.define_method("pack", method!(WasiVfs::pack, 1))?;
|
237
|
+
|
238
|
+
let component_link = module.define_class("ComponentLink", ruby.class_object())?;
|
239
|
+
component_link.define_singleton_method("new", function!(ComponentLink::new, 0))?;
|
240
|
+
component_link.define_method("library", method!(ComponentLink::library, 3))?;
|
241
|
+
component_link.define_method("adapter", method!(ComponentLink::adapter, 2))?;
|
242
|
+
component_link.define_method("validate", method!(ComponentLink::validate, 1))?;
|
243
|
+
component_link.define_method("stack_size", method!(ComponentLink::stack_size, 1))?;
|
244
|
+
component_link.define_method(
|
245
|
+
"stub_missing_functions",
|
246
|
+
method!(ComponentLink::stub_missing_functions, 1),
|
247
|
+
)?;
|
248
|
+
component_link.define_method(
|
249
|
+
"use_built_in_libdl",
|
250
|
+
method!(ComponentLink::use_built_in_libdl, 1),
|
251
|
+
)?;
|
252
|
+
component_link.define_method("encode", method!(ComponentLink::encode, 0))?;
|
253
|
+
|
254
|
+
let component_encode = module.define_class("ComponentEncode", ruby.class_object())?;
|
255
|
+
component_encode.define_singleton_method("new", function!(ComponentEncode::new, 0))?;
|
256
|
+
component_encode.define_method("validate", method!(ComponentEncode::validate, 1))?;
|
257
|
+
component_encode.define_method("adapter", method!(ComponentEncode::adapter, 2))?;
|
258
|
+
component_encode.define_method("module", method!(ComponentEncode::module, 1))?;
|
259
|
+
component_encode.define_method(
|
260
|
+
"realloc_via_memory_grow",
|
261
|
+
method!(ComponentEncode::realloc_via_memory_grow, 1),
|
262
|
+
)?;
|
263
|
+
component_encode.define_method(
|
264
|
+
"import_name_map",
|
265
|
+
method!(ComponentEncode::import_name_map, 1),
|
266
|
+
)?;
|
267
|
+
component_encode.define_method("encode", method!(ComponentEncode::encode, 0))?;
|
268
|
+
|
68
269
|
Ok(())
|
69
270
|
}
|