Skip to content

Commit

Permalink
Escape maps when expanding __ENV__
Browse files Browse the repository at this point in the history
  • Loading branch information
josevalim committed Dec 12, 2022
1 parent 6549d20 commit ec31cc2
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 4 deletions.
11 changes: 8 additions & 3 deletions lib/elixir/lib/macro.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1795,13 +1795,15 @@ defmodule Macro do
defp do_expand_once({:__DIR__, _, atom}, env) when is_atom(atom),
do: {:filename.dirname(env.file), true}

defp do_expand_once({:__ENV__, _, atom}, env) when is_atom(atom),
do: {{:%{}, [], Map.to_list(env)}, true}
defp do_expand_once({:__ENV__, _, atom}, env) when is_atom(atom) do
env = update_in(env.versioned_vars, &maybe_escape_map/1)
{maybe_escape_map(env), true}
end

defp do_expand_once({{:., _, [{:__ENV__, _, atom}, field]}, _, []} = original, env)
when is_atom(atom) and is_atom(field) do
if Map.has_key?(env, field) do
{Map.get(env, field), true}
{maybe_escape_map(Map.get(env, field)), true}
else
{original, false}
end
Expand Down Expand Up @@ -1884,6 +1886,9 @@ defmodule Macro do
# Anything else is just returned
defp do_expand_once(other, _env), do: {other, false}

defp maybe_escape_map(map) when is_map(map), do: {:%{}, [], Map.to_list(map)}
defp maybe_escape_map(other), do: other

@doc """
Returns `true` if the given name and arity is a special form.
"""
Expand Down
10 changes: 9 additions & 1 deletion lib/elixir/test/elixir/macro_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,17 @@ defmodule MacroTest do

test "env" do
env = %{__ENV__ | line: 0}
assert Macro.expand_once(quote(do: __ENV__), env) == {:%{}, [], Map.to_list(env)}

expanded = Macro.expand_once(quote(do: __ENV__), env)
assert Macro.validate(expanded) == :ok
assert Code.eval_quoted(expanded) == {env, []}

assert Macro.expand_once(quote(do: __ENV__.file), env) == env.file
assert Macro.expand_once(quote(do: __ENV__.unknown), env) == quote(do: __ENV__.unknown)

expanded = Macro.expand_once(quote(do: __ENV__.versioned_vars), env)
assert Macro.validate(expanded) == :ok
assert Code.eval_quoted(expanded) == {env.versioned_vars, []}
end

defmacro local_macro(), do: raise("ignored")
Expand Down

0 comments on commit ec31cc2

Please sign in to comment.