@@ -26,6 +26,13 @@ WPT Display: open
26
26
urlPrefix: https://tc39.es/ecma262/#; spec: ECMASCRIPT
27
27
type: dfn
28
28
text: current realm
29
+ text: an Object; url: sec-object-type
30
+ text: IsPromise; url: sec-ispromise
31
+ text: GetMethod; url: sec-getmethod
32
+ text: GetIteratorFromMethod; url: sec-getiteratorfrommethod
33
+ text: IteratorStepValue; url: sec-iteratorstepvalue
34
+ text: normal completion; url: sec-normalcompletion
35
+ text: throw completion; url: sec-throwcompletion
29
36
urlPrefix: https://dom.spec.whatwg.org; spec: DOM
30
37
type: dfn
31
38
for: event listener
@@ -37,6 +44,11 @@ urlPrefix: https://dom.spec.whatwg.org; spec: DOM
37
44
for: AbortSignal
38
45
text: dependent signals; url: abortsignal-dependent-signals
39
46
text: signal abort; url:abortsignal-signal-abort
47
+ urlPrefix: https://webidl.spec.whatwg.org; spec: WEBIDL
48
+ type: dfn
49
+ text: a promise rejected with
50
+ type: dfn
51
+ text: react
40
52
</pre>
41
53
42
54
<style>
@@ -354,7 +366,7 @@ interface Observable {
354
366
//
355
367
// takeUntil() can consume promises, iterables, async iterables, and other
356
368
// observables.
357
- Observable takeUntil(any notifier );
369
+ Observable takeUntil(any value );
358
370
Observable map(Mapper mapper);
359
371
Observable filter(Predicate predicate);
360
372
Observable take(unsigned long long amount);
@@ -442,6 +454,133 @@ An <dfn>internal observer</dfn> is a [=struct=] with the following [=struct/item
442
454
[[#promise-returning-operators]] that make use of this, for example.</p>
443
455
</div>
444
456
457
+ <div algorithm>
458
+ To <dfn for=Observable>convert to an Observable</dfn> given an {{any}} |value|, run these steps:
459
+
460
+ Note: We split this algorithm out from the Web IDL {{Observable/from()}} method, so that
461
+ spec prose can <a for=Observable lt="convert to an observable">convert</a> an {{Observable}}
462
+ without going through the Web IDL bindings.
463
+
464
+ Note: The resolution of value to its descrete types happens before
465
+ [=Observable/subscribe callback=] is called. This means mutations of values, such as adding
466
+ the iterable protocols to the object, will not take affect between the creation of the returned
467
+ observable, and when it is subscribed to.
468
+
469
+ 1. If |value| is not [=an Object=] , throw a {{TypeError}} .
470
+
471
+ Note: This prevents primitive types from being coerced into iterables (e.g. String).
472
+
473
+ 1. If |value| is an {{Observable}} , then return |value|.
474
+
475
+ 1. Let |asyncIteratorMethodRecord| be ? [=GetMethod=] (|value|, %Symbol.asyncIterator%).
476
+
477
+ 1. If |asyncIteratorMethodRecord|'s \[[Value]] is not undefined, then:
478
+
479
+ Note: [=GetMethod=] might return a [=normal completion=] with an undefined value when the
480
+ object simply has no asyncIterator method.
481
+
482
+ 1. Let |nextAlgorithm| be the following steps, given |iterator|:
483
+
484
+ 1. If |iterator|'s \[[Done]] is true, then:
485
+
486
+ 1. Run |subscriber|'s {{Subscriber/complete()}} method and abort these steps.
487
+
488
+ 1. Let |nextRecord| be [=IteratorStepValue=] (|iterator|).
489
+
490
+ 1. Let |nextPromise| be undefined.
491
+
492
+ 1. If |nextRecord| is a [=throw completion=] then:
493
+
494
+ 1. Set |nextPromise| to [=a promise rejected with=] |nextRecord|'s \[[Value]] .
495
+
496
+ 1. Otherwise, set |nextPromise| to |nextRecord|'s \[[Value]] .
497
+
498
+ 1. React to |nextPromise|:
499
+
500
+ 1. If |nextPromise| was fulfilled with value |v|, then:
501
+
502
+ 1. Run |subscriber|'s {{Subscriber/next()}} method, given |v|.
503
+
504
+ 1. Run |nextAlgorithm|, given |iterator|.
505
+
506
+ 1. If |nextPromise| was rejected with reason |r|, then run |subscriber|'s
507
+ {{Subscriber/error()}} method, given |r|.
508
+
509
+ 1. Return a [=new=] {{Observable}} whose [=Observable/subscribe callback=] is an
510
+ algorithm that takes a {{Subscriber}} |subscriber| and does the following:
511
+
512
+ 1. Let |iteratorRecord| be [=GetIteratorFromMethod=] (|value|, %Symbol.asyncIterator%).
513
+
514
+ 1. If |iteratorRecord| is a [=throw completion=] then:
515
+
516
+ 1. [=queue a microtask=] to perform the following steps:
517
+
518
+ 1. Run |subscriber|'s {{Subscriber/error()}} method, given |iteratorRecord|' s \[[Value]] .
519
+
520
+ 1. Otherwise, [=queue a microtask=] to perform the following steps:
521
+
522
+ 1. Run |nextAlgorithm| given |iteratorRecord|'s \[[Value]] .
523
+
524
+ Note: It is important to [=queue a microtask=] in both branches here to guarantee that
525
+ coercing an AsyncIterable never stops the Subscription synchronously, thereby releasing
526
+ Zalgo.
527
+
528
+ 1. Let |iteratorMethodRecord| be ? [=GetMethod=] (|value|, %Symbol.iterator%).
529
+
530
+ 1. If |iteratorMethodRecord|'s \[[Value]] is not undefined, then:
531
+
532
+ Note: [=GetMethod=] might return a [=normal completion=] with an undefined value when the
533
+ object simply has no asyncIterator method.
534
+
535
+ 1. Return a [=new=] {{Observable}} whose [=Observable/subscribe callback=] is an
536
+ algorithm that takes a {{Subscriber}} |subscriber| and does the following:
537
+
538
+ 1. Let |iteratorRecord| be [=GetIteratorFromMethod=] (|value|, %Symbol.iterator%).
539
+
540
+ 1. If |iteratorRecord| is a [=throw completion=] then:
541
+
542
+ 1. Run |subscriber|'s {{Subscriber/error()}} method, given |iteratorRecord|' s \[[Value]] .
543
+
544
+ 1. Abort these steps.
545
+
546
+ 1. Let |iterator| be |iteratorRecord|'s \[[Value]] .
547
+
548
+ 1. Repeat:
549
+
550
+ 1. If |iterator|'s \[[Done]] is true, then:
551
+
552
+ 1. Run |subscriber|'s {{Subscriber/complete()}} method and abort these steps.
553
+
554
+ 1. Let |nextRecord| be [=IteratorStepValue=] (|iterator|).
555
+
556
+ 1. If |nextRecord| is a [=throw completion=] then:
557
+
558
+ 1. Run |subscriber|'s {{Subscriber/error()}} method, given |nextRecord|' s \[[Value]] .
559
+
560
+ 1. Abort these steps.
561
+
562
+ 1. Run |subscriber|'s {{Subscriber/next()}} given |nextRecord|' s \[[Value]] .
563
+
564
+ 1. If [=IsPromise=] (|value|) is true, then:
565
+
566
+ 1. Return a [=new=] {{Observable}} whose [=Observable/subscribe callback=] is an
567
+ algorithm that takes a {{Subscriber}} |subscriber| and does the following:
568
+
569
+ 1. React to |value|:
570
+
571
+ 1. If |value| was fulfilled with value |v|, then:
572
+
573
+ 1. Run |subscriber|'s {{Subscriber/next()}} method, given |v|.
574
+
575
+ 1. Run |subscriber|'s {{Subscriber/complete()}} method.
576
+
577
+ 1. If |value| was rejected with reason |r|, then run |subscriber|'s
578
+ {{Subscriber/error()}} method, given |r|.
579
+
580
+ 1. Throw a {{TypeError}} .
581
+
582
+ </div>
583
+
445
584
<div algorithm>
446
585
To <dfn for=Observable>subscribe to an {{Observable}}</dfn> given an
447
586
{{ObserverUnion}} -or-[=internal observer=] |observer|, and a {{SubscribeOptions}} |options|, run
@@ -556,15 +695,25 @@ For now, see [https://github.com/wicg/observable#operators](https://github.com/w
556
695
557
696
<h4 id=observable-from>{{Observable/from()}}</h4>
558
697
559
- <p class=XXX> Spec the exact semantics of {{Observable/from()}} conversion.</p>
698
+ <div algorithm>
699
+ The <dfn for=Observable method><code>from(|value|)</code></dfn> method steps
700
+ are:
701
+
702
+ 1. Return the result of <a for=Observable lt="convert to an Observable">
703
+ converting</a> |value| to an Observable.
704
+
705
+ </div>
560
706
561
707
<h4 id=observable-returning-operators>{{Observable}}-returning operators</h4>
562
708
563
709
<div algorithm>
564
- The <dfn for=Observable method><code>takeUntil(|notifier |)</code></dfn> method steps are:
710
+ The <dfn for=Observable method><code>takeUntil(|value |)</code></dfn> method steps are:
565
711
566
712
1. Let |sourceObservable| be [=this=] .
567
713
714
+ 1. Let |notifier| be the result of <a for=Observable lt="convert to an Observable">
715
+ converting</a> |value| to an Observable.
716
+
568
717
1. Let |observable| be a [=new=] {{Observable}} whose [=Observable/subscribe callback=] is an
569
718
algorithm that takes a {{Subscriber}} |subscriber| and does the following:
570
719
0 commit comments