Skip to content

Commit

Permalink
Optimize nested for comprehension (#1874)
Browse files Browse the repository at this point in the history
* Share comprehension roots

Co-authored-by: José Valim <[email protected]>
  • Loading branch information
chrismccord and josevalim authored Feb 8, 2022
1 parent 8db95a4 commit bb3a06d
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 15 deletions.
2 changes: 1 addition & 1 deletion assets/js/phoenix_live_view/rendered.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ export default class Rendered {
comprehensionToBuffer(rendered, templates, output){
let {[DYNAMICS]: dynamics, [STATIC]: statics} = rendered
statics = this.templateStatic(statics, templates)
let compTemplates = rendered[TEMPLATES]
let compTemplates = templates || rendered[TEMPLATES]

for(let d = 0; d < dynamics.length; d++){
let dynamic = dynamics[d]
Expand Down
34 changes: 20 additions & 14 deletions lib/phoenix_live_view/diff.ex
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ defmodule Phoenix.LiveView.Diff do

defp to_iodata(%{@dynamics => dynamics, @static => static} = comp, components, template, mapper) do
static = template_static(static, template)
template = comp[@template]
template = template || comp[@template]

Enum.map_reduce(dynamics, components, fn dynamic, components ->
many_to_iodata(static, dynamic, [], components, template, mapper)
Expand Down Expand Up @@ -430,10 +430,10 @@ defmodule Phoenix.LiveView.Diff do
nil = template

{dynamics, {pending, components, {_, comprehension_template}}} =
traverse_comprehension(socket, dynamics, pending, components)
traverse_comprehension(socket, dynamics, pending, components, {%{}, %{}})

{maybe_add_template(%{@dynamics => dynamics}, comprehension_template), fingerprint, pending,
components, nil}
diff = maybe_add_template(%{@dynamics => dynamics}, comprehension_template)
{diff, fingerprint, pending, components, nil}
end

defp traverse(
Expand All @@ -458,15 +458,23 @@ defmodule Phoenix.LiveView.Diff do
template,
_changed?
) do
{dynamics, {pending, components, {_, comprehension_template}}} =
traverse_comprehension(socket, dynamics, pending, components)
if template do
{dynamics, {pending, components, template}} =
traverse_comprehension(socket, dynamics, pending, components, template)

{diff, template} =
maybe_template_static(%{@dynamics => dynamics}, fingerprint, static, template)

{diff, fingerprint, pending, components, template}
else
{dynamics, {pending, components, {_, comprehension_template}}} =
traverse_comprehension(socket, dynamics, pending, components, {%{}, %{}})

{diff, template} =
%{@dynamics => dynamics}
|> maybe_add_template(comprehension_template)
|> maybe_template_static(fingerprint, static, template)
diff =
maybe_add_template(%{@dynamics => dynamics, @static => static}, comprehension_template)

{diff, fingerprint, pending, components, template}
{diff, fingerprint, pending, components, nil}
end
end

defp traverse(_socket, nil, fingerprint_tree, pending, components, template, _changed?) do
Expand Down Expand Up @@ -506,9 +514,7 @@ defmodule Phoenix.LiveView.Diff do
end)
end

defp traverse_comprehension(socket, dynamics, pending, components) do
template = {%{}, %{}}

defp traverse_comprehension(socket, dynamics, pending, components, template) do
Enum.map_reduce(dynamics, {pending, components, template}, fn rendereds, acc ->
Enum.map_reduce(rendereds, acc, fn rendered, {pending, components, template} ->
{diff, _, pending, components, template} =
Expand Down
42 changes: 42 additions & 0 deletions test/phoenix_live_view/diff_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@ defmodule Phoenix.LiveView.DiffTest do
"""
end

def nested_comprehension_template(assigns) do
~H"""
<div>
<h1><%= @title %></h1>
<%= for name <- @names do %>
<br/><%= name %>
<%= for score <- @scores do %>
<br/><%= score %>
<% end %>
<% end %>
</div>
"""
end

defp nested_rendered(changed? \\ true) do
%Rendered{
static: ["<h2>", "</h2>", "<span>", "</span>"],
Expand Down Expand Up @@ -229,6 +243,34 @@ defmodule Phoenix.LiveView.DiffTest do

assert {^fingerprint, %{1 => ^comprehension_print}} = socket.fingerprints
end

test "nested comprehensions" do
%{fingerprint: fingerprint} =
rendered =
nested_comprehension_template(%{
title: "Users",
names: ["phoenix", "elixir"],
scores: [1, 2]
})

{socket, full_render, _} = render(rendered)

assert full_render == %{
0 => "Users",
1 => %{
d: [
["phoenix", %{d: [["1"], ["2"]], s: 0}],
["elixir", %{d: [["1"], ["2"]], s: 0}]
],
p: %{0 => ["\n <br>", "\n "]},
s: ["\n <br>", "\n ", "\n "]
},
:s => ["<div>\n <h1>", "</h1>\n ", "\n</div>"]
}

assert {^fingerprint, %{1 => comprehension_print}} = socket.fingerprints
assert is_integer(comprehension_print)
end
end

describe "diffed render with fingerprints" do
Expand Down

0 comments on commit bb3a06d

Please sign in to comment.