@@ -177,8 +177,8 @@ interface Subscriber {
177177};
178178</xmp>
179179
180- Each {{Subscriber}} has a <dfn for=Subscriber>internal observer </dfn> , which is an [=internal
181- observer=] .
180+ Each {{Subscriber}} has an [=ordered set=] of <dfn for=Subscriber>internal observers </dfn> ,
181+ initially empty .
182182
183183Each {{Subscriber}} has a <dfn for=Subscriber>teardown callbacks</dfn> , which is a [=list=] of
184184{{VoidFunction}} s, initially empty.
@@ -205,21 +205,22 @@ The <dfn attribute for=Subscriber><code>signal</code></dfn> getter steps are to
205205 1. If [=this=] 's [=relevant global object=] is a {{Window}} object, and its [=associated
206206 Document=] is not [=Document/fully active=] , then return.
207207
208- 1. Run [=this=] 's [=Subscriber/internal observer=]' s [=internal observer/next steps=] given
209- |value|.
208+ 1. [=set/For each=] |observer| of [=this=] 's [=Subscriber/internal observers=] :
210209
211- [=Assert=] : No <a spec=webidl lt="an exception was thrown">exception was thrown</a> .
210+ 1. Run |observer|'s [=internal observer/next steps=] given |value| .
212211
213- <div class=note>
214- <p> Note: No exception can be thrown here because in the case where the
215- [=Subscriber/internal observer=] 's [=internal observer/next steps=] is just a wrapper
216- around a script-provided callback, the <a href=#process-observer>process observer</a> steps
217- take care to wrap these callbacks in logic that, when invoking them, catches any
218- exceptions, and reports them to the global.</p>
219-
220- <p> When the [=internal observer/next steps=] is a spec algorithm, those steps take care to
221- not throw any exceptions outside of itself, to appease this assert.</p>
222- </div>
212+ [=Assert=] : No <a spec=webidl lt="an exception was thrown">exception was thrown</a> .
213+
214+ <div class=note>
215+ <p> Note: No exception can be thrown here because in the case where the
216+ [=Subscriber/internal observer=] 's [=internal observer/next steps=] is just a wrapper
217+ around a script-provided callback, the <a href=#process-observer>process observer</a>
218+ steps take care to wrap these callbacks in logic that, when invoking them, catches any
219+ exceptions, and reports them to the global.</p>
220+
221+ <p> When the [=internal observer/next steps=] is a spec algorithm, those steps take care
222+ to not throw any exceptions outside of itself, to appease this assert.</p>
223+ </div>
223224</div>
224225
225226<div algorithm>
@@ -232,12 +233,13 @@ The <dfn attribute for=Subscriber><code>signal</code></dfn> getter steps are to
232233
233234 1. [=close a subscription|Close=] [=this=] .
234235
235- 1. Run [=this=] 's [=Subscriber/internal observer=]' s [=internal observer/error steps=] given
236- |error|.
236+ 1. [=set/For each=] |observer| of [=this=] 's [=Subscriber/internal observers=] :
237+
238+ 1. Run |observer|'s [=internal observer/error steps=] given |error|.
237239
238- [=Assert=] : No <a spec=webidl lt="an exception was thrown">exception was thrown</a> .
240+ [=Assert=] : No <a spec=webidl lt="an exception was thrown">exception was thrown</a> .
239241
240- Note: See the documentation in {{Subscriber/next()}} for details on why this is true.
242+ Note: See the documentation in {{Subscriber/next()}} for details on why this is true.
241243</div>
242244
243245<div algorithm>
@@ -250,11 +252,13 @@ The <dfn attribute for=Subscriber><code>signal</code></dfn> getter steps are to
250252
251253 1. [=close a subscription|Close=] [=this=] .
252254
253- 1. Run [=this=] 's [=Subscriber/internal observer =]' s [=internal observer/complete steps=] .
255+ 1. [=set/For each=] |observer| of [=this =] 's [=Subscriber/ internal observers=] :
254256
255- [=Assert=] : No <a spec=webidl lt="an exception was thrown">exception was thrown</a> .
257+ 1. Run |observer|'s [=internal observer/complete steps=] .
256258
257- Note: See the documentation in {{Subscriber/next()}} for details on why this is true.
259+ [=Assert=] : No <a spec=webidl lt="an exception was thrown">exception was thrown</a> .
260+
261+ Note: See the documentation in {{Subscriber/next()}} for details on why this is true.
258262</div>
259263
260264<div algorithm>
@@ -407,6 +411,9 @@ interface Observable {
407411Each {{Observable}} has a <dfn for=Observable>subscribe callback</dfn> , which is a
408412{{SubscribeCallback}} or a set of steps that take in a {{Subscriber}} .
409413
414+ Each {{Observable}} has a <dfn for=Observable>weak subscriber</dfn> , which is a weak reference to a
415+ {{Subscriber}} -or-null, initially null.
416+
410417Note: The "union" of these types is to support both {{Observable}} s created by JavaScript (that are
411418always constructed with a {{SubscribeCallback}} ), and natively-constructed {{Observable}} objects
412419(whose [=Observable/subscribe callback=] could be an arbitrary set of native steps, not a JavaScript
@@ -732,9 +739,38 @@ An <dfn>internal observer</dfn> is a [=struct=] with the following [=struct/item
732739 error algorithm=] , or an algorithm that [=invokes=] the provided
733740 {{SubscriptionObserver/error}} [=callback function=] .
734741
742+ 1. If [=this=] 's [=Observable/weak subscriber=] is not null and [=this=]' s [=Observable/weak
743+ subscriber=] 's [=Subscriber/active=] is true:
744+
745+ 1. Let |subscriber| be [=this=] 's [=Observable/weak subscriber=] .
746+
747+ 1. [=set/Append=] |internal observer| to |subscriber|'s [=Subscriber/internal observers=] .
748+
749+ 1. If |options|'s {{SubscribeOptions/signal}} [=map/exists=] , then:
750+
751+ 1. If |options|'s {{SubscribeOptions/signal}} is [=AbortSignal/aborted=] , then
752+ [=set/remove=] |internal observer| from |subscriber|'s [=Subscriber/internal
753+ observers=] .
754+
755+ 1. Otherwise, [=AbortSignal/add|add the following abort algorithm=] to |options|'s
756+ {{SubscribeOptions/signal}} :
757+
758+ 1. If |subscriber|'s [=Subscriber/active=] is false, then abort these steps.
759+
760+ 1. [=set/Remove=] |internal observer| from |subscriber|'s [=Subscriber/internal
761+ observers=] .
762+
763+ 1. If |subscriber|'s [=Subscriber/internal observers=] is [=set/empty=] , then [=close a
764+ subscription|close=] |subscriber| with |options|'s {{SubscribeOptions/signal}}' s
765+ [=AbortSignal/abort reason=] .
766+
767+ 1. Return.
768+
735769 1. Let |subscriber| be a [=new=] {{Subscriber}} .
736770
737- 1. Set |subscriber|'s [=Subscriber/internal observer=] to |internal observer|.
771+ 1. [=set/Append=] |internal observer| to |subscriber|'s [=Subscriber/internal observers=] .
772+
773+ 1. Set [=this=] 's [=Observable/weak subscriber=] to |subscriber|.
738774
739775 1. If |options|'s {{SubscribeOptions/signal}} [=map/exists=] , then:
740776
@@ -745,8 +781,14 @@ An <dfn>internal observer</dfn> is a [=struct=] with the following [=struct/item
745781 1. Otherwise, [=AbortSignal/add|add the following abort algorithm=] to |options|'s
746782 {{SubscribeOptions/signal}} :
747783
748- 1. [=close a subscription|Close=] |subscriber| with |options|'s
749- {{SubscribeOptions/signal}} [=AbortSignal/abort reason=] .
784+ 1. If |subscriber|'s [=Subscriber/active=] is false, then abort these steps.
785+
786+ 1. [=set/Remove=] |internal observer| from |subscriber|'s [=Subscriber/internal
787+ observers=] .
788+
789+ 1. If |subscriber|'s [=Subscriber/internal observers=] is [=set/empty=] , then [=close a
790+ subscription|close=] |subscriber| with |options|'s {{SubscribeOptions/signal}}' s
791+ [=AbortSignal/abort reason=] .
750792
751793 1. If [=this=] 's [=Observable/subscribe callback=] is a {{SubscribeCallback}} , [=invoke=] it
752794 with |subscriber|.
0 commit comments