mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
Automatically lock v8 whenever performing any JavaScript operation.
This commit is contained in:
parent
12b58f3289
commit
0d3bf45af4
7 changed files with 65 additions and 44 deletions
|
@ -25,6 +25,7 @@ extern "C" {
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void Init_v8() {
|
void Init_v8() {
|
||||||
|
v8::Locker locker;
|
||||||
rr_init_handle();
|
rr_init_handle();
|
||||||
rr_init_context();
|
rr_init_context();
|
||||||
rr_init_value();
|
rr_init_value();
|
||||||
|
|
|
@ -7,24 +7,26 @@ module V8
|
||||||
def initialize(opts = {})
|
def initialize(opts = {})
|
||||||
@access = Access.new
|
@access = Access.new
|
||||||
@to = Portal.new(self, @access)
|
@to = Portal.new(self, @access)
|
||||||
with = opts[:with]
|
@to.lock do
|
||||||
constructor = nil
|
with = opts[:with]
|
||||||
template = if with
|
constructor = nil
|
||||||
constructor = @to.templates.to_constructor(with.class)
|
template = if with
|
||||||
constructor.disable()
|
constructor = @to.templates.to_constructor(with.class)
|
||||||
constructor.template.InstanceTemplate()
|
constructor.disable()
|
||||||
else
|
constructor.template.InstanceTemplate()
|
||||||
C::ObjectTemplate::New()
|
else
|
||||||
|
C::ObjectTemplate::New()
|
||||||
|
end
|
||||||
|
@native = opts[:with] ? C::Context::New(template) : C::Context::New()
|
||||||
|
@native.enter do
|
||||||
|
@global = @native.Global()
|
||||||
|
@to.proxies.register_javascript_proxy @global, :for => with if with
|
||||||
|
constructor.enable() if constructor
|
||||||
|
@scope = @to.rb(@global)
|
||||||
|
@global.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyContext"), C::External::New(self))
|
||||||
|
end
|
||||||
|
yield(self) if block_given?
|
||||||
end
|
end
|
||||||
@native = opts[:with] ? C::Context::New(template) : C::Context::New()
|
|
||||||
@native.enter do
|
|
||||||
@global = @native.Global()
|
|
||||||
@to.proxies.register_javascript_proxy @global, :for => with if with
|
|
||||||
constructor.enable() if constructor
|
|
||||||
@scope = @to.rb(@global)
|
|
||||||
@global.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyContext"), C::External::New(self))
|
|
||||||
end
|
|
||||||
yield(self) if block_given?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def eval(javascript, filename = "<eval>", line = 1)
|
def eval(javascript, filename = "<eval>", line = 1)
|
||||||
|
@ -33,17 +35,19 @@ module V8
|
||||||
end
|
end
|
||||||
err = nil
|
err = nil
|
||||||
value = nil
|
value = nil
|
||||||
C::TryCatch.try do |try|
|
@to.lock do
|
||||||
@native.enter do
|
C::TryCatch.try do |try|
|
||||||
script = C::Script::Compile(@to.v8(javascript.to_s), @to.v8(filename.to_s))
|
@native.enter do
|
||||||
if try.HasCaught()
|
script = C::Script::Compile(@to.v8(javascript.to_s), @to.v8(filename.to_s))
|
||||||
err = JSError.new(try, @to)
|
|
||||||
else
|
|
||||||
result = script.Run()
|
|
||||||
if try.HasCaught()
|
if try.HasCaught()
|
||||||
err = JSError.new(try, @to)
|
err = JSError.new(try, @to)
|
||||||
else
|
else
|
||||||
value = @to.rb(result)
|
result = script.Run()
|
||||||
|
if try.HasCaught()
|
||||||
|
err = JSError.new(try, @to)
|
||||||
|
else
|
||||||
|
value = @to.rb(result)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
module V8
|
module V8
|
||||||
class Function < V8::Object
|
class Function < V8::Object
|
||||||
|
|
||||||
def methodcall(thisObject, *args)
|
def methodcall(thisObject, *args)
|
||||||
err = nil
|
err = nil
|
||||||
return_value = nil
|
return_value = nil
|
||||||
C::TryCatch.try do |try|
|
@portal.open do |to|
|
||||||
@portal.open do |to|
|
C::TryCatch.try do |try|
|
||||||
this = to.v8(thisObject)
|
this = to.v8(thisObject)
|
||||||
return_value = to.rb(@native.Call(this, to.v8(args)))
|
return_value = to.rb(@native.Call(this, to.v8(args)))
|
||||||
err = JSError.new(try, to) if try.HasCaught()
|
err = JSError.new(try, to) if try.HasCaught()
|
||||||
|
@ -14,11 +14,13 @@ module V8
|
||||||
raise err if err
|
raise err if err
|
||||||
return return_value
|
return return_value
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(*args)
|
def call(*args)
|
||||||
self.methodcall(@portal.context.native.Global(), *args)
|
@portal.open do
|
||||||
|
self.methodcall(@portal.context.native.Global(), *args)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def new(*args)
|
def new(*args)
|
||||||
@portal.open do |to|
|
@portal.open do |to|
|
||||||
to.rb(@native.NewInstance(to.v8(args)))
|
to.rb(@native.NewInstance(to.v8(args)))
|
||||||
|
|
|
@ -11,10 +11,19 @@ module V8
|
||||||
@caller = Caller.new(self)
|
@caller = Caller.new(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def lock
|
||||||
|
lock = V8::C::Locker.new
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
lock.delete
|
||||||
|
end
|
||||||
|
|
||||||
def open
|
def open
|
||||||
@context.native.enter do
|
lock do
|
||||||
yield(self)
|
@context.native.enter do
|
||||||
end if block_given?
|
yield(self)
|
||||||
|
end if block_given?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def rb(value)
|
def rb(value)
|
||||||
|
|
|
@ -3,7 +3,10 @@ require "#{File.dirname(__FILE__)}/../spec_helper.rb"
|
||||||
|
|
||||||
include V8
|
include V8
|
||||||
|
|
||||||
describe C::Context do
|
describe C::Context do
|
||||||
|
|
||||||
|
before {@lock = C::Locker.new}
|
||||||
|
after {@lock.delete}
|
||||||
|
|
||||||
it "should not have a current context if no context is open" do
|
it "should not have a current context if no context is open" do
|
||||||
C::Context::GetEntered().should be_nil
|
C::Context::GetEntered().should be_nil
|
||||||
|
@ -26,11 +29,11 @@ describe C::Context do
|
||||||
function one() {
|
function one() {
|
||||||
return two();
|
return two();
|
||||||
}
|
}
|
||||||
|
|
||||||
function two() {
|
function two() {
|
||||||
return three();
|
return three();
|
||||||
}
|
}
|
||||||
|
|
||||||
function three() {
|
function three() {
|
||||||
return getTrace()
|
return getTrace()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,14 @@ module V8::ExtSpec
|
||||||
def self.included(object)
|
def self.included(object)
|
||||||
object.class_eval do
|
object.class_eval do
|
||||||
before do
|
before do
|
||||||
|
@lock = c::Locker.new
|
||||||
@cxt = c::Context::New()
|
@cxt = c::Context::New()
|
||||||
@cxt.Enter()
|
@cxt.Enter()
|
||||||
end
|
end
|
||||||
after do
|
after do
|
||||||
@cxt.Exit()
|
@cxt.Exit()
|
||||||
@cxt.Dispose()
|
@cxt.Dispose()
|
||||||
|
@lock.delete
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,25 +4,25 @@ include V8
|
||||||
|
|
||||||
describe C::TryCatch do
|
describe C::TryCatch do
|
||||||
|
|
||||||
before {@cxt = C::Context::New()}
|
before {@lock = C::Locker.new;@cxt = C::Context::New();}
|
||||||
after {@cxt.Dispose()}
|
after {@cxt.Dispose(); @lock.delete}
|
||||||
|
|
||||||
it "does not allow instance creation by default" do
|
it "does not allow instance creation by default" do
|
||||||
lambda {
|
lambda {
|
||||||
C::TryCatch.new
|
C::TryCatch.new
|
||||||
}.should raise_error
|
}.should raise_error
|
||||||
end
|
end
|
||||||
|
|
||||||
it "will do nothing if not passed a block" do
|
it "will do nothing if not passed a block" do
|
||||||
C::TryCatch.try.should == nil
|
C::TryCatch.try.should == nil
|
||||||
end
|
end
|
||||||
|
|
||||||
it "executes a block in the context of a C++ stack frame" do
|
it "executes a block in the context of a C++ stack frame" do
|
||||||
C::TryCatch.try do |catch|
|
C::TryCatch.try do |catch|
|
||||||
catch.HasCaught().should be(false)
|
catch.HasCaught().should be(false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "raises an erro if you try to access it outside of its scope" do
|
it "raises an erro if you try to access it outside of its scope" do
|
||||||
tc = C::TryCatch.try do |catch|
|
tc = C::TryCatch.try do |catch|
|
||||||
catch.tap {}
|
catch.tap {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue