Wed, 31 Dec 2014 06:09:35 +0100
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);