Skip to content

Commit

Permalink
Merge pull request #208 from travigd/td/fix-webio-integration
Browse files Browse the repository at this point in the history
Fix WebIO integration, make Window's sync by default.
  • Loading branch information
pfitzseb authored Jul 24, 2019
2 parents 63fcfbb + 90af75a commit 6e07a9d
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 17 deletions.
54 changes: 37 additions & 17 deletions src/AtomShell/window.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mutable struct Window
id::Int
shell::Shell
content
inittask::Union{Nothing, Task}
end

"""
Expand Down Expand Up @@ -39,38 +40,48 @@ const window_defaults = @d(:url => "about:blank",

raw_window(a::Electron, opts) = @js a createWindow($(merge(window_defaults, opts)))

function Window(a::Shell, opts::AbstractDict = Dict(); async=true)
function Window(a::Shell, opts::AbstractDict = Dict(); async=false)
# TODO: Custom urls don't support async b/c don't load Blink.js. (Same as https://github.com/JunoLab/Blink.jl/issues/150)
return haskey(opts, :url) ?
Window(raw_window(a, opts), a, nothing) :
Window(raw_window(a, opts), a, nothing, nothing) :
Window(a, Page(), opts, async=async)
end

function Window(a::Shell, content::Page, opts::AbstractDict = Dict(); async=true)
id, cond = Blink.callback!()
function Window(a::Shell, content::Page, opts::AbstractDict = Dict(); async=false)
id, callback_cond = Blink.callback!()
url = Blink.localurl(content) * "?callback=$id"

# Create the window.
opts = merge(opts, Dict(:url => url))
w = Window(raw_window(a, opts), a, content)
w = Window(raw_window(a, opts), a, content, nothing)

# Note: we have to use a task here because of the use of Condition throughout
# the codebase (it might be better to use Channel or Future which are not
# edge-triggered). We also need to initialize this after the Window
# constructor because we have to pass the window into the damn function.
w.inittask = @async try
initwindow!(w, callback_cond)
catch exc
@error(
"An error occurred while trying to initialize a Blink window!",
exception=exc,
)
end

if async
@async initwindow!(w, cond)
else
initwindow!(w, cond)
if !async
wait(w)
end

return w
end

function initwindow!(w::Window, cond::Condition)
result = wait(cond)
if isa(result, AbstractDict) && get(result, "type", "") == "error"
err = JSError(
get(result, "name", "unknown"),
get(result, "message", "blank"),
)
throw(err)
function initwindow!(w::Window, callback_cond::Condition)
initresult = wait(callback_cond)
if isa(initresult, AbstractDict) && get(initresult, "type", "") == "error"
throw(JSError(
get(initresult, "name", "unknown"),
get(initresult, "message", "blank"),
))
end
initwebio!(w)
end
Expand All @@ -94,6 +105,15 @@ macro dot_(win, code)
:(dot_($(esc(win)), $(Expr(:quote, Expr(:., :this, QuoteNode(code))))))
end

# Base.* methods

function Base.wait(w::Window)
if w.inittask === nothing
error("Cannot wait() a \"raw\" window (was this window created with a url arg?).")
end
return wait(w.inittask)
end

# Window management APIs

active(s::Electron, win::Integer) =
Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ end

include("content/api.jl");
include("AtomShell/window.jl");
include("./webio.jl")

if Sys.iswindows()
# Uninstalling AtomShell on Windows is currently broken:
Expand Down
59 changes: 59 additions & 0 deletions test/webio.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using Test
using Blink
using WebIO

"""
Execute function f() with a timeout of `timeout` seconds. Returns the
result of f() or `nothing` in the case of a timeout.
"""
function with_timeout(f::Function, timeout)
c = Channel{Any}(1)
@async begin
put!(c, f())
end
@async begin
sleep(timeout)
put!(c, nothing)
end
take!(c)
end

@testset "WebIO integration" begin
@testset "mount test" begin
w = Window(Dict(:show => false))
mounted = Channel(false)
setmounted = () -> push!(mounted, true)
scope = Scope()
onmount(scope, js"""
function () {
$setmounted()
}
""")
body!(w, scope)
did_mount = with_timeout(() -> take!(mounted), 5)
@test did_mount
end

@testset "button click" begin
w = Window(Dict(:show => false))
scope = Scope()
obs = Observable(scope, "obs", false)
obschannel = Channel(1)
on((x) -> push!(obschannel, x), obs)
scope(dom"button#mybutton"(
events=Dict(
"click" => @js function()
$obs[] = true
end
)
))
body!(w, scope)

# Sleep to allow WebIO scope to mount in Electron
sleep(0.25)

@js w document.querySelector("#mybutton").click()
did_click = with_timeout(() -> take!(obschannel), 5)
@test did_click
end
end

0 comments on commit 6e07a9d

Please sign in to comment.