Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Simple implementation for working numeric array indexes.

  • Loading branch information...
commit e0d5bf2357e5c15c42cda94c20c07fab237827d8 1 parent b7616dd
@jbarnette authored
View
27 ext/spidermonkey/js_land_proxy.c
@@ -73,6 +73,11 @@ static JSBool attribute_p(VALUE self, char* name)
rb_intern("js_property?"), 2, self, ID2SYM(rb_id));
}
+static JSBool indexable_p(VALUE self)
+{
+ rb_funcall(self, rb_intern("respond_to?"), 1, ID2SYM(rb_intern("[]")));
+}
+
static JSBool has_key_p(VALUE self, char* name)
{
return rb_funcall(self, rb_intern("respond_to?"), 1, ID2SYM(rb_intern("[]")))
@@ -119,6 +124,17 @@ static JSBool get(JSContext* js_context, JSObject* obj, jsval id, jsval* retval)
VALUE self;
assert(self = (VALUE)JS_GetInstancePrivate(context->js, obj, JS_GET_CLASS(context->js, obj), NULL));
+ // Short-circuit for numeric indexes
+
+ if (JSVAL_IS_INT(id))
+ {
+ if (indexable_p(self))
+ *retval = convert_to_js(context,
+ rb_funcall(self, rb_intern("[]"), 1, INT2FIX(JSVAL_TO_INT(id))));
+
+ return JS_TRUE;
+ }
+
char* name = JS_GetStringBytes(JSVAL_TO_STRING(id));
VALUE ruby_id = rb_intern(name);
@@ -218,6 +234,17 @@ static JSBool set(JSContext* js_context, JSObject* obj, jsval id, jsval* value)
VALUE self;
assert(self = (VALUE)JS_GetInstancePrivate(context->js, obj, JS_GET_CLASS(context->js, obj), NULL));
+ // Short-circuit for numeric indexes
+
+ if (JSVAL_IS_INT(id))
+ {
+ if (indexable_p(self))
+ rb_funcall(self, rb_intern("[]="),
+ 2, INT2FIX(JSVAL_TO_INT(id)), convert_to_ruby(context, *value));
+
+ return JS_TRUE;
+ }
+
char* key = JS_GetStringBytes(JSVAL_TO_STRING(id));
VALUE ruby_key = rb_str_new2(key);
View
36 test/johnson/conversions/array_test.rb
@@ -0,0 +1,36 @@
+require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
+
+module Johnson
+ module Conversions
+ class ArrayTest < Johnson::TestCase
+ def setup
+ @context = Johnson::Context.new
+ end
+
+ def test_array_index_get
+ @context[:list] = [1, 2, 3, 4]
+ assert_equal(1, @context.evaluate("list[0]"))
+ end
+
+ def test_array_index_set
+ @context[:list] = []
+ @context.evaluate("list[0] = 42")
+ assert_equal(42, @context[:list][0])
+ end
+
+ def test_array_works_with_for_in
+ list = [1, 2, 3, 4]
+
+ @context['alert'] = lambda { |x| p x }
+ @context['list'] = list
+ @context.evaluate("
+ var new_list = [];
+ for(x in list) {
+ new_list.push(x + 1);
+ }
+ ")
+ assert_equal(list.map { |x| x + 1}, @context['new_list'].to_a)
+ end
+ end
+ end
+end
View
14 test/johnson/spidermonkey/js_land_proxy_test.rb
@@ -79,20 +79,6 @@ def test_catch_missing_require
}
")
end
-
- def test_array_gets_returned
- list = [1,2,3,4]
-
- @context['alert'] = lambda { |x| p x }
- @context['list'] = list
- @context.evaluate("
- var new_list = [];
- for(x in list) {
- new_list.push(x + 1);
- }
- ")
- assert_equal(list.map { |x| x + 1}, @context['new_list'].to_a)
- end
def test_proxies_get_reused
@context["foo"] = @context["bar"] = Foo.new
Please sign in to comment.
Something went wrong with that request. Please try again.