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

streams: fixes for webstreams #51168

Merged
merged 20 commits into from
Dec 26, 2023
Merged

streams: fixes for webstreams #51168

merged 20 commits into from
Dec 26, 2023

Conversation

MattiasBuelens
Copy link
Contributor

Follow-up on #50126.

  • Avoid PromiseResolve in ensureIsPromise. Web IDL requires this to always return a new Promise, whereas PromiseResolve may return the same Promise. This leads to a different timing, since new Promise() takes at least one microtask to resolve. See my previous comment.
  • Fix handling sync errors from source cancel and sink abort. We were not correctly handling synchronously-thrown errors from these, which could leave the stream in an incorrect state.
  • Check for promise only when constructing from source/sink/transformer. When constructing an internal stream, these algorithms must always return a promise, and we shouldn't wrap them again with ensureIsPromise().
  • Fix TeeReadableStream. This should construct an internal stream with internal callbacks using setupReadableStreamDefaultController, but it was incorrectly using user-land callbacks with setupReadableStreamDefaultControllerFromSource.
  • Use internal streams for teeing a readable byte stream. This was using the user-land ReadableStream constructor, which is incorrect. The new implementation mirrors how we handle teeing "default" readable streams.
  • Use internal streams for ReadableStream.from(). Again, this was incorrectly using the user-land ReadableStream constructor.
  • Use internal streams for TransformStream. Same thing again.
  • Add a helper to create the internal state of a ReadableStream and WritableStream. This code was duplicated a few times, so it made sense to extract a helper function.
  • Remove an unused field in the ReadableStream internal state. This seemed like a copy-paste mistake: other classes (like ReadableStreamDefaultController) do have a stream field in their state, but ReadableStream shouldn't.
  • Fix validating callbacks. Previously, we asserted that the given callbacks were indeed typeof callback === "function" by virtue of bluntly trying to call FunctionPrototypeBind on them. We no longer use FunctionPrototypeBind for this, so we need to manually call validateFunction for each callback. I've wrapped that in a createPromiseCallback helper.
  • Update expectations for the Streams WPT tests.

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/web-standards

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. web streams labels Dec 15, 2023
lib/internal/webstreams/readablestream.js Outdated Show resolved Hide resolved
Comment on lines 183 to 190
function ensureIsPromise(fn, thisArg, ...args) {
try {
const value = FunctionPrototypeCall(fn, thisArg, ...args);
return isPromise(value) ? value : PromiseResolve(value);
return new Promise((r) => r(value));
} catch (error) {
return PromiseReject(error);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

if it's always making a new promise, any reason not to do this?

Suggested change
function ensureIsPromise(fn, thisArg, ...args) {
try {
const value = FunctionPrototypeCall(fn, thisArg, ...args);
return isPromise(value) ? value : PromiseResolve(value);
return new Promise((r) => r(value));
} catch (error) {
return PromiseReject(error);
}
}
async function ensureIsPromise(fn, thisArg, ...args) {
return await FunctionPrototypeCall(fn, thisArg, ...args);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like that a lot! An async function always returns a fresh Promise, so this should satisfy Web IDL. 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately, this change causes some tests to fail again... 😞

However, if you remove the await, it does work:

async function ensureIsPromise(fn, thisArg, ...args) {
  return FunctionPrototypeCall(fn, thisArg, ...args);
}

You still get a fresh Promise (from async function), errors are still correctly turned into rejections, and the timings match Web IDL.

Still, I don't like how sensitive these tests are to the number of microtasks. I'll try to fix this in upstream WPT.

lib/internal/webstreams/writablestream.js Outdated Show resolved Hide resolved
lib/internal/webstreams/writablestream.js Outdated Show resolved Hide resolved
@debadree25
Copy link
Member

cc @nodejs/whatwg-stream

@debadree25 debadree25 added the request-ci Add this label to start a Jenkins CI on a PR. label Dec 16, 2023
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Dec 16, 2023
@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

@mcollina mcollina added commit-queue Add this label to land a pull request using GitHub Actions. commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. and removed needs-ci PRs that need a full CI run. labels Dec 26, 2023
@nodejs-github-bot nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Dec 26, 2023
@nodejs-github-bot nodejs-github-bot merged commit 20c6313 into nodejs:main Dec 26, 2023
60 checks passed
@nodejs-github-bot
Copy link
Collaborator

Landed in 20c6313

@MattiasBuelens MattiasBuelens deleted the webstreams-fixes branch December 27, 2023 10:27
RafaelGSS pushed a commit that referenced this pull request Jan 2, 2024
PR-URL: #51168
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
@RafaelGSS RafaelGSS mentioned this pull request Jan 2, 2024
@marco-ippolito marco-ippolito added the backport-requested-v20.x PRs awaiting manual backport to the v20.x-staging branch. label May 1, 2024
@marco-ippolito
Copy link
Member

this doesn't land cleanly on v20 requires a manual backport

@MattiasBuelens
Copy link
Contributor Author

@marco-ippolito This PR builds upon #50107, specifically: 0d45e6f needs a85e418. However, that other PR is marked "dont-land-on-v20.x". 😕

I'm not sure how to proceed with a manual backport. Should I try to rework my changes without that PR, or should we backport #50107 to v20.x anyway?

@marco-ippolito
Copy link
Member

marco-ippolito commented May 1, 2024

I guess then we wont backport it, @targos I saw you marked #50107 as dont not land on v20, wdyt

@marco-ippolito marco-ippolito added dont-land-on-v20.x PRs that should not land on the v20.x-staging branch and should not be released in v20.x. and removed backport-requested-v20.x PRs awaiting manual backport to the v20.x-staging branch. labels May 1, 2024
MattiasBuelens added a commit to MattiasBuelens/node that referenced this pull request May 1, 2024
PR-URL: nodejs#51168
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
@MattiasBuelens
Copy link
Contributor Author

On second thought, I think I can rework my changes. Let me try something... 👨‍🔬

MattiasBuelens added a commit to MattiasBuelens/node that referenced this pull request May 1, 2024
PR-URL: nodejs#51168
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
@MattiasBuelens
Copy link
Contributor Author

@marco-ippolito I managed to make it work without #50107, see #52773.

However, If we also want to backport #50107, then I'll need to change it up again. 😛 Let me know how you want to proceed.

@targos
Copy link
Member

targos commented May 1, 2024

I marked it dont-land because it depended on #47956, which was dont-land. Feel free to remove the label and backport.

@marco-ippolito marco-ippolito added backport-open-v20.x Indicate that the PR has an open backport and removed dont-land-on-v20.x PRs that should not land on the v20.x-staging branch and should not be released in v20.x. labels May 1, 2024
MattiasBuelens added a commit to MattiasBuelens/node that referenced this pull request May 16, 2024
PR-URL: nodejs#51168
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
MattiasBuelens added a commit to MattiasBuelens/node that referenced this pull request Jun 25, 2024
PR-URL: nodejs#51168
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
MattiasBuelens added a commit to MattiasBuelens/node that referenced this pull request Jun 25, 2024
PR-URL: nodejs#51168
Backport-PR-URL: nodejs#52773
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
marco-ippolito pushed a commit that referenced this pull request Jul 19, 2024
PR-URL: #51168
Backport-PR-URL: #52773
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
@targos targos added backported-to-v20.x PRs backported to the v20.x-staging branch. and removed backport-open-v20.x Indicate that the PR has an open backport labels Sep 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. backported-to-v20.x PRs backported to the v20.x-staging branch. commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. web streams
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants