Open carcinocron opened 2 years ago
unrelated information on crystal wasm hello world build size:
+ lib/js/scripts/build.sh src/main.cr --error-trace
+ ls -lh main.js main.wasm
-rw-r--r-- 1 forge forge 6.6K Jul 31 10:30 main.js
-rwxr-xr-x 1 forge forge 502K Jul 31 10:30 main.wasm
+ lib/js/scripts/build.sh src/main.cr --release
+ ls -lh main.js main.wasm
-rw-r--r-- 1 forge forge 3.2K Jul 31 10:30 main.js
-rwxr-xr-x 1 forge forge 53K Jul 31 10:30 main.wasm
Let's say if we had a seperate js file that needed to call a function from crystal, what would that look like?
main.cr
def foo
return "bar"
end
main2.ts
console.log(foo())
pp "A"
begin
raise "B"
rescue ex
pp ex
end
pp "C"
only outputs "A"
and EXITING: Attempting to raise: B (Exception)
. I think this is WebAssembly's fault though: https://github.com/WebAssembly/exception-handling
I tried this and it compiled but it didn't crash or output "fired"
.
class ::Web::EventTarget
def addEventListener(name : ::String, listener : Proc(Nil)) : Nil
pp "::Web::EventTarget.addEventListener before #{__LINE__}"
<<-js
"\#{self}".id.addEventListener(#{name}, #{listener})
js
pp "::Web::EventTarget.addEventListener after #{__LINE__}"
end
end
cb = -> : Nil { pp "fired" }
canvas.addEventListener("onmouseover", cb)
Hi there.
how to make events work?
For events to work we need to pass a callback from Crystal to JavaScript. Currently Procs are not supported by crystal-js, only primitive types, strings and array-like types. It needs to support both "sending" a Proc from Crystal to a JavaScript function, and the way back, before we can support DOM events here.
Let's say if we had a seperate js file that needed to call a function from crystal, what would that look like?
main.cr
def foo return "bar" end
main2.ts
console.log(foo())
This repo assumes that Crystal calls JavaScript, but not the other way around. You can export a Crystal function (using the fun
syntax instead of def
), but if you do that, you will only be able to take numbers as arguments and to return a single number as result, nothing more complicated than that. These exported functions will show up in the wasm module.
It would be, of course, a nice feature to facilitate exporting Crystal functions to JavaScript with full support for complex types. I'll keep it in the backlog.
pp "A" begin raise "B" rescue ex pp ex end pp "C"
only outputs
"A"
andEXITING: Attempting to raise: B (Exception)
. I think this is WebAssembly's fault though: WebAssembly/exception-handling
Exceptions are not implemented yet for the WASM target of Crystal. See https://github.com/crystal-lang/crystal/issues/12002 for more details. Currently the behavior is that whenever a exception is thrown, the application will just crash and exit right there, with no way of catching and recovering.
I tried this and it compiled but it didn't crash or output
"fired"
.class ::Web::EventTarget def addEventListener(name : ::String, listener : Proc(Nil)) : Nil pp "::Web::EventTarget.addEventListener before #{__LINE__}" <<-js "\#{self}".id.addEventListener(#{name}, #{listener}) js pp "::Web::EventTarget.addEventListener after #{__LINE__}" end end cb = -> : Nil { pp "fired" } canvas.addEventListener("onmouseover", cb)
Please check the README at https://github.com/lbguilherme/crystal-js. It explains more about how new methods can be created. But in short: you need to annotate them with @[JS::Method]
and their body can't anything other than one single string literal with special interpolations for bridge values. Also, Proc isn't supported yet. You will receive a compile-time error about that.
All in all, this repository is a proof of concept and a experiment. It shows that creating Web bindings for Crystal is possible, but there is still a long way before it gets to a usable point. Please tell me a little about your intended use case so I can better understand how to evolve this shard in the future.
Thanks!
I wanted to make an interactive canvas thing with most of the core logic in crystal, but I need at least mouse events for it to be feasible. Proc
specifically aren't important, but that's that only guess I can think of to get events in general listened to by crystal code.
how to make events work?