ruby_wasm 2.5.0 → 2.5.2

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +7 -7
  3. data/Cargo.lock +91 -6
  4. data/Gemfile +1 -1
  5. data/README.md +9 -9
  6. data/Rakefile +9 -7
  7. data/docs/cheat_sheet.md +8 -8
  8. data/ext/ruby_wasm/Cargo.toml +3 -1
  9. data/ext/ruby_wasm/src/lib.rs +198 -8
  10. data/lib/ruby_wasm/build/executor.rb +4 -0
  11. data/lib/ruby_wasm/build/product/crossruby.rb +59 -25
  12. data/lib/ruby_wasm/build/product/libyaml.rb +5 -3
  13. data/lib/ruby_wasm/build/product/openssl.rb +7 -2
  14. data/lib/ruby_wasm/build/product/product.rb +3 -3
  15. data/lib/ruby_wasm/build/product/ruby_source.rb +3 -3
  16. data/lib/ruby_wasm/build/product/wasi_vfs.rb +1 -1
  17. data/lib/ruby_wasm/build/product/zlib.rb +3 -1
  18. data/lib/ruby_wasm/build/target.rb +24 -0
  19. data/lib/ruby_wasm/build/toolchain/wit_bindgen.rb +2 -2
  20. data/lib/ruby_wasm/build/toolchain.rb +1 -1
  21. data/lib/ruby_wasm/build.rb +7 -3
  22. data/lib/ruby_wasm/cli.rb +147 -11
  23. data/lib/ruby_wasm/feature_set.rb +30 -0
  24. data/lib/ruby_wasm/packager/component_adapter/wasi_snapshot_preview1.command.wasm +0 -0
  25. data/lib/ruby_wasm/packager/component_adapter/wasi_snapshot_preview1.reactor.wasm +0 -0
  26. data/lib/ruby_wasm/packager/component_adapter.rb +14 -0
  27. data/lib/ruby_wasm/packager/core.rb +199 -5
  28. data/lib/ruby_wasm/packager/file_system.rb +5 -3
  29. data/lib/ruby_wasm/packager.rb +22 -82
  30. data/lib/ruby_wasm/rake_task.rb +1 -0
  31. data/lib/ruby_wasm/version.rb +1 -1
  32. data/lib/ruby_wasm.rb +2 -0
  33. data/package-lock.json +5571 -7015
  34. data/package.json +3 -3
  35. data/rakelib/check.rake +23 -10
  36. data/rakelib/ci.rake +3 -3
  37. data/rakelib/packaging.rake +44 -15
  38. data/sig/ruby_wasm/build.rbs +38 -28
  39. data/sig/ruby_wasm/cli.rbs +27 -3
  40. data/sig/ruby_wasm/ext.rbs +25 -2
  41. data/sig/ruby_wasm/feature_set.rbs +12 -0
  42. data/sig/ruby_wasm/packager.rbs +44 -7
  43. metadata +9 -10
  44. data/builders/wasm32-unknown-emscripten/Dockerfile +0 -43
  45. data/builders/wasm32-unknown-emscripten/entrypoint.sh +0 -7
  46. data/builders/wasm32-unknown-wasi/Dockerfile +0 -47
  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: f42f03a6e5dcd06b68414f462b48a22402e1944e5535342f3d3b707697ffff42
4
- data.tar.gz: f685a3c61822ab104266c30e1646384a0e5450c9b2eab24d84ad565b03c7b192
3
+ metadata.gz: a8c30db752d99a73771fdaf73c72a139b22757ba34d0cfd20b6b319eb2dae41f
4
+ data.tar.gz: c00f1796d9e1b2008c6e08690f41e4d8037d43732ce6894480f2ab34bee6439d
5
5
  SHA512:
6
- metadata.gz: 96dfec4b5cb068578c121106228bf646246fca5d28b9b7fa94d47a8668bd9ead185cbc29e9f002fd25c302132970bd509ffa27dce3ee967a2c8ea203d6f3df50
7
- data.tar.gz: adbaf753357914c4b25791f39915a62863f61fc062903f21037ce95c8a075b45c14228aa08acfc81ca69fd994a1b473b7fcaf219fad145b4a7cff238b240895e
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-wasi-full
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-wasi-full
51
+ $ rake build:head-wasm32-unknown-wasip1-full
52
52
  # Clean up the build directory
53
- $ rake build:head-wasm32-unknown-wasi-full:clean
53
+ $ rake build:head-wasm32-unknown-wasip1-full:clean
54
54
  # Force to re-execute "make install"
55
- $ rake build:head-wasm32-unknown-wasi-full:remake
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-wasi-full
59
- rubies/head-wasm32-unknown-wasi-full/
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.0-2024-01-28-a
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.86"
1272
+ version = "0.9.97"
1272
1273
  source = "registry+https://github.com/rust-lang/crates.io-index"
1273
- checksum = "7285f2a7b92f58ab198e3fd59a71d2861478f9c4642f41e83582385818941697"
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.86"
1281
+ version = "0.9.97"
1281
1282
  source = "registry+https://github.com/rust-lang/crates.io-index"
1282
- checksum = "71583945f94dabb6c0dfa63f1b71e929c1901e1e288ef3739ab8bed3b7069550"
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
@@ -7,7 +7,7 @@ gemspec
7
7
  group :development do
8
8
  gem "rake"
9
9
  gem "rake-compiler"
10
- gem "rb_sys", "0.9.85"
10
+ gem "rb_sys", "0.9.97"
11
11
  end
12
12
 
13
13
  group :check do
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.0/dist/browser.script.iife.js"></script>
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 # => Hello, world! (printed to the browser console)
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-wasi-full.tar.gz
44
- $ tar xfz ruby-3.3-wasm32-unknown-wasi-full.tar.gz
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-wasi-full/usr/local/bin/ruby ruby.wasm
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-wasi-full/usr::/usr -o my-ruby-app.wasm
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-wasi</code></td>
114
- <td>Targeting WASI-compatible environments (e.g. Node.js, browsers with polyfill, <a href="https://github.com/bytecodealliance/wasmtime">wasmtime</a>, and so on)</td>
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-wasi", profile] } +
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-wasi"
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-wasi"
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-wasi"
45
+ target: "wasm32-unknown-wasip1"
44
46
  },
45
- { name: "ruby-wasm-wasi", target: "wasm32-unknown-wasi" }
47
+ { name: "ruby-wasm-wasi", target: "wasm32-unknown-wasip1" }
46
48
  ]
47
49
 
48
50
  STANDALONE_PACKAGES = [
49
- { name: "ruby", build: "head-wasm32-unknown-wasi-full" },
50
- { name: "irb", build: "head-wasm32-unknown-wasi-full" }
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.0/dist/browser.script.iife.js"></script>
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.0/dist/browser/+esm";
55
- const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.0/dist/ruby+stdlib.wasm");
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.0/dist/browser.umd.js"></script>
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.0/dist/ruby+stdlib.wasm");
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.0/dist/browser.script.iife.js"></script>
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.0/dist/browser/+esm";
147
- const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.0/dist/ruby+stdlib.wasm");
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
 
@@ -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"
@@ -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: Vec<u8>) -> Result<Vec<u8>, Error> {
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.borrow_mut().map_dirs.push((guest_dir.into(), host_dir.into()));
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 pack(&self, wasm_bytes: Vec<u8>) -> Result<Vec<u8>, Error> {
57
- let output_bytes = wasi_vfs_cli::pack(&wasm_bytes, self.0.borrow().map_dirs.clone()).map_err(|e| {
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
- format!("failed to pack wasi vfs: {}", e),
165
+ "encoder is already consumed".to_string(),
61
166
  )
62
167
  })?;
63
- Ok(output_bytes)
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
  }
@@ -128,6 +128,10 @@ module RubyWasm
128
128
  FileUtils.mkdir_p(list)
129
129
  end
130
130
 
131
+ def ln_s(src, dest)
132
+ FileUtils.ln_s(src, dest)
133
+ end
134
+
131
135
  def write(path, data)
132
136
  File.write(path, data)
133
137
  end