Skip to content

Commit

Permalink
Merge pull request #819 from binaryseed/interface-covariant-cycle-fix
Browse files Browse the repository at this point in the history
Fix infinite loop in interface covariance calculation
  • Loading branch information
benwilson512 committed Dec 7, 2019
2 parents 0e1f75a + f51011d commit 4043efe
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,25 @@ defmodule Absinthe.Phase.Schema.Validation.ObjectMustImplementInterfaces do
end
end

defp check_covariant(
%Blueprint.Schema.InterfaceTypeDefinition{identifier: interface_ident},
interface_ident,
_field_ident,
_types
) do
:ok
end

defp check_covariant(
%Blueprint.Schema.InterfaceTypeDefinition{identifier: interface_ident},
field_type,
field_ident,
types
) do
%{interfaces: field_type_interfaces} = Map.get(types, field_type)
(interface_ident in field_type_interfaces && :ok) || {:error, field_ident}
end

defp check_covariant(
%wrapper{of_type: inner_type1},
%wrapper{of_type: inner_type2},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ defmodule Absinthe.Schema.Rule.ObjectMustImplementInterfacesTest do
object :user do
interface :named
field :name, :string
field :id, :id
field :parent, :named
field :another_parent, :user
end
end

Expand All @@ -16,20 +19,36 @@ defmodule Absinthe.Schema.Rule.ObjectMustImplementInterfacesTest do

interface :named do
field :name, :string
field :parent, :named
field :another_parent, :named

resolve_type fn
%{type: :dog} -> :dog
%{type: :user} -> :user
_ -> nil
%{type: :dog}, _ -> :dog
%{type: :user}, _ -> :user
_, _ -> nil
end
end

object :dog do
field :name, :string
interface :named
field :parent, :named
field :another_parent, :user
end

query do
field :user, :user do
resolve fn _, _ ->
{:ok,
%{
type: :user,
id: "abc-123",
name: "User Name",
parent: %{type: :user, id: "def-456", name: "Parent User"},
another_parent: %{type: :user, id: "ghi-789", name: "Another Parent"}
}}
end
end
end
end

Expand All @@ -55,4 +74,37 @@ defmodule Absinthe.Schema.Rule.ObjectMustImplementInterfacesTest do
}
])
end

test "Interfaces can contain fields of their own type" do
doc = """
{
user {
... on User {
id
parent {
... on Named {
name
}
... on User {
id
}
}
anotherParent {
id
}
}
... on Named {
name
}
}
}
"""

{:ok, %{data: data}} = Absinthe.run(doc, Schema)

assert get_in(data, ["user", "id"]) == "abc-123"
assert get_in(data, ["user", "parent", "id"]) == "def-456"
assert get_in(data, ["user", "parent", "name"]) == "Parent User"
assert get_in(data, ["user", "anotherParent", "id"]) == "ghi-789"
end
end

0 comments on commit 4043efe

Please sign in to comment.