fix(webgpu): add webidl records and simple unions (#9698)

The only functional user facing difference is that this commit allows the
use SPIRV shaders, not just WGSL. This matches FF and Chrome Canary.
This commit is contained in:
Luca Casonato 2021-03-08 14:22:05 +01:00 committed by GitHub
parent 0bc488c85c
commit c009dad982
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 249 additions and 110 deletions

View file

@ -596,6 +596,13 @@
converters.VoidFunction = convertCallbackFunction; converters.VoidFunction = convertCallbackFunction;
converters["UVString?"] = createNullableConverter(
converters.USVString,
);
converters["sequence<double>"] = createSequenceConverter(
converters["double"],
);
function requiredArguments(length, required, opts = {}) { function requiredArguments(length, required, opts = {}) {
if (length < required) { if (length < required) {
const errMsg = `${ const errMsg = `${
@ -737,6 +744,26 @@
}; };
} }
function createRecordConverter(keyConverter, valueConverter) {
return (V, opts) => {
if (typeof V !== "object") {
throw makeException(
TypeError,
"can not be converted to dictionary.",
opts,
);
}
const result = {};
for (const key of V) {
const typedKey = keyConverter(key, opts);
const value = V[key];
const typedValue = valueConverter(value, opts);
result[typedKey] = typedValue;
}
return result;
};
}
const brand = Symbol("[[webidl.brand]]"); const brand = Symbol("[[webidl.brand]]");
function createInterfaceConverter(name, prototype) { function createInterfaceConverter(name, prototype) {
@ -766,12 +793,14 @@
window.__bootstrap ??= {}; window.__bootstrap ??= {};
window.__bootstrap.webidl = { window.__bootstrap.webidl = {
makeException,
converters, converters,
requiredArguments, requiredArguments,
createDictionaryConverter, createDictionaryConverter,
createEnumConverter, createEnumConverter,
createNullableConverter, createNullableConverter,
createSequenceConverter, createSequenceConverter,
createRecordConverter,
createInterfaceConverter, createInterfaceConverter,
brand, brand,
createBranded, createBranded,

View file

@ -25,6 +25,11 @@ declare namespace globalThis {
*/ */
context: string; context: string;
} }
declare function makeException(
ErrorType: any,
message: string,
opts: ValueConverterOpts,
): any;
declare interface IntConverterOpts extends ValueConverterOpts { declare interface IntConverterOpts extends ValueConverterOpts {
/** /**
* Wether to throw if the number is outside of the acceptable values for * Wether to throw if the number is outside of the acceptable values for
@ -191,6 +196,8 @@ declare namespace globalThis {
* Convert a value into a `VoidFunction` (() => void). * Convert a value into a `VoidFunction` (() => void).
*/ */
VoidFunction(v: any, opts?: ValueConverterOpts): () => void; VoidFunction(v: any, opts?: ValueConverterOpts): () => void;
["UVString?"](v: any, opts?: ValueConverterOpts): string | null;
["sequence<double>"](v: any, opts?: ValueConverterOpts): number[];
[type: string]: (v: any, opts: ValueConverterOpts) => any; [type: string]: (v: any, opts: ValueConverterOpts) => any;
}; };
@ -268,6 +275,17 @@ declare namespace globalThis {
name: string, name: string,
prototype: any, prototype: any,
): (v: any, opts: ValueConverterOpts) => any; ): (v: any, opts: ValueConverterOpts) => any;
declare function createRecordConverter<
K extends string | number | symbol,
V,
>(
keyConverter: (v: any, opts: ValueConverterOpts) => K,
valueConverter: (v: any, opts: ValueConverterOpts) => V,
): (
v: Record<K, V>,
opts: ValueConverterOpts,
) => any;
} }
declare var eventTarget: { declare var eventTarget: {

View file

@ -42,7 +42,6 @@
// This needs to be initalized after all of the base classes are implmented, // This needs to be initalized after all of the base classes are implmented,
// otherwise their converters might not be available yet. // otherwise their converters might not be available yet.
// DICTIONARY: GPUObjectDescriptorBase // DICTIONARY: GPUObjectDescriptorBase
const dictMembersGPUObjectDescriptorBase = [ const dictMembersGPUObjectDescriptorBase = [
{ key: "label", converter: webidl.converters["USVString"] }, { key: "label", converter: webidl.converters["USVString"] },
@ -109,6 +108,10 @@
], ],
); );
// TYPEDEF: GPUSize32
webidl.converters["GPUSize32"] = (V, opts) =>
webidl.converters["unsigned long"](V, { ...opts, enforceRange: true });
// DICTIONARY: GPUDeviceDescriptor // DICTIONARY: GPUDeviceDescriptor
const dictMembersGPUDeviceDescriptor = [ const dictMembersGPUDeviceDescriptor = [
{ {
@ -120,7 +123,10 @@
}, },
{ {
key: "nonGuaranteedLimits", key: "nonGuaranteedLimits",
converter: webidl.converters.any, converter: webidl.createRecordConverter(
webidl.converters["DOMString"],
webidl.converters["GPUSize32"],
),
defaultValue: {}, defaultValue: {},
}, },
]; ];
@ -192,16 +198,54 @@
GPUTexture, GPUTexture,
); );
// TYPEDEF: GPUExtent3D
webidl.converters["GPUExtent3D"] = webidl.converters.any;
// TYPEDEF: GPUIntegerCoordinate // TYPEDEF: GPUIntegerCoordinate
webidl.converters["GPUIntegerCoordinate"] = (V, opts) => webidl.converters["GPUIntegerCoordinate"] = (V, opts) =>
webidl.converters["unsigned long"](V, { ...opts, enforceRange: true }); webidl.converters["unsigned long"](V, { ...opts, enforceRange: true });
webidl.converters["sequence<GPUIntegerCoordinate>"] = webidl
.createSequenceConverter(webidl.converters["GPUIntegerCoordinate"]);
// TYPEDEF: GPUSize32 // DICTIONARY: GPUExtent3DDict
webidl.converters["GPUSize32"] = (V, opts) => const dictMembersGPUExtent3DDict = [
webidl.converters["unsigned long"](V, { ...opts, enforceRange: true }); {
key: "width",
converter: webidl.converters["GPUIntegerCoordinate"],
defaultValue: 1,
},
{
key: "height",
converter: webidl.converters["GPUIntegerCoordinate"],
defaultValue: 1,
},
{
key: "depthOrArrayLayers",
converter: webidl.converters["GPUIntegerCoordinate"],
defaultValue: 1,
},
];
webidl.converters["GPUExtent3DDict"] = webidl.createDictionaryConverter(
"GPUExtent3DDict",
dictMembersGPUExtent3DDict,
);
// TYPEDEF: GPUExtent3D
webidl.converters["GPUExtent3D"] = (V, opts) => {
// Union for (sequence<GPUIntegerCoordinate> or GPUExtent3DDict)
if (V === null || V === undefined) {
return webidl.converters["GPUExtent3DDict"](V, opts);
}
if (typeof V === "object") {
const method = V[Symbol.iterator];
if (method !== undefined) {
return webidl.converters["sequence<GPUIntegerCoordinate>"](V, opts);
}
return webidl.converters["GPUExtent3DDict"](V, opts);
}
throw webidl.makeException(
TypeError,
"can not be converted to sequence<GPUIntegerCoordinate> or GPUExtent3DDict.",
opts,
);
};
// ENUM: GPUTextureDimension // ENUM: GPUTextureDimension
webidl.converters["GPUTextureDimension"] = webidl.createEnumConverter( webidl.converters["GPUTextureDimension"] = webidl.createEnumConverter(
@ -685,8 +729,28 @@
GPUBindGroup, GPUBindGroup,
); );
// DICTIONARY: GPUBufferBinding
const dictMembersGPUBufferBinding = [
{
key: "buffer",
converter: webidl.converters["GPUBuffer"],
required: true,
},
{
key: "offset",
converter: webidl.converters["GPUSize64"],
defaultValue: 0,
},
{ key: "size", converter: webidl.converters["GPUSize64"] },
];
webidl.converters["GPUBufferBinding"] = webidl.createDictionaryConverter(
"GPUBufferBinding",
dictMembersGPUBufferBinding,
);
// TYPEDEF: GPUBindingResource // TYPEDEF: GPUBindingResource
webidl.converters["GPUBindingResource"] = webidl.converters.any; webidl.converters["GPUBindingResource"] =
webidl.converters.any /** put union here! **/;
// DICTIONARY: GPUBindGroupEntry // DICTIONARY: GPUBindGroupEntry
const dictMembersGPUBindGroupEntry = [ const dictMembersGPUBindGroupEntry = [
@ -728,25 +792,6 @@
dictMembersGPUBindGroupDescriptor, dictMembersGPUBindGroupDescriptor,
); );
// DICTIONARY: GPUBufferBinding
const dictMembersGPUBufferBinding = [
{
key: "buffer",
converter: webidl.converters["GPUBuffer"],
required: true,
},
{
key: "offset",
converter: webidl.converters["GPUSize64"],
defaultValue: 0,
},
{ key: "size", converter: webidl.converters["GPUSize64"] },
];
webidl.converters["GPUBufferBinding"] = webidl.createDictionaryConverter(
"GPUBufferBinding",
dictMembersGPUBufferBinding,
);
// INTERFACE: GPUPipelineLayout // INTERFACE: GPUPipelineLayout
webidl.converters.GPUPipelineLayout = webidl.createInterfaceConverter( webidl.converters.GPUPipelineLayout = webidl.createInterfaceConverter(
"GPUPipelineLayout", "GPUPipelineLayout",
@ -800,7 +845,23 @@
// DICTIONARY: GPUShaderModuleDescriptor // DICTIONARY: GPUShaderModuleDescriptor
const dictMembersGPUShaderModuleDescriptor = [ const dictMembersGPUShaderModuleDescriptor = [
{ key: "code", converter: webidl.converters["USVString"], required: true }, {
key: "code",
converter: (V, opts) => {
if (V instanceof Uint32Array) {
return webidl.converters["Uint32Array"](V, opts);
}
if (typeof V === "string") {
return webidl.converters["DOMString"](V, opts);
}
throw webidl.makeException(
TypeError,
"can not be converted to Uint32Array or DOMString.",
opts,
);
},
required: true,
},
{ key: "sourceMap", converter: webidl.converters["object"] }, { key: "sourceMap", converter: webidl.converters["object"] },
]; ];
webidl.converters["GPUShaderModuleDescriptor"] = webidl webidl.converters["GPUShaderModuleDescriptor"] = webidl
@ -1333,6 +1394,8 @@
"GPUCommandBuffer", "GPUCommandBuffer",
GPUCommandBuffer, GPUCommandBuffer,
); );
webidl.converters["sequence<GPUCommandBuffer>"] = webidl
.createSequenceConverter(webidl.converters["GPUCommandBuffer"]);
// DICTIONARY: GPUCommandBufferDescriptor // DICTIONARY: GPUCommandBufferDescriptor
const dictMembersGPUCommandBufferDescriptor = []; const dictMembersGPUCommandBufferDescriptor = [];
@ -1393,8 +1456,48 @@
dictMembersGPUImageCopyBuffer, dictMembersGPUImageCopyBuffer,
); );
// DICTIONARY: GPUOrigin3DDict
const dictMembersGPUOrigin3DDict = [
{
key: "x",
converter: webidl.converters["GPUIntegerCoordinate"],
defaultValue: 0,
},
{
key: "y",
converter: webidl.converters["GPUIntegerCoordinate"],
defaultValue: 0,
},
{
key: "z",
converter: webidl.converters["GPUIntegerCoordinate"],
defaultValue: 0,
},
];
webidl.converters["GPUOrigin3DDict"] = webidl.createDictionaryConverter(
"GPUOrigin3DDict",
dictMembersGPUOrigin3DDict,
);
// TYPEDEF: GPUOrigin3D // TYPEDEF: GPUOrigin3D
webidl.converters["GPUOrigin3D"] = webidl.converters.any; webidl.converters["GPUOrigin3D"] = (V, opts) => {
// Union for (sequence<GPUIntegerCoordinate> or GPUOrigin3DDict)
if (V === null || V === undefined) {
return webidl.converters["GPUOrigin3DDict"](V, opts);
}
if (typeof V === "object") {
const method = V[Symbol.iterator];
if (method !== undefined) {
return webidl.converters["sequence<GPUIntegerCoordinate>"](V, opts);
}
return webidl.converters["GPUOrigin3DDict"](V, opts);
}
throw webidl.makeException(
TypeError,
"can not be converted to sequence<GPUIntegerCoordinate> or GPUOrigin3DDict.",
opts,
);
};
// DICTIONARY: GPUImageCopyTexture // DICTIONARY: GPUImageCopyTexture
const dictMembersGPUImageCopyTexture = [ const dictMembersGPUImageCopyTexture = [
@ -1445,7 +1548,43 @@
GPURenderPassEncoder, GPURenderPassEncoder,
); );
// ENUM: GPUStoreOp // ENUM: GPULoadOp
webidl.converters["GPULoadOp"] = webidl.createEnumConverter("GPULoadOp", [
"load",
]);
// DICTIONARY: GPUColorDict
const dictMembersGPUColorDict = [
{ key: "r", converter: webidl.converters["double"], required: true },
{ key: "g", converter: webidl.converters["double"], required: true },
{ key: "b", converter: webidl.converters["double"], required: true },
{ key: "a", converter: webidl.converters["double"], required: true },
];
webidl.converters["GPUColorDict"] = webidl.createDictionaryConverter(
"GPUColorDict",
dictMembersGPUColorDict,
);
// TYPEDEF: GPUColor
webidl.converters["GPUColor"] = (V, opts) => {
// Union for (sequence<double> or GPUColorDict)
if (V === null || V === undefined) {
return webidl.converters["GPUColorDict"](V, opts);
}
if (typeof V === "object") {
const method = V[Symbol.iterator];
if (method !== undefined) {
return webidl.converters["sequence<double>"](V, opts);
}
return webidl.converters["GPUColorDict"](V, opts);
}
throw webidl.makeException(
TypeError,
"can not be converted to sequence<double> or GPUColorDict.",
opts,
);
}; // ENUM: GPUStoreOp
webidl.converters["GPUStoreOp"] = webidl.createEnumConverter("GPUStoreOp", [ webidl.converters["GPUStoreOp"] = webidl.createEnumConverter("GPUStoreOp", [
"store", "store",
"clear", "clear",
@ -1459,7 +1598,11 @@
required: true, required: true,
}, },
{ key: "resolveTarget", converter: webidl.converters["GPUTextureView"] }, { key: "resolveTarget", converter: webidl.converters["GPUTextureView"] },
{ key: "loadValue", converter: webidl.converters.any, required: true }, {
key: "loadValue",
converter: webidl.converters.any, /** put union here! **/
required: true,
},
{ {
key: "storeOp", key: "storeOp",
converter: webidl.converters["GPUStoreOp"], converter: webidl.converters["GPUStoreOp"],
@ -1479,7 +1622,11 @@
converter: webidl.converters["GPUTextureView"], converter: webidl.converters["GPUTextureView"],
required: true, required: true,
}, },
{ key: "depthLoadValue", converter: webidl.converters.any, required: true }, {
key: "depthLoadValue",
converter: webidl.converters.any, /** put union here! **/
required: true,
},
{ {
key: "depthStoreOp", key: "depthStoreOp",
converter: webidl.converters["GPUStoreOp"], converter: webidl.converters["GPUStoreOp"],
@ -1492,7 +1639,7 @@
}, },
{ {
key: "stencilLoadValue", key: "stencilLoadValue",
converter: webidl.converters.any, converter: webidl.converters.any, /** put union here! **/
required: true, required: true,
}, },
{ {
@ -1540,16 +1687,13 @@
dictMembersGPURenderPassDescriptor, dictMembersGPURenderPassDescriptor,
); );
// ENUM: GPULoadOp
webidl.converters["GPULoadOp"] = webidl.createEnumConverter("GPULoadOp", [
"load",
]);
// INTERFACE: GPURenderBundle // INTERFACE: GPURenderBundle
webidl.converters.GPURenderBundle = webidl.createInterfaceConverter( webidl.converters.GPURenderBundle = webidl.createInterfaceConverter(
"GPURenderBundle", "GPURenderBundle",
GPURenderBundle, GPURenderBundle,
); );
webidl.converters["sequence<GPURenderBundle>"] = webidl
.createSequenceConverter(webidl.converters["GPURenderBundle"]);
// DICTIONARY: GPURenderBundleDescriptor // DICTIONARY: GPURenderBundleDescriptor
const dictMembersGPURenderBundleDescriptor = []; const dictMembersGPURenderBundleDescriptor = [];
@ -1678,7 +1822,7 @@
); );
// TYPEDEF: GPUError // TYPEDEF: GPUError
webidl.converters["GPUError"] = webidl.converters.any; webidl.converters["GPUError"] = webidl.converters.any /** put union here! **/;
// // INTERFACE: GPUUncapturedErrorEvent // // INTERFACE: GPUUncapturedErrorEvent
// webidl.converters.GPUUncapturedErrorEvent = webidl.createInterfaceConverter( // webidl.converters.GPUUncapturedErrorEvent = webidl.createInterfaceConverter(
@ -1708,21 +1852,6 @@
// TYPEDEF: GPUFlagsConstant // TYPEDEF: GPUFlagsConstant
webidl.converters["GPUFlagsConstant"] = webidl.converters["unsigned long"]; webidl.converters["GPUFlagsConstant"] = webidl.converters["unsigned long"];
// DICTIONARY: GPUColorDict
const dictMembersGPUColorDict = [
{ key: "r", converter: webidl.converters["double"], required: true },
{ key: "g", converter: webidl.converters["double"], required: true },
{ key: "b", converter: webidl.converters["double"], required: true },
{ key: "a", converter: webidl.converters["double"], required: true },
];
webidl.converters["GPUColorDict"] = webidl.createDictionaryConverter(
"GPUColorDict",
dictMembersGPUColorDict,
);
// TYPEDEF: GPUColor
webidl.converters["GPUColor"] = webidl.converters.any;
// DICTIONARY: GPUOrigin2DDict // DICTIONARY: GPUOrigin2DDict
const dictMembersGPUOrigin2DDict = [ const dictMembersGPUOrigin2DDict = [
{ {
@ -1742,59 +1871,22 @@
); );
// TYPEDEF: GPUOrigin2D // TYPEDEF: GPUOrigin2D
webidl.converters["GPUOrigin2D"] = webidl.converters.any; webidl.converters["GPUOrigin2D"] = (V, opts) => {
// Union for (sequence<GPUIntegerCoordinate> or GPUOrigin2DDict)
// DICTIONARY: GPUOrigin3DDict if (V === null || V === undefined) {
const dictMembersGPUOrigin3DDict = [ return webidl.converters["GPUOrigin2DDict"](V, opts);
{ }
key: "x", if (typeof V === "object") {
converter: webidl.converters["GPUIntegerCoordinate"], const method = V[Symbol.iterator];
defaultValue: 0, if (method !== undefined) {
}, return webidl.converters["sequence<GPUIntegerCoordinate>"](V, opts);
{ }
key: "y", return webidl.converters["GPUOrigin2DDict"](V, opts);
converter: webidl.converters["GPUIntegerCoordinate"], }
defaultValue: 0, throw webidl.makeException(
}, TypeError,
{ "can not be converted to sequence<GPUIntegerCoordinate> or GPUOrigin2DDict.",
key: "z", opts,
converter: webidl.converters["GPUIntegerCoordinate"], );
defaultValue: 0, };
},
];
webidl.converters["GPUOrigin3DDict"] = webidl.createDictionaryConverter(
"GPUOrigin3DDict",
dictMembersGPUOrigin3DDict,
);
// DICTIONARY: GPUExtent3DDict
const dictMembersGPUExtent3DDict = [
{
key: "width",
converter: webidl.converters["GPUIntegerCoordinate"],
defaultValue: 1,
},
{
key: "height",
converter: webidl.converters["GPUIntegerCoordinate"],
defaultValue: 1,
},
{
key: "depthOrArrayLayers",
converter: webidl.converters["GPUIntegerCoordinate"],
defaultValue: 1,
},
];
webidl.converters["GPUExtent3DDict"] = webidl.createDictionaryConverter(
"GPUExtent3DDict",
dictMembersGPUExtent3DDict,
);
webidl.converters["sequence<GPURenderBundle>"] = webidl
.createSequenceConverter(webidl.converters["GPURenderBundle"]);
webidl.converters["sequence<GPUCommandBuffer>"] = webidl
.createSequenceConverter(webidl.converters["GPUCommandBuffer"]);
webidl.converters["UVString?"] = webidl.createNullableConverter(
webidl.converters.USVString,
);
})(this); })(this);