зеркало из https://github.com/github/ruby.git
[ruby/irb] Rescue errors from main.to_s/inspect when formatting
prompt (https://github.com/ruby/irb/pull/791) Currently, IRB just terminates if `main.to_s` raises while IRB constructs the prompt string. This can easily happen if the user wants to start an IRB session in the instance scope of an uninitialized object, for example: ``` class C def initialize binding.irb @values = [] end def to_s = @values.join(',') # raises if uninitialized end C.new ``` This patch makes IRB rescue from such an exception and displays the class name of the exception instead of `main.to_s` to indicate some error has occurred. We may display more detailed information about the exception, but this patch chooses not to do so because 1) the prompt has limited space, 2) users can evaluate `to_s` in IRB to examine the error if they want, and 3) obtaining the details can also raise, which requires nested exception handling and can be complicated. https://github.com/ruby/irb/commit/412ab26067
This commit is contained in:
Родитель
9365b78d49
Коммит
5fc71feb6c
|
@ -930,9 +930,11 @@ module IRB
|
|||
when "N"
|
||||
@context.irb_name
|
||||
when "m"
|
||||
truncate_prompt_main(@context.main.to_s)
|
||||
main_str = @context.main.to_s rescue "!#{$!.class}"
|
||||
truncate_prompt_main(main_str)
|
||||
when "M"
|
||||
truncate_prompt_main(@context.main.inspect)
|
||||
main_str = @context.main.inspect rescue "!#{$!.class}"
|
||||
truncate_prompt_main(main_str)
|
||||
when "l"
|
||||
ltype
|
||||
when "i"
|
||||
|
|
|
@ -631,6 +631,15 @@ module TestIRB
|
|||
assert_equal('irb("aaaaaaaaaaaaaaaaaaaaaaaaaaaa...)>', irb.send(:format_prompt, 'irb(%M)>', nil, 1, 1))
|
||||
end
|
||||
|
||||
def test_prompt_main_raise
|
||||
main = Object.new
|
||||
def main.to_s; raise TypeError; end
|
||||
def main.inspect; raise ArgumentError; end
|
||||
irb = IRB::Irb.new(IRB::WorkSpace.new(main), TestInputMethod.new)
|
||||
assert_equal("irb(!TypeError)>", irb.send(:format_prompt, 'irb(%m)>', nil, 1, 1))
|
||||
assert_equal("irb(!ArgumentError)>", irb.send(:format_prompt, 'irb(%M)>', nil, 1, 1))
|
||||
end
|
||||
|
||||
def test_lineno
|
||||
input = TestInputMethod.new([
|
||||
"\n",
|
||||
|
|
Загрузка…
Ссылка в новой задаче