Project

General

Profile

Bug #1769

eval with binding, without location

Added by yugui (Yuki Sonoda) over 10 years ago. Updated over 8 years ago.

Status:
Closed
Priority:
Normal
Target version:
ruby -v:
ruby 1.9.2dev (2009-07-13 trunk 24067) [i386-darwin9.7.0]
Backport:
[ruby-dev:38767]

Description

=begin
evalの第3, 4引数を省略した際にbindingが持っているfile, lineが伝播しなく
なっています。これは意図したことでしょうか。
irbのバックトレースがこれのためにちょっと不親切になっています。

% cat test.rb
b = binding
p eval("FILE", b)

b = eval('binding', TOPLEVEL_BINDING, FILE, LINE)
p eval("FILE", b)

% ruby18 -v test.rb
ruby 1.8.7 (2009-04-08 patchlevel 160) [i686-darwin9]
"test.rb"
"test.rb"

% ruby-trunk -v test.rb
ruby 1.9.2dev (2009-07-13 trunk 24067) [i386-darwin9.7.0]
"(eval)"
"(eval)"

--
Yugui yugui@yugui.jp
http://yugui.jp
私は私をDumpする
=end


Related issues

Is duplicate of Ruby master - Bug #2782: Binding#eval not completely indicative of its bindingClosed02/23/2010Actions

History

#1

Updated by yugui (Yuki Sonoda) over 10 years ago

  • Assignee set to ko1 (Koichi Sasada)
  • Target version set to 1.9.2
  • ruby -v set to ruby 1.9.2dev (2009-07-13 trunk 24067) [i386-darwin9.7.0]

=begin

=end

#2

Updated by yugui (Yuki Sonoda) over 10 years ago

  • Priority changed from 3 to Normal

=begin

=end

#3

Updated by mame (Yusuke Endoh) over 9 years ago

  • Assignee changed from ko1 (Koichi Sasada) to mame (Yusuke Endoh)

=begin
遠藤です。

evalの第3, 4引数を省略した際にbindingが持っているfile, lineが伝播しなく
なっています。これは意図したことでしょうか。

rb_binding_t にファイル名と行番号を持たせてみました。
bootstraptest/test_eval.rb に 1 か所、rubyspec に 4 箇所修正を
加えた上で、make check と make test-rubyspec を通過しました。

反対がなければコミットします。

diff --git a/bootstraptest/test_eval.rb b/bootstraptest/test_eval.rb
index c5ab953..9ae50a6 100644
--- a/bootstraptest/test_eval.rb
+++ b/bootstraptest/test_eval.rb
@@ -287,7 +287,7 @@ assert_normal_exit %q{
eval("", method(:proc).call {}.binding)
}

-assert_equal "(eval):1:in `block in ': ", %q{
+assert_equal "", %q{
b = binding
10.times{
eval('', b)
diff --git a/proc.c b/proc.c
index 7e8e0e1..035897c 100644
--- a/proc.c
+++ b/proc.c
@@ -254,6 +254,7 @@ binding_mark(void *ptr)
if (ptr) {
bind = ptr;
RUBY_MARK_UNLESS_NULL(bind->env);

  • RUBY_MARK_UNLESS_NULL(bind->filename); } RUBY_MARK_LEAVE("binding"); } @@ -289,6 +290,8 @@ binding_dup(VALUE self) GetBindingPtr(self, src); GetBindingPtr(bindval, dst); dst->env = src->env;
  • dst->filename = src->filename;
  • dst->line_no = src->line_no; return bindval; }

@@ -315,6 +318,8 @@ rb_binding_new(void)

  GetBindingPtr(bindval, bind);
  bind->env = rb_vm_make_env_object(th, cfp);
  • bind->filename = cfp->iseq->filename;
  • bind->line_no = rb_vm_get_sourceline(cfp); return bindval; }

@@ -1893,6 +1898,8 @@ proc_binding(VALUE self)
bindval = binding_alloc(rb_cBinding);
GetBindingPtr(bindval, bind);
bind->env = proc->envval;

  • bind->filename = proc->block.iseq->filename;
  • bind->line_no = rb_iseq_first_lineno(proc->block.iseq); return bindval; }

diff --git a/vm_core.h b/vm_core.h
index b5c1bf0..15f7c59 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -519,6 +519,8 @@ typedef struct {

typedef struct {
VALUE env;

  • VALUE filename;
  • unsigned short line_no; } rb_binding_t;

/* used by compile time and send insn */
diff --git a/vm_eval.c b/vm_eval.c
index fefe6d6..9806762 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -963,6 +963,10 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char
if (rb_obj_is_kind_of(scope, rb_cBinding)) {
GetBindingPtr(scope, bind);
envval = bind->env;

  • if (strcmp(file, "(eval)") == 0) {
  • file = RSTRING_PTR(bind->filename);
  • line = bind->line_no;
  • } } else { rb_raise(rb_eTypeError,

rubyspec 側のパッチ:

diff --git a/core/kernel/caller_spec.rb b/core/kernel/caller_spec.rb
index 3ecde8a..923a1ec 100644
--- a/core/kernel/caller_spec.rb
+++ b/core/kernel/caller_spec.rb
@@ -93,7 +93,7 @@ describe "Kernel#caller in a Proc or eval" do
ruby_version_is "1.9" do
it "returns the definition trace of a block when evaluated in a Proc binding" do
stack = CallerFixture.caller_of(CallerFixture.block)

  • stack[0].should == "(eval):1:in `'"
  •  stack[0].should =~ /caller_fixture1\.rb:4:in `<top \(required\)>'/
    stack[1].should =~ /caller_fixture2\.rb:18:in `eval'/
    stack[2].should =~ /caller_fixture2\.rb:18:in `caller_of'/
    stack[3].should =~ /caller_spec\.rb:95:in `block \(3 levels\) in <top \(required\)>'/
    

    @@ -101,7 +101,7 @@ describe "Kernel#caller in a Proc or eval" do

    it "returns the definition trace of a Proc" do
    stack = CallerFixture.caller_of(CallerFixture.example_proc)

  •  stack[0].should == "(eval):1:in `example_proc'"
    
  •  stack[0].should =~ /caller_fixture1\.rb:14:in `example_proc'/
    stack[1].should =~ /caller_fixture2\.rb:18:in `eval'/
    stack[2].should =~ /caller_fixture2\.rb:18:in `caller_of'/
    stack[3].should =~ /caller_spec\.rb:103:in `block \(3 levels\) in <top \(required\)>'/
    

    @@ -119,7 +119,7 @@ describe "Kernel#caller in a Proc or eval" do
    # the correct behaviour
    it "returns the correct definition line for a complex Proc trace" do
    stack = CallerFixture.caller_of(CallerFixture.entry_point)

  •  stack[0].should == "(eval):1:in `third'"
    
  •  stack[0].should =~ /caller_fixture1\.rb:29:in `third'/
    stack[1].should =~ /caller_fixture2\.rb:18:in `eval'/
    stack[2].should =~ /caller_fixture2\.rb:18:in `caller_of'/
    stack[3].should =~ /caller_spec.rb:121:in `block \(3 levels\) in <top \(required\)>'/
    

    diff --git a/core/kernel/eval_spec.rb b/core/kernel/eval_spec.rb
    index 187c8f3..4bc731b 100644
    --- a/core/kernel/eval_spec.rb
    +++ b/core/kernel/eval_spec.rb
    @@ -252,26 +252,13 @@ describe "Kernel#eval" do
    end
    end

  • ruby_version_is ""..."1.9" do

  • it "uses the filename of the binding if none is provided" do

  •  eval("__FILE__").should == "(eval)"
    
  •  eval("__FILE__", binding).should == __FILE__
    
  •  eval("__FILE__", binding, "success").should == "success"
    
  •  eval("eval '__FILE__', binding").should == "(eval)"
    
  •  eval("eval '__FILE__', binding", binding).should == __FILE__
    
  •  eval("eval '__FILE__', binding", binding, 'success').should == 'success'
    
  • end

  • end

  • ruby_version_is "1.9" do

  • it "uses a filename of (eval) if none is provided" do

  •  eval("__FILE__").should == "(eval)"
    
  •  eval("__FILE__", binding).should == "(eval)"
    
  •  eval("__FILE__", binding, "success").should == "success"
    
  •  eval("eval '__FILE__', binding").should == "(eval)"
    
  •  eval("eval '__FILE__', binding", binding).should == "(eval)"
    
  •  eval("eval '__FILE__', binding", binding, 'success').should == '(eval)'
    
  • end

  • it "uses the filename of the binding if none is provided" do

  • eval("FILE").should == "(eval)"

  • eval("FILE", binding).should == FILE

  • eval("FILE", binding, "success").should == "success"

  • eval("eval 'FILE', binding").should == "(eval)"

  • eval("eval 'FILE', binding", binding).should == FILE

  • eval("eval 'FILE', binding", binding, 'success').should == 'success'
    end

    Found via Rubinius bug github:#149

--
Yusuke Endoh mame@tsg.ne.jp
=end

#4

Updated by mame (Yusuke Endoh) over 9 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

=begin
This issue was solved with changeset r27716.
Yuki, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

Also available in: Atom PDF