diff --git a/inputfiles/addedTypes.jsonc b/inputfiles/addedTypes.jsonc index b022ae90d..f7eb3af4e 100644 --- a/inputfiles/addedTypes.jsonc +++ b/inputfiles/addedTypes.jsonc @@ -1,28 +1,4 @@ { - "mixins": { - "mixin": { - "DocumentOrShadowRoot": { - // Manually moved from Document - // See https://github.com/w3c/csswg-drafts/issues/5886 and https://github.com/w3c/csswg-drafts/issues/556 - "methods": { - "method": { - "elementFromPoint": { - "name": "elementFromPoint", - "overrideSignatures": [ - "elementFromPoint(x: number, y: number): Element | null" - ] - }, - "elementsFromPoint": { - "name": "elementsFromPoint", - "overrideSignatures": [ - "elementsFromPoint(x: number, y: number): Element[]" - ] - } - } - } - } - } - }, "interfaces": { "interface": { // ImportMeta is not a true DOM interface, but we are forced to declare it as one in order to emit method definitions. diff --git a/inputfiles/patches/cssom-view.kdl b/inputfiles/patches/cssom-view.kdl new file mode 100644 index 000000000..58dc5121c --- /dev/null +++ b/inputfiles/patches/cssom-view.kdl @@ -0,0 +1,16 @@ +// Manually moved from Document +// See https://github.com/w3c/csswg-drafts/issues/5886 and https://github.com/w3c/csswg-drafts/issues/556 +interface-mixin DocumentOrShadowRoot { + method elementFromPoint { + type Element nullable=#true + param x type=long + param y type=long + } + method elementsFromPoint { + type sequence { + type Element + } + param x type=long + param y type=long + } +} diff --git a/src/build/patches.ts b/src/build/patches.ts index 0b0da41df..9d619b02a 100644 --- a/src/build/patches.ts +++ b/src/build/patches.ts @@ -1,5 +1,12 @@ import { parse, type Value, type Node } from "kdljs"; -import type { Enum, Event, Property, Interface, WebIdl } from "./types.js"; +import type { + Enum, + Event, + Property, + Interface, + WebIdl, + Method, +} from "./types.js"; import { readdir, readFile } from "fs/promises"; import { merge } from "./helpers.js"; @@ -25,6 +32,20 @@ function optionalMember(prop: string, type: T, value?: Value) { }; } +function handleTyped(type: Node, returnType: string) { + const isTyped = type.name == "type"; + const name = isTyped ? (type.values[0] as string) : returnType; + const subType = + type.children.length > 0 + ? { type: type.children[0].values[0] as string } + : undefined; + return { + type: name, + subtype: subType, + ...optionalMember("nullable", "boolean", type.properties?.nullable), + }; +} + /** * Converts patch files in KDL to match the [types](types.d.ts). */ @@ -94,6 +115,7 @@ function handleMixin(node: Node): DeepPartial { const event: Event[] = []; const property: Record> = {}; + const method: Record> = {}; for (const child of node.children) { switch (child.name) { @@ -105,6 +127,11 @@ function handleMixin(node: Node): DeepPartial { property[propName] = handleProperty(child); break; } + case "method": { + const methodName = child.values[0] as string; + method[methodName] = handleMethod(child); + break; + } default: throw new Error(`Unknown node name: ${child.name}`); } @@ -114,6 +141,7 @@ function handleMixin(node: Node): DeepPartial { name, events: { event }, properties: { property }, + methods: { method }, ...optionalMember("extends", "string", node.properties?.extends), } as DeepPartial; } @@ -142,6 +170,31 @@ function handleProperty(child: Node): Partial { }; } +/** + * Handles a child node of type "method" and adds it to the method object. + * @param child The child node to handle. + */ +function handleMethod(child: Node): Partial { + const name = child.values[0] as string; + const type = child.children[0]; + const returnType = child.properties.returns as string; + + const params = child.children + .filter((c) => c.properties.type) + .map((c) => ({ + name: c.values[0] as string, + type: c.properties.type as string, + })); + + const signature: Method["signature"] = [ + { + param: params, + ...handleTyped(type, returnType), + }, + ]; + return { name, signature }; +} + /** * Collect all file URLs in a directory. */