Question

Once I store a method in a V8::Context, all subsequent instances of that method stored in any context under any name behave like the initial one (i.e. as if the original instance had been stored again).

I tried to isolate/demonstrate the problem with the following:

require 'V8'

class TestClass
  def test_method
    self.inspect
  end
end

(1..2).each do |cxt_i|
  cxt = V8::Context.new
  [:test_method, :test_method2].each_with_index do |method_name, method_i|
    method = TestClass.new.method(:test_method)
    cxt[method_name.to_s] = method
    script = method_name.to_s+'()'
    puts "Context #{cxt_i}, method #{method_i+1} result is #{method.call}, V8 returns #{cxt.eval(script)}"
  end
end

Which produces the following output:

Context 1, method 1 result is #<TestClass:0x007fce2419cdb0>, V8 returns #<TestClass:0x007fce2419cdb0>
Context 1, method 2 result is #<TestClass:0x007fce2419b780>, V8 returns #<TestClass:0x007fce2419cdb0>
Context 2, method 1 result is #<TestClass:0x007fce2419abc8>, V8 returns #<TestClass:0x007fce2419cdb0>
Context 2, method 2 result is #<TestClass:0x007fce24199a98>, V8 returns #<TestClass:0x007fce2419cdb0>
Was it helpful?

Solution

It's a weak reference issue. By inserting a GC.start inside the inner loop, we force the weak references in the V8 context to be garbage collected. Slows it down immensely though.

require 'v8'

class TestClass
  def test_method
    self.inspect
  end
end

(1..2).each do |cxt_i|
  cxt = V8::Context.new
  [:test_method, :test_method2].each_with_index do |method_name, method_i|
    method = TestClass.new.method(:test_method)
    cxt[method_name.to_s] = method
    script = method_name.to_s+'()'
    puts "Context #{cxt_i}, method #{method_i+1} result is #{method.call}, V8 returns #{cxt.eval(script)}"
    GC.start # <<<<=========
  end
end

Output:

Context 1, method 1 result is #<TestClass:0x007f8f13a26cd8>, V8 returns #<TestClass:0x007f8f13a26cd8>
Context 1, method 2 result is #<TestClass:0x007f8f135cca48>, V8 returns #<TestClass:0x007f8f135cca48>
Context 2, method 1 result is #<TestClass:0x007f8f135ceac8>, V8 returns #<TestClass:0x007f8f135ceac8>
Context 2, method 2 result is #<TestClass:0x007f8f135cdbf0>, V8 returns #<TestClass:0x007f8f135cdbf0>

ruby -v is ruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-linux], libv8 is 3.11.8.17 x86_64-linux

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top