Search code examples
javascriptexceptionprototypejs

Bug with Prototype 1.7.1 and Native Array Usage


Using chrome 21 and prototype 1.7.1, I have discovered that using throw $break does not work.

The Error gets thrown up to the browser when it should have been stopped by

if (e != $break) { ... }

I suspect that this occurs because inject has a native implementation in Chrome, and it does not get wrapped by the same functionality as the other built-in functions.

Am I correct when assuming this, or is there something wrong with my code?

Code to re-create:

var a = [1,2,3,4,5,6,7,9].inject([], function(arr, e) {
    console.log(e);
    if (e === 5) {
        throw $break;
    }

    arr.push('Done ' + e);
    return arr;
});
console.log('Final Array : ' + a)

update

just tested with Firefox 14 and IE 9, the same error presents itself..

update (2015)

This seems to be fixed by 1.7.3, tested with Chrome 45.0.2454.101

Verified by checking the source, reduce was removed


Solution

  • The problem is that as of Prototype 1.7.1, Array#inject has two implementations, and they behave differently. (This is Not Goodtm.) It's a breaking change between Prototype 1.7.1 and 1.7.0, as we can see using this fiddle vs. this one.

    If the native Array object has the reduce function from ES5, Array#inject uses it — without handling $break — whereas if it doesn't, Array#inject is implemented via Enumerable#inject, which uses Enumerable#each, which handles $break.

    You can see this if you search the Prototype 1.7.1 source. First you find the non-reduce version in Enumerable, then you find the reduce version further down in the Array stuff, and you see that the Array version grabs the Enumerable version if reduce isn't there.