Class: AppMap::Handler::Eval
- Inherits:
-
Function
- Object
- AppMap::Hook::Method
- Function
- AppMap::Handler::Eval
- Defined in:
- lib/appmap/handler/eval.rb
Overview
Handler class for Kernel#eval.
Second argument to eval is a Binding, which despite the name (and the accessible methods) in addition to locals and receiver also encapsulates the entire execution context, in particular including the lexical scope. This is especially important for constant lookup and definition.
If the binding is not provided, by default eval will run in the
current frame. Since we call it here, this will mean the #do_call
frame, which would make AppMap::Handler::Eval the lexical scope
for constant lookup and definition; as a consequence
eg. eval "class Foo; end" would define
AppMap::Handler::Eval::Foo instead of defining it in
the module where the original call was made.
To avoid this, we explicitly substitute the correct execution context, up several stack frames.
Constant Summary collapse
- FRAME_DEPTH =
The depth of the frame we need to pluck out:
- Hook::Method#do_call
- Hook::Method#trace_call
- Hook::Method#call
- proc generated by Hook::Method#hook_method_def
- the (intended) frame of the original eval that we hooked Note it needs to be adjusted if this call sequence changes.
5
Instance Attribute Summary
Attributes inherited from AppMap::Hook::Method
#arity, #hook_class, #hook_method, #hook_package, #parameters
Instance Method Summary collapse
Methods inherited from Function
Methods inherited from AppMap::Hook::Method
Constructor Details
This class inherits a constructor from AppMap::Hook::Method
Instance Method Details
#do_call(receiver, src = nil, context = nil, *rest) ⇒ Object
35 36 37 38 |
# File 'lib/appmap/handler/eval.rb', line 35 def do_call(receiver, src = nil, context = nil, *rest) context ||= AppMap.caller_binding FRAME_DEPTH hook_method.bind(receiver).call(src, context, *rest) end |