@@ -120,6 +120,16 @@ function isEventHandler(p: Browser.Property) {
120
120
return typeof p [ "event-handler" ] === "string" ;
121
121
}
122
122
123
+ const newToConstructorRegExp = / ^ n e w (?: < .+ ?> ) ? ( \( .+ ?\) ) (?: : ? [ ^ ) ] + ) ? $ / u;
124
+ function convertNewToConstructor ( signature : string ) {
125
+ const result = newToConstructorRegExp . exec ( signature ) ;
126
+ if ( result ) {
127
+ return `constructor${ result [ 1 ] } ` ;
128
+ } else {
129
+ return signature ;
130
+ }
131
+ }
132
+
123
133
export function emitWebIdl ( webidl : Browser . WebIdl , flavor : Flavor ) {
124
134
// Global print target
125
135
const printer = createTextWriter ( "\n" ) ;
@@ -383,16 +393,16 @@ export function emitWebIdl(webidl: Browser.WebIdl, flavor: Flavor) {
383
393
return `${ i . name } <${ typeParameters . map ( t => t . name ) } >` ;
384
394
}
385
395
386
- function emitConstant ( c : Browser . Constant ) {
396
+ function emitConstant ( c : Browser . Constant , prefix = "" ) {
387
397
emitComments ( c , printer . printLine ) ;
388
- printer . printLine ( `readonly ${ c . name } : ${ convertDomTypeToTsType ( c ) } ;` ) ;
398
+ printer . printLine ( `${ prefix } readonly ${ c . name } : ${ convertDomTypeToTsType ( c ) } ;` ) ;
389
399
}
390
400
391
- function emitConstants ( i : Browser . Interface ) {
401
+ function emitConstants ( i : Browser . Interface , prefix = "" ) {
392
402
if ( i . constants ) {
393
403
mapToArray ( i . constants . constant )
394
404
. sort ( compareName )
395
- . forEach ( emitConstant ) ;
405
+ . forEach ( c => emitConstant ( c , prefix ) ) ;
396
406
}
397
407
}
398
408
@@ -627,11 +637,11 @@ export function emitWebIdl(webidl: Browser.WebIdl, flavor: Flavor) {
627
637
if ( ! required && prefix ) {
628
638
pType += " | undefined"
629
639
}
630
- const readOnlyModifier = p [ "read-only" ] === 1 && prefix === "" ? "readonly " : "" ;
640
+ const readOnlyModifier = p [ "read-only" ] === 1 && ( prefix === "" || prefix === "static " ) ? "readonly " : "" ;
631
641
printer . printLine ( `${ prefix } ${ readOnlyModifier } ${ p . name } ${ requiredModifier } : ${ pType } ;` ) ;
632
642
}
633
643
634
- if ( p . stringifier ) {
644
+ if ( p . stringifier && emitScope !== EmitScope . StaticOnly ) {
635
645
printer . printLine ( "toString(): string;" )
636
646
}
637
647
}
@@ -688,19 +698,24 @@ export function emitWebIdl(webidl: Browser.WebIdl, flavor: Flavor) {
688
698
689
699
function emitSignature ( s : Browser . Signature , prefix : string | undefined , name : string | undefined , printLine : ( s : string ) => void ) {
690
700
const paramsString = s . param ? paramsToString ( s . param ) : "" ;
691
- let returnType = convertDomTypeToTsType ( s ) ;
692
- returnType = s . nullable ? makeNullable ( returnType ) : returnType ;
701
+ let returnType = "" ;
702
+ if ( name !== "constructor" ) {
703
+ returnType = `: ${ convertDomTypeToTsType ( s ) } ` ;
704
+ returnType = s . nullable ? makeNullable ( returnType ) : returnType ;
705
+ }
693
706
emitComments ( s , printLine ) ;
694
- printLine ( `${ prefix || "" } ${ name || "" } (${ paramsString } ): ${ returnType } ;` ) ;
707
+ printLine ( `${ prefix || "" } ${ name || "" } (${ paramsString } )${ returnType } ;` ) ;
695
708
}
696
709
697
710
function emitSignatures ( method : { signature ?: Browser . Signature [ ] , "override-signatures" ?: string [ ] , "additional-signatures" ?: string [ ] } , prefix : string , name : string , printLine : ( s : string ) => void ) {
698
711
if ( method [ "override-signatures" ] ) {
699
- method [ "override-signatures" ] ! . forEach ( s => printLine ( `${ prefix } ${ s } ;` ) ) ;
712
+ method [ "override-signatures" ] ! . forEach ( s => {
713
+ printLine ( `${ prefix } ${ name === "constructor" ? convertNewToConstructor ( s ) : s } ;` ) ;
714
+ } ) ;
700
715
}
701
716
else if ( method . signature ) {
702
717
if ( method [ "additional-signatures" ] ) {
703
- method [ "additional-signatures" ] ! . forEach ( s => printLine ( `${ prefix } ${ s } ;` ) ) ;
718
+ method [ "additional-signatures" ] ! . forEach ( s => printLine ( `${ prefix } ${ name === "constructor" ? convertNewToConstructor ( s ) : s } ;` ) ) ;
704
719
}
705
720
method . signature . forEach ( sig => emitSignature ( sig , prefix , name , printLine ) ) ;
706
721
}
@@ -715,7 +730,7 @@ export function emitWebIdl(webidl: Browser.WebIdl, flavor: Flavor) {
715
730
. sort ( compareName )
716
731
. forEach ( m => emitMethod ( prefix , m , conflictedMembers ) ) ;
717
732
}
718
- if ( i [ "anonymous-methods" ] ) {
733
+ if ( i [ "anonymous-methods" ] && emitScope !== EmitScope . StaticOnly ) {
719
734
const stringifier = i [ "anonymous-methods" ] . method . find ( m => m . stringifier ) ;
720
735
if ( stringifier ) {
721
736
printer . printLine ( "toString(): string;" ) ;
@@ -746,7 +761,7 @@ export function emitWebIdl(webidl: Browser.WebIdl, flavor: Flavor) {
746
761
function emitMembers ( prefix : string , emitScope : EmitScope , i : Browser . Interface ) {
747
762
const conflictedMembers = extendConflictsBaseTypes [ i . name ] ? extendConflictsBaseTypes [ i . name ] . memberNames : new Set < string > ( ) ;
748
763
emitProperties ( prefix , emitScope , i ) ;
749
- const methodPrefix = prefix . startsWith ( "declare var" ) ? "declare function " : "" ;
764
+ const methodPrefix = prefix . startsWith ( "declare var" ) ? "declare function " : prefix . startsWith ( "static" ) ? "static " : "" ;
750
765
emitMethods ( methodPrefix , emitScope , i , conflictedMembers ) ;
751
766
if ( emitScope === EmitScope . InstanceOnly ) {
752
767
emitIteratorForEach ( i ) ;
@@ -799,16 +814,16 @@ export function emitWebIdl(webidl: Browser.WebIdl, flavor: Flavor) {
799
814
}
800
815
}
801
816
802
- function emitConstructorSignature ( i : Browser . Interface ) {
817
+ function emitConstructorSignature ( i : Browser . Interface , keyword = "new" ) {
803
818
const constructor = typeof i . constructor === "object" ? i . constructor : undefined ;
804
819
805
820
// Emit constructor signature
806
821
if ( constructor ) {
807
822
emitComments ( constructor , printer . print ) ;
808
- emitSignatures ( constructor , "" , "new" , printer . printLine ) ;
823
+ emitSignatures ( constructor , "" , keyword , printer . printLine ) ;
809
824
}
810
- else {
811
- printer . printLine ( `new (): ${ i . name } ;` ) ;
825
+ else if ( keyword !== "constructor" ) {
826
+ printer . printLine ( `${ keyword } (): ${ i . name } ;` ) ;
812
827
}
813
828
}
814
829
@@ -845,6 +860,7 @@ export function emitWebIdl(webidl: Browser.WebIdl, flavor: Flavor) {
845
860
printer . printLine ( `declare var ${ nc . name } : {` ) ;
846
861
printer . increaseIndent ( ) ;
847
862
nc . signature . forEach ( s => printer . printLine ( `new(${ s . param ? paramsToString ( s . param ) : "" } ): ${ i . name } ;` ) ) ;
863
+ printer . printLine ( `readonly prototype: ${ i . name } ;` ) ;
848
864
printer . decreaseIndent ( ) ;
849
865
printer . printLine ( `};` ) ;
850
866
}
@@ -857,11 +873,11 @@ export function emitWebIdl(webidl: Browser.WebIdl, flavor: Flavor) {
857
873
. forEach ( emitNamedConstructor ) ;
858
874
}
859
875
860
- function emitInterfaceDeclaration ( i : Browser . Interface ) {
861
- function processIName ( iName : string ) {
862
- return extendConflictsBaseTypes [ iName ] ? `${ iName } Base` : iName ;
863
- }
876
+ function processIName ( iName : string ) {
877
+ return extendConflictsBaseTypes [ iName ] ? `${ iName } Base` : iName ;
878
+ }
864
879
880
+ function emitInterfaceDeclaration ( i : Browser . Interface ) {
865
881
const processedIName = processIName ( i . name ) ;
866
882
867
883
if ( processedIName !== i . name ) {
@@ -986,6 +1002,71 @@ export function emitWebIdl(webidl: Browser.WebIdl, flavor: Flavor) {
986
1002
}
987
1003
}
988
1004
1005
+ function emitClassDeclaration ( i : Browser . Interface , prefix = "" ) {
1006
+ let finalExtendsName = i . extends && i . extends !== "Object" ? i . extends : null ;
1007
+ let extendsKeyword = "extends" ;
1008
+ const finalImplements = ( i . implements || [ ] ) . sort ( ) . map ( processIName ) ;
1009
+
1010
+ if ( finalExtendsName ) {
1011
+ if ( finalExtendsName !== processIName ( finalExtendsName ) ||
1012
+ ! allInterfacesMap [ finalExtendsName ] ||
1013
+ allInterfacesMap [ finalExtendsName ] [ "no-interface-object" ] ) {
1014
+ finalImplements . unshift ( processIName ( finalExtendsName ) ) ;
1015
+ finalExtendsName = null ;
1016
+ }
1017
+ }
1018
+
1019
+
1020
+ if ( i . comment ) {
1021
+ printer . printLine ( `/** ${ i . comment } */` ) ;
1022
+ }
1023
+
1024
+ if ( finalImplements . length ) {
1025
+ printer . printLine ( `interface ${ getNameWithTypeParameter ( i , i . name ) } extends ${ finalImplements . join ( ", " ) } {}` ) ;
1026
+ }
1027
+
1028
+ printer . print ( `${ prefix } class ${ getNameWithTypeParameter ( i , i . name ) } ` ) ;
1029
+ if ( finalExtendsName ) {
1030
+ printer . print ( ` ${ extendsKeyword } ${ finalExtendsName } ` )
1031
+ }
1032
+ printer . print ( " {" ) ;
1033
+ printer . endLine ( ) ;
1034
+ }
1035
+
1036
+ function emitClass ( i : Browser . Interface , prefix = "" ) {
1037
+ printer . clearStack ( ) ;
1038
+ emitInterfaceEventMap ( i ) ;
1039
+
1040
+ emitClassDeclaration ( i , prefix ) ;
1041
+ printer . increaseIndent ( ) ;
1042
+ emitConstructorSignature ( i , "constructor" ) ;
1043
+
1044
+ emitMembers ( /*prefix*/ "" , EmitScope . InstanceOnly , i ) ;
1045
+ emitConstants ( i ) ;
1046
+ emitEventHandlers ( /*prefix*/ "" , i ) ;
1047
+ emitIndexers ( EmitScope . InstanceOnly , i ) ;
1048
+
1049
+ emitMembers ( /*prefix*/ "static " , EmitScope . StaticOnly , i ) ;
1050
+ emitConstants ( i , /*prefix*/ "static " ) ;
1051
+ if ( iNameToConstParents [ i . name ] && iNameToConstParents [ i . name ] . length ) {
1052
+ for ( const parent of iNameToConstParents [ i . name ] ) {
1053
+ emitConstants ( parent , /*prefix*/ "static " ) ;
1054
+ }
1055
+ }
1056
+
1057
+ printer . decreaseIndent ( ) ;
1058
+ printer . printLine ( "}" ) ;
1059
+ printer . printLine ( "" ) ;
1060
+
1061
+ if ( flavor === Flavor . Web && i [ "legacy-window-alias" ] ) {
1062
+ for ( const alias of i [ "legacy-window-alias" ] ! ) {
1063
+ printer . printLine ( `type ${ alias } = ${ i . name } ;` ) ;
1064
+ printer . printLine ( `declare var ${ alias } : typeof ${ i . name } ;` ) ;
1065
+ printer . printLine ( "" ) ;
1066
+ }
1067
+ }
1068
+ }
1069
+
989
1070
function emitStaticInterface ( i : Browser . Interface ) {
990
1071
// Some types are static types with non-static members. For example,
991
1072
// NodeFilter is a static method itself, however it has an "acceptNode" method
@@ -1053,6 +1134,9 @@ export function emitWebIdl(webidl: Browser.WebIdl, flavor: Flavor) {
1053
1134
else if ( i [ "no-interface-object" ] ) {
1054
1135
emitInterface ( i ) ;
1055
1136
}
1137
+ else if ( processIName ( i . name ) === i . name ) {
1138
+ emitClass ( i , "declare " ) ;
1139
+ }
1056
1140
else {
1057
1141
emitInterface ( i ) ;
1058
1142
emitConstructor ( i , "declare " ) ;
@@ -1080,8 +1164,13 @@ export function emitWebIdl(webidl: Browser.WebIdl, flavor: Flavor) {
1080
1164
namespace . nested . interfaces
1081
1165
. sort ( compareName )
1082
1166
. forEach ( i => {
1083
- emitInterface ( i ) ;
1084
- emitConstructor ( i ) ;
1167
+ if ( processIName ( i . name ) === i . name ) {
1168
+ emitClass ( i )
1169
+ }
1170
+ else {
1171
+ emitInterface ( i ) ;
1172
+ emitConstructor ( i ) ;
1173
+ }
1085
1174
} ) ;
1086
1175
namespace . nested . dictionaries
1087
1176
. sort ( compareName )
0 commit comments