Skip to content

Commit

Permalink
Use target obj as self for instance_eval. Fixes #2301.
Browse files Browse the repository at this point in the history
  • Loading branch information
headius committed Apr 6, 2015
1 parent 870f979 commit 7774be5
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 9 deletions.
6 changes: 3 additions & 3 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -1574,7 +1574,7 @@ public IRubyObject instance_exec19(ThreadContext context, IRubyObject[] args, Bl
* with this implementation.
*/
protected IRubyObject yieldUnder(final ThreadContext context, RubyModule under, IRubyObject[] args, Block block) {
context.preExecuteUnder(under, block);
context.preExecuteUnder(this, under, block);

IRubyObject savedBindingSelf = block.getBinding().getSelf();
IRubyObject savedFrameSelf = block.getBinding().getFrame().getSelf();
Expand Down Expand Up @@ -1616,7 +1616,7 @@ private Block setupBlock(Block block) {
* with this implementation.
*/
protected IRubyObject yieldUnder(final ThreadContext context, RubyModule under, Block block) {
context.preExecuteUnder(under, block);
context.preExecuteUnder(this, under, block);

IRubyObject savedBindingSelf = block.getBinding().getSelf();
IRubyObject savedFrameSelf = block.getBinding().getFrame().getSelf();
Expand Down Expand Up @@ -1759,7 +1759,7 @@ protected RubyModule getInstanceEvalClass() {
public IRubyObject evalUnder(final ThreadContext context, RubyModule under, RubyString src, String file, int line) {
Visibility savedVisibility = context.getCurrentVisibility();
context.setCurrentVisibility(PUBLIC);
context.preExecuteUnder(under, Block.NULL_BLOCK);
context.preExecuteUnder(this, under, Block.NULL_BLOCK);
try {
return ASTInterpreter.evalSimple(context, this, src,
file, line);
Expand Down
11 changes: 5 additions & 6 deletions core/src/main/java/org/jruby/runtime/ThreadContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -1176,20 +1176,19 @@ public void postNodeEval() {
popFrame();
popRubyClass();
}

// XXX: Again, screwy evaling under previous frame's scope
public void preExecuteUnder(RubyModule executeUnderClass, Block block) {

public void preExecuteUnder(IRubyObject self, RubyModule executeUnderClass, Block block) {
Frame frame = getCurrentFrame();

pushRubyClass(executeUnderClass);
DynamicScope scope = getCurrentScope();
StaticScope sScope = runtime.getStaticScopeFactory().newBlockScope(scope.getStaticScope());
sScope.setModule(executeUnderClass);
pushScope(DynamicScope.newDynamicScope(sScope, scope));
pushCallFrame(frame.getKlazz(), frame.getName(), frame.getSelf(), block);
pushCallFrame(frame.getKlazz(), frame.getName(), self, block);
getCurrentFrame().setVisibility(getPreviousFrame().getVisibility());
}

public void postExecuteUnder() {
popFrame();
popScope();
Expand Down
13 changes: 13 additions & 0 deletions spec/regression/GH-2301_instance_eval_uses_target_as_self_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
describe "Object#instance_eval" do
it "uses the target object as self in the executed code" do
o = Object.new
o.instance_variable_set :@foo, 1
newself, binding = o.instance_eval "[self, binding]"
expect(newself).to eq(o)
expect(eval('self', binding)).to eq(self)

newself, binding = o.instance_eval {[self, binding]}
expect(newself).to eq(o)
expect(eval('self', binding)).to eq(self)
end
end

0 comments on commit 7774be5

Please sign in to comment.