Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 484 lines (372 sloc) 14.488 kb
e18f74d @jbarnette Renaming proxies for clarity.
authored
1 #include "js_land_proxy.h"
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
2
3 static JSBool get(JSContext* js_context, JSObject* obj, jsval id, jsval* retval);
4 static JSBool set(JSContext* context, JSObject* obj, jsval id, jsval* retval);
b77b3ad @jbarnette Make sure multiple proxy classes are supported.
authored
5 static JSBool construct(JSContext* js_context, JSObject* obj, uintN argc, jsval* argv, jsval* retval);
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
6 static JSBool resolve(JSContext *js_context, JSObject *obj, jsval id, uintN flags, JSObject **objp);
73ad637 @jbarnette Cleaned up proxying of callable (Proc, Method) Ruby objects.
authored
7 static JSBool call(JSContext* js_context, JSObject* obj, uintN argc, jsval* argv, jsval* retval);
b77b3ad @jbarnette Make sure multiple proxy classes are supported.
authored
8 static void finalize(JSContext* context, JSObject* obj);
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
9
510f1b5 @jbarnette Fix some vestigal renaming issues.
authored
10 static JSClass JSLandProxyClass = {
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
11 "JSLandProxy", JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
12 JS_PropertyStub,
13 JS_PropertyStub,
14 get,
15 set,
16 JS_EnumerateStub,
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
17 resolve,
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
18 JS_ConvertStub,
19 finalize
20 };
21
b77b3ad @jbarnette Make sure multiple proxy classes are supported.
authored
22 static JSClass JSLandClassProxyClass = {
23 "JSLandClassProxy", JSCLASS_HAS_PRIVATE,
24 JS_PropertyStub,
25 JS_PropertyStub,
26 get,
27 set,
28 JS_EnumerateStub,
29 JS_ResolveStub,
30 JS_ConvertStub,
31 finalize,
32 NULL,
33 NULL,
34 NULL,
35 construct
36 };
37
73ad637 @jbarnette Cleaned up proxying of callable (Proc, Method) Ruby objects.
authored
38 static JSClass JSLandCallableProxyClass = {
39 "JSLandCallableProxy", JSCLASS_HAS_PRIVATE,
40 JS_PropertyStub,
41 JS_PropertyStub,
42 JS_PropertyStub,
43 JS_PropertyStub,
44 JS_EnumerateStub,
45 JS_ResolveStub,
46 JS_ConvertStub,
47 finalize,
48 NULL,
49 NULL,
50 call
51 };
52
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
53 static JSBool autovivified_p(VALUE ruby_context, VALUE self, char* name)
54 {
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
55 return rb_funcall(Johnson_SpiderMonkey_JSLandProxy(), rb_intern("autovivified?"), 2,
56 self, rb_str_new2(name));
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
57 }
58
59 static JSBool const_p(VALUE self, char* name)
60 {
61 return rb_obj_is_kind_of(self, rb_cModule)
62 && rb_is_const_id(rb_intern(name))
63 && rb_funcall(self, rb_intern("const_defined?"), 1, ID2SYM(rb_intern(name)));
64 }
65
66 static JSBool global_p(char* name)
67 {
68 return rb_ary_includes(rb_f_global_variables(), rb_str_new2(name));
69 }
70
71 static JSBool method_p(VALUE self, char* name)
72 {
73 return rb_funcall(self, rb_intern("respond_to?"), 1, ID2SYM(rb_intern(name)));
74 }
75
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
76 static JSBool attribute_p(VALUE self, char* name)
77 {
78 if (!method_p(self, name))
79 return JS_FALSE;
80
81 VALUE rb_id = rb_intern(name);
82 VALUE rb_method = rb_funcall(self, rb_intern("method"), 1, ID2SYM(rb_id));
83
84 METHOD* method;
85 Data_Get_Struct(rb_method, METHOD, method);
86
87 return nd_type(method->body) == NODE_IVAR
88 || rb_funcall(Johnson_SpiderMonkey_JSLandProxy(),
89 rb_intern("js_property?"), 2, self, ID2SYM(rb_id));
90 }
91
e0d5bf2 @jbarnette Simple implementation for working numeric array indexes.
authored
92 static JSBool indexable_p(VALUE self)
93 {
94 rb_funcall(self, rb_intern("respond_to?"), 1, ID2SYM(rb_intern("[]")));
95 }
96
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
97 static JSBool has_key_p(VALUE self, char* name)
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
98 {
99 return rb_funcall(self, rb_intern("respond_to?"), 1, ID2SYM(rb_intern("[]")))
100 && rb_funcall(self, rb_intern("respond_to?"), 1, ID2SYM(rb_intern("key?")))
101 && rb_funcall(self, rb_intern("key?"), 1, rb_str_new2(name));
102 }
103
104 static JSBool respond_to_p(JSContext* js_context, JSObject* obj, char* name)
105 {
106 VALUE ruby_context;
107 assert(ruby_context = (VALUE)JS_GetContextPrivate(js_context));
108
109 OurContext* context;
110 Data_Get_Struct(ruby_context, OurContext, context);
111
112 VALUE self;
113 VALUE symbol = ID2SYM(rb_intern(name));
114
115 assert(self = (VALUE)JS_GetInstancePrivate(
116 context->js, obj, JS_GET_CLASS(context->js, obj), NULL));
117
118 return autovivified_p(ruby_context, self, name)
119 || const_p(self, name)
120 || global_p(name)
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
121 || attribute_p(self, name)
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
122 || method_p(self, name)
123 || has_key_p(self, name);
124 }
125
63b6e8d @tenderlove reducing the iterator code
tenderlove authored
126 static jsval property_get(OurContext * context, char * property) {
127 jsval retval;
128 JSBool ok = JS_EvaluateScript(context->js, context->global,
129 property, strlen(property), NULL, 1,
130 &retval);
131 return retval;
132 }
133
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
134 static JSBool get(JSContext* js_context, JSObject* obj, jsval id, jsval* retval)
135 {
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
136 // pull out our Ruby context, which is embedded in js_context
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
137
138 VALUE ruby_context;
139 assert(ruby_context = (VALUE)JS_GetContextPrivate(js_context));
140
141 // get our struct, which is embedded in ruby_context
142
143 OurContext* context;
144 Data_Get_Struct(ruby_context, OurContext, context);
145
146 // get the Ruby object that backs this proxy
147
148 VALUE self;
109858e @jbarnette Make JSLandProxyClass more easily parameterizable.
authored
149 assert(self = (VALUE)JS_GetInstancePrivate(context->js, obj, JS_GET_CLASS(context->js, obj), NULL));
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
150
e0d5bf2 @jbarnette Simple implementation for working numeric array indexes.
authored
151 // Short-circuit for numeric indexes
152
153 if (JSVAL_IS_INT(id))
154 {
155 if (indexable_p(self))
156 *retval = convert_to_js(context,
157 rb_funcall(self, rb_intern("[]"), 1, INT2FIX(JSVAL_TO_INT(id))));
158
159 return JS_TRUE;
160 }
161
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
162 char* name = JS_GetStringBytes(JSVAL_TO_STRING(id));
163 VALUE ruby_id = rb_intern(name);
164
d45a2d5 @jbarnette Added some notes for the future.
authored
165 // FIXME: this is necessarily ugly. Maybe we should write something like
166 // jsval foo = property_expression(context->js, context->global, "Johnson.Generator.create")
167 // this would make the code where we look up Johnson.Symbol cleaner too (in conversions.c)
168
169 // FIXME: we should probably just JS_DefineProperty this, and it shouldn't be enumerable
170
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
171 if (!strcasecmp("__iterator__", name)) {
63b6e8d @tenderlove reducing the iterator code
tenderlove authored
172 *retval = property_get(context, "Johnson.Generator.create");
576e1fe #28 #23 arrays work in js land and so does for .. in
Aaron Patterson authored
173 return JS_TRUE;
174 }
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
175
204c021 switching to hash based dynamic properties
Aaron Patterson authored
176 // if the Ruby object has a dynamic js property with a key
177 // matching the property we're looking for, pull the value out of
178 // that map.
78f8bf9 @jbarnette Naming and formatting nitpicks.
authored
179
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
180 else if (autovivified_p(ruby_context, self, name))
204c021 switching to hash based dynamic properties
Aaron Patterson authored
181 {
182 *retval = convert_to_js(context,
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
183 rb_funcall(Johnson_SpiderMonkey_JSLandProxy(),
184 rb_intern("autovivified"), 2, self, rb_str_new2(name)));
204c021 switching to hash based dynamic properties
Aaron Patterson authored
185 }
186
5ccbbfa Constants can be accessed as properties in JSLand.
jbarnette authored
187 // if the Ruby object is a Module or Class and has a matching
188 // const defined, return the converted result of const_get
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
189
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
190 else if (const_p(self, name))
5ccbbfa Constants can be accessed as properties in JSLand.
jbarnette authored
191 {
192 *retval = convert_to_js(context,
193 rb_funcall(self, rb_intern("const_get"), 1, ID2SYM(ruby_id)));
194 }
1f9f150 @tenderlove giving spidermonkey access to ruby constants
tenderlove authored
195
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
196 // otherwise, if it's a global, return the global
197 else if (global_p(name))
1f9f150 @tenderlove giving spidermonkey access to ruby constants
tenderlove authored
198 {
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
199 *retval = convert_to_js(context, rb_gv_get(name));
1f9f150 @tenderlove giving spidermonkey access to ruby constants
tenderlove authored
200 }
5ccbbfa Constants can be accessed as properties in JSLand.
jbarnette authored
201
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
202 // otherwise, if the Ruby object has a an attribute method matching
5ccbbfa Constants can be accessed as properties in JSLand.
jbarnette authored
203 // the property we're trying to get, call it and return the converted result
204
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
205 else if (attribute_p(self, name))
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
206 {
207 VALUE method = rb_funcall(self, rb_intern("method"), 1, ID2SYM(ruby_id));
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
208 *retval = convert_to_js(context, rb_funcall(self, ruby_id, 0));
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
209 }
5ccbbfa Constants can be accessed as properties in JSLand.
jbarnette authored
210
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
211 // otherwise, if the Ruby object quacks sorta like a hash (it responds to
212 // "[]" and "key?"), index it by key and return the converted result
213
214 else if (has_key_p(self, name))
215 {
216 *retval = convert_to_js(context, rb_funcall(self, rb_intern("[]"), 1, rb_str_new2(name)));
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
217 }
218
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
219 // otherwise, it's a method being accessed as a property, which means
220 // we need to return a lambda
221
cfcba6d @jbarnette Added a few more FIXMEs.
authored
222 // FIXME: this should really wrap the Method for 'name' in a JS class
223 // rather than generating a wrapper Proc
224
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
225 else if (method_p(self, name))
226 {
227 *retval = convert_to_js(context,
73ad637 @jbarnette Cleaned up proxying of callable (Proc, Method) Ruby objects.
authored
228 rb_funcall(self, rb_intern("method"), 1, rb_str_new2(name)));
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
229 }
230
231 // else it's undefined (JS_VOID) by default
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
232 return JS_TRUE;
233 }
234
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
235 // called for lazily resolved properties, which should go away
236 static JSBool get_and_destroy_resolved_property(
237 JSContext* js_context, JSObject* obj, jsval id, jsval* retval)
238 {
239 char* name = JS_GetStringBytes(JSVAL_TO_STRING(id));
240 JS_DeleteProperty(js_context, obj, name);
241 return get(js_context, obj, id, retval);
242 }
243
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
244 static JSBool set(JSContext* js_context, JSObject* obj, jsval id, jsval* value)
245 {
246 VALUE ruby_context;
247 assert(ruby_context = (VALUE)JS_GetContextPrivate(js_context));
248
249 OurContext* context;
250 Data_Get_Struct(ruby_context, OurContext, context);
251
252 VALUE self;
109858e @jbarnette Make JSLandProxyClass more easily parameterizable.
authored
253 assert(self = (VALUE)JS_GetInstancePrivate(context->js, obj, JS_GET_CLASS(context->js, obj), NULL));
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
254
e0d5bf2 @jbarnette Simple implementation for working numeric array indexes.
authored
255 // Short-circuit for numeric indexes
256
257 if (JSVAL_IS_INT(id))
258 {
259 if (indexable_p(self))
260 rb_funcall(self, rb_intern("[]="),
261 2, INT2FIX(JSVAL_TO_INT(id)), convert_to_ruby(context, *value));
262
263 return JS_TRUE;
264 }
265
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
266 char* key = JS_GetStringBytes(JSVAL_TO_STRING(id));
267 VALUE ruby_key = rb_str_new2(key);
268
269 VALUE setter = rb_str_append(rb_str_new3(ruby_key), rb_str_new2("="));
270 VALUE setter_id = rb_intern(StringValuePtr(setter));
271
46ffbc1 @jbarnette JSland proxies of Ruby classes have working constructors. [#29 state:res...
authored
272 VALUE settable_p = rb_funcall(self, rb_intern("respond_to?"), 1, ID2SYM(setter_id));
273 VALUE indexable_p = rb_funcall(self, rb_intern("respond_to?"), 1, ID2SYM(rb_intern("[]=")));
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
274
46ffbc1 @jbarnette JSland proxies of Ruby classes have working constructors. [#29 state:res...
authored
275 if (settable_p)
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
276 {
277 VALUE method = rb_funcall(self, rb_intern("method"), 1, ID2SYM(setter_id));
278 int arity = NUM2INT(rb_funcall(method, rb_intern("arity"), 0));
279
280 // if the Ruby object has a 1-arity method named "property=",
281 // call it with the converted value
282
283 if (arity == 1)
284 rb_funcall(self, setter_id, 1, convert_to_ruby(context, *value));
285 }
46ffbc1 @jbarnette JSland proxies of Ruby classes have working constructors. [#29 state:res...
authored
286 else if(indexable_p)
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
287 {
288 // otherwise, if the Ruby object quacks sorta like a hash for assignment
289 // (it responds to "[]="), assign it by key
290
7329bb5 autovivifying attributes from js land
Aaron Patterson authored
291 rb_funcall(self, rb_intern("[]="), 2, ruby_key, convert_to_ruby(context, *value));
78f8bf9 @jbarnette Naming and formatting nitpicks.
authored
292 }
293 else
294 {
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
295 rb_funcall(Johnson_SpiderMonkey_JSLandProxy(), rb_intern("autovivify"),
296 3, self, ruby_key, convert_to_ruby(context, *value));
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
297 }
298
299 return JS_TRUE;
300 }
301
b77b3ad @jbarnette Make sure multiple proxy classes are supported.
authored
302 static JSBool construct(JSContext* js_context, JSObject* obj, uintN argc, jsval* argv, jsval* retval)
303 {
46ffbc1 @jbarnette JSland proxies of Ruby classes have working constructors. [#29 state:res...
authored
304 VALUE ruby_context;
305 assert(ruby_context = (VALUE)JS_GetContextPrivate(js_context));
306
307 OurContext* context;
308 Data_Get_Struct(ruby_context, OurContext, context);
309
310 VALUE klass = convert_to_ruby(context, JS_ARGV_CALLEE(argv));
311 VALUE args = rb_ary_new();
312
313 int i;
314
315 for (i = 0; i < argc; ++i)
316 rb_ary_push(args, convert_to_ruby(context, argv[i]));
317
318 *retval = convert_to_js(context,
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
319 rb_funcall(Johnson_SpiderMonkey_JSLandProxy(), rb_intern("send_with_possible_block"),
320 3, klass, ID2SYM(rb_intern("new")), args));
46ffbc1 @jbarnette JSland proxies of Ruby classes have working constructors. [#29 state:res...
authored
321
b77b3ad @jbarnette Make sure multiple proxy classes are supported.
authored
322 return JS_TRUE;
323 }
324
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
325 static JSBool resolve(JSContext *js_context, JSObject *obj, jsval id, uintN flags, JSObject **objp)
326 {
327 VALUE ruby_context;
328 assert(ruby_context = (VALUE)JS_GetContextPrivate(js_context));
329
330 OurContext* context;
331 Data_Get_Struct(ruby_context, OurContext, context);
332
333 char* name = JS_GetStringBytes(JS_ValueToString(js_context, id));
334
335 if (respond_to_p(js_context, obj, name))
336 {
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
337 assert(JS_DefineProperty(js_context, obj, name, JSVAL_VOID,
6b3683d @jbarnette Make with() work. [#31 state:resolved]
authored
338 get_and_destroy_resolved_property, set, JSPROP_ENUMERATE));
339
340 *objp = obj;
341 }
342
343 return JS_TRUE;
344 }
345
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
346 static JSBool method_missing(JSContext* js_context, JSObject* obj, uintN argc, jsval* argv, jsval* retval)
347 {
348 VALUE ruby_context;
349 assert(ruby_context = (VALUE)JS_GetContextPrivate(js_context));
350
351 OurContext* context;
352 Data_Get_Struct(ruby_context, OurContext, context);
353
354 VALUE self;
109858e @jbarnette Make JSLandProxyClass more easily parameterizable.
authored
355 assert(self = (VALUE)JS_GetInstancePrivate(context->js, obj, JS_GET_CLASS(context->js, obj), NULL));
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
356
357 char* key = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
358 VALUE ruby_id = rb_intern(key);
359
78f8bf9 @jbarnette Naming and formatting nitpicks.
authored
360 // FIXME: this is horrible and lazy, to_a comes from enumerable on proxy (argv[1] is a JSArray)
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
361 VALUE args = rb_funcall(convert_to_ruby(context, argv[1]), rb_intern("to_a"), 0);
362
363 *retval = convert_to_js(context,
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
364 rb_funcall(Johnson_SpiderMonkey_JSLandProxy(), rb_intern("send_with_possible_block"),
365 3, self, ID2SYM(ruby_id), args));
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
366
367 return JS_TRUE;
368 }
369
73ad637 @jbarnette Cleaned up proxying of callable (Proc, Method) Ruby objects.
authored
370 static JSBool call(JSContext* js_context, JSObject* obj, uintN argc, jsval* argv, jsval* retval)
371 {
372 VALUE ruby_context;
373 assert(ruby_context = (VALUE)JS_GetContextPrivate(js_context));
374
375 OurContext* context;
376 Data_Get_Struct(ruby_context, OurContext, context);
377
378 VALUE self;// = convert_to_ruby(context, JS_ARGV_CALLEE(argv));
379 assert(self = (VALUE)JS_GetInstancePrivate(context->js, JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv)), &JSLandCallableProxyClass, NULL));
380
381 VALUE args = rb_ary_new();
382 int i;
383
384 for (i = 0; i < argc; ++i)
385 rb_ary_push(args, convert_to_ruby(context, argv[i]));
386
387 *retval = convert_to_js(context,
388 rb_funcall(Johnson_SpiderMonkey_JSLandProxy(), rb_intern("send_with_possible_block"),
389 3, self, ID2SYM(rb_intern("call")), args));
390
391 return JS_TRUE;
392 }
393
01b0682 @jbarnette JS proxies roundtrip.
authored
394 JSBool js_value_is_proxy(OurContext* context, jsval maybe_proxy)
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
395 {
b77b3ad @jbarnette Make sure multiple proxy classes are supported.
authored
396 JSClass* klass = JS_GET_CLASS(context->js, JSVAL_TO_OBJECT(maybe_proxy));
73ad637 @jbarnette Cleaned up proxying of callable (Proc, Method) Ruby objects.
authored
397
398 return &JSLandProxyClass == klass
399 || &JSLandClassProxyClass == klass
400 || &JSLandCallableProxyClass == klass;
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
401 }
402
e18f74d @jbarnette Renaming proxies for clarity.
authored
403 VALUE unwrap_js_land_proxy(OurContext* context, jsval proxy)
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
404 {
01b0682 @jbarnette JS proxies roundtrip.
authored
405 VALUE value;
109858e @jbarnette Make JSLandProxyClass more easily parameterizable.
authored
406 JSObject *proxy_object = JSVAL_TO_OBJECT(proxy);
407
408 assert(value = (VALUE)JS_GetInstancePrivate(context->js, proxy_object,
409 JS_GET_CLASS(context->js, proxy_object), NULL));
410
f0cc336 js proxies roundtrip correctly. still no gc root.
jbarnette authored
411 return value;
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
412 }
413
3c24fe9 Fixed Ruby value tracking/GC rooting.
jbarnette authored
414 static void finalize(JSContext* js_context, JSObject* obj)
415 {
416 VALUE ruby_context = (VALUE)JS_GetContextPrivate(js_context);
417
418 if (ruby_context)
419 {
420 OurContext* context;
421 Data_Get_Struct(ruby_context, OurContext, context);
422
423 VALUE self;
109858e @jbarnette Make JSLandProxyClass more easily parameterizable.
authored
424 assert(self = (VALUE)JS_GetInstancePrivate(context->js, obj,
425 JS_GET_CLASS(context->js, obj), NULL));
3c24fe9 Fixed Ruby value tracking/GC rooting.
jbarnette authored
426
427 // remove the proxy OID from the id map
428 JS_HashTableRemove(context->rbids, (void *)rb_obj_id(self));
429
430 // free up the ruby value for GC
431 rb_funcall(ruby_context, rb_intern("remove_gcthing"), 1, self);
432 }
433 }
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
434
e18f74d @jbarnette Renaming proxies for clarity.
authored
435 jsval make_js_land_proxy(OurContext* context, VALUE value)
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
436 {
3c24fe9 Fixed Ruby value tracking/GC rooting.
jbarnette authored
437 jsid id = (jsid)JS_HashTableLookup(context->rbids, (void *)rb_obj_id(value));
438 jsval js;
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
439
3c24fe9 Fixed Ruby value tracking/GC rooting.
jbarnette authored
440 if (id)
441 {
442 assert(JS_IdToValue(context->js, id, &js));
443 }
444 else
445 {
446 JSObject *jsobj;
b77b3ad @jbarnette Make sure multiple proxy classes are supported.
authored
447
448 JSClass *klass = &JSLandProxyClass;
449 if (T_CLASS == TYPE(value)) klass = &JSLandClassProxyClass;
450
73ad637 @jbarnette Cleaned up proxying of callable (Proc, Method) Ruby objects.
authored
451 // FIXME: hack; should happen in Rubyland
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
452 if (T_STRUCT == TYPE(value))
453 rb_funcall(Johnson_SpiderMonkey_JSLandProxy(),
454 rb_intern("treat_all_properties_as_methods"), 1, value);
73ad637 @jbarnette Cleaned up proxying of callable (Proc, Method) Ruby objects.
authored
455
456 JSBool callable_p = rb_class_of(value) == rb_cMethod
457 || rb_class_of(value) == rb_cProc;
b7616dd @jbarnette Reimplement property and method access. Mostly.
authored
458
73ad637 @jbarnette Cleaned up proxying of callable (Proc, Method) Ruby objects.
authored
459 if (callable_p)
460 klass = &JSLandCallableProxyClass;
461
b77b3ad @jbarnette Make sure multiple proxy classes are supported.
authored
462 assert(jsobj = JS_NewObject(context->js, klass, NULL, NULL));
3c24fe9 Fixed Ruby value tracking/GC rooting.
jbarnette authored
463 assert(JS_SetPrivate(context->js, jsobj, (void*)value));
576e1fe #28 #23 arrays work in js land and so does for .. in
Aaron Patterson authored
464
73ad637 @jbarnette Cleaned up proxying of callable (Proc, Method) Ruby objects.
authored
465 if (!callable_p)
466 assert(JS_DefineFunction(context->js, jsobj,
467 "__noSuchMethod__", method_missing, 2, 0));
3c24fe9 Fixed Ruby value tracking/GC rooting.
jbarnette authored
468
469 js = OBJECT_TO_JSVAL(jsobj);
470
471 jsval newid;
472 assert(JS_ValueToId(context->js, js, &newid));
473
474 // put the proxy OID in the id map
475 assert(JS_HashTableAdd(context->rbids, (void *)rb_obj_id(value), (void *)newid));
476
477 // root the ruby value for GC
478 VALUE ruby_context = (VALUE)JS_GetContextPrivate(context->js);
479 rb_funcall(ruby_context, rb_intern("add_gcthing"), 1, value);
480 }
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
481
3c24fe9 Fixed Ruby value tracking/GC rooting.
jbarnette authored
482 return js;
69ace87 JS-land proxies for Ruby objects. No support for GC or roundtripping.
jbarnette authored
483 }
Something went wrong with that request. Please try again.