You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
6.2 KiB
187 lines
6.2 KiB
'use strict'; |
|
// https://github.com/tc39/proposal-observable |
|
var $ = require('../internals/export'); |
|
var call = require('../internals/function-call'); |
|
var DESCRIPTORS = require('../internals/descriptors'); |
|
var setSpecies = require('../internals/set-species'); |
|
var aCallable = require('../internals/a-callable'); |
|
var isCallable = require('../internals/is-callable'); |
|
var anObject = require('../internals/an-object'); |
|
var isObject = require('../internals/is-object'); |
|
var anInstance = require('../internals/an-instance'); |
|
var getMethod = require('../internals/get-method'); |
|
var defineBuiltIn = require('../internals/define-built-in'); |
|
var defineBuiltIns = require('../internals/define-built-ins'); |
|
var defineBuiltInAccessor = require('../internals/define-built-in-accessor'); |
|
var hostReportErrors = require('../internals/host-report-errors'); |
|
var wellKnownSymbol = require('../internals/well-known-symbol'); |
|
var InternalStateModule = require('../internals/internal-state'); |
|
var OBSERVABLE_FORCED = require('../internals/observable-forced'); |
|
|
|
var $$OBSERVABLE = wellKnownSymbol('observable'); |
|
var OBSERVABLE = 'Observable'; |
|
var SUBSCRIPTION = 'Subscription'; |
|
var SUBSCRIPTION_OBSERVER = 'SubscriptionObserver'; |
|
var getterFor = InternalStateModule.getterFor; |
|
var setInternalState = InternalStateModule.set; |
|
var getObservableInternalState = getterFor(OBSERVABLE); |
|
var getSubscriptionInternalState = getterFor(SUBSCRIPTION); |
|
var getSubscriptionObserverInternalState = getterFor(SUBSCRIPTION_OBSERVER); |
|
|
|
var SubscriptionState = function (observer) { |
|
this.observer = anObject(observer); |
|
this.cleanup = undefined; |
|
this.subscriptionObserver = undefined; |
|
}; |
|
|
|
SubscriptionState.prototype = { |
|
type: SUBSCRIPTION, |
|
clean: function () { |
|
var cleanup = this.cleanup; |
|
if (cleanup) { |
|
this.cleanup = undefined; |
|
try { |
|
cleanup(); |
|
} catch (error) { |
|
hostReportErrors(error); |
|
} |
|
} |
|
}, |
|
close: function () { |
|
if (!DESCRIPTORS) { |
|
var subscription = this.facade; |
|
var subscriptionObserver = this.subscriptionObserver; |
|
subscription.closed = true; |
|
if (subscriptionObserver) subscriptionObserver.closed = true; |
|
} this.observer = undefined; |
|
}, |
|
isClosed: function () { |
|
return this.observer === undefined; |
|
} |
|
}; |
|
|
|
var Subscription = function (observer, subscriber) { |
|
var subscriptionState = setInternalState(this, new SubscriptionState(observer)); |
|
var start; |
|
if (!DESCRIPTORS) this.closed = false; |
|
try { |
|
if (start = getMethod(observer, 'start')) call(start, observer, this); |
|
} catch (error) { |
|
hostReportErrors(error); |
|
} |
|
if (subscriptionState.isClosed()) return; |
|
var subscriptionObserver = subscriptionState.subscriptionObserver = new SubscriptionObserver(subscriptionState); |
|
try { |
|
var cleanup = subscriber(subscriptionObserver); |
|
var subscription = cleanup; |
|
if (cleanup != null) subscriptionState.cleanup = isCallable(cleanup.unsubscribe) |
|
? function () { subscription.unsubscribe(); } |
|
: aCallable(cleanup); |
|
} catch (error) { |
|
subscriptionObserver.error(error); |
|
return; |
|
} if (subscriptionState.isClosed()) subscriptionState.clean(); |
|
}; |
|
|
|
Subscription.prototype = defineBuiltIns({}, { |
|
unsubscribe: function unsubscribe() { |
|
var subscriptionState = getSubscriptionInternalState(this); |
|
if (!subscriptionState.isClosed()) { |
|
subscriptionState.close(); |
|
subscriptionState.clean(); |
|
} |
|
} |
|
}); |
|
|
|
if (DESCRIPTORS) defineBuiltInAccessor(Subscription.prototype, 'closed', { |
|
configurable: true, |
|
get: function closed() { |
|
return getSubscriptionInternalState(this).isClosed(); |
|
} |
|
}); |
|
|
|
var SubscriptionObserver = function (subscriptionState) { |
|
setInternalState(this, { |
|
type: SUBSCRIPTION_OBSERVER, |
|
subscriptionState: subscriptionState |
|
}); |
|
if (!DESCRIPTORS) this.closed = false; |
|
}; |
|
|
|
SubscriptionObserver.prototype = defineBuiltIns({}, { |
|
next: function next(value) { |
|
var subscriptionState = getSubscriptionObserverInternalState(this).subscriptionState; |
|
if (!subscriptionState.isClosed()) { |
|
var observer = subscriptionState.observer; |
|
try { |
|
var nextMethod = getMethod(observer, 'next'); |
|
if (nextMethod) call(nextMethod, observer, value); |
|
} catch (error) { |
|
hostReportErrors(error); |
|
} |
|
} |
|
}, |
|
error: function error(value) { |
|
var subscriptionState = getSubscriptionObserverInternalState(this).subscriptionState; |
|
if (!subscriptionState.isClosed()) { |
|
var observer = subscriptionState.observer; |
|
subscriptionState.close(); |
|
try { |
|
var errorMethod = getMethod(observer, 'error'); |
|
if (errorMethod) call(errorMethod, observer, value); |
|
else hostReportErrors(value); |
|
} catch (err) { |
|
hostReportErrors(err); |
|
} subscriptionState.clean(); |
|
} |
|
}, |
|
complete: function complete() { |
|
var subscriptionState = getSubscriptionObserverInternalState(this).subscriptionState; |
|
if (!subscriptionState.isClosed()) { |
|
var observer = subscriptionState.observer; |
|
subscriptionState.close(); |
|
try { |
|
var completeMethod = getMethod(observer, 'complete'); |
|
if (completeMethod) call(completeMethod, observer); |
|
} catch (error) { |
|
hostReportErrors(error); |
|
} subscriptionState.clean(); |
|
} |
|
} |
|
}); |
|
|
|
if (DESCRIPTORS) defineBuiltInAccessor(SubscriptionObserver.prototype, 'closed', { |
|
configurable: true, |
|
get: function closed() { |
|
return getSubscriptionObserverInternalState(this).subscriptionState.isClosed(); |
|
} |
|
}); |
|
|
|
var $Observable = function Observable(subscriber) { |
|
anInstance(this, ObservablePrototype); |
|
setInternalState(this, { |
|
type: OBSERVABLE, |
|
subscriber: aCallable(subscriber) |
|
}); |
|
}; |
|
|
|
var ObservablePrototype = $Observable.prototype; |
|
|
|
defineBuiltIns(ObservablePrototype, { |
|
subscribe: function subscribe(observer) { |
|
var length = arguments.length; |
|
return new Subscription(isCallable(observer) ? { |
|
next: observer, |
|
error: length > 1 ? arguments[1] : undefined, |
|
complete: length > 2 ? arguments[2] : undefined |
|
} : isObject(observer) ? observer : {}, getObservableInternalState(this).subscriber); |
|
} |
|
}); |
|
|
|
defineBuiltIn(ObservablePrototype, $$OBSERVABLE, function () { return this; }); |
|
|
|
$({ global: true, constructor: true, forced: OBSERVABLE_FORCED }, { |
|
Observable: $Observable |
|
}); |
|
|
|
setSpecies(OBSERVABLE);
|
|
|