Sorry, make that LGTM2 On Wed, Mar 5, 2025 at 1:00 PM Chris Harrelson <chris...@chromium.org> wrote:
> Thanks Dominic! > > LGTM1 > > On Wed, Mar 5, 2025 at 12:57 PM Dominic Farolino <d...@chromium.org> wrote: > >> Thanks for the summary Jake. So from the perspective of API OWNERS, I >> don't believe anything is blocking here. Folks agree that the ref-counted >> producer design is the right way, consistent with the developer feedback, >> and while you can hold the API in a way that appears surprising, (1) there >> are more surprises/quirks with the non-ref-counted approach, and (2) our >> design is consistent with the ways developers use Observables in the wild, >> mitigating the consequences of any surprises—I believe we're making the >> right trade-off. >> >> Given that, I believe we can proceed with the review. >> >> On Fri, Feb 28, 2025 at 12:32 PM Jake Archibald <jaffathec...@gmail.com> >> wrote: >> >>> By missing the end, I mean this: >>> >>> const ob = new Observable((subscriber) => { >>> subscriber.next(1); >>> setTimeout(() => { >>> subscriber.next(2); >>> subscriber.complete(); >>> }, 1000); >>> }); >>> >>> ob.toArray().then((vals) => { >>> // You're first, so you get things from the start. >>> console.log(vals); // [1, 2] >>> }); >>> >>> ob.toArray().then((vals) => { >>> // You missed the start, so you get the remaining values. >>> // I'd describe the model here as: too late, you miss out! >>> console.log(vals); // [2] >>> }); >>> >>> setTimeout(() => { >>> ob.toArray().then((vals) => { >>> // You missed the end, so we restart. >>> // I'd describe the model here as: we'll fix it so you don't miss out >>> console.log(vals); // [1, 2] >>> }); >>> }, 1500); >>> >>> The bit where it sometimes restarts the thing so you don't miss out, and >>> sometimes doesn't, felt unusual to me. To be clear, I think the >>> ref-counting approach is right, but it would have felt more consistent if >>> the final log was [], since the thing had already completed. >>> >>> The other case I found inconsistent is: >>> >>> const ob = Observable.from([1, 2, 3]); >>> >>> ob.toArray().then((vals) => { >>> console.log(vals); // [1, 2, 3] >>> }); >>> >>> ob.toArray().then((vals) => { >>> console.log(vals); // [1, 2, 3] >>> }); >>> >>> vs >>> >>> const ob = Observable.from([1, 2, 3].values()); >>> >>> ob.toArray().then((vals) => { >>> console.log(vals); // [1, 2, 3] >>> }); >>> >>> ob.toArray().then((vals) => { >>> console.log(vals); // [] >>> }); >>> >>> I had a meeting with Dominic and I now understand why it happens. It >>> still seems unusual, but given that this hasn't come up for anyone else >>> looking at the API (people who have way more experience with observables >>> than I do), I guess it's just that I'm unfamiliar with these patterns. It's >>> certainly something I'd call out in developer documentation for others >>> coming to this fresh. >>> >>> Thanks all! >>> Jake. >>> >>> On Fri, 28 Feb 2025 at 15:32, Dominic Farolino <d...@chromium.org> wrote: >>> >>>> Responding to Jake: >>>> >>>> With the example in the codepen, as the holder of the observable, I >>>>> don't think I have a way of knowing if I'm getting the start, or something >>>>> in the middle. Isn't that a bit odd? >>>> >>>> >>>> Hmm, I see how it can feel a little intuitive, but I think this >>>> tradeoff is *less unintuitive* than it was without ref-counted >>>> producers, where Observable doesn't really represent anything related to >>>> the subscription, causing the footguns that led to us pursuing this path in >>>> the first place. Regarding: >>>> >>>> If it's ok to miss the start, why isn't it ok to miss the end? >>>> >>>> >>>> I don't think it is OK to miss the end, and I don't quite think our >>>> proposal makes this possible? If you subscribe half-way through, you will >>>> still get `complete()` notifications so you know that the stream has ended. >>>> The closest example of "missing the end" I can think of would be the one >>>> you mentioned over X/Twitter, which is if you subscribe to an async >>>> iterator (not iterable that can be restarted), and you exhaust the >>>> iterator, what do subsequent subscriptions do after the iterator is >>>> exhausted? >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> * async function* asyncNumbers() { yield* [1,2,3,4]; } const ob = >>>> Observable.from(asyncNumbers()); await ob.toArray().then(result => >>>> console.log('one', result)); ob.subscribe({ next: v => >>>> console.log('second subscription: ', v), complete: () => >>>> console.log('complete'), })* >>>> >>>> By the time the second subscription rolls around, the iterator has been >>>> exhausted. But you still don't "miss the end" since the `complete()` >>>> handler fires. Hopefully that makes sense. Either way, it's entirely >>>> possible this thread isn't the best place to hash all of this out :) >>>> >>>> On Fri, Feb 28, 2025 at 10:20 AM Dominic Farolino <d...@chromium.org> >>>> wrote: >>>> >>>>> I was told that it would be good to clarify something here from the >>>>> original email sent here, about *TC39's engagement* and *WebKit's >>>>> standards position*. >>>>> >>>>> *WebKit*: Positive ( >>>>>> https://github.com/WebKit/standards-positions/issues/292) >>>>> >>>>> >>>>> I marked WebKit's standards position as positive since Anne had >>>>> mentioned WebKit folks were supportive and he recommended marking the >>>>> issue >>>>> as `position: support` >>>>> <https://github.com/WebKit/standards-positions/issues/292#issuecomment-2520739850>. >>>>> However, he has since walked it back since the proposal has not been >>>>> formally presented to TC39. Such a presentation is abnormal for web APIs >>>>> not developing *within* TC39, however is still a reasonable idea that >>>>> I am happy to do. (For what it's worth, I tried to present this proposal >>>>> to >>>>> TC39 at the Tokyo virtual meeting in October 2024 after TPAC last year, >>>>> and >>>>> unfortunately after staying up late to do, so I got bumped from the agenda >>>>> last minute because other items went over time). >>>>> >>>>> Regarding my comment on *TC39 engagement*, I wrote: >>>>> >>>>> We've gotten good design feedback from TC39 members on many issues >>>>>> which we have implemented accordingly. >>>>> >>>>> >>>>> This is true—various ECMAScript editors have engaged with us on >>>>> substantial design issues. However, since we have not formally presented >>>>> to >>>>> TC39, I was made aware that this kind of engagement might not count as >>>>> proper *TC39 engagement*. So I wanted to call out here that we have >>>>> not yet sought or received any kind of formal "sign-off" by ECMAScript >>>>> editors on our proposal. >>>>> >>>>> On Thu, Feb 27, 2025 at 1:00 AM Domenic Denicola <dome...@chromium.org> >>>>> wrote: >>>>> >>>>>> I looked into >>>>>> <https://github.com/WICG/observable/issues/177#issuecomment-2686242878> >>>>>> the >>>>>> SuppressedError proposal a bit more. I'm now about 90% convinced >>>>>> SuppressedError does not need to be used. (Or if there is a case for it, >>>>>> it's in extreme edge cases that we could address after shipping.) >>>>>> >>>>>> Given how complete every other aspect of this Intent is, LGTM1, >>>>>> conditional on Dominic agreeing with my reasoning that we don't want to >>>>>> use >>>>>> SuppressedError for most callbacks. If I misunderstood, then we should >>>>>> delay until that gets straightened out. >>>>>> >>>>>> On Thu, Feb 27, 2025 at 5:53 AM Jake Archibald < >>>>>> jaffathec...@gmail.com> wrote: >>>>>> >>>>>>> On Wed, 26 Feb 2025 at 20:39, Dominic Farolino <d...@chromium.org> >>>>>>> wrote: >>>>>>> >>>>>>>> https://codepen.io/jaffathecake/pen/raNWMmK?editors=0012 - it >>>>>>>>> seems inconsistent that two of the calls to ob.map create a new >>>>>>>>> subscriber, >>>>>>>>> whereas the other picks up the observable half way through. >>>>>>>> >>>>>>>> >>>>>>>> Right, the idea that a subscription doesn't have side effects if an >>>>>>>> existing subscription is in-flight was essentially the outcome of >>>>>>>> https://github.com/WICG/observable/issues/170 & >>>>>>>> https://github.com/WICG/observable/issues/178. The alternative, >>>>>>>> where producer:consumer are 1:1, made it easy to write >>>>>>>> performance foot-guns where what you actually want is to tap into an >>>>>>>> existing stream of values without paying the cost of setting it up each >>>>>>>> time if it already exists. Many userland Observables inevitably get >>>>>>>> `share()` slapped on them somewhere in the chain to alleviate this, >>>>>>>> but the >>>>>>>> inconsistency made it hard to judge whether your subscription would >>>>>>>> have >>>>>>>> side-effects or not. We also saw a lot of Observable learning material >>>>>>>> was taking pains to caveat >>>>>>>> <https://ronnieschaniel.com/rxjs/rxjs-mastery-hot-vs-cold-observables/#:~:text=Why%20do%20we%20need%20cold%20and%20hot%20Observables%20in%20RxJS%3F> >>>>>>>> right >>>>>>>> away, this unintuitive idea that the Observable type itself doesn't >>>>>>>> represent anything but a stateless subscription vendor. Now it >>>>>>>> basically >>>>>>>> represents the producer, and I think that matches peoples' mental >>>>>>>> models >>>>>>>> <https://github.com/WICG/observable/issues/178#issuecomment-2480525113> >>>>>>>> . >>>>>>>> >>>>>>>> I guess the rule is: A new subscriber is created if the observer >>>>>>>>> has closed, but isn't this really inconsistent? >>>>>>>> >>>>>>>> >>>>>>>> I think it is consistent though, no? It's true that it's neither >>>>>>>> "only one call to the subscriber" nor "each call to the initial >>>>>>>> observable >>>>>>>> initiates a new subscription". But it is similar to what you wrote >>>>>>>> above: a >>>>>>>> subscriber is invoked/spun up if its subscription is closed (not >>>>>>>> observer). >>>>>>>> The pay-off is that you know you're never going to have "extra" side >>>>>>>> effects when subscribing. At most you will spin up a single producer >>>>>>>> (which >>>>>>>> you're OK with since you're subscribing), and at best you will listen >>>>>>>> in on >>>>>>>> an existing one. >>>>>>>> >>>>>>> >>>>>>> I think where it gets confusing is when the observable has a >>>>>>> beginning and an end. It's fine for event targets, because they don't >>>>>>> have >>>>>>> that. >>>>>>> >>>>>>> For event target observables it's 'interested' (add the listener) >>>>>>> and 'distinerested' (remove the listener). Whereas the underlying events >>>>>>> are still continuing. >>>>>>> >>>>>>> With the example in the codepen, as the holder of the observable, I >>>>>>> don't think I have a way of knowing if I'm getting the start, or >>>>>>> something >>>>>>> in the middle. Isn't that a bit odd? If it's ok to miss the start, why >>>>>>> isn't it ok to miss the end? >>>>>>> >>>>>>> Again it might be because I'm not used to the patterns, and they're >>>>>>> well understood elsewhere. >>>>>>> >>>>>>> >>>>>>>> If you need a new subscriber to be created on each subscription, >>>>>>>> you'll need to basically take a closure over the Observable-vending >>>>>>>> API and >>>>>>>> call each `subscribe()` on it, which I hope is not too burdensome. >>>>>>>> >>>>>>>> On Wed, Feb 26, 2025 at 2:55 PM Jake Archibald < >>>>>>>> jaffathec...@gmail.com> wrote: >>>>>>>> >>>>>>>>> I'm struggling a little to get my head around how this works. >>>>>>>>> >>>>>>>>> https://codepen.io/jaffathecake/pen/raNWMmK?editors=0012 - it >>>>>>>>> seems inconsistent that two of the calls to ob.map create a new >>>>>>>>> subscriber, >>>>>>>>> whereas the other picks up the observable half way through. >>>>>>>>> >>>>>>>>> If I put the .complete call in a setTimeout, then there's only one >>>>>>>>> subscriber created. >>>>>>>>> >>>>>>>>> I guess the rule is: A new subscriber is created if the observer >>>>>>>>> has closed, but isn't this really inconsistent? >>>>>>>>> >>>>>>>>> I'd expect it to be one way or the other. As in: >>>>>>>>> >>>>>>>>> There's only one call to the subscriber. >>>>>>>>> Or >>>>>>>>> Each call to the initial observable is a new subscription. >>>>>>>>> >>>>>>>>> The way it's neither one or the other is confusing to me. But >>>>>>>>> maybe that's totally normal for folks who are used to observables? >>>>>>>>> >>>>>>>>> On Friday, 21 February 2025 at 21:25:05 UTC Chromestatus wrote: >>>>>>>>> >>>>>>>>>> Contact emails d...@chromium.org >>>>>>>>>> >>>>>>>>>> Explainer https://github.com/WICG/observable >>>>>>>>>> >>>>>>>>>> Specification https://wicg.github.io/observable >>>>>>>>>> >>>>>>>>>> Summary >>>>>>>>>> >>>>>>>>>> Observables are a popular reactive-programming paradigm to handle >>>>>>>>>> an asynchronous stream of push-based events. They can be thought of >>>>>>>>>> as >>>>>>>>>> Promises but for multiple events, and aim to do what Promises did for >>>>>>>>>> callbacks/nesting. That is, they allow ergonomic event handling by >>>>>>>>>> providing an Observable object that represents the asynchronous flow >>>>>>>>>> of >>>>>>>>>> events. You can "subscribe" to this object to receive events as they >>>>>>>>>> come >>>>>>>>>> in, and call any of its operators/combinators to declaratively >>>>>>>>>> describe the >>>>>>>>>> flow of transformations through which events go. This is in contrast >>>>>>>>>> with >>>>>>>>>> the imperative version, which often requires complicated nesting with >>>>>>>>>> things like `addEventListener()`. For more on this, see the examples >>>>>>>>>> in the >>>>>>>>>> explainer. The big selling point for native Observables is their >>>>>>>>>> integration with EventTarget — its proposed `when()` method that >>>>>>>>>> returns an >>>>>>>>>> Observable which is a "better" `addEventListener()`. See >>>>>>>>>> https://github.com/WICG/observable and >>>>>>>>>> https://twitter.com/domfarolino/status/1684921351004430336. See >>>>>>>>>> the spec https://wicg.github.io/observable/ and the design doc: >>>>>>>>>> https://docs.google.com/document/d/1NEobxgiQO-fTSocxJBqcOOOVZRmXcTFg9Iqrhebb7bg/edit >>>>>>>>>> . >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Blink component Blink>DOM >>>>>>>>>> <https://issues.chromium.org/issues?q=customfield1222907:%22Blink%3EDOM%22> >>>>>>>>>> >>>>>>>>>> TAG review https://github.com/w3ctag/design-reviews/issues/902 >>>>>>>>>> >>>>>>>>>> TAG review status Issues addressed >>>>>>>>>> >>>>>>>>>> Risks >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Interoperability and Compatibility >>>>>>>>>> >>>>>>>>>> Initially we proposed adding the `.on()` method to EventTarget, >>>>>>>>>> which was found to conflict with userland versions of the same >>>>>>>>>> method. The >>>>>>>>>> conflict was found to be too significant to justify shipping our >>>>>>>>>> native >>>>>>>>>> version of this API (see >>>>>>>>>> https://github.com/WICG/observable/issues/39) so we renamed it >>>>>>>>>> to `.when()` and we strongly believe this resolves any naming >>>>>>>>>> collision >>>>>>>>>> issues after searching through public libraries and performing >>>>>>>>>> developer >>>>>>>>>> outreach on X. See the discussion on that issue. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> *Gecko*: No signal ( >>>>>>>>>> https://github.com/mozilla/standards-positions/issues/945) >>>>>>>>>> >>>>>>>>>> *WebKit*: Positive ( >>>>>>>>>> https://github.com/WebKit/standards-positions/issues/292) >>>>>>>>>> >>>>>>>>>> *Web developers*: Strongly positive ( >>>>>>>>>> https://twitter.com/domfarolino/status/1684921351004430336) Also >>>>>>>>>> see https://foolip.github.io/spec-reactions/ and the developer >>>>>>>>>> interest in the original WHATWG DOM issue. >>>>>>>>>> >>>>>>>>>> *Other signals*: We've gotten good design feedback from TC39 >>>>>>>>>> members on many issues which we have implemented accordingly. This >>>>>>>>>> has led >>>>>>>>>> to positive feedback from Node.js, and luke-warm non-negative >>>>>>>>>> feedback from >>>>>>>>>> WinterCG. See https://github.com/WICG/observable/issues/93; >>>>>>>>>> specifically >>>>>>>>>> https://github.com/nodejs/standards-positions/issues/1 & >>>>>>>>>> https://github.com/WICG/observable/issues/30 for Node, and >>>>>>>>>> https://github.com/wintercg/proposal-minimum-common-api/issues/72 >>>>>>>>>> for WinterCG. >>>>>>>>>> >>>>>>>>>> WebView application risks >>>>>>>>>> >>>>>>>>>> Does this intent deprecate or change behavior of existing APIs, >>>>>>>>>> such that it has potentially high risk for Android WebView-based >>>>>>>>>> applications? >>>>>>>>>> >>>>>>>>>> None >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Debuggability >>>>>>>>>> >>>>>>>>>> The developer experience of Observables might benefit from >>>>>>>>>> Observable-specific DevTools tracking of events and streams (see >>>>>>>>>> https://github.com/WICG/observable/issues/55). It is possible >>>>>>>>>> that the existing DevTools work that assists asynchronous task >>>>>>>>>> tracking and >>>>>>>>>> callstack tagging may be sufficient though. At the moment, however, >>>>>>>>>> our >>>>>>>>>> effort is focused on the platform implementation of Observables. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Will this feature be supported on all six Blink platforms >>>>>>>>>> (Windows, Mac, Linux, ChromeOS, Android, and Android WebView)? >>>>>>>>>> Yes >>>>>>>>>> >>>>>>>>>> Is this feature fully tested by web-platform-tests >>>>>>>>>> <https://chromium.googlesource.com/chromium/src/+/main/docs/testing/web_platform_tests.md> >>>>>>>>>> ? Yes >>>>>>>>>> >>>>>>>>>> See https://wpt.fyi/results/dom/observable/tentative. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Flag name on about://flags observable-api >>>>>>>>>> >>>>>>>>>> Finch feature name ObservableAPI >>>>>>>>>> >>>>>>>>>> Requires code in //chrome? False >>>>>>>>>> >>>>>>>>>> Tracking bug >>>>>>>>>> https://bugs.chromium.org/p/chromium/issues/detail?id=1485981 >>>>>>>>>> >>>>>>>>>> Estimated milestones >>>>>>>>>> Shipping on desktop 135 >>>>>>>>>> >>>>>>>>>> Anticipated spec changes >>>>>>>>>> >>>>>>>>>> Open questions about a feature may be a source of future web >>>>>>>>>> compat or interop issues. Please list open issues (e.g. links to >>>>>>>>>> known >>>>>>>>>> github issues in the project for the feature specification) whose >>>>>>>>>> resolution may introduce web compat/interop risk (e.g., changing to >>>>>>>>>> naming >>>>>>>>>> or structure of the API in a non-backward-compatible way). >>>>>>>>>> Issues with the "possible future enhancement" label [1] track >>>>>>>>>> possible changes to the feature that may come after we ship the >>>>>>>>>> initial >>>>>>>>>> API. One issue (https://github.com/WICG/observable/issues/200) >>>>>>>>>> is identified to have behavior changes that theoretically pose a >>>>>>>>>> compat >>>>>>>>>> risk, but only for developers that subclass the API. The behavior >>>>>>>>>> change >>>>>>>>>> proposed puts the implementation more inline with what subclass >>>>>>>>>> users want: >>>>>>>>>> the operators that return native Observable objects would instead >>>>>>>>>> return >>>>>>>>>> objects of `this.constructor` type, as to return instances of the >>>>>>>>>> subclass >>>>>>>>>> that the operators are called on. This is how JS built-ins like >>>>>>>>>> `Array` >>>>>>>>>> work, however, no other web platform feature works like this and it >>>>>>>>>> likely >>>>>>>>>> requires non-trivial Web IDL support. [1]: >>>>>>>>>> https://github.com/WICG/observable/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22possible%20future%20enhancement%22 >>>>>>>>>> >>>>>>>>>> Link to entry on the Chrome Platform Status >>>>>>>>>> https://chromestatus.com/feature/5154593776599040?gate=5141110901178368 >>>>>>>>>> >>>>>>>>>> Links to previous Intent discussions Intent to Prototype: >>>>>>>>>> https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAP-uykBH1%3DUoLN6%3DBRSEZE%2B1iUq6UdcTpo3qtTQ5T%3DSRxwnu5Q%40mail.gmail.com >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> This intent message was generated by Chrome Platform Status >>>>>>>>>> <https://chromestatus.com>. >>>>>>>>>> >>>>>>>>> -- >>>>>>> You received this message because you are subscribed to the Google >>>>>>> Groups "blink-dev" group. >>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>> send an email to blink-dev+unsubscr...@chromium.org. >>>>>>> To view this discussion visit >>>>>>> https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAJ5xic-3d9ziBOmqHYiSGPxLmDzhu19vfbQHffqJSkprFcE%2Btg%40mail.gmail.com >>>>>>> <https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAJ5xic-3d9ziBOmqHYiSGPxLmDzhu19vfbQHffqJSkprFcE%2Btg%40mail.gmail.com?utm_medium=email&utm_source=footer> >>>>>>> . >>>>>>> >>>>>> -- >> You received this message because you are subscribed to the Google Groups >> "blink-dev" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to blink-dev+unsubscr...@chromium.org. >> To view this discussion visit >> https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAP-uykDqj_RgJ8xkPvkgxeGqVbj9vHbipMuzMjR35fH%3DpY-NJw%40mail.gmail.com >> <https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAP-uykDqj_RgJ8xkPvkgxeGqVbj9vHbipMuzMjR35fH%3DpY-NJw%40mail.gmail.com?utm_medium=email&utm_source=footer> >> . >> > -- You received this message because you are subscribed to the Google Groups "blink-dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscr...@chromium.org. To view this discussion visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAOMQ%2Bw_U3Wa45QJKUB-ned8EVoHCjKJgC5ECNjLsR7Or%3D_kv%3DQ%40mail.gmail.com.