rxjs-rails 2.3.0 → 2.3.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rxjs/rails/version.rb +1 -1
  3. data/vendor/assets/javascripts/rx.aggregates.js +115 -27
  4. data/vendor/assets/javascripts/rx.aggregates.min.js +1 -1
  5. data/vendor/assets/javascripts/rx.all.compat.js +2751 -2702
  6. data/vendor/assets/javascripts/rx.all.compat.min.js +3 -3
  7. data/vendor/assets/javascripts/rx.all.js +2605 -2589
  8. data/vendor/assets/javascripts/rx.all.min.js +3 -3
  9. data/vendor/assets/javascripts/rx.async.compat.js +41 -22
  10. data/vendor/assets/javascripts/rx.async.compat.min.js +1 -1
  11. data/vendor/assets/javascripts/rx.async.js +41 -22
  12. data/vendor/assets/javascripts/rx.async.min.js +1 -1
  13. data/vendor/assets/javascripts/rx.backpressure.js +41 -45
  14. data/vendor/assets/javascripts/rx.backpressure.min.js +1 -1
  15. data/vendor/assets/javascripts/rx.binding.js +81 -111
  16. data/vendor/assets/javascripts/rx.binding.min.js +1 -1
  17. data/vendor/assets/javascripts/rx.coincidence.js +567 -486
  18. data/vendor/assets/javascripts/rx.coincidence.min.js +1 -1
  19. data/vendor/assets/javascripts/rx.compat.js +1430 -1532
  20. data/vendor/assets/javascripts/rx.compat.min.js +2 -2
  21. data/vendor/assets/javascripts/rx.core.compat.js +76 -127
  22. data/vendor/assets/javascripts/rx.core.compat.min.js +1 -1
  23. data/vendor/assets/javascripts/rx.core.js +76 -127
  24. data/vendor/assets/javascripts/rx.core.min.js +1 -1
  25. data/vendor/assets/javascripts/rx.experimental.js +36 -36
  26. data/vendor/assets/javascripts/rx.experimental.min.js +1 -1
  27. data/vendor/assets/javascripts/rx.joinpatterns.js +281 -281
  28. data/vendor/assets/javascripts/rx.js +1286 -1421
  29. data/vendor/assets/javascripts/rx.lite.compat.js +1443 -1749
  30. data/vendor/assets/javascripts/rx.lite.compat.min.js +2 -2
  31. data/vendor/assets/javascripts/rx.lite.extras.js +133 -205
  32. data/vendor/assets/javascripts/rx.lite.extras.min.js +1 -1
  33. data/vendor/assets/javascripts/rx.lite.js +1319 -1658
  34. data/vendor/assets/javascripts/rx.lite.min.js +2 -2
  35. data/vendor/assets/javascripts/rx.min.js +2 -2
  36. data/vendor/assets/javascripts/rx.testing.js +302 -322
  37. data/vendor/assets/javascripts/rx.testing.min.js +1 -1
  38. data/vendor/assets/javascripts/rx.time.js +90 -75
  39. data/vendor/assets/javascripts/rx.time.min.js +1 -1
  40. data/vendor/assets/javascripts/rx.virtualtime.js +264 -279
  41. data/vendor/assets/javascripts/rx.virtualtime.min.js +1 -1
  42. metadata +10 -11
@@ -1,4 +1,4 @@
1
- // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
1
+ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
2
 
3
3
  ;(function (undefined) {
4
4
 
@@ -29,27 +29,27 @@
29
29
  helpers: { }
30
30
  };
31
31
 
32
- // Defaults
33
- var noop = Rx.helpers.noop = function () { },
34
- notDefined = Rx.helpers.notDefined = function (x) { return typeof x === 'undefined'; },
35
- isScheduler = Rx.helpers.isScheduler = function (x) { return x instanceof Rx.Scheduler; },
36
- identity = Rx.helpers.identity = function (x) { return x; },
37
- pluck = Rx.helpers.pluck = function (property) { return function (x) { return x[property]; }; },
38
- just = Rx.helpers.just = function (value) { return function () { return value; }; },
39
- defaultNow = Rx.helpers.defaultNow = (function () { return !!Date.now ? Date.now : function () { return +new Date; }; }()),
40
- defaultComparer = Rx.helpers.defaultComparer = function (x, y) { return isEqual(x, y); },
41
- defaultSubComparer = Rx.helpers.defaultSubComparer = function (x, y) { return x > y ? 1 : (x < y ? -1 : 0); },
42
- defaultKeySerializer = Rx.helpers.defaultKeySerializer = function (x) { return x.toString(); },
43
- defaultError = Rx.helpers.defaultError = function (err) { throw err; },
44
- isPromise = Rx.helpers.isPromise = function (p) { return !!p && typeof p.then === 'function' && p.then !== Rx.Observable.prototype.then; },
45
- asArray = Rx.helpers.asArray = function () { return Array.prototype.slice.call(arguments); },
46
- not = Rx.helpers.not = function (a) { return !a; };
47
-
48
- // Errors
49
- var sequenceContainsNoElements = 'Sequence contains no elements.';
50
- var argumentOutOfRange = 'Argument out of range';
51
- var objectDisposed = 'Object has been disposed';
52
- function checkDisposed() { if (this.isDisposed) { throw new Error(objectDisposed); } }
32
+ // Defaults
33
+ var noop = Rx.helpers.noop = function () { },
34
+ notDefined = Rx.helpers.notDefined = function (x) { return typeof x === 'undefined'; },
35
+ isScheduler = Rx.helpers.isScheduler = function (x) { return x instanceof Rx.Scheduler; },
36
+ identity = Rx.helpers.identity = function (x) { return x; },
37
+ pluck = Rx.helpers.pluck = function (property) { return function (x) { return x[property]; }; },
38
+ just = Rx.helpers.just = function (value) { return function () { return value; }; },
39
+ defaultNow = Rx.helpers.defaultNow = (function () { return !!Date.now ? Date.now : function () { return +new Date; }; }()),
40
+ defaultComparer = Rx.helpers.defaultComparer = function (x, y) { return isEqual(x, y); },
41
+ defaultSubComparer = Rx.helpers.defaultSubComparer = function (x, y) { return x > y ? 1 : (x < y ? -1 : 0); },
42
+ defaultKeySerializer = Rx.helpers.defaultKeySerializer = function (x) { return x.toString(); },
43
+ defaultError = Rx.helpers.defaultError = function (err) { throw err; },
44
+ isPromise = Rx.helpers.isPromise = function (p) { return !!p && typeof p.then === 'function'; },
45
+ asArray = Rx.helpers.asArray = function () { return Array.prototype.slice.call(arguments); },
46
+ not = Rx.helpers.not = function (a) { return !a; };
47
+
48
+ // Errors
49
+ var sequenceContainsNoElements = 'Sequence contains no elements.';
50
+ var argumentOutOfRange = 'Argument out of range';
51
+ var objectDisposed = 'Object has been disposed';
52
+ function checkDisposed() { if (this.isDisposed) { throw new Error(objectDisposed); } }
53
53
 
54
54
  // Shim in iterator support
55
55
  var $iterator$ = (typeof Symbol === 'function' && Symbol.iterator) ||
@@ -82,9 +82,9 @@
82
82
  propertyIsEnumerable = objectProto.propertyIsEnumerable;
83
83
 
84
84
  try {
85
- suportNodeClass = !(toString.call(document) == objectClass && !({ 'toString': 0 } + ''));
85
+ suportNodeClass = !(toString.call(document) == objectClass && !({ 'toString': 0 } + ''));
86
86
  } catch(e) {
87
- suportNodeClass = true;
87
+ suportNodeClass = true;
88
88
  }
89
89
 
90
90
  var shadowedProps = [
@@ -395,309 +395,320 @@
395
395
  return a;
396
396
  }
397
397
 
398
- // Utilities
399
- if (!Function.prototype.bind) {
400
- Function.prototype.bind = function (that) {
401
- var target = this,
402
- args = slice.call(arguments, 1);
403
- var bound = function () {
404
- if (this instanceof bound) {
405
- function F() { }
406
- F.prototype = target.prototype;
407
- var self = new F();
408
- var result = target.apply(self, args.concat(slice.call(arguments)));
409
- if (Object(result) === result) {
410
- return result;
411
- }
412
- return self;
413
- } else {
414
- return target.apply(that, args.concat(slice.call(arguments)));
415
- }
416
- };
398
+ // Utilities
399
+ if (!Function.prototype.bind) {
400
+ Function.prototype.bind = function (that) {
401
+ var target = this,
402
+ args = slice.call(arguments, 1);
403
+ var bound = function () {
404
+ if (this instanceof bound) {
405
+ function F() { }
406
+ F.prototype = target.prototype;
407
+ var self = new F();
408
+ var result = target.apply(self, args.concat(slice.call(arguments)));
409
+ if (Object(result) === result) {
410
+ return result;
411
+ }
412
+ return self;
413
+ } else {
414
+ return target.apply(that, args.concat(slice.call(arguments)));
415
+ }
416
+ };
417
417
 
418
- return bound;
419
- };
420
- }
418
+ return bound;
419
+ };
420
+ }
421
421
 
422
- var boxedString = Object("a"),
423
- splitString = boxedString[0] != "a" || !(0 in boxedString);
424
- if (!Array.prototype.every) {
425
- Array.prototype.every = function every(fun /*, thisp */) {
426
- var object = Object(this),
427
- self = splitString && {}.toString.call(this) == stringClass ?
428
- this.split("") :
429
- object,
430
- length = self.length >>> 0,
431
- thisp = arguments[1];
432
-
433
- if ({}.toString.call(fun) != funcClass) {
434
- throw new TypeError(fun + " is not a function");
435
- }
422
+ if (!Array.prototype.forEach) {
436
423
 
437
- for (var i = 0; i < length; i++) {
438
- if (i in self && !fun.call(thisp, self[i], i, object)) {
439
- return false;
440
- }
441
- }
442
- return true;
443
- };
444
- }
445
-
446
- if (!Array.prototype.map) {
447
- Array.prototype.map = function map(fun /*, thisp*/) {
448
- var object = Object(this),
449
- self = splitString && {}.toString.call(this) == stringClass ?
450
- this.split("") :
451
- object,
452
- length = self.length >>> 0,
453
- result = Array(length),
454
- thisp = arguments[1];
455
-
456
- if ({}.toString.call(fun) != funcClass) {
457
- throw new TypeError(fun + " is not a function");
458
- }
424
+ Array.prototype.forEach = function (callback, thisArg) {
425
+ var T, k;
459
426
 
460
- for (var i = 0; i < length; i++) {
461
- if (i in self)
462
- result[i] = fun.call(thisp, self[i], i, object);
463
- }
464
- return result;
465
- };
427
+ if (this == null) {
428
+ throw new TypeError(" this is null or not defined");
466
429
  }
467
430
 
468
- if (!Array.prototype.filter) {
469
- Array.prototype.filter = function (predicate) {
470
- var results = [], item, t = new Object(this);
471
- for (var i = 0, len = t.length >>> 0; i < len; i++) {
472
- item = t[i];
473
- if (i in t && predicate.call(arguments[1], item, i, t)) {
474
- results.push(item);
475
- }
476
- }
477
- return results;
478
- };
479
- }
431
+ var O = Object(this);
432
+ var len = O.length >>> 0;
480
433
 
481
- if (!Array.isArray) {
482
- Array.isArray = function (arg) {
483
- return Object.prototype.toString.call(arg) == arrayClass;
484
- };
434
+ if (typeof callback !== "function") {
435
+ throw new TypeError(callback + " is not a function");
485
436
  }
486
437
 
487
- if (!Array.prototype.indexOf) {
488
- Array.prototype.indexOf = function indexOf(searchElement) {
489
- var t = Object(this);
490
- var len = t.length >>> 0;
491
- if (len === 0) {
492
- return -1;
493
- }
494
- var n = 0;
495
- if (arguments.length > 1) {
496
- n = Number(arguments[1]);
497
- if (n !== n) {
498
- n = 0;
499
- } else if (n !== 0 && n != Infinity && n !== -Infinity) {
500
- n = (n > 0 || -1) * Math.floor(Math.abs(n));
501
- }
502
- }
503
- if (n >= len) {
504
- return -1;
505
- }
506
- var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
507
- for (; k < len; k++) {
508
- if (k in t && t[k] === searchElement) {
509
- return k;
510
- }
511
- }
512
- return -1;
513
- };
438
+ if (arguments.length > 1) {
439
+ T = thisArg;
514
440
  }
515
441
 
516
- // Collections
517
- var IndexedItem = function (id, value) {
518
- this.id = id;
519
- this.value = value;
520
- };
442
+ k = 0;
443
+ while (k < len) {
444
+ var kValue;
445
+ if (k in O) {
446
+ kValue = O[k];
447
+ callback.call(T, kValue, k, O);
448
+ }
449
+ k++;
450
+ }
451
+ };
452
+ }
453
+
454
+ var boxedString = Object("a"),
455
+ splitString = boxedString[0] != "a" || !(0 in boxedString);
456
+ if (!Array.prototype.every) {
457
+ Array.prototype.every = function every(fun /*, thisp */) {
458
+ var object = Object(this),
459
+ self = splitString && {}.toString.call(this) == stringClass ?
460
+ this.split("") :
461
+ object,
462
+ length = self.length >>> 0,
463
+ thisp = arguments[1];
464
+
465
+ if ({}.toString.call(fun) != funcClass) {
466
+ throw new TypeError(fun + " is not a function");
467
+ }
521
468
 
522
- IndexedItem.prototype.compareTo = function (other) {
523
- var c = this.value.compareTo(other.value);
524
- if (c === 0) {
525
- c = this.id - other.id;
469
+ for (var i = 0; i < length; i++) {
470
+ if (i in self && !fun.call(thisp, self[i], i, object)) {
471
+ return false;
526
472
  }
527
- return c;
528
- };
529
-
530
- // Priority Queue for Scheduling
531
- var PriorityQueue = Rx.internals.PriorityQueue = function (capacity) {
532
- this.items = new Array(capacity);
533
- this.length = 0;
473
+ }
474
+ return true;
534
475
  };
476
+ }
535
477
 
536
- var priorityProto = PriorityQueue.prototype;
537
- priorityProto.isHigherPriority = function (left, right) {
538
- return this.items[left].compareTo(this.items[right]) < 0;
539
- };
478
+ if (!Array.prototype.map) {
479
+ Array.prototype.map = function map(fun /*, thisp*/) {
480
+ var object = Object(this),
481
+ self = splitString && {}.toString.call(this) == stringClass ?
482
+ this.split("") :
483
+ object,
484
+ length = self.length >>> 0,
485
+ result = Array(length),
486
+ thisp = arguments[1];
487
+
488
+ if ({}.toString.call(fun) != funcClass) {
489
+ throw new TypeError(fun + " is not a function");
490
+ }
540
491
 
541
- priorityProto.percolate = function (index) {
542
- if (index >= this.length || index < 0) {
543
- return;
544
- }
545
- var parent = index - 1 >> 1;
546
- if (parent < 0 || parent === index) {
547
- return;
548
- }
549
- if (this.isHigherPriority(index, parent)) {
550
- var temp = this.items[index];
551
- this.items[index] = this.items[parent];
552
- this.items[parent] = temp;
553
- this.percolate(parent);
492
+ for (var i = 0; i < length; i++) {
493
+ if (i in self) {
494
+ result[i] = fun.call(thisp, self[i], i, object);
554
495
  }
496
+ }
497
+ return result;
555
498
  };
499
+ }
556
500
 
557
- priorityProto.heapify = function (index) {
558
- if (index === undefined) {
559
- index = 0;
501
+ if (!Array.prototype.filter) {
502
+ Array.prototype.filter = function (predicate) {
503
+ var results = [], item, t = new Object(this);
504
+ for (var i = 0, len = t.length >>> 0; i < len; i++) {
505
+ item = t[i];
506
+ if (i in t && predicate.call(arguments[1], item, i, t)) {
507
+ results.push(item);
560
508
  }
561
- if (index >= this.length || index < 0) {
562
- return;
563
- }
564
- var left = 2 * index + 1,
565
- right = 2 * index + 2,
566
- first = index;
567
- if (left < this.length && this.isHigherPriority(left, first)) {
568
- first = left;
569
- }
570
- if (right < this.length && this.isHigherPriority(right, first)) {
571
- first = right;
572
- }
573
- if (first !== index) {
574
- var temp = this.items[index];
575
- this.items[index] = this.items[first];
576
- this.items[first] = temp;
577
- this.heapify(first);
578
- }
579
- };
580
-
581
- priorityProto.peek = function () { return this.items[0].value; };
582
-
583
- priorityProto.removeAt = function (index) {
584
- this.items[index] = this.items[--this.length];
585
- delete this.items[this.length];
586
- this.heapify();
587
- };
588
-
589
- priorityProto.dequeue = function () {
590
- var result = this.peek();
591
- this.removeAt(0);
592
- return result;
509
+ }
510
+ return results;
593
511
  };
512
+ }
594
513
 
595
- priorityProto.enqueue = function (item) {
596
- var index = this.length++;
597
- this.items[index] = new IndexedItem(PriorityQueue.count++, item);
598
- this.percolate(index);
514
+ if (!Array.isArray) {
515
+ Array.isArray = function (arg) {
516
+ return {}.toString.call(arg) == arrayClass;
599
517
  };
518
+ }
600
519
 
601
- priorityProto.remove = function (item) {
602
- for (var i = 0; i < this.length; i++) {
603
- if (this.items[i].value === item) {
604
- this.removeAt(i);
605
- return true;
606
- }
520
+ if (!Array.prototype.indexOf) {
521
+ Array.prototype.indexOf = function indexOf(searchElement) {
522
+ var t = Object(this);
523
+ var len = t.length >>> 0;
524
+ if (len === 0) {
525
+ return -1;
526
+ }
527
+ var n = 0;
528
+ if (arguments.length > 1) {
529
+ n = Number(arguments[1]);
530
+ if (n !== n) {
531
+ n = 0;
532
+ } else if (n !== 0 && n != Infinity && n !== -Infinity) {
533
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
607
534
  }
608
- return false;
609
- };
610
- PriorityQueue.count = 0;
611
- /**
612
- * Represents a group of disposable resources that are disposed together.
613
- * @constructor
614
- */
615
- var CompositeDisposable = Rx.CompositeDisposable = function () {
616
- this.disposables = argsOrArray(arguments, 0);
617
- this.isDisposed = false;
618
- this.length = this.disposables.length;
619
- };
620
-
621
- var CompositeDisposablePrototype = CompositeDisposable.prototype;
622
-
623
- /**
624
- * Adds a disposable to the CompositeDisposable or disposes the disposable if the CompositeDisposable is disposed.
625
- * @param {Mixed} item Disposable to add.
626
- */
627
- CompositeDisposablePrototype.add = function (item) {
628
- if (this.isDisposed) {
629
- item.dispose();
630
- } else {
631
- this.disposables.push(item);
632
- this.length++;
535
+ }
536
+ if (n >= len) {
537
+ return -1;
538
+ }
539
+ var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
540
+ for (; k < len; k++) {
541
+ if (k in t && t[k] === searchElement) {
542
+ return k;
633
543
  }
544
+ }
545
+ return -1;
634
546
  };
547
+ }
635
548
 
636
- /**
637
- * Removes and disposes the first occurrence of a disposable from the CompositeDisposable.
638
- * @param {Mixed} item Disposable to remove.
639
- * @returns {Boolean} true if found; false otherwise.
640
- */
641
- CompositeDisposablePrototype.remove = function (item) {
642
- var shouldDispose = false;
643
- if (!this.isDisposed) {
644
- var idx = this.disposables.indexOf(item);
645
- if (idx !== -1) {
646
- shouldDispose = true;
647
- this.disposables.splice(idx, 1);
648
- this.length--;
649
- item.dispose();
650
- }
651
-
652
- }
653
- return shouldDispose;
654
- };
549
+ // Collections
550
+ var IndexedItem = function (id, value) {
551
+ this.id = id;
552
+ this.value = value;
553
+ };
554
+
555
+ IndexedItem.prototype.compareTo = function (other) {
556
+ var c = this.value.compareTo(other.value);
557
+ if (c === 0) {
558
+ c = this.id - other.id;
559
+ }
560
+ return c;
561
+ };
562
+
563
+ // Priority Queue for Scheduling
564
+ var PriorityQueue = Rx.internals.PriorityQueue = function (capacity) {
565
+ this.items = new Array(capacity);
566
+ this.length = 0;
567
+ };
568
+
569
+ var priorityProto = PriorityQueue.prototype;
570
+ priorityProto.isHigherPriority = function (left, right) {
571
+ return this.items[left].compareTo(this.items[right]) < 0;
572
+ };
573
+
574
+ priorityProto.percolate = function (index) {
575
+ if (index >= this.length || index < 0) {
576
+ return;
577
+ }
578
+ var parent = index - 1 >> 1;
579
+ if (parent < 0 || parent === index) {
580
+ return;
581
+ }
582
+ if (this.isHigherPriority(index, parent)) {
583
+ var temp = this.items[index];
584
+ this.items[index] = this.items[parent];
585
+ this.items[parent] = temp;
586
+ this.percolate(parent);
587
+ }
588
+ };
589
+
590
+ priorityProto.heapify = function (index) {
591
+ if (index === undefined) {
592
+ index = 0;
593
+ }
594
+ if (index >= this.length || index < 0) {
595
+ return;
596
+ }
597
+ var left = 2 * index + 1,
598
+ right = 2 * index + 2,
599
+ first = index;
600
+ if (left < this.length && this.isHigherPriority(left, first)) {
601
+ first = left;
602
+ }
603
+ if (right < this.length && this.isHigherPriority(right, first)) {
604
+ first = right;
605
+ }
606
+ if (first !== index) {
607
+ var temp = this.items[index];
608
+ this.items[index] = this.items[first];
609
+ this.items[first] = temp;
610
+ this.heapify(first);
611
+ }
612
+ };
613
+
614
+ priorityProto.peek = function () { return this.items[0].value; };
615
+
616
+ priorityProto.removeAt = function (index) {
617
+ this.items[index] = this.items[--this.length];
618
+ delete this.items[this.length];
619
+ this.heapify();
620
+ };
621
+
622
+ priorityProto.dequeue = function () {
623
+ var result = this.peek();
624
+ this.removeAt(0);
625
+ return result;
626
+ };
627
+
628
+ priorityProto.enqueue = function (item) {
629
+ var index = this.length++;
630
+ this.items[index] = new IndexedItem(PriorityQueue.count++, item);
631
+ this.percolate(index);
632
+ };
633
+
634
+ priorityProto.remove = function (item) {
635
+ for (var i = 0; i < this.length; i++) {
636
+ if (this.items[i].value === item) {
637
+ this.removeAt(i);
638
+ return true;
639
+ }
640
+ }
641
+ return false;
642
+ };
643
+ PriorityQueue.count = 0;
644
+ /**
645
+ * Represents a group of disposable resources that are disposed together.
646
+ * @constructor
647
+ */
648
+ var CompositeDisposable = Rx.CompositeDisposable = function () {
649
+ this.disposables = argsOrArray(arguments, 0);
650
+ this.isDisposed = false;
651
+ this.length = this.disposables.length;
652
+ };
655
653
 
656
- /**
657
- * Disposes all disposables in the group and removes them from the group.
658
- */
659
- CompositeDisposablePrototype.dispose = function () {
660
- if (!this.isDisposed) {
661
- this.isDisposed = true;
662
- var currentDisposables = this.disposables.slice(0);
663
- this.disposables = [];
664
- this.length = 0;
654
+ var CompositeDisposablePrototype = CompositeDisposable.prototype;
665
655
 
666
- for (var i = 0, len = currentDisposables.length; i < len; i++) {
667
- currentDisposables[i].dispose();
668
- }
669
- }
670
- };
656
+ /**
657
+ * Adds a disposable to the CompositeDisposable or disposes the disposable if the CompositeDisposable is disposed.
658
+ * @param {Mixed} item Disposable to add.
659
+ */
660
+ CompositeDisposablePrototype.add = function (item) {
661
+ if (this.isDisposed) {
662
+ item.dispose();
663
+ } else {
664
+ this.disposables.push(item);
665
+ this.length++;
666
+ }
667
+ };
671
668
 
672
- /**
673
- * Removes and disposes all disposables from the CompositeDisposable, but does not dispose the CompositeDisposable.
674
- */
675
- CompositeDisposablePrototype.clear = function () {
676
- var currentDisposables = this.disposables.slice(0);
677
- this.disposables = [];
678
- this.length = 0;
679
- for (var i = 0, len = currentDisposables.length; i < len; i++) {
680
- currentDisposables[i].dispose();
681
- }
682
- };
669
+ /**
670
+ * Removes and disposes the first occurrence of a disposable from the CompositeDisposable.
671
+ * @param {Mixed} item Disposable to remove.
672
+ * @returns {Boolean} true if found; false otherwise.
673
+ */
674
+ CompositeDisposablePrototype.remove = function (item) {
675
+ var shouldDispose = false;
676
+ if (!this.isDisposed) {
677
+ var idx = this.disposables.indexOf(item);
678
+ if (idx !== -1) {
679
+ shouldDispose = true;
680
+ this.disposables.splice(idx, 1);
681
+ this.length--;
682
+ item.dispose();
683
+ }
684
+ }
685
+ return shouldDispose;
686
+ };
683
687
 
684
- /**
685
- * Determines whether the CompositeDisposable contains a specific disposable.
686
- * @param {Mixed} item Disposable to search for.
687
- * @returns {Boolean} true if the disposable was found; otherwise, false.
688
- */
689
- CompositeDisposablePrototype.contains = function (item) {
690
- return this.disposables.indexOf(item) !== -1;
691
- };
688
+ /**
689
+ * Disposes all disposables in the group and removes them from the group.
690
+ */
691
+ CompositeDisposablePrototype.dispose = function () {
692
+ if (!this.isDisposed) {
693
+ this.isDisposed = true;
694
+ var currentDisposables = this.disposables.slice(0);
695
+ this.disposables = [];
696
+ this.length = 0;
697
+
698
+ for (var i = 0, len = currentDisposables.length; i < len; i++) {
699
+ currentDisposables[i].dispose();
700
+ }
701
+ }
702
+ };
692
703
 
693
- /**
694
- * Converts the existing CompositeDisposable to an array of disposables
695
- * @returns {Array} An array of disposable objects.
696
- */
697
- CompositeDisposablePrototype.toArray = function () {
698
- return this.disposables.slice(0);
699
- };
700
-
704
+ /**
705
+ * Converts the existing CompositeDisposable to an array of disposables
706
+ * @returns {Array} An array of disposable objects.
707
+ */
708
+ CompositeDisposablePrototype.toArray = function () {
709
+ return this.disposables.slice(0);
710
+ };
711
+
701
712
  /**
702
713
  * Provides a set of static methods for creating Disposables.
703
714
  *
@@ -729,90 +740,52 @@
729
740
  */
730
741
  var disposableEmpty = Disposable.empty = { dispose: noop };
731
742
 
732
- var BooleanDisposable = (function () {
733
- function BooleanDisposable (isSingle) {
734
- this.isSingle = isSingle;
735
- this.isDisposed = false;
736
- this.current = null;
737
- }
738
-
739
- var booleanDisposablePrototype = BooleanDisposable.prototype;
740
-
741
- /**
742
- * Gets the underlying disposable.
743
- * @return The underlying disposable.
744
- */
745
- booleanDisposablePrototype.getDisposable = function () {
746
- return this.current;
747
- };
748
-
749
- /**
750
- * Sets the underlying disposable.
751
- * @param {Disposable} value The new underlying disposable.
752
- */
753
- booleanDisposablePrototype.setDisposable = function (value) {
754
- if (this.current && this.isSingle) {
755
- throw new Error('Disposable has already been assigned');
756
- }
757
-
758
- var shouldDispose = this.isDisposed, old;
759
- if (!shouldDispose) {
760
- old = this.current;
761
- this.current = value;
762
- }
763
- if (old) {
764
- old.dispose();
765
- }
766
- if (shouldDispose && value) {
767
- value.dispose();
768
- }
769
- };
770
-
771
- /**
772
- * Disposes the underlying disposable as well as all future replacements.
773
- */
774
- booleanDisposablePrototype.dispose = function () {
775
- var old;
776
- if (!this.isDisposed) {
777
- this.isDisposed = true;
778
- old = this.current;
779
- this.current = null;
780
- }
781
- if (old) {
782
- old.dispose();
783
- }
784
- };
743
+ var SingleAssignmentDisposable = Rx.SingleAssignmentDisposable =
744
+ SerialDisposable = Rx.SerialDisposable = (function () {
745
+ function BooleanDisposable () {
746
+ this.isDisposed = false;
747
+ this.current = null;
748
+ }
785
749
 
786
- return BooleanDisposable;
787
- }());
750
+ var booleanDisposablePrototype = BooleanDisposable.prototype;
788
751
 
789
752
  /**
790
- * Represents a disposable resource which only allows a single assignment of its underlying disposable resource.
791
- * If an underlying disposable resource has already been set, future attempts to set the underlying disposable resource will throw an Error.
753
+ * Gets the underlying disposable.
754
+ * @return The underlying disposable.
792
755
  */
793
- var SingleAssignmentDisposable = Rx.SingleAssignmentDisposable = (function (super_) {
794
- inherits(SingleAssignmentDisposable, super_);
795
-
796
- function SingleAssignmentDisposable() {
797
- super_.call(this, true);
798
- }
799
-
800
- return SingleAssignmentDisposable;
801
- }(BooleanDisposable));
756
+ booleanDisposablePrototype.getDisposable = function () {
757
+ return this.current;
758
+ };
802
759
 
803
760
  /**
804
- * Represents a disposable resource whose underlying disposable resource can be replaced by another disposable resource, causing automatic disposal of the previous underlying disposable resource.
805
- */
806
- var SerialDisposable = Rx.SerialDisposable = (function (super_) {
807
- inherits(SerialDisposable, super_);
808
-
809
- function SerialDisposable() {
810
- super_.call(this, false);
811
- }
761
+ * Sets the underlying disposable.
762
+ * @param {Disposable} value The new underlying disposable.
763
+ */
764
+ booleanDisposablePrototype.setDisposable = function (value) {
765
+ var shouldDispose = this.isDisposed, old;
766
+ if (!shouldDispose) {
767
+ old = this.current;
768
+ this.current = value;
769
+ }
770
+ old && old.dispose();
771
+ shouldDispose && value && value.dispose();
772
+ };
812
773
 
813
- return SerialDisposable;
814
- }(BooleanDisposable));
774
+ /**
775
+ * Disposes the underlying disposable as well as all future replacements.
776
+ */
777
+ booleanDisposablePrototype.dispose = function () {
778
+ var old;
779
+ if (!this.isDisposed) {
780
+ this.isDisposed = true;
781
+ old = this.current;
782
+ this.current = null;
783
+ }
784
+ old && old.dispose();
785
+ };
815
786
 
787
+ return BooleanDisposable;
788
+ }());
816
789
  /**
817
790
  * Represents a disposable resource that only disposes its underlying disposable resource when all dependent disposable objects have been disposed.
818
791
  */
@@ -875,423 +848,460 @@
875
848
  return RefCountDisposable;
876
849
  })();
877
850
 
878
- function ScheduledDisposable(scheduler, disposable) {
879
- this.scheduler = scheduler;
880
- this.disposable = disposable;
881
- this.isDisposed = false;
851
+ function ScheduledDisposable(scheduler, disposable) {
852
+ this.scheduler = scheduler;
853
+ this.disposable = disposable;
854
+ this.isDisposed = false;
855
+ }
856
+
857
+ ScheduledDisposable.prototype.dispose = function () {
858
+ var parent = this;
859
+ this.scheduler.schedule(function () {
860
+ if (!parent.isDisposed) {
861
+ parent.isDisposed = true;
862
+ parent.disposable.dispose();
863
+ }
864
+ });
865
+ };
866
+
867
+ var ScheduledItem = Rx.internals.ScheduledItem = function (scheduler, state, action, dueTime, comparer) {
868
+ this.scheduler = scheduler;
869
+ this.state = state;
870
+ this.action = action;
871
+ this.dueTime = dueTime;
872
+ this.comparer = comparer || defaultSubComparer;
873
+ this.disposable = new SingleAssignmentDisposable();
874
+ }
875
+
876
+ ScheduledItem.prototype.invoke = function () {
877
+ this.disposable.setDisposable(this.invokeCore());
878
+ };
879
+
880
+ ScheduledItem.prototype.compareTo = function (other) {
881
+ return this.comparer(this.dueTime, other.dueTime);
882
+ };
883
+
884
+ ScheduledItem.prototype.isCancelled = function () {
885
+ return this.disposable.isDisposed;
886
+ };
887
+
888
+ ScheduledItem.prototype.invokeCore = function () {
889
+ return this.action(this.scheduler, this.state);
890
+ };
891
+
892
+ /** Provides a set of static properties to access commonly used schedulers. */
893
+ var Scheduler = Rx.Scheduler = (function () {
894
+
895
+ function Scheduler(now, schedule, scheduleRelative, scheduleAbsolute) {
896
+ this.now = now;
897
+ this._schedule = schedule;
898
+ this._scheduleRelative = scheduleRelative;
899
+ this._scheduleAbsolute = scheduleAbsolute;
882
900
  }
883
901
 
884
- ScheduledDisposable.prototype.dispose = function () {
885
- var parent = this;
886
- this.scheduler.schedule(function () {
887
- if (!parent.isDisposed) {
888
- parent.isDisposed = true;
889
- parent.disposable.dispose();
902
+ function invokeRecImmediate(scheduler, pair) {
903
+ var state = pair.first, action = pair.second, group = new CompositeDisposable(),
904
+ recursiveAction = function (state1) {
905
+ action(state1, function (state2) {
906
+ var isAdded = false, isDone = false,
907
+ d = scheduler.scheduleWithState(state2, function (scheduler1, state3) {
908
+ if (isAdded) {
909
+ group.remove(d);
910
+ } else {
911
+ isDone = true;
890
912
  }
913
+ recursiveAction(state3);
914
+ return disposableEmpty;
915
+ });
916
+ if (!isDone) {
917
+ group.add(d);
918
+ isAdded = true;
919
+ }
891
920
  });
892
- };
921
+ };
922
+ recursiveAction(state);
923
+ return group;
924
+ }
893
925
 
894
- var ScheduledItem = Rx.internals.ScheduledItem = function (scheduler, state, action, dueTime, comparer) {
895
- this.scheduler = scheduler;
896
- this.state = state;
897
- this.action = action;
898
- this.dueTime = dueTime;
899
- this.comparer = comparer || defaultSubComparer;
900
- this.disposable = new SingleAssignmentDisposable();
926
+ function invokeRecDate(scheduler, pair, method) {
927
+ var state = pair.first, action = pair.second, group = new CompositeDisposable(),
928
+ recursiveAction = function (state1) {
929
+ action(state1, function (state2, dueTime1) {
930
+ var isAdded = false, isDone = false,
931
+ d = scheduler[method].call(scheduler, state2, dueTime1, function (scheduler1, state3) {
932
+ if (isAdded) {
933
+ group.remove(d);
934
+ } else {
935
+ isDone = true;
936
+ }
937
+ recursiveAction(state3);
938
+ return disposableEmpty;
939
+ });
940
+ if (!isDone) {
941
+ group.add(d);
942
+ isAdded = true;
943
+ }
944
+ });
945
+ };
946
+ recursiveAction(state);
947
+ return group;
901
948
  }
902
949
 
903
- ScheduledItem.prototype.invoke = function () {
904
- this.disposable.setDisposable(this.invokeCore());
905
- };
950
+ function invokeAction(scheduler, action) {
951
+ action();
952
+ return disposableEmpty;
953
+ }
906
954
 
907
- ScheduledItem.prototype.compareTo = function (other) {
908
- return this.comparer(this.dueTime, other.dueTime);
909
- };
955
+ var schedulerProto = Scheduler.prototype;
910
956
 
911
- ScheduledItem.prototype.isCancelled = function () {
912
- return this.disposable.isDisposed;
957
+ /**
958
+ * Schedules an action to be executed.
959
+ * @param {Function} action Action to execute.
960
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
961
+ */
962
+ schedulerProto.schedule = function (action) {
963
+ return this._schedule(action, invokeAction);
913
964
  };
914
965
 
915
- ScheduledItem.prototype.invokeCore = function () {
916
- return this.action(this.scheduler, this.state);
966
+ /**
967
+ * Schedules an action to be executed.
968
+ * @param state State passed to the action to be executed.
969
+ * @param {Function} action Action to be executed.
970
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
971
+ */
972
+ schedulerProto.scheduleWithState = function (state, action) {
973
+ return this._schedule(state, action);
917
974
  };
918
975
 
919
- /** Provides a set of static properties to access commonly used schedulers. */
920
- var Scheduler = Rx.Scheduler = (function () {
921
-
922
- /**
923
- * @constructor
924
- * @private
925
- */
926
- function Scheduler(now, schedule, scheduleRelative, scheduleAbsolute) {
927
- this.now = now;
928
- this._schedule = schedule;
929
- this._scheduleRelative = scheduleRelative;
930
- this._scheduleAbsolute = scheduleAbsolute;
931
- }
932
-
933
- function invokeRecImmediate(scheduler, pair) {
934
- var state = pair.first, action = pair.second, group = new CompositeDisposable(),
935
- recursiveAction = function (state1) {
936
- action(state1, function (state2) {
937
- var isAdded = false, isDone = false,
938
- d = scheduler.scheduleWithState(state2, function (scheduler1, state3) {
939
- if (isAdded) {
940
- group.remove(d);
941
- } else {
942
- isDone = true;
943
- }
944
- recursiveAction(state3);
945
- return disposableEmpty;
946
- });
947
- if (!isDone) {
948
- group.add(d);
949
- isAdded = true;
950
- }
951
- });
952
- };
953
- recursiveAction(state);
954
- return group;
955
- }
956
-
957
- function invokeRecDate(scheduler, pair, method) {
958
- var state = pair.first, action = pair.second, group = new CompositeDisposable(),
959
- recursiveAction = function (state1) {
960
- action(state1, function (state2, dueTime1) {
961
- var isAdded = false, isDone = false,
962
- d = scheduler[method].call(scheduler, state2, dueTime1, function (scheduler1, state3) {
963
- if (isAdded) {
964
- group.remove(d);
965
- } else {
966
- isDone = true;
967
- }
968
- recursiveAction(state3);
969
- return disposableEmpty;
970
- });
971
- if (!isDone) {
972
- group.add(d);
973
- isAdded = true;
974
- }
975
- });
976
- };
977
- recursiveAction(state);
978
- return group;
979
- }
980
-
981
- function invokeAction(scheduler, action) {
982
- action();
983
- return disposableEmpty;
984
- }
985
-
986
- var schedulerProto = Scheduler.prototype;
976
+ /**
977
+ * Schedules an action to be executed after the specified relative due time.
978
+ * @param {Function} action Action to execute.
979
+ * @param {Number} dueTime Relative time after which to execute the action.
980
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
981
+ */
982
+ schedulerProto.scheduleWithRelative = function (dueTime, action) {
983
+ return this._scheduleRelative(action, dueTime, invokeAction);
984
+ };
987
985
 
988
- /**
989
- * Returns a scheduler that wraps the original scheduler, adding exception handling for scheduled actions.
990
- * @param {Function} handler Handler that's run if an exception is caught. The exception will be rethrown if the handler returns false.
991
- * @returns {Scheduler} Wrapper around the original scheduler, enforcing exception handling.
992
- */
993
- schedulerProto.catchException = schedulerProto['catch'] = function (handler) {
994
- return new CatchScheduler(this, handler);
995
- };
996
-
997
- /**
998
- * Schedules a periodic piece of work by dynamically discovering the scheduler's capabilities. The periodic task will be scheduled using window.setInterval for the base implementation.
999
- * @param {Number} period Period for running the work periodically.
1000
- * @param {Function} action Action to be executed.
1001
- * @returns {Disposable} The disposable object used to cancel the scheduled recurring action (best effort).
1002
- */
1003
- schedulerProto.schedulePeriodic = function (period, action) {
1004
- return this.schedulePeriodicWithState(null, period, function () {
1005
- action();
1006
- });
1007
- };
986
+ /**
987
+ * Schedules an action to be executed after dueTime.
988
+ * @param state State passed to the action to be executed.
989
+ * @param {Function} action Action to be executed.
990
+ * @param {Number} dueTime Relative time after which to execute the action.
991
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
992
+ */
993
+ schedulerProto.scheduleWithRelativeAndState = function (state, dueTime, action) {
994
+ return this._scheduleRelative(state, dueTime, action);
995
+ };
1008
996
 
1009
- /**
1010
- * Schedules a periodic piece of work by dynamically discovering the scheduler's capabilities. The periodic task will be scheduled using window.setInterval for the base implementation.
1011
- * @param {Mixed} state Initial state passed to the action upon the first iteration.
1012
- * @param {Number} period Period for running the work periodically.
1013
- * @param {Function} action Action to be executed, potentially updating the state.
1014
- * @returns {Disposable} The disposable object used to cancel the scheduled recurring action (best effort).
1015
- */
1016
- schedulerProto.schedulePeriodicWithState = function (state, period, action) {
1017
- var s = state, id = setInterval(function () {
1018
- s = action(s);
1019
- }, period);
1020
- return disposableCreate(function () {
1021
- clearInterval(id);
1022
- });
1023
- };
997
+ /**
998
+ * Schedules an action to be executed at the specified absolute due time.
999
+ * @param {Function} action Action to execute.
1000
+ * @param {Number} dueTime Absolute time at which to execute the action.
1001
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1002
+ */
1003
+ schedulerProto.scheduleWithAbsolute = function (dueTime, action) {
1004
+ return this._scheduleAbsolute(action, dueTime, invokeAction);
1005
+ };
1024
1006
 
1025
- /**
1026
- * Schedules an action to be executed.
1027
- * @param {Function} action Action to execute.
1028
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1029
- */
1030
- schedulerProto.schedule = function (action) {
1031
- return this._schedule(action, invokeAction);
1032
- };
1007
+ /**
1008
+ * Schedules an action to be executed at dueTime.
1009
+ * @param {Mixed} state State passed to the action to be executed.
1010
+ * @param {Function} action Action to be executed.
1011
+ * @param {Number}dueTime Absolute time at which to execute the action.
1012
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1013
+ */
1014
+ schedulerProto.scheduleWithAbsoluteAndState = function (state, dueTime, action) {
1015
+ return this._scheduleAbsolute(state, dueTime, action);
1016
+ };
1033
1017
 
1034
- /**
1035
- * Schedules an action to be executed.
1036
- * @param state State passed to the action to be executed.
1037
- * @param {Function} action Action to be executed.
1038
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1039
- */
1040
- schedulerProto.scheduleWithState = function (state, action) {
1041
- return this._schedule(state, action);
1042
- };
1018
+ /** Gets the current time according to the local machine's system clock. */
1019
+ Scheduler.now = defaultNow;
1043
1020
 
1044
- /**
1045
- * Schedules an action to be executed after the specified relative due time.
1046
- * @param {Function} action Action to execute.
1047
- * @param {Number} dueTime Relative time after which to execute the action.
1048
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1049
- */
1050
- schedulerProto.scheduleWithRelative = function (dueTime, action) {
1051
- return this._scheduleRelative(action, dueTime, invokeAction);
1052
- };
1021
+ /**
1022
+ * Normalizes the specified TimeSpan value to a positive value.
1023
+ * @param {Number} timeSpan The time span value to normalize.
1024
+ * @returns {Number} The specified TimeSpan value if it is zero or positive; otherwise, 0
1025
+ */
1026
+ Scheduler.normalize = function (timeSpan) {
1027
+ timeSpan < 0 && (timeSpan = 0);
1028
+ return timeSpan;
1029
+ };
1053
1030
 
1054
- /**
1055
- * Schedules an action to be executed after dueTime.
1056
- * @param state State passed to the action to be executed.
1057
- * @param {Function} action Action to be executed.
1058
- * @param {Number} dueTime Relative time after which to execute the action.
1059
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1060
- */
1061
- schedulerProto.scheduleWithRelativeAndState = function (state, dueTime, action) {
1062
- return this._scheduleRelative(state, dueTime, action);
1063
- };
1031
+ return Scheduler;
1032
+ }());
1064
1033
 
1065
- /**
1066
- * Schedules an action to be executed at the specified absolute due time.
1067
- * @param {Function} action Action to execute.
1068
- * @param {Number} dueTime Absolute time at which to execute the action.
1069
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1070
- */
1071
- schedulerProto.scheduleWithAbsolute = function (dueTime, action) {
1072
- return this._scheduleAbsolute(action, dueTime, invokeAction);
1073
- };
1034
+ var normalizeTime = Scheduler.normalize;
1035
+
1036
+ (function (schedulerProto) {
1037
+ function invokeRecImmediate(scheduler, pair) {
1038
+ var state = pair.first, action = pair.second, group = new CompositeDisposable(),
1039
+ recursiveAction = function (state1) {
1040
+ action(state1, function (state2) {
1041
+ var isAdded = false, isDone = false,
1042
+ d = scheduler.scheduleWithState(state2, function (scheduler1, state3) {
1043
+ if (isAdded) {
1044
+ group.remove(d);
1045
+ } else {
1046
+ isDone = true;
1047
+ }
1048
+ recursiveAction(state3);
1049
+ return disposableEmpty;
1050
+ });
1051
+ if (!isDone) {
1052
+ group.add(d);
1053
+ isAdded = true;
1054
+ }
1055
+ });
1056
+ };
1057
+ recursiveAction(state);
1058
+ return group;
1059
+ }
1074
1060
 
1075
- /**
1076
- * Schedules an action to be executed at dueTime.
1077
- * @param {Mixed} state State passed to the action to be executed.
1078
- * @param {Function} action Action to be executed.
1079
- * @param {Number}dueTime Absolute time at which to execute the action.
1080
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1081
- */
1082
- schedulerProto.scheduleWithAbsoluteAndState = function (state, dueTime, action) {
1083
- return this._scheduleAbsolute(state, dueTime, action);
1084
- };
1061
+ function invokeRecDate(scheduler, pair, method) {
1062
+ var state = pair.first, action = pair.second, group = new CompositeDisposable(),
1063
+ recursiveAction = function (state1) {
1064
+ action(state1, function (state2, dueTime1) {
1065
+ var isAdded = false, isDone = false,
1066
+ d = scheduler[method].call(scheduler, state2, dueTime1, function (scheduler1, state3) {
1067
+ if (isAdded) {
1068
+ group.remove(d);
1069
+ } else {
1070
+ isDone = true;
1071
+ }
1072
+ recursiveAction(state3);
1073
+ return disposableEmpty;
1074
+ });
1075
+ if (!isDone) {
1076
+ group.add(d);
1077
+ isAdded = true;
1078
+ }
1079
+ });
1080
+ };
1081
+ recursiveAction(state);
1082
+ return group;
1083
+ }
1085
1084
 
1086
- /**
1087
- * Schedules an action to be executed recursively.
1088
- * @param {Function} action Action to execute recursively. The parameter passed to the action is used to trigger recursive scheduling of the action.
1089
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1090
- */
1091
- schedulerProto.scheduleRecursive = function (action) {
1092
- return this.scheduleRecursiveWithState(action, function (_action, self) {
1093
- _action(function () {
1094
- self(_action);
1095
- });
1096
- });
1097
- };
1085
+ function scheduleInnerRecursive(action, self) {
1086
+ action(function(dt) { self(action, dt); });
1087
+ }
1098
1088
 
1099
- /**
1100
- * Schedules an action to be executed recursively.
1101
- * @param {Mixed} state State passed to the action to be executed.
1102
- * @param {Function} action Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in recursive invocation state.
1103
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1104
- */
1105
- schedulerProto.scheduleRecursiveWithState = function (state, action) {
1106
- return this.scheduleWithState({ first: state, second: action }, function (s, p) {
1107
- return invokeRecImmediate(s, p);
1108
- });
1109
- };
1089
+ /**
1090
+ * Schedules an action to be executed recursively.
1091
+ * @param {Function} action Action to execute recursively. The parameter passed to the action is used to trigger recursive scheduling of the action.
1092
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1093
+ */
1094
+ schedulerProto.scheduleRecursive = function (action) {
1095
+ return this.scheduleRecursiveWithState(action, function (_action, self) {
1096
+ _action(function () { self(_action); }); });
1097
+ };
1110
1098
 
1111
- /**
1112
- * Schedules an action to be executed recursively after a specified relative due time.
1113
- * @param {Function} action Action to execute recursively. The parameter passed to the action is used to trigger recursive scheduling of the action at the specified relative time.
1114
- * @param {Number}dueTime Relative time after which to execute the action for the first time.
1115
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1116
- */
1117
- schedulerProto.scheduleRecursiveWithRelative = function (dueTime, action) {
1118
- return this.scheduleRecursiveWithRelativeAndState(action, dueTime, function (_action, self) {
1119
- _action(function (dt) {
1120
- self(_action, dt);
1121
- });
1122
- });
1123
- };
1099
+ /**
1100
+ * Schedules an action to be executed recursively.
1101
+ * @param {Mixed} state State passed to the action to be executed.
1102
+ * @param {Function} action Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in recursive invocation state.
1103
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1104
+ */
1105
+ schedulerProto.scheduleRecursiveWithState = function (state, action) {
1106
+ return this.scheduleWithState({ first: state, second: action }, invokeRecImmediate);
1107
+ };
1124
1108
 
1125
- /**
1126
- * Schedules an action to be executed recursively after a specified relative due time.
1127
- * @param {Mixed} state State passed to the action to be executed.
1128
- * @param {Function} action Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in the recursive due time and invocation state.
1129
- * @param {Number}dueTime Relative time after which to execute the action for the first time.
1130
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1131
- */
1132
- schedulerProto.scheduleRecursiveWithRelativeAndState = function (state, dueTime, action) {
1133
- return this._scheduleRelative({ first: state, second: action }, dueTime, function (s, p) {
1134
- return invokeRecDate(s, p, 'scheduleWithRelativeAndState');
1135
- });
1136
- };
1109
+ /**
1110
+ * Schedules an action to be executed recursively after a specified relative due time.
1111
+ * @param {Function} action Action to execute recursively. The parameter passed to the action is used to trigger recursive scheduling of the action at the specified relative time.
1112
+ * @param {Number}dueTime Relative time after which to execute the action for the first time.
1113
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1114
+ */
1115
+ schedulerProto.scheduleRecursiveWithRelative = function (dueTime, action) {
1116
+ return this.scheduleRecursiveWithRelativeAndState(action, dueTime, scheduleInnerRecursive);
1117
+ };
1137
1118
 
1138
- /**
1139
- * Schedules an action to be executed recursively at a specified absolute due time.
1140
- * @param {Function} action Action to execute recursively. The parameter passed to the action is used to trigger recursive scheduling of the action at the specified absolute time.
1141
- * @param {Number}dueTime Absolute time at which to execute the action for the first time.
1142
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1143
- */
1144
- schedulerProto.scheduleRecursiveWithAbsolute = function (dueTime, action) {
1145
- return this.scheduleRecursiveWithAbsoluteAndState(action, dueTime, function (_action, self) {
1146
- _action(function (dt) {
1147
- self(_action, dt);
1148
- });
1149
- });
1150
- };
1119
+ /**
1120
+ * Schedules an action to be executed recursively after a specified relative due time.
1121
+ * @param {Mixed} state State passed to the action to be executed.
1122
+ * @param {Function} action Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in the recursive due time and invocation state.
1123
+ * @param {Number}dueTime Relative time after which to execute the action for the first time.
1124
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1125
+ */
1126
+ schedulerProto.scheduleRecursiveWithRelativeAndState = function (state, dueTime, action) {
1127
+ return this._scheduleRelative({ first: state, second: action }, dueTime, function (s, p) {
1128
+ return invokeRecDate(s, p, 'scheduleWithRelativeAndState');
1129
+ });
1130
+ };
1151
1131
 
1152
- /**
1153
- * Schedules an action to be executed recursively at a specified absolute due time.
1154
- * @param {Mixed} state State passed to the action to be executed.
1155
- * @param {Function} action Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in the recursive due time and invocation state.
1156
- * @param {Number}dueTime Absolute time at which to execute the action for the first time.
1157
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1158
- */
1159
- schedulerProto.scheduleRecursiveWithAbsoluteAndState = function (state, dueTime, action) {
1160
- return this._scheduleAbsolute({ first: state, second: action }, dueTime, function (s, p) {
1161
- return invokeRecDate(s, p, 'scheduleWithAbsoluteAndState');
1162
- });
1163
- };
1132
+ /**
1133
+ * Schedules an action to be executed recursively at a specified absolute due time.
1134
+ * @param {Function} action Action to execute recursively. The parameter passed to the action is used to trigger recursive scheduling of the action at the specified absolute time.
1135
+ * @param {Number}dueTime Absolute time at which to execute the action for the first time.
1136
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1137
+ */
1138
+ schedulerProto.scheduleRecursiveWithAbsolute = function (dueTime, action) {
1139
+ return this.scheduleRecursiveWithAbsoluteAndState(action, dueTime, scheduleInnerRecursive);
1140
+ };
1164
1141
 
1165
- /** Gets the current time according to the local machine's system clock. */
1166
- Scheduler.now = defaultNow;
1142
+ /**
1143
+ * Schedules an action to be executed recursively at a specified absolute due time.
1144
+ * @param {Mixed} state State passed to the action to be executed.
1145
+ * @param {Function} action Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in the recursive due time and invocation state.
1146
+ * @param {Number}dueTime Absolute time at which to execute the action for the first time.
1147
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1148
+ */
1149
+ schedulerProto.scheduleRecursiveWithAbsoluteAndState = function (state, dueTime, action) {
1150
+ return this._scheduleAbsolute({ first: state, second: action }, dueTime, function (s, p) {
1151
+ return invokeRecDate(s, p, 'scheduleWithAbsoluteAndState');
1152
+ });
1153
+ };
1154
+ }(Scheduler.prototype));
1167
1155
 
1168
- /**
1169
- * Normalizes the specified TimeSpan value to a positive value.
1170
- * @param {Number} timeSpan The time span value to normalize.
1171
- * @returns {Number} The specified TimeSpan value if it is zero or positive; otherwise, 0
1172
- */
1173
- Scheduler.normalize = function (timeSpan) {
1174
- if (timeSpan < 0) {
1175
- timeSpan = 0;
1176
- }
1177
- return timeSpan;
1178
- };
1156
+ (function (schedulerProto) {
1157
+ /**
1158
+ * Schedules a periodic piece of work by dynamically discovering the scheduler's capabilities. The periodic task will be scheduled using window.setInterval for the base implementation.
1159
+ * @param {Number} period Period for running the work periodically.
1160
+ * @param {Function} action Action to be executed.
1161
+ * @returns {Disposable} The disposable object used to cancel the scheduled recurring action (best effort).
1162
+ */
1163
+ Scheduler.prototype.schedulePeriodic = function (period, action) {
1164
+ return this.schedulePeriodicWithState(null, period, action);
1165
+ };
1179
1166
 
1180
- return Scheduler;
1181
- }());
1167
+ /**
1168
+ * Schedules a periodic piece of work by dynamically discovering the scheduler's capabilities. The periodic task will be scheduled using window.setInterval for the base implementation.
1169
+ * @param {Mixed} state Initial state passed to the action upon the first iteration.
1170
+ * @param {Number} period Period for running the work periodically.
1171
+ * @param {Function} action Action to be executed, potentially updating the state.
1172
+ * @returns {Disposable} The disposable object used to cancel the scheduled recurring action (best effort).
1173
+ */
1174
+ Scheduler.prototype.schedulePeriodicWithState = function (state, period, action) {
1175
+ var s = state;
1176
+
1177
+ var id = setInterval(function () {
1178
+ s = action(s);
1179
+ }, period);
1182
1180
 
1183
- var normalizeTime = Scheduler.normalize;
1184
-
1185
- var SchedulePeriodicRecursive = Rx.internals.SchedulePeriodicRecursive = (function () {
1186
- function tick(command, recurse) {
1187
- recurse(0, this._period);
1188
- try {
1189
- this._state = this._action(this._state);
1190
- } catch (e) {
1191
- this._cancel.dispose();
1192
- throw e;
1193
- }
1194
- }
1181
+ return disposableCreate(function () {
1182
+ clearInterval(id);
1183
+ });
1184
+ };
1185
+ }(Scheduler.prototype));
1186
+
1187
+ (function (schedulerProto) {
1188
+ /**
1189
+ * Returns a scheduler that wraps the original scheduler, adding exception handling for scheduled actions.
1190
+ * @param {Function} handler Handler that's run if an exception is caught. The exception will be rethrown if the handler returns false.
1191
+ * @returns {Scheduler} Wrapper around the original scheduler, enforcing exception handling.
1192
+ */
1193
+ schedulerProto.catchError = schedulerProto['catch'] = function (handler) {
1194
+ return new CatchScheduler(this, handler);
1195
+ };
1196
+ }(Scheduler.prototype));
1197
+
1198
+ var SchedulePeriodicRecursive = Rx.internals.SchedulePeriodicRecursive = (function () {
1199
+ function tick(command, recurse) {
1200
+ recurse(0, this._period);
1201
+ try {
1202
+ this._state = this._action(this._state);
1203
+ } catch (e) {
1204
+ this._cancel.dispose();
1205
+ throw e;
1206
+ }
1207
+ }
1208
+
1209
+ function SchedulePeriodicRecursive(scheduler, state, period, action) {
1210
+ this._scheduler = scheduler;
1211
+ this._state = state;
1212
+ this._period = period;
1213
+ this._action = action;
1214
+ }
1215
+
1216
+ SchedulePeriodicRecursive.prototype.start = function () {
1217
+ var d = new SingleAssignmentDisposable();
1218
+ this._cancel = d;
1219
+ d.setDisposable(this._scheduler.scheduleRecursiveWithRelativeAndState(0, this._period, tick.bind(this)));
1220
+
1221
+ return d;
1222
+ };
1223
+
1224
+ return SchedulePeriodicRecursive;
1225
+ }());
1226
+
1227
+ /**
1228
+ * Gets a scheduler that schedules work immediately on the current thread.
1229
+ */
1230
+ var immediateScheduler = Scheduler.immediate = (function () {
1231
+
1232
+ function scheduleNow(state, action) { return action(this, state); }
1233
+
1234
+ function scheduleRelative(state, dueTime, action) {
1235
+ var dt = normalizeTime(dt);
1236
+ while (dt - this.now() > 0) { }
1237
+ return action(this, state);
1238
+ }
1239
+
1240
+ function scheduleAbsolute(state, dueTime, action) {
1241
+ return this.scheduleWithRelativeAndState(state, dueTime - this.now(), action);
1242
+ }
1243
+
1244
+ return new Scheduler(defaultNow, scheduleNow, scheduleRelative, scheduleAbsolute);
1245
+ }());
1195
1246
 
1196
- function SchedulePeriodicRecursive(scheduler, state, period, action) {
1197
- this._scheduler = scheduler;
1198
- this._state = state;
1199
- this._period = period;
1200
- this._action = action;
1247
+ /**
1248
+ * Gets a scheduler that schedules work as soon as possible on the current thread.
1249
+ */
1250
+ var currentThreadScheduler = Scheduler.currentThread = (function () {
1251
+ var queue;
1252
+
1253
+ function runTrampoline (q) {
1254
+ var item;
1255
+ while (q.length > 0) {
1256
+ item = q.dequeue();
1257
+ if (!item.isCancelled()) {
1258
+ // Note, do not schedule blocking work!
1259
+ while (item.dueTime - Scheduler.now() > 0) {
1260
+ }
1261
+ if (!item.isCancelled()) {
1262
+ item.invoke();
1263
+ }
1201
1264
  }
1265
+ }
1266
+ }
1202
1267
 
1203
- SchedulePeriodicRecursive.prototype.start = function () {
1204
- var d = new SingleAssignmentDisposable();
1205
- this._cancel = d;
1206
- d.setDisposable(this._scheduler.scheduleRecursiveWithRelativeAndState(0, this._period, tick.bind(this)));
1207
-
1208
- return d;
1209
- };
1210
-
1211
- return SchedulePeriodicRecursive;
1212
- }());
1213
-
1214
- /**
1215
- * Gets a scheduler that schedules work immediately on the current thread.
1216
- */
1217
- var immediateScheduler = Scheduler.immediate = (function () {
1218
-
1219
- function scheduleNow(state, action) { return action(this, state); }
1268
+ function scheduleNow(state, action) {
1269
+ return this.scheduleWithRelativeAndState(state, 0, action);
1270
+ }
1220
1271
 
1221
1272
  function scheduleRelative(state, dueTime, action) {
1222
- var dt = normalizeTime(dt);
1223
- while (dt - this.now() > 0) { }
1224
- return action(this, state);
1273
+ var dt = this.now() + Scheduler.normalize(dueTime),
1274
+ si = new ScheduledItem(this, state, action, dt);
1275
+
1276
+ if (!queue) {
1277
+ queue = new PriorityQueue(4);
1278
+ queue.enqueue(si);
1279
+ try {
1280
+ runTrampoline(queue);
1281
+ } catch (e) {
1282
+ throw e;
1283
+ } finally {
1284
+ queue = null;
1285
+ }
1286
+ } else {
1287
+ queue.enqueue(si);
1288
+ }
1289
+ return si.disposable;
1225
1290
  }
1226
1291
 
1227
1292
  function scheduleAbsolute(state, dueTime, action) {
1228
1293
  return this.scheduleWithRelativeAndState(state, dueTime - this.now(), action);
1229
1294
  }
1230
1295
 
1231
- return new Scheduler(defaultNow, scheduleNow, scheduleRelative, scheduleAbsolute);
1232
- }());
1233
-
1234
- /**
1235
- * Gets a scheduler that schedules work as soon as possible on the current thread.
1236
- */
1237
- var currentThreadScheduler = Scheduler.currentThread = (function () {
1238
- var queue;
1239
-
1240
- function runTrampoline (q) {
1241
- var item;
1242
- while (q.length > 0) {
1243
- item = q.dequeue();
1244
- if (!item.isCancelled()) {
1245
- // Note, do not schedule blocking work!
1246
- while (item.dueTime - Scheduler.now() > 0) {
1247
- }
1248
- if (!item.isCancelled()) {
1249
- item.invoke();
1250
- }
1251
- }
1252
- }
1253
- }
1254
-
1255
- function scheduleNow(state, action) {
1256
- return this.scheduleWithRelativeAndState(state, 0, action);
1257
- }
1258
-
1259
- function scheduleRelative(state, dueTime, action) {
1260
- var dt = this.now() + Scheduler.normalize(dueTime),
1261
- si = new ScheduledItem(this, state, action, dt),
1262
- t;
1263
- if (!queue) {
1264
- queue = new PriorityQueue(4);
1265
- queue.enqueue(si);
1266
- try {
1267
- runTrampoline(queue);
1268
- } catch (e) {
1269
- throw e;
1270
- } finally {
1271
- queue = null;
1272
- }
1273
- } else {
1274
- queue.enqueue(si);
1275
- }
1276
- return si.disposable;
1277
- }
1278
-
1279
- function scheduleAbsolute(state, dueTime, action) {
1280
- return this.scheduleWithRelativeAndState(state, dueTime - this.now(), action);
1281
- }
1282
-
1283
- var currentScheduler = new Scheduler(defaultNow, scheduleNow, scheduleRelative, scheduleAbsolute);
1284
- currentScheduler.scheduleRequired = function () { return queue === null; };
1285
- currentScheduler.ensureTrampoline = function (action) {
1286
- if (queue === null) {
1287
- return this.schedule(action);
1288
- } else {
1289
- return action();
1290
- }
1291
- };
1296
+ var currentScheduler = new Scheduler(defaultNow, scheduleNow, scheduleRelative, scheduleAbsolute);
1297
+
1298
+ currentScheduler.scheduleRequired = function () { return !queue; };
1299
+ currentScheduler.ensureTrampoline = function (action) {
1300
+ if (!queue) { this.schedule(action); } else { action(); }
1301
+ };
1292
1302
 
1293
- return currentScheduler;
1294
- }());
1303
+ return currentScheduler;
1304
+ }());
1295
1305
 
1296
1306
 
1297
1307
  var scheduleMethod, clearMethod = noop;
@@ -1619,150 +1629,150 @@
1619
1629
  };
1620
1630
  }());
1621
1631
 
1622
- var Enumerator = Rx.internals.Enumerator = function (next) {
1623
- this._next = next;
1624
- };
1625
-
1626
- Enumerator.prototype.next = function () {
1627
- return this._next();
1628
- };
1629
-
1630
- Enumerator.prototype[$iterator$] = function () { return this; }
1631
-
1632
- var Enumerable = Rx.internals.Enumerable = function (iterator) {
1633
- this._iterator = iterator;
1634
- };
1635
-
1636
- Enumerable.prototype[$iterator$] = function () {
1637
- return this._iterator();
1638
- };
1639
-
1640
- Enumerable.prototype.concat = function () {
1641
- var sources = this;
1642
- return new AnonymousObservable(function (observer) {
1643
- var e;
1644
- try {
1645
- e = sources[$iterator$]();
1646
- } catch(err) {
1647
- observer.onError();
1648
- return;
1649
- }
1650
-
1651
- var isDisposed,
1652
- subscription = new SerialDisposable();
1653
- var cancelable = immediateScheduler.scheduleRecursive(function (self) {
1654
- var currentItem;
1655
- if (isDisposed) { return; }
1656
-
1657
- try {
1658
- currentItem = e.next();
1659
- } catch (ex) {
1660
- observer.onError(ex);
1661
- return;
1662
- }
1663
-
1664
- if (currentItem.done) {
1665
- observer.onCompleted();
1666
- return;
1667
- }
1668
-
1669
- // Check if promise
1670
- var currentValue = currentItem.value;
1671
- isPromise(currentValue) && (currentValue = observableFromPromise(currentValue));
1672
-
1673
- var d = new SingleAssignmentDisposable();
1674
- subscription.setDisposable(d);
1675
- d.setDisposable(currentValue.subscribe(
1676
- observer.onNext.bind(observer),
1677
- observer.onError.bind(observer),
1678
- function () { self(); })
1679
- );
1680
- });
1681
-
1682
- return new CompositeDisposable(subscription, cancelable, disposableCreate(function () {
1683
- isDisposed = true;
1684
- }));
1685
- });
1686
- };
1687
-
1688
- Enumerable.prototype.catchException = function () {
1689
- var sources = this;
1690
- return new AnonymousObservable(function (observer) {
1691
- var e;
1692
- try {
1693
- e = sources[$iterator$]();
1694
- } catch(err) {
1695
- observer.onError();
1696
- return;
1697
- }
1698
-
1699
- var isDisposed,
1700
- lastException,
1701
- subscription = new SerialDisposable();
1702
- var cancelable = immediateScheduler.scheduleRecursive(function (self) {
1703
- if (isDisposed) { return; }
1704
-
1705
- var currentItem;
1706
- try {
1707
- currentItem = e.next();
1708
- } catch (ex) {
1709
- observer.onError(ex);
1710
- return;
1711
- }
1712
-
1713
- if (currentItem.done) {
1714
- if (lastException) {
1715
- observer.onError(lastException);
1716
- } else {
1717
- observer.onCompleted();
1718
- }
1719
- return;
1720
- }
1721
-
1722
- // Check if promise
1723
- var currentValue = currentItem.value;
1724
- isPromise(currentValue) && (currentValue = observableFromPromise(currentValue));
1725
-
1726
- var d = new SingleAssignmentDisposable();
1727
- subscription.setDisposable(d);
1728
- d.setDisposable(currentValue.subscribe(
1729
- observer.onNext.bind(observer),
1730
- function (exn) {
1731
- lastException = exn;
1732
- self();
1733
- },
1734
- observer.onCompleted.bind(observer)));
1735
- });
1736
- return new CompositeDisposable(subscription, cancelable, disposableCreate(function () {
1737
- isDisposed = true;
1738
- }));
1739
- });
1740
- };
1741
-
1742
- var enumerableRepeat = Enumerable.repeat = function (value, repeatCount) {
1743
- if (repeatCount == null) { repeatCount = -1; }
1744
- return new Enumerable(function () {
1745
- var left = repeatCount;
1746
- return new Enumerator(function () {
1747
- if (left === 0) { return doneEnumerator; }
1748
- if (left > 0) { left--; }
1749
- return { done: false, value: value };
1750
- });
1751
- });
1752
- };
1753
-
1754
- var enumerableFor = Enumerable.forEach = function (source, selector, thisArg) {
1755
- selector || (selector = identity);
1756
- return new Enumerable(function () {
1757
- var index = -1;
1758
- return new Enumerator(
1759
- function () {
1760
- return ++index < source.length ?
1761
- { done: false, value: selector.call(thisArg, source[index], index, source) } :
1762
- doneEnumerator;
1763
- });
1764
- });
1765
- };
1632
+ var Enumerator = Rx.internals.Enumerator = function (next) {
1633
+ this._next = next;
1634
+ };
1635
+
1636
+ Enumerator.prototype.next = function () {
1637
+ return this._next();
1638
+ };
1639
+
1640
+ Enumerator.prototype[$iterator$] = function () { return this; }
1641
+
1642
+ var Enumerable = Rx.internals.Enumerable = function (iterator) {
1643
+ this._iterator = iterator;
1644
+ };
1645
+
1646
+ Enumerable.prototype[$iterator$] = function () {
1647
+ return this._iterator();
1648
+ };
1649
+
1650
+ Enumerable.prototype.concat = function () {
1651
+ var sources = this;
1652
+ return new AnonymousObservable(function (observer) {
1653
+ var e;
1654
+ try {
1655
+ e = sources[$iterator$]();
1656
+ } catch(err) {
1657
+ observer.onError();
1658
+ return;
1659
+ }
1660
+
1661
+ var isDisposed,
1662
+ subscription = new SerialDisposable();
1663
+ var cancelable = immediateScheduler.scheduleRecursive(function (self) {
1664
+ var currentItem;
1665
+ if (isDisposed) { return; }
1666
+
1667
+ try {
1668
+ currentItem = e.next();
1669
+ } catch (ex) {
1670
+ observer.onError(ex);
1671
+ return;
1672
+ }
1673
+
1674
+ if (currentItem.done) {
1675
+ observer.onCompleted();
1676
+ return;
1677
+ }
1678
+
1679
+ // Check if promise
1680
+ var currentValue = currentItem.value;
1681
+ isPromise(currentValue) && (currentValue = observableFromPromise(currentValue));
1682
+
1683
+ var d = new SingleAssignmentDisposable();
1684
+ subscription.setDisposable(d);
1685
+ d.setDisposable(currentValue.subscribe(
1686
+ observer.onNext.bind(observer),
1687
+ observer.onError.bind(observer),
1688
+ function () { self(); })
1689
+ );
1690
+ });
1691
+
1692
+ return new CompositeDisposable(subscription, cancelable, disposableCreate(function () {
1693
+ isDisposed = true;
1694
+ }));
1695
+ });
1696
+ };
1697
+
1698
+ Enumerable.prototype.catchException = function () {
1699
+ var sources = this;
1700
+ return new AnonymousObservable(function (observer) {
1701
+ var e;
1702
+ try {
1703
+ e = sources[$iterator$]();
1704
+ } catch(err) {
1705
+ observer.onError();
1706
+ return;
1707
+ }
1708
+
1709
+ var isDisposed,
1710
+ lastException,
1711
+ subscription = new SerialDisposable();
1712
+ var cancelable = immediateScheduler.scheduleRecursive(function (self) {
1713
+ if (isDisposed) { return; }
1714
+
1715
+ var currentItem;
1716
+ try {
1717
+ currentItem = e.next();
1718
+ } catch (ex) {
1719
+ observer.onError(ex);
1720
+ return;
1721
+ }
1722
+
1723
+ if (currentItem.done) {
1724
+ if (lastException) {
1725
+ observer.onError(lastException);
1726
+ } else {
1727
+ observer.onCompleted();
1728
+ }
1729
+ return;
1730
+ }
1731
+
1732
+ // Check if promise
1733
+ var currentValue = currentItem.value;
1734
+ isPromise(currentValue) && (currentValue = observableFromPromise(currentValue));
1735
+
1736
+ var d = new SingleAssignmentDisposable();
1737
+ subscription.setDisposable(d);
1738
+ d.setDisposable(currentValue.subscribe(
1739
+ observer.onNext.bind(observer),
1740
+ function (exn) {
1741
+ lastException = exn;
1742
+ self();
1743
+ },
1744
+ observer.onCompleted.bind(observer)));
1745
+ });
1746
+ return new CompositeDisposable(subscription, cancelable, disposableCreate(function () {
1747
+ isDisposed = true;
1748
+ }));
1749
+ });
1750
+ };
1751
+
1752
+ var enumerableRepeat = Enumerable.repeat = function (value, repeatCount) {
1753
+ if (repeatCount == null) { repeatCount = -1; }
1754
+ return new Enumerable(function () {
1755
+ var left = repeatCount;
1756
+ return new Enumerator(function () {
1757
+ if (left === 0) { return doneEnumerator; }
1758
+ if (left > 0) { left--; }
1759
+ return { done: false, value: value };
1760
+ });
1761
+ });
1762
+ };
1763
+
1764
+ var enumerableFor = Enumerable.forEach = function (source, selector, thisArg) {
1765
+ selector || (selector = identity);
1766
+ return new Enumerable(function () {
1767
+ var index = -1;
1768
+ return new Enumerator(
1769
+ function () {
1770
+ return ++index < source.length ?
1771
+ { done: false, value: selector.call(thisArg, source[index], index, source) } :
1772
+ doneEnumerator;
1773
+ });
1774
+ });
1775
+ };
1766
1776
 
1767
1777
  /**
1768
1778
  * Supports push-style iteration over an observable sequence.
@@ -2194,21 +2204,19 @@
2194
2204
  * @returns {Observable} An Observable sequence which wraps the existing promise success and failure.
2195
2205
  */
2196
2206
  var observableFromPromise = Observable.fromPromise = function (promise) {
2197
- return new AnonymousObservable(function (observer) {
2207
+ return observableDefer(function () {
2208
+ var subject = new Rx.AsyncSubject();
2209
+
2198
2210
  promise.then(
2199
2211
  function (value) {
2200
- observer.onNext(value);
2201
- observer.onCompleted();
2202
- },
2203
- function (reason) {
2204
- observer.onError(reason);
2205
- });
2212
+ if (!subject.isDisposed) {
2213
+ subject.onNext(value);
2214
+ subject.onCompleted();
2215
+ }
2216
+ },
2217
+ subject.onError.bind(subject));
2206
2218
 
2207
- return function () {
2208
- if (promise && promise.abort) {
2209
- promise.abort();
2210
- }
2211
- }
2219
+ return subject;
2212
2220
  });
2213
2221
  };
2214
2222
  /*
@@ -2261,20 +2269,20 @@
2261
2269
  });
2262
2270
  };
2263
2271
 
2264
- /**
2265
- * Creates an observable sequence from a specified subscribe method implementation.
2266
- *
2267
- * @example
2268
- * var res = Rx.Observable.create(function (observer) { return function () { } );
2269
- * var res = Rx.Observable.create(function (observer) { return Rx.Disposable.empty; } );
2270
- * var res = Rx.Observable.create(function (observer) { } );
2271
- *
2272
- * @param {Function} subscribe Implementation of the resulting observable sequence's subscribe method, returning a function that will be wrapped in a Disposable.
2273
- * @returns {Observable} The observable sequence with the specified implementation for the Subscribe method.
2274
- */
2275
- Observable.create = Observable.createWithDisposable = function (subscribe) {
2276
- return new AnonymousObservable(subscribe);
2277
- };
2272
+ /**
2273
+ * Creates an observable sequence from a specified subscribe method implementation.
2274
+ *
2275
+ * @example
2276
+ * var res = Rx.Observable.create(function (observer) { return function () { } );
2277
+ * var res = Rx.Observable.create(function (observer) { return Rx.Disposable.empty; } );
2278
+ * var res = Rx.Observable.create(function (observer) { } );
2279
+ *
2280
+ * @param {Function} subscribe Implementation of the resulting observable sequence's subscribe method, returning a function that will be wrapped in a Disposable.
2281
+ * @returns {Observable} The observable sequence with the specified implementation for the Subscribe method.
2282
+ */
2283
+ Observable.create = Observable.createWithDisposable = function (subscribe) {
2284
+ return new AnonymousObservable(subscribe);
2285
+ };
2278
2286
 
2279
2287
  /**
2280
2288
  * Returns an observable sequence that invokes the specified factory function whenever a new observer subscribes.
@@ -2870,63 +2878,53 @@
2870
2878
  return this.merge(1);
2871
2879
  };
2872
2880
 
2873
- /**
2874
- * Merges an observable sequence of observable sequences into an observable sequence, limiting the number of concurrent subscriptions to inner sequences.
2875
- * Or merges two observable sequences into a single observable sequence.
2876
- *
2877
- * @example
2878
- * 1 - merged = sources.merge(1);
2879
- * 2 - merged = source.merge(otherSource);
2880
- * @param {Mixed} [maxConcurrentOrOther] Maximum number of inner observable sequences being subscribed to concurrently or the second observable sequence.
2881
- * @returns {Observable} The observable sequence that merges the elements of the inner sequences.
2882
- */
2883
- observableProto.merge = function (maxConcurrentOrOther) {
2884
- if (typeof maxConcurrentOrOther !== 'number') {
2885
- return observableMerge(this, maxConcurrentOrOther);
2881
+ /**
2882
+ * Merges an observable sequence of observable sequences into an observable sequence, limiting the number of concurrent subscriptions to inner sequences.
2883
+ * Or merges two observable sequences into a single observable sequence.
2884
+ *
2885
+ * @example
2886
+ * 1 - merged = sources.merge(1);
2887
+ * 2 - merged = source.merge(otherSource);
2888
+ * @param {Mixed} [maxConcurrentOrOther] Maximum number of inner observable sequences being subscribed to concurrently or the second observable sequence.
2889
+ * @returns {Observable} The observable sequence that merges the elements of the inner sequences.
2890
+ */
2891
+ observableProto.merge = function (maxConcurrentOrOther) {
2892
+ if (typeof maxConcurrentOrOther !== 'number') { return observableMerge(this, maxConcurrentOrOther); }
2893
+ var sources = this;
2894
+ return new AnonymousObservable(function (observer) {
2895
+ var activeCount = 0, group = new CompositeDisposable(), isStopped = false, q = [];
2896
+
2897
+ function subscribe(xs) {
2898
+ var subscription = new SingleAssignmentDisposable();
2899
+ group.add(subscription);
2900
+
2901
+ // Check for promises support
2902
+ isPromise(xs) && (xs = observableFromPromise(xs));
2903
+
2904
+ subscription.setDisposable(xs.subscribe(observer.onNext.bind(observer), observer.onError.bind(observer), function () {
2905
+ group.remove(subscription);
2906
+ if (q.length > 0) {
2907
+ subscribe(q.shift());
2908
+ } else {
2909
+ activeCount--;
2910
+ isStopped && activeCount === 0 && observer.onCompleted();
2911
+ }
2912
+ }));
2913
+ }
2914
+ group.add(sources.subscribe(function (innerSource) {
2915
+ if (activeCount < maxConcurrentOrOther) {
2916
+ activeCount++;
2917
+ subscribe(innerSource);
2918
+ } else {
2919
+ q.push(innerSource);
2886
2920
  }
2887
- var sources = this;
2888
- return new AnonymousObservable(function (observer) {
2889
- var activeCount = 0,
2890
- group = new CompositeDisposable(),
2891
- isStopped = false,
2892
- q = [],
2893
- subscribe = function (xs) {
2894
- var subscription = new SingleAssignmentDisposable();
2895
- group.add(subscription);
2896
-
2897
- // Check for promises support
2898
- if (isPromise(xs)) { xs = observableFromPromise(xs); }
2899
-
2900
- subscription.setDisposable(xs.subscribe(observer.onNext.bind(observer), observer.onError.bind(observer), function () {
2901
- var s;
2902
- group.remove(subscription);
2903
- if (q.length > 0) {
2904
- s = q.shift();
2905
- subscribe(s);
2906
- } else {
2907
- activeCount--;
2908
- if (isStopped && activeCount === 0) {
2909
- observer.onCompleted();
2910
- }
2911
- }
2912
- }));
2913
- };
2914
- group.add(sources.subscribe(function (innerSource) {
2915
- if (activeCount < maxConcurrentOrOther) {
2916
- activeCount++;
2917
- subscribe(innerSource);
2918
- } else {
2919
- q.push(innerSource);
2920
- }
2921
- }, observer.onError.bind(observer), function () {
2922
- isStopped = true;
2923
- if (activeCount === 0) {
2924
- observer.onCompleted();
2925
- }
2926
- }));
2927
- return group;
2928
- });
2929
- };
2921
+ }, observer.onError.bind(observer), function () {
2922
+ isStopped = true;
2923
+ activeCount === 0 && observer.onCompleted();
2924
+ }));
2925
+ return group;
2926
+ });
2927
+ };
2930
2928
 
2931
2929
  /**
2932
2930
  * Merges all the observable sequences into a single observable sequence.
@@ -3363,62 +3361,62 @@
3363
3361
  });
3364
3362
  };
3365
3363
 
3366
- /**
3367
- * Invokes an action for each element in the observable sequence and invokes an action upon graceful or exceptional termination of the observable sequence.
3368
- * This method can be used for debugging, logging, etc. of query behavior by intercepting the message stream to run arbitrary actions for messages on the pipeline.
3369
- *
3370
- * @example
3371
- * var res = observable.doAction(observer);
3372
- * var res = observable.doAction(onNext);
3373
- * var res = observable.doAction(onNext, onError);
3374
- * var res = observable.doAction(onNext, onError, onCompleted);
3375
- * @param {Mixed} observerOrOnNext Action to invoke for each element in the observable sequence or an observer.
3376
- * @param {Function} [onError] Action to invoke upon exceptional termination of the observable sequence. Used if only the observerOrOnNext parameter is also a function.
3377
- * @param {Function} [onCompleted] Action to invoke upon graceful termination of the observable sequence. Used if only the observerOrOnNext parameter is also a function.
3378
- * @returns {Observable} The source sequence with the side-effecting behavior applied.
3379
- */
3380
- observableProto['do'] = observableProto.doAction = function (observerOrOnNext, onError, onCompleted) {
3381
- var source = this, onNextFunc;
3382
- if (typeof observerOrOnNext === 'function') {
3383
- onNextFunc = observerOrOnNext;
3364
+ /**
3365
+ * Invokes an action for each element in the observable sequence and invokes an action upon graceful or exceptional termination of the observable sequence.
3366
+ * This method can be used for debugging, logging, etc. of query behavior by intercepting the message stream to run arbitrary actions for messages on the pipeline.
3367
+ *
3368
+ * @example
3369
+ * var res = observable.do(observer);
3370
+ * var res = observable.do(onNext);
3371
+ * var res = observable.do(onNext, onError);
3372
+ * var res = observable.do(onNext, onError, onCompleted);
3373
+ * @param {Function | Observer} observerOrOnNext Action to invoke for each element in the observable sequence or an observer.
3374
+ * @param {Function} [onError] Action to invoke upon exceptional termination of the observable sequence. Used if only the observerOrOnNext parameter is also a function.
3375
+ * @param {Function} [onCompleted] Action to invoke upon graceful termination of the observable sequence. Used if only the observerOrOnNext parameter is also a function.
3376
+ * @returns {Observable} The source sequence with the side-effecting behavior applied.
3377
+ */
3378
+ observableProto['do'] = observableProto.doAction = observableProto.tap = function (observerOrOnNext, onError, onCompleted) {
3379
+ var source = this, onNextFunc;
3380
+ if (typeof observerOrOnNext === 'function') {
3381
+ onNextFunc = observerOrOnNext;
3382
+ } else {
3383
+ onNextFunc = observerOrOnNext.onNext.bind(observerOrOnNext);
3384
+ onError = observerOrOnNext.onError.bind(observerOrOnNext);
3385
+ onCompleted = observerOrOnNext.onCompleted.bind(observerOrOnNext);
3386
+ }
3387
+ return new AnonymousObservable(function (observer) {
3388
+ return source.subscribe(function (x) {
3389
+ try {
3390
+ onNextFunc(x);
3391
+ } catch (e) {
3392
+ observer.onError(e);
3393
+ }
3394
+ observer.onNext(x);
3395
+ }, function (err) {
3396
+ if (!onError) {
3397
+ observer.onError(err);
3384
3398
  } else {
3385
- onNextFunc = observerOrOnNext.onNext.bind(observerOrOnNext);
3386
- onError = observerOrOnNext.onError.bind(observerOrOnNext);
3387
- onCompleted = observerOrOnNext.onCompleted.bind(observerOrOnNext);
3399
+ try {
3400
+ onError(err);
3401
+ } catch (e) {
3402
+ observer.onError(e);
3403
+ }
3404
+ observer.onError(err);
3388
3405
  }
3389
- return new AnonymousObservable(function (observer) {
3390
- return source.subscribe(function (x) {
3391
- try {
3392
- onNextFunc(x);
3393
- } catch (e) {
3394
- observer.onError(e);
3395
- }
3396
- observer.onNext(x);
3397
- }, function (exception) {
3398
- if (!onError) {
3399
- observer.onError(exception);
3400
- } else {
3401
- try {
3402
- onError(exception);
3403
- } catch (e) {
3404
- observer.onError(e);
3405
- }
3406
- observer.onError(exception);
3407
- }
3408
- }, function () {
3409
- if (!onCompleted) {
3410
- observer.onCompleted();
3411
- } else {
3412
- try {
3413
- onCompleted();
3414
- } catch (e) {
3415
- observer.onError(e);
3416
- }
3417
- observer.onCompleted();
3418
- }
3419
- });
3420
- });
3421
- };
3406
+ }, function () {
3407
+ if (!onCompleted) {
3408
+ observer.onCompleted();
3409
+ } else {
3410
+ try {
3411
+ onCompleted();
3412
+ } catch (e) {
3413
+ observer.onError(e);
3414
+ }
3415
+ observer.onCompleted();
3416
+ }
3417
+ });
3418
+ });
3419
+ };
3422
3420
 
3423
3421
  /**
3424
3422
  * Invokes a specified action after the source observable sequence terminates gracefully or exceptionally.
@@ -3601,48 +3599,54 @@
3601
3599
  return enumerableFor([observableFromArray(values, scheduler), this]).concat();
3602
3600
  };
3603
3601
 
3604
- /**
3605
- * Returns a specified number of contiguous elements from the end of an observable sequence, using an optional scheduler to drain the queue.
3606
- *
3607
- * @example
3608
- * var res = source.takeLast(5);
3609
- * var res = source.takeLast(5, Rx.Scheduler.timeout);
3610
- *
3611
- * @description
3612
- * This operator accumulates a buffer with a length enough to store elements count elements. Upon completion of
3613
- * the source sequence, this buffer is drained on the result sequence. This causes the elements to be delayed.
3614
- * @param {Number} count Number of elements to take from the end of the source sequence.
3615
- * @param {Scheduler} [scheduler] Scheduler used to drain the queue upon completion of the source sequence.
3616
- * @returns {Observable} An observable sequence containing the specified number of elements from the end of the source sequence.
3617
- */
3618
- observableProto.takeLast = function (count, scheduler) {
3619
- return this.takeLastBuffer(count).selectMany(function (xs) { return observableFromArray(xs, scheduler); });
3620
- };
3602
+ /**
3603
+ * Returns a specified number of contiguous elements from the end of an observable sequence.
3604
+ *
3605
+ * @example
3606
+ * var res = source.takeLast(5);
3607
+ *
3608
+ * @description
3609
+ * This operator accumulates a buffer with a length enough to store elements count elements. Upon completion of
3610
+ * the source sequence, this buffer is drained on the result sequence. This causes the elements to be delayed.
3611
+ * @param {Number} count Number of elements to take from the end of the source sequence.
3612
+ * @returns {Observable} An observable sequence containing the specified number of elements from the end of the source sequence.
3613
+ */
3614
+ observableProto.takeLast = function (count) {
3615
+ var source = this;
3616
+ return new AnonymousObservable(function (observer) {
3617
+ var q = [];
3618
+ return source.subscribe(function (x) {
3619
+ q.push(x);
3620
+ q.length > count && q.shift();
3621
+ }, observer.onError.bind(observer), function () {
3622
+ while(q.length > 0) { observer.onNext(q.shift()); }
3623
+ observer.onCompleted();
3624
+ });
3625
+ });
3626
+ };
3621
3627
 
3622
- /**
3623
- * Returns an array with the specified number of contiguous elements from the end of an observable sequence.
3624
- *
3625
- * @description
3626
- * This operator accumulates a buffer with a length enough to store count elements. Upon completion of the
3627
- * source sequence, this buffer is produced on the result sequence.
3628
- * @param {Number} count Number of elements to take from the end of the source sequence.
3629
- * @returns {Observable} An observable sequence containing a single array with the specified number of elements from the end of the source sequence.
3630
- */
3631
- observableProto.takeLastBuffer = function (count) {
3632
- var source = this;
3633
- return new AnonymousObservable(function (observer) {
3634
- var q = [];
3635
- return source.subscribe(function (x) {
3636
- q.push(x);
3637
- if (q.length > count) {
3638
- q.shift();
3639
- }
3640
- }, observer.onError.bind(observer), function () {
3641
- observer.onNext(q);
3642
- observer.onCompleted();
3643
- });
3644
- });
3645
- };
3628
+ /**
3629
+ * Returns an array with the specified number of contiguous elements from the end of an observable sequence.
3630
+ *
3631
+ * @description
3632
+ * This operator accumulates a buffer with a length enough to store count elements. Upon completion of the
3633
+ * source sequence, this buffer is produced on the result sequence.
3634
+ * @param {Number} count Number of elements to take from the end of the source sequence.
3635
+ * @returns {Observable} An observable sequence containing a single array with the specified number of elements from the end of the source sequence.
3636
+ */
3637
+ observableProto.takeLastBuffer = function (count) {
3638
+ var source = this;
3639
+ return new AnonymousObservable(function (observer) {
3640
+ var q = [];
3641
+ return source.subscribe(function (x) {
3642
+ q.push(x);
3643
+ q.length > count && q.shift();
3644
+ }, observer.onError.bind(observer), function () {
3645
+ observer.onNext(q);
3646
+ observer.onCompleted();
3647
+ });
3648
+ });
3649
+ };
3646
3650
 
3647
3651
  /**
3648
3652
  * Projects each element of an observable sequence into zero or more windows which are produced based on element count information.
@@ -3704,53 +3708,33 @@
3704
3708
  });
3705
3709
  };
3706
3710
 
3707
- function concatMap(selector) {
3708
- return this.map(function (x, i) {
3709
- var result = selector(x, i);
3711
+ function concatMap(source, selector, thisArg) {
3712
+ return source.map(function (x, i) {
3713
+ var result = selector.call(thisArg, x, i);
3710
3714
  return isPromise(result) ? observableFromPromise(result) : result;
3711
3715
  }).concatAll();
3712
3716
  }
3713
3717
 
3714
- function concatMapObserver(onNext, onError, onCompleted) {
3715
- var source = this;
3716
- return new AnonymousObservable(function (observer) {
3717
- var index = 0;
3718
-
3719
- return source.subscribe(
3720
- function (x) {
3721
- observer.onNext(onNext(x, index++));
3722
- },
3723
- function (err) {
3724
- observer.onNext(onError(err));
3725
- observer.completed();
3726
- },
3727
- function () {
3728
- observer.onNext(onCompleted());
3729
- observer.onCompleted();
3730
- });
3731
- }).concatAll();
3732
- }
3733
-
3734
3718
  /**
3735
3719
  * One of the Following:
3736
3720
  * Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence.
3737
3721
  *
3738
3722
  * @example
3739
- * var res = source.selectMany(function (x) { return Rx.Observable.range(0, x); });
3723
+ * var res = source.concatMap(function (x) { return Rx.Observable.range(0, x); });
3740
3724
  * Or:
3741
3725
  * Projects each element of an observable sequence to an observable sequence, invokes the result selector for the source element and each of the corresponding inner sequence's elements, and merges the results into one observable sequence.
3742
3726
  *
3743
- * var res = source.selectMany(function (x) { return Rx.Observable.range(0, x); }, function (x, y) { return x + y; });
3727
+ * var res = source.concatMap(function (x) { return Rx.Observable.range(0, x); }, function (x, y) { return x + y; });
3744
3728
  * Or:
3745
3729
  * Projects each element of the source observable sequence to the other observable sequence and merges the resulting observable sequences into one observable sequence.
3746
3730
  *
3747
- * var res = source.selectMany(Rx.Observable.fromArray([1,2,3]));
3731
+ * var res = source.concatMap(Rx.Observable.fromArray([1,2,3]));
3748
3732
  * @param selector A transform function to apply to each element or an observable sequence to project each element from the
3749
3733
  * source sequence onto which could be either an observable or Promise.
3750
3734
  * @param {Function} [resultSelector] A transform function to apply to each element of the intermediate sequence.
3751
3735
  * @returns {Observable} An observable sequence whose elements are the result of invoking the one-to-many transform function collectionSelector on each element of the input sequence and then mapping each of those sequence elements and their corresponding source element to a result element.
3752
3736
  */
3753
- observableProto.selectConcat = observableProto.concatMap = function (selector, resultSelector) {
3737
+ observableProto.selectConcat = observableProto.concatMap = function (selector, resultSelector, thisArg) {
3754
3738
  if (resultSelector) {
3755
3739
  return this.concatMap(function (x, i) {
3756
3740
  var selectorResult = selector(x, i),
@@ -3761,14 +3745,62 @@
3761
3745
  });
3762
3746
  });
3763
3747
  }
3764
- if (typeof selector === 'function') {
3765
- return concatMap.call(this, selector);
3766
- }
3767
- return concatMap.call(this, function () {
3768
- return selector;
3769
- });
3748
+ return typeof selector === 'function' ?
3749
+ concatMap(this, selector, thisArg) :
3750
+ concatMap(this, function () { return selector; });
3770
3751
  };
3771
3752
 
3753
+ /**
3754
+ * Projects each notification of an observable sequence to an observable sequence and concats the resulting observable sequences into one observable sequence.
3755
+ * @param {Function} onNext A transform function to apply to each element; the second parameter of the function represents the index of the source element.
3756
+ * @param {Function} onError A transform function to apply when an error occurs in the source sequence.
3757
+ * @param {Function} onCompleted A transform function to apply when the end of the source sequence is reached.
3758
+ * @param {Any} [thisArg] An optional "this" to use to invoke each transform.
3759
+ * @returns {Observable} An observable sequence whose elements are the result of invoking the one-to-many transform function corresponding to each notification in the input sequence.
3760
+ */
3761
+ observableProto.concatMapObserver = observableProto.selectConcatObserver = function(onNext, onError, onCompleted, thisArg) {
3762
+ var source = this;
3763
+ return new AnonymousObservable(function (observer) {
3764
+ var index = 0;
3765
+
3766
+ return source.subscribe(
3767
+ function (x) {
3768
+ var result;
3769
+ try {
3770
+ result = onNext.call(thisArg, x, index++);
3771
+ } catch (e) {
3772
+ observer.onError(e);
3773
+ return;
3774
+ }
3775
+ isPromise(result) && (result = observableFromPromise(result));
3776
+ observer.onNext(result);
3777
+ },
3778
+ function (err) {
3779
+ var result;
3780
+ try {
3781
+ result = onError.call(thisArg, err);
3782
+ } catch (e) {
3783
+ observer.onError(e);
3784
+ return;
3785
+ }
3786
+ isPromise(result) && (result = observableFromPromise(result));
3787
+ observer.onNext(result);
3788
+ observer.onCompleted();
3789
+ },
3790
+ function () {
3791
+ var result;
3792
+ try {
3793
+ result = onCompleted.call(thisArg);
3794
+ } catch (e) {
3795
+ observer.onError(e);
3796
+ return;
3797
+ }
3798
+ isPromise(result) && (result = observableFromPromise(result));
3799
+ observer.onNext(result);
3800
+ observer.onCompleted();
3801
+ });
3802
+ }).concatAll();
3803
+ };
3772
3804
  /**
3773
3805
  * Returns the elements of the specified sequence or the specified value in a singleton sequence if the sequence is empty.
3774
3806
  *
@@ -3777,194 +3809,80 @@
3777
3809
  *
3778
3810
  * @memberOf Observable#
3779
3811
  * @param defaultValue The value to return if the sequence is empty. If not provided, this defaults to null.
3780
- * @returns {Observable} An observable sequence that contains the specified default value if the source is empty; otherwise, the elements of the source itself.
3781
- */
3782
- observableProto.defaultIfEmpty = function (defaultValue) {
3783
- var source = this;
3784
- if (defaultValue === undefined) {
3785
- defaultValue = null;
3786
- }
3787
- return new AnonymousObservable(function (observer) {
3788
- var found = false;
3789
- return source.subscribe(function (x) {
3790
- found = true;
3791
- observer.onNext(x);
3792
- }, observer.onError.bind(observer), function () {
3793
- if (!found) {
3794
- observer.onNext(defaultValue);
3795
- }
3796
- observer.onCompleted();
3797
- });
3798
- });
3799
- };
3800
-
3801
- /**
3802
- * Returns an observable sequence that contains only distinct elements according to the keySelector and the comparer.
3803
- * Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.
3804
- *
3805
- * @example
3806
- * var res = obs = xs.distinct();
3807
- * 2 - obs = xs.distinct(function (x) { return x.id; });
3808
- * 2 - obs = xs.distinct(function (x) { return x.id; }, function (x) { return x.toString(); });
3809
- * @param {Function} [keySelector] A function to compute the comparison key for each element.
3810
- * @param {Function} [keySerializer] Used to serialize the given object into a string for object comparison.
3811
- * @returns {Observable} An observable sequence only containing the distinct elements, based on a computed key value, from the source sequence.
3812
- */
3813
- observableProto.distinct = function (keySelector, keySerializer) {
3814
- var source = this;
3815
- keySelector || (keySelector = identity);
3816
- keySerializer || (keySerializer = defaultKeySerializer);
3817
- return new AnonymousObservable(function (observer) {
3818
- var hashSet = {};
3819
- return source.subscribe(function (x) {
3820
- var key, serializedKey, otherKey, hasMatch = false;
3821
- try {
3822
- key = keySelector(x);
3823
- serializedKey = keySerializer(key);
3824
- } catch (exception) {
3825
- observer.onError(exception);
3826
- return;
3827
- }
3828
- for (otherKey in hashSet) {
3829
- if (serializedKey === otherKey) {
3830
- hasMatch = true;
3831
- break;
3832
- }
3833
- }
3834
- if (!hasMatch) {
3835
- hashSet[serializedKey] = null;
3836
- observer.onNext(x);
3837
- }
3838
- }, observer.onError.bind(observer), observer.onCompleted.bind(observer));
3839
- });
3840
- };
3841
-
3842
- /**
3843
- * Groups the elements of an observable sequence according to a specified key selector function and comparer and selects the resulting elements by using a specified function.
3844
- *
3845
- * @example
3846
- * var res = observable.groupBy(function (x) { return x.id; });
3847
- * 2 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; });
3848
- * 3 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; }, function (x) { return x.toString(); });
3849
- * @param {Function} keySelector A function to extract the key for each element.
3850
- * @param {Function} [elementSelector] A function to map each source element to an element in an observable group.
3851
- * @param {Function} [keySerializer] Used to serialize the given object into a string for object comparison.
3852
- * @returns {Observable} A sequence of observable groups, each of which corresponds to a unique key value, containing all elements that share that same key value.
3853
- */
3854
- observableProto.groupBy = function (keySelector, elementSelector, keySerializer) {
3855
- return this.groupByUntil(keySelector, elementSelector, function () {
3856
- return observableNever();
3857
- }, keySerializer);
3858
- };
3859
-
3860
- /**
3861
- * Groups the elements of an observable sequence according to a specified key selector function.
3862
- * A duration selector function is used to control the lifetime of groups. When a group expires, it receives an OnCompleted notification. When a new element with the same
3863
- * key value as a reclaimed group occurs, the group will be reborn with a new lifetime request.
3864
- *
3865
- * @example
3866
- * var res = observable.groupByUntil(function (x) { return x.id; }, null, function () { return Rx.Observable.never(); });
3867
- * 2 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; }, function () { return Rx.Observable.never(); });
3868
- * 3 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; }, function () { return Rx.Observable.never(); }, function (x) { return x.toString(); });
3869
- * @param {Function} keySelector A function to extract the key for each element.
3870
- * @param {Function} durationSelector A function to signal the expiration of a group.
3871
- * @param {Function} [keySerializer] Used to serialize the given object into a string for object comparison.
3872
- * @returns {Observable}
3873
- * A sequence of observable groups, each of which corresponds to a unique key value, containing all elements that share that same key value.
3874
- * If a group's lifetime expires, a new group with the same key value can be created once an element with such a key value is encoutered.
3875
- *
3812
+ * @returns {Observable} An observable sequence that contains the specified default value if the source is empty; otherwise, the elements of the source itself.
3876
3813
  */
3877
- observableProto.groupByUntil = function (keySelector, elementSelector, durationSelector, keySerializer) {
3814
+ observableProto.defaultIfEmpty = function (defaultValue) {
3878
3815
  var source = this;
3879
- elementSelector || (elementSelector = identity);
3880
- keySerializer || (keySerializer = defaultKeySerializer);
3816
+ if (defaultValue === undefined) {
3817
+ defaultValue = null;
3818
+ }
3881
3819
  return new AnonymousObservable(function (observer) {
3882
- var map = {},
3883
- groupDisposable = new CompositeDisposable(),
3884
- refCountDisposable = new RefCountDisposable(groupDisposable);
3885
- groupDisposable.add(source.subscribe(function (x) {
3886
- var duration, durationGroup, element, fireNewMapEntry, group, key, serializedKey, md, writer, w;
3887
- try {
3888
- key = keySelector(x);
3889
- serializedKey = keySerializer(key);
3890
- } catch (e) {
3891
- for (w in map) {
3892
- map[w].onError(e);
3893
- }
3894
- observer.onError(e);
3895
- return;
3896
- }
3897
- fireNewMapEntry = false;
3898
- try {
3899
- writer = map[serializedKey];
3900
- if (!writer) {
3901
- writer = new Subject();
3902
- map[serializedKey] = writer;
3903
- fireNewMapEntry = true;
3904
- }
3905
- } catch (e) {
3906
- for (w in map) {
3907
- map[w].onError(e);
3908
- }
3909
- observer.onError(e);
3910
- return;
3911
- }
3912
- if (fireNewMapEntry) {
3913
- group = new GroupedObservable(key, writer, refCountDisposable);
3914
- durationGroup = new GroupedObservable(key, writer);
3915
- try {
3916
- duration = durationSelector(durationGroup);
3917
- } catch (e) {
3918
- for (w in map) {
3919
- map[w].onError(e);
3920
- }
3921
- observer.onError(e);
3922
- return;
3923
- }
3924
- observer.onNext(group);
3925
- md = new SingleAssignmentDisposable();
3926
- groupDisposable.add(md);
3927
- var expire = function () {
3928
- if (serializedKey in map) {
3929
- delete map[serializedKey];
3930
- writer.onCompleted();
3931
- }
3932
- groupDisposable.remove(md);
3933
- };
3934
- md.setDisposable(duration.take(1).subscribe(noop, function (exn) {
3935
- for (w in map) {
3936
- map[w].onError(exn);
3937
- }
3938
- observer.onError(exn);
3939
- }, function () {
3940
- expire();
3941
- }));
3942
- }
3943
- try {
3944
- element = elementSelector(x);
3945
- } catch (e) {
3946
- for (w in map) {
3947
- map[w].onError(e);
3948
- }
3949
- observer.onError(e);
3950
- return;
3951
- }
3952
- writer.onNext(element);
3953
- }, function (ex) {
3954
- for (var w in map) {
3955
- map[w].onError(ex);
3956
- }
3957
- observer.onError(ex);
3958
- }, function () {
3959
- for (var w in map) {
3960
- map[w].onCompleted();
3820
+ var found = false;
3821
+ return source.subscribe(function (x) {
3822
+ found = true;
3823
+ observer.onNext(x);
3824
+ }, observer.onError.bind(observer), function () {
3825
+ if (!found) {
3826
+ observer.onNext(defaultValue);
3961
3827
  }
3962
3828
  observer.onCompleted();
3963
- }));
3964
- return refCountDisposable;
3829
+ });
3965
3830
  });
3966
3831
  };
3967
3832
 
3833
+ // Swap out for Array.findIndex
3834
+ function arrayIndexOfComparer(array, item, comparer) {
3835
+ for (var i = 0, len = array.length; i < len; i++) {
3836
+ if (comparer(array[i], item)) { return i; }
3837
+ }
3838
+ return -1;
3839
+ }
3840
+
3841
+ function HashSet(comparer) {
3842
+ this.comparer = comparer;
3843
+ this.set = [];
3844
+ }
3845
+ HashSet.prototype.push = function(value) {
3846
+ var retValue = arrayIndexOfComparer(this.set, value, this.comparer) === -1;
3847
+ retValue && this.set.push(value);
3848
+ return retValue;
3849
+ };
3850
+
3851
+ /**
3852
+ * Returns an observable sequence that contains only distinct elements according to the keySelector and the comparer.
3853
+ * Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.
3854
+ *
3855
+ * @example
3856
+ * var res = obs = xs.distinct();
3857
+ * 2 - obs = xs.distinct(function (x) { return x.id; });
3858
+ * 2 - obs = xs.distinct(function (x) { return x.id; }, function (a,b) { return a === b; });
3859
+ * @param {Function} [keySelector] A function to compute the comparison key for each element.
3860
+ * @param {Function} [comparer] Used to compare items in the collection.
3861
+ * @returns {Observable} An observable sequence only containing the distinct elements, based on a computed key value, from the source sequence.
3862
+ */
3863
+ observableProto.distinct = function (keySelector, comparer) {
3864
+ var source = this;
3865
+ comparer || (comparer = defaultComparer);
3866
+ return new AnonymousObservable(function (observer) {
3867
+ var hashSet = new HashSet(comparer);
3868
+ return source.subscribe(function (x) {
3869
+ var key = x;
3870
+
3871
+ if (keySelector) {
3872
+ try {
3873
+ key = keySelector(x);
3874
+ } catch (e) {
3875
+ observer.onError(e);
3876
+ return;
3877
+ }
3878
+ }
3879
+ hashSet.push(key) && observer.onNext(x);
3880
+ },
3881
+ observer.onError.bind(observer),
3882
+ observer.onCompleted.bind(observer));
3883
+ });
3884
+ };
3885
+
3968
3886
  /**
3969
3887
  * Projects each element of an observable sequence into a new form by incorporating the element's index.
3970
3888
  * @param {Function} selector A transform function to apply to each source element; the second parameter of the function represents the index of the source element.
@@ -3997,33 +3915,13 @@
3997
3915
  return this.select(function (x) { return x[property]; });
3998
3916
  };
3999
3917
 
4000
- function selectMany(selector) {
4001
- return this.select(function (x, i) {
4002
- var result = selector(x, i);
3918
+ function flatMap(source, selector, thisArg) {
3919
+ return source.map(function (x, i) {
3920
+ var result = selector.call(thisArg, x, i);
4003
3921
  return isPromise(result) ? observableFromPromise(result) : result;
4004
3922
  }).mergeObservable();
4005
3923
  }
4006
3924
 
4007
- function selectManyObserver(onNext, onError, onCompleted) {
4008
- var source = this;
4009
- return new AnonymousObservable(function (observer) {
4010
- var index = 0;
4011
-
4012
- return source.subscribe(
4013
- function (x) {
4014
- observer.onNext(onNext(x, index++));
4015
- },
4016
- function (err) {
4017
- observer.onNext(onError(err));
4018
- observer.completed();
4019
- },
4020
- function () {
4021
- observer.onNext(onCompleted());
4022
- observer.onCompleted();
4023
- });
4024
- }).mergeAll();
4025
- }
4026
-
4027
3925
  /**
4028
3926
  * One of the Following:
4029
3927
  * Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence.
@@ -4041,27 +3939,76 @@
4041
3939
  * @param selector A transform function to apply to each element or an observable sequence to project each element from the
4042
3940
  * source sequence onto which could be either an observable or Promise.
4043
3941
  * @param {Function} [resultSelector] A transform function to apply to each element of the intermediate sequence.
3942
+ * @param {Any} [thisArg] Object to use as this when executing callback.
4044
3943
  * @returns {Observable} An observable sequence whose elements are the result of invoking the one-to-many transform function collectionSelector on each element of the input sequence and then mapping each of those sequence elements and their corresponding source element to a result element.
4045
3944
  */
4046
- observableProto.selectMany = observableProto.flatMap = function (selector, resultSelector) {
3945
+ observableProto.selectMany = observableProto.flatMap = function (selector, resultSelector, thisArg) {
4047
3946
  if (resultSelector) {
4048
- return this.selectMany(function (x, i) {
3947
+ return this.flatMap(function (x, i) {
4049
3948
  var selectorResult = selector(x, i),
4050
3949
  result = isPromise(selectorResult) ? observableFromPromise(selectorResult) : selectorResult;
4051
3950
 
4052
- return result.select(function (y) {
3951
+ return result.map(function (y) {
4053
3952
  return resultSelector(x, y, i);
4054
3953
  });
4055
- });
4056
- }
4057
- if (typeof selector === 'function') {
4058
- return selectMany.call(this, selector);
3954
+ }, thisArg);
4059
3955
  }
4060
- return selectMany.call(this, function () {
4061
- return selector;
4062
- });
3956
+ return typeof selector === 'function' ?
3957
+ flatMap(this, selector, thisArg) :
3958
+ flatMap(this, function () { return selector; });
4063
3959
  };
4064
3960
 
3961
+ /**
3962
+ * Projects each notification of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence.
3963
+ * @param {Function} onNext A transform function to apply to each element; the second parameter of the function represents the index of the source element.
3964
+ * @param {Function} onError A transform function to apply when an error occurs in the source sequence.
3965
+ * @param {Function} onCompleted A transform function to apply when the end of the source sequence is reached.
3966
+ * @param {Any} [thisArg] An optional "this" to use to invoke each transform.
3967
+ * @returns {Observable} An observable sequence whose elements are the result of invoking the one-to-many transform function corresponding to each notification in the input sequence.
3968
+ */
3969
+ observableProto.flatMapObserver = observableProto.selectManyObserver = function (onNext, onError, onCompleted, thisArg) {
3970
+ var source = this;
3971
+ return new AnonymousObservable(function (observer) {
3972
+ var index = 0;
3973
+
3974
+ return source.subscribe(
3975
+ function (x) {
3976
+ var result;
3977
+ try {
3978
+ result = onNext.call(thisArg, x, index++);
3979
+ } catch (e) {
3980
+ observer.onError(e);
3981
+ return;
3982
+ }
3983
+ isPromise(result) && (result = observableFromPromise(result));
3984
+ observer.onNext(result);
3985
+ },
3986
+ function (err) {
3987
+ var result;
3988
+ try {
3989
+ result = onError.call(thisArg, err);
3990
+ } catch (e) {
3991
+ observer.onError(e);
3992
+ return;
3993
+ }
3994
+ isPromise(result) && (result = observableFromPromise(result));
3995
+ observer.onNext(result);
3996
+ observer.onCompleted();
3997
+ },
3998
+ function () {
3999
+ var result;
4000
+ try {
4001
+ result = onCompleted.call(thisArg);
4002
+ } catch (e) {
4003
+ observer.onError(e);
4004
+ return;
4005
+ }
4006
+ isPromise(result) && (result = observableFromPromise(result));
4007
+ observer.onNext(result);
4008
+ observer.onCompleted();
4009
+ });
4010
+ }).mergeAll();
4011
+ };
4065
4012
  /**
4066
4013
  * Projects each element of an observable sequence into a new sequence of observable sequences by incorporating the element's index and then
4067
4014
  * transforms an observable sequence of observable sequences into an observable sequence producing values only from the most recent observable sequence.
@@ -4334,13 +4281,11 @@
4334
4281
 
4335
4282
  // Fix subscriber to check for undefined or function returned to decorate as Disposable
4336
4283
  function fixSubscriber(subscriber) {
4337
- if (typeof subscriber === 'undefined') {
4338
- subscriber = disposableEmpty;
4339
- } else if (typeof subscriber === 'function') {
4340
- subscriber = disposableCreate(subscriber);
4341
- }
4284
+ if (subscriber && typeof subscriber.dispose === 'function') { return subscriber; }
4342
4285
 
4343
- return subscriber;
4286
+ return typeof subscriber === 'function' ?
4287
+ disposableCreate(subscriber) :
4288
+ disposableEmpty;
4344
4289
  }
4345
4290
 
4346
4291
  function AnonymousObservable(subscribe) {
@@ -4437,48 +4382,23 @@
4437
4382
  return AutoDetachObserver;
4438
4383
  }(AbstractObserver));
4439
4384
 
4440
- /** @private */
4441
- var GroupedObservable = (function (_super) {
4442
- inherits(GroupedObservable, _super);
4443
-
4444
- function subscribe(observer) {
4445
- return this.underlyingObservable.subscribe(observer);
4446
- }
4447
-
4448
- /**
4449
- * @constructor
4450
- * @private
4451
- */
4452
- function GroupedObservable(key, underlyingObservable, mergedDisposable) {
4453
- _super.call(this, subscribe);
4454
- this.key = key;
4455
- this.underlyingObservable = !mergedDisposable ?
4456
- underlyingObservable :
4457
- new AnonymousObservable(function (observer) {
4458
- return new CompositeDisposable(mergedDisposable.getDisposable(), underlyingObservable.subscribe(observer));
4459
- });
4460
- }
4461
-
4462
- return GroupedObservable;
4463
- }(Observable));
4464
-
4465
- /** @private */
4466
- var InnerSubscription = function (subject, observer) {
4467
- this.subject = subject;
4468
- this.observer = observer;
4469
- };
4470
-
4471
- /**
4472
- * @private
4473
- * @memberOf InnerSubscription
4474
- */
4475
- InnerSubscription.prototype.dispose = function () {
4476
- if (!this.subject.isDisposed && this.observer !== null) {
4477
- var idx = this.subject.observers.indexOf(this.observer);
4478
- this.subject.observers.splice(idx, 1);
4479
- this.observer = null;
4480
- }
4481
- };
4385
+ /** @private */
4386
+ var InnerSubscription = function (subject, observer) {
4387
+ this.subject = subject;
4388
+ this.observer = observer;
4389
+ };
4390
+
4391
+ /**
4392
+ * @private
4393
+ * @memberOf InnerSubscription
4394
+ */
4395
+ InnerSubscription.prototype.dispose = function () {
4396
+ if (!this.subject.isDisposed && this.observer !== null) {
4397
+ var idx = this.subject.observers.indexOf(this.observer);
4398
+ this.subject.observers.splice(idx, 1);
4399
+ this.observer = null;
4400
+ }
4401
+ };
4482
4402
 
4483
4403
  /**
4484
4404
  * Represents an object that is both an observable sequence as well as an observer.
@@ -4587,192 +4507,170 @@
4587
4507
  return Subject;
4588
4508
  }(Observable));
4589
4509
 
4590
- /**
4591
- * Represents the result of an asynchronous operation.
4592
- * The last value before the OnCompleted notification, or the error received through OnError, is sent to all subscribed observers.
4593
- */
4594
- var AsyncSubject = Rx.AsyncSubject = (function (_super) {
4595
-
4596
- function subscribe(observer) {
4597
- checkDisposed.call(this);
4598
-
4599
- if (!this.isStopped) {
4600
- this.observers.push(observer);
4601
- return new InnerSubscription(this, observer);
4602
- }
4603
-
4604
- var ex = this.exception,
4605
- hv = this.hasValue,
4606
- v = this.value;
4607
-
4608
- if (ex) {
4609
- observer.onError(ex);
4610
- } else if (hv) {
4611
- observer.onNext(v);
4612
- observer.onCompleted();
4613
- } else {
4614
- observer.onCompleted();
4615
- }
4616
-
4617
- return disposableEmpty;
4618
- }
4510
+ /**
4511
+ * Represents the result of an asynchronous operation.
4512
+ * The last value before the OnCompleted notification, or the error received through OnError, is sent to all subscribed observers.
4513
+ */
4514
+ var AsyncSubject = Rx.AsyncSubject = (function (__super__) {
4619
4515
 
4620
- inherits(AsyncSubject, _super);
4516
+ function subscribe(observer) {
4517
+ checkDisposed.call(this);
4518
+
4519
+ if (!this.isStopped) {
4520
+ this.observers.push(observer);
4521
+ return new InnerSubscription(this, observer);
4522
+ }
4621
4523
 
4622
- /**
4623
- * Creates a subject that can only receive one value and that value is cached for all future observations.
4624
- * @constructor
4625
- */
4626
- function AsyncSubject() {
4627
- _super.call(this, subscribe);
4524
+ var ex = this.exception,
4525
+ hv = this.hasValue,
4526
+ v = this.value;
4628
4527
 
4629
- this.isDisposed = false;
4630
- this.isStopped = false;
4631
- this.value = null;
4632
- this.hasValue = false;
4633
- this.observers = [];
4634
- this.exception = null;
4635
- }
4528
+ if (ex) {
4529
+ observer.onError(ex);
4530
+ } else if (hv) {
4531
+ observer.onNext(v);
4532
+ observer.onCompleted();
4533
+ } else {
4534
+ observer.onCompleted();
4535
+ }
4636
4536
 
4637
- addProperties(AsyncSubject.prototype, Observer, {
4638
- /**
4639
- * Indicates whether the subject has observers subscribed to it.
4640
- * @returns {Boolean} Indicates whether the subject has observers subscribed to it.
4641
- */
4642
- hasObservers: function () {
4643
- checkDisposed.call(this);
4644
- return this.observers.length > 0;
4645
- },
4646
- /**
4647
- * Notifies all subscribed observers about the end of the sequence, also causing the last received value to be sent out (if any).
4648
- */
4649
- onCompleted: function () {
4650
- var o, i, len;
4651
- checkDisposed.call(this);
4652
- if (!this.isStopped) {
4653
- this.isStopped = true;
4654
- var os = this.observers.slice(0),
4655
- v = this.value,
4656
- hv = this.hasValue;
4657
-
4658
- if (hv) {
4659
- for (i = 0, len = os.length; i < len; i++) {
4660
- o = os[i];
4661
- o.onNext(v);
4662
- o.onCompleted();
4663
- }
4664
- } else {
4665
- for (i = 0, len = os.length; i < len; i++) {
4666
- os[i].onCompleted();
4667
- }
4668
- }
4537
+ return disposableEmpty;
4538
+ }
4669
4539
 
4670
- this.observers = [];
4671
- }
4672
- },
4673
- /**
4674
- * Notifies all subscribed observers about the exception.
4675
- * @param {Mixed} error The exception to send to all observers.
4676
- */
4677
- onError: function (exception) {
4678
- checkDisposed.call(this);
4679
- if (!this.isStopped) {
4680
- var os = this.observers.slice(0);
4681
- this.isStopped = true;
4682
- this.exception = exception;
4540
+ inherits(AsyncSubject, __super__);
4683
4541
 
4684
- for (var i = 0, len = os.length; i < len; i++) {
4685
- os[i].onError(exception);
4686
- }
4542
+ /**
4543
+ * Creates a subject that can only receive one value and that value is cached for all future observations.
4544
+ * @constructor
4545
+ */
4546
+ function AsyncSubject() {
4547
+ __super__.call(this, subscribe);
4548
+
4549
+ this.isDisposed = false;
4550
+ this.isStopped = false;
4551
+ this.value = null;
4552
+ this.hasValue = false;
4553
+ this.observers = [];
4554
+ this.exception = null;
4555
+ }
4687
4556
 
4688
- this.observers = [];
4689
- }
4690
- },
4691
- /**
4692
- * Sends a value to the subject. The last value received before successful termination will be sent to all subscribed and future observers.
4693
- * @param {Mixed} value The value to store in the subject.
4694
- */
4695
- onNext: function (value) {
4696
- checkDisposed.call(this);
4697
- if (!this.isStopped) {
4698
- this.value = value;
4699
- this.hasValue = true;
4700
- }
4701
- },
4702
- /**
4703
- * Unsubscribe all observers and release resources.
4704
- */
4705
- dispose: function () {
4706
- this.isDisposed = true;
4707
- this.observers = null;
4708
- this.exception = null;
4709
- this.value = null;
4557
+ addProperties(AsyncSubject.prototype, Observer, {
4558
+ /**
4559
+ * Indicates whether the subject has observers subscribed to it.
4560
+ * @returns {Boolean} Indicates whether the subject has observers subscribed to it.
4561
+ */
4562
+ hasObservers: function () {
4563
+ checkDisposed.call(this);
4564
+ return this.observers.length > 0;
4565
+ },
4566
+ /**
4567
+ * Notifies all subscribed observers about the end of the sequence, also causing the last received value to be sent out (if any).
4568
+ */
4569
+ onCompleted: function () {
4570
+ var o, i, len;
4571
+ checkDisposed.call(this);
4572
+ if (!this.isStopped) {
4573
+ this.isStopped = true;
4574
+ var os = this.observers.slice(0),
4575
+ v = this.value,
4576
+ hv = this.hasValue;
4577
+
4578
+ if (hv) {
4579
+ for (i = 0, len = os.length; i < len; i++) {
4580
+ o = os[i];
4581
+ o.onNext(v);
4582
+ o.onCompleted();
4710
4583
  }
4711
- });
4712
-
4713
- return AsyncSubject;
4714
- }(Observable));
4715
-
4716
- /** @private */
4717
- var AnonymousSubject = (function (_super) {
4718
- inherits(AnonymousSubject, _super);
4584
+ } else {
4585
+ for (i = 0, len = os.length; i < len; i++) {
4586
+ os[i].onCompleted();
4587
+ }
4588
+ }
4719
4589
 
4720
- function subscribe(observer) {
4721
- return this.observable.subscribe(observer);
4590
+ this.observers = [];
4722
4591
  }
4592
+ },
4593
+ /**
4594
+ * Notifies all subscribed observers about the error.
4595
+ * @param {Mixed} error The Error to send to all observers.
4596
+ */
4597
+ onError: function (error) {
4598
+ checkDisposed.call(this);
4599
+ if (!this.isStopped) {
4600
+ var os = this.observers.slice(0);
4601
+ this.isStopped = true;
4602
+ this.exception = error;
4603
+
4604
+ for (var i = 0, len = os.length; i < len; i++) {
4605
+ os[i].onError(error);
4606
+ }
4723
4607
 
4724
- /**
4725
- * @private
4726
- * @constructor
4727
- */
4728
- function AnonymousSubject(observer, observable) {
4729
- _super.call(this, subscribe);
4730
- this.observer = observer;
4731
- this.observable = observable;
4608
+ this.observers = [];
4732
4609
  }
4610
+ },
4611
+ /**
4612
+ * Sends a value to the subject. The last value received before successful termination will be sent to all subscribed and future observers.
4613
+ * @param {Mixed} value The value to store in the subject.
4614
+ */
4615
+ onNext: function (value) {
4616
+ checkDisposed.call(this);
4617
+ if (this.isStopped) { return; }
4618
+ this.value = value;
4619
+ this.hasValue = true;
4620
+ },
4621
+ /**
4622
+ * Unsubscribe all observers and release resources.
4623
+ */
4624
+ dispose: function () {
4625
+ this.isDisposed = true;
4626
+ this.observers = null;
4627
+ this.exception = null;
4628
+ this.value = null;
4629
+ }
4630
+ });
4733
4631
 
4734
- addProperties(AnonymousSubject.prototype, Observer, {
4735
- /**
4736
- * @private
4737
- * @memberOf AnonymousSubject#
4738
- */
4739
- onCompleted: function () {
4740
- this.observer.onCompleted();
4741
- },
4742
- /**
4743
- * @private
4744
- * @memberOf AnonymousSubject#
4745
- */
4746
- onError: function (exception) {
4747
- this.observer.onError(exception);
4748
- },
4749
- /**
4750
- * @private
4751
- * @memberOf AnonymousSubject#
4752
- */
4753
- onNext: function (value) {
4754
- this.observer.onNext(value);
4755
- }
4756
- });
4757
-
4758
- return AnonymousSubject;
4759
- }(Observable));
4760
-
4761
- if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
4762
- root.Rx = Rx;
4632
+ return AsyncSubject;
4633
+ }(Observable));
4763
4634
 
4764
- define(function() {
4765
- return Rx;
4766
- });
4767
- } else if (freeExports && freeModule) {
4768
- // in Node.js or RingoJS
4769
- if (moduleExports) {
4770
- (freeModule.exports = Rx).Rx = Rx;
4771
- } else {
4772
- freeExports.Rx = Rx;
4773
- }
4774
- } else {
4775
- // in a browser or Rhino
4776
- root.Rx = Rx;
4635
+ var AnonymousSubject = Rx.AnonymousSubject = (function (__super__) {
4636
+ inherits(AnonymousSubject, __super__);
4637
+
4638
+ function AnonymousSubject(observer, observable) {
4639
+ this.observer = observer;
4640
+ this.observable = observable;
4641
+ __super__.call(this, this.observable.subscribe.bind(this.observable));
4642
+ }
4643
+
4644
+ addProperties(AnonymousSubject.prototype, Observer, {
4645
+ onCompleted: function () {
4646
+ this.observer.onCompleted();
4647
+ },
4648
+ onError: function (exception) {
4649
+ this.observer.onError(exception);
4650
+ },
4651
+ onNext: function (value) {
4652
+ this.observer.onNext(value);
4653
+ }
4654
+ });
4655
+
4656
+ return AnonymousSubject;
4657
+ }(Observable));
4658
+
4659
+ if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
4660
+ root.Rx = Rx;
4661
+
4662
+ define(function() {
4663
+ return Rx;
4664
+ });
4665
+ } else if (freeExports && freeModule) {
4666
+ // in Node.js or RingoJS
4667
+ if (moduleExports) {
4668
+ (freeModule.exports = Rx).Rx = Rx;
4669
+ } else {
4670
+ freeExports.Rx = Rx;
4671
+ }
4672
+ } else {
4673
+ // in a browser or Rhino
4674
+ root.Rx = Rx;
4777
4675
  }
4778
4676
  }.call(this));