@@ -117,32 +117,55 @@ let matchSingleParamMethodSignature (m: Browser.Method) expectedMName expectedMT
117117/// Emit overloads for the createElement method
118118let EmitCreateElementOverloads ( m : Browser.Method ) =
119119 if matchSingleParamMethodSignature m " createElement" " Element" " string" then
120- for e in tagNameToEleName do
121- if iNameToIDependList.ContainsKey e.Value && Seq.contains " HTMLElement" iNameToIDependList.[ e.Value] then
122- Pt.printl " createElement(tagName: \" %s \" ): %s ;" e.Key e.Value
120+ Pt.printl " createElement<K extends keyof HTMLElementTagNameMap>(tagName: K): HTMLElementTagNameMap[K];"
123121 Pt.printl " createElement(tagName: string): HTMLElement;"
124122
125123/// Emit overloads for the getElementsByTagName method
126124let EmitGetElementsByTagNameOverloads ( m : Browser.Method ) =
127125 if matchSingleParamMethodSignature m " getElementsByTagName" " NodeList" " string" then
128- for e in tagNameToEleName do
129- Pt.printl " getElementsByTagName(%s : \" %s \" ): NodeListOf<%s >;" m.Params.[ 0 ]. Name ( e.Key.ToLower()) e.Value
126+ Pt.printl " getElementsByTagName<K extends keyof ElementListTagNameMap>(%s : K): ElementListTagNameMap[K];" m.Params.[ 0 ]. Name
130127 Pt.printl " getElementsByTagName(%s : string): NodeListOf<Element>;" m.Params.[ 0 ]. Name
131128
132129/// Emit overloads for the querySelector method
133130let EmitQuerySelectorOverloads ( m : Browser.Method ) =
134131 if matchSingleParamMethodSignature m " querySelector" " Element" " string" then
135- for e in tagNameToEleName do
136- Pt.printl " querySelector(selectors: \" %s \" ): %s | null;" ( e.Key.ToLower()) e.Value
132+ Pt.printl " querySelector<K extends keyof ElementTagNameMap>(selectors: K): ElementTagNameMap[K] | null;"
137133 Pt.printl " querySelector(selectors: string): Element | null;"
138134
139135/// Emit overloads for the querySelectorAll method
140136let EmitQuerySelectorAllOverloads ( m : Browser.Method ) =
141137 if matchSingleParamMethodSignature m " querySelectorAll" " NodeList" " string" then
142- for e in tagNameToEleName do
143- Pt.printl " querySelectorAll(selectors: \" %s \" ): NodeListOf<%s >;" ( e.Key.ToLower()) e.Value
138+ Pt.printl " querySelectorAll<K extends keyof ElementListTagNameMap>(selectors: K): ElementListTagNameMap[K];"
144139 Pt.printl " querySelectorAll(selectors: string): NodeListOf<Element>;"
145140
141+ let EmitHTMLElementTagNameMap () =
142+ Pt.printl " interface HTMLElementTagNameMap {"
143+ Pt.increaseIndent()
144+ for e in tagNameToEleName do
145+ if iNameToIDependList.ContainsKey e.Value && Seq.contains " HTMLElement" iNameToIDependList.[ e.Value] then
146+ Pt.printl " \" %s \" : %s ;" ( e.Key.ToLower()) e.Value
147+ Pt.decreaseIndent()
148+ Pt.printl " }"
149+ Pt.printl " "
150+
151+ let EmitElementTagNameMap () =
152+ Pt.printl " interface ElementTagNameMap {"
153+ Pt.increaseIndent()
154+ for e in tagNameToEleName do
155+ Pt.printl " \" %s \" : %s ;" ( e.Key.ToLower()) e.Value
156+ Pt.decreaseIndent()
157+ Pt.printl " }"
158+ Pt.printl " "
159+
160+ let EmitElementListTagNameMap () =
161+ Pt.printl " interface ElementListTagNameMap {"
162+ Pt.increaseIndent()
163+ for e in tagNameToEleName do
164+ Pt.printl " \" %s \" : NodeListOf<%s >;" ( e.Key.ToLower()) e.Value
165+ Pt.decreaseIndent()
166+ Pt.printl " }"
167+ Pt.printl " "
168+
146169/// Emit overloads for the createEvent method
147170let EmitCreateEventOverloads ( m : Browser.Method ) =
148171 if matchSingleParamMethodSignature m " createEvent" " Event" " string" then
@@ -205,7 +228,7 @@ let EmitMethod flavor prefix (i:Browser.Interface) (m:Browser.Method) =
205228 let overloads = GetOverloads ( Function.Method m) false
206229 for { ParamCombinations = pCombList; ReturnTypes = rTypes; Nullable = isNullable } in overloads do
207230 let paramsString = ParamsToString pCombList
208- let returnString =
231+ let returnString =
209232 let returnType = rTypes |> List.map DomTypeToTsType |> String.concat " | "
210233 if isNullable then makeNullable returnType else returnType
211234 Pt.printl " %s%s (%s ): %s ;" prefix ( if m.Name.IsSome then m.Name.Value else " " ) paramsString returnString
@@ -243,12 +266,11 @@ let EmitEnums () =
243266 let emitEnum ( e : Browser.Enum ) = Pt.printl " declare var %s : string;" e.Name
244267 browser.Enums |> Array.iter emitEnum
245268
246- let EmitEventHandlerThis flavor ( prefix : string ) =
247- if prefix = " " then " this: this , "
269+ let EmitEventHandlerThis flavor ( prefix : string ) ( i : Browser.Interface ) =
270+ if prefix = " " then " this: " + i.Name + " , "
248271 else match GetGlobalPollutor flavor with
249272 | Some pollutor -> " this: " + pollutor.Name + " , "
250273 | _ -> " "
251-
252274let EmitProperties flavor prefix ( emitScope : EmitScope ) ( i : Browser.Interface )=
253275 let emitPropertyFromJson ( p : ItemsType.Root ) =
254276 let readOnlyModifier =
@@ -272,15 +294,15 @@ let EmitProperties flavor prefix (emitScope: EmitScope) (i: Browser.Interface)=
272294 let pType =
273295 match p.Type with
274296 | " EventHandler" ->
275- // Sometimes event handlers with the same name may actually handle different
276- // events in different interfaces. For example, "onerror" handles "ErrorEvent"
297+ // Sometimes event handlers with the same name may actually handle different
298+ // events in different interfaces. For example, "onerror" handles "ErrorEvent"
277299 // normally, but in "SVGSVGElement" it handles "SVGError" event instead.
278- let eType =
300+ let eType =
279301 if p.EventHandler.IsSome then
280302 getEventTypeInInterface p.EventHandler.Value i.Name
281- else
303+ else
282304 " Event"
283- String.Format( " ({0}ev: {1}) => any" , EmitEventHandlerThis flavor prefix, eType)
305+ String.Format( " ({0}ev: {1}) => any" , EmitEventHandlerThis flavor prefix i , eType)
284306 | _ -> DomTypeToTsType p.Type
285307 let pTypeAndNull = if p.Nullable.IsSome then makeNullable pType else pType
286308 let readOnlyModifier = if p.ReadOnly.IsSome && prefix = " " then " readonly " else " "
@@ -307,15 +329,11 @@ let EmitMethods flavor prefix (emitScope: EmitScope) (i: Browser.Interface) =
307329 let emitMethodFromJson ( m : ItemsType.Root ) =
308330 m.Signatures |> Array.iter ( Pt.printl " %s%s ;" prefix)
309331
310- // Because eventhandler overload are not inherited between interfaces,
311- // they need to be taken care of seperately
312- let hasEventHandlers =
313- iNameToEhList.ContainsKey i.Name &&
314- not iNameToEhList.[ i.Name]. IsEmpty
315-
332+ // If prefix is not empty, then this is the global declare function addEventListener, we want to override this
333+ // Otherwise, this is EventTarget.addEventListener, we want to keep that.
316334 let mFilter ( m : Browser.Method ) =
317335 matchScope emitScope m &&
318- not ( hasEventHandlers && OptionCheckValue " addEventListener" m.Name)
336+ not ( prefix <> " " && OptionCheckValue " addEventListener" m.Name)
319337
320338 if i.Methods.IsSome then
321339 i.Methods.Value.Methods
@@ -349,36 +367,30 @@ let rec EmitAllMembers flavor (i:Browser.Interface) =
349367 | _ -> ()
350368
351369let EmitEventHandlers ( flavor : Flavor ) ( prefix : string ) ( i : Browser.Interface ) =
352- let emitEventHandler prefix ( eHandler : EventHandler ) =
353- let eventType =
354- getEventTypeInInterface eHandler.EventName i.Name
370+ let fPrefix =
371+ if prefix.StartsWith " declare var" then " declare function " else " "
372+
373+ let emitEventHandler prefix ( i : Browser.Interface ) =
355374 Pt.printl
356- " %s addEventListener(type: \" %s \" , listener: (%s ev: %s ) => any, useCapture?: boolean): void;"
357- prefix eHandler.EventName ( EmitEventHandlerThis flavor prefix) eventType
358-
359- let fPrefix = if prefix.StartsWith " declare var" then " declare function " else " "
360-
361- // Inheritance of "addEventListener" has two cases:
362- // 1. No own eventhandlers -> it inherits all the eventhandlers from base interfaces
363- // 2. Has own eventhandlers -> TypeScript's inherit mechanism erases all inherited eventhandler overloads
364- // so they need to be reprinted.
365- if iNameToEhList.ContainsKey i.Name then
366- iNameToEhList.[ i.Name] |> List.sortBy ( fun eh -> eh.EventName) |> List.iter ( emitEventHandler fPrefix)
367- let shouldPrintAddEventListener =
368- if iNameToEhList.[ i.Name]. Length > 0 then true
369- else
370- match i.Extends, i.Implements.Length with
371- | _, 0 -> false
372- | " Object" , 1 -> false
373- | _ ->
374- let allParents = Array.append [| i.Extends|] i.Implements
375- match allParents |> Array.filter iNameToEhList.ContainsKey |> Array.length with
376- // only one of the implemented interface has EventHandlers
377- | 0 | 1 -> false
378- // multiple implemented interfaces have EventHandlers
379- | _ -> true
380- if shouldPrintAddEventListener then
381- Pt.printl " %s addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;" fPrefix
375+ " %s addEventListener<K extends keyof %s EventMap>(type: K, listener: (this: %s , ev: %s EventMap[K]) => any, useCapture?: boolean): void;"
376+ prefix i.Name i.Name i.Name
377+
378+ let shouldEmitStringEventHandler =
379+ if iNameToEhList.ContainsKey i.Name && not iNameToEhList.[ i.Name]. IsEmpty then
380+ emitEventHandler fPrefix i
381+ true
382+ elif iNameToEhParents.ContainsKey i.Name && not iNameToEhParents.[ i.Name]. IsEmpty then
383+ iNameToEhParents.[ i.Name]
384+ |> List.sortBy ( fun i -> i.Name)
385+ |> List.iter ( emitEventHandler fPrefix)
386+ true
387+ else
388+ false
389+
390+ if shouldEmitStringEventHandler then
391+ Pt.printl
392+ " %s addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;"
393+ fPrefix
382394
383395let EmitConstructorSignature ( i : Browser.Interface ) =
384396 let emitConstructorSigFromJson ( c : ItemsType.Root ) =
@@ -430,7 +442,7 @@ let EmitNamedConstructors () =
430442
431443let EmitInterfaceDeclaration ( i : Browser.Interface ) =
432444 Pt.printl " interface %s " i.Name
433- let finalExtends =
445+ let finalExtends =
434446 let overridenExtendsFromJson =
435447 JsonItems.getOverriddenItemsByInterfaceName ItemKind.Extends Flavor.All i.Name
436448 |> Array.map ( fun e -> e.BaseInterface.Value) |> List.ofArray
@@ -516,7 +528,27 @@ let EmitIndexers emitScope (i: Browser.Interface) =
516528 |> Array.filter ( matchInterface i.Name)
517529 |> Array.iter emitIndexerFromJson
518530
531+ let EmitInterfaceEventMap flavor ( i : Browser.Interface ) =
532+ let EmitInterfaceEventMapEntry ( eHandler : EventHandler ) =
533+ let eventType =
534+ getEventTypeInInterface eHandler.EventName i.Name
535+ Pt.printl " \" %s \" : %s ;" eHandler.EventName eventType
536+
537+ let ownEventHandles = if iNameToEhList.ContainsKey i.Name && not iNameToEhList.[ i.Name]. IsEmpty then iNameToEhList.[ i.Name] else []
538+ if ownEventHandles.Length > 0 then
539+ Pt.printl " interface %s EventMap" i.Name
540+ if iNameToEhParents.ContainsKey i.Name && not iNameToEhParents.[ i.Name]. IsEmpty then
541+ let extends = iNameToEhParents.[ i.Name] |> List.map ( fun i -> i.Name + " EventMap" )
542+ Pt.print " extends %s " ( String.Join( " , " , extends))
543+ Pt.print " {"
544+ Pt.increaseIndent()
545+ ownEventHandles |> List.iter EmitInterfaceEventMapEntry
546+ Pt.decreaseIndent()
547+ Pt.printl " }"
548+ Pt.printl " "
519549let EmitInterface flavor ( i : Browser.Interface ) =
550+ EmitInterfaceEventMap flavor i
551+
520552 Pt.resetIndent()
521553 EmitInterfaceDeclaration i
522554 Pt.increaseIndent()
@@ -718,6 +750,9 @@ let EmitTheWholeThing flavor (target:TextWriter) =
718750 EmitCallBackFunctions flavor
719751
720752 if flavor <> Worker then
753+ EmitHTMLElementTagNameMap()
754+ EmitElementTagNameMap()
755+ EmitElementListTagNameMap()
721756 EmitNamedConstructors()
722757
723758 match GetGlobalPollutor flavor with
0 commit comments