therubyracer 0.10.2 → 0.11.0beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of therubyracer might be problematic. Click here for more details.
- data/.gitignore +21 -11
- data/.travis.yml +2 -1
- data/Changelog.md +46 -0
- data/Gemfile +16 -1
- data/README.md +31 -13
- data/Rakefile +42 -23
- data/benchmarks.rb +217 -0
- data/ext/v8/accessor.cc +181 -0
- data/ext/v8/array.cc +26 -0
- data/ext/v8/backref.cc +56 -0
- data/ext/v8/build.rb +51 -0
- data/ext/v8/constants.cc +34 -0
- data/ext/v8/constraints.cc +52 -0
- data/ext/v8/context.cc +130 -0
- data/ext/v8/date.cc +18 -0
- data/ext/v8/exception.cc +38 -0
- data/ext/v8/extconf.rb +14 -18
- data/ext/v8/external.cc +43 -0
- data/ext/v8/function.cc +58 -0
- data/ext/v8/gc.cc +43 -0
- data/ext/v8/handles.cc +34 -0
- data/ext/v8/heap.cc +31 -0
- data/ext/v8/init.cc +39 -0
- data/ext/v8/invocation.cc +86 -0
- data/ext/v8/locker.cc +77 -0
- data/ext/v8/message.cc +51 -0
- data/ext/v8/object.cc +334 -0
- data/ext/v8/primitive.cc +8 -0
- data/ext/v8/rr.cc +83 -0
- data/ext/v8/rr.h +878 -36
- data/ext/v8/script.cc +80 -0
- data/ext/v8/signature.cc +18 -0
- data/ext/v8/stack.cc +75 -0
- data/ext/v8/string.cc +47 -0
- data/ext/v8/template.cc +175 -0
- data/ext/v8/trycatch.cc +86 -0
- data/ext/v8/v8.cc +87 -0
- data/ext/v8/value.cc +239 -0
- data/lib/v8.rb +30 -22
- data/lib/v8/access.rb +5 -87
- data/lib/v8/access/indices.rb +40 -0
- data/lib/v8/access/invocation.rb +47 -0
- data/lib/v8/access/names.rb +65 -0
- data/lib/v8/array.rb +19 -10
- data/lib/v8/context.rb +85 -78
- data/lib/v8/conversion.rb +35 -0
- data/lib/v8/conversion/array.rb +11 -0
- data/lib/v8/conversion/class.rb +120 -0
- data/lib/v8/conversion/code.rb +38 -0
- data/lib/v8/conversion/fundamental.rb +11 -0
- data/lib/v8/conversion/hash.rb +11 -0
- data/lib/v8/conversion/indentity.rb +31 -0
- data/lib/v8/conversion/method.rb +26 -0
- data/lib/v8/conversion/object.rb +28 -0
- data/lib/v8/conversion/primitive.rb +7 -0
- data/lib/v8/conversion/proc.rb +5 -0
- data/lib/v8/conversion/reference.rb +16 -0
- data/lib/v8/conversion/string.rb +12 -0
- data/lib/v8/conversion/symbol.rb +7 -0
- data/lib/v8/conversion/time.rb +13 -0
- data/lib/v8/error.rb +18 -123
- data/lib/v8/error/protect.rb +20 -0
- data/lib/v8/error/try.rb +15 -0
- data/lib/v8/function.rb +18 -34
- data/lib/v8/object.rb +48 -52
- data/lib/v8/util/weakcell.rb +29 -0
- data/lib/v8/version.rb +2 -2
- data/spec/c/array_spec.rb +17 -0
- data/spec/c/constants_spec.rb +20 -0
- data/spec/c/exception_spec.rb +26 -0
- data/spec/c/external_spec.rb +9 -0
- data/spec/c/function_spec.rb +46 -0
- data/spec/c/handles_spec.rb +35 -0
- data/spec/c/locker_spec.rb +38 -0
- data/spec/c/object_spec.rb +46 -0
- data/spec/c/script_spec.rb +28 -0
- data/spec/c/string_spec.rb +16 -0
- data/spec/c/template_spec.rb +30 -0
- data/spec/c/trycatch_spec.rb +51 -0
- data/spec/mem/blunt_spec.rb +42 -0
- data/spec/redjs_spec.rb +10 -0
- data/spec/spec_helper.rb +40 -4
- data/spec/threading_spec.rb +52 -0
- data/spec/v8/context_spec.rb +19 -0
- data/spec/v8/conversion_spec.rb +9 -0
- data/spec/v8/error_spec.rb +15 -125
- data/spec/v8/function_spec.rb +9 -0
- data/therubyracer.gemspec +15 -24
- metadata +102 -135
- data/.gitmodules +0 -3
- data/.rspec +0 -1
- data/.yardopts +0 -1
- data/bin/therubyracer +0 -11
- data/ext/v8/rr.cpp +0 -189
- data/ext/v8/v8.cpp +0 -48
- data/ext/v8/v8_array.cpp +0 -48
- data/ext/v8/v8_array.h +0 -8
- data/ext/v8/v8_callbacks.cpp +0 -81
- data/ext/v8/v8_callbacks.h +0 -8
- data/ext/v8/v8_context.cpp +0 -92
- data/ext/v8/v8_context.h +0 -6
- data/ext/v8/v8_date.cpp +0 -34
- data/ext/v8/v8_date.h +0 -6
- data/ext/v8/v8_debug.cpp +0 -17
- data/ext/v8/v8_debug.h +0 -6
- data/ext/v8/v8_exception.cpp +0 -133
- data/ext/v8/v8_exception.h +0 -11
- data/ext/v8/v8_external.cpp +0 -70
- data/ext/v8/v8_external.h +0 -8
- data/ext/v8/v8_function.cpp +0 -69
- data/ext/v8/v8_function.h +0 -11
- data/ext/v8/v8_handle.cpp +0 -186
- data/ext/v8/v8_handle.h +0 -48
- data/ext/v8/v8_locker.cpp +0 -139
- data/ext/v8/v8_locker.h +0 -6
- data/ext/v8/v8_message.cpp +0 -67
- data/ext/v8/v8_message.h +0 -10
- data/ext/v8/v8_object.cpp +0 -122
- data/ext/v8/v8_object.h +0 -10
- data/ext/v8/v8_script.cpp +0 -36
- data/ext/v8/v8_script.h +0 -8
- data/ext/v8/v8_string.cpp +0 -52
- data/ext/v8/v8_string.h +0 -9
- data/ext/v8/v8_template.cpp +0 -344
- data/ext/v8/v8_template.h +0 -8
- data/ext/v8/v8_try_catch.cpp +0 -70
- data/ext/v8/v8_try_catch.h +0 -5
- data/ext/v8/v8_v8.cpp +0 -35
- data/ext/v8/v8_v8.h +0 -6
- data/ext/v8/v8_value.cpp +0 -175
- data/ext/v8/v8_value.h +0 -10
- data/ext/v8/v8_weakref.cpp +0 -61
- data/ext/v8/v8_weakref.h +0 -29
- data/lib/v8/c/locker.rb +0 -18
- data/lib/v8/cli.rb +0 -133
- data/lib/v8/portal.rb +0 -86
- data/lib/v8/portal/caller.rb +0 -37
- data/lib/v8/portal/constructor.rb +0 -98
- data/lib/v8/portal/function.rb +0 -63
- data/lib/v8/portal/interceptors.rb +0 -152
- data/lib/v8/portal/proxies.rb +0 -151
- data/lib/v8/portal/templates.rb +0 -73
- data/lib/v8/stack.rb +0 -66
- data/lib/v8/tap.rb +0 -9
- data/spec/ext/array_spec.rb +0 -15
- data/spec/ext/cxt_spec.rb +0 -57
- data/spec/ext/ext_spec_helper.rb +0 -27
- data/spec/ext/func_spec.rb +0 -64
- data/spec/ext/object_spec.rb +0 -10
- data/spec/ext/string_spec.rb +0 -11
- data/spec/ext/try_catch_spec.rb +0 -60
- data/spec/redjs_helper.rb +0 -3
- data/spec/v8/portal/proxies_spec.rb +0 -106
- data/specmem/handle_memspec.rb +0 -41
- data/specmem/object_memspec.rb +0 -14
- data/specmem/proxies_memspec.rb +0 -49
- data/specmem/spec_helper.rb +0 -24
- data/specthread/spec_helper.rb +0 -2
- data/specthread/threading_spec.rb +0 -13
data/lib/v8/portal.rb
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
|
2
|
-
module V8
|
3
|
-
class Portal
|
4
|
-
attr_reader :context, :access, :proxies, :templates, :interceptors, :caller
|
5
|
-
|
6
|
-
def initialize(context, access)
|
7
|
-
@context, @access = context, access
|
8
|
-
@proxies = Proxies.new
|
9
|
-
@templates = Templates.new(self)
|
10
|
-
@interceptors = Interceptors.new(self)
|
11
|
-
@caller = Caller.new(self)
|
12
|
-
end
|
13
|
-
|
14
|
-
def lock
|
15
|
-
lock = V8::C::Locker.new
|
16
|
-
yield
|
17
|
-
ensure
|
18
|
-
lock.delete
|
19
|
-
end
|
20
|
-
|
21
|
-
def open
|
22
|
-
lock do
|
23
|
-
@context.native.enter do
|
24
|
-
yield(self)
|
25
|
-
end if block_given?
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def rb(value)
|
30
|
-
@proxies.js2rb(value) do
|
31
|
-
case value
|
32
|
-
when V8::C::Function then V8::Function.new(value, self)
|
33
|
-
when V8::C::Array then V8::Array.new(value, self)
|
34
|
-
when V8::C::Object then V8::Object.new(value, self)
|
35
|
-
when V8::C::String then value.Utf8Value.tap {|s| return s.respond_to?(:force_encoding) ? s.force_encoding("UTF-8") : s}
|
36
|
-
when V8::C::Date then Time.at(value.NumberValue() / 1000)
|
37
|
-
when V8::C::StackTrace then V8::StackTrace.new(self, value)
|
38
|
-
when V8::C::Value then nil if value.IsEmpty()
|
39
|
-
else
|
40
|
-
value
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def v8(value)
|
46
|
-
case value
|
47
|
-
when V8::Object
|
48
|
-
value.instance_eval {@native}
|
49
|
-
when String
|
50
|
-
C::String::New(value)
|
51
|
-
when Symbol
|
52
|
-
C::String::NewSymbol(value.to_s)
|
53
|
-
when Proc,Method,UnboundMethod
|
54
|
-
@proxies.rb2js(value) do
|
55
|
-
@templates.to_function(value).function
|
56
|
-
end
|
57
|
-
when ::Array
|
58
|
-
C::Array::New(value.length).tap do |a|
|
59
|
-
value.each_with_index do |item, i|
|
60
|
-
a.Set(i, v8(item))
|
61
|
-
end
|
62
|
-
end
|
63
|
-
when ::Hash
|
64
|
-
C::Object::New().tap do |o|
|
65
|
-
value.each do |key, val|
|
66
|
-
o.Set(v8(key), v8(val))
|
67
|
-
end
|
68
|
-
end
|
69
|
-
when ::Time
|
70
|
-
C::Date::New(value.to_f * 1000)
|
71
|
-
when ::Class
|
72
|
-
@proxies.rb2js(value) do
|
73
|
-
constructor = @templates.to_constructor(value)
|
74
|
-
constructor.exposed = true
|
75
|
-
constructor.function
|
76
|
-
end
|
77
|
-
when nil,Numeric,TrueClass,FalseClass, C::Value
|
78
|
-
value
|
79
|
-
else
|
80
|
-
@proxies.rb2js(value) do
|
81
|
-
@templates.to_constructor(value.class).allocate(value)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
data/lib/v8/portal/caller.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
|
2
|
-
module V8
|
3
|
-
class Portal
|
4
|
-
class Caller
|
5
|
-
|
6
|
-
def initialize(portal)
|
7
|
-
@portal = portal
|
8
|
-
end
|
9
|
-
|
10
|
-
def raw
|
11
|
-
yield
|
12
|
-
rescue Exception => e
|
13
|
-
case e
|
14
|
-
when SystemExit, NoMemoryError
|
15
|
-
raise e
|
16
|
-
else
|
17
|
-
error = V8::C::Exception::Error(V8::C::String::New(e.message))
|
18
|
-
#TODO: This is almost certainly a crash here.
|
19
|
-
#we need to hold onto `error` while it bubbles up the javascript stack.
|
20
|
-
error.SetHiddenValue("TheRubyRacer::Cause", C::External::New(e))
|
21
|
-
V8::C::ThrowException(error)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def protect(*args, &block)
|
26
|
-
@portal.v8 raw(*args, &block)
|
27
|
-
end
|
28
|
-
|
29
|
-
def invoke(code, *args, &block)
|
30
|
-
protect do
|
31
|
-
args = args.slice(0, code.arity) if code.arity >= 0
|
32
|
-
code.call(*args, &block)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,98 +0,0 @@
|
|
1
|
-
|
2
|
-
module V8
|
3
|
-
class Portal
|
4
|
-
class ConstructorAdapter
|
5
|
-
attr_reader :template, :exposed
|
6
|
-
alias_method :exposed?, :exposed
|
7
|
-
|
8
|
-
def initialize(templates, class_id)
|
9
|
-
@exposed = false
|
10
|
-
@class_id = class_id
|
11
|
-
@templates = templates
|
12
|
-
@invoke = method(:invoke)
|
13
|
-
@template = C::FunctionTemplate::New(@invoke)
|
14
|
-
portal.interceptors.setup(@template.InstanceTemplate())
|
15
|
-
cls = self.ruby_class
|
16
|
-
superclass = cls.superclass
|
17
|
-
if cls != ::Object && superclass != ::Object && superclass != ::Class
|
18
|
-
@template.Inherit(templates.to_constructor(superclass).template)
|
19
|
-
end
|
20
|
-
if cls.name && cls.name =~ /(::)?(\w+?)$/
|
21
|
-
template.SetClassName(C::String::NewSymbol("rb::" + $2))
|
22
|
-
else
|
23
|
-
template.SetClassName("Ruby")
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def function
|
28
|
-
@template.GetFunction()
|
29
|
-
end
|
30
|
-
|
31
|
-
def allocate(object)
|
32
|
-
arguments = C::Array::New(1)
|
33
|
-
arguments.Set(0, C::External::New(object))
|
34
|
-
function.NewInstance(arguments)
|
35
|
-
end
|
36
|
-
|
37
|
-
def disable
|
38
|
-
@disabled = true
|
39
|
-
end
|
40
|
-
|
41
|
-
def enable
|
42
|
-
@disabled = nil
|
43
|
-
end
|
44
|
-
|
45
|
-
def invoke(arguments)
|
46
|
-
return if @disabled
|
47
|
-
if !@exposed
|
48
|
-
unless arguments.Length() == 1 && arguments[0].kind_of?(C::External)
|
49
|
-
C::ThrowException(C::Exception::Error(C::String::New("cannot call native constructor from javascript")))
|
50
|
-
else
|
51
|
-
object = arguments[0].Value()
|
52
|
-
proxies.register_javascript_proxy arguments.This(), :for => object
|
53
|
-
end
|
54
|
-
else
|
55
|
-
instance = nil
|
56
|
-
if arguments.Length() > 0 && arguments[0].kind_of?(C::External)
|
57
|
-
instance = arguments[0].Value()
|
58
|
-
else
|
59
|
-
rbargs = []
|
60
|
-
for i in 0..arguments.Length() - 1
|
61
|
-
rbargs << @templates.portal.rb(arguments[i])
|
62
|
-
end
|
63
|
-
instance = portal.caller.raw do
|
64
|
-
self.ruby_class.new(*rbargs)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
proxies.register_javascript_proxy arguments.This(), :for => instance
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def exposed=(exposed)
|
72
|
-
if exposed && !@augmented
|
73
|
-
#create a prototype so that this constructor also acts like a ruby object
|
74
|
-
prototype_template = C::ObjectTemplate::New()
|
75
|
-
portal.interceptors.setup(prototype_template)
|
76
|
-
prototype = prototype_template.NewInstance()
|
77
|
-
#set *that* object's prototype to an empty function so that it will look and behave like a function.
|
78
|
-
prototype.SetPrototype(C::FunctionTemplate::New().GetFunction())
|
79
|
-
template.GetFunction().SetPrototype(prototype)
|
80
|
-
@augmented = true
|
81
|
-
end
|
82
|
-
@exposed = exposed
|
83
|
-
end
|
84
|
-
|
85
|
-
def ruby_class
|
86
|
-
ObjectSpace._id2ref(@class_id)
|
87
|
-
end
|
88
|
-
|
89
|
-
def proxies
|
90
|
-
@templates.proxies
|
91
|
-
end
|
92
|
-
|
93
|
-
def portal
|
94
|
-
@templates.portal
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
data/lib/v8/portal/function.rb
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
module V8
|
2
|
-
class Portal
|
3
|
-
class FunctionAdapter
|
4
|
-
|
5
|
-
attr_reader :template
|
6
|
-
|
7
|
-
def initialize(portal, code)
|
8
|
-
@portal = portal
|
9
|
-
@caller = case code
|
10
|
-
when Method then BoundCall.new(portal)
|
11
|
-
when UnboundMethod then BindAndCall.new(portal)
|
12
|
-
else Call.new(portal)
|
13
|
-
end
|
14
|
-
@code = code
|
15
|
-
@template = V8::C::FunctionTemplate::New(@caller, @code)
|
16
|
-
end
|
17
|
-
|
18
|
-
def function
|
19
|
-
@template.GetFunction()
|
20
|
-
end
|
21
|
-
|
22
|
-
class Call
|
23
|
-
def initialize(portal)
|
24
|
-
@portal = portal
|
25
|
-
end
|
26
|
-
|
27
|
-
def call(arguments)
|
28
|
-
proc = arguments.Data()
|
29
|
-
rbargs = [@portal.rb(arguments.This())]
|
30
|
-
for i in 0..arguments.Length() - 1
|
31
|
-
rbargs << @portal.rb(arguments[i])
|
32
|
-
end
|
33
|
-
@portal.caller.invoke(proc, *rbargs)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
class BoundCall < Call
|
38
|
-
def call(arguments)
|
39
|
-
proc = arguments.Data()
|
40
|
-
rbargs = []
|
41
|
-
for i in 0..arguments.Length() - 1
|
42
|
-
rbargs << @portal.rb(arguments[i])
|
43
|
-
end
|
44
|
-
@portal.caller.invoke(proc, *rbargs)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
class BindAndCall < Call
|
49
|
-
def call(arguments)
|
50
|
-
method = arguments.Data()
|
51
|
-
rbargs = []
|
52
|
-
for i in 0..arguments.Length() - 1
|
53
|
-
rbargs << @portal.rb(arguments[i])
|
54
|
-
end
|
55
|
-
this = @portal.rb(arguments.This())
|
56
|
-
@portal.caller.protect do
|
57
|
-
method.bind(this).call(*rbargs)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,152 +0,0 @@
|
|
1
|
-
module V8
|
2
|
-
class Portal
|
3
|
-
class Interceptors
|
4
|
-
def initialize(portal)
|
5
|
-
@getter = NamedPropertyGetter.new(portal)
|
6
|
-
@setter = NamedPropertySetter.new(portal)
|
7
|
-
@query = nil
|
8
|
-
@deleter = nil
|
9
|
-
@enumerator = NamedPropertyEnumerator.new(portal)
|
10
|
-
@igetter = IndexedPropertyGetter.new(portal)
|
11
|
-
@isetter = IndexedPropertySetter.new(portal)
|
12
|
-
@iquery = nil
|
13
|
-
@ideleter = nil
|
14
|
-
@ienumerator = IndexedPropertyEnumerator.new(portal)
|
15
|
-
end
|
16
|
-
|
17
|
-
def setup(template)
|
18
|
-
template.SetNamedPropertyHandler(@getter,@setter,@query,@deleter,@enumerator, nil)
|
19
|
-
template.SetIndexedPropertyHandler(@igetter,@isetter,@iquery,@ideleter,@ienumerator, nil)
|
20
|
-
end
|
21
|
-
|
22
|
-
class PropertyAttributes
|
23
|
-
attr_reader :flags
|
24
|
-
def initialize
|
25
|
-
@flags = 0
|
26
|
-
end
|
27
|
-
|
28
|
-
def read_only
|
29
|
-
tap do
|
30
|
-
@flags |= V8::C::ReadOnly
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def dont_enum
|
35
|
-
tap do
|
36
|
-
@flags |= V8::C::DontEnum
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def dont_delete
|
41
|
-
tap do
|
42
|
-
@flags |= V8::C::DontDelete
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
class Interceptor
|
48
|
-
|
49
|
-
def initialize(portal)
|
50
|
-
@to, @access = portal, portal.access
|
51
|
-
end
|
52
|
-
|
53
|
-
def intercept(info, retval = nil, &code)
|
54
|
-
obj = @to.rb(info.This())
|
55
|
-
intercepts = true
|
56
|
-
result = @to.caller.protect do
|
57
|
-
dontintercept = proc do
|
58
|
-
intercepts = false
|
59
|
-
end
|
60
|
-
code.call(obj, dontintercept)
|
61
|
-
end
|
62
|
-
intercepts ? (retval || result) : C::Empty
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
class NamedPropertyGetter < Interceptor
|
67
|
-
def call(property, info)
|
68
|
-
intercept(info) do |obj, dontintercept|
|
69
|
-
@access.get(obj, @to.rb(property), &dontintercept)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
class NamedPropertySetter < Interceptor
|
75
|
-
def call(property, value, info)
|
76
|
-
intercept(info, value) do |obj, dontintercept|
|
77
|
-
@access.set(obj, @to.rb(property), @to.rb(value), &dontintercept)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
class NamedPropertyQuery
|
83
|
-
def call(property, info)
|
84
|
-
attributes = PropertyAttributes.new
|
85
|
-
result = intercept(info) do |obj, dontintercept|
|
86
|
-
@access.query(obj, @to.rb(property), attributes, &dontintercept)
|
87
|
-
end
|
88
|
-
return result == C::Empty ? result : C::Integer::New(attributes.flags)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
class NamedPropertyEnumerator < Interceptor
|
93
|
-
def call(info)
|
94
|
-
intercept(info) do |obj, dontintercept|
|
95
|
-
@access.names(obj, &dontintercept).to_a
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
class NamedPropertyDeleter < Interceptor
|
101
|
-
def call(property, info)
|
102
|
-
intercept(info) do |obj, dontintercept|
|
103
|
-
@access.delete(obj, property, &dontintercept)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
class IndexedPropertyGetter < Interceptor
|
109
|
-
def call(index, info)
|
110
|
-
intercept(info) do |obj, dontintercept|
|
111
|
-
@access.iget(obj, index, &dontintercept)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
class IndexedPropertySetter < Interceptor
|
117
|
-
def call(index, value, info)
|
118
|
-
intercept(info, value) do |obj, dontintercept|
|
119
|
-
@access.iset(obj, index, @to.rb(value), &dontintercept)
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
class IndexedPropertyQuery < Interceptor
|
125
|
-
def call(property, info)
|
126
|
-
attributes = PropertyAttributes.new
|
127
|
-
result = intercept(info) do |obj, dontintercept|
|
128
|
-
@access.indices(obj, &dontintercept)
|
129
|
-
end
|
130
|
-
result == C::Empty ? C::Empty : C::Integer::New(attributes.flags)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
class IndexedPropertyDeleter < Interceptor
|
135
|
-
def call(index, info)
|
136
|
-
intercept(info) do |obj, dontintercept|
|
137
|
-
@access.idelete(obj, index, &dontintercept)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
class IndexedPropertyEnumerator < Interceptor
|
143
|
-
def call(info)
|
144
|
-
intercept(info) do |obj, dontintercept|
|
145
|
-
@access.indices(obj, &dontintercept)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
data/lib/v8/portal/proxies.rb
DELETED
@@ -1,151 +0,0 @@
|
|
1
|
-
module V8
|
2
|
-
class Portal
|
3
|
-
class Proxies
|
4
|
-
|
5
|
-
def initialize
|
6
|
-
@js_proxies_rb2js = {}
|
7
|
-
@js_proxies_js2rb = {}
|
8
|
-
@rb_proxies_rb2js = {}
|
9
|
-
@rb_proxies_js2rb = {}
|
10
|
-
@clear_js_proxy = ClearJSProxy.new(@js_proxies_rb2js, @js_proxies_js2rb)
|
11
|
-
@clear_rb_proxy = ClearRubyProxy.new(@rb_proxies_rb2js, @rb_proxies_js2rb)
|
12
|
-
end
|
13
|
-
|
14
|
-
def js2rb(js)
|
15
|
-
if rb = js_proxy_2_rb_object(js)
|
16
|
-
return rb
|
17
|
-
elsif rb = js_object_2_rb_proxy(js)
|
18
|
-
return rb
|
19
|
-
else
|
20
|
-
proxy = block_given? ? yield(js) : Object.new
|
21
|
-
register_ruby_proxy proxy, :for => js if proxy && js && js.kind_of?(V8::C::Handle)
|
22
|
-
return proxy
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def rb2js(rb)
|
27
|
-
if js = rb_proxy_2_js_object(rb)
|
28
|
-
return js
|
29
|
-
elsif js = rb_object_2_js_proxy(rb)
|
30
|
-
return js
|
31
|
-
else
|
32
|
-
proxy = block_given? ? yield(rb) : V8::C::Object::New()
|
33
|
-
register_javascript_proxy proxy, :for => rb unless @js_proxies_rb2js[rb]
|
34
|
-
return proxy
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def register_javascript_proxy(proxy, options = {})
|
39
|
-
target = options[:for] or fail ArgumentError, "must specify the object that you're proxying with the :for => param"
|
40
|
-
fail ArgumentError, "javascript proxy must be a V8::C::Handle, not #{proxy.class}" unless proxy.kind_of?(V8::C::Handle)
|
41
|
-
fail DoubleProxyError, "target already has a registered proxy" if @js_proxies_rb2js[target]
|
42
|
-
|
43
|
-
@js_proxies_js2rb[proxy] = target
|
44
|
-
@js_proxies_rb2js[target] = proxy
|
45
|
-
proxy.MakeWeak(nil, @clear_js_proxy)
|
46
|
-
end
|
47
|
-
|
48
|
-
# Lookup the JavaScript proxy for a natively Ruby object
|
49
|
-
# @param [Object] object the Ruby object
|
50
|
-
# @return [V8::C::Handle] the JavaScript proxy representing `object`
|
51
|
-
def rb_object_2_js_proxy(object)
|
52
|
-
@js_proxies_rb2js[object]
|
53
|
-
end
|
54
|
-
|
55
|
-
# Look up a natively Ruby object given its JavaScript proxy
|
56
|
-
# @param [V8::C::Handle] proxy the JavaScript proxy
|
57
|
-
# @return [Object] the Ruby object represented by `proxy`
|
58
|
-
def js_proxy_2_rb_object(proxy)
|
59
|
-
@js_proxies_js2rb[proxy]
|
60
|
-
end
|
61
|
-
|
62
|
-
def register_ruby_proxy(proxy, options = {})
|
63
|
-
target = options[:for] or fail ArgumentError, "must specify the object that you're proxying with the :for => param"
|
64
|
-
fail ArgumentError, "'#{proxy.inspect}' is not a Handle to an actual V8 object" unless target.kind_of?(V8::C::Handle)
|
65
|
-
@rb_proxies_rb2js[proxy.object_id] = target
|
66
|
-
@rb_proxies_js2rb[target] = proxy.object_id
|
67
|
-
ObjectSpace.define_finalizer(proxy, @clear_rb_proxy)
|
68
|
-
end
|
69
|
-
|
70
|
-
# Looks up the Ruby proxy for an object that is natively JavaScript
|
71
|
-
# @param [V8::C::Handle] object the JavaScript whose proxy we want
|
72
|
-
# @return [Object] the Ruby proxy for `object`
|
73
|
-
def js_object_2_rb_proxy(object)
|
74
|
-
if id = @rb_proxies_js2rb[object]
|
75
|
-
ObjectSpace._id2ref id
|
76
|
-
end
|
77
|
-
rescue RangeError
|
78
|
-
# sometimes, the Ruby proxy has been garbage collected, but
|
79
|
-
# the finalizer which runs has not been called. That's OK
|
80
|
-
# we just clear out the entry, and return nil so that a new
|
81
|
-
# proxy can be created.
|
82
|
-
@clear_rb_proxy.call(id)
|
83
|
-
return nil
|
84
|
-
end
|
85
|
-
|
86
|
-
# Looks up a native JavaScript object by its Ruby proxy
|
87
|
-
# @param [Object] proxy the Ruby proxy
|
88
|
-
# @return [V8::C::Handle] the native JavaScript object
|
89
|
-
def rb_proxy_2_js_object(proxy)
|
90
|
-
@rb_proxies_rb2js[proxy.object_id]
|
91
|
-
end
|
92
|
-
|
93
|
-
def js_empty?
|
94
|
-
@js_proxies_rb2js.empty? && @js_proxies_js2rb.empty?
|
95
|
-
end
|
96
|
-
|
97
|
-
def rb_empty?
|
98
|
-
@rb_proxies_rb2js.empty? && @rb_proxies_js2rb.empty?
|
99
|
-
end
|
100
|
-
|
101
|
-
def empty?
|
102
|
-
js_empty? && rb_empty?
|
103
|
-
end
|
104
|
-
DoubleProxyError = Class.new(StandardError)
|
105
|
-
|
106
|
-
class ClearJSProxy
|
107
|
-
|
108
|
-
def initialize(rb2js, js2rb)
|
109
|
-
@rb2js, @js2rb = rb2js, js2rb
|
110
|
-
end
|
111
|
-
|
112
|
-
def call(proxy, parameter)
|
113
|
-
rb = @js2rb[proxy]
|
114
|
-
@js2rb.delete(proxy)
|
115
|
-
@rb2js.delete(rb)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# @Private
|
120
|
-
# Remove the linkage between a Ruby proxy and a native
|
121
|
-
# JavaScript object. In general, this object is registered
|
122
|
-
# as a finalizer on the Ruby proxy itself, so that when it is
|
123
|
-
# garbage collected, it releases the back reference to the
|
124
|
-
# native JavaScript object.
|
125
|
-
#
|
126
|
-
# It is important to do this as soon as is reasonably possible
|
127
|
-
# so that the native JavaScript object can itself be garbage
|
128
|
-
# collected (provided there are no other references to it)
|
129
|
-
class ClearRubyProxy
|
130
|
-
def initialize(rb2js, js2rb)
|
131
|
-
@rb2js, @js2rb = rb2js, js2rb
|
132
|
-
end
|
133
|
-
|
134
|
-
# takes the object id of a Ruby proxy that has been garbage collected
|
135
|
-
# and releases the reference to the native JavaScript object that
|
136
|
-
# it was bound to.
|
137
|
-
# @param[Fixnum] proxy_id the proxy id of the garbage collected Ruby proxy
|
138
|
-
def call(proxy_id)
|
139
|
-
# TODO: this if-check should be synchronized, so that if called manually
|
140
|
-
# it will not conflict with the finalization thread. It's not so heinous
|
141
|
-
# if the refererence gets cleared twice, but we definiteily dont't want
|
142
|
-
# to double-decrement the v8 GC hint.
|
143
|
-
if js = @rb2js[proxy_id]
|
144
|
-
@rb2js.delete(proxy_id)
|
145
|
-
@js2rb.delete(js)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|