зеркало из https://github.com/github/ruby.git
[Feature #20335] `Thread.each_caller_location` arguments
Accecpt the same arguments as `caller` and `caller_locations`.
This commit is contained in:
Родитель
7bc66a366d
Коммит
09638741ba
|
@ -143,18 +143,8 @@ module Gem::BUNDLED_GEMS
|
||||||
# Additionally, we need to skip Bootsnap and Zeitwerk if present, these
|
# Additionally, we need to skip Bootsnap and Zeitwerk if present, these
|
||||||
# gems decorate Kernel#require, so they are not really the ones issuing
|
# gems decorate Kernel#require, so they are not really the ones issuing
|
||||||
# the require call users should be warned about. Those are upwards.
|
# the require call users should be warned about. Those are upwards.
|
||||||
frames_to_skip = 2
|
location = Thread.each_caller_location(2) do |cl|
|
||||||
location = nil
|
break cl.path unless cl.base_label == "require"
|
||||||
Thread.each_caller_location do |cl|
|
|
||||||
if frames_to_skip >= 1
|
|
||||||
frames_to_skip -= 1
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
if cl.base_label != "require"
|
|
||||||
location = cl.path
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if location && File.file?(location) && !location.start_with?(Gem::BUNDLED_GEMS::LIBDIR)
|
if location && File.file?(location) && !location.start_with?(Gem::BUNDLED_GEMS::LIBDIR)
|
||||||
|
|
|
@ -40,10 +40,10 @@ describe "Thread.each_caller_location" do
|
||||||
}.should raise_error(LocalJumpError, "no block given")
|
}.should raise_error(LocalJumpError, "no block given")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't accept positional and keyword arguments" do
|
it "doesn't accept keyword arguments" do
|
||||||
-> {
|
-> {
|
||||||
Thread.each_caller_location(12, foo: 10) {}
|
Thread.each_caller_location(12, foo: 10) {}
|
||||||
}.should raise_error(ArgumentError, "wrong number of arguments (given 2, expected 0)")
|
}.should raise_error(ArgumentError);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -33,12 +33,6 @@ def compile_extension(name)
|
||||||
ruby_header = "#{rubyhdrdir}/ruby.h"
|
ruby_header = "#{rubyhdrdir}/ruby.h"
|
||||||
abi_header = "#{rubyhdrdir}/ruby/internal/abi.h"
|
abi_header = "#{rubyhdrdir}/ruby/internal/abi.h"
|
||||||
|
|
||||||
if RbConfig::CONFIG["ENABLE_SHARED"] == "yes"
|
|
||||||
# below is defined since 2.1, except for mswin, and maybe other platforms
|
|
||||||
libdirname = RbConfig::CONFIG.fetch 'libdirname', 'libdir'
|
|
||||||
libruby = "#{RbConfig::CONFIG[libdirname]}/#{RbConfig::CONFIG['LIBRUBY']}"
|
|
||||||
end
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
mtime = File.mtime(lib)
|
mtime = File.mtime(lib)
|
||||||
rescue Errno::ENOENT
|
rescue Errno::ENOENT
|
||||||
|
@ -49,7 +43,6 @@ def compile_extension(name)
|
||||||
when mtime <= File.mtime("#{spec_ext_dir}/#{ext}.c")
|
when mtime <= File.mtime("#{spec_ext_dir}/#{ext}.c")
|
||||||
when mtime <= File.mtime(ruby_header)
|
when mtime <= File.mtime(ruby_header)
|
||||||
when (mtime <= File.mtime(abi_header) rescue nil)
|
when (mtime <= File.mtime(abi_header) rescue nil)
|
||||||
when libruby && mtime <= File.mtime(libruby)
|
|
||||||
else
|
else
|
||||||
return lib # up-to-date
|
return lib # up-to-date
|
||||||
end
|
end
|
||||||
|
|
|
@ -155,6 +155,10 @@ class TestBacktrace < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_each_backtrace_location
|
def test_each_backtrace_location
|
||||||
|
assert_nil(Thread.each_caller_location {})
|
||||||
|
|
||||||
|
assert_raise(LocalJumpError) {Thread.each_caller_location}
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
cl = caller_locations(1, 1)[0]; ecl = Thread.each_caller_location{|x| i+=1; break x if i == 1}
|
cl = caller_locations(1, 1)[0]; ecl = Thread.each_caller_location{|x| i+=1; break x if i == 1}
|
||||||
assert_equal(cl.to_s, ecl.to_s)
|
assert_equal(cl.to_s, ecl.to_s)
|
||||||
|
@ -181,6 +185,10 @@ class TestBacktrace < Test::Unit::TestCase
|
||||||
assert_raise(StopIteration) {
|
assert_raise(StopIteration) {
|
||||||
ecl.next
|
ecl.next
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ary = []
|
||||||
|
cl = caller_locations(1, 2); Thread.each_caller_location(1, 2) {|x| ary << x}
|
||||||
|
assert_equal(cl.map(&:to_s), ary.map(&:to_s))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_caller_locations_first_label
|
def test_caller_locations_first_label
|
||||||
|
|
|
@ -1170,17 +1170,17 @@ rb_make_backtrace(void)
|
||||||
return rb_ec_backtrace_str_ary(GET_EC(), BACKTRACE_START, ALL_BACKTRACE_LINES);
|
return rb_ec_backtrace_str_ary(GET_EC(), BACKTRACE_START, ALL_BACKTRACE_LINES);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static long
|
||||||
ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *argv, int lev_default, int lev_plus, int to_str)
|
ec_backtrace_range(const rb_execution_context_t *ec, int argc, const VALUE *argv, int lev_default, int lev_plus, long *len_ptr)
|
||||||
{
|
{
|
||||||
VALUE level, vn;
|
VALUE level, vn, opts;
|
||||||
long lev, n;
|
long lev, n;
|
||||||
VALUE btval;
|
|
||||||
VALUE r;
|
|
||||||
int too_large;
|
|
||||||
|
|
||||||
rb_scan_args(argc, argv, "02", &level, &vn);
|
rb_scan_args(argc, argv, "02:", &level, &vn, &opts);
|
||||||
|
|
||||||
|
if (!NIL_P(opts)) {
|
||||||
|
rb_get_kwargs(opts, (ID []){0}, 0, 0, NULL);
|
||||||
|
}
|
||||||
if (argc == 2 && NIL_P(vn)) argc--;
|
if (argc == 2 && NIL_P(vn)) argc--;
|
||||||
|
|
||||||
switch (argc) {
|
switch (argc) {
|
||||||
|
@ -1201,7 +1201,7 @@ ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *arg
|
||||||
n = ALL_BACKTRACE_LINES;
|
n = ALL_BACKTRACE_LINES;
|
||||||
break;
|
break;
|
||||||
case Qnil:
|
case Qnil:
|
||||||
return Qnil;
|
return -1;
|
||||||
default:
|
default:
|
||||||
lev = beg + lev_plus;
|
lev = beg + lev_plus;
|
||||||
n = len;
|
n = len;
|
||||||
|
@ -1225,6 +1225,20 @@ ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *arg
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*len_ptr = n;
|
||||||
|
return lev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *argv, int lev_default, int lev_plus, int to_str)
|
||||||
|
{
|
||||||
|
long lev, n;
|
||||||
|
VALUE btval, r;
|
||||||
|
int too_large;
|
||||||
|
|
||||||
|
lev = ec_backtrace_range(ec, argc, argv, lev_default, lev_plus, &n);
|
||||||
|
if (lev < 0) return Qnil;
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
return rb_ary_new();
|
return rb_ary_new();
|
||||||
}
|
}
|
||||||
|
@ -1354,15 +1368,19 @@ rb_f_caller_locations(int argc, VALUE *argv, VALUE _)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* Thread.each_caller_location{ |loc| ... } -> nil
|
* Thread.each_caller_location(...) { |loc| ... } -> nil
|
||||||
*
|
*
|
||||||
* Yields each frame of the current execution stack as a
|
* Yields each frame of the current execution stack as a
|
||||||
* backtrace location object.
|
* backtrace location object.
|
||||||
*/
|
*/
|
||||||
static VALUE
|
static VALUE
|
||||||
each_caller_location(VALUE unused)
|
each_caller_location(int argc, VALUE *argv, VALUE _)
|
||||||
{
|
{
|
||||||
rb_ec_partial_backtrace_object(GET_EC(), 2, ALL_BACKTRACE_LINES, NULL, FALSE, TRUE);
|
rb_execution_context_t *ec = GET_EC();
|
||||||
|
long n, lev = ec_backtrace_range(ec, argc, argv, 1, 1, &n);
|
||||||
|
if (lev >= 0 && n != 0) {
|
||||||
|
rb_ec_partial_backtrace_object(ec, lev, n, NULL, FALSE, TRUE);
|
||||||
|
}
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1442,7 +1460,7 @@ Init_vm_backtrace(void)
|
||||||
rb_define_global_function("caller", rb_f_caller, -1);
|
rb_define_global_function("caller", rb_f_caller, -1);
|
||||||
rb_define_global_function("caller_locations", rb_f_caller_locations, -1);
|
rb_define_global_function("caller_locations", rb_f_caller_locations, -1);
|
||||||
|
|
||||||
rb_define_singleton_method(rb_cThread, "each_caller_location", each_caller_location, 0);
|
rb_define_singleton_method(rb_cThread, "each_caller_location", each_caller_location, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* debugger API */
|
/* debugger API */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче