@@ -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 ) =
@@ -905,6 +910,16 @@ module Emit =
905
910
| Some comment -> printLine " %s " comment
906
911
| _ -> ()
907
912
913
+ // A covariant EventHandler is one that is defined in a parent interface as then redefined in current interface with a more specific argument types
914
+ // These patterns are unsafe, and flagged as error under --strictFunctionTypes.
915
+ // Here we know the property is already defined on the interface, we elide its declaration if the parent has the same handler defined
916
+ let isCovariantEventHandler ( p : Browser.Property ) =
917
+ p.Type = " EventHandler" &&
918
+ iNameToEhParents.ContainsKey i.Name &&
919
+ not iNameToEhParents.[ i.Name]. IsEmpty &&
920
+ iNameToEhParents.[ i.Name]
921
+ |> List.exists ( fun i -> iNameToEhList.ContainsKey i.Name && not iNameToEhList.[ i.Name]. IsEmpty && iNameToEhList.[ i.Name] |> List.exists ( fun e -> e.Name = p.Name))
922
+
908
923
let emitProperty ( p : Browser.Property ) =
909
924
let printLine content =
910
925
if conflictedMembers.Contains p.Name then Pt.PrintlToStack content else Pt.Printl content
@@ -941,6 +956,7 @@ module Emit =
941
956
| Some ps ->
942
957
ps.Properties
943
958
|> Array.filter ( ShouldKeep flavor)
959
+ |> Array.filter ( isCovariantEventHandler >> not )
944
960
|> Array.iter emitProperty
945
961
| None -> ()
946
962
@@ -966,7 +982,12 @@ module Emit =
966
982
// Otherwise, this is EventTarget.addEventListener, we want to keep that.
967
983
let mFilter ( m : Browser.Method ) =
968
984
matchScope emitScope m &&
969
- not ( prefix <> " " && OptionCheckValue " addEventListener" m.Name)
985
+ not (
986
+ prefix <> " " && (
987
+ ( OptionCheckValue " addEventListener" m.Name) ||
988
+ ( OptionCheckValue " removeEventListener" m.Name)
989
+ )
990
+ )
970
991
971
992
let emitMethod flavor prefix ( i : Browser.Interface ) ( m : Browser.Method ) =
972
993
let printLine content =
@@ -1049,30 +1070,43 @@ module Emit =
1049
1070
| _ -> ()
1050
1071
1051
1072
let EmitEventHandlers ( flavor : Flavor ) ( prefix : string ) ( i : Browser.Interface ) =
1073
+ let getOptionsType ( addOrRemove : string ) =
1074
+ if addOrRemove = " add" then " AddEventListenerOptions" else " EventListenerOptions"
1075
+
1052
1076
let fPrefix =
1053
1077
if prefix.StartsWith " declare var" then " declare function " else " "
1054
1078
1055
- let emitEventHandler prefix ( iParent : Browser.Interface ) =
1079
+ let emitTypedEventHandler ( prefix : string ) ( addOrRemove : string ) ( iParent : Browser.Interface ) =
1056
1080
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
1081
+ " %s%s EventListener <K extends keyof %s EventMap>(type: K, listener: (this: %s , ev: %s EventMap[K]) => any, options ?: boolean | %s ): void;"
1082
+ prefix addOrRemove iParent.Name i.Name iParent.Name ( getOptionsType addOrRemove )
1059
1083
1060
- let shouldEmitStringEventHandler =
1084
+ let emitStringEventHandler ( addOrRemove : string ) =
1085
+ Pt.Printl
1086
+ " %s%s EventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | %s ): void;"
1087
+ fPrefix addOrRemove ( getOptionsType addOrRemove)
1088
+
1089
+ let tryEmitTypedEventHandlerForInterface ( addOrRemove : string ) =
1061
1090
if iNameToEhList.ContainsKey i.Name && not iNameToEhList.[ i.Name]. IsEmpty then
1062
- emitEventHandler fPrefix i
1091
+ emitTypedEventHandler fPrefix addOrRemove i
1063
1092
true
1064
1093
elif iNameToEhParents.ContainsKey i.Name && not iNameToEhParents.[ i.Name]. IsEmpty then
1065
1094
iNameToEhParents.[ i.Name]
1066
1095
|> List.sortBy ( fun i -> i.Name)
1067
- |> List.iter ( emitEventHandler fPrefix)
1096
+ |> List.iter ( emitTypedEventHandler fPrefix addOrRemove )
1068
1097
true
1069
1098
else
1070
1099
false
1071
1100
1072
- if shouldEmitStringEventHandler then
1073
- Pt.Printl
1074
- " %s addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;"
1075
- fPrefix
1101
+ let emitEventHandler ( addOrRemove : string ) =
1102
+ if tryEmitTypedEventHandlerForInterface addOrRemove then
1103
+ // only emit the string event handler if we just emited a typed handler
1104
+ emitStringEventHandler addOrRemove
1105
+
1106
+
1107
+ emitEventHandler " add"
1108
+ emitEventHandler " remove"
1109
+
1076
1110
1077
1111
let EmitConstructorSignature flavor ( i : Browser.Interface ) =
1078
1112
let emitConstructorSigFromJson ( c : InputJsonType.Root ) =
@@ -1130,9 +1164,9 @@ module Emit =
1130
1164
1131
1165
let processedIName = processIName i.Name
1132
1166
if processedIName <> i.Name then
1133
- Pt.PrintlToStack " interface %s extends %s {" i.Name processedIName
1167
+ Pt.PrintlToStack " interface %s extends %s {" ( processInterfaceType i.Name) processedIName
1134
1168
1135
- Pt.Printl " interface %s " processedIName
1169
+ Pt.Printl " interface %s " ( processInterfaceType processedIName)
1136
1170
let finalExtends =
1137
1171
let overridenExtendsFromJson =
1138
1172
InputJson.getOverriddenItemsByInterfaceName ItemKind.Extends Flavor.All i.Name
@@ -1357,13 +1391,18 @@ module Emit =
1357
1391
EmitConstructor flavor i
1358
1392
1359
1393
let EmitDictionaries flavor =
1394
+
1360
1395
let emitDictionary ( dict : Browser.Dictionary ) =
1361
1396
match dict.Extends with
1362
- | " Object" -> Pt.Printl " interface %s {" dict.Name
1363
- | _ -> Pt.Printl " interface %s extends %s {" dict.Name dict.Extends
1397
+ | " Object" -> Pt.Printl " interface %s {" ( processInterfaceType dict.Name)
1398
+ | _ -> Pt.Printl " interface %s extends %s {" ( processInterfaceType dict.Name) dict.Extends
1364
1399
1365
1400
let emitJsonProperty ( p : InputJsonType.Root ) =
1366
- Pt.Printl " %s : %s ;" p.Name.Value p.Type.Value
1401
+ let readOnlyModifier =
1402
+ match p.Readonly with
1403
+ | Some( true ) -> " readonly "
1404
+ | _ -> " "
1405
+ Pt.Printl " %s%s : %s ;" readOnlyModifier p.Name.Value p.Type.Value
1367
1406
1368
1407
let removedPropNames =
1369
1408
getRemovedItems ItemKind.Property flavor
0 commit comments