testing/mochitest/tests/MochiKit-1.4.2/MochiKit/Iter.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial