From d1b047133d17a560cc2c1ad720280ddf00dd95a1 Mon Sep 17 00:00:00 2001 From: Dominic Farolino Date: Tue, 27 Aug 2024 12:34:48 -0400 Subject: [PATCH 1/3] Reduce operator --- spec.bs | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/spec.bs b/spec.bs index 69c5ad9..7fd51ae 100644 --- a/spec.bs +++ b/spec.bs @@ -345,7 +345,7 @@ dictionary SubscribeOptions { }; callback Predicate = boolean (any value, unsigned long long index); -callback Reducer = any (any accumulator, any currentValue); +callback Reducer = any (any accumulator, any currentValue, unsigned long long index); callback Mapper = any (any value, unsigned long long index); // Differs from Mapper only in return type, since this callback is exclusively // used to visit each element in a sequence, not transform it. @@ -1604,7 +1604,64 @@ For now, see [https://github.com/wicg/observable#operators](https://github.com/w The reduce(|reducer|, |initialValue|, |options|) method steps are: - 1. TODO: Spec this and use |reducer|, |initialValue|, and |options|. + 1. Let |p| [=a new promise=]. + + 1. Let |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 + «|controller|'s [=AbortController/signal=], |options|'s + {{SubscribeOptions/signal}} if non-null», using {{AbortSignal}}, and the [=current realm=]. + + 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=]. + + 1. Let |idx| be an {{unsigned long long}}, initially 0. + + 1. Let |accumulator| be |initialValue| if it is given, and the string "unset" otherwise. + + 1. Let |observer| be a new [=internal observer=], initialized as follows: + + : [=internal observer/next steps=] + :: 1. If |accumulator| is the string "unset", then set |accumulator| to the + passed in |value| and abort these steps. + + Note: This means that |reducer| will not be called with the first |value| that [=this=] + produces set as the {{Reducer/currentValue}}. Rather, when the *second* value is + eventually emitted, we will call |reducer| with *it* as the {[Reducer/currentValue}}, + and the first value (that we're saving here) as the {{Reducer/accumulator}}. + + 1. [=Invoke=] |reducer| with |accumulator| as {{Reducer/accumulator}}, the passed in + |value| as {{Reducer/currentValue}}, and |idx| as {{Reducer/index}}. Let |result| be + the returned value. + + If an exception |E| was thrown, then + [=reject=] |p| with |E|, and [=AbortController/signal abort=] |controller| with |E|. + + 1. Set |idx| to |idx| + 1. + + 1. Set |accumulator| to |result|. + + : [=internal observer/error steps=] + :: [=Reject=] |p| with the passed in error. + + : [=internal observer/complete steps=] + :: [=Resolve=] |p| with false. + + 1. Subscribe to [=this=] given |observer| + and |internal options|. + + 1. Return |p|. From d35a8676fc4f9ea2166652978805e2a576aa1270 Mon Sep 17 00:00:00 2001 From: Dominic Farolino Date: Tue, 27 Aug 2024 15:24:45 -0400 Subject: [PATCH 2/3] Finish --- spec.bs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/spec.bs b/spec.bs index 7fd51ae..79c1e27 100644 --- a/spec.bs +++ b/spec.bs @@ -1628,17 +1628,19 @@ For now, see [https://github.com/wicg/observable#operators](https://github.com/w 1. Let |idx| be an {{unsigned long long}}, initially 0. - 1. Let |accumulator| be |initialValue| if it is given, and the string "unset" otherwise. + 1. Let |accumulator| be |initialValue| if it is given, and the string "unset" + otherwise. 1. Let |observer| be a new [=internal observer=], initialized as follows: : [=internal observer/next steps=] - :: 1. If |accumulator| is the string "unset", then set |accumulator| to the - passed in |value| and abort these steps. + :: + 1. If |accumulator| is the string "unset", then set |accumulator| to the + passed in |value|, set |idx| to |idx| + 1, and abort these steps. Note: This means that |reducer| will not be called with the first |value| that [=this=] produces set as the {{Reducer/currentValue}}. Rather, when the *second* value is - eventually emitted, we will call |reducer| with *it* as the {[Reducer/currentValue}}, + eventually emitted, we will call |reducer| with *it* as the {{Reducer/currentValue}}, and the first value (that we're saving here) as the {{Reducer/accumulator}}. 1. [=Invoke=] |reducer| with |accumulator| as {{Reducer/accumulator}}, the passed in @@ -1648,15 +1650,17 @@ For now, see [https://github.com/wicg/observable#operators](https://github.com/w If an exception |E| was thrown, then [=reject=] |p| with |E|, and [=AbortController/signal abort=] |controller| with |E|. - 1. Set |idx| to |idx| + 1. + 1. Set |idx| to |idx| + 1. - 1. Set |accumulator| to |result|. + 1. Set |accumulator| to |result|. : [=internal observer/error steps=] :: [=Reject=] |p| with the passed in error. : [=internal observer/complete steps=] - :: [=Resolve=] |p| with false. + :: 1. If |accumulator| is not "unset", then [=resolve=] |p| with |accumulator|. + + Otherwise, [=reject=] |p| with a {{TypeError}}. 1. Subscribe to [=this=] given |observer| and |internal options|. From 2760e0054a48415680aa6b5aedfb14fd23088fcc Mon Sep 17 00:00:00 2001 From: Dominic Farolino Date: Tue, 27 Aug 2024 22:18:51 -0400 Subject: [PATCH 3/3] Stop using a value that script can pass in. --- spec.bs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/spec.bs b/spec.bs index 79c1e27..b25552d 100644 --- a/spec.bs +++ b/spec.bs @@ -1628,15 +1628,14 @@ For now, see [https://github.com/wicg/observable#operators](https://github.com/w 1. Let |idx| be an {{unsigned long long}}, initially 0. - 1. Let |accumulator| be |initialValue| if it is given, and the string "unset" - otherwise. + 1. Let |accumulator| be |initialValue| if it is given, and uninitialized otherwise. 1. Let |observer| be a new [=internal observer=], initialized as follows: : [=internal observer/next steps=] :: - 1. If |accumulator| is the string "unset", then set |accumulator| to the - passed in |value|, set |idx| to |idx| + 1, and abort these steps. + 1. If |accumulator| is uninitialized (meaning no |initialValue| was passed in), then set + |accumulator| to the passed in |value|, set |idx| to |idx| + 1, and abort these steps. Note: This means that |reducer| will not be called with the first |value| that [=this=] produces set as the {{Reducer/currentValue}}. Rather, when the *second* value is