Created
February 12, 2013 21:08
-
-
Save headius/4773409 to your computer and use it in GitHub Desktop.
Example of Binding.of_caller in JRuby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ext-jruby-local ~/projects/jruby $ jruby -X-C -S irb | |
irb(main):001:0> def foo | |
irb(main):002:1> a = 1 | |
irb(main):003:1> bar | |
irb(main):004:1> puts a | |
irb(main):005:1> end | |
=> nil | |
irb(main):006:0> def bar | |
irb(main):007:1> eval 'a = 2', Binding.of_caller(1) | |
irb(main):008:1> end | |
=> nil | |
irb(main):009:0> foo | |
2 | |
=> nil |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/org/jruby/RubyBinding.java b/src/org/jruby/RubyBinding.java | |
index 13ee964..6e5d5a5 100644 | |
--- a/src/org/jruby/RubyBinding.java | |
+++ b/src/org/jruby/RubyBinding.java | |
@@ -133,4 +133,10 @@ public class RubyBinding extends RubyObject { | |
return RubyKernel.eval(context, this, newArgs, Block.NULL_BLOCK); | |
} | |
+ | |
+ @JRubyMethod(meta = true) | |
+ public static IRubyObject of_caller(ThreadContext context, IRubyObject self, IRubyObject level) { | |
+ Binding binding = context.bindingOfCaller((int)level.convertToInteger().getLongValue()); | |
+ return new RubyBinding(context.runtime, (RubyClass)self, binding); | |
+ } | |
} | |
diff --git a/src/org/jruby/runtime/ThreadContext.java b/src/org/jruby/runtime/ThreadContext.java | |
index b811b3e..dbe0889 100644 | |
--- a/src/org/jruby/runtime/ThreadContext.java | |
+++ b/src/org/jruby/runtime/ThreadContext.java | |
@@ -1276,6 +1276,22 @@ public final class ThreadContext { | |
} | |
/** | |
+ * Return a binding representing call state from the specified levels above | |
+ * the current call. This will generally produce unpredictable results when | |
+ * JRuby's compiler optimizations are active since compiled calls will omit | |
+ * some or all of this state. | |
+ * | |
+ * @return the binding at the specified level above the current call | |
+ */ | |
+ public Binding bindingOfCaller(int level) { | |
+ // FIXME: no bounds check | |
+ Frame frame = frameStack[frameIndex - level]; | |
+ DynamicScope scope = scopeStack[scopeIndex - level]; | |
+ BacktraceElement element = backtrace[backtraceIndex - level]; | |
+ return new Binding(frame, scope.getStaticScope().getModule(), scope, element.clone()); | |
+ } | |
+ | |
+ /** | |
* Return a binding representing the previous call's state but with a specified self | |
* @param self the self object to use | |
* @return the current binding, using the specified self |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment