diff --git a/spec.bs b/spec.bs
index 0ada9c8..69c5ad9 100644
--- a/spec.bs
+++ b/spec.bs
@@ -326,7 +326,19 @@ dictionary SubscriptionObserver {
VoidFunction complete;
};
+callback ObservableInspectorAbortHandler = undefined (any value);
+
+dictionary ObservableInspector {
+ ObservableSubscriptionCallback next;
+ ObservableSubscriptionCallback error;
+ VoidFunction complete;
+
+ VoidFunction subscribe;
+ ObservableInspectorAbortHandler abort;
+};
+
typedef (ObservableSubscriptionCallback or SubscriptionObserver) ObserverUnion;
+typedef (ObservableSubscriptionCallback or ObservableInspector) ObservableInspectorUnion;
dictionary SubscribeOptions {
AbortSignal signal;
@@ -362,6 +374,7 @@ interface Observable {
Observable drop(unsigned long long amount);
Observable flatMap(Mapper mapper);
Observable switchMap(Mapper mapper);
+ Observable inspect(optional ObservableInspectorUnion inspect_observer = {});
Observable finally(VoidFunction callback);
// Promise-returning operators.
@@ -1085,6 +1098,115 @@ For now, see [https://github.com/wicg/observable#operators](https://github.com/w
|innerObserver| and |innerOptions|.
+
+ The
inspect(|inspector_union|)
method steps are:
+
+ 1. Let |subscribe callback| be a {{VoidFunction}}-or-null, initially null.
+
+ 1. Let |next callback| be a {{ObservableSubscriptionCallback}}-or-null, initially null.
+
+ 1. Let |error callback| be a {{ObservableSubscriptionCallback}}-or-null, initially null.
+
+ 1. Let |complete callback| be a {{VoidFunction}}-or-null, initially null.
+
+ 1. Let |abort callback| be a {{ObservableInspectorAbortHandler}}-or-null, initially null.
+
+ 1. Process |inspector_union| as follows:
+
+ - If |inspector_union| is an {{ObservableSubscriptionCallback}}
+ -
+ 1. Set |next callback| to |inspector_union|.
+
+
- If |inspector_union| is an {{ObservableInspector}}
+ -
+ 1. If {{ObservableInspector/subscribe}} [=map/exists=] in |inspector_union|, then set
+ |subscribe callback| to it.
+
+ 1. If {{ObservableInspector/next}} [=map/exists=] in |inspector_union|, then set
+ |next callback| to it.
+
+ 1. If {{ObservableInspector/error}} [=map/exists=] in |inspector_union|, then set
+ |error callback| to it.
+
+ 1. If {{ObservableInspector/complete}} [=map/exists=] in |inspector_union|, then set
+ |complete callback| to it.
+
+ 1. If {{ObservableInspector/abort}} [=map/exists=] in |inspector_union|, then set
+ |abort callback| to it.
+
+
+
+ 1. Let |sourceObservable| be [=this=].
+
+ 1. Let |observable| be a [=new=] {{Observable}} whose [=Observable/subscribe callback=] is an
+ algorithm that takes a {{Subscriber}} |subscriber| and does the following:
+
+ 1. If |subscribe callback| is not null, then [=invoke=] it.
+
+ If
an exception |E| was thrown, then run
+ |subscriber|'s {{Subscriber/error()}} method, given |E|, and abort these steps.
+
+ Note: The result of this is that |sourceObservable| is never subscribed to.
+
+ 1. If |abort callback| is not null, then [=AbortSignal/add|add the following abort
+ algorithm=] to |subscriber|'s [=Subscriber/subscription controller=]'s
+ [=AbortController/signal=]:
+
+ 1. [=Invoke=] |abort callback| with |subscriber|'s [=Subscriber/subscription
+ controller=]'s [=AbortController/signal=]'s [=AbortSignal/abort reason=].
+
+ If
an exception |E| was thrown, then
+ [=report the exception=] |E|.
+
+ 1. Let |sourceObserver| be a new [=internal observer=], initialized as follows:
+
+ : [=internal observer/next steps=]
+ :: 1. If |next callback| is not null, then [=invoke=] |next callback| with the passed in
+ |value|.
+
+ If
an exception |E| was thrown, then:
+
+ 1. [=AbortSignal/Remove=] |abort callback| from |subscriber|'s
+ [=Subscriber/subscription controller=]'s [=AbortController/signal=].
+
+ Note: This step is important, because the |abort callback| is only meant to be
+ called for *consumer-initiated* unsubscriptions. When the producer terminates
+ the subscription (via |subscriber|'s {{Subscriber/error()}} or
+ {{Subscriber/complete()}} methods) like below, we have to ensure that
+ |abort callback| is not run.
+
+ Issue: This matches Chromium's implementation, but consider holding a reference
+ to the originally-passed-in {{SubscribeOptions}}'s {{SubscribeOptions/signal}}
+ and just invoking |abort callback| when *it* aborts. The result is likely the
+ same, but needs investigation.
+
+ 1. Run |subscriber|'s {{Subscriber/error()}} method, given |E|, and return.
+
+ 1. Run |subscriber|'s {{Subscriber/next()}} method with the passed in |value|.
+
+ : [=internal observer/error steps=]
+ :: [=AbortSignal/Remove=] |abort callback| from |subscriber|'s [=Subscriber/subscription
+ controller=]'s [=AbortController/signal=], and run |subscriber|'s
+ {{Subscriber/error()}} method, given the passed in
error.
+
+ : [=internal observer/complete steps=]
+ :: [=AbortSignal/Remove=] |abort callback| from |subscriber|'s [=Subscriber/subscription
+ controller=]'s [=AbortController/signal=], and run |subscriber|'s
+ {{Subscriber/complete()}} method.
+
+ 1. Let |options| be a new {{SubscribeOptions}} whose {{SubscribeOptions/signal}} is
+ |subscriber|'s [=Subscriber/subscription controller=]'s [=AbortController/signal=].
+
+ 1.
Subscribe to |sourceObservable|
+ given |sourceObserver| and |options|.
+
+ 1. Return |observable|.
+
+
+ /dom/observable/tentative/observable-inspect.any.js
+
+
+