1 | 'use strict';
|
2 |
|
3 | var $ = require('../internals/export');
|
4 | var call = require('../internals/function-call');
|
5 | var DESCRIPTORS = require('../internals/descriptors');
|
6 | var setSpecies = require('../internals/set-species');
|
7 | var aCallable = require('../internals/a-callable');
|
8 | var anObject = require('../internals/an-object');
|
9 | var anInstance = require('../internals/an-instance');
|
10 | var isCallable = require('../internals/is-callable');
|
11 | var isNullOrUndefined = require('../internals/is-null-or-undefined');
|
12 | var isObject = require('../internals/is-object');
|
13 | var getMethod = require('../internals/get-method');
|
14 | var defineBuiltIn = require('../internals/define-built-in');
|
15 | var defineBuiltIns = require('../internals/define-built-ins');
|
16 | var defineBuiltInAccessor = require('../internals/define-built-in-accessor');
|
17 | var hostReportErrors = require('../internals/host-report-errors');
|
18 | var wellKnownSymbol = require('../internals/well-known-symbol');
|
19 | var InternalStateModule = require('../internals/internal-state');
|
20 |
|
21 | var $$OBSERVABLE = wellKnownSymbol('observable');
|
22 | var OBSERVABLE = 'Observable';
|
23 | var SUBSCRIPTION = 'Subscription';
|
24 | var SUBSCRIPTION_OBSERVER = 'SubscriptionObserver';
|
25 | var getterFor = InternalStateModule.getterFor;
|
26 | var setInternalState = InternalStateModule.set;
|
27 | var getObservableInternalState = getterFor(OBSERVABLE);
|
28 | var getSubscriptionInternalState = getterFor(SUBSCRIPTION);
|
29 | var getSubscriptionObserverInternalState = getterFor(SUBSCRIPTION_OBSERVER);
|
30 |
|
31 | var SubscriptionState = function (observer) {
|
32 | this.observer = anObject(observer);
|
33 | this.cleanup = undefined;
|
34 | this.subscriptionObserver = undefined;
|
35 | };
|
36 |
|
37 | SubscriptionState.prototype = {
|
38 | type: SUBSCRIPTION,
|
39 | clean: function () {
|
40 | var cleanup = this.cleanup;
|
41 | if (cleanup) {
|
42 | this.cleanup = undefined;
|
43 | try {
|
44 | cleanup();
|
45 | } catch (error) {
|
46 | hostReportErrors(error);
|
47 | }
|
48 | }
|
49 | },
|
50 | close: function () {
|
51 | if (!DESCRIPTORS) {
|
52 | var subscription = this.facade;
|
53 | var subscriptionObserver = this.subscriptionObserver;
|
54 | subscription.closed = true;
|
55 | if (subscriptionObserver) subscriptionObserver.closed = true;
|
56 | } this.observer = undefined;
|
57 | },
|
58 | isClosed: function () {
|
59 | return this.observer === undefined;
|
60 | }
|
61 | };
|
62 |
|
63 | var Subscription = function (observer, subscriber) {
|
64 | var subscriptionState = setInternalState(this, new SubscriptionState(observer));
|
65 | var start;
|
66 | if (!DESCRIPTORS) this.closed = false;
|
67 | try {
|
68 | if (start = getMethod(observer, 'start')) call(start, observer, this);
|
69 | } catch (error) {
|
70 | hostReportErrors(error);
|
71 | }
|
72 | if (subscriptionState.isClosed()) return;
|
73 | var subscriptionObserver = subscriptionState.subscriptionObserver = new SubscriptionObserver(subscriptionState);
|
74 | try {
|
75 | var cleanup = subscriber(subscriptionObserver);
|
76 | var subscription = cleanup;
|
77 | if (!isNullOrUndefined(cleanup)) subscriptionState.cleanup = isCallable(cleanup.unsubscribe)
|
78 | ? function () { subscription.unsubscribe(); }
|
79 | : aCallable(cleanup);
|
80 | } catch (error) {
|
81 | subscriptionObserver.error(error);
|
82 | return;
|
83 | } if (subscriptionState.isClosed()) subscriptionState.clean();
|
84 | };
|
85 |
|
86 | Subscription.prototype = defineBuiltIns({}, {
|
87 | unsubscribe: function unsubscribe() {
|
88 | var subscriptionState = getSubscriptionInternalState(this);
|
89 | if (!subscriptionState.isClosed()) {
|
90 | subscriptionState.close();
|
91 | subscriptionState.clean();
|
92 | }
|
93 | }
|
94 | });
|
95 |
|
96 | if (DESCRIPTORS) defineBuiltInAccessor(Subscription.prototype, 'closed', {
|
97 | configurable: true,
|
98 | get: function closed() {
|
99 | return getSubscriptionInternalState(this).isClosed();
|
100 | }
|
101 | });
|
102 |
|
103 | var SubscriptionObserver = function (subscriptionState) {
|
104 | setInternalState(this, {
|
105 | type: SUBSCRIPTION_OBSERVER,
|
106 | subscriptionState: subscriptionState
|
107 | });
|
108 | if (!DESCRIPTORS) this.closed = false;
|
109 | };
|
110 |
|
111 | SubscriptionObserver.prototype = defineBuiltIns({}, {
|
112 | next: function next(value) {
|
113 | var subscriptionState = getSubscriptionObserverInternalState(this).subscriptionState;
|
114 | if (!subscriptionState.isClosed()) {
|
115 | var observer = subscriptionState.observer;
|
116 | try {
|
117 | var nextMethod = getMethod(observer, 'next');
|
118 | if (nextMethod) call(nextMethod, observer, value);
|
119 | } catch (error) {
|
120 | hostReportErrors(error);
|
121 | }
|
122 | }
|
123 | },
|
124 | error: function error(value) {
|
125 | var subscriptionState = getSubscriptionObserverInternalState(this).subscriptionState;
|
126 | if (!subscriptionState.isClosed()) {
|
127 | var observer = subscriptionState.observer;
|
128 | subscriptionState.close();
|
129 | try {
|
130 | var errorMethod = getMethod(observer, 'error');
|
131 | if (errorMethod) call(errorMethod, observer, value);
|
132 | else hostReportErrors(value);
|
133 | } catch (err) {
|
134 | hostReportErrors(err);
|
135 | } subscriptionState.clean();
|
136 | }
|
137 | },
|
138 | complete: function complete() {
|
139 | var subscriptionState = getSubscriptionObserverInternalState(this).subscriptionState;
|
140 | if (!subscriptionState.isClosed()) {
|
141 | var observer = subscriptionState.observer;
|
142 | subscriptionState.close();
|
143 | try {
|
144 | var completeMethod = getMethod(observer, 'complete');
|
145 | if (completeMethod) call(completeMethod, observer);
|
146 | } catch (error) {
|
147 | hostReportErrors(error);
|
148 | } subscriptionState.clean();
|
149 | }
|
150 | }
|
151 | });
|
152 |
|
153 | if (DESCRIPTORS) defineBuiltInAccessor(SubscriptionObserver.prototype, 'closed', {
|
154 | configurable: true,
|
155 | get: function closed() {
|
156 | return getSubscriptionObserverInternalState(this).subscriptionState.isClosed();
|
157 | }
|
158 | });
|
159 |
|
160 | var $Observable = function Observable(subscriber) {
|
161 | anInstance(this, ObservablePrototype);
|
162 | setInternalState(this, {
|
163 | type: OBSERVABLE,
|
164 | subscriber: aCallable(subscriber)
|
165 | });
|
166 | };
|
167 |
|
168 | var ObservablePrototype = $Observable.prototype;
|
169 |
|
170 | defineBuiltIns(ObservablePrototype, {
|
171 | subscribe: function subscribe(observer) {
|
172 | var length = arguments.length;
|
173 | return new Subscription(isCallable(observer) ? {
|
174 | next: observer,
|
175 | error: length > 1 ? arguments[1] : undefined,
|
176 | complete: length > 2 ? arguments[2] : undefined
|
177 | } : isObject(observer) ? observer : {}, getObservableInternalState(this).subscriber);
|
178 | }
|
179 | });
|
180 |
|
181 | defineBuiltIn(ObservablePrototype, $$OBSERVABLE, function () { return this; });
|
182 |
|
183 | $({ global: true, constructor: true, forced: true }, {
|
184 | Observable: $Observable
|
185 | });
|
186 |
|
187 | setSpecies(OBSERVABLE);
|