mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-11-13 07:31:37 +08:00
Fix imports and process dictionary being erased after errored evaluation (#2822)
This commit is contained in:
parent
cb1484ab6d
commit
f2b5382ae7
2 changed files with 103 additions and 3 deletions
|
|
@ -468,8 +468,20 @@ defmodule Livebook.Runtime.Evaluator do
|
||||||
identifiers_used = :unknown
|
identifiers_used = :unknown
|
||||||
identifiers_defined = %{}
|
identifiers_defined = %{}
|
||||||
identifier_definitions = []
|
identifier_definitions = []
|
||||||
# Empty context
|
|
||||||
new_context = initial_context()
|
# Mostly empty context, however we keep imports and process
|
||||||
|
# dictionary from the previous context, since these are not
|
||||||
|
# diffed
|
||||||
|
new_context = %{
|
||||||
|
id: random_long_id(),
|
||||||
|
binding: [],
|
||||||
|
env:
|
||||||
|
context.env
|
||||||
|
|> prune_env(%Evaluator.Tracer{})
|
||||||
|
|> Map.replace!(:versioned_vars, %{}),
|
||||||
|
pdict: context.pdict
|
||||||
|
}
|
||||||
|
|
||||||
{new_context, result, identifiers_used, identifiers_defined, identifier_definitions}
|
{new_context, result, identifiers_used, identifiers_defined, identifier_definitions}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -811,7 +811,7 @@ defmodule Livebook.Runtime.EvaluatorTest do
|
||||||
ref = eval_idx
|
ref = eval_idx
|
||||||
parent_refs = Enum.to_list((eval_idx - 1)..0//-1)
|
parent_refs = Enum.to_list((eval_idx - 1)..0//-1)
|
||||||
Evaluator.evaluate_code(evaluator, :elixir, code, ref, parent_refs)
|
Evaluator.evaluate_code(evaluator, :elixir, code, ref, parent_refs)
|
||||||
assert_receive {:runtime_evaluation_response, ^ref, terminal_text(_), metadata}
|
assert_receive {:runtime_evaluation_response, ^ref, _output, metadata}
|
||||||
%{used: metadata.identifiers_used, defined: metadata.identifiers_defined}
|
%{used: metadata.identifiers_used, defined: metadata.identifiers_defined}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -1191,6 +1191,94 @@ defmodule Livebook.Runtime.EvaluatorTest do
|
||||||
|
|
||||||
assert context.pdict == %{x: 1, y: 2}
|
assert context.pdict == %{x: 1, y: 2}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "context merging with errored evaluation", %{evaluator: evaluator} do
|
||||||
|
# This test is similar to the above, but the second evaluation
|
||||||
|
# fails with an error
|
||||||
|
|
||||||
|
"""
|
||||||
|
x = 1
|
||||||
|
y = 1
|
||||||
|
|
||||||
|
alias Enum, as: E
|
||||||
|
alias Map, as: M
|
||||||
|
|
||||||
|
require Enum
|
||||||
|
|
||||||
|
import Integer, only: [is_odd: 1, is_even: 1, to_string: 2, to_charlist: 2]
|
||||||
|
|
||||||
|
Process.put(:x, 1)
|
||||||
|
Process.put(:y, 1)
|
||||||
|
Process.put(:z, 1)
|
||||||
|
|
||||||
|
defmodule Livebook.Runtime.EvaluatorTest.Identifiers.ErrorContextMergingOne do
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
|> eval(evaluator, 0)
|
||||||
|
|
||||||
|
"""
|
||||||
|
y = 2
|
||||||
|
|
||||||
|
alias MapSet, as: M
|
||||||
|
|
||||||
|
require Map
|
||||||
|
|
||||||
|
import Integer, except: [is_even: 1, to_string: 2]
|
||||||
|
|
||||||
|
Process.put(:y, 2)
|
||||||
|
Process.delete(:z)
|
||||||
|
|
||||||
|
defmodule Livebook.Runtime.EvaluatorTest.Identifiers.ErrorContextMergingTwo do
|
||||||
|
end
|
||||||
|
|
||||||
|
raise "oops"
|
||||||
|
"""
|
||||||
|
|> eval(evaluator, 1)
|
||||||
|
|
||||||
|
# Evaluation 1 context
|
||||||
|
#
|
||||||
|
# Should be empty, except for imports and process dictionary,
|
||||||
|
# which are not diffed and should be kept from evaluation 0.
|
||||||
|
|
||||||
|
context = Evaluator.get_evaluation_context(evaluator, [1])
|
||||||
|
|
||||||
|
assert Enum.sort(context.binding) == []
|
||||||
|
|
||||||
|
assert Enum.sort(context.env.aliases) == []
|
||||||
|
|
||||||
|
assert Map not in context.env.requires
|
||||||
|
assert Enum not in context.env.requires
|
||||||
|
|
||||||
|
assert [_, _ | _] = context.env.functions[Integer]
|
||||||
|
assert [_, _ | _] = context.env.macros[Integer]
|
||||||
|
|
||||||
|
assert context.env.versioned_vars == %{}
|
||||||
|
|
||||||
|
assert context.env.context_modules == []
|
||||||
|
|
||||||
|
assert context.pdict == %{x: 1, y: 1, z: 1}
|
||||||
|
|
||||||
|
# Merged context
|
||||||
|
|
||||||
|
context = Evaluator.get_evaluation_context(evaluator, [1, 0])
|
||||||
|
|
||||||
|
assert Enum.sort(context.binding) == [x: 1, y: 1]
|
||||||
|
|
||||||
|
assert Enum.sort(context.env.aliases) == [{E, Enum}, {M, Map}]
|
||||||
|
|
||||||
|
assert Enum in context.env.requires
|
||||||
|
|
||||||
|
assert [_, _ | _] = context.env.functions[Integer]
|
||||||
|
assert [_, _ | _] = context.env.macros[Integer]
|
||||||
|
|
||||||
|
assert context.env.versioned_vars == %{{:x, nil} => 0, {:y, nil} => 1}
|
||||||
|
|
||||||
|
assert context.env.context_modules == [
|
||||||
|
Livebook.Runtime.EvaluatorTest.Identifiers.ErrorContextMergingOne
|
||||||
|
]
|
||||||
|
|
||||||
|
assert context.pdict == %{x: 1, y: 1, z: 1}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "forget_evaluation/2" do
|
describe "forget_evaluation/2" do
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue