From d8579acf28acca6ed021abfa91ce6d3a598a35b7 Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Tue, 12 Jun 2012 03:44:50 -0500 Subject: [PATCH] create a context with a Ruby object as its scope --- lib/v8.rb | 3 ++- lib/v8/context.rb | 18 ++++++++++++++++-- lib/v8/conversion/object.rb | 14 +++++++++----- lib/v8/util/weakcell.rb | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 lib/v8/util/weakcell.rb diff --git a/lib/v8.rb b/lib/v8.rb index b6d36da..cff7787 100644 --- a/lib/v8.rb +++ b/lib/v8.rb @@ -19,4 +19,5 @@ require 'v8/access/indices' require 'v8/access' require 'v8/context' require 'v8/object' -require 'v8/array' \ No newline at end of file +require 'v8/array' +require 'v8/util/weakcell' \ No newline at end of file diff --git a/lib/v8/context.rb b/lib/v8/context.rb index 6ce336d..f2a1729 100644 --- a/lib/v8/context.rb +++ b/lib/v8/context.rb @@ -2,10 +2,24 @@ module V8 class Context attr_reader :native, :conversion, :access - def initialize - @native = V8::C::Context::New() + def initialize(options = {}) @conversion = Conversion.new @access = Access.new + if global = options[:with] + V8::C::Locker() do + V8::C::HandleScope() do + tmp = V8::C::Context::New() + tmp.Enter() + global_template = global.to_v8_template + tmp.Exit() + @native = V8::C::Context::New(nil, global_template) + enter { link global, @native.Global() } + end + end + else + @native = V8::C::Context::New() + end + yield self if block_given? end def to_ruby(v8_object) diff --git a/lib/v8/conversion/object.rb b/lib/v8/conversion/object.rb index f18b792..3a5019c 100644 --- a/lib/v8/conversion/object.rb +++ b/lib/v8/conversion/object.rb @@ -1,11 +1,15 @@ class V8::Conversion module Object def to_v8 - template = V8::C::ObjectTemplate::New() - template.SetNamedPropertyHandler(Get, Set, nil, nil, nil, V8::C::External::New(self)) - instance = template.NewInstance() - V8::Context.link self, instance - return instance + object = to_v8_template.NewInstance() + V8::Context.link self, object + return object + end + + def to_v8_template + V8::C::ObjectTemplate::New().tap do |template| + template.SetNamedPropertyHandler(Get, Set, nil, nil, nil, V8::C::External::New(self)) + end end def to_ruby diff --git a/lib/v8/util/weakcell.rb b/lib/v8/util/weakcell.rb new file mode 100644 index 0000000..bc0e9c6 --- /dev/null +++ b/lib/v8/util/weakcell.rb @@ -0,0 +1,32 @@ +require 'weakref' +module V8 + module Util + module Weakcell + def weakcell(name, &block) + unless storage = instance_variable_get("@#{name}") + storage = instance_variable_set("@#{name}", Storage.new) + end + storage.access(&block) + end + class Storage + def access(&block) + if @ref + @ref.__getobj__ + else + populate(block) + end + rescue RefError + populate(block) + end + + private + + def populate(block) + occupant = block.call() + @ref = WeakRef.new(occupant) + return occupant + end + end + end + end +end \ No newline at end of file