diff --git a/base/client.jl b/base/client.jl index 8ff925d0d9ba4..ad52a4cf5972d 100644 --- a/base/client.jl +++ b/base/client.jl @@ -120,6 +120,10 @@ function display_error(io::IO, er, bt) end display_error(er, bt=nothing) = display_error(stderr, er, bt) +# N.B.: Any functions starting with __repl_entry cut off backtraces when printing in the REPL. +__repl_entry_client_lower(mod::Module, @nospecialize(ast)) = Meta.lower(mod, ast) +__repl_entry_client_eval(mod::Module, @nospecialize(ast)) = Core.eval(mod, ast) + function eval_user_input(errio, @nospecialize(ast), show_value::Bool) errcount = 0 lasterr = nothing @@ -136,8 +140,8 @@ function eval_user_input(errio, @nospecialize(ast), show_value::Bool) errcount = 0 lasterr = nothing else - ast = Meta.lower(Main, ast) - value = Core.eval(Main, ast) + ast = __repl_entry_client_lower(Main, ast) + value = __repl_entry_client_eval(Main, ast) setglobal!(Base.MainInclude, :ans, value) if !(value === nothing) && show_value if have_color diff --git a/test/client.jl b/test/client.jl index 61fe7d5093474..fd129712e2db0 100644 --- a/test/client.jl +++ b/test/client.jl @@ -1,5 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +import Base.StackTraces: StackFrame + nested_error_expr = quote try __not_a_binding__ @@ -57,3 +59,34 @@ end @test eval(:(ans = 1)) == 1 @test eval(:(err = 1)) == 1 end + +@testset "scrub REPL-related frames" begin + repl_bt = [StackFrame(:foo, "foo.jl", 1), + StackFrame(:__repl_entry_anysuffix, "client.jl", 2), + StackFrame(:bar, "bar.jl", 3)] + scrubbed_repl_bt = Base.scrub_repl_backtrace(repl_bt) + + nonrepl_bt = [StackFrame(:foo, "foo.jl", 1), + StackFrame(:baz, "baz.jl", 2), + StackFrame(:bar, "bar.jl", 3)] + scrubbed_nonrepl_bt = Base.scrub_repl_backtrace(nonrepl_bt) + + @test length(scrubbed_repl_bt) == 1 + @test scrubbed_repl_bt[1].func == :foo + @test length(scrubbed_nonrepl_bt) == 3 + + errio = IOBuffer() + lower_errexpr = :(@bad) + Base.eval_user_input(errio, lower_errexpr, false) + outstr = String(take!(errio)) + @test occursin("ERROR: LoadError: UndefVarError: `@bad`", outstr) + @test !occursin("_repl_entry", outstr) + @test !occursin(r"\.[/\\]client.jl", outstr) + + errexpr = :(error("fail")) + Base.eval_user_input(errio, errexpr, false) + outstr = String(take!(errio)) + @test occursin("ERROR: fail", outstr) + @test !occursin("_repl_entry", outstr) + @test !occursin(r"\.[/\\]client.jl", outstr) +end