@@ -304,6 +304,9 @@ eval_forms(Tree, Binding, OrigE) ->
304304 eval_forms (Tree , Binding , OrigE , []).
305305eval_forms (Tree , Binding , OrigE , Opts ) ->
306306 Prune = proplists :get_value (prune_binding , Opts , false ),
307+ % % We save and restore the previous dbg_callback so nested eval calls in
308+ % % the same process do not clobber the outer callback.
309+ PreviousDbg = erlang :get ({elixir , dbg_callback }),
307310 case proplists :get_value (dbg_callback , Opts ) of
308311 undefined -> ok ;
309312 DbgCallback -> erlang :put ({elixir , dbg_callback }, DbgCallback )
@@ -332,7 +335,10 @@ eval_forms(Tree, Binding, OrigE, Opts) ->
332335 {Value , DumpedBinding , NewE #{versioned_vars := DumpedVars }}
333336 end
334337 after
335- erlang :erase ({elixir , dbg_callback })
338+ case PreviousDbg of
339+ undefined -> erlang :erase ({elixir , dbg_callback });
340+ _ -> erlang :put ({elixir , dbg_callback }, PreviousDbg )
341+ end
336342 end .
337343
338344% % Evaluate Erlang code with careful handling of local and external functions
@@ -341,20 +347,27 @@ erl_eval(Expr, Binding, Env) ->
341347 LocalHandler = {value , fun ? MODULE :eval_local_handler /2 },
342348 ExternalHandler = {value , fun ? MODULE :eval_external_handler /3 },
343349
350+ % % ?elixir_eval_env is used by the external handler.
351+ % %
352+ % % The reason why we use the process dictionary to pass the environment
353+ % % is because we want to avoid passing closures to erl_eval, as that
354+ % % would effectively tie the eval code to the Elixir version and it is
355+ % % best if it depends solely on Erlang/OTP.
356+ % %
357+ % % The downside is that functions that escape the eval context will no
358+ % % longer have the original environment they came from.
359+ % %
360+ % % We save and restore the previous env so nested eval calls in the same
361+ % % process do not clobber the outer env.
362+ PreviousEvalEnv = erlang :get (? elixir_eval_env ),
363+ erlang :put (? elixir_eval_env , Env ),
344364 try
345- % % ?elixir_eval_env is used by the external handler.
346- % %
347- % % The reason why we use the process dictionary to pass the environment
348- % % is because we want to avoid passing closures to erl_eval, as that
349- % % would effectively tie the eval code to the Elixir version and it is
350- % % best if it depends solely on Erlang/OTP.
351- % %
352- % % The downside is that functions that escape the eval context will no
353- % % longer have the original environment they came from.
354- erlang :put (? elixir_eval_env , Env ),
355365 erl_eval :expr (Expr , Binding , LocalHandler , ExternalHandler )
356366 after
357- erlang :erase (? elixir_eval_env )
367+ case PreviousEvalEnv of
368+ undefined -> erlang :erase (? elixir_eval_env );
369+ _ -> erlang :put (? elixir_eval_env , PreviousEvalEnv )
370+ end
358371 end .
359372
360373eval_local_handler (FunName , Args ) ->
0 commit comments