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

View file

@ -57,6 +57,14 @@ defmodule LivebookWeb.JSViewChannelTest do
assert_push "event:1", %{"root" => [["ping"], [1, 2, 3]]} assert_push "event:1", %{"root" => [["ping"], [1, 2, 3]]}
end 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 describe "binary payload" do
test "initial data", %{socket: socket} do test "initial data", %{socket: socket} do
push(socket, "connect", %{"connect_token" => connect_token(), "ref" => "1", "id" => "id1"}) push(socket, "connect", %{"connect_token" => connect_token(), "ref" => "1", "id" => "id1"})