@@ -175,7 +175,7 @@ module InputJson =
175
175
176
176
let getItemByName ( allItems : InputJsonType.Root []) ( itemName : string ) ( kind : ItemKind ) otherFilter =
177
177
let filter ( item : InputJsonType.Root ) =
178
- OptionCheckValue itemName item.Name &&
178
+ ( OptionCheckValue itemName item.Name || OptionCheckValue ( sprintf " %s ? " itemName ) item.Name ) &&
179
179
item.Kind.ToLower() = kind.ToString() &&
180
180
otherFilter item
181
181
allItems |> Array.tryFind filter
@@ -535,6 +535,7 @@ module Data =
535
535
|> Array.map ( fun i -> ( i.Name, getEventHandler i))
536
536
|> Map.ofArray
537
537
538
+ // Map of interface.Name -> List of base interfaces with event handlers
538
539
let iNameToEhParents =
539
540
let hasHandler ( i : Browser.Interface ) =
540
541
iNameToEhList.ContainsKey i.Name && not iNameToEhList.[ i.Name]. IsEmpty
@@ -778,6 +779,10 @@ module Emit =
778
779
( DomTypeToNullableTsType m.Type m.Nullable.IsSome) = expectedMType &&
779
780
m.Params.Length = 1 &&
780
781
( 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
781
786
782
787
/// Emit overloads for the createElement method
783
788
let EmitCreateElementOverloads ( m : Browser.Method ) =
@@ -788,45 +793,47 @@ module Emit =
788
793
/// Emit overloads for the getElementsByTagName method
789
794
let EmitGetElementsByTagNameOverloads ( m : Browser.Method ) =
790
795
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
792
798
Pt.Printl " getElementsByTagName(%s : string): NodeListOf<Element>;" m.Params.[ 0 ]. Name
793
799
794
800
/// Emit overloads for the querySelector method
795
801
let EmitQuerySelectorOverloads ( m : Browser.Method ) =
796
802
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;"
798
805
Pt.Printl " querySelector<E extends Element = Element>(selectors: string): E | null;"
799
806
800
807
/// Emit overloads for the querySelectorAll method
801
808
let EmitQuerySelectorAllOverloads ( m : Browser.Method ) =
802
809
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]>;"
804
812
Pt.Printl " querySelectorAll<E extends Element = Element>(selectors: string): NodeListOf<E>;"
805
813
806
814
let EmitHTMLElementTagNameMap () =
807
815
Pt.Printl " interface HTMLElementTagNameMap {"
808
816
Pt.IncreaseIndent()
809
817
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
811
819
Pt.Printl " \" %s \" : %s ;" ( e.Key.ToLower()) e.Value
812
820
Pt.DecreaseIndent()
813
821
Pt.Printl " }"
814
822
Pt.Printl " "
815
823
816
- let EmitElementTagNameMap () =
817
- Pt.Printl " interface ElementTagNameMap extends HTMLElementTagNameMap {"
824
+ let EmitSVGElementTagNameMap () =
825
+ Pt.Printl " interface SVGElementTagNameMap {"
818
826
Pt.IncreaseIndent()
819
827
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
821
829
Pt.Printl " \" %s \" : %s ;" ( e.Key.ToLower()) e.Value
822
830
Pt.DecreaseIndent()
823
831
Pt.Printl " }"
824
832
Pt.Printl " "
825
833
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 { }"
830
837
Pt.Printl " "
831
838
832
839
/// Emit overloads for the createEvent method
@@ -905,6 +912,16 @@ module Emit =
905
912
| Some comment -> printLine " %s " comment
906
913
| _ -> ()
907
914
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
+
908
925
let emitProperty ( p : Browser.Property ) =
909
926
let printLine content =
910
927
if conflictedMembers.Contains p.Name then Pt.PrintlToStack content else Pt.Printl content
@@ -941,6 +958,7 @@ module Emit =
941
958
| Some ps ->
942
959
ps.Properties
943
960
|> Array.filter ( ShouldKeep flavor)
961
+ |> Array.filter ( isCovariantEventHandler >> not )
944
962
|> Array.iter emitProperty
945
963
| None -> ()
946
964
@@ -966,7 +984,12 @@ module Emit =
966
984
// Otherwise, this is EventTarget.addEventListener, we want to keep that.
967
985
let mFilter ( m : Browser.Method ) =
968
986
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
+ )
970
993
971
994
let emitMethod flavor prefix ( i : Browser.Interface ) ( m : Browser.Method ) =
972
995
let printLine content =
@@ -1049,30 +1072,43 @@ module Emit =
1049
1072
| _ -> ()
1050
1073
1051
1074
let EmitEventHandlers ( flavor : Flavor ) ( prefix : string ) ( i : Browser.Interface ) =
1075
+ let getOptionsType ( addOrRemove : string ) =
1076
+ if addOrRemove = " add" then " AddEventListenerOptions" else " EventListenerOptions"
1077
+
1052
1078
let fPrefix =
1053
1079
if prefix.StartsWith " declare var" then " declare function " else " "
1054
1080
1055
- let emitEventHandler prefix ( iParent : Browser.Interface ) =
1081
+ let emitTypedEventHandler ( prefix : string ) ( addOrRemove : string ) ( iParent : Browser.Interface ) =
1082
+ Pt.Printl
1083
+ " %s%s EventListener<K extends keyof %s EventMap>(type: K, listener: (this: %s , ev: %s EventMap[K]) => any, options?: boolean | %s ): void;"
1084
+ prefix addOrRemove iParent.Name i.Name iParent.Name ( getOptionsType addOrRemove)
1085
+
1086
+ let emitStringEventHandler ( addOrRemove : string ) =
1056
1087
Pt.Printl
1057
- " %s addEventListener<K extends keyof %s EventMap> (type: K , listener: (this: %s , ev: %s EventMap[K]) => any, useCapture ?: boolean): void;"
1058
- prefix iParent.Name i.Name iParent.Name
1088
+ " %s%s EventListener (type: string , listener: EventListenerOrEventListenerObject, options ?: boolean | %s ): void;"
1089
+ fPrefix addOrRemove ( getOptionsType addOrRemove )
1059
1090
1060
- let shouldEmitStringEventHandler =
1091
+ let tryEmitTypedEventHandlerForInterface ( addOrRemove : string ) =
1061
1092
if iNameToEhList.ContainsKey i.Name && not iNameToEhList.[ i.Name]. IsEmpty then
1062
- emitEventHandler fPrefix i
1093
+ emitTypedEventHandler fPrefix addOrRemove i
1063
1094
true
1064
1095
elif iNameToEhParents.ContainsKey i.Name && not iNameToEhParents.[ i.Name]. IsEmpty then
1065
1096
iNameToEhParents.[ i.Name]
1066
1097
|> List.sortBy ( fun i -> i.Name)
1067
- |> List.iter ( emitEventHandler fPrefix)
1098
+ |> List.iter ( emitTypedEventHandler fPrefix addOrRemove )
1068
1099
true
1069
1100
else
1070
1101
false
1071
1102
1072
- if shouldEmitStringEventHandler then
1073
- Pt.Printl
1074
- " %s addEventListener(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
+
1076
1112
1077
1113
let EmitConstructorSignature flavor ( i : Browser.Interface ) =
1078
1114
let emitConstructorSigFromJson ( c : InputJsonType.Root ) =
@@ -1130,9 +1166,9 @@ module Emit =
1130
1166
1131
1167
let processedIName = processIName i.Name
1132
1168
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
1134
1170
1135
- Pt.Printl " interface %s " processedIName
1171
+ Pt.Printl " interface %s " ( processInterfaceType processedIName)
1136
1172
let finalExtends =
1137
1173
let overridenExtendsFromJson =
1138
1174
InputJson.getOverriddenItemsByInterfaceName ItemKind.Extends Flavor.All i.Name
@@ -1357,13 +1393,18 @@ module Emit =
1357
1393
EmitConstructor flavor i
1358
1394
1359
1395
let EmitDictionaries flavor =
1396
+
1360
1397
let emitDictionary ( dict : Browser.Dictionary ) =
1361
1398
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
1364
1401
1365
1402
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
1367
1408
1368
1409
let removedPropNames =
1369
1410
getRemovedItems ItemKind.Property flavor
@@ -1477,8 +1518,8 @@ module Emit =
1477
1518
1478
1519
if flavor <> Worker then
1479
1520
EmitHTMLElementTagNameMap()
1521
+ EmitSVGElementTagNameMap()
1480
1522
EmitElementTagNameMap()
1481
- EmitElementListTagNameMap()
1482
1523
EmitNamedConstructors()
1483
1524
1484
1525
match GetGlobalPollutor flavor with
0 commit comments