Skip to content

Commit

Permalink
Wrap Function.prototype.apply to accept Ruby arrays.
Browse files Browse the repository at this point in the history
In the process, fix Array#length to be a JS property, too.
  • Loading branch information
matthewd committed Sep 25, 2009
1 parent 1cf5975 commit 4694592
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 0 deletions.
13 changes: 13 additions & 0 deletions lib/johnson/js/prelude.js
Expand Up @@ -27,6 +27,19 @@ Object.defineProperty(String.prototype, "toSymbol", function() {
return Johnson.symbolize(this.toString());
}, Object.READ_ONLY | Object.NON_DELETABLE);

(function(origApply) {
Object.defineProperty(Function.prototype, "apply", function(thisObj, arrayLike) {
var realArray = arrayLike;
if (!(arrayLike instanceof Array)) {
realArray = [];
for (var i = arrayLike.length - 1; i >= 0; i--) {
realArray[i] = arrayLike[i];
}
}
return origApply.call(this, thisObj, realArray);
}, Object.READ_ONLY | Object.NON_DELETABLE);
})(Function.prototype.apply);

Johnson.Generator = function(enumerableProxy) {
this.items = enumerableProxy.toArray();
this.index = 0;
Expand Down
7 changes: 7 additions & 0 deletions lib/johnson/spidermonkey/js_land_proxy.rb
@@ -1,3 +1,10 @@
# FIXME: This definition should probably be somewhere else
class Array
def js_property?(name)
name == :length
end
end

module Johnson
module SpiderMonkey
module JSLandProxy #:nodoc:
Expand Down
23 changes: 23 additions & 0 deletions test/johnson/conversions/array_test.rb
Expand Up @@ -14,6 +14,11 @@ def test_array_index_set
assert_equal(42, @runtime[:list][0])
end

def test_array_length
@runtime[:list] = [1, 2, 3, 4]
assert_equal(4, @runtime.evaluate("list.length"))
end

def test_array_works_with_for_in
list = [1, 2, 3, 4]

Expand All @@ -27,6 +32,24 @@ def test_array_works_with_for_in
")
assert_equal(list.map { |x| x + 1}, @runtime['new_list'].to_a)
end

def test_array_works_with_function_apply
list = [1, 2, 3, 4]

@runtime['alert'] = lambda { |x| p x }
@runtime['list'] = list
@runtime.evaluate("
var new_list = [];
function process_list(a, b, c, d) {
new_list.push(a * 2);
new_list.push(b * 2);
// skip c
new_list.push(d * 2);
}
process_list.apply(process_list, list);
")
assert_equal([2, 4, 8], @runtime['new_list'].to_a)
end
end
end
end

0 comments on commit 4694592

Please sign in to comment.