Skip to content
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

Add basic observable constructor tests #42219

Merged
merged 20 commits into from
Nov 9, 2023

Conversation

benlesh
Copy link
Contributor

@benlesh benlesh commented Sep 28, 2023

Attn @domfarolino ... here's a basic battery of tests covering new Observable, observation semantics, handled and unhandled errors in various scenarios, addTeardown, subscribe and forEach.

@wpt-pr-bot wpt-pr-bot added the dom label Sep 28, 2023
@wpt-pr-bot wpt-pr-bot requested review from annevk and jdm September 28, 2023 16:44
@domfarolino domfarolino assigned domfarolino and unassigned annevk Sep 28, 2023
@domfarolino domfarolino requested review from domfarolino and removed request for jdm and annevk September 28, 2023 17:38
@wpt-pr-bot
Copy link
Collaborator

There are no reviewers for this pull request. Please reach out on the chat room to get help with this. Thank you!

Copy link
Member

@domfarolino domfarolino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments, nothing too serious. The biggest concern I have is .closed which I don't think was discussed in the explainer repo at all. I'd prefer to leave that out here and address it there first to collect more feedback and thoughts if you're OK with that. In part because its utility is not 100% clear to me, so having that discussion outside of this test PR seems good.

dom/observable/tentative/observable-ctor.any.js Outdated Show resolved Hide resolved
subscriber.next(1);
throw error;
} finally {
assert_true(subscriber.closed, "subscriber is closed after error");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, we haven't really discussed the .closed attribute on the Subscriber interface yet, so maybe we should hold off on this assertion. Can we assert other side-effects, (i.e., would subscriber.signal.aborted be true? Maybe not since the outer AbortController didn't actually abort this).

Maybe it would just be good to assert the teardown is called, and talk about this attribute later.

Copy link
Contributor Author

@benlesh benlesh Sep 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(i.e., would subscriber.signal.aborted be true? Maybe not since the outer AbortController didn't actually abort this).

There's some "dead space" where there's a difference between "closed" and "signal.aborted"

Basically, the signal is aborted after your complete handler is fired. But at the moment subscriber.complete is called, the subscriber has to be shut down (closed).

Consider the following: (this may seem outlandish, but it's just a small bit of code simulating some of the things that can happen with home brew observable operators, in particular, reentrancy, where someone composes an observable that emits into itself in a roundabout way)

let level = 0;
const source = new Observable(subscriber => {
  subscriber.addTeardown(() => {
    console.log('torn down!');
  });
  
  if (level++ === 0) {
    // Rentrant code
    source.subscribe({
      complete: () => {
        if ((!subscriber.signal.aborted) {
          subscriber.complete();
        }
      },
      signal: subscriber.signal
    })
  } else {
    subscriber.complete();
  }
})

const ac = new AbortController();
source.subscribe({
  complete: () => console.log('complete!'),
  signal: ac.signal
})

In the above case, the provided subscriber.signal, which is following whatever signal was passed into the subscribe call, would not be "aborted" yet, because it should semantically abort AFTER the complete handler fires. So we'll get stuck in a loop.

There's already a pieces of state we have to track internally in the Subscriber so that next, error, and complete can't be called if error or complete have already been called. This is an important part of the guarantee.

So the lifecycle inside the subscriber (if complete or error is called):

  1. "close" the subscriber to new calls/actions (disable next, report errors passed to error, disable complete, and put addTeardown in a state of "execute immediately". This is a safety mechanism and a valuable guarantee.
  2. emit complete (or error)
  3. Tear down (by aborting the signal attached to this, which also controls everything registed with addTeardown.

The closed property of Subscriber exposes this "close" state from 1 above.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that makes sense, I just think we should put this in the explainer with a PR first, with the justification above etc. Also I think it's worth having some discussion about:

In the above case, the provided subscriber.signal, which is following whatever signal was passed into the subscribe call, would not be "aborted" yet, because it should semantically abort AFTER the complete handler fires.

It sounds like you're saying that even with .closed existing, you think the AbortSignal should be aborted after complete() or error() is fired, which seems weird to me. I think only AbortController should be able to abort an AbortSignal. But maybe you're only saying this in the theoretical world where .closed didn't exist (like the example you have above)... either way, all of this discussion should probably happen on https://github.com/WICG/observable instead of here, if that makes sense.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we'll get stuck in a loop.

This part I'm not sure I see. It seems like the re-entrant (i.e., the most nested) call to complete() would just trigger the outermost complete() handler, right? I don't think I see an actual infinite loop here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you think the AbortSignal should be aborted after complete() or error() is fired, which seems weird to me. I think only AbortController should be able to abort an AbortSignal

There's the AbortSignal that was passed into the subscription, and then there's an AbortSignal related to the status of the subscription. If the subscription is "complete" or "errors" we need to teardown resources and cancel any upcoming work. Therefor, if you complete() or error() the signal that is on the Subscriber should be aborted. This signal would not be the same signal that was passed into the subscription.

new Observable(subscriber => {
  console.log(subscriber.signal.aborted); // false
  subscriber.complete();
  console.log(subscriber.signal.aborted); // true.
})

dom/observable/tentative/observable-ctor.any.js Outdated Show resolved Hide resolved
});

source.subscribe();
}, "subscriber is closed after complete");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the above comment about .closed. It isn't totally clear to me what this buys us, so maybe we could discuss it on the explainer before writing test expectations around it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

closed is necessary for "synchronous firehose" scenarios. If you want take to work in this scenario:

const result = new Observable(subscriber => {
  let n = 0;
  while (!subscriber.closed) {
    subscriber.next(n++);
  }
})

result.take(3).subscribe({ 
  next: console.log
})

If there's no way to examine if the subscription has been ended by the take(3), then there's no way to break that while loop.

source.subscribe();
}, "subscriber is closed after complete");

test(() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

dom/observable/tentative/observable-ctor.any.js Outdated Show resolved Hide resolved
dom/observable/tentative/observable-ctor.any.js Outdated Show resolved Hide resolved
dom/observable/tentative/observable-ctor.any.js Outdated Show resolved Hide resolved
"should emit values synchronously, but not error after complete"
);

assert_true(errorReported);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the error reporting handler be called twice? And if so, should we assert that one way or another?

chromium-wpt-export-bot pushed a commit that referenced this pull request Oct 4, 2023
This CL adds the SubscribeCallback type and invokes it when the
subscribe method is called. This passes a few more tests in
#42219, but is very
limited because we don't actually add the `Subscriber` interface yet,
or the corresponding `Observer` dictionary event handlers.

Those will come in another CL. For now, this just implements the
Observable subscription invocation semantics as well as the report
exception semantics.

R=masonf@chromium.org

Bug: 1485981
Change-Id: Id32a21ed943908e3a2e61d50261a1b4b3fbd5e97
chromium-wpt-export-bot pushed a commit that referenced this pull request Oct 4, 2023
This CL adds the SubscribeCallback type and invokes it when the
subscribe method is called. It also adds some rudimentary `Observable`
constructor tests that were ported from
#42219 into this CL.

The results are very limited because we haven't introduced the
`Subscriber` interface yet, or the corresponding `Observer` dictionary
event handlers. Those will come in another CL. For now, this just
implements the Observable subscription invocation semantics as well as
the report exception semantics.

For WPTs:
Co-authored-by: ben@benlesh.com

R=masonf@chromium.org

Bug: 1485981
Change-Id: Id32a21ed943908e3a2e61d50261a1b4b3fbd5e97
chromium-wpt-export-bot pushed a commit that referenced this pull request Oct 4, 2023
This CL adds the SubscribeCallback type and invokes it when the
subscribe method is called. It also adds some rudimentary `Observable`
constructor tests that were ported from
#42219 into this CL.

The results are very limited because we haven't introduced the
`Subscriber` interface yet, or the corresponding `Observer` dictionary
event handlers. Those will come in another CL. For now, this just
implements the Observable subscription invocation semantics as well as
the report exception semantics.

For WPTs:
Co-authored-by: ben@benlesh.com

R=masonf@chromium.org

Bug: 1485981
Change-Id: Id32a21ed943908e3a2e61d50261a1b4b3fbd5e97
aarongable pushed a commit to chromium/chromium that referenced this pull request Oct 5, 2023
This CL adds the SubscribeCallback type and invokes it when the
subscribe method is called. It also adds some rudimentary `Observable`
constructor tests that were ported from
web-platform-tests/wpt#42219 into this CL.

The results are very limited because we haven't introduced the
`Subscriber` interface yet, or the corresponding `Observer` dictionary
event handlers. Those will come in another CL. For now, this just
implements the Observable subscription invocation semantics as well as
the report exception semantics.

For WPTs:
Co-authored-by: ben@benlesh.com

R=masonf@chromium.org

Bug: 1485981
Change-Id: Id32a21ed943908e3a2e61d50261a1b4b3fbd5e97
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4904686
Reviewed-by: Mason Freed <masonf@chromium.org>
Commit-Queue: Dominic Farolino <dom@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1205647}
chromium-wpt-export-bot pushed a commit that referenced this pull request Oct 5, 2023
This CL adds the SubscribeCallback type and invokes it when the
subscribe method is called. It also adds some rudimentary `Observable`
constructor tests that were ported from
#42219 into this CL.

The results are very limited because we haven't introduced the
`Subscriber` interface yet, or the corresponding `Observer` dictionary
event handlers. Those will come in another CL. For now, this just
implements the Observable subscription invocation semantics as well as
the report exception semantics.

For WPTs:
Co-authored-by: ben@benlesh.com

R=masonf@chromium.org

Bug: 1485981
Change-Id: Id32a21ed943908e3a2e61d50261a1b4b3fbd5e97
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4904686
Reviewed-by: Mason Freed <masonf@chromium.org>
Commit-Queue: Dominic Farolino <dom@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1205647}
chromium-wpt-export-bot pushed a commit that referenced this pull request Oct 5, 2023
This CL adds the SubscribeCallback type and invokes it when the
subscribe method is called. It also adds some rudimentary `Observable`
constructor tests that were ported from
#42219 into this CL.

The results are very limited because we haven't introduced the
`Subscriber` interface yet, or the corresponding `Observer` dictionary
event handlers. Those will come in another CL. For now, this just
implements the Observable subscription invocation semantics as well as
the report exception semantics.

For WPTs:
Co-authored-by: ben@benlesh.com

R=masonf@chromium.org

Bug: 1485981
Change-Id: Id32a21ed943908e3a2e61d50261a1b4b3fbd5e97
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4904686
Reviewed-by: Mason Freed <masonf@chromium.org>
Commit-Queue: Dominic Farolino <dom@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1205647}
cookiecrook pushed a commit to cookiecrook/wpt that referenced this pull request Oct 11, 2023
This CL adds the SubscribeCallback type and invokes it when the
subscribe method is called. It also adds some rudimentary `Observable`
constructor tests that were ported from
web-platform-tests#42219 into this CL.

The results are very limited because we haven't introduced the
`Subscriber` interface yet, or the corresponding `Observer` dictionary
event handlers. Those will come in another CL. For now, this just
implements the Observable subscription invocation semantics as well as
the report exception semantics.

For WPTs:
Co-authored-by: ben@benlesh.com

R=masonf@chromium.org

Bug: 1485981
Change-Id: Id32a21ed943908e3a2e61d50261a1b4b3fbd5e97
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4904686
Reviewed-by: Mason Freed <masonf@chromium.org>
Commit-Queue: Dominic Farolino <dom@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1205647}
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this pull request Oct 26, 2023
…nctionality, a=testonly

Automatic update from web-platform-tests
DOM: Add Observable SubscribeCallback functionality

This CL adds the SubscribeCallback type and invokes it when the
subscribe method is called. It also adds some rudimentary `Observable`
constructor tests that were ported from
web-platform-tests/wpt#42219 into this CL.

The results are very limited because we haven't introduced the
`Subscriber` interface yet, or the corresponding `Observer` dictionary
event handlers. Those will come in another CL. For now, this just
implements the Observable subscription invocation semantics as well as
the report exception semantics.

For WPTs:
Co-authored-by: ben@benlesh.com

R=masonf@chromium.org

Bug: 1485981
Change-Id: Id32a21ed943908e3a2e61d50261a1b4b3fbd5e97
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4904686
Reviewed-by: Mason Freed <masonf@chromium.org>
Commit-Queue: Dominic Farolino <dom@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1205647}

--

wpt-commits: b213cbfd9c0cad9a3cf2005a57194fefac1b9b64
wpt-pr: 42341
ErichDonGubler pushed a commit to erichdongubler-mozilla/firefox that referenced this pull request Oct 27, 2023
…nctionality, a=testonly

Automatic update from web-platform-tests
DOM: Add Observable SubscribeCallback functionality

This CL adds the SubscribeCallback type and invokes it when the
subscribe method is called. It also adds some rudimentary `Observable`
constructor tests that were ported from
web-platform-tests/wpt#42219 into this CL.

The results are very limited because we haven't introduced the
`Subscriber` interface yet, or the corresponding `Observer` dictionary
event handlers. Those will come in another CL. For now, this just
implements the Observable subscription invocation semantics as well as
the report exception semantics.

For WPTs:
Co-authored-by: ben@benlesh.com

R=masonf@chromium.org

Bug: 1485981
Change-Id: Id32a21ed943908e3a2e61d50261a1b4b3fbd5e97
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4904686
Reviewed-by: Mason Freed <masonf@chromium.org>
Commit-Queue: Dominic Farolino <dom@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1205647}

--

wpt-commits: b213cbfd9c0cad9a3cf2005a57194fefac1b9b64
wpt-pr: 42341
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified-and-comments-removed that referenced this pull request Oct 30, 2023
…nctionality, a=testonly

Automatic update from web-platform-tests
DOM: Add Observable SubscribeCallback functionality

This CL adds the SubscribeCallback type and invokes it when the
subscribe method is called. It also adds some rudimentary `Observable`
constructor tests that were ported from
web-platform-tests/wpt#42219 into this CL.

The results are very limited because we haven't introduced the
`Subscriber` interface yet, or the corresponding `Observer` dictionary
event handlers. Those will come in another CL. For now, this just
implements the Observable subscription invocation semantics as well as
the report exception semantics.

For WPTs:
Co-authored-by: benbenlesh.com

R=masonfchromium.org

Bug: 1485981
Change-Id: Id32a21ed943908e3a2e61d50261a1b4b3fbd5e97
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4904686
Reviewed-by: Mason Freed <masonfchromium.org>
Commit-Queue: Dominic Farolino <domchromium.org>
Cr-Commit-Position: refs/heads/main{#1205647}

--

wpt-commits: b213cbfd9c0cad9a3cf2005a57194fefac1b9b64
wpt-pr: 42341

UltraBlame original commit: 0b36f23073b503e392372b6ba718cb32fe4c7d13
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified that referenced this pull request Oct 30, 2023
…nctionality, a=testonly

Automatic update from web-platform-tests
DOM: Add Observable SubscribeCallback functionality

This CL adds the SubscribeCallback type and invokes it when the
subscribe method is called. It also adds some rudimentary `Observable`
constructor tests that were ported from
web-platform-tests/wpt#42219 into this CL.

The results are very limited because we haven't introduced the
`Subscriber` interface yet, or the corresponding `Observer` dictionary
event handlers. Those will come in another CL. For now, this just
implements the Observable subscription invocation semantics as well as
the report exception semantics.

For WPTs:
Co-authored-by: benbenlesh.com

R=masonfchromium.org

Bug: 1485981
Change-Id: Id32a21ed943908e3a2e61d50261a1b4b3fbd5e97
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4904686
Reviewed-by: Mason Freed <masonfchromium.org>
Commit-Queue: Dominic Farolino <domchromium.org>
Cr-Commit-Position: refs/heads/main{#1205647}

--

wpt-commits: b213cbfd9c0cad9a3cf2005a57194fefac1b9b64
wpt-pr: 42341

UltraBlame original commit: 0b36f23073b503e392372b6ba718cb32fe4c7d13
gecko-dev-updater pushed a commit to marco-c/gecko-dev-comments-removed that referenced this pull request Oct 30, 2023
…nctionality, a=testonly

Automatic update from web-platform-tests
DOM: Add Observable SubscribeCallback functionality

This CL adds the SubscribeCallback type and invokes it when the
subscribe method is called. It also adds some rudimentary `Observable`
constructor tests that were ported from
web-platform-tests/wpt#42219 into this CL.

The results are very limited because we haven't introduced the
`Subscriber` interface yet, or the corresponding `Observer` dictionary
event handlers. Those will come in another CL. For now, this just
implements the Observable subscription invocation semantics as well as
the report exception semantics.

For WPTs:
Co-authored-by: benbenlesh.com

R=masonfchromium.org

Bug: 1485981
Change-Id: Id32a21ed943908e3a2e61d50261a1b4b3fbd5e97
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4904686
Reviewed-by: Mason Freed <masonfchromium.org>
Commit-Queue: Dominic Farolino <domchromium.org>
Cr-Commit-Position: refs/heads/main{#1205647}

--

wpt-commits: b213cbfd9c0cad9a3cf2005a57194fefac1b9b64
wpt-pr: 42341

UltraBlame original commit: 0b36f23073b503e392372b6ba718cb32fe4c7d13
@domfarolino domfarolino changed the title Add basic observable tests for constructor, subscribe, and forEach Add basic observable constructor tests Nov 7, 2023
@domfarolino domfarolino enabled auto-merge (squash) November 9, 2023 18:28
@domfarolino domfarolino merged commit 03d5b9b into web-platform-tests:master Nov 9, 2023
@domfarolino domfarolino deleted the observable-tentative branch November 9, 2023 18:58
Lightning00Blade pushed a commit to Lightning00Blade/wpt that referenced this pull request Dec 11, 2023
This CL adds the SubscribeCallback type and invokes it when the
subscribe method is called. It also adds some rudimentary `Observable`
constructor tests that were ported from
web-platform-tests#42219 into this CL.

The results are very limited because we haven't introduced the
`Subscriber` interface yet, or the corresponding `Observer` dictionary
event handlers. Those will come in another CL. For now, this just
implements the Observable subscription invocation semantics as well as
the report exception semantics.

For WPTs:
Co-authored-by: ben@benlesh.com

R=masonf@chromium.org

Bug: 1485981
Change-Id: Id32a21ed943908e3a2e61d50261a1b4b3fbd5e97
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4904686
Reviewed-by: Mason Freed <masonf@chromium.org>
Commit-Queue: Dominic Farolino <dom@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1205647}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants