-
Notifications
You must be signed in to change notification settings - Fork 440
Add Streams #541
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 Streams #541
Conversation
Mainly looking for some feedback. Is there a nicer way to introduce a type parameter on a interface ReadableStreamDefaultControllerCallback<R> {
(controller: ReadableStreamDefaultController<R>): any;
} I have to do add this to "callback-functions": {
"callback-function": {
"ReadableStreamDefaultControllerCallback": {
"name": "ReadableStreamDefaultControllerCallback<R>",
"override-signatures": [
"(controller: ReadableStreamDefaultController<R>): any"
]
}
}
} but then I also have to add a line in {
"Window": [
"ReadableStreamDefaultControllerCallback<R>"
]
} I tried using |
@saschanaz can you please review this change. |
You may fix |
inputfiles/overridingTypes.json
Outdated
}, | ||
"ReadableStream": { | ||
"name": "ReadableStream", | ||
"override-exposed": "Window Worker", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
name
and override-exposed
are redundant here. Yes, name
s in e.g. Worker are also redundant, but no need to fix them in this PR.
}, | ||
"ReadableStreamReader": { | ||
"name": "ReadableStreamReader", | ||
"override-exposed": "Window Worker", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here.
inputfiles/overridingTypes.json
Outdated
} | ||
}, | ||
"ReadableStreamReadResult": { | ||
"name": "ReadableStreamReadResult", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here too.
inputfiles/overridingTypes.json
Outdated
}, | ||
"ReadableStreamBYOBReader": { | ||
"name": "ReadableStreamBYOBReader", | ||
"override-exposed": "Window Worker", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also here, because the IDL has [Exposed=(Window,Worker)]
.
inputfiles/idlSources.json
Outdated
}, | ||
{ | ||
"url": "https://streams.spec.whatwg.org/", | ||
"title": "Streams" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move this above Storage? Also, npm run fetch
will fail because the spec page does not have any IDL. We may add "local": true
and fix fetcher.ts so that it won't fetch IDL when marked as local
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe you mean below storage, since "Storage"
< "Streams"
? Sure, I can move "Streams" into alphabetical order.
inputfiles/overridingTypes.json
Outdated
} | ||
}, | ||
"ReadableWritableStreamPair": { | ||
"name": "ReadableWritableStreamPair<R extends ReadableStream, W extends WritableStream>", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now, TypeParameter
only supports name
and default
. Therefore, I simply patched in the type parameters into directly the interface's name. Ideally, this would go into the "type-parameters"
property of the interface.
I tried to fix this by adding an extends
property to TypeParameter
and modifying the emitter, but that immediately caused the emitter to throw a "Maximum call stack size exceeded"
error in getParentsWithEventHandler
and getParentEventHandler
. I'll look into this again later, to see why this would cause infinite recursion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found it! The overriding interface still needs a name
property for this to work, which I had removed while testing. Putting the name
back fixes it.
inputfiles/overridingTypes.json
Outdated
} | ||
} | ||
}, | ||
"no-interface-object": "1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- A dictionary should be in dictionary part of overridingTypes.json.
- A dictionary doesn't need
override-exposed
. - A dictionary shouldn't use
"no-interface-object": "1"
. (It's for interfaces marked as[NoInterfaceObject]
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixing this may introduce other problems as currently some interfaces incorrectly extends from dictionaries. This is not a strict blocker, anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably a leftover from my initial hack to make <R extends ReadableStream>
work. I'll look into it.
}; | ||
|
||
interface ReadableStreamReader { | ||
interface ReadableStreamReadResult<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A more precise type for this would be:
type ReadableStreamReadResult<T> = {
done: false;
value: T;
} | {
done: true;
value: undefined;
};
However, I also want this to be compatible with IteratorResult<T>
, which is still defined as a regular interface:
interface IteratorResult<T> {
done: boolean;
value: T;
}
So yeah... ¯\_(ツ)_/¯
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In addition, the IteratorResult type is only defined in es2015.lib as I found out the hard way.
All right, I think I got all of the types sorted out now. I tried using the new types against the tests for |
baselines/dom.generated.d.ts
Outdated
|
||
interface TransformStreamDefaultController<R = any> { | ||
readonly desiredSize: number | null; | ||
enqueue(chunk: any): void; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah dangit, I missed one.
@saschanaz If you find some time for another review, that'd be much appreciated! 😁 (If not, that's okay as well, I can wait.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks okay for me, given that we have minimal changes in emitter.ts.
Not sure this is maintainable, as updating things should be completely manual.
Understandable. It'd be nicer if the streams spec had its own WebIDL definition, but there's still the whole "JSIDL vs WebIDL" discussion going on there. Even better would be if Microsoft Edge updated its implementation to the latest version of the spec so we could use its generated types, but it doesn't seem like that's going to happen any time soon. I can help keep these types up-to-date. Feel free to @ me if you see any streams-related issues popping up. 😉 |
Any idea when this might land? I can wait, but it'd be nice to know when to expect this in a future TypeScript release. I noticed that the last time a PR got merged was on August 2, and all newer PRs are still open. Are the maintainers taking a (well deserved) break, or are you working on something else? |
@mhegazy is (probably) taking a break 😁 |
His twitter status says:
|
Oh man, why did I not check this before I started my own version of adding all the types to TSJS, I only checked another issue in the main TS repo Aargh!… Anyway…, since the maintainer is MIA and this is still open for edits, can I make some? Mostly for @MattiasBuelens
Great work, I will also gladly help out with updating these if necessary. |
BTW, this will also close microsoft/TypeScript#17247 |
@zenmumbler Ah dangit, I didn't see that issue, otherwise I would have definitely put a link to this PR. Hope you didn't spend too much time on your own PR. 😅 Anyway, I definitely see the benefit of swapping the type arguments on |
Rebased on @zenmumbler Could you have a look? 😃 |
Hi @MattiasBuelens, something I found quickly, will do another round of checks in a bit: The following types all need
This is because these objects, according to the spec, cannot be directly constructed and have hidden/private constructor types. The spec even adds checks in the constructors themselves to throw if invoked from outside the Streams internals if the user acquired a constructor function through sneaky means. |
Regarding several locations where E.g. the I would remove these It concerns all fields in the following interfaces that have an
|
OK, I compared all the resulting types with what I had manually created for my streams implementation and with the Streams Spec on hand I found the following final points:
instead of
? That would also make the OK, unless I missed something that is all there is. Again, thanks for the great work and if you have no time to work on these changes, I can do that as well. Cheers. |
Thanks @MattiasBuelens @zenmumbler and @saschanaz for all your work on this one. I have taken over this repo since @mhegazy has moved on, so I'll merge it when you all judge that it's done. |
@MattiasBuelens Do you have time to look into this this week, I'm not actually sure how I would help out if you don't have time, would I clone your branch? Anyway, 3.2 is slated for November and I'd really like to get this in for that release to avoid having to do more workarounds for my streams code. Thanks! |
@zenmumbler Thanks for your extensive review! I'll go over it today. 😃 |
Sorry it took so long to respond. Anyway, here we go:
Good catch! The reader and writer classes are a bit weird though. Although they aren't globally accessible, these classes do have a non-throwing constructor. There's even a test for this: const ReadableStreamDefaultReader = (new ReadableStream()).getReader().constructor;
const reader = new ReadableStreamDefaultReader(new ReadableStream()); We'd need to write very tricky types just to give this constructor a correct signature without also defining a global variable. And since these constructors shouldn't really be used, I agree that it's better to simply remove them entirely.
This seems to be an artifact of how WebIDL dictionaries are converted. Apparently, they're marked both
Good catch, there's indeed no As for the return type, see below.
I guess I tried to be too clever for this one. Indeed, SetUpReadableStreamBYOBRequest requires However, the streams spec seems to leave room for a future update to create a BYOB request with a different typed array. Therefore, I agree that it's probably safer to change it back to
There was some discussion about this in whatwg/streams#45, see comment. Basically, the streams spec allows you to return However, I agree that we should change this to
Agreed, we should use
Thanks! 😄
I don't think I added an
This was taken from the DefinitelyTyped definitions. It allows pipeThrough<T extends ReadableStream>(pair: WritableReadableStreamPair<WritableStream<R>, T>, options?: PipeOptions): T; This has the advantage that if However, I agree that this shouldn't complicate the other types. I think I'll just inline and remove
I feel like As mentioned before, I think it's cleaner to simply inline (Also, you have a small typo in your proposed type definition: |
Oh wow, I actually had that wrong in my own types. Good catch again.
Sorry, probably made a typo there, my reason to comment was to indicate that the
Yes! I saw that and wanted to fix it but probably saw something shiny and forgot. I mean, I left that in to keep you on your toes. |
Ah, I see. I think we can do the |
@zenmumbler Do you think this is good to go, or are there still some changes needed? (Pro tip: go to the "Files changed" tab and click the fancy "Review changes" button to indicate whether you approve, or whether this needs more changes. Then it shows up nicely in this thread. 😄 ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one final thing to discuss with the concept-crossing pipeThrough
method. Sorry I didn't do this earlier, due to GH's layout I completely missed you had already made the changes with your earlier comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, I think we've covered everything. Thanks again for all your efforts! cc: @sandersn
Hi @sandersn, thanks for merging. This is the first time I've contributed to the lib generator and I was wondering how often these definitions are merged back in the main TS repo. Is it on the |
@zenmumbler From the history of |
Thanks @MattiasBuelens, I kind of need to use this today so I just resorted to copying over the contents of the TSJS generated file into my local TS installs… Not exactly scalable, but workable until 3.2(rc) comes out 😅. Only thing I can't do is publish updates to my packages until then but I have pnpm and verdaccio to take care of that. |
@zenmumbler microsoft/TypeScript#28343 has landed, so the new stream types are now available on |
This was added to the upstream dom typings in the Nov 2018 update. ref: microsoft/TypeScript@b830ef8 microsoft/TypeScript#28343 microsoft/TypeScript-DOM-lib-generator#541
This PR updates the type definitions for streams to the latest version of the spec (snapshot). This also introduces generic type parameters for the
chunk
argument, which enables type-safe reading, writing, transforming and piping of streams.This is largely based on
@types/whatwg-streams
. Important differences:any
(instead ofArrayBufferView
). This ensures that developers can still useReadableStream
(and others) as before and read chunks asany
. In places where we know the precise chunk type (e.g.BodyInit
andBody.body
), I've added an explicit type parameter.callback
definitions.Since the streams spec does not provide an official WebIDL (see whatwg/streams#45), the input WebIDL file was hand-written just for type generation purposes. The generated types are then further adjusted to add generics.
Fixes #521
Fixes microsoft/TypeScript#25277