UNPKG

13.7 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8
9function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
10
11// === Symbol Support ===
12
13var hasSymbols = function () {
14 return typeof Symbol === 'function';
15};
16var hasSymbol = function (name) {
17 return hasSymbols() && Boolean(Symbol[name]);
18};
19var getSymbol = function (name) {
20 return hasSymbol(name) ? Symbol[name] : '@@' + name;
21};
22
23if (hasSymbols() && !hasSymbol('observable')) {
24 Symbol.observable = Symbol('observable');
25}
26
27// === Abstract Operations ===
28
29function getMethod(obj, key) {
30 var value = obj[key];
31
32 if (value == null) return undefined;
33
34 if (typeof value !== 'function') throw new TypeError(value + ' is not a function');
35
36 return value;
37}
38
39function getSpecies(obj) {
40 var ctor = obj.constructor;
41 if (ctor !== undefined) {
42 ctor = ctor[getSymbol('species')];
43 if (ctor === null) {
44 ctor = undefined;
45 }
46 }
47 return ctor !== undefined ? ctor : Observable;
48}
49
50function isObservable(x) {
51 return x instanceof Observable; // SPEC: Brand check
52}
53
54function hostReportError(e) {
55 if (hostReportError.log) {
56 hostReportError.log(e);
57 } else {
58 setTimeout(function () {
59 throw e;
60 });
61 }
62}
63
64function enqueue(fn) {
65 Promise.resolve().then(function () {
66 try {
67 fn();
68 } catch (e) {
69 hostReportError(e);
70 }
71 });
72}
73
74function cleanupSubscription(subscription) {
75 var cleanup = subscription._cleanup;
76 if (cleanup === undefined) return;
77
78 subscription._cleanup = undefined;
79
80 if (!cleanup) {
81 return;
82 }
83
84 try {
85 if (typeof cleanup === 'function') {
86 cleanup();
87 } else {
88 var unsubscribe = getMethod(cleanup, 'unsubscribe');
89 if (unsubscribe) {
90 unsubscribe.call(cleanup);
91 }
92 }
93 } catch (e) {
94 hostReportError(e);
95 }
96}
97
98function closeSubscription(subscription) {
99 subscription._observer = undefined;
100 subscription._queue = undefined;
101 subscription._state = 'closed';
102}
103
104function flushSubscription(subscription) {
105 var queue = subscription._queue;
106 subscription._queue = undefined;
107 subscription._state = 'ready';
108 for (var i = 0; i < queue.length; ++i) {
109 notifySubscription(subscription, queue[i].type, queue[i].value);
110 }
111}
112
113function notifySubscription(subscription, type, value) {
114 if (subscription._state === 'closed') return;
115
116 if (subscription._state !== 'ready') {
117 if (!subscription._queue) {
118 enqueue(function () {
119 return flushSubscription(subscription);
120 });
121 subscription._queue = [];
122 }
123 subscription._queue.push({ type: type, value: value });
124 return;
125 }
126
127 var observer = subscription._observer;
128
129 try {
130 var m = getMethod(observer, type);
131 switch (type) {
132 case 'next':
133 if (m) m.call(observer, value);
134 break;
135 case 'error':
136 closeSubscription(subscription);
137 if (m) m.call(observer, value);else throw value;
138 break;
139 case 'complete':
140 closeSubscription(subscription);
141 if (m) m.call(observer);
142 break;
143 }
144 } catch (e) {
145 hostReportError(e);
146 }
147
148 if (subscription._state === 'closed') cleanupSubscription(subscription);
149}
150
151var Subscription = function () {
152 function Subscription(observer, subscriber) {
153 _classCallCheck(this, Subscription);
154
155 // ASSERT: observer is an object
156 // ASSERT: subscriber is callable
157
158 this._cleanup = undefined;
159 this._observer = observer;
160 this._queue = undefined;
161 this._state = 'initializing';
162
163 var subscriptionObserver = new SubscriptionObserver(this);
164
165 try {
166 this._cleanup = subscriber.call(undefined, subscriptionObserver);
167 } catch (e) {
168 subscriptionObserver.error(e);
169 }
170
171 if (!this._queue) this._state = 'ready';
172 }
173
174 _createClass(Subscription, [{
175 key: 'unsubscribe',
176 value: function unsubscribe() {
177 if (this._state !== 'closed') {
178 closeSubscription(this);
179 cleanupSubscription(this);
180 }
181 }
182 }, {
183 key: 'closed',
184 get: function () {
185 return this._state === 'closed';
186 }
187 }]);
188
189 return Subscription;
190}();
191
192var SubscriptionObserver = function () {
193 function SubscriptionObserver(subscription) {
194 _classCallCheck(this, SubscriptionObserver);
195
196 this._subscription = subscription;
197 }
198
199 _createClass(SubscriptionObserver, [{
200 key: 'next',
201 value: function next(value) {
202 notifySubscription(this._subscription, 'next', value);
203 }
204 }, {
205 key: 'error',
206 value: function error(value) {
207 notifySubscription(this._subscription, 'error', value);
208 }
209 }, {
210 key: 'complete',
211 value: function complete() {
212 notifySubscription(this._subscription, 'complete');
213 }
214 }, {
215 key: 'closed',
216 get: function () {
217 return this._subscription._state === 'closed';
218 }
219 }]);
220
221 return SubscriptionObserver;
222}();
223
224var Observable = exports.Observable = function () {
225 function Observable(subscriber) {
226 _classCallCheck(this, Observable);
227
228 if (!(this instanceof Observable)) throw new TypeError('Observable cannot be called as a function');
229
230 if (typeof subscriber !== 'function') throw new TypeError('Observable initializer must be a function');
231
232 this._subscriber = subscriber;
233 }
234
235 _createClass(Observable, [{
236 key: 'subscribe',
237 value: function subscribe(observer) {
238 if (typeof observer !== 'object' || observer === null) {
239 observer = {
240 next: observer,
241 error: arguments[1],
242 complete: arguments[2]
243 };
244 }
245 return new Subscription(observer, this._subscriber);
246 }
247 }, {
248 key: 'forEach',
249 value: function forEach(fn) {
250 var _this = this;
251
252 return new Promise(function (resolve, reject) {
253 if (typeof fn !== 'function') {
254 reject(new TypeError(fn + ' is not a function'));
255 return;
256 }
257
258 function done() {
259 subscription.unsubscribe();
260 resolve();
261 }
262
263 var subscription = _this.subscribe({
264 next: function (value) {
265 try {
266 fn(value, done);
267 } catch (e) {
268 reject(e);
269 subscription.unsubscribe();
270 }
271 },
272
273 error: reject,
274 complete: resolve
275 });
276 });
277 }
278 }, {
279 key: 'map',
280 value: function map(fn) {
281 var _this2 = this;
282
283 if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
284
285 var C = getSpecies(this);
286
287 return new C(function (observer) {
288 return _this2.subscribe({
289 next: function (value) {
290 try {
291 value = fn(value);
292 } catch (e) {
293 return observer.error(e);
294 }
295 observer.next(value);
296 },
297 error: function (e) {
298 observer.error(e);
299 },
300 complete: function () {
301 observer.complete();
302 }
303 });
304 });
305 }
306 }, {
307 key: 'filter',
308 value: function filter(fn) {
309 var _this3 = this;
310
311 if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
312
313 var C = getSpecies(this);
314
315 return new C(function (observer) {
316 return _this3.subscribe({
317 next: function (value) {
318 try {
319 if (!fn(value)) return;
320 } catch (e) {
321 return observer.error(e);
322 }
323 observer.next(value);
324 },
325 error: function (e) {
326 observer.error(e);
327 },
328 complete: function () {
329 observer.complete();
330 }
331 });
332 });
333 }
334 }, {
335 key: 'reduce',
336 value: function reduce(fn) {
337 var _this4 = this;
338
339 if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
340
341 var C = getSpecies(this);
342 var hasSeed = arguments.length > 1;
343 var hasValue = false;
344 var seed = arguments[1];
345 var acc = seed;
346
347 return new C(function (observer) {
348 return _this4.subscribe({
349 next: function (value) {
350 var first = !hasValue;
351 hasValue = true;
352
353 if (!first || hasSeed) {
354 try {
355 acc = fn(acc, value);
356 } catch (e) {
357 return observer.error(e);
358 }
359 } else {
360 acc = value;
361 }
362 },
363 error: function (e) {
364 observer.error(e);
365 },
366 complete: function () {
367 if (!hasValue && !hasSeed) return observer.error(new TypeError('Cannot reduce an empty sequence'));
368
369 observer.next(acc);
370 observer.complete();
371 }
372 });
373 });
374 }
375 }, {
376 key: 'concat',
377 value: function concat() {
378 var _this5 = this;
379
380 for (var _len = arguments.length, sources = Array(_len), _key = 0; _key < _len; _key++) {
381 sources[_key] = arguments[_key];
382 }
383
384 var C = getSpecies(this);
385
386 return new C(function (observer) {
387 var subscription = void 0;
388
389 function startNext(next) {
390 subscription = next.subscribe({
391 next: function (v) {
392 observer.next(v);
393 },
394 error: function (e) {
395 observer.error(e);
396 },
397 complete: function () {
398 if (sources.length === 0) {
399 subscription = undefined;
400 observer.complete();
401 } else {
402 startNext(C.from(sources.shift()));
403 }
404 }
405 });
406 }
407
408 startNext(_this5);
409
410 return function () {
411 if (subscription) {
412 subscription = undefined;
413 subscription.unsubscribe();
414 }
415 };
416 });
417 }
418 }, {
419 key: getSymbol('observable'),
420 value: function () {
421 return this;
422 }
423 }], [{
424 key: 'from',
425 value: function from(x) {
426 var C = typeof this === 'function' ? this : Observable;
427
428 if (x == null) throw new TypeError(x + ' is not an object');
429
430 var method = getMethod(x, getSymbol('observable'));
431 if (method) {
432 var observable = method.call(x);
433
434 if (Object(observable) !== observable) throw new TypeError(observable + ' is not an object');
435
436 if (isObservable(observable) && observable.constructor === C) return observable;
437
438 return new C(function (observer) {
439 return observable.subscribe(observer);
440 });
441 }
442
443 if (hasSymbol('iterator')) {
444 method = getMethod(x, getSymbol('iterator'));
445 if (method) {
446 return new C(function (observer) {
447 enqueue(function () {
448 if (observer.closed) return;
449 var _iteratorNormalCompletion = true;
450 var _didIteratorError = false;
451 var _iteratorError = undefined;
452
453 try {
454 for (var _iterator = method.call(x)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
455 var item = _step.value;
456
457 observer.next(item);
458 if (observer.closed) return;
459 }
460 } catch (err) {
461 _didIteratorError = true;
462 _iteratorError = err;
463 } finally {
464 try {
465 if (!_iteratorNormalCompletion && _iterator.return) {
466 _iterator.return();
467 }
468 } finally {
469 if (_didIteratorError) {
470 throw _iteratorError;
471 }
472 }
473 }
474
475 observer.complete();
476 });
477 });
478 }
479 }
480
481 if (Array.isArray(x)) {
482 return new C(function (observer) {
483 enqueue(function () {
484 if (observer.closed) return;
485 for (var i = 0; i < x.length; ++i) {
486 observer.next(x[i]);
487 if (observer.closed) return;
488 }
489 observer.complete();
490 });
491 });
492 }
493
494 throw new TypeError(x + ' is not observable');
495 }
496 }, {
497 key: 'of',
498 value: function of() {
499 for (var _len2 = arguments.length, items = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
500 items[_key2] = arguments[_key2];
501 }
502
503 var C = typeof this === 'function' ? this : Observable;
504
505 return new C(function (observer) {
506 enqueue(function () {
507 if (observer.closed) return;
508 for (var i = 0; i < items.length; ++i) {
509 observer.next(items[i]);
510 if (observer.closed) return;
511 }
512 observer.complete();
513 });
514 });
515 }
516 }, {
517 key: getSymbol('species'),
518 get: function () {
519 return this;
520 }
521 }]);
522
523 return Observable;
524}();
525
526if (hasSymbols()) {
527 Object.defineProperty(Observable, Symbol('extensions'), {
528 value: {
529 symbol: getSymbol('observable'),
530 hostReportError: hostReportError
531 },
532 configurabe: true
533 });
534}
\No newline at end of file