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
@@ -0,0 +1,40 @@
|
|
1
|
+
class V8::Access
|
2
|
+
module Indices
|
3
|
+
|
4
|
+
def indices(obj)
|
5
|
+
obj.respond_to?(:length) ? (0..obj.length).to_a : []
|
6
|
+
end
|
7
|
+
|
8
|
+
def iget(obj, index, &dontintercept)
|
9
|
+
if obj.respond_to?(:[])
|
10
|
+
obj.send(:[], index, &dontintercept)
|
11
|
+
else
|
12
|
+
yield
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def iset(obj, index, value, &dontintercept)
|
17
|
+
if obj.respond_to?(:[]=)
|
18
|
+
obj.send(:[]=, index, value, &dontintercept)
|
19
|
+
else
|
20
|
+
yield
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def iquery(obj, index, attributes, &dontintercept)
|
25
|
+
if obj.respond_to?(:[])
|
26
|
+
attributes.dont_delete
|
27
|
+
unless obj.respond_to?(:[]=)
|
28
|
+
attributes.read_only
|
29
|
+
end
|
30
|
+
else
|
31
|
+
yield
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def idelete(obj, index, &dontintercept)
|
36
|
+
yield
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class V8::Access
|
2
|
+
module Invocation
|
3
|
+
def methodcall(code, this, args)
|
4
|
+
code.methodcall this, args
|
5
|
+
end
|
6
|
+
|
7
|
+
module Aritize
|
8
|
+
def aritize(args)
|
9
|
+
arity < 0 ? args : Array.new(arity).to_enum(:each_with_index).map {|item, i| args[i]}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Proc
|
14
|
+
include Aritize
|
15
|
+
def methodcall(this, args)
|
16
|
+
call *aritize([this].concat(args))
|
17
|
+
end
|
18
|
+
::Proc.send :include, self
|
19
|
+
end
|
20
|
+
|
21
|
+
module Method
|
22
|
+
include Aritize
|
23
|
+
def methodcall(this, args)
|
24
|
+
context = V8::Context.current
|
25
|
+
access = context.access
|
26
|
+
if this.equal? self.receiver
|
27
|
+
call *aritize(args)
|
28
|
+
elsif this.class <= self.receiver.class
|
29
|
+
access.methodcall(unbind, this, args)
|
30
|
+
elsif this.equal? context.scope
|
31
|
+
call *aritize(args)
|
32
|
+
else
|
33
|
+
fail TypeError, "cannot invoke #{self} on #{this}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
::Method.send :include, self
|
37
|
+
end
|
38
|
+
|
39
|
+
module UnboundMethod
|
40
|
+
def methodcall(this, args)
|
41
|
+
access = V8::Context.current.access
|
42
|
+
access.methodcall bind(this), this, args
|
43
|
+
end
|
44
|
+
::UnboundMethod.send :include, self
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'set'
|
2
|
+
class V8::Access
|
3
|
+
module Names
|
4
|
+
def names(obj)
|
5
|
+
accessible_names(obj)
|
6
|
+
end
|
7
|
+
|
8
|
+
def get(obj, name, &dontintercept)
|
9
|
+
methods = accessible_names(obj)
|
10
|
+
if methods.include?(name)
|
11
|
+
method = obj.method(name)
|
12
|
+
method.arity == 0 ? method.call : method.unbind
|
13
|
+
elsif obj.respond_to?(:[]) && !special?(name)
|
14
|
+
obj.send(:[], name, &dontintercept)
|
15
|
+
else
|
16
|
+
yield
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def set(obj, name, value, &dontintercept)
|
21
|
+
setter = name + "="
|
22
|
+
methods = accessible_names(obj, true)
|
23
|
+
if methods.include?(setter)
|
24
|
+
obj.send(setter, value)
|
25
|
+
elsif obj.respond_to?(:[]=) && !special?(name)
|
26
|
+
obj.send(:[]=, name, value, &dontintercept)
|
27
|
+
else
|
28
|
+
yield
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def query(obj, name, attributes, &dontintercept)
|
33
|
+
if obj.respond_to?(name)
|
34
|
+
attributes.dont_delete
|
35
|
+
unless obj.respond_to?(name + "=")
|
36
|
+
attributes.read_only
|
37
|
+
end
|
38
|
+
else
|
39
|
+
yield
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete(obj, name, &dontintercept)
|
44
|
+
yield
|
45
|
+
end
|
46
|
+
|
47
|
+
def accessible_names(obj, special_methods = false)
|
48
|
+
obj.public_methods(false).map {|m| m.to_s}.to_set.tap do |methods|
|
49
|
+
ancestors = obj.class.ancestors.dup
|
50
|
+
while ancestor = ancestors.shift
|
51
|
+
break if ancestor == ::Object
|
52
|
+
methods.merge(ancestor.public_instance_methods(false).map {|m| m.to_s})
|
53
|
+
end
|
54
|
+
methods.reject!(&special?) unless special_methods
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def special?(name = nil)
|
61
|
+
@special ||= lambda {|m| m == "[]" || m == "[]=" || m =~ /=$/}
|
62
|
+
name.nil? ? @special : @special[name]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/v8/array.rb
CHANGED
@@ -1,17 +1,26 @@
|
|
1
|
+
class V8::Array < V8::Object
|
1
2
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
def initialize(native_or_length = nil)
|
4
|
+
super do
|
5
|
+
if native_or_length.is_a?(Numeric)
|
6
|
+
V8::C::Array::New(native_or_length)
|
7
|
+
elsif native_or_length.is_a?(V8::C::Array)
|
8
|
+
native_or_length
|
9
|
+
else
|
10
|
+
V8::C::Array::New()
|
10
11
|
end
|
11
12
|
end
|
13
|
+
end
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
+
def each
|
16
|
+
@context.enter do
|
17
|
+
0.upto(@native.Length() - 1) do |i|
|
18
|
+
yield @context.to_ruby(@native.Get(i))
|
19
|
+
end
|
15
20
|
end
|
16
21
|
end
|
22
|
+
|
23
|
+
def length
|
24
|
+
@native.Length()
|
25
|
+
end
|
17
26
|
end
|
data/lib/v8/context.rb
CHANGED
@@ -1,111 +1,118 @@
|
|
1
1
|
require 'stringio'
|
2
|
-
|
3
2
|
module V8
|
4
3
|
class Context
|
5
|
-
|
4
|
+
include V8::Error::Try
|
5
|
+
attr_reader :native, :conversion, :access
|
6
6
|
|
7
|
-
def initialize(
|
7
|
+
def initialize(options = {})
|
8
|
+
@conversion = Conversion.new
|
8
9
|
@access = Access.new
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
template = if with
|
14
|
-
constructor = @to.templates.to_constructor(with.class)
|
15
|
-
constructor.disable()
|
16
|
-
constructor.template.InstanceTemplate()
|
17
|
-
else
|
18
|
-
C::ObjectTemplate::New()
|
19
|
-
end
|
20
|
-
@native = opts[:with] ? C::Context::New(template) : C::Context::New()
|
21
|
-
@native.enter do
|
22
|
-
@global = @native.Global()
|
23
|
-
@to.proxies.register_javascript_proxy @global, :for => with if with
|
24
|
-
constructor.enable() if constructor
|
25
|
-
@scope = @to.rb(@global)
|
26
|
-
@global.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyContext"), C::External::New(self))
|
10
|
+
if global = options[:with]
|
11
|
+
Context.new.enter do
|
12
|
+
global_template = global.class.to_template.InstanceTemplate()
|
13
|
+
@native = V8::C::Context::New(nil, global_template)
|
27
14
|
end
|
28
|
-
|
15
|
+
enter {link global, @native.Global()}
|
16
|
+
else
|
17
|
+
@native = V8::C::Context::New()
|
29
18
|
end
|
19
|
+
yield self if block_given?
|
30
20
|
end
|
31
21
|
|
32
|
-
def eval(
|
33
|
-
if IO ===
|
34
|
-
|
22
|
+
def eval(source, filename = '<eval>', line = 1)
|
23
|
+
if IO === source || StringIO === source
|
24
|
+
source = source.read
|
35
25
|
end
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
C::TryCatch.try do |try|
|
40
|
-
@native.enter do
|
41
|
-
script = C::Script::Compile(@to.v8(javascript.to_s), @to.v8(filename.to_s))
|
42
|
-
if try.HasCaught()
|
43
|
-
err = JSError.new(try, @to)
|
44
|
-
else
|
45
|
-
result = script.Run()
|
46
|
-
if try.HasCaught()
|
47
|
-
err = JSError.new(try, @to)
|
48
|
-
else
|
49
|
-
value = @to.rb(result)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
raise err if err
|
56
|
-
return value
|
57
|
-
end
|
58
|
-
|
59
|
-
def load(filename)
|
60
|
-
File.open(filename) do |file|
|
61
|
-
self.eval file, filename, 1
|
26
|
+
enter do
|
27
|
+
script = try { V8::C::Script::New(source.to_s, filename.to_s) }
|
28
|
+
to_ruby try {script.Run()}
|
62
29
|
end
|
63
30
|
end
|
64
31
|
|
65
32
|
def [](key)
|
66
|
-
|
67
|
-
@
|
33
|
+
enter do
|
34
|
+
to_ruby(@native.Global().Get(to_v8(key)))
|
68
35
|
end
|
69
36
|
end
|
70
37
|
|
71
38
|
def []=(key, value)
|
72
|
-
|
73
|
-
@
|
39
|
+
enter do
|
40
|
+
@native.Global().Set(to_v8(key), to_v8(value))
|
74
41
|
end
|
75
42
|
return value
|
76
43
|
end
|
77
44
|
|
78
|
-
def
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
45
|
+
def dispose
|
46
|
+
return unless @native
|
47
|
+
@native.Dispose()
|
48
|
+
@native = nil
|
49
|
+
V8::C::V8::ContextDisposedNotification()
|
50
|
+
def self.enter
|
51
|
+
fail "cannot enter a context which has already been disposed"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def scope
|
56
|
+
enter { to_ruby @native.Global() }
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_ruby(v8_object)
|
60
|
+
@conversion.to_ruby(v8_object)
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_v8(ruby_object)
|
64
|
+
@conversion.to_v8(ruby_object)
|
65
|
+
end
|
66
|
+
|
67
|
+
def link(ruby_object, v8_object)
|
68
|
+
@conversion.equate ruby_object, v8_object
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.link(*args)
|
72
|
+
current.link *args
|
73
|
+
end
|
74
|
+
|
75
|
+
def enter(&block)
|
76
|
+
if !entered?
|
77
|
+
lock_scope_and_enter(&block)
|
83
78
|
else
|
84
|
-
|
79
|
+
yield
|
85
80
|
end
|
86
81
|
end
|
87
|
-
|
88
|
-
def
|
89
|
-
|
82
|
+
|
83
|
+
def entered?
|
84
|
+
Context.current == self
|
90
85
|
end
|
91
|
-
end
|
92
86
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
87
|
+
def self.current
|
88
|
+
Thread.current[:v8_context]
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.current=(context)
|
92
|
+
Thread.current[:v8_context] = context
|
93
|
+
end
|
94
|
+
|
95
|
+
def lock_scope_and_enter
|
96
|
+
current = Context.current
|
97
|
+
Context.current = self
|
98
|
+
V8::C::Locker() do
|
99
|
+
V8::C::HandleScope() do
|
100
|
+
begin
|
101
|
+
@native.Enter()
|
102
|
+
yield if block_given?
|
103
|
+
ensure
|
104
|
+
@native.Exit()
|
106
105
|
end
|
107
106
|
end
|
108
107
|
end
|
108
|
+
ensure
|
109
|
+
Context.current = current
|
110
|
+
end
|
111
|
+
|
112
|
+
def load(filename)
|
113
|
+
File.open(filename) do |file|
|
114
|
+
self.eval file, filename
|
115
|
+
end
|
109
116
|
end
|
110
117
|
end
|
111
118
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
class V8::Conversion
|
3
|
+
include Fundamental
|
4
|
+
include Identity
|
5
|
+
|
6
|
+
def to_ruby(v8_object)
|
7
|
+
super v8_object
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_v8(ruby_object)
|
11
|
+
super ruby_object
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
for type in [TrueClass, FalseClass, NilClass, Float, Fixnum] do
|
16
|
+
type.class_eval do
|
17
|
+
include V8::Conversion::Primitive
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
for type in [Class, Object, Array, Hash, String, Symbol, Time, Proc, Method] do
|
22
|
+
type.class_eval do
|
23
|
+
include V8::Conversion.const_get(name)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
class UnboundMethod
|
27
|
+
include V8::Conversion::Method
|
28
|
+
end
|
29
|
+
|
30
|
+
for type in [:Object, :String, :Date] do
|
31
|
+
V8::C::const_get(type).class_eval do
|
32
|
+
include V8::Conversion::const_get("Native#{type}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,120 @@
|
|
1
|
+
class V8::Conversion
|
2
|
+
module Class
|
3
|
+
include V8::Conversion::Code
|
4
|
+
|
5
|
+
def to_template
|
6
|
+
weakcell(:constructor) do
|
7
|
+
template = V8::C::FunctionTemplate::New(Constructor.new(self))
|
8
|
+
prototype = template.InstanceTemplate()
|
9
|
+
prototype.SetNamedPropertyHandler(Get, Set)
|
10
|
+
prototype.SetIndexedPropertyHandler(IGet, ISet)
|
11
|
+
if self != ::Object && superclass != ::Object && superclass != ::Class
|
12
|
+
template.Inherit(superclass.to_template)
|
13
|
+
end
|
14
|
+
template
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Constructor
|
19
|
+
include V8::Error::Protect
|
20
|
+
|
21
|
+
def initialize(cls)
|
22
|
+
@class = cls
|
23
|
+
end
|
24
|
+
|
25
|
+
def call(arguments)
|
26
|
+
arguments.extend Args
|
27
|
+
protect do
|
28
|
+
if arguments.linkage_call?
|
29
|
+
arguments.link
|
30
|
+
else
|
31
|
+
arguments.construct @class
|
32
|
+
end
|
33
|
+
end
|
34
|
+
return arguments.This()
|
35
|
+
end
|
36
|
+
|
37
|
+
module Args
|
38
|
+
def linkage_call?
|
39
|
+
self.Length() == 1 && self[0].IsExternal()
|
40
|
+
end
|
41
|
+
|
42
|
+
def link
|
43
|
+
external = self[0]
|
44
|
+
This().SetHiddenValue("rr::implementation", external)
|
45
|
+
context.link external.Value(), This()
|
46
|
+
end
|
47
|
+
|
48
|
+
def construct(cls)
|
49
|
+
context.link cls.new(*to_args), This()
|
50
|
+
end
|
51
|
+
|
52
|
+
def context
|
53
|
+
V8::Context.current
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_args
|
57
|
+
args = ::Array.new(Length())
|
58
|
+
0.upto(args.length - 1) do |i|
|
59
|
+
args[i] = self[i]
|
60
|
+
end
|
61
|
+
return args
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
module Accessor
|
67
|
+
include V8::Error::Protect
|
68
|
+
def intercept(info, key, &block)
|
69
|
+
context = V8::Context.current
|
70
|
+
access = context.access
|
71
|
+
object = context.to_ruby(info.This())
|
72
|
+
handles_property = true
|
73
|
+
dontintercept = proc do
|
74
|
+
handles_property = false
|
75
|
+
end
|
76
|
+
protect do
|
77
|
+
result = block.call(context, access, object, context.to_ruby(key), dontintercept)
|
78
|
+
handles_property ? context.to_v8(result) : V8::C::Value::Empty
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Get
|
84
|
+
extend Accessor
|
85
|
+
def self.call(property, info)
|
86
|
+
intercept(info, property) do |context, access, object, key, dontintercept|
|
87
|
+
access.get(object, key, &dontintercept)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class Set
|
93
|
+
extend Accessor
|
94
|
+
def self.call(property, value, info)
|
95
|
+
intercept(info, property) do |context, access, object, key, dontintercept|
|
96
|
+
access.set(object, key, context.to_ruby(value), &dontintercept)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class IGet
|
102
|
+
extend Accessor
|
103
|
+
def self.call(property, info)
|
104
|
+
intercept(info, property) do |context, access, object, key, dontintercept|
|
105
|
+
access.iget(object, key, &dontintercept)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class ISet
|
111
|
+
extend Accessor
|
112
|
+
def self.call(property, value, info)
|
113
|
+
intercept(info, property) do |context, access, object, key, dontintercept|
|
114
|
+
access.iset(object, key, context.to_ruby(value), &dontintercept)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|