My blink + interact code is not working after julia update

, ,

Hello,

I have a code that was working well before updating Julia to 1.8.5, but now I got an error that I don’t uderstand at all…
The idea was to generate an interactive interface that can show a png/gif file depending on some sliders/buttons. I use Blink in order to get a window, and Interact with WebIO for the slider/button/observable parts.
It is very rudimental because I know nothing almost nothing about HTTP, websocket, thread or HTML, javascript and etc… I was using it as a nice blackbox.

This is what it looks like

Before the update I was getting only one or two lines of texr, today when I run my code I get:

[ Info: Listening on: 127.0.0.1:8283, thread id: 1
Page(1, HTTP.WebSockets.WebSocket(UUID("8891d0af-0290-4580-b435-5ef6b52fe313"), 🔁   10s 127.0.0.1:8283:8283 Base.Libc.WindowsRawSocket(0x0000000000001f34), HTTP.Messages.Request:
"""
GET /1?callback=1/1 HTTP/1.1
Host: 127.0.0.1:8283
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.167 Electron/19.0.9 Safari/537.36
Upgrade: websocket
Origin: http://127.0.0.1:8283
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US
Sec-WebSocket-Key: ULb8maJqg+glVJecTX3b/g==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

""", HTTP.Messages.Response:
"""
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: cq2PnbcYfGgws84cstKXGehGdlk=

""", 9223372036854775807, 1024, false, UInt8[0x7b, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x63  …  0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x7d], UInt8[], false, false), Dict{String, Any}("webio" => Blink.AtomShell.var"#19#20"{Blink.AtomShell.WebIOBlinkComm}(Blink.AtomShell.WebIOBlinkComm(Window(1, Electron(Process(`'C:\Users\ludop\.julia\artifacts\77dde9ca99aacbbcdc9754e39062ed451ef26861\electron.exe' 'C:\Users\ludop\.julia\packages\Blink\SMxOp\src\AtomShell\main.js' port 5712`, ProcessRunning), Sockets.TCPSocket(Base.Libc.WindowsRawSocket(0x000000000000214c) active, 0 bytes waiting), Dict{String, Any}("callback" => Blink.var"#1#2"())), Page(#= circular reference @-5 =#), Task (done) @0x00000291ee411940))), "callback" => Blink.var"#1#2"()), Distributed.Future(1, 1, 1, ReentrantLock(nothing, 0x00000000, 0x00, Base.GenericCondition{Base.Threads.SpinLock}(Base.InvasiveLinkedList{Task}(nothing, nothing), Base.Threads.SpinLock(0)), (0, 140704510726416, 4294967297)), Some(true)))

But When I want to interact with the widgets I get this error:

┌ Error: An exception occurred while trying to send a WebIO message to a frontend:
│   exception =
│    IOError: stream is closed or unusable
│    Stacktrace:
│      [1] check_open
│        @ .\stream.jl:388 [inlined]
│      [2] uv_write_async(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1072
│      [3] uv_write(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1035
│      [4] unsafe_write(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1118
│      [5] unsafe_write
│        @ .\io.jl:683 [inlined]
│      [6] unsafe_write(s::Sockets.TCPSocket, p::Base.RefValue{UInt16}, n::Int64)
│        @ Base .\io.jl:681
│      [7] write
│        @ .\io.jl:684 [inlined]
│      [8] write
│        @ .\io.jl:687 [inlined]
│      [9] writeframe(io::HTTP.ConnectionPool.Connection{Sockets.TCPSocket}, x::HTTP.WebSockets.Frame)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:186
│     [10] send(ws::HTTP.WebSockets.WebSocket, x::String)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:519
│     [11] msg(p::Page, m::Dict{Symbol, Any})
│        @ Blink C:\Users\ludop\.julia\packages\Blink\SMxOp\src\content\content.jl:45
│     [12] msg(win::Window, m::Dict{Symbol, Any})
│        @ Blink.AtomShell C:\Users\ludop\.julia\packages\Blink\SMxOp\src\AtomShell\window.jl:261
│     [13] send
│        @ C:\Users\ludop\.julia\packages\Blink\SMxOp\src\AtomShell\webio.jl:38 [inlined]
│     [14] send_message(pool::WebIO.ConnectionPool, connection::Blink.AtomShell.WebIOBlinkComm, msg::Dict{String, Any})
│        @ WebIO C:\Users\ludop\.julia\packages\WebIO\rv35l\src\connection.jl:115
│     [15] (::WebIO.var"#5#6"{WebIO.ConnectionPool, Dict{String, Any}, Blink.AtomShell.WebIOBlinkComm})()
│        @ WebIO .\task.jl:484
└ @ WebIO C:\Users\ludop\.julia\packages\WebIO\rv35l\src\connection.jl:120
┌ Error: An exception occurred while trying to send a WebIO message to a frontend:
│   exception =
│    IOError: stream is closed or unusable
│    Stacktrace:
│      [1] check_open
│        @ .\stream.jl:388 [inlined]
│      [2] uv_write_async(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1072
│      [3] uv_write(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1035
│      [4] unsafe_write(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1118
│      [5] unsafe_write
│        @ .\io.jl:683 [inlined]
│      [6] unsafe_write(s::Sockets.TCPSocket, p::Base.RefValue{UInt16}, n::Int64)
│        @ Base .\io.jl:681
│      [7] write
│        @ .\io.jl:684 [inlined]
│      [8] write
│        @ .\io.jl:687 [inlined]
│      [9] writeframe(io::HTTP.ConnectionPool.Connection{Sockets.TCPSocket}, x::HTTP.WebSockets.Frame)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:186
│     [10] send(ws::HTTP.WebSockets.WebSocket, x::String)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:519
│     [11] msg(p::Page, m::Dict{Symbol, Any})
│        @ Blink C:\Users\ludop\.julia\packages\Blink\SMxOp\src\content\content.jl:45
│     [12] msg(win::Window, m::Dict{Symbol, Any})
│        @ Blink.AtomShell C:\Users\ludop\.julia\packages\Blink\SMxOp\src\AtomShell\window.jl:261
│     [13] send
│        @ C:\Users\ludop\.julia\packages\Blink\SMxOp\src\AtomShell\webio.jl:38 [inlined]
│     [14] send_message(pool::WebIO.ConnectionPool, connection::Blink.AtomShell.WebIOBlinkComm, msg::Dict{String, Any})
│        @ WebIO C:\Users\ludop\.julia\packages\WebIO\rv35l\src\connection.jl:115
│     [15] (::WebIO.var"#5#6"{WebIO.ConnectionPool, Dict{String, Any}, Blink.AtomShell.WebIOBlinkComm})()
│        @ WebIO .\task.jl:484
└ @ WebIO C:\Users\ludop\.julia\packages\WebIO\rv35l\src\connection.jl:120
┌ Error: An exception occurred while trying to send a WebIO message to a frontend:
│   exception =
│    IOError: stream is closed or unusable
│    Stacktrace:
│      [1] check_open
│        @ .\stream.jl:388 [inlined]
│      [2] uv_write_async(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1072
│      [3] uv_write(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1035
│      [4] unsafe_write(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1118
│      [5] unsafe_write
│        @ .\io.jl:683 [inlined]
│      [6] unsafe_write(s::Sockets.TCPSocket, p::Base.RefValue{UInt16}, n::Int64)
│        @ Base .\io.jl:681
│      [7] write
│        @ .\io.jl:684 [inlined]
│      [8] write
│        @ .\io.jl:687 [inlined]
│      [9] writeframe(io::HTTP.ConnectionPool.Connection{Sockets.TCPSocket}, x::HTTP.WebSockets.Frame)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:186
│     [10] send(ws::HTTP.WebSockets.WebSocket, x::String)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:519
│     [11] msg(p::Page, m::Dict{Symbol, Any})
│        @ Blink C:\Users\ludop\.julia\packages\Blink\SMxOp\src\content\content.jl:45
│     [12] msg(win::Window, m::Dict{Symbol, Any})
│        @ Blink.AtomShell C:\Users\ludop\.julia\packages\Blink\SMxOp\src\AtomShell\window.jl:261
│     [13] send
│        @ C:\Users\ludop\.julia\packages\Blink\SMxOp\src\AtomShell\webio.jl:38 [inlined]
│     [14] send_message(pool::WebIO.ConnectionPool, connection::Blink.AtomShell.WebIOBlinkComm, msg::Dict{String, Any})
│        @ WebIO C:\Users\ludop\.julia\packages\WebIO\rv35l\src\connection.jl:115
│     [15] (::WebIO.var"#5#6"{WebIO.ConnectionPool, Dict{String, Any}, Blink.AtomShell.WebIOBlinkComm})()
│        @ WebIO .\task.jl:484
└ @ WebIO C:\Users\ludop\.julia\packages\WebIO\rv35l\src\connection.jl:120
┌ Error: An exception occurred while trying to send a WebIO message to a frontend:
│   exception =
│    IOError: stream is closed or unusable
│    Stacktrace:
│      [1] check_open
│        @ .\stream.jl:388 [inlined]
│      [2] uv_write_async(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1072
│      [3] uv_write(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1035
│      [4] unsafe_write(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1118
│      [5] unsafe_write
│        @ .\io.jl:683 [inlined]
│      [6] unsafe_write(s::Sockets.TCPSocket, p::Base.RefValue{UInt16}, n::Int64)
│        @ Base .\io.jl:681
│      [7] write
│        @ .\io.jl:684 [inlined]
│      [8] write
│        @ .\io.jl:687 [inlined]
│      [9] writeframe(io::HTTP.ConnectionPool.Connection{Sockets.TCPSocket}, x::HTTP.WebSockets.Frame)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:186
│     [10] send(ws::HTTP.WebSockets.WebSocket, x::String)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:519
│     [11] msg(p::Page, m::Dict{Symbol, Any})
│        @ Blink C:\Users\ludop\.julia\packages\Blink\SMxOp\src\content\content.jl:45
│     [12] msg(win::Window, m::Dict{Symbol, Any})
│        @ Blink.AtomShell C:\Users\ludop\.julia\packages\Blink\SMxOp\src\AtomShell\window.jl:261
│     [13] send
│        @ C:\Users\ludop\.julia\packages\Blink\SMxOp\src\AtomShell\webio.jl:38 [inlined]
│     [14] send_message(pool::WebIO.ConnectionPool, connection::Blink.AtomShell.WebIOBlinkComm, msg::Dict{String, Any})
│        @ WebIO C:\Users\ludop\.julia\packages\WebIO\rv35l\src\connection.jl:115
│     [15] (::WebIO.var"#5#6"{WebIO.ConnectionPool, Dict{String, Any}, Blink.AtomShell.WebIOBlinkComm})()
│        @ WebIO .\task.jl:484
└ @ WebIO C:\Users\ludop\.julia\packages\WebIO\rv35l\src\connection.jl:120
┌ Error: An exception occurred while trying to send a WebIO message to a frontend:
│   exception =
│    IOError: write: operation canceled (ECANCELED)
│    Stacktrace:
│      [1] uv_write(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1064
│      [2] unsafe_write(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1118
│      [3] unsafe_write
│        @ .\io.jl:683 [inlined]
│      [4] unsafe_write(s::Sockets.TCPSocket, p::Base.RefValue{UInt16}, n::Int64)
│        @ Base .\io.jl:681
│      [5] write
│        @ .\io.jl:684 [inlined]
│      [6] write
│        @ .\io.jl:687 [inlined]
│      [7] writeframe(io::HTTP.ConnectionPool.Connection{Sockets.TCPSocket}, x::HTTP.WebSockets.Frame)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:184
│      [8] send(ws::HTTP.WebSockets.WebSocket, x::String)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:519
│      [9] msg(p::Page, m::Dict{Symbol, Any})
│        @ Blink C:\Users\ludop\.julia\packages\Blink\SMxOp\src\content\content.jl:45
│     [10] msg(win::Window, m::Dict{Symbol, Any})
│        @ Blink.AtomShell C:\Users\ludop\.julia\packages\Blink\SMxOp\src\AtomShell\window.jl:261
│     [11] send
│        @ C:\Users\ludop\.julia\packages\Blink\SMxOp\src\AtomShell\webio.jl:38 [inlined]
│     [12] send_message(pool::WebIO.ConnectionPool, connection::Blink.AtomShell.WebIOBlinkComm, msg::Dict{String, String})
│        @ WebIO C:\Users\ludop\.julia\packages\WebIO\rv35l\src\connection.jl:115
│     [13] (::WebIO.var"#5#6"{WebIO.ConnectionPool, Dict{String, String}, Blink.AtomShell.WebIOBlinkComm})()
│        @ WebIO .\task.jl:484
└ @ WebIO C:\Users\ludop\.julia\packages\WebIO\rv35l\src\connection.jl:120
┌ Error: An exception occurred while trying to send a WebIO message to a frontend:
│   exception =
│    IOError: write: operation canceled (ECANCELED)
│    Stacktrace:
│      [1] uv_write(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1064
│      [2] unsafe_write(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│        @ Base .\stream.jl:1118
│      [3] unsafe_write
│        @ .\io.jl:683 [inlined]
│      [4] unsafe_write(s::Sockets.TCPSocket, p::Base.RefValue{UInt16}, n::Int64)
│        @ Base .\io.jl:681
│      [5] write
│        @ .\io.jl:684 [inlined]
│      [6] write
│        @ .\io.jl:687 [inlined]
│      [7] writeframe(io::HTTP.ConnectionPool.Connection{Sockets.TCPSocket}, x::HTTP.WebSockets.Frame)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:184
│      [8] send(ws::HTTP.WebSockets.WebSocket, x::String)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:519
│      [9] msg(p::Page, m::Dict{Symbol, Any})
│        @ Blink C:\Users\ludop\.julia\packages\Blink\SMxOp\src\content\content.jl:45
│     [10] msg(win::Window, m::Dict{Symbol, Any})
│        @ Blink.AtomShell C:\Users\ludop\.julia\packages\Blink\SMxOp\src\AtomShell\window.jl:261
│     [11] send
│        @ C:\Users\ludop\.julia\packages\Blink\SMxOp\src\AtomShell\webio.jl:38 [inlined]
│     [12] send_message(pool::WebIO.ConnectionPool, connection::Blink.AtomShell.WebIOBlinkComm, msg::Dict{String, Any})
│        @ WebIO C:\Users\ludop\.julia\packages\WebIO\rv35l\src\connection.jl:115
│     [13] (::WebIO.var"#5#6"{WebIO.ConnectionPool, Dict{String, Any}, Blink.AtomShell.WebIOBlinkComm})()
│        @ WebIO .\task.jl:484
└ @ WebIO C:\Users\ludop\.julia\packages\WebIO\rv35l\src\connection.jl:120
┌ Error: 8891d0af-0290-4580-b435-5ef6b52fe313: Unexpected websocket server error
│   (e, catch_backtrace()) =
│    EOFError: read end of file
│    Stacktrace:
│      [1] unsafe_read(c::HTTP.ConnectionPool.Connection{Sockets.TCPSocket}, p::Ptr{UInt8}, n::UInt64)
│        @ HTTP.ConnectionPool C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\ConnectionPool.jl:181
│      [2] unsafe_read
│        @ .\io.jl:759 [inlined]
│      [3] unsafe_read(s::HTTP.ConnectionPool.Connection{Sockets.TCPSocket}, p::Base.RefValue{UInt16}, n::Int64)
│        @ Base .\io.jl:758
│      [4] read!
│        @ .\io.jl:760 [inlined]
│      [5] read
│        @ .\io.jl:764 [inlined]
│      [6] readframe(io::HTTP.ConnectionPool.Connection{Sockets.TCPSocket}, ::Type{HTTP.WebSockets.Frame}, buffer::Vector{UInt8}, first_fragment_opcode::HTTP.WebSockets.OpCode)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:128
│      [7] readframe(io::HTTP.ConnectionPool.Connection{Sockets.TCPSocket}, ::Type{HTTP.WebSockets.Frame}, buffer::Vector{UInt8})
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:127
│      [8] receive(ws::HTTP.WebSockets.WebSocket)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:658
│      [9] iterate(ws::HTTP.WebSockets.WebSocket, st::Nothing)
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:697
│     [10] ws_handler(ws::HTTP.WebSockets.WebSocket)
│        @ Blink C:\Users\ludop\.julia\packages\Blink\SMxOp\src\content\server.jl:47
│     [11] (::Mux.var"#9#10"{Mux.App})(sock::HTTP.WebSockets.WebSocket)
│        @ Mux C:\Users\ludop\.julia\packages\Mux\PipQ9\src\server.jl:48
│     [12] upgrade(f::Mux.var"#9#10"{Mux.App}, http::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.ConnectionPool.Connection{Sockets.TCPSocket}}; suppress_close_error::Bool, maxframesize::Int64, maxfragmentation::Int64, kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
│        @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:439
│     [13] upgrade
│        @ C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:419 [inlined]
│     [14] (::Mux.var"#14#15"{Mux.App, Mux.App})(http::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.ConnectionPool.Connection{Sockets.TCPSocket}})
│        @ Mux C:\Users\ludop\.julia\packages\Mux\PipQ9\src\server.jl:81
│     [15] #invokelatest#2
│        @ .\essentials.jl:729 [inlined]
│     [16] invokelatest
│        @ .\essentials.jl:726 [inlined]
│     [17] handle_connection(f::Function, c::HTTP.ConnectionPool.Connection{Sockets.TCPSocket}, listener::HTTP.Servers.Listener{Nothing, Sockets.TCPServer}, readtimeout::Int64, access_log::Nothing)
│        @ HTTP.Servers C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\Servers.jl:447
│     [18] (::HTTP.Servers.var"#16#17"{Mux.var"#14#15"{Mux.App, Mux.App}, HTTP.Servers.Listener{Nothing, Sockets.TCPServer}, Set{HTTP.ConnectionPool.Connection}, Int64, Nothing, Base.Semaphore, HTTP.ConnectionPool.Connection{Sockets.TCPSocket}})()
│        @ HTTP.Servers .\task.jl:484
└ @ HTTP.WebSockets C:\Users\ludop\.julia\packages\HTTP\z8l0i\src\WebSockets.jl:442

I use Windows 10, jupyter lab with jupyter server, addtionnal infos:

Julia Version 1.8.5
Commit 17cfb8e65e (2023-01-08 06:45 UTC)
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: 8 × Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, skylake)
  Threads: 8 on 8 virtual cores
Environment:
  JULIA_NUM_THREADS = 8
Status `C:\Users\ludop\.julia\environments\v1.8\Project.toml`
  [ad839575] Blink v0.12.6
  [336ed68f] CSV v0.10.9  
  [052768ef] CUDA v4.1.0
  [5ae59095] Colors v0.12.10
  [a93c6f00] DataFrames v1.5.0
  [5789e2e9] FileIO v1.16.0
  [53c48c17] FixedPointNumbers v0.8.4
  [7073ff75] IJulia v1.24.0
  [916415d5] Images v0.25.2
  [c601a237] Interact v0.10.5
  [4138dd39] JLD v0.13.3
  [682c06a0] JSON v0.21.3
  [ee78f7c6] Makie v0.19.3
  [cbe49d4c] RemoteFiles v0.5.0
  [0f1e0344] WebIO v0.8.20
  [9bd350c2] OpenSSH_jll v9.1.0+0

Thank you in advance for your help,
Best regards,
Ludovic

I wonder if you’re able to post some example code that reproduces the error for us?

2 Likes

I wonder if you might try running the code just using a single thread, that is, start Julia as julia -t 1

1 Like

Thank you for your answers !

I tried with one thread, I got the same error message.

Trying to reproduce the error with a small code is more difficult than expected.
I tried to modify my code but in my code the number of widget depends on the number of columns of the DataFrames that I give. Everything is generated using metaprogramming. As I am a beginner, I lost myself. I am now trying to reproduce the error starting from an example in the tutorial of Interact.

The simple example of the tutorial works fine:

import Colors
using Plots
using Blink, Interact
w = Window()
width, height = 700, 300
colors = ["black", "gray", "silver", "maroon", "red", "olive", "yellow", "green", "lime", "teal", "aqua", "navy", "blue", "purple", "fuchsia"]
color(i) = colors[i%length(colors)+1]
ui = @manipulate for nsamples in 1:200,
        sample_step in slider(0.01:0.01:1.0, value=0.1, label="sample step"),
        phase in slider(0:0.1:2pi, value=0.0, label="phase"),
        radii in 0.1:0.1:60
    cxs_unscaled = [i*sample_step + phase for i in 1:nsamples]
    cys = sin.(cxs_unscaled) .* height/3 .+ height/2
    cxs = cxs_unscaled .* width/4pi
    dom"svg:svg[width=$width, height=$height]"(
        (dom"svg:circle[cx=$(cxs[i]), cy=$(cys[i]), r=$radii, fill=$(color(i))]"()
            for i in 1:nsamples)...
    )
end

body!(w, ui)

I think the issue come from the feedback of sliders on other sliders. In my “app” sliders are input and output.
Then I tried to add one slider that is updated only when one slider is moving:

import Colors
using Plots
using Blink, Interact, WebIO
w = Window()
width, height = 700, 300
colors = ["black", "gray", "silver", "maroon", "red", "olive", "yellow", "green", "lime", "teal", "aqua", "navy", "blue", "purple", "fuchsia"]
color(i) = colors[i%length(colors)+1]
sl_nsamples = Interact.slider(1:200, value=100, label="nsamples")
sl_sample_step = Interact.slider(0.01:0.01:1.0, value=0.1, label="sample step")
sl_sample_step_b = Interact.slider(0.01:0.01:1.0, value=0.1, label="sample step_b")
sl_phase = Interact.slider(0.0:0.1:6.0, value=0.0, label="phase")
sl_radii = Interact.slider(0.1:0.1:60,value=10.0, label="radii")

ui = Observable{Any}()

on(sl_sample_step) do v
    println("Value of sample_step = ", v)
    sl_sample_step_b[] = v
end

function getui(sl_nsamples, sl_sample_step, sl_sample_step_b, sl_phase, sl_radii, color)    
    cxs_unscaled = [i*sl_sample_step[] + sl_phase[] for i in 1:sl_nsamples[]]
    cys = sin.(cxs_unscaled) .* height/3 .+ height/2
    cxs = cxs_unscaled .* width/4pi
    rr = sl_radii[]
    return dom"svg:svg[width=$width, height=$height]"(
    (dom"svg:circle[cx=$(cxs[i]), cy=$(cys[i]), r=$rr, fill=$(color(i))]"()
        for i in 1:sl_nsamples[])...
    )
end
map!(getui, ui, sl_nsamples, sl_sample_step, sl_sample_step_b, sl_phase, sl_radii, color)
body!(w, dom"div"( hbox( vbox(sl_nsamples, sl_sample_step, sl_sample_step_b, sl_phase, sl_radii), ui) ) )

Maybe I need to downgrade to an older version of Interact, Blink or WebIO ? Because it was working well before, 5 coworkers are still using my older code on the older version of these packages.

Thank you for your help !

1 Like

Blink, Interact and WebIO are pretty much unmaintained…
JSServe isn’t and can do most of those things…
I admit, I did uncover a bug in the SVG serialization, so I needed to add a small workaround when porting your example:

import Colors
using JSServe
using Electron
import JSServe.TailwindDashboard as D
using Hyperscript
using Observables: to_value

width, height = 900, 300
colors = ["black", "gray", "silver", "maroon", "red", "olive", "yellow", "green", "lime", "teal", "aqua", "navy", "blue", "purple", "fuchsia"]
color(i) = colors[i%length(colors)+1]

function getui(sl_nsamples, sl_sample_step, sl_sample_step_b, sl_phase, sl_radii, color)    
    cxs_unscaled = [i*sl_sample_step + sl_phase for i in 1:sl_nsamples]
    cys = sin.(cxs_unscaled) .* height/3 .+ height/2
    cxs = cxs_unscaled .* width/4pi
    rr = sl_radii
    # DOM.div/svg/etc is just a convenience in JSServe for using Hyperscript, but circle isn't wrapped like that yet
    circle = Hyperscript.m("circle")
    return DOM.svg(
        (circle(cx=cxs[i], cy=cys[i], r=rr, fill=color(i)) for i in 1:sl_nsamples[])...;
        width=width, height=height, xmlns="http://www.w3.org/2000/svg", viewBox="0 0 $width $height",
        Symbol("xmlns:xlink") => "http://www.w3.org/1999/xlink"
    )
end

app = App() do session
    sl_nsamples = D.Slider("nsamples", 1:200, value=100)
    sl_nsamples.widget[] = 100
    sl_sample_step = D.Slider("sample step", 0.01:0.01:1.0, value=0.1)
    sl_sample_step.widget[] = 0.1
    sl_sample_step_b = D.Slider("sample step_b", 0.01:0.01:1.0, value=0.1)
    sl_sample_step_b.widget[] = 0.1
    sl_phase = D.Slider("phase", 0.0:0.1:6.0, value=0.0)
    sl_radii = D.Slider("radii", 0.1:0.1:60, value=10.0)
    sl_radii.widget[] = 10
    width, height = 700, 300
    svg = DOM.div()
    function update_svg(args...)
        # It seems like SVG needs some special treatment, 
        # Otherwise one could just do:
        # return DOM.div(map(getui, args...)) 
        # And the observable with the svg DOM node should just work
        # Anyways, we can just manually render the string representation and use that to update the node
        html = repr(MIME"text/html"(), getui(args...))
        evaljs(session, js"$(svg).innerHTML = $(html)")
    end
    args = (sl_nsamples.widget.value, sl_sample_step.widget.value, sl_sample_step_b.widget.value, sl_phase.widget.value, sl_radii.widget.value, color)
    onany(update_svg, args...)
    update_svg(to_value.(args)...) # onany doesn't trigger, so one needs to call it first
    return DOM.div(D.FlexRow(D.FlexCol(sl_nsamples, sl_sample_step, sl_sample_step_b, sl_phase, sl_radii), svg))
end;
display(app) # display in VSCode plotpane, Pluto/IJulia, or a browser if run from the REPL

using Electron; 
disp = JSServe.use_electron_display()
Electron.toggle_devtools(disp.window) # devtools are open by default (should change this)
display(disp, app) # if vscode plotpane is inactive display(app) would be enough, but this forces it to use the correct display
3 Likes

On JSServe#sd/bonito this works now:

using JSServe, Hyperscript, Colors
import JSServe.TailwindDashboard as D
using Observables: to_value

function getui(sl_nsamples, sl_sample_step, sl_sample_step_b, sl_phase, sl_radii, color)    
    width, height = 900, 300
    cxs_unscaled = [i*sl_sample_step + sl_phase for i in 1:sl_nsamples]
    cys = sin.(cxs_unscaled) .* height/3 .+ height/2
    cxs = cxs_unscaled .* width/4pi
    rr = sl_radii
    # JSServe.SVG ensures that SVG is properly serialized & rendered
    geom = [SVG.circle(cx=cxs[i], cy=cys[i], r=rr, fill=color(i)) for i in 1:sl_nsamples[]]
    return SVG.svg(SVG.g(geom...); width=width, height=height)
end

app = App() do session
    colors = ["black", "gray", "silver", "maroon", "red", "olive", "yellow", "green", "lime", "teal", "aqua", "navy", "blue", "purple", "fuchsia"]
    color(i) = colors[i%length(colors)+1]
    sl_nsamples = D.Slider("nsamples", 1:200, value=100)
    sl_sample_step = D.Slider("sample step", 0.01:0.01:1.0, value=0.1)
    sl_sample_step_b = D.Slider("sample step_b", 0.01:0.01:1.0, value=0.1)
    sl_phase = D.Slider("phase", 0.0:0.1:6.0, value=0.0)
    sl_radii = D.Slider("radii", 0.1:0.1:60, value=10.0)
    on(sl_sample_step.value) do v
        println("Value of sample_step = ", v)
        sl_sample_step_b.widget[] = v
    end
    svg = map(getui, sl_nsamples.value, sl_sample_step.value, sl_sample_step_b.value, sl_phase.value, sl_radii.value, color)
    return DOM.div(D.FlexRow(D.FlexCol(sl_nsamples, sl_sample_step, sl_sample_step_b, sl_phase, sl_radii), svg))
end
2 Likes

You could try pinning the Blink version back to 0.12.5.

1 Like

Thank you !
I am trying to redo things using JSServe and its TailwindDashboard, I have an issue because usually my slider are not define as a Range but as a vector of Float. An example would be D.Slider("a", [0.01, 0.05, 0.1, 0.5, 2.0]) but if I do that I get this error:

WidgetsBase.Slider(::Vector{Float64}; style="width: 100%;")
Closest candidates are:
  WidgetsBase.Slider(::T) where T<:AbstractRange

When I try this with slider defined with range, it works:

using JSServe, Hyperscript, Colors
import JSServe.TailwindDashboard as D
using Observables: to_value
JSServe.browser_display()

app = App() do session
    ui = Observable{Any}("Gello Wolrd")
    colors = ["black", "gray", "silver", "maroon", "red", "olive", "yellow", "green", "lime", "teal", "aqua", "navy", "blue", "purple", "fuchsia"]
    color(i) = colors[i%length(colors)+1]
    sl_nsamples = D.Slider("nsamples", 1:200)
    sl_sample_step = D.Slider("sample step", 0.01:0.01:1.0)
    sl_sample_step_b = D.Slider("sample step_b", 0.01:0.01:1.0)
    on(sl_sample_step.widget.value) do v
        println("Value of sample_step = ", v)
        sl_sample_step_b.widget[] = v
    end
    on(sl_nsamples.widget.value) do x
        ui[] = "Hello World $x"
    end
    return DOM.div(D.FlexRow(D.FlexCol(sl_nsamples, sl_sample_step, sl_sample_step_b), ui))
end
display(app)

But If I want to show this in a jupyterlab console, there is no interactivity :frowning:

Is there a way to define slider using an array ?
Is it possible to get interaction in a jupyterlab console ?
Thank you

Pinning Blink to version 0.12.5 solved everything.

But I would like to make it works with JSServe :thinking:
It seems more future proof, and I would like to be able to update other packages that are blocked by the version of Blink without having to create an other environment.

In sd/bonito D.Slider should work for any vector of items:

app = App() do session
    sl_sample_step_b = D.Slider("sample step", [0.1, 0.2, 0.3])
end
1 Like

Thank you ! I hope your branch will soon be merged with the master one.
I’ll try to find how I can add a package from a specific branch.

]add JSServe#sd/bonito :wink:

1 Like

Im currently working on merging and tagging this, so if the command fails it means ive merged it and you should try #master instead :wink:

1 Like

Thank you, it is almost working ! But I can’t see the pictures :frowning:
I want to load .png or .gif files. I tried with

files = JSServe.Asset.(joinpath.(dir, filter(x-> endswith(x, ".png"), readdir(dir))))
    slider = JSServe.Slider(1:length(files))

but I only get:
littlegif2

Before, with Blink, I was using this kind of function:

function showpng(filename; h=h)
    open(filename) do f
        base64f = base64encode(f)
        return HTML("""<img src="data:image/png;base64,$base64f" style=$h>""")
    end
end

Then with one Observable HTML{string}, it was ok, but now it doesn’t work anymore, any suggestion ?

EDIT: Everything works well, I am just stupid ! I made a mistake in the path of dir then there was no png to show.
JSServe is really awesome to do simple things without knowledge ! And probably more !
Thank you so much !
(Maybe radio button is still missing in TailwindDashboard :sweat_smile: :innocent:)

Ugh, indeed, image with asset was broken ^^
Fixed it before the release and made sure the other examples are still working:

1 Like