diff --git a/types/node/path.d.ts b/types/node/path.d.ts index d363397ffe8228..08b8a318bb40f2 100644 --- a/types/node/path.d.ts +++ b/types/node/path.d.ts @@ -67,7 +67,7 @@ declare module "path" { interface PlatformPath { /** * Normalize a string path, reducing '..' and '.' parts. - * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used. + * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used. If the path is a zero-length string, '.' is returned, representing the current working directory. * * @param path string path to normalize. * @throws {TypeError} if `path` is not a string. diff --git a/types/node/v20/path.d.ts b/types/node/v20/path.d.ts index 7bdc7c5f1acca2..dd69692a33474c 100644 --- a/types/node/v20/path.d.ts +++ b/types/node/v20/path.d.ts @@ -67,7 +67,7 @@ declare module "path" { interface PlatformPath { /** * Normalize a string path, reducing '..' and '.' parts. - * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used. + * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used. If the path is a zero-length string, '.' is returned, representing the current working directory. * * @param path string path to normalize. * @throws {TypeError} if `path` is not a string. diff --git a/types/node/v22/path.d.ts b/types/node/v22/path.d.ts index 25bfc802b66fa8..b83d8f50723479 100644 --- a/types/node/v22/path.d.ts +++ b/types/node/v22/path.d.ts @@ -67,7 +67,7 @@ declare module "path" { interface PlatformPath { /** * Normalize a string path, reducing '..' and '.' parts. - * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used. + * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used. If the path is a zero-length string, '.' is returned, representing the current working directory. * * @param path string path to normalize. * @throws {TypeError} if `path` is not a string. diff --git a/types/phoenix/index.d.ts b/types/phoenix/index.d.ts index 8dcc83d4dffa17..66ddf89ee30f9b 100644 --- a/types/phoenix/index.d.ts +++ b/types/phoenix/index.d.ts @@ -34,6 +34,7 @@ export type BinaryType = "arraybuffer" | "blob"; export type ConnectionState = "connecting" | "open" | "closing" | "closed"; export interface SocketConnectOption { + authToken: string; binaryType: BinaryType; params: object | (() => object); transport: new(endpoint: string) => object; diff --git a/types/phoenix/phoenix-tests.ts b/types/phoenix/phoenix-tests.ts index 0e598806bab9eb..49f4822803f6ad 100644 --- a/types/phoenix/phoenix-tests.ts +++ b/types/phoenix/phoenix-tests.ts @@ -19,6 +19,7 @@ class InMemoryStorage { function test_socket() { const socket = new Socket("/ws", { + authToken: "my-secret-token", binaryType: "arraybuffer", params: { userToken: "123" }, reconnectAfterMs: tries => 1000, diff --git a/types/w3c-controlled-frame/.npmignore b/types/w3c-controlled-frame/.npmignore new file mode 100644 index 00000000000000..93e307400a5456 --- /dev/null +++ b/types/w3c-controlled-frame/.npmignore @@ -0,0 +1,5 @@ +* +!**/*.d.ts +!**/*.d.cts +!**/*.d.mts +!**/*.d.*.ts diff --git a/types/w3c-controlled-frame/index.d.ts b/types/w3c-controlled-frame/index.d.ts new file mode 100644 index 00000000000000..418182bbedc0d3 --- /dev/null +++ b/types/w3c-controlled-frame/index.d.ts @@ -0,0 +1,598 @@ +/** + * @see https://wicg.github.io/controlled-frame + * @see https://wicg.github.io/urlpattern + */ + +export type URLPatternInput = string | URLPatternInit; + +export type URLPatternCompatible = string | URLPatternInit | URLPattern; + +export type URLPatternComponent = + | "protocol" + | "username" + | "password" + | "hostname" + | "port" + | "pathname" + | "search" + | "hash"; + +export class URLPattern { + constructor(input: URLPatternInput, baseURL: string | URL, options?: URLPatternOptions); + constructor(input?: URLPatternInput, options?: URLPatternOptions); + test(input?: URLPatternInput, baseURL?: string): boolean; + exec(input?: URLPatternInput, baseURL?: string): URLPatternResult | null; + generate(component: URLPatternComponent, groups: Record): string; + readonly protocol: string; + readonly username: string; + readonly password: string; + readonly hostname: string; + readonly port: string; + readonly pathname: string; + readonly search: string; + readonly hash: string; + readonly hasRegExpGroups: boolean; +} + +export interface URLPatternComponentResult { + input?: string; + groups?: Record; +} + +export interface URLPatternInit { + protocol?: string; + username?: string; + password?: string; + hostname?: string; + port?: string; + pathname?: string; + search?: string; + hash?: string; + baseURL?: string; +} + +export interface URLPatternOptions { + /** @default false */ + ignoreCase?: boolean; +} + +export interface URLPatternResult { + inputs?: URLPatternInput[]; + protocol?: URLPatternComponentResult; + username?: URLPatternComponentResult; + password?: URLPatternComponentResult; + hostname?: URLPatternComponentResult; + port?: URLPatternComponentResult; + pathname?: URLPatternComponentResult; + search?: URLPatternComponentResult; + hash?: URLPatternComponentResult; +} + +export class HTMLControlledFrameElement extends HTMLElement { + constructor(); + src: string; + partition: string; + readonly contentWindow: WindowProxy | null; + readonly contextMenus: ContextMenus; + readonly request: WebRequest; + back(): Promise; + canGoBack(): Promise; + forward(): Promise; + canGoForward(): Promise; + go(relativeIndex: number): Promise; + reload(): undefined; + stop(): undefined; + addContentScripts(contentScriptList: ContentScriptDetails[]): Promise; + executeScript(details?: InjectDetails): Promise; + insertCSS(details?: InjectDetails): Promise; + removeContentScripts(scriptNameList?: string[]): Promise; + clearData(options?: ClearDataOptions, types?: ClearDataTypeSet): Promise; + getAudioState(): Promise; + getZoom(): Promise; + getZoomMode(): Promise; + isAudioMuted(): Promise; + setAudioMuted(mute: boolean): undefined; + setZoom(zoomFactor: number): Promise; + setZoomMode(zoomMode: string): Promise; + captureVisibleRegion(options?: ImageDetails): Promise; + print(): undefined; + onconsolemessage: ((ev: Event) => any) | null; + oncontentload: ((ev: Event) => any) | null; + ondialog: ((ev: Event) => any) | null; + onloadabort: ((ev: Event) => any) | null; + onloadcommit: ((ev: Event) => any) | null; + onloadstart: ((ev: Event) => any) | null; + onloadstop: ((ev: Event) => any) | null; + onnewwindow: ((ev: Event) => any) | null; + onpermissionrequest: ((ev: Event) => any) | null; + onsizechanged: ((ev: Event) => any) | null; + onzoomchange: ((ev: Event) => any) | null; +} + +export interface InjectDetails { + code?: string; + file?: string; +} + +export interface InjectionItems { + code?: string; + files?: string[]; +} + +export type RunAt = + | "document-start" + | "document-end" + | "document-idle"; + +export interface ContentScriptDetails { + name: string; + js?: InjectionItems; + css?: InjectionItems; + urlPatterns: (URLPattern | URLPatternInput)[]; + excludeURLPatterns?: (URLPattern | URLPatternInput)[]; + allFrames?: boolean; + matchAboutBlank?: boolean; + runAt?: RunAt; +} + +export interface ClearDataOptions { + since?: number; +} + +export interface ClearDataTypeSet { + cache?: boolean; + cookies?: boolean; + fileSystems?: boolean; + indexedDB?: boolean; + localStorage?: boolean; + persistentCookies?: boolean; + sessionCookies?: boolean; +} + +export type ZoomMode = + | "per-origin" + | "per-view" + | "disabled"; + +export interface ImageDetails { + format?: string; + quality?: string; +} + +export interface ConsoleMessage { + readonly level: number; + readonly message: string; +} + +export class ConsoleMessageEvent extends Event { + constructor(type: string, eventInitDict?: ConsoleMessageEventInit); + readonly consoleMessage: ConsoleMessage; +} + +export interface ConsoleMessageEventInit extends EventInit { + consoleMessage?: ConsoleMessage | null; +} + +export type DialogType = + | "alert" + | "confirm" + | "prompt"; + +export interface DialogController { + okay(response?: string): undefined; + cancel(): undefined; +} + +export interface DialogMessage { + readonly messageType: DialogType; + readonly messageText: string; + readonly dialog: DialogController; +} + +export class DialogEvent extends Event { + constructor(type: string, eventInitDict?: DialogEventInit); + readonly dialogMessage: DialogMessage; +} + +export interface DialogEventInit extends EventInit { + dialogMessage?: DialogMessage | null; +} + +export type WindowOpenDisposition = + | "ignore" + | "save_to_disk" + | "current_tab" + | "new_background_tab" + | "new_foreground_tab" + | "new_window" + | "new_popup"; + +export interface NewWindowController { + attach(newControlledFrame: HTMLControlledFrameElement): undefined; + discard(): undefined; +} + +export interface NewWindow { + readonly window: NewWindowController; + readonly targetUrl: string; + readonly name: string; + readonly windowOpenDisposition: WindowOpenDisposition; +} + +export class NewWindowEvent extends Event { + constructor(type: string, eventInitDict?: NewWindowEventInit); + readonly newWindow: NewWindow; +} + +export interface NewWindowEventInit extends EventInit { + newWindow?: NewWindow | null; +} + +export type PermissionType = + | "media" + | "geolocation" + | "pointerLock" + | "download" + | "filesystem" + | "fullscreen" + | "hid"; + +export interface PermissionRequestControllerBase { + allow(): undefined; + cancel(): undefined; +} + +export interface MediaPermissionRequestController extends PermissionRequestControllerBase { + readonly url: string; +} + +export interface GeolocationPermissionRequestController extends PermissionRequestControllerBase { + readonly url: string; +} + +export interface PointerLockPermissionRequestController extends PermissionRequestControllerBase { + readonly lastUnlockedBySelf: boolean; + readonly userGesture: boolean; + readonly url: string; +} + +export interface DownloadPermissionRequestController extends PermissionRequestControllerBase { + readonly requestMethod: string; + readonly url: string; +} + +export interface FileSystemPermissionRequestController extends PermissionRequestControllerBase { + readonly url: string; +} + +export interface FullscreenPermissionRequestController extends PermissionRequestControllerBase { + readonly origin: string; +} + +export interface HidPermissionRequestController extends PermissionRequestControllerBase { + readonly url: string; +} + +export interface PermissionRequest { + readonly permission: PermissionType; + readonly request: PermissionRequestControllerBase; +} + +export class PermissionRequestEvent extends Event { + constructor(type: string, eventInitDict?: PermissionRequestEventInit); + readonly permissionRequest: PermissionRequest; +} + +export interface PermissionRequestEventInit extends EventInit { + permissionRequest?: PermissionRequest | null; +} + +export interface SizeChange { + readonly oldWidth: number; + readonly oldHeight: number; + readonly newWidth: number; + readonly newHeight: number; +} + +export class SizeChangedEvent extends Event { + constructor(type: string, eventInitDict?: SizeChangedEventInit); + readonly sizeChange: SizeChange; +} + +export interface SizeChangedEventInit extends EventInit { + sizeChange?: SizeChange | null; +} + +export interface ZoomChange { + readonly oldZoomFactor: number; + readonly newZoomFactor: number; +} + +export class ZoomChangeEvent extends Event { + constructor(type: string, eventInitDict?: ZoomChangeEventInit); + readonly zoomChange: ZoomChange; +} + +export interface ZoomChangeEventInit extends EventInit { + zoomChange?: ZoomChange | null; +} + +export class ContentLoadEvent extends Event { + constructor(type: string, eventInitDict?: EventInit); +} + +export interface LoadInfo { + readonly url: string; + readonly isTopLevel: boolean; +} + +export interface LoadAbortInfo extends LoadInfo { + readonly code: number; + readonly reason: string; +} + +export interface LoadRedirectInfo { + readonly oldUrl: string; + readonly newUrl: string; + readonly isTopLevel: boolean; +} + +export class LoadAbortEvent extends Event { + constructor(type: string, eventInitDict?: LoadAbortEventInit); + readonly loadAbortInfo: LoadAbortInfo; +} + +export interface LoadAbortEventInit extends EventInit { + loadAbortInfo?: LoadAbortInfo | null; +} + +export class LoadCommitEvent extends Event { + constructor(type: string, eventInitDict?: LoadCommitEventInit); + readonly loadInfo: LoadInfo; +} + +export interface LoadCommitEventInit extends EventInit { + loadInfo?: LoadInfo | null; +} + +export class LoadStartEvent extends Event { + constructor(type: string, eventInitDict?: LoadStartEventInit); + readonly loadInfo: LoadInfo; +} + +export interface LoadStartEventInit extends EventInit { + loadInfo?: LoadInfo | null; +} + +export class LoadStopEvent extends Event { + constructor(type: string, eventInitDict?: LoadStopEventInit); +} + +export type LoadStopEventInit = EventInit; + +export class LoadRedirectEvent extends Event { + constructor(type: string, eventInitDict?: LoadRedirectEventInit); + readonly loadRedirectInfo: LoadRedirectInfo; +} + +export interface LoadRedirectEventInit extends EventInit { + loadRedirectInfo?: LoadRedirectInfo | null; +} + +export type ResourceType = + | "main-frame" + | "sub-frame" + | "stylesheet" + | "script" + | "image" + | "font" + | "object" + | "xmlhttprequest" + | "ping" + | "csp-report" + | "media" + | "websocket" + | "other"; + +export type RequestedHeaders = + | "none" + | "cors" + | "all"; + +export interface WebRequestInterceptorOptions { + urlPatterns: (URLPattern | URLPatternInput)[]; + /** @default [] */ + resourceTypes?: ResourceType[]; + /** @default false */ + blocking?: boolean; + /** @default false */ + includeRequestBody?: boolean; + /** @default "none" */ + includeHeaders?: RequestedHeaders; +} + +export interface WebRequest { + createWebRequestInterceptor(options: WebRequestInterceptorOptions): WebRequestInterceptor; +} + +export interface WebRequestInterceptor extends EventTarget { + onauthrequired: ((ev: Event) => any) | null; + onbeforeredirect: ((ev: Event) => any) | null; + onbeforerequest: ((ev: Event) => any) | null; + onbeforesendheaders: ((ev: Event) => any) | null; + oncompleted: ((ev: Event) => any) | null; + onerroroccurred: ((ev: Event) => any) | null; + onheadersreceived: ((ev: Event) => any) | null; + onsendheaders: ((ev: Event) => any) | null; + onresponsestarted: ((ev: Event) => any) | null; +} + +export type DocumentLifecycle = + | "prerender" + | "active" + | "cached" + | "pending-deletion"; + +export type FrameType = + | "outermost-frame" + | "fenced-frame" + | "sub-frame"; + +export interface UploadData { + readonly bytes: ArrayBuffer | null; + readonly file: string | null; +} + +export interface RequestBody { + readonly error: string | null; + readonly formData: any; + readonly raw: readonly UploadData[] | null; +} + +export interface WebRequestRequest { + readonly method: string; + readonly id: string; + readonly type: ResourceType; + readonly url: string; + readonly initiator: string | null; + readonly headers: Headers | null; + readonly body: RequestBody | null; +} + +export interface AuthChallenger { + readonly host: string; + readonly port: number; +} + +export interface WebRequestAuthDetails { + readonly challenger: AuthChallenger; + readonly isProxy: boolean; + readonly scheme: string; + readonly realm: string | null; +} + +export interface WebRequestResponse { + readonly statusCode: number; + readonly statusLine: string; + readonly fromCache: boolean; + readonly headers: Headers | null; + readonly ip: string | null; + readonly redirectURL: string | null; + readonly auth: WebRequestAuthDetails | null; +} + +export interface WebRequestEvent extends Event { + readonly request: WebRequestRequest; + readonly frameId: number; + readonly frameType: FrameType | null; + readonly documentId: string | null; + readonly documentLifecycle: DocumentLifecycle | null; + readonly parentDocumentId: string | null; + readonly parentFrameId: number | null; +} + +export interface WebRequestAuthCredentials { + username: string; + password: string; +} + +export interface WebRequestAuthOptions { + signal?: AbortSignal; +} + +export interface WebRequestAuthRequiredEvent extends WebRequestEvent { + readonly response: WebRequestResponse; + setCredentials(credentials: Promise, options?: WebRequestAuthOptions): undefined; +} + +export interface WebRequestBeforeRedirectEvent extends WebRequestEvent { + readonly response: WebRequestResponse; +} + +export interface WebRequestBeforeRequestEvent extends WebRequestEvent { + redirect(redirectURL: string): undefined; +} + +export interface WebRequestBeforeSendHeadersEvent extends WebRequestEvent { + setRequestHeaders(requestHeaders: Headers | HeadersInit): undefined; +} + +export interface WebRequestCompletedEvent extends WebRequestEvent { + readonly response: WebRequestResponse; +} + +export interface WebRequestErrorOccurredEvent extends WebRequestEvent { + readonly error: string; +} + +export interface WebRequestHeadersReceivedEvent extends WebRequestEvent { + readonly response: WebRequestResponse; + redirect(redirectURL: string): undefined; + setResponseHeaders(responseHeaders: Headers | HeadersInit): undefined; +} + +export interface WebRequestResponseStartedEvent extends WebRequestEvent { + readonly response: WebRequestResponse; +} + +export type WebRequestSendHeadersEvent = WebRequestEvent; + +export type ContextType = + | "all" + | "page" + | "frame" + | "selection" + | "link" + | "editable" + | "image" + | "video" + | "audio"; + +export type ItemType = + | "normal" + | "checkbox" + | "radio" + | "separator"; + +export interface ContextMenusProperties { + checked?: boolean; + contexts?: ContextType[]; + documentURLPatterns?: (URLPattern | URLPatternInput)[]; + enabled?: boolean; + parentId?: string; + targetURLPatterns?: (URLPattern | URLPatternInput)[]; + title?: string; + type?: ItemType; +} + +export interface ContextMenusCreateProperties extends ContextMenusProperties { + id: string; +} + +export interface ContextMenus extends EventTarget { + create(properties: ContextMenusCreateProperties): Promise; + remove(id: string): Promise; + removeAll(): Promise; + update(id: string, properties?: ContextMenusProperties): Promise; + onclick: ((ev: Event) => any) | null; + onshow: ((ev: Event) => any) | null; +} + +export interface MenuItemDetails { + readonly id: string; + readonly parentMenuId: string | null; + readonly checked: boolean | null; + readonly wasChecked: boolean | null; +} + +export interface ContextMenusClickEvent extends Event { + readonly menuItem: MenuItemDetails; + readonly frameId: number; + readonly frameURL: string; + readonly pageURL: string; + readonly editable: boolean; + readonly linkURL: string | null; + readonly mediaType: string | null; + readonly selectionText: string | null; + readonly srcURL: string | null; +} diff --git a/types/w3c-controlled-frame/package.json b/types/w3c-controlled-frame/package.json new file mode 100644 index 00000000000000..5b9b9d2236de01 --- /dev/null +++ b/types/w3c-controlled-frame/package.json @@ -0,0 +1,28 @@ +{ + "private": true, + "nonNpm": true, + "nonNpmDescription": "Implementation of Isolated Web App (IWA) APIs resides in Chromium.", + "name": "@types/w3c-controlled-frame", + "version": "0.0.9999", + "projects": [ + "https://github.com/WICG/isolated-web-apps" + ], + "devDependencies": { + "@types/web": "*", + "@types/w3c-controlled-frame": "workspace:." + }, + "owners": [ + { + "name": "Paulina Gacek", + "githubUsername": "paulinagacek" + }, + { + "name": "Andrew Rayskiy", + "githubUsername": "GrapeGreen" + }, + { + "name": "Simon Hangl", + "githubUsername": "shangl" + } + ] +} diff --git a/types/w3c-controlled-frame/tsconfig.json b/types/w3c-controlled-frame/tsconfig.json new file mode 100644 index 00000000000000..12a23a7fd366ba --- /dev/null +++ b/types/w3c-controlled-frame/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "module": "node16", + "lib": [ + "es6", + "dom" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true, + "paths": { + "w3c-controlled-frame": [ + "./index.d.ts" + ] + } + }, + "files": [ + "index.d.ts", + "w3c-controlled-frame-tests.ts" + ] +} diff --git a/types/w3c-controlled-frame/w3c-controlled-frame-tests.ts b/types/w3c-controlled-frame/w3c-controlled-frame-tests.ts new file mode 100644 index 00000000000000..1141808be72015 --- /dev/null +++ b/types/w3c-controlled-frame/w3c-controlled-frame-tests.ts @@ -0,0 +1,294 @@ +import { + ClearDataOptions, + ClearDataTypeSet, + ConsoleMessage, + ConsoleMessageEvent, + ContentScriptDetails, + ContextMenus, + ContextMenusClickEvent, + ContextMenusCreateProperties, + DialogController, + DialogEvent, + DialogMessage, + DialogType, + HTMLControlledFrameElement, + ImageDetails, + InjectDetails, + LoadAbortEvent, + LoadAbortInfo, + LoadRedirectEvent, + LoadRedirectInfo, + NewWindow, + NewWindowController, + NewWindowEvent, + PermissionRequest, + PermissionRequestControllerBase, + PermissionRequestEvent, + PermissionType, + RequestedHeaders, + ResourceType, + RunAt, + SizeChange, + SizeChangedEvent, + URLPattern, + WebRequest, + WebRequestAuthCredentials, + WebRequestAuthOptions, + WebRequestAuthRequiredEvent, + WebRequestBeforeRequestEvent, + WebRequestBeforeSendHeadersEvent, + WebRequestHeadersReceivedEvent, + WebRequestInterceptorOptions, + WebRequestResponse, + WindowOpenDisposition, + ZoomChange, + ZoomChangeEvent, + ZoomMode, +} from "w3c-controlled-frame"; + +const dummyControlledFrame: HTMLControlledFrameElement = {} as HTMLControlledFrameElement; +const dummyDialog: DialogController = {} as DialogController; +const dummyPermController: PermissionRequestControllerBase = {} as PermissionRequestControllerBase; +const dummyNewWindowController: NewWindowController = {} as NewWindowController; +const dummyResponse: WebRequestResponse = {} as WebRequestResponse; +const dummyHeaders: Headers = {} as Headers; + +const urlPatternInput = { pathname: "/test/*" }; +const urlPattern = {} as URLPattern; +const url = "https://example.com/page"; + +async function testControlledFrame() { + // -------------------------------------------------------------------------------- + // HTMLControlledFrameElement Properties (Attribute Checking) + // -------------------------------------------------------------------------------- + + // $ExpectType string + dummyControlledFrame.src; + // $ExpectType string + dummyControlledFrame.partition; + + // $ExpectType ContextMenus + dummyControlledFrame.contextMenus; + // $ExpectType WebRequest + dummyControlledFrame.request; + + // -------------------------------------------------------------------------------- + // HTMLControlledFrameElement Methods + // -------------------------------------------------------------------------------- + + // $ExpectType Promise + dummyControlledFrame.back(); + // $ExpectType Promise + dummyControlledFrame.canGoBack(); + // $ExpectType Promise + dummyControlledFrame.go(1); + // $ExpectType undefined + dummyControlledFrame.reload(); + + const contentScript: ContentScriptDetails = { + name: "myScript", + urlPatterns: [urlPatternInput], + js: { files: ["script.js"] }, + runAt: "document-idle" as RunAt, + }; + // $ExpectType Promise + dummyControlledFrame.addContentScripts([contentScript]); + + const injectDetails: InjectDetails = { code: "console.log(\"hi\")" }; + // $ExpectType Promise + dummyControlledFrame.executeScript(injectDetails); + // $ExpectType Promise + dummyControlledFrame.insertCSS({ file: "style.css" }); + // $ExpectType Promise + dummyControlledFrame.removeContentScripts(["myScript"]); + + const clearOptions: ClearDataOptions = { since: 0 }; + const clearTypes: ClearDataTypeSet = { cookies: true, localStorage: true }; + // $ExpectType Promise + dummyControlledFrame.clearData(clearOptions, clearTypes); + // $ExpectType Promise + dummyControlledFrame.getZoom(); + // $ExpectType undefined + dummyControlledFrame.setAudioMuted(true); + // $ExpectType Promise + dummyControlledFrame.setZoomMode("disabled" as ZoomMode); + + const imageDetails: ImageDetails = { format: "jpeg", quality: "90" }; + // $ExpectType Promise + dummyControlledFrame.captureVisibleRegion(imageDetails); + // $ExpectType undefined + dummyControlledFrame.print(); + + // -------------------------------------------------------------------------------- + // Complex Event Types + // -------------------------------------------------------------------------------- + + const consoleMessage: ConsoleMessage = {} as ConsoleMessage; + const consoleEvent = new ConsoleMessageEvent("consolemessage", { + consoleMessage, + }); + // $ExpectType ConsoleMessage + consoleEvent.consoleMessage; + + const dialogMessage: DialogMessage = { + messageType: "prompt" as DialogType, + messageText: "Q", + dialog: dummyDialog, + } as DialogMessage; + const dialogEvent = new DialogEvent("dialog", { dialogMessage }); + // $ExpectType DialogMessage + dialogEvent.dialogMessage; + + const newWindow: NewWindow = { + window: dummyNewWindowController, + targetUrl: url, + name: "NewPopup", + windowOpenDisposition: "new_window" as WindowOpenDisposition, + } as NewWindow; + const newWindowEvent = new NewWindowEvent("newwindow", { newWindow }); + // $ExpectType NewWindow + newWindowEvent.newWindow; + + const permRequest: PermissionRequest = { + permission: "media" as PermissionType, + request: dummyPermController, + } as PermissionRequest; + const permissionEvent = new PermissionRequestEvent("permissionrequest", { + permissionRequest: permRequest, + }); + // $ExpectType PermissionRequest + permissionEvent.permissionRequest; + + const sizeChange: SizeChange = { + oldWidth: 100, + oldHeight: 100, + newWidth: 200, + newHeight: 200, + }; + const sizeEvent = new SizeChangedEvent("sizechanged", { sizeChange }); + // $ExpectType SizeChange + sizeEvent.sizeChange; + + const zoomChange: ZoomChange = { oldZoomFactor: 1.0, newZoomFactor: 1.2 }; + const zoomEvent = new ZoomChangeEvent("zoomchange", { zoomChange }); + // $ExpectType ZoomChange + zoomEvent.zoomChange; + + // LoadAbortEvent + const loadAbortInfo: LoadAbortInfo = { + url, + isTopLevel: true, + code: 1, + reason: "ERR", + } as LoadAbortInfo; + const loadAbortEvent = new LoadAbortEvent("loadabort", { loadAbortInfo }); + // $ExpectType LoadAbortInfo + loadAbortEvent.loadAbortInfo; + + // LoadRedirectEvent + const loadRedirectInfo: LoadRedirectInfo = { + oldUrl: "a", + newUrl: "b", + isTopLevel: true, + } as LoadRedirectInfo; + const loadRedirectEvent = new LoadRedirectEvent("loadredirect", { + loadRedirectInfo, + }); + // $ExpectType LoadRedirectInfo + loadRedirectEvent.loadRedirectInfo; + + // -------------------------------------------------------------------------------- + // ContextMenus API + // -------------------------------------------------------------------------------- + + const contextMenus: ContextMenus = dummyControlledFrame.contextMenus; + const createProps: ContextMenusCreateProperties = { + id: "1", + title: "New Item", + contexts: ["page", "selection"], + documentURLPatterns: [urlPatternInput], + }; + + // $ExpectType Promise + contextMenus.create(createProps); + // $ExpectType Promise + contextMenus.remove("1"); + // $ExpectType Promise + contextMenus.removeAll(); + // $ExpectType Promise + contextMenus.update("1", { + enabled: false, + targetURLPatterns: [urlPatternInput], + }); + + const clickEvent: ContextMenusClickEvent = {} as ContextMenusClickEvent; + // $ExpectType number + clickEvent.frameId; + // $ExpectType string + clickEvent.pageURL; + // $ExpectType MenuItemDetails + clickEvent.menuItem; + // $ExpectType string | null + clickEvent.linkURL; + + type ContextMenusClickListener = (ev: ContextMenusClickEvent) => any; + const clickListener: ContextMenusClickListener = (ev) => ev.menuItem.id; + // $ExpectType void + contextMenus.addEventListener( + "click", + clickListener as EventListenerOrEventListenerObject, + ); + + // $ExpectType ((ev: Event) => any) | null + contextMenus.onclick; + + // -------------------------------------------------------------------------------- + // WebRequest API + // -------------------------------------------------------------------------------- + + const webRequest: WebRequest = dummyControlledFrame.request; + const interceptorOptions: WebRequestInterceptorOptions = { + urlPatterns: [urlPattern], + resourceTypes: ["script", "image"] as ResourceType[], + blocking: true, + includeHeaders: "all" as RequestedHeaders, + }; + + const interceptor = webRequest.createWebRequestInterceptor(interceptorOptions); + // $ExpectType WebRequestInterceptor + interceptor; + + const authEvent: WebRequestAuthRequiredEvent = { + response: dummyResponse, + } as WebRequestAuthRequiredEvent; + + const credentialsPromise: Promise = Promise.resolve({ username: "u", password: "p" }); + const authOptions: WebRequestAuthOptions = { signal: {} as AbortSignal }; + + // $ExpectType undefined + authEvent.setCredentials(credentialsPromise, authOptions); + + const beforeRequestEvent: WebRequestBeforeRequestEvent = {} as WebRequestBeforeRequestEvent; + // $ExpectType undefined + beforeRequestEvent.redirect("https://new.url"); + + const beforeSendHeadersEvent: WebRequestBeforeSendHeadersEvent = {} as WebRequestBeforeSendHeadersEvent; + // $ExpectType undefined + beforeSendHeadersEvent.setRequestHeaders(dummyHeaders); + + const headersReceivedEvent: WebRequestHeadersReceivedEvent = { + response: dummyResponse, + } as WebRequestHeadersReceivedEvent; + // $ExpectType undefined + headersReceivedEvent.setResponseHeaders(dummyHeaders); + + type BeforeRequestListener = (ev: WebRequestBeforeRequestEvent) => any; + const beforeRequestListener: BeforeRequestListener = (ev) => { + ev.redirect(url); + }; + // $ExpectType void + interceptor.addEventListener( + "beforerequest", + beforeRequestListener as EventListenerOrEventListenerObject, + ); +} diff --git a/types/w3c-direct-sockets/.npmignore b/types/w3c-direct-sockets/.npmignore new file mode 100644 index 00000000000000..93e307400a5456 --- /dev/null +++ b/types/w3c-direct-sockets/.npmignore @@ -0,0 +1,5 @@ +* +!**/*.d.ts +!**/*.d.cts +!**/*.d.mts +!**/*.d.*.ts diff --git a/types/w3c-direct-sockets/index.d.ts b/types/w3c-direct-sockets/index.d.ts new file mode 100644 index 00000000000000..29860061091e59 --- /dev/null +++ b/types/w3c-direct-sockets/index.d.ts @@ -0,0 +1,92 @@ +/** + * @see https://github.com/WICG/direct-sockets/blob/main/docs/explainer.md + */ + +export class UDPSocket { + constructor(options: UDPSocketOptions); + readonly opened: Promise; + readonly closed: Promise; + close(): Promise; +} + +export interface UDPMessage { + data?: BufferSource; + remoteAddress?: string; + remotePort?: number; + dnsQueryType?: SocketDnsQueryType; +} + +export class TCPSocket { + constructor(remoteAddress: string, remotePort: number, options?: TCPSocketOptions); + readonly opened: Promise; + readonly closed: Promise; + close(): Promise; +} + +export class TCPServerSocket { + constructor(localAddress: string, options?: TCPServerSocketOptions); + readonly opened: Promise; + readonly closed: Promise; + close(): Promise; +} + +export type SocketDnsQueryType = + | "ipv4" + | "ipv6"; + +export interface SocketOptions { + sendBufferSize?: number; + receiveBufferSize?: number; +} + +export interface TCPSocketOptions extends SocketOptions { + /** @default false */ + noDelay?: boolean; + keepAliveDelay?: number; + dnsQueryType?: SocketDnsQueryType; +} + +export interface UDPSocketOptions extends SocketOptions { + remoteAddress?: string; + remotePort?: number; + localAddress?: string; + localPort?: number; + dnsQueryType?: SocketDnsQueryType; + ipv6Only?: boolean; + multicastAllowAddressSharing?: boolean; + multicastTimeToLive?: number; + multicastLoopback?: boolean; +} + +export interface TCPServerSocketOptions { + localPort?: number; + backlog?: number; + ipv6Only?: boolean; +} + +export interface SocketOpenInfo { + readable?: ReadableStream; + writable?: WritableStream; + remoteAddress?: string; + remotePort?: number; + localAddress?: string; + localPort?: number; +} + +export type TCPSocketOpenInfo = SocketOpenInfo; + +export interface UDPSocketOpenInfo extends SocketOpenInfo { + multicastController?: MulticastController; +} + +export interface TCPServerSocketOpenInfo { + readable?: ReadableStream; + localAddress?: string; + localPort?: number; +} + +export interface MulticastController { + joinGroup(ipAddress: string): Promise; + leaveGroup(ipAddress: string): Promise; + readonly joinedGroups: readonly string[]; +} diff --git a/types/w3c-direct-sockets/package.json b/types/w3c-direct-sockets/package.json new file mode 100644 index 00000000000000..a084458d6272c8 --- /dev/null +++ b/types/w3c-direct-sockets/package.json @@ -0,0 +1,28 @@ +{ + "private": true, + "nonNpm": true, + "nonNpmDescription": "Implementation of Isolated Web App (IWA) APIs resides in Chromium.", + "name": "@types/w3c-direct-sockets", + "version": "0.0.9999", + "projects": [ + "https://github.com/WICG/isolated-web-apps" + ], + "devDependencies": { + "@types/web": "*", + "@types/w3c-direct-sockets": "workspace:." + }, + "owners": [ + { + "name": "Paulina Gacek", + "githubUsername": "paulinagacek" + }, + { + "name": "Andrew Rayskiy", + "githubUsername": "GrapeGreen" + }, + { + "name": "Simon Hangl", + "githubUsername": "shangl" + } + ] +} diff --git a/types/w3c-direct-sockets/tsconfig.json b/types/w3c-direct-sockets/tsconfig.json new file mode 100644 index 00000000000000..77f4807deb6c44 --- /dev/null +++ b/types/w3c-direct-sockets/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "module": "node16", + "lib": [ + "es6", + "dom" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true, + "paths": { + "w3c-direct-sockets": [ + "./index.d.ts" + ] + } + }, + "files": [ + "index.d.ts", + "w3c-direct-sockets-tests.ts" + ] +} diff --git a/types/w3c-direct-sockets/w3c-direct-sockets-tests.ts b/types/w3c-direct-sockets/w3c-direct-sockets-tests.ts new file mode 100644 index 00000000000000..c3fd5fed0efc2f --- /dev/null +++ b/types/w3c-direct-sockets/w3c-direct-sockets-tests.ts @@ -0,0 +1,152 @@ +import { + MulticastController, + SocketDnsQueryType, + TCPServerSocket, + TCPServerSocketOpenInfo, + TCPServerSocketOptions, + TCPSocket, + TCPSocketOpenInfo, + TCPSocketOptions, + UDPMessage, + UDPSocket, + UDPSocketOpenInfo, + UDPSocketOptions, +} from "w3c-direct-sockets"; + +async function testDirectSockets() { + const remoteAddress = "192.168.1.1"; + const localAddress = "0.0.0.0"; + const remotePort = 8080; + const localPort = 3000; + + // -------------------------------------------------------------------------------- + // SocketDnsQueryType (Enum Test) + // -------------------------------------------------------------------------------- + const dnsTypeIpv4: SocketDnsQueryType = "ipv4"; + // $ExpectType "ipv4" + dnsTypeIpv4; + + // $ExpectType "ipv6" + const dnsTypeIpv6: SocketDnsQueryType = "ipv6"; + + // -------------------------------------------------------------------------------- + // UDPSocket + // -------------------------------------------------------------------------------- + const udpOptions: UDPSocketOptions = { + remoteAddress: remoteAddress, + remotePort: remotePort, + localAddress: localAddress, + localPort: localPort, + dnsQueryType: "ipv4", + ipv6Only: false, + sendBufferSize: 1024, + multicastAllowAddressSharing: true, + multicastTimeToLive: 32, + multicastLoopback: true, + }; + + const udpSocket = new UDPSocket(udpOptions); + // $ExpectType UDPSocket + udpSocket; + + // $ExpectType Promise + udpSocket.opened; + + // $ExpectType Promise + udpSocket.closed; + + // $ExpectType Promise + udpSocket.close(); + + // Cast to 'any' or 'UDPMessage' to avoid "missing properties" error during test compilation + // because UDPMessage likely requires 'data' which {} does not have. + const udpMessage = {} as UDPMessage; + + // $ExpectType BufferSource | undefined + udpMessage.data; + // $ExpectType string | undefined + udpMessage.remoteAddress; + + // -------------------------------------------------------------------------------- + // TCPSocket + // -------------------------------------------------------------------------------- + const tcpOptions: TCPSocketOptions = { + noDelay: true, + keepAliveDelay: 300, + dnsQueryType: "ipv6", + receiveBufferSize: 4096, + }; + + const tcpSocket = new TCPSocket(remoteAddress, remotePort, tcpOptions); + // $ExpectType TCPSocket + tcpSocket; + + // $ExpectType Promise + tcpSocket.opened; + + // $ExpectType Promise + tcpSocket.closed; + + // $ExpectType Promise + tcpSocket.close(); + + // -------------------------------------------------------------------------------- + // TCPServerSocket + // -------------------------------------------------------------------------------- + const tcpServerOptions: TCPServerSocketOptions = { + localPort: 0, + backlog: 5, + ipv6Only: false, + }; + + // Constructor + const tcpServerSocket = new TCPServerSocket(localAddress, tcpServerOptions); + // $ExpectType TCPServerSocket + tcpServerSocket; + + // $ExpectType Promise + tcpServerSocket.opened; + + // $ExpectType Promise + tcpServerSocket.closed; + + // $ExpectType Promise + tcpServerSocket.close(); + + // -------------------------------------------------------------------------------- + // Open Info Structures + // -------------------------------------------------------------------------------- + + const udpOpenInfo: UDPSocketOpenInfo = {}; + // $ExpectType MulticastController | undefined + udpOpenInfo.multicastController; + // $ExpectType ReadableStream | undefined + udpOpenInfo.readable; + + const tcpOpenInfo: TCPSocketOpenInfo = {}; + // @ts-expect-error + tcpOpenInfo.multicastController; + // $ExpectType WritableStream | undefined + tcpOpenInfo.writable; + + const tcpServerOpenInfo: TCPServerSocketOpenInfo = {}; + // $ExpectType ReadableStream | undefined + tcpServerOpenInfo.readable; + // @ts-expect-error + tcpServerOpenInfo.writable; + + // -------------------------------------------------------------------------------- + // MulticastController + // -------------------------------------------------------------------------------- + + const multicastController = {} as MulticastController; + + // $ExpectType readonly string[] + multicastController.joinedGroups; + + // $ExpectType Promise + multicastController.joinGroup(remoteAddress); + + // $ExpectType Promise + multicastController.leaveGroup(remoteAddress); +} diff --git a/types/w3c-web-smart-card/.npmignore b/types/w3c-web-smart-card/.npmignore new file mode 100644 index 00000000000000..93e307400a5456 --- /dev/null +++ b/types/w3c-web-smart-card/.npmignore @@ -0,0 +1,5 @@ +* +!**/*.d.ts +!**/*.d.cts +!**/*.d.mts +!**/*.d.*.ts diff --git a/types/w3c-web-smart-card/index.d.ts b/types/w3c-web-smart-card/index.d.ts new file mode 100644 index 00000000000000..a3c79cc2ca0063 --- /dev/null +++ b/types/w3c-web-smart-card/index.d.ts @@ -0,0 +1,166 @@ +/** + * @see https://wicg.github.io/web-smart-card + */ + +export interface SmartCardResourceManager { + establishContext(): Promise; +} + +export type SmartCardResponseCode = + | "no-service" + | "no-smartcard" + | "not-ready" + | "not-transacted" + | "proto-mismatch" + | "reader-unavailable" + | "removed-card" + | "reset-card" + | "server-too-busy" + | "sharing-violation" + | "system-cancelled" + | "unknown-reader" + | "unpowered-card" + | "unresponsive-card" + | "unsupported-card" + | "unsupported-feature"; + +export interface SmartCardErrorOptions { + responseCode: SmartCardResponseCode; +} + +export class SmartCardError extends DOMException { + constructor(message: string, options: SmartCardErrorOptions); + readonly responseCode: SmartCardResponseCode; +} + +export interface SmartCardReaderStateIn { + readerName: string; + currentState: SmartCardReaderStateFlagsIn; + currentCount?: number; +} + +export interface SmartCardReaderStateOut { + readerName: string; + eventState: SmartCardReaderStateFlagsOut; + eventCount: number; + answerToReset: ArrayBuffer; +} + +export interface SmartCardReaderStateFlags { + /** @default false */ + ignore?: boolean; + /** @default false */ + unavailable?: boolean; + /** @default false */ + empty?: boolean; + /** @default false */ + present?: boolean; + /** @default false */ + exclusive?: boolean; + /** @default false */ + inuse?: boolean; + /** @default false */ + mute?: boolean; + /** @default false */ + unpowered?: boolean; +} + +export interface SmartCardReaderStateFlagsIn extends SmartCardReaderStateFlags { + /** @default false */ + unaware?: boolean; +} + +export interface SmartCardReaderStateFlagsOut extends SmartCardReaderStateFlags { + /** @default false */ + changed?: boolean; + /** @default false */ + unknown?: boolean; +} + +export type SmartCardProtocol = + | "raw" + | "t0" + | "t1"; + +export interface SmartCardConnectResult { + connection: SmartCardConnection; + activeProtocol?: SmartCardProtocol; +} + +export type SmartCardAccessMode = + | "shared" + | "exclusive" + | "direct"; + +export interface SmartCardGetStatusChangeOptions { + timeout?: DOMHighResTimeStamp; + signal?: AbortSignal; +} + +export interface SmartCardConnectOptions { + preferredProtocols?: SmartCardProtocol[]; +} + +export interface SmartCardContext { + listReaders(): Promise; + getStatusChange( + readerStates: SmartCardReaderStateIn[], + options?: SmartCardGetStatusChangeOptions, + ): Promise; + connect( + readerName: string, + accessMode: SmartCardAccessMode, + options?: SmartCardConnectOptions, + ): Promise; +} + +export type SmartCardConnectionState = + | "absent" + | "present" + | "swallowed" + | "powered" + | "negotiable" + | "t0" + | "t1" + | "raw"; + +export interface SmartCardConnectionStatus { + readerName: string; + state: SmartCardConnectionState; + answerToReset?: ArrayBuffer; +} + +export type SmartCardDisposition = + | "leave" + | "reset" + | "unpower" + | "eject"; + +export interface SmartCardTransactionOptions { + signal?: AbortSignal; +} + +export interface SmartCardTransmitOptions { + protocol?: SmartCardProtocol; +} + +export type SmartCardTransactionCallback = () => Promise; + +export interface SmartCardConnection { + disconnect(disposition?: SmartCardDisposition): Promise; + transmit(sendBuffer: BufferSource, options?: SmartCardTransmitOptions): Promise; + status(): Promise; + control(controlCode: number, data: BufferSource): Promise; + getAttribute(tag: number): Promise; + setAttribute(tag: number, value: BufferSource): Promise; + startTransaction( + transaction: SmartCardTransactionCallback, + options?: SmartCardTransactionOptions, + ): Promise; +} + +declare global { + interface Navigator { + readonly smartCard: SmartCardResourceManager; + } +} diff --git a/types/w3c-web-smart-card/package.json b/types/w3c-web-smart-card/package.json new file mode 100644 index 00000000000000..f9b62c3b0a8b7e --- /dev/null +++ b/types/w3c-web-smart-card/package.json @@ -0,0 +1,32 @@ +{ + "private": true, + "nonNpm": true, + "nonNpmDescription": "Implementation of Isolated Web App (IWA) APIs resides in Chromium.", + "name": "@types/w3c-web-smart-card", + "version": "0.0.9999", + "projects": [ + "https://wicg.github.io/web-smart-card/" + ], + "devDependencies": { + "@types/web": "*", + "@types/w3c-web-smart-card": "workspace:." + }, + "owners": [ + { + "name": "Paulina Gacek", + "githubUsername": "paulinagacek" + }, + { + "name": "Zgroza (Luke) Klimek", + "githubUsername": "zgroza" + }, + { + "name": "Andrew Rayskiy", + "githubUsername": "GrapeGreen" + }, + { + "name": "Simon Hangl", + "githubUsername": "shangl" + } + ] +} diff --git a/types/w3c-web-smart-card/tsconfig.json b/types/w3c-web-smart-card/tsconfig.json new file mode 100644 index 00000000000000..077cf260675212 --- /dev/null +++ b/types/w3c-web-smart-card/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "module": "node16", + "lib": [ + "es6", + "dom" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true, + "paths": { + "w3c-web-smart-card": [ + "./index.d.ts" + ] + } + }, + "files": [ + "index.d.ts", + "w3c-web-smart-card-tests.ts" + ] +} diff --git a/types/w3c-web-smart-card/w3c-web-smart-card-tests.ts b/types/w3c-web-smart-card/w3c-web-smart-card-tests.ts new file mode 100644 index 00000000000000..72bce7d3b30b76 --- /dev/null +++ b/types/w3c-web-smart-card/w3c-web-smart-card-tests.ts @@ -0,0 +1,174 @@ +import { + SmartCardAccessMode, + SmartCardConnection, + SmartCardConnectionStatus, + SmartCardConnectOptions, + SmartCardContext, + SmartCardDisposition, + SmartCardError, + SmartCardErrorOptions, + SmartCardGetStatusChangeOptions, + SmartCardProtocol, + SmartCardReaderStateFlagsIn, + SmartCardReaderStateIn, + SmartCardResponseCode, + SmartCardTransactionCallback, + SmartCardTransactionOptions, + SmartCardTransmitOptions, +} from "w3c-web-smart-card"; + +const bufferSource: BufferSource = new ArrayBuffer(10); +const controlCode = 1234; +const tag = 0x80; + +async function testSmartCardApi() { + // -------------------------------------------------------------------------------- + // Synchronous Type Definitions (Enums, Interfaces) + // -------------------------------------------------------------------------------- + + const responseCode: SmartCardResponseCode = "no-service"; + // $ExpectType "no-service" + responseCode; + + const protocolT0: SmartCardProtocol = "t0"; + // $ExpectType "t0" + protocolT0; + + const accessModeShared: SmartCardAccessMode = "shared"; + // $ExpectType "shared" + accessModeShared; + + const dispositionLeave: SmartCardDisposition = "leave"; + // $ExpectType "leave" + dispositionLeave; + + const flagsIn: SmartCardReaderStateFlagsIn = { + present: true, + unaware: false, + }; + // $ExpectType boolean | undefined + flagsIn.unavailable; + // $ExpectType boolean | undefined + flagsIn.unaware; + + const readerStateIn: SmartCardReaderStateIn = { + readerName: "Reader A", + currentState: flagsIn, + currentCount: 5, + }; + // $ExpectType string + readerStateIn.readerName; + + const status: SmartCardConnectionStatus = { + readerName: "Reader A", + state: "present", + }; + // $ExpectType SmartCardConnectionState + status.state; + + // -------------------------------------------------------------------------------- + // SmartCardError + // -------------------------------------------------------------------------------- + + const errorOptions: SmartCardErrorOptions = { + responseCode: "removed-card", + }; + + const error = new SmartCardError( + "Card removed during transaction.", + errorOptions, + ); + // $ExpectType SmartCardError + error; + + // $ExpectType SmartCardResponseCode + error.responseCode; + // $ExpectType string + error.name; // Inherited from DOMException + + // @ts-expect-error invalid response code + new SmartCardError("Msg", { responseCode: "invalid-code" }); + + // -------------------------------------------------------------------------------- + // SmartCardResourceManager (Navigator Augmentation) + // -------------------------------------------------------------------------------- + if (navigator.smartCard) { + const resourceManager = navigator.smartCard; + // $ExpectType SmartCardResourceManager + resourceManager; + + // $ExpectType Promise + resourceManager.establishContext(); + } + + const context: SmartCardContext = {} as SmartCardContext; + + // -------------------------------------------------------------------------------- + // SmartCardContext + // -------------------------------------------------------------------------------- + + const readersPromise = context.listReaders(); + // $ExpectType Promise + readersPromise; + + const statusOptions: SmartCardGetStatusChangeOptions = { + timeout: 1000 as DOMHighResTimeStamp, + signal: {} as AbortSignal, + }; + const statusChangePromise = context.getStatusChange( + [readerStateIn], + statusOptions, + ); + // $ExpectType Promise + statusChangePromise; + + const connectOptions: SmartCardConnectOptions = { + preferredProtocols: ["t1", "raw"], + }; + const connectPromise = context.connect( + readerStateIn.readerName, + "exclusive", + connectOptions, + ); + // $ExpectType Promise + connectPromise; + + // -------------------------------------------------------------------------------- + // SmartCardConnection + // -------------------------------------------------------------------------------- + + const connection: SmartCardConnection = {} as SmartCardConnection; + + // $ExpectType Promise + connection.disconnect("unpower"); + + // $ExpectType Promise + connection.disconnect(); + + const transmitOptions: SmartCardTransmitOptions = { + protocol: "t1", + }; + + // $ExpectType Promise + connection.transmit(bufferSource, transmitOptions); + + // $ExpectType Promise + connection.status(); + + // $ExpectType Promise + connection.control(controlCode, bufferSource); + + // $ExpectType Promise + connection.getAttribute(tag); + + // $ExpectType Promise + connection.setAttribute(tag, bufferSource); + + const transactionCallback: SmartCardTransactionCallback = async () => "reset"; + const transactionOptions: SmartCardTransactionOptions = { + signal: {} as AbortSignal, + }; + + // $ExpectType Promise + connection.startTransaction(transactionCallback, transactionOptions); +}