Skip to content

Commit f5afa68

Browse files
REPL: call display on the backend
1 parent b8dc57e commit f5afa68

File tree

2 files changed

+56
-23
lines changed

2 files changed

+56
-23
lines changed

stdlib/REPL/src/REPL.jl

+55-22
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,22 @@ mutable struct REPLBackend
120120
end
121121
REPLBackend() = REPLBackend(Channel(1), Channel(1), false)
122122

123+
# A reference to a backend that is not mutable
124+
struct REPLBackendRef
125+
repl_channel::Channel{Any}
126+
response_channel::Channel{Any}
127+
end
128+
REPLBackendRef(backend::REPLBackend) = REPLBackendRef(backend.repl_channel, backend.response_channel)
129+
130+
function destroy(ref::REPLBackendRef, state::Task)
131+
if istaskfailed(state)
132+
close(ref.repl_channel, TaskFailedException(state))
133+
close(ref.response_channel, TaskFailedException(state))
134+
end
135+
close(ref.repl_channel)
136+
close(ref.response_channel)
137+
end
138+
123139
"""
124140
softscope(ex)
125141
@@ -418,12 +434,23 @@ function repl_backend_loop(backend::REPLBackend, get_module::Function)
418434
while true
419435
tls = task_local_storage()
420436
tls[:SOURCE_PATH] = nothing
421-
ast, show_value = take!(backend.repl_channel)
437+
ast_or_func, show_value = take!(backend.repl_channel)
422438
if show_value == -1
423439
# exit flag
424440
break
425441
end
426-
eval_user_input(ast, backend, get_module())
442+
if ast_or_func isa Expr
443+
ast = ast_or_func
444+
eval_user_input(ast, backend, get_module())
445+
else
446+
f = ast_or_func
447+
try
448+
ret = f()
449+
put!(backend.response_channel, Pair{Any, Bool}(ret, false))
450+
catch err
451+
put!(backend.response_channel, Pair{Any, Bool}(err, true))
452+
end
453+
end
427454
end
428455
return nothing
429456
end
@@ -526,7 +553,7 @@ function print_response(repl::AbstractREPL, response, show_value::Bool, have_col
526553
repl.waserror = response[2]
527554
with_repl_linfo(repl) do io
528555
io = IOContext(io, :module => Base.active_module(repl)::Module)
529-
print_response(io, response, show_value, have_color, specialdisplay(repl))
556+
print_response(io, response, backend(repl), show_value, have_color, specialdisplay(repl))
530557
end
531558
return nothing
532559
end
@@ -543,7 +570,7 @@ function repl_display_error(errio::IO, @nospecialize errval)
543570
return nothing
544571
end
545572

546-
function print_response(errio::IO, response, show_value::Bool, have_color::Bool, specialdisplay::Union{AbstractDisplay,Nothing}=nothing)
573+
function print_response(errio::IO, response, backend::Union{REPLBackendRef,Nothing}, show_value::Bool, have_color::Bool, specialdisplay::Union{AbstractDisplay,Nothing}=nothing)
547574
Base.sigatomic_begin()
548575
val, iserr = response
549576
while true
@@ -557,9 +584,14 @@ function print_response(errio::IO, response, show_value::Bool, have_color::Bool,
557584
if val !== nothing && show_value
558585
try
559586
if specialdisplay === nothing
560-
Base.invokelatest(display, val)
587+
# display calls may require being run on the main thread
588+
eval_with_backend(backend) do
589+
Base.invokelatest(display, val)
590+
end
561591
else
562-
Base.invokelatest(display, specialdisplay, val)
592+
eval_with_backend(backend) do
593+
Base.invokelatest(display, specialdisplay, val)
594+
end
563595
end
564596
catch
565597
println(errio, "Error showing value of type ", typeof(val), ":")
@@ -593,21 +625,7 @@ function print_response(errio::IO, response, show_value::Bool, have_color::Bool,
593625
nothing
594626
end
595627

596-
# A reference to a backend that is not mutable
597-
struct REPLBackendRef
598-
repl_channel::Channel{Any}
599-
response_channel::Channel{Any}
600-
end
601-
REPLBackendRef(backend::REPLBackend) = REPLBackendRef(backend.repl_channel, backend.response_channel)
602628

603-
function destroy(ref::REPLBackendRef, state::Task)
604-
if istaskfailed(state)
605-
close(ref.repl_channel, TaskFailedException(state))
606-
close(ref.response_channel, TaskFailedException(state))
607-
end
608-
close(ref.repl_channel)
609-
close(ref.response_channel)
610-
end
611629

612630
"""
613631
run_repl(repl::AbstractREPL)
@@ -1130,10 +1148,25 @@ find_hist_file() = get(ENV, "JULIA_HISTORY",
11301148

11311149
backend(r::AbstractREPL) = r.backendref
11321150

1133-
function eval_with_backend(ast, backend::REPLBackendRef)
1134-
put!(backend.repl_channel, (ast, 1))
1151+
1152+
function eval_with_backend(ast::Expr, backend::REPLBackendRef)
1153+
put!(backend.repl_channel, (ast, 1)) # (f, show_value)
1154+
return take!(backend.response_channel) # (val, iserr)
1155+
end
1156+
function eval_with_backend(f, backend::REPLBackendRef)
1157+
put!(backend.repl_channel, (f, false)) # (f, show_value)
11351158
return take!(backend.response_channel) # (val, iserr)
11361159
end
1160+
# if no backend just eval (used by tests)
1161+
function eval_with_backend(f, backend::Nothing)
1162+
try
1163+
ret = f()
1164+
return (ret, false) # (val, iserr)
1165+
catch err
1166+
return (err, true)
1167+
end
1168+
end
1169+
11371170

11381171
function respond(f, repl, main; pass_empty::Bool = false, suppress_on_semicolon::Bool = true)
11391172
return function do_respond(s::MIState, buf, ok::Bool)

stdlib/REPL/test/repl.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ function test19864()
925925
@eval Base.showerror(io::IO, e::Error19864) = print(io, "correct19864")
926926
buf = IOBuffer()
927927
fake_response = (Base.ExceptionStack([(exception=Error19864(),backtrace=Ptr{Cvoid}[])]),true)
928-
REPL.print_response(buf, fake_response, false, false, nothing)
928+
REPL.print_response(buf, fake_response, nothing, false, false, nothing)
929929
return String(take!(buf))
930930
end
931931
@test occursin("correct19864", test19864())

0 commit comments

Comments
 (0)