Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 deletions lib/phoenix_live_view/diff.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ defmodule Phoenix.LiveView.Diff do
# handled here.
@moduledoc false

require Logger

alias Phoenix.LiveView.{
Component,
Comprehension,
Expand Down Expand Up @@ -76,10 +78,16 @@ defmodule Phoenix.LiveView.Diff do
end

defp to_iodata(cid, components, _template, mapper) when is_integer(cid) do
# Resolve component pointers and update the component entries
components = resolve_components_xrefs(cid, components)
{iodata, components} = to_iodata(Map.fetch!(components, cid), components, nil, mapper)
{mapper.(cid, iodata), components}

case components do
%{^cid => component_diff} ->
{iodata, components} = to_iodata(component_diff, components, nil, mapper)
{mapper.(cid, iodata), components}

%{} ->
{[], components}
end
end

defp to_iodata(binary, components, _template, _mapper) when is_binary(binary) do
Expand All @@ -102,11 +110,36 @@ defmodule Phoenix.LiveView.Diff do
case components[cid] do
%{@static => static} = diff when is_integer(static) ->
static = abs(static)
components = resolve_components_xrefs(static, components)
Map.put(components, cid, deep_merge(components[static], Map.delete(diff, @static)))

case components[static] do
nil ->
Logger.debug(
"Dropping component CID #{cid}: cross-reference target CID #{static} missing"
)

Map.delete(components, cid)

_ ->
components = resolve_components_xrefs(static, components)

case components[static] do
nil ->
Logger.debug(
"Dropping component CID #{cid}: cross-reference target CID #{static} removed during resolution"
)

Map.delete(components, cid)

resolved ->
Map.put(components, cid, deep_merge(resolved, Map.delete(diff, @static)))
end
end

%{} ->
components

nil ->
components
end
end

Expand Down
37 changes: 37 additions & 0 deletions test/phoenix_live_view/diff_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,43 @@ defmodule Phoenix.LiveView.DiffTest do
map |> Diff.to_iodata() |> IO.iodata_to_binary()
end

describe "to_iodata - resolve_components_xrefs" do
test "handles missing component CID referenced by cross-reference" do
rendered = %{
0 => 1,
:c => %{
1 => %{0 => "hello", :s => -2}
},
:s => ["<div>", "</div>"]
}

assert rendered_to_binary(rendered) == "<div></div>"
end

test "handles chain of cross-references where leaf target is missing" do
rendered = %{
0 => 3,
:c => %{
3 => %{0 => "content", :s => -2},
2 => %{0 => "inner", :s => -1}
},
:s => ["<div>", "</div>"]
}

assert rendered_to_binary(rendered) == "<div></div>"
end

test "handles CID referenced in template but missing from components" do
rendered = %{
0 => 42,
:c => %{},
:s => ["<div>", "</div>"]
}

assert rendered_to_binary(rendered) == "<div></div>"
end
end

describe "to_iodata" do
test "with subtrees chain" do
assert rendered_to_binary(%{
Expand Down