Skip to content

Commit 20c61ba

Browse files
authored
Merge pull request #1 from Microsoft/master
Merging Microsoft fork
2 parents 59f63d0 + 5b748d4 commit 20c61ba

File tree

10 files changed

+2595
-904
lines changed

10 files changed

+2595
-904
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ The common steps to send a pull request are:
2929
1. Add missing elements to `inputfiles/addedTypes.json`, overriding elements to `inputfiles/overridingTypes.json`, or elements to remove to `inputfiles/removedTypes.json`.
3030
2. Run the build script locally to obtain new `dom.generated.d.ts` and `webworker.generated.d.ts`.
3131
3. Update the files in the `baselines` folder using the newly generated files
32-
under `generated` folder (`cp ./generated/* ./baseline/`).
32+
under `generated` folder (`cp ./generated/* ./baselines/`).
3333

3434
### When should a DOM API be included here?
3535

TS.fsx

Lines changed: 70 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ module InputJson =
175175

176176
let getItemByName (allItems: InputJsonType.Root []) (itemName: string) (kind: ItemKind) otherFilter =
177177
let filter (item: InputJsonType.Root) =
178-
OptionCheckValue itemName item.Name &&
178+
(OptionCheckValue itemName item.Name || OptionCheckValue (sprintf "%s?" itemName) item.Name) &&
179179
item.Kind.ToLower() = kind.ToString() &&
180180
otherFilter item
181181
allItems |> Array.tryFind filter
@@ -535,6 +535,7 @@ module Data =
535535
|> Array.map (fun i -> (i.Name, getEventHandler i))
536536
|> Map.ofArray
537537

538+
// Map of interface.Name -> List of base interfaces with event handlers
538539
let iNameToEhParents =
539540
let hasHandler (i : Browser.Interface) =
540541
iNameToEhList.ContainsKey i.Name && not iNameToEhList.[i.Name].IsEmpty
@@ -778,6 +779,10 @@ module Emit =
778779
(DomTypeToNullableTsType m.Type m.Nullable.IsSome) = expectedMType &&
779780
m.Params.Length = 1 &&
780781
(DomTypeToTsType m.Params.[0].Type) = expectedParamType
782+
let processInterfaceType iName =
783+
match getOverriddenItems ItemKind.Interface Flavor.All |> Array.tryFind (matchInterface iName) with
784+
| Some it -> iName + "<" + (it.TypeParameters |> String.concat ", ") + ">"
785+
| _ -> iName
781786

782787
/// Emit overloads for the createElement method
783788
let EmitCreateElementOverloads (m: Browser.Method) =
@@ -788,45 +793,47 @@ module Emit =
788793
/// Emit overloads for the getElementsByTagName method
789794
let EmitGetElementsByTagNameOverloads (m: Browser.Method) =
790795
if matchSingleParamMethodSignature m "getElementsByTagName" "NodeList" "string" then
791-
Pt.Printl "getElementsByTagName<K extends keyof ElementListTagNameMap>(%s: K): ElementListTagNameMap[K];" m.Params.[0].Name
796+
Pt.Printl "getElementsByTagName<K extends keyof HTMLElementTagNameMap>(%s: K): NodeListOf<HTMLElementTagNameMap[K]>;" m.Params.[0].Name
797+
Pt.Printl "getElementsByTagName<K extends keyof SVGElementTagNameMap>(%s: K): NodeListOf<SVGElementTagNameMap[K]>;" m.Params.[0].Name
792798
Pt.Printl "getElementsByTagName(%s: string): NodeListOf<Element>;" m.Params.[0].Name
793799

794800
/// Emit overloads for the querySelector method
795801
let EmitQuerySelectorOverloads (m: Browser.Method) =
796802
if matchSingleParamMethodSignature m "querySelector" "Element" "string" then
797-
Pt.Printl "querySelector<K extends keyof ElementTagNameMap>(selectors: K): ElementTagNameMap[K] | null;"
803+
Pt.Printl "querySelector<K extends keyof HTMLElementTagNameMap>(selectors: K): HTMLElementTagNameMap[K] | null;"
804+
Pt.Printl "querySelector<K extends keyof SVGElementTagNameMap>(selectors: K): SVGElementTagNameMap[K] | null;"
798805
Pt.Printl "querySelector<E extends Element = Element>(selectors: string): E | null;"
799806

800807
/// Emit overloads for the querySelectorAll method
801808
let EmitQuerySelectorAllOverloads (m: Browser.Method) =
802809
if matchSingleParamMethodSignature m "querySelectorAll" "NodeList" "string" then
803-
Pt.Printl "querySelectorAll<K extends keyof ElementListTagNameMap>(selectors: K): ElementListTagNameMap[K];"
810+
Pt.Printl "querySelectorAll<K extends keyof HTMLElementTagNameMap>(selectors: K): NodeListOf<HTMLElementTagNameMap[K]>;"
811+
Pt.Printl "querySelectorAll<K extends keyof SVGElementTagNameMap>(selectors: K): NodeListOf<SVGElementTagNameMap[K]>;"
804812
Pt.Printl "querySelectorAll<E extends Element = Element>(selectors: string): NodeListOf<E>;"
805813

806814
let EmitHTMLElementTagNameMap () =
807815
Pt.Printl "interface HTMLElementTagNameMap {"
808816
Pt.IncreaseIndent()
809817
for e in tagNameToEleName do
810-
if iNameToIDependList.ContainsKey e.Value && Seq.contains "HTMLElement" iNameToIDependList.[e.Value] then
818+
if iNameToIDependList.ContainsKey e.Value && not (Seq.contains "SVGElement" iNameToIDependList.[e.Value]) then
811819
Pt.Printl "\"%s\": %s;" (e.Key.ToLower()) e.Value
812820
Pt.DecreaseIndent()
813821
Pt.Printl "}"
814822
Pt.Printl ""
815823

816-
let EmitElementTagNameMap () =
817-
Pt.Printl "interface ElementTagNameMap extends HTMLElementTagNameMap {"
824+
let EmitSVGElementTagNameMap () =
825+
Pt.Printl "interface SVGElementTagNameMap {"
818826
Pt.IncreaseIndent()
819827
for e in tagNameToEleName do
820-
if iNameToIDependList.ContainsKey e.Value && not (Seq.contains "HTMLElement" iNameToIDependList.[e.Value]) then
828+
if iNameToIDependList.ContainsKey e.Value && Seq.contains "SVGElement" iNameToIDependList.[e.Value] then
821829
Pt.Printl "\"%s\": %s;" (e.Key.ToLower()) e.Value
822830
Pt.DecreaseIndent()
823831
Pt.Printl "}"
824832
Pt.Printl ""
825833

826-
let EmitElementListTagNameMap () =
827-
Pt.Printl "type ElementListTagNameMap = {"
828-
Pt.PrintWithAddedIndent "[key in keyof ElementTagNameMap]: NodeListOf<ElementTagNameMap[key]>"
829-
Pt.Printl "};"
834+
let EmitElementTagNameMap () =
835+
Pt.Printl "/** @deprecated Directly use HTMLElementTagNameMap or SVGElementTagNameMap as appropriate, instead. */"
836+
Pt.Printl "interface ElementTagNameMap extends HTMLElementTagNameMap, SVGElementTagNameMap { }"
830837
Pt.Printl ""
831838

832839
/// Emit overloads for the createEvent method
@@ -905,6 +912,16 @@ module Emit =
905912
| Some comment -> printLine "%s" comment
906913
| _ -> ()
907914

915+
// A covariant EventHandler is one that is defined in a parent interface as then redefined in current interface with a more specific argument types
916+
// These patterns are unsafe, and flagged as error under --strictFunctionTypes.
917+
// Here we know the property is already defined on the interface, we elide its declaration if the parent has the same handler defined
918+
let isCovariantEventHandler (p: Browser.Property) =
919+
p.Type = "EventHandler" &&
920+
iNameToEhParents.ContainsKey i.Name &&
921+
not iNameToEhParents.[i.Name].IsEmpty &&
922+
iNameToEhParents.[i.Name]
923+
|> List.exists (fun i -> iNameToEhList.ContainsKey i.Name && not iNameToEhList.[i.Name].IsEmpty && iNameToEhList.[i.Name] |> List.exists (fun e-> e.Name = p.Name))
924+
908925
let emitProperty (p: Browser.Property) =
909926
let printLine content =
910927
if conflictedMembers.Contains p.Name then Pt.PrintlToStack content else Pt.Printl content
@@ -941,6 +958,7 @@ module Emit =
941958
| Some ps ->
942959
ps.Properties
943960
|> Array.filter (ShouldKeep flavor)
961+
|> Array.filter (isCovariantEventHandler >> not)
944962
|> Array.iter emitProperty
945963
| None -> ()
946964

@@ -966,7 +984,12 @@ module Emit =
966984
// Otherwise, this is EventTarget.addEventListener, we want to keep that.
967985
let mFilter (m:Browser.Method) =
968986
matchScope emitScope m &&
969-
not (prefix <> "" && OptionCheckValue "addEventListener" m.Name)
987+
not (
988+
prefix <> "" && (
989+
(OptionCheckValue "addEventListener" m.Name) ||
990+
(OptionCheckValue "removeEventListener" m.Name)
991+
)
992+
)
970993

971994
let emitMethod flavor prefix (i:Browser.Interface) (m:Browser.Method) =
972995
let printLine content =
@@ -1049,30 +1072,43 @@ module Emit =
10491072
| _ -> ()
10501073

10511074
let EmitEventHandlers (flavor: Flavor) (prefix: string) (i:Browser.Interface) =
1075+
let getOptionsType (addOrRemove: string) =
1076+
if addOrRemove = "add" then "AddEventListenerOptions" else "EventListenerOptions"
1077+
10521078
let fPrefix =
10531079
if prefix.StartsWith "declare var" then "declare function " else ""
10541080

1055-
let emitEventHandler prefix (iParent:Browser.Interface) =
1081+
let emitTypedEventHandler (prefix: string) (addOrRemove: string) (iParent:Browser.Interface) =
1082+
Pt.Printl
1083+
"%s%sEventListener<K extends keyof %sEventMap>(type: K, listener: (this: %s, ev: %sEventMap[K]) => any, options?: boolean | %s): void;"
1084+
prefix addOrRemove iParent.Name i.Name iParent.Name (getOptionsType addOrRemove)
1085+
1086+
let emitStringEventHandler (addOrRemove: string) =
10561087
Pt.Printl
1057-
"%saddEventListener<K extends keyof %sEventMap>(type: K, listener: (this: %s, ev: %sEventMap[K]) => any, useCapture?: boolean): void;"
1058-
prefix iParent.Name i.Name iParent.Name
1088+
"%s%sEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | %s): void;"
1089+
fPrefix addOrRemove (getOptionsType addOrRemove)
10591090

1060-
let shouldEmitStringEventHandler =
1091+
let tryEmitTypedEventHandlerForInterface (addOrRemove: string) =
10611092
if iNameToEhList.ContainsKey i.Name && not iNameToEhList.[i.Name].IsEmpty then
1062-
emitEventHandler fPrefix i
1093+
emitTypedEventHandler fPrefix addOrRemove i
10631094
true
10641095
elif iNameToEhParents.ContainsKey i.Name && not iNameToEhParents.[i.Name].IsEmpty then
10651096
iNameToEhParents.[i.Name]
10661097
|> List.sortBy (fun i -> i.Name)
1067-
|> List.iter (emitEventHandler fPrefix)
1098+
|> List.iter (emitTypedEventHandler fPrefix addOrRemove)
10681099
true
10691100
else
10701101
false
10711102

1072-
if shouldEmitStringEventHandler then
1073-
Pt.Printl
1074-
"%saddEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;"
1075-
fPrefix
1103+
let emitEventHandler (addOrRemove: string) =
1104+
if tryEmitTypedEventHandlerForInterface addOrRemove then
1105+
// only emit the string event handler if we just emited a typed handler
1106+
emitStringEventHandler addOrRemove
1107+
1108+
1109+
emitEventHandler "add"
1110+
emitEventHandler "remove"
1111+
10761112

10771113
let EmitConstructorSignature flavor (i:Browser.Interface) =
10781114
let emitConstructorSigFromJson (c: InputJsonType.Root) =
@@ -1130,9 +1166,9 @@ module Emit =
11301166

11311167
let processedIName = processIName i.Name
11321168
if processedIName <> i.Name then
1133-
Pt.PrintlToStack "interface %s extends %s {" i.Name processedIName
1169+
Pt.PrintlToStack "interface %s extends %s {" (processInterfaceType i.Name) processedIName
11341170

1135-
Pt.Printl "interface %s" processedIName
1171+
Pt.Printl "interface %s" (processInterfaceType processedIName)
11361172
let finalExtends =
11371173
let overridenExtendsFromJson =
11381174
InputJson.getOverriddenItemsByInterfaceName ItemKind.Extends Flavor.All i.Name
@@ -1357,13 +1393,18 @@ module Emit =
13571393
EmitConstructor flavor i
13581394

13591395
let EmitDictionaries flavor =
1396+
13601397
let emitDictionary (dict:Browser.Dictionary) =
13611398
match dict.Extends with
1362-
| "Object" -> Pt.Printl "interface %s {" dict.Name
1363-
| _ -> Pt.Printl "interface %s extends %s {" dict.Name dict.Extends
1399+
| "Object" -> Pt.Printl "interface %s {" (processInterfaceType dict.Name)
1400+
| _ -> Pt.Printl "interface %s extends %s {" (processInterfaceType dict.Name) dict.Extends
13641401

13651402
let emitJsonProperty (p: InputJsonType.Root) =
1366-
Pt.Printl "%s: %s;" p.Name.Value p.Type.Value
1403+
let readOnlyModifier =
1404+
match p.Readonly with
1405+
| Some(true) -> "readonly "
1406+
| _ -> ""
1407+
Pt.Printl "%s%s: %s;" readOnlyModifier p.Name.Value p.Type.Value
13671408

13681409
let removedPropNames =
13691410
getRemovedItems ItemKind.Property flavor
@@ -1477,8 +1518,8 @@ module Emit =
14771518

14781519
if flavor <> Worker then
14791520
EmitHTMLElementTagNameMap()
1521+
EmitSVGElementTagNameMap()
14801522
EmitElementTagNameMap()
1481-
EmitElementListTagNameMap()
14821523
EmitNamedConstructors()
14831524

14841525
match GetGlobalPollutor flavor with

0 commit comments

Comments
 (0)