Make getAllTypes unwrap IDL record<K, V> types (#37039)

IDL `record` types can themselves contain types that are not described
anywhere else. An example is in
https://github.com/servo/servo/issues/37038, where the `record` contains
a definition of a union. These inner types must be returned from
`getAllTypes`, otherwise we won't generate code for them.

This PR also adds a few type annotations. I can remove them if
requested, but I think they're helpful.

Testing:  Includes a regression test
Fixes: https://github.com/servo/servo/issues/37038

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
Simon Wülker 2025-05-18 11:30:20 +02:00 committed by GitHub
parent 070a8cf937
commit edea2caec1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 33 additions and 2 deletions

View file

@ -6,6 +6,7 @@
from collections import defaultdict from collections import defaultdict
from itertools import groupby from itertools import groupby
from typing import Generator, Tuple, Optional, List
import operator import operator
import os import os
@ -18,7 +19,9 @@ from WebIDL import (
BuiltinTypes, BuiltinTypes,
IDLArgument, IDLArgument,
IDLBuiltinType, IDLBuiltinType,
IDLCallback,
IDLDefaultDictionaryValue, IDLDefaultDictionaryValue,
IDLDictionary,
IDLEmptySequenceValue, IDLEmptySequenceValue,
IDLInterface, IDLInterface,
IDLInterfaceMember, IDLInterfaceMember,
@ -27,12 +30,15 @@ from WebIDL import (
IDLObject, IDLObject,
IDLPromiseType, IDLPromiseType,
IDLType, IDLType,
IDLTypedef,
IDLTypedefType, IDLTypedefType,
IDLUndefinedValue, IDLUndefinedValue,
IDLWrapperType, IDLWrapperType,
) )
from Configuration import ( from Configuration import (
Configuration,
Descriptor,
MakeNativeName, MakeNativeName,
MemberIsLegacyUnforgeable, MemberIsLegacyUnforgeable,
getModuleFromObject, getModuleFromObject,
@ -2580,7 +2586,12 @@ class CGCallbackTempRoot(CGGeneric):
CGGeneric.__init__(self, f"{name.replace('<D>', '::<D>')}::new(cx, ${{val}}.get().to_object())") CGGeneric.__init__(self, f"{name.replace('<D>', '::<D>')}::new(cx, ${{val}}.get().to_object())")
def getAllTypes(descriptors, dictionaries, callbacks, typedefs): def getAllTypes(
descriptors: List[Descriptor],
dictionaries: List[IDLDictionary],
callbacks: List[IDLCallback],
typedefs: List[IDLTypedef]
) -> Generator[Tuple[IDLType, Optional[Descriptor]], None, None]:
""" """
Generate all the types we're dealing with. For each type, a tuple Generate all the types we're dealing with. For each type, a tuple
containing type, descriptor, dictionary is yielded. The containing type, descriptor, dictionary is yielded. The
@ -2588,18 +2599,32 @@ def getAllTypes(descriptors, dictionaries, callbacks, typedefs):
""" """
for d in descriptors: for d in descriptors:
for t in getTypesFromDescriptor(d): for t in getTypesFromDescriptor(d):
if t.isRecord():
yield (t.inner, d)
yield (t, d) yield (t, d)
for dictionary in dictionaries: for dictionary in dictionaries:
for t in getTypesFromDictionary(dictionary): for t in getTypesFromDictionary(dictionary):
if t.isRecord():
yield (t.inner, None)
yield (t, None) yield (t, None)
for callback in callbacks: for callback in callbacks:
for t in getTypesFromCallback(callback): for t in getTypesFromCallback(callback):
if t.isRecord():
yield (t.inner, None)
yield (t, None) yield (t, None)
for typedef in typedefs: for typedef in typedefs:
if typedef.innerType.isRecord():
yield (typedef.innerType.inner, None)
yield (typedef.innerType, None) yield (typedef.innerType, None)
def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config): def UnionTypes(
descriptors: List[Descriptor],
dictionaries: List[IDLDictionary],
callbacks: List[IDLCallback],
typedefs: List[IDLTypedef],
config: Configuration
):
""" """
Returns a CGList containing CGUnionStructs for every union. Returns a CGList containing CGUnionStructs for every union.
""" """

View file

@ -621,3 +621,9 @@ namespace TestNS {
}; };
typedef Promise<undefined> PromiseUndefined; typedef Promise<undefined> PromiseUndefined;
// https://github.com/servo/servo/issues/37038
dictionary NotUsedAnyWhereElse {};
dictionary RecordFieldWithUnionInside {
record<USVString, (USVString or NotUsedAnyWhereElse)> recordWithUnionField;
};