tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Iter.js (23930B)


      1 /***
      2 
      3 MochiKit.Iter 1.4
      4 
      5 See <http://mochikit.com/> for documentation, downloads, license, etc.
      6 
      7 (c) 2005 Bob Ippolito.  All rights Reserved.
      8 
      9 ***/
     10 
     11 if (typeof(dojo) != 'undefined') {
     12    dojo.provide('MochiKit.Iter');
     13    dojo.require('MochiKit.Base');
     14 }
     15 
     16 if (typeof(JSAN) != 'undefined') {
     17    JSAN.use("MochiKit.Base", []);
     18 }
     19 
     20 try {
     21    if (typeof(MochiKit.Base) == 'undefined') {
     22        throw "";
     23    }
     24 } catch (e) {
     25    throw "MochiKit.Iter depends on MochiKit.Base!";
     26 }
     27 
     28 if (typeof(MochiKit.Iter) == 'undefined') {
     29    MochiKit.Iter = {};
     30 }
     31 
     32 MochiKit.Iter.NAME = "MochiKit.Iter";
     33 MochiKit.Iter.VERSION = "1.4";
     34 MochiKit.Base.update(MochiKit.Iter, {
     35    __repr__: function () {
     36        return "[" + this.NAME + " " + this.VERSION + "]";
     37    },
     38    toString: function () {
     39        return this.__repr__();
     40    },
     41 
     42    /** @id MochiKit.Iter.registerIteratorFactory  */
     43    registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) {
     44        MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override);
     45    },
     46 
     47    /** @id MochiKit.Iter.iter */
     48    iter: function (iterable, /* optional */ sentinel) {
     49        var self = MochiKit.Iter;
     50        if (arguments.length == 2) {
     51            return self.takewhile(
     52                function (a) { return a != sentinel; },
     53                iterable
     54            );
     55        }
     56        if (typeof(iterable.next) == 'function') {
     57            return iterable;
     58        } else if (typeof(iterable.iter) == 'function') {
     59            return iterable.iter();
     60        /*
     61        }  else if (typeof(iterable.__iterator__) == 'function') {
     62            //
     63            // XXX: We can't support JavaScript 1.7 __iterator__ directly
     64            //      because of Object.prototype.__iterator__
     65            //
     66            return iterable.__iterator__();
     67        */
     68        }
     69 
     70        try {
     71            return self.iteratorRegistry.match(iterable);
     72        } catch (e) {
     73            var m = MochiKit.Base;
     74            if (e == m.NotFound) {
     75                e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable");
     76            }
     77            throw e;
     78        }
     79    },
     80 
     81    /** @id MochiKit.Iter.count */
     82    count: function (n) {
     83        if (!n) {
     84            n = 0;
     85        }
     86        var m = MochiKit.Base;
     87        return {
     88            repr: function () { return "count(" + n + ")"; },
     89            toString: m.forwardCall("repr"),
     90            next: m.counter(n)
     91        };
     92    },
     93 
     94    /** @id MochiKit.Iter.cycle */
     95    cycle: function (p) {
     96        var self = MochiKit.Iter;
     97        var m = MochiKit.Base;
     98        var lst = [];
     99        var iterator = self.iter(p);
    100        return {
    101            repr: function () { return "cycle(...)"; },
    102            toString: m.forwardCall("repr"),
    103            next: function () {
    104                try {
    105                    var rval = iterator.next();
    106                    lst.push(rval);
    107                    return rval;
    108                } catch (e) {
    109                    if (e != self.StopIteration) {
    110                        throw e;
    111                    }
    112                    if (lst.length === 0) {
    113                        this.next = function () {
    114                            throw self.StopIteration;
    115                        };
    116                    } else {
    117                        var i = -1;
    118                        this.next = function () {
    119                            i = (i + 1) % lst.length;
    120                            return lst[i];
    121                        };
    122                    }
    123                    return this.next();
    124                }
    125            }
    126        };
    127    },
    128 
    129    /** @id MochiKit.Iter.repeat */
    130    repeat: function (elem, /* optional */n) {
    131        var m = MochiKit.Base;
    132        if (typeof(n) == 'undefined') {
    133            return {
    134                repr: function () {
    135                    return "repeat(" + m.repr(elem) + ")";
    136                },
    137                toString: m.forwardCall("repr"),
    138                next: function () {
    139                    return elem;
    140                }
    141            };
    142        }
    143        return {
    144            repr: function () {
    145                return "repeat(" + m.repr(elem) + ", " + n + ")";
    146            },
    147            toString: m.forwardCall("repr"),
    148            next: function () {
    149                if (n <= 0) {
    150                    throw MochiKit.Iter.StopIteration;
    151                }
    152                n -= 1;
    153                return elem;
    154            }
    155        };
    156    },
    157 
    158    /** @id MochiKit.Iter.next */
    159    next: function (iterator) {
    160        return iterator.next();
    161    },
    162 
    163    /** @id MochiKit.Iter.izip */
    164    izip: function (p, q/*, ...*/) {
    165        var m = MochiKit.Base;
    166        var self = MochiKit.Iter;
    167        var next = self.next;
    168        var iterables = m.map(self.iter, arguments);
    169        return {
    170            repr: function () { return "izip(...)"; },
    171            toString: m.forwardCall("repr"),
    172            next: function () { return m.map(next, iterables); }
    173        };
    174    },
    175 
    176    /** @id MochiKit.Iter.ifilter */
    177    ifilter: function (pred, seq) {
    178        var m = MochiKit.Base;
    179        seq = MochiKit.Iter.iter(seq);
    180        if (pred === null) {
    181            pred = m.operator.truth;
    182        }
    183        return {
    184            repr: function () { return "ifilter(...)"; },
    185            toString: m.forwardCall("repr"),
    186            next: function () {
    187                while (true) {
    188                    var rval = seq.next();
    189                    if (pred(rval)) {
    190                        return rval;
    191                    }
    192                }
    193                // mozilla warnings aren't too bright
    194                return undefined;
    195            }
    196        };
    197    },
    198 
    199    /** @id MochiKit.Iter.ifilterfalse */
    200    ifilterfalse: function (pred, seq) {
    201        var m = MochiKit.Base;
    202        seq = MochiKit.Iter.iter(seq);
    203        if (pred === null) {
    204            pred = m.operator.truth;
    205        }
    206        return {
    207            repr: function () { return "ifilterfalse(...)"; },
    208            toString: m.forwardCall("repr"),
    209            next: function () {
    210                while (true) {
    211                    var rval = seq.next();
    212                    if (!pred(rval)) {
    213                        return rval;
    214                    }
    215                }
    216                // mozilla warnings aren't too bright
    217                return undefined;
    218            }
    219        };
    220    },
    221 
    222    /** @id MochiKit.Iter.islice */
    223    islice: function (seq/*, [start,] stop[, step] */) {
    224        var self = MochiKit.Iter;
    225        var m = MochiKit.Base;
    226        seq = self.iter(seq);
    227        var start = 0;
    228        var stop = 0;
    229        var step = 1;
    230        var i = -1;
    231        if (arguments.length == 2) {
    232            stop = arguments[1];
    233        } else if (arguments.length == 3) {
    234            start = arguments[1];
    235            stop = arguments[2];
    236        } else {
    237            start = arguments[1];
    238            stop = arguments[2];
    239            step = arguments[3];
    240        }
    241        return {
    242            repr: function () {
    243                return "islice(" + ["...", start, stop, step].join(", ") + ")";
    244            },
    245            toString: m.forwardCall("repr"),
    246            next: function () {
    247                var rval;
    248                while (i < start) {
    249                    rval = seq.next();
    250                    i++;
    251                }
    252                if (start >= stop) {
    253                    throw self.StopIteration;
    254                }
    255                start += step;
    256                return rval;
    257            }
    258        };
    259    },
    260 
    261    /** @id MochiKit.Iter.imap */
    262    imap: function (fun, p, q/*, ...*/) {
    263        var m = MochiKit.Base;
    264        var self = MochiKit.Iter;
    265        var iterables = m.map(self.iter, m.extend(null, arguments, 1));
    266        var map = m.map;
    267        var next = self.next;
    268        return {
    269            repr: function () { return "imap(...)"; },
    270            toString: m.forwardCall("repr"),
    271            next: function () {
    272                return fun.apply(this, map(next, iterables));
    273            }
    274        };
    275    },
    276 
    277    /** @id MochiKit.Iter.applymap */
    278    applymap: function (fun, seq, self) {
    279        seq = MochiKit.Iter.iter(seq);
    280        var m = MochiKit.Base;
    281        return {
    282            repr: function () { return "applymap(...)"; },
    283            toString: m.forwardCall("repr"),
    284            next: function () {
    285                return fun.apply(self, seq.next());
    286            }
    287        };
    288    },
    289 
    290    /** @id MochiKit.Iter.chain */
    291    chain: function (p, q/*, ...*/) {
    292        // dumb fast path
    293        var self = MochiKit.Iter;
    294        var m = MochiKit.Base;
    295        if (arguments.length == 1) {
    296            return self.iter(arguments[0]);
    297        }
    298        var argiter = m.map(self.iter, arguments);
    299        return {
    300            repr: function () { return "chain(...)"; },
    301            toString: m.forwardCall("repr"),
    302            next: function () {
    303                while (argiter.length > 1) {
    304                    try {
    305                        return argiter[0].next();
    306                    } catch (e) {
    307                        if (e != self.StopIteration) {
    308                            throw e;
    309                        }
    310                        argiter.shift();
    311                    }
    312                }
    313                if (argiter.length == 1) {
    314                    // optimize last element
    315                    var arg = argiter.shift();
    316                    this.next = m.bind("next", arg);
    317                    return this.next();
    318                }
    319                throw self.StopIteration;
    320            }
    321        };
    322    },
    323 
    324    /** @id MochiKit.Iter.takewhile */
    325    takewhile: function (pred, seq) {
    326        var self = MochiKit.Iter;
    327        seq = self.iter(seq);
    328        return {
    329            repr: function () { return "takewhile(...)"; },
    330            toString: MochiKit.Base.forwardCall("repr"),
    331            next: function () {
    332                var rval = seq.next();
    333                if (!pred(rval)) {
    334                    this.next = function () {
    335                        throw self.StopIteration;
    336                    };
    337                    this.next();
    338                }
    339                return rval;
    340            }
    341        };
    342    },
    343 
    344    /** @id MochiKit.Iter.dropwhile */
    345    dropwhile: function (pred, seq) {
    346        seq = MochiKit.Iter.iter(seq);
    347        var m = MochiKit.Base;
    348        var bind = m.bind;
    349        return {
    350            "repr": function () { return "dropwhile(...)"; },
    351            "toString": m.forwardCall("repr"),
    352            "next": function () {
    353                while (true) {
    354                    var rval = seq.next();
    355                    if (!pred(rval)) {
    356                        break;
    357                    }
    358                }
    359                this.next = bind("next", seq);
    360                return rval;
    361            }
    362        };
    363    },
    364 
    365    _tee: function (ident, sync, iterable) {
    366        sync.pos[ident] = -1;
    367        var m = MochiKit.Base;
    368        var listMin = m.listMin;
    369        return {
    370            repr: function () { return "tee(" + ident + ", ...)"; },
    371            toString: m.forwardCall("repr"),
    372            next: function () {
    373                var rval;
    374                var i = sync.pos[ident];
    375 
    376                if (i == sync.max) {
    377                    rval = iterable.next();
    378                    sync.deque.push(rval);
    379                    sync.max += 1;
    380                    sync.pos[ident] += 1;
    381                } else {
    382                    rval = sync.deque[i - sync.min];
    383                    sync.pos[ident] += 1;
    384                    if (i == sync.min && listMin(sync.pos) != sync.min) {
    385                        sync.min += 1;
    386                        sync.deque.shift();
    387                    }
    388                }
    389                return rval;
    390            }
    391        };
    392    },
    393 
    394    /** @id MochiKit.Iter.tee */
    395    tee: function (iterable, n/* = 2 */) {
    396        var rval = [];
    397        var sync = {
    398            "pos": [],
    399            "deque": [],
    400            "max": -1,
    401            "min": -1
    402        };
    403        if (arguments.length == 1 || typeof(n) == "undefined" || n === null) {
    404            n = 2;
    405        }
    406        var self = MochiKit.Iter;
    407        iterable = self.iter(iterable);
    408        var _tee = self._tee;
    409        for (var i = 0; i < n; i++) {
    410            rval.push(_tee(i, sync, iterable));
    411        }
    412        return rval;
    413    },
    414 
    415    /** @id MochiKit.Iter.list */
    416    list: function (iterable) {
    417        // Fast-path for Array and Array-like
    418        var rval;
    419        if (iterable instanceof Array) {
    420            return iterable.slice();
    421        } 
    422        // this is necessary to avoid a Safari crash
    423        if (typeof(iterable) == "function" &&
    424                !(iterable instanceof Function) &&
    425                typeof(iterable.length) == 'number') {
    426            rval = [];
    427            for (var i = 0; i < iterable.length; i++) {
    428                rval.push(iterable[i]);
    429            }
    430            return rval;
    431        }
    432 
    433        var self = MochiKit.Iter;
    434        iterable = self.iter(iterable);
    435        var rval = [];
    436        try {
    437            while (true) {
    438                rval.push(iterable.next());
    439            }
    440        } catch (e) {
    441            if (e != self.StopIteration) {
    442                throw e;
    443            }
    444            return rval;
    445        }
    446        // mozilla warnings aren't too bright
    447        return undefined;
    448    },
    449 
    450 
    451    /** @id MochiKit.Iter.reduce */
    452    reduce: function (fn, iterable, /* optional */initial) {
    453        var i = 0;
    454        var x = initial;
    455        var self = MochiKit.Iter;
    456        iterable = self.iter(iterable);
    457        if (arguments.length < 3) {
    458            try {
    459                x = iterable.next();
    460            } catch (e) {
    461                if (e == self.StopIteration) {
    462                    e = new TypeError("reduce() of empty sequence with no initial value");
    463                }
    464                throw e;
    465            }
    466            i++;
    467        }
    468        try {
    469            while (true) {
    470                x = fn(x, iterable.next());
    471            }
    472        } catch (e) {
    473            if (e != self.StopIteration) {
    474                throw e;
    475            }
    476        }
    477        return x;
    478    },
    479 
    480    /** @id MochiKit.Iter.range */
    481    range: function (/* [start,] stop[, step] */) {
    482        var start = 0;
    483        var stop = 0;
    484        var step = 1;
    485        if (arguments.length == 1) {
    486            stop = arguments[0];
    487        } else if (arguments.length == 2) {
    488            start = arguments[0];
    489            stop = arguments[1];
    490        } else if (arguments.length == 3) {
    491            start = arguments[0];
    492            stop = arguments[1];
    493            step = arguments[2];
    494        } else {
    495            throw new TypeError("range() takes 1, 2, or 3 arguments!");
    496        }
    497        if (step === 0) {
    498            throw new TypeError("range() step must not be 0");
    499        }
    500        return {
    501            next: function () {
    502                if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
    503                    throw MochiKit.Iter.StopIteration;
    504                }
    505                var rval = start;
    506                start += step;
    507                return rval;
    508            },
    509            repr: function () {
    510                return "range(" + [start, stop, step].join(", ") + ")";
    511            },
    512            toString: MochiKit.Base.forwardCall("repr")
    513        };
    514    },
    515 
    516    /** @id MochiKit.Iter.sum */
    517    sum: function (iterable, start/* = 0 */) {
    518        if (typeof(start) == "undefined" || start === null) {
    519            start = 0;
    520        }
    521        var x = start;
    522        var self = MochiKit.Iter;
    523        iterable = self.iter(iterable);
    524        try {
    525            while (true) {
    526                x += iterable.next();
    527            }
    528        } catch (e) {
    529            if (e != self.StopIteration) {
    530                throw e;
    531            }
    532        }
    533        return x;
    534    },
    535 
    536    /** @id MochiKit.Iter.exhaust */
    537    exhaust: function (iterable) {
    538        var self = MochiKit.Iter;
    539        iterable = self.iter(iterable);
    540        try {
    541            while (true) {
    542                iterable.next();
    543            }
    544        } catch (e) {
    545            if (e != self.StopIteration) {
    546                throw e;
    547            }
    548        }
    549    },
    550 
    551    /** @id MochiKit.Iter.forEach */
    552    forEach: function (iterable, func, /* optional */self) {
    553        var m = MochiKit.Base;
    554        if (arguments.length > 2) {
    555            func = m.bind(func, self);
    556        }
    557        // fast path for array
    558        if (m.isArrayLike(iterable)) {
    559            try {
    560                for (var i = 0; i < iterable.length; i++) {
    561                    func(iterable[i]);
    562                }
    563            } catch (e) {
    564                if (e != MochiKit.Iter.StopIteration) {
    565                    throw e;
    566                }
    567            }
    568        } else {
    569            self = MochiKit.Iter;
    570            self.exhaust(self.imap(func, iterable));
    571        }
    572    },
    573 
    574    /** @id MochiKit.Iter.every */
    575    every: function (iterable, func) {
    576        var self = MochiKit.Iter;
    577        try {
    578            self.ifilterfalse(func, iterable).next();
    579            return false;
    580        } catch (e) {
    581            if (e != self.StopIteration) {
    582                throw e;
    583            }
    584            return true;
    585        }
    586    },
    587 
    588    /** @id MochiKit.Iter.sorted */
    589    sorted: function (iterable, /* optional */cmp) {
    590        var rval = MochiKit.Iter.list(iterable);
    591        if (arguments.length == 1) {
    592            cmp = MochiKit.Base.compare;
    593        }
    594        rval.sort(cmp);
    595        return rval;
    596    },
    597 
    598    /** @id MochiKit.Iter.reversed */
    599    reversed: function (iterable) {
    600        var rval = MochiKit.Iter.list(iterable);
    601        rval.reverse();
    602        return rval;
    603    },
    604 
    605    /** @id MochiKit.Iter.some */
    606    some: function (iterable, func) {
    607        var self = MochiKit.Iter;
    608        try {
    609            self.ifilter(func, iterable).next();
    610            return true;
    611        } catch (e) {
    612            if (e != self.StopIteration) {
    613                throw e;
    614            }
    615            return false;
    616        }
    617    },
    618 
    619    /** @id MochiKit.Iter.iextend */
    620    iextend: function (lst, iterable) {
    621        if (MochiKit.Base.isArrayLike(iterable)) {
    622            // fast-path for array-like
    623            for (var i = 0; i < iterable.length; i++) {
    624                lst.push(iterable[i]);
    625            }
    626        } else {
    627            var self = MochiKit.Iter;
    628            iterable = self.iter(iterable);
    629            try {
    630                while (true) {
    631                    lst.push(iterable.next());
    632                }
    633            } catch (e) {
    634                if (e != self.StopIteration) {
    635                    throw e;
    636                }
    637            }
    638        }
    639        return lst;
    640    },
    641 
    642    /** @id MochiKit.Iter.groupby */
    643    groupby: function(iterable, /* optional */ keyfunc) {
    644        var m = MochiKit.Base;
    645        var self = MochiKit.Iter;
    646        if (arguments.length < 2) {
    647            keyfunc = m.operator.identity;
    648        }
    649        iterable = self.iter(iterable);
    650 
    651        // shared
    652        var pk = undefined;
    653        var k = undefined;
    654        var v;
    655 
    656        function fetch() {
    657            v = iterable.next();
    658            k = keyfunc(v);
    659        };
    660 
    661        function eat() {
    662            var ret = v;
    663            v = undefined;
    664            return ret;
    665        };
    666 
    667        var first = true;
    668        var compare = m.compare;
    669        return {
    670            repr: function () { return "groupby(...)"; },
    671            next: function() {
    672                // iterator-next
    673 
    674                // iterate until meet next group
    675                while (compare(k, pk) === 0) {
    676                    fetch();
    677                    if (first) {
    678                        first = false;
    679                        break;
    680                    }
    681                }
    682                pk = k;
    683                return [k, {
    684                    next: function() {
    685                        // subiterator-next
    686                        if (v == undefined) { // Is there something to eat?
    687                            fetch();
    688                        }
    689                        if (compare(k, pk) !== 0) {
    690                            throw self.StopIteration;
    691                        }
    692                        return eat();
    693                    }
    694                }];
    695            }
    696        };
    697    },
    698 
    699    /** @id MochiKit.Iter.groupby_as_array */
    700    groupby_as_array: function (iterable, /* optional */ keyfunc) {
    701        var m = MochiKit.Base;
    702        var self = MochiKit.Iter;
    703        if (arguments.length < 2) {
    704            keyfunc = m.operator.identity;
    705        }
    706 
    707        iterable = self.iter(iterable);
    708        var result = [];
    709        var first = true;
    710        var prev_key;
    711        var compare = m.compare;
    712        while (true) {
    713            try {
    714                var value = iterable.next();
    715                var key = keyfunc(value);
    716            } catch (e) {
    717                if (e == self.StopIteration) {
    718                    break;
    719                }
    720                throw e;
    721            }
    722            if (first || compare(key, prev_key) !== 0) {
    723                var values = [];
    724                result.push([key, values]);
    725            }
    726            values.push(value);
    727            first = false;
    728            prev_key = key;
    729        }
    730        return result;
    731    },
    732 
    733    /** @id MochiKit.Iter.arrayLikeIter */
    734    arrayLikeIter: function (iterable) {
    735        var i = 0;
    736        return {
    737            repr: function () { return "arrayLikeIter(...)"; },
    738            toString: MochiKit.Base.forwardCall("repr"),
    739            next: function () {
    740                if (i >= iterable.length) {
    741                    throw MochiKit.Iter.StopIteration;
    742                }
    743                return iterable[i++];
    744            }
    745        };
    746    },
    747 
    748    /** @id MochiKit.Iter.hasIterateNext */
    749    hasIterateNext: function (iterable) {
    750        return (iterable && typeof(iterable.iterateNext) == "function");
    751    },
    752 
    753    /** @id MochiKit.Iter.iterateNextIter */
    754    iterateNextIter: function (iterable) {
    755        return {
    756            repr: function () { return "iterateNextIter(...)"; },
    757            toString: MochiKit.Base.forwardCall("repr"),
    758            next: function () {
    759                var rval = iterable.iterateNext();
    760                if (rval === null || rval === undefined) {
    761                    throw MochiKit.Iter.StopIteration;
    762                }
    763                return rval;
    764            }
    765        };
    766    }
    767 });
    768 
    769 
    770 MochiKit.Iter.EXPORT_OK = [
    771    "iteratorRegistry",
    772    "arrayLikeIter",
    773    "hasIterateNext",
    774    "iterateNextIter",
    775 ];
    776 
    777 MochiKit.Iter.EXPORT = [
    778    "StopIteration",
    779    "registerIteratorFactory",
    780    "iter",
    781    "count",
    782    "cycle",
    783    "repeat",
    784    "next",
    785    "izip",
    786    "ifilter",
    787    "ifilterfalse",
    788    "islice",
    789    "imap",
    790    "applymap",
    791    "chain",
    792    "takewhile",
    793    "dropwhile",
    794    "tee",
    795    "list",
    796    "reduce",
    797    "range",
    798    "sum",
    799    "exhaust",
    800    "forEach",
    801    "every",
    802    "sorted",
    803    "reversed",
    804    "some",
    805    "iextend",
    806    "groupby",
    807    "groupby_as_array"
    808 ];
    809 
    810 MochiKit.Iter.__new__ = function () {
    811    var m = MochiKit.Base;
    812    // Re-use StopIteration if exists (e.g. SpiderMonkey)
    813    if (typeof(StopIteration) != "undefined") {
    814        this.StopIteration = StopIteration;
    815    } else {
    816        /** @id MochiKit.Iter.StopIteration */
    817        this.StopIteration = new m.NamedError("StopIteration");
    818    }
    819    this.iteratorRegistry = new m.AdapterRegistry();
    820    // Register the iterator factory for arrays
    821    this.registerIteratorFactory(
    822        "arrayLike",
    823        m.isArrayLike,
    824        this.arrayLikeIter
    825    );
    826 
    827    this.registerIteratorFactory(
    828        "iterateNext",
    829        this.hasIterateNext,
    830        this.iterateNextIter
    831    );
    832 
    833    this.EXPORT_TAGS = {
    834        ":common": this.EXPORT,
    835        ":all": m.concat(this.EXPORT, this.EXPORT_OK)
    836    };
    837 
    838    m.nameFunctions(this);
    839 
    840 };
    841 
    842 MochiKit.Iter.__new__();
    843 
    844 //
    845 // XXX: Internet Explorer blows
    846 //
    847 if (MochiKit.__export__) {
    848    reduce = MochiKit.Iter.reduce;
    849 }
    850 
    851 MochiKit.Base._exportSymbols(this, MochiKit.Iter);