ruby_wasm 2.5.0 → 2.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +7 -7
- data/Cargo.lock +91 -6
- data/Gemfile +1 -1
- data/README.md +9 -9
- data/Rakefile +9 -7
- data/docs/cheat_sheet.md +8 -8
- data/ext/ruby_wasm/Cargo.toml +3 -1
- data/ext/ruby_wasm/src/lib.rs +198 -8
- data/lib/ruby_wasm/build/executor.rb +4 -0
- data/lib/ruby_wasm/build/product/crossruby.rb +59 -25
- 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 -1
- data/lib/ruby_wasm/build/product/zlib.rb +3 -1
- data/lib/ruby_wasm/build/target.rb +24 -0
- data/lib/ruby_wasm/build/toolchain/wit_bindgen.rb +2 -2
- data/lib/ruby_wasm/build/toolchain.rb +1 -1
- data/lib/ruby_wasm/build.rb +7 -3
- data/lib/ruby_wasm/cli.rb +147 -11
- 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 +199 -5
- data/lib/ruby_wasm/packager/file_system.rb +5 -3
- data/lib/ruby_wasm/packager.rb +22 -82
- data/lib/ruby_wasm/rake_task.rb +1 -0
- data/lib/ruby_wasm/version.rb +1 -1
- data/lib/ruby_wasm.rb +2 -0
- data/package-lock.json +5571 -7015
- data/package.json +3 -3
- data/rakelib/check.rake +23 -10
- data/rakelib/ci.rake +3 -3
- data/rakelib/packaging.rake +44 -15
- data/sig/ruby_wasm/build.rbs +38 -28
- data/sig/ruby_wasm/cli.rbs +27 -3
- data/sig/ruby_wasm/ext.rbs +25 -2
- data/sig/ruby_wasm/feature_set.rbs +12 -0
- data/sig/ruby_wasm/packager.rbs +44 -7
- metadata +9 -10
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8c30db752d99a73771fdaf73c72a139b22757ba34d0cfd20b6b319eb2dae41f
|
4
|
+
data.tar.gz: c00f1796d9e1b2008c6e08690f41e4d8037d43732ce6894480f2ab34bee6439d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e78b6ceb43db9a27b9928aa048b1c4b0ab647053e6205ca68e9d5b1cdb2bee685828e7716ff87a6553a8216d6fe60682af9a76640cb2aab56c8c9f74ebdd5ef
|
7
|
+
data.tar.gz: 6fe16881179f2cfee7c54c24d8d963a774d041e5c225f1cad07300c33ecb04d2cccf7c95b7748cc1a1b48685c1305da781752a7cff27fec5d9ce54482c52b853
|
data/CONTRIBUTING.md
CHANGED
@@ -21,7 +21,7 @@ $ rake --tasks
|
|
21
21
|
$ rake build:download_prebuilt
|
22
22
|
|
23
23
|
# Build Ruby (if you need to build Ruby by yourself)
|
24
|
-
$ rake build:head-wasm32-unknown-
|
24
|
+
$ rake build:head-wasm32-unknown-wasip1-full
|
25
25
|
|
26
26
|
# Build npm package
|
27
27
|
$ rake npm:ruby-head-wasm-wasi
|
@@ -48,15 +48,15 @@ To select a build profile, see [profiles section in README](https://github.com/r
|
|
48
48
|
|
49
49
|
```console
|
50
50
|
# Build only a specific combination of ruby version, profile, and target
|
51
|
-
$ rake build:head-wasm32-unknown-
|
51
|
+
$ rake build:head-wasm32-unknown-wasip1-full
|
52
52
|
# Clean up the build directory
|
53
|
-
$ rake build:head-wasm32-unknown-
|
53
|
+
$ rake build:head-wasm32-unknown-wasip1-full:clean
|
54
54
|
# Force to re-execute "make install"
|
55
|
-
$ rake build:head-wasm32-unknown-
|
55
|
+
$ rake build:head-wasm32-unknown-wasip1-full:remake
|
56
56
|
|
57
57
|
# Output is in the `rubies` directory
|
58
|
-
$ tree -L 3 rubies/head-wasm32-unknown-
|
59
|
-
rubies/head-wasm32-unknown-
|
58
|
+
$ tree -L 3 rubies/head-wasm32-unknown-wasip1-full
|
59
|
+
rubies/head-wasm32-unknown-wasip1-full/
|
60
60
|
├── usr
|
61
61
|
│ └── local
|
62
62
|
│ ├── bin
|
@@ -124,5 +124,5 @@ $ npm install --save @ruby/wasm-wasi@latest
|
|
124
124
|
# or if you want the nightly snapshot
|
125
125
|
$ npm install --save @ruby/wasm-wasi@next
|
126
126
|
# or you can specify the exact snapshot version
|
127
|
-
$ npm install --save @ruby/wasm-wasi@2.5.
|
127
|
+
$ npm install --save @ruby/wasm-wasi@2.5.2-2024-05-04-a
|
128
128
|
```
|
data/Cargo.lock
CHANGED
@@ -1012,6 +1012,7 @@ version = "0.6.2"
|
|
1012
1012
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
1013
1013
|
checksum = "4778544796676e8428e9c622460ebf284bea52d8b10db3aeb449d8b5e61b3a13"
|
1014
1014
|
dependencies = [
|
1015
|
+
"bytes",
|
1015
1016
|
"magnus-macros",
|
1016
1017
|
"rb-sys",
|
1017
1018
|
"rb-sys-env",
|
@@ -1268,18 +1269,18 @@ dependencies = [
|
|
1268
1269
|
|
1269
1270
|
[[package]]
|
1270
1271
|
name = "rb-sys"
|
1271
|
-
version = "0.9.
|
1272
|
+
version = "0.9.97"
|
1272
1273
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
1273
|
-
checksum = "
|
1274
|
+
checksum = "47d30bcad206b51f2f66121190ca678dce1fdf3a2eae0ac5d838d1818b19bdf5"
|
1274
1275
|
dependencies = [
|
1275
1276
|
"rb-sys-build",
|
1276
1277
|
]
|
1277
1278
|
|
1278
1279
|
[[package]]
|
1279
1280
|
name = "rb-sys-build"
|
1280
|
-
version = "0.9.
|
1281
|
+
version = "0.9.97"
|
1281
1282
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
1282
|
-
checksum = "
|
1283
|
+
checksum = "3cbd92f281615f3c2dcb9dcb0f0576624752afbf9a7f99173b37c4b55b62dd8a"
|
1283
1284
|
dependencies = [
|
1284
1285
|
"bindgen",
|
1285
1286
|
"lazy_static",
|
@@ -1362,9 +1363,11 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
|
1362
1363
|
name = "ruby_wasm"
|
1363
1364
|
version = "0.0.0"
|
1364
1365
|
dependencies = [
|
1366
|
+
"bytes",
|
1365
1367
|
"magnus",
|
1366
1368
|
"structopt",
|
1367
1369
|
"wasi-vfs-cli",
|
1370
|
+
"wit-component",
|
1368
1371
|
"wizer",
|
1369
1372
|
]
|
1370
1373
|
|
@@ -1498,6 +1501,15 @@ dependencies = [
|
|
1498
1501
|
"windows-sys 0.48.0",
|
1499
1502
|
]
|
1500
1503
|
|
1504
|
+
[[package]]
|
1505
|
+
name = "spdx"
|
1506
|
+
version = "0.10.4"
|
1507
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
1508
|
+
checksum = "29ef1a0fa1e39ac22972c8db23ff89aea700ab96aa87114e1fb55937a631a0c9"
|
1509
|
+
dependencies = [
|
1510
|
+
"smallvec",
|
1511
|
+
]
|
1512
|
+
|
1501
1513
|
[[package]]
|
1502
1514
|
name = "sptr"
|
1503
1515
|
version = "0.3.2"
|
@@ -1892,6 +1904,31 @@ dependencies = [
|
|
1892
1904
|
"leb128",
|
1893
1905
|
]
|
1894
1906
|
|
1907
|
+
[[package]]
|
1908
|
+
name = "wasm-encoder"
|
1909
|
+
version = "0.203.0"
|
1910
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
1911
|
+
checksum = "87e3b46a0d9d9143d57aa926c42e2af284b5cb8f0c7b71079afc7a6fca42db50"
|
1912
|
+
dependencies = [
|
1913
|
+
"leb128",
|
1914
|
+
]
|
1915
|
+
|
1916
|
+
[[package]]
|
1917
|
+
name = "wasm-metadata"
|
1918
|
+
version = "0.203.0"
|
1919
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
1920
|
+
checksum = "19fbd9b7017bdb3ceb63503a18d1aa7b0d026e18ce659d40b93bd9a15391424f"
|
1921
|
+
dependencies = [
|
1922
|
+
"anyhow",
|
1923
|
+
"indexmap 2.1.0",
|
1924
|
+
"serde",
|
1925
|
+
"serde_derive",
|
1926
|
+
"serde_json",
|
1927
|
+
"spdx",
|
1928
|
+
"wasm-encoder 0.203.0",
|
1929
|
+
"wasmparser 0.203.0",
|
1930
|
+
]
|
1931
|
+
|
1895
1932
|
[[package]]
|
1896
1933
|
name = "wasmparser"
|
1897
1934
|
version = "0.106.0"
|
@@ -1912,6 +1949,17 @@ dependencies = [
|
|
1912
1949
|
"semver",
|
1913
1950
|
]
|
1914
1951
|
|
1952
|
+
[[package]]
|
1953
|
+
name = "wasmparser"
|
1954
|
+
version = "0.203.0"
|
1955
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
1956
|
+
checksum = "1b473b35fff082e8c8377f4e2c8d48075e562aa051e48a02229bdcafbf349d37"
|
1957
|
+
dependencies = [
|
1958
|
+
"bitflags 2.4.1",
|
1959
|
+
"indexmap 2.1.0",
|
1960
|
+
"semver",
|
1961
|
+
]
|
1962
|
+
|
1915
1963
|
[[package]]
|
1916
1964
|
name = "wasmprinter"
|
1917
1965
|
version = "0.2.75"
|
@@ -2002,7 +2050,7 @@ dependencies = [
|
|
2002
2050
|
"syn 2.0.48",
|
2003
2051
|
"wasmtime-component-util",
|
2004
2052
|
"wasmtime-wit-bindgen",
|
2005
|
-
"wit-parser",
|
2053
|
+
"wit-parser 0.13.0",
|
2006
2054
|
]
|
2007
2055
|
|
2008
2056
|
[[package]]
|
@@ -2255,7 +2303,7 @@ dependencies = [
|
|
2255
2303
|
"anyhow",
|
2256
2304
|
"heck 0.4.1",
|
2257
2305
|
"indexmap 2.1.0",
|
2258
|
-
"wit-parser",
|
2306
|
+
"wit-parser 0.13.0",
|
2259
2307
|
]
|
2260
2308
|
|
2261
2309
|
[[package]]
|
@@ -2525,6 +2573,25 @@ dependencies = [
|
|
2525
2573
|
"windows-sys 0.52.0",
|
2526
2574
|
]
|
2527
2575
|
|
2576
|
+
[[package]]
|
2577
|
+
name = "wit-component"
|
2578
|
+
version = "0.203.0"
|
2579
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
2580
|
+
checksum = "379c4e193d37b3e2c808e99515c2a91dc19e7b3b160adfbb374463875375d6ff"
|
2581
|
+
dependencies = [
|
2582
|
+
"anyhow",
|
2583
|
+
"bitflags 2.4.1",
|
2584
|
+
"indexmap 2.1.0",
|
2585
|
+
"log",
|
2586
|
+
"serde",
|
2587
|
+
"serde_derive",
|
2588
|
+
"serde_json",
|
2589
|
+
"wasm-encoder 0.203.0",
|
2590
|
+
"wasm-metadata",
|
2591
|
+
"wasmparser 0.203.0",
|
2592
|
+
"wit-parser 0.203.0",
|
2593
|
+
]
|
2594
|
+
|
2528
2595
|
[[package]]
|
2529
2596
|
name = "wit-parser"
|
2530
2597
|
version = "0.13.0"
|
@@ -2542,6 +2609,24 @@ dependencies = [
|
|
2542
2609
|
"unicode-xid",
|
2543
2610
|
]
|
2544
2611
|
|
2612
|
+
[[package]]
|
2613
|
+
name = "wit-parser"
|
2614
|
+
version = "0.203.0"
|
2615
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
2616
|
+
checksum = "3f547f9154c0fbd020c81c348d703b549bafd16ea68b15927acb5c890467e734"
|
2617
|
+
dependencies = [
|
2618
|
+
"anyhow",
|
2619
|
+
"id-arena",
|
2620
|
+
"indexmap 2.1.0",
|
2621
|
+
"log",
|
2622
|
+
"semver",
|
2623
|
+
"serde",
|
2624
|
+
"serde_derive",
|
2625
|
+
"serde_json",
|
2626
|
+
"unicode-xid",
|
2627
|
+
"wasmparser 0.203.0",
|
2628
|
+
]
|
2629
|
+
|
2545
2630
|
[[package]]
|
2546
2631
|
name = "witx"
|
2547
2632
|
version = "0.9.1"
|
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.5.
|
26
|
+
<script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.2/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>
|
@@ -40,18 +40,18 @@ Dependencies: [wasmtime](https://github.com/bytecodealliance/wasmtime)
|
|
40
40
|
```console
|
41
41
|
$ gem install ruby_wasm
|
42
42
|
# Download a prebuilt Ruby release
|
43
|
-
$ curl -LO https://github.com/ruby/ruby.wasm/releases/latest/download/ruby-3.3-wasm32-unknown-
|
44
|
-
$ tar xfz ruby-3.3-wasm32-unknown-
|
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
|
45
45
|
|
46
46
|
# Extract ruby binary not to pack itself
|
47
|
-
$ mv ruby-3.3-wasm32-unknown-
|
47
|
+
$ mv ruby-3.3-wasm32-unknown-wasip1-full/usr/local/bin/ruby ruby.wasm
|
48
48
|
|
49
49
|
# Put your app code
|
50
50
|
$ mkdir src
|
51
51
|
$ echo "puts 'Hello'" > src/my_app.rb
|
52
52
|
|
53
53
|
# Pack the whole directory under /usr and your app dir
|
54
|
-
$ rbwasm pack ruby.wasm --dir ./src::/src --dir ./ruby-3.3-wasm32-unknown-
|
54
|
+
$ rbwasm pack ruby.wasm --dir ./src::/src --dir ./ruby-3.3-wasm32-unknown-wasip1-full/usr::/usr -o my-ruby-app.wasm
|
55
55
|
|
56
56
|
# Run the packed scripts
|
57
57
|
$ wasmtime my-ruby-app.wasm /src/my_app.rb
|
@@ -110,8 +110,8 @@ A _build_ is a combination of ruby version, _profile_, and _target_.
|
|
110
110
|
</thead>
|
111
111
|
<tbody>
|
112
112
|
<tr>
|
113
|
-
<td><code>wasm32-unknown-
|
114
|
-
<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>
|
115
115
|
</tr>
|
116
116
|
<tr>
|
117
117
|
<td><code>wasm32-unknown-emscripten</code></td>
|
data/Rakefile
CHANGED
@@ -7,6 +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
|
+
require "ruby_wasm/cli"
|
10
11
|
|
11
12
|
BUILD_SOURCES = %w[3.3 3.2 head]
|
12
13
|
BUILD_PROFILES = %w[full minimal]
|
@@ -14,7 +15,7 @@ BUILD_PROFILES = %w[full minimal]
|
|
14
15
|
BUILDS =
|
15
16
|
BUILD_SOURCES
|
16
17
|
.product(BUILD_PROFILES)
|
17
|
-
.map { |src, profile| [src, "wasm32-unknown-
|
18
|
+
.map { |src, profile| [src, "wasm32-unknown-wasip1", profile] } +
|
18
19
|
BUILD_SOURCES.map { |src| [src, "wasm32-unknown-emscripten", "full"] }
|
19
20
|
|
20
21
|
NPM_PACKAGES = [
|
@@ -28,26 +29,27 @@ NPM_PACKAGES = [
|
|
28
29
|
name: "ruby-head-wasm-wasi",
|
29
30
|
ruby_version: "head",
|
30
31
|
gemfile: "packages/npm-packages/ruby-wasm-wasi/Gemfile",
|
31
|
-
target: "wasm32-unknown-
|
32
|
+
target: "wasm32-unknown-wasip1",
|
33
|
+
enable_component_model: true,
|
32
34
|
},
|
33
35
|
{
|
34
36
|
name: "ruby-3.3-wasm-wasi",
|
35
37
|
ruby_version: "3.3",
|
36
38
|
gemfile: "packages/npm-packages/ruby-wasm-wasi/Gemfile",
|
37
|
-
target: "wasm32-unknown-
|
39
|
+
target: "wasm32-unknown-wasip1"
|
38
40
|
},
|
39
41
|
{
|
40
42
|
name: "ruby-3.2-wasm-wasi",
|
41
43
|
ruby_version: "3.2",
|
42
44
|
gemfile: "packages/npm-packages/ruby-wasm-wasi/Gemfile",
|
43
|
-
target: "wasm32-unknown-
|
45
|
+
target: "wasm32-unknown-wasip1"
|
44
46
|
},
|
45
|
-
{ name: "ruby-wasm-wasi", target: "wasm32-unknown-
|
47
|
+
{ name: "ruby-wasm-wasi", target: "wasm32-unknown-wasip1" }
|
46
48
|
]
|
47
49
|
|
48
50
|
STANDALONE_PACKAGES = [
|
49
|
-
{ name: "ruby", build: "head-wasm32-unknown-
|
50
|
-
{ name: "irb", build: "head-wasm32-unknown-
|
51
|
+
{ name: "ruby", build: "head-wasm32-unknown-wasip1-full" },
|
52
|
+
{ name: "irb", build: "head-wasm32-unknown-wasip1-full" }
|
51
53
|
]
|
52
54
|
|
53
55
|
LIB_ROOT = File.dirname(__FILE__)
|
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.5.
|
41
|
+
<script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.2/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.5.
|
55
|
-
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.
|
54
|
+
import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.5.2/dist/browser/+esm";
|
55
|
+
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.2/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.5.
|
72
|
+
<script src="https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.5.2/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.5.
|
76
|
+
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.2/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.5.
|
131
|
+
<script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.2/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.5.
|
147
|
-
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.
|
146
|
+
import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.5.2/dist/browser/+esm";
|
147
|
+
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.2/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,7 +10,9 @@ publish = false
|
|
10
10
|
crate-type = ["cdylib"]
|
11
11
|
|
12
12
|
[dependencies]
|
13
|
-
magnus = "0.6.2"
|
13
|
+
magnus = { version = "0.6.2", features = ["bytes"] }
|
14
|
+
bytes = "1"
|
14
15
|
wizer = "4.0.0"
|
15
16
|
wasi-vfs-cli = { git = "https://github.com/kateinoigakukun/wasi-vfs/", tag = "0.5.2" }
|
16
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,13 +6,13 @@ use magnus::{
|
|
6
6
|
value::{self, InnerValue},
|
7
7
|
wrap, Error, ExceptionClass, RModule, Ruby,
|
8
8
|
};
|
9
|
-
use wizer::Wizer;
|
10
9
|
use structopt::StructOpt;
|
10
|
+
use wizer::Wizer;
|
11
11
|
|
12
12
|
static RUBY_WASM: value::Lazy<RModule> =
|
13
13
|
value::Lazy::new(|ruby| ruby.define_module("RubyWasmExt").unwrap());
|
14
14
|
|
15
|
-
fn preinit(core_module:
|
15
|
+
fn preinit(core_module: bytes::Bytes) -> Result<bytes::Bytes, Error> {
|
16
16
|
let rbwasm_error = eval("RubyWasmExt::Error")?;
|
17
17
|
let rbwasm_error = ExceptionClass::from_value(rbwasm_error).unwrap();
|
18
18
|
let mut wizer = Wizer::new();
|
@@ -26,6 +26,7 @@ fn preinit(core_module: Vec<u8>) -> Result<Vec<u8>, Error> {
|
|
26
26
|
wizer
|
27
27
|
.run(&core_module)
|
28
28
|
.map_err(|e| Error::new(rbwasm_error, format!("failed to run wizer: {}", e)))
|
29
|
+
.map(|output| output.into())
|
29
30
|
}
|
30
31
|
|
31
32
|
struct WasiVfsInner {
|
@@ -50,17 +51,174 @@ impl WasiVfs {
|
|
50
51
|
}
|
51
52
|
|
52
53
|
fn map_dir(&self, guest_dir: String, host_dir: String) {
|
53
|
-
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())
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
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(|| {
|
86
|
+
Error::new(
|
87
|
+
exception::standard_error(),
|
88
|
+
"linker is already consumed".to_string(),
|
89
|
+
)
|
90
|
+
})?;
|
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
|
+
)))
|
54
154
|
}
|
55
155
|
|
56
|
-
fn
|
57
|
-
|
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(|| {
|
58
163
|
Error::new(
|
59
164
|
exception::standard_error(),
|
60
|
-
|
165
|
+
"encoder is already consumed".to_string(),
|
61
166
|
)
|
62
167
|
})?;
|
63
|
-
|
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())
|
64
222
|
}
|
65
223
|
}
|
66
224
|
|
@@ -76,5 +234,37 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
|
|
76
234
|
wasi_vfs.define_singleton_method("run_cli", function!(WasiVfs::run_cli, 1))?;
|
77
235
|
wasi_vfs.define_method("map_dir", method!(WasiVfs::map_dir, 2))?;
|
78
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
|
+
|
79
269
|
Ok(())
|
80
270
|
}
|