diff --git a/TS.fsx b/TS.fsx index 7ccb2907a..92858a677 100644 --- a/TS.fsx +++ b/TS.fsx @@ -33,6 +33,11 @@ module Helpers = match FSharpValue.GetUnionFields(x, typeof<'a>) with | case, _ -> case.Name + let inline toNameMap< ^a when ^a: (member Name: string) > (data: array< ^a > ) = + data + |> Array.map (fun x -> ((^a: (member Name: string) x), x)) + |> Map.ofArray + module Option = let runIfSome f x = match x with @@ -131,6 +136,142 @@ module Types = type ExtendConflict = { BaseType: string; ExtendType: string list; MemberNames: string list } +module InputIdlJson = + open Helpers + open System.Xml.Linq + + type InputIdlJsonType = JsonProvider<"inputfiles/sample.webidl.json"> + + let inputIdl = + let jsons = + DirectoryInfo(GlobalVars.inputFolder + @"/idls").GetFiles() + |> Array.map (fun file -> file.FullName |> File.ReadAllText |> InputIdlJsonType.Parse) + + let inline extractJsonArray f = + jsons |> Array.collect f |> Array.map (fun item -> (^a: (member JsonValue: JsonValue) item)) |> JsonValue.Array; + + let list = [| ("callbackFunctions", extractJsonArray (fun json -> json.CallbackFunctions)); + ("interfaces", extractJsonArray (fun json -> json.Interfaces)); + ("dictionaries", extractJsonArray (fun json -> json.Dictionaries)); + ("typedefs", extractJsonArray (fun json -> json.Typedefs)) |] + InputIdlJsonType.Root(JsonValue.Record list) + + let allCallbackFunctionsMap = + inputIdl.CallbackFunctions |> toNameMap + + let allInterfacesMap = + inputIdl.Interfaces |> toNameMap + + let allDictionariesMap = + inputIdl.Dictionaries |> toNameMap + + let allTypedefsMap = + inputIdl.Typedefs |> toNameMap + + let hasType itemName = + allCallbackFunctionsMap.ContainsKey itemName || + allInterfacesMap.ContainsKey itemName || + allDictionariesMap.ContainsKey itemName || + allTypedefsMap.ContainsKey itemName + + module Compat = + let xNamespace = XNamespace.Get "http://schemas.microsoft.com/ie/webidl-xml" + let convertArgument (i: InputIdlJsonType.Argument) = + let param = XElement(xNamespace + "param", XAttribute (XName.Get "name", i.Name), XAttribute (XName.Get "type", i.Type)) + if OptionCheckValue true i.Optional then + param.Add (XAttribute(XName.Get "optional", "1")) + if OptionCheckValue true i.Nullable then + param.Add (XAttribute(XName.Get "nullable", "1")) + if OptionCheckValue true i.Variadic then + param.Add (XAttribute(XName.Get "variadic", "1")) + param + + let convertOperation (i: InputIdlJsonType.Operation) = + let method = XElement(xNamespace + "method", XAttribute (XName.Get "name", i.Name), XAttribute (XName.Get "type", i.Type)) + + method.Add(i.Arguments |> Array.map convertArgument) + if OptionCheckValue true i.Static then + method.Add(XAttribute(XName.Get "static", "1")) + if OptionCheckValue true i.Nullable then + method.Add(XAttribute(XName.Get "nullable", "1")) + + method + + let convertConstructor(i: InputIdlJsonType.Constructor) = + let constructor = XElement(xNamespace + "constructor") + + if not (Array.isEmpty i.Arguments) then + constructor.Add(i.Arguments |> Array.map convertArgument) + + constructor + + let convertAttribute (i: InputIdlJsonType.Attribute) = + let property = XElement(xNamespace + "property", XAttribute (XName.Get "name", i.Name), XAttribute (XName.Get "type", i.Type)) + + if OptionCheckValue true i.Readonly then + property.Add(XAttribute(XName.Get "read-only", "1")) + if OptionCheckValue true i.Static then + property.Add(XAttribute(XName.Get "static", "1")) + if OptionCheckValue true i.Stringifier then + property.Add(XAttribute(XName.Get "stringifier", "1")) + if OptionCheckValue true i.Nullable then + property.Add(XAttribute(XName.Get "nullable", "1")) + + property + + let convertConstant (i: InputIdlJsonType.Constant) = + XElement(xNamespace + "constant", XAttribute (XName.Get "name", i.Name), XAttribute (XName.Get "type", i.Type), XAttribute (XName.Get "value", i.Value)) + + let convertCallbackFunction (i: InputIdlJsonType.CallbackFunction) = + let callbackFunction = XElement(xNamespace + "callback-function", XAttribute (XName.Get "name", i.Name), XAttribute (XName.Get "type", i.Type)) + + callbackFunction.Add(i.Arguments |> Array.map convertArgument) + if OptionCheckValue true i.Nullable then + callbackFunction.Add(XAttribute(XName.Get "nullable", "1")) + + Types.Browser.CallbackFunction callbackFunction + + let convertInterface (i: InputIdlJsonType.Interfacis) = + let interfaceEl = XElement(xNamespace + "interface", XAttribute (XName.Get "name", i.Name)) + + interfaceEl.Add (XAttribute (XName.Get "extends", if i.Extends.IsSome then i.Extends.Value else "Object")) + if not (Array.isEmpty i.Constructors) then + interfaceEl.Add(i.Constructors |> Array.map convertConstructor) + if not (Array.isEmpty i.Operations) then + interfaceEl.Add(XElement(xNamespace + "methods", i.Operations |> Array.map convertOperation)) + if not (Array.isEmpty i.Attributes) then + interfaceEl.Add(XElement(xNamespace + "properties", i.Attributes |> Array.map convertAttribute)) + if not (Array.isEmpty i.Constants) then + interfaceEl.Add(XElement(xNamespace + "constants", i.Constants |> Array.map convertConstant)) + + Types.Browser.Interface interfaceEl + + let convertDictionary (i: InputIdlJsonType.Dictionary) = + let dictionary = XElement(xNamespace + "dictionary", XAttribute (XName.Get "name", i.Name)) + + dictionary.Add (XAttribute (XName.Get "extends", if i.Extends.IsSome then i.Extends.Value else "Object")) + let members = + [ for memberDef in i.Members do + let memberEl = XElement(xNamespace + "member", XAttribute (XName.Get "name", memberDef.Name), XAttribute (XName.Get "type", memberDef.Type)) + + if OptionCheckValue true memberDef.Nullable then + memberEl.Add(XAttribute(XName.Get "nullable", "1")) + if OptionCheckValue true memberDef.Required then + memberEl.Add(XAttribute(XName.Get "required", "1")) + + yield memberEl ] + + dictionary.Add(XElement(xNamespace + "members", members)) + Types.Browser.Dictionary dictionary + + let convertTypedef (i: InputIdlJsonType.Typedef) = + let typedef = XElement(xNamespace + "typedef", XAttribute (XName.Get "new-type", i.Name), XAttribute (XName.Get "type", i.Type)) + + if OptionCheckValue true i.Nullable then + typedef.Add(XAttribute(XName.Get "nullable", "1")) + + Types.Browser.Typedef typedef + module InputJson = open Helpers open Types @@ -243,6 +384,7 @@ module CommentJson = | _ -> None module Data = + open Helpers open Types // Used to decide if a member should be emitted given its static property and @@ -299,11 +441,6 @@ module Data = let allInterfaces = Array.concat [| allWebInterfaces; allWorkerAdditionalInterfaces |] - let inline toNameMap< ^a when ^a: (member Name: string) > (data: array< ^a > ) = - data - |> Array.map (fun x -> ((^a: (member Name: string) x), x)) - |> Map.ofArray - let allInterfacesMap = allInterfaces |> toNameMap @@ -682,7 +819,6 @@ module Emit = | "CanvasPixelArray" -> "number[]" | "DOMHighResTimeStamp" -> "number" | "DOMString" -> "string" - | "DOMTimeStamp" -> "number" | "EndOfStreamError" -> "number" | "double" | "float" -> "number" | "object" -> "any" @@ -699,7 +835,8 @@ module Emit = if allInterfacesMap.ContainsKey objDomType || allCallbackFuncs.ContainsKey objDomType || allDictionariesMap.ContainsKey objDomType || - allEnumsMap.ContainsKey objDomType then + allEnumsMap.ContainsKey objDomType || + InputIdlJson.hasType objDomType then objDomType // Name of a type alias. Just return itself elif typeDefSet.Contains objDomType then objDomType @@ -867,7 +1004,12 @@ module Emit = getAddedItems ItemKind.Callback flavor |> Array.iter emitCallbackFunctionsFromJson - GetCallbackFuncsByFlavor flavor |> Array.iter emitCallBackFunction + let map = GetCallbackFuncsByFlavor flavor |> Array.map(fun i -> (i.Name, i)) |> dict |> Dictionary + InputIdlJson.inputIdl.CallbackFunctions + |> Array.filter (fun i -> flavor <> Worker || knownWorkerInterfaces.Contains i.Name) + |> Array.iter (InputIdlJson.Compat.convertCallbackFunction >> (fun i -> map.[i.Name] <- i)) + + map.Values |> Array.ofSeq |> Array.iter emitCallBackFunction let EmitEnums flavor = let emitEnum (e: Browser.Enum) = @@ -1363,7 +1505,7 @@ module Emit = if hasNonStaticMember then emitStaticInterfaceWithNonStaticMembers() else emitPureStaticInterface() let EmitNonCallbackInterfaces flavor = - for i in GetNonCallbackInterfacesByFlavor flavor do + let emitNonCallbackInterface (i: Browser.Interface) = // If the static attribute has a value, it means the type doesn't have a constructor if i.Static.IsSome then EmitStaticInterface flavor i @@ -1373,6 +1515,13 @@ module Emit = EmitInterface flavor i EmitConstructor flavor i + let map = GetNonCallbackInterfacesByFlavor flavor |> Array.map(fun i -> (i.Name, i)) |> dict |> Dictionary + InputIdlJson.inputIdl.Interfaces + |> Array.filter (fun i -> flavor <> Worker || i.Exposed |> Array.contains "Worker") + |> Array.iter (InputIdlJson.Compat.convertInterface >> (fun i -> map.[i.Name] <- i)) + + map.Values |> Array.ofSeq |> Array.iter emitNonCallbackInterface + let EmitDictionaries flavor = let emitDictionary (dict:Browser.Dictionary) = @@ -1412,12 +1561,19 @@ module Emit = Pt.Printl "}" Pt.Printl "" - browser.Dictionaries - |> Array.filter (fun dict -> flavor <> Worker || knownWorkerInterfaces.Contains dict.Name) - |> Array.iter emitDictionary + let map = + browser.Dictionaries + |> Array.filter (fun dict -> flavor <> Worker || knownWorkerInterfaces.Contains dict.Name) + |> Array.map(fun i -> (i.Name, i)) |> dict |> Dictionary if flavor = Worker then - worker.Dictionaries |> Array.iter emitDictionary + worker.Dictionaries |> Array.iter (fun dict -> map.[dict.Name] <- dict) + + InputIdlJson.inputIdl.Dictionaries + |> Array.filter (fun dict -> flavor <> Worker || knownWorkerInterfaces.Contains dict.Name) + |> Array.iter (InputIdlJson.Compat.convertDictionary >> (fun i -> map.[i.Name] <- i)) + + map.Values |> Array.ofSeq |> Array.iter emitDictionary let EmitAddedInterface (ai: InputJsonType.Root) = match ai.Extends with @@ -1463,15 +1619,14 @@ module Emit = let emitTypeDefFromJson (typeDef: InputJsonType.Root) = Pt.Printl "type %s = %s;" typeDef.Name.Value typeDef.Type.Value - match flavor with - | Flavor.Worker -> - browser.Typedefs - |> Array.filter (fun typedef -> knownWorkerInterfaces.Contains typedef.NewType) - |> Array.iter emitTypeDef - | _ -> - browser.Typedefs - |> Array.filter (fun typedef -> getRemovedItemByName typedef.NewType ItemKind.TypeDef "" |> Option.isNone) - |> Array.iter emitTypeDef + let mutable map = browser.Typedefs |> Array.map(fun i -> (i.NewType, i)) |> Map.ofArray + InputIdlJson.inputIdl.Typedefs + |> Array.iter (InputIdlJson.Compat.convertTypedef >> (fun i -> map <- map.Add(i.NewType, i))) + + map |> Map.toArray |> Array.map snd + |> Array.filter (fun typedef -> getRemovedItemByName typedef.NewType ItemKind.TypeDef "" |> Option.isNone) + |> Array.filter (fun i -> (flavor <> Flavor.Worker || knownWorkerInterfaces.Contains i.NewType)) + |> Array.iter emitTypeDef InputJson.getAddedItems ItemKind.TypeDef flavor |> Array.iter emitTypeDefFromJson diff --git a/baselines/dom.generated.d.ts b/baselines/dom.generated.d.ts index 6d679933a..5e5b104fd 100644 --- a/baselines/dom.generated.d.ts +++ b/baselines/dom.generated.d.ts @@ -1169,6 +1169,15 @@ interface WheelEventInit extends MouseEventInit { deltaZ?: number; } +interface TextDecodeOptions { + stream?: boolean; +} + +interface TextDecoderOptions { + fatal?: boolean; + ignoreBOM?: boolean; +} + type EventListener = (evt: Event) => void | { handleEvent(evt: Event): void; }; type WebKitEntriesCallback = (entries: WebKitEntry[]) => void | { handleEvent(entries: WebKitEntry[]): void; }; @@ -3356,7 +3365,6 @@ interface DOMException { readonly code: number; readonly message: string; readonly name: string; - toString(): string; readonly ABORT_ERR: number; readonly DATA_CLONE_ERR: number; readonly DOMSTRING_SIZE_ERR: number; @@ -3374,10 +3382,8 @@ interface DOMException { readonly NO_MODIFICATION_ALLOWED_ERR: number; readonly NOT_FOUND_ERR: number; readonly NOT_SUPPORTED_ERR: number; - readonly PARSE_ERR: number; readonly QUOTA_EXCEEDED_ERR: number; readonly SECURITY_ERR: number; - readonly SERIALIZE_ERR: number; readonly SYNTAX_ERR: number; readonly TIMEOUT_ERR: number; readonly TYPE_MISMATCH_ERR: number; @@ -3406,10 +3412,8 @@ declare var DOMException: { readonly NO_MODIFICATION_ALLOWED_ERR: number; readonly NOT_FOUND_ERR: number; readonly NOT_SUPPORTED_ERR: number; - readonly PARSE_ERR: number; readonly QUOTA_EXCEEDED_ERR: number; readonly SECURITY_ERR: number; - readonly SERIALIZE_ERR: number; readonly SYNTAX_ERR: number; readonly TIMEOUT_ERR: number; readonly TYPE_MISMATCH_ERR: number; @@ -9069,7 +9073,7 @@ declare var PopStateEvent: { interface Position { readonly coords: Coordinates; - readonly timestamp: number; + readonly timestamp: DOMTimeStamp; } declare var Position: { @@ -14234,6 +14238,28 @@ interface XMLHttpRequestEventTarget { removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void; } +interface TextDecoder { + readonly encoding: string; + readonly fatal: boolean; + readonly ignoreBOM: boolean; + decode(input?: BufferSource, options?: TextDecodeOptions): USVString; +} + +declare var TextDecoder: { + prototype: TextDecoder; + new(label?: string, options?: TextDecoderOptions): TextDecoder; +}; + +interface TextEncoder { + readonly encoding: string; + encode(input?: USVString): Uint8Array; +} + +declare var TextEncoder: { + prototype: TextEncoder; + new(): TextEncoder; +}; + interface BroadcastChannel extends EventTarget { readonly name: string; onmessage: (ev: MessageEvent) => any; @@ -14914,6 +14940,9 @@ interface RTCStatsCallback { interface VoidFunction { (): void; } +interface Function { + (...arguments: any[]): any; +} interface HTMLElementTagNameMap { "a": HTMLAnchorElement; "abbr": HTMLElement; @@ -15318,12 +15347,14 @@ declare function removeEventListener(type: string, listener: EventListener, opti type AAGUID = string; type AlgorithmIdentifier = string | Algorithm; type BodyInit = Blob | BufferSource | FormData | string; +type BufferSource = ArrayBufferView | ArrayBuffer; type ByteString = string; type ConstrainBoolean = boolean | ConstrainBooleanParameters; type ConstrainDOMString = string | string[] | ConstrainDOMStringParameters; type ConstrainDouble = number | ConstrainDoubleRange; type ConstrainLong = number | ConstrainLongRange; type CryptoOperationData = ArrayBufferView; +type DOMTimeStamp = number; type GLbitfield = number; type GLboolean = boolean; type GLbyte = number; @@ -15353,7 +15384,6 @@ type payloadtype = number; type ScrollBehavior = "auto" | "instant" | "smooth"; type ScrollLogicalPosition = "start" | "center" | "end" | "nearest"; type IDBValidKey = number | string | Date | IDBArrayKey; -type BufferSource = ArrayBuffer | ArrayBufferView; type MouseWheelEvent = WheelEvent; type ScrollRestoration = "auto" | "manual"; type FormDataEntryValue = string | File; diff --git a/baselines/webworker.generated.d.ts b/baselines/webworker.generated.d.ts index d851dc422..c4a02bcd8 100644 --- a/baselines/webworker.generated.d.ts +++ b/baselines/webworker.generated.d.ts @@ -128,6 +128,15 @@ interface SyncEventInit extends ExtendableEventInit { lastChance?: boolean; } +interface TextDecodeOptions { + stream?: boolean; +} + +interface TextDecoderOptions { + fatal?: boolean; + ignoreBOM?: boolean; +} + type EventListener = (evt: Event) => void | { handleEvent(evt: Event): void; }; type WebKitEntriesCallback = (entries: WebKitEntry[]) => void | { handleEvent(entries: WebKitEntry[]): void; }; @@ -275,7 +284,6 @@ interface DOMException { readonly code: number; readonly message: string; readonly name: string; - toString(): string; readonly ABORT_ERR: number; readonly DATA_CLONE_ERR: number; readonly DOMSTRING_SIZE_ERR: number; @@ -293,10 +301,8 @@ interface DOMException { readonly NO_MODIFICATION_ALLOWED_ERR: number; readonly NOT_FOUND_ERR: number; readonly NOT_SUPPORTED_ERR: number; - readonly PARSE_ERR: number; readonly QUOTA_EXCEEDED_ERR: number; readonly SECURITY_ERR: number; - readonly SERIALIZE_ERR: number; readonly SYNTAX_ERR: number; readonly TIMEOUT_ERR: number; readonly TYPE_MISMATCH_ERR: number; @@ -325,10 +331,8 @@ declare var DOMException: { readonly NO_MODIFICATION_ALLOWED_ERR: number; readonly NOT_FOUND_ERR: number; readonly NOT_SUPPORTED_ERR: number; - readonly PARSE_ERR: number; readonly QUOTA_EXCEEDED_ERR: number; readonly SECURITY_ERR: number; - readonly SERIALIZE_ERR: number; readonly SYNTAX_ERR: number; readonly TIMEOUT_ERR: number; readonly TYPE_MISMATCH_ERR: number; @@ -846,7 +850,7 @@ declare var PerformanceTiming: { interface Position { readonly coords: Coordinates; - readonly timestamp: number; + readonly timestamp: DOMTimeStamp; } declare var Position: { @@ -1534,6 +1538,28 @@ interface WorkerUtils extends Object, WindowBase64 { setTimeout(handler: any, timeout?: any, ...args: any[]): number; } +interface TextDecoder { + readonly encoding: string; + readonly fatal: boolean; + readonly ignoreBOM: boolean; + decode(input?: BufferSource, options?: TextDecodeOptions): USVString; +} + +declare var TextDecoder: { + prototype: TextDecoder; + new(label?: string, options?: TextDecoderOptions): TextDecoder; +}; + +interface TextEncoder { + readonly encoding: string; + encode(input?: USVString): Uint8Array; +} + +declare var TextEncoder: { + prototype: TextEncoder; + new(): TextEncoder; +}; + interface BroadcastChannel extends EventTarget { readonly name: string; onmessage: (ev: MessageEvent) => any; @@ -1910,11 +1936,12 @@ declare function removeEventListener