Ignore channel events for unknown JS Views (#2363)

This commit is contained in:
Jonatan Kłosko 2023-11-17 13:10:48 +01:00 committed by GitHub
parent d345c9eeff
commit 9076e15a69
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 14 deletions

View file

@ -47,30 +47,40 @@ defmodule LivebookWeb.JSViewChannel do
def handle_in("event", raw, socket) do
{[event, ref], payload} = transport_decode!(raw)
pid = socket.assigns.ref_with_info[ref].pid
send(pid, {:event, event, payload, %{origin: socket.assigns.client_id, ref: ref}})
with %{^ref => info} <- socket.assigns.ref_with_info do
send(info.pid, {:event, event, payload, %{origin: socket.assigns.client_id, ref: ref}})
end
{:noreply, socket}
end
def handle_in("ping", %{"ref" => ref}, socket) do
pid = socket.assigns.ref_with_info[ref].pid
send(pid, {:ping, self(), nil, %{ref: ref}})
with %{^ref => info} <- socket.assigns.ref_with_info do
send(info.pid, {:ping, self(), nil, %{ref: ref}})
end
{:noreply, socket}
end
def handle_in("disconnect", %{"ref" => ref}, socket) do
socket =
if socket.assigns.ref_with_info[ref].count == 1 do
Livebook.Session.unsubscribe_from_runtime_events(
socket.assigns.session_id,
"js_live",
ref
)
case socket.assigns.ref_with_info do
%{^ref => %{count: 1}} ->
Livebook.Session.unsubscribe_from_runtime_events(
socket.assigns.session_id,
"js_live",
ref
)
{_, socket} = pop_in(socket.assigns.ref_with_info[ref])
socket
else
update_in(socket.assigns.ref_with_info[ref], &%{&1 | count: &1.count - 1})
{_, socket} = pop_in(socket.assigns.ref_with_info[ref])
socket
%{^ref => %{count: count}} when count > 1 ->
update_in(socket.assigns.ref_with_info[ref], &%{&1 | count: &1.count - 1})
%{} ->
socket
end
{:noreply, socket}

View file

@ -57,6 +57,14 @@ defmodule LivebookWeb.JSViewChannelTest do
assert_push "event:1", %{"root" => [["ping"], [1, 2, 3]]}
end
test "ignores client events when no connection is found", %{socket: socket} do
push(socket, "event", %{"root" => [["ping", "1"], [1, 2, 3]]})
# The channel should still be operational
push(socket, "connect", %{"connect_token" => connect_token(), "ref" => "1", "id" => "id1"})
assert_receive {:connect, _from, %{}}
end
describe "binary payload" do
test "initial data", %{socket: socket} do
push(socket, "connect", %{"connect_token" => connect_token(), "ref" => "1", "id" => "id1"})