From bc607f6d522154960e3e91a9ed3a1a509248be35 Mon Sep 17 00:00:00 2001 From: Dominic Farolino Date: Tue, 30 Jan 2024 11:47:21 -0500 Subject: [PATCH 1/3] Initial spec for `forEach()` operator --- spec.bs | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/spec.bs b/spec.bs index 38b265a..cade980 100644 --- a/spec.bs +++ b/spec.bs @@ -743,7 +743,45 @@ For now, see [https://github.com/wicg/observable#operators](https://github.com/w
The forEach(|callback|, |options|) method steps are: - 1. TODO: Spec this and use |callback| and |options|. + 1. Let |p| [=a new promise=]. + + 1. If |options|'s {{SubscribeOptions/signal}} is not null: + + 1. If |options|'s {{SubscribeOptions/signal}} is [=AbortSignal/aborted=], then: + + 1. [=Reject=] |p| with |options|'s {{SubscribeOptions/signal}}'s [=AbortSignal/abort + reason=]. + + 1. Return |p|. + + 1. [=AbortSignal/add|Add the following abort algorithm=] to |options|'s + {{SubscribeOptions/signal}}: + + 1. [=Reject=] |p| with |options|'s {{SubscribeOptions/signal}}'s [=AbortSignal/abort + reason=]. + + 1. Let |idx| be an {{unsigned long long}}, initially 0. + + 1. Let |observer| be a new [=internal observer=], initialized as follows: + + : [=internal observer/next steps=] + :: 1. [=Invoke=] |callback| with the passed in value, and |idx|. + + If an exception |E| was thrown, + then [=report the exception=] |E|. + + 1. Increment |idx|. + + : [=internal observer/error steps=] + :: [=Reject=] |p| with the passed in error. + + : [=internal observer/complete steps=] + :: [=Resolve=] |p| with {{undefined}}. + + 1. Subscribe to [=this=] given |observer| + and |options|. + + 1. Return |p|.
From 025da7eaba532ac8a7564098e57dde3d1373642d Mon Sep 17 00:00:00 2001 From: Dominic Farolino Date: Tue, 30 Jan 2024 16:54:51 -0500 Subject: [PATCH 2/3] Abort from `next()` steps appropriately --- spec.bs | 64 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/spec.bs b/spec.bs index cade980..f30c1a3 100644 --- a/spec.bs +++ b/spec.bs @@ -745,20 +745,49 @@ For now, see [https://github.com/wicg/observable#operators](https://github.com/w 1. Let |p| [=a new promise=]. - 1. If |options|'s {{SubscribeOptions/signal}} is not null: - - 1. If |options|'s {{SubscribeOptions/signal}} is [=AbortSignal/aborted=], then: - - 1. [=Reject=] |p| with |options|'s {{SubscribeOptions/signal}}'s [=AbortSignal/abort - reason=]. - - 1. Return |p|. - - 1. [=AbortSignal/add|Add the following abort algorithm=] to |options|'s - {{SubscribeOptions/signal}}: - - 1. [=Reject=] |p| with |options|'s {{SubscribeOptions/signal}}'s [=AbortSignal/abort - reason=]. + 1. Let |visitor callback controller| be a [=new=] {{AbortController}}. + + 1. Let |internal options| be a new {{SubscribeOptions}} whose {{SubscribeOptions/signal}} is the + result of [=creating a dependent abort signal=] from the list + «|visitor callback controller|'s [=AbortController/signal=], |options|'s + {{SubscribeOptions/signal}} if non-null», using {{AbortSignal}}, and the [=current realm=]. + +
+

Many trivial [=internal observers=] act as pass-throughs, and do not control the + subscription to the {{Observable}} that they represent; that is, their [=internal + observer/error steps=] and [=internal observer/complete steps=] are called when the + subscription is terminated, and their [=internal observer/next steps=] simply pass some + version of the given value along the chain.

+ +

For this operator, however, the below |observer|'s [=internal observer/next steps=] are + responsible for actually aborting the underlying subscription to [=this=], in the event + that |callback| throws an exception. In that case, the {{SubscribeOptions}}'s + {{SubscribeOptions/signal}} we pass through to "Subscribe to an Observable", needs to be a [=creating a + dependent abort signal|dependent signal=] derived from |options|'s + {{SubscribeOptions/signal}}, **and** the {{AbortSignal}} of an {{AbortController}} that the + [=internal observer/next steps=] below has access to, and can [=AbortController/signal + abort=] when needed. +

+ + 1. If |internal options|'s {{SubscribeOptions/signal}} is [=AbortSignal/aborted=], then: + + 1. [=Reject=] |p| with |internal options|'s {{SubscribeOptions/signal}}'s + [=AbortSignal/abort reason=]. + + 1. Return |p|. + + 1. [=AbortSignal/add|Add the following abort algorithm=] to |internal options|'s + {{SubscribeOptions/signal}}: + + 1. [=Reject=] |p| with |internal options|'s {{SubscribeOptions/signal}}'s [=AbortSignal/abort + reason=]. + + Note: The fact that rejection of |p| is tied to |internal options|'s + {{SubscribeOptions/signal}}, and not |options|'s {{SubscribeOptions/signal}} means, that + any [=microtasks=] [=queue a microtask|queued=] during the firing of |options|'s + {{SubscribeOptions/signal}}'s {{AbortSignal/abort}} event will run before |p|'s + rejection handler runs. 1. Let |idx| be an {{unsigned long long}}, initially 0. @@ -767,8 +796,9 @@ For now, see [https://github.com/wicg/observable#operators](https://github.com/w : [=internal observer/next steps=] :: 1. [=Invoke=] |callback| with the passed in value, and |idx|. - If an exception |E| was thrown, - then [=report the exception=] |E|. + If an exception |E| was thrown, then + [=reject=] |p| with |E|, and [=AbortController/signal abort=] |visitor callback + controller| with |E|. 1. Increment |idx|. @@ -779,7 +809,7 @@ For now, see [https://github.com/wicg/observable#operators](https://github.com/w :: [=Resolve=] |p| with {{undefined}}. 1. Subscribe to [=this=] given |observer| - and |options|. + and |internal options|. 1. Return |p|.
From 243f85e2ee97103844dc7eee15dd2dd7393f7cbf Mon Sep 17 00:00:00 2001 From: Dominic Farolino Date: Tue, 30 Jan 2024 16:56:18 -0500 Subject: [PATCH 3/3] Indentation --- spec.bs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec.bs b/spec.bs index f30c1a3..6db9875 100644 --- a/spec.bs +++ b/spec.bs @@ -794,13 +794,14 @@ For now, see [https://github.com/wicg/observable#operators](https://github.com/w 1. Let |observer| be a new [=internal observer=], initialized as follows: : [=internal observer/next steps=] - :: 1. [=Invoke=] |callback| with the passed in value, and |idx|. + :: + 1. [=Invoke=] |callback| with the passed in value, and |idx|. If an exception |E| was thrown, then [=reject=] |p| with |E|, and [=AbortController/signal abort=] |visitor callback controller| with |E|. - 1. Increment |idx|. + 1. Increment |idx|. : [=internal observer/error steps=] :: [=Reject=] |p| with the passed in error.