UNPKG

43.7 kBJavaScriptView Raw
1// Copyright (c) Microsoft, All rights reserved. See License.txt in the project root for license information.
2
3;(function (undefined) {
4
5 var objectTypes = {
6 'function': true,
7 'object': true
8 };
9
10 function checkGlobal(value) {
11 return (value && value.Object === Object) ? value : null;
12 }
13
14 var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) ? exports : null;
15 var freeModule = (objectTypes[typeof module] && module && !module.nodeType) ? module : null;
16 var freeGlobal = checkGlobal(freeExports && freeModule && typeof global === 'object' && global);
17 var freeSelf = checkGlobal(objectTypes[typeof self] && self);
18 var freeWindow = checkGlobal(objectTypes[typeof window] && window);
19 var moduleExports = (freeModule && freeModule.exports === freeExports) ? freeExports : null;
20 var thisGlobal = checkGlobal(objectTypes[typeof this] && this);
21 var root = freeGlobal || ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || freeSelf || thisGlobal || Function('return this')();
22
23 var Rx = {
24 internals: {},
25 config: {
26 Promise: root.Promise
27 },
28 helpers: { }
29 };
30
31// Defaults
32var
33 noop = Rx.helpers.noop = function () { },
34 defaultNow = Rx.helpers.defaultNow = (function () { return !!Date.now ? Date.now : function () { return +new Date; }; }()),
35 defaultError = Rx.helpers.defaultError = function (err) { throw err; },
36 isPromise = Rx.helpers.isPromise = function (p) { return !!p && !isFunction(p.subscribe) && isFunction(p.then); },
37 defaultSubComparer = Rx.helpers.defaultSubComparer = function (x, y) { return x > y ? 1 : (x < y ? -1 : 0); }
38 isFunction = Rx.helpers.isFunction = (function () {
39 var isFn = function (value) {
40 return typeof value == 'function' || false;
41 };
42
43 // fallback for older versions of Chrome and Safari
44 if (isFn(/x/)) {
45 isFn = function(value) {
46 return typeof value == 'function' && toString.call(value) == '[object Function]';
47 };
48 }
49 return isFn;
50 }());
51
52 var NotImplementedError = Rx.NotImplementedError = function (message) {
53 this.message = message || 'This operation is not implemented';
54 Error.call(this);
55 };
56 NotImplementedError.prototype = Error.prototype;
57
58 var NotSupportedError = Rx.NotSupportedError = function (message) {
59 this.message = message || 'This operation is not supported';
60 Error.call(this);
61 };
62 NotSupportedError.prototype = Error.prototype;
63
64 var notImplemented = Rx.helpers.notImplemented = function () {
65 throw new NotImplementedError();
66 };
67
68 var notSupported = Rx.helpers.notSupported = function () {
69 throw new NotSupportedError();
70 };
71
72 var errorObj = {e: {}};
73
74 function tryCatcherGen(tryCatchTarget) {
75 return function tryCatcher() {
76 try {
77 return tryCatchTarget.apply(this, arguments);
78 } catch (e) {
79 errorObj.e = e;
80 return errorObj;
81 }
82 };
83 }
84
85 var tryCatch = Rx.internals.tryCatch = function tryCatch(fn) {
86 if (!isFunction(fn)) { throw new TypeError('fn must be a function'); }
87 return tryCatcherGen(fn);
88 };
89
90 function thrower(e) {
91 throw e;
92 }
93
94 Rx.config.longStackSupport = false;
95 var hasStacks = false, stacks = tryCatch(function () { throw new Error(); })();
96 hasStacks = !!stacks.e && !!stacks.e.stack;
97
98 // All code after this point will be filtered from stack traces reported by RxJS
99 var rStartingLine = captureLine(), rFileName;
100
101 var STACK_JUMP_SEPARATOR = 'From previous event:';
102
103 function makeStackTraceLong(error, observable) {
104 // If possible, transform the error stack trace by removing Node and RxJS
105 // cruft, then concatenating with the stack trace of `observable`.
106 if (hasStacks &&
107 observable.stack &&
108 typeof error === 'object' &&
109 error !== null &&
110 error.stack &&
111 error.stack.indexOf(STACK_JUMP_SEPARATOR) === -1
112 ) {
113 var stacks = [];
114 for (var o = observable; !!o; o = o.source) {
115 if (o.stack) {
116 stacks.unshift(o.stack);
117 }
118 }
119 stacks.unshift(error.stack);
120
121 var concatedStacks = stacks.join('\n' + STACK_JUMP_SEPARATOR + '\n');
122 error.stack = filterStackString(concatedStacks);
123 }
124 }
125
126 function filterStackString(stackString) {
127 var lines = stackString.split('\n'), desiredLines = [];
128 for (var i = 0, len = lines.length; i < len; i++) {
129 var line = lines[i];
130
131 if (!isInternalFrame(line) && !isNodeFrame(line) && line) {
132 desiredLines.push(line);
133 }
134 }
135 return desiredLines.join('\n');
136 }
137
138 function isInternalFrame(stackLine) {
139 var fileNameAndLineNumber = getFileNameAndLineNumber(stackLine);
140 if (!fileNameAndLineNumber) {
141 return false;
142 }
143 var fileName = fileNameAndLineNumber[0], lineNumber = fileNameAndLineNumber[1];
144
145 return fileName === rFileName &&
146 lineNumber >= rStartingLine &&
147 lineNumber <= rEndingLine;
148 }
149
150 function isNodeFrame(stackLine) {
151 return stackLine.indexOf('(module.js:') !== -1 ||
152 stackLine.indexOf('(node.js:') !== -1;
153 }
154
155 function captureLine() {
156 if (!hasStacks) { return; }
157
158 try {
159 throw new Error();
160 } catch (e) {
161 var lines = e.stack.split('\n');
162 var firstLine = lines[0].indexOf('@') > 0 ? lines[1] : lines[2];
163 var fileNameAndLineNumber = getFileNameAndLineNumber(firstLine);
164 if (!fileNameAndLineNumber) { return; }
165
166 rFileName = fileNameAndLineNumber[0];
167 return fileNameAndLineNumber[1];
168 }
169 }
170
171 function getFileNameAndLineNumber(stackLine) {
172 // Named functions: 'at functionName (filename:lineNumber:columnNumber)'
173 var attempt1 = /at .+ \((.+):(\d+):(?:\d+)\)$/.exec(stackLine);
174 if (attempt1) { return [attempt1[1], Number(attempt1[2])]; }
175
176 // Anonymous functions: 'at filename:lineNumber:columnNumber'
177 var attempt2 = /at ([^ ]+):(\d+):(?:\d+)$/.exec(stackLine);
178 if (attempt2) { return [attempt2[1], Number(attempt2[2])]; }
179
180 // Firefox style: 'function@filename:lineNumber or @filename:lineNumber'
181 var attempt3 = /.*@(.+):(\d+)$/.exec(stackLine);
182 if (attempt3) { return [attempt3[1], Number(attempt3[2])]; }
183 }
184
185 var hasProp = {}.hasOwnProperty,
186 slice = Array.prototype.slice;
187
188 var inherits = Rx.internals.inherits = function (child, parent) {
189 function __() { this.constructor = child; }
190 __.prototype = parent.prototype;
191 child.prototype = new __();
192 };
193
194 var addProperties = Rx.internals.addProperties = function (obj) {
195 for(var sources = [], i = 1, len = arguments.length; i < len; i++) { sources.push(arguments[i]); }
196 for (var idx = 0, ln = sources.length; idx < ln; idx++) {
197 var source = sources[idx];
198 for (var prop in source) {
199 obj[prop] = source[prop];
200 }
201 }
202 };
203
204 // Rx Utils
205 var addRef = Rx.internals.addRef = function (xs, r) {
206 return new AnonymousObservable(function (observer) {
207 return new BinaryDisposable(r.getDisposable(), xs.subscribe(observer));
208 });
209 };
210
211 function arrayInitialize(count, factory) {
212 var a = new Array(count);
213 for (var i = 0; i < count; i++) {
214 a[i] = factory();
215 }
216 return a;
217 }
218
219 /**
220 * Represents a group of disposable resources that are disposed together.
221 * @constructor
222 */
223 var CompositeDisposable = Rx.CompositeDisposable = function () {
224 var args = [], i, len;
225 if (Array.isArray(arguments[0])) {
226 args = arguments[0];
227 } else {
228 len = arguments.length;
229 args = new Array(len);
230 for(i = 0; i < len; i++) { args[i] = arguments[i]; }
231 }
232 this.disposables = args;
233 this.isDisposed = false;
234 this.length = args.length;
235 };
236
237 var CompositeDisposablePrototype = CompositeDisposable.prototype;
238
239 /**
240 * Adds a disposable to the CompositeDisposable or disposes the disposable if the CompositeDisposable is disposed.
241 * @param {Mixed} item Disposable to add.
242 */
243 CompositeDisposablePrototype.add = function (item) {
244 if (this.isDisposed) {
245 item.dispose();
246 } else {
247 this.disposables.push(item);
248 this.length++;
249 }
250 };
251
252 /**
253 * Removes and disposes the first occurrence of a disposable from the CompositeDisposable.
254 * @param {Mixed} item Disposable to remove.
255 * @returns {Boolean} true if found; false otherwise.
256 */
257 CompositeDisposablePrototype.remove = function (item) {
258 var shouldDispose = false;
259 if (!this.isDisposed) {
260 var idx = this.disposables.indexOf(item);
261 if (idx !== -1) {
262 shouldDispose = true;
263 this.disposables.splice(idx, 1);
264 this.length--;
265 item.dispose();
266 }
267 }
268 return shouldDispose;
269 };
270
271 /**
272 * Disposes all disposables in the group and removes them from the group.
273 */
274 CompositeDisposablePrototype.dispose = function () {
275 if (!this.isDisposed) {
276 this.isDisposed = true;
277 var len = this.disposables.length, currentDisposables = new Array(len);
278 for(var i = 0; i < len; i++) { currentDisposables[i] = this.disposables[i]; }
279 this.disposables = [];
280 this.length = 0;
281
282 for (i = 0; i < len; i++) {
283 currentDisposables[i].dispose();
284 }
285 }
286 };
287
288 /**
289 * Provides a set of static methods for creating Disposables.
290 * @param {Function} dispose Action to run during the first call to dispose. The action is guaranteed to be run at most once.
291 */
292 var Disposable = Rx.Disposable = function (action) {
293 this.isDisposed = false;
294 this.action = action || noop;
295 };
296
297 /** Performs the task of cleaning up resources. */
298 Disposable.prototype.dispose = function () {
299 if (!this.isDisposed) {
300 this.action();
301 this.isDisposed = true;
302 }
303 };
304
305 /**
306 * Creates a disposable object that invokes the specified action when disposed.
307 * @param {Function} dispose Action to run during the first call to dispose. The action is guaranteed to be run at most once.
308 * @return {Disposable} The disposable object that runs the given action upon disposal.
309 */
310 var disposableCreate = Disposable.create = function (action) { return new Disposable(action); };
311
312 /**
313 * Gets the disposable that does nothing when disposed.
314 */
315 var disposableEmpty = Disposable.empty = { dispose: noop };
316
317 /**
318 * Validates whether the given object is a disposable
319 * @param {Object} Object to test whether it has a dispose method
320 * @returns {Boolean} true if a disposable object, else false.
321 */
322 var isDisposable = Disposable.isDisposable = function (d) {
323 return d && isFunction(d.dispose);
324 };
325
326 var checkDisposed = Disposable.checkDisposed = function (disposable) {
327 if (disposable.isDisposed) { throw new ObjectDisposedError(); }
328 };
329
330 var disposableFixup = Disposable._fixup = function (result) {
331 return isDisposable(result) ? result : disposableEmpty;
332 };
333
334 // Single assignment
335 var SingleAssignmentDisposable = Rx.SingleAssignmentDisposable = function () {
336 this.isDisposed = false;
337 this.current = null;
338 };
339 SingleAssignmentDisposable.prototype.getDisposable = function () {
340 return this.current;
341 };
342 SingleAssignmentDisposable.prototype.setDisposable = function (value) {
343 if (this.current) { throw new Error('Disposable has already been assigned'); }
344 var shouldDispose = this.isDisposed;
345 !shouldDispose && (this.current = value);
346 shouldDispose && value && value.dispose();
347 };
348 SingleAssignmentDisposable.prototype.dispose = function () {
349 if (!this.isDisposed) {
350 this.isDisposed = true;
351 var old = this.current;
352 this.current = null;
353 old && old.dispose();
354 }
355 };
356
357 // Multiple assignment disposable
358 var SerialDisposable = Rx.SerialDisposable = function () {
359 this.isDisposed = false;
360 this.current = null;
361 };
362 SerialDisposable.prototype.getDisposable = function () {
363 return this.current;
364 };
365 SerialDisposable.prototype.setDisposable = function (value) {
366 var shouldDispose = this.isDisposed;
367 if (!shouldDispose) {
368 var old = this.current;
369 this.current = value;
370 }
371 old && old.dispose();
372 shouldDispose && value && value.dispose();
373 };
374 SerialDisposable.prototype.dispose = function () {
375 if (!this.isDisposed) {
376 this.isDisposed = true;
377 var old = this.current;
378 this.current = null;
379 }
380 old && old.dispose();
381 };
382
383 var BinaryDisposable = Rx.BinaryDisposable = function (first, second) {
384 this._first = first;
385 this._second = second;
386 this.isDisposed = false;
387 };
388
389 BinaryDisposable.prototype.dispose = function () {
390 if (!this.isDisposed) {
391 this.isDisposed = true;
392 var old1 = this._first;
393 this._first = null;
394 old1 && old1.dispose();
395 var old2 = this._second;
396 this._second = null;
397 old2 && old2.dispose();
398 }
399 };
400
401 var NAryDisposable = Rx.NAryDisposable = function (disposables) {
402 this._disposables = disposables;
403 this.isDisposed = false;
404 };
405
406 NAryDisposable.prototype.dispose = function () {
407 if (!this.isDisposed) {
408 this.isDisposed = true;
409 for (var i = 0, len = this._disposables.length; i < len; i++) {
410 this._disposables[i].dispose();
411 }
412 this._disposables.length = 0;
413 }
414 };
415
416 var ScheduledItem = Rx.internals.ScheduledItem = function (scheduler, state, action, dueTime, comparer) {
417 this.scheduler = scheduler;
418 this.state = state;
419 this.action = action;
420 this.dueTime = dueTime;
421 this.comparer = comparer || defaultSubComparer;
422 this.disposable = new SingleAssignmentDisposable();
423 };
424
425 ScheduledItem.prototype.invoke = function () {
426 this.disposable.setDisposable(this.invokeCore());
427 };
428
429 ScheduledItem.prototype.compareTo = function (other) {
430 return this.comparer(this.dueTime, other.dueTime);
431 };
432
433 ScheduledItem.prototype.isCancelled = function () {
434 return this.disposable.isDisposed;
435 };
436
437 ScheduledItem.prototype.invokeCore = function () {
438 return disposableFixup(this.action(this.scheduler, this.state));
439 };
440
441 /** Provides a set of static properties to access commonly used schedulers. */
442 var Scheduler = Rx.Scheduler = (function () {
443
444 function Scheduler() { }
445
446 /** Determines whether the given object is a scheduler */
447 Scheduler.isScheduler = function (s) {
448 return s instanceof Scheduler;
449 };
450
451 var schedulerProto = Scheduler.prototype;
452
453 /**
454 * Schedules an action to be executed.
455 * @param state State passed to the action to be executed.
456 * @param {Function} action Action to be executed.
457 * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
458 */
459 schedulerProto.schedule = function (state, action) {
460 throw new NotImplementedError();
461 };
462
463 /**
464 * Schedules an action to be executed after dueTime.
465 * @param state State passed to the action to be executed.
466 * @param {Function} action Action to be executed.
467 * @param {Number} dueTime Relative time after which to execute the action.
468 * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
469 */
470 schedulerProto.scheduleFuture = function (state, dueTime, action) {
471 var dt = dueTime;
472 dt instanceof Date && (dt = dt - this.now());
473 dt = Scheduler.normalize(dt);
474
475 if (dt === 0) { return this.schedule(state, action); }
476
477 return this._scheduleFuture(state, dt, action);
478 };
479
480 schedulerProto._scheduleFuture = function (state, dueTime, action) {
481 throw new NotImplementedError();
482 };
483
484 /** Gets the current time according to the local machine's system clock. */
485 Scheduler.now = defaultNow;
486
487 /** Gets the current time according to the local machine's system clock. */
488 Scheduler.prototype.now = defaultNow;
489
490 /**
491 * Normalizes the specified TimeSpan value to a positive value.
492 * @param {Number} timeSpan The time span value to normalize.
493 * @returns {Number} The specified TimeSpan value if it is zero or positive; otherwise, 0
494 */
495 Scheduler.normalize = function (timeSpan) {
496 timeSpan < 0 && (timeSpan = 0);
497 return timeSpan;
498 };
499
500 return Scheduler;
501 }());
502
503 var normalizeTime = Scheduler.normalize, isScheduler = Scheduler.isScheduler;
504
505 (function (schedulerProto) {
506
507 function invokeRecImmediate(scheduler, pair) {
508 var state = pair[0], action = pair[1], group = new CompositeDisposable();
509 action(state, innerAction);
510 return group;
511
512 function innerAction(state2) {
513 var isAdded = false, isDone = false;
514
515 var d = scheduler.schedule(state2, scheduleWork);
516 if (!isDone) {
517 group.add(d);
518 isAdded = true;
519 }
520
521 function scheduleWork(_, state3) {
522 if (isAdded) {
523 group.remove(d);
524 } else {
525 isDone = true;
526 }
527 action(state3, innerAction);
528 return disposableEmpty;
529 }
530 }
531 }
532
533 function invokeRecDate(scheduler, pair) {
534 var state = pair[0], action = pair[1], group = new CompositeDisposable();
535 action(state, innerAction);
536 return group;
537
538 function innerAction(state2, dueTime1) {
539 var isAdded = false, isDone = false;
540
541 var d = scheduler.scheduleFuture(state2, dueTime1, scheduleWork);
542 if (!isDone) {
543 group.add(d);
544 isAdded = true;
545 }
546
547 function scheduleWork(_, state3) {
548 if (isAdded) {
549 group.remove(d);
550 } else {
551 isDone = true;
552 }
553 action(state3, innerAction);
554 return disposableEmpty;
555 }
556 }
557 }
558
559 /**
560 * Schedules an action to be executed recursively.
561 * @param {Mixed} state State passed to the action to be executed.
562 * @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.
563 * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
564 */
565 schedulerProto.scheduleRecursive = function (state, action) {
566 return this.schedule([state, action], invokeRecImmediate);
567 };
568
569 /**
570 * Schedules an action to be executed recursively after a specified relative or absolute due time.
571 * @param {Mixed} state State passed to the action to be executed.
572 * @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.
573 * @param {Number | Date} dueTime Relative or absolute time after which to execute the action for the first time.
574 * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
575 */
576 schedulerProto.scheduleRecursiveFuture = function (state, dueTime, action) {
577 return this.scheduleFuture([state, action], dueTime, invokeRecDate);
578 };
579
580 }(Scheduler.prototype));
581
582 (function (schedulerProto) {
583
584 /**
585 * 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.
586 * @param {Mixed} state Initial state passed to the action upon the first iteration.
587 * @param {Number} period Period for running the work periodically.
588 * @param {Function} action Action to be executed, potentially updating the state.
589 * @returns {Disposable} The disposable object used to cancel the scheduled recurring action (best effort).
590 */
591 schedulerProto.schedulePeriodic = function(state, period, action) {
592 if (typeof root.setInterval === 'undefined') { throw new NotSupportedError(); }
593 period = normalizeTime(period);
594 var s = state, id = root.setInterval(function () { s = action(s); }, period);
595 return disposableCreate(function () { root.clearInterval(id); });
596 };
597
598 }(Scheduler.prototype));
599
600 var SchedulePeriodicRecursive = Rx.internals.SchedulePeriodicRecursive = (function () {
601 function createTick(self) {
602 return function tick(command, recurse) {
603 recurse(0, self._period);
604 var state = tryCatch(self._action)(self._state);
605 if (state === errorObj) {
606 self._cancel.dispose();
607 thrower(state.e);
608 }
609 self._state = state;
610 };
611 }
612
613 function SchedulePeriodicRecursive(scheduler, state, period, action) {
614 this._scheduler = scheduler;
615 this._state = state;
616 this._period = period;
617 this._action = action;
618 }
619
620 SchedulePeriodicRecursive.prototype.start = function () {
621 var d = new SingleAssignmentDisposable();
622 this._cancel = d;
623 d.setDisposable(this._scheduler.scheduleRecursiveFuture(0, this._period, createTick(this)));
624
625 return d;
626 };
627
628 return SchedulePeriodicRecursive;
629 }());
630
631 /** Gets a scheduler that schedules work immediately on the current thread. */
632 var ImmediateScheduler = (function (__super__) {
633 inherits(ImmediateScheduler, __super__);
634 function ImmediateScheduler() {
635 __super__.call(this);
636 }
637
638 ImmediateScheduler.prototype.schedule = function (state, action) {
639 return disposableFixup(action(this, state));
640 };
641
642 return ImmediateScheduler;
643 }(Scheduler));
644
645 var immediateScheduler = Scheduler.immediate = new ImmediateScheduler();
646
647 /**
648 * Gets a scheduler that schedules work as soon as possible on the current thread.
649 */
650 var CurrentThreadScheduler = (function (__super__) {
651 var queue;
652
653 function runTrampoline () {
654 while (queue.length > 0) {
655 var item = queue.dequeue();
656 !item.isCancelled() && item.invoke();
657 }
658 }
659
660 inherits(CurrentThreadScheduler, __super__);
661 function CurrentThreadScheduler() {
662 __super__.call(this);
663 }
664
665 CurrentThreadScheduler.prototype.schedule = function (state, action) {
666 var si = new ScheduledItem(this, state, action, this.now());
667
668 if (!queue) {
669 queue = new PriorityQueue(4);
670 queue.enqueue(si);
671
672 var result = tryCatch(runTrampoline)();
673 queue = null;
674 if (result === errorObj) { thrower(result.e); }
675 } else {
676 queue.enqueue(si);
677 }
678 return si.disposable;
679 };
680
681 CurrentThreadScheduler.prototype.scheduleRequired = function () { return !queue; };
682
683 return CurrentThreadScheduler;
684 }(Scheduler));
685
686 var currentThreadScheduler = Scheduler.currentThread = new CurrentThreadScheduler();
687
688 var scheduleMethod, clearMethod;
689
690 var localTimer = (function () {
691 var localSetTimeout, localClearTimeout = noop;
692 if (!!root.setTimeout) {
693 localSetTimeout = root.setTimeout;
694 localClearTimeout = root.clearTimeout;
695 } else if (!!root.WScript) {
696 localSetTimeout = function (fn, time) {
697 root.WScript.Sleep(time);
698 fn();
699 };
700 } else {
701 throw new NotSupportedError();
702 }
703
704 return {
705 setTimeout: localSetTimeout,
706 clearTimeout: localClearTimeout
707 };
708 }());
709 var localSetTimeout = localTimer.setTimeout,
710 localClearTimeout = localTimer.clearTimeout;
711
712 (function () {
713
714 var nextHandle = 1, tasksByHandle = {}, currentlyRunning = false;
715
716 clearMethod = function (handle) {
717 delete tasksByHandle[handle];
718 };
719
720 function runTask(handle) {
721 if (currentlyRunning) {
722 localSetTimeout(function () { runTask(handle); }, 0);
723 } else {
724 var task = tasksByHandle[handle];
725 if (task) {
726 currentlyRunning = true;
727 var result = tryCatch(task)();
728 clearMethod(handle);
729 currentlyRunning = false;
730 if (result === errorObj) { thrower(result.e); }
731 }
732 }
733 }
734
735 var reNative = new RegExp('^' +
736 String(toString)
737 .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
738 .replace(/toString| for [^\]]+/g, '.*?') + '$'
739 );
740
741 var setImmediate = typeof (setImmediate = freeGlobal && moduleExports && freeGlobal.setImmediate) == 'function' &&
742 !reNative.test(setImmediate) && setImmediate;
743
744 function postMessageSupported () {
745 // Ensure not in a worker
746 if (!root.postMessage || root.importScripts) { return false; }
747 var isAsync = false, oldHandler = root.onmessage;
748 // Test for async
749 root.onmessage = function () { isAsync = true; };
750 root.postMessage('', '*');
751 root.onmessage = oldHandler;
752
753 return isAsync;
754 }
755
756 // Use in order, setImmediate, nextTick, postMessage, MessageChannel, script readystatechanged, setTimeout
757 if (isFunction(setImmediate)) {
758 scheduleMethod = function (action) {
759 var id = nextHandle++;
760 tasksByHandle[id] = action;
761 setImmediate(function () { runTask(id); });
762
763 return id;
764 };
765 } else if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
766 scheduleMethod = function (action) {
767 var id = nextHandle++;
768 tasksByHandle[id] = action;
769 process.nextTick(function () { runTask(id); });
770
771 return id;
772 };
773 } else if (postMessageSupported()) {
774 var MSG_PREFIX = 'ms.rx.schedule' + Math.random();
775
776 var onGlobalPostMessage = function (event) {
777 // Only if we're a match to avoid any other global events
778 if (typeof event.data === 'string' && event.data.substring(0, MSG_PREFIX.length) === MSG_PREFIX) {
779 runTask(event.data.substring(MSG_PREFIX.length));
780 }
781 };
782
783 root.addEventListener('message', onGlobalPostMessage, false);
784
785 scheduleMethod = function (action) {
786 var id = nextHandle++;
787 tasksByHandle[id] = action;
788 root.postMessage(MSG_PREFIX + currentId, '*');
789 return id;
790 };
791 } else if (!!root.MessageChannel) {
792 var channel = new root.MessageChannel();
793
794 channel.port1.onmessage = function (e) { runTask(e.data); };
795
796 scheduleMethod = function (action) {
797 var id = nextHandle++;
798 tasksByHandle[id] = action;
799 channel.port2.postMessage(id);
800 return id;
801 };
802 } else if ('document' in root && 'onreadystatechange' in root.document.createElement('script')) {
803
804 scheduleMethod = function (action) {
805 var scriptElement = root.document.createElement('script');
806 var id = nextHandle++;
807 tasksByHandle[id] = action;
808
809 scriptElement.onreadystatechange = function () {
810 runTask(id);
811 scriptElement.onreadystatechange = null;
812 scriptElement.parentNode.removeChild(scriptElement);
813 scriptElement = null;
814 };
815 root.document.documentElement.appendChild(scriptElement);
816 return id;
817 };
818
819 } else {
820 scheduleMethod = function (action) {
821 var id = nextHandle++;
822 tasksByHandle[id] = action;
823 localSetTimeout(function () {
824 runTask(id);
825 }, 0);
826
827 return id;
828 };
829 }
830 }());
831
832 /**
833 * Gets a scheduler that schedules work via a timed callback based upon platform.
834 */
835 var DefaultScheduler = (function (__super__) {
836 inherits(DefaultScheduler, __super__);
837 function DefaultScheduler() {
838 __super__.call(this);
839 }
840
841 function scheduleAction(disposable, action, scheduler, state) {
842 return function schedule() {
843 disposable.setDisposable(Disposable._fixup(action(scheduler, state)));
844 };
845 }
846
847 function ClearDisposable(id) {
848 this._id = id;
849 this.isDisposed = false;
850 }
851
852 ClearDisposable.prototype.dispose = function () {
853 if (!this.isDisposed) {
854 this.isDisposed = true;
855 clearMethod(this._id);
856 }
857 };
858
859 function LocalClearDisposable(id) {
860 this._id = id;
861 this.isDisposed = false;
862 }
863
864 LocalClearDisposable.prototype.dispose = function () {
865 if (!this.isDisposed) {
866 this.isDisposed = true;
867 localClearTimeout(this._id);
868 }
869 };
870
871 DefaultScheduler.prototype.schedule = function (state, action) {
872 var disposable = new SingleAssignmentDisposable(),
873 id = scheduleMethod(scheduleAction(disposable, action, this, state));
874 return new BinaryDisposable(disposable, new ClearDisposable(id));
875 };
876
877 DefaultScheduler.prototype._scheduleFuture = function (state, dueTime, action) {
878 if (dueTime === 0) { return this.schedule(state, action); }
879 var disposable = new SingleAssignmentDisposable(),
880 id = localSetTimeout(scheduleAction(disposable, action, this, state), dueTime);
881 return new BinaryDisposable(disposable, new LocalClearDisposable(id));
882 };
883
884 return DefaultScheduler;
885 }(Scheduler));
886
887 var defaultScheduler = Scheduler['default'] = Scheduler.async = new DefaultScheduler();
888
889 function IndexedItem(id, value) {
890 this.id = id;
891 this.value = value;
892 }
893
894 IndexedItem.prototype.compareTo = function (other) {
895 var c = this.value.compareTo(other.value);
896 c === 0 && (c = this.id - other.id);
897 return c;
898 };
899
900 var PriorityQueue = Rx.internals.PriorityQueue = function (capacity) {
901 this.items = new Array(capacity);
902 this.length = 0;
903 };
904
905 var priorityProto = PriorityQueue.prototype;
906 priorityProto.isHigherPriority = function (left, right) {
907 return this.items[left].compareTo(this.items[right]) < 0;
908 };
909
910 priorityProto.percolate = function (index) {
911 if (index >= this.length || index < 0) { return; }
912 var parent = index - 1 >> 1;
913 if (parent < 0 || parent === index) { return; }
914 if (this.isHigherPriority(index, parent)) {
915 var temp = this.items[index];
916 this.items[index] = this.items[parent];
917 this.items[parent] = temp;
918 this.percolate(parent);
919 }
920 };
921
922 priorityProto.heapify = function (index) {
923 +index || (index = 0);
924 if (index >= this.length || index < 0) { return; }
925 var left = 2 * index + 1,
926 right = 2 * index + 2,
927 first = index;
928 if (left < this.length && this.isHigherPriority(left, first)) {
929 first = left;
930 }
931 if (right < this.length && this.isHigherPriority(right, first)) {
932 first = right;
933 }
934 if (first !== index) {
935 var temp = this.items[index];
936 this.items[index] = this.items[first];
937 this.items[first] = temp;
938 this.heapify(first);
939 }
940 };
941
942 priorityProto.peek = function () { return this.items[0].value; };
943
944 priorityProto.removeAt = function (index) {
945 this.items[index] = this.items[--this.length];
946 this.items[this.length] = undefined;
947 this.heapify();
948 };
949
950 priorityProto.dequeue = function () {
951 var result = this.peek();
952 this.removeAt(0);
953 return result;
954 };
955
956 priorityProto.enqueue = function (item) {
957 var index = this.length++;
958 this.items[index] = new IndexedItem(PriorityQueue.count++, item);
959 this.percolate(index);
960 };
961
962 priorityProto.remove = function (item) {
963 for (var i = 0; i < this.length; i++) {
964 if (this.items[i].value === item) {
965 this.removeAt(i);
966 return true;
967 }
968 }
969 return false;
970 };
971 PriorityQueue.count = 0;
972
973 /**
974 * Supports push-style iteration over an observable sequence.
975 */
976 var Observer = Rx.Observer = function () { };
977
978 /**
979 * Creates an observer from the specified OnNext, along with optional OnError, and OnCompleted actions.
980 * @param {Function} [onNext] Observer's OnNext action implementation.
981 * @param {Function} [onError] Observer's OnError action implementation.
982 * @param {Function} [onCompleted] Observer's OnCompleted action implementation.
983 * @returns {Observer} The observer object implemented using the given actions.
984 */
985 var observerCreate = Observer.create = function (onNext, onError, onCompleted) {
986 onNext || (onNext = noop);
987 onError || (onError = defaultError);
988 onCompleted || (onCompleted = noop);
989 return new AnonymousObserver(onNext, onError, onCompleted);
990 };
991
992 /**
993 * Abstract base class for implementations of the Observer class.
994 * This base class enforces the grammar of observers where OnError and OnCompleted are terminal messages.
995 */
996 var AbstractObserver = Rx.internals.AbstractObserver = (function (__super__) {
997 inherits(AbstractObserver, __super__);
998
999 /**
1000 * Creates a new observer in a non-stopped state.
1001 */
1002 function AbstractObserver() {
1003 this.isStopped = false;
1004 }
1005
1006 // Must be implemented by other observers
1007 AbstractObserver.prototype.next = notImplemented;
1008 AbstractObserver.prototype.error = notImplemented;
1009 AbstractObserver.prototype.completed = notImplemented;
1010
1011 /**
1012 * Notifies the observer of a new element in the sequence.
1013 * @param {Any} value Next element in the sequence.
1014 */
1015 AbstractObserver.prototype.onNext = function (value) {
1016 !this.isStopped && this.next(value);
1017 };
1018
1019 /**
1020 * Notifies the observer that an exception has occurred.
1021 * @param {Any} error The error that has occurred.
1022 */
1023 AbstractObserver.prototype.onError = function (error) {
1024 if (!this.isStopped) {
1025 this.isStopped = true;
1026 this.error(error);
1027 }
1028 };
1029
1030 /**
1031 * Notifies the observer of the end of the sequence.
1032 */
1033 AbstractObserver.prototype.onCompleted = function () {
1034 if (!this.isStopped) {
1035 this.isStopped = true;
1036 this.completed();
1037 }
1038 };
1039
1040 /**
1041 * Disposes the observer, causing it to transition to the stopped state.
1042 */
1043 AbstractObserver.prototype.dispose = function () { this.isStopped = true; };
1044
1045 AbstractObserver.prototype.fail = function (e) {
1046 if (!this.isStopped) {
1047 this.isStopped = true;
1048 this.error(e);
1049 return true;
1050 }
1051
1052 return false;
1053 };
1054
1055 return AbstractObserver;
1056 }(Observer));
1057
1058 /**
1059 * Class to create an Observer instance from delegate-based implementations of the on* methods.
1060 */
1061 var AnonymousObserver = Rx.AnonymousObserver = (function (__super__) {
1062 inherits(AnonymousObserver, __super__);
1063
1064 /**
1065 * Creates an observer from the specified OnNext, OnError, and OnCompleted actions.
1066 * @param {Any} onNext Observer's OnNext action implementation.
1067 * @param {Any} onError Observer's OnError action implementation.
1068 * @param {Any} onCompleted Observer's OnCompleted action implementation.
1069 */
1070 function AnonymousObserver(onNext, onError, onCompleted) {
1071 __super__.call(this);
1072 this._onNext = onNext;
1073 this._onError = onError;
1074 this._onCompleted = onCompleted;
1075 }
1076
1077 /**
1078 * Calls the onNext action.
1079 * @param {Any} value Next element in the sequence.
1080 */
1081 AnonymousObserver.prototype.next = function (value) {
1082 this._onNext(value);
1083 };
1084
1085 /**
1086 * Calls the onError action.
1087 * @param {Any} error The error that has occurred.
1088 */
1089 AnonymousObserver.prototype.error = function (error) {
1090 this._onError(error);
1091 };
1092
1093 /**
1094 * Calls the onCompleted action.
1095 */
1096 AnonymousObserver.prototype.completed = function () {
1097 this._onCompleted();
1098 };
1099
1100 return AnonymousObserver;
1101 }(AbstractObserver));
1102
1103 var observableProto;
1104
1105 /**
1106 * Represents a push-style collection.
1107 */
1108 var Observable = Rx.Observable = (function () {
1109
1110 function makeSubscribe(self, subscribe) {
1111 return function (o) {
1112 var oldOnError = o.onError;
1113 o.onError = function (e) {
1114 makeStackTraceLong(e, self);
1115 oldOnError.call(o, e);
1116 };
1117
1118 return subscribe.call(self, o);
1119 };
1120 }
1121
1122 function Observable() {
1123 if (Rx.config.longStackSupport && hasStacks) {
1124 var oldSubscribe = this._subscribe;
1125 var e = tryCatch(thrower)(new Error()).e;
1126 this.stack = e.stack.substring(e.stack.indexOf('\n') + 1);
1127 this._subscribe = makeSubscribe(this, oldSubscribe);
1128 }
1129 }
1130
1131 observableProto = Observable.prototype;
1132
1133 /**
1134 * Determines whether the given object is an Observable
1135 * @param {Any} An object to determine whether it is an Observable
1136 * @returns {Boolean} true if an Observable, else false.
1137 */
1138 Observable.isObservable = function (o) {
1139 return o && isFunction(o.subscribe);
1140 };
1141
1142 /**
1143 * Subscribes an o to the observable sequence.
1144 * @param {Mixed} [oOrOnNext] The object that is to receive notifications or an action to invoke for each element in the observable sequence.
1145 * @param {Function} [onError] Action to invoke upon exceptional termination of the observable sequence.
1146 * @param {Function} [onCompleted] Action to invoke upon graceful termination of the observable sequence.
1147 * @returns {Diposable} A disposable handling the subscriptions and unsubscriptions.
1148 */
1149 observableProto.subscribe = observableProto.forEach = function (oOrOnNext, onError, onCompleted) {
1150 return this._subscribe(typeof oOrOnNext === 'object' ?
1151 oOrOnNext :
1152 observerCreate(oOrOnNext, onError, onCompleted));
1153 };
1154
1155 /**
1156 * Subscribes to the next value in the sequence with an optional "this" argument.
1157 * @param {Function} onNext The function to invoke on each element in the observable sequence.
1158 * @param {Any} [thisArg] Object to use as this when executing callback.
1159 * @returns {Disposable} A disposable handling the subscriptions and unsubscriptions.
1160 */
1161 observableProto.subscribeOnNext = function (onNext, thisArg) {
1162 return this._subscribe(observerCreate(typeof thisArg !== 'undefined' ? function(x) { onNext.call(thisArg, x); } : onNext));
1163 };
1164
1165 /**
1166 * Subscribes to an exceptional condition in the sequence with an optional "this" argument.
1167 * @param {Function} onError The function to invoke upon exceptional termination of the observable sequence.
1168 * @param {Any} [thisArg] Object to use as this when executing callback.
1169 * @returns {Disposable} A disposable handling the subscriptions and unsubscriptions.
1170 */
1171 observableProto.subscribeOnError = function (onError, thisArg) {
1172 return this._subscribe(observerCreate(null, typeof thisArg !== 'undefined' ? function(e) { onError.call(thisArg, e); } : onError));
1173 };
1174
1175 /**
1176 * Subscribes to the next value in the sequence with an optional "this" argument.
1177 * @param {Function} onCompleted The function to invoke upon graceful termination of the observable sequence.
1178 * @param {Any} [thisArg] Object to use as this when executing callback.
1179 * @returns {Disposable} A disposable handling the subscriptions and unsubscriptions.
1180 */
1181 observableProto.subscribeOnCompleted = function (onCompleted, thisArg) {
1182 return this._subscribe(observerCreate(null, null, typeof thisArg !== 'undefined' ? function() { onCompleted.call(thisArg); } : onCompleted));
1183 };
1184
1185 return Observable;
1186 })();
1187
1188 var AnonymousObservable = Rx.AnonymousObservable = (function (__super__) {
1189 inherits(AnonymousObservable, __super__);
1190
1191 // Fix subscriber to check for undefined or function returned to decorate as Disposable
1192 function fixSubscriber(subscriber) {
1193 return subscriber && isFunction(subscriber.dispose) ? subscriber :
1194 isFunction(subscriber) ? disposableCreate(subscriber) : disposableEmpty;
1195 }
1196
1197 function setDisposable(s, state) {
1198 var ado = state[0], self = state[1];
1199 var sub = tryCatch(self.__subscribe).call(self, ado);
1200 if (sub === errorObj && !ado.fail(errorObj.e)) { thrower(errorObj.e); }
1201 ado.setDisposable(fixSubscriber(sub));
1202 }
1203
1204 function AnonymousObservable(subscribe, parent) {
1205 this.source = parent;
1206 this.__subscribe = subscribe;
1207 __super__.call(this);
1208 }
1209
1210 AnonymousObservable.prototype._subscribe = function (o) {
1211 var ado = new AutoDetachObserver(o), state = [ado, this];
1212
1213 if (currentThreadScheduler.scheduleRequired()) {
1214 currentThreadScheduler.schedule(state, setDisposable);
1215 } else {
1216 setDisposable(null, state);
1217 }
1218 return ado;
1219 };
1220
1221 return AnonymousObservable;
1222
1223 }(Observable));
1224
1225 var ObservableBase = Rx.ObservableBase = (function (__super__) {
1226 inherits(ObservableBase, __super__);
1227
1228 function fixSubscriber(subscriber) {
1229 return subscriber && isFunction(subscriber.dispose) ? subscriber :
1230 isFunction(subscriber) ? disposableCreate(subscriber) : disposableEmpty;
1231 }
1232
1233 function setDisposable(s, state) {
1234 var ado = state[0], self = state[1];
1235 var sub = tryCatch(self.subscribeCore).call(self, ado);
1236 if (sub === errorObj && !ado.fail(errorObj.e)) { thrower(errorObj.e); }
1237 ado.setDisposable(fixSubscriber(sub));
1238 }
1239
1240 function ObservableBase() {
1241 __super__.call(this);
1242 }
1243
1244 ObservableBase.prototype._subscribe = function (o) {
1245 var ado = new AutoDetachObserver(o), state = [ado, this];
1246
1247 if (currentThreadScheduler.scheduleRequired()) {
1248 currentThreadScheduler.schedule(state, setDisposable);
1249 } else {
1250 setDisposable(null, state);
1251 }
1252 return ado;
1253 };
1254
1255 ObservableBase.prototype.subscribeCore = notImplemented;
1256
1257 return ObservableBase;
1258 }(Observable));
1259
1260 var AutoDetachObserver = (function (__super__) {
1261 inherits(AutoDetachObserver, __super__);
1262
1263 function AutoDetachObserver(observer) {
1264 __super__.call(this);
1265 this.observer = observer;
1266 this.m = new SingleAssignmentDisposable();
1267 }
1268
1269 var AutoDetachObserverPrototype = AutoDetachObserver.prototype;
1270
1271 AutoDetachObserverPrototype.next = function (value) {
1272 var result = tryCatch(this.observer.onNext).call(this.observer, value);
1273 if (result === errorObj) {
1274 this.dispose();
1275 thrower(result.e);
1276 }
1277 };
1278
1279 AutoDetachObserverPrototype.error = function (err) {
1280 var result = tryCatch(this.observer.onError).call(this.observer, err);
1281 this.dispose();
1282 result === errorObj && thrower(result.e);
1283 };
1284
1285 AutoDetachObserverPrototype.completed = function () {
1286 var result = tryCatch(this.observer.onCompleted).call(this.observer);
1287 this.dispose();
1288 result === errorObj && thrower(result.e);
1289 };
1290
1291 AutoDetachObserverPrototype.setDisposable = function (value) { this.m.setDisposable(value); };
1292 AutoDetachObserverPrototype.getDisposable = function () { return this.m.getDisposable(); };
1293
1294 AutoDetachObserverPrototype.dispose = function () {
1295 __super__.prototype.dispose.call(this);
1296 this.m.dispose();
1297 };
1298
1299 return AutoDetachObserver;
1300 }(AbstractObserver));
1301
1302 /**
1303 * Creates an observable sequence from a specified subscribe method implementation.
1304 * @example
1305 * var res = Rx.Observable.create(function (observer) { return function () { } );
1306 * var res = Rx.Observable.create(function (observer) { return Rx.Disposable.empty; } );
1307 * var res = Rx.Observable.create(function (observer) { } );
1308 * @param {Function} subscribe Implementation of the resulting observable sequence's subscribe method, returning a function that will be wrapped in a Disposable.
1309 * @returns {Observable} The observable sequence with the specified implementation for the Subscribe method.
1310 */
1311 Observable.create = function (subscribe, parent) {
1312 return new AnonymousObservable(subscribe, parent);
1313 };
1314
1315 if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
1316 root.Rx = Rx;
1317
1318 define(function() {
1319 return Rx;
1320 });
1321 } else if (freeExports && freeModule) {
1322 // in Node.js or RingoJS
1323 if (moduleExports) {
1324 (freeModule.exports = Rx).Rx = Rx;
1325 } else {
1326 freeExports.Rx = Rx;
1327 }
1328 } else {
1329 // in a browser or Rhino
1330 root.Rx = Rx;
1331 }
1332
1333 // All code before this point will be filtered from stack traces.
1334 var rEndingLine = captureLine();
1335
1336}.call(this));