Open kainino0x opened 3 years ago
The WebIDL spec defines a sequence
as an ECMAScript Array
.
Unfortunately Array
and Iterable
are not a 1 to 1 mapping because Array
always allows index access to its members through square brackets notation while an Iterable
is only expected to implement the Symbol.iterator
property as seen in the TypeScript declaration
An alternative would be declaring an iterable object as defined in the WebIDL spec.
Ah, there's an effective difference between input sequence
s and output sequence
s.
IDL allows any JS iterable to be passed in to a sequence
-typed WebIDL binding, but when it passes a WebIDL sequence
out to a JS value it produces an array.
WebGPU doesn't actually use any output sequence
s (IIRC), instead using FrozenArray
(which as of today it only uses in one place).
Unfortunately I can't think of an easy way to be 100% correct about input vs output types. Many types can be used in both input and output (any that are sequence or dictionary, at least). IIRC these are only recommended to be used in input situations but they're allowed to be used in output situations as well.
yeah, this one is a difficult one.
for function arguments or return types a simple input/output heuristic could be used:
undefined setSequence(sequence<any> value);
sequence<any> getSequence();
would translate to:
setSequence(Iterable<any> value): void;
getSequence(): Array<any>;
Properties are more difficult since they can either be readonly
or read/write
which makes it so they must always be Array
.
The closest solution that I can think of is to follow the heuristic above and create setters and getters to be verbose:
dictionary GPUBindGroupLayoutDescriptor : GPUObjectDescriptorBase {
required sequence<GPUBindGroupLayoutEntry> entries;
};
would translate to:
interface GPUBindGroupLayoutDescriptor extends GPUObjectDescriptorBase {
set entries(value: Iterable<GPUBindGroupLayoutEntry>);
get entries(): Array<GPUBindGroupLayoutEntry>;
}
but that feels off
Yeah, that wouldn't work if the type were used as a local variable:
const x: GPUBindGroupLayoutDescriptor = { entries: new Set(...) };
const y = x.entries[0];
Unfortunately the only thing I can think of is to generate both input and output versions of every type (perhaps differentiated by a type parameter??), then optionally prune any input or output variants that go unused...
We can not worry about this for now for WebGPU though. The diff that we have to deal with manually is very small.
In principle all the descriptors need to be readonly
on input too, but fortunately (I guess) typescript is not strict about this. https://github.com/microsoft/TypeScript/issues/18770
I did a little experimentation with the idea I had above and it could work: https://github.com/gpuweb/types/compare/main...kainino0x:idlsequence-proof-of-concept
WebIDL
sequence
s are (I think) equivalent to TypeScriptIterable
s - the WebIDL conversion rules from JS will iterate the value to produce an array. For example:generates:
but should generate: