Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

isArray breaks #54

Closed
gregwebs opened this Issue · 9 comments

2 participants

@gregwebs

The constructor of a proxied array does in fact === Array
However, everyone uses toString.apply to determine if an object is an array, and this changes once an object is proxied. I was just looking at the direct proxies ticket and it seems this issue is solved there. Is it possible for us to have a work around until then?

@disnet
Owner

Ha! Yeah, I just ran into this bug too. It causes [].concat(proxiedArray) to give a array of length 1 instead of merging the proxiedArray's elements.

I'm not sure about a workaround yet. Maybe the direct proxy shim fixes the issue? I'll try hacking that into contracts.js and see if that fixes things.

@gregwebs

was reading this: http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
apparently there are issues with checking the constructor in an iframe.
Is it possible for contracts.js to override the toString implementation?

@disnet
Owner

Ugh, and that's a no on the direct proxy shim workaround.

% cat array.js 
require('harmony-reflect');

var arr = Proxy([1,2], {});
console.log([].concat([1,2]))
console.log([].concat(arr))
% node --harmony array.js
[ 1, 2 ]
[ { '0': 1, '1': 2 } ]
@disnet
Owner

Right so the normal way of checking for an array without using the new Array.isArray builtin is:

Object.prototype.toString(arr) === '[object Array]'

So it would be straightforward to just patch Object.prototype.toString. The problem is that the functions we really care about like [].concat don't use toString, rather they consult the internal (c++) representation to decide if it's an array or not. Dito Array.isArray. So no amount of patching will help us there.

Humm...although we could just patch concat and Array.isArray directly to do the right thing by reimplementing their functionality in pure js for proxied arrays (and toString for people using the isArray polyfil).

@gregwebs

yikes! We already don't care about performance of contracts, so re-implemenation in js is fine if it isn't buggy.

Is it possible for the contracts proxy behavior be modified? So that it does less for arrays and the proxy is added/removed earlier? I don't know if that actually make sense...

@disnet
Owner

Yeah, I think that's probably the best option for now. Just do simple one-time checks when the contract get applied to a value (is the value actually an array, etc.) and don't wrap it. This means we don't get to check array accesses but things actually work.

@disnet disnet referenced this issue from a commit
@disnet no longer wrapping arrays #54 ccc269d
@disnet
Owner

Ok, contracts are no longer wrapping arrays. New version pushed out to npm too.

Hopefully direct proxies land soon.

@gregwebs

awesome! I had to turn my contracts off :(
will test soon

@gregwebs

seems to be working. Thanks!

@gregwebs gregwebs closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.