script_bindings: Add type definitions for configuration.py (#38450)

*Describe the changes that this pull request makes here. This will be
the commit message.*

Testing: *Describe how this pull request is tested or why it doesn't
require tests*
Fixes: *Link to an issue this pull requests fixes or remove this line if
there is no issue*

---------

Signed-off-by: Jerens Lensun <jerensslensun@gmail.com>
This commit is contained in:
Jerens Lensun 2025-08-06 13:44:05 +08:00 committed by GitHub
parent 62b181dc85
commit 5b148cf5de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 66 additions and 45 deletions

View file

@ -136,10 +136,9 @@ def isDomInterface(t: IDLObject, logging: bool = False) -> bool:
t = t.inner
if isinstance(t, IDLInterface):
return True
# pyrefly: ignore # missing-attribute
assert isinstance(t, IDLType)
if t.isCallback() or t.isPromise():
return True
# pyrefly: ignore # missing-attribute
return t.isInterface() and (t.isSpiderMonkeyInterface() and not t.isBufferSource())
@ -160,9 +159,9 @@ def containsDomInterface(t: IDLObject, logging: bool = False) -> bool:
return any(map(lambda x: containsDomInterface(x), t.members)) or (t.parent and containsDomInterface(t.parent))
if isDomInterface(t):
return True
# pyrefly: ignore # missing-attribute
assert isinstance(t, IDLType)
if t.isSequence():
# pyrefly: ignore # missing-attribute
assert isinstance(t, IDLSequenceType)
return containsDomInterface(t.inner)
return False
@ -2674,11 +2673,13 @@ def getAllTypes(
for dictionary in dictionaries:
for t in getTypesFromDictionary(dictionary):
if t.isRecord():
# pyrefly: ignore # missing-attribute
yield (t.inner, None)
yield (t, None)
for callback in callbacks:
for t in getTypesFromCallback(callback):
if t.isRecord():
# pyrefly: ignore # missing-attribute
yield (t.inner, None)
yield (t, None)
for typedef in typedefs:
@ -2713,7 +2714,7 @@ def UnionTypes(
t = t.unroll()
if not t.isUnion():
continue
# pyrefly: ignore # missing-attribute
assert isinstance(t, IDLUnionType) and t.flatMemberTypes is not None
for memberType in t.flatMemberTypes:
if memberType.isDictionary() or memberType.isEnum() or memberType.isCallback():
memberModule = getModuleFromObject(memberType)
@ -7828,43 +7829,38 @@ def type_needs_tracing(t: IDLObject):
assert isinstance(t, IDLObject), (t, type(t))
if t.isType():
assert isinstance(t, IDLType)
if isinstance(t, IDLWrapperType):
return type_needs_tracing(t.inner)
# pyrefly: ignore # missing-attribute
if t.nullable():
# pyrefly: ignore # missing-attribute
assert isinstance(t, IDLNullableType)
return type_needs_tracing(t.inner)
# pyrefly: ignore # missing-attribute
if t.isAny():
return True
# pyrefly: ignore # missing-attribute
if t.isObject():
return True
# pyrefly: ignore # missing-attribute
if t.isSequence() :
# pyrefly: ignore # missing-attribute
assert isinstance(t, IDLSequenceType)
return type_needs_tracing(t.inner)
if t.isUnion():
# pyrefly: ignore # not-iterable
assert isinstance(t, IDLUnionType) and t.flatMemberTypes is not None
return any(type_needs_tracing(member) for member in t.flatMemberTypes)
# pyrefly: ignore # bad-argument-type
if is_typed_array(t):
return True
return False
if t.isDictionary():
# pyrefly: ignore # missing-attribute, bad-argument-type
assert isinstance(t, IDLDictionary)
if t.parent and type_needs_tracing(t.parent):
return True
# pyrefly: ignore # missing-attribute
if any(type_needs_tracing(member.type) for member in t.members):
return True

View file

@ -4,8 +4,21 @@
import functools
import os
from typing import Any
from WebIDL import IDLExternalInterface, IDLSequenceType, IDLWrapperType, WebIDLError
from WebIDL import (
IDLExternalInterface,
IDLSequenceType,
IDLWrapperType,
WebIDLError,
IDLObject,
IDLType,
IDLInterface,
IDLDictionary,
IDLCallback,
IDLAttribute,
IDLMethod,
)
class Configuration:
@ -13,7 +26,14 @@ class Configuration:
Represents global configuration state based on IDL parse data and
the configuration file.
"""
def __init__(self, filename, parseData) -> None:
glbl: dict[str, Any]
enumConfig: dict[str, Any]
dictConfig: dict[str, Any]
unionConfig: dict[str, Any]
descriptors: list["Descriptor"]
interfaces: dict[str, IDLInterface]
def __init__(self, filename: str, parseData: list[IDLInterface]) -> None:
# Read the configuration file.
glbl = {}
exec(compile(open(filename).read(), filename, 'exec'), glbl)
@ -70,15 +90,15 @@ class Configuration:
return (x > y) - (x < y)
self.descriptors.sort(key=functools.cmp_to_key(lambda x, y: cmp(x.name, y.name)))
def getInterface(self, ifname):
def getInterface(self, ifname: str) -> IDLInterface:
return self.interfaces[ifname]
def getDescriptors(self, **filters):
def getDescriptors(self, **filters) -> list["Descriptor"]:
"""Gets the descriptors that match the given filters."""
curr = self.descriptors
for key, val in filters.items():
if key == 'webIDLFile':
def getter(x):
def getter(x: Descriptor):
return x.interface.location.filename
elif key == 'hasInterfaceObject':
def getter(x):
@ -110,36 +130,36 @@ class Configuration:
curr = [x for x in curr if getter(x) == val]
return curr
def getEnums(self, webIDLFile):
def getEnums(self, webIDLFile: str) -> list[IDLInterface]:
return [e for e in self.enums if e.filename == webIDLFile]
def getEnumConfig(self, name):
def getEnumConfig(self, name: str) -> dict[str, Any]:
return self.enumConfig.get(name, {})
def getTypedefs(self, webIDLFile):
def getTypedefs(self, webIDLFile: str) -> list[IDLInterface]:
return [e for e in self.typedefs if e.filename == webIDLFile]
@staticmethod
def _filterForFile(items, webIDLFile=""):
def _filterForFile(items: list[IDLInterface], webIDLFile: str = "") -> list[IDLInterface]:
"""Gets the items that match the given filters."""
if not webIDLFile:
return items
return [x for x in items if x.filename == webIDLFile]
def getUnionConfig(self, name):
def getUnionConfig(self, name: str) -> dict[str, Any]:
return self.unionConfig.get(name, {})
def getDictionaries(self, webIDLFile=""):
def getDictionaries(self, webIDLFile: str = "") -> list[IDLInterface]:
return self._filterForFile(self.dictionaries, webIDLFile=webIDLFile)
def getDictConfig(self, name):
def getDictConfig(self, name: str) -> dict[str, Any]:
return self.dictConfig.get(name, {})
def getCallbacks(self, webIDLFile=""):
def getCallbacks(self, webIDLFile: str = "") -> list[IDLInterface]:
return self._filterForFile(self.callbacks, webIDLFile=webIDLFile)
def getDescriptor(self, interfaceName):
def getDescriptor(self, interfaceName: str) -> "Descriptor":
"""
Gets the appropriate descriptor for the given interface name.
"""
@ -152,7 +172,7 @@ class Configuration:
+ str(len(descriptors)) + " matches")
return descriptors[0]
def getDescriptorProvider(self):
def getDescriptorProvider(self) -> "DescriptorProvider":
"""
Gets a descriptor provider that can provide descriptors as needed.
"""
@ -171,7 +191,7 @@ class DescriptorProvider:
def __init__(self, config) -> None:
self.config = config
def getDescriptor(self, interfaceName):
def getDescriptor(self, interfaceName: str) -> "Descriptor":
"""
Gets the appropriate descriptor for the given interface name given the
context of the current descriptor.
@ -179,7 +199,7 @@ class DescriptorProvider:
return self.config.getDescriptor(interfaceName)
def MemberIsLegacyUnforgeable(member, descriptor):
def MemberIsLegacyUnforgeable(member: IDLAttribute | IDLMethod, descriptor: "Descriptor") -> bool:
return ((member.isAttr() or member.isMethod())
and not member.isStatic()
and (member.isLegacyUnforgeable()
@ -190,7 +210,10 @@ class Descriptor(DescriptorProvider):
"""
Represents a single descriptor for an interface. See Bindings.conf.
"""
def __init__(self, config, interface, desc) -> None:
interface: IDLInterface
uniqueImplementation: bool
def __init__(self, config, interface: IDLInterface, desc: dict[str, Any]) -> None:
DescriptorProvider.__init__(self, config)
self.interface = interface
@ -211,6 +234,7 @@ class Descriptor(DescriptorProvider):
# functionality.
prefix = "D::"
if self.interface.isIteratorInterface():
assert self.interface.iterableInterface is not None
itrName = self.interface.iterableInterface.identifier.name
itrDesc = self.getDescriptor(itrName)
nativeTypeDefault = iteratorNativeType(itrDesc)
@ -290,7 +314,7 @@ class Descriptor(DescriptorProvider):
self.hasDefaultToJSON = True
if self.concrete:
iface = self.interface
iface: IDLInterface | None = self.interface
while iface:
for m in iface.members:
if not m.isMethod():
@ -346,7 +370,7 @@ class Descriptor(DescriptorProvider):
else:
assert isinstance(config, str)
if config == '*':
iface = self.interface
iface: IDLInterface | None = self.interface
while iface:
add('all', [m.name for m in iface.members], attribute)
iface = iface.parent
@ -373,7 +397,7 @@ class Descriptor(DescriptorProvider):
# Build the prototype chain.
self.prototypeChain = []
parent = interface
parent: IDLInterface | None = interface
while parent:
self.prototypeChain.insert(0, parent.identifier.name)
parent = parent.parent
@ -392,10 +416,10 @@ class Descriptor(DescriptorProvider):
return filename
return None
def binaryNameFor(self, name, isStatic):
def binaryNameFor(self, name: str, isStatic: bool):
return self._binaryNames.get((name, isStatic), name)
def internalNameFor(self, name):
def internalNameFor(self, name: str):
return self._internalNames.get(name, name)
def hasNamedPropertiesObject(self) -> bool:
@ -487,15 +511,15 @@ def MakeNativeName(name):
return name[0].upper() + name[1:]
def getIdlFileName(object):
def getIdlFileName(object: IDLObject):
return os.path.basename(object.location.filename).split('.webidl')[0]
def getModuleFromObject(object):
def getModuleFromObject(object: IDLObject):
return ('crate::codegen::GenericBindings::' + getIdlFileName(object) + 'Binding')
def getTypesFromDescriptor(descriptor):
def getTypesFromDescriptor(descriptor: Descriptor):
"""
Get all argument and return types for all members of the descriptor
"""
@ -515,7 +539,7 @@ def getTypesFromDescriptor(descriptor):
return types
def getTypesFromDictionary(dictionary):
def getTypesFromDictionary(dictionary: IDLDictionary) -> list[IDLType]:
"""
Get all member types for this dictionary
"""
@ -529,7 +553,7 @@ def getTypesFromDictionary(dictionary):
return types
def getTypesFromCallback(callback):
def getTypesFromCallback(callback: IDLCallback) -> list[IDLType]:
"""
Get the types this callback depends on: its return type and the
types of its arguments.
@ -540,13 +564,14 @@ def getTypesFromCallback(callback):
return types
def getUnwrappedType(type):
def getUnwrappedType(type: IDLType) -> IDLType:
while isinstance(type, IDLSequenceType):
type = type.inner
return type
def iteratorNativeType(descriptor, infer=False):
def iteratorNativeType(descriptor: Descriptor, infer: bool = False):
assert descriptor.interface.maplikeOrSetlikeOrIterable is not None
iterableDecl = descriptor.interface.maplikeOrSetlikeOrIterable
assert (iterableDecl.isIterable() and iterableDecl.isPairIterator()) \
or iterableDecl.isSetlike() or iterableDecl.isMaplike()