Skip to content

Commit 0941e07

Browse files
committed
Refactor the CRubyWASI engine runner
1 parent 931f6b1 commit 0941e07

File tree

3 files changed

+72
-55
lines changed

3 files changed

+72
-55
lines changed

app/ruby_engine/cruby_wasi.rb

Lines changed: 71 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
1+
# await: *await*
2+
3+
require 'await'
4+
15
class RubyEngine
26
class CRubyWASI < RubyEngine
7+
REQUIRED_SCRIPTS = [
8+
{
9+
src: "https://cdn.jsdelivr.net/npm/ruby-wasm-wasi@0.1.2/dist/index.umd.js",
10+
integrity: "sha256-cPmKu5S3jkz5j0NnceapOfiWkzhBQqiBovOLjeYXwA0=",
11+
crossorigin: "anonymous"
12+
},
13+
{
14+
src: "https://cdn.jsdelivr.net/npm/@wasmer/wasmfs@0.12.0/lib/index.iife.js",
15+
integrity: "sha256-sOd4ekxVsN4PXhR+cn/4uNAxeQOJRcsaW5qalYfvkTw=",
16+
crossorigin: "anonymous"
17+
},
18+
{
19+
src: "https://cdn.jsdelivr.net/npm/@wasmer/wasi@0.12.0/lib/index.iife.js",
20+
integrity: "sha256-FslFp/Vq4bDf2GXu+9QyBEDLtEWO3fkMjpyOaJMHJT8=",
21+
crossorigin: "anonymous"
22+
}
23+
]
24+
325
def initialize(ruby_wasm_url, version)
426
@ruby_wasm_url = ruby_wasm_url
527
@version = version
@@ -13,53 +35,63 @@ def engine_id
1335
"cruby-#{@version}"
1436
end
1537

38+
# Below functions will be compiled as async functions
39+
def self.inject_scripts
40+
@injected ||= begin
41+
REQUIRED_SCRIPTS.map do |script|
42+
promise = PromiseV2.new
43+
script = $document.create_element("script", attrs: script)
44+
script.on("load") { promise.resolve }
45+
script.on("error") { promise.reject(StandardError.new("failed to load #{script[:src]}")) }
46+
$document.head << script
47+
promise
48+
end.each_await(&:itself)
49+
true
50+
end
51+
end
52+
1653
def wasm_module
17-
return @module if @module
18-
%x{
19-
#{@module} = (async function() {
20-
const response = await fetch(#{@ruby_wasm_url});
21-
const buffer = await response.arrayBuffer();
22-
return await WebAssembly.compile(buffer);
23-
})();
24-
}
25-
@module
54+
@module ||= begin
55+
response = `fetch(#{@ruby_wasm_url})`.await
56+
buffer = `response.arrayBuffer()`.await
57+
`WebAssembly.compile(buffer)`.await
58+
end
2659
end
2760

2861
def run(source, writer)
29-
%x{
30-
async function instantiateVM() {
31-
const $WASI = window["WASI"].WASI;
32-
const $WasmFs = window["WasmFs"].WasmFs;
33-
const $RubyVM = window["ruby-wasm-wasi"].RubyVM;
62+
CRubyWASI.inject_scripts.await
3463

35-
const wasmFs = new $WasmFs();
36-
const originalWriteSync = wasmFs.fs.writeSync.bind(wasmFs.fs);
37-
const textDecoder = new TextDecoder("utf-8");
38-
wasmFs.fs.writeSync = (fd, buffer, offset, length, position) => {
39-
const text = textDecoder.decode(buffer);
40-
if (fd == 1 || fd == 2) {
41-
#{writer.print_to_output(`text`, "")};
42-
}
43-
return originalWriteSync(fd, buffer, offset, length, position);
44-
};
64+
%x{
65+
const $WASI = window["WASI"].WASI;
66+
const $WasmFs = window["WasmFs"].WasmFs;
67+
const $RubyVM = window["ruby-wasm-wasi"].RubyVM;
4568
46-
const vm = new $RubyVM();
47-
const wasi = new $WASI({
48-
bindings: { ...$WASI.defaultBindings, fs: wasmFs.fs },
49-
});
50-
const imports = { wasi_snapshot_preview1: wasi.wasiImport };
51-
vm.addToImports(imports);
52-
const wasmInstance = await WebAssembly.instantiate(await #{wasm_module}, imports);
53-
await vm.setInstance(wasmInstance);
54-
wasi.setMemory(wasmInstance.exports.memory);
55-
vm.initialize();
56-
return vm;
57-
}
69+
const wasmFs = new $WasmFs();
70+
const originalWriteSync = wasmFs.fs.writeSync.bind(wasmFs.fs);
71+
const textDecoder = new TextDecoder("utf-8");
72+
wasmFs.fs.writeSync = (fd, buffer, offset, length, position) => {
73+
const text = textDecoder.decode(buffer);
74+
if (fd == 1 || fd == 2) {
75+
#{writer.print_to_output(`text`, "")};
76+
}
77+
return originalWriteSync(fd, buffer, offset, length, position);
78+
};
5879
59-
instantiateVM()
60-
.then((vm) => { #{yield `vm.eval(source).toString()`} })
61-
.catch((err) => { #{writer.log_error(`err`)} })
80+
const vm = new $RubyVM();
81+
const wasi = new $WASI({
82+
bindings: { ...$WASI.defaultBindings, fs: wasmFs.fs },
83+
});
84+
const imports = { wasi_snapshot_preview1: wasi.wasiImport };
85+
vm.addToImports(imports);
86+
const wasmInstance = await WebAssembly.instantiate(#{wasm_module.await}, imports);
87+
await vm.setInstance(wasmInstance);
88+
wasi.setMemory(wasmInstance.exports.memory);
89+
vm.initialize();
6290
}
91+
92+
yield `vm.eval(source).toString()`
93+
rescue JS::Error => err
94+
writer.log_error(err)
6395
end
6496
end
6597
end

app/ruby_engine/opal.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
class RubyEngine
22
class Opal < RubyEngine
33
def name
4-
"Opal #{Opal::VERSION}"
4+
"Opal #{::Opal::VERSION}"
55
end
66

77
def engine_id

source/layouts/layout.html.erb

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,6 @@
4141
integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13"
4242
crossorigin="anonymous"
4343
></script>
44-
<script
45-
src="https://cdn.jsdelivr.net/npm/ruby-wasm-wasi@0.1.2/dist/index.umd.js"
46-
integrity="sha256-cPmKu5S3jkz5j0NnceapOfiWkzhBQqiBovOLjeYXwA0="
47-
crossorigin="anonymous"
48-
></script>
49-
<script
50-
src="https://cdn.jsdelivr.net/npm/@wasmer/wasmfs@0.12.0/lib/index.iife.js"
51-
integrity="sha256-sOd4ekxVsN4PXhR+cn/4uNAxeQOJRcsaW5qalYfvkTw="
52-
crossorigin="anonymous"
53-
></script>
54-
<script
55-
src="https://cdn.jsdelivr.net/npm/@wasmer/wasi@0.12.0/lib/index.iife.js"
56-
integrity="sha256-FslFp/Vq4bDf2GXu+9QyBEDLtEWO3fkMjpyOaJMHJT8="
57-
crossorigin="anonymous"
58-
></script>
5944
<%= javascript_include_tag "vendor/codemirror-compressed-4.8" %>
6045
<%= javascript_include_tag "application" %>
6146
</head>

0 commit comments

Comments
 (0)