therubyracer 0.8.2 → 0.9.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/Changelog.md +1 -1
- data/ext/v8/rr.cpp +14 -7
- data/ext/v8/rr.h +1 -0
- data/ext/v8/v8.cpp +27 -25
- data/ext/v8/v8_array.cpp +7 -9
- data/ext/v8/v8_callbacks.cpp +1 -1
- data/ext/v8/{v8_cxt.cpp → v8_context.cpp} +11 -11
- data/ext/v8/{v8_cxt.h → v8_context.h} +1 -1
- data/ext/v8/v8_date.cpp +6 -6
- data/ext/v8/v8_exception.cpp +10 -11
- data/ext/v8/v8_external.cpp +7 -24
- data/ext/v8/v8_external.h +0 -1
- data/ext/v8/{v8_func.cpp → v8_function.cpp} +14 -14
- data/ext/v8/{v8_func.h → v8_function.h} +1 -2
- data/ext/v8/v8_handle.cpp +119 -0
- data/ext/v8/v8_handle.h +27 -0
- data/ext/v8/{v8_msg.cpp → v8_message.cpp} +8 -9
- data/ext/v8/{v8_msg.h → v8_message.h} +1 -1
- data/ext/v8/{v8_obj.cpp → v8_object.cpp} +51 -29
- data/ext/v8/{v8_obj.h → v8_object.h} +3 -4
- data/ext/v8/v8_script.cpp +5 -5
- data/ext/v8/{v8_str.cpp → v8_string.cpp} +9 -11
- data/ext/v8/{v8_str.h → v8_string.h} +1 -1
- data/ext/v8/v8_template.cpp +113 -98
- data/ext/v8/v8_try_catch.cpp +1 -1
- data/ext/v8/v8_v8.cpp +7 -0
- data/ext/v8/v8_value.cpp +44 -36
- data/ext/v8/v8_value.h +2 -2
- data/ext/v8/v8_weakref.cpp +51 -0
- data/ext/v8/v8_weakref.h +30 -0
- data/lib/v8.rb +6 -1
- data/lib/v8/context.rb +13 -3
- data/lib/v8/error.rb +1 -1
- data/lib/v8/portal.rb +26 -277
- data/lib/v8/portal/caller.rb +36 -0
- data/lib/v8/portal/constructor.rb +98 -0
- data/lib/v8/portal/function.rb +48 -0
- data/lib/v8/portal/interceptors.rb +153 -0
- data/lib/v8/portal/proxies.rb +102 -0
- data/lib/v8/portal/templates.rb +73 -0
- data/lib/v8/version.rb +1 -1
- data/spec/ext/array_spec.rb +15 -0
- data/spec/ext/cxt_spec.rb +4 -4
- data/spec/ext/ext_spec_helper.rb +43 -0
- data/spec/ext/mem_spec.rb +42 -0
- data/spec/ext/object_spec.rb +22 -0
- data/spec/redjs/jsapi_spec.rb +4 -4
- data/spec/spec_helper.rb +1 -1
- data/spec/v8/portal/proxies_spec.rb +189 -0
- metadata +38 -42
- data/ext/v8/v8_ref.cpp +0 -37
- data/ext/v8/v8_ref.h +0 -28
- data/lib/v8/portal/functions.rb +0 -45
data/ext/v8/v8_value.h
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
#include "v8.h"
|
2
|
+
#include "v8_weakref.h"
|
3
|
+
|
4
|
+
using namespace v8;
|
5
|
+
|
6
|
+
v8_weakref::v8_weakref(VALUE object) {
|
7
|
+
this->external = Persistent<External>::New(External::New((void *)this));
|
8
|
+
this->external.MakeWeak(this, v8_weakref_dispose);
|
9
|
+
this->set(object);
|
10
|
+
}
|
11
|
+
|
12
|
+
void v8_weakref::set(VALUE value) {
|
13
|
+
this->object_id = rb_obj_id(value);
|
14
|
+
VALUE data = Data_Wrap_Struct(rb_cObject, 0, 0, this);
|
15
|
+
VALUE finalizer = rb_proc_new((VALUE (*)(...))v8_weakref_finalize, data);
|
16
|
+
rb_funcall(v8_weakref_objectspace(), rb_intern("define_finalizer"), 2, value, finalizer);
|
17
|
+
}
|
18
|
+
|
19
|
+
VALUE v8_weakref::get() {
|
20
|
+
if (this->object_id) {
|
21
|
+
return rb_rescue((VALUE (*)(...))v8_weakref_id2ref, this->object_id, (VALUE (*)(...))v8_weakref_nil, Qnil);
|
22
|
+
} else {
|
23
|
+
return Qnil;
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
VALUE v8_weakref_finalize(VALUE object_id, VALUE data) {
|
28
|
+
v8_weakref* weakref = 0;
|
29
|
+
Data_Get_Struct(data, struct v8_weakref, weakref);
|
30
|
+
weakref->object_id = Qnil;
|
31
|
+
return Qnil;
|
32
|
+
}
|
33
|
+
|
34
|
+
void v8_weakref_dispose(Persistent<Value> value, void* weakref) {
|
35
|
+
value.Dispose();
|
36
|
+
value.Clear();
|
37
|
+
delete (v8_weakref*)weakref;
|
38
|
+
}
|
39
|
+
|
40
|
+
VALUE v8_weakref_nil(VALUE nil, VALUE exception) {
|
41
|
+
return nil;
|
42
|
+
}
|
43
|
+
|
44
|
+
VALUE v8_weakref_objectspace() {
|
45
|
+
return rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
|
46
|
+
}
|
47
|
+
|
48
|
+
VALUE v8_weakref_id2ref(VALUE id) {
|
49
|
+
return rb_funcall(v8_weakref_objectspace(), rb_intern("_id2ref"), 1, id);
|
50
|
+
}
|
51
|
+
|
data/ext/v8/v8_weakref.h
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#ifndef _RR_V8_WEAKREF_
|
2
|
+
#define _RR_V8_WEAKREF_
|
3
|
+
|
4
|
+
#include <v8.h>
|
5
|
+
#include "ruby.h"
|
6
|
+
#include "ruby/version.h"
|
7
|
+
|
8
|
+
struct v8_weakref {
|
9
|
+
v8_weakref(VALUE object);
|
10
|
+
VALUE get();
|
11
|
+
void set(VALUE object);
|
12
|
+
void retain();
|
13
|
+
void release();
|
14
|
+
|
15
|
+
VALUE object_id;
|
16
|
+
v8::Persistent<v8::External> external;
|
17
|
+
};
|
18
|
+
|
19
|
+
void v8_weakref_dispose(v8::Persistent<v8::Value> value, void* weakref);
|
20
|
+
VALUE v8_weakref_finalize(VALUE self, VALUE object_id);
|
21
|
+
VALUE v8_weakref_objectspace();
|
22
|
+
VALUE v8_weakref_nil(VALUE nil, VALUE exception);
|
23
|
+
VALUE v8_weakref_id2ref(VALUE id);
|
24
|
+
|
25
|
+
|
26
|
+
#if RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8
|
27
|
+
extern "C" VALUE rb_proc_new(VALUE (*)(ANYARGS/* VALUE yieldarg[, VALUE procarg] */), VALUE);
|
28
|
+
#endif
|
29
|
+
|
30
|
+
#endif
|
data/lib/v8.rb
CHANGED
@@ -5,7 +5,12 @@ module V8
|
|
5
5
|
require 'v8/version'
|
6
6
|
require 'v8/v8' #native glue
|
7
7
|
require 'v8/portal'
|
8
|
-
require 'v8/portal/
|
8
|
+
require 'v8/portal/caller'
|
9
|
+
require 'v8/portal/proxies'
|
10
|
+
require 'v8/portal/templates'
|
11
|
+
require 'v8/portal/function'
|
12
|
+
require 'v8/portal/constructor'
|
13
|
+
require 'v8/portal/interceptors'
|
9
14
|
require 'v8/context'
|
10
15
|
require 'v8/object'
|
11
16
|
require 'v8/array'
|
data/lib/v8/context.rb
CHANGED
@@ -7,11 +7,21 @@ module V8
|
|
7
7
|
def initialize(opts = {})
|
8
8
|
@access = Access.new
|
9
9
|
@to = Portal.new(self, @access)
|
10
|
-
|
10
|
+
with = opts[:with]
|
11
|
+
constructor = nil
|
12
|
+
template = if with
|
13
|
+
constructor = @to.templates.to_constructor(with.class)
|
14
|
+
constructor.disable()
|
15
|
+
constructor.template.InstanceTemplate()
|
16
|
+
else
|
17
|
+
C::ObjectTemplate::New()
|
18
|
+
end
|
19
|
+
@native = opts[:with] ? C::Context::New(template) : C::Context::New()
|
11
20
|
@native.enter do
|
12
21
|
@global = @native.Global()
|
22
|
+
@to.proxies.register_javascript_proxy @global, :for => with if with
|
23
|
+
constructor.enable() if constructor
|
13
24
|
@scope = @to.rb(@global)
|
14
|
-
@global.SetHiddenValue(C::String::New("TheRubyRacer::RubyObject"), C::External::New(opts[:with])) if opts[:with]
|
15
25
|
@global.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyContext"), C::External::New(self))
|
16
26
|
end
|
17
27
|
yield(self) if block_given?
|
@@ -58,7 +68,7 @@ module V8
|
|
58
68
|
|
59
69
|
def self.stack(limit = 99)
|
60
70
|
if native = C::Context::GetEntered()
|
61
|
-
global = native.Global()
|
71
|
+
global = native.Global()
|
62
72
|
cxt = global.GetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyContext")).Value()
|
63
73
|
cxt.instance_eval {@to.rb(C::StackTrace::CurrentStackTrace(limit))}
|
64
74
|
else
|
data/lib/v8/error.rb
CHANGED
@@ -106,7 +106,7 @@ module V8
|
|
106
106
|
#in these instances, we have to pull it out of the Message object
|
107
107
|
#in the TryCatch. Is there a better way to detect a syntax error
|
108
108
|
def syntax_error?(try)
|
109
|
-
ex = try.Exception()
|
109
|
+
ex = @to.rb(try.Exception())
|
110
110
|
if ex && ex.kind_of?(V8::Object)
|
111
111
|
type = ex["constructor"]
|
112
112
|
type && type.kind_of?(V8::Function) && type.name == "SyntaxError"
|
data/lib/v8/portal.rb
CHANGED
@@ -1,73 +1,14 @@
|
|
1
1
|
|
2
2
|
module V8
|
3
3
|
class Portal
|
4
|
-
attr_reader :context
|
4
|
+
attr_reader :context, :access, :proxies, :templates, :interceptors, :caller
|
5
5
|
|
6
6
|
def initialize(context, access)
|
7
7
|
@context, @access = context, access
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@
|
12
|
-
@named_property_enumerator = Interceptor(NamedPropertyEnumerator)
|
13
|
-
|
14
|
-
@indexed_property_getter = Interceptor(IndexedPropertyGetter)
|
15
|
-
@indexed_property_setter = Interceptor(IndexedPropertySetter)
|
16
|
-
@indexed_property_query = nil
|
17
|
-
@indexed_property_deleter = nil
|
18
|
-
@indexed_property_enumerator = Interceptor(IndexedPropertyEnumerator)
|
19
|
-
|
20
|
-
@constructors = Hash.new do |h, cls|
|
21
|
-
h[cls] = template = C::FunctionTemplate::New() do |arguments|
|
22
|
-
unless arguments.Length() == 1 && arguments[0].kind_of?(C::External)
|
23
|
-
C::ThrowException(C::Exception::Error(C::String::New("cannot call native constructor from javascript")))
|
24
|
-
else
|
25
|
-
arguments.This().tap do |this|
|
26
|
-
this.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyObject"), arguments[0])
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
template.tap do
|
31
|
-
setuptemplate(template.InstanceTemplate())
|
32
|
-
if cls != ::Object && cls.superclass != ::Object && cls.superclass != ::Class
|
33
|
-
template.Inherit(@constructors[cls.superclass])
|
34
|
-
end
|
35
|
-
if cls.name && cls.name =~ /(::)?(\w+?)$/
|
36
|
-
template.SetClassName(C::String::NewSymbol("rb::" + $2))
|
37
|
-
else
|
38
|
-
template.SetClassName("Ruby")
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
@instances = Hash.new do |h, obj|
|
44
|
-
args = C::Array::New(1)
|
45
|
-
args.Set(0, C::External::New(obj))
|
46
|
-
h[obj] = @constructors[obj.class].GetFunction().NewInstance(args)
|
47
|
-
end
|
48
|
-
|
49
|
-
@functions = Functions.new(self)
|
50
|
-
|
51
|
-
@embedded_constructors = Hash.new do |h, cls|
|
52
|
-
template = @constructors[cls]
|
53
|
-
template.SetCallHandler() do |arguments|
|
54
|
-
wrap = nil
|
55
|
-
if arguments.Length() > 0 && arguments[0].kind_of?(C::External)
|
56
|
-
wrap = arguments[0]
|
57
|
-
else
|
58
|
-
rbargs = []
|
59
|
-
for i in 0..arguments.Length() - 1
|
60
|
-
rbargs << rb(arguments[i])
|
61
|
-
end
|
62
|
-
instance = rubysend(cls, :new, *rbargs)
|
63
|
-
wrap = C::External::New(instance)
|
64
|
-
end
|
65
|
-
arguments.This().tap do |this|
|
66
|
-
this.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyObject"), wrap)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
h[cls] = template
|
70
|
-
end
|
8
|
+
@proxies = Proxies.new
|
9
|
+
@templates = Templates.new(self)
|
10
|
+
@interceptors = Interceptors.new(self)
|
11
|
+
@caller = Caller.new(self)
|
71
12
|
end
|
72
13
|
|
73
14
|
def open
|
@@ -77,16 +18,18 @@ module V8
|
|
77
18
|
end
|
78
19
|
|
79
20
|
def rb(value)
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
21
|
+
@proxies.js2rb(value) do
|
22
|
+
case value
|
23
|
+
when V8::C::Function then V8::Function.new(value, self)
|
24
|
+
when V8::C::Array then V8::Array.new(value, self)
|
25
|
+
when V8::C::Object then V8::Object.new(value, self)
|
26
|
+
when V8::C::String then value.Utf8Value.tap {|s| return s.respond_to?(:force_encoding) ? s.force_encoding("UTF-8") : s}
|
27
|
+
when V8::C::Date then Time.at(value.NumberValue() / 1000)
|
28
|
+
when V8::C::StackTrace then V8::StackTrace.new(self, value)
|
29
|
+
when V8::C::Value then nil if value.IsEmpty()
|
30
|
+
else
|
31
|
+
value
|
32
|
+
end
|
90
33
|
end
|
91
34
|
end
|
92
35
|
|
@@ -99,7 +42,9 @@ module V8
|
|
99
42
|
when Symbol
|
100
43
|
C::String::NewSymbol(value.to_s)
|
101
44
|
when Proc,Method,UnboundMethod
|
102
|
-
@
|
45
|
+
@proxies.rb2js(value) do
|
46
|
+
@templates.to_function(value).function
|
47
|
+
end
|
103
48
|
when ::Array
|
104
49
|
C::Array::New(value.length).tap do |a|
|
105
50
|
value.each_with_index do |item, i|
|
@@ -115,212 +60,16 @@ module V8
|
|
115
60
|
when ::Time
|
116
61
|
C::Date::New(value.to_f * 1000)
|
117
62
|
when ::Class
|
118
|
-
@
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
#set *that* object's prototype to an empty function so that it will look and behave like a function.
|
123
|
-
prototype.SetPrototype(C::FunctionTemplate::New() {}.GetFunction())
|
124
|
-
f.SetPrototype(prototype)
|
63
|
+
@proxies.rb2js(value) do
|
64
|
+
constructor = @templates.to_constructor(value)
|
65
|
+
constructor.exposed = true
|
66
|
+
constructor.function
|
125
67
|
end
|
126
68
|
when nil,Numeric,TrueClass,FalseClass, C::Value
|
127
69
|
value
|
128
70
|
else
|
129
|
-
@
|
130
|
-
|
131
|
-
end
|
132
|
-
|
133
|
-
def rubyprotect
|
134
|
-
begin
|
135
|
-
v8 yield
|
136
|
-
rescue Exception => e
|
137
|
-
case e
|
138
|
-
when SystemExit, NoMemoryError
|
139
|
-
raise e
|
140
|
-
else
|
141
|
-
error = V8::C::Exception::Error(V8::C::String::New(e.message))
|
142
|
-
error.SetHiddenValue("TheRubyRacer::Cause", C::External::New(e))
|
143
|
-
V8::C::ThrowException(error)
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def rubycall(rubycode, *args, &block)
|
149
|
-
rubyprotect do
|
150
|
-
rubycode.call(*args, &block)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def rubysend(obj, message, *args, &block)
|
155
|
-
rubyprotect do
|
156
|
-
obj.send(message, *args, &block)
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
def rubytemplate
|
161
|
-
C::ObjectTemplate::New().tap do |t|
|
162
|
-
setuptemplate(t)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
def setuptemplate(t)
|
167
|
-
t.SetNamedPropertyHandler(
|
168
|
-
@named_property_getter,
|
169
|
-
@named_property_setter,
|
170
|
-
nil,
|
171
|
-
nil,
|
172
|
-
@named_property_enumerator
|
173
|
-
)
|
174
|
-
t.SetIndexedPropertyHandler(
|
175
|
-
@indexed_property_getter,
|
176
|
-
@indexed_property_setter,
|
177
|
-
nil,
|
178
|
-
nil,
|
179
|
-
@indexed_property_enumerator
|
180
|
-
)
|
181
|
-
end
|
182
|
-
|
183
|
-
private
|
184
|
-
|
185
|
-
def peer(value)
|
186
|
-
external = value.GetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyObject"))
|
187
|
-
if external && !external.IsEmpty()
|
188
|
-
external.Value()
|
189
|
-
else
|
190
|
-
yield.new(value, self).tap do |object|
|
191
|
-
value.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyObject"), C::External::New(object))
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
class Interceptor
|
197
|
-
def initialize(portal, access)
|
198
|
-
@to, @access = portal, access
|
199
|
-
end
|
200
|
-
|
201
|
-
def intercept(info, retval = nil, &code)
|
202
|
-
obj = @to.rb(info.This())
|
203
|
-
intercepts = true
|
204
|
-
result = @to.rubyprotect do
|
205
|
-
dontintercept = proc do
|
206
|
-
intercepts = false
|
207
|
-
end
|
208
|
-
code.call(obj, dontintercept)
|
209
|
-
end
|
210
|
-
intercepts ? (retval || result) : C::Empty
|
211
|
-
end
|
212
|
-
|
213
|
-
end
|
214
|
-
|
215
|
-
def Interceptor(cls)
|
216
|
-
cls.new self, @access
|
217
|
-
end
|
218
|
-
|
219
|
-
class PropertyAttributes
|
220
|
-
attr_reader :flags
|
221
|
-
def initialize
|
222
|
-
@flags = 0
|
223
|
-
end
|
224
|
-
|
225
|
-
def read_only
|
226
|
-
tap do
|
227
|
-
@flags |= V8::C::ReadOnly
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
def dont_enum
|
232
|
-
tap do
|
233
|
-
@flags |= V8::C::DontEnum
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
def dont_delete
|
238
|
-
tap do
|
239
|
-
@flags |= V8::C::DontDelete
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
class NamedPropertyGetter < Interceptor
|
245
|
-
def call(property, info)
|
246
|
-
intercept(info) do |obj, dontintercept|
|
247
|
-
@access.get(obj, @to.rb(property), &dontintercept)
|
248
|
-
end
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
class NamedPropertySetter < Interceptor
|
253
|
-
def call(property, value, info)
|
254
|
-
intercept(info, value) do |obj, dontintercept|
|
255
|
-
@access.set(obj, @to.rb(property), @to.rb(value), &dontintercept)
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
class NamedPropertyQuery
|
261
|
-
def call(property, info)
|
262
|
-
attributes = PropertyAttributes.new
|
263
|
-
result = intercept(info) do |obj, dontintercept|
|
264
|
-
@access.query(obj, @to.rb(property), attributes, &dontintercept)
|
265
|
-
end
|
266
|
-
return result == C::Empty ? result : C::Integer::New(attributes.flags)
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
|
-
class NamedPropertyEnumerator < Interceptor
|
271
|
-
def call(info)
|
272
|
-
intercept(info) do |obj, dontintercept|
|
273
|
-
@access.names(obj, &dontintercept).to_a
|
274
|
-
end
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
class NamedPropertyDeleter < Interceptor
|
279
|
-
def call(property, info)
|
280
|
-
intercept(info) do |obj, dontintercept|
|
281
|
-
@access.delete(obj, property, &dontintercept)
|
282
|
-
end
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
class IndexedPropertyGetter < Interceptor
|
287
|
-
def call(index, info)
|
288
|
-
intercept(info) do |obj, dontintercept|
|
289
|
-
@access.iget(obj, index, &dontintercept)
|
290
|
-
end
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
class IndexedPropertySetter < Interceptor
|
295
|
-
def call(index, value, info)
|
296
|
-
intercept(info, value) do |obj, dontintercept|
|
297
|
-
@access.iset(obj, index, @to.rb(value), &dontintercept)
|
298
|
-
end
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
class IndexedPropertyQuery < Interceptor
|
303
|
-
def call(property, info)
|
304
|
-
attributes = PropertyAttributes.new
|
305
|
-
result = intercept(info) do |obj, dontintercept|
|
306
|
-
@access.indices(obj, &dontintercept)
|
307
|
-
end
|
308
|
-
result == C::Empty ? C::Empty : C::Integer::New(attributes.flags)
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
|
-
class IndexedPropertyDeleter < Interceptor
|
313
|
-
def call(index, info)
|
314
|
-
intercept(info) do |obj, dontintercept|
|
315
|
-
@access.idelete(obj, index, &dontintercept)
|
316
|
-
end
|
317
|
-
end
|
318
|
-
end
|
319
|
-
|
320
|
-
class IndexedPropertyEnumerator < Interceptor
|
321
|
-
def call(info)
|
322
|
-
intercept(info) do |obj, dontintercept|
|
323
|
-
@access.indices(obj, &dontintercept)
|
71
|
+
@proxies.rb2js(value) do
|
72
|
+
@templates.to_constructor(value.class).allocate(value)
|
324
73
|
end
|
325
74
|
end
|
326
75
|
end
|