therubyracer-freebsd 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.travis.yml +8 -0
- data/.yardopts +1 -0
- data/Changelog.md +231 -0
- data/Gemfile +3 -0
- data/README.md +167 -0
- data/Rakefile +26 -0
- data/bin/therubyracer +11 -0
- data/ext/v8/extconf.rb +26 -0
- data/ext/v8/rr.cpp +189 -0
- data/ext/v8/rr.h +41 -0
- data/ext/v8/v8.cpp +48 -0
- data/ext/v8/v8_array.cpp +48 -0
- data/ext/v8/v8_array.h +8 -0
- data/ext/v8/v8_callbacks.cpp +81 -0
- data/ext/v8/v8_callbacks.h +8 -0
- data/ext/v8/v8_context.cpp +92 -0
- data/ext/v8/v8_context.h +6 -0
- data/ext/v8/v8_date.cpp +40 -0
- data/ext/v8/v8_date.h +6 -0
- data/ext/v8/v8_debug.cpp +17 -0
- data/ext/v8/v8_debug.h +6 -0
- data/ext/v8/v8_exception.cpp +133 -0
- data/ext/v8/v8_exception.h +11 -0
- data/ext/v8/v8_external.cpp +70 -0
- data/ext/v8/v8_external.h +8 -0
- data/ext/v8/v8_function.cpp +69 -0
- data/ext/v8/v8_function.h +11 -0
- data/ext/v8/v8_handle.cpp +186 -0
- data/ext/v8/v8_handle.h +48 -0
- data/ext/v8/v8_locker.cpp +139 -0
- data/ext/v8/v8_locker.h +6 -0
- data/ext/v8/v8_message.cpp +67 -0
- data/ext/v8/v8_message.h +10 -0
- data/ext/v8/v8_object.cpp +122 -0
- data/ext/v8/v8_object.h +10 -0
- data/ext/v8/v8_script.cpp +36 -0
- data/ext/v8/v8_script.h +8 -0
- data/ext/v8/v8_string.cpp +52 -0
- data/ext/v8/v8_string.h +9 -0
- data/ext/v8/v8_template.cpp +344 -0
- data/ext/v8/v8_template.h +8 -0
- data/ext/v8/v8_try_catch.cpp +70 -0
- data/ext/v8/v8_try_catch.h +5 -0
- data/ext/v8/v8_v8.cpp +34 -0
- data/ext/v8/v8_v8.h +6 -0
- data/ext/v8/v8_value.cpp +175 -0
- data/ext/v8/v8_value.h +10 -0
- data/ext/v8/v8_weakref.cpp +61 -0
- data/ext/v8/v8_weakref.h +29 -0
- data/lib/v8.rb +23 -0
- data/lib/v8/access.rb +92 -0
- data/lib/v8/array.rb +17 -0
- data/lib/v8/c/locker.rb +18 -0
- data/lib/v8/cli.rb +133 -0
- data/lib/v8/context.rb +111 -0
- data/lib/v8/error.rb +130 -0
- data/lib/v8/function.rb +44 -0
- data/lib/v8/object.rb +69 -0
- data/lib/v8/portal.rb +86 -0
- data/lib/v8/portal/caller.rb +37 -0
- data/lib/v8/portal/constructor.rb +98 -0
- data/lib/v8/portal/function.rb +63 -0
- data/lib/v8/portal/interceptors.rb +152 -0
- data/lib/v8/portal/proxies.rb +151 -0
- data/lib/v8/portal/templates.rb +73 -0
- data/lib/v8/stack.rb +66 -0
- data/lib/v8/tap.rb +9 -0
- data/lib/v8/version.rb +3 -0
- data/spec/ext/array_spec.rb +15 -0
- data/spec/ext/cxt_spec.rb +57 -0
- data/spec/ext/ext_spec_helper.rb +27 -0
- data/spec/ext/func_spec.rb +64 -0
- data/spec/ext/object_spec.rb +10 -0
- data/spec/ext/string_spec.rb +11 -0
- data/spec/ext/try_catch_spec.rb +60 -0
- data/spec/redjs_spec.rb +9 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/v8/error_spec.rb +131 -0
- data/spec/v8/portal/proxies_spec.rb +106 -0
- data/specmem/handle_memspec.rb +41 -0
- data/specmem/object_memspec.rb +14 -0
- data/specmem/proxies_memspec.rb +49 -0
- data/specmem/spec_helper.rb +24 -0
- data/specthread/spec_helper.rb +2 -0
- data/specthread/threading_spec.rb +13 -0
- data/thefrontside.png +0 -0
- data/therubyracer.gemspec +27 -0
- metadata +183 -0
data/lib/v8/object.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
|
2
|
+
module V8
|
3
|
+
class Object
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(native, portal)
|
7
|
+
@native, @portal = native, portal
|
8
|
+
end
|
9
|
+
|
10
|
+
def [](key)
|
11
|
+
@portal.open do |to|
|
12
|
+
to.rb(@native.Get(to.v8(key)))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def []=(key, value)
|
17
|
+
value.tap do
|
18
|
+
@portal.open do |to|
|
19
|
+
@native.Set(to.v8(key), to.v8(value))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
@portal.open do |to|
|
26
|
+
to.rb(@native.ToString())
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def each
|
31
|
+
@portal.open do |to|
|
32
|
+
for prop in to.rb(@native.GetPropertyNames())
|
33
|
+
yield prop, self[prop]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def respond_to?(method)
|
39
|
+
super or self[method] != nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def method_missing(name, *args, &block)
|
43
|
+
if name.to_s =~ /(.*)=$/
|
44
|
+
if args.length > 1
|
45
|
+
self[$1] = args
|
46
|
+
return args
|
47
|
+
else
|
48
|
+
self[$1] = args.first
|
49
|
+
return args
|
50
|
+
end
|
51
|
+
end
|
52
|
+
return super(name, *args, &block) unless self.respond_to?(name)
|
53
|
+
property = self[name]
|
54
|
+
if property.kind_of?(V8::Function)
|
55
|
+
property.methodcall(self, *args)
|
56
|
+
elsif args.empty?
|
57
|
+
property
|
58
|
+
else
|
59
|
+
raise ArgumentError, "wrong number of arguments (#{args.length} for 0)" unless args.empty?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Object
|
66
|
+
def eval_js(javascript)
|
67
|
+
V8::Context.new(:with => self).eval(javascript)
|
68
|
+
end
|
69
|
+
end
|
data/lib/v8/portal.rb
ADDED
@@ -0,0 +1,86 @@
|
|
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
|
@@ -0,0 +1,37 @@
|
|
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
|
@@ -0,0 +1,98 @@
|
|
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
|
@@ -0,0 +1,63 @@
|
|
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
|
@@ -0,0 +1,152 @@
|
|
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
|
+
|