-
Notifications
You must be signed in to change notification settings - Fork 19
Spec from()
static converter
#160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
eb51b11
ca59164
742a5a8
11ea953
e5c1c9a
d1aa196
199ea62
e28cc67
5461f18
4c74aa8
d328e70
4a34553
3b3312b
06a1a66
1b92dc5
4159a04
8745064
d772941
57b2d19
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,13 @@ WPT Display: open | |
urlPrefix: https://tc39.es/ecma262/#; spec: ECMASCRIPT | ||
type: dfn | ||
text: current realm | ||
text: Object; url: sec-object-type | ||
text: normal completion; url: sec-normalcompletion | ||
text: throw completion; url: sec-throwcompletion | ||
url: sec-returnifabrupt-shorthands | ||
text: ? | ||
type: abstract-op | ||
text: Type; url: sec-ecmascript-data-types-and-values | ||
urlPrefix: https://dom.spec.whatwg.org; spec: DOM | ||
type: dfn | ||
for: event listener | ||
|
@@ -38,6 +45,11 @@ urlPrefix: https://dom.spec.whatwg.org; spec: DOM | |
text: dependent signals; url: abortsignal-dependent-signals | ||
text: signal abort; url:abortsignal-signal-abort | ||
text: abort reason; url:abortsignal-abort-reason | ||
urlPrefix: https://webidl.spec.whatwg.org; spec: WEBIDL | ||
type: dfn | ||
text: a promise rejected with | ||
type: dfn | ||
text: react | ||
</pre> | ||
|
||
<style> | ||
|
@@ -371,7 +383,7 @@ interface Observable { | |
// | ||
// takeUntil() can consume promises, iterables, async iterables, and other | ||
// observables. | ||
Observable takeUntil(any notifier); | ||
Observable takeUntil(any value); | ||
Observable map(Mapper mapper); | ||
Observable filter(Predicate predicate); | ||
Observable take(unsigned long long amount); | ||
|
@@ -461,6 +473,146 @@ An <dfn>internal observer</dfn> is a [=struct=] with the following [=struct/item | |
[[#promise-returning-operators]] that make use of this, for example.</p> | ||
</div> | ||
|
||
<div algorithm> | ||
To <dfn for=Observable>convert to an Observable</dfn> given an {{any}} |value|, run these steps: | ||
|
||
Note: We split this algorithm out from the Web IDL {{Observable/from()}} method, so that | ||
spec prose can <a for=Observable lt="convert to an observable">convert</a> an {{Observable}} | ||
without going through the Web IDL bindings. | ||
|
||
Note: The resolution of value to its descrete types happens before | ||
[=Observable/subscribe callback=] is called. This means mutations of values, such as adding | ||
the iterable protocols to the object, will not take affect between the creation of the returned | ||
observable, and when it is subscribed to. | ||
|
||
1. If [$Type$](|value|) is not [=Object=], [=exception/throw=] a {{TypeError}}. | ||
|
||
Note: This prevents primitive types from being coerced into iterables (e.g., String). | ||
|
||
Issue: See if this is even the behavior we want. See <a | ||
href=https://github.com/WICG/observable/issues/125>WICG/observable#125</a> | ||
|
||
|
||
1. <i id=from-observable-conversion><b>From Observable</b></i>: If |value|'s [=specific type=] | ||
is an {{Observable}}, then return |value|. | ||
|
||
1. <i id=from-async-iterable-conversion><b>From async iterator</b></i>: Let | ||
|
||
|asyncIteratorMethodRecord| be [=?=] [$GetMethod$](|value|, {{%Symbol.asyncIterator%}}). | ||
|
||
Note: We have to use [$GetMethod$] directly instead of [$GetIterator$], because | ||
[$GetIterator$] makes it impossible to distinguish between (a) the case where |value| simply | ||
doesn't implement any iterable protocol, and (b) the case where |value| implements one of the | ||
iterator protocols, and its method getter throws an exception. | ||
|
||
Note: This step is web-observable, and re-throws any errors that the {{%Symbol.iterator%}} | ||
method *getter* might have thrown. | ||
|
||
1. If |asyncIteratorMethodRecord|'s \[[Value]] is undefined or null, then jump to the step | ||
labeled <a href=#from-iterable-conversion>From iterable</a>. | ||
|
||
1. If [$IsCallable$](|asyncIteratorMethodRecord|'s \[[Value]]) is false, then | ||
[=exception/throw=] a {{TypeError}}. | ||
|
||
Otherwise, let |nextAlgorithm| be the following steps, given |subscriber| and |iterator|: | ||
domfarolino marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
1. If |iterator|'s \[[Done]] is true, then: run |subscriber|'s {{Subscriber/complete()}} | ||
method and abort these steps. | ||
|
||
1. Let |nextRecord| be [$IteratorStepValue$](|iterator|). | ||
domfarolino marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
1. Let |nextPromise| be undefined. | ||
|
||
1. If |nextRecord| is a [=throw completion=], then set |nextPromise| to [=a promise | ||
rejected with=] |nextRecord|'s \[[Value]]. | ||
|
||
1. Otherwise, set |nextPromise| to |nextRecord|'s \[[Value]]. | ||
|
||
1. [=React=] to |nextPromise|: | ||
|
||
1. If |nextPromise| was fulfilled with value |v|, then: | ||
|
||
1. Run |subscriber|'s {{Subscriber/next()}} method, given |v|. | ||
|
||
1. Run |nextAlgorithm|, given |subscriber| and |iterator|. | ||
|
||
1. If |nextPromise| was rejected with reason |r|, then run |subscriber|'s | ||
{{Subscriber/error()}} method, given |r|. | ||
|
||
1. Return a [=new=] {{Observable}} whose [=Observable/subscribe callback=] is an algorithm that | ||
takes a {{Subscriber}} |subscriber| and does the following: | ||
|
||
1. Let |iteratorRecord| be [$GetIteratorFromMethod$](|value|, {{%Symbol.asyncIterator%}}). | ||
domfarolino marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
1. If |iteratorRecord| is a [=throw completion=], then [=queue a microtask=] to run | ||
|subscriber|'s {{Subscriber/error()}} method, given |iteratorRecord|'s \[[Value]]. | ||
|
||
1. Otherwise, [=queue a microtask=] to run |nextAlgorithm| given |subscriber| and | ||
domfarolino marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|iteratorRecord|'s \[[Value]]. | ||
domfarolino marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
Note: It is important to [=queue a microtask=] in both branches here to guarantee that | ||
coercing an AsyncIterable never stops the Subscription synchronously, thereby releasing | ||
Zalgo. | ||
|
||
1. <i id=from-iterable-conversion><b>From iterable</b></i>: Let |iteratorMethodRecord| be [=?=] | ||
[$GetMethod$](|value|, {{%Symbol.iterator%}}). | ||
|
||
Note: This step is web-observable, and re-throws any errors that the {{%Symbol.iterator%}} | ||
method *getter* might have thrown. | ||
|
||
1. If |iteratorMethodRecord|'s \[[Value]] is undefined or null, then jump to the step labeled <a | ||
href=#from-promise-conversion>From Promise</a>. | ||
|
||
1. If [$IsCallable$](|iteratorMethodRecord|'s \[[Value]]) is false, then [=exception/throw=] a | ||
|
||
{{TypeError}}. | ||
|
||
Otherwise, return a [=new=] {{Observable}} whose [=Observable/subscribe callback=] is an | ||
algorithm that takes a {{Subscriber}} |subscriber| and does the following: | ||
|
||
1. Let |iteratorRecord| be [$GetIterator$](|value|, sync). | ||
|
||
Note: This re-invokes any method getters for the {{%Symbol.iterator%}} method on | ||
domfarolino marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|value|. Whether or not this is desirable is an extreme corner case, but this behavior | ||
currently matches what is expected by tests. See <a | ||
href=https://github.com/WICG/observable/issues/127>issue#127</a> for discussion. | ||
|
||
1. If |iteratorRecord| is a [=throw completion=], then run |subscriber|'s | ||
{{Subscriber/error()}} method, given |iteratorRecord|'s \[[Value]], and abort these | ||
steps. | ||
|
||
1. Let |iterator| be |iteratorRecord|'s \[[Value]]. | ||
|
||
1. [=iteration/While=] true: | ||
|
||
1. If |iterator|'s \[[Done]] is true, then run |subscriber|'s {{Subscriber/complete()}} | ||
method, and [=iteration/break=]. | ||
|
||
1. Let |nextRecord| be [$IteratorStepValue$](|iterator|). | ||
|
||
1. If |nextRecord| is a [=throw completion=], then run |subscriber|'s | ||
{{Subscriber/error()}} method, given |nextRecord|'s \[[Value]], and | ||
[=iteration/break=]. | ||
|
||
Otherwise, run |subscriber|'s {{Subscriber/next()}} given |nextRecord|'s \[[Value]]. | ||
|
||
1. <i id=from-promise-conversion><b>From Promise</b></i>: If [$IsPromise$](|value|) is true, | ||
then: | ||
|
||
1. Return a [=new=] {{Observable}} whose [=Observable/subscribe callback=] is an algorithm | ||
that takes a {{Subscriber}} |subscriber| and does the following: | ||
|
||
1. [=React=] to |value|: | ||
|
||
1. If |value| was fulfilled with value |v|, then: | ||
|
||
1. Run |subscriber|'s {{Subscriber/next()}} method, given |v|. | ||
|
||
1. Run |subscriber|'s {{Subscriber/complete()}} method. | ||
|
||
1. If |value| was rejected with reason |r|, then run |subscriber|'s | ||
{{Subscriber/error()}} method, given |r|. | ||
|
||
1. [=exception/Throw=] a {{TypeError}}. | ||
</div> | ||
|
||
<div algorithm> | ||
To <dfn for=Observable>subscribe to an {{Observable}}</dfn> given an | ||
{{ObserverUnion}}-or-[=internal observer=] |observer|, and a {{SubscribeOptions}} |options|, run | ||
|
@@ -577,15 +729,23 @@ For now, see [https://github.com/wicg/observable#operators](https://github.com/w | |
|
||
<h4 id=observable-from>{{Observable/from()}}</h4> | ||
|
||
<p class=XXX>Spec the exact semantics of {{Observable/from()}} conversion.</p> | ||
<div algorithm> | ||
The <dfn for=Observable method><code>from(|value|)</code></dfn> method steps are: | ||
|
||
1. Return the result of <a for=Observable lt="convert to an Observable">converting</a> |value| | ||
to an {{Observable}}. Rethrow any exceptions. | ||
</div> | ||
|
||
<h4 id=observable-returning-operators>{{Observable}}-returning operators</h4> | ||
|
||
<div algorithm> | ||
The <dfn for=Observable method><code>takeUntil(|notifier|)</code></dfn> method steps are: | ||
The <dfn for=Observable method><code>takeUntil(|value|)</code></dfn> method steps are: | ||
|
||
1. Let |sourceObservable| be [=this=]. | ||
|
||
1. Let |notifier| be the result of <a for=Observable lt="convert to an Observable"> | ||
converting</a> |value| to an Observable. | ||
|
||
1. Let |observable| be a [=new=] {{Observable}} whose [=Observable/subscribe callback=] is an | ||
algorithm that takes a {{Subscriber}} |subscriber| and does the following: | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.