@@ -117,32 +117,55 @@ let matchSingleParamMethodSignature (m: Browser.Method) expectedMName expectedMT
117
117
/// Emit overloads for the createElement method
118
118
let EmitCreateElementOverloads ( m : Browser.Method ) =
119
119
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];"
123
121
Pt.printl " createElement(tagName: string): HTMLElement;"
124
122
125
123
/// Emit overloads for the getElementsByTagName method
126
124
let EmitGetElementsByTagNameOverloads ( m : Browser.Method ) =
127
125
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
130
127
Pt.printl " getElementsByTagName(%s : string): NodeListOf<Element>;" m.Params.[ 0 ]. Name
131
128
132
129
/// Emit overloads for the querySelector method
133
130
let EmitQuerySelectorOverloads ( m : Browser.Method ) =
134
131
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;"
137
133
Pt.printl " querySelector(selectors: string): Element | null;"
138
134
139
135
/// Emit overloads for the querySelectorAll method
140
136
let EmitQuerySelectorAllOverloads ( m : Browser.Method ) =
141
137
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];"
144
139
Pt.printl " querySelectorAll(selectors: string): NodeListOf<Element>;"
145
140
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
+
146
169
/// Emit overloads for the createEvent method
147
170
let EmitCreateEventOverloads ( m : Browser.Method ) =
148
171
if matchSingleParamMethodSignature m " createEvent" " Event" " string" then
@@ -205,7 +228,7 @@ let EmitMethod flavor prefix (i:Browser.Interface) (m:Browser.Method) =
205
228
let overloads = GetOverloads ( Function.Method m) false
206
229
for { ParamCombinations = pCombList; ReturnTypes = rTypes; Nullable = isNullable } in overloads do
207
230
let paramsString = ParamsToString pCombList
208
- let returnString =
231
+ let returnString =
209
232
let returnType = rTypes |> List.map DomTypeToTsType |> String.concat " | "
210
233
if isNullable then makeNullable returnType else returnType
211
234
Pt.printl " %s%s (%s ): %s ;" prefix ( if m.Name.IsSome then m.Name.Value else " " ) paramsString returnString
@@ -243,12 +266,11 @@ let EmitEnums () =
243
266
let emitEnum ( e : Browser.Enum ) = Pt.printl " declare var %s : string;" e.Name
244
267
browser.Enums |> Array.iter emitEnum
245
268
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 + " , "
248
271
else match GetGlobalPollutor flavor with
249
272
| Some pollutor -> " this: " + pollutor.Name + " , "
250
273
| _ -> " "
251
-
252
274
let EmitProperties flavor prefix ( emitScope : EmitScope ) ( i : Browser.Interface )=
253
275
let emitPropertyFromJson ( p : ItemsType.Root ) =
254
276
let readOnlyModifier =
@@ -272,15 +294,15 @@ let EmitProperties flavor prefix (emitScope: EmitScope) (i: Browser.Interface)=
272
294
let pType =
273
295
match p.Type with
274
296
| " 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"
277
299
// normally, but in "SVGSVGElement" it handles "SVGError" event instead.
278
- let eType =
300
+ let eType =
279
301
if p.EventHandler.IsSome then
280
302
getEventTypeInInterface p.EventHandler.Value i.Name
281
- else
303
+ else
282
304
" Event"
283
- String.Format( " ({0}ev: {1}) => any" , EmitEventHandlerThis flavor prefix, eType)
305
+ String.Format( " ({0}ev: {1}) => any" , EmitEventHandlerThis flavor prefix i , eType)
284
306
| _ -> DomTypeToTsType p.Type
285
307
let pTypeAndNull = if p.Nullable.IsSome then makeNullable pType else pType
286
308
let readOnlyModifier = if p.ReadOnly.IsSome && prefix = " " then " readonly " else " "
@@ -307,15 +329,11 @@ let EmitMethods flavor prefix (emitScope: EmitScope) (i: Browser.Interface) =
307
329
let emitMethodFromJson ( m : ItemsType.Root ) =
308
330
m.Signatures |> Array.iter ( Pt.printl " %s%s ;" prefix)
309
331
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.
316
334
let mFilter ( m : Browser.Method ) =
317
335
matchScope emitScope m &&
318
- not ( hasEventHandlers && OptionCheckValue " addEventListener" m.Name)
336
+ not ( prefix <> " " && OptionCheckValue " addEventListener" m.Name)
319
337
320
338
if i.Methods.IsSome then
321
339
i.Methods.Value.Methods
@@ -349,36 +367,30 @@ let rec EmitAllMembers flavor (i:Browser.Interface) =
349
367
| _ -> ()
350
368
351
369
let 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 ) =
355
374
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
382
394
383
395
let EmitConstructorSignature ( i : Browser.Interface ) =
384
396
let emitConstructorSigFromJson ( c : ItemsType.Root ) =
@@ -430,7 +442,7 @@ let EmitNamedConstructors () =
430
442
431
443
let EmitInterfaceDeclaration ( i : Browser.Interface ) =
432
444
Pt.printl " interface %s " i.Name
433
- let finalExtends =
445
+ let finalExtends =
434
446
let overridenExtendsFromJson =
435
447
JsonItems.getOverriddenItemsByInterfaceName ItemKind.Extends Flavor.All i.Name
436
448
|> Array.map ( fun e -> e.BaseInterface.Value) |> List.ofArray
@@ -516,7 +528,27 @@ let EmitIndexers emitScope (i: Browser.Interface) =
516
528
|> Array.filter ( matchInterface i.Name)
517
529
|> Array.iter emitIndexerFromJson
518
530
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 " "
519
549
let EmitInterface flavor ( i : Browser.Interface ) =
550
+ EmitInterfaceEventMap flavor i
551
+
520
552
Pt.resetIndent()
521
553
EmitInterfaceDeclaration i
522
554
Pt.increaseIndent()
@@ -718,6 +750,9 @@ let EmitTheWholeThing flavor (target:TextWriter) =
718
750
EmitCallBackFunctions flavor
719
751
720
752
if flavor <> Worker then
753
+ EmitHTMLElementTagNameMap()
754
+ EmitElementTagNameMap()
755
+ EmitElementListTagNameMap()
721
756
EmitNamedConstructors()
722
757
723
758
match GetGlobalPollutor flavor with
0 commit comments