Permalink
Browse files

JS proxies roundtrip.

  • Loading branch information...
1 parent fd40f93 commit 01b068241ff99cfb5fa604bac46ea28d9dc4c212 @jbarnette committed Apr 1, 2008
View
65 ext/spidermonkey/conversions.c
@@ -119,6 +119,40 @@ static JSBool jsval_is_a_symbol(OurContext* context, jsval maybe_symbol)
return is_a_symbol;
}
+VALUE convert_object_to_ruby(OurContext* context, jsval object)
+{
+ if (JSVAL_NULL == object) return Qnil;
+
+ if (jsval_is_a_symbol(context, object))
+ return ID2SYM(rb_intern(JS_GetStringBytes(JS_ValueToString(context->js, object))));
+
+ if (js_value_is_proxy(context, object))
+ return unwrap_js_proxy(context, object);
+
+ VALUE id = (VALUE)JS_HashTableLookup(context->jsids, (void *)object);
+
+ if (id)
+ {
+ // if we already have a proxy, return it
+ return rb_funcall(rb_const_get(rb_cObject,
+ rb_intern("ObjectSpace")), rb_intern("_id2ref"), 1, id);
+ }
+ else
+ {
+ // otherwise make one and cache it
+ VALUE proxy = make_ruby_proxy(context, object);
+
+ // put the proxy OID in the id map
+ assert(JS_HashTableAdd(context->jsids, (void *)object, (void *)rb_obj_id(proxy)));
+
+ // root the value for JS GC
+ char key[10];
+ sprintf(key, "%x", (int)object);
+ JS_SetProperty(context->js, context->gcthings, key, &object);
+
+ return proxy;
+ }
+}
VALUE convert_to_ruby(OurContext* context, jsval js)
{
@@ -129,36 +163,7 @@ VALUE convert_to_ruby(OurContext* context, jsval js)
case JSTYPE_FUNCTION:
case JSTYPE_OBJECT:
- if (JSVAL_NULL == js) return Qnil;
-
- if (jsval_is_a_symbol(context, js))
- return ID2SYM(rb_intern(JS_GetStringBytes(JS_ValueToString(context->js, js))));
-
- // FIXME: if it's wrapping a Ruby object, unwrap and return it
-
- VALUE id = (VALUE)JS_HashTableLookup(context->jsids, (void *)js);
-
- if (id)
- {
- // if we already have a proxy, return it
- return rb_funcall(rb_const_get(rb_cObject,
- rb_intern("ObjectSpace")), rb_intern("_id2ref"), 1, id);
- }
- else
- {
- // otherwise make one and cache it
- VALUE proxy = make_ruby_proxy(context, js);
-
- // put the proxy OID in the id map
- assert(JS_HashTableAdd(context->jsids, (void *)js, (void *)rb_obj_id(proxy)));
-
- // root the value for JS GC
- char key[10];
- sprintf(key, "%x", (int)js);
- JS_SetProperty(context->js, context->gcthings, key, &js);
-
- return proxy;
- }
+ return convert_object_to_ruby(context, js);
case JSTYPE_BOOLEAN:
return JSVAL_TRUE == js ? Qtrue : Qfalse;
View
7 ext/spidermonkey/js_proxy.c
@@ -156,14 +156,15 @@ static JSBool method_missing(JSContext* js_context, JSObject* obj, uintN argc, j
return JS_TRUE;
}
-JSBool js_value_is_proxy(jsval maybe_proxy)
+JSBool js_value_is_proxy(OurContext* context, jsval maybe_proxy)
{
- return JS_FALSE;
+ return JS_InstanceOf(context->js, JSVAL_TO_OBJECT(maybe_proxy), &JSProxyClass, NULL);
}
VALUE unwrap_js_proxy(OurContext* context, jsval proxy)
{
- return Qnil;
+ VALUE value;
+ assert(value = (VALUE)JS_GetInstancePrivate(context->js, proxy, &JSProxyClass, NULL));
}
// static jsval convert_ruby_object_to_jsval(CombinedContext* context, VALUE ruby)
View
2 ext/spidermonkey/js_proxy.h
@@ -4,7 +4,7 @@
#include "spidermonkey.h"
#include "context.h"
-JSBool js_value_is_proxy(jsval maybe_proxy);
+JSBool js_value_is_proxy(OurContext* context, jsval maybe_proxy);
VALUE unwrap_js_proxy(OurContext* context, jsval proxy);
jsval make_js_proxy(OurContext* context, VALUE value);
View
5 test/johnson/spidermonkey/js_proxy_test.rb
@@ -54,6 +54,11 @@ def test_proxies_get_reused
assert_js_equal(true, "foo === bar")
end
+ def test_proxies_roundtrip
+ @context["foo"] = foo = Foo.new
+ assert_same(foo, @context.evaluate("foo"))
+ end
+
def test_getter_calls_0_arity_method
@context["foo"] = Foo.new
assert_js_equal(10, "foo.bar")

0 comments on commit 01b0682

Please sign in to comment.