From e1ab2dad94e987dcd30e4e5c1941be0e955fa466 Mon Sep 17 00:00:00 2001 From: Florian Rival Date: Thu, 12 Feb 2026 17:25:57 +0100 Subject: [PATCH] Prepare the files for the codemod to upgrade to Flow 0.299.0 (#8262) --- .vscode/settings.json | 1 + newIDE/app/flow-libs/bom.js | 1967 +++++++++ newIDE/app/flow-libs/cssom.js | 570 +++ newIDE/app/flow-libs/dom.js | 4071 ++++++++++++++++++ newIDE/app/flow-libs/indexeddb.js | 127 + newIDE/app/flow-libs/intl.js | 196 + newIDE/app/flow-libs/react-dom.js | 692 +++ newIDE/app/flow-libs/serviceworkers.js | 222 + newIDE/app/flow-libs/streams.js | 139 + newIDE/app/flow-libs/webassembly.js | 102 + newIDE/app/scripts/add-flow-fixme.py | 176 + newIDE/app/scripts/convert-jsx-flowfixme.py | 194 + newIDE/app/scripts/fix-arrow-return-types.py | 215 + newIDE/app/scripts/fix-codemod-syntax.py | 611 +++ newIDE/app/scripts/fix-flow-errors.sh | 884 ++++ 15 files changed, 10167 insertions(+) create mode 100644 newIDE/app/flow-libs/bom.js create mode 100644 newIDE/app/flow-libs/cssom.js create mode 100644 newIDE/app/flow-libs/dom.js create mode 100644 newIDE/app/flow-libs/indexeddb.js create mode 100644 newIDE/app/flow-libs/intl.js create mode 100644 newIDE/app/flow-libs/react-dom.js create mode 100644 newIDE/app/flow-libs/serviceworkers.js create mode 100644 newIDE/app/flow-libs/streams.js create mode 100644 newIDE/app/flow-libs/webassembly.js create mode 100644 newIDE/app/scripts/add-flow-fixme.py create mode 100644 newIDE/app/scripts/convert-jsx-flowfixme.py create mode 100644 newIDE/app/scripts/fix-arrow-return-types.py create mode 100644 newIDE/app/scripts/fix-codemod-syntax.py create mode 100755 newIDE/app/scripts/fix-flow-errors.sh diff --git a/.vscode/settings.json b/.vscode/settings.json index 9785cecd70..338982b2e2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -130,6 +130,7 @@ // Support for Flowtype (for newIDE): "javascript.validate.enable": false, "flow.useNPMPackagedFlow": true, + "flow.pathToFlow": "{workspaceFolder}/newIDE/app/node_modules/.bin/flow", // Clang format styling (duplicated in scripts/CMakeClangUtils.txt) "C_Cpp.clang_format_style": "{BasedOnStyle: Google, BinPackParameters: false, BinPackArguments: false}" diff --git a/newIDE/app/flow-libs/bom.js b/newIDE/app/flow-libs/bom.js new file mode 100644 index 0000000000..0f056e3864 --- /dev/null +++ b/newIDE/app/flow-libs/bom.js @@ -0,0 +1,1967 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* BOM */ + +declare class Screen { + +availHeight: number; + +availWidth: number; + +availLeft: number; + +availTop: number; + +top: number; + +left: number; + +colorDepth: number; + +pixelDepth: number; + +width: number; + +height: number; + +orientation?: { + lock(): Promise; + unlock(): void; + angle: number; + onchange: () => mixed; + type: 'portrait-primary' | 'portrait-secondary' | 'landscape-primary' | 'landscape-secondary'; + ... + }; + // deprecated + mozLockOrientation?: (orientation: string | Array) => boolean; + mozUnlockOrientation?: () => void; + mozOrientation?: string; + onmozorientationchange?: (...args: any[]) => mixed; +} + +declare var screen: Screen; +declare var window: any; + +type GamepadButton = { + pressed: bool, + value: number, + ... +} +type GamepadHapticActuator = { + type: 'vibration', + pulse(value: number, duration: number): Promise, + ... +} +type GamepadPose = { + angularAcceleration: null | Float32Array, + angularVelocity: null | Float32Array, + hasOrientation: boolean, + hasPosition: boolean, + linearAcceleration: null | Float32Array, + linearVelocity: null | Float32Array, + orientation: null | Float32Array, + position: null | Float32Array, + ... +} +type Gamepad = { + axes: number[], + buttons: GamepadButton[], + connected: bool, + displayId?: number, + hapticActuators?: GamepadHapticActuator[], + hand?: '' | 'left' | 'right', + id: string, + index: number, + mapping: string, + pose?: null | GamepadPose, + timestamp: number, + ... +} + +// deprecated +type BatteryManager = { + +charging: boolean, + +chargingTime: number, + +dischargingTime: number, + +level: number, + onchargingchange: ?((event: any) => mixed), + onchargingtimechange: ?((event: any) => mixed), + ondischargingtimechange: ?((event: any) => mixed), + onlevelchange: ?((event: any) => mixed), + ... +} + +// https://wicg.github.io/web-share +type ShareData = { + title?: string, + text?: string, + url?: string, + ... +} + +type PermissionName = + | "geolocation" + | "notifications" + | "push" + | "midi" + | "camera" + | "microphone" + | "speaker" + | "device-info" + | "background-sync" + | "bluetooth" + | "persistent-storage" + | "ambient-light-sensor" + | "accelerometer" + | "gyroscope" + | "magnetometer" + | "clipboard-read" + | "clipboard-write"; + +type PermissionState = + | "granted" + | "denied" + | "prompt"; + +type PermissionDescriptor = {| + name: PermissionName; +|} + +type DevicePermissionDescriptor = {| + deviceId?: string; + name: "camera" | "microphone" | "speaker"; +|} + +type MidiPermissionDescriptor = {| + name: "midi"; + sysex?: boolean; +|} + +type PushPermissionDescriptor = {| + name: "push"; + userVisibleOnly?: boolean; +|} + +type ClipboardPermissionDescriptor = {| + name: "clipboard-read" | "clipboard-write"; + allowWithoutGesture: boolean; +|} + +declare class PermissionStatus extends EventTarget { + onchange: ?((event: any) => mixed); + +state: PermissionState; +} + +declare class Permissions { + query( + permissionDesc: + | DevicePermissionDescriptor + | MidiPermissionDescriptor + | PushPermissionDescriptor + | ClipboardPermissionDescriptor + | PermissionDescriptor + ): Promise; +} + +type MIDIPortType = 'input' | 'output'; +type MIDIPortDeviceState = 'connected' | 'disconnected'; +type MIDIPortConnectionState = 'open' | 'closed' | 'pending'; + +type MIDIOptions = {| + sysex: boolean; + software: boolean; +|} + +type MIDIMessageEvent$Init = Event$Init & { + data: Uint8Array; + ... +} + +declare class MIDIMessageEvent extends Event { + constructor(type: string, eventInitDict: MIDIMessageEvent$Init): void; + +data: Uint8Array; +} + +type MIDIConnectionEvent$Init = Event$Init & { + port: MIDIPort; + ... +} + +declare class MIDIConnectionEvent extends Event { + constructor(type: string, eventInitDict: MIDIConnectionEvent$Init): void; + +port: MIDIPort; +} + +declare class MIDIPort extends EventTarget { + +id: string; + +manufacturer?: string; + +name?: string; + +type: MIDIPortType; + +version?: string; + +state: MIDIPortDeviceState; + +connection: MIDIPortConnectionState; + onstatechange: ?((ev: MIDIConnectionEvent) => mixed); + open(): Promise; + close(): Promise; +} + +declare class MIDIInput extends MIDIPort { + onmidimessage: ?((ev: MIDIMessageEvent) => mixed); +} + +declare class MIDIOutput extends MIDIPort { + send(data: Iterable, timestamp?: number): void; + clear(): void; +} + +declare class MIDIInputMap extends $ReadOnlyMap {} + +declare class MIDIOutputMap extends $ReadOnlyMap {} + +declare class MIDIAccess extends EventTarget { + +inputs: MIDIInputMap; + +outputs: MIDIOutputMap; + +sysexEnabled: boolean; + onstatechange: ?((ev: MIDIConnectionEvent) => mixed); +} + +declare class NavigatorID { + appName: 'Netscape'; + appCodeName: 'Mozilla'; + product: 'Gecko'; + appVersion: string; + platform: string; + userAgent: string; +} + +declare class NavigatorLanguage { + +language: string; + +languages: $ReadOnlyArray; +} + +declare class NavigatorContentUtils { + registerContentHandler(mimeType: string, uri: string, title: string): void; + registerProtocolHandler(protocol: string, uri: string, title: string): void; +} + +declare class NavigatorCookies { + +cookieEnabled: boolean; +} + +declare class NavigatorPlugins { + +plugins: PluginArray; + +mimeTypes: MimeTypeArray; + javaEnabled(): boolean; +} + +declare class NavigatorOnLine { + +onLine: boolean; +} + +declare class NavigatorConcurrentHardware { + +hardwareConcurrency: number; +} + +declare class Navigator mixins + NavigatorID, + NavigatorLanguage, + NavigatorOnLine, + NavigatorContentUtils, + NavigatorCookies, + NavigatorPlugins, + NavigatorConcurrentHardware { + productSub: '20030107' | '20100101'; + vendor: '' | 'Google Inc.' | 'Apple Computer, Inc'; + vendorSub: ''; + + activeVRDisplays?: VRDisplay[]; + appCodeName: 'Mozilla'; + buildID: string; + doNotTrack: string | null; + geolocation: Geolocation; + mediaDevices?: MediaDevices; + maxTouchPoints: number; + permissions: Permissions; + serviceWorker?: ServiceWorkerContainer; + getGamepads?: () => Array; + webkitGetGamepads?: Function; + mozGetGamepads?: Function; + mozGamepads?: any; + gamepads?: any; + webkitGamepads?: any; + getVRDisplays?: () => Promise; + registerContentHandler(mimeType: string, uri: string, title: string): void; + registerProtocolHandler(protocol: string, uri: string, title: string): void; + requestMIDIAccess?: (options?: MIDIOptions) => Promise; + requestMediaKeySystemAccess?: (keySystem: string, supportedConfigurations: any[]) => Promise; + sendBeacon?: (url: string, data?: BodyInit) => boolean; + vibrate?: (pattern: number | number[]) => boolean; + mozVibrate?: (pattern: number | number[]) => boolean; + webkitVibrate?: (pattern: number | number[]) => boolean; + share?: (shareData: ShareData) => Promise; + clipboard: Clipboard; + credentials?: CredMgmtCredentialsContainer; + + // deprecated + getBattery?: () => Promise; + mozGetBattery?: () => Promise; + + // deprecated + getUserMedia?: Function; + webkitGetUserMedia?: Function; + mozGetUserMedia?: Function; + msGetUserMedia?: Function; + + // Gecko + taintEnabled?: () => false; + oscpu: string; +} + +declare class Clipboard extends EventTarget { + read(): Promise; + readText(): Promise; + write(data: DataTransfer): Promise; + writeText(data: string): Promise; +} + +declare var navigator: Navigator; + +declare class MimeType { + type: string; + description: string; + suffixes: string; + enabledPlugin: Plugin; +} + +declare class MimeTypeArray { + length: number; + item(index: number): MimeType; + namedItem(name: string): MimeType; + [key: number | string]: MimeType; +} + +declare class Plugin { + description: string; + filename: string; + name: string; + version?: string; // Gecko only + length: number; + item(index: number): MimeType; + namedItem(name: string): MimeType; + [key: number | string]: MimeType; +} + +declare class PluginArray { + length: number; + item(index: number): Plugin; + namedItem(name: string): Plugin; + refresh(): void; + [key: number | string]: Plugin; +} + +// https://www.w3.org/TR/hr-time-2/#dom-domhighrestimestamp +// https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp +declare type DOMHighResTimeStamp = number; + +// https://www.w3.org/TR/navigation-timing-2/ +declare class PerformanceTiming { + connectEnd: number; + connectStart: number; + domainLookupEnd: number; + domainLookupStart: number; + domComplete: number; + domContentLoadedEventEnd: number; + domContentLoadedEventStart: number; + domInteractive: number; + domLoading: number; + fetchStart: number; + loadEventEnd: number; + loadEventStart: number; + navigationStart: number; + redirectEnd: number; + redirectStart: number; + requestStart: number; + responseEnd: number; + responseStart: number; + secureConnectionStart: number; + unloadEventEnd: number; + unloadEventStart: number; +} + +declare class PerformanceNavigation { + TYPE_NAVIGATE: 0; + TYPE_RELOAD: 1; + TYPE_BACK_FORWARD: 2; + TYPE_RESERVED: 255; + + type: 0 | 1 | 2 | 255; + redirectCount: number; +} + +type PerformanceEntryFilterOptions = { + name: string, + entryType: string, + initiatorType: string, + ... +} + +// https://www.w3.org/TR/performance-timeline-2/ +declare class PerformanceEntry { + name: string; + entryType: string; + startTime: DOMHighResTimeStamp; + duration: DOMHighResTimeStamp; + toJSON(): string; +} + +// https://www.w3.org/TR/resource-timing/ +declare class PerformanceResourceTiming extends PerformanceEntry { + initiatorType: string; + redirectStart: number; + redirectEnd: number; + fetchStart: number; + domainLookupStart: number; + domainLookupEnd: number; + connectStart: number; + connectEnd: number; + secureConnectionStart: number; + requestStart: number; + responseStart: number; + responseEnd: number; +} + +// https://www.w3.org/TR/navigation-timing-2/ +declare class PerformanceNavigationTiming extends PerformanceResourceTiming { + unloadEventStart: number; + unloadEventEnd: number; + domInteractive: number; + domContentLoadedEventStart: number; + domContentLoadedEventEnd: number; + domComplete: number; + loadEventStart: number; + loadEventEnd: number; + type: 'navigate' | 'reload' | 'back_forward' | 'prerender'; + redirectCount: number; +} + +declare class Performance { + // deprecated + navigation: PerformanceNavigation; + timing: PerformanceTiming; + + onresourcetimingbufferfull: (ev: any) => mixed; + clearMarks(name?: string): void; + clearMeasures(name?: string): void; + clearResourceTimings(): void; + getEntries(options?: PerformanceEntryFilterOptions): Array; + getEntriesByName(name: string, type?: string): Array; + getEntriesByType(type: string): Array; + mark(name: string): void; + measure(name: string, startMark?: string, endMark?: string): void; + now(): DOMHighResTimeStamp; + setResourceTimingBufferSize(maxSize: number): void; + toJSON(): string; +} + +declare var performance: Performance; + +type PerformanceEntryList = PerformanceEntry[]; + +declare interface PerformanceObserverEntryList { + getEntries(): PerformanceEntryList; + getEntriesByType(type: string): PerformanceEntryList; + getEntriesByName(name: string, type: ?string): PerformanceEntryList; +} + +type PerformanceObserverInit = { + entryTypes?: string[]; + type?: string; + buffered?: boolean; + ... +} + +declare class PerformanceObserver { + constructor(callback: (entries: PerformanceObserverEntryList, observer: PerformanceObserver) => mixed): void; + + observe(options: ?PerformanceObserverInit): void; + disconnect(): void; + takeRecords(): PerformanceEntryList; + + static supportedEntryTypes: string[]; +} + +declare class History { + length: number; + scrollRestoration: 'auto' | 'manual'; + state: any; + back(): void; + forward(): void; + go(delta?: number): void; + pushState(statedata: any, title: string, url?: string): void; + replaceState(statedata: any, title: string, url?: string): void; +} + +declare var history: History; + +declare class Location { + ancestorOrigins: string[]; + hash: string; + host: string; + hostname: string; + href: string; + origin: string; + pathname: string; + port: string; + protocol: string; + search: string; + assign(url: string): void; + reload(flag?: boolean): void; + replace(url: string): void; + toString(): string; +} + +declare var location: Location; + +/////////////////////////////////////////////////////////////////////////////// + +declare class DOMParser { + parseFromString(source: string, mimeType: string): Document; +} + +type FormDataEntryValue = string | File + +declare class FormData { + constructor(form?: HTMLFormElement): void; + + has(name: string): boolean; + get(name: string): ?FormDataEntryValue; + getAll(name: string): Array; + + set(name: string, value: string): void; + set(name: string, value: Blob, filename?: string): void; + set(name: string, value: File, filename?: string): void; + + append(name: string, value: string): void; + append(name: string, value: Blob, filename?: string): void; + append(name: string, value: File, filename?: string): void; + + delete(name: string): void; + + keys(): Iterator; + values(): Iterator; + entries(): Iterator<[string, FormDataEntryValue]>; +} + +declare class MutationRecord { + type: 'attributes' | 'characterData' | 'childList'; + target: Node; + addedNodes: NodeList; + removedNodes: NodeList; + previousSibling: ?Node; + nextSibling: ?Node; + attributeName: ?string; + attributeNamespace: ?string; + oldValue: ?string; +} + +type MutationObserverInitRequired = + | { childList: true, ... } + | { attributes: true, ... } + | { characterData: true, ... } + +declare type MutationObserverInit = MutationObserverInitRequired & { + subtree?: boolean, + attributeOldValue?: boolean, + characterDataOldValue?: boolean, + attributeFilter?: Array, + ... +} + +declare class MutationObserver { + constructor(callback: (arr: Array, observer: MutationObserver) => mixed): void; + observe(target: Node, options: MutationObserverInit): void; + takeRecords(): Array; + disconnect(): void; +} + +declare class DOMRectReadOnly { + static fromRect(rectangle?: { + x: number, + y: number, + width: number, + height: number, + ... + }): DOMRectReadOnly; + constructor(x: number, y: number, width: number, height: number): void; + +bottom: number; + +height: number; + +left: number; + +right: number; + +top: number; + +width: number; + +x: number; + +y: number; +} + +declare class DOMRect extends DOMRectReadOnly { + static fromRect(rectangle?: { + x: number, + y: number, + width: number, + height: number, + ... + }): DOMRect; + bottom: number; + height: number; + left: number; + right: number; + top: number; + width: number; + x: number; + y: number; +} + +declare class DOMRectList { + @@iterator(): Iterator; + length: number; + item(index: number): DOMRect; + [index: number]: DOMRect; +} + +declare type IntersectionObserverEntry = { + boundingClientRect: DOMRectReadOnly, + intersectionRatio: number, + intersectionRect: DOMRectReadOnly, + isIntersecting: boolean, + rootBounds: DOMRectReadOnly, + target: HTMLElement, + time: DOMHighResTimeStamp, + ... +}; + +declare type IntersectionObserverCallback = ( + entries: Array, + observer: IntersectionObserver, +) => mixed; + +declare type IntersectionObserverOptions = { + root?: Node | null, + rootMargin?: string, + threshold?: number | Array, + ... +}; + +declare class IntersectionObserver { + constructor( + callback: IntersectionObserverCallback, + options?: IntersectionObserverOptions + ): void, + observe(target: HTMLElement): void, + unobserve(target: HTMLElement): void, + takeRecords(): Array, + disconnect(): void, +} + +declare class ResizeObserverEntry { + target: Element; + contentRect: DOMRectReadOnly; +} + +declare class ResizeObserver { + constructor(callback: (entries: ResizeObserverEntry[], observer: ResizeObserver) => mixed): void; + observe(target: Element): void; + unobserve(target: Element): void; + disconnect(): void; +} + +declare var NodeFilter: { + acceptNode(n: Node): number, + SHOW_ENTITY_REFERENCE: number, + SHOW_NOTATION: number, + SHOW_ENTITY: number, + SHOW_DOCUMENT: number, + SHOW_PROCESSING_INSTRUCTION: number, + FILTER_REJECT: number, + SHOW_CDATA_SECTION: number, + FILTER_ACCEPT: number, + SHOW_ALL: number, + SHOW_DOCUMENT_TYPE: number, + SHOW_TEXT: number, + SHOW_ELEMENT: number, + SHOW_COMMENT: number, + FILTER_SKIP: number, + SHOW_ATTRIBUTE: number, + SHOW_DOCUMENT_FRAGMENT: number, + ... +}; + +declare class CloseEvent extends Event { + code: number; + reason: string; + wasClean: boolean; +} + +declare class WebSocket extends EventTarget { + static CONNECTING: 0; + static OPEN: 1; + static CLOSING: 2; + static CLOSED: 3; + constructor(url: string, protocols?: string | Array): void; + protocol: string; + readyState: number; + bufferedAmount: number; + extensions: string; + onopen: (ev: any) => mixed; + onmessage: (ev: MessageEvent) => mixed; + onclose: (ev: CloseEvent) => mixed; + onerror: (ev: any) => mixed; + binaryType: 'blob' | 'arraybuffer'; + url: string; + close(code?: number, reason?: string): void; + send(data: string): void; + send(data: Blob): void; + send(data: ArrayBuffer): void; + send(data: $ArrayBufferView): void; + CONNECTING: 0; + OPEN: 1; + CLOSING: 2; + CLOSED: 3; +} + +type WorkerOptions = { + type?: WorkerType, + credentials?: CredentialsType, + name?: string, + ... +} + +declare class Worker extends EventTarget { + constructor(stringUrl: string, workerOptions?: WorkerOptions): void; + onerror: null | (ev: any) => mixed; + onmessage: null | (ev: MessageEvent) => mixed; + onmessageerror: null | (ev: MessageEvent) => mixed; + postMessage(message: any, ports?: any): void; + terminate(): void; +} + +declare class SharedWorker extends EventTarget { + constructor(stringUrl: string, name?: string): void; + constructor(stringUrl: string, workerOptions?: WorkerOptions): void; + port: MessagePort; + onerror: (ev: any) => mixed; +} + +declare function importScripts(...urls: Array): void; + +declare class WorkerGlobalScope extends EventTarget { + self: this; + location: WorkerLocation; + navigator: WorkerNavigator; + close(): void; + importScripts(...urls: Array): void; + onerror: (ev: any) => mixed; + onlanguagechange: (ev: any) => mixed; + onoffline: (ev: any) => mixed; + ononline: (ev: any) => mixed; + onrejectionhandled: (ev: PromiseRejectionEvent) => mixed; + onunhandledrejection: (ev: PromiseRejectionEvent) => mixed; +} + +declare class DedicatedWorkerGlobalScope extends WorkerGlobalScope { + onmessage: (ev: MessageEvent) => mixed; + onmessageerror: (ev: MessageEvent) => mixed; + postMessage(message: any, transfer?: Iterable): void; +} + +declare class SharedWorkerGlobalScope extends WorkerGlobalScope { + name: string; + onconnect: (ev: MessageEvent) => mixed; +} + +declare class WorkerLocation { + origin: string; + protocol: string; + host: string; + hostname: string; + port: string; + pathname: string; + search: string; + hash: string; +} + +declare class WorkerNavigator mixins + NavigatorID, + NavigatorLanguage, + NavigatorOnLine, + NavigatorConcurrentHardware { + permissions: Permissions; + } + + +// deprecated +declare class XDomainRequest { + timeout: number; + onerror: () => mixed; + onload: () => mixed; + onprogress: () => mixed; + ontimeout: () => mixed; + +responseText: string; + +contentType: string; + open(method: "GET" | "POST", url: string): void; + abort(): void; + send(data?: string): void; + + statics: { create(): XDomainRequest, ... } +} + +declare class XMLHttpRequest extends EventTarget { + static LOADING: number; + static DONE: number; + static UNSENT: number; + static OPENED: number; + static HEADERS_RECEIVED: number; + responseBody: any; + status: number; + readyState: number; + responseText: string; + responseXML: any; + responseURL: string; + ontimeout: ProgressEventHandler; + statusText: string; + onreadystatechange: (ev: any) => mixed; + timeout: number; + onload: ProgressEventHandler; + response: any; + withCredentials: boolean; + onprogress: ProgressEventHandler; + onabort: ProgressEventHandler; + responseType: string; + onloadend: ProgressEventHandler; + upload: XMLHttpRequestEventTarget; + onerror: ProgressEventHandler; + onloadstart: ProgressEventHandler; + msCaching: string; + open(method: string, url: string, async?: boolean, user?: string, password?: string): void; + send(data?: any): void; + abort(): void; + getAllResponseHeaders(): string; + setRequestHeader(header: string, value: string): void; + getResponseHeader(header: string): string; + msCachingEnabled(): boolean; + overrideMimeType(mime: string): void; + LOADING: number; + DONE: number; + UNSENT: number; + OPENED: number; + HEADERS_RECEIVED: number; + + statics: { create(): XMLHttpRequest, ... } +} + +declare class XMLHttpRequestEventTarget extends EventTarget { + onprogress: ProgressEventHandler; + onerror: ProgressEventHandler; + onload: ProgressEventHandler; + ontimeout: ProgressEventHandler; + onabort: ProgressEventHandler; + onloadstart: ProgressEventHandler; + onloadend: ProgressEventHandler; +} + +declare class XMLSerializer { + serializeToString(target: Node): string; +} + +declare class Geolocation { + getCurrentPosition( + success: (position: Position) => mixed, + error?: (error: PositionError) => mixed, + options?: PositionOptions + ): void; + watchPosition( + success: (position: Position) => mixed, + error?: (error: PositionError) => mixed, + options?: PositionOptions + ): number; + clearWatch(id: number): void; +} + +declare class Position { + coords: Coordinates; + timestamp: number; +} + +declare class Coordinates { + latitude: number; + longitude: number; + altitude?: number; + accuracy: number; + altitudeAccuracy?: number; + heading?: number; + speed?: number; +} + +declare class PositionError { + code: number; + message: string; + PERMISSION_DENIED: 1; + POSITION_UNAVAILABLE: 2; + TIMEOUT: 3; +} + +type PositionOptions = { + enableHighAccuracy?: boolean, + timeout?: number, + maximumAge?: number, + ... +} + +type AudioContextState = 'suspended' | 'running' | 'closed'; + +// deprecated +type AudioProcessingEvent$Init = Event$Init & { + playbackTime: number; + inputBuffer: AudioBuffer; + outputBuffer: AudioBuffer; + ... +} + +// deprecated +declare class AudioProcessingEvent extends Event { + constructor(type: string, eventInitDict: AudioProcessingEvent$Init): void; + + +playbackTime: number; + +inputBuffer: AudioBuffer; + +outputBuffer: AudioBuffer; +} + +type OfflineAudioCompletionEvent$Init = Event$Init & { + renderedBuffer: AudioBuffer; + ... +} + +declare class OfflineAudioCompletionEvent extends Event { + constructor(type: string, eventInitDict: OfflineAudioCompletionEvent$Init): void; + + +renderedBuffer: AudioBuffer; +} + +declare class BaseAudioContext extends EventTarget { + currentTime: number; + destination: AudioDestinationNode; + listener: AudioListener; + sampleRate: number; + state: AudioContextState; + onstatechange: (ev: any) => mixed; + createBuffer(numOfChannels: number, length: number, sampleRate: number): AudioBuffer; + createBufferSource(myMediaElement?: HTMLMediaElement): AudioBufferSourceNode; + createMediaElementSource(myMediaElement: HTMLMediaElement): MediaElementAudioSourceNode; + createMediaStreamSource(stream: MediaStream): MediaStreamAudioSourceNode; + createMediaStreamDestination(): MediaStreamAudioDestinationNode; + + // deprecated + createScriptProcessor(bufferSize: number, numberOfInputChannels: number, numberOfOutputChannels: number): ScriptProcessorNode; + + createAnalyser(): AnalyserNode; + createBiquadFilter(): BiquadFilterNode; + createChannelMerger(numberOfInputs?: number): ChannelMergerNode; + createChannelSplitter(numberOfInputs?: number): ChannelSplitterNode; + createConstantSource(): ConstantSourceNode; + createConvolver(): ConvolverNode; + createDelay(maxDelayTime?: number): DelayNode; + createDynamicsCompressor(): DynamicsCompressorNode; + createGain(): GainNode; + createIIRFilter (feedforward: Float32Array, feedback: Float32Array): IIRFilterNode; + createOscillator(): OscillatorNode; + createPanner(): PannerNode; + createStereoPanner(): StereoPannerNode; + createPeriodicWave(real: Float32Array, img: Float32Array, options?: { disableNormalization: bool, ... }): PeriodicWave; + createStereoPanner(): StereoPannerNode; + createWaveShaper(): WaveShaperNode; + decodeAudioData(arrayBuffer: ArrayBuffer, decodeSuccessCallback: (decodedData: AudioBuffer) => mixed, decodeErrorCallback: (err: DOMError) => mixed): void; + decodeAudioData(arrayBuffer: ArrayBuffer): Promise; +} + +declare class AudioTimestamp { + contextTime: number; + performanceTime: number; +} + +declare class AudioContext extends BaseAudioContext { + baseLatency: number; + outputLatency: number; + getOutputTimestamp(): AudioTimestamp; + resume(): Promise; + suspend(): Promise; + close(): Promise; + createMediaElementSource(myMediaElement: HTMLMediaElement): MediaElementAudioSourceNode; + createMediaStreamSource(myMediaStream: MediaStream): MediaStreamAudioSourceNode; + createMediaStreamTrackSource(myMediaStreamTrack: MediaStreamTrack): MediaStreamTrackAudioSourceNode; + createMediaStreamDestination(): MediaStreamAudioDestinationNode; +} + +declare class OfflineAudioContext extends BaseAudioContext { + startRendering(): Promise; + suspend(suspendTime: number): Promise; + length: number; + oncomplete: (ev: OfflineAudioCompletionEvent) => mixed; +} + +declare class AudioNode extends EventTarget { + context: AudioContext; + numberOfInputs: number; + numberOfOutputs: number; + channelCount: number; + channelCountMode: 'max' | 'clamped-max' | 'explicit'; + channelInterpretation: 'speakers' | 'discrete'; + connect(audioNode: AudioNode, output?: number, input?: number): AudioNode; + connect(destination: AudioParam, output?: number): void; + disconnect(destination?: AudioNode, output?: number, input?: number): void; +} + +declare class AudioParam extends AudioNode { + value: number; + defaultValue: number; + setValueAtTime(value: number, startTime: number): this; + linearRampToValueAtTime(value: number, endTime: number): this; + exponentialRampToValueAtTime(value: number, endTime: number): this; + setTargetAtTime(target: number, startTime: number, timeConstant: number): this; + setValueCurveAtTime(values: Float32Array, startTime: number, duration: number): this; + cancelScheduledValues(startTime: number): this; +} + +declare class AudioDestinationNode extends AudioNode { + maxChannelCount: number; +} + +declare class AudioListener extends AudioNode { + positionX: AudioParam; + positionY: AudioParam; + positionZ: AudioParam; + forwardX: AudioParam; + forwardY: AudioParam; + forwardZ: AudioParam; + upX: AudioParam; + upY: AudioParam; + upZ: AudioParam; + setPosition(x: number, y: number, c: number): void; + setOrientation(x: number, y: number, z: number, xUp: number, yUp: number, zUp: number): void; +} + +declare class AudioBuffer { + sampleRate: number; + length: number; + duration: number; + numberOfChannels: number; + getChannelData(channel: number): Float32Array; + copyFromChannel(destination: Float32Array, channelNumber: number, startInChannel?: number): void; + copyToChannel(source: Float32Array, channelNumber: number, startInChannel?: number): void; +} + +declare class AudioBufferSourceNode extends AudioNode { + buffer: AudioBuffer; + detune: AudioParam; + loop: bool; + loopStart: number; + loopEnd: number; + playbackRate: AudioParam; + onended: (ev: any) => mixed; + start(when?: number, offset?: number, duration?: number): void; + stop(when?: number): void; +} + +declare class CanvasCaptureMediaStream extends MediaStream { + canvas: HTMLCanvasElement; + requestFrame(): void; +} + +type DoubleRange = { + max?: number; + min?: number; + ... +} + +type LongRange = { + max?: number; + min?: number; + ... +} + +type ConstrainBooleanParameters = { + exact?: boolean; + ideal?: boolean; + ... +} + +type ConstrainDOMStringParameters = { + exact?: string | string[]; + ideal?: string | string[]; + ... +} + +type ConstrainDoubleRange = { + ...DoubleRange; + exact?: number; + ideal?: number; + ... +} + +type ConstrainLongRange = { + ...LongRange; + exact?: number; + ideal?: number; + ... +} + +type MediaTrackSupportedConstraints = {| + width: boolean; + height: boolean; + aspectRatio: boolean; + frameRate: boolean; + facingMode: boolean; + resizeMode: boolean; + volume: boolean; + sampleRate: boolean; + sampleSize: boolean; + echoCancellation: boolean; + autoGainControl: boolean; + noiseSuppression: boolean; + latency: boolean; + channelCount: boolean; + deviceId: boolean; + groupId: boolean; +|} + +type MediaTrackConstraintSet = { + width?: number | ConstrainLongRange; + height?: number | ConstrainLongRange; + aspectRatio?: number | ConstrainDoubleRange; + frameRate?: number | ConstrainDoubleRange; + facingMode?: string | string[] | ConstrainDOMStringParameters; + resizeMode?: string | string[] | ConstrainDOMStringParameters; + volume?: number | ConstrainDoubleRange; + sampleRate?: number | ConstrainLongRange; + sampleSize?: number | ConstrainLongRange; + echoCancellation?: boolean | ConstrainBooleanParameters; + autoGainControl?: boolean | ConstrainBooleanParameters; + noiseSuppression?: boolean | ConstrainBooleanParameters; + latency?: number | ConstrainDoubleRange; + channelCount?: number | ConstrainLongRange; + deviceId?: string | string[] | ConstrainDOMStringParameters; + groupId?: string | string[] | ConstrainDOMStringParameters; + ... +} + +type MediaTrackConstraints = { + ...MediaTrackConstraintSet; + advanced?: Array; + ... +} + +type DisplayMediaStreamConstraints = { + video?: boolean | MediaTrackConstraints; + audio?: boolean | MediaTrackConstraints; + ... +} + +type MediaStreamConstraints = { + audio?: boolean | MediaTrackConstraints; + video?: boolean | MediaTrackConstraints; + peerIdentity?: string; + ... +} + +type MediaTrackSettings = { + aspectRatio?: number; + deviceId?: string; + echoCancellation?: boolean; + facingMode?: string; + frameRate?: number; + groupId?: string; + height?: number; + sampleRate?: number; + sampleSize?: number; + volume?: number; + width?: number; + ... +} + +type MediaTrackCapabilities = { + aspectRatio?: number | DoubleRange; + deviceId?: string; + echoCancellation?: boolean[]; + facingMode?: string; + frameRate?: number | DoubleRange; + groupId?: string; + height?: number | LongRange; + sampleRate?: number | LongRange; + sampleSize?: number | LongRange; + volume?: number | DoubleRange; + width?: number | LongRange; + ... +} + +declare class MediaDevices extends EventTarget { + ondevicechange: (ev: any) => mixed; + enumerateDevices: () => Promise>; + getSupportedConstraints: () => MediaTrackSupportedConstraints; + getDisplayMedia: (constraints?: DisplayMediaStreamConstraints) => Promise; + getUserMedia: (constraints: MediaStreamConstraints) => Promise; +} + +declare class MediaDeviceInfo { + +deviceId: string; + +groupId: string; + +kind: 'videoinput' | 'audioinput' | 'audiooutput'; + +label: string; +} + +declare class MediaStream extends EventTarget { + active: bool; + ended: bool; + id: string; + onactive: (ev: any) => mixed; + oninactive: (ev: any) => mixed; + onended: (ev: any) => mixed; + onaddtrack: (ev: MediaStreamTrackEvent) => mixed; + onremovetrack: (ev: MediaStreamTrackEvent) => mixed; + addTrack(track: MediaStreamTrack): void; + clone(): MediaStream; + getAudioTracks(): MediaStreamTrack[]; + getTrackById(trackid?: string): ?MediaStreamTrack; + getTracks(): MediaStreamTrack[]; + getVideoTracks(): MediaStreamTrack[]; + removeTrack(track: MediaStreamTrack): void; +} + +declare class MediaStreamTrack extends EventTarget { + enabled: bool; + id: string; + kind: string; + label: string; + muted: bool; + readonly: bool; + readyState: 'live' | 'ended'; + remote: bool; + onstarted: (ev: any) => mixed; + onmute: (ev: any) => mixed; + onunmute: (ev: any) => mixed; + onoverconstrained: (ev: any) => mixed; + onended: (ev: any) => mixed; + getConstraints(): MediaTrackConstraints; + applyConstraints(constraints?: MediaTrackConstraints): Promise; + getSettings(): MediaTrackSettings; + getCapabilities(): MediaTrackCapabilities; + clone(): MediaStreamTrack; + stop(): void; +} + +declare class MediaStreamTrackEvent extends Event { + track: MediaStreamTrack; +} + +declare class MediaElementAudioSourceNode extends AudioNode {} +declare class MediaStreamAudioSourceNode extends AudioNode {} +declare class MediaStreamTrackAudioSourceNode extends AudioNode {} + +declare class MediaStreamAudioDestinationNode extends AudioNode { + stream: MediaStream; +} + +// deprecated +declare class ScriptProcessorNode extends AudioNode { + bufferSize: number; + onaudioprocess: (ev: AudioProcessingEvent) => mixed; +} + +declare class AnalyserNode extends AudioNode { + fftSize: number; + frequencyBinCount: number; + minDecibels: number; + maxDecibels: number; + smoothingTimeConstant: number; + getFloatFrequencyData(array: Float32Array): Float32Array; + getByteFrequencyData(array: Uint8Array): Uint8Array; + getFloatTimeDomainData(array: Float32Array): Float32Array; + getByteTimeDomainData(array: Uint8Array): Uint8Array; +} + +declare class BiquadFilterNode extends AudioNode { + frequency: AudioParam; + detune: AudioParam; + Q: AudioParam; + gain: AudioParam; + type: 'lowpass'|'highpass'|'bandpass'|'lowshelf'|'highshelf'|'peaking'|'notch'|'allpass'; + getFrequencyResponse(frequencyHz: Float32Array, magResponse: Float32Array, phaseResponse: Float32Array): void; +} + +declare class ChannelMergerNode extends AudioNode {} +declare class ChannelSplitterNode extends AudioNode {} + +type ConstantSourceOptions = { offset?: number, ... } +declare class ConstantSourceNode extends AudioNode { + constructor(context: BaseAudioContext, options?: ConstantSourceOptions): void; + offset: AudioParam; + onended: (ev: any) => mixed; + start(when?: number): void; + stop(when?: number): void; +} + +declare class ConvolverNode extends AudioNode { + buffer: AudioBuffer; + normalize: bool; +} + +declare class DelayNode extends AudioNode { + delayTime: number; +} + +declare class DynamicsCompressorNode extends AudioNode { + threshold: AudioParam; + knee: AudioParam; + ratio: AudioParam; + reduction: AudioParam; + attack: AudioParam; + release: AudioParam; +} + +declare class GainNode extends AudioNode { + gain: AudioParam; +} + +declare class IIRFilterNode extends AudioNode { + getFrequencyResponse(frequencyHz: Float32Array, magResponse: Float32Array, phaseResponse: Float32Array): void; +} + +declare class OscillatorNode extends AudioNode { + frequency: AudioParam; + detune: AudioParam; + type: 'sine' | 'square' | 'sawtooth' | 'triangle' | 'custom'; + start(when?: number): void; + stop(when?: number): void; + setPeriodicWave(periodicWave: PeriodicWave): void; + onended: (ev: any) => mixed; +} + +declare class StereoPannerNode extends AudioNode { + pan: AudioParam; +} + +declare class PannerNode extends AudioNode { + panningModel: 'equalpower'|'HRTF'; + distanceModel: 'linear'|'inverse'|'exponential'; + refDistance: number; + maxDistance: number; + rolloffFactor: number; + coneInnerAngle: number; + coneOuterAngle: number; + coneOuterGain: number; + setPosition(x: number, y: number, z: number): void; + setOrientation(x: number, y: number, z: number): void; +} + +declare class PeriodicWave extends AudioNode {} +declare class WaveShaperNode extends AudioNode { + curve: Float32Array; + oversample: 'none'|'2x'|'4x'; +} + + +// this part of spec is not finished yet, apparently +// https://stackoverflow.com/questions/35296664/can-fetch-get-object-as-headers +type HeadersInit = Headers | Array<[string, string]> | { [key: string]: string, ... }; + + +// TODO Heades and URLSearchParams are almost the same thing. +// Could it somehow be abstracted away? +declare class Headers { + @@iterator(): Iterator<[string, string]>; + constructor(init?: HeadersInit): void; + append(name: string, value: string): void; + delete(name: string): void; + entries(): Iterator<[string, string]>; + forEach(callback: (value: string, name: string, headers: Headers) => mixed, thisArg?: any): void; + get(name: string): null | string; + has(name: string): boolean; + keys(): Iterator; + set(name: string, value: string): void; + values(): Iterator; +} + +declare class URLSearchParams { + @@iterator(): Iterator<[string, string]>; + constructor(query?: string | URLSearchParams | Array<[string, string]> | { [string]: string, ... } ): void; + append(name: string, value: string): void; + delete(name: string): void; + entries(): Iterator<[string, string]>; + forEach(callback: (value: string, name: string, params: URLSearchParams) => mixed, thisArg?: any): void; + get(name: string): null | string; + getAll(name: string): Array; + has(name: string): boolean; + keys(): Iterator; + set(name: string, value: string): void; + values(): Iterator; +} + +type CacheType = 'default' | 'no-store' | 'reload' | 'no-cache' | 'force-cache' | 'only-if-cached'; +type CredentialsType = 'omit' | 'same-origin' | 'include'; +type ModeType = 'cors' | 'no-cors' | 'same-origin'; +type RedirectType = 'follow' | 'error' | 'manual'; +type ReferrerPolicyType = + '' | 'no-referrer' | 'no-referrer-when-downgrade' | 'same-origin' | + 'origin' | 'strict-origin' | 'origin-when-cross-origin' | + 'strict-origin-when-cross-origin' | 'unsafe-url'; + +type ResponseType = 'basic' | 'cors' | 'default' | 'error' | 'opaque' | 'opaqueredirect' ; + +type BodyInit = string | URLSearchParams | FormData | Blob | ArrayBuffer | $ArrayBufferView | ReadableStream; + +type RequestInfo = Request | URL | string; + +type RequestOptions = { + body?: ?BodyInit, + cache?: CacheType, + credentials?: CredentialsType, + headers?: HeadersInit, + integrity?: string, + keepalive?: boolean, + method?: string, + mode?: ModeType, + redirect?: RedirectType, + referrer?: string, + referrerPolicy?: ReferrerPolicyType, + signal?: ?AbortSignal, + window?: any, + ... +} + +type ResponseOptions = { + status?: number, + statusText?: string, + headers?: HeadersInit, + ... +} + +declare class Response { + constructor(input?: ?BodyInit, init?: ResponseOptions): void; + clone(): Response; + static error(): Response; + static redirect(url: string, status?: number): Response; + + redirected: boolean; + type: ResponseType; + url: string; + ok: boolean; + status: number; + statusText: string; + headers: Headers; + trailer: Promise; + + // Body methods and attributes + bodyUsed: boolean; + body: ?ReadableStream, + + arrayBuffer(): Promise; + blob(): Promise; + formData(): Promise; + json(): Promise; + text(): Promise; +} + +declare class Request { + constructor(input: RequestInfo, init?: RequestOptions): void; + clone(): Request; + + url: string; + + cache: CacheType; + credentials: CredentialsType; + headers: Headers; + integrity: string; + method: string; + mode: ModeType; + redirect: RedirectType; + referrer: string; + referrerPolicy: ReferrerPolicyType; + +signal: AbortSignal; + + // Body methods and attributes + bodyUsed: boolean; + + arrayBuffer(): Promise; + blob(): Promise; + formData(): Promise; + json(): Promise; + text(): Promise; +} + +declare class AbortController { + constructor(): void; + +signal: AbortSignal; + abort(): void; +} + +declare class AbortSignal extends EventTarget { + +aborted: boolean; + onabort: (event: any) => mixed; +} + +declare function fetch(input: RequestInfo, init?: RequestOptions): Promise; + + +type TextEncoder$availableEncodings = 'utf-8' | 'utf8' | 'unicode-1-1-utf-8' | 'utf-16be' | 'utf-16' | 'utf-16le'; + +declare class TextEncoder { + constructor(encoding?: TextEncoder$availableEncodings): void; + encode(buffer: string, options?: { stream: bool, ... }): Uint8Array; + encoding: TextEncoder$availableEncodings; +} + +type TextDecoder$availableEncodings = + | '866' + | 'ansi_x3.4-1968' + | 'arabic' + | 'ascii' + | 'asmo-708' + | 'big5-hkscs' + | 'big5' + | 'chinese' + | 'cn-big5' + | 'cp1250' + | 'cp1251' + | 'cp1252' + | 'cp1253' + | 'cp1254' + | 'cp1255' + | 'cp1256' + | 'cp1257' + | 'cp1258' + | 'cp819' + | 'cp866' + | 'csbig5' + | 'cseuckr' + | 'cseucpkdfmtjapanese' + | 'csgb2312' + | 'csibm866' + | 'csiso2022jp' + | 'csiso2022kr' + | 'csiso58gb231280' + | 'csiso88596e' + | 'csiso88596i' + | 'csiso88598e' + | 'csiso88598i' + | 'csisolatin1' + | 'csisolatin2' + | 'csisolatin3' + | 'csisolatin4' + | 'csisolatin5' + | 'csisolatin6' + | 'csisolatin9' + | 'csisolatinarabic' + | 'csisolatincyrillic' + | 'csisolatingreek' + | 'csisolatinhebrew' + | 'cskoi8r' + | 'csksc56011987' + | 'csmacintosh' + | 'csshiftjis' + | 'cyrillic' + | 'dos-874' + | 'ecma-114' + | 'ecma-118' + | 'elot_928' + | 'euc-jp' + | 'euc-kr' + | 'gb_2312-80' + | 'gb_2312' + | 'gb18030' + | 'gb2312' + | 'gbk' + | 'greek' + | 'greek8' + | 'hebrew' + | 'hz-gb-2312' + | 'ibm819' + | 'ibm866' + | 'iso_8859-1:1987' + | 'iso_8859-1' + | 'iso_8859-2:1987' + | 'iso_8859-2' + | 'iso_8859-3:1988' + | 'iso_8859-3' + | 'iso_8859-4:1988' + | 'iso_8859-4' + | 'iso_8859-5:1988' + | 'iso_8859-5' + | 'iso_8859-6:1987' + | 'iso_8859-6' + | 'iso_8859-7:1987' + | 'iso_8859-7' + | 'iso_8859-8:1988' + | 'iso_8859-8' + | 'iso_8859-9:1989' + | 'iso_8859-9' + | 'iso-2022-cn-ext' + | 'iso-2022-cn' + | 'iso-2022-jp' + | 'iso-2022-kr' + | 'iso-8859-1' + | 'iso-8859-10' + | 'iso-8859-11' + | 'iso-8859-13' + | 'iso-8859-14' + | 'iso-8859-15' + | 'iso-8859-16' + | 'iso-8859-2' + | 'iso-8859-3' + | 'iso-8859-4' + | 'iso-8859-5' + | 'iso-8859-6-e' + | 'iso-8859-6-i' + | 'iso-8859-6' + | 'iso-8859-7' + | 'iso-8859-8-e' + | 'iso-8859-8-i' + | 'iso-8859-8' + | 'iso-8859-9' + | 'iso-ir-100' + | 'iso-ir-101' + | 'iso-ir-109' + | 'iso-ir-110' + | 'iso-ir-126' + | 'iso-ir-127' + | 'iso-ir-138' + | 'iso-ir-144' + | 'iso-ir-148' + | 'iso-ir-149' + | 'iso-ir-157' + | 'iso-ir-58' + | 'iso8859-1' + | 'iso8859-10' + | 'iso8859-11' + | 'iso8859-13' + | 'iso8859-14' + | 'iso8859-15' + | 'iso8859-2' + | 'iso8859-3' + | 'iso8859-4' + | 'iso8859-6' + | 'iso8859-7' + | 'iso8859-8' + | 'iso8859-9' + | 'iso88591' + | 'iso885910' + | 'iso885911' + | 'iso885913' + | 'iso885914' + | 'iso885915' + | 'iso88592' + | 'iso88593' + | 'iso88594' + | 'iso88595' + | 'iso88596' + | 'iso88597' + | 'iso88598' + | 'iso88599' + | 'koi' + | 'koi8_r' + | 'koi8-r' + | 'koi8-u' + | 'koi8' + | 'korean' + | 'ks_c_5601-1987' + | 'ks_c_5601-1989' + | 'ksc_5601' + | 'ksc5601' + | 'l1' + | 'l2' + | 'l3' + | 'l4' + | 'l5' + | 'l6' + | 'l9' + | 'latin1' + | 'latin2' + | 'latin3' + | 'latin4' + | 'latin5' + | 'latin6' + | 'latin9' + | 'logical' + | 'mac' + | 'macintosh' + | 'ms_kanji' + | 'shift_jis' + | 'shift-jis' + | 'sjis' + | 'sun_eu_greek' + | 'tis-620' + | 'unicode-1-1-utf-8' + | 'us-ascii' + | 'utf-16' + | 'utf-16be' + | 'utf-16le' + | 'utf-8' + | 'utf8' + | 'visual' + | 'windows-1250' + | 'windows-1251' + | 'windows-1252' + | 'windows-1253' + | 'windows-1254' + | 'windows-1255' + | 'windows-1256' + | 'windows-1257' + | 'windows-1258' + | 'windows-31j' + | 'windows-874' + | 'windows-949' + | 'x-cp1250' + | 'x-cp1251' + | 'x-cp1252' + | 'x-cp1253' + | 'x-cp1254' + | 'x-cp1255' + | 'x-cp1256' + | 'x-cp1257' + | 'x-cp1258' + | 'x-euc-jp' + | 'x-gbk' + | 'x-mac-cyrillic' + | 'x-mac-roman' + | 'x-mac-ukrainian' + | 'x-sjis' + | 'x-user-defined' + | 'x-x-big5'; + + +declare class TextDecoder { + constructor(encoding?: TextDecoder$availableEncodings, options?: { fatal: bool, ... }): void; + encoding: TextDecoder$availableEncodings; + fatal: bool; + ignoreBOM: bool; + decode(buffer?: ArrayBuffer | $ArrayBufferView, options?: { stream: bool, ... }): string; +} + +declare class MessagePort extends EventTarget { + postMessage(message: any, transfer?: Iterable): void; + start(): void; + close(): void; + + onmessage: null | (ev: MessageEvent) => mixed; + onmessageerror: null | (ev: MessageEvent) => mixed; +} + +declare class MessageChannel { + port1: MessagePort; + port2: MessagePort; +} + +declare class VRDisplay extends EventTarget { + capabilities: VRDisplayCapabilities; + depthFar: number; + depthNear: number; + displayId: number; + displayName: string; + isPresenting: boolean; + stageParameters: null | VRStageParameters; + + cancelAnimationFrame(number): void; + exitPresent(): Promise; + getEyeParameters(VREye): VREyeParameters; + getFrameData(VRFrameData): boolean; + getLayers(): VRLayerInit[]; + requestAnimationFrame(cb: (number) => mixed): number; + requestPresent(VRLayerInit[]): Promise; + submitFrame(): void; +} + +type VRSource = HTMLCanvasElement; + +type VRLayerInit = { + leftBounds?: number[], + rightBounds?: number[], + source?: null | VRSource, + ... +}; + +type VRDisplayCapabilities = { + canPresent: boolean, + hasExternalDisplay: boolean, + hasPosition: boolean, + maxLayers: number, + ... +}; + +type VREye = 'left' | 'right'; + +type VRPose = { + angularAcceleration?: Float32Array, + angularVelocity?: Float32Array, + linearAcceleration?: Float32Array, + linearVelocity?: Float32Array, + orientation?: Float32Array, + position?: Float32Array, + ... +}; + +declare class VRFrameData { + leftProjectionMatrix: Float32Array; + leftViewMatrix: Float32Array; + pose: VRPose; + rightProjectionMatrix: Float32Array; + rightViewMatrix: Float32Array; + timestamp: number; +} + +type VREyeParameters = { + offset: Float32Array, + renderWidth: number, + renderHeight: number, + ... +}; + +type VRStageParameters = { + sittingToStandingTransform: Float32Array, + sizeX: number, + sizeZ: number, + ... +}; + +type VRDisplayEventReason = 'mounted' | 'navigation' | 'requested' | 'unmounted'; + +type VRDisplayEventInit = { + display: VRDisplay, + reason: VRDisplayEventReason, + ... +}; + +declare class VRDisplayEvent extends Event { + constructor(type: string, eventInitDict: VRDisplayEventInit): void; + display: VRDisplay; + reason?: VRDisplayEventReason; +} + +declare class MediaQueryListEvent { + matches: boolean; + media: string; +} + +declare type MediaQueryListListener = MediaQueryListEvent => void; + +declare class MediaQueryList extends EventTarget { + matches: boolean; + media: string; + addListener: MediaQueryListListener => void; + removeListener: MediaQueryListListener => void; + onchange: MediaQueryListListener; +} + +declare var matchMedia: string => MediaQueryList; + +// https://w3c.github.io/webappsec-credential-management/#idl-index +declare type CredMgmtCredentialRequestOptions = { + mediation: 'silent' | 'optional' | 'required', + signal: AbortSignal, + ... +} + +declare type CredMgmtCredentialCreationOptions = { signal: AbortSignal, ... } + +declare interface CredMgmtCredential { + id: string; + type: string; +} + +declare interface CredMgmtPasswordCredential extends CredMgmtCredential { + password: string; +} + +declare interface CredMgmtCredentialsContainer { + get(option?: CredMgmtCredentialRequestOptions): Promise; + store(credential: CredMgmtCredential): Promise; + create( + creationOption?: CredMgmtCredentialCreationOptions, + ): Promise; + preventSilentAccess(): Promise; +} + +type SpeechSynthesisErrorCode = + | "canceled" + | "interrupted" + | "audio-busy" + | "audio-hardware" + | "network" + | "synthesis-unavailable" + | "synthesis-failed" + | "language-unavailable" + | "voice-unavailable" + | "text-too-long" + | "invalid-argument" + | "not-allowed"; + +declare class SpeechSynthesis extends EventTarget { + +pending: boolean; + +speaking: boolean; + +paused: boolean; + + onvoiceschanged: ?((ev: Event) => mixed); + + speak(utterance: SpeechSynthesisUtterance): void; + cancel(): void; + pause(): void; + resume(): void; + getVoices(): Array; +} + +declare var speechSynthesis: SpeechSynthesis; + +declare class SpeechSynthesisUtterance extends EventTarget { + constructor(text?: string): void; + + text: string; + lang: string; + voice: SpeechSynthesisVoice | null; + volume: number; + rate: number; + pitch: number; + + onstart: ?((ev: SpeechSynthesisEvent) => mixed); + onend: ?((ev: SpeechSynthesisEvent) => mixed); + onerror: ?((ev: SpeechSynthesisErrorEvent) => mixed); + onpause: ?((ev: SpeechSynthesisEvent) => mixed); + onresume: ?((ev: SpeechSynthesisEvent) => mixed); + onmark: ?((ev: SpeechSynthesisEvent) => mixed); + onboundary: ?((ev: SpeechSynthesisEvent) => mixed); +} + +type SpeechSynthesisEvent$Init = Event$Init & { + utterance: SpeechSynthesisUtterance; + charIndex?: number; + charLength?: number; + elapsedTime?: number; + name?: string; + ... +} + +declare class SpeechSynthesisEvent extends Event { + constructor(type: string, eventInitDict?: SpeechSynthesisEvent$Init): void; + + +utterance: SpeechSynthesisUtterance; + charIndex: number; + charLength: number; + elapsedTime: number; + name: string; +} + +type SpeechSynthesisErrorEvent$Init = SpeechSynthesisEvent$Init & { + error: SpeechSynthesisErrorCode; + ... +} + +declare class SpeechSynthesisErrorEvent extends SpeechSynthesisEvent { + constructor(type: string, eventInitDict?: SpeechSynthesisErrorEvent$Init): void; + +error: SpeechSynthesisErrorCode; +} + +declare class SpeechSynthesisVoice { + +voiceURI: string; + +name: string; + +lang: string; + +localService: boolean; + +default: boolean; +} diff --git a/newIDE/app/flow-libs/cssom.js b/newIDE/app/flow-libs/cssom.js new file mode 100644 index 0000000000..556b94d1f0 --- /dev/null +++ b/newIDE/app/flow-libs/cssom.js @@ -0,0 +1,570 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +declare class StyleSheet { + disabled: boolean; + +href: string; + +media: MediaList; + +ownerNode: Node; + +parentStyleSheet: ?StyleSheet; + +title: string; + +type: string; +} + +declare class StyleSheetList { + @@iterator(): Iterator; + length: number; + [index: number]: StyleSheet; +} + +declare class MediaList { + @@iterator(): Iterator; + mediaText: string; + length: number; + item(index: number): ?string; + deleteMedium(oldMedium: string): void; + appendMedium(newMedium: string): void; + [index: number]: string; +} + +declare class CSSStyleSheet extends StyleSheet { + +cssRules: CSSRuleList; + +ownerRule: ?CSSRule; + deleteRule(index: number): void; + insertRule(rule: string, index: number): number; +} + +declare class CSSGroupingRule extends CSSRule { + +cssRules: CSSRuleList; + deleteRule(index: number): void; + insertRule(rule: string, index: number): number; +} + +declare class CSSConditionRule extends CSSGroupingRule { + conditionText: string; +} + +declare class CSSMediaRule extends CSSConditionRule { + +media: MediaList; +} + +declare class CSSStyleRule extends CSSRule { + selectorText: string; + +style: CSSStyleDeclaration; +} + +declare class CSSRule { + cssText: string; + +parentRule: ?CSSRule; + +parentStyleSheet: ?CSSStyleSheet; + +type: number; + static STYLE_RULE: number; + static MEDIA_RULE: number; + static FONT_FACE_RULE: number; + static PAGE_RULE: number; + static IMPORT_RULE: number; + static CHARSET_RULE: number; + static UNKNOWN_RULE: number; + static KEYFRAMES_RULE: number; + static KEYFRAME_RULE: number; + static NAMESPACE_RULE: number; + static COUNTER_STYLE_RULE: number; + static SUPPORTS_RULE: number; + static DOCUMENT_RULE: number; + static FONT_FEATURE_VALUES_RULE: number; + static VIEWPORT_RULE: number; + static REGION_STYLE_RULE: number; +} + +declare class CSSKeyframeRule extends CSSRule { + keyText: string; + +style: CSSStyleDeclaration; +} + +declare class CSSKeyframesRule extends CSSRule { + name: string; + +cssRules: CSSRuleList; + appendRule(rule: string): void; + deleteRule(select: string): void; + findRule(select: string): CSSKeyframeRule | null; +} + +declare class CSSRuleList { + @@iterator(): Iterator; + length: number; + item(index: number): ?CSSRule; + [index: number]: CSSRule; +} + +declare class CSSStyleDeclaration { + @@iterator(): Iterator; + /* DOM CSS Properties */ + alignContent: string; + alignItems: string; + alignSelf: string; + all: string; + animation: string; + animationDelay: string; + animationDirection: string; + animationDuration: string; + animationFillMode: string; + animationIterationCount: string; + animationName: string; + animationPlayState: string; + animationTimingFunction: string; + backdropFilter: string; + webkitBackdropFilter: string; + backfaceVisibility: string; + background: string; + backgroundAttachment: string; + backgroundBlendMode: string; + backgroundClip: string; + backgroundColor: string; + backgroundImage: string; + backgroundOrigin: string; + backgroundPosition: string; + backgroundPositionX: string; + backgroundPositionY: string; + backgroundRepeat: string; + backgroundSize: string; + blockSize: string; + border: string; + borderBlockEnd: string; + borderBlockEndColor: string; + borderBlockEndStyle: string; + borderBlockEndWidth: string; + borderBlockStart: string; + borderBlockStartColor: string; + borderBlockStartStyle: string; + borderBlockStartWidth: string; + borderBottom: string; + borderBottomColor: string; + borderBottomLeftRadius: string; + borderBottomRightRadius: string; + borderBottomStyle: string; + borderBottomWidth: string; + borderCollapse: string; + borderColor: string; + borderImage: string; + borderImageOutset: string; + borderImageRepeat: string; + borderImageSlice: string; + borderImageSource: string; + borderImageWidth: string; + borderInlineEnd: string; + borderInlineEndColor: string; + borderInlineEndStyle: string; + borderInlineEndWidth: string; + borderInlineStart: string; + borderInlineStartColor: string; + borderInlineStartStyle: string; + borderInlineStartWidth: string; + borderLeft: string; + borderLeftColor: string; + borderLeftStyle: string; + borderLeftWidth: string; + borderRadius: string; + borderRight: string; + borderRightColor: string; + borderRightStyle: string; + borderRightWidth: string; + borderSpacing: string; + borderStyle: string; + borderTop: string; + borderTopColor: string; + borderTopLeftRadius: string; + borderTopRightRadius: string; + borderTopStyle: string; + borderTopWidth: string; + borderWidth: string; + bottom: string; + boxDecorationBreak: string; + boxShadow: string; + boxSizing: string; + breakAfter: string; + breakBefore: string; + breakInside: string; + captionSide: string; + clear: string; + clip: string; + clipPath: string; + color: string; + columns: string; + columnCount: string; + columnFill: string; + columnGap: string; + columnRule: string; + columnRuleColor: string; + columnRuleStyle: string; + columnRuleWidth: string; + columnSpan: string; + columnWidth: string; + contain: string; + content: string; + counterIncrement: string; + counterReset: string; + cursor: string; + direction: string; + display: string; + emptyCells: string; + filter: string; + flex: string; + flexBasis: string; + flexDirection: string; + flexFlow: string; + flexGrow: string; + flexShrink: string; + flexWrap: string; + float: string; + font: string; + fontFamily: string; + fontFeatureSettings: string; + fontKerning: string; + fontLanguageOverride: string; + fontSize: string; + fontSizeAdjust: string; + fontStretch: string; + fontStyle: string; + fontSynthesis: string; + fontVariant: string; + fontVariantAlternates: string; + fontVariantCaps: string; + fontVariantEastAsian: string; + fontVariantLigatures: string; + fontVariantNumeric: string; + fontVariantPosition: string; + fontWeight: string; + grad: string; + grid: string; + gridArea: string; + gridAutoColumns: string; + gridAutoFlow: string; + gridAutoPosition: string; + gridAutoRows: string; + gridColumn: string; + gridColumnStart: string; + gridColumnEnd: string; + gridRow: string; + gridRowStart: string; + gridRowEnd: string; + gridTemplate: string; + gridTemplateAreas: string; + gridTemplateRows: string; + gridTemplateColumns: string; + height: string; + hyphens: string; + imageRendering: string; + imageResolution: string; + imageOrientation: string; + imeMode: string; + inherit: string; + initial: string; + inlineSize: string; + isolation: string; + justifyContent: string; + left: string; + letterSpacing: string; + lineBreak: string; + lineHeight: string; + listStyle: string; + listStyleImage: string; + listStylePosition: string; + listStyleType: string; + margin: string; + marginBlockEnd: string; + marginBlockStart: string; + marginBottom: string; + marginInlineEnd: string; + marginInlineStart: string; + marginLeft: string; + marginRight: string; + marginTop: string; + marks: string; + mask: string; + maskType: string; + maxBlockSize: string; + maxHeight: string; + maxInlineSize: string; + maxWidth: string; + minBlockSize: string; + minHeight: string; + minInlineSize: string; + minWidth: string; + mixBlendMode: string; + mozTransform: string; + mozTransformOrigin: string; + mozTransitionDelay: string; + mozTransitionDuration: string; + mozTransitionProperty: string; + mozTransitionTimingFunction: string; + objectFit: string; + objectPosition: string; + offsetBlockEnd: string; + offsetBlockStart: string; + offsetInlineEnd: string; + offsetInlineStart: string; + opacity: string; + order: string; + orphans: string; + outline: string; + outlineColor: string; + outlineOffset: string; + outlineStyle: string; + outlineWidth: string; + overflow: string; + overflowWrap: string; + overflowX: string; + overflowY: string; + padding: string; + paddingBlockEnd: string; + paddingBlockStart: string; + paddingBottom: string; + paddingInlineEnd: string; + paddingInlineStart: string; + paddingLeft: string; + paddingRight: string; + paddingTop: string; + pageBreakAfter: string; + pageBreakBefore: string; + pageBreakInside: string; + perspective: string; + perspectiveOrigin: string; + pointerEvents: string; + position: string; + quotes: string; + rad: string; + resize: string; + right: string; + rubyAlign: string; + rubyMerge: string; + rubyPosition: string; + scrollBehavior: string; + scrollSnapCoordinate: string; + scrollSnapDestination: string; + scrollSnapPointsX: string; + scrollSnapPointsY: string; + scrollSnapType: string; + shapeImageThreshold: string; + shapeMargin: string; + shapeOutside: string; + tableLayout: string; + tabSize: string; + textAlign: string; + textAlignLast: string; + textCombineUpright: string; + textDecoration: string; + textDecorationColor: string; + textDecorationLine: string; + textDecorationStyle: string; + textIndent: string; + textOrientation: string; + textOverflow: string; + textRendering: string; + textShadow: string; + textTransform: string; + textUnderlinePosition: string; + top: string; + touchAction: string; + transform: string; + transformOrigin: string; + transformStyle: string; + transition: string; + transitionDelay: string; + transitionDuration: string; + transitionProperty: string; + transitionTimingFunction: string; + turn: string; + unicodeBidi: string; + unicodeRange: string; + userSelect: string; + verticalAlign: string; + visibility: string; + webkitOverflowScrolling: string; + webkitTransform: string; + webkitTransformOrigin: string; + webkitTransitionDelay: string; + webkitTransitionDuration: string; + webkitTransitionProperty: string; + webkitTransitionTimingFunction: string; + whiteSpace: string; + widows: string; + width: string; + willChange: string; + wordBreak: string; + wordSpacing: string; + wordWrap: string; + writingMode: string; + zIndex: string; + + cssFloat: string; + cssText: string; + getPropertyPriority(property: string): string; + getPropertyValue(property:string): string; + item(index: number): string; + [index: number]: string; + length: number; + parentRule: CSSRule; + removeProperty(property: string): string; + setProperty(property: string, value: ?string, priority: ?string): void; + setPropertyPriority(property: string, priority: string): void; +} + +declare class TransitionEvent extends Event { + elapsedTime: number; // readonly + pseudoElement: string; // readonly + propertyName: string; // readonly +} + +type AnimationPlayState = 'idle' | 'running' | 'paused' | 'finished' +type AnimationReplaceState = 'active' | 'removed' | 'persisted' +type FillMode = 'none' | 'forwards' | 'backwards' | 'both' | 'auto' +type PlaybackDirection = 'normal' | 'reverse' | 'alternate' | 'alternate-reverse' +type IterationCompositeOperation = 'replace' | 'accumulate' +type CompositeOperation = 'replace' | 'add' | 'accumulate' +type CompositeOperationOrAuto = CompositeOperation | 'auto' + +declare class AnimationTimeline { + +currentTime: number | null; +} + +type DocumentTimelineOptions = { + originTime?: DOMHighResTimeStamp; + ... +} + +declare class DocumentTimeline extends AnimationTimeline { + constructor(options?: DocumentTimelineOptions): void; +} + +type EffectTiming = { + delay: number; + endDelay: number; + fill: FillMode; + iterationStart: number; + iterations: number; + duration: number | string; + direction: PlaybackDirection; + easing: string; + ... +} + +type OptionalEffectTiming = $Rest + +type ComputedEffectTiming = EffectTiming & { + endTime: number; + activeDuration: number; + localTime: number | null; + progress: number | null; + currentIteration: number | null; + ... +} + +declare class AnimationEffect { + getTiming(): EffectTiming; + getComputedTiming(): ComputedEffectTiming; + updateTiming(timing?: OptionalEffectTiming): void; +} + +type Keyframe = { + composite?: CompositeOperationOrAuto; + easing?: string; + offset?: number | null; + [property: string]: string | number | null | void; + ... +} + +type ComputedKeyframe = { + composite: CompositeOperationOrAuto; + computedOffset: number; + easing: string; + offset: number | null; + [property: string]: string | number | null | void; + ... +} + +type PropertyIndexedKeyframes = { + composite?: CompositeOperationOrAuto | CompositeOperationOrAuto[]; + easing?: string | string[]; + offset?: number | (number | null)[]; + [property: string]: string | string[] | number | null | (number | null)[] | void; + ... +} + +type KeyframeEffectOptions = $Rest & { + iterationComposite?: IterationCompositeOperation; + composite?: CompositeOperation; + ... +} + +declare class KeyframeEffect extends AnimationEffect { + constructor( + target: Element | null, + keyframes: Keyframe[] | PropertyIndexedKeyframes | null, + options?: number | KeyframeEffectOptions, + ): void; + constructor(source: KeyframeEffect): void; + + target: Element | null; + iterationComposite: IterationCompositeOperation; + composite: CompositeOperation; + getKeyframes(): ComputedKeyframe[]; + setKeyframes(keyframes: Keyframe[] | PropertyIndexedKeyframes | null): void; +} + +declare class Animation extends EventTarget { + constructor(effect?: AnimationEffect | null, timeline?: AnimationTimeline | null): void; + + id: string; + effect: AnimationEffect | null; + timeline: AnimationTimeline | null; + startTime: number | null; + currentTime: number | null; + playbackRate: number; + +playState: AnimationPlayState; + +replaceState: AnimationReplaceState; + +pending: boolean; + +ready: Promise; + +finished: Promise; + onfinish: ?((ev: AnimationPlaybackEvent) => mixed); + oncancel: ?((ev: AnimationPlaybackEvent) => mixed); + onremove: ?((ev: AnimationPlaybackEvent) => mixed); + cancel(): void; + finish(): void; + play(): void; + pause(): void; + updatePlaybackRate(playbackRate: number): void; + reverse(): void; + persist(): void; + commitStyles(): void; +} + +type KeyframeAnimationOptions = KeyframeEffectOptions & { + id?: string; + ... +} + +type GetAnimationsOptions = { + subtree?: boolean; + ... +} + +interface Animatable { + animate(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions): Animation; + getAnimations(options?: GetAnimationsOptions): Animation[]; +} + +type AnimationPlaybackEvent$Init = Event$Init & { + currentTime?: number | null; + timelineTime?: number | null; + ... +} + +declare class AnimationPlaybackEvent extends Event { + constructor(type: string, animationEventInitDict?: AnimationPlaybackEvent$Init): void; + +currentTime: number | null; + +timelineTime: number | null; +} diff --git a/newIDE/app/flow-libs/dom.js b/newIDE/app/flow-libs/dom.js new file mode 100644 index 0000000000..b620a873ad --- /dev/null +++ b/newIDE/app/flow-libs/dom.js @@ -0,0 +1,4071 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* Files */ + +declare class Blob { + constructor(blobParts?: Array, options?: { + type?: string, + endings?: string, + ... + }): void; + isClosed: bool; + size: number; + type: string; + close(): void; + slice(start?: number, end?: number, contentType?: string): Blob; + arrayBuffer(): Promise; + text(): Promise, + stream(): ReadableStream, +} + +declare class FileReader extends EventTarget { + +EMPTY: 0; + +LOADING: 1; + +DONE: 2; + +error: null | DOMError; + +readyState: 0 | 1 | 2; + +result: null | string | ArrayBuffer; + abort(): void; + onabort: null | (ev: ProgressEvent) => any; + onerror: null | (ev: ProgressEvent) => any; + onload: null | (ev: ProgressEvent) => any; + onloadend: null | (ev: ProgressEvent) => any; + onloadstart: null | (ev: ProgressEvent) => any; + onprogress: null | (ev: ProgressEvent) => any; + readAsArrayBuffer(blob: Blob): void; + readAsBinaryString(blob: Blob): void; + readAsDataURL(blob: Blob): void; + readAsText(blob: Blob, encoding?: string): void; +} + +declare type FilePropertyBag = { + type?: string, + lastModified?: number, + ... +}; +declare class File extends Blob { + constructor( + fileBits: $ReadOnlyArray, + filename: string, + options?: FilePropertyBag, + ): void; + lastModified: number; + name: string; +} + +declare class FileList { + @@iterator(): Iterator; + length: number; + item(index: number): File; + [index: number]: File; +} + +/* DataTransfer */ + +declare class DataTransfer { + clearData(format?: string): void; + getData(format: string): string; + setData(format: string, data: string): void; + setDragImage(image: Element, x: number, y: number): void; + dropEffect: string; + effectAllowed: string; + files: FileList; // readonly + items: DataTransferItemList; // readonly + types: Array; // readonly +} + +declare class DataTransferItemList { + @@iterator(): Iterator; + length: number; // readonly + [index: number]: DataTransferItem; + add(data: string, type: string): ?DataTransferItem; + add(data: File): ?DataTransferItem; + remove(index: number): void; + clear(): void; +}; + +declare class DataTransferItem { + kind: string; // readonly + type: string; // readonly + getAsString(_callback: ?(data: string) => mixed): void; + getAsFile(): ?File; + /* + * This is not supported by all browsers, please have a fallback plan for it. + * For more information, please checkout + * https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/webkitGetAsEntry + */ + webkitGetAsEntry(): void | () => any; +}; + +/* DOM */ + +declare type DOMStringMap = { [key:string]: string, ... } + +declare class DOMError { + name: string; +} + +declare type ElementDefinitionOptions = { extends?: string, ... } + +declare interface CustomElementRegistry { + define(name: string, ctor: Class, options?: ElementDefinitionOptions): void; + get(name: string): any; + whenDefined(name: string): Promise; +} + +declare interface ShadowRoot extends DocumentFragment { + host: Element; + innerHTML: string; +} + +declare type ShadowRootMode = 'open'|'closed'; + +declare type ShadowRootInit = { + delegatesFocus?: boolean, + mode: ShadowRootMode, + ... +} + +declare type ScrollToOptions = { + top?: number; + left?: number; + behavior?: 'auto' | 'smooth'; + ... +} + +type EventHandler = (event: Event) => mixed +type EventListener = { handleEvent: EventHandler, ... } | EventHandler +type MouseEventHandler = (event: MouseEvent) => mixed +type MouseEventListener = { handleEvent: MouseEventHandler, ... } | MouseEventHandler +type FocusEventHandler = (event: FocusEvent) => mixed +type FocusEventListener = { handleEvent: FocusEventHandler, ... } | FocusEventHandler +type KeyboardEventHandler = (event: KeyboardEvent) => mixed +type KeyboardEventListener = { handleEvent: KeyboardEventHandler, ... } | KeyboardEventHandler +type InputEventHandler = (event: InputEvent) => mixed +type InputEventListener = { handleEvent: InputEventHandler, ... } | InputEventHandler +type TouchEventHandler = (event: TouchEvent) => mixed +type TouchEventListener = { handleEvent: TouchEventHandler, ... } | TouchEventHandler +type WheelEventHandler = (event: WheelEvent) => mixed +type WheelEventListener = { handleEvent: WheelEventHandler, ... } | WheelEventHandler +type AbortProgressEventHandler = (event: ProgressEvent) => mixed +type AbortProgressEventListener = { handleEvent: AbortProgressEventHandler, ... } | AbortProgressEventHandler +type ProgressEventHandler = (event: ProgressEvent) => mixed +type ProgressEventListener = { handleEvent: ProgressEventHandler, ... } | ProgressEventHandler +type DragEventHandler = (event: DragEvent) => mixed +type DragEventListener = { handleEvent: DragEventHandler, ... } | DragEventHandler +type PointerEventHandler = (event: PointerEvent) => mixed +type PointerEventListener = { handleEvent: PointerEventHandler, ... } | PointerEventHandler +type AnimationEventHandler = (event: AnimationEvent) => mixed +type AnimationEventListener = { handleEvent: AnimationEventHandler, ... } | AnimationEventHandler +type ClipboardEventHandler = (event: ClipboardEvent) => mixed +type ClipboardEventListener = { handleEvent: ClipboardEventHandler, ... } | ClipboardEventHandler +type TransitionEventHandler = (event: TransitionEvent) => mixed +type TransitionEventListener = { handleEvent: TransitionEventHandler, ... } | TransitionEventHandler +type MessageEventHandler = (event: MessageEvent) => mixed +type MessageEventListener = { handleEvent: MessageEventHandler, ... } | MessageEventHandler +type BeforeUnloadEventHandler = (event: BeforeUnloadEvent) => mixed +type BeforeUnloadEventListener = { handleEvent: BeforeUnloadEventHandler, ... } | BeforeUnloadEventHandler +type StorageEventHandler = (event: StorageEvent) => mixed +type StorageEventListener = { handleEvent: StorageEventHandler, ... } | StorageEventHandler + +type MediaKeySessionType = 'temporary' | 'persistent-license'; +type MediaKeyStatus = 'usable' | 'expired' | 'released' | 'output-restricted' | 'output-downscaled' | 'status-pending' | 'internal-error'; +type MouseEventTypes = 'contextmenu' | 'mousedown' | 'mouseenter' | 'mouseleave' | 'mousemove' | 'mouseout' | 'mouseover' | 'mouseup' | 'click' | 'dblclick'; +type FocusEventTypes = 'blur' | 'focus' | 'focusin' | 'focusout'; +type KeyboardEventTypes = 'keydown' | 'keyup' | 'keypress'; +type InputEventTypes = 'input' | 'beforeinput' +type TouchEventTypes = 'touchstart' | 'touchmove' | 'touchend' | 'touchcancel'; +type WheelEventTypes = 'wheel'; +type AbortProgressEventTypes = 'abort'; +type ProgressEventTypes = 'abort' | 'error' | 'load' | 'loadend' | 'loadstart' | 'progress' | 'timeout'; +type DragEventTypes = 'drag' | 'dragend' | 'dragenter' | 'dragexit' | 'dragleave' | 'dragover' | 'dragstart' | 'drop'; +type PointerEventTypes = 'pointerover' | 'pointerenter' | 'pointerdown' | 'pointermove' | 'pointerup' | 'pointercancel' | 'pointerout' | 'pointerleave' | 'gotpointercapture' | 'lostpointercapture'; +type AnimationEventTypes = 'animationstart' | 'animationend' | 'animationiteration'; +type ClipboardEventTypes = 'clipboardchange' | 'cut' | 'copy' | 'paste'; +type TransitionEventTypes = 'transitionrun' | 'transitionstart' | 'transitionend' | 'transitioncancel'; +type MessageEventTypes = string; +type BeforeUnloadEventTypes = 'beforeunload'; +type StorageEventTypes = 'storage'; + +type EventListenerOptionsOrUseCapture = boolean | { + capture?: boolean, + once?: boolean, + passive?: boolean, + ... +}; + +declare class EventTarget { + addEventListener(type: MouseEventTypes, listener: MouseEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: FocusEventTypes, listener: FocusEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: KeyboardEventTypes, listener: KeyboardEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: InputEventTypes, listener: InputEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: TouchEventTypes, listener: TouchEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: WheelEventTypes, listener: WheelEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: AbortProgressEventTypes, listener: AbortProgressEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: ProgressEventTypes, listener: ProgressEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: DragEventTypes, listener: DragEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: PointerEventTypes, listener: PointerEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: AnimationEventTypes, listener: AnimationEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: ClipboardEventTypes, listener: ClipboardEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: TransitionEventTypes, listener: TransitionEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: MessageEventTypes, listener: MessageEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: BeforeUnloadEventTypes, listener: BeforeUnloadEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: StorageEventTypes, listener: StorageEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + addEventListener(type: string, listener: EventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + + removeEventListener(type: MouseEventTypes, listener: MouseEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: FocusEventTypes, listener: FocusEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: KeyboardEventTypes, listener: KeyboardEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: InputEventTypes, listener: InputEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: TouchEventTypes, listener: TouchEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: WheelEventTypes, listener: WheelEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: AbortProgressEventTypes, listener: AbortProgressEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: ProgressEventTypes, listener: ProgressEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: DragEventTypes, listener: DragEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: PointerEventTypes, listener: PointerEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: AnimationEventTypes, listener: AnimationEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: ClipboardEventTypes, listener: ClipboardEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: TransitionEventTypes, listener: TransitionEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: MessageEventTypes, listener: MessageEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: BeforeUnloadEventTypes, listener: BeforeUnloadEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: StorageEventTypes, listener: StorageEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + removeEventListener(type: string, listener: EventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void; + + attachEvent?: (type: MouseEventTypes, listener: MouseEventListener) => void; + attachEvent?: (type: FocusEventTypes, listener: FocusEventListener) => void; + attachEvent?: (type: KeyboardEventTypes, listener: KeyboardEventListener) => void; + attachEvent?: (type: InputEventTypes, listener: InputEventListener) => void; + attachEvent?: (type: TouchEventTypes, listener: TouchEventListener) => void; + attachEvent?: (type: WheelEventTypes, listener: WheelEventListener) => void; + attachEvent?: (type: AbortProgressEventTypes, listener: AbortProgressEventListener) => void; + attachEvent?: (type: ProgressEventTypes, listener: ProgressEventListener) => void; + attachEvent?: (type: DragEventTypes, listener: DragEventListener) => void; + attachEvent?: (type: PointerEventTypes, listener: PointerEventListener) => void; + attachEvent?: (type: AnimationEventTypes, listener: AnimationEventListener) => void; + attachEvent?: (type: ClipboardEventTypes, listener: ClipboardEventListener) => void; + attachEvent?: (type: TransitionEventTypes, listener: TransitionEventListener) => void; + attachEvent?: (type: MessageEventTypes, listener: MessageEventListener) => void; + attachEvent?: (type: BeforeUnloadEventTypes, listener: BeforeUnloadEventListener) => void; + attachEvent?: (type: StorageEventTypes, listener: StorageEventListener) => void; + attachEvent?: (type: string, listener: EventListener) => void; + + detachEvent?: (type: MouseEventTypes, listener: MouseEventListener) => void; + detachEvent?: (type: FocusEventTypes, listener: FocusEventListener) => void; + detachEvent?: (type: KeyboardEventTypes, listener: KeyboardEventListener) => void; + detachEvent?: (type: InputEventTypes, listener: InputEventListener) => void; + detachEvent?: (type: TouchEventTypes, listener: TouchEventListener) => void; + detachEvent?: (type: WheelEventTypes, listener: WheelEventListener) => void; + detachEvent?: (type: AbortProgressEventTypes, listener: AbortProgressEventListener) => void; + detachEvent?: (type: ProgressEventTypes, listener: ProgressEventListener) => void; + detachEvent?: (type: DragEventTypes, listener: DragEventListener) => void; + detachEvent?: (type: PointerEventTypes, listener: PointerEventListener) => void; + detachEvent?: (type: AnimationEventTypes, listener: AnimationEventListener) => void; + detachEvent?: (type: ClipboardEventTypes, listener: ClipboardEventListener) => void; + detachEvent?: (type: TransitionEventTypes, listener: TransitionEventListener) => void; + detachEvent?: (type: MessageEventTypes, listener: MessageEventListener) => void; + detachEvent?: (type: BeforeUnloadEventTypes, listener: BeforeUnloadEventListener) => void; + detachEvent?: (type: StorageEventTypes, listener: StorageEventListener) => void; + detachEvent?: (type: string, listener: EventListener) => void; + + dispatchEvent(evt: Event): boolean; + + // Deprecated + + cancelBubble: boolean; + initEvent(eventTypeArg: string, canBubbleArg: boolean, cancelableArg: boolean): void; +} + +type Event$Init = { + bubbles?: boolean, + cancelable?: boolean, + composed?: boolean, + scoped?: boolean, + ... +} + +declare class Event { + constructor(type: string, eventInitDict?: Event$Init): void; + bubbles: boolean; + cancelable: boolean; + currentTarget: EventTarget; + deepPath?: () => EventTarget[]; + defaultPrevented: boolean; + eventPhase: number; + isTrusted: boolean; + scoped: boolean; + srcElement: Element; + target: EventTarget; + timeStamp: number; + type: string; + preventDefault(): void; + stopImmediatePropagation(): void; + stopPropagation(): void; + AT_TARGET: number; + BUBBLING_PHASE: number; + CAPTURING_PHASE: number; + + // deprecated + initEvent( + type: string, + bubbles: boolean, + cancelable: boolean + ): void; +} + +type CustomEvent$Init = Event$Init & { detail?: any, ... } + +declare class CustomEvent extends Event { + constructor(type: string, eventInitDict?: CustomEvent$Init): void; + detail: any; + + // deprecated + initCustomEvent( + type: string, + bubbles: boolean, + cancelable: boolean, + detail: any + ): CustomEvent; +} + +declare class UIEvent extends Event { + detail: number; + view: any; +} + +type MouseEvent$MouseEventInit = { + screenX?: number, + screenY?: number, + clientX?: number, + clientY?: number, + ctrlKey?: boolean, + shiftKey?: boolean, + altKey?: boolean, + metaKey?: boolean, + button?: number, + buttons?: number, + region?: string | null, + relatedTarget?: EventTarget | null, + ... +}; + +declare class MouseEvent extends UIEvent { + constructor( + typeArg: string, + mouseEventInit?: MouseEvent$MouseEventInit, + ): void; + altKey: boolean; + button: number; + buttons: number; + clientX: number; + clientY: number; + ctrlKey: boolean; + metaKey: boolean; + movementX: number; + movementY: number; + offsetX: number; + offsetY: number; + pageX: number; + pageY: number; + region: string | null; + relatedTarget: EventTarget | null; + screenX: number; + screenY: number; + shiftKey: boolean; + x: number; + y: number; + getModifierState(keyArg: string): boolean; +} + +declare class FocusEvent extends UIEvent { + relatedTarget: ?EventTarget; +} + +declare class WheelEvent extends MouseEvent { + deltaX: number; // readonly + deltaY: number; // readonly + deltaZ: number; // readonly + deltaMode: 0x00 | 0x01 | 0x02; // readonly +} + +declare class DragEvent extends MouseEvent { + dataTransfer: ?DataTransfer; // readonly +} + +type PointerEvent$PointerEventInit = MouseEvent$MouseEventInit & { + pointerId?: number, + width?: number, + height?: number, + pressure?: number, + tangentialPressure?: number, + tiltX?: number, + tiltY?: number, + twist?: number, + pointerType?: string, + isPrimary?: boolean, + ... +}; + +declare class PointerEvent extends MouseEvent { + constructor( + typeArg: string, + pointerEventInit?: PointerEvent$PointerEventInit, + ): void; + pointerId: number; + width: number; + height: number; + pressure: number; + tangentialPressure: number; + tiltX: number; + tiltY: number; + twist: number; + pointerType: string; + isPrimary: boolean; +} + +declare class ProgressEvent extends Event { + lengthComputable: boolean; + loaded: number; + total: number; + + // Deprecated + initProgressEvent( + typeArg: string, + canBubbleArg: boolean, + cancelableArg: boolean, + lengthComputableArg: boolean, + loadedArg: number, + totalArg: number + ): void; +} + +declare class PromiseRejectionEvent extends Event { + promise: Promise; + reason: any; +} + +// used for websockets and postMessage, for example. See: +// https://www.w3.org/TR/2011/WD-websockets-20110419/ +// and +// https://www.w3.org/TR/2008/WD-html5-20080610/comms.html +// and +// https://html.spec.whatwg.org/multipage/comms.html#the-messageevent-interfaces +declare class MessageEvent extends Event { + data: mixed; + origin: string; + lastEventId: string; + source: WindowProxy; +} + +// https://www.w3.org/TR/eventsource/ +declare class EventSource extends EventTarget { + constructor(url: string, configuration?: { withCredentials: boolean, ... }): void; + +CLOSED: 2; + +CONNECTING: 0; + +OPEN: 1; + +readyState: 0 | 1 | 2; + +url: string; + +withCredentials: boolean; + onerror: () => void; + onmessage: MessageEventListener; + onopen: () => void; + close: () => void; +} + +declare class KeyboardEvent extends UIEvent { + altKey: boolean; + code: string; + ctrlKey: boolean; + isComposing: boolean; + key: string; + location: number; + metaKey: boolean; + repeat: boolean; + shiftKey: boolean; + getModifierState(keyArg?: string): boolean; + + // Deprecated + charCode: number; + keyCode: number; + which: number; +} + +declare class InputEvent extends UIEvent { + data: string | null; + isComposing: boolean; +} + +declare class AnimationEvent extends Event { + animationName: string; + elapsedTime: number; + pseudoElement: string; + + // deprecated + + initAnimationEvent: ( + type: 'animationstart' | 'animationend' | 'animationiteration', + canBubble: boolean, + cancelable: boolean, + animationName: string, + elapsedTime: number + ) => void; +} + +// https://html.spec.whatwg.org/multipage/web-messaging.html#broadcasting-to-other-browsing-contexts +declare class BroadcastChannel extends EventTarget { + name: string; + onmessage: ?(event: MessageEvent) => void; + onmessageerror: ?(event: MessageEvent) => void; + + constructor(name: string): void; + postMessage(msg: mixed): void; + close(): void; +} + +// https://www.w3.org/TR/touch-events/#idl-def-Touch +declare class Touch { + clientX: number, + clientY: number, + identifier: number, + pageX: number, + pageY: number, + screenX: number, + screenY: number, + target: EventTarget, +} + +// https://www.w3.org/TR/touch-events/#idl-def-TouchList +// TouchList#item(index) will return null if n > #length. Should #item's +// return type just been Touch? +declare class TouchList { + @@iterator(): Iterator; + length: number, + item(index: number): null | Touch, + [index: number]: Touch, +} + +// https://www.w3.org/TR/touch-events/#touchevent-interface +declare class TouchEvent extends UIEvent { + altKey: boolean, + changedTouches: TouchList, + ctrlKey: boolean, + metaKey: boolean, + shiftKey: boolean, + targetTouches: TouchList, + touches: TouchList, +} + +// https://www.w3.org/TR/webstorage/#the-storageevent-interface +declare class StorageEvent extends Event { + key: ?string, + oldValue: ?string, + newValue: ?string, + url: string, + storageArea: ?Storage, +} + +// https://w3c.github.io/clipboard-apis/ as of 15 May 2018 +type ClipboardEvent$Init = Event$Init & { clipboardData: DataTransfer | null, ... }; + +declare class ClipboardEvent extends Event { + constructor(type: ClipboardEventTypes, eventInit?: ClipboardEvent$Init): void; + +clipboardData: ?DataTransfer; // readonly +} + +// https://www.w3.org/TR/2017/WD-css-transitions-1-20171130/#interface-transitionevent +type TransitionEvent$Init = Event$Init & { + propertyName: string, + elapsedTime: number, + pseudoElement: string, + ... +}; + +declare class TransitionEvent extends Event { + constructor(type: TransitionEventTypes, eventInit?: TransitionEvent$Init): void; + + +propertyName: string; // readonly + +elapsedTime: number; // readonly + +pseudoElement: string; // readonly +} + +// https://www.w3.org/TR/html50/browsers.html#beforeunloadevent +declare class BeforeUnloadEvent extends Event { + returnValue: string, +} + +// TODO: *Event + +declare class Node extends EventTarget { + baseURI: ?string; + childNodes: NodeList; + firstChild: ?Node; + +isConnected: boolean; + lastChild: ?Node; + nextSibling: ?Node; + nodeName: string; + nodeType: number; + nodeValue: string; + ownerDocument: Document; + parentElement: ?Element; + parentNode: ?Node; + previousSibling: ?Node; + rootNode: Node; + textContent: string; + appendChild(newChild: T): T; + cloneNode(deep?: boolean): this; + compareDocumentPosition(other: Node): number; + contains(other: ?Node): boolean; + getRootNode(options?: { composed: boolean, ... }): Node; + hasChildNodes(): boolean; + insertBefore(newChild: T, refChild?: ?Node): T; + isDefaultNamespace(namespaceURI: string): boolean; + isEqualNode(arg: Node): boolean; + isSameNode(other: Node): boolean; + lookupNamespaceURI(prefix: string): string; + lookupPrefix(namespaceURI: string): string; + normalize(): void; + removeChild(oldChild: T): T; + replaceChild(newChild: Node, oldChild: T): T; + static ATTRIBUTE_NODE: number; + static CDATA_SECTION_NODE: number; + static COMMENT_NODE: number; + static DOCUMENT_FRAGMENT_NODE: number; + static DOCUMENT_NODE: number; + static DOCUMENT_POSITION_CONTAINED_BY: number; + static DOCUMENT_POSITION_CONTAINS: number; + static DOCUMENT_POSITION_DISCONNECTED: number; + static DOCUMENT_POSITION_FOLLOWING: number; + static DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: number; + static DOCUMENT_POSITION_PRECEDING: number; + static DOCUMENT_TYPE_NODE: number; + static ELEMENT_NODE: number; + static ENTITY_NODE: number; + static ENTITY_REFERENCE_NODE: number; + static NOTATION_NODE: number; + static PROCESSING_INSTRUCTION_NODE: number; + static TEXT_NODE: number; + + // Non-standard + innerText?: string; + outerText?: string; +} + +declare class NodeList { + @@iterator(): Iterator; + length: number; + item(index: number): T; + [index: number]: T; + + forEach(callbackfn: (value: T, index: number, list: NodeList) => any, thisArg?: any): void; + entries(): Iterator<[number, T]>; + keys(): Iterator; + values(): Iterator; +} + +declare class NamedNodeMap { + @@iterator(): Iterator; + length: number; + removeNamedItemNS(namespaceURI: string, localName: string): Attr; + item(index: number): Attr; + [index: number | string]: Attr; + removeNamedItem(name: string): Attr; + getNamedItem(name: string): Attr; + setNamedItem(arg: Attr): Attr; + getNamedItemNS(namespaceURI: string, localName: string): Attr; + setNamedItemNS(arg: Attr): Attr; +} + +declare class Attr extends Node { + isId: boolean; + specified: boolean; + ownerElement: Element | null; + value: string; + name: string; + namespaceURI: string | null; + prefix: string | null; + localName: string; +} + +declare class HTMLCollection<+Elem: HTMLElement> { + @@iterator(): Iterator; + length: number; + item(nameOrIndex?: any, optionalIndex?: any): Elem | null; + namedItem(name: string): Elem | null; + [index: number | string]: Elem; +} + +// from https://www.w3.org/TR/custom-elements/#extensions-to-document-interface-to-register +// See also https://github.com/w3c/webcomponents/ +type ElementRegistrationOptions = { + +prototype?: { + // from https://www.w3.org/TR/custom-elements/#types-of-callbacks + // See also https://github.com/w3c/webcomponents/ + +createdCallback?: () => mixed, + +attachedCallback?: () => mixed, + +detachedCallback?: () => mixed, + +attributeChangedCallback?: + // attribute is set + (( + attributeLocalName: string, + oldAttributeValue: null, + newAttributeValue: string, + attributeNamespace: string + ) => mixed) & + // attribute is changed + (( + attributeLocalName: string, + oldAttributeValue: string, + newAttributeValue: string, + attributeNamespace: string + ) => mixed) & + // attribute is removed + (( + attributeLocalName: string, + oldAttributeValue: string, + newAttributeValue: null, + attributeNamespace: string + ) => mixed), + ... + }, + +extends?: string, + ... +} + +type ElementCreationOptions = { is: string, ...} + +declare class Document extends Node { + +timeline: DocumentTimeline; + getAnimations(): Array; + URL: string; + adoptNode(source: T): T; + anchors: HTMLCollection; + applets: HTMLCollection; + body: HTMLBodyElement | null; + characterSet: string; + close(): void; + cookie: string; + createAttribute(name: string): Attr; + createAttributeNS(namespaceURI: string | null, qualifiedName: string): Attr; + createCDATASection(data: string): Text; + createComment(data: string): Comment; + createDocumentFragment(): DocumentFragment; + createElement(tagName: 'a', options?: ElementCreationOptions): HTMLAnchorElement; + createElement(tagName: 'area', options?: ElementCreationOptions): HTMLAreaElement; + createElement(tagName: 'audio', options?: ElementCreationOptions): HTMLAudioElement; + createElement(tagName: 'blockquote', options?: ElementCreationOptions): HTMLQuoteElement; + createElement(tagName: 'body', options?: ElementCreationOptions): HTMLBodyElement; + createElement(tagName: 'br', options?: ElementCreationOptions): HTMLBRElement; + createElement(tagName: 'button', options?: ElementCreationOptions): HTMLButtonElement; + createElement(tagName: 'canvas', options?: ElementCreationOptions): HTMLCanvasElement; + createElement(tagName: 'col', options?: ElementCreationOptions): HTMLTableColElement; + createElement(tagName: 'colgroup', options?: ElementCreationOptions): HTMLTableColElement; + createElement(tagName: 'data', options?: ElementCreationOptions): HTMLDataElement; + createElement(tagName: 'datalist', options?: ElementCreationOptions): HTMLDataListElement; + createElement(tagName: 'del', options?: ElementCreationOptions): HTMLModElement; + createElement(tagName: 'details', options?: ElementCreationOptions): HTMLDetailsElement; + createElement(tagName: 'dialog', options?: ElementCreationOptions): HTMLDialogElement; + createElement(tagName: 'div', options?: ElementCreationOptions): HTMLDivElement; + createElement(tagName: 'dl', options?: ElementCreationOptions): HTMLDListElement; + createElement(tagName: 'embed', options?: ElementCreationOptions): HTMLEmbedElement; + createElement(tagName: 'fieldset', options?: ElementCreationOptions): HTMLFieldSetElement; + createElement(tagName: 'form', options?: ElementCreationOptions): HTMLFormElement; + createElement(tagName: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', options?: ElementCreationOptions): HTMLHeadingElement; + createElement(tagName: 'head', options?: ElementCreationOptions): HTMLHeadElement; + createElement(tagName: 'hr', options?: ElementCreationOptions): HTMLHRElement; + createElement(tagName: 'html', options?: ElementCreationOptions): HTMLHtmlElement; + createElement(tagName: 'iframe', options?: ElementCreationOptions): HTMLIFrameElement; + createElement(tagName: 'img', options?: ElementCreationOptions): HTMLImageElement; + createElement(tagName: 'input', options?: ElementCreationOptions): HTMLInputElement; + createElement(tagName: 'ins', options?: ElementCreationOptions): HTMLModElement; + createElement(tagName: 'label', options?: ElementCreationOptions): HTMLLabelElement; + createElement(tagName: 'legend', options?: ElementCreationOptions): HTMLLegendElement; + createElement(tagName: 'li', options?: ElementCreationOptions): HTMLLIElement; + createElement(tagName: 'link', options?: ElementCreationOptions): HTMLLinkElement; + createElement(tagName: 'map', options?: ElementCreationOptions): HTMLMapElement; + createElement(tagName: 'meta', options?: ElementCreationOptions): HTMLMetaElement; + createElement(tagName: 'meter', options?: ElementCreationOptions): HTMLMeterElement; + createElement(tagName: 'object', options?: ElementCreationOptions): HTMLObjectElement; + createElement(tagName: 'ol', options?: ElementCreationOptions): HTMLOListElement; + createElement(tagName: 'optgroup', options?: ElementCreationOptions): HTMLOptGroupElement; + createElement(tagName: 'option', options?: ElementCreationOptions): HTMLOptionElement; + createElement(tagName: 'p', options?: ElementCreationOptions): HTMLParagraphElement; + createElement(tagName: 'param', options?: ElementCreationOptions): HTMLParamElement; + createElement(tagName: 'picture', options?: ElementCreationOptions): HTMLPictureElement; + createElement(tagName: 'pre', options?: ElementCreationOptions): HTMLPreElement; + createElement(tagName: 'progress', options?: ElementCreationOptions): HTMLProgressElement; + createElement(tagName: 'q', options?: ElementCreationOptions): HTMLQuoteElement; + createElement(tagName: 'script', options?: ElementCreationOptions): HTMLScriptElement; + createElement(tagName: 'select', options?: ElementCreationOptions): HTMLSelectElement; + createElement(tagName: 'source', options?: ElementCreationOptions): HTMLSourceElement; + createElement(tagName: 'span', options?: ElementCreationOptions): HTMLSpanElement; + createElement(tagName: 'style', options?: ElementCreationOptions): HTMLStyleElement; + createElement(tagName: 'textarea', options?: ElementCreationOptions): HTMLTextAreaElement; + createElement(tagName: 'time', options?: ElementCreationOptions): HTMLTimeElement; + createElement(tagName: 'title', options?: ElementCreationOptions): HTMLTitleElement; + createElement(tagName: 'track', options?: ElementCreationOptions): HTMLTrackElement; + createElement(tagName: 'video', options?: ElementCreationOptions): HTMLVideoElement; + createElement(tagName: 'table', options?: ElementCreationOptions): HTMLTableElement; + createElement(tagName: 'caption', options?: ElementCreationOptions): HTMLTableCaptionElement; + createElement(tagName: 'thead' | 'tfoot' | 'tbody', options?: ElementCreationOptions): HTMLTableSectionElement; + createElement(tagName: 'tr', options?: ElementCreationOptions): HTMLTableRowElement; + createElement(tagName: 'td' | 'th', options?: ElementCreationOptions): HTMLTableCellElement; + createElement(tagName: 'template', options?: ElementCreationOptions): HTMLTemplateElement; + createElement(tagName: 'ul', options?: ElementCreationOptions): HTMLUListElement; + createElement(tagName: string, options?: ElementCreationOptions): HTMLElement; + createElementNS(namespaceURI: string | null, qualifiedName: string, options?: ElementCreationOptions): Element; + createTextNode(data: string): Text; + currentScript: HTMLScriptElement | null; + dir: 'rtl' | 'ltr'; + doctype: DocumentType | null; + documentElement: HTMLElement | null; + documentMode: number; + domain: string | null; + embeds: HTMLCollection; + exitFullscreen(): Promise, + queryCommandSupported(cmdID: string): boolean; + execCommand(cmdID: string, showUI?: boolean, value?: any): boolean; + forms: HTMLCollection; + fullscreenElement: Element | null; + fullscreenEnabled: boolean; + getElementsByClassName(classNames: string): HTMLCollection; + getElementsByName(elementName: string): HTMLCollection; + getElementsByTagName(name: 'a'): HTMLCollection; + getElementsByTagName(name: 'area'): HTMLCollection; + getElementsByTagName(name: 'audio'): HTMLCollection; + getElementsByTagName(name: 'blockquote'): HTMLCollection; + getElementsByTagName(name: 'body'): HTMLCollection; + getElementsByTagName(name: 'br'): HTMLCollection; + getElementsByTagName(name: 'button'): HTMLCollection; + getElementsByTagName(name: 'canvas'): HTMLCollection; + getElementsByTagName(name: 'col'): HTMLCollection; + getElementsByTagName(name: 'colgroup'): HTMLCollection; + getElementsByTagName(name: 'data'): HTMLCollection; + getElementsByTagName(name: 'datalist'): HTMLCollection; + getElementsByTagName(name: 'del'): HTMLCollection; + getElementsByTagName(name: 'details'): HTMLCollection; + getElementsByTagName(name: 'dialog'): HTMLCollection; + getElementsByTagName(name: 'div'): HTMLCollection; + getElementsByTagName(name: 'dl'): HTMLCollection; + getElementsByTagName(name: 'embed'): HTMLCollection; + getElementsByTagName(name: 'fieldset'): HTMLCollection; + getElementsByTagName(name: 'form'): HTMLCollection; + getElementsByTagName(name: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'): HTMLCollection; + getElementsByTagName(name: 'head'): HTMLCollection; + getElementsByTagName(name: 'hr'): HTMLCollection; + getElementsByTagName(name: 'html'): HTMLCollection; + getElementsByTagName(name: 'iframe'): HTMLCollection; + getElementsByTagName(name: 'img'): HTMLCollection; + getElementsByTagName(name: 'input'): HTMLCollection; + getElementsByTagName(name: 'ins'): HTMLCollection; + getElementsByTagName(name: 'label'): HTMLCollection; + getElementsByTagName(name: 'legend'): HTMLCollection; + getElementsByTagName(name: 'li'): HTMLCollection; + getElementsByTagName(name: 'link'): HTMLCollection; + getElementsByTagName(name: 'map'): HTMLCollection; + getElementsByTagName(name: 'meta'): HTMLCollection; + getElementsByTagName(name: 'meter'): HTMLCollection; + getElementsByTagName(name: 'object'): HTMLCollection; + getElementsByTagName(name: 'ol'): HTMLCollection; + getElementsByTagName(name: 'option'): HTMLCollection; + getElementsByTagName(name: 'optgroup'): HTMLCollection; + getElementsByTagName(name: 'p'): HTMLCollection; + getElementsByTagName(name: 'param'): HTMLCollection; + getElementsByTagName(name: 'picture'): HTMLCollection; + getElementsByTagName(name: 'pre'): HTMLCollection; + getElementsByTagName(name: 'progress'): HTMLCollection; + getElementsByTagName(name: 'q'): HTMLCollection; + getElementsByTagName(name: 'script'): HTMLCollection; + getElementsByTagName(name: 'select'): HTMLCollection; + getElementsByTagName(name: 'source'): HTMLCollection; + getElementsByTagName(name: 'span'): HTMLCollection; + getElementsByTagName(name: 'style'): HTMLCollection; + getElementsByTagName(name: 'textarea'): HTMLCollection; + getElementsByTagName(name: 'time'): HTMLCollection; + getElementsByTagName(name: 'title'): HTMLCollection; + getElementsByTagName(name: 'track'): HTMLCollection; + getElementsByTagName(name: 'video'): HTMLCollection; + getElementsByTagName(name: 'table'): HTMLCollection; + getElementsByTagName(name: 'caption'): HTMLCollection; + getElementsByTagName(name: 'thead' | 'tfoot' | 'tbody'): HTMLCollection; + getElementsByTagName(name: 'tr'): HTMLCollection; + getElementsByTagName(name: 'td' | 'th'): HTMLCollection; + getElementsByTagName(name: 'template'): HTMLCollection; + getElementsByTagName(name: 'ul'): HTMLCollection; + getElementsByTagName(name: string): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'a'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'area'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'audio'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'blockquote'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'body'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'br'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'button'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'canvas'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'col'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'colgroup'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'data'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'datalist'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'del'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'details'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'dialog'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'div'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'dl'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'embed'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'fieldset'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'form'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'head'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'hr'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'html'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'iframe'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'img'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'input'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'ins'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'label'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'legend'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'li'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'link'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'map'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'meta'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'meter'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'object'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'ol'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'option'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'optgroup'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'p'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'param'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'picture'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'pre'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'progress'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'q'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'script'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'select'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'source'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'span'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'style'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'textarea'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'time'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'title'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'track'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'video'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'table'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'caption'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'thead' | 'tfoot' | 'tbody'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'tr'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'td' | 'th'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'template'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'ul'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: string): HTMLCollection; + head: HTMLHeadElement | null; + images: HTMLCollection; + implementation: DOMImplementation; + importNode(importedNode: T, deep: boolean): T; + inputEncoding: string; + lastModified: string; + links: HTMLCollection; + media: string; + open(url?: string, name?: string, features?: string, replace?: boolean): any; + readyState: string; + referrer: string; + scripts: HTMLCollection; + scrollingElement: HTMLElement | null; + styleSheets: StyleSheetList; + title: string; + visibilityState: 'visible' | 'hidden' | 'prerender' | 'unloaded'; + write(...content: Array): void; + writeln(...content: Array): void; + xmlEncoding: string; + xmlStandalone: boolean; + xmlVersion: string; + + registerElement(type: string, options?: ElementRegistrationOptions): any; + getSelection(): Selection | null; + + // 6.4.6 Focus management APIs + activeElement: HTMLElement | null; + hasFocus(): boolean; + + // extension + location: Location; + createEvent(eventInterface: 'CustomEvent'): CustomEvent; + createEvent(eventInterface: string): Event; + createRange(): Range; + elementFromPoint(x: number, y: number): HTMLElement | null; + elementsFromPoint(x: number, y: number): Array; + defaultView: any; + compatMode: 'BackCompat' | 'CSS1Compat'; + hidden: boolean; + + // Pointer Lock specification + exitPointerLock(): void; + pointerLockElement: Element | null; + + // from ParentNode interface + childElementCount: number; + children: HTMLCollection; + firstElementChild: ?Element; + lastElementChild: ?Element; + append(...nodes: Array): void; + prepend(...nodes: Array): void; + + querySelector(selector: 'a'): HTMLAnchorElement | null; + querySelector(selector: 'area'): HTMLAreaElement | null; + querySelector(selector: 'audio'): HTMLAudioElement | null; + querySelector(selector: 'blockquote'): HTMLQuoteElement | null; + querySelector(selector: 'body'): HTMLBodyElement | null; + querySelector(selector: 'br'): HTMLBRElement | null; + querySelector(selector: 'button'): HTMLButtonElement | null; + querySelector(selector: 'canvas'): HTMLCanvasElement | null; + querySelector(selector: 'col'): HTMLTableColElement | null; + querySelector(selector: 'colgroup'): HTMLTableColElement | null; + querySelector(selector: 'data'): HTMLDataElement | null; + querySelector(selector: 'datalist'): HTMLDataListElement | null; + querySelector(selector: 'del'): HTMLModElement | null; + querySelector(selector: 'details'): HTMLDetailsElement | null; + querySelector(selector: 'dialog'): HTMLDialogElement | null; + querySelector(selector: 'div'): HTMLDivElement | null; + querySelector(selector: 'dl'): HTMLDListElement | null; + querySelector(selector: 'embed'): HTMLEmbedElement | null; + querySelector(selector: 'fieldset'): HTMLFieldSetElement | null; + querySelector(selector: 'form'): HTMLFormElement | null; + querySelector(selector: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'): HTMLHeadingElement; + querySelector(selector: 'head'): HTMLHeadElement | null; + querySelector(selector: 'hr'): HTMLHRElement | null; + querySelector(selector: 'html'): HTMLHtmlElement | null; + querySelector(selector: 'iframe'): HTMLIFrameElement | null; + querySelector(selector: 'img'): HTMLImageElement | null; + querySelector(selector: 'ins'): HTMLModElement | null; + querySelector(selector: 'input'): HTMLInputElement | null; + querySelector(selector: 'label'): HTMLLabelElement | null; + querySelector(selector: 'legend'): HTMLLegendElement | null; + querySelector(selector: 'li'): HTMLLIElement | null; + querySelector(selector: 'link'): HTMLLinkElement | null; + querySelector(selector: 'map'): HTMLMapElement | null; + querySelector(selector: 'meta'): HTMLMetaElement | null; + querySelector(selector: 'meter'): HTMLMeterElement | null; + querySelector(selector: 'object'): HTMLObjectElement | null; + querySelector(selector: 'ol'): HTMLOListElement | null; + querySelector(selector: 'option'): HTMLOptionElement | null; + querySelector(selector: 'optgroup'): HTMLOptGroupElement | null; + querySelector(selector: 'p'): HTMLParagraphElement | null; + querySelector(selector: 'param'): HTMLParamElement | null; + querySelector(selector: 'picture'): HTMLPictureElement | null; + querySelector(selector: 'pre'): HTMLPreElement | null; + querySelector(selector: 'progress'): HTMLProgressElement | null; + querySelector(selector: 'q'): HTMLQuoteElement | null; + querySelector(selector: 'script'): HTMLScriptElement | null; + querySelector(selector: 'select'): HTMLSelectElement | null; + querySelector(selector: 'source'): HTMLSourceElement | null; + querySelector(selector: 'span'): HTMLSpanElement | null; + querySelector(selector: 'style'): HTMLStyleElement | null; + querySelector(selector: 'textarea'): HTMLTextAreaElement | null; + querySelector(selector: 'time'): HTMLTimeElement | null; + querySelector(selector: 'title'): HTMLTitleElement | null; + querySelector(selector: 'track'): HTMLTrackElement | null; + querySelector(selector: 'video'): HTMLVideoElement | null; + querySelector(selector: 'table'): HTMLTableElement | null; + querySelector(selector: 'caption'): HTMLTableCaptionElement | null; + querySelector(selector: 'thead' | 'tfoot' | 'tbody'): HTMLTableSectionElement | null; + querySelector(selector: 'tr'): HTMLTableRowElement | null; + querySelector(selector: 'td' | 'th'): HTMLTableCellElement | null; + querySelector(selector: 'template'): HTMLTemplateElement | null; + querySelector(selector: 'ul'): HTMLUListElement | null; + querySelector(selector: string): HTMLElement | null; + + querySelectorAll(selector: 'a'): NodeList; + querySelectorAll(selector: 'area'): NodeList; + querySelectorAll(selector: 'audio'): NodeList; + querySelectorAll(selector: 'blockquote'): NodeList; + querySelectorAll(selector: 'body'): NodeList; + querySelectorAll(selector: 'br'): NodeList; + querySelectorAll(selector: 'button'): NodeList; + querySelectorAll(selector: 'canvas'): NodeList; + querySelectorAll(selector: 'col'): NodeList; + querySelectorAll(selector: 'colgroup'): NodeList; + querySelectorAll(selector: 'data'): NodeList; + querySelectorAll(selector: 'datalist'): NodeList; + querySelectorAll(selector: 'del'): NodeList; + querySelectorAll(selector: 'details'): NodeList; + querySelectorAll(selector: 'dialog'): NodeList; + querySelectorAll(selector: 'div'): NodeList; + querySelectorAll(selector: 'dl'): NodeList; + querySelectorAll(selector: 'embed'): NodeList; + querySelectorAll(selector: 'fieldset'): NodeList; + querySelectorAll(selector: 'form'): NodeList; + querySelectorAll(selector: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'): NodeList; + querySelectorAll(selector: 'head'): NodeList; + querySelectorAll(selector: 'hr'): NodeList; + querySelectorAll(selector: 'html'): NodeList; + querySelectorAll(selector: 'iframe'): NodeList; + querySelectorAll(selector: 'img'): NodeList; + querySelectorAll(selector: 'input'): NodeList; + querySelectorAll(selector: 'ins'): NodeList; + querySelectorAll(selector: 'label'): NodeList; + querySelectorAll(selector: 'legend'): NodeList; + querySelectorAll(selector: 'li'): NodeList; + querySelectorAll(selector: 'link'): NodeList; + querySelectorAll(selector: 'map'): NodeList; + querySelectorAll(selector: 'meta'): NodeList; + querySelectorAll(selector: 'meter'): NodeList; + querySelectorAll(selector: 'object'): NodeList; + querySelectorAll(selector: 'ol'): NodeList; + querySelectorAll(selector: 'option'): NodeList; + querySelectorAll(selector: 'optgroup'): NodeList; + querySelectorAll(selector: 'p'): NodeList; + querySelectorAll(selector: 'param'): NodeList; + querySelectorAll(selector: 'picture'): NodeList; + querySelectorAll(selector: 'pre'): NodeList; + querySelectorAll(selector: 'progress'): NodeList; + querySelectorAll(selector: 'q'): NodeList; + querySelectorAll(selector: 'script'): NodeList; + querySelectorAll(selector: 'select'): NodeList; + querySelectorAll(selector: 'source'): NodeList; + querySelectorAll(selector: 'span'): NodeList; + querySelectorAll(selector: 'style'): NodeList; + querySelectorAll(selector: 'textarea'): NodeList; + querySelectorAll(selector: 'time'): NodeList; + querySelectorAll(selector: 'title'): NodeList; + querySelectorAll(selector: 'track'): NodeList; + querySelectorAll(selector: 'video'): NodeList; + querySelectorAll(selector: 'table'): NodeList; + querySelectorAll(selector: 'caption'): NodeList; + querySelectorAll(selector: 'thead' | 'tfoot' | 'tbody'): NodeList; + querySelectorAll(selector: 'tr'): NodeList; + querySelectorAll(selector: 'td' | 'th'): NodeList; + querySelectorAll(selector: 'template'): NodeList; + querySelectorAll(selector: 'ul'): NodeList; + querySelectorAll(selector: string): NodeList; + + // Interface DocumentTraversal + // http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113/traversal.html#Traversal-Document + + // Not all combinations of RootNodeT and whatToShow are logically possible. + // The bitmasks NodeFilter.SHOW_CDATA_SECTION, + // NodeFilter.SHOW_ENTITY_REFERENCE, NodeFilter.SHOW_ENTITY, and + // NodeFilter.SHOW_NOTATION are deprecated and do not correspond to types + // that Flow knows about. + + // NodeFilter.SHOW_ATTRIBUTE is also deprecated, but corresponds to the + // type Attr. While there is no reason to prefer it to Node.attributes, + // it does have meaning and can be typed: When (whatToShow & + // NodeFilter.SHOW_ATTRIBUTE === 1), RootNodeT must be Attr, and when + // RootNodeT is Attr, bitmasks other than NodeFilter.SHOW_ATTRIBUTE are + // meaningless. + createNodeIterator(root: RootNodeT, whatToShow: 2, filter?: NodeFilterInterface): NodeIterator; + createTreeWalker(root: RootNodeT, whatToShow: 2, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + + // NodeFilter.SHOW_PROCESSING_INSTRUCTION is not implemented because Flow + // does not currently define a ProcessingInstruction class. + + // When (whatToShow & NodeFilter.SHOW_DOCUMENT === 1 || whatToShow & + // NodeFilter.SHOW_DOCUMENT_TYPE === 1), RootNodeT must be Document. + createNodeIterator(root: RootNodeT, whatToShow: 256, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 257, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 260, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 261, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 384, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 385, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 388, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 389, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 512, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 513, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 516, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 517, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 640, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 641, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 644, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 645, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 768, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 769, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 772, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 773, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 896, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 897, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 900, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 901, filter?: NodeFilterInterface): NodeIterator; + createTreeWalker(root: RootNodeT, whatToShow: 256, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 257, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 260, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 261, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 384, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 385, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 388, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 389, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 512, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 513, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 516, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 517, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 640, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 641, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 644, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 645, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 768, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 769, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 772, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 773, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 896, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 897, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 900, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 901, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + + // When (whatToShow & NodeFilter.SHOW_DOCUMENT_FRAGMENT === 1), RootNodeT + // must be a DocumentFragment. + createNodeIterator(root: RootNodeT, whatToShow: 1024, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 1025, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 1028, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 1029, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 1152, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 1153, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 1156, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 1157, filter?: NodeFilterInterface): NodeIterator; + createTreeWalker(root: RootNodeT, whatToShow: 1024, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 1025, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 1028, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 1029, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 1152, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 1153, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 1156, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 1157, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + + // In the general case, RootNodeT may be any Node and whatToShow may be + // NodeFilter.SHOW_ALL or any combination of NodeFilter.SHOW_ELEMENT, + // NodeFilter.SHOW_TEXT and/or NodeFilter.SHOW_COMMENT + createNodeIterator(root: RootNodeT, whatToShow: 1, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 4, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 5, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 128, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 129, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 132, filter?: NodeFilterInterface): NodeIterator; + createNodeIterator(root: RootNodeT, whatToShow: 133, filter?: NodeFilterInterface): NodeIterator; + createTreeWalker(root: RootNodeT, whatToShow: 1, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 4, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 5, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 128, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 129, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 132, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + createTreeWalker(root: RootNodeT, whatToShow: 133, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + + // Catch all for when we don't know the value of `whatToShow` + // And for when whatToShow is not provided, it is assumed to be SHOW_ALL + createNodeIterator(root: RootNodeT, whatToShow?: number, filter?: NodeFilterInterface): NodeIterator; + createTreeWalker(root: RootNodeT, whatToShow?: number, filter?: NodeFilterInterface, entityReferenceExpansion?: boolean): TreeWalker; + + // From NonElementParentNode Mixin. + getElementById(elementId: string): HTMLElement | null; +} + +declare class DocumentFragment extends Node { + // from ParentNode interface + childElementCount: number; + children: HTMLCollection; + firstElementChild: ?Element; + lastElementChild: ?Element; + append(...nodes: Array): void; + prepend(...nodes: Array): void; + + querySelector(selector: string): HTMLElement | null; + querySelectorAll(selector: string): NodeList; + + // From NonElementParentNode Mixin. + getElementById(elementId: string): HTMLElement | null; +} + +declare class Selection { + anchorNode: Node | null; + anchorOffset: number; + focusNode: Node | null; + focusOffset: number; + isCollapsed: boolean; + rangeCount: number; + type: string; + addRange(range: Range): void; + getRangeAt(index: number): Range; + removeRange(range: Range): void; + removeAllRanges(): void; + collapse(parentNode: Node | null, offset?: number): void; + collapseToStart(): void; + collapseToEnd(): void; + containsNode(aNode: Node, aPartlyContained?: boolean): boolean; + deleteFromDocument(): void; + extend(parentNode: Node, offset?: number): void; + empty(): void; + selectAllChildren(parentNode: Node): void; + setPosition(aNode: Node | null, offset?: number): void; + setBaseAndExtent(anchorNode: Node, anchorOffset: number, focusNode: Node, focusOffset: number): void; + toString(): string; +} + +declare class Range { // extension + startOffset: number; + collapsed: boolean; + endOffset: number; + startContainer: Node; + endContainer: Node; + commonAncestorContainer: Node; + setStart(refNode: Node, offset: number): void; + setEndBefore(refNode: Node): void; + setStartBefore(refNode: Node): void; + selectNode(refNode: Node): void; + detach(): void; + getBoundingClientRect(): ClientRect; + toString(): string; + compareBoundaryPoints(how: number, sourceRange: Range): number; + insertNode(newNode: Node): void; + collapse(toStart: boolean): void; + selectNodeContents(refNode: Node): void; + cloneContents(): DocumentFragment; + setEnd(refNode: Node, offset: number): void; + cloneRange(): Range; + getClientRects(): ClientRectList; + surroundContents(newParent: Node): void; + deleteContents(): void; + setStartAfter(refNode: Node): void; + extractContents(): DocumentFragment; + setEndAfter(refNode: Node): void; + createContextualFragment(fragment: string): DocumentFragment; + static END_TO_END: number; + static START_TO_START: number; + static START_TO_END: number; + static END_TO_START: number; +} + +declare var document: Document; + +// TODO: HTMLDocument +type FocusOptions = { preventScroll?: boolean, ... } + +declare class DOMTokenList { + @@iterator(): Iterator; + length: number; + item(index: number): string; + contains(token: string): boolean; + add(...token: Array): void; + remove(...token: Array): void; + toggle(token: string, force?: boolean): boolean; + replace(oldToken: string, newToken: string): boolean; + + forEach(callbackfn: (value: string, index: number, list: DOMTokenList) => any, thisArg?: any): void; + entries(): Iterator<[number, string]>; + keys(): Iterator; + values(): Iterator; +} + + +declare class Element extends Node implements Animatable { + animate(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions): Animation; + getAnimations(options?: GetAnimationsOptions): Animation[]; + assignedSlot: ?HTMLSlotElement; + attachShadow(shadowRootInitDict: ShadowRootInit): ShadowRoot; + attributes: NamedNodeMap; + classList: DOMTokenList; + className: string; + clientHeight: number; + clientLeft: number; + clientTop: number; + clientWidth: number; + id: string; + innerHTML: string; + localName: string; + namespaceURI: ?string; + nextElementSibling: ?Element; + outerHTML: string; + prefix: string | null; + previousElementSibling: ?Element; + scrollHeight: number; + scrollLeft: number; + scrollTop: number; + scrollWidth: number; + tagName: string; + + closest(selectors: string): ?Element; + dispatchEvent(event: Event): bool; + + getAttribute(name?: string): ?string; + getAttributeNS(namespaceURI: string | null, localName: string): string | null; + getAttributeNode(name: string): Attr | null; + getAttributeNodeNS(namespaceURI: string | null, localName: string): Attr | null; + getBoundingClientRect(): ClientRect; + getClientRects(): ClientRect[]; + getElementsByClassName(names: string): HTMLCollection; + getElementsByTagName(name: 'a'): HTMLCollection; + getElementsByTagName(name: 'audio'): HTMLCollection; + getElementsByTagName(name: 'br'): HTMLCollection; + getElementsByTagName(name: 'button'): HTMLCollection; + getElementsByTagName(name: 'canvas'): HTMLCollection; + getElementsByTagName(name: 'col'): HTMLCollection; + getElementsByTagName(name: 'colgroup'): HTMLCollection; + getElementsByTagName(name: 'data'): HTMLCollection; + getElementsByTagName(name: 'datalist'): HTMLCollection; + getElementsByTagName(name: 'del'): HTMLCollection; + getElementsByTagName(name: 'details'): HTMLCollection; + getElementsByTagName(name: 'dialog'): HTMLCollection; + getElementsByTagName(name: 'div'): HTMLCollection; + getElementsByTagName(name: 'dl'): HTMLCollection; + getElementsByTagName(name: 'fieldset'): HTMLCollection; + getElementsByTagName(name: 'form'): HTMLCollection; + getElementsByTagName(name: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'): HTMLCollection; + getElementsByTagName(name: 'head'): HTMLCollection; + getElementsByTagName(name: 'hr'): HTMLCollection; + getElementsByTagName(name: 'iframe'): HTMLCollection; + getElementsByTagName(name: 'img'): HTMLCollection; + getElementsByTagName(name: 'input'): HTMLCollection; + getElementsByTagName(name: 'ins'): HTMLCollection; + getElementsByTagName(name: 'label'): HTMLCollection; + getElementsByTagName(name: 'legend'): HTMLCollection; + getElementsByTagName(name: 'li'): HTMLCollection; + getElementsByTagName(name: 'link'): HTMLCollection; + getElementsByTagName(name: 'meta'): HTMLCollection; + getElementsByTagName(name: 'meter'): HTMLCollection; + getElementsByTagName(name: 'object'): HTMLCollection; + getElementsByTagName(name: 'ol'): HTMLCollection; + getElementsByTagName(name: 'option'): HTMLCollection; + getElementsByTagName(name: 'optgroup'): HTMLCollection; + getElementsByTagName(name: 'p'): HTMLCollection; + getElementsByTagName(name: 'param'): HTMLCollection; + getElementsByTagName(name: 'picture'): HTMLCollection; + getElementsByTagName(name: 'pre'): HTMLCollection; + getElementsByTagName(name: 'progress'): HTMLCollection; + getElementsByTagName(name: 'script'): HTMLCollection; + getElementsByTagName(name: 'select'): HTMLCollection; + getElementsByTagName(name: 'source'): HTMLCollection; + getElementsByTagName(name: 'span'): HTMLCollection; + getElementsByTagName(name: 'style'): HTMLCollection; + getElementsByTagName(name: 'textarea'): HTMLCollection; + getElementsByTagName(name: 'video'): HTMLCollection; + getElementsByTagName(name: 'table'): HTMLCollection; + getElementsByTagName(name: 'title'): HTMLCollection; + getElementsByTagName(name: 'caption'): HTMLCollection; + getElementsByTagName(name: 'thead' | 'tfoot' | 'tbody'): HTMLCollection; + getElementsByTagName(name: 'tr'): HTMLCollection; + getElementsByTagName(name: 'td' | 'th'): HTMLCollection; + getElementsByTagName(name: 'template'): HTMLCollection; + getElementsByTagName(name: 'ul'): HTMLCollection; + getElementsByTagName(name: string): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'a'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'audio'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'br'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'button'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'canvas'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'col'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'colgroup'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'data'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'datalist'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'del'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'details'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'dialog'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'div'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'dl'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'fieldset'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'form'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'head'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'hr'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'iframe'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'img'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'input'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'ins'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'label'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'legend'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'li'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'link'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'meta'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'meter'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'object'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'ol'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'option'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'optgroup'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'p'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'param'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'picture'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'pre'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'progress'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'script'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'select'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'source'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'span'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'style'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'textarea'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'video'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'table'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'title'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'caption'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'thead' | 'tfoot' | 'tbody'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'tr'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'td' | 'th'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'template'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: 'ul'): HTMLCollection; + getElementsByTagNameNS(namespaceURI: string | null, localName: string): HTMLCollection; + hasAttribute(name: string): boolean; + hasAttributeNS(namespaceURI: string | null, localName: string): boolean; + hasAttributes(): boolean; + insertAdjacentElement(position: 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend', element: Element): void; + insertAdjacentHTML(position: 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend', html: string): void; + insertAdjacentText(position: 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend', text: string): void; + matches(selector: string): bool; + releasePointerCapture(pointerId: string): void; + removeAttribute(name?: string): void; + removeAttributeNode(attributeNode: Attr): Attr; + removeAttributeNS(namespaceURI: string | null, localName: string): void; + requestFullscreen(options?: { navigationUI: 'auto' | 'show' | 'hide', ... }): Promise; + requestPointerLock(): void; + scrollIntoView(arg?: (boolean | { + behavior?: ('auto' | 'instant' | 'smooth'), + block?: ('start' | 'center' | 'end' | 'nearest'), + inline?: ('start' | 'center' | 'end' | 'nearest'), + ... + })): void; + scroll(x: number, y: number): void; + scroll(options: ScrollToOptions): void; + scrollTo(x: number, y: number): void; + scrollTo(options: ScrollToOptions): void; + scrollBy(x: number, y: number): void; + scrollBy(options: ScrollToOptions): void; + setAttribute(name?: string, value?: string): void; + toggleAttribute(name?: string, force?: boolean): void; + setAttributeNS(namespaceURI: string | null, qualifiedName: string, value: string): void; + setAttributeNode(newAttr: Attr): Attr | null; + setAttributeNodeNS(newAttr: Attr): Attr | null; + setPointerCapture(pointerId: string): void; + shadowRoot?: ShadowRoot; + slot?: string; + + // from ParentNode interface + childElementCount: number; + children: HTMLCollection; + firstElementChild: ?Element; + lastElementChild: ?Element; + append(...nodes: Array): void; + prepend(...nodes: Array): void; + + querySelector(selector: 'a'): HTMLAnchorElement | null; + querySelector(selector: 'area'): HTMLAreaElement | null; + querySelector(selector: 'audio'): HTMLAudioElement | null; + querySelector(selector: 'blockquote'): HTMLQuoteElement | null; + querySelector(selector: 'body'): HTMLBodyElement | null; + querySelector(selector: 'br'): HTMLBRElement | null; + querySelector(selector: 'button'): HTMLButtonElement | null; + querySelector(selector: 'canvas'): HTMLCanvasElement | null; + querySelector(selector: 'col'): HTMLTableColElement | null; + querySelector(selector: 'colgroup'): HTMLTableColElement | null; + querySelector(selector: 'data'): HTMLDataElement | null; + querySelector(selector: 'datalist'): HTMLDataListElement | null; + querySelector(selector: 'del'): HTMLModElement | null; + querySelector(selector: 'details'): HTMLDetailsElement | null; + querySelector(selector: 'dialog'): HTMLDialogElement | null; + querySelector(selector: 'div'): HTMLDivElement | null; + querySelector(selector: 'dl'): HTMLDListElement | null; + querySelector(selector: 'embed'): HTMLEmbedElement | null; + querySelector(selector: 'fieldset'): HTMLFieldSetElement | null; + querySelector(selector: 'form'): HTMLFormElement | null; + querySelector(selector: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'): HTMLHeadingElement; + querySelector(selector: 'head'): HTMLHeadElement | null; + querySelector(selector: 'hr'): HTMLHRElement | null; + querySelector(selector: 'html'): HTMLHtmlElement | null; + querySelector(selector: 'iframe'): HTMLIFrameElement | null; + querySelector(selector: 'img'): HTMLImageElement | null; + querySelector(selector: 'ins'): HTMLModElement | null; + querySelector(selector: 'input'): HTMLInputElement | null; + querySelector(selector: 'label'): HTMLLabelElement | null; + querySelector(selector: 'legend'): HTMLLegendElement | null; + querySelector(selector: 'li'): HTMLLIElement | null; + querySelector(selector: 'link'): HTMLLinkElement | null; + querySelector(selector: 'map'): HTMLMapElement | null; + querySelector(selector: 'meta'): HTMLMetaElement | null; + querySelector(selector: 'meter'): HTMLMeterElement | null; + querySelector(selector: 'object'): HTMLObjectElement | null; + querySelector(selector: 'ol'): HTMLOListElement | null; + querySelector(selector: 'option'): HTMLOptionElement | null; + querySelector(selector: 'optgroup'): HTMLOptGroupElement | null; + querySelector(selector: 'p'): HTMLParagraphElement | null; + querySelector(selector: 'param'): HTMLParamElement | null; + querySelector(selector: 'picture'): HTMLPictureElement | null; + querySelector(selector: 'pre'): HTMLPreElement | null; + querySelector(selector: 'progress'): HTMLProgressElement | null; + querySelector(selector: 'q'): HTMLQuoteElement | null; + querySelector(selector: 'script'): HTMLScriptElement | null; + querySelector(selector: 'select'): HTMLSelectElement | null; + querySelector(selector: 'source'): HTMLSourceElement | null; + querySelector(selector: 'span'): HTMLSpanElement | null; + querySelector(selector: 'style'): HTMLStyleElement | null; + querySelector(selector: 'textarea'): HTMLTextAreaElement | null; + querySelector(selector: 'time'): HTMLTimeElement | null; + querySelector(selector: 'title'): HTMLTitleElement | null; + querySelector(selector: 'track'): HTMLTrackElement | null; + querySelector(selector: 'video'): HTMLVideoElement | null; + querySelector(selector: 'table'): HTMLTableElement | null; + querySelector(selector: 'caption'): HTMLTableCaptionElement | null; + querySelector(selector: 'thead' | 'tfoot' | 'tbody'): HTMLTableSectionElement | null; + querySelector(selector: 'tr'): HTMLTableRowElement | null; + querySelector(selector: 'td' | 'th'): HTMLTableCellElement | null; + querySelector(selector: 'template'): HTMLTemplateElement | null; + querySelector(selector: 'ul'): HTMLUListElement | null; + querySelector(selector: string): HTMLElement | null; + + querySelectorAll(selector: 'a'): NodeList; + querySelectorAll(selector: 'area'): NodeList; + querySelectorAll(selector: 'audio'): NodeList; + querySelectorAll(selector: 'blockquote'): NodeList; + querySelectorAll(selector: 'body'): NodeList; + querySelectorAll(selector: 'br'): NodeList; + querySelectorAll(selector: 'button'): NodeList; + querySelectorAll(selector: 'canvas'): NodeList; + querySelectorAll(selector: 'col'): NodeList; + querySelectorAll(selector: 'colgroup'): NodeList; + querySelectorAll(selector: 'data'): NodeList; + querySelectorAll(selector: 'datalist'): NodeList; + querySelectorAll(selector: 'del'): NodeList; + querySelectorAll(selector: 'details'): NodeList; + querySelectorAll(selector: 'dialog'): NodeList; + querySelectorAll(selector: 'div'): NodeList; + querySelectorAll(selector: 'dl'): NodeList; + querySelectorAll(selector: 'embed'): NodeList; + querySelectorAll(selector: 'fieldset'): NodeList; + querySelectorAll(selector: 'form'): NodeList; + querySelectorAll(selector: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'): NodeList; + querySelectorAll(selector: 'head'): NodeList; + querySelectorAll(selector: 'hr'): NodeList; + querySelectorAll(selector: 'html'): NodeList; + querySelectorAll(selector: 'iframe'): NodeList; + querySelectorAll(selector: 'img'): NodeList; + querySelectorAll(selector: 'input'): NodeList; + querySelectorAll(selector: 'ins'): NodeList; + querySelectorAll(selector: 'label'): NodeList; + querySelectorAll(selector: 'legend'): NodeList; + querySelectorAll(selector: 'li'): NodeList; + querySelectorAll(selector: 'link'): NodeList; + querySelectorAll(selector: 'map'): NodeList; + querySelectorAll(selector: 'meta'): NodeList; + querySelectorAll(selector: 'meter'): NodeList; + querySelectorAll(selector: 'object'): NodeList; + querySelectorAll(selector: 'ol'): NodeList; + querySelectorAll(selector: 'option'): NodeList; + querySelectorAll(selector: 'optgroup'): NodeList; + querySelectorAll(selector: 'p'): NodeList; + querySelectorAll(selector: 'param'): NodeList; + querySelectorAll(selector: 'picture'): NodeList; + querySelectorAll(selector: 'pre'): NodeList; + querySelectorAll(selector: 'progress'): NodeList; + querySelectorAll(selector: 'q'): NodeList; + querySelectorAll(selector: 'script'): NodeList; + querySelectorAll(selector: 'select'): NodeList; + querySelectorAll(selector: 'source'): NodeList; + querySelectorAll(selector: 'span'): NodeList; + querySelectorAll(selector: 'style'): NodeList; + querySelectorAll(selector: 'textarea'): NodeList; + querySelectorAll(selector: 'time'): NodeList; + querySelectorAll(selector: 'title'): NodeList; + querySelectorAll(selector: 'track'): NodeList; + querySelectorAll(selector: 'video'): NodeList; + querySelectorAll(selector: 'table'): NodeList; + querySelectorAll(selector: 'caption'): NodeList; + querySelectorAll(selector: 'thead' | 'tfoot' | 'tbody'): NodeList; + querySelectorAll(selector: 'tr'): NodeList; + querySelectorAll(selector: 'td' | 'th'): NodeList; + querySelectorAll(selector: 'template'): NodeList; + querySelectorAll(selector: 'ul'): NodeList; + querySelectorAll(selector: string): NodeList; + + // from ChildNode interface + after(...nodes: Array): void; + before(...nodes: Array): void; + replaceWith(...nodes: Array): void; + remove(): void; +} + +declare class HTMLElement extends Element { + blur(): void; + click(): void; + focus(options?: FocusOptions): void; + getBoundingClientRect(): ClientRect; + forceSpellcheck(): void; + accessKey: string; + accessKeyLabel: string; + className: string; + contentEditable: string; + contextMenu: ?HTMLMenuElement; + dataset: DOMStringMap; + dir: 'ltr' | 'rtl' | 'auto'; + draggable: bool; + dropzone: any; + hidden: boolean; + id: string; + innerHTML: string; + isContentEditable: boolean; + itemProp: any; + itemScope: bool; + itemType: any; + itemValue: Object; + lang: string; + offsetHeight: number; + offsetLeft: number; + offsetParent: ?Element; + offsetTop: number; + offsetWidth: number; + onabort: ?Function; + onblur: ?Function; + oncancel: ?Function; + oncanplay: ?Function; + oncanplaythrough: ?Function; + onchange: ?Function; + onclick: ?Function; + oncontextmenu: ?Function; + oncuechange: ?Function; + ondblclick: ?Function; + ondurationchange: ?Function; + onemptied: ?Function; + onended: ?Function; + onerror: ?Function; + onfocus: ?Function; + onfullscreenchange: ?Function; + onfullscreenerror: ?Function; + ongotpointercapture: ?Function, + oninput: ?Function; + oninvalid: ?Function; + onkeydown: ?Function; + onkeypress: ?Function; + onkeyup: ?Function; + onload: ?Function; + onloadeddata: ?Function; + onloadedmetadata: ?Function; + onloadstart: ?Function; + onlostpointercapture: ?Function, + onmousedown: ?Function; + onmouseenter: ?Function; + onmouseleave: ?Function; + onmousemove: ?Function; + onmouseout: ?Function; + onmouseover: ?Function; + onmouseup: ?Function; + onmousewheel: ?Function; + onpause: ?Function; + onplay: ?Function; + onplaying: ?Function; + onpointercancel: ?Function, + onpointerdown: ?Function, + onpointerenter: ?Function, + onpointerleave: ?Function, + onpointermove: ?Function, + onpointerout: ?Function, + onpointerover: ?Function, + onpointerup: ?Function, + onprogress: ?Function; + onratechange: ?Function; + onreadystatechange: ?Function; + onreset: ?Function; + onresize: ?Function; + onscroll: ?Function; + onseeked: ?Function; + onseeking: ?Function; + onselect: ?Function; + onshow: ?Function; + onstalled: ?Function; + onsubmit: ?Function; + onsuspend: ?Function; + ontimeupdate: ?Function; + ontoggle: ?Function; + onvolumechange: ?Function; + onwaiting: ?Function; + properties: any; + spellcheck: boolean; + style: CSSStyleDeclaration; + tabIndex: number; + title: string; + translate: boolean; +} + +declare class HTMLSlotElement extends HTMLElement { + name: string; + assignedNodes(options?: { flatten: boolean, ... }): Node[]; +} + +declare class HTMLTableElement extends HTMLElement { + caption: HTMLTableCaptionElement; + tHead: HTMLTableSectionElement; + tFoot: HTMLTableSectionElement; + tBodies: HTMLCollection; + rows: HTMLCollection; + createTHead(): HTMLTableSectionElement; + deleteTHead(): void; + createTFoot(): HTMLTableSectionElement; + deleteTFoot(): void; + createCaption(): HTMLTableCaptionElement; + deleteCaption(): void; + insertRow(index: ?number): HTMLTableRowElement; + deleteRow(index: number): void; +} + +declare class HTMLTableCaptionElement extends HTMLElement { + +} + +declare class HTMLTableSectionElement extends HTMLElement { + rows: HTMLCollection; +} + +declare class HTMLTableCellElement extends HTMLElement { + colSpan: number; + rowSpan: number; + cellIndex: number; +} + +declare class HTMLTableRowElement extends HTMLElement { + align: 'left' | 'right' | 'center'; + rowIndex: number; + +cells: HTMLCollection; + deleteCell(index: number): void; + insertCell(index: number): HTMLTableCellElement; +} + +declare class HTMLMenuElement extends HTMLElement { + getCompact(): bool; + setCompact(compact: bool): void; +} + +declare class HTMLBaseElement extends HTMLElement { + href: string; + target: string; +} + +declare class HTMLTemplateElement extends HTMLElement { + content: DocumentFragment; +} + +declare class CanvasGradient { + addColorStop(offset: number, color: string): void; +} + +declare class CanvasPattern { + setTransform(matrix: SVGMatrix): void; +} + +declare class ImageBitmap { + close(): void; + width: number; + height: number; +} + +type CanvasFillRule = string; + +type CanvasImageSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | CanvasRenderingContext2D | ImageBitmap; + +declare class HitRegionOptions { + path?: Path2D, + fillRule?: CanvasFillRule, + id?: string, + parentID?: string; + cursor?: string; + control?: Element; + label: ?string; + role: ?string; +}; + +declare class CanvasDrawingStyles { + lineWidth: number; + lineCap: string; + lineJoin: string; + miterLimit: number; + + // dashed lines + setLineDash(segments: Array): void; + getLineDash(): Array; + lineDashOffset: number; + + // text + font: string; + textAlign: string; + textBaseline: string; + direction: string; +}; + +declare class SVGMatrix { + getComponent(index: number): number; + mMultiply(secondMatrix: SVGMatrix): SVGMatrix; + inverse(): SVGMatrix; + mTranslate(x: number, y: number): SVGMatrix; + mScale(scaleFactor: number): SVGMatrix; + mRotate(angle: number): SVGMatrix; +}; + +declare class TextMetrics { + // x-direction + width: number; + actualBoundingBoxLeft: number; + actualBoundingBoxRight: number; + + // y-direction + fontBoundingBoxAscent: number; + fontBoundingBoxDescent: number; + actualBoundingBoxAscent: number; + actualBoundingBoxDescent: number; + emHeightAscent: number; + emHeightDescent: number; + hangingBaseline: number; + alphabeticBaseline: number; + ideographicBaseline: number; +}; + +declare class Path2D { + constructor(path?: Path2D | string): void; + + addPath(path: Path2D, transformation?: ?SVGMatrix): void; + addPathByStrokingPath(path: Path2D, styles: CanvasDrawingStyles, transformation?: ?SVGMatrix): void; + addText(text: string, styles: CanvasDrawingStyles, transformation: ?SVGMatrix, x: number, y: number, maxWidth?: number): void; + addPathByStrokingText(text: string, styles: CanvasDrawingStyles, transformation: ?SVGMatrix, x: number, y: number, maxWidth?: number): void; + addText(text: string, styles: CanvasDrawingStyles, transformation: ?SVGMatrix, path: Path2D, maxWidth?: number): void; + addPathByStrokingText(text: string, styles: CanvasDrawingStyles, transformation: ?SVGMatrix, path: Path2D, maxWidth?: number): void; + + // CanvasPathMethods + // shared path API methods + arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void; + arcTo(x1: number, y1: number, x2: number, y2: number, radius: number, _: void, _: void): void; + arcTo(x1: number, y1: number, x2: number, y2: number, radiusX: number, radiusY: number, rotation: number): void; + bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void; + closePath(): void; + ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void; + lineTo(x: number, y: number): void; + moveTo(x: number, y: number): void; + quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void; + rect(x: number, y: number, w: number, h: number): void; +}; + +declare class ImageData { + width: number; + height: number; + data: Uint8ClampedArray; + + // constructor methods are used in Worker where CanvasRenderingContext2D + // is unavailable. + // https://html.spec.whatwg.org/multipage/scripting.html#dom-imagedata + constructor(data: Uint8ClampedArray, width: number, height: number): void; + constructor(width: number, height: number): void; +}; + +declare class CanvasRenderingContext2D { + canvas: HTMLCanvasElement; + + // canvas dimensions + width: number; + height: number; + + // for contexts that aren't directly fixed to a specific canvas + commit(): void; + + // state + save(): void; + restore(): void; + + // transformations + currentTransform: SVGMatrix; + scale(x: number, y: number): void; + rotate(angle: number): void; + translate(x: number, y: number): void; + transform(a: number, b: number, c: number, d: number, e: number, f: number): void; + setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void; + resetTransform(): void; + + // compositing + globalAlpha: number; + globalCompositeOperation: string; + + // image smoothing + imageSmoothingEnabled: boolean; + imageSmoothingQuality: 'low' | 'medium' | 'high'; + + // filters + filter: string; + + // colours and styles + strokeStyle: string | CanvasGradient | CanvasPattern; + fillStyle: string | CanvasGradient | CanvasPattern; + createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient; + createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient; + createPattern(image: CanvasImageSource, repetition: ?string): CanvasPattern; + + // shadows + shadowOffsetX: number; + shadowOffsetY: number; + shadowBlur: number; + shadowColor: string; + + // rects + clearRect(x: number, y: number, w: number, h: number): void; + fillRect(x: number, y: number, w: number, h: number): void; + strokeRect(x: number, y: number, w: number, h: number): void; + + // path API + beginPath(): void; + fill(fillRule?: CanvasFillRule): void; + fill(path: Path2D, fillRule?: CanvasFillRule): void; + stroke(): void; + stroke(path: Path2D): void; + drawFocusIfNeeded(element: Element): void; + drawFocusIfNeeded(path: Path2D, element: Element): void; + scrollPathIntoView(): void; + scrollPathIntoView(path: Path2D): void; + clip(fillRule?: CanvasFillRule): void; + clip(path: Path2D, fillRule?: CanvasFillRule): void; + resetClip(): void; + isPointInPath(x: number, y: number, fillRule?: CanvasFillRule): boolean; + isPointInPath(path: Path2D, x: number, y: number, fillRule?: CanvasFillRule): boolean; + isPointInStroke(x: number, y: number): boolean; + isPointInStroke(path: Path2D, x: number, y: number): boolean; + + // text (see also the CanvasDrawingStyles interface) + fillText(text: string, x: number, y: number, maxWidth?: number): void; + strokeText(text: string, x: number, y: number, maxWidth?: number): void; + measureText(text: string): TextMetrics; + + // drawing images + drawImage(image: CanvasImageSource, dx: number, dy: number): void; + drawImage(image: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void; + drawImage(image: CanvasImageSource, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void; + + // hit regions + addHitRegion(options?: HitRegionOptions): void; + removeHitRegion(id: string): void; + clearHitRegions(): void; + + // pixel manipulation + createImageData(sw: number, sh: number): ImageData; + createImageData(imagedata: ImageData): ImageData; + getImageData(sx: number, sy: number, sw: number, sh: number): ImageData; + putImageData(imagedata: ImageData, dx: number, dy: number): void; + putImageData(imagedata: ImageData, dx: number, dy: number, dirtyX: number, dirtyY: number, dirtyWidth: number, dirtyHeight: number): void; + + // CanvasDrawingStyles + // line caps/joins + lineWidth: number; + lineCap: string; + lineJoin: string; + miterLimit: number; + + // dashed lines + setLineDash(segments: Array): void; + getLineDash(): Array; + lineDashOffset: number; + + // text + font: string; + textAlign: string; + textBaseline: string; + direction: string; + + // CanvasPathMethods + // shared path API methods + closePath(): void; + moveTo(x: number, y: number): void; + lineTo(x: number, y: number): void; + quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void; + bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void; + arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void; + arcTo(x1: number, y1: number, x2: number, y2: number, radiusX: number, radiusY: number, rotation: number): void; + rect(x: number, y: number, w: number, h: number): void; + arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void; + ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void; +} + + +// WebGL idl: https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl + +type WebGLContextAttributes = { + alpha: bool, + depth: bool, + stencil: bool, + antialias: bool, + premultipliedAlpha: bool, + preserveDrawingBuffer: bool, + preferLowPowerToHighPerformance: bool, + failIfMajorPerformanceCaveat: bool, + ... +}; + +interface WebGLObject { +}; + +interface WebGLBuffer extends WebGLObject { +}; + +interface WebGLFramebuffer extends WebGLObject { +}; + +interface WebGLProgram extends WebGLObject { +}; + +interface WebGLRenderbuffer extends WebGLObject { +}; + +interface WebGLShader extends WebGLObject { +}; + +interface WebGLTexture extends WebGLObject { +}; + +interface WebGLUniformLocation { +}; + +interface WebGLActiveInfo { + size: number; + type: number; + name: string; +}; + +interface WebGLShaderPrecisionFormat { + rangeMin: number; + rangeMax: number; + precision: number; +}; + +type BufferDataSource = ArrayBuffer | $ArrayBufferView; + +type TexImageSource = + ImageBitmap | + ImageData | + HTMLImageElement | + HTMLCanvasElement | + HTMLVideoElement; + +type VertexAttribFVSource = + Float32Array | + Array; + +/* flow */ +declare class WebGLRenderingContext { + static DEPTH_BUFFER_BIT : 0x00000100; + DEPTH_BUFFER_BIT : 0x00000100; + static STENCIL_BUFFER_BIT : 0x00000400; + STENCIL_BUFFER_BIT : 0x00000400; + static COLOR_BUFFER_BIT : 0x00004000; + COLOR_BUFFER_BIT : 0x00004000; + static POINTS : 0x0000; + POINTS : 0x0000; + static LINES : 0x0001; + LINES : 0x0001; + static LINE_LOOP : 0x0002; + LINE_LOOP : 0x0002; + static LINE_STRIP : 0x0003; + LINE_STRIP : 0x0003; + static TRIANGLES : 0x0004; + TRIANGLES : 0x0004; + static TRIANGLE_STRIP : 0x0005; + TRIANGLE_STRIP : 0x0005; + static TRIANGLE_FAN : 0x0006; + TRIANGLE_FAN : 0x0006; + static ZERO : 0; + ZERO : 0; + static ONE : 1; + ONE : 1; + static SRC_COLOR : 0x0300; + SRC_COLOR : 0x0300; + static ONE_MINUS_SRC_COLOR : 0x0301; + ONE_MINUS_SRC_COLOR : 0x0301; + static SRC_ALPHA : 0x0302; + SRC_ALPHA : 0x0302; + static ONE_MINUS_SRC_ALPHA : 0x0303; + ONE_MINUS_SRC_ALPHA : 0x0303; + static DST_ALPHA : 0x0304; + DST_ALPHA : 0x0304; + static ONE_MINUS_DST_ALPHA : 0x0305; + ONE_MINUS_DST_ALPHA : 0x0305; + static DST_COLOR : 0x0306; + DST_COLOR : 0x0306; + static ONE_MINUS_DST_COLOR : 0x0307; + ONE_MINUS_DST_COLOR : 0x0307; + static SRC_ALPHA_SATURATE : 0x0308; + SRC_ALPHA_SATURATE : 0x0308; + static FUNC_ADD : 0x8006; + FUNC_ADD : 0x8006; + static BLEND_EQUATION : 0x8009; + BLEND_EQUATION : 0x8009; + static BLEND_EQUATION_RGB : 0x8009; + BLEND_EQUATION_RGB : 0x8009; + static BLEND_EQUATION_ALPHA : 0x883D; + BLEND_EQUATION_ALPHA : 0x883D; + static FUNC_SUBTRACT : 0x800A; + FUNC_SUBTRACT : 0x800A; + static FUNC_REVERSE_SUBTRACT : 0x800B; + FUNC_REVERSE_SUBTRACT : 0x800B; + static BLEND_DST_RGB : 0x80C8; + BLEND_DST_RGB : 0x80C8; + static BLEND_SRC_RGB : 0x80C9; + BLEND_SRC_RGB : 0x80C9; + static BLEND_DST_ALPHA : 0x80CA; + BLEND_DST_ALPHA : 0x80CA; + static BLEND_SRC_ALPHA : 0x80CB; + BLEND_SRC_ALPHA : 0x80CB; + static CONSTANT_COLOR : 0x8001; + CONSTANT_COLOR : 0x8001; + static ONE_MINUS_CONSTANT_COLOR : 0x8002; + ONE_MINUS_CONSTANT_COLOR : 0x8002; + static CONSTANT_ALPHA : 0x8003; + CONSTANT_ALPHA : 0x8003; + static ONE_MINUS_CONSTANT_ALPHA : 0x8004; + ONE_MINUS_CONSTANT_ALPHA : 0x8004; + static BLEND_COLOR : 0x8005; + BLEND_COLOR : 0x8005; + static ARRAY_BUFFER : 0x8892; + ARRAY_BUFFER : 0x8892; + static ELEMENT_ARRAY_BUFFER : 0x8893; + ELEMENT_ARRAY_BUFFER : 0x8893; + static ARRAY_BUFFER_BINDING : 0x8894; + ARRAY_BUFFER_BINDING : 0x8894; + static ELEMENT_ARRAY_BUFFER_BINDING : 0x8895; + ELEMENT_ARRAY_BUFFER_BINDING : 0x8895; + static STREAM_DRAW : 0x88E0; + STREAM_DRAW : 0x88E0; + static STATIC_DRAW : 0x88E4; + STATIC_DRAW : 0x88E4; + static DYNAMIC_DRAW : 0x88E8; + DYNAMIC_DRAW : 0x88E8; + static BUFFER_SIZE : 0x8764; + BUFFER_SIZE : 0x8764; + static BUFFER_USAGE : 0x8765; + BUFFER_USAGE : 0x8765; + static CURRENT_VERTEX_ATTRIB : 0x8626; + CURRENT_VERTEX_ATTRIB : 0x8626; + static FRONT : 0x0404; + FRONT : 0x0404; + static BACK : 0x0405; + BACK : 0x0405; + static FRONT_AND_BACK : 0x0408; + FRONT_AND_BACK : 0x0408; + static CULL_FACE : 0x0B44; + CULL_FACE : 0x0B44; + static BLEND : 0x0BE2; + BLEND : 0x0BE2; + static DITHER : 0x0BD0; + DITHER : 0x0BD0; + static STENCIL_TEST : 0x0B90; + STENCIL_TEST : 0x0B90; + static DEPTH_TEST : 0x0B71; + DEPTH_TEST : 0x0B71; + static SCISSOR_TEST : 0x0C11; + SCISSOR_TEST : 0x0C11; + static POLYGON_OFFSET_FILL : 0x8037; + POLYGON_OFFSET_FILL : 0x8037; + static SAMPLE_ALPHA_TO_COVERAGE : 0x809E; + SAMPLE_ALPHA_TO_COVERAGE : 0x809E; + static SAMPLE_COVERAGE : 0x80A0; + SAMPLE_COVERAGE : 0x80A0; + static NO_ERROR : 0; + NO_ERROR : 0; + static INVALID_ENUM : 0x0500; + INVALID_ENUM : 0x0500; + static INVALID_VALUE : 0x0501; + INVALID_VALUE : 0x0501; + static INVALID_OPERATION : 0x0502; + INVALID_OPERATION : 0x0502; + static OUT_OF_MEMORY : 0x0505; + OUT_OF_MEMORY : 0x0505; + static CW : 0x0900; + CW : 0x0900; + static CCW : 0x0901; + CCW : 0x0901; + static LINE_WIDTH : 0x0B21; + LINE_WIDTH : 0x0B21; + static ALIASED_POINT_SIZE_RANGE : 0x846D; + ALIASED_POINT_SIZE_RANGE : 0x846D; + static ALIASED_LINE_WIDTH_RANGE : 0x846E; + ALIASED_LINE_WIDTH_RANGE : 0x846E; + static CULL_FACE_MODE : 0x0B45; + CULL_FACE_MODE : 0x0B45; + static FRONT_FACE : 0x0B46; + FRONT_FACE : 0x0B46; + static DEPTH_RANGE : 0x0B70; + DEPTH_RANGE : 0x0B70; + static DEPTH_WRITEMASK : 0x0B72; + DEPTH_WRITEMASK : 0x0B72; + static DEPTH_CLEAR_VALUE : 0x0B73; + DEPTH_CLEAR_VALUE : 0x0B73; + static DEPTH_FUNC : 0x0B74; + DEPTH_FUNC : 0x0B74; + static STENCIL_CLEAR_VALUE : 0x0B91; + STENCIL_CLEAR_VALUE : 0x0B91; + static STENCIL_FUNC : 0x0B92; + STENCIL_FUNC : 0x0B92; + static STENCIL_FAIL : 0x0B94; + STENCIL_FAIL : 0x0B94; + static STENCIL_PASS_DEPTH_FAIL : 0x0B95; + STENCIL_PASS_DEPTH_FAIL : 0x0B95; + static STENCIL_PASS_DEPTH_PASS : 0x0B96; + STENCIL_PASS_DEPTH_PASS : 0x0B96; + static STENCIL_REF : 0x0B97; + STENCIL_REF : 0x0B97; + static STENCIL_VALUE_MASK : 0x0B93; + STENCIL_VALUE_MASK : 0x0B93; + static STENCIL_WRITEMASK : 0x0B98; + STENCIL_WRITEMASK : 0x0B98; + static STENCIL_BACK_FUNC : 0x8800; + STENCIL_BACK_FUNC : 0x8800; + static STENCIL_BACK_FAIL : 0x8801; + STENCIL_BACK_FAIL : 0x8801; + static STENCIL_BACK_PASS_DEPTH_FAIL : 0x8802; + STENCIL_BACK_PASS_DEPTH_FAIL : 0x8802; + static STENCIL_BACK_PASS_DEPTH_PASS : 0x8803; + STENCIL_BACK_PASS_DEPTH_PASS : 0x8803; + static STENCIL_BACK_REF : 0x8CA3; + STENCIL_BACK_REF : 0x8CA3; + static STENCIL_BACK_VALUE_MASK : 0x8CA4; + STENCIL_BACK_VALUE_MASK : 0x8CA4; + static STENCIL_BACK_WRITEMASK : 0x8CA5; + STENCIL_BACK_WRITEMASK : 0x8CA5; + static VIEWPORT : 0x0BA2; + VIEWPORT : 0x0BA2; + static SCISSOR_BOX : 0x0C10; + SCISSOR_BOX : 0x0C10; + static COLOR_CLEAR_VALUE : 0x0C22; + COLOR_CLEAR_VALUE : 0x0C22; + static COLOR_WRITEMASK : 0x0C23; + COLOR_WRITEMASK : 0x0C23; + static UNPACK_ALIGNMENT : 0x0CF5; + UNPACK_ALIGNMENT : 0x0CF5; + static PACK_ALIGNMENT : 0x0D05; + PACK_ALIGNMENT : 0x0D05; + static MAX_TEXTURE_SIZE : 0x0D33; + MAX_TEXTURE_SIZE : 0x0D33; + static MAX_VIEWPORT_DIMS : 0x0D3A; + MAX_VIEWPORT_DIMS : 0x0D3A; + static SUBPIXEL_BITS : 0x0D50; + SUBPIXEL_BITS : 0x0D50; + static RED_BITS : 0x0D52; + RED_BITS : 0x0D52; + static GREEN_BITS : 0x0D53; + GREEN_BITS : 0x0D53; + static BLUE_BITS : 0x0D54; + BLUE_BITS : 0x0D54; + static ALPHA_BITS : 0x0D55; + ALPHA_BITS : 0x0D55; + static DEPTH_BITS : 0x0D56; + DEPTH_BITS : 0x0D56; + static STENCIL_BITS : 0x0D57; + STENCIL_BITS : 0x0D57; + static POLYGON_OFFSET_UNITS : 0x2A00; + POLYGON_OFFSET_UNITS : 0x2A00; + static POLYGON_OFFSET_FACTOR : 0x8038; + POLYGON_OFFSET_FACTOR : 0x8038; + static TEXTURE_BINDING_2D : 0x8069; + TEXTURE_BINDING_2D : 0x8069; + static SAMPLE_BUFFERS : 0x80A8; + SAMPLE_BUFFERS : 0x80A8; + static SAMPLES : 0x80A9; + SAMPLES : 0x80A9; + static SAMPLE_COVERAGE_VALUE : 0x80AA; + SAMPLE_COVERAGE_VALUE : 0x80AA; + static SAMPLE_COVERAGE_INVERT : 0x80AB; + SAMPLE_COVERAGE_INVERT : 0x80AB; + static COMPRESSED_TEXTURE_FORMATS : 0x86A3; + COMPRESSED_TEXTURE_FORMATS : 0x86A3; + static DONT_CARE : 0x1100; + DONT_CARE : 0x1100; + static FASTEST : 0x1101; + FASTEST : 0x1101; + static NICEST : 0x1102; + NICEST : 0x1102; + static GENERATE_MIPMAP_HINT : 0x8192; + GENERATE_MIPMAP_HINT : 0x8192; + static BYTE : 0x1400; + BYTE : 0x1400; + static UNSIGNED_BYTE : 0x1401; + UNSIGNED_BYTE : 0x1401; + static SHORT : 0x1402; + SHORT : 0x1402; + static UNSIGNED_SHORT : 0x1403; + UNSIGNED_SHORT : 0x1403; + static INT : 0x1404; + INT : 0x1404; + static UNSIGNED_INT : 0x1405; + UNSIGNED_INT : 0x1405; + static FLOAT : 0x1406; + FLOAT : 0x1406; + static DEPTH_COMPONENT : 0x1902; + DEPTH_COMPONENT : 0x1902; + static ALPHA : 0x1906; + ALPHA : 0x1906; + static RGB : 0x1907; + RGB : 0x1907; + static RGBA : 0x1908; + RGBA : 0x1908; + static LUMINANCE : 0x1909; + LUMINANCE : 0x1909; + static LUMINANCE_ALPHA : 0x190A; + LUMINANCE_ALPHA : 0x190A; + static UNSIGNED_SHORT_4_4_4_4 : 0x8033; + UNSIGNED_SHORT_4_4_4_4 : 0x8033; + static UNSIGNED_SHORT_5_5_5_1 : 0x8034; + UNSIGNED_SHORT_5_5_5_1 : 0x8034; + static UNSIGNED_SHORT_5_6_5 : 0x8363; + UNSIGNED_SHORT_5_6_5 : 0x8363; + static FRAGMENT_SHADER : 0x8B30; + FRAGMENT_SHADER : 0x8B30; + static VERTEX_SHADER : 0x8B31; + VERTEX_SHADER : 0x8B31; + static MAX_VERTEX_ATTRIBS : 0x8869; + MAX_VERTEX_ATTRIBS : 0x8869; + static MAX_VERTEX_UNIFORM_VECTORS : 0x8DFB; + MAX_VERTEX_UNIFORM_VECTORS : 0x8DFB; + static MAX_VARYING_VECTORS : 0x8DFC; + MAX_VARYING_VECTORS : 0x8DFC; + static MAX_COMBINED_TEXTURE_IMAGE_UNITS : 0x8B4D; + MAX_COMBINED_TEXTURE_IMAGE_UNITS : 0x8B4D; + static MAX_VERTEX_TEXTURE_IMAGE_UNITS : 0x8B4C; + MAX_VERTEX_TEXTURE_IMAGE_UNITS : 0x8B4C; + static MAX_TEXTURE_IMAGE_UNITS : 0x8872; + MAX_TEXTURE_IMAGE_UNITS : 0x8872; + static MAX_FRAGMENT_UNIFORM_VECTORS : 0x8DFD; + MAX_FRAGMENT_UNIFORM_VECTORS : 0x8DFD; + static SHADER_TYPE : 0x8B4F; + SHADER_TYPE : 0x8B4F; + static DELETE_STATUS : 0x8B80; + DELETE_STATUS : 0x8B80; + static LINK_STATUS : 0x8B82; + LINK_STATUS : 0x8B82; + static VALIDATE_STATUS : 0x8B83; + VALIDATE_STATUS : 0x8B83; + static ATTACHED_SHADERS : 0x8B85; + ATTACHED_SHADERS : 0x8B85; + static ACTIVE_UNIFORMS : 0x8B86; + ACTIVE_UNIFORMS : 0x8B86; + static ACTIVE_ATTRIBUTES : 0x8B89; + ACTIVE_ATTRIBUTES : 0x8B89; + static SHADING_LANGUAGE_VERSION : 0x8B8C; + SHADING_LANGUAGE_VERSION : 0x8B8C; + static CURRENT_PROGRAM : 0x8B8D; + CURRENT_PROGRAM : 0x8B8D; + static NEVER : 0x0200; + NEVER : 0x0200; + static LESS : 0x0201; + LESS : 0x0201; + static EQUAL : 0x0202; + EQUAL : 0x0202; + static LEQUAL : 0x0203; + LEQUAL : 0x0203; + static GREATER : 0x0204; + GREATER : 0x0204; + static NOTEQUAL : 0x0205; + NOTEQUAL : 0x0205; + static GEQUAL : 0x0206; + GEQUAL : 0x0206; + static ALWAYS : 0x0207; + ALWAYS : 0x0207; + static KEEP : 0x1E00; + KEEP : 0x1E00; + static REPLACE : 0x1E01; + REPLACE : 0x1E01; + static INCR : 0x1E02; + INCR : 0x1E02; + static DECR : 0x1E03; + DECR : 0x1E03; + static INVERT : 0x150A; + INVERT : 0x150A; + static INCR_WRAP : 0x8507; + INCR_WRAP : 0x8507; + static DECR_WRAP : 0x8508; + DECR_WRAP : 0x8508; + static VENDOR : 0x1F00; + VENDOR : 0x1F00; + static RENDERER : 0x1F01; + RENDERER : 0x1F01; + static VERSION : 0x1F02; + VERSION : 0x1F02; + static NEAREST : 0x2600; + NEAREST : 0x2600; + static LINEAR : 0x2601; + LINEAR : 0x2601; + static NEAREST_MIPMAP_NEAREST : 0x2700; + NEAREST_MIPMAP_NEAREST : 0x2700; + static LINEAR_MIPMAP_NEAREST : 0x2701; + LINEAR_MIPMAP_NEAREST : 0x2701; + static NEAREST_MIPMAP_LINEAR : 0x2702; + NEAREST_MIPMAP_LINEAR : 0x2702; + static LINEAR_MIPMAP_LINEAR : 0x2703; + LINEAR_MIPMAP_LINEAR : 0x2703; + static TEXTURE_MAG_FILTER : 0x2800; + TEXTURE_MAG_FILTER : 0x2800; + static TEXTURE_MIN_FILTER : 0x2801; + TEXTURE_MIN_FILTER : 0x2801; + static TEXTURE_WRAP_S : 0x2802; + TEXTURE_WRAP_S : 0x2802; + static TEXTURE_WRAP_T : 0x2803; + TEXTURE_WRAP_T : 0x2803; + static TEXTURE_2D : 0x0DE1; + TEXTURE_2D : 0x0DE1; + static TEXTURE : 0x1702; + TEXTURE : 0x1702; + static TEXTURE_CUBE_MAP : 0x8513; + TEXTURE_CUBE_MAP : 0x8513; + static TEXTURE_BINDING_CUBE_MAP : 0x8514; + TEXTURE_BINDING_CUBE_MAP : 0x8514; + static TEXTURE_CUBE_MAP_POSITIVE_X : 0x8515; + TEXTURE_CUBE_MAP_POSITIVE_X : 0x8515; + static TEXTURE_CUBE_MAP_NEGATIVE_X : 0x8516; + TEXTURE_CUBE_MAP_NEGATIVE_X : 0x8516; + static TEXTURE_CUBE_MAP_POSITIVE_Y : 0x8517; + TEXTURE_CUBE_MAP_POSITIVE_Y : 0x8517; + static TEXTURE_CUBE_MAP_NEGATIVE_Y : 0x8518; + TEXTURE_CUBE_MAP_NEGATIVE_Y : 0x8518; + static TEXTURE_CUBE_MAP_POSITIVE_Z : 0x8519; + TEXTURE_CUBE_MAP_POSITIVE_Z : 0x8519; + static TEXTURE_CUBE_MAP_NEGATIVE_Z : 0x851A; + TEXTURE_CUBE_MAP_NEGATIVE_Z : 0x851A; + static MAX_CUBE_MAP_TEXTURE_SIZE : 0x851C; + MAX_CUBE_MAP_TEXTURE_SIZE : 0x851C; + static TEXTURE0 : 0x84C0; + TEXTURE0 : 0x84C0; + static TEXTURE1 : 0x84C1; + TEXTURE1 : 0x84C1; + static TEXTURE2 : 0x84C2; + TEXTURE2 : 0x84C2; + static TEXTURE3 : 0x84C3; + TEXTURE3 : 0x84C3; + static TEXTURE4 : 0x84C4; + TEXTURE4 : 0x84C4; + static TEXTURE5 : 0x84C5; + TEXTURE5 : 0x84C5; + static TEXTURE6 : 0x84C6; + TEXTURE6 : 0x84C6; + static TEXTURE7 : 0x84C7; + TEXTURE7 : 0x84C7; + static TEXTURE8 : 0x84C8; + TEXTURE8 : 0x84C8; + static TEXTURE9 : 0x84C9; + TEXTURE9 : 0x84C9; + static TEXTURE10 : 0x84CA; + TEXTURE10 : 0x84CA; + static TEXTURE11 : 0x84CB; + TEXTURE11 : 0x84CB; + static TEXTURE12 : 0x84CC; + TEXTURE12 : 0x84CC; + static TEXTURE13 : 0x84CD; + TEXTURE13 : 0x84CD; + static TEXTURE14 : 0x84CE; + TEXTURE14 : 0x84CE; + static TEXTURE15 : 0x84CF; + TEXTURE15 : 0x84CF; + static TEXTURE16 : 0x84D0; + TEXTURE16 : 0x84D0; + static TEXTURE17 : 0x84D1; + TEXTURE17 : 0x84D1; + static TEXTURE18 : 0x84D2; + TEXTURE18 : 0x84D2; + static TEXTURE19 : 0x84D3; + TEXTURE19 : 0x84D3; + static TEXTURE20 : 0x84D4; + TEXTURE20 : 0x84D4; + static TEXTURE21 : 0x84D5; + TEXTURE21 : 0x84D5; + static TEXTURE22 : 0x84D6; + TEXTURE22 : 0x84D6; + static TEXTURE23 : 0x84D7; + TEXTURE23 : 0x84D7; + static TEXTURE24 : 0x84D8; + TEXTURE24 : 0x84D8; + static TEXTURE25 : 0x84D9; + TEXTURE25 : 0x84D9; + static TEXTURE26 : 0x84DA; + TEXTURE26 : 0x84DA; + static TEXTURE27 : 0x84DB; + TEXTURE27 : 0x84DB; + static TEXTURE28 : 0x84DC; + TEXTURE28 : 0x84DC; + static TEXTURE29 : 0x84DD; + TEXTURE29 : 0x84DD; + static TEXTURE30 : 0x84DE; + TEXTURE30 : 0x84DE; + static TEXTURE31 : 0x84DF; + TEXTURE31 : 0x84DF; + static ACTIVE_TEXTURE : 0x84E0; + ACTIVE_TEXTURE : 0x84E0; + static REPEAT : 0x2901; + REPEAT : 0x2901; + static CLAMP_TO_EDGE : 0x812F; + CLAMP_TO_EDGE : 0x812F; + static MIRRORED_REPEAT : 0x8370; + MIRRORED_REPEAT : 0x8370; + static FLOAT_VEC2 : 0x8B50; + FLOAT_VEC2 : 0x8B50; + static FLOAT_VEC3 : 0x8B51; + FLOAT_VEC3 : 0x8B51; + static FLOAT_VEC4 : 0x8B52; + FLOAT_VEC4 : 0x8B52; + static INT_VEC2 : 0x8B53; + INT_VEC2 : 0x8B53; + static INT_VEC3 : 0x8B54; + INT_VEC3 : 0x8B54; + static INT_VEC4 : 0x8B55; + INT_VEC4 : 0x8B55; + static BOOL : 0x8B56; + BOOL : 0x8B56; + static BOOL_VEC2 : 0x8B57; + BOOL_VEC2 : 0x8B57; + static BOOL_VEC3 : 0x8B58; + BOOL_VEC3 : 0x8B58; + static BOOL_VEC4 : 0x8B59; + BOOL_VEC4 : 0x8B59; + static FLOAT_MAT2 : 0x8B5A; + FLOAT_MAT2 : 0x8B5A; + static FLOAT_MAT3 : 0x8B5B; + FLOAT_MAT3 : 0x8B5B; + static FLOAT_MAT4 : 0x8B5C; + FLOAT_MAT4 : 0x8B5C; + static SAMPLER_2D : 0x8B5E; + SAMPLER_2D : 0x8B5E; + static SAMPLER_CUBE : 0x8B60; + SAMPLER_CUBE : 0x8B60; + static VERTEX_ATTRIB_ARRAY_ENABLED : 0x8622; + VERTEX_ATTRIB_ARRAY_ENABLED : 0x8622; + static VERTEX_ATTRIB_ARRAY_SIZE : 0x8623; + VERTEX_ATTRIB_ARRAY_SIZE : 0x8623; + static VERTEX_ATTRIB_ARRAY_STRIDE : 0x8624; + VERTEX_ATTRIB_ARRAY_STRIDE : 0x8624; + static VERTEX_ATTRIB_ARRAY_TYPE : 0x8625; + VERTEX_ATTRIB_ARRAY_TYPE : 0x8625; + static VERTEX_ATTRIB_ARRAY_NORMALIZED : 0x886A; + VERTEX_ATTRIB_ARRAY_NORMALIZED : 0x886A; + static VERTEX_ATTRIB_ARRAY_POINTER : 0x8645; + VERTEX_ATTRIB_ARRAY_POINTER : 0x8645; + static VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : 0x889F; + VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : 0x889F; + static IMPLEMENTATION_COLOR_READ_TYPE : 0x8B9A; + IMPLEMENTATION_COLOR_READ_TYPE : 0x8B9A; + static IMPLEMENTATION_COLOR_READ_FORMAT : 0x8B9B; + IMPLEMENTATION_COLOR_READ_FORMAT : 0x8B9B; + static COMPILE_STATUS : 0x8B81; + COMPILE_STATUS : 0x8B81; + static LOW_FLOAT : 0x8DF0; + LOW_FLOAT : 0x8DF0; + static MEDIUM_FLOAT : 0x8DF1; + MEDIUM_FLOAT : 0x8DF1; + static HIGH_FLOAT : 0x8DF2; + HIGH_FLOAT : 0x8DF2; + static LOW_INT : 0x8DF3; + LOW_INT : 0x8DF3; + static MEDIUM_INT : 0x8DF4; + MEDIUM_INT : 0x8DF4; + static HIGH_INT : 0x8DF5; + HIGH_INT : 0x8DF5; + static FRAMEBUFFER : 0x8D40; + FRAMEBUFFER : 0x8D40; + static RENDERBUFFER : 0x8D41; + RENDERBUFFER : 0x8D41; + static RGBA4 : 0x8056; + RGBA4 : 0x8056; + static RGB5_A1 : 0x8057; + RGB5_A1 : 0x8057; + static RGB565 : 0x8D62; + RGB565 : 0x8D62; + static DEPTH_COMPONENT16 : 0x81A5; + DEPTH_COMPONENT16 : 0x81A5; + static STENCIL_INDEX : 0x1901; + STENCIL_INDEX : 0x1901; + static STENCIL_INDEX8 : 0x8D48; + STENCIL_INDEX8 : 0x8D48; + static DEPTH_STENCIL : 0x84F9; + DEPTH_STENCIL : 0x84F9; + static RENDERBUFFER_WIDTH : 0x8D42; + RENDERBUFFER_WIDTH : 0x8D42; + static RENDERBUFFER_HEIGHT : 0x8D43; + RENDERBUFFER_HEIGHT : 0x8D43; + static RENDERBUFFER_INTERNAL_FORMAT : 0x8D44; + RENDERBUFFER_INTERNAL_FORMAT : 0x8D44; + static RENDERBUFFER_RED_SIZE : 0x8D50; + RENDERBUFFER_RED_SIZE : 0x8D50; + static RENDERBUFFER_GREEN_SIZE : 0x8D51; + RENDERBUFFER_GREEN_SIZE : 0x8D51; + static RENDERBUFFER_BLUE_SIZE : 0x8D52; + RENDERBUFFER_BLUE_SIZE : 0x8D52; + static RENDERBUFFER_ALPHA_SIZE : 0x8D53; + RENDERBUFFER_ALPHA_SIZE : 0x8D53; + static RENDERBUFFER_DEPTH_SIZE : 0x8D54; + RENDERBUFFER_DEPTH_SIZE : 0x8D54; + static RENDERBUFFER_STENCIL_SIZE : 0x8D55; + RENDERBUFFER_STENCIL_SIZE : 0x8D55; + static FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE : 0x8CD0; + FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE : 0x8CD0; + static FRAMEBUFFER_ATTACHMENT_OBJECT_NAME : 0x8CD1; + FRAMEBUFFER_ATTACHMENT_OBJECT_NAME : 0x8CD1; + static FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL : 0x8CD2; + FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL : 0x8CD2; + static FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE : 0x8CD3; + FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE : 0x8CD3; + static COLOR_ATTACHMENT0 : 0x8CE0; + COLOR_ATTACHMENT0 : 0x8CE0; + static DEPTH_ATTACHMENT : 0x8D00; + DEPTH_ATTACHMENT : 0x8D00; + static STENCIL_ATTACHMENT : 0x8D20; + STENCIL_ATTACHMENT : 0x8D20; + static DEPTH_STENCIL_ATTACHMENT : 0x821A; + DEPTH_STENCIL_ATTACHMENT : 0x821A; + static NONE : 0; + NONE : 0; + static FRAMEBUFFER_COMPLETE : 0x8CD5; + FRAMEBUFFER_COMPLETE : 0x8CD5; + static FRAMEBUFFER_INCOMPLETE_ATTACHMENT : 0x8CD6; + FRAMEBUFFER_INCOMPLETE_ATTACHMENT : 0x8CD6; + static FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT : 0x8CD7; + FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT : 0x8CD7; + static FRAMEBUFFER_INCOMPLETE_DIMENSIONS : 0x8CD9; + FRAMEBUFFER_INCOMPLETE_DIMENSIONS : 0x8CD9; + static FRAMEBUFFER_UNSUPPORTED : 0x8CDD; + FRAMEBUFFER_UNSUPPORTED : 0x8CDD; + static FRAMEBUFFER_BINDING : 0x8CA6; + FRAMEBUFFER_BINDING : 0x8CA6; + static RENDERBUFFER_BINDING : 0x8CA7; + RENDERBUFFER_BINDING : 0x8CA7; + static MAX_RENDERBUFFER_SIZE : 0x84E8; + MAX_RENDERBUFFER_SIZE : 0x84E8; + static INVALID_FRAMEBUFFER_OPERATION : 0x0506; + INVALID_FRAMEBUFFER_OPERATION : 0x0506; + static UNPACK_FLIP_Y_WEBGL : 0x9240; + UNPACK_FLIP_Y_WEBGL : 0x9240; + static UNPACK_PREMULTIPLY_ALPHA_WEBGL : 0x9241; + UNPACK_PREMULTIPLY_ALPHA_WEBGL : 0x9241; + static CONTEXT_LOST_WEBGL : 0x9242; + CONTEXT_LOST_WEBGL : 0x9242; + static UNPACK_COLORSPACE_CONVERSION_WEBGL : 0x9243; + UNPACK_COLORSPACE_CONVERSION_WEBGL : 0x9243; + static BROWSER_DEFAULT_WEBGL : 0x9244; + BROWSER_DEFAULT_WEBGL : 0x9244; + + canvas: HTMLCanvasElement; + drawingBufferWidth: number; + drawingBufferHeight: number; + + getContextAttributes(): ?WebGLContextAttributes; + isContextLost(): bool; + + getSupportedExtensions(): ?Array; + getExtension(name: string): any; + + activeTexture(texture: number): void; + attachShader(program: WebGLProgram, shader: WebGLShader): void; + bindAttribLocation(program: WebGLProgram, index: number, name: string): void; + bindBuffer(target: number, buffer: ?WebGLBuffer): void; + bindFramebuffer(target: number, framebuffer: ?WebGLFramebuffer): void; + bindRenderbuffer(target: number, renderbuffer: ?WebGLRenderbuffer): void; + bindTexture(target: number, texture: ?WebGLTexture): void; + blendColor(red: number, green: number, blue: number, alpha: number): void; + blendEquation(mode: number): void; + blendEquationSeparate(modeRGB: number, modeAlpha: number): void; + blendFunc(sfactor: number, dfactor: number): void; + blendFuncSeparate(srcRGB: number, dstRGB: number, srcAlpha: number, dstAlpha: number): void; + + bufferData(target: number, size: number, usage: number): void; + bufferData(target: number, data: ?ArrayBuffer, usage: number): void; + bufferData(target: number, data: $ArrayBufferView, usage: number): void; + bufferSubData(target: number, offset: number, data: BufferDataSource): void; + + checkFramebufferStatus(target: number): number; + clear(mask: number): void; + clearColor(red: number, green: number, blue: number, alpha: number): void; + clearDepth(depth: number): void; + clearStencil(s: number): void; + colorMask(red: bool, green: bool, blue: bool, alpha: bool): void; + compileShader(shader: WebGLShader): void; + + compressedTexImage2D(target: number, level: number, internalformat: number, + width: number, height: number, border: number, + data: $ArrayBufferView): void; + + compressedTexSubImage2D(target: number, level: number, + xoffset: number, yoffset: number, + width: number, height: number, format: number, + data: $ArrayBufferView): void; + + copyTexImage2D(target: number, level: number, internalformat: number, + x: number, y: number, width: number, height: number, + border: number): void; + copyTexSubImage2D(target: number, level: number, xoffset: number, yoffset: number, + x: number, y: number, width: number, height: number): void; + + createBuffer(): ?WebGLBuffer; + createFramebuffer(): ?WebGLFramebuffer; + createProgram(): ?WebGLProgram; + createRenderbuffer(): ?WebGLRenderbuffer; + createShader(type: number): ?WebGLShader; + createTexture(): ?WebGLTexture; + + cullFace(mode: number): void; + + deleteBuffer(buffer: ?WebGLBuffer): void; + deleteFramebuffer(framebuffer: ?WebGLFramebuffer): void; + deleteProgram(program: ?WebGLProgram): void; + deleteRenderbuffer(renderbuffer: ?WebGLRenderbuffer): void; + deleteShader(shader: ?WebGLShader): void; + deleteTexture(texture: ?WebGLTexture): void; + + depthFunc(func: number): void; + depthMask(flag: bool): void; + depthRange(zNear: number, zFar: number): void; + detachShader(program: WebGLProgram, shader: WebGLShader): void; + disable(cap: number): void; + disableVertexAttribArray(index: number): void; + drawArrays(mode: number, first: number, count: number): void; + drawElements(mode: number, count: number, type: number, offset: number): void; + + enable(cap: number): void; + enableVertexAttribArray(index: number): void; + finish(): void; + flush(): void; + framebufferRenderbuffer(target: number, attachment: number, + renderbuffertarget: number, + renderbuffer: ?WebGLRenderbuffer): void; + framebufferTexture2D(target: number, attachment: number, textarget: number, + texture: ?WebGLTexture, level: number): void; + frontFace(mode: number): void; + + generateMipmap(target: number): void; + + getActiveAttrib(program: WebGLProgram, index: number): ?WebGLActiveInfo; + getActiveUniform(program: WebGLProgram, index: number): ?WebGLActiveInfo; + getAttachedShaders(program: WebGLProgram): ?Array; + + getAttribLocation(program: WebGLProgram, name: string): number; + + getBufferParameter(target: number, pname: number): any; + getParameter(pname: number): any; + + getError(): number; + + getFramebufferAttachmentParameter(target: number, attachment: number, + pname: number): any; + getProgramParameter(program: WebGLProgram, pname: number): any; + getProgramInfoLog(program: WebGLProgram): ?string; + getRenderbufferParameter(target: number, pname: number): any; + getShaderParameter(shader: WebGLShader, pname: number): any; + getShaderPrecisionFormat(shadertype: number, precisiontype: number): ?WebGLShaderPrecisionFormat; + getShaderInfoLog(shader: WebGLShader): ?string; + + getShaderSource(shader: WebGLShader): ?string; + + getTexParameter(target: number, pname: number): any; + + getUniform(program: WebGLProgram, location: WebGLUniformLocation): any; + + getUniformLocation(program: WebGLProgram, name: string): ?WebGLUniformLocation; + + getVertexAttrib(index: number, pname: number): any; + + getVertexAttribOffset(index: number, pname: number): number; + + hint(target: number, mode: number): void; + isBuffer(buffer: ?WebGLBuffer): boolean; + isEnabled(cap: number): boolean; + isFramebuffer(framebuffer: ?WebGLFramebuffer): boolean; + isProgram(program: ?WebGLProgram): boolean; + isRenderbuffer(renderbuffer: ?WebGLRenderbuffer): boolean; + isShader(shader: ?WebGLShader): boolean; + isTexture(texture: ?WebGLTexture): boolean; + lineWidth(width: number): void; + linkProgram(program: WebGLProgram): void; + pixelStorei(pname: number, param: number): void; + polygonOffset(factor: number, units: number): void; + + readPixels(x: number, y: number, width: number, height: number, + format: number, type: number, pixels: ?$ArrayBufferView): void; + + renderbufferStorage(target: number, internalformat: number, + width: number, height: number): void; + sampleCoverage(value: number, invert: bool): void; + scissor(x: number, y: number, width: number, height: number): void; + + shaderSource(shader: WebGLShader, source: string): void; + + stencilFunc(func: number, ref: number, mask: number): void; + stencilFuncSeparate(face: number, func: number, ref: number, mask: number): void; + stencilMask(mask: number): void; + stencilMaskSeparate(face: number, mask: number): void; + stencilOp(fail: number, zfail: number, zpass: number): void; + stencilOpSeparate(face: number, fail: number, zfail: number, zpass: number): void; + + texImage2D(target: number, level: number, internalformat: number, + width: number, height: number, border: number, format: number, + type: number, pixels: ?$ArrayBufferView): void; + texImage2D(target: number, level: number, internalformat: number, + format: number, type: number, source: TexImageSource): void; + + texParameterf(target: number, pname: number, param: number): void; + texParameteri(target: number, pname: number, param: number): void; + + texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, + width: number, height: number, + format: number, type: number, pixels: ?$ArrayBufferView): void; + texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, + format: number, type: number, source: TexImageSource): void; + + uniform1f(location: ?WebGLUniformLocation, x: number): void; + uniform1fv(location: ?WebGLUniformLocation, v: Float32Array): void; + uniform1fv(location: ?WebGLUniformLocation, v: Array): void; + uniform1fv(location: ?WebGLUniformLocation, v: [number]): void; + uniform1i(location: ?WebGLUniformLocation, x: number): void; + uniform1iv(location: ?WebGLUniformLocation, v: Int32Array): void; + uniform1iv(location: ?WebGLUniformLocation, v: Array): void; + uniform1iv(location: ?WebGLUniformLocation, v: [number]): void; + uniform2f(location: ?WebGLUniformLocation, x: number, y: number): void; + uniform2fv(location: ?WebGLUniformLocation, v: Float32Array): void; + uniform2fv(location: ?WebGLUniformLocation, v: Array): void; + uniform2fv(location: ?WebGLUniformLocation, v: [number, number]): void; + uniform2i(location: ?WebGLUniformLocation, x: number, y: number): void; + uniform2iv(location: ?WebGLUniformLocation, v: Int32Array): void; + uniform2iv(location: ?WebGLUniformLocation, v: Array): void; + uniform2iv(location: ?WebGLUniformLocation, v: [number, number]): void; + uniform3f(location: ?WebGLUniformLocation, x: number, y: number, z: number): void; + uniform3fv(location: ?WebGLUniformLocation, v: Float32Array): void; + uniform3fv(location: ?WebGLUniformLocation, v: Array): void; + uniform3fv(location: ?WebGLUniformLocation, v: [number, number, number]): void; + uniform3i(location: ?WebGLUniformLocation, x: number, y: number, z: number): void; + uniform3iv(location: ?WebGLUniformLocation, v: Int32Array): void; + uniform3iv(location: ?WebGLUniformLocation, v: Array): void; + uniform3iv(location: ?WebGLUniformLocation, v: [number, number, number]): void; + uniform4f(location: ?WebGLUniformLocation, x: number, y: number, z: number, w: number): void; + uniform4fv(location: ?WebGLUniformLocation, v: Float32Array): void; + uniform4fv(location: ?WebGLUniformLocation, v: Array): void; + uniform4fv(location: ?WebGLUniformLocation, v: [number, number, number, number]): void; + uniform4i(location: ?WebGLUniformLocation, x: number, y: number, z: number, w: number): void; + uniform4iv(location: ?WebGLUniformLocation, v: Int32Array): void; + uniform4iv(location: ?WebGLUniformLocation, v: Array): void; + uniform4iv(location: ?WebGLUniformLocation, v: [number, number, number, number]): void; + + uniformMatrix2fv(location: ?WebGLUniformLocation, transpose: bool, + value: Float32Array): void; + uniformMatrix2fv(location: ?WebGLUniformLocation, transpose: bool, + value: Array): void; + uniformMatrix3fv(location: ?WebGLUniformLocation, transpose: bool, + value: Float32Array): void; + uniformMatrix3fv(location: ?WebGLUniformLocation, transpose: bool, + value: Array): void; + uniformMatrix4fv(location: ?WebGLUniformLocation, transpose: bool, + value: Float32Array): void; + uniformMatrix4fv(location: ?WebGLUniformLocation, transpose: bool, + value: Array): void; + + useProgram(program: ?WebGLProgram): void; + validateProgram(program: WebGLProgram): void; + + vertexAttrib1f(index: number, x: number): void; + vertexAttrib1fv(index: number, values: VertexAttribFVSource): void; + vertexAttrib2f(index: number, x: number, y: number): void; + vertexAttrib2fv(index: number, values: VertexAttribFVSource): void; + vertexAttrib3f(index: number, x: number, y: number, z: number): void; + vertexAttrib3fv(index: number, values: VertexAttribFVSource): void; + vertexAttrib4f(index: number, x: number, y: number, z: number, w: number): void; + vertexAttrib4fv(index: number, values: VertexAttribFVSource): void; + vertexAttribPointer(index: number, size: number, type: number, + normalized: bool, stride: number, offset: number): void; + + viewport(x: number, y: number, width: number, height: number): void; +}; + +declare class WebGLContextEvent extends Event { + statusMessage: string; +}; + +// http://www.w3.org/TR/html5/scripting-1.html#renderingcontext +type RenderingContext = CanvasRenderingContext2D | WebGLRenderingContext; + +// https://www.w3.org/TR/html5/scripting-1.html#htmlcanvaselement +declare class HTMLCanvasElement extends HTMLElement { + width: number; + height: number; + getContext(contextId: "2d", ...args: any): CanvasRenderingContext2D; + getContext(contextId: "webgl", contextAttributes?: $Shape): ?WebGLRenderingContext; + // IE currently only supports "experimental-webgl" + getContext(contextId: "experimental-webgl", contextAttributes?: $Shape): ?WebGLRenderingContext; + getContext(contextId: string, ...args: any): ?RenderingContext; // fallback + toDataURL(type?: string, ...args: any): string; + toBlob(callback: (v: File) => void, type?: string, ...args: any): void; + captureStream(frameRate?: number): CanvasCaptureMediaStream; +} + +// https://html.spec.whatwg.org/multipage/forms.html#the-details-element +declare class HTMLDetailsElement extends HTMLElement { + open: boolean; +} + +declare class HTMLFormElement extends HTMLElement { + @@iterator(): Iterator; + [index: number | string]: HTMLElement | null; + acceptCharset: string; + action: string; + elements: HTMLCollection; + encoding: string; + enctype: string; + length: number; + method: string; + name: string; + target: string; + + checkValidity(): boolean; + reportValidity(): boolean; + reset(): void; + submit(): void; +} + +// https://www.w3.org/TR/html5/forms.html#the-fieldset-element +declare class HTMLFieldSetElement extends HTMLElement { + disabled: boolean; + elements: HTMLCollection; // readonly + form: HTMLFormElement | null; // readonly + name: string; + type: string; // readonly + + checkValidity(): boolean; + setCustomValidity(error: string): void; +} + +declare class HTMLLegendElement extends HTMLElement { + form: HTMLFormElement | null; // readonly +} + +declare class HTMLIFrameElement extends HTMLElement { + allowFullScreen: boolean; + contentDocument: Document; + contentWindow: any; + frameBorder: string; + height: string; + marginHeight: string; + marginWidth: string; + name: string; + scrolling: string; + sandbox: DOMTokenList; + src: string; + srcdoc: string; + width: string; +} + +declare class HTMLImageElement extends HTMLElement { + alt: string; + complete: boolean; // readonly + crossOrigin: ?string; + currentSrc: string; // readonly + height: number; + decode(): Promise; + isMap: boolean; + naturalHeight: number; // readonly + naturalWidth: number; // readonly + sizes: string; + src: string; + srcset: string; + useMap: string; + width: number; +} + +declare class Image extends HTMLImageElement { + constructor(width?: number, height?: number): void; +} + +declare class MediaError { + MEDIA_ERR_ABORTED: number; + MEDIA_ERR_NETWORK: number; + MEDIA_ERR_DECODE: number; + MEDIA_ERR_SRC_NOT_SUPPORTED: number; + code: number; + message: ?string; +} + +declare class TimeRanges { + length: number; + start(index: number): number; + end(index: number): number; +} +declare class Audio extends HTMLAudioElement { + constructor(URLString?: string): void; +} + +declare class AudioTrack { + id: string; + kind: string; + label: string; + language: string; + enabled: boolean; +} + +declare class AudioTrackList extends EventTarget { + length: number; + [index: number]: AudioTrack; + + getTrackById(id: string): ?AudioTrack; + + onchange: (ev: any) => any; + onaddtrack: (ev: any) => any; + onremovetrack: (ev: any) => any; +} + +declare class VideoTrack { + id: string; + kind: string; + label: string; + language: string; + selected: boolean; +} + +declare class VideoTrackList extends EventTarget { + length: number; + [index: number]: VideoTrack; + getTrackById(id: string): ?VideoTrack; + selectedIndex: number; + + onchange: (ev: any) => any; + onaddtrack: (ev: any) => any; + onremovetrack: (ev: any) => any; +} + +declare class TextTrackCue extends EventTarget { + constructor(startTime: number, endTime: number, text: string): void; + + track: TextTrack; + id: string; + startTime: number; + endTime: number; + pauseOnExit: boolean; + vertical: string; + snapToLines: boolean; + lines: number; + position: number; + size: number; + align: string; + text: string; + + getCueAsHTML(): Node; + onenter: (ev: any) => any; + onexit: (ev: any) => any; +} + +declare class TextTrackCueList { + @@iterator(): Iterator; + length: number; + [index: number]: TextTrackCue; + getCueById(id: string): ?TextTrackCue; +} + +declare class TextTrack extends EventTarget { + kind: string; + label: string; + language: string; + + mode: string; + + cues: TextTrackCueList; + activeCues: TextTrackCueList; + + addCue(cue: TextTrackCue): void; + removeCue(cue: TextTrackCue): void; + + oncuechange: (ev: any) => any; +} + +declare class TextTrackList extends EventTarget { + length: number; + [index: number]: TextTrack; + + onaddtrack: (ev: any) => any; + onremovetrack: (ev: any) => any; +} + +declare class MediaKeyStatusMap { + @@iterator(): Iterator<[BufferDataSource, MediaKeyStatus]>; + size: number; + entries(): Iterator<[BufferDataSource, MediaKeyStatus]>; + forEach(callbackfn: (value: MediaKeyStatus, key: BufferDataSource, map: MediaKeyStatusMap) => any, thisArg?: any): void; + get(key: BufferDataSource): MediaKeyStatus; + has(key: BufferDataSource): boolean; + keys(): Iterator; + values(): Iterator; +} + +declare class MediaKeySession extends EventTarget { + sessionId: string; + expiration: number; + closed: Promise; + keyStatuses: MediaKeyStatusMap; + + generateRequest(initDataType: string, initData: BufferDataSource): Promise; + load(sessionId: string): Promise; + update(response: BufferDataSource): Promise; + close(): Promise; + remove(): Promise; + + onkeystatuschange: (ev: any) => any; + onmessage: (ev: any) => any; +} + +declare class MediaKeys { + createSession(mediaKeySessionType: MediaKeySessionType): MediaKeySession; + setServerCertificate(serverCertificate: BufferDataSource): Promise; +} + +declare class HTMLMediaElement extends HTMLElement { + // error state + error: ?MediaError; + + // network state + src: string; + srcObject: ?any; + currentSrc: string; + crossOrigin: ?string; + NETWORK_EMPTY: number; + NETWORK_IDLE: number; + NETWORK_LOADING: number; + NETWORK_NO_SOURCE: number; + networkState: number; + preload: string; + buffered: TimeRanges; + load(): void; + canPlayType(type: string): string; + + // ready state + HAVE_NOTHING: number; + HAVE_METADATA: number; + HAVE_CURRENT_DATA: number; + HAVE_FUTURE_DATA: number; + HAVE_ENOUGH_DATA: number; + readyState: number; + seeking: boolean; + + // playback state + currentTime: number; + duration: number; + startDate: Date; + paused: boolean; + defaultPlaybackRate: number; + playbackRate: number; + played: TimeRanges; + seekable: TimeRanges; + ended: boolean; + autoplay: boolean; + loop: boolean; + play(): Promise; + pause(): void; + fastSeek(): void; + captureStream(): MediaStream; + + // media controller + mediaGroup: string; + controller: ?any; + + // controls + controls: boolean; + volume: number; + muted: boolean; + defaultMuted: boolean; + controlsList?: DOMTokenList; + + // tracks + audioTracks: AudioTrackList; + videoTracks: VideoTrackList; + textTracks: TextTrackList; + addTextTrack(kind: string, label?: string, language?: string): TextTrack; + + // media keys + mediaKeys?: ?MediaKeys; + setMediakeys?: (mediakeys: ?MediaKeys) => Promise; +} + +declare class HTMLAudioElement extends HTMLMediaElement { +} + +declare class HTMLVideoElement extends HTMLMediaElement { + width: number; + height: number; + videoWidth: number; + videoHeight: number; + poster: string; +} + +declare class HTMLSourceElement extends HTMLElement { + src: string; + type: string; + + //when used with the picture element + srcset: string; + sizes: string; + media: string; +} + +declare class ValidityState { + badInput: boolean; + customError: boolean; + patternMismatch: boolean; + rangeOverflow: boolean; + rangeUnderflow: boolean; + stepMismatch: boolean; + tooLong: boolean; + tooShort: boolean; + typeMismatch: boolean; + valueMissing: boolean; + valid: boolean; +} + +// https://w3c.github.io/html/sec-forms.html#dom-selectionapielements-setselectionrange +type SelectionDirection = 'backward' | 'forward' | 'none'; +type SelectionMode = 'select' | 'start' | 'end' | 'preserve'; +declare class HTMLInputElement extends HTMLElement { + accept: string; + align: string; + alt: string; + autocomplete: string; + autofocus: boolean; + border: string; + checked: boolean; + complete: boolean; + defaultChecked: boolean; + defaultValue: string; + dirname: string; + disabled: boolean; + dynsrc: string; + files: FileList; + form: HTMLFormElement | null; + formAction: string; + formEncType: string; + formMethod: string; + formNoValidate: boolean; + formTarget: string; + height: string; + hspace: number; + indeterminate: boolean; + labels: NodeList; + list: HTMLElement | null; + loop: number; + lowsrc: string; + max: string; + maxLength: number; + min: string; + multiple: boolean; + name: string; + pattern: string; + placeholder: string; + readOnly: boolean; + required: boolean; + selectionDirection: SelectionDirection; + selectionEnd: number; + selectionStart: number; + size: number; + src: string; + start: string; + status: boolean; + step: string; + tabIndex: number; + type: string; + useMap: string; + validationMessage: string; + validity: ValidityState; + value: string; + valueAsDate: Date; + valueAsNumber: number; + vrml: string; + vspace: number; + width: string; + willValidate: boolean; + + blur(): void; + checkValidity(): boolean; + reportValidity(): boolean; + setCustomValidity(error: string): void; + click(): void; + createTextRange(): TextRange; + focus(): void; + select(): void; + setRangeText(replacement: string, start?: void, end?: void, selectMode?: void): void; + setRangeText(replacement: string, start: number, end: number, selectMode?: SelectionMode): void; + setSelectionRange(start: number, end: number, direction?: SelectionDirection): void; +} + +declare class HTMLButtonElement extends HTMLElement { + autofocus: boolean; + disabled: boolean; + form: HTMLFormElement | null; + labels: NodeList | null; + name: string; + type: string; + validationMessage: string; + validity: ValidityState; + value: string; + willValidate: boolean; + + checkValidity(): boolean; + reportValidity(): boolean; + setCustomValidity(error: string): void; +} + +// https://w3c.github.io/html/sec-forms.html#the-textarea-element +declare class HTMLTextAreaElement extends HTMLElement { + autofocus: boolean; + cols: number; + dirName: string; + disabled: boolean; + form: HTMLFormElement | null; + maxLength: number; + name: string; + placeholder: string; + readOnly: boolean; + required: boolean; + rows: number; + wrap: string; + + type: string; + defaultValue: string; + value: string; + textLength: number; + + willValidate: boolean; + validity: ValidityState; + validationMessage: string; + checkValidity(): boolean; + setCustomValidity(error: string): void; + + labels: NodeList; + + select(): void; + selectionStart: number; + selectionEnd: number; + selectionDirection: SelectionDirection; + setSelectionRange(start: number, end: number, direction?: SelectionDirection): void; +} + +declare class HTMLSelectElement extends HTMLElement { + autocomplete: string; + autofocus: boolean; + disabled: boolean; + form: HTMLFormElement | null; + labels: NodeList; + length: number; + multiple: boolean; + name: string; + options: HTMLOptionsCollection; + required: boolean; + selectedIndex: number; + selectedOptions: HTMLCollection; + size: number; + type: string; + validationMessage: string; + validity: ValidityState; + value: string; + willValidate: boolean; + + add(element: HTMLElement, before?: HTMLElement): void; + checkValidity(): boolean; + item(index: number): HTMLOptionElement | null; + namedItem(name: string): HTMLOptionElement | null; + remove(index?: number): void; + setCustomValidity(error: string): void; +} + +declare class HTMLOptionsCollection extends HTMLCollection { + selectedIndex: number; + add(element: HTMLOptionElement | HTMLOptGroupElement, before?: HTMLElement | number): void; + remove(index: number): void; +} + +declare class HTMLOptionElement extends HTMLElement { + defaultSelected: boolean; + disabled: boolean; + form: HTMLFormElement | null; + index: number; + label: string; + selected: boolean; + text: string; + value: string; +} + +declare class HTMLOptGroupElement extends HTMLElement { + disabled: boolean; + label: string; +} + +declare class HTMLAnchorElement extends HTMLElement { + charset: string; + coords: string; + download: string; + hash: string; + host: string; + hostname: string; + href: string; + hreflang: string; + media: string; + name: string; + origin: string; + password: string; + pathname: string; + port: string; + protocol: string; + rel: string; + rev: string; + search: string; + shape: string; + target: string; + text: string; + type: string; + username: string; +} + +// https://w3c.github.io/html/sec-forms.html#the-label-element +declare class HTMLLabelElement extends HTMLElement { + form: HTMLFormElement | null; + htmlFor: string; + control: HTMLElement | null; +} + +declare class HTMLLinkElement extends HTMLElement { + crossOrigin: ?('anonymous' | 'use-credentials'); + href: string; + hreflang: string; + media: string; + rel: string; + sizes: DOMTokenList; + type: string; + as: string; +} + +declare class HTMLScriptElement extends HTMLElement { + async: boolean; + charset: string; + crossOrigin?: string; + defer: boolean; + src: string; + text: string; + type: string; +} + +declare class HTMLStyleElement extends HTMLElement { + disabled: boolean; + media: string; + scoped: boolean; + sheet: ?CSSStyleSheet; + type: string; +} + +declare class HTMLParagraphElement extends HTMLElement { + align: 'left' | 'center' | 'right' | 'justify'; // deprecated in HTML 4.01 +} + +declare class HTMLHtmlElement extends HTMLElement {} + +declare class HTMLBodyElement extends HTMLElement {} + +declare class HTMLHeadElement extends HTMLElement {} + +declare class HTMLDivElement extends HTMLElement {} + +declare class HTMLSpanElement extends HTMLElement {} + +declare class HTMLAppletElement extends HTMLElement {} + +declare class HTMLHeadingElement extends HTMLElement {} + +declare class HTMLHRElement extends HTMLElement {} + +declare class HTMLBRElement extends HTMLElement {} + +declare class HTMLDListElement extends HTMLElement {} + +declare class HTMLAreaElement extends HTMLElement { + alt: string; + coords: string; + shape: string; + target: string; + download: string; + ping: string; + rel: string; + relList: DOMTokenList; + referrerPolicy: string; +} + +declare class HTMLDataElement extends HTMLElement { + value: string; +} + +declare class HTMLDataListElement extends HTMLElement { + options: HTMLCollection; +} + +declare class HTMLDialogElement extends HTMLElement { + open: boolean; + returnValue: string; + show(): void; + showModal(): void; + close(returnValue: ?string): void; +} + +declare class HTMLEmbedElement extends HTMLElement { + src: string; + type: string; + width: string; + height: string; + getSVGDocument(): ?Document; +} + +declare class HTMLMapElement extends HTMLElement { + areas: HTMLCollection; + images: HTMLCollection; + name: string; +} + +declare class HTMLMeterElement extends HTMLElement { + high: number; + low: number; + max: number; + min: number; + optimum: number; + value: number; + labels: NodeList; +} + +declare class HTMLModElement extends HTMLElement { + cite: string; + dateTime: string; +} + +declare class HTMLObjectElement extends HTMLElement { + contentDocument: ?Document; + contentWindow: ?WindowProxy; + data: string; + form: ?HTMLFormElement; + height: string; + name: string; + type: string; + typeMustMatch: boolean; + useMap: string; + validationMessage: string; + validity: ValidityState; + width: string; + willValidate: boolean; + checkValidity(): boolean; + getSVGDocument(): ?Document; + reportValidity(): boolean; + setCustomValidity(error: string): void; +} + +declare class HTMLOutputElement extends HTMLElement { + defaultValue: string; + form: ?HTMLFormElement; + htmlFor: DOMTokenList; + labels: NodeList; + name: string; + type: string; + validationMessage: string; + validity: ValidityState; + value: string; + willValidate: boolean; + checkValidity(): boolean; + reportValidity(): boolean; + setCustomValidity(error: string): void; +} + +declare class HTMLParamElement extends HTMLElement { + name: string; + value: string; +} + +declare class HTMLProgressElement extends HTMLElement { + labels: NodeList; + max: number; + position: number; + value: number; +} + +declare class HTMLPictureElement extends HTMLElement {} + +declare class HTMLTableColElement extends HTMLElement { + span: number; +} + +declare class HTMLTimeElement extends HTMLElement { + dateTime: string; +} + +declare class HTMLTitleElement extends HTMLElement { + text: string; +} + +declare class HTMLTrackElement extends HTMLElement { + static NONE: 0; + static LOADING: 1; + static LOADED: 2; + static ERROR: 3; + + default: boolean; + kind: string; + label: string; + readyState: 0 | 1 | 2 | 3; + src: string; + srclang: string; + track: TextTrack; +} + +declare class HTMLQuoteElement extends HTMLElement { + cite: string; +} + +declare class HTMLOListElement extends HTMLElement { + reversed: boolean; + start: number; + type: string; +} + +declare class HTMLUListElement extends HTMLElement {} + +declare class HTMLLIElement extends HTMLElement { + value: number; +} + +declare class HTMLPreElement extends HTMLElement {} + +declare class HTMLMetaElement extends HTMLElement { + content: string; + httpEquiv: string; + name: string; +} + +declare class HTMLUnknownElement extends HTMLElement {} + +declare class TextRange { + boundingLeft: number; + htmlText: string; + offsetLeft: number; + boundingWidth: number; + boundingHeight: number; + boundingTop: number; + text: string; + offsetTop: number; + moveToPoint(x: number, y: number): void; + queryCommandValue(cmdID: string): any; + getBookmark(): string; + move(unit: string, count?: number): number; + queryCommandIndeterm(cmdID: string): boolean; + scrollIntoView(fStart?: boolean): void; + findText(string: string, count?: number, flags?: number): boolean; + execCommand(cmdID: string, showUI?: boolean, value?: any): boolean; + getBoundingClientRect(): ClientRect | DOMRect; + moveToBookmark(bookmark: string): boolean; + isEqual(range: TextRange): boolean; + duplicate(): TextRange; + collapse(start?: boolean): void; + queryCommandText(cmdID: string): string; + select(): void; + pasteHTML(html: string): void; + inRange(range: TextRange): boolean; + moveEnd(unit: string, count?: number): number; + getClientRects(): ClientRectList | DOMRectList; + moveStart(unit: string, count?: number): number; + parentElement(): Element; + queryCommandState(cmdID: string): boolean; + compareEndPoints(how: string, sourceRange: TextRange): number; + execCommandShowHelp(cmdID: string): boolean; + moveToElementText(element: Element): void; + expand(Unit: string): boolean; + queryCommandSupported(cmdID: string): boolean; + setEndPoint(how: string, SourceRange: TextRange): void; + queryCommandEnabled(cmdID: string): boolean; +} + +declare class ClientRect { // extension + left: number; + width: number; + right: number; + top: number; + bottom: number; + height: number; +} + +declare class ClientRectList { // extension + @@iterator(): Iterator; + length: number; + item(index: number): ClientRect; + [index: number]: ClientRect; +} + +// TODO: HTML*Element + +declare class DOMImplementation { + createDocumentType(qualifiedName: string, publicId: string, systemId: string): DocumentType; + createDocument(namespaceURI: string | null, qualifiedName: string, doctype?: DocumentType | null): Document; + hasFeature(feature: string, version?: string): boolean; + + // non-standard + createHTMLDocument(title?: string): Document; +} + +declare class DocumentType extends Node { + name: string; + notations: NamedNodeMap; + systemId: string; + internalSubset: string; + entities: NamedNodeMap; + publicId: string; + + // from ChildNode interface + after(...nodes: Array): void; + before(...nodes: Array): void; + replaceWith(...nodes: Array): void; + remove(): void; +} + +declare class CharacterData extends Node { + length: number; + data: string; + deleteData(offset: number, count: number): void; + replaceData(offset: number, count: number, arg: string): void; + appendData(arg: string): void; + insertData(offset: number, arg: string): void; + substringData(offset: number, count: number): string; + + // from ChildNode interface + after(...nodes: Array): void; + before(...nodes: Array): void; + replaceWith(...nodes: Array): void; + remove(): void; +} + +declare class Text extends CharacterData { + assignedSlot?: HTMLSlotElement; + wholeText: string; + splitText(offset: number): Text; + replaceWholeText(content: string): Text; +} + +declare class Comment extends CharacterData { + text: string; +} + +declare class URL { + static createObjectURL(blob: Blob): string; + static createObjectURL(mediaSource: MediaSource): string; + static createFor(blob: Blob): string; + static revokeObjectURL(url: string): void; + constructor(url: string, base?: string | URL): void; + hash: string; + host: string; + hostname: string; + href: string; + origin: string; // readonly + password: string; + pathname: string; + port: string; + protocol: string; + search: string; + searchParams: URLSearchParams; // readonly + username: string; +} + +declare class MediaSource extends EventTarget { + sourceBuffers: SourceBufferList; + activeSourceBuffers: SourceBufferList; + readyState: "closed" | "opened" | "ended"; + duration: number; + addSourceBuffer(type: string): SourceBuffer; + removeSourceBuffer(sourceBuffer: SourceBuffer): void; + endOfStream(error?: string): void; + static isTypeSupported(type: string): bool; +} + +declare class SourceBuffer extends EventTarget { + mode: "segments" | "sequence"; + updating: bool; + buffered: TimeRanges; + timestampOffset: number; + audioTracks: AudioTrackList; + videoTracks: VideoTrackList; + textTracks: TextTrackList; + appendWindowStart: number; + appendWindowEnd: number; + + appendBuffer(data: ArrayBuffer | $ArrayBufferView): void; + // TODO: Add ReadableStream + // appendStream(stream: ReadableStream, maxSize?: number): void; + abort(): void; + remove(start: number, end: number): void; + + trackDefaults: TrackDefaultList; +} + +declare class SourceBufferList extends EventTarget { + @@iterator(): Iterator; + [index: number]: SourceBuffer; + length: number; +} + +declare class Storage { + length: number; + getItem(key: string): ?string; + setItem(key: string, data: string): void; + clear(): void; + removeItem(key: string): void; + key(index: number): ?string; + [name: string]: ?string; +} + +declare class TrackDefaultList { + [index: number]: TrackDefault; + length: number; +} + +declare class TrackDefault { + type: "audio" | "video" | "text"; + byteStreamTrackID: string; + language: string; + label: string; + kinds: Array; +} + +// TODO: The use of `typeof` makes this function signature effectively +// (node: Node) => number, but it should be (node: Node) => 1|2|3 +type NodeFilterCallback = (node: Node) => +typeof NodeFilter.FILTER_ACCEPT | +typeof NodeFilter.FILTER_REJECT | +typeof NodeFilter.FILTER_SKIP; + +type NodeFilterInterface = NodeFilterCallback | { acceptNode: NodeFilterCallback, ... } + +// TODO: window.NodeFilter exists at runtime and behaves as a constructor +// as far as `instanceof` is concerned, but it is not callable. +declare class NodeFilter { + static SHOW_ALL: -1; + static SHOW_ELEMENT: 1; + static SHOW_ATTRIBUTE: 2; // deprecated + static SHOW_TEXT: 4; + static SHOW_CDATA_SECTION: 8; // deprecated + static SHOW_ENTITY_REFERENCE: 16; // deprecated + static SHOW_ENTITY: 32; // deprecated + static SHOW_PROCESSING_INSTRUCTION: 64; + static SHOW_COMMENT: 128; + static SHOW_DOCUMENT: 256; + static SHOW_DOCUMENT_TYPE: 512; + static SHOW_DOCUMENT_FRAGMENT: 1024; + static SHOW_NOTATION: 2048; // deprecated + static FILTER_ACCEPT: 1; + static FILTER_REJECT: 2; + static FILTER_SKIP: 3; + acceptNode: NodeFilterCallback; +} + +// TODO: window.NodeIterator exists at runtime and behaves as a constructor +// as far as `instanceof` is concerned, but it is not callable. +declare class NodeIterator { + root: RootNodeT; + whatToShow: number; + filter: NodeFilter; + expandEntityReferences: boolean; + referenceNode: RootNodeT | WhatToShowT; + pointerBeforeReferenceNode: boolean; + detach(): void; + previousNode(): WhatToShowT | null; + nextNode(): WhatToShowT | null; +} + +// TODO: window.TreeWalker exists at runtime and behaves as a constructor +// as far as `instanceof` is concerned, but it is not callable. +declare class TreeWalker { + root: RootNodeT; + whatToShow: number; + filter: NodeFilter; + expandEntityReferences: boolean; + currentNode: RootNodeT | WhatToShowT; + parentNode(): WhatToShowT | null; + firstChild(): WhatToShowT | null; + lastChild(): WhatToShowT | null; + previousSibling(): WhatToShowT | null; + nextSibling(): WhatToShowT | null; + previousNode(): WhatToShowT | null; + nextNode(): WhatToShowT | null; +} + +/* window */ + +declare type WindowProxy = any; +declare function alert(message?: any): void; +declare function prompt(message?: any, value?: any): string; +declare function close(): void; +declare function confirm(message?: string): boolean; +declare function getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration; +declare opaque type AnimationFrameID; +declare function requestAnimationFrame(callback: (timestamp: number) => void): AnimationFrameID; +declare function cancelAnimationFrame(requestId: AnimationFrameID): void; +declare opaque type IdleCallbackID; +declare function requestIdleCallback( + cb: (deadline: { + didTimeout: boolean, + timeRemaining: () => number, + ... + }) => void, + opts?: { timeout: number, ... }, +): IdleCallbackID; +declare function cancelIdleCallback(id: IdleCallbackID): void; +declare var localStorage: Storage; +declare function focus(): void; +declare function onfocus(ev: Event): any; +declare function onmessage(ev: MessageEvent): any; +declare function open(url?: string, target?: string, features?: string, replace?: boolean): any; +declare var parent: WindowProxy; +declare function print(): void; +declare var self: any; +declare var sessionStorage: Storage; +declare var status: string; +declare var top: WindowProxy; +declare function getSelection(): Selection | null; +declare var customElements: CustomElementRegistry; +declare function scroll(x: number, y: number): void; +declare function scroll(options: ScrollToOptions): void; +declare function scrollTo(x: number, y: number): void; +declare function scrollTo(options: ScrollToOptions): void; +declare function scrollBy(x: number, y: number): void; +declare function scrollBy(options: ScrollToOptions): void; + +/* Notification */ +type NotificationPermission = 'default' | 'denied' | 'granted'; +type NotificationDirection = 'auto' | 'ltr' | 'rtl'; +type VibratePattern = number | Array; +type NotificationAction = { + action: string, + title: string, + icon?: string, + ... +}; +type NotificationOptions = { + dir?: NotificationDirection, + lang?: string, + body?: string, + tag?: string, + image?: string, + icon?: string, + badge?: string, + sound?: string, + vibrate?: VibratePattern, + timestamp?: number, + renotify?: boolean, + silent?: boolean, + requireInteraction?: boolean, + data?: ?any, + actions?: Array, + ... +}; + +declare class Notification extends EventTarget { + constructor(title: string, options?: NotificationOptions): void; + static +permission: NotificationPermission; + static requestPermission( + callback?: (perm: NotificationPermission) => mixed + ): Promise; + static +maxActions: number; + onclick: ?(evt: Event) => mixed; + onclose: ?(evt: Event) => mixed; + onerror: ?(evt: Event) => mixed; + onshow: ?(evt: Event) => mixed; + +title: string; + +dir: NotificationDirection; + +lang: string; + +body: string; + +tag: string; + +image?: string; + +icon?: string; + +badge?: string; + +vibrate?: Array; + +timestamp: number; + +renotify: boolean; + +silent: boolean; + +requireInteraction: boolean; + +data: any; + +actions: Array; + + close(): void; +} diff --git a/newIDE/app/flow-libs/indexeddb.js b/newIDE/app/flow-libs/indexeddb.js new file mode 100644 index 0000000000..c24e71af2e --- /dev/null +++ b/newIDE/app/flow-libs/indexeddb.js @@ -0,0 +1,127 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// Implemented by window & worker +declare interface IDBEnvironment { + indexedDB: IDBFactory; +} + +type IDBDirection = 'next' | 'nextunique' | 'prev' | 'prevunique'; + +// Implemented by window.indexedDB & worker.indexedDB +declare interface IDBFactory { + open(name: string, version?: number): IDBOpenDBRequest; + deleteDatabase(name: string): IDBOpenDBRequest; + cmp(a: any, b: any): -1|0|1; +} + +declare interface IDBRequest extends EventTarget { + result: IDBObjectStore; + error: Error; + source: ?(IDBIndex | IDBObjectStore | IDBCursor); + transaction: IDBTransaction; + readyState: 'pending'|'done'; + onerror: (err: any) => mixed; + onsuccess: (e: any) => mixed; +} + +declare interface IDBOpenDBRequest extends IDBRequest { + onblocked: (e: any) => mixed; + onupgradeneeded: (e: any) => mixed; +} + +declare interface IDBDatabase extends EventTarget { + close(): void; + createObjectStore(name: string, options?: { + keyPath?: ?(string|string[]), + autoIncrement?: bool, + ... + }): IDBObjectStore; + deleteObjectStore(name: string): void; + transaction(storeNames: string|string[], mode?: 'readonly'|'readwrite'|'versionchange'): IDBTransaction; + name: string; + version: number; + objectStoreNames: string[]; + onabort: (e: any) => mixed; + onclose: (e: any) => mixed; + onerror: (e: any) => mixed; + onversionchange: (e: any) => mixed; +} + +declare interface IDBTransaction extends EventTarget { + abort(): void; + db: IDBDatabase; + error: Error; + mode: 'readonly'|'readwrite'|'versionchange'; + name: string; + objectStore(name: string): IDBObjectStore; + onabort: (e: any) => mixed; + oncomplete: (e: any) => mixed; + onerror: (e: any) => mixed; +} + +declare interface IDBObjectStore { + add(value: any, key?: any): IDBRequest; + autoIncrement: bool; + clear(): IDBRequest; + createIndex(indexName: string, keyPath: string|string[], optionalParameter?: { + unique?: bool, + multiEntry?: bool, + ... + }): IDBIndex; + count(keyRange?: any|IDBKeyRange): IDBRequest; + delete(key: any): IDBRequest; + deleteIndex(indexName: string): void; + get(key: any): IDBRequest; + index(indexName: string): IDBIndex; + indexNames: string[]; + name: string; + keyPath: any; + openCursor(range?: any|IDBKeyRange, direction?: IDBDirection): IDBRequest; + openKeyCursor(range?: any|IDBKeyRange, direction?: IDBDirection): IDBRequest; + put(value: any, key?: any): IDBRequest; + transaction : IDBTransaction; +} + +declare interface IDBIndex extends EventTarget { + count(key?: any|IDBKeyRange): IDBRequest; + get(key: any|IDBKeyRange): IDBRequest; + getKey(key: any|IDBKeyRange): IDBRequest; + openCursor(range?: any|IDBKeyRange, direction?: IDBDirection): IDBRequest; + openKeyCursor(range?: any|IDBKeyRange, direction?: IDBDirection): IDBRequest; + name: string; + objectStore: IDBObjectStore; + keyPath: any; + multiEntry: bool; + unique: bool; +} + +declare interface IDBKeyRange { + bound(lower: any, upper: any, lowerOpen?: bool, upperOpen?: bool): IDBKeyRange; + only(value: any): IDBKeyRange; + lowerBound(bound: any, open?: bool): IDBKeyRange; + upperBound(bound: any, open?: bool): IDBKeyRange; + lower: any; + upper: any; + lowerOpen: bool; + upperOpen: bool; +} + +declare interface IDBCursor { + advance(count: number): void; + continue(key?: any): void; + delete(): IDBRequest; + update(newValue: any): IDBRequest; + source: IDBObjectStore|IDBIndex; + direction: IDBDirection; + key: any; + primaryKey: any; +} + +declare interface IDBCursorWithValue extends IDBCursor { + value: any; +} diff --git a/newIDE/app/flow-libs/intl.js b/newIDE/app/flow-libs/intl.js new file mode 100644 index 0000000000..275502858f --- /dev/null +++ b/newIDE/app/flow-libs/intl.js @@ -0,0 +1,196 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +declare var Intl: { + Collator: Class, + DateTimeFormat: Class, + NumberFormat: Class, + PluralRules: ?Class, + getCanonicalLocales?: (locales?: Intl$Locales) => Intl$Locale[], + ... +} + +type Intl$Locale = string +type Intl$Locales = Intl$Locale | Intl$Locale[] + +declare class Intl$Collator { + constructor ( + locales?: Intl$Locales, + options?: Intl$CollatorOptions + ): Intl$Collator; + + static ( + locales?: Intl$Locales, + options?: Intl$CollatorOptions + ): Intl$Collator; + + compare (string, string): number; + + resolvedOptions (): { + locale: Intl$Locale, + usage: 'sort' | 'search', + sensitivity: 'base' | 'accent' | 'case' | 'variant', + ignorePunctuation: boolean, + collation: string, + numeric: boolean, + caseFirst?: 'upper' | 'lower' | 'false', + ... + }; + + static supportedLocalesOf (locales?: Intl$Locales): Intl$Locale[]; +} + +declare type Intl$CollatorOptions = { + localeMatcher?: 'lookup' | 'best fit', + usage?: 'sort' | 'search', + sensitivity?: 'base' | 'accent' | 'case' | 'variant', + ignorePunctuation?: boolean, + numeric?: boolean, + caseFirst?: 'upper' | 'lower' | 'false', + ... +} + +type FormatToPartsType = | 'day' | 'dayPeriod' | 'era' | 'hour' | 'literal' + | 'minute' | 'month' | 'second' | 'timeZoneName' | 'weekday' | 'year'; + +declare class Intl$DateTimeFormat { + constructor ( + locales?: Intl$Locales, + options?: Intl$DateTimeFormatOptions + ): Intl$DateTimeFormat; + + static ( + locales?: Intl$Locales, + options?: Intl$DateTimeFormatOptions + ): Intl$DateTimeFormat; + + format (value?: Date | number): string; + + formatToParts (value?: Date | number): Array<{ + type: FormatToPartsType, + value: string, + ... + }>; + + resolvedOptions (): { + locale: Intl$Locale, + calendar: string, + numberingSystem: string, + timeZone?: string, + hour12: boolean, + weekday?: 'narrow' | 'short' | 'long', + era?: 'narrow' | 'short' | 'long', + year?: 'numeric' | '2-digit', + month?: 'numeric' | '2-digit' | 'narrow' | 'short' | 'long', + day?: 'numeric' | '2-digit', + hour?: 'numeric' | '2-digit', + minute?: 'numeric' | '2-digit', + second?: 'numeric' | '2-digit', + timeZoneName?: 'short' | 'long', + ... + }; + + static supportedLocalesOf (locales?: Intl$Locales): Intl$Locale[]; +} + +declare type Intl$DateTimeFormatOptions = { + localeMatcher?: 'lookup' | 'best fit', + timeZone?: string, + hour12?: boolean, + formatMatcher?: 'basic' | 'best fit', + weekday?: 'narrow' | 'short' | 'long', + era?: 'narrow' | 'short' | 'long', + year?: 'numeric' | '2-digit', + month?: 'numeric' | '2-digit' | 'narrow' | 'short' | 'long', + day?: 'numeric' | '2-digit', + hour?: 'numeric' | '2-digit', + minute?: 'numeric' | '2-digit', + second?: 'numeric' | '2-digit', + timeZoneName?: 'short' | 'long', + ... +} + +declare class Intl$NumberFormat { + constructor ( + locales?: Intl$Locales, + options?: Intl$NumberFormatOptions + ): Intl$NumberFormat; + + static ( + locales?: Intl$Locales, + options?: Intl$NumberFormatOptions + ): Intl$NumberFormat; + + format (number): string; + + resolvedOptions (): { + locale: Intl$Locale, + numberingSystem: string, + style: 'decimal' | 'currency' | 'percent', + currency?: string, + currencyDisplay?: 'symbol' | 'code' | 'name', + useGrouping: boolean, + minimumIntegerDigits?: number, + minimumFractionDigits?: number, + maximumFractionDigits?: number, + minimumSignificantDigits?: number, + maximumSignificantDigits?: number, + ... + }; + + static supportedLocalesOf (locales?: Intl$Locales): Intl$Locale[]; +} + +declare type Intl$NumberFormatOptions = { + localeMatcher?: 'lookup' | 'best fit', + style?: 'decimal' | 'currency' | 'percent', + currency?: string, + currencyDisplay?: 'symbol' | 'code' | 'name', + useGrouping?: boolean, + minimumIntegerDigits?: number, + minimumFractionDigits?: number, + maximumFractionDigits?: number, + minimumSignificantDigits?: number, + maximumSignificantDigits?: number, + ... +} + +declare class Intl$PluralRules { + constructor ( + locales?: Intl$Locales, + options?: Intl$PluralRulesOptions + ): Intl$PluralRules; + + select (number): Intl$PluralRule; + + resolvedOptions (): { + locale: Intl$Locale, + type: 'cardinal' | 'ordinal', + minimumIntegerDigits?: number, + minimumFractionDigits?: number, + maximumFractionDigits?: number, + minimumSignificantDigits?: number, + maximumSignificantDigits?: number, + pluralCategories: Intl$PluralRule[], + ... + }; + + static supportedLocalesOf (locales?: Intl$Locales): Intl$Locale[]; +} + +type Intl$PluralRule = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other' + +declare type Intl$PluralRulesOptions = { + localeMatcher?: 'lookup' | 'best fit', + type?: 'cardinal' | 'ordinal', + minimumIntegerDigits?: number, + minimumFractionDigits?: number, + maximumFractionDigits?: number, + minimumSignificantDigits?: number, + maximumSignificantDigits?: number, + ... +} diff --git a/newIDE/app/flow-libs/react-dom.js b/newIDE/app/flow-libs/react-dom.js new file mode 100644 index 0000000000..5e44d4ce76 --- /dev/null +++ b/newIDE/app/flow-libs/react-dom.js @@ -0,0 +1,692 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @nolint + * @format + */ + +// The react-dom, react-dom/server and react-dom/test-utils modules were moved to flow-typed. + +declare class SyntheticEvent<+T: EventTarget = EventTarget, +E: Event = Event> { + bubbles: boolean; + cancelable: boolean; + +currentTarget: T; + defaultPrevented: boolean; + eventPhase: number; + isDefaultPrevented(): boolean; + isPropagationStopped(): boolean; + isTrusted: boolean; + nativeEvent: E; + preventDefault(): void; + stopPropagation(): void; + // This should not be `T`. Use `currentTarget` instead. See: + // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/11508#issuecomment-256045682 + +target: EventTarget; + timeStamp: number; + type: string; + persist(): void; +} + +declare class SyntheticAnimationEvent< + +T: EventTarget = EventTarget, +> extends SyntheticEvent { + animationName: string; + elapsedTime: number; + pseudoElement: string; +} + +declare class SyntheticClipboardEvent< + +T: EventTarget = EventTarget, +> extends SyntheticEvent { + clipboardData: any; +} + +declare class SyntheticCompositionEvent< + +T: EventTarget = EventTarget, +> extends SyntheticEvent { + data: any; +} + +declare class SyntheticInputEvent< + +T: EventTarget = EventTarget, +> extends SyntheticEvent { + +target: HTMLInputElement; + data: any; +} + +declare class SyntheticUIEvent< + +T: EventTarget = EventTarget, + +E: Event = Event, +> extends SyntheticEvent { + detail: number; + view: any; +} + +declare class SyntheticFocusEvent< + +T: EventTarget = EventTarget, +> extends SyntheticUIEvent { + relatedTarget: EventTarget; +} + +declare class SyntheticKeyboardEvent< + +T: EventTarget = EventTarget, +> extends SyntheticUIEvent { + altKey: boolean; + charCode: number; + ctrlKey: boolean; + getModifierState(keyArg?: string): boolean; + key: string; + keyCode: number; + locale: string; + location: number; + metaKey: boolean; + repeat: boolean; + shiftKey: boolean; + which: number; +} + +declare class SyntheticMouseEvent< + +T: EventTarget = EventTarget, + +E: Event = MouseEvent, +> extends SyntheticUIEvent { + altKey: boolean; + button: number; + buttons: number; + clientX: number; + clientY: number; + ctrlKey: boolean; + getModifierState(keyArg: string): boolean; + metaKey: boolean; + pageX: number; + pageY: number; + relatedTarget: EventTarget; + screenX: number; + screenY: number; + shiftKey: boolean; +} + +declare class SyntheticDragEvent< + +T: EventTarget = EventTarget, +> extends SyntheticMouseEvent { + dataTransfer: any; +} + +declare class SyntheticWheelEvent< + +T: EventTarget = EventTarget, +> extends SyntheticMouseEvent { + deltaMode: number; + deltaX: number; + deltaY: number; + deltaZ: number; +} + +declare class SyntheticPointerEvent< + +T: EventTarget = EventTarget, +> extends SyntheticMouseEvent { + pointerId: number; + width: number; + height: number; + pressure: number; + tangentialPressure: number; + tiltX: number; + tiltY: number; + twist: number; + pointerType: string; + isPrimary: boolean; +} + +declare class SyntheticTouchEvent< + +T: EventTarget = EventTarget, +> extends SyntheticUIEvent { + altKey: boolean; + changedTouches: any; + ctrlKey: boolean; + getModifierState: any; + metaKey: boolean; + shiftKey: boolean; + targetTouches: any; + touches: any; +} + +declare class SyntheticTransitionEvent< + +T: EventTarget = EventTarget, +> extends SyntheticEvent { + propertyName: string; + elapsedTime: number; + pseudoElement: string; +} + +// prettier-ignore +declare type $JSXIntrinsics = { + // Catch-all for custom elements. + [string]: ReactDOM$HTMLElementJSXIntrinsic, + // HTML + a: { + instance: HTMLAnchorElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + abbr: ReactDOM$HTMLElementJSXIntrinsic, + address: ReactDOM$HTMLElementJSXIntrinsic, + area: ReactDOM$HTMLElementJSXIntrinsic, + article: ReactDOM$HTMLElementJSXIntrinsic, + aside: ReactDOM$HTMLElementJSXIntrinsic, + audio: { + instance: HTMLAudioElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + b: ReactDOM$HTMLElementJSXIntrinsic, + base: ReactDOM$HTMLElementJSXIntrinsic, + bdi: ReactDOM$HTMLElementJSXIntrinsic, + bdo: ReactDOM$HTMLElementJSXIntrinsic, + big: ReactDOM$HTMLElementJSXIntrinsic, + blockquote: ReactDOM$HTMLElementJSXIntrinsic, + body: ReactDOM$HTMLElementJSXIntrinsic, + br: { + instance: HTMLBRElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + button: { + instance: HTMLButtonElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + canvas: { + instance: HTMLCanvasElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + caption: { + instance: HTMLTableCaptionElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + cite: ReactDOM$HTMLElementJSXIntrinsic, + code: ReactDOM$HTMLElementJSXIntrinsic, + col: ReactDOM$HTMLElementJSXIntrinsic, + colgroup: ReactDOM$HTMLElementJSXIntrinsic, + data: ReactDOM$HTMLElementJSXIntrinsic, + datalist: ReactDOM$HTMLElementJSXIntrinsic, + dd: ReactDOM$HTMLElementJSXIntrinsic, + del: ReactDOM$HTMLElementJSXIntrinsic, + details: { + instance: HTMLDetailsElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + dfn: ReactDOM$HTMLElementJSXIntrinsic, + dialog: ReactDOM$HTMLElementJSXIntrinsic, + div: { + instance: HTMLDivElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + dl: { + instance: HTMLDListElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + dt: ReactDOM$HTMLElementJSXIntrinsic, + em: ReactDOM$HTMLElementJSXIntrinsic, + embed: ReactDOM$HTMLElementJSXIntrinsic, + fieldset: { + instance: HTMLFieldSetElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + figcaption: ReactDOM$HTMLElementJSXIntrinsic, + figure: ReactDOM$HTMLElementJSXIntrinsic, + footer: ReactDOM$HTMLElementJSXIntrinsic, + form: { + instance: HTMLFormElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + h1: { + instance: HTMLHeadingElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + h2: { + instance: HTMLHeadingElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + h3: { + instance: HTMLHeadingElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + h4: { + instance: HTMLHeadingElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + h5: { + instance: HTMLHeadingElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + h6: { + instance: HTMLHeadingElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + head: ReactDOM$HTMLElementJSXIntrinsic, + header: ReactDOM$HTMLElementJSXIntrinsic, + hgroup: ReactDOM$HTMLElementJSXIntrinsic, + hr: { + instance: HTMLHRElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + html: ReactDOM$HTMLElementJSXIntrinsic, + i: ReactDOM$HTMLElementJSXIntrinsic, + iframe: { + instance: HTMLIFrameElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + img: { + instance: HTMLImageElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + ins: ReactDOM$HTMLElementJSXIntrinsic, + kbd: ReactDOM$HTMLElementJSXIntrinsic, + keygen: ReactDOM$HTMLElementJSXIntrinsic, + label: { + instance: HTMLLabelElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + legend: { + instance: HTMLLegendElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + li: { + instance: HTMLLIElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + link: { + instance: HTMLLinkElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + main: ReactDOM$HTMLElementJSXIntrinsic, + map: ReactDOM$HTMLElementJSXIntrinsic, + mark: ReactDOM$HTMLElementJSXIntrinsic, + menu: ReactDOM$HTMLElementJSXIntrinsic, + menuitem: ReactDOM$HTMLElementJSXIntrinsic, + meta: { + instance: HTMLMetaElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + meter: ReactDOM$HTMLElementJSXIntrinsic, + nav: ReactDOM$HTMLElementJSXIntrinsic, + noscript: ReactDOM$HTMLElementJSXIntrinsic, + object: ReactDOM$HTMLElementJSXIntrinsic, + ol: { + instance: HTMLOListElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + optgroup: { + instance: HTMLOptGroupElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + option: { + instance: HTMLOptionElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + output: ReactDOM$HTMLElementJSXIntrinsic, + p: { + instance: HTMLParagraphElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + param: ReactDOM$HTMLElementJSXIntrinsic, + picture: ReactDOM$HTMLElementJSXIntrinsic, + pre: { + instance: HTMLPreElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + progress: ReactDOM$HTMLElementJSXIntrinsic, + q: ReactDOM$HTMLElementJSXIntrinsic, + rp: ReactDOM$HTMLElementJSXIntrinsic, + rt: ReactDOM$HTMLElementJSXIntrinsic, + ruby: ReactDOM$HTMLElementJSXIntrinsic, + s: ReactDOM$HTMLElementJSXIntrinsic, + samp: ReactDOM$HTMLElementJSXIntrinsic, + script: { + instance: HTMLScriptElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + section: ReactDOM$HTMLElementJSXIntrinsic, + small: ReactDOM$HTMLElementJSXIntrinsic, + source: { + instance: HTMLSourceElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + span: { + instance: HTMLSpanElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + strong: ReactDOM$HTMLElementJSXIntrinsic, + style: { + instance: HTMLStyleElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + sub: ReactDOM$HTMLElementJSXIntrinsic, + summary: ReactDOM$HTMLElementJSXIntrinsic, + sup: ReactDOM$HTMLElementJSXIntrinsic, + table: { + instance: HTMLTableElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + tbody: { + instance: HTMLTableSectionElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + td: { + instance: HTMLTableCellElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + tfoot: { + instance: HTMLTableSectionElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + th: { + instance: HTMLTableCellElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + thead: { + instance: HTMLTableSectionElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + time: ReactDOM$HTMLElementJSXIntrinsic, + title: ReactDOM$HTMLElementJSXIntrinsic, + tr: { + instance: HTMLTableRowElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + track: ReactDOM$HTMLElementJSXIntrinsic, + u: ReactDOM$HTMLElementJSXIntrinsic, + ul: { + instance: HTMLUListElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + 'var': ReactDOM$HTMLElementJSXIntrinsic, + video: { + instance: HTMLVideoElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + wbr: ReactDOM$HTMLElementJSXIntrinsic, + // SVG + svg: ReactDOM$SVGElementJSXIntrinsic, + animate: ReactDOM$SVGElementJSXIntrinsic, + circle: ReactDOM$SVGElementJSXIntrinsic, + defs: ReactDOM$SVGElementJSXIntrinsic, + ellipse: ReactDOM$SVGElementJSXIntrinsic, + g: ReactDOM$SVGElementJSXIntrinsic, + image: ReactDOM$SVGElementJSXIntrinsic, + line: ReactDOM$SVGElementJSXIntrinsic, + linearGradient: ReactDOM$SVGElementJSXIntrinsic, + mask: ReactDOM$SVGElementJSXIntrinsic, + path: ReactDOM$SVGElementJSXIntrinsic, + pattern: ReactDOM$SVGElementJSXIntrinsic, + polygon: ReactDOM$SVGElementJSXIntrinsic, + polyline: ReactDOM$SVGElementJSXIntrinsic, + radialGradient: ReactDOM$SVGElementJSXIntrinsic, + rect: ReactDOM$SVGElementJSXIntrinsic, + stop: ReactDOM$SVGElementJSXIntrinsic, + symbol: ReactDOM$SVGElementJSXIntrinsic, + text: ReactDOM$SVGElementJSXIntrinsic, + tspan: ReactDOM$SVGElementJSXIntrinsic, + use: ReactDOM$SVGElementJSXIntrinsic, + // Elements React adds extra props for. + input: { + instance: HTMLInputElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + textarea: { + instance: HTMLTextAreaElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + select: { + instance: HTMLSelectElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... + }, + ... +}; + +type ReactDOM$HTMLElementJSXIntrinsic = { + instance: HTMLElement, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... +}; + +type ReactDOM$SVGElementJSXIntrinsic = { + instance: Element, + props: { + [key: string]: any, + children?: React$Node, + ... + }, + ... +}; diff --git a/newIDE/app/flow-libs/serviceworkers.js b/newIDE/app/flow-libs/serviceworkers.js new file mode 100644 index 0000000000..f450168a92 --- /dev/null +++ b/newIDE/app/flow-libs/serviceworkers.js @@ -0,0 +1,222 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +type FrameType = 'auxiliary' | 'top-level' | 'nested' | 'none'; +type VisibilityState = 'hidden' | 'visible' | 'prerender' | 'unloaded'; + +declare class WindowClient extends Client { + visibilityState: VisibilityState, + focused: boolean, + focus(): Promise, + navigate(url: string): Promise, +} + +declare class Client { + id: string, + reserved: boolean, + url: string, + frameType: FrameType, + postMessage(message: any, transfer?: Iterator | Array): void, +} + +declare class ExtendableEvent extends Event { + waitUntil(f: Promise): void, +} + +type ForeignFetchOptions = { + scopes: Iterator, + origins: Iterator, + ... +}; + +declare class InstallEvent extends ExtendableEvent { + registerForeignFetch(options: ForeignFetchOptions): void, +} + +declare class FetchEvent extends ExtendableEvent { + request: Request, + clientId: string, + isReload: boolean, + respondWith(response: Response | Promise): void, + preloadResponse: Promise, +} + +type ClientType = 'window' | 'worker' | 'sharedworker' | 'all'; +type ClientQueryOptions = { + includeUncontrolled?: boolean, + includeReserved?: boolean, + type?: ClientType, + ... +}; + +declare class Clients { + get(id: string): Promise, + matchAll(options?: ClientQueryOptions): Promise>, + openWindow(url: string): Promise, + claim(): Promise, +} + +type ServiceWorkerState = 'installing' + | 'installed' + | 'activating' + | 'activated' + | 'redundant'; + +declare class ServiceWorker extends EventTarget { + scriptURL: string, + state: ServiceWorkerState, + + postMessage(message: any, transfer?: Iterator): void, + + onstatechange?: EventHandler, +} + +declare class NavigationPreloadState { + enabled: boolean, + headerValue: string, +} + +declare class NavigationPreloadManager { + enable: Promise, + disable: Promise, + setHeaderValue(value: string): Promise, + getState: Promise, +} + +type PushSubscriptionOptions = { + userVisibleOnly?: boolean, + applicationServerKey?: string | ArrayBuffer | $ArrayBufferView, + ... +} + +declare class PushSubscriptionJSON { + endpoint: string, + expirationTime: number | null, + keys: { [string]: string, ... }; +} + +declare class PushSubscription { + +endpoint: string, + +expirationTime: number | null, + +options: PushSubscriptionOptions, + getKey(name: string): ArrayBuffer | null, + toJSON(): PushSubscriptionJSON, + unsubscribe(): Promise, +} + +declare class PushManager { + +supportedContentEncodings: Array, + subscribe(options?: PushSubscriptionOptions): Promise, + getSubscription(): Promise, + permissionState(options?: PushSubscriptionOptions): Promise<'granted' | 'denied' | 'prompt'>, +} + +type ServiceWorkerUpdateViaCache = 'imports' | 'all' | 'none'; + +declare class ServiceWorkerRegistration extends EventTarget { + +installing: ?ServiceWorker, + +waiting: ?ServiceWorker, + +active: ?ServiceWorker, + +navigationPreload: NavigationPreloadManager, + +scope: string, + +updateViaCache: ServiceWorkerUpdateViaCache, + +pushManager: PushManager, + + update(): Promise, + unregister(): Promise, + + onupdatefound?: EventHandler, +} + +type WorkerType = 'classic' | 'module'; + +type RegistrationOptions = { + scope?: string, + type?: WorkerType, + updateViaCache?: ServiceWorkerUpdateViaCache, + ... +}; + +declare class ServiceWorkerContainer extends EventTarget { + +controller: ?ServiceWorker, + +ready: Promise, + + getRegistration(clientURL?: string): Promise, + getRegistrations(): Promise>, + register( + scriptURL: string, + options?: RegistrationOptions + ): Promise, + startMessages(): void, + + oncontrollerchange?: EventHandler, + onmessage?: EventHandler, + onmessageerror?: EventHandler, +} + +/** + * This feature has been removed from the Web standards. + */ +declare class ServiceWorkerMessageEvent extends Event { + data: any, + lastEventId: string, + origin: string, + ports: Array, + source: ?(ServiceWorker | MessagePort), +} + +declare class ExtendableMessageEvent extends ExtendableEvent { + data: any, + lastEventId: string, + origin: string, + ports: Array, + source: ?(ServiceWorker | MessagePort), +} + +type CacheQueryOptions = { + ignoreSearch?: boolean, + ignoreMethod?: boolean, + ignoreVary?: boolean, + cacheName?: string, + ... +} + +declare class Cache { + match(request: RequestInfo, options?: CacheQueryOptions): Promise, + matchAll( + request: RequestInfo, + options?: CacheQueryOptions + ): Promise>, + add(request: RequestInfo): Promise, + addAll(requests: Array): Promise, + put(request: RequestInfo, response: Response): Promise, + delete(request: RequestInfo, options?: CacheQueryOptions): Promise, + keys( + request?: RequestInfo, + options?: CacheQueryOptions + ): Promise>, +} + +declare class CacheStorage { + match(request: RequestInfo, options?: CacheQueryOptions): Promise, + has(cacheName: string): Promise, + open(cacheName: string): Promise, + delete(cacheName: string): Promise, + keys(): Promise>, +} + +// Service worker global scope +// https://www.w3.org/TR/service-workers/#service-worker-global-scope +declare var clients: Clients; +declare var caches: CacheStorage; +declare var registration: ServiceWorkerRegistration; +declare function skipWaiting(): Promise; +declare var onactivate: ?EventHandler; +declare var oninstall: ?EventHandler; +declare var onfetch: ?EventHandler; +declare var onforeignfetch: ?EventHandler; +declare var onmessage: ?EventHandler; diff --git a/newIDE/app/flow-libs/streams.js b/newIDE/app/flow-libs/streams.js new file mode 100644 index 0000000000..290f99ee67 --- /dev/null +++ b/newIDE/app/flow-libs/streams.js @@ -0,0 +1,139 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +type TextEncodeOptions = { options?: boolean, ... }; + +declare class TextEncoder { + encode(buffer: string, options?: TextEncodeOptions): Uint8Array, +} + +declare class ReadableStreamController { + constructor( + stream: ReadableStream, + underlyingSource: UnderlyingSource, + size: number, + highWaterMark: number, + ): void, + + desiredSize: number, + + close(): void, + enqueue(chunk: any): void, + error(error: Error): void, +} + +declare class ReadableStreamBYOBRequest { + constructor(controller: ReadableStreamController, view: $TypedArray): void, + + view: $TypedArray, + + respond(bytesWritten: number): ?any, + respondWithNewView(view: $TypedArray): ?any, +} + +declare class ReadableByteStreamController extends ReadableStreamController { + constructor( + stream: ReadableStream, + underlyingSource: UnderlyingSource, + highWaterMark: number, + ): void, + + byobRequest: ReadableStreamBYOBRequest, +} + +declare class ReadableStreamReader { + constructor(stream: ReadableStream): void, + + closed: boolean, + + cancel(reason: string): void, + read(): Promise<{ + value: ?any, + done: boolean, + ... + }>, + releaseLock(): void, +} + +declare interface UnderlyingSource { + autoAllocateChunkSize?: number, + type?: string, + + start?: (controller: ReadableStreamController) => ?Promise, + pull?: (controller: ReadableStreamController) => ?Promise, + cancel?: (reason: string) => ?Promise, +} + +declare class TransformStream { + readable: ReadableStream, + writable: WritableStream, +}; + +type PipeToOptions = { + preventClose?: boolean, + preventAbort?: boolean, + preventCancel?: boolean, + ... +}; + +type QueuingStrategy = { + highWaterMark: number, + size(chunk: ?any): number, + ... +}; + +declare class ReadableStream { + constructor( + underlyingSource: ?UnderlyingSource, + queuingStrategy: ?QueuingStrategy, + ): void, + + locked: boolean, + + cancel(reason: string): void, + getReader(): ReadableStreamReader, + pipeThrough(transform: TransformStream, options: ?any): void, + pipeTo(dest: WritableStream, options: ?PipeToOptions): Promise, + tee(): [ReadableStream, ReadableStream], +}; + +declare interface WritableStreamController { + error(error: Error): void, +} + +declare interface UnderlyingSink { + autoAllocateChunkSize?: number, + type?: string, + + abort?: (reason: string) => ?Promise, + close?: (controller: WritableStreamController) => ?Promise, + start?: (controller: WritableStreamController) => ?Promise, + write?: (chunk: any, controller: WritableStreamController) => ?Promise, +} + +declare interface WritableStreamWriter { + closed: Promise, + desiredSize?: number, + ready: Promise, + + abort(reason: string): ?Promise, + close(): Promise, + releaseLock(): void, + write(chunk: any): Promise, +} + +declare class WritableStream { + constructor( + underlyingSink: ?UnderlyingSink, + queuingStrategy: QueuingStrategy, + ): void, + + locked: boolean, + + abort(reason: string): void, + getWriter(): WritableStreamWriter, +} diff --git a/newIDE/app/flow-libs/webassembly.js b/newIDE/app/flow-libs/webassembly.js new file mode 100644 index 0000000000..b77b295d3b --- /dev/null +++ b/newIDE/app/flow-libs/webassembly.js @@ -0,0 +1,102 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// https://github.com/WebAssembly/design/blob/master/JS.md +// https://developer.mozilla.org/en-US/docs/WebAssembly +// https://github.com/WebAssembly/design/blob/master/Web.md + +type BufferSource = $TypedArray | ArrayBuffer; +type ImportExportKind = 'function' | 'table' | 'memory' | 'global'; +type ImportObject = Object; +type ResultObject = { + module: WebAssembly$Module, + instance: WebAssembly$Instance, + ... +}; + +// https://github.com/WebAssembly/design/blob/master/JS.md#exported-function-exotic-objects +declare class ExportedFunctionExoticObject extends Function { + (): mixed; +} + +declare class WebAssembly$Module { + constructor(bufferSource: BufferSource): void; + + static exports(moduleObject: WebAssembly$Module): Array<{ + name: string, + kind: ImportExportKind, + ... + }>; + static imports(moduleObject: WebAssembly$Module): Array<{ + name: string, + name: string, + kind: ImportExportKind, + ... + }>; + static customSections(moduleObject: WebAssembly$Module, sectionName: string): Array; +} + +declare class WebAssembly$Instance { + constructor(moduleObject: WebAssembly$Module, importObject?: ImportObject): void; + + +exports: { [exportedFunction: string]: ExportedFunctionExoticObject, ... }; +} + +type MemoryDescriptor = { + initial: number, + maximum?: number, + ... +}; + +declare class WebAssembly$Memory { + constructor(memoryDescriptor: MemoryDescriptor): void; + + +buffer: ArrayBuffer; + + grow(delta: number): number; +} + +type TableDescriptor = { + element: 'anyfunc', + initial: number, + maximum?: number, + ... +}; + +declare class WebAssembly$Table { + constructor(tableDescriptor: TableDescriptor): void; + + +length: number; + + grow(delta: number): number; + get(index: number): ExportedFunctionExoticObject; + set(index: number, value: ExportedFunctionExoticObject): void; +} + +declare class WebAssembly$CompileError extends Error {} +declare class WebAssembly$LinkError extends Error {} +declare class WebAssembly$RuntimeError extends Error {} + +declare function WebAssembly$instantiate(bufferSource: BufferSource, importObject?: ImportObject): Promise; +declare function WebAssembly$instantiate(moduleObject: WebAssembly$Module, importObject?: ImportObject): Promise; + +declare var WebAssembly: { + Module: typeof WebAssembly$Module, + Instance: typeof WebAssembly$Instance, + Memory: typeof WebAssembly$Memory, + Table: typeof WebAssembly$Table, + CompileError: typeof WebAssembly$CompileError, + LinkError: typeof WebAssembly$LinkError, + RuntimeError: typeof WebAssembly$RuntimeError, + validate(bufferSource: BufferSource): boolean, + compile(bufferSource: BufferSource): Promise, + instantiate: typeof WebAssembly$instantiate, + // web embedding API + compileStreaming(source: Response | Promise): Promise, + instantiateStreaming(source: Response | Promise, importObject?: ImportObject): Promise, + ... +} diff --git a/newIDE/app/scripts/add-flow-fixme.py b/newIDE/app/scripts/add-flow-fixme.py new file mode 100644 index 0000000000..ab67e24ede --- /dev/null +++ b/newIDE/app/scripts/add-flow-fixme.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python3 +""" +Add $FlowFixMe comments to lines with Flow errors that can't be auto-fixed. +This script is idempotent - running it multiple times produces the same result. +""" + +import subprocess +import json +import sys +import os +import re +from collections import defaultdict + +APP_DIR = os.environ.get('APP_DIR', os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + + +def get_flow_errors(): + """Run flow and get errors as JSON.""" + result = subprocess.run( + ['npx', 'flow', '--json', '--show-all-errors'], + capture_output=True, text=True, cwd=APP_DIR, + timeout=300 + ) + + output = result.stdout + json_start = output.find('{"flowVersion"') + if json_start == -1: + json_start = result.stderr.find('{"flowVersion"') + if json_start != -1: + output = result.stderr + else: + print("ERROR: Could not find JSON in flow output") + return [] + + json_str = output[json_start:] + try: + data = json.loads(json_str) + return data.get('errors', []) + except json.JSONDecodeError as e: + print(f"ERROR: JSON parse error: {e}") + return [] + + +def add_flowfixme_comments(errors): + """Add $FlowFixMe comments to files with errors.""" + # Group errors by file and line, collecting ALL error codes per line + file_errors = defaultdict(lambda: defaultdict(set)) + + for error in errors: + messages = error.get('message', []) + error_codes = error.get('error_codes', []) + + if not messages: + continue + + primary = messages[0] + loc = primary.get('loc', {}) + source = loc.get('source', '') + line = loc.get('start', {}).get('line', 0) + + if not source or not line: + continue + + # Only fix files in src/ directory of the app + if APP_DIR + '/src/' not in source: + continue + + error_code = error_codes[0] if error_codes else 'incompatible-type' + # Never rely on signature-verification-failure suppressions, as this + # degrades typed exports/imports too much. + if error_code == 'signature-verification-failure': + error_code = 'incompatible-type' + file_errors[source][line].add(error_code) + + files_modified = 0 + comments_added = 0 + + for filepath, line_errors in sorted(file_errors.items()): + if not os.path.isfile(filepath): + continue + + try: + with open(filepath, 'r') as f: + lines = f.readlines() + except (IOError, UnicodeDecodeError): + continue + + # Sort lines in reverse order so we can insert without offset issues + sorted_lines = sorted(line_errors.keys(), reverse=True) + modified = False + + for line_num in sorted_lines: + error_codes = line_errors[line_num] + idx = line_num - 1 # 0-indexed + + if idx < 0 or idx >= len(lines): + continue + + # Collect existing $FlowFixMe codes above this line + existing_codes = set() + check_idx = idx - 1 + while check_idx >= 0 and '$FlowFixMe' in lines[check_idx]: + # Extract the code from existing $FlowFixMe comment + match = re.search(r'\$FlowFixMe\[([^\]]+)\]', lines[check_idx]) + if match: + existing_codes.add(match.group(1)) + check_idx -= 1 + + # Also check if current line has inline $FlowFixMe + if '$FlowFixMe' in lines[idx]: + match = re.search(r'\$FlowFixMe\[([^\]]+)\]', lines[idx]) + if match: + existing_codes.add(match.group(1)) + + # Determine which codes need to be added + needed_codes = error_codes - existing_codes + + if not needed_codes: + continue + + # Get the indentation of the error line + current_line = lines[idx] + indent = '' + for ch in current_line: + if ch in (' ', '\t'): + indent += ch + else: + break + + # Add $FlowFixMe comments for each needed code + for code in sorted(needed_codes): + comment = f"{indent}// $FlowFixMe[{code}]\n" + lines.insert(idx, comment) + modified = True + comments_added += 1 + + if modified: + with open(filepath, 'w') as f: + f.writelines(lines) + files_modified += 1 + + print(f" Added {comments_added} $FlowFixMe comments across {files_modified} files") + return comments_added + + +def main(): + print(" Getting Flow errors...") + errors = get_flow_errors() + print(f" Found {len(errors)} errors total") + + if not errors: + print(" No errors to fix!") + return 0 + + src_errors = 0 + for error in errors: + messages = error.get('message', []) + if messages: + loc = messages[0].get('loc', {}) + source = loc.get('source', '') + if APP_DIR + '/src/' in source: + src_errors += 1 + + print(f" Found {src_errors} errors in src/ files") + + if src_errors == 0: + print(" No src/ errors to fix!") + return 0 + + count = add_flowfixme_comments(errors) + return count + + +if __name__ == '__main__': + added = main() + sys.exit(0 if added >= 0 else 1) diff --git a/newIDE/app/scripts/convert-jsx-flowfixme.py b/newIDE/app/scripts/convert-jsx-flowfixme.py new file mode 100644 index 0000000000..b361baedd6 --- /dev/null +++ b/newIDE/app/scripts/convert-jsx-flowfixme.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python3 +""" +Convert // $FlowFixMe[code] comments that are inside JSX to {/* $FlowFixMe[code] */} format. +This is needed because // comments don't work inside JSX element content. +""" + +import json +import subprocess +import os +import re +from collections import defaultdict + +APP_DIR = os.environ.get('APP_DIR', os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + + +def looks_like_jsx_context(lines, code_idx): + """ + Heuristic to detect if a line is inside JSX where // comments are invalid. + """ + if code_idx < 0 or code_idx >= len(lines): + return False + + for idx in range(code_idx, min(len(lines), code_idx + 4)): + stripped = lines[idx].lstrip() + if not stripped: + continue + if stripped.startswith('//') or stripped.startswith('/*') or stripped.startswith('*'): + continue + + if ( + stripped.startswith('<') + or stripped.startswith('') + or stripped.startswith('{<') + or stripped.startswith('(<') + ): + return True + + # JSX expression containers can start with "{" and contain JSX on + # following lines: + # { + # condition && ( + # + # ) + # } + if stripped.startswith('{'): + for look_ahead in range(idx + 1, min(len(lines), idx + 5)): + next_stripped = lines[look_ahead].lstrip() + if not next_stripped: + continue + if ( + next_stripped.startswith('<') + or next_stripped.startswith('') + ): + return True + if ( + next_stripped.startswith('//') + or next_stripped.startswith('/*') + or next_stripped.startswith('*') + ): + continue + break + + # Common pattern: + # { + # condition && ( + # + # ) + # } + if stripped.startswith('(') and idx + 1 < len(lines): + next_stripped = lines[idx + 1].lstrip() + if ( + next_stripped.startswith('<') + or next_stripped.startswith('') + ): + return True + + return False + + return False + + +def get_flow_errors(): + """Run flow and get errors as JSON.""" + result = subprocess.run( + ['npx', 'flow', '--json', '--show-all-errors'], + capture_output=True, text=True, cwd=APP_DIR, + timeout=300 + ) + output = result.stdout + idx = output.find('{"flowVersion"') + if idx == -1: + return [] + try: + data = json.loads(output[idx:]) + return data.get('errors', []) + except json.JSONDecodeError: + return [] + + +def main(): + errors = get_flow_errors() + + # Find errors where $FlowFixMe is on the line above but not suppressing + file_fixes = defaultdict(set) + + for e in errors: + msgs = e.get('message', []) + codes = e.get('error_codes', []) + if not msgs: + continue + loc = msgs[0].get('loc', {}) + source = loc.get('source', '') + line = loc.get('start', {}).get('line', 0) + if '/src/' not in source: + continue + code = codes[0] if codes else 'incompatible-type' + + if not os.path.isfile(source): + continue + + with open(source) as f: + lines = f.readlines() + + if line < 2 or line > len(lines): + continue + + above = lines[line - 2] + target = '// $FlowFixMe[' + code + ']' + if target in above: + file_fixes[source].add(line - 2) + + # Convert the failing comments to JSX format + fixes_count = 0 + reverted_count = 0 + for filepath, fixme_indices in file_fixes.items(): + with open(filepath) as f: + lines = f.readlines() + + modified = False + converted_indices = set() + for idx in sorted(fixme_indices): + if idx >= len(lines): + continue + line = lines[idx] + m = re.match(r'^(\s*)// (\$FlowFixMe\[[^\]]+\])(.*?)$', line.rstrip()) + if m: + indent = m.group(1) + fixme = m.group(2) + rest = m.group(3).strip() + if rest: + lines[idx] = f'{indent}{{/* {fixme} {rest} */}}\n' + else: + lines[idx] = f'{indent}{{/* {fixme} */}}\n' + modified = True + fixes_count += 1 + converted_indices.add(idx) + + # If a JSX-style FlowFixMe ended up outside JSX (can happen with noisy + # parse errors), restore it back to normal // comment syntax. + # Skip indices that were just converted from Flow error analysis - + # those are known to be in JSX context even if the heuristic can't tell. + for idx, line in enumerate(lines): + if idx in converted_indices: + continue + m = re.match(r'^(\s*)\{/\*\s*(\$FlowFixMe\[[^\]]+\])(?:\s+(.*?))?\s*\*/\}\s*$', line.rstrip()) + if not m: + continue + if looks_like_jsx_context(lines, idx + 1): + continue + + indent = m.group(1) + fixme = m.group(2) + rest = (m.group(3) or '').strip() + if rest: + lines[idx] = f'{indent}// {fixme} {rest}\n' + else: + lines[idx] = f'{indent}// {fixme}\n' + modified = True + reverted_count += 1 + + if modified: + with open(filepath, 'w') as f: + f.writelines(lines) + + print(f"Converted {fixes_count} FlowFixMe comments to JSX format") + if reverted_count: + print(f"Reverted {reverted_count} non-JSX FlowFixMe comments back to // syntax") + + +if __name__ == '__main__': + main() diff --git a/newIDE/app/scripts/fix-arrow-return-types.py b/newIDE/app/scripts/fix-arrow-return-types.py new file mode 100644 index 0000000000..3c0d271ef7 --- /dev/null +++ b/newIDE/app/scripts/fix-arrow-return-types.py @@ -0,0 +1,215 @@ +#!/usr/bin/env python3 +""" +Fix arrow-function inline object return types that prettier 1.15 can't parse. + +The Flow codemod may add return type annotations like: + const foo = (): { prop: Type, ... } => { ... } + +Prettier 1.15 cannot parse (): { ... } => because it confuses the opening +brace of the return type with a function body. + +This script detects files with prettier parse errors and, for each one, +extracts the inline object return type into a named type alias: + + type _FooReturnType = { prop: Type, ... }; + const foo = (): _FooReturnType => { ... } + +The script is idempotent. +""" + +import os +import re +import subprocess +import sys + +APP_DIR = os.environ.get('APP_DIR', os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +SRC_DIR = os.path.join(APP_DIR, 'src') + + +def get_prettier_errors(): + """Run prettier --list-different and find files with syntax errors.""" + result = subprocess.run( + ['npx', 'prettier', '--list-different', 'src/!(locales)/**/*.js'], + capture_output=True, text=True, cwd=APP_DIR, timeout=120 + ) + # Combine stdout and stderr to find error lines + all_output = result.stdout + '\n' + result.stderr + error_files = set() + for line in all_output.split('\n'): + m = re.match(r'\[error\]\s+(src/\S+\.js):\s+SyntaxError', line) + if m: + error_files.add(os.path.join(APP_DIR, m.group(1))) + return error_files + + +def find_brace_end(content, start): + """Find the matching closing brace for an opening brace at position start.""" + depth = 0 + i = start + while i < len(content): + ch = content[i] + if ch == '{': + depth += 1 + elif ch == '}': + depth -= 1 + if depth == 0: + return i + elif ch == "'" or ch == '"' or ch == '`': + # Skip strings + quote = ch + i += 1 + while i < len(content) and content[i] != quote: + if content[i] == '\\': + i += 1 + i += 1 + elif ch == '/' and i + 1 < len(content): + if content[i + 1] == '/': + # Line comment + i = content.find('\n', i) + if i == -1: + return -1 + elif content[i + 1] == '*': + # Block comment + i = content.find('*/', i + 2) + if i == -1: + return -1 + i += 1 + i += 1 + return -1 + + +def extract_identifier_name(content, pos): + """Extract the identifier name before `= (` at the given position.""" + # Walk backwards from `= (` to find the variable/const name + i = pos - 1 + while i >= 0 and content[i] in ' \t': + i -= 1 + if i < 0 or content[i] != '=': + return None + i -= 1 + while i >= 0 and content[i] in ' \t': + i -= 1 + if i < 0: + return None + end = i + 1 + while i >= 0 and (content[i].isalnum() or content[i] == '_' or content[i] == '$'): + i -= 1 + name = content[i + 1:end] + if name and name[0].isalpha(): + return name + return None + + +def fix_file(filepath): + """Fix arrow function return types in a single file.""" + with open(filepath) as f: + content = f.read() + + original = content + # Pattern: = (params): { ... } => { + # We need to find ): { where { starts a type annotation, not a body + # The type annotation ends with } => + pattern = re.compile(r'(=\s*\([^)]*\))\s*:\s*\{') + + insertions = [] # (position, type_name, type_body) to insert before the line + replacements = [] # (start, end, replacement) + used_names = set() + + for m in pattern.finditer(content): + prefix = m.group(1) # e.g., '= (params)' + brace_start = content.index('{', m.start() + len(prefix)) + brace_end = find_brace_end(content, brace_start) + + if brace_end == -1: + continue + + # Check if followed by => { (arrow function body) + after_brace = content[brace_end + 1:].lstrip() + if not after_brace.startswith('=>'): + continue + + # Verify the type spans multiple lines (single-line types are ok for prettier) + type_text = content[brace_start:brace_end + 1] + if '\n' not in type_text: + continue + + # Get the identifier name for the type alias + call_start = content.index('(', m.start()) + name = extract_identifier_name(content, call_start) + if not name: + name = 'Anonymous' + + # Create a unique type name + base_type_name = f'_{name[0].upper()}{name[1:]}ReturnType' + type_name = base_type_name + suffix = 2 + while type_name in used_names: + type_name = f'{base_type_name}{suffix}' + suffix += 1 + used_names.add(type_name) + + # Find the line start for inserting the type declaration + line_start = content.rfind('\n', 0, m.start()) + if line_start == -1: + line_start = 0 + else: + line_start += 1 + + insertions.append((line_start, type_name, type_text)) + + # Replace ): { ...type... } => with ): TypeName => + colon_pos = content.index(':', m.start() + len(prefix)) + replacements.append((colon_pos, brace_end + 1, f': {type_name}')) + + if not replacements: + return False + + # Apply replacements in reverse order + combined = list(zip(insertions, replacements)) + combined.sort(key=lambda x: x[1][0], reverse=True) + + for (insert_pos, type_name, type_body), (rep_start, rep_end, rep_text) in combined: + content = content[:rep_start] + rep_text + content[rep_end:] + + # Now insert type declarations (from bottom to top to maintain positions) + insertion_list = [(ins[0], ins[1], ins[2]) for ins, _ in combined] + insertion_list.sort(key=lambda x: x[0], reverse=True) + for insert_pos, type_name, type_body in insertion_list: + type_decl = f'type {type_name} = {type_body};\n' + content = content[:insert_pos] + type_decl + content[insert_pos:] + + if content != original: + with open(filepath, 'w') as f: + f.write(content) + return True + return False + + +def main(): + # First, find files that have prettier parse errors + error_files = get_prettier_errors() + + if not error_files: + print(" No prettier parse errors found - no fixes needed.") + return + + print(f" Found {len(error_files)} files with prettier parse errors") + + fixed = 0 + for filepath in sorted(error_files): + if fix_file(filepath): + fixed += 1 + print(f" Fixed: {os.path.relpath(filepath, SRC_DIR)}") + + print(f" Fixed {fixed} files") + + # Verify no more errors + remaining = get_prettier_errors() + if remaining: + print(f" WARNING: {len(remaining)} files still have prettier parse errors:") + for f in sorted(remaining): + print(f" {os.path.relpath(f, SRC_DIR)}") + + +if __name__ == '__main__': + main() diff --git a/newIDE/app/scripts/fix-codemod-syntax.py b/newIDE/app/scripts/fix-codemod-syntax.py new file mode 100644 index 0000000000..d967a9dddd --- /dev/null +++ b/newIDE/app/scripts/fix-codemod-syntax.py @@ -0,0 +1,611 @@ +#!/usr/bin/env python3 +""" +Normalize Flow codemod syntax to Babel-compatible Flow syntax. + +Flow 0.299 annotate-exports introduces syntax that older Babel/Flow tooling in this +project cannot parse: + - component(...) type annotations + - renders type operator + - as-casts + +This script rewrites those constructs while preserving runtime behavior and as much +type information as possible: + - component(...) -> React.ComponentType + - React.AbstractComponent -> React.ComponentType<{...Props, ref?: React.RefSetter}> + - renders T -> T (with renders any/mixed/empty/Fragment normalized to React.Node) + - expr as T -> (expr: T) + +The script is idempotent. +""" + +from __future__ import annotations + +import json +import os +import pathlib +import re +import subprocess +import sys +from typing import Any, Dict, List, Optional, Tuple + +APP_DIR = os.environ.get( + "APP_DIR", + os.path.dirname(os.path.dirname(os.path.abspath(__file__))), +) +SRC_DIR = pathlib.Path(APP_DIR) / "src" +FLOW_BIN = pathlib.Path(APP_DIR) / "node_modules" / ".bin" / "flow" +FLOW_AST_CMD = [str(FLOW_BIN), "ast"] if FLOW_BIN.exists() else ["npx", "flow", "ast"] + + +def _extract_json(output: str) -> Optional[Dict[str, Any]]: + start = output.find("{") + if start == -1: + return None + try: + return json.loads(output[start:]) + except json.JSONDecodeError: + return None + + +def _run_flow_ast(relative_path: str, content_text: str) -> Optional[Dict[str, Any]]: + result = subprocess.run( + FLOW_AST_CMD + ["--path", relative_path], + input=content_text.encode("utf-8"), + capture_output=True, + cwd=APP_DIR, + ) + stdout = result.stdout.decode("utf-8", errors="replace") + stderr = result.stderr.decode("utf-8", errors="replace") + data = _extract_json(stdout) + if data is not None: + return data + # Flow may occasionally emit JSON to stderr on failure. + return _extract_json(stderr) + + +def _walk(node: Any, visit, parent_type: Optional[str] = None) -> None: + if isinstance(node, dict): + node_type = node.get("type") + visit(node, parent_type) + for value in node.values(): + _walk(value, visit, node_type) + elif isinstance(node, list): + for item in node: + _walk(item, visit, parent_type) + + +def _node_text(content: bytes, node: Dict[str, Any]) -> str: + start, end = node["range"] + return content[start:end].decode("utf-8") + + +def _is_render_node_like(type_text: str) -> bool: + normalized = "".join(type_text.split()) + if normalized in { + "any", + "mixed", + "empty", + "void", + "null", + "Fragment", + "React.Node", + "React$Node", + "React.MixedElement", + }: + return True + return ( + "React.Node" in normalized + or "React$Node" in normalized + or "React.MixedElement" in normalized + ) + + +def _normalize_renders_target(type_text: str) -> str: + stripped = type_text.strip() + if stripped in {"any", "mixed", "empty", "Fragment"}: + return "React.Node" + return stripped + + +def _object_property_key_name(property_node: Dict[str, Any]) -> Optional[str]: + key = property_node.get("key") + if not isinstance(key, dict): + return None + key_type = key.get("type") + if key_type == "Identifier": + return key.get("name") + if key_type == "Literal": + return key.get("value") + return None + + +def _object_type_has_ref_property(object_type_node: Dict[str, Any]) -> bool: + for prop in object_type_node.get("properties", []): + if not isinstance(prop, dict): + continue + if prop.get("type") != "ObjectTypeProperty": + continue + if _object_property_key_name(prop) == "ref": + return True + return False + + +def _qualified_type_identifier_name(type_id_node: Any) -> Optional[str]: + if not isinstance(type_id_node, dict): + return None + node_type = type_id_node.get("type") + if node_type == "Identifier": + return type_id_node.get("name") + if node_type == "QualifiedTypeIdentifier": + left = _qualified_type_identifier_name(type_id_node.get("qualification")) + right = _qualified_type_identifier_name(type_id_node.get("id")) + if left and right: + return f"{left}.{right}" + return right + return None + + +def _is_react_abstract_component_type(type_id_node: Any) -> bool: + type_name = _qualified_type_identifier_name(type_id_node) + return type_name in {"React.AbstractComponent", "React$AbstractComponent"} + + +def _type_parameter_nodes(type_parameters_node: Any) -> List[Dict[str, Any]]: + if not isinstance(type_parameters_node, dict): + return [] + params = type_parameters_node.get("params") + if not isinstance(params, list): + return [] + return [param for param in params if isinstance(param, dict)] + + +def _is_ref_setter_type(type_text: str) -> bool: + stripped = type_text.strip() + return stripped.startswith("React.RefSetter<") or stripped.startswith( + "React$RefSetter<" + ) + + +def _to_ref_setter_type(instance_type_text: str) -> str: + stripped = instance_type_text.strip() + if not stripped: + return "React.RefSetter" + if _is_ref_setter_type(stripped): + return stripped.replace("React$RefSetter", "React.RefSetter") + return f"React.RefSetter<{stripped}>" + + +def _props_text_has_ref_property(props_type_text: str) -> bool: + return ( + re.search(r"(^|[,{]\s*)\+?ref\??\s*:", props_type_text, re.MULTILINE) + is not None + ) + + +def _append_ref_property_to_object_type( + props_type_text: str, ref_prop_type: str +) -> str: + original = props_type_text + stripped = original.rstrip() + trailing_whitespace = original[len(stripped) :] + + if stripped.startswith("{|") and stripped.endswith("|}"): + open_token, close_token = "{|", "|}" + elif stripped.startswith("{") and stripped.endswith("}"): + open_token, close_token = "{", "}" + else: + return f"{{ ...{props_type_text.strip()}, +ref?: {ref_prop_type} }}" + + inner = stripped[len(open_token) : -len(close_token)] + if _props_text_has_ref_property(inner): + return props_type_text + + is_multiline = "\n" in stripped + inner_content = inner.strip() + if not is_multiline: + if inner_content: + separator = "," if not inner_content.endswith(",") else "" + return ( + f"{open_token} {inner_content}{separator} +ref?: {ref_prop_type} " + f"{close_token}{trailing_whitespace}" + ) + return ( + f"{open_token} +ref?: {ref_prop_type} " + f"{close_token}{trailing_whitespace}" + ) + + # Multiline object type: place the new property on its own line and keep + # existing indentation style if possible. + closing_indent_match = re.search(r"\n([ \t]*)\s*$", inner) + closing_indent = closing_indent_match.group(1) if closing_indent_match else "" + property_indent_match = re.search(r"\n([ \t]+)\S", inner) + property_indent = ( + property_indent_match.group(1) + if property_indent_match + else f"{closing_indent} " + ) + + inner_without_trailing_space = inner.rstrip() + if inner_content: + if not inner_without_trailing_space.endswith(","): + inner_without_trailing_space += "," + if not inner_without_trailing_space.endswith("\n"): + inner_without_trailing_space += "\n" + new_inner = ( + f"{inner_without_trailing_space}" + f"{property_indent}+ref?: {ref_prop_type},\n" + f"{closing_indent}" + ) + else: + new_inner = ( + f"\n{property_indent}+ref?: {ref_prop_type},\n" + f"{closing_indent}" + ) + + return f"{open_token}{new_inner}{close_token}{trailing_whitespace}" + + +def _with_optional_ref_property( + props_type_text: str, + props_type_node: Optional[Dict[str, Any]], + instance_type_text: Optional[str], +) -> str: + if not instance_type_text: + return props_type_text + if _props_text_has_ref_property(props_type_text): + return props_type_text + ref_prop_type = _to_ref_setter_type(instance_type_text) + if props_type_node and props_type_node.get("type") == "ObjectTypeAnnotation": + if _object_type_has_ref_property(props_type_node): + return props_type_text + return _append_ref_property_to_object_type(props_type_text, ref_prop_type) + if props_type_text.strip() == "any": + return f"{{ +ref?: {ref_prop_type}, ... }}" + return f"{{ ...{props_type_text}, +ref?: {ref_prop_type} }}" + + +def _abstract_component_to_component_type( + node: Dict[str, Any], content: bytes +) -> Optional[str]: + if node.get("type") != "GenericTypeAnnotation": + return None + if not _is_react_abstract_component_type(node.get("id")): + return None + + type_params = _type_parameter_nodes(node.get("typeParameters")) + if not type_params: + return "React.ComponentType" + + props_node = type_params[0] + props_type = ( + _node_text(content, props_node).strip() if "range" in props_node else "any" + ) + if not props_type: + props_type = "any" + + instance_type = None + if len(type_params) >= 2: + instance_node = type_params[1] + if "range" in instance_node: + instance_type = _node_text(content, instance_node).strip() + + props_type = _with_optional_ref_property(props_type, props_node, instance_type) + return f"React.ComponentType<{props_type}>" + + +def _extract_ref_type_from_component( + component_node: Dict[str, Any], content: bytes +) -> Optional[str]: + # Form: component(ref: Type, ...Props) + for param in component_node.get("params", []): + if not isinstance(param, dict): + continue + if param.get("name") == "ref": + type_annotation = param.get("typeAnnotation") + if isinstance(type_annotation, dict) and "range" in type_annotation: + return _node_text(content, type_annotation).strip() + + # Form: component(...{ ...Props, +ref?: Type }) + rest = component_node.get("rest") + if not isinstance(rest, dict): + return None + rest_type = rest.get("typeAnnotation") + if not isinstance(rest_type, dict): + return None + if rest_type.get("type") != "ObjectTypeAnnotation": + return None + for prop in rest_type.get("properties", []): + if not isinstance(prop, dict): + continue + if prop.get("type") != "ObjectTypeProperty": + continue + if _object_property_key_name(prop) != "ref": + continue + value = prop.get("value") + if isinstance(value, dict) and "range" in value: + return _node_text(content, value).strip() + return None + + +def _component_to_legacy_type( + component_node: Dict[str, Any], content: bytes +) -> str: + props_type = "any" + props_type_node: Optional[Dict[str, Any]] = None + rest = component_node.get("rest") + if isinstance(rest, dict): + rest_type = rest.get("typeAnnotation") + if isinstance(rest_type, dict) and "range" in rest_type: + props_type_node = rest_type + extracted_props = _node_text(content, rest_type).strip() + if extracted_props: + props_type = extracted_props + + ref_type = _extract_ref_type_from_component(component_node, content) + + renders_type = None + renders = component_node.get("rendersType") + if isinstance(renders, dict): + rendered = renders.get("typeAnnotation") + if isinstance(rendered, dict) and "range" in rendered: + renders_type = _node_text(content, rendered).strip() + + ref_instance_type = ref_type + if not ref_instance_type and renders_type and not _is_render_node_like(renders_type): + # Non-React-node renders targets generally represent a component + # interface/instance type. In modern Flow this is represented with a + # `ref` prop typed with React.RefSetter. + ref_instance_type = renders_type + + props_type = _with_optional_ref_property( + props_type, props_type_node, ref_instance_type + ) + + return f"React.ComponentType<{props_type}>" + + +def _apply_replacements( + content: bytes, replacements: List[Tuple[int, int, str]] +) -> Tuple[bytes, int]: + valid: List[Tuple[int, int, bytes]] = [] + for start, end, replacement in replacements: + if start >= end: + continue + replacement_bytes = replacement.encode("utf-8") + if content[start:end] == replacement_bytes: + continue + valid.append((start, end, replacement_bytes)) + + if not valid: + return content, 0 + + # Prefer outer nodes first when ranges overlap. + valid.sort(key=lambda item: (item[0], -(item[1] - item[0]))) + non_overlapping: List[Tuple[int, int, bytes]] = [] + current_end = -1 + for start, end, replacement_bytes in valid: + if start < current_end: + continue + non_overlapping.append((start, end, replacement_bytes)) + current_end = end + + updated = bytearray(content) + for start, end, replacement_bytes in reversed(non_overlapping): + updated[start:end] = replacement_bytes + + return bytes(updated), len(non_overlapping) + + +def _collect_component_and_renders_replacements( + ast: Dict[str, Any], content: bytes +) -> List[Tuple[int, int, str]]: + replacements: List[Tuple[int, int, str]] = [] + + def visit(node: Dict[str, Any], parent_type: Optional[str]) -> None: + node_type = node.get("type") + if node_type == "ComponentTypeAnnotation" and "range" in node: + start, end = node["range"] + replacements.append((start, end, _component_to_legacy_type(node, content))) + return + + if node_type == "GenericTypeAnnotation" and "range" in node: + replacement = _abstract_component_to_component_type(node, content) + if replacement: + start, end = node["range"] + replacements.append((start, end, replacement)) + + if ( + node_type == "TypeOperator" + and node.get("operator") == "renders" + and parent_type != "ComponentTypeAnnotation" + and "range" in node + ): + type_annotation = node.get("typeAnnotation") + if isinstance(type_annotation, dict) and "range" in type_annotation: + rendered_type = _node_text(content, type_annotation) + replacements.append( + ( + node["range"][0], + node["range"][1], + _normalize_renders_target(rendered_type), + ) + ) + + _walk(ast, visit) + return replacements + + +def _collect_as_replacements( + ast: Dict[str, Any], content: bytes +) -> List[Tuple[int, int, str]]: + replacements: List[Tuple[int, int, str]] = [] + + def visit(node: Dict[str, Any], _parent_type: Optional[str]) -> None: + if node.get("type") != "AsExpression": + return + if "range" not in node: + return + expression = node.get("expression") + type_annotation = node.get("typeAnnotation") + if not isinstance(expression, dict) or "range" not in expression: + return + if not isinstance(type_annotation, dict) or "range" not in type_annotation: + return + + start, end = node["range"] + expr_start, expr_end = expression["range"] + type_start, _type_end = type_annotation["range"] + type_text = _node_text(content, type_annotation) + + leading = content[start:expr_start].decode("utf-8") + expr_core = content[expr_start:expr_end].decode("utf-8") + between = content[expr_end:type_start].decode("utf-8") + as_index = between.rfind(" as ") + if as_index == -1: + return + + between_before_as = between[:as_index] + trailing_comment = "" + + line_comment_index = between_before_as.rfind("//") + block_comment_index = between_before_as.rfind("/*") + if line_comment_index != -1: + trailing_comment = between_before_as[line_comment_index:].strip() + between_before_as = between_before_as[:line_comment_index] + elif block_comment_index != -1 and "*/" in between_before_as[block_comment_index:]: + trailing_comment = between_before_as[block_comment_index:].strip() + between_before_as = between_before_as[:block_comment_index] + + expression_text = f"{leading}{expr_core}{between_before_as}".rstrip() + replacement = f"({expression_text}: {type_text})" + if trailing_comment: + replacement = f"{replacement} {trailing_comment}" + replacements.append((start, end, replacement)) + + _walk(ast, visit) + return replacements + + +def _remove_stale_prop_missing_fixmes(content: bytes) -> Tuple[bytes, int]: + try: + text = content.decode("utf-8") + except UnicodeDecodeError: + return content, 0 + + lines = text.splitlines(keepends=True) + keep_lines: List[str] = [] + removed = 0 + + specific_fixme_re = re.compile(r"^\s*// \$FlowFixMe\[prop-missing\]\s*$") + any_fixme_re = re.compile(r"^\s*// \$FlowFixMe\[[^\]]+\]\s*$") + + i = 0 + while i < len(lines): + current_stripped = lines[i].strip() + if specific_fixme_re.match(current_stripped): + j = i + 1 + inspected = 0 + remove_current = False + while j < len(lines) and inspected < 8: + candidate = lines[j].strip() + inspected += 1 + if not candidate: + j += 1 + continue + if any_fixme_re.match(candidate): + j += 1 + continue + if "React.ComponentType<" in lines[j]: + remove_current = True + break + if remove_current: + removed += 1 + i += 1 + continue + keep_lines.append(lines[i]) + i += 1 + + if removed == 0: + return content, 0 + return "".join(keep_lines).encode("utf-8"), removed + + +def _process_file(path: pathlib.Path) -> Tuple[bool, int]: + original = path.read_bytes() + + # Quick pre-filter to avoid expensive AST parsing on unrelated files. + has_componenttype_prop_missing = ( + b"$FlowFixMe[prop-missing]" in original and b"React.ComponentType<" in original + ) + if ( + b"component(" not in original + and b"renders " not in original + and b" as " not in original + and b"AbstractComponent" not in original + and b"React$AbstractComponent" not in original + and not has_componenttype_prop_missing + ): + return False, 0 + + try: + text = original.decode("utf-8") + except UnicodeDecodeError: + return False, 0 + + relative_path = os.path.relpath(path, APP_DIR) + ast = _run_flow_ast(relative_path, text) + if ast is None: + return False, 0 + + content = original + total_replacements = 0 + + # Pass 1: component(...) + renders. + pass1_replacements = _collect_component_and_renders_replacements(ast, content) + content, applied = _apply_replacements(content, pass1_replacements) + total_replacements += applied + + # Pass 2: "as" casts. Run iteratively to handle nested casts. + for _ in range(10): + if b" as " not in content: + break + try: + content_text = content.decode("utf-8") + except UnicodeDecodeError: + break + as_ast = _run_flow_ast(relative_path, content_text) + if as_ast is None: + break + as_replacements = _collect_as_replacements(as_ast, content) + content, applied = _apply_replacements(content, as_replacements) + total_replacements += applied + if applied == 0: + break + + content, removed_fixmes = _remove_stale_prop_missing_fixmes(content) + total_replacements += removed_fixmes + + if content != original: + path.write_bytes(content) + return True, total_replacements + return False, 0 + + +def main() -> int: + files_modified = 0 + replacements_applied = 0 + + for path in sorted(SRC_DIR.rglob("*.js")): + if not path.is_file(): + continue + modified, replacements = _process_file(path) + if modified: + files_modified += 1 + replacements_applied += replacements + + print(f" Modified {files_modified} files ({replacements_applied} replacements)") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/newIDE/app/scripts/fix-flow-errors.sh b/newIDE/app/scripts/fix-flow-errors.sh new file mode 100755 index 0000000000..1b2d558496 --- /dev/null +++ b/newIDE/app/scripts/fix-flow-errors.sh @@ -0,0 +1,884 @@ +#!/bin/bash +set -e + +# Flow migration fix script (0.131 -> 0.299) +# This script is idempotent - it can be run multiple times safely. +# It fixes Flow type errors after upgrading from Flow 0.131 to 0.299. +# +# NOTE: We DO run "flow codemod annotate-exports", then normalize the +# generated modern syntax (component()/renders/as-casts) back to +# Babel-compatible Flow syntax. +# +# Usage: cd newIDE/app && bash scripts/fix-flow-errors.sh + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +APP_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +export APP_DIR + +cd "$APP_DIR" + +echo "=== Flow Migration Fix Script ===" +echo "Working directory: $APP_DIR" + +############################################################################### +# STEP 1: Ensure flow-libs directory exists +############################################################################### +echo "" +echo "--- Step 1: Ensuring flow-libs are in place ---" +if [ ! -d "$APP_DIR/flow-libs" ]; then + echo "ERROR: flow-libs directory not found." + exit 1 +fi +echo " OK." + +############################################################################### +# STEP 1b: Update flow-bin version to 0.299.0 in package.json and npm install +############################################################################### +echo "" +echo "--- Step 1b: Updating flow-bin version to 0.299.0 ---" +sed -i 's/"flow-bin": "0.131.0"/"flow-bin": "0.299.0"/' "$APP_DIR/package.json" +echo " Updated package.json. Running npm install..." +npm install +echo " Done." + +############################################################################### +# STEP 2: Update .flowconfig +############################################################################### +echo "" +echo "--- Step 2: Updating .flowconfig ---" + +if ! grep -q 'flow-libs' "$APP_DIR/.flowconfig"; then + sed -i '/^\[libs\]/a flow-libs' "$APP_DIR/.flowconfig" +fi +if ! grep -q '/flow-typed/\.\*' "$APP_DIR/.flowconfig"; then + sed -i '/^\[declarations\]/a /flow-typed/.*' "$APP_DIR/.flowconfig" +fi +if ! grep -q 'GDevelop.js/types/\.\*' "$APP_DIR/.flowconfig"; then + sed -i '/^\[declarations\]/a /../../GDevelop.js/types/.*' "$APP_DIR/.flowconfig" +fi +if ! grep -q '/flow-libs/\.\*' "$APP_DIR/.flowconfig"; then + sed -i '/^\[declarations\]/a /flow-libs/.*' "$APP_DIR/.flowconfig" +fi +if ! grep -q 'fbjs' "$APP_DIR/.flowconfig"; then + sed -i '/^\[declarations\]/a /node_modules/fbjs/.*' "$APP_DIR/.flowconfig" +fi +if ! grep -q '^\[lints\]' "$APP_DIR/.flowconfig"; then + echo -e "\n[lints]" >> "$APP_DIR/.flowconfig" +fi +echo " Done." + +############################################################################### +# STEP 3: Fix deprecated syntax in src/ files +############################################################################### +echo "" +echo "--- Step 3: Fixing deprecated syntax ---" + +# Fix existential type * -> any +find "$APP_DIR/src" -name "*.js" -type f -exec perl -pi -e ' + s/(<[^>]*?)\*([,>])/${1}any${2}/g; + s/(<[^>]*?)\*([,>])/${1}any${2}/g; + s/& \*\b/\& any/g; +' {} + + +# Fix %checks (removed in new Flow) +find "$APP_DIR/src" -name "*.js" -type f -exec sed -i 's/ %checks//g' {} + + +# Fix React$ type names -> React. namespace +find "$APP_DIR/src" -name "*.js" -type f -exec sed -i \ + -e 's/\bReact\$Element\b/React.Element/g' \ + -e 's/\bReact\$Component\b/React.Component/g' \ + -e 's/\bReact\$Node\b/React.Node/g' \ + -e 's/\bReact\$Context\b/React.Context/g' \ + -e 's/\bReact\$Ref\b/React.Ref/g' \ + -e 's/\bReact\$Key\b/React.Key/g' \ + -e 's/\bReact\$ElementRef\b/React.ElementRef/g' \ + -e 's/\bReact\$ElementConfig\b/React.ElementConfig/g' \ + -e 's/\bReact\$ComponentType\b/React.ComponentType/g' \ + {} + + +# Fix $PropertyType -> indexed access type +find "$APP_DIR/src" -name "*.js" -type f -exec perl -pi -e " + s/\\\$PropertyType<([^,]+),\s*'([^']+)'>/\$1['\$2']/g; + s/\\\$PropertyType<([^,]+),\s*\"([^\"]+)\">/\$1[\"\$2\"]/g; +" {} + + +# Fix $FlowExpectedError -> $FlowFixMe[incompatible-type] +find "$APP_DIR/src" -name "*.js" -type f -exec perl -pi -e ' + s/\$FlowExpectedError(?!\[)/\$FlowFixMe[incompatible-type]/g; + s/\$FlowExpectedError\[([^\]]+)\]/\$FlowFixMe[$1]/g; +' {} + + +# Fix old $FlowFixMe without error codes +find "$APP_DIR/src" -name "*.js" -type f -exec perl -pi -e ' + s/\$FlowFixMe(?!\[)/\$FlowFixMe[incompatible-type]/g; +' {} + + +echo " Done." + +############################################################################### +# STEP 4: Run annotate-exports and normalize syntax +############################################################################### +echo "" +echo "--- Step 4: Running Flow codemod annotate-exports ---" + +npx flow stop 2>/dev/null || true + +for i in $(seq 1 5); do + echo " Codemod iteration $i..." + set +e + CODEMOD_OUTPUT=$(npx flow codemod annotate-exports --write --default-any src 2>&1) + CODEMOD_EXIT=$? + set -e + + echo "$CODEMOD_OUTPUT" | grep -E \ + "Files changed:|Number of annotations added:|Number of sig\. ver\. errors:|Number of annotations required:" || true + + if [ $CODEMOD_EXIT -ne 0 ]; then + echo " WARNING: annotate-exports exited with status $CODEMOD_EXIT" + break + fi + + FILES_CHANGED=$(echo "$CODEMOD_OUTPUT" | sed -n 's/.*Files changed:[[:space:]]*\([0-9][0-9]*\).*/\1/p' | head -n 1) + if [ -z "$FILES_CHANGED" ]; then + echo " WARNING: Could not parse codemod output." + break + fi + + if [ "$FILES_CHANGED" -eq 0 ]; then + echo " Codemod converged." + break + fi +done + +echo " Normalizing codemod syntax to Babel-compatible Flow..." +python3 "$SCRIPT_DIR/fix-codemod-syntax.py" + +# Fix arrow-function inline object return types that prettier 1.15 can't parse. +# The codemod may add return type annotations like: +# const foo = (): { prop: Type } => { ... } +# Prettier 1.15 can't parse the `: { ... } =>` pattern. +# Fix: extract the inline type into a named type alias, preserving typing. +echo " Fixing arrow-function return types for prettier compatibility..." +python3 "$SCRIPT_DIR/fix-arrow-return-types.py" + +echo " Done." + +############################################################################### +# STEP 4b: Fix codemod artifacts that cause parse errors or Flow issues +############################################################################### +echo "" +echo "--- Step 4b: Fixing codemod artifacts ---" + +# 0. Remove stale FlowFixMe[prop-missing] comments that were previously added +# for invalid React.AbstractComponent output from older codemod runs. +find "$APP_DIR/src" -name "*.js" -type f -exec perl -0pi -e ' + s/^[ \t]*\/\/ \$FlowFixMe\[prop-missing\]\n(?=(?:[ \t]*\/\/ \$FlowFixMe\[[^\]]+\]\n|[ \t]*\n)*[^\n]*React\.ComponentType<)//mg; +' {} + + +# 1. Fix missing commas after ([]: Array) in object literals. +# The codemod turns "[]," into "([]: Array)" but loses the comma. +find "$APP_DIR/src" -name "*.js" -type f -exec perl -pi -e ' + s/\(\[\]: Array\)(\s*\/\/.*)$/([]: Array),$1/g; +' {} + + +# 2. Fix "new Array(n)" -> "new Array(n)" to avoid underconstrained type +find "$APP_DIR/src" -name "*.js" -type f -exec perl -pi -e ' + s/new Array\(([^)]+)\)\.fill\(0\)/new Array($1).fill(0)/g; +' {} + + +# 3. Fix !== null comparisons on number types -> != null +# (Flow 0.299 is strict about comparing non-nullable numbers to null) +find "$APP_DIR/src" -name "*.js" -type f -exec perl -pi -e ' + s/selectedCompletionIndex !== null/selectedCompletionIndex != null/g; +' {} + + +# 5. Generic type params like new Set(), new Map(), React.createRef() +# are NOT parseable by prettier 1.15 (it treats < as comparison operator). +# These will get FlowFixMe[underconstrained-implicit-instantiation] automatically. + +# 6. new Array(n) patterns beyond .fill(0) also can't use with prettier 1.15. + +# 7. axios calls with type params - skip, prettier 1.15 mangles method() syntax. +# These will get FlowFixMe[underconstrained-implicit-instantiation] automatically. + +# 8. jest.fn() - leave as-is, prettier 1.15 can't parse jest.fn() +# These will get FlowFixMe[underconstrained-implicit-instantiation] automatically. + +# 9. Fix method-unbinding for common patterns: .push.apply -> spread syntax +# Handles both single-line and multi-line push.apply patterns. +python3 << 'PYEOF' +import os, re + +src_dir = os.path.join(os.environ.get('APP_DIR', os.getcwd()), 'src') +fixed = 0 + +for root, dirs, files in os.walk(src_dir): + for fname in files: + if not fname.endswith('.js'): + continue + filepath = os.path.join(root, fname) + with open(filepath) as f: + content = f.read() + original = content + # Multi-line pattern: arr.push.apply(\n arr,\n items\n) + content = re.sub( + r'(\w+)\.push\.apply\(\s*\1\s*,\s*([^)]+?)\s*\)', + lambda m: f'{m.group(1)}.push(...{m.group(2).strip()})', + content, + flags=re.DOTALL) + if content != original: + with open(filepath, 'w') as f: + f.write(content) + fixed += 1 + +print(f" Converted {fixed} push.apply to spread syntax") +PYEOF + +# 10. Fix import-type-as-value: convert value imports of type-only symbols to import type. +# I18n from @lingui/core is a type (interface) used only in type positions. +find "$APP_DIR/src" -name "*.js" -type f -exec perl -pi -e ' + s/^(\/\/ \$FlowFixMe\[import-type-as-value\]\n)?import \{ I18n as I18nType \} from/import type { I18n as I18nType } from/g; +' {} + + +# Fix TreeViewItemContent import-type-as-value: these are interfaces (type-only) +python3 << 'PYEOF' +import os, re + +app_dir = os.environ.get('APP_DIR', os.getcwd()) +src_dir = os.path.join(app_dir, 'src') +fixed = 0 + +for root, dirs, files in os.walk(src_dir): + for fname in files: + if not fname.endswith('.js'): + continue + filepath = os.path.join(root, fname) + with open(filepath) as f: + content = f.read() + original = content + + # Remove FlowFixMe[import-type-as-value] above import lines where + # we can safely convert to import type + lines = content.split('\n') + new_lines = [] + i = 0 + while i < len(lines): + line = lines[i] + # Skip FlowFixMe[import-type-as-value] if the next line is an import we'll fix + if '$FlowFixMe[import-type-as-value]' in line: + # Check if this is a standalone FlowFixMe comment line + stripped = line.lstrip() + if stripped.startswith('// $FlowFixMe[import-type-as-value]'): + # Check if next line is an import statement + if i + 1 < len(lines) and 'import' in lines[i + 1]: + # Skip this FlowFixMe comment + i += 1 + continue + # Check if this is inside an import block (destructured import) + # Look backwards for the import statement + is_in_import = False + for j in range(i - 1, max(i - 10, -1), -1): + if 'import' in lines[j] and '{' in lines[j]: + is_in_import = True + break + if '}' in lines[j] and 'from' in lines[j]: + break + if is_in_import: + # Skip this FlowFixMe + i += 1 + continue + new_lines.append(line) + i += 1 + + content = '\n'.join(new_lines) + + # Convert import { I18n as I18nType } to import type + content = re.sub( + r"import \{ I18n as I18nType \} from '@lingui/core'", + "import type { I18n as I18nType } from '@lingui/core'", + content) + + if content != original: + with open(filepath, 'w') as f: + f.write(content) + fixed += 1 + +print(f" Fixed {fixed} import-type-as-value issues") +PYEOF + +# 4. Fix inline object return types on multi-line arrow function params +# that fix-arrow-return-types.py couldn't handle (nested parens in destructured args). +# Pattern: ): { ... } => { (where the object return type causes prettier parse error) +python3 << 'PYEOF' +import os, re, subprocess + +app_dir = os.environ.get('APP_DIR', os.getcwd()) + +# Find files with prettier parse errors +result = subprocess.run( + ['npx', 'prettier', '--list-different', 'src/!(locales)/**/*.js'], + capture_output=True, text=True, cwd=app_dir, timeout=120 +) +all_output = result.stdout + '\n' + result.stderr +error_files = set() +for line in all_output.split('\n'): + m = re.match(r'\[error\]\s+(src/\S+\.js):\s+SyntaxError', line) + if m: + error_files.add(os.path.join(app_dir, m.group(1))) + +fixed = 0 +for filepath in error_files: + if not os.path.isfile(filepath): + continue + with open(filepath) as f: + content = f.read() + original = content + + # Find ): { ... } => patterns (multi-line object return types) + # This regex works on the whole content to find the ): { ... } => pattern + # We need to use a balanced-brace approach + pos = 0 + replacements = [] + while True: + idx = content.find('):', pos) + if idx == -1: + break + # Check if followed by whitespace then { + rest = content[idx+2:].lstrip() + if not rest.startswith('{'): + pos = idx + 2 + continue + brace_start = content.index('{', idx + 2) + # Find matching close brace + depth = 0 + i = brace_start + while i < len(content): + if content[i] == '{': + depth += 1 + elif content[i] == '}': + depth -= 1 + if depth == 0: + break + elif content[i] in ('"', "'", '`'): + q = content[i] + i += 1 + while i < len(content) and content[i] != q: + if content[i] == '\\': + i += 1 + i += 1 + i += 1 + if depth != 0: + pos = idx + 2 + continue + brace_end = i + # Check if followed by => (arrow) + after = content[brace_end+1:].lstrip() + if not after.startswith('=>'): + pos = idx + 2 + continue + type_text = content[brace_start:brace_end+1] + if '\n' not in type_text: + pos = idx + 2 + continue + # Find function name for type alias + line_start = content.rfind('\n', 0, idx) + if line_start == -1: + line_start = 0 + # Find export const/let/var name = ... pattern + preceding = content[max(0, line_start-200):idx+2] + name_match = re.search(r'(?:const|let|var|function)\s+(\w+)', preceding) + name = name_match.group(1) if name_match else 'Func' + type_name = f'_{name[0].upper()}{name[1:]}ReturnType' + # Check if type alias already exists + if f'type {type_name}' in content: + pos = idx + 2 + continue + replacements.append((brace_start, brace_end+1, type_name, type_text)) + pos = brace_end + 1 + + if not replacements: + continue + + # Apply in reverse + for brace_start, brace_end, type_name, type_text in reversed(replacements): + content = content[:brace_start] + type_name + content[brace_end:] + + # Insert type declarations at the top (after imports) + insert_lines = [] + for _, _, type_name, type_text in replacements: + insert_lines.append(f'type {type_name} = {type_text};\n') + + # Find insertion point (after last import) + last_import = 0 + for m in re.finditer(r'^(?:import\s|from\s)', content, re.MULTILINE): + eol = content.find('\n', m.start()) + # Handle multi-line imports + if '{' in content[m.start():eol] and '}' not in content[m.start():eol]: + eol = content.find('}', eol) + eol = content.find('\n', eol) + # Handle from '...' on next line + next_line_start = eol + 1 + if next_line_start < len(content): + next_stripped = content[next_line_start:].lstrip() + if next_stripped.startswith("from ") or next_stripped.startswith("} from "): + eol = content.find('\n', next_line_start) + if eol > last_import: + last_import = eol + if last_import > 0: + insert_pos = last_import + 1 + else: + insert_pos = 0 + insert_text = '\n' + ''.join(insert_lines) + '\n' + content = content[:insert_pos] + insert_text + content[insert_pos:] + + if content != original: + with open(filepath, 'w') as f: + f.write(content) + fixed += 1 + +print(f" Fixed {fixed} additional arrow-return-type files") +PYEOF + +echo " Done." + +############################################################################### +# STEP 5: Fix specific known issues +############################################################################### +echo "" +echo "--- Step 5: Fixing specific known issues ---" + +# Fix GDevelop.js type files (if they exist and don't have FlowFixMe) +GD_TYPES="$APP_DIR/../../GDevelop.js/types" +if [ -d "$GD_TYPES" ]; then + python3 << 'PYEOF' +import os, re + +gd_types = os.environ.get('GD_TYPES', '../../GDevelop.js/types') + +for fname in ['gdbehaviorjsimplementation.js', 'gdbehaviorshareddatajsimplementation.js']: + filepath = os.path.join(gd_types, fname) + if not os.path.isfile(filepath): + continue + with open(filepath) as f: + content = f.read() + if '$FlowFixMe' in content: + continue + for method in ['getProperties(', 'updateProperty(', 'initializeContent(']: + content = content.replace(f' {method}', f' // $FlowFixMe[incompatible-type]\n {method}') + with open(filepath, 'w') as f: + f.write(content) + +filepath = os.path.join(gd_types, 'libgdevelop.js') +if os.path.isfile(filepath): + with open(filepath) as f: + lines = f.readlines() + if '$FlowFixMe' not in ''.join(lines): + fixes = {19: 'cannot-resolve-name', 20: 'cannot-resolve-name', 39: 'cannot-resolve-name', 297: 'cannot-resolve-name'} + new_lines = [] + for i, line in enumerate(lines): + if i + 1 in fixes: + new_lines.append(f' // $FlowFixMe[{fixes[i+1]}]\n') + new_lines.append(line) + with open(filepath, 'w') as f: + f.writelines(new_lines) + +print(" Fixed GDevelop.js types") +PYEOF +fi + +# Fix Theme/index.js - $PropertyType replacement may leave empty type or +# indexed access type (Theme['gdevelopTheme']) that prettier 1.15 can't parse. +# Use typeof DefaultLightTheme.gdevelopTheme which both Flow 0.299 and prettier understand. +THEME_FILE="$APP_DIR/src/UI/Theme/index.js" +python3 << 'PYEOF' +import os, re +theme_file = os.path.join(os.environ.get('APP_DIR', os.getcwd()), 'src/UI/Theme/index.js') +if os.path.isfile(theme_file): + with open(theme_file) as f: + content = f.read() + original = content + # Fix empty type from $PropertyType removal + content = content.replace("export type GDevelopTheme = ;", + "export type GDevelopTheme = typeof DefaultLightTheme.gdevelopTheme;") + # Fix indexed access type that prettier 1.15 can't parse + content = re.sub( + r"export type GDevelopTheme = Theme\['gdevelopTheme'\];", + "export type GDevelopTheme = typeof DefaultLightTheme.gdevelopTheme;", + content) + # Remove any stray FlowFixMe above the type export + content = re.sub( + r'(?://\s*\$FlowFixMe\[incompatible-type\]\s*\n|\{/\*\s*\$FlowFixMe\[incompatible-type\]\s*\*/\}\s*\n)' + r'(export type GDevelopTheme)', + r'\1', content) + # Remove any stale prettier-ignore before the line + content = re.sub( + r'// prettier-ignore\n(export type GDevelopTheme)', + r'\1', content) + if content != original: + with open(theme_file, 'w') as f: + f.write(content) + print(" Fixed Theme/index.js") + else: + print(" Theme/index.js already correct") +PYEOF + +# Fix known annotate-exports gaps and formatting-displacement issues. +python3 << 'PYEOF' +import os +import re + +app_dir = os.environ.get('APP_DIR', os.getcwd()) + +# Regex-based replacements for signature-verification gaps +replacements = [ + ( + os.path.join(app_dir, 'src/EventsSheet/index.js'), + r'onResourceExternallyChanged = resourceInfo => \{', + 'onResourceExternallyChanged = (resourceInfo: any) => {', + ), + ( + os.path.join(app_dir, 'src/Leaderboard/LeaderboardContext.js'), + r'deleteLeaderboardEntry: async entryId => \{\},', + 'deleteLeaderboardEntry: async (entryId: any) => {},', + ), +] + +fixed = 0 +for filepath, pattern, replacement in replacements: + if not os.path.isfile(filepath): + continue + with open(filepath) as f: + content = f.read() + updated = re.sub(pattern, replacement, content) + if updated != content: + with open(filepath, 'w') as f: + f.write(updated) + fixed += 1 + +# Fix PrivateGameTemplateStoreContext: add type annotation to empty object +# that prettier splits across lines (causing FlowFixMe displacement). +pgts_file = os.path.join(app_dir, + 'src/AssetStore/PrivateGameTemplates/PrivateGameTemplateStoreContext.js') +if os.path.isfile(pgts_file): + with open(pgts_file) as f: + content = f.read() + # Add type annotation to the untyped empty object + updated = content.replace( + 'const privateGameTemplateListingDatasById = {};', + 'const privateGameTemplateListingDatasById: {[string]: any} = {};') + # Remove any stacked FlowFixMe[prop-missing] that accumulated from previous runs + updated = re.sub( + r'(\s*// \$FlowFixMe\[prop-missing\]\n)+(\s*privateGameTemplateListingDatasById\[)', + r'\2', updated) + # Also remove FlowFixMe[invalid-computed-prop] for the typed object (no longer needed) + updated = re.sub( + r'\s*// \$FlowFixMe\[invalid-computed-prop\]\n(\s*if \(privateGameTemplateListingDatasById\[)', + r'\n\1', updated) + if updated != content: + with open(pgts_file, 'w') as f: + f.write(updated) + fixed += 1 + +# Fix ConditionsActionsColumns.js - renderActionsList type needs style prop +cac_file = os.path.join(app_dir, 'src/EventsSheet/EventsTree/ConditionsActionsColumns.js') +if os.path.isfile(cac_file): + with open(cac_file) as f: + content = f.read() + updated = content.replace( + 'renderActionsList: ({ className: string }) => React.Node,', + 'renderActionsList: ({ style?: Object, className: string }) => React.Node,') + if updated != content: + with open(cac_file, 'w') as f: + f.write(updated) + fixed += 1 + +# Fix PreferencesContext.js - annotate missing params for signature-verification +pref_file = os.path.join(app_dir, 'src/MainFrame/Preferences/PreferencesContext.js') +if os.path.isfile(pref_file): + with open(pref_file) as f: + content = f.read() + updated = content + updated = updated.replace( + 'getRecentProjectFiles: options => [],', + 'getRecentProjectFiles: (options: any): any => [],') + updated = updated.replace( + 'getEditorStateForProject: projectId => {},', + 'getEditorStateForProject: (projectId: any): any => {},') + if updated != content: + with open(pref_file, 'w') as f: + f.write(updated) + fixed += 1 + +# Fix ShortcutsList.js - annotate commandName parameter +sc_file = os.path.join(app_dir, 'src/KeyboardShortcuts/ShortcutsList.js') +if os.path.isfile(sc_file): + with open(sc_file) as f: + content = f.read() + updated = content.replace( + 'areaWiseCommands[areaName].map(commandName =>', + 'areaWiseCommands[areaName].map((commandName: string) =>') + if updated != content: + with open(sc_file, 'w') as f: + f.write(updated) + fixed += 1 + +# Fix ProjectManager/index.js - useState(null) needs type param for ?gdLayout +pm_file = os.path.join(app_dir, 'src/ProjectManager/index.js') +if os.path.isfile(pm_file): + with open(pm_file) as f: + content = f.read() + updated = content + # Add type annotation to useState calls that should be ?gdLayout + updated = re.sub( + r'const \[editedPropertiesLayout, setEditedPropertiesLayout\] = React\.useState\(\s*\n\s*null\s*\n\s*\)', + 'const [editedPropertiesLayout, setEditedPropertiesLayout] = React.useState(\n null\n )', + updated) + updated = re.sub( + r'const \[editedVariablesLayout, setEditedVariablesLayout\] = React\.useState\(\s*\n\s*null\s*\n\s*\)', + 'const [editedVariablesLayout, setEditedVariablesLayout] = React.useState(\n null\n )', + updated) + if updated != content: + with open(pm_file, 'w') as f: + f.write(updated) + fixed += 1 + +# Fix CollisionMasksPreview.js - use type cast for inexact/exact mismatch +cmp_file = os.path.join(app_dir, 'src/ObjectEditor/Editors/SpriteEditor/CollisionMasksEditor/CollisionMasksPreview.js') +if os.path.isfile(cmp_file): + with open(cmp_file) as f: + content = f.read() + # Cast polygons to any to bypass inexact/exact mismatch + updated = content.replace( + 'mapVector(polygons,', + 'mapVector((polygons: any),') + if updated != content: + with open(cmp_file, 'w') as f: + f.write(updated) + fixed += 1 + +print(f" Fixed {fixed} known annotate-exports signature gaps and type issues") +PYEOF + +echo " Done." + +############################################################################### +# STEP 6: Run prettier formatting (pre-FlowFixMe) +############################################################################### +echo "" +echo "--- Step 6: Running prettier formatting (pre-FlowFixMe) ---" + +# Format all source files before adding FlowFixMe. +# This ensures FlowFixMe comments will be placed at the correct post-format +# line numbers. +npm run format 2>&1 || true +echo " Done." + +############################################################################### +# STEP 7: Add $FlowFixMe for all remaining errors (iterative) +############################################################################### +echo "" +echo "--- Step 7: Adding \$FlowFixMe for all errors (iterative) ---" + +npx flow stop 2>/dev/null || true + +PREV_ERROR_COUNT="" +for i in $(seq 1 15); do + echo " Iteration $i..." + + # Add FlowFixMe comments for errors + FLOWFIXME_OUTPUT=$(python3 "$SCRIPT_DIR/add-flow-fixme.py" 2>&1 || true) + echo "$FLOWFIXME_OUTPUT" | grep -E "Added|Found|No" || true + + # Convert // FlowFixMe in JSX context to {/* FlowFixMe */} + JSX_CONVERT_OUTPUT=$(python3 "$SCRIPT_DIR/convert-jsx-flowfixme.py" 2>&1 || true) + echo "$JSX_CONVERT_OUTPUT" | grep -E "Converted|Reverted" || true + + npx flow stop 2>/dev/null || true + + # Check remaining errors + set +e + ERROR_OUTPUT=$(npx flow 2>&1) + FLOW_EXIT=$? + set -e + if echo "$ERROR_OUTPUT" | grep -q "No errors"; then + echo " No more errors!" + break + fi + + ERROR_COUNT=$(echo "$ERROR_OUTPUT" | grep "Found" | grep -o '[0-9]*' | head -1) + echo " Remaining errors: ${ERROR_COUNT:-unknown} (flow exit: $FLOW_EXIT)" + + if echo "$FLOWFIXME_OUTPUT" | grep -q "Added 0 \$FlowFixMe comments" && \ + [ -n "$ERROR_COUNT" ] && [ "$ERROR_COUNT" = "$PREV_ERROR_COUNT" ]; then + echo " No automatic progress in this iteration; stopping early." + break + fi + + PREV_ERROR_COUNT="$ERROR_COUNT" + npx flow stop 2>/dev/null || true +done + +############################################################################### +# STEP 8: Post-FlowFixMe format + fix cycle +############################################################################### +echo "" +echo "--- Step 8: Post-FlowFixMe format and fix cycle ---" + +# After adding FlowFixMe comments, formatting may introduce new errors +# (e.g., FlowFixMe comments getting displaced from error lines). +# Run format + flow check + FlowFixMe in a cycle until stable. +for j in $(seq 1 3); do + echo " Format-fix cycle iteration $j..." + + npm run format 2>&1 || true + + npx flow stop 2>/dev/null || true + set +e + CYCLE_CHECK=$(npx flow 2>&1) + set -e + + if echo "$CYCLE_CHECK" | grep -q "No errors"; then + echo " No errors after formatting - cycle complete!" + break + fi + + CYCLE_ERRORS=$(echo "$CYCLE_CHECK" | grep "Found" | grep -o '[0-9]*' | head -1) + echo " $CYCLE_ERRORS errors after formatting, adding FlowFixMe..." + + python3 "$SCRIPT_DIR/add-flow-fixme.py" 2>&1 || true + python3 "$SCRIPT_DIR/convert-jsx-flowfixme.py" 2>&1 || true +done + +echo " Done." + +############################################################################### +# STEP 9: Final format verification +############################################################################### +echo "" +echo "--- Step 9: Final format verification ---" + +npm run format 2>&1 || true + +npx flow stop 2>/dev/null || true +set +e +FINAL_CHECK=$(npx flow 2>&1) +set -e + +if echo "$FINAL_CHECK" | grep -q "No errors"; then + echo " All clean!" +else + echo " WARNING: Still have errors after all cycles:" + echo "$FINAL_CHECK" | grep "Found" || true +fi + +echo " Done." + +############################################################################### +# STEP 10: Fix eslint-disable-next-line ordering with $FlowFixMe +############################################################################### +echo "" +echo "--- Step 10: Fixing eslint/FlowFixMe comment ordering ---" + +# When $FlowFixMe is inserted between eslint-disable-next-line and the code, +# eslint-disable no longer applies (it targets the FlowFixMe comment instead). +# Fix: wrap the code with eslint-disable/eslint-enable block comments, so that +# both the FlowFixMe suppression and the eslint suppression work correctly. +python3 << 'PYEOF' +import os, re + +src_dir = os.path.join(os.environ.get('APP_DIR', os.getcwd()), 'src') +fixed = 0 + +for root, dirs, files in os.walk(src_dir): + for fname in files: + if not fname.endswith('.js'): + continue + filepath = os.path.join(root, fname) + with open(filepath) as f: + lines = f.readlines() + + modified = False + new_lines = [] + i = 0 + while i < len(lines): + # Pattern: eslint-disable-next-line, then one or more $FlowFixMe[...], then code + if (i + 2 < len(lines) and + 'eslint-disable-next-line' in lines[i] and + '$FlowFixMe[' in lines[i + 1]): + m = re.search(r'eslint-disable-next-line\s+(.+)', lines[i]) + if m: + rule = m.group(1).strip() + # Collect all consecutive FlowFixMe lines + fixme_lines = [] + j = i + 1 + while j < len(lines) and '$FlowFixMe[' in lines[j]: + fixme_lines.append(lines[j]) + j += 1 + if j < len(lines): + code_line = lines[j] + indent = '' + for ch in code_line: + if ch in (' ', '\t'): + indent += ch + else: + break + # Use eslint-disable/enable block wrapping FlowFixMe + code + new_lines.append(f'{indent}/* eslint-disable {rule} */\n') + for fl in fixme_lines: + new_lines.append(fl) + new_lines.append(code_line) + new_lines.append(f'{indent}/* eslint-enable {rule} */\n') + i = j + 1 + modified = True + fixed += 1 + continue + # Pattern: one or more $FlowFixMe[...], then eslint-disable-next-line, then code + elif (i + 2 < len(lines) and + '$FlowFixMe[' in lines[i] and + 'eslint-disable-next-line' in lines[i + 1]): + # Find where the FlowFixMe block starts + fixme_start = i + # The eslint line is after one FlowFixMe; collect FlowFixMe after it too + m = re.search(r'eslint-disable-next-line\s+(.+)', lines[i + 1]) + if m: + rule = m.group(1).strip() + j = i + 2 + # Code line is right after eslint-disable-next-line + if j < len(lines): + code_line = lines[j] + indent = '' + for ch in code_line: + if ch in (' ', '\t'): + indent += ch + else: + break + new_lines.append(f'{indent}/* eslint-disable {rule} */\n') + new_lines.append(lines[i]) # Keep $FlowFixMe + new_lines.append(code_line) + new_lines.append(f'{indent}/* eslint-enable {rule} */\n') + i = j + 1 + modified = True + fixed += 1 + continue + + new_lines.append(lines[i]) + i += 1 + + if modified: + with open(filepath, 'w') as f: + f.writelines(new_lines) + +print(f" Fixed {fixed} eslint/FlowFixMe orderings") +PYEOF + +############################################################################### +# STEP 11: Final format after all fixes +############################################################################### +echo "" +echo "--- Step 11: Final format pass ---" +npm run format 2>&1 || true +echo " Done." + +echo "" +echo "=== Flow Migration Fix Script Complete ===" +echo "Run 'npm run flow' and 'npm run build' to verify."