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
 
@@ -41,7 +41,7 @@
41
41
  defaultSubComparer = Rx.helpers.defaultSubComparer = function (x, y) { return x > y ? 1 : (x < y ? -1 : 0); },
42
42
  defaultKeySerializer = Rx.helpers.defaultKeySerializer = function (x) { return x.toString(); },
43
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; },
44
+ isPromise = Rx.helpers.isPromise = function (p) { return !!p && typeof p.then === 'function'; },
45
45
  asArray = Rx.helpers.asArray = function () { return Array.prototype.slice.call(arguments); },
46
46
  not = Rx.helpers.not = function (a) { return !a; };
47
47
 
@@ -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,191 +395,169 @@
395
395
  return a;
396
396
  }
397
397
 
398
- // Collections
399
- var IndexedItem = function (id, value) {
400
- this.id = id;
401
- this.value = value;
402
- };
403
-
404
- IndexedItem.prototype.compareTo = function (other) {
405
- var c = this.value.compareTo(other.value);
406
- if (c === 0) {
407
- c = this.id - other.id;
408
- }
409
- return c;
410
- };
411
-
412
- // Priority Queue for Scheduling
413
- var PriorityQueue = Rx.internals.PriorityQueue = function (capacity) {
414
- this.items = new Array(capacity);
415
- this.length = 0;
416
- };
417
-
418
- var priorityProto = PriorityQueue.prototype;
419
- priorityProto.isHigherPriority = function (left, right) {
420
- return this.items[left].compareTo(this.items[right]) < 0;
421
- };
422
-
423
- priorityProto.percolate = function (index) {
424
- if (index >= this.length || index < 0) {
425
- return;
426
- }
427
- var parent = index - 1 >> 1;
428
- if (parent < 0 || parent === index) {
429
- return;
430
- }
431
- if (this.isHigherPriority(index, parent)) {
432
- var temp = this.items[index];
433
- this.items[index] = this.items[parent];
434
- this.items[parent] = temp;
435
- this.percolate(parent);
436
- }
437
- };
438
-
439
- priorityProto.heapify = function (index) {
440
- if (index === undefined) {
441
- index = 0;
442
- }
443
- if (index >= this.length || index < 0) {
444
- return;
445
- }
446
- var left = 2 * index + 1,
447
- right = 2 * index + 2,
448
- first = index;
449
- if (left < this.length && this.isHigherPriority(left, first)) {
450
- first = left;
451
- }
452
- if (right < this.length && this.isHigherPriority(right, first)) {
453
- first = right;
454
- }
455
- if (first !== index) {
456
- var temp = this.items[index];
457
- this.items[index] = this.items[first];
458
- this.items[first] = temp;
459
- this.heapify(first);
460
- }
461
- };
462
-
463
- priorityProto.peek = function () { return this.items[0].value; };
464
-
465
- priorityProto.removeAt = function (index) {
466
- this.items[index] = this.items[--this.length];
467
- delete this.items[this.length];
468
- this.heapify();
469
- };
470
-
471
- priorityProto.dequeue = function () {
472
- var result = this.peek();
473
- this.removeAt(0);
474
- return result;
475
- };
476
-
477
- priorityProto.enqueue = function (item) {
478
- var index = this.length++;
479
- this.items[index] = new IndexedItem(PriorityQueue.count++, item);
480
- this.percolate(index);
481
- };
482
-
483
- priorityProto.remove = function (item) {
484
- for (var i = 0; i < this.length; i++) {
485
- if (this.items[i].value === item) {
486
- this.removeAt(i);
487
- return true;
488
- }
489
- }
490
- return false;
491
- };
398
+ // Collections
399
+ var IndexedItem = function (id, value) {
400
+ this.id = id;
401
+ this.value = value;
402
+ };
403
+
404
+ IndexedItem.prototype.compareTo = function (other) {
405
+ var c = this.value.compareTo(other.value);
406
+ if (c === 0) {
407
+ c = this.id - other.id;
408
+ }
409
+ return c;
410
+ };
411
+
412
+ // Priority Queue for Scheduling
413
+ var PriorityQueue = Rx.internals.PriorityQueue = function (capacity) {
414
+ this.items = new Array(capacity);
415
+ this.length = 0;
416
+ };
417
+
418
+ var priorityProto = PriorityQueue.prototype;
419
+ priorityProto.isHigherPriority = function (left, right) {
420
+ return this.items[left].compareTo(this.items[right]) < 0;
421
+ };
422
+
423
+ priorityProto.percolate = function (index) {
424
+ if (index >= this.length || index < 0) {
425
+ return;
426
+ }
427
+ var parent = index - 1 >> 1;
428
+ if (parent < 0 || parent === index) {
429
+ return;
430
+ }
431
+ if (this.isHigherPriority(index, parent)) {
432
+ var temp = this.items[index];
433
+ this.items[index] = this.items[parent];
434
+ this.items[parent] = temp;
435
+ this.percolate(parent);
436
+ }
437
+ };
438
+
439
+ priorityProto.heapify = function (index) {
440
+ if (index === undefined) {
441
+ index = 0;
442
+ }
443
+ if (index >= this.length || index < 0) {
444
+ return;
445
+ }
446
+ var left = 2 * index + 1,
447
+ right = 2 * index + 2,
448
+ first = index;
449
+ if (left < this.length && this.isHigherPriority(left, first)) {
450
+ first = left;
451
+ }
452
+ if (right < this.length && this.isHigherPriority(right, first)) {
453
+ first = right;
454
+ }
455
+ if (first !== index) {
456
+ var temp = this.items[index];
457
+ this.items[index] = this.items[first];
458
+ this.items[first] = temp;
459
+ this.heapify(first);
460
+ }
461
+ };
462
+
463
+ priorityProto.peek = function () { return this.items[0].value; };
464
+
465
+ priorityProto.removeAt = function (index) {
466
+ this.items[index] = this.items[--this.length];
467
+ delete this.items[this.length];
468
+ this.heapify();
469
+ };
470
+
471
+ priorityProto.dequeue = function () {
472
+ var result = this.peek();
473
+ this.removeAt(0);
474
+ return result;
475
+ };
476
+
477
+ priorityProto.enqueue = function (item) {
478
+ var index = this.length++;
479
+ this.items[index] = new IndexedItem(PriorityQueue.count++, item);
480
+ this.percolate(index);
481
+ };
482
+
483
+ priorityProto.remove = function (item) {
484
+ for (var i = 0; i < this.length; i++) {
485
+ if (this.items[i].value === item) {
486
+ this.removeAt(i);
487
+ return true;
488
+ }
489
+ }
490
+ return false;
491
+ };
492
492
  PriorityQueue.count = 0;
493
- /**
494
- * Represents a group of disposable resources that are disposed together.
495
- * @constructor
496
- */
497
- var CompositeDisposable = Rx.CompositeDisposable = function () {
498
- this.disposables = argsOrArray(arguments, 0);
499
- this.isDisposed = false;
500
- this.length = this.disposables.length;
501
- };
502
-
503
- var CompositeDisposablePrototype = CompositeDisposable.prototype;
504
-
505
- /**
506
- * Adds a disposable to the CompositeDisposable or disposes the disposable if the CompositeDisposable is disposed.
507
- * @param {Mixed} item Disposable to add.
508
- */
509
- CompositeDisposablePrototype.add = function (item) {
510
- if (this.isDisposed) {
511
- item.dispose();
512
- } else {
513
- this.disposables.push(item);
514
- this.length++;
515
- }
516
- };
517
-
518
- /**
519
- * Removes and disposes the first occurrence of a disposable from the CompositeDisposable.
520
- * @param {Mixed} item Disposable to remove.
521
- * @returns {Boolean} true if found; false otherwise.
522
- */
523
- CompositeDisposablePrototype.remove = function (item) {
524
- var shouldDispose = false;
525
- if (!this.isDisposed) {
526
- var idx = this.disposables.indexOf(item);
527
- if (idx !== -1) {
528
- shouldDispose = true;
529
- this.disposables.splice(idx, 1);
530
- this.length--;
531
- item.dispose();
532
- }
533
-
534
- }
535
- return shouldDispose;
536
- };
493
+ /**
494
+ * Represents a group of disposable resources that are disposed together.
495
+ * @constructor
496
+ */
497
+ var CompositeDisposable = Rx.CompositeDisposable = function () {
498
+ this.disposables = argsOrArray(arguments, 0);
499
+ this.isDisposed = false;
500
+ this.length = this.disposables.length;
501
+ };
537
502
 
538
- /**
539
- * Disposes all disposables in the group and removes them from the group.
540
- */
541
- CompositeDisposablePrototype.dispose = function () {
542
- if (!this.isDisposed) {
543
- this.isDisposed = true;
544
- var currentDisposables = this.disposables.slice(0);
545
- this.disposables = [];
546
- this.length = 0;
503
+ var CompositeDisposablePrototype = CompositeDisposable.prototype;
547
504
 
548
- for (var i = 0, len = currentDisposables.length; i < len; i++) {
549
- currentDisposables[i].dispose();
550
- }
551
- }
552
- };
505
+ /**
506
+ * Adds a disposable to the CompositeDisposable or disposes the disposable if the CompositeDisposable is disposed.
507
+ * @param {Mixed} item Disposable to add.
508
+ */
509
+ CompositeDisposablePrototype.add = function (item) {
510
+ if (this.isDisposed) {
511
+ item.dispose();
512
+ } else {
513
+ this.disposables.push(item);
514
+ this.length++;
515
+ }
516
+ };
553
517
 
554
- /**
555
- * Removes and disposes all disposables from the CompositeDisposable, but does not dispose the CompositeDisposable.
556
- */
557
- CompositeDisposablePrototype.clear = function () {
558
- var currentDisposables = this.disposables.slice(0);
559
- this.disposables = [];
560
- this.length = 0;
561
- for (var i = 0, len = currentDisposables.length; i < len; i++) {
562
- currentDisposables[i].dispose();
563
- }
564
- };
518
+ /**
519
+ * Removes and disposes the first occurrence of a disposable from the CompositeDisposable.
520
+ * @param {Mixed} item Disposable to remove.
521
+ * @returns {Boolean} true if found; false otherwise.
522
+ */
523
+ CompositeDisposablePrototype.remove = function (item) {
524
+ var shouldDispose = false;
525
+ if (!this.isDisposed) {
526
+ var idx = this.disposables.indexOf(item);
527
+ if (idx !== -1) {
528
+ shouldDispose = true;
529
+ this.disposables.splice(idx, 1);
530
+ this.length--;
531
+ item.dispose();
532
+ }
533
+ }
534
+ return shouldDispose;
535
+ };
565
536
 
566
- /**
567
- * Determines whether the CompositeDisposable contains a specific disposable.
568
- * @param {Mixed} item Disposable to search for.
569
- * @returns {Boolean} true if the disposable was found; otherwise, false.
570
- */
571
- CompositeDisposablePrototype.contains = function (item) {
572
- return this.disposables.indexOf(item) !== -1;
573
- };
537
+ /**
538
+ * Disposes all disposables in the group and removes them from the group.
539
+ */
540
+ CompositeDisposablePrototype.dispose = function () {
541
+ if (!this.isDisposed) {
542
+ this.isDisposed = true;
543
+ var currentDisposables = this.disposables.slice(0);
544
+ this.disposables = [];
545
+ this.length = 0;
546
+
547
+ for (var i = 0, len = currentDisposables.length; i < len; i++) {
548
+ currentDisposables[i].dispose();
549
+ }
550
+ }
551
+ };
574
552
 
575
- /**
576
- * Converts the existing CompositeDisposable to an array of disposables
577
- * @returns {Array} An array of disposable objects.
578
- */
579
- CompositeDisposablePrototype.toArray = function () {
580
- return this.disposables.slice(0);
581
- };
582
-
553
+ /**
554
+ * Converts the existing CompositeDisposable to an array of disposables
555
+ * @returns {Array} An array of disposable objects.
556
+ */
557
+ CompositeDisposablePrototype.toArray = function () {
558
+ return this.disposables.slice(0);
559
+ };
560
+
583
561
  /**
584
562
  * Provides a set of static methods for creating Disposables.
585
563
  *
@@ -611,90 +589,52 @@
611
589
  */
612
590
  var disposableEmpty = Disposable.empty = { dispose: noop };
613
591
 
614
- var BooleanDisposable = (function () {
615
- function BooleanDisposable (isSingle) {
616
- this.isSingle = isSingle;
617
- this.isDisposed = false;
618
- this.current = null;
619
- }
620
-
621
- var booleanDisposablePrototype = BooleanDisposable.prototype;
622
-
623
- /**
624
- * Gets the underlying disposable.
625
- * @return The underlying disposable.
626
- */
627
- booleanDisposablePrototype.getDisposable = function () {
628
- return this.current;
629
- };
630
-
631
- /**
632
- * Sets the underlying disposable.
633
- * @param {Disposable} value The new underlying disposable.
634
- */
635
- booleanDisposablePrototype.setDisposable = function (value) {
636
- if (this.current && this.isSingle) {
637
- throw new Error('Disposable has already been assigned');
638
- }
639
-
640
- var shouldDispose = this.isDisposed, old;
641
- if (!shouldDispose) {
642
- old = this.current;
643
- this.current = value;
644
- }
645
- if (old) {
646
- old.dispose();
647
- }
648
- if (shouldDispose && value) {
649
- value.dispose();
650
- }
651
- };
652
-
653
- /**
654
- * Disposes the underlying disposable as well as all future replacements.
655
- */
656
- booleanDisposablePrototype.dispose = function () {
657
- var old;
658
- if (!this.isDisposed) {
659
- this.isDisposed = true;
660
- old = this.current;
661
- this.current = null;
662
- }
663
- if (old) {
664
- old.dispose();
665
- }
666
- };
592
+ var SingleAssignmentDisposable = Rx.SingleAssignmentDisposable =
593
+ SerialDisposable = Rx.SerialDisposable = (function () {
594
+ function BooleanDisposable () {
595
+ this.isDisposed = false;
596
+ this.current = null;
597
+ }
667
598
 
668
- return BooleanDisposable;
669
- }());
599
+ var booleanDisposablePrototype = BooleanDisposable.prototype;
670
600
 
671
601
  /**
672
- * Represents a disposable resource which only allows a single assignment of its underlying disposable resource.
673
- * If an underlying disposable resource has already been set, future attempts to set the underlying disposable resource will throw an Error.
602
+ * Gets the underlying disposable.
603
+ * @return The underlying disposable.
674
604
  */
675
- var SingleAssignmentDisposable = Rx.SingleAssignmentDisposable = (function (super_) {
676
- inherits(SingleAssignmentDisposable, super_);
677
-
678
- function SingleAssignmentDisposable() {
679
- super_.call(this, true);
680
- }
681
-
682
- return SingleAssignmentDisposable;
683
- }(BooleanDisposable));
605
+ booleanDisposablePrototype.getDisposable = function () {
606
+ return this.current;
607
+ };
684
608
 
685
609
  /**
686
- * Represents a disposable resource whose underlying disposable resource can be replaced by another disposable resource, causing automatic disposal of the previous underlying disposable resource.
687
- */
688
- var SerialDisposable = Rx.SerialDisposable = (function (super_) {
689
- inherits(SerialDisposable, super_);
690
-
691
- function SerialDisposable() {
692
- super_.call(this, false);
693
- }
610
+ * Sets the underlying disposable.
611
+ * @param {Disposable} value The new underlying disposable.
612
+ */
613
+ booleanDisposablePrototype.setDisposable = function (value) {
614
+ var shouldDispose = this.isDisposed, old;
615
+ if (!shouldDispose) {
616
+ old = this.current;
617
+ this.current = value;
618
+ }
619
+ old && old.dispose();
620
+ shouldDispose && value && value.dispose();
621
+ };
694
622
 
695
- return SerialDisposable;
696
- }(BooleanDisposable));
623
+ /**
624
+ * Disposes the underlying disposable as well as all future replacements.
625
+ */
626
+ booleanDisposablePrototype.dispose = function () {
627
+ var old;
628
+ if (!this.isDisposed) {
629
+ this.isDisposed = true;
630
+ old = this.current;
631
+ this.current = null;
632
+ }
633
+ old && old.dispose();
634
+ };
697
635
 
636
+ return BooleanDisposable;
637
+ }());
698
638
  /**
699
639
  * Represents a disposable resource that only disposes its underlying disposable resource when all dependent disposable objects have been disposed.
700
640
  */
@@ -757,423 +697,460 @@
757
697
  return RefCountDisposable;
758
698
  })();
759
699
 
760
- function ScheduledDisposable(scheduler, disposable) {
761
- this.scheduler = scheduler;
762
- this.disposable = disposable;
763
- this.isDisposed = false;
700
+ function ScheduledDisposable(scheduler, disposable) {
701
+ this.scheduler = scheduler;
702
+ this.disposable = disposable;
703
+ this.isDisposed = false;
704
+ }
705
+
706
+ ScheduledDisposable.prototype.dispose = function () {
707
+ var parent = this;
708
+ this.scheduler.schedule(function () {
709
+ if (!parent.isDisposed) {
710
+ parent.isDisposed = true;
711
+ parent.disposable.dispose();
712
+ }
713
+ });
714
+ };
715
+
716
+ var ScheduledItem = Rx.internals.ScheduledItem = function (scheduler, state, action, dueTime, comparer) {
717
+ this.scheduler = scheduler;
718
+ this.state = state;
719
+ this.action = action;
720
+ this.dueTime = dueTime;
721
+ this.comparer = comparer || defaultSubComparer;
722
+ this.disposable = new SingleAssignmentDisposable();
723
+ }
724
+
725
+ ScheduledItem.prototype.invoke = function () {
726
+ this.disposable.setDisposable(this.invokeCore());
727
+ };
728
+
729
+ ScheduledItem.prototype.compareTo = function (other) {
730
+ return this.comparer(this.dueTime, other.dueTime);
731
+ };
732
+
733
+ ScheduledItem.prototype.isCancelled = function () {
734
+ return this.disposable.isDisposed;
735
+ };
736
+
737
+ ScheduledItem.prototype.invokeCore = function () {
738
+ return this.action(this.scheduler, this.state);
739
+ };
740
+
741
+ /** Provides a set of static properties to access commonly used schedulers. */
742
+ var Scheduler = Rx.Scheduler = (function () {
743
+
744
+ function Scheduler(now, schedule, scheduleRelative, scheduleAbsolute) {
745
+ this.now = now;
746
+ this._schedule = schedule;
747
+ this._scheduleRelative = scheduleRelative;
748
+ this._scheduleAbsolute = scheduleAbsolute;
764
749
  }
765
750
 
766
- ScheduledDisposable.prototype.dispose = function () {
767
- var parent = this;
768
- this.scheduler.schedule(function () {
769
- if (!parent.isDisposed) {
770
- parent.isDisposed = true;
771
- parent.disposable.dispose();
751
+ function invokeRecImmediate(scheduler, pair) {
752
+ var state = pair.first, action = pair.second, group = new CompositeDisposable(),
753
+ recursiveAction = function (state1) {
754
+ action(state1, function (state2) {
755
+ var isAdded = false, isDone = false,
756
+ d = scheduler.scheduleWithState(state2, function (scheduler1, state3) {
757
+ if (isAdded) {
758
+ group.remove(d);
759
+ } else {
760
+ isDone = true;
772
761
  }
762
+ recursiveAction(state3);
763
+ return disposableEmpty;
764
+ });
765
+ if (!isDone) {
766
+ group.add(d);
767
+ isAdded = true;
768
+ }
773
769
  });
774
- };
770
+ };
771
+ recursiveAction(state);
772
+ return group;
773
+ }
775
774
 
776
- var ScheduledItem = Rx.internals.ScheduledItem = function (scheduler, state, action, dueTime, comparer) {
777
- this.scheduler = scheduler;
778
- this.state = state;
779
- this.action = action;
780
- this.dueTime = dueTime;
781
- this.comparer = comparer || defaultSubComparer;
782
- this.disposable = new SingleAssignmentDisposable();
775
+ function invokeRecDate(scheduler, pair, method) {
776
+ var state = pair.first, action = pair.second, group = new CompositeDisposable(),
777
+ recursiveAction = function (state1) {
778
+ action(state1, function (state2, dueTime1) {
779
+ var isAdded = false, isDone = false,
780
+ d = scheduler[method].call(scheduler, state2, dueTime1, function (scheduler1, state3) {
781
+ if (isAdded) {
782
+ group.remove(d);
783
+ } else {
784
+ isDone = true;
785
+ }
786
+ recursiveAction(state3);
787
+ return disposableEmpty;
788
+ });
789
+ if (!isDone) {
790
+ group.add(d);
791
+ isAdded = true;
792
+ }
793
+ });
794
+ };
795
+ recursiveAction(state);
796
+ return group;
783
797
  }
784
798
 
785
- ScheduledItem.prototype.invoke = function () {
786
- this.disposable.setDisposable(this.invokeCore());
787
- };
799
+ function invokeAction(scheduler, action) {
800
+ action();
801
+ return disposableEmpty;
802
+ }
788
803
 
789
- ScheduledItem.prototype.compareTo = function (other) {
790
- return this.comparer(this.dueTime, other.dueTime);
791
- };
804
+ var schedulerProto = Scheduler.prototype;
792
805
 
793
- ScheduledItem.prototype.isCancelled = function () {
794
- return this.disposable.isDisposed;
806
+ /**
807
+ * Schedules an action to be executed.
808
+ * @param {Function} action Action to execute.
809
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
810
+ */
811
+ schedulerProto.schedule = function (action) {
812
+ return this._schedule(action, invokeAction);
795
813
  };
796
814
 
797
- ScheduledItem.prototype.invokeCore = function () {
798
- return this.action(this.scheduler, this.state);
815
+ /**
816
+ * Schedules an action to be executed.
817
+ * @param state State passed to the action to be executed.
818
+ * @param {Function} action Action to be executed.
819
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
820
+ */
821
+ schedulerProto.scheduleWithState = function (state, action) {
822
+ return this._schedule(state, action);
799
823
  };
800
824
 
801
- /** Provides a set of static properties to access commonly used schedulers. */
802
- var Scheduler = Rx.Scheduler = (function () {
803
-
804
- /**
805
- * @constructor
806
- * @private
807
- */
808
- function Scheduler(now, schedule, scheduleRelative, scheduleAbsolute) {
809
- this.now = now;
810
- this._schedule = schedule;
811
- this._scheduleRelative = scheduleRelative;
812
- this._scheduleAbsolute = scheduleAbsolute;
813
- }
814
-
815
- function invokeRecImmediate(scheduler, pair) {
816
- var state = pair.first, action = pair.second, group = new CompositeDisposable(),
817
- recursiveAction = function (state1) {
818
- action(state1, function (state2) {
819
- var isAdded = false, isDone = false,
820
- d = scheduler.scheduleWithState(state2, function (scheduler1, state3) {
821
- if (isAdded) {
822
- group.remove(d);
823
- } else {
824
- isDone = true;
825
- }
826
- recursiveAction(state3);
827
- return disposableEmpty;
828
- });
829
- if (!isDone) {
830
- group.add(d);
831
- isAdded = true;
832
- }
833
- });
834
- };
835
- recursiveAction(state);
836
- return group;
837
- }
838
-
839
- function invokeRecDate(scheduler, pair, method) {
840
- var state = pair.first, action = pair.second, group = new CompositeDisposable(),
841
- recursiveAction = function (state1) {
842
- action(state1, function (state2, dueTime1) {
843
- var isAdded = false, isDone = false,
844
- d = scheduler[method].call(scheduler, state2, dueTime1, function (scheduler1, state3) {
845
- if (isAdded) {
846
- group.remove(d);
847
- } else {
848
- isDone = true;
849
- }
850
- recursiveAction(state3);
851
- return disposableEmpty;
852
- });
853
- if (!isDone) {
854
- group.add(d);
855
- isAdded = true;
856
- }
857
- });
858
- };
859
- recursiveAction(state);
860
- return group;
861
- }
862
-
863
- function invokeAction(scheduler, action) {
864
- action();
865
- return disposableEmpty;
866
- }
867
-
868
- var schedulerProto = Scheduler.prototype;
825
+ /**
826
+ * Schedules an action to be executed after the specified relative due time.
827
+ * @param {Function} action Action to execute.
828
+ * @param {Number} dueTime Relative time after which to execute the action.
829
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
830
+ */
831
+ schedulerProto.scheduleWithRelative = function (dueTime, action) {
832
+ return this._scheduleRelative(action, dueTime, invokeAction);
833
+ };
869
834
 
870
- /**
871
- * Returns a scheduler that wraps the original scheduler, adding exception handling for scheduled actions.
872
- * @param {Function} handler Handler that's run if an exception is caught. The exception will be rethrown if the handler returns false.
873
- * @returns {Scheduler} Wrapper around the original scheduler, enforcing exception handling.
874
- */
875
- schedulerProto.catchException = schedulerProto['catch'] = function (handler) {
876
- return new CatchScheduler(this, handler);
877
- };
878
-
879
- /**
880
- * 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.
881
- * @param {Number} period Period for running the work periodically.
882
- * @param {Function} action Action to be executed.
883
- * @returns {Disposable} The disposable object used to cancel the scheduled recurring action (best effort).
884
- */
885
- schedulerProto.schedulePeriodic = function (period, action) {
886
- return this.schedulePeriodicWithState(null, period, function () {
887
- action();
888
- });
889
- };
835
+ /**
836
+ * Schedules an action to be executed after dueTime.
837
+ * @param state State passed to the action to be executed.
838
+ * @param {Function} action Action to be executed.
839
+ * @param {Number} dueTime Relative time after which to execute the action.
840
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
841
+ */
842
+ schedulerProto.scheduleWithRelativeAndState = function (state, dueTime, action) {
843
+ return this._scheduleRelative(state, dueTime, action);
844
+ };
890
845
 
891
- /**
892
- * 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.
893
- * @param {Mixed} state Initial state passed to the action upon the first iteration.
894
- * @param {Number} period Period for running the work periodically.
895
- * @param {Function} action Action to be executed, potentially updating the state.
896
- * @returns {Disposable} The disposable object used to cancel the scheduled recurring action (best effort).
897
- */
898
- schedulerProto.schedulePeriodicWithState = function (state, period, action) {
899
- var s = state, id = setInterval(function () {
900
- s = action(s);
901
- }, period);
902
- return disposableCreate(function () {
903
- clearInterval(id);
904
- });
905
- };
846
+ /**
847
+ * Schedules an action to be executed at the specified absolute due time.
848
+ * @param {Function} action Action to execute.
849
+ * @param {Number} dueTime Absolute time at which to execute the action.
850
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
851
+ */
852
+ schedulerProto.scheduleWithAbsolute = function (dueTime, action) {
853
+ return this._scheduleAbsolute(action, dueTime, invokeAction);
854
+ };
906
855
 
907
- /**
908
- * Schedules an action to be executed.
909
- * @param {Function} action Action to execute.
910
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
911
- */
912
- schedulerProto.schedule = function (action) {
913
- return this._schedule(action, invokeAction);
914
- };
856
+ /**
857
+ * Schedules an action to be executed at dueTime.
858
+ * @param {Mixed} state State passed to the action to be executed.
859
+ * @param {Function} action Action to be executed.
860
+ * @param {Number}dueTime Absolute time at which to execute the action.
861
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
862
+ */
863
+ schedulerProto.scheduleWithAbsoluteAndState = function (state, dueTime, action) {
864
+ return this._scheduleAbsolute(state, dueTime, action);
865
+ };
915
866
 
916
- /**
917
- * Schedules an action to be executed.
918
- * @param state State passed to the action to be executed.
919
- * @param {Function} action Action to be executed.
920
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
921
- */
922
- schedulerProto.scheduleWithState = function (state, action) {
923
- return this._schedule(state, action);
924
- };
867
+ /** Gets the current time according to the local machine's system clock. */
868
+ Scheduler.now = defaultNow;
925
869
 
926
- /**
927
- * Schedules an action to be executed after the specified relative due time.
928
- * @param {Function} action Action to execute.
929
- * @param {Number} dueTime Relative time after which to execute the action.
930
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
931
- */
932
- schedulerProto.scheduleWithRelative = function (dueTime, action) {
933
- return this._scheduleRelative(action, dueTime, invokeAction);
934
- };
870
+ /**
871
+ * Normalizes the specified TimeSpan value to a positive value.
872
+ * @param {Number} timeSpan The time span value to normalize.
873
+ * @returns {Number} The specified TimeSpan value if it is zero or positive; otherwise, 0
874
+ */
875
+ Scheduler.normalize = function (timeSpan) {
876
+ timeSpan < 0 && (timeSpan = 0);
877
+ return timeSpan;
878
+ };
935
879
 
936
- /**
937
- * Schedules an action to be executed after dueTime.
938
- * @param state State passed to the action to be executed.
939
- * @param {Function} action Action to be executed.
940
- * @param {Number} dueTime Relative time after which to execute the action.
941
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
942
- */
943
- schedulerProto.scheduleWithRelativeAndState = function (state, dueTime, action) {
944
- return this._scheduleRelative(state, dueTime, action);
945
- };
880
+ return Scheduler;
881
+ }());
946
882
 
947
- /**
948
- * Schedules an action to be executed at the specified absolute due time.
949
- * @param {Function} action Action to execute.
950
- * @param {Number} dueTime Absolute time at which to execute the action.
951
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
952
- */
953
- schedulerProto.scheduleWithAbsolute = function (dueTime, action) {
954
- return this._scheduleAbsolute(action, dueTime, invokeAction);
955
- };
883
+ var normalizeTime = Scheduler.normalize;
884
+
885
+ (function (schedulerProto) {
886
+ function invokeRecImmediate(scheduler, pair) {
887
+ var state = pair.first, action = pair.second, group = new CompositeDisposable(),
888
+ recursiveAction = function (state1) {
889
+ action(state1, function (state2) {
890
+ var isAdded = false, isDone = false,
891
+ d = scheduler.scheduleWithState(state2, function (scheduler1, state3) {
892
+ if (isAdded) {
893
+ group.remove(d);
894
+ } else {
895
+ isDone = true;
896
+ }
897
+ recursiveAction(state3);
898
+ return disposableEmpty;
899
+ });
900
+ if (!isDone) {
901
+ group.add(d);
902
+ isAdded = true;
903
+ }
904
+ });
905
+ };
906
+ recursiveAction(state);
907
+ return group;
908
+ }
956
909
 
957
- /**
958
- * Schedules an action to be executed at dueTime.
959
- * @param {Mixed} state State passed to the action to be executed.
960
- * @param {Function} action Action to be executed.
961
- * @param {Number}dueTime Absolute time at which to execute the action.
962
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
963
- */
964
- schedulerProto.scheduleWithAbsoluteAndState = function (state, dueTime, action) {
965
- return this._scheduleAbsolute(state, dueTime, action);
966
- };
910
+ function invokeRecDate(scheduler, pair, method) {
911
+ var state = pair.first, action = pair.second, group = new CompositeDisposable(),
912
+ recursiveAction = function (state1) {
913
+ action(state1, function (state2, dueTime1) {
914
+ var isAdded = false, isDone = false,
915
+ d = scheduler[method].call(scheduler, state2, dueTime1, function (scheduler1, state3) {
916
+ if (isAdded) {
917
+ group.remove(d);
918
+ } else {
919
+ isDone = true;
920
+ }
921
+ recursiveAction(state3);
922
+ return disposableEmpty;
923
+ });
924
+ if (!isDone) {
925
+ group.add(d);
926
+ isAdded = true;
927
+ }
928
+ });
929
+ };
930
+ recursiveAction(state);
931
+ return group;
932
+ }
967
933
 
968
- /**
969
- * Schedules an action to be executed recursively.
970
- * @param {Function} action Action to execute recursively. The parameter passed to the action is used to trigger recursive scheduling of the action.
971
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
972
- */
973
- schedulerProto.scheduleRecursive = function (action) {
974
- return this.scheduleRecursiveWithState(action, function (_action, self) {
975
- _action(function () {
976
- self(_action);
977
- });
978
- });
979
- };
934
+ function scheduleInnerRecursive(action, self) {
935
+ action(function(dt) { self(action, dt); });
936
+ }
980
937
 
981
- /**
982
- * Schedules an action to be executed recursively.
983
- * @param {Mixed} state State passed to the action to be executed.
984
- * @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.
985
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
986
- */
987
- schedulerProto.scheduleRecursiveWithState = function (state, action) {
988
- return this.scheduleWithState({ first: state, second: action }, function (s, p) {
989
- return invokeRecImmediate(s, p);
990
- });
991
- };
938
+ /**
939
+ * Schedules an action to be executed recursively.
940
+ * @param {Function} action Action to execute recursively. The parameter passed to the action is used to trigger recursive scheduling of the action.
941
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
942
+ */
943
+ schedulerProto.scheduleRecursive = function (action) {
944
+ return this.scheduleRecursiveWithState(action, function (_action, self) {
945
+ _action(function () { self(_action); }); });
946
+ };
992
947
 
993
- /**
994
- * Schedules an action to be executed recursively after a specified relative due time.
995
- * @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.
996
- * @param {Number}dueTime Relative time after which to execute the action for the first time.
997
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
998
- */
999
- schedulerProto.scheduleRecursiveWithRelative = function (dueTime, action) {
1000
- return this.scheduleRecursiveWithRelativeAndState(action, dueTime, function (_action, self) {
1001
- _action(function (dt) {
1002
- self(_action, dt);
1003
- });
1004
- });
1005
- };
948
+ /**
949
+ * Schedules an action to be executed recursively.
950
+ * @param {Mixed} state State passed to the action to be executed.
951
+ * @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.
952
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
953
+ */
954
+ schedulerProto.scheduleRecursiveWithState = function (state, action) {
955
+ return this.scheduleWithState({ first: state, second: action }, invokeRecImmediate);
956
+ };
1006
957
 
1007
- /**
1008
- * Schedules an action to be executed recursively after a specified relative due time.
1009
- * @param {Mixed} state State passed to the action to be executed.
1010
- * @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.
1011
- * @param {Number}dueTime Relative time after which to execute the action for the first time.
1012
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1013
- */
1014
- schedulerProto.scheduleRecursiveWithRelativeAndState = function (state, dueTime, action) {
1015
- return this._scheduleRelative({ first: state, second: action }, dueTime, function (s, p) {
1016
- return invokeRecDate(s, p, 'scheduleWithRelativeAndState');
1017
- });
1018
- };
958
+ /**
959
+ * Schedules an action to be executed recursively after a specified relative due time.
960
+ * @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.
961
+ * @param {Number}dueTime Relative time after which to execute the action for the first time.
962
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
963
+ */
964
+ schedulerProto.scheduleRecursiveWithRelative = function (dueTime, action) {
965
+ return this.scheduleRecursiveWithRelativeAndState(action, dueTime, scheduleInnerRecursive);
966
+ };
1019
967
 
1020
- /**
1021
- * Schedules an action to be executed recursively at a specified absolute due time.
1022
- * @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.
1023
- * @param {Number}dueTime Absolute time at which to execute the action for the first time.
1024
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1025
- */
1026
- schedulerProto.scheduleRecursiveWithAbsolute = function (dueTime, action) {
1027
- return this.scheduleRecursiveWithAbsoluteAndState(action, dueTime, function (_action, self) {
1028
- _action(function (dt) {
1029
- self(_action, dt);
1030
- });
1031
- });
1032
- };
968
+ /**
969
+ * Schedules an action to be executed recursively after a specified relative due time.
970
+ * @param {Mixed} state State passed to the action to be executed.
971
+ * @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.
972
+ * @param {Number}dueTime Relative time after which to execute the action for the first time.
973
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
974
+ */
975
+ schedulerProto.scheduleRecursiveWithRelativeAndState = function (state, dueTime, action) {
976
+ return this._scheduleRelative({ first: state, second: action }, dueTime, function (s, p) {
977
+ return invokeRecDate(s, p, 'scheduleWithRelativeAndState');
978
+ });
979
+ };
1033
980
 
1034
- /**
1035
- * Schedules an action to be executed recursively at a specified absolute due time.
1036
- * @param {Mixed} state State passed to the action to be executed.
1037
- * @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.
1038
- * @param {Number}dueTime Absolute time at which to execute the action for the first time.
1039
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
1040
- */
1041
- schedulerProto.scheduleRecursiveWithAbsoluteAndState = function (state, dueTime, action) {
1042
- return this._scheduleAbsolute({ first: state, second: action }, dueTime, function (s, p) {
1043
- return invokeRecDate(s, p, 'scheduleWithAbsoluteAndState');
1044
- });
1045
- };
981
+ /**
982
+ * Schedules an action to be executed recursively at a specified absolute due time.
983
+ * @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.
984
+ * @param {Number}dueTime Absolute time at which to execute the action for the first time.
985
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
986
+ */
987
+ schedulerProto.scheduleRecursiveWithAbsolute = function (dueTime, action) {
988
+ return this.scheduleRecursiveWithAbsoluteAndState(action, dueTime, scheduleInnerRecursive);
989
+ };
1046
990
 
1047
- /** Gets the current time according to the local machine's system clock. */
1048
- Scheduler.now = defaultNow;
991
+ /**
992
+ * Schedules an action to be executed recursively at a specified absolute due time.
993
+ * @param {Mixed} state State passed to the action to be executed.
994
+ * @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.
995
+ * @param {Number}dueTime Absolute time at which to execute the action for the first time.
996
+ * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
997
+ */
998
+ schedulerProto.scheduleRecursiveWithAbsoluteAndState = function (state, dueTime, action) {
999
+ return this._scheduleAbsolute({ first: state, second: action }, dueTime, function (s, p) {
1000
+ return invokeRecDate(s, p, 'scheduleWithAbsoluteAndState');
1001
+ });
1002
+ };
1003
+ }(Scheduler.prototype));
1049
1004
 
1050
- /**
1051
- * Normalizes the specified TimeSpan value to a positive value.
1052
- * @param {Number} timeSpan The time span value to normalize.
1053
- * @returns {Number} The specified TimeSpan value if it is zero or positive; otherwise, 0
1054
- */
1055
- Scheduler.normalize = function (timeSpan) {
1056
- if (timeSpan < 0) {
1057
- timeSpan = 0;
1058
- }
1059
- return timeSpan;
1060
- };
1005
+ (function (schedulerProto) {
1006
+ /**
1007
+ * 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.
1008
+ * @param {Number} period Period for running the work periodically.
1009
+ * @param {Function} action Action to be executed.
1010
+ * @returns {Disposable} The disposable object used to cancel the scheduled recurring action (best effort).
1011
+ */
1012
+ Scheduler.prototype.schedulePeriodic = function (period, action) {
1013
+ return this.schedulePeriodicWithState(null, period, action);
1014
+ };
1061
1015
 
1062
- return Scheduler;
1063
- }());
1016
+ /**
1017
+ * 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.
1018
+ * @param {Mixed} state Initial state passed to the action upon the first iteration.
1019
+ * @param {Number} period Period for running the work periodically.
1020
+ * @param {Function} action Action to be executed, potentially updating the state.
1021
+ * @returns {Disposable} The disposable object used to cancel the scheduled recurring action (best effort).
1022
+ */
1023
+ Scheduler.prototype.schedulePeriodicWithState = function (state, period, action) {
1024
+ var s = state;
1025
+
1026
+ var id = setInterval(function () {
1027
+ s = action(s);
1028
+ }, period);
1064
1029
 
1065
- var normalizeTime = Scheduler.normalize;
1066
-
1067
- var SchedulePeriodicRecursive = Rx.internals.SchedulePeriodicRecursive = (function () {
1068
- function tick(command, recurse) {
1069
- recurse(0, this._period);
1070
- try {
1071
- this._state = this._action(this._state);
1072
- } catch (e) {
1073
- this._cancel.dispose();
1074
- throw e;
1075
- }
1076
- }
1030
+ return disposableCreate(function () {
1031
+ clearInterval(id);
1032
+ });
1033
+ };
1034
+ }(Scheduler.prototype));
1035
+
1036
+ (function (schedulerProto) {
1037
+ /**
1038
+ * Returns a scheduler that wraps the original scheduler, adding exception handling for scheduled actions.
1039
+ * @param {Function} handler Handler that's run if an exception is caught. The exception will be rethrown if the handler returns false.
1040
+ * @returns {Scheduler} Wrapper around the original scheduler, enforcing exception handling.
1041
+ */
1042
+ schedulerProto.catchError = schedulerProto['catch'] = function (handler) {
1043
+ return new CatchScheduler(this, handler);
1044
+ };
1045
+ }(Scheduler.prototype));
1046
+
1047
+ var SchedulePeriodicRecursive = Rx.internals.SchedulePeriodicRecursive = (function () {
1048
+ function tick(command, recurse) {
1049
+ recurse(0, this._period);
1050
+ try {
1051
+ this._state = this._action(this._state);
1052
+ } catch (e) {
1053
+ this._cancel.dispose();
1054
+ throw e;
1055
+ }
1056
+ }
1057
+
1058
+ function SchedulePeriodicRecursive(scheduler, state, period, action) {
1059
+ this._scheduler = scheduler;
1060
+ this._state = state;
1061
+ this._period = period;
1062
+ this._action = action;
1063
+ }
1064
+
1065
+ SchedulePeriodicRecursive.prototype.start = function () {
1066
+ var d = new SingleAssignmentDisposable();
1067
+ this._cancel = d;
1068
+ d.setDisposable(this._scheduler.scheduleRecursiveWithRelativeAndState(0, this._period, tick.bind(this)));
1069
+
1070
+ return d;
1071
+ };
1072
+
1073
+ return SchedulePeriodicRecursive;
1074
+ }());
1075
+
1076
+ /**
1077
+ * Gets a scheduler that schedules work immediately on the current thread.
1078
+ */
1079
+ var immediateScheduler = Scheduler.immediate = (function () {
1080
+
1081
+ function scheduleNow(state, action) { return action(this, state); }
1082
+
1083
+ function scheduleRelative(state, dueTime, action) {
1084
+ var dt = normalizeTime(dt);
1085
+ while (dt - this.now() > 0) { }
1086
+ return action(this, state);
1087
+ }
1088
+
1089
+ function scheduleAbsolute(state, dueTime, action) {
1090
+ return this.scheduleWithRelativeAndState(state, dueTime - this.now(), action);
1091
+ }
1092
+
1093
+ return new Scheduler(defaultNow, scheduleNow, scheduleRelative, scheduleAbsolute);
1094
+ }());
1077
1095
 
1078
- function SchedulePeriodicRecursive(scheduler, state, period, action) {
1079
- this._scheduler = scheduler;
1080
- this._state = state;
1081
- this._period = period;
1082
- this._action = action;
1096
+ /**
1097
+ * Gets a scheduler that schedules work as soon as possible on the current thread.
1098
+ */
1099
+ var currentThreadScheduler = Scheduler.currentThread = (function () {
1100
+ var queue;
1101
+
1102
+ function runTrampoline (q) {
1103
+ var item;
1104
+ while (q.length > 0) {
1105
+ item = q.dequeue();
1106
+ if (!item.isCancelled()) {
1107
+ // Note, do not schedule blocking work!
1108
+ while (item.dueTime - Scheduler.now() > 0) {
1109
+ }
1110
+ if (!item.isCancelled()) {
1111
+ item.invoke();
1112
+ }
1083
1113
  }
1114
+ }
1115
+ }
1084
1116
 
1085
- SchedulePeriodicRecursive.prototype.start = function () {
1086
- var d = new SingleAssignmentDisposable();
1087
- this._cancel = d;
1088
- d.setDisposable(this._scheduler.scheduleRecursiveWithRelativeAndState(0, this._period, tick.bind(this)));
1089
-
1090
- return d;
1091
- };
1092
-
1093
- return SchedulePeriodicRecursive;
1094
- }());
1095
-
1096
- /**
1097
- * Gets a scheduler that schedules work immediately on the current thread.
1098
- */
1099
- var immediateScheduler = Scheduler.immediate = (function () {
1100
-
1101
- function scheduleNow(state, action) { return action(this, state); }
1117
+ function scheduleNow(state, action) {
1118
+ return this.scheduleWithRelativeAndState(state, 0, action);
1119
+ }
1102
1120
 
1103
1121
  function scheduleRelative(state, dueTime, action) {
1104
- var dt = normalizeTime(dt);
1105
- while (dt - this.now() > 0) { }
1106
- return action(this, state);
1122
+ var dt = this.now() + Scheduler.normalize(dueTime),
1123
+ si = new ScheduledItem(this, state, action, dt);
1124
+
1125
+ if (!queue) {
1126
+ queue = new PriorityQueue(4);
1127
+ queue.enqueue(si);
1128
+ try {
1129
+ runTrampoline(queue);
1130
+ } catch (e) {
1131
+ throw e;
1132
+ } finally {
1133
+ queue = null;
1134
+ }
1135
+ } else {
1136
+ queue.enqueue(si);
1137
+ }
1138
+ return si.disposable;
1107
1139
  }
1108
1140
 
1109
1141
  function scheduleAbsolute(state, dueTime, action) {
1110
1142
  return this.scheduleWithRelativeAndState(state, dueTime - this.now(), action);
1111
1143
  }
1112
1144
 
1113
- return new Scheduler(defaultNow, scheduleNow, scheduleRelative, scheduleAbsolute);
1114
- }());
1115
-
1116
- /**
1117
- * Gets a scheduler that schedules work as soon as possible on the current thread.
1118
- */
1119
- var currentThreadScheduler = Scheduler.currentThread = (function () {
1120
- var queue;
1121
-
1122
- function runTrampoline (q) {
1123
- var item;
1124
- while (q.length > 0) {
1125
- item = q.dequeue();
1126
- if (!item.isCancelled()) {
1127
- // Note, do not schedule blocking work!
1128
- while (item.dueTime - Scheduler.now() > 0) {
1129
- }
1130
- if (!item.isCancelled()) {
1131
- item.invoke();
1132
- }
1133
- }
1134
- }
1135
- }
1136
-
1137
- function scheduleNow(state, action) {
1138
- return this.scheduleWithRelativeAndState(state, 0, action);
1139
- }
1140
-
1141
- function scheduleRelative(state, dueTime, action) {
1142
- var dt = this.now() + Scheduler.normalize(dueTime),
1143
- si = new ScheduledItem(this, state, action, dt),
1144
- t;
1145
- if (!queue) {
1146
- queue = new PriorityQueue(4);
1147
- queue.enqueue(si);
1148
- try {
1149
- runTrampoline(queue);
1150
- } catch (e) {
1151
- throw e;
1152
- } finally {
1153
- queue = null;
1154
- }
1155
- } else {
1156
- queue.enqueue(si);
1157
- }
1158
- return si.disposable;
1159
- }
1160
-
1161
- function scheduleAbsolute(state, dueTime, action) {
1162
- return this.scheduleWithRelativeAndState(state, dueTime - this.now(), action);
1163
- }
1164
-
1165
- var currentScheduler = new Scheduler(defaultNow, scheduleNow, scheduleRelative, scheduleAbsolute);
1166
- currentScheduler.scheduleRequired = function () { return queue === null; };
1167
- currentScheduler.ensureTrampoline = function (action) {
1168
- if (queue === null) {
1169
- return this.schedule(action);
1170
- } else {
1171
- return action();
1172
- }
1173
- };
1145
+ var currentScheduler = new Scheduler(defaultNow, scheduleNow, scheduleRelative, scheduleAbsolute);
1146
+
1147
+ currentScheduler.scheduleRequired = function () { return !queue; };
1148
+ currentScheduler.ensureTrampoline = function (action) {
1149
+ if (!queue) { this.schedule(action); } else { action(); }
1150
+ };
1174
1151
 
1175
- return currentScheduler;
1176
- }());
1152
+ return currentScheduler;
1153
+ }());
1177
1154
 
1178
1155
 
1179
1156
  var scheduleMethod, clearMethod = noop;
@@ -1501,150 +1478,150 @@
1501
1478
  };
1502
1479
  }());
1503
1480
 
1504
- var Enumerator = Rx.internals.Enumerator = function (next) {
1505
- this._next = next;
1506
- };
1507
-
1508
- Enumerator.prototype.next = function () {
1509
- return this._next();
1510
- };
1511
-
1512
- Enumerator.prototype[$iterator$] = function () { return this; }
1513
-
1514
- var Enumerable = Rx.internals.Enumerable = function (iterator) {
1515
- this._iterator = iterator;
1516
- };
1517
-
1518
- Enumerable.prototype[$iterator$] = function () {
1519
- return this._iterator();
1520
- };
1521
-
1522
- Enumerable.prototype.concat = function () {
1523
- var sources = this;
1524
- return new AnonymousObservable(function (observer) {
1525
- var e;
1526
- try {
1527
- e = sources[$iterator$]();
1528
- } catch(err) {
1529
- observer.onError();
1530
- return;
1531
- }
1532
-
1533
- var isDisposed,
1534
- subscription = new SerialDisposable();
1535
- var cancelable = immediateScheduler.scheduleRecursive(function (self) {
1536
- var currentItem;
1537
- if (isDisposed) { return; }
1538
-
1539
- try {
1540
- currentItem = e.next();
1541
- } catch (ex) {
1542
- observer.onError(ex);
1543
- return;
1544
- }
1545
-
1546
- if (currentItem.done) {
1547
- observer.onCompleted();
1548
- return;
1549
- }
1550
-
1551
- // Check if promise
1552
- var currentValue = currentItem.value;
1553
- isPromise(currentValue) && (currentValue = observableFromPromise(currentValue));
1554
-
1555
- var d = new SingleAssignmentDisposable();
1556
- subscription.setDisposable(d);
1557
- d.setDisposable(currentValue.subscribe(
1558
- observer.onNext.bind(observer),
1559
- observer.onError.bind(observer),
1560
- function () { self(); })
1561
- );
1562
- });
1563
-
1564
- return new CompositeDisposable(subscription, cancelable, disposableCreate(function () {
1565
- isDisposed = true;
1566
- }));
1567
- });
1568
- };
1569
-
1570
- Enumerable.prototype.catchException = function () {
1571
- var sources = this;
1572
- return new AnonymousObservable(function (observer) {
1573
- var e;
1574
- try {
1575
- e = sources[$iterator$]();
1576
- } catch(err) {
1577
- observer.onError();
1578
- return;
1579
- }
1580
-
1581
- var isDisposed,
1582
- lastException,
1583
- subscription = new SerialDisposable();
1584
- var cancelable = immediateScheduler.scheduleRecursive(function (self) {
1585
- if (isDisposed) { return; }
1586
-
1587
- var currentItem;
1588
- try {
1589
- currentItem = e.next();
1590
- } catch (ex) {
1591
- observer.onError(ex);
1592
- return;
1593
- }
1594
-
1595
- if (currentItem.done) {
1596
- if (lastException) {
1597
- observer.onError(lastException);
1598
- } else {
1599
- observer.onCompleted();
1600
- }
1601
- return;
1602
- }
1603
-
1604
- // Check if promise
1605
- var currentValue = currentItem.value;
1606
- isPromise(currentValue) && (currentValue = observableFromPromise(currentValue));
1607
-
1608
- var d = new SingleAssignmentDisposable();
1609
- subscription.setDisposable(d);
1610
- d.setDisposable(currentValue.subscribe(
1611
- observer.onNext.bind(observer),
1612
- function (exn) {
1613
- lastException = exn;
1614
- self();
1615
- },
1616
- observer.onCompleted.bind(observer)));
1617
- });
1618
- return new CompositeDisposable(subscription, cancelable, disposableCreate(function () {
1619
- isDisposed = true;
1620
- }));
1621
- });
1622
- };
1623
-
1624
- var enumerableRepeat = Enumerable.repeat = function (value, repeatCount) {
1625
- if (repeatCount == null) { repeatCount = -1; }
1626
- return new Enumerable(function () {
1627
- var left = repeatCount;
1628
- return new Enumerator(function () {
1629
- if (left === 0) { return doneEnumerator; }
1630
- if (left > 0) { left--; }
1631
- return { done: false, value: value };
1632
- });
1633
- });
1634
- };
1635
-
1636
- var enumerableFor = Enumerable.forEach = function (source, selector, thisArg) {
1637
- selector || (selector = identity);
1638
- return new Enumerable(function () {
1639
- var index = -1;
1640
- return new Enumerator(
1641
- function () {
1642
- return ++index < source.length ?
1643
- { done: false, value: selector.call(thisArg, source[index], index, source) } :
1644
- doneEnumerator;
1645
- });
1646
- });
1647
- };
1481
+ var Enumerator = Rx.internals.Enumerator = function (next) {
1482
+ this._next = next;
1483
+ };
1484
+
1485
+ Enumerator.prototype.next = function () {
1486
+ return this._next();
1487
+ };
1488
+
1489
+ Enumerator.prototype[$iterator$] = function () { return this; }
1490
+
1491
+ var Enumerable = Rx.internals.Enumerable = function (iterator) {
1492
+ this._iterator = iterator;
1493
+ };
1494
+
1495
+ Enumerable.prototype[$iterator$] = function () {
1496
+ return this._iterator();
1497
+ };
1498
+
1499
+ Enumerable.prototype.concat = function () {
1500
+ var sources = this;
1501
+ return new AnonymousObservable(function (observer) {
1502
+ var e;
1503
+ try {
1504
+ e = sources[$iterator$]();
1505
+ } catch(err) {
1506
+ observer.onError();
1507
+ return;
1508
+ }
1509
+
1510
+ var isDisposed,
1511
+ subscription = new SerialDisposable();
1512
+ var cancelable = immediateScheduler.scheduleRecursive(function (self) {
1513
+ var currentItem;
1514
+ if (isDisposed) { return; }
1515
+
1516
+ try {
1517
+ currentItem = e.next();
1518
+ } catch (ex) {
1519
+ observer.onError(ex);
1520
+ return;
1521
+ }
1522
+
1523
+ if (currentItem.done) {
1524
+ observer.onCompleted();
1525
+ return;
1526
+ }
1527
+
1528
+ // Check if promise
1529
+ var currentValue = currentItem.value;
1530
+ isPromise(currentValue) && (currentValue = observableFromPromise(currentValue));
1531
+
1532
+ var d = new SingleAssignmentDisposable();
1533
+ subscription.setDisposable(d);
1534
+ d.setDisposable(currentValue.subscribe(
1535
+ observer.onNext.bind(observer),
1536
+ observer.onError.bind(observer),
1537
+ function () { self(); })
1538
+ );
1539
+ });
1540
+
1541
+ return new CompositeDisposable(subscription, cancelable, disposableCreate(function () {
1542
+ isDisposed = true;
1543
+ }));
1544
+ });
1545
+ };
1546
+
1547
+ Enumerable.prototype.catchException = function () {
1548
+ var sources = this;
1549
+ return new AnonymousObservable(function (observer) {
1550
+ var e;
1551
+ try {
1552
+ e = sources[$iterator$]();
1553
+ } catch(err) {
1554
+ observer.onError();
1555
+ return;
1556
+ }
1557
+
1558
+ var isDisposed,
1559
+ lastException,
1560
+ subscription = new SerialDisposable();
1561
+ var cancelable = immediateScheduler.scheduleRecursive(function (self) {
1562
+ if (isDisposed) { return; }
1563
+
1564
+ var currentItem;
1565
+ try {
1566
+ currentItem = e.next();
1567
+ } catch (ex) {
1568
+ observer.onError(ex);
1569
+ return;
1570
+ }
1571
+
1572
+ if (currentItem.done) {
1573
+ if (lastException) {
1574
+ observer.onError(lastException);
1575
+ } else {
1576
+ observer.onCompleted();
1577
+ }
1578
+ return;
1579
+ }
1580
+
1581
+ // Check if promise
1582
+ var currentValue = currentItem.value;
1583
+ isPromise(currentValue) && (currentValue = observableFromPromise(currentValue));
1584
+
1585
+ var d = new SingleAssignmentDisposable();
1586
+ subscription.setDisposable(d);
1587
+ d.setDisposable(currentValue.subscribe(
1588
+ observer.onNext.bind(observer),
1589
+ function (exn) {
1590
+ lastException = exn;
1591
+ self();
1592
+ },
1593
+ observer.onCompleted.bind(observer)));
1594
+ });
1595
+ return new CompositeDisposable(subscription, cancelable, disposableCreate(function () {
1596
+ isDisposed = true;
1597
+ }));
1598
+ });
1599
+ };
1600
+
1601
+ var enumerableRepeat = Enumerable.repeat = function (value, repeatCount) {
1602
+ if (repeatCount == null) { repeatCount = -1; }
1603
+ return new Enumerable(function () {
1604
+ var left = repeatCount;
1605
+ return new Enumerator(function () {
1606
+ if (left === 0) { return doneEnumerator; }
1607
+ if (left > 0) { left--; }
1608
+ return { done: false, value: value };
1609
+ });
1610
+ });
1611
+ };
1612
+
1613
+ var enumerableFor = Enumerable.forEach = function (source, selector, thisArg) {
1614
+ selector || (selector = identity);
1615
+ return new Enumerable(function () {
1616
+ var index = -1;
1617
+ return new Enumerator(
1618
+ function () {
1619
+ return ++index < source.length ?
1620
+ { done: false, value: selector.call(thisArg, source[index], index, source) } :
1621
+ doneEnumerator;
1622
+ });
1623
+ });
1624
+ };
1648
1625
 
1649
1626
  /**
1650
1627
  * Supports push-style iteration over an observable sequence.
@@ -2076,21 +2053,19 @@
2076
2053
  * @returns {Observable} An Observable sequence which wraps the existing promise success and failure.
2077
2054
  */
2078
2055
  var observableFromPromise = Observable.fromPromise = function (promise) {
2079
- return new AnonymousObservable(function (observer) {
2056
+ return observableDefer(function () {
2057
+ var subject = new Rx.AsyncSubject();
2058
+
2080
2059
  promise.then(
2081
2060
  function (value) {
2082
- observer.onNext(value);
2083
- observer.onCompleted();
2084
- },
2085
- function (reason) {
2086
- observer.onError(reason);
2087
- });
2061
+ if (!subject.isDisposed) {
2062
+ subject.onNext(value);
2063
+ subject.onCompleted();
2064
+ }
2065
+ },
2066
+ subject.onError.bind(subject));
2088
2067
 
2089
- return function () {
2090
- if (promise && promise.abort) {
2091
- promise.abort();
2092
- }
2093
- }
2068
+ return subject;
2094
2069
  });
2095
2070
  };
2096
2071
  /*
@@ -2143,20 +2118,20 @@
2143
2118
  });
2144
2119
  };
2145
2120
 
2146
- /**
2147
- * Creates an observable sequence from a specified subscribe method implementation.
2148
- *
2149
- * @example
2150
- * var res = Rx.Observable.create(function (observer) { return function () { } );
2151
- * var res = Rx.Observable.create(function (observer) { return Rx.Disposable.empty; } );
2152
- * var res = Rx.Observable.create(function (observer) { } );
2153
- *
2154
- * @param {Function} subscribe Implementation of the resulting observable sequence's subscribe method, returning a function that will be wrapped in a Disposable.
2155
- * @returns {Observable} The observable sequence with the specified implementation for the Subscribe method.
2156
- */
2157
- Observable.create = Observable.createWithDisposable = function (subscribe) {
2158
- return new AnonymousObservable(subscribe);
2159
- };
2121
+ /**
2122
+ * Creates an observable sequence from a specified subscribe method implementation.
2123
+ *
2124
+ * @example
2125
+ * var res = Rx.Observable.create(function (observer) { return function () { } );
2126
+ * var res = Rx.Observable.create(function (observer) { return Rx.Disposable.empty; } );
2127
+ * var res = Rx.Observable.create(function (observer) { } );
2128
+ *
2129
+ * @param {Function} subscribe Implementation of the resulting observable sequence's subscribe method, returning a function that will be wrapped in a Disposable.
2130
+ * @returns {Observable} The observable sequence with the specified implementation for the Subscribe method.
2131
+ */
2132
+ Observable.create = Observable.createWithDisposable = function (subscribe) {
2133
+ return new AnonymousObservable(subscribe);
2134
+ };
2160
2135
 
2161
2136
  /**
2162
2137
  * Returns an observable sequence that invokes the specified factory function whenever a new observer subscribes.
@@ -2752,63 +2727,53 @@
2752
2727
  return this.merge(1);
2753
2728
  };
2754
2729
 
2755
- /**
2756
- * Merges an observable sequence of observable sequences into an observable sequence, limiting the number of concurrent subscriptions to inner sequences.
2757
- * Or merges two observable sequences into a single observable sequence.
2758
- *
2759
- * @example
2760
- * 1 - merged = sources.merge(1);
2761
- * 2 - merged = source.merge(otherSource);
2762
- * @param {Mixed} [maxConcurrentOrOther] Maximum number of inner observable sequences being subscribed to concurrently or the second observable sequence.
2763
- * @returns {Observable} The observable sequence that merges the elements of the inner sequences.
2764
- */
2765
- observableProto.merge = function (maxConcurrentOrOther) {
2766
- if (typeof maxConcurrentOrOther !== 'number') {
2767
- return observableMerge(this, maxConcurrentOrOther);
2730
+ /**
2731
+ * Merges an observable sequence of observable sequences into an observable sequence, limiting the number of concurrent subscriptions to inner sequences.
2732
+ * Or merges two observable sequences into a single observable sequence.
2733
+ *
2734
+ * @example
2735
+ * 1 - merged = sources.merge(1);
2736
+ * 2 - merged = source.merge(otherSource);
2737
+ * @param {Mixed} [maxConcurrentOrOther] Maximum number of inner observable sequences being subscribed to concurrently or the second observable sequence.
2738
+ * @returns {Observable} The observable sequence that merges the elements of the inner sequences.
2739
+ */
2740
+ observableProto.merge = function (maxConcurrentOrOther) {
2741
+ if (typeof maxConcurrentOrOther !== 'number') { return observableMerge(this, maxConcurrentOrOther); }
2742
+ var sources = this;
2743
+ return new AnonymousObservable(function (observer) {
2744
+ var activeCount = 0, group = new CompositeDisposable(), isStopped = false, q = [];
2745
+
2746
+ function subscribe(xs) {
2747
+ var subscription = new SingleAssignmentDisposable();
2748
+ group.add(subscription);
2749
+
2750
+ // Check for promises support
2751
+ isPromise(xs) && (xs = observableFromPromise(xs));
2752
+
2753
+ subscription.setDisposable(xs.subscribe(observer.onNext.bind(observer), observer.onError.bind(observer), function () {
2754
+ group.remove(subscription);
2755
+ if (q.length > 0) {
2756
+ subscribe(q.shift());
2757
+ } else {
2758
+ activeCount--;
2759
+ isStopped && activeCount === 0 && observer.onCompleted();
2760
+ }
2761
+ }));
2762
+ }
2763
+ group.add(sources.subscribe(function (innerSource) {
2764
+ if (activeCount < maxConcurrentOrOther) {
2765
+ activeCount++;
2766
+ subscribe(innerSource);
2767
+ } else {
2768
+ q.push(innerSource);
2768
2769
  }
2769
- var sources = this;
2770
- return new AnonymousObservable(function (observer) {
2771
- var activeCount = 0,
2772
- group = new CompositeDisposable(),
2773
- isStopped = false,
2774
- q = [],
2775
- subscribe = function (xs) {
2776
- var subscription = new SingleAssignmentDisposable();
2777
- group.add(subscription);
2778
-
2779
- // Check for promises support
2780
- if (isPromise(xs)) { xs = observableFromPromise(xs); }
2781
-
2782
- subscription.setDisposable(xs.subscribe(observer.onNext.bind(observer), observer.onError.bind(observer), function () {
2783
- var s;
2784
- group.remove(subscription);
2785
- if (q.length > 0) {
2786
- s = q.shift();
2787
- subscribe(s);
2788
- } else {
2789
- activeCount--;
2790
- if (isStopped && activeCount === 0) {
2791
- observer.onCompleted();
2792
- }
2793
- }
2794
- }));
2795
- };
2796
- group.add(sources.subscribe(function (innerSource) {
2797
- if (activeCount < maxConcurrentOrOther) {
2798
- activeCount++;
2799
- subscribe(innerSource);
2800
- } else {
2801
- q.push(innerSource);
2802
- }
2803
- }, observer.onError.bind(observer), function () {
2804
- isStopped = true;
2805
- if (activeCount === 0) {
2806
- observer.onCompleted();
2807
- }
2808
- }));
2809
- return group;
2810
- });
2811
- };
2770
+ }, observer.onError.bind(observer), function () {
2771
+ isStopped = true;
2772
+ activeCount === 0 && observer.onCompleted();
2773
+ }));
2774
+ return group;
2775
+ });
2776
+ };
2812
2777
 
2813
2778
  /**
2814
2779
  * Merges all the observable sequences into a single observable sequence.
@@ -3245,62 +3210,62 @@
3245
3210
  });
3246
3211
  };
3247
3212
 
3248
- /**
3249
- * Invokes an action for each element in the observable sequence and invokes an action upon graceful or exceptional termination of the observable sequence.
3250
- * 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.
3251
- *
3252
- * @example
3253
- * var res = observable.doAction(observer);
3254
- * var res = observable.doAction(onNext);
3255
- * var res = observable.doAction(onNext, onError);
3256
- * var res = observable.doAction(onNext, onError, onCompleted);
3257
- * @param {Mixed} observerOrOnNext Action to invoke for each element in the observable sequence or an observer.
3258
- * @param {Function} [onError] Action to invoke upon exceptional termination of the observable sequence. Used if only the observerOrOnNext parameter is also a function.
3259
- * @param {Function} [onCompleted] Action to invoke upon graceful termination of the observable sequence. Used if only the observerOrOnNext parameter is also a function.
3260
- * @returns {Observable} The source sequence with the side-effecting behavior applied.
3261
- */
3262
- observableProto['do'] = observableProto.doAction = function (observerOrOnNext, onError, onCompleted) {
3263
- var source = this, onNextFunc;
3264
- if (typeof observerOrOnNext === 'function') {
3265
- onNextFunc = observerOrOnNext;
3213
+ /**
3214
+ * Invokes an action for each element in the observable sequence and invokes an action upon graceful or exceptional termination of the observable sequence.
3215
+ * 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.
3216
+ *
3217
+ * @example
3218
+ * var res = observable.do(observer);
3219
+ * var res = observable.do(onNext);
3220
+ * var res = observable.do(onNext, onError);
3221
+ * var res = observable.do(onNext, onError, onCompleted);
3222
+ * @param {Function | Observer} observerOrOnNext Action to invoke for each element in the observable sequence or an observer.
3223
+ * @param {Function} [onError] Action to invoke upon exceptional termination of the observable sequence. Used if only the observerOrOnNext parameter is also a function.
3224
+ * @param {Function} [onCompleted] Action to invoke upon graceful termination of the observable sequence. Used if only the observerOrOnNext parameter is also a function.
3225
+ * @returns {Observable} The source sequence with the side-effecting behavior applied.
3226
+ */
3227
+ observableProto['do'] = observableProto.doAction = observableProto.tap = function (observerOrOnNext, onError, onCompleted) {
3228
+ var source = this, onNextFunc;
3229
+ if (typeof observerOrOnNext === 'function') {
3230
+ onNextFunc = observerOrOnNext;
3231
+ } else {
3232
+ onNextFunc = observerOrOnNext.onNext.bind(observerOrOnNext);
3233
+ onError = observerOrOnNext.onError.bind(observerOrOnNext);
3234
+ onCompleted = observerOrOnNext.onCompleted.bind(observerOrOnNext);
3235
+ }
3236
+ return new AnonymousObservable(function (observer) {
3237
+ return source.subscribe(function (x) {
3238
+ try {
3239
+ onNextFunc(x);
3240
+ } catch (e) {
3241
+ observer.onError(e);
3242
+ }
3243
+ observer.onNext(x);
3244
+ }, function (err) {
3245
+ if (!onError) {
3246
+ observer.onError(err);
3266
3247
  } else {
3267
- onNextFunc = observerOrOnNext.onNext.bind(observerOrOnNext);
3268
- onError = observerOrOnNext.onError.bind(observerOrOnNext);
3269
- onCompleted = observerOrOnNext.onCompleted.bind(observerOrOnNext);
3248
+ try {
3249
+ onError(err);
3250
+ } catch (e) {
3251
+ observer.onError(e);
3252
+ }
3253
+ observer.onError(err);
3270
3254
  }
3271
- return new AnonymousObservable(function (observer) {
3272
- return source.subscribe(function (x) {
3273
- try {
3274
- onNextFunc(x);
3275
- } catch (e) {
3276
- observer.onError(e);
3277
- }
3278
- observer.onNext(x);
3279
- }, function (exception) {
3280
- if (!onError) {
3281
- observer.onError(exception);
3282
- } else {
3283
- try {
3284
- onError(exception);
3285
- } catch (e) {
3286
- observer.onError(e);
3287
- }
3288
- observer.onError(exception);
3289
- }
3290
- }, function () {
3291
- if (!onCompleted) {
3292
- observer.onCompleted();
3293
- } else {
3294
- try {
3295
- onCompleted();
3296
- } catch (e) {
3297
- observer.onError(e);
3298
- }
3299
- observer.onCompleted();
3300
- }
3301
- });
3302
- });
3303
- };
3255
+ }, function () {
3256
+ if (!onCompleted) {
3257
+ observer.onCompleted();
3258
+ } else {
3259
+ try {
3260
+ onCompleted();
3261
+ } catch (e) {
3262
+ observer.onError(e);
3263
+ }
3264
+ observer.onCompleted();
3265
+ }
3266
+ });
3267
+ });
3268
+ };
3304
3269
 
3305
3270
  /**
3306
3271
  * Invokes a specified action after the source observable sequence terminates gracefully or exceptionally.
@@ -3483,48 +3448,54 @@
3483
3448
  return enumerableFor([observableFromArray(values, scheduler), this]).concat();
3484
3449
  };
3485
3450
 
3486
- /**
3487
- * Returns a specified number of contiguous elements from the end of an observable sequence, using an optional scheduler to drain the queue.
3488
- *
3489
- * @example
3490
- * var res = source.takeLast(5);
3491
- * var res = source.takeLast(5, Rx.Scheduler.timeout);
3492
- *
3493
- * @description
3494
- * This operator accumulates a buffer with a length enough to store elements count elements. Upon completion of
3495
- * the source sequence, this buffer is drained on the result sequence. This causes the elements to be delayed.
3496
- * @param {Number} count Number of elements to take from the end of the source sequence.
3497
- * @param {Scheduler} [scheduler] Scheduler used to drain the queue upon completion of the source sequence.
3498
- * @returns {Observable} An observable sequence containing the specified number of elements from the end of the source sequence.
3499
- */
3500
- observableProto.takeLast = function (count, scheduler) {
3501
- return this.takeLastBuffer(count).selectMany(function (xs) { return observableFromArray(xs, scheduler); });
3502
- };
3451
+ /**
3452
+ * Returns a specified number of contiguous elements from the end of an observable sequence.
3453
+ *
3454
+ * @example
3455
+ * var res = source.takeLast(5);
3456
+ *
3457
+ * @description
3458
+ * This operator accumulates a buffer with a length enough to store elements count elements. Upon completion of
3459
+ * the source sequence, this buffer is drained on the result sequence. This causes the elements to be delayed.
3460
+ * @param {Number} count Number of elements to take from the end of the source sequence.
3461
+ * @returns {Observable} An observable sequence containing the specified number of elements from the end of the source sequence.
3462
+ */
3463
+ observableProto.takeLast = function (count) {
3464
+ var source = this;
3465
+ return new AnonymousObservable(function (observer) {
3466
+ var q = [];
3467
+ return source.subscribe(function (x) {
3468
+ q.push(x);
3469
+ q.length > count && q.shift();
3470
+ }, observer.onError.bind(observer), function () {
3471
+ while(q.length > 0) { observer.onNext(q.shift()); }
3472
+ observer.onCompleted();
3473
+ });
3474
+ });
3475
+ };
3503
3476
 
3504
- /**
3505
- * Returns an array with the specified number of contiguous elements from the end of an observable sequence.
3506
- *
3507
- * @description
3508
- * This operator accumulates a buffer with a length enough to store count elements. Upon completion of the
3509
- * source sequence, this buffer is produced on the result sequence.
3510
- * @param {Number} count Number of elements to take from the end of the source sequence.
3511
- * @returns {Observable} An observable sequence containing a single array with the specified number of elements from the end of the source sequence.
3512
- */
3513
- observableProto.takeLastBuffer = function (count) {
3514
- var source = this;
3515
- return new AnonymousObservable(function (observer) {
3516
- var q = [];
3517
- return source.subscribe(function (x) {
3518
- q.push(x);
3519
- if (q.length > count) {
3520
- q.shift();
3521
- }
3522
- }, observer.onError.bind(observer), function () {
3523
- observer.onNext(q);
3524
- observer.onCompleted();
3525
- });
3526
- });
3527
- };
3477
+ /**
3478
+ * Returns an array with the specified number of contiguous elements from the end of an observable sequence.
3479
+ *
3480
+ * @description
3481
+ * This operator accumulates a buffer with a length enough to store count elements. Upon completion of the
3482
+ * source sequence, this buffer is produced on the result sequence.
3483
+ * @param {Number} count Number of elements to take from the end of the source sequence.
3484
+ * @returns {Observable} An observable sequence containing a single array with the specified number of elements from the end of the source sequence.
3485
+ */
3486
+ observableProto.takeLastBuffer = function (count) {
3487
+ var source = this;
3488
+ return new AnonymousObservable(function (observer) {
3489
+ var q = [];
3490
+ return source.subscribe(function (x) {
3491
+ q.push(x);
3492
+ q.length > count && q.shift();
3493
+ }, observer.onError.bind(observer), function () {
3494
+ observer.onNext(q);
3495
+ observer.onCompleted();
3496
+ });
3497
+ });
3498
+ };
3528
3499
 
3529
3500
  /**
3530
3501
  * Projects each element of an observable sequence into zero or more windows which are produced based on element count information.
@@ -3586,53 +3557,33 @@
3586
3557
  });
3587
3558
  };
3588
3559
 
3589
- function concatMap(selector) {
3590
- return this.map(function (x, i) {
3591
- var result = selector(x, i);
3560
+ function concatMap(source, selector, thisArg) {
3561
+ return source.map(function (x, i) {
3562
+ var result = selector.call(thisArg, x, i);
3592
3563
  return isPromise(result) ? observableFromPromise(result) : result;
3593
3564
  }).concatAll();
3594
3565
  }
3595
3566
 
3596
- function concatMapObserver(onNext, onError, onCompleted) {
3597
- var source = this;
3598
- return new AnonymousObservable(function (observer) {
3599
- var index = 0;
3600
-
3601
- return source.subscribe(
3602
- function (x) {
3603
- observer.onNext(onNext(x, index++));
3604
- },
3605
- function (err) {
3606
- observer.onNext(onError(err));
3607
- observer.completed();
3608
- },
3609
- function () {
3610
- observer.onNext(onCompleted());
3611
- observer.onCompleted();
3612
- });
3613
- }).concatAll();
3614
- }
3615
-
3616
3567
  /**
3617
3568
  * One of the Following:
3618
3569
  * Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence.
3619
3570
  *
3620
3571
  * @example
3621
- * var res = source.selectMany(function (x) { return Rx.Observable.range(0, x); });
3572
+ * var res = source.concatMap(function (x) { return Rx.Observable.range(0, x); });
3622
3573
  * Or:
3623
3574
  * 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.
3624
3575
  *
3625
- * var res = source.selectMany(function (x) { return Rx.Observable.range(0, x); }, function (x, y) { return x + y; });
3576
+ * var res = source.concatMap(function (x) { return Rx.Observable.range(0, x); }, function (x, y) { return x + y; });
3626
3577
  * Or:
3627
3578
  * Projects each element of the source observable sequence to the other observable sequence and merges the resulting observable sequences into one observable sequence.
3628
3579
  *
3629
- * var res = source.selectMany(Rx.Observable.fromArray([1,2,3]));
3580
+ * var res = source.concatMap(Rx.Observable.fromArray([1,2,3]));
3630
3581
  * @param selector A transform function to apply to each element or an observable sequence to project each element from the
3631
3582
  * source sequence onto which could be either an observable or Promise.
3632
3583
  * @param {Function} [resultSelector] A transform function to apply to each element of the intermediate sequence.
3633
3584
  * @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.
3634
3585
  */
3635
- observableProto.selectConcat = observableProto.concatMap = function (selector, resultSelector) {
3586
+ observableProto.selectConcat = observableProto.concatMap = function (selector, resultSelector, thisArg) {
3636
3587
  if (resultSelector) {
3637
3588
  return this.concatMap(function (x, i) {
3638
3589
  var selectorResult = selector(x, i),
@@ -3643,14 +3594,62 @@
3643
3594
  });
3644
3595
  });
3645
3596
  }
3646
- if (typeof selector === 'function') {
3647
- return concatMap.call(this, selector);
3648
- }
3649
- return concatMap.call(this, function () {
3650
- return selector;
3651
- });
3597
+ return typeof selector === 'function' ?
3598
+ concatMap(this, selector, thisArg) :
3599
+ concatMap(this, function () { return selector; });
3652
3600
  };
3653
3601
 
3602
+ /**
3603
+ * Projects each notification of an observable sequence to an observable sequence and concats the resulting observable sequences into one observable sequence.
3604
+ * @param {Function} onNext A transform function to apply to each element; the second parameter of the function represents the index of the source element.
3605
+ * @param {Function} onError A transform function to apply when an error occurs in the source sequence.
3606
+ * @param {Function} onCompleted A transform function to apply when the end of the source sequence is reached.
3607
+ * @param {Any} [thisArg] An optional "this" to use to invoke each transform.
3608
+ * @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.
3609
+ */
3610
+ observableProto.concatMapObserver = observableProto.selectConcatObserver = function(onNext, onError, onCompleted, thisArg) {
3611
+ var source = this;
3612
+ return new AnonymousObservable(function (observer) {
3613
+ var index = 0;
3614
+
3615
+ return source.subscribe(
3616
+ function (x) {
3617
+ var result;
3618
+ try {
3619
+ result = onNext.call(thisArg, x, index++);
3620
+ } catch (e) {
3621
+ observer.onError(e);
3622
+ return;
3623
+ }
3624
+ isPromise(result) && (result = observableFromPromise(result));
3625
+ observer.onNext(result);
3626
+ },
3627
+ function (err) {
3628
+ var result;
3629
+ try {
3630
+ result = onError.call(thisArg, err);
3631
+ } catch (e) {
3632
+ observer.onError(e);
3633
+ return;
3634
+ }
3635
+ isPromise(result) && (result = observableFromPromise(result));
3636
+ observer.onNext(result);
3637
+ observer.onCompleted();
3638
+ },
3639
+ function () {
3640
+ var result;
3641
+ try {
3642
+ result = onCompleted.call(thisArg);
3643
+ } catch (e) {
3644
+ observer.onError(e);
3645
+ return;
3646
+ }
3647
+ isPromise(result) && (result = observableFromPromise(result));
3648
+ observer.onNext(result);
3649
+ observer.onCompleted();
3650
+ });
3651
+ }).concatAll();
3652
+ };
3654
3653
  /**
3655
3654
  * Returns the elements of the specified sequence or the specified value in a singleton sequence if the sequence is empty.
3656
3655
  *
@@ -3659,194 +3658,80 @@
3659
3658
  *
3660
3659
  * @memberOf Observable#
3661
3660
  * @param defaultValue The value to return if the sequence is empty. If not provided, this defaults to null.
3662
- * @returns {Observable} An observable sequence that contains the specified default value if the source is empty; otherwise, the elements of the source itself.
3663
- */
3664
- observableProto.defaultIfEmpty = function (defaultValue) {
3665
- var source = this;
3666
- if (defaultValue === undefined) {
3667
- defaultValue = null;
3668
- }
3669
- return new AnonymousObservable(function (observer) {
3670
- var found = false;
3671
- return source.subscribe(function (x) {
3672
- found = true;
3673
- observer.onNext(x);
3674
- }, observer.onError.bind(observer), function () {
3675
- if (!found) {
3676
- observer.onNext(defaultValue);
3677
- }
3678
- observer.onCompleted();
3679
- });
3680
- });
3681
- };
3682
-
3683
- /**
3684
- * Returns an observable sequence that contains only distinct elements according to the keySelector and the comparer.
3685
- * Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.
3686
- *
3687
- * @example
3688
- * var res = obs = xs.distinct();
3689
- * 2 - obs = xs.distinct(function (x) { return x.id; });
3690
- * 2 - obs = xs.distinct(function (x) { return x.id; }, function (x) { return x.toString(); });
3691
- * @param {Function} [keySelector] A function to compute the comparison key for each element.
3692
- * @param {Function} [keySerializer] Used to serialize the given object into a string for object comparison.
3693
- * @returns {Observable} An observable sequence only containing the distinct elements, based on a computed key value, from the source sequence.
3694
- */
3695
- observableProto.distinct = function (keySelector, keySerializer) {
3696
- var source = this;
3697
- keySelector || (keySelector = identity);
3698
- keySerializer || (keySerializer = defaultKeySerializer);
3699
- return new AnonymousObservable(function (observer) {
3700
- var hashSet = {};
3701
- return source.subscribe(function (x) {
3702
- var key, serializedKey, otherKey, hasMatch = false;
3703
- try {
3704
- key = keySelector(x);
3705
- serializedKey = keySerializer(key);
3706
- } catch (exception) {
3707
- observer.onError(exception);
3708
- return;
3709
- }
3710
- for (otherKey in hashSet) {
3711
- if (serializedKey === otherKey) {
3712
- hasMatch = true;
3713
- break;
3714
- }
3715
- }
3716
- if (!hasMatch) {
3717
- hashSet[serializedKey] = null;
3718
- observer.onNext(x);
3719
- }
3720
- }, observer.onError.bind(observer), observer.onCompleted.bind(observer));
3721
- });
3722
- };
3723
-
3724
- /**
3725
- * 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.
3726
- *
3727
- * @example
3728
- * var res = observable.groupBy(function (x) { return x.id; });
3729
- * 2 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; });
3730
- * 3 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; }, function (x) { return x.toString(); });
3731
- * @param {Function} keySelector A function to extract the key for each element.
3732
- * @param {Function} [elementSelector] A function to map each source element to an element in an observable group.
3733
- * @param {Function} [keySerializer] Used to serialize the given object into a string for object comparison.
3734
- * @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.
3735
- */
3736
- observableProto.groupBy = function (keySelector, elementSelector, keySerializer) {
3737
- return this.groupByUntil(keySelector, elementSelector, function () {
3738
- return observableNever();
3739
- }, keySerializer);
3740
- };
3741
-
3742
- /**
3743
- * Groups the elements of an observable sequence according to a specified key selector function.
3744
- * 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
3745
- * key value as a reclaimed group occurs, the group will be reborn with a new lifetime request.
3746
- *
3747
- * @example
3748
- * var res = observable.groupByUntil(function (x) { return x.id; }, null, function () { return Rx.Observable.never(); });
3749
- * 2 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; }, function () { return Rx.Observable.never(); });
3750
- * 3 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; }, function () { return Rx.Observable.never(); }, function (x) { return x.toString(); });
3751
- * @param {Function} keySelector A function to extract the key for each element.
3752
- * @param {Function} durationSelector A function to signal the expiration of a group.
3753
- * @param {Function} [keySerializer] Used to serialize the given object into a string for object comparison.
3754
- * @returns {Observable}
3755
- * A sequence of observable groups, each of which corresponds to a unique key value, containing all elements that share that same key value.
3756
- * 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.
3757
- *
3661
+ * @returns {Observable} An observable sequence that contains the specified default value if the source is empty; otherwise, the elements of the source itself.
3758
3662
  */
3759
- observableProto.groupByUntil = function (keySelector, elementSelector, durationSelector, keySerializer) {
3663
+ observableProto.defaultIfEmpty = function (defaultValue) {
3760
3664
  var source = this;
3761
- elementSelector || (elementSelector = identity);
3762
- keySerializer || (keySerializer = defaultKeySerializer);
3665
+ if (defaultValue === undefined) {
3666
+ defaultValue = null;
3667
+ }
3763
3668
  return new AnonymousObservable(function (observer) {
3764
- var map = {},
3765
- groupDisposable = new CompositeDisposable(),
3766
- refCountDisposable = new RefCountDisposable(groupDisposable);
3767
- groupDisposable.add(source.subscribe(function (x) {
3768
- var duration, durationGroup, element, fireNewMapEntry, group, key, serializedKey, md, writer, w;
3769
- try {
3770
- key = keySelector(x);
3771
- serializedKey = keySerializer(key);
3772
- } catch (e) {
3773
- for (w in map) {
3774
- map[w].onError(e);
3775
- }
3776
- observer.onError(e);
3777
- return;
3778
- }
3779
- fireNewMapEntry = false;
3780
- try {
3781
- writer = map[serializedKey];
3782
- if (!writer) {
3783
- writer = new Subject();
3784
- map[serializedKey] = writer;
3785
- fireNewMapEntry = true;
3786
- }
3787
- } catch (e) {
3788
- for (w in map) {
3789
- map[w].onError(e);
3790
- }
3791
- observer.onError(e);
3792
- return;
3793
- }
3794
- if (fireNewMapEntry) {
3795
- group = new GroupedObservable(key, writer, refCountDisposable);
3796
- durationGroup = new GroupedObservable(key, writer);
3797
- try {
3798
- duration = durationSelector(durationGroup);
3799
- } catch (e) {
3800
- for (w in map) {
3801
- map[w].onError(e);
3802
- }
3803
- observer.onError(e);
3804
- return;
3805
- }
3806
- observer.onNext(group);
3807
- md = new SingleAssignmentDisposable();
3808
- groupDisposable.add(md);
3809
- var expire = function () {
3810
- if (serializedKey in map) {
3811
- delete map[serializedKey];
3812
- writer.onCompleted();
3813
- }
3814
- groupDisposable.remove(md);
3815
- };
3816
- md.setDisposable(duration.take(1).subscribe(noop, function (exn) {
3817
- for (w in map) {
3818
- map[w].onError(exn);
3819
- }
3820
- observer.onError(exn);
3821
- }, function () {
3822
- expire();
3823
- }));
3824
- }
3825
- try {
3826
- element = elementSelector(x);
3827
- } catch (e) {
3828
- for (w in map) {
3829
- map[w].onError(e);
3830
- }
3831
- observer.onError(e);
3832
- return;
3833
- }
3834
- writer.onNext(element);
3835
- }, function (ex) {
3836
- for (var w in map) {
3837
- map[w].onError(ex);
3838
- }
3839
- observer.onError(ex);
3840
- }, function () {
3841
- for (var w in map) {
3842
- map[w].onCompleted();
3669
+ var found = false;
3670
+ return source.subscribe(function (x) {
3671
+ found = true;
3672
+ observer.onNext(x);
3673
+ }, observer.onError.bind(observer), function () {
3674
+ if (!found) {
3675
+ observer.onNext(defaultValue);
3843
3676
  }
3844
3677
  observer.onCompleted();
3845
- }));
3846
- return refCountDisposable;
3678
+ });
3847
3679
  });
3848
3680
  };
3849
3681
 
3682
+ // Swap out for Array.findIndex
3683
+ function arrayIndexOfComparer(array, item, comparer) {
3684
+ for (var i = 0, len = array.length; i < len; i++) {
3685
+ if (comparer(array[i], item)) { return i; }
3686
+ }
3687
+ return -1;
3688
+ }
3689
+
3690
+ function HashSet(comparer) {
3691
+ this.comparer = comparer;
3692
+ this.set = [];
3693
+ }
3694
+ HashSet.prototype.push = function(value) {
3695
+ var retValue = arrayIndexOfComparer(this.set, value, this.comparer) === -1;
3696
+ retValue && this.set.push(value);
3697
+ return retValue;
3698
+ };
3699
+
3700
+ /**
3701
+ * Returns an observable sequence that contains only distinct elements according to the keySelector and the comparer.
3702
+ * Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.
3703
+ *
3704
+ * @example
3705
+ * var res = obs = xs.distinct();
3706
+ * 2 - obs = xs.distinct(function (x) { return x.id; });
3707
+ * 2 - obs = xs.distinct(function (x) { return x.id; }, function (a,b) { return a === b; });
3708
+ * @param {Function} [keySelector] A function to compute the comparison key for each element.
3709
+ * @param {Function} [comparer] Used to compare items in the collection.
3710
+ * @returns {Observable} An observable sequence only containing the distinct elements, based on a computed key value, from the source sequence.
3711
+ */
3712
+ observableProto.distinct = function (keySelector, comparer) {
3713
+ var source = this;
3714
+ comparer || (comparer = defaultComparer);
3715
+ return new AnonymousObservable(function (observer) {
3716
+ var hashSet = new HashSet(comparer);
3717
+ return source.subscribe(function (x) {
3718
+ var key = x;
3719
+
3720
+ if (keySelector) {
3721
+ try {
3722
+ key = keySelector(x);
3723
+ } catch (e) {
3724
+ observer.onError(e);
3725
+ return;
3726
+ }
3727
+ }
3728
+ hashSet.push(key) && observer.onNext(x);
3729
+ },
3730
+ observer.onError.bind(observer),
3731
+ observer.onCompleted.bind(observer));
3732
+ });
3733
+ };
3734
+
3850
3735
  /**
3851
3736
  * Projects each element of an observable sequence into a new form by incorporating the element's index.
3852
3737
  * @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.
@@ -3879,33 +3764,64 @@
3879
3764
  return this.select(function (x) { return x[property]; });
3880
3765
  };
3881
3766
 
3882
- function selectMany(selector) {
3883
- return this.select(function (x, i) {
3884
- var result = selector(x, i);
3767
+ /**
3768
+ * Projects each notification of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence.
3769
+ * @param {Function} onNext A transform function to apply to each element; the second parameter of the function represents the index of the source element.
3770
+ * @param {Function} onError A transform function to apply when an error occurs in the source sequence.
3771
+ * @param {Function} onCompleted A transform function to apply when the end of the source sequence is reached.
3772
+ * @param {Any} [thisArg] An optional "this" to use to invoke each transform.
3773
+ * @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.
3774
+ */
3775
+ observableProto.flatMapObserver = observableProto.selectManyObserver = function (onNext, onError, onCompleted, thisArg) {
3776
+ var source = this;
3777
+ return new AnonymousObservable(function (observer) {
3778
+ var index = 0;
3779
+
3780
+ return source.subscribe(
3781
+ function (x) {
3782
+ var result;
3783
+ try {
3784
+ result = onNext.call(thisArg, x, index++);
3785
+ } catch (e) {
3786
+ observer.onError(e);
3787
+ return;
3788
+ }
3789
+ isPromise(result) && (result = observableFromPromise(result));
3790
+ observer.onNext(result);
3791
+ },
3792
+ function (err) {
3793
+ var result;
3794
+ try {
3795
+ result = onError.call(thisArg, err);
3796
+ } catch (e) {
3797
+ observer.onError(e);
3798
+ return;
3799
+ }
3800
+ isPromise(result) && (result = observableFromPromise(result));
3801
+ observer.onNext(result);
3802
+ observer.onCompleted();
3803
+ },
3804
+ function () {
3805
+ var result;
3806
+ try {
3807
+ result = onCompleted.call(thisArg);
3808
+ } catch (e) {
3809
+ observer.onError(e);
3810
+ return;
3811
+ }
3812
+ isPromise(result) && (result = observableFromPromise(result));
3813
+ observer.onNext(result);
3814
+ observer.onCompleted();
3815
+ });
3816
+ }).mergeAll();
3817
+ };
3818
+ function flatMap(source, selector, thisArg) {
3819
+ return source.map(function (x, i) {
3820
+ var result = selector.call(thisArg, x, i);
3885
3821
  return isPromise(result) ? observableFromPromise(result) : result;
3886
3822
  }).mergeObservable();
3887
3823
  }
3888
3824
 
3889
- function selectManyObserver(onNext, onError, onCompleted) {
3890
- var source = this;
3891
- return new AnonymousObservable(function (observer) {
3892
- var index = 0;
3893
-
3894
- return source.subscribe(
3895
- function (x) {
3896
- observer.onNext(onNext(x, index++));
3897
- },
3898
- function (err) {
3899
- observer.onNext(onError(err));
3900
- observer.completed();
3901
- },
3902
- function () {
3903
- observer.onNext(onCompleted());
3904
- observer.onCompleted();
3905
- });
3906
- }).mergeAll();
3907
- }
3908
-
3909
3825
  /**
3910
3826
  * One of the Following:
3911
3827
  * Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence.
@@ -3923,25 +3839,23 @@
3923
3839
  * @param selector A transform function to apply to each element or an observable sequence to project each element from the
3924
3840
  * source sequence onto which could be either an observable or Promise.
3925
3841
  * @param {Function} [resultSelector] A transform function to apply to each element of the intermediate sequence.
3842
+ * @param {Any} [thisArg] Object to use as this when executing callback.
3926
3843
  * @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.
3927
3844
  */
3928
- observableProto.selectMany = observableProto.flatMap = function (selector, resultSelector) {
3845
+ observableProto.selectMany = observableProto.flatMap = function (selector, resultSelector, thisArg) {
3929
3846
  if (resultSelector) {
3930
- return this.selectMany(function (x, i) {
3847
+ return this.flatMap(function (x, i) {
3931
3848
  var selectorResult = selector(x, i),
3932
3849
  result = isPromise(selectorResult) ? observableFromPromise(selectorResult) : selectorResult;
3933
3850
 
3934
- return result.select(function (y) {
3851
+ return result.map(function (y) {
3935
3852
  return resultSelector(x, y, i);
3936
3853
  });
3937
- });
3938
- }
3939
- if (typeof selector === 'function') {
3940
- return selectMany.call(this, selector);
3854
+ }, thisArg);
3941
3855
  }
3942
- return selectMany.call(this, function () {
3943
- return selector;
3944
- });
3856
+ return typeof selector === 'function' ?
3857
+ flatMap(this, selector, thisArg) :
3858
+ flatMap(this, function () { return selector; });
3945
3859
  };
3946
3860
 
3947
3861
  /**
@@ -4216,13 +4130,11 @@
4216
4130
 
4217
4131
  // Fix subscriber to check for undefined or function returned to decorate as Disposable
4218
4132
  function fixSubscriber(subscriber) {
4219
- if (typeof subscriber === 'undefined') {
4220
- subscriber = disposableEmpty;
4221
- } else if (typeof subscriber === 'function') {
4222
- subscriber = disposableCreate(subscriber);
4223
- }
4133
+ if (subscriber && typeof subscriber.dispose === 'function') { return subscriber; }
4224
4134
 
4225
- return subscriber;
4135
+ return typeof subscriber === 'function' ?
4136
+ disposableCreate(subscriber) :
4137
+ disposableEmpty;
4226
4138
  }
4227
4139
 
4228
4140
  function AnonymousObservable(subscribe) {
@@ -4319,48 +4231,23 @@
4319
4231
  return AutoDetachObserver;
4320
4232
  }(AbstractObserver));
4321
4233
 
4322
- /** @private */
4323
- var GroupedObservable = (function (_super) {
4324
- inherits(GroupedObservable, _super);
4325
-
4326
- function subscribe(observer) {
4327
- return this.underlyingObservable.subscribe(observer);
4328
- }
4329
-
4330
- /**
4331
- * @constructor
4332
- * @private
4333
- */
4334
- function GroupedObservable(key, underlyingObservable, mergedDisposable) {
4335
- _super.call(this, subscribe);
4336
- this.key = key;
4337
- this.underlyingObservable = !mergedDisposable ?
4338
- underlyingObservable :
4339
- new AnonymousObservable(function (observer) {
4340
- return new CompositeDisposable(mergedDisposable.getDisposable(), underlyingObservable.subscribe(observer));
4341
- });
4342
- }
4343
-
4344
- return GroupedObservable;
4345
- }(Observable));
4346
-
4347
- /** @private */
4348
- var InnerSubscription = function (subject, observer) {
4349
- this.subject = subject;
4350
- this.observer = observer;
4351
- };
4352
-
4353
- /**
4354
- * @private
4355
- * @memberOf InnerSubscription
4356
- */
4357
- InnerSubscription.prototype.dispose = function () {
4358
- if (!this.subject.isDisposed && this.observer !== null) {
4359
- var idx = this.subject.observers.indexOf(this.observer);
4360
- this.subject.observers.splice(idx, 1);
4361
- this.observer = null;
4362
- }
4363
- };
4234
+ /** @private */
4235
+ var InnerSubscription = function (subject, observer) {
4236
+ this.subject = subject;
4237
+ this.observer = observer;
4238
+ };
4239
+
4240
+ /**
4241
+ * @private
4242
+ * @memberOf InnerSubscription
4243
+ */
4244
+ InnerSubscription.prototype.dispose = function () {
4245
+ if (!this.subject.isDisposed && this.observer !== null) {
4246
+ var idx = this.subject.observers.indexOf(this.observer);
4247
+ this.subject.observers.splice(idx, 1);
4248
+ this.observer = null;
4249
+ }
4250
+ };
4364
4251
 
4365
4252
  /**
4366
4253
  * Represents an object that is both an observable sequence as well as an observer.
@@ -4469,192 +4356,170 @@
4469
4356
  return Subject;
4470
4357
  }(Observable));
4471
4358
 
4472
- /**
4473
- * Represents the result of an asynchronous operation.
4474
- * The last value before the OnCompleted notification, or the error received through OnError, is sent to all subscribed observers.
4475
- */
4476
- var AsyncSubject = Rx.AsyncSubject = (function (_super) {
4477
-
4478
- function subscribe(observer) {
4479
- checkDisposed.call(this);
4480
-
4481
- if (!this.isStopped) {
4482
- this.observers.push(observer);
4483
- return new InnerSubscription(this, observer);
4484
- }
4485
-
4486
- var ex = this.exception,
4487
- hv = this.hasValue,
4488
- v = this.value;
4489
-
4490
- if (ex) {
4491
- observer.onError(ex);
4492
- } else if (hv) {
4493
- observer.onNext(v);
4494
- observer.onCompleted();
4495
- } else {
4496
- observer.onCompleted();
4497
- }
4498
-
4499
- return disposableEmpty;
4500
- }
4359
+ /**
4360
+ * Represents the result of an asynchronous operation.
4361
+ * The last value before the OnCompleted notification, or the error received through OnError, is sent to all subscribed observers.
4362
+ */
4363
+ var AsyncSubject = Rx.AsyncSubject = (function (__super__) {
4501
4364
 
4502
- inherits(AsyncSubject, _super);
4365
+ function subscribe(observer) {
4366
+ checkDisposed.call(this);
4367
+
4368
+ if (!this.isStopped) {
4369
+ this.observers.push(observer);
4370
+ return new InnerSubscription(this, observer);
4371
+ }
4503
4372
 
4504
- /**
4505
- * Creates a subject that can only receive one value and that value is cached for all future observations.
4506
- * @constructor
4507
- */
4508
- function AsyncSubject() {
4509
- _super.call(this, subscribe);
4373
+ var ex = this.exception,
4374
+ hv = this.hasValue,
4375
+ v = this.value;
4510
4376
 
4511
- this.isDisposed = false;
4512
- this.isStopped = false;
4513
- this.value = null;
4514
- this.hasValue = false;
4515
- this.observers = [];
4516
- this.exception = null;
4517
- }
4377
+ if (ex) {
4378
+ observer.onError(ex);
4379
+ } else if (hv) {
4380
+ observer.onNext(v);
4381
+ observer.onCompleted();
4382
+ } else {
4383
+ observer.onCompleted();
4384
+ }
4518
4385
 
4519
- addProperties(AsyncSubject.prototype, Observer, {
4520
- /**
4521
- * Indicates whether the subject has observers subscribed to it.
4522
- * @returns {Boolean} Indicates whether the subject has observers subscribed to it.
4523
- */
4524
- hasObservers: function () {
4525
- checkDisposed.call(this);
4526
- return this.observers.length > 0;
4527
- },
4528
- /**
4529
- * Notifies all subscribed observers about the end of the sequence, also causing the last received value to be sent out (if any).
4530
- */
4531
- onCompleted: function () {
4532
- var o, i, len;
4533
- checkDisposed.call(this);
4534
- if (!this.isStopped) {
4535
- this.isStopped = true;
4536
- var os = this.observers.slice(0),
4537
- v = this.value,
4538
- hv = this.hasValue;
4539
-
4540
- if (hv) {
4541
- for (i = 0, len = os.length; i < len; i++) {
4542
- o = os[i];
4543
- o.onNext(v);
4544
- o.onCompleted();
4545
- }
4546
- } else {
4547
- for (i = 0, len = os.length; i < len; i++) {
4548
- os[i].onCompleted();
4549
- }
4550
- }
4386
+ return disposableEmpty;
4387
+ }
4551
4388
 
4552
- this.observers = [];
4553
- }
4554
- },
4555
- /**
4556
- * Notifies all subscribed observers about the exception.
4557
- * @param {Mixed} error The exception to send to all observers.
4558
- */
4559
- onError: function (exception) {
4560
- checkDisposed.call(this);
4561
- if (!this.isStopped) {
4562
- var os = this.observers.slice(0);
4563
- this.isStopped = true;
4564
- this.exception = exception;
4389
+ inherits(AsyncSubject, __super__);
4565
4390
 
4566
- for (var i = 0, len = os.length; i < len; i++) {
4567
- os[i].onError(exception);
4568
- }
4391
+ /**
4392
+ * Creates a subject that can only receive one value and that value is cached for all future observations.
4393
+ * @constructor
4394
+ */
4395
+ function AsyncSubject() {
4396
+ __super__.call(this, subscribe);
4397
+
4398
+ this.isDisposed = false;
4399
+ this.isStopped = false;
4400
+ this.value = null;
4401
+ this.hasValue = false;
4402
+ this.observers = [];
4403
+ this.exception = null;
4404
+ }
4569
4405
 
4570
- this.observers = [];
4571
- }
4572
- },
4573
- /**
4574
- * Sends a value to the subject. The last value received before successful termination will be sent to all subscribed and future observers.
4575
- * @param {Mixed} value The value to store in the subject.
4576
- */
4577
- onNext: function (value) {
4578
- checkDisposed.call(this);
4579
- if (!this.isStopped) {
4580
- this.value = value;
4581
- this.hasValue = true;
4582
- }
4583
- },
4584
- /**
4585
- * Unsubscribe all observers and release resources.
4586
- */
4587
- dispose: function () {
4588
- this.isDisposed = true;
4589
- this.observers = null;
4590
- this.exception = null;
4591
- this.value = null;
4406
+ addProperties(AsyncSubject.prototype, Observer, {
4407
+ /**
4408
+ * Indicates whether the subject has observers subscribed to it.
4409
+ * @returns {Boolean} Indicates whether the subject has observers subscribed to it.
4410
+ */
4411
+ hasObservers: function () {
4412
+ checkDisposed.call(this);
4413
+ return this.observers.length > 0;
4414
+ },
4415
+ /**
4416
+ * Notifies all subscribed observers about the end of the sequence, also causing the last received value to be sent out (if any).
4417
+ */
4418
+ onCompleted: function () {
4419
+ var o, i, len;
4420
+ checkDisposed.call(this);
4421
+ if (!this.isStopped) {
4422
+ this.isStopped = true;
4423
+ var os = this.observers.slice(0),
4424
+ v = this.value,
4425
+ hv = this.hasValue;
4426
+
4427
+ if (hv) {
4428
+ for (i = 0, len = os.length; i < len; i++) {
4429
+ o = os[i];
4430
+ o.onNext(v);
4431
+ o.onCompleted();
4592
4432
  }
4593
- });
4594
-
4595
- return AsyncSubject;
4596
- }(Observable));
4597
-
4598
- /** @private */
4599
- var AnonymousSubject = (function (_super) {
4600
- inherits(AnonymousSubject, _super);
4433
+ } else {
4434
+ for (i = 0, len = os.length; i < len; i++) {
4435
+ os[i].onCompleted();
4436
+ }
4437
+ }
4601
4438
 
4602
- function subscribe(observer) {
4603
- return this.observable.subscribe(observer);
4439
+ this.observers = [];
4604
4440
  }
4441
+ },
4442
+ /**
4443
+ * Notifies all subscribed observers about the error.
4444
+ * @param {Mixed} error The Error to send to all observers.
4445
+ */
4446
+ onError: function (error) {
4447
+ checkDisposed.call(this);
4448
+ if (!this.isStopped) {
4449
+ var os = this.observers.slice(0);
4450
+ this.isStopped = true;
4451
+ this.exception = error;
4452
+
4453
+ for (var i = 0, len = os.length; i < len; i++) {
4454
+ os[i].onError(error);
4455
+ }
4605
4456
 
4606
- /**
4607
- * @private
4608
- * @constructor
4609
- */
4610
- function AnonymousSubject(observer, observable) {
4611
- _super.call(this, subscribe);
4612
- this.observer = observer;
4613
- this.observable = observable;
4457
+ this.observers = [];
4614
4458
  }
4459
+ },
4460
+ /**
4461
+ * Sends a value to the subject. The last value received before successful termination will be sent to all subscribed and future observers.
4462
+ * @param {Mixed} value The value to store in the subject.
4463
+ */
4464
+ onNext: function (value) {
4465
+ checkDisposed.call(this);
4466
+ if (this.isStopped) { return; }
4467
+ this.value = value;
4468
+ this.hasValue = true;
4469
+ },
4470
+ /**
4471
+ * Unsubscribe all observers and release resources.
4472
+ */
4473
+ dispose: function () {
4474
+ this.isDisposed = true;
4475
+ this.observers = null;
4476
+ this.exception = null;
4477
+ this.value = null;
4478
+ }
4479
+ });
4615
4480
 
4616
- addProperties(AnonymousSubject.prototype, Observer, {
4617
- /**
4618
- * @private
4619
- * @memberOf AnonymousSubject#
4620
- */
4621
- onCompleted: function () {
4622
- this.observer.onCompleted();
4623
- },
4624
- /**
4625
- * @private
4626
- * @memberOf AnonymousSubject#
4627
- */
4628
- onError: function (exception) {
4629
- this.observer.onError(exception);
4630
- },
4631
- /**
4632
- * @private
4633
- * @memberOf AnonymousSubject#
4634
- */
4635
- onNext: function (value) {
4636
- this.observer.onNext(value);
4637
- }
4638
- });
4639
-
4640
- return AnonymousSubject;
4641
- }(Observable));
4642
-
4643
- if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
4644
- root.Rx = Rx;
4481
+ return AsyncSubject;
4482
+ }(Observable));
4645
4483
 
4646
- define(function() {
4647
- return Rx;
4648
- });
4649
- } else if (freeExports && freeModule) {
4650
- // in Node.js or RingoJS
4651
- if (moduleExports) {
4652
- (freeModule.exports = Rx).Rx = Rx;
4653
- } else {
4654
- freeExports.Rx = Rx;
4655
- }
4656
- } else {
4657
- // in a browser or Rhino
4658
- root.Rx = Rx;
4484
+ var AnonymousSubject = Rx.AnonymousSubject = (function (__super__) {
4485
+ inherits(AnonymousSubject, __super__);
4486
+
4487
+ function AnonymousSubject(observer, observable) {
4488
+ this.observer = observer;
4489
+ this.observable = observable;
4490
+ __super__.call(this, this.observable.subscribe.bind(this.observable));
4491
+ }
4492
+
4493
+ addProperties(AnonymousSubject.prototype, Observer, {
4494
+ onCompleted: function () {
4495
+ this.observer.onCompleted();
4496
+ },
4497
+ onError: function (exception) {
4498
+ this.observer.onError(exception);
4499
+ },
4500
+ onNext: function (value) {
4501
+ this.observer.onNext(value);
4502
+ }
4503
+ });
4504
+
4505
+ return AnonymousSubject;
4506
+ }(Observable));
4507
+
4508
+ if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
4509
+ root.Rx = Rx;
4510
+
4511
+ define(function() {
4512
+ return Rx;
4513
+ });
4514
+ } else if (freeExports && freeModule) {
4515
+ // in Node.js or RingoJS
4516
+ if (moduleExports) {
4517
+ (freeModule.exports = Rx).Rx = Rx;
4518
+ } else {
4519
+ freeExports.Rx = Rx;
4520
+ }
4521
+ } else {
4522
+ // in a browser or Rhino
4523
+ root.Rx = Rx;
4659
4524
  }
4660
4525
  }.call(this));