diff --git a/ext/debase_internals.c b/ext/debase_internals.c index 7dc3cf6..2668f2a 100644 --- a/ext/debase_internals.c +++ b/ext/debase_internals.c @@ -637,7 +637,7 @@ Debase_enable_file_filtering(VALUE self, VALUE value) return value; } -#if RUBY_API_VERSION_CODE >= 20500 +#if RUBY_API_VERSION_CODE >= 20500 && !(RUBY_RELEASE_YEAR == 2017 && RUBY_RELEASE_MONTH == 10 && RUBY_RELEASE_DAY == 10) static const rb_iseq_t * my_iseqw_check(VALUE iseqw) { @@ -654,17 +654,28 @@ Debase_enable_file_filtering(VALUE self, VALUE value) } static void - Debase_set_trace_flag_to_iseq(VALUE self, VALUE rb_iseq) - { + Debase_set_trace_flag_to_iseq(VALUE self, VALUE rb_iseq) { if (!SPECIAL_CONST_P(rb_iseq) && RBASIC_CLASS(rb_iseq) == rb_cISeq) { rb_iseq_t *iseq = my_iseqw_check(rb_iseq); rb_iseq_trace_set(iseq, RUBY_EVENT_TRACEPOINT_ALL); } } + + static void + Debase_unset_trace_flags(VALUE self, VALUE rb_iseq) { + if (!SPECIAL_CONST_P(rb_iseq) && RBASIC_CLASS(rb_iseq) == rb_cISeq) { + rb_iseq_t *iseq = my_iseqw_check(rb_iseq); + rb_iseq_trace_set(iseq, RUBY_EVENT_NONE); + } + } #else static void Debase_set_trace_flag_to_iseq(VALUE self, VALUE rb_iseq) { } + + static void + Debase_unset_trace_flags(VALUE self, VALUE rb_iseq) { + } #endif static VALUE @@ -712,6 +723,9 @@ Init_debase_internals() rb_define_module_function(mDebase, "init_variables", Debase_init_variables, 0); rb_define_module_function(mDebase, "set_trace_flag_to_iseq", Debase_set_trace_flag_to_iseq, 1); + //use only for tests + rb_define_module_function(mDebase, "unset_iseq_flags", Debase_unset_trace_flags, 1); + idAlive = rb_intern("alive?"); idAtLine = rb_intern("at_line"); idAtBreakpoint = rb_intern("at_breakpoint"); diff --git a/lib/debase.rb b/lib/debase.rb index d28bf1f..305c1db 100644 --- a/lib/debase.rb +++ b/lib/debase.rb @@ -30,7 +30,7 @@ def monkey_patch_prepend class << RubyVM::InstructionSequence def self.prepend(mod, *smth) super - if mod.to_s.include? 'Bootsnap' + if mod.to_s.include?('Bootsnap') && RUBY_VERSION >= "2.5" prepend InstructionSequenceMixin end end @@ -107,7 +107,7 @@ def load_iseq(path) def do_set_flags(iseq) Debugger.set_trace_flag_to_iseq(iseq) - iseq.each_child{|child_iseq| do_set_flags(child_iseq)} + iseq.each_child { |child_iseq| do_set_flags(child_iseq) } if iseq.respond_to? :each_child end end end diff --git a/test/example/bootsnap/a.rb b/test/example/bootsnap/a.rb new file mode 100644 index 0000000..9d19e3e --- /dev/null +++ b/test/example/bootsnap/a.rb @@ -0,0 +1,5 @@ +class A + def foo(a) + puts a + end +end \ No newline at end of file diff --git a/test/example/bootsnap/bootsnap.rb b/test/example/bootsnap/bootsnap.rb new file mode 100644 index 0000000..3600ee0 --- /dev/null +++ b/test/example/bootsnap/bootsnap.rb @@ -0,0 +1,3 @@ +require_relative 'a.rb' + +A.new.foo('hi') \ No newline at end of file diff --git a/test/test_load.rb b/test/test_load.rb index 137d4c4..9a4d7ba 100644 --- a/test/test_load.rb +++ b/test/test_load.rb @@ -3,6 +3,9 @@ # Test of Debugger.debug_load in C extension ruby_debug.so class TestDebugLoad < Test::Unit::TestCase + + self.test_order = :defined + class << self def at_line(file, line) @@at_line = [File.basename(file), line] @@ -41,4 +44,35 @@ def test_debug_load ensure Debugger.stop if Debugger.started? end + + module MyBootsnap + def load_iseq(path) + iseq = RubyVM::InstructionSequence.compile_file(path) + + Debugger.unset_iseq_flags(iseq) + iseq + end + end + + def test_bootsnap + @@at_line = nil + src_dir = File.dirname(__FILE__) + prog_script = File.join(src_dir, 'example', 'bootsnap', 'bootsnap.rb') + + class << RubyVM::InstructionSequence + prepend MyBootsnap + end + bt = Debugger.debug_load(prog_script, true) + assert_equal(nil, bt) + assert_not_nil(@@at_line) + if RUBY_VERSION >= '2.5' + assert_equal(['debase.rb', 101], @@at_line) + end + + assert(Debugger.started?) + Debugger.stop + + class << RubyVM::InstructionSequence; self end.class_eval { undef_method :load_iseq } + + end end