diff --git a/baselines/dom.generated.d.ts b/baselines/dom.generated.d.ts index ff13a032b..15c81be44 100644 --- a/baselines/dom.generated.d.ts +++ b/baselines/dom.generated.d.ts @@ -1513,6 +1513,30 @@ interface TextDecoderOptions { ignoreBOM?: boolean; } +interface TouchEventInit extends EventModifierInit { + changedTouches?: Touch[]; + targetTouches?: Touch[]; + touches?: Touch[]; +} + +interface TouchInit { + altitudeAngle?: number; + azimuthAngle?: number; + clientX?: number; + clientY?: number; + force?: number; + identifier?: number; + pageX?: number; + pageY?: number; + radiusX?: number; + radiusY?: number; + rotationAngle?: number; + screenX?: number; + screenY?: number; + target?: EventTarget; + touchType?: TouchType; +} + interface TrackEventInit extends EventInit { track?: VideoTrack | AudioTrack | TextTrack | null; } @@ -13270,46 +13294,43 @@ declare var TimeRanges: { }; interface Touch { + readonly altitudeAngle: number; + readonly azimuthAngle: number; readonly clientX: number; readonly clientY: number; + readonly force: number; readonly identifier: number; readonly pageX: number; readonly pageY: number; + readonly radiusX: number; + readonly radiusY: number; + readonly rotationAngle: number; readonly screenX: number; readonly screenY: number; readonly target: EventTarget; + readonly touchType: TouchType; } declare var Touch: { prototype: Touch; - new(): Touch; + new(touchInitDict: TouchInit): Touch; }; interface TouchEvent extends UIEvent { readonly altKey: boolean; readonly changedTouches: TouchList; - readonly charCode: number; readonly ctrlKey: boolean; - readonly keyCode: number; readonly metaKey: boolean; readonly shiftKey: boolean; readonly targetTouches: TouchList; readonly touches: TouchList; - /** @deprecated */ - readonly which: number; } declare var TouchEvent: { prototype: TouchEvent; - new(type: string, touchEventInit?: TouchEventInit): TouchEvent; + new(type: string, eventInitDict?: TouchEventInit): TouchEvent; }; -interface TouchEventInit extends EventModifierInit { - changedTouches?: Touch[]; - targetTouches?: Touch[]; - touches?: Touch[]; -} - interface TouchList { readonly length: number; item(index: number): Touch | null; @@ -16057,6 +16078,7 @@ type ScopedCredentialType = "ScopedCred"; type ServiceWorkerState = "installing" | "installed" | "activating" | "activated" | "redundant"; type TextTrackKind = "subtitles" | "captions" | "descriptions" | "chapters" | "metadata"; type TextTrackMode = "disabled" | "hidden" | "showing"; +type TouchType = "direct" | "stylus"; type Transport = "usb" | "nfc" | "ble"; type VRDisplayEventReason = "mounted" | "navigation" | "requested" | "unmounted"; type VREye = "left" | "right"; diff --git a/inputfiles/addedTypes.json b/inputfiles/addedTypes.json index ea512da93..c0fe5569b 100644 --- a/inputfiles/addedTypes.json +++ b/inputfiles/addedTypes.json @@ -1473,31 +1473,6 @@ } } }, - "TouchEventInit": { - "name": "TouchEventInit", - "flavor": "Web", - "extends": "EventModifierInit", - "properties": { - "property": { - "touches": { - "name": "touches", - "override-type": "Touch[]", - "required": 0 - }, - "targetTouches": { - "name": "targetTouches", - "override-type": "Touch[]", - "required": 0 - }, - "changedTouches": { - "name": "changedTouches", - "override-type": "Touch[]", - "required": 0 - } - } - }, - "no-interface-object": "1" - }, "ValidityState": { "name": "ValidityState", "properties": { diff --git a/inputfiles/idl/Touch Events.widl b/inputfiles/idl/Touch Events.widl new file mode 100644 index 000000000..d15511f6c --- /dev/null +++ b/inputfiles/idl/Touch Events.widl @@ -0,0 +1,77 @@ +enum TouchType { + "direct", + "stylus" +}; + +dictionary TouchInit { + required long identifier; + required EventTarget target; + double clientX = 0; + double clientY = 0; + double screenX = 0; + double screenY = 0; + double pageX = 0; + double pageY = 0; + float radiusX = 0; + float radiusY = 0; + float rotationAngle = 0; + float force = 0; + double altitudeAngle = 0; + double azimuthAngle = 0; + TouchType touchType = "direct"; +}; + +[Constructor(TouchInit touchInitDict), Exposed=Window] +interface Touch { + readonly attribute long identifier; + readonly attribute EventTarget target; + readonly attribute double screenX; + readonly attribute double screenY; + readonly attribute double clientX; + readonly attribute double clientY; + readonly attribute double pageX; + readonly attribute double pageY; + readonly attribute float radiusX; + readonly attribute float radiusY; + readonly attribute float rotationAngle; + readonly attribute float force; + readonly attribute float altitudeAngle; + readonly attribute float azimuthAngle; + readonly attribute TouchType touchType; +}; + +interface TouchList { + readonly attribute unsigned long length; + getter Touch? item (unsigned long index); +}; + +dictionary TouchEventInit : EventModifierInit { + sequence touches = []; + sequence targetTouches = []; + sequence changedTouches = []; +}; + +[Constructor(DOMString type, optional TouchEventInit eventInitDict), Exposed=Window] +interface TouchEvent : UIEvent { + readonly attribute TouchList touches; + readonly attribute TouchList targetTouches; + readonly attribute TouchList changedTouches; + readonly attribute boolean altKey; + readonly attribute boolean metaKey; + readonly attribute boolean ctrlKey; + readonly attribute boolean shiftKey; +}; + +partial interface GlobalEventHandlers { + attribute EventHandler ontouchstart; + attribute EventHandler ontouchend; + attribute EventHandler ontouchmove; + attribute EventHandler ontouchcancel; +}; + +partial interface Document { + // Deprecated in this specification + Touch createTouch (WindowProxy view, EventTarget target, long identifier, double pageX, double pageY, double screenX, double screenY); + // Deprecated in this specification + TouchList createTouchList (Touch... touches); +}; diff --git a/inputfiles/idlSources.json b/inputfiles/idlSources.json index 918cd668b..60acfc75f 100644 --- a/inputfiles/idlSources.json +++ b/inputfiles/idlSources.json @@ -3,6 +3,10 @@ "url": "https://encoding.spec.whatwg.org/", "title": "Encoding" }, + { + "url": "https://w3c.github.io/touch-events/", + "title": "Touch Events" + }, { "url": "https://heycam.github.io/webidl/", "title": "Web IDL" diff --git a/inputfiles/overridingTypes.json b/inputfiles/overridingTypes.json index 9e9015105..7b6c440aa 100644 --- a/inputfiles/overridingTypes.json +++ b/inputfiles/overridingTypes.json @@ -1511,14 +1511,6 @@ } } }, - "TouchEvent": { - "name": "TouchEvent", - "constructor": { - "override-signatures": [ - "new(type: string, touchEventInit?: TouchEventInit): TouchEvent" - ] - } - }, "Text": { "name": "Text", "constructor": { @@ -2091,4 +2083,4 @@ "typedefs": { "typedef": [] } -} \ No newline at end of file +} diff --git a/src/emitter.ts b/src/emitter.ts index e116b72b0..c0cba83de 100644 --- a/src/emitter.ts +++ b/src/emitter.ts @@ -273,7 +273,7 @@ export function emitWebIDl(webidl: Browser.WebIdl, flavor: Flavor) { function convertDomTypeToTsTypeWorker(obj: Browser.Typed): { name: string; nullable: boolean } { let type; if (typeof obj.type === "string") { - type = { name: covertDomTypeToTsTypeSimple(obj.type), nullable: !!obj.nullable }; + type = { name: convertDomTypeToTsTypeSimple(obj.type), nullable: !!obj.nullable }; } else { const types = obj.type.map(convertDomTypeToTsTypeWorker); @@ -309,7 +309,7 @@ export function emitWebIDl(webidl: Browser.WebIdl, flavor: Flavor) { return elementType.includes("|") ? `(${elementType})[]` : `${elementType}[]`; } - function covertDomTypeToTsTypeSimple(objDomType: string): string { + function convertDomTypeToTsTypeSimple(objDomType: string): string { switch (objDomType) { case "AbortMode": return "String"; case "bool": @@ -351,7 +351,7 @@ export function emitWebIDl(webidl: Browser.WebIdl, flavor: Flavor) { if (allTypeDefsMap.has(objDomType)) return objDomType; // Union types if (objDomType.includes(" or ")) { - const allTypes: string[] = decomposeTypes(objDomType).map(t => covertDomTypeToTsTypeSimple(t.replace("?", ""))); + const allTypes: string[] = decomposeTypes(objDomType).map(t => convertDomTypeToTsTypeSimple(t.replace("?", ""))); return allTypes.includes("any") ? "any" : allTypes.join(" | "); } else { @@ -360,12 +360,12 @@ export function emitWebIDl(webidl: Browser.WebIdl, flavor: Flavor) { const genericMatch = /^(\w+)<([\w, <>]+)>$/; const match = genericMatch.exec(unescaped); if (match) { - const tName: string = covertDomTypeToTsTypeSimple(match[1]); - const paramName: string = covertDomTypeToTsTypeSimple(match[2]); + const tName: string = convertDomTypeToTsTypeSimple(match[1]); + const paramName: string = convertDomTypeToTsTypeSimple(match[2]); return tName === "Array" ? paramName + "[]" : tName + "<" + paramName + ">"; } if (objDomType.endsWith("[]")) { - return covertDomTypeToTsTypeSimple(objDomType.replace("[]", "").trim()) + "[]"; + return convertDomTypeToTsTypeSimple(objDomType.replace("[]", "").trim()) + "[]"; } } } @@ -1110,4 +1110,4 @@ export function emitWebIDl(webidl: Browser.WebIdl, flavor: Flavor) { return printer.getResult(); } -} \ No newline at end of file +} diff --git a/src/fetcher.ts b/src/fetcher.ts index 608ce756a..2a6e6efaf 100644 --- a/src/fetcher.ts +++ b/src/fetcher.ts @@ -26,10 +26,46 @@ async function fetchIDL(source: IDLSource) { throw new Error("Found no IDL code"); } const last = elements[elements.length - 1]; - if (last.previousElementSibling!.textContent!.includes("IDL Index")) { + if (last.previousElementSibling && + last.previousElementSibling.textContent!.includes("IDL Index") + ) { // IDL Index includes all IDL codes return last.textContent!.trim(); } - return elements.map(element => element.textContent!.trim()).join('\n\n'); + return elements.map(element => trimCommonIndentation(element.textContent!).trim()).join('\n\n'); +} + +/** + * Remove common indentation: + *
+ *       typedef Type = "type";
+ *       dictionary Dictionary {
+ *         "member"
+ *       };
+ *     
+ * Here the textContent has 6 common preceding whitespaces that can be unindented. + */ +function trimCommonIndentation(text: string) { + const lines = text.split("\n"); + if (!lines[0].trim()) { + lines.shift(); + } + if (!lines[lines.length - 1].trim()) { + lines.pop(); + } + const commonIndentation = Math.min(...lines.map(getIndentation)); + return lines.map(line => line.slice(commonIndentation)).join("\n"); +} + +/** Count preceding whitespaces */ +function getIndentation(line: string) { + let count = 0; + for (const ch of line) { + if (ch !== " ") { + break; + } + count++; + } + return count; } diff --git a/src/widlprocess.ts b/src/widlprocess.ts index 17bf7f09e..296fb2f9b 100644 --- a/src/widlprocess.ts +++ b/src/widlprocess.ts @@ -29,6 +29,9 @@ export function convert(text: string) { else if (rootType.type === "dictionary") { browser.dictionaries!.dictionary[rootType.name] = convertDictionary(rootType); } + else if (rootType.type === "enum") { + browser.enums!.enum[rootType.name] = convertEnum(rootType); + } else if (rootType.type === "typedef") { browser.typedefs!.typedef.push(convertTypedef(rootType)); } @@ -201,6 +204,13 @@ function convertDictionaryMember(member: webidl2.DictionaryMemberType): Browser. } } +function convertEnum(en: webidl2.EnumType): Browser.Enum { + return { + name: en.name, + value: en.values.map(value => value.value) + } +} + function convertTypedef(typedef: webidl2.TypedefType): Browser.TypeDef { return { "new-type": typedef.name,