Skip to content

Commit 9f47f92

Browse files
committed
Add loading indication
1 parent 012dc1f commit 9f47f92

5 files changed

Lines changed: 86 additions & 45 deletions

File tree

app/ruby_engine.rb

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,31 @@
1+
# await: true
2+
13
# require 'ruby_engine/opal'
24
require 'ruby_engine/opal_webworker'
35
require 'ruby_engine/cruby_wasi'
46

57
class RubyEngine
6-
def run(source, instance)
8+
def run(source)
79
raise NotImplementedError
810
end
911

12+
def run_with_writer(source, writer, &block)
13+
@writer = writer
14+
@dots = 0
15+
run(source, &block)
16+
end
17+
18+
# Display a message while a block is being executed
19+
def loading(part = nil)
20+
# Debug option:
21+
# @writer.output = "*** Loading... #{"(#{part})" if part}"
22+
@dots += 1
23+
@writer.output = "*** Loading#{"." * @dots}"
24+
result = yield.__await__
25+
@writer.output = ""
26+
result
27+
end
28+
1029
# When you update the engines, ensure that they are tested correctly.
1130
# Update the engine list also in spec/playground_spec.
1231
ENGINES = [

app/ruby_engine/cruby_wasi.rb

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# await: *await*
1+
# await: *await*, loading
22

33
require 'await'
44

@@ -58,40 +58,55 @@ def wasm_module
5858
end
5959
end
6060

61-
def run(source, writer)
62-
CRubyWASI.inject_scripts.await
63-
64-
%x{
65-
const $WASI = window["WASI"].WASI;
66-
const $WasmFs = window["WasmFs"].WasmFs;
67-
const $RubyVM = window["ruby-wasm-wasi"].RubyVM;
68-
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-
};
79-
80-
const vm = new $RubyVM();
81-
const wasi = new $WASI({
61+
def run(source)
62+
`var $WASI, $WasmFs, $RubyVM`
63+
wasmInstance, wasmModule, vm, wasi, imports = nil
64+
65+
loading("downloading scripts") { CRubyWASI.inject_scripts.await }
66+
67+
loading("early load") do
68+
`$WASI = window["WASI"].WASI`
69+
`$WasmFs = window["WasmFs"].WasmFs`
70+
`$RubyVM = window["ruby-wasm-wasi"].RubyVM`
71+
72+
wasmFs = `new $WasmFs()`
73+
originalWriteSync = `wasmFs.fs.writeSync.bind(wasmFs.fs)`
74+
textDecoder = `new TextDecoder("utf-8")`
75+
%x{
76+
wasmFs.fs.writeSync = (fd, buffer, offset, length, position) => {
77+
const text = textDecoder.decode(buffer);
78+
if (fd == 1 || fd == 2) {
79+
#{@writer.print_to_output(`text`, "")};
80+
}
81+
return originalWriteSync(fd, buffer, offset, length, position);
82+
};
83+
}
84+
85+
vm = `new $RubyVM()`
86+
wasi = `new $WASI({
8287
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();
90-
}
88+
})`
89+
imports = `{ wasi_snapshot_preview1: wasi.wasiImport }`
90+
`vm.addToImports(imports)`
91+
end
92+
93+
loading("downloading ruby") do
94+
wasmModule = wasm_module.await
95+
end
96+
97+
loading("instantiating") do
98+
wasmInstance = `WebAssembly.instantiate(wasmModule, imports)`.await
99+
end
100+
101+
loading("initializing") do await
102+
`vm.setInstance(wasmInstance)`.await
103+
`wasi.setMemory(wasmInstance.exports.memory)`
104+
`vm.initialize()`
105+
end
91106

92107
yield `vm.eval(source).toString()`
93108
rescue JS::Error => err
94-
writer.log_error(err)
109+
@writer.log_error(err)
95110
end
96111
end
97112
end

app/ruby_engine/opal.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def engine_id
1111
"opal"
1212
end
1313

14-
def run(source, writer)
14+
def run(source)
1515
# Compile
1616
js_code = ::Opal.compile(source)
1717

app/ruby_engine/opal_webworker.rb

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# await: *await*
1+
# await: *await*, loading
22

33
require 'base64'
44
require 'json'
@@ -81,10 +81,10 @@ def initialize(version)
8181
super()
8282
end
8383

84-
def upload_opal_await
85-
upload_script_await("opal")
86-
upload_script_await("opal/full")
87-
upload_script_await("opal-parser")
84+
def upload_opal_await(engine)
85+
engine.loading("downloading ruby") { upload_script_await("opal") }
86+
engine.loading("downloading ruby extras") { upload_script_await("opal/full") }
87+
engine.loading("downloading ruby compiler") { upload_script_await("opal-parser") }
8888
end
8989

9090
def upload_script_await(name)
@@ -96,8 +96,7 @@ def eval_ruby_await(ruby)
9696
send_await(:eval, "var out = eval(Opal.compile(#{ruby.to_json})); out === Opal.nil ? '' : out.$to_s();")
9797
end
9898

99-
def prepare_stdio_await(writer)
100-
@writer = writer
99+
def prepare_stdio_await
101100
eval_ruby_await <<~RUBY
102101
$stdout.write_proc = $stderr.write_proc = ->(str) do
103102
`postMessage(["stdout", str])`
@@ -143,11 +142,15 @@ def engine_id
143142
"opal-ww-#{@version}"
144143
end
145144

146-
def run(source, writer)
145+
def run(source)
147146
worker = OpalWorker.new(@version)
148-
worker.upload_opal_await
149-
worker.prepare_error_handler_await
150-
worker.prepare_stdio_await(writer)
147+
148+
worker.upload_opal_await(self)
149+
150+
loading("preparing ruby") do
151+
worker.prepare_error_handler_await
152+
worker.prepare_stdio_await
153+
end
151154

152155
yield(worker.eval_ruby_await(source))
153156

app/try_ruby.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ def update_screen(item)
369369
# Code has already been compiled into js
370370
def eval_code(source)
371371
begin
372-
@engine.run(source, self) do |retval|
372+
@engine.run_with_writer(source, self) do |retval|
373373
show_result(retval)
374374
end.__await__
375375
# Here, __await__ is a special Opal instruction
@@ -449,6 +449,10 @@ def print_to_output(str, term = "\n")
449449
@output_buffer << str.to_s + term
450450
@output.value = @output_buffer.join
451451
end
452+
453+
def output=(text)
454+
@output.value = text
455+
end
452456
end
453457

454458
$window.on("dom:load") { TryRuby.start }

0 commit comments

Comments
 (0)