diff --git a/baselines/dom.generated.d.ts b/baselines/dom.generated.d.ts index 95307ebba..cbf1a3c97 100644 --- a/baselines/dom.generated.d.ts +++ b/baselines/dom.generated.d.ts @@ -10260,7 +10260,7 @@ interface HTMLFormElement extends HTMLElement { * * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLFormElement/autocomplete) */ - autocomplete: string; + autocomplete: AutoFillBase; /** * Retrieves a collection, in source order, of all controls in a given form. * @@ -10928,7 +10928,7 @@ interface HTMLInputElement extends HTMLElement, PopoverInvokerElement { * * [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLInputElement/autocomplete) */ - autocomplete: string; + autocomplete: AutoFill; capture: string; /** Sets or retrieves the state of the check box or radio button. */ checked: boolean; @@ -12309,7 +12309,7 @@ declare var HTMLScriptElement: { */ interface HTMLSelectElement extends HTMLElement { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/autocomplete) */ - autocomplete: string; + autocomplete: AutoFill; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/disabled) */ disabled: boolean; /** @@ -13111,7 +13111,7 @@ declare var HTMLTemplateElement: { */ interface HTMLTextAreaElement extends HTMLElement { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLTextAreaElement/autocomplete) */ - autocomplete: string; + autocomplete: AutoFill; /** Sets or retrieves the width of the object. */ cols: number; /** Sets or retrieves the initial contents of the object. */ @@ -27926,6 +27926,9 @@ declare function addEventListener(type: string, listener: EventListenerOrEventLi declare function removeEventListener(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | EventListenerOptions): void; declare function removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; type AlgorithmIdentifier = Algorithm | string; +type AutoFill = AutoFillBase | `${OptionalPrefixToken}${OptionalPrefixToken}${AutoFillField}${OptionalPostfixToken}`; +type AutoFillField = AutoFillNormalField | `${OptionalPrefixToken}${AutoFillContactField}`; +type AutoFillSection = `section-${string}`; type BigInteger = Uint8Array; type BinaryData = ArrayBuffer | ArrayBufferView; type BlobPart = BufferSource | Blob | string; @@ -27976,6 +27979,8 @@ type NamedCurve = string; type OffscreenRenderingContext = OffscreenCanvasRenderingContext2D | ImageBitmapRenderingContext | WebGLRenderingContext | WebGL2RenderingContext; type OnBeforeUnloadEventHandler = OnBeforeUnloadEventHandlerNonNull | null; type OnErrorEventHandler = OnErrorEventHandlerNonNull | null; +type OptionalPostfixToken = ` ${T}` | ""; +type OptionalPrefixToken = `${T} ` | ""; type PerformanceEntryList = PerformanceEntry[]; type ReadableStreamController = ReadableStreamDefaultController | ReadableByteStreamController; type ReadableStreamReadResult = ReadableStreamReadValueResult | ReadableStreamReadDoneResult; @@ -28000,6 +28005,12 @@ type AudioContextLatencyCategory = "balanced" | "interactive" | "playback"; type AudioContextState = "closed" | "running" | "suspended"; type AuthenticatorAttachment = "cross-platform" | "platform"; type AuthenticatorTransport = "ble" | "hybrid" | "internal" | "nfc" | "usb"; +type AutoFillAddressKind = "billing" | "shipping"; +type AutoFillBase = "" | "off" | "on"; +type AutoFillContactField = "email" | "tel" | "tel-area-code" | "tel-country-code" | "tel-extension" | "tel-local" | "tel-local-prefix" | "tel-local-suffix" | "tel-national"; +type AutoFillContactKind = "home" | "mobile" | "work"; +type AutoFillCredentialField = "webauthn"; +type AutoFillNormalField = "additional-name" | "address-level1" | "address-level2" | "address-level3" | "address-level4" | "address-line1" | "address-line2" | "address-line3" | "bday-day" | "bday-month" | "bday-year" | "cc-csc" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-family-name" | "cc-given-name" | "cc-name" | "cc-number" | "cc-type" | "country" | "country-name" | "current-password" | "family-name" | "given-name" | "honorific-prefix" | "honorific-suffix" | "name" | "new-password" | "one-time-code" | "organization" | "postal-code" | "street-address" | "transaction-amount" | "transaction-currency" | "username"; type AutoKeyword = "auto"; type AutomationRate = "a-rate" | "k-rate"; type AvcBitstreamFormat = "annexb" | "avc"; diff --git a/inputfiles/addedTypes.jsonc b/inputfiles/addedTypes.jsonc index c2d236a40..dce7677b9 100644 --- a/inputfiles/addedTypes.jsonc +++ b/inputfiles/addedTypes.jsonc @@ -352,6 +352,98 @@ // https://developer.mozilla.org/en-US/docs/Web/API/WebXR_Device_API#browser_compatibility "xr-spatial-tracking" ] + }, + "AutoFillBase": { + "name": "AutoFillBase", + "value": [ + // Off + "off", + // Automatic + "on", + "" + ] + }, + "AutoFillAddressKind": { + "name": "AutoFillAddressKind", + "value": [ + "shipping", + "billing" + ] + }, + "AutoFillNormalField": { + "name": "AutoFillNormalField", + "value": [ + "name", + "honorific-prefix", + "given-name", + "additional-name", + "family-name", + "honorific-suffix", + + "username", + "new-password", + "current-password", + // Supported in iOS Safari too even though WPT tests + // for Safari currently fail as of 2023-06. + "one-time-code", + + "organization", + "street-address", + "address-line1", + "address-line2", + "address-line3", + "address-level4", + "address-level3", + "address-level2", + "address-level1", + "country", + "country-name", + "postal-code", + + "cc-name", + "cc-given-name", + "cc-family-name", + "cc-number", + "cc-exp", + "cc-exp-month", + "cc-exp-year", + "cc-csc", + "cc-type", + "transaction-currency", + "transaction-amount", + + "bday-day", + "bday-month", + "bday-year" + ] + }, + "AutoFillContactKind": { + "name": "AutoFillContactKind", + "value": [ + "home", + "work", + "mobile" + ] + }, + "AutoFillContactField": { + "name": "AutoFillContactField", + "value": [ + "tel", + "tel-country-code", + "tel-national", + "tel-area-code", + "tel-local", + "tel-local-prefix", + "tel-local-suffix", + "tel-extension", + "email" + ] + }, + "AutoFillCredentialField": { + "name": "AutoFillCredentialField", + "value": [ + "webauthn" + ] } } }, @@ -1422,6 +1514,42 @@ { "name": "EventListenerOrEventListenerObject", "overrideType": "EventListener | EventListenerObject" + }, + { + "name": "OptionalPrefixToken", + "typeParameters": [ + { + "name": "T extends string" + } + ], + "overrideType": "`${T} ` | \"\"" + }, + { + "name": "OptionalPostfixToken", + "typeParameters": [ + { + "name": "T extends string" + } + ], + "overrideType": "` ${T}` | \"\"" + }, + { + "name": "AutoFillSection", + // Note: this will also eagerly match any invalid string + // after section- instead of stopping at the first whitespace. + // It should be something like /section-\S/ if it were supported. + "overrideType": "`section-${string}`" + }, + { + "name": "AutoFillField", + "overrideType": "AutoFillNormalField | `${OptionalPrefixToken}${AutoFillContactField}`" + }, + { + // See the full list of possible autofill values for the `autocomplete` attribute: + // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#determine-a-field's-category + // Full spec at https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill. + "name": "AutoFill", + "overrideType": "AutoFillBase | `${OptionalPrefixToken}${OptionalPrefixToken}${AutoFillField}${OptionalPostfixToken}`" } ] } diff --git a/inputfiles/knownTypes.json b/inputfiles/knownTypes.json index aba727e73..85c2528b2 100644 --- a/inputfiles/knownTypes.json +++ b/inputfiles/knownTypes.json @@ -6,6 +6,15 @@ "AesGcmParams", "AesKeyAlgorithm", "AesKeyGenParams", + "AutoFillBase", + "AutoFillSection", + "AutoFillAddressKind", + "AutoFillNormalField", + "AutoFillContactKind", + "AutoFillContactField", + "AutoFillField", + "AutoFillCredentialField", + "AutoFill", "BigInteger", "ClientQueryOptions", "ClientTypes", @@ -29,6 +38,8 @@ "Keyframe", "MutationRecordType", "NamedCurve", + "OptionalPrefixToken", + "OptionalPostfixToken", "Pbkdf2Params", "PropertyIndexedKeyframes", "RsaHashedImportParams", diff --git a/inputfiles/overridingTypes.jsonc b/inputfiles/overridingTypes.jsonc index 640982f05..7e072c3a7 100644 --- a/inputfiles/overridingTypes.jsonc +++ b/inputfiles/overridingTypes.jsonc @@ -1281,6 +1281,10 @@ "HTMLSelectElement": { "properties": { "property": { + "autocomplete": { + "name": "autocomplete", + "overrideType": "AutoFill" + }, "selectedOptions": { "name": "selectedOptions", "overrideType": "HTMLCollectionOf" @@ -1684,6 +1688,10 @@ "HTMLInputElement": { "properties": { "property": { + "autocomplete": { + "name": "autocomplete", + "overrideType": "AutoFill" + }, "selectionDirection": { "name": "selectionDirection", "overrideType": "\"forward\" | \"backward\" | \"none\"" @@ -1806,6 +1814,10 @@ "HTMLTextAreaElement": { "properties": { "property": { + "autocomplete": { + "name": "autocomplete", + "overrideType": "AutoFill" + }, "labels": { "name": "labels", "overrideType": "NodeListOf" @@ -2443,7 +2455,15 @@ "overrideIndexSignatures": [ "[index: number]: Element", "[name: string]: any" - ] + ], + "properties": { + "property": { + "autocomplete": { + "name": "autocomplete", + "overrideType": "AutoFillBase" + } + } + } }, "Blob": { "methods": { diff --git a/unittests/files/autocomplete.ts b/unittests/files/autocomplete.ts new file mode 100644 index 000000000..051243fa7 --- /dev/null +++ b/unittests/files/autocomplete.ts @@ -0,0 +1,59 @@ +// @ts-expect-error should be a string +document.body.getElementsByTagName("input")[0].autocomplete = false; +// @ts-expect-error wrong value for this attribute +document.body.getElementsByTagName("input")[0].autocomplete = "undefined"; +// @ts-expect-error does not accept boolean attributes +document.body.getElementsByTagName("input")[0].autocomplete = "true"; +// @ts-expect-error does not accept boolean attributes +document.body.getElementsByTagName("input")[0].autocomplete = "false"; + +// @ts-expect-error missing autofill token before webauthn +document.body.getElementsByTagName("input")[0].autocomplete = "webauthn"; + +// @ts-expect-error wrong order for webauthn token +document.body.getElementsByTagName("input")[0].autocomplete = + "webauthn username"; + +// @ts-expect-error wrong order for contact specifier +document.body.getElementsByTagName("input")[0].autocomplete = "tel mobile"; + +// @ts-expect-error off should be standalone +document.body.getElementsByTagName("input")[0].autocomplete = + "section-wrong off"; + +// @ts-expect-error on should be standalone +document.body.getElementsByTagName("input")[0].autocomplete = "on username"; + +// @ts-expect-error home, work or mobile are only for contact tokens +document.body.getElementsByTagName("input")[0].autocomplete = "mobile username"; + +// @ts-expect-error should probably be current-password or new-password +document.body.getElementsByTagName("input")[0].autocomplete = "password"; + +document.body.getElementsByTagName("input")[0].autocomplete = ""; +document.body.getElementsByTagName("input")[0].autocomplete = "on"; +document.body.getElementsByTagName("input")[0].autocomplete = "off"; +document.body.getElementsByTagName("input")[0].autocomplete = "new-password"; +document.body.getElementsByTagName("input")[0].autocomplete = + "current-password"; +document.body.getElementsByTagName("input")[0].autocomplete = "one-time-code"; + +document.body.getElementsByTagName("input")[0].autocomplete = + "username webauthn"; + +document.body.getElementsByTagName("input")[0].autocomplete = + "shipping street-address"; +document.body.getElementsByTagName("input")[0].autocomplete = + "section-custom shipping street-address"; + +document.body.getElementsByTagName("input")[0].autocomplete = "work email"; +document.body.getElementsByTagName("input")[0].autocomplete = + "section-custom billing mobile tel"; + +// @ts-expect-error only on and off are available on a form +document.body.getElementsByTagName("form")[0].autocomplete = "new-password"; + +document.body.getElementsByTagName("form")[0].autocomplete = "off"; + +// @ts-expect-error autocomplete attribute is only for form elements +document.body.getElementsByTagName("p")[0].autocomplete = "off";