Issue #15778 has been updated by Eregon (Benoit Daloze).


> This is current situation.

Thanks for the summary.

> For example, if people rely on Binding.of_caller, we can't use delegation code freely.

I think it's fair enough for usages of Binding.of_caller to have to care about this.

@ko1 The `debug_inspector` gem just makes the Bindings of the stack available to Ruby code, so if somebody wants to use them in application code they already can (but agreed it's very rarely good to do so).
My opinion is it's not valuable to "hide" such capabilities by moving them to C extensions, because they are still easy to access if one wants them (i.e., it's easy to write a C ext or add debug_inspector as dependency).

The fact that `binding_of_caller` is used in the wild shows that it's not because a C-API is needed that it's not or less used.
https://github.com/banister/binding_of_caller/network/dependents

I think rather we should just document these methods are meant for debugging and might slow down execution significantly, and therefore should not be used in application code.
Maybe a good way too to indicate that further than documentation is having a clear namespace, such as e.g., `::DebugInspector` or `::Debugging`.
Then it's fairly clear this is only meant for debugging.

https://github.com/banister/debug_inspector#usage clearly shows having Thread::Backtrace::Location#binding is a natural fit.
Is there any use-case for `frame_iseq`? That's obviously going to be MRI-specific, isn't?
Can `frame_class` be derived from the Binding? Is it like `Module.nesting.first`?

I think we should really aim to have portable debugging APIs if we want Ruby tooling to improve.
And therefore, they must be defined in Ruby (it doesn't make much sense for JRuby to implement a C API).

@ko1 What do you think of the new API `caller_locations(debug: true)` + `Thread::Backtrace::Location#binding`, doesn't it make perfect sense?
We would of course document that the `:debug` keyword should only be used for debugging, and `Thread::Backtrace::Location#binding` would raise an ArgumentError if `:debug` is not given.

----------------------------------------
Feature #15778: Expose an API to pry-open the stack frames in Ruby
https://bugs.ruby-lang.org/issues/15778#change-77777

* Author: gsamokovarov (Genadi Samokovarov)
* Status: Open
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
* Target version: 
----------------------------------------
Hello,

I'm the maintainer of the web-console (https://github.com/rails/web-console/) gem, where one of our features is to jump between the frames in which an error occurred. To accomplish this, I currently use the Debug Inspector CRuby API. I think we should expose this functionality in Rubyland, so tools like web-console don't need to resort to C code for this. This also makes it quite harder for me to support different implementations like JRuby or TruffleRuby as everyone is having a different way to create Ruby Binding objects that represent the frames.

Here the API ideas:

Add `Thread::Backtrace::Location#binding` method that can create a binding for a specific caller of the current frame. We can reuse the existing `Kernel.caller_locations` method to generate the array of `Thread::Backtrace::Location` objects. We can optionally have the `Kernel.caller_locations(debug: true)` argument if we cannot generate the bindings lazily on the VM that can instruct the VM to do the slower operation.

- `Thread::Backtrace::Location#binding` returns `Binding|nil`. Nil result may mean that the current location is a C frame or a JITted/optimized frame and we cannot debug it.

We can also expose the DebugInspector API directly, as done in the https://github.com/banister/debug_inspector gem, but for tools like web-console, we'd need to map the bindings with the backtrace, as we cannot generate Bindings for every frame (C frames) and this needs to be done in application code, so I think the `Thread::Backtrace::Location#binding` is the better API for Ruby-land.

Such API can help us eventually write most of our debuggers in Ruby as right now we don't have a way to do Post-Mortem debugging without native code or even start our debuggers without monkey-patching `Binding`.

I have presented this idea in a RubyKaigi's 2019 talk called "Writing Debuggers in Plain Ruby", you can check-out the slides for more context: http://kaigi-debuggers-in-ruby.herokuapp.com.



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>