Permalink
Browse files

autovivifying attributes from js land

  • Loading branch information...
1 parent 1146a19 commit 7329bb592deca42946f4c0262925107a385ef52b Aaron Patterson committed Apr 9, 2008
Showing with 26 additions and 6 deletions.
  1. +1 −0 .gitignore
  2. +6 −6 ext/spidermonkey/js_proxy.c
  3. +9 −0 lib/johnson/spidermonkey/context.rb
  4. +10 −0 test/johnson/spidermonkey/js_proxy_test.rb
View
@@ -12,4 +12,5 @@
/vendor/spidermonkey/*.OBJ
/vendor/spidermonkey/editline/*.OBJ
+.*.swp
@@ -91,6 +91,8 @@ static JSBool set(JSContext* js_context, JSObject* obj, jsval id, jsval* value)
VALUE setter_id = rb_intern(StringValuePtr(setter));
VALUE has_setter = rb_funcall(self, rb_intern("respond_to?"), 1, ID2SYM(setter_id));
+ VALUE is_index_assignable =
+ rb_funcall(self, rb_intern("respond_to?"), 1, ID2SYM(rb_intern("[]=")));
if (has_setter)
{
@@ -103,16 +105,14 @@ static JSBool set(JSContext* js_context, JSObject* obj, jsval id, jsval* value)
if (arity == 1)
rb_funcall(self, setter_id, 1, convert_to_ruby(context, *value));
}
- else
+ else if(is_index_assignable)
{
// otherwise, if the Ruby object quacks sorta like a hash for assignment
// (it responds to "[]="), assign it by key
- VALUE is_index_assignable =
- rb_funcall(self, rb_intern("respond_to?"), 1, ID2SYM(rb_intern("[]=")));
-
- if (is_index_assignable)
- rb_funcall(self, rb_intern("[]="), 2, ruby_key, convert_to_ruby(context, *value));
+ rb_funcall(self, rb_intern("[]="), 2, ruby_key, convert_to_ruby(context, *value));
+ } else {
+ rb_funcall(ruby_context, rb_intern("autovivify"), 3, self, ruby_key, convert_to_ruby(context, *value));
}
return JS_TRUE;
@@ -24,6 +24,15 @@ def jsend(target, symbol, args)
block = args.pop if args.last.is_a?(RubyProxy) && args.last.function?
target.__send__(symbol, *args, &block)
end
+
+ # called from js_proxy.c:set
+ def autovivify(target, attribute, value)
+ (class << target; self; end).instance_eval do
+ attr_accessor :"#{attribute}"
+ end
+
+ target.send(:"#{attribute}=", value)
+ end
# called from js_proxy.c:make_js_proxy
def add_gcthing(thing)
@@ -58,6 +58,16 @@ def test_proxies_get_reused
@context["foo"] = @context["bar"] = Foo.new
assert_js_equal(true, "foo === bar")
end
+
+ def test_attributes_get_added_to_ruby
+ foo = @context["foo"] = Foo.new
+ assert !foo.respond_to?(:johnson)
+ @context.evaluate("foo.johnson = 'explode';")
+ assert foo.respond_to?(:johnson)
+ assert_equal('explode', foo.johnson)
+ assert_js_equal('explode', 'foo.johnson')
+ assert !Foo.new.respond_to?(:johnson)
+ end
def test_proxies_roundtrip
@context["foo"] = foo = Foo.new

0 comments on commit 7329bb5

Please sign in to comment.