-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
ReadableStream internal state #39627
Comments
@nodejs/whatwg-stream |
I'm +1 to expose this via a @domenic wdyt? |
I'll reiterate:
This is why we have a static I vote a static |
We'll end up adding something anyway as we would not have any other way to accessing this state. We might just decide to not expose this |
We already add symbols? |
Adds a helper util used to determine whether a stream has been disturbed (read or cancelled). Refs: nodejs#39627
Adds a helper util used to determine whether a stream has been disturbed (read or cancelled). Refs: nodejs#39627
Adding things we don't consider our public API is risky but fine as long as it's implementation detail and we don't rely on it. If we can't even build without the internal API - that's a good indication we should expose that API (via a static method). Since there is a simple, spec-compliant workaround here (a static method) I suggest we stick to that :) (If we need an API like isDisturbed - contributing back to whatwg is also a good viable option, I am super busy with baby/new-job/new-house/family-health-stuff but technically that can be something I work on in my job, just not in the coming months) |
whatwg/streams#1025 this looks positive |
Adding non-spec statics is not spec-compliant; I'm not sure why you'd think they're any different from prototype properties. |
I would add separate methods that are not hung off the classes at all. const { isDisturbed, isFinished } = require ('stream')
isDisturbed(readable)
isFinished(readable) The challenge with these is that they will have to rely on internal state and not public API but that's fine. |
Adds a helper util used to determine whether a stream has been disturbed (read or cancelled). Refs: nodejs#39627
@domenic I thought adding statics that are not part of the spec does not violate the spec while adding methods to the interface does. Did I misunderstand? const s = getStream();
s.isDisturbed(); // not allowed, adds a method to the prototype
ReadableStream.isDisturbed(s); // not allowed, adds a method to ReadableStream
const { isDisturbed } = await import('nodejs/stream-utils');
isDisturbed(s); // this is fine |
Or did my phrasing imply I meant adding a static to the interface? (That was not my intention nor the implementation in the PR ronag followed up with) |
Ah, yeah, I thought by static you meant the thing you get in JavaScript when using the static keyword :). If you're talking about module exports then no problem! |
I have to re-open this as I've encountered another state. https://fetch.spec.whatwg.org/#abort-fetch
How can I inspect whether "body" is "readable" without access to internal state?
|
@jasnell I don't think you are going to be happy with me... but I found a way 😄 function isReadable (stream) {
// This is a hack!
return /state: 'readable'/.test(util.inspect(stream))
} |
My understanding is - |
Correct. We need it to implement fetch in user land outside of core. |
If async suffices the following should work I believe: async function isReadable(reader) {
let readable = true;
reader.closed.then(() => { readable = false; }, () => { readable = false; });
await Promise.resolve();
// If the stream was closed or errored then the closed promise would have settled by now and updated readable.
// If not then it's readable.
return readable;
} This is untested. In particular you might need more than one |
You're right! Don't do that lol. @domenic ... one challenge we're going to have here is that we need to be able to find out the readable/locked/closed/errored state when we likely won't have access to any attached I've been thinking about opening a spec proposal to add a couple of new getters to the |
Stream.locked already exists, no? |
Well, only the person with the reader should be able to introspect the stream; that's a design goal. |
Adds a helper util used to determine whether a stream has been disturbed (read or cancelled). Refs: nodejs#39627 PR-URL: nodejs#39628 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Adds a helper util used to determine whether a stream has been disturbed (read or cancelled). Refs: nodejs#39627 PR-URL: nodejs#39628 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Backport-PR-URL: nodejs#39819
Adds a helper util used to determine whether a stream has been disturbed (read or cancelled). Refs: nodejs#39627 PR-URL: nodejs#39628 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Backport-PR-URL: nodejs#39819
What's about @domenic's example: async function isReadable(reader) {
let readable = true;
reader.closed.then(() => { readable = false; }, () => { readable = false; });
await Promise.resolve();
// If the stream was closed or errored then the closed promise would have settled by now and updated readable.
// If not then it's readable.
return readable;
} I'll copy my opinion over it from whatwg/streams#1025:
So having synchronous check in the case of directly owned a) non-nested undisturbed stream and b) disturbed or closed streams (I expect it as the most cases) all of extra payload will be eliminated, and only indirectly owned undisturbed or closing nested streams would require read attempt to fail. Thus provided code is doing redundant work. |
While working implementing fetch in undici I've noticed a limitation on how compliant we can be towards the spec.
In order to "extract" a request body we need to have access to the streams
[[disturbed]]
state. However, this state is inaccessible through the public API.Is there a way we could make this accessible behind a public symbol or something? Otherwise fetch can't be fully implemented outside of core as per my understanding of the specification.
The text was updated successfully, but these errors were encountered: