Skip to content

Commit

Permalink
Perform change tracking on form access
Browse files Browse the repository at this point in the history
  • Loading branch information
josevalim committed Jan 23, 2023
1 parent 8f9d560 commit 35de681
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 17 deletions.
37 changes: 21 additions & 16 deletions lib/phoenix_live_view/engine.ex
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ defmodule Phoenix.LiveView.Engine do
handled lazily by the diff algorithm.
"""

alias Phoenix.HTML.Form
@behaviour Phoenix.Template.Engine

@impl true
Expand Down Expand Up @@ -571,10 +572,10 @@ defmodule Phoenix.LiveView.Engine do
[assign | tail] ->
quote do
unquote(__MODULE__).nested_changed_assign?(
unquote(@assigns_var),
changed,
unquote(tail),
unquote(assign),
unquote(tail)
unquote(@assigns_var),
changed
)
end
end
Expand Down Expand Up @@ -725,14 +726,14 @@ defmodule Phoenix.LiveView.Engine do
defp component_changed([path], assigns, changed) do
case path do
[key] -> changed_assign(changed, key)
[key | tail] -> nested_changed_assign(assigns, changed, key, tail)
[key | tail] -> nested_changed_assign(tail, key, assigns, changed)
end
end

defp component_changed(entries, assigns, changed) do
Enum.any?(entries, fn
[key] -> changed_assign?(changed, key)
[key | tail] -> nested_changed_assign?(assigns, changed, key, tail)
[key | tail] -> nested_changed_assign?(tail, key, assigns, changed)
end)
end

Expand Down Expand Up @@ -1192,14 +1193,14 @@ defmodule Phoenix.LiveView.Engine do
end

@doc false
def nested_changed_assign?(assigns, changed, head, tail),
do: nested_changed_assign(assigns, changed, head, tail) != false
def nested_changed_assign?(tail, head, assigns, changed),
do: nested_changed_assign(tail, head, assigns, changed) != false

defp nested_changed_assign(assigns, changed, head, tail) do
defp nested_changed_assign(tail, head, assigns, changed) do
case changed do
%{^head => changed} ->
case assigns do
%{^head => assigns} -> recur_changed_assign(assigns, changed, tail)
%{^head => assigns} -> recur_changed_assign(tail, assigns, changed)
%{} -> true
end

Expand All @@ -1211,30 +1212,34 @@ defmodule Phoenix.LiveView.Engine do
end
end

defp recur_changed_assign(assigns, changed, [{:struct, head} | tail]) do
recur_changed_assign(assigns, changed, head, tail)
defp recur_changed_assign([{:struct, head} | tail], assigns, changed) do
recur_changed_assign(tail, head, assigns, changed)
end

defp recur_changed_assign([{:access, head}], %Form{} = form1, %Form{} = form2) do
Form.input_changed?(form1, form2, head)
end

defp recur_changed_assign(assigns, changed, [{:access, head} | tail]) do
defp recur_changed_assign([{:access, head} | tail], assigns, changed) do
if match?(%_{}, assigns) or match?(%_{}, changed) do
true
else
recur_changed_assign(assigns, changed, head, tail)
recur_changed_assign(tail, head, assigns, changed)
end
end

defp recur_changed_assign(assigns, changed, head, []) do
defp recur_changed_assign([], head, assigns, changed) do
case {assigns, changed} do
{%{^head => value}, %{^head => value}} -> false
{_, %{^head => value}} when is_map(value) -> value
{_, _} -> true
end
end

defp recur_changed_assign(assigns, changed, head, tail) do
defp recur_changed_assign(tail, head, assigns, changed) do
case {assigns, changed} do
{%{^head => assigns_value}, %{^head => changed_value}} ->
recur_changed_assign(assigns_value, changed_value, tail)
recur_changed_assign(tail, assigns_value, changed_value)

{_, _} ->
true
Expand Down
2 changes: 1 addition & 1 deletion mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"},
"nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"},
"phoenix": {:hex, :phoenix, "1.6.15", "0a1d96bbc10747fd83525370d691953cdb6f3ccbac61aa01b4acb012474b047d", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d70ab9fbf6b394755ea88b644d34d79d8b146e490973151f248cacd122d20672"},
"phoenix_html": {:git, "https://github.com/phoenixframework/phoenix_html.git", "da9c164bbd54c4ca3bfac7e5c914e9430f9a2ef6", []},
"phoenix_html": {:git, "https://github.com/phoenixframework/phoenix_html.git", "f829bcbf9e87e5d08595c1ea531e1243f0510bf4", []},
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.4.1", "2aff698f5e47369decde4357ba91fc9c37c6487a512b41732818f2204a8ef1d3", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "9bffb834e7ddf08467fe54ae58b5785507aaba6255568ae22b4d46e2bb3615ab"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"},
"phoenix_template": {:hex, :phoenix_template, "1.0.0", "c57bc5044f25f007dc86ab21895688c098a9f846a8dda6bc40e2d0ddc146e38f", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "1b066f99a26fd22064c12b2600a9a6e56700f591bf7b20b418054ea38b4d4357"},
Expand Down
15 changes: 15 additions & 0 deletions test/phoenix_live_view/engine_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,21 @@ defmodule Phoenix.LiveView.EngineTest do
assert changed(template, new_changed_bar, old) == ["777"]
end

test "renders dynamic with access tracking for forms" do
form1 = Phoenix.Component.to_form(%{"foo" => "bar"})
form2 = Phoenix.Component.to_form(%{"foo" => "bar", "baz" => "bat"})
form3 = Phoenix.Component.to_form(%{"foo" => "baz"})

template = "<%= Map.fetch!(@form[:foo], :value) %>"
assert changed(template, %{form: form1}, nil) == ["bar"]

template = "<%= Map.fetch!(@form[:foo], :value) %>"
assert changed(template, %{form: form1}, %{}) == [nil]
assert changed(template, %{form: form1}, %{form: form1}) == [nil]
assert changed(template, %{form: form2}, %{form: form1}) == [nil]
assert changed(template, %{form: form3}, %{form: form1}) == ["baz"]
end

test "renders dynamic with access tracking inside comprehension" do
template = """
<%= for x <- [:a, :b, :c] do %>
Expand Down

0 comments on commit 35de681

Please sign in to comment.