Support multiple WebIDL interfaces being generated in the same output binding file.

Each interface gets its own module named ${Interface}Binding. Structs, enums, and callbacks
continue to use the root module of the binding file. If there is only one interface in the
file, we generate reexports for several public APIs and types so that existing DOM implementations
don't need any modifications. When multiple interfaces exist, the reexported names get the interface
name prepended (eg. FooWrap instead of Wrap).

As part of this work, stop glob-importing all DOM types in every generated binding and start generating
more targeted lists of relevant types based on the methods, members, etc. of WebIDL types that are in use.
This commit is contained in:
Josh Matthews 2016-08-11 11:21:47 -04:00
parent 49d483590e
commit 221bc84693
5 changed files with 239 additions and 135 deletions

View file

@ -21,6 +21,7 @@ from WebIDL import (
IDLType, IDLType,
IDLInterfaceMember, IDLInterfaceMember,
IDLUndefinedValue, IDLUndefinedValue,
IDLWrapperType,
) )
from Configuration import ( from Configuration import (
@ -942,7 +943,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
assert not type.treatNonObjectAsNull() or not type.treatNonCallableAsNull() assert not type.treatNonObjectAsNull() or not type.treatNonCallableAsNull()
callback = type.unroll().callback callback = type.unroll().callback
declType = CGGeneric('%s::%s' % (getModuleFromObject(callback), callback.identifier.name)) declType = CGGeneric(callback.identifier.name)
finalDeclType = CGTemplatedType("Rc", declType) finalDeclType = CGTemplatedType("Rc", declType)
conversion = CGCallbackTempRoot(declType.define()) conversion = CGCallbackTempRoot(declType.define())
@ -1738,7 +1739,7 @@ class CGImports(CGWrapper):
""" """
Generates the appropriate import/use statements. Generates the appropriate import/use statements.
""" """
def __init__(self, child, descriptors, callbacks, imports, config, ignored_warnings=None): def __init__(self, child, descriptors, callbacks, dictionaries, enums, imports, config, ignored_warnings=None):
""" """
Adds a set of imports. Adds a set of imports.
""" """
@ -1752,17 +1753,19 @@ class CGImports(CGWrapper):
] ]
def componentTypes(type): def componentTypes(type):
if type.nullable(): if type.isType() and type.nullable():
type = type.unroll() type = type.unroll()
if type.isUnion(): if type.isUnion():
return type.flatMemberTypes return type.flatMemberTypes
if type.isDictionary():
return [type] + getTypesFromDictionary(type)
return [type] return [type]
def isImportable(type): def isImportable(type):
if not type.isType(): if not type.isType():
assert type.isInterface() assert type.isInterface() or type.isDictionary() or type.isEnum()
return not type.isCallback() return True
return type.isNonCallbackInterface() and not type.builtin return not (type.builtin or type.isSequence() or type.isUnion())
def relatedTypesForSignatures(method): def relatedTypesForSignatures(method):
types = [] types = []
@ -1774,12 +1777,26 @@ class CGImports(CGWrapper):
def getIdentifier(t): def getIdentifier(t):
if t.isType(): if t.isType():
return t.inner.identifier if t.nullable():
assert t.isInterface() t = t.inner
if t.isCallback():
return t.callback.identifier
return t.identifier return t.identifier
assert t.isInterface() or t.isDictionary() or t.isEnum()
return t.identifier
def removeWrapperAndNullableTypes(types):
normalized = []
for t in types:
while (t.isType() and t.nullable()) or isinstance(t, IDLWrapperType):
t = t.inner
if isImportable(t):
normalized += [t]
return normalized
types = [] types = []
for d in descriptors: for d in descriptors:
if not d.interface.isCallback():
types += [d.interface] types += [d.interface]
members = d.interface.members + d.interface.namedConstructors members = d.interface.members + d.interface.namedConstructors
@ -1796,19 +1813,39 @@ class CGImports(CGWrapper):
elif m.isAttr(): elif m.isAttr():
types += componentTypes(m.type) types += componentTypes(m.type)
# Import the type names used in the callbacks that are being defined.
for c in callbacks: for c in callbacks:
types += relatedTypesForSignatures(c) types += relatedTypesForSignatures(c)
# Import the type names used in the dictionaries that are being defined.
for d in dictionaries:
types += componentTypes(d)
# Normalize the types we've collected and remove any ones which can't be imported.
types = removeWrapperAndNullableTypes(types)
descriptorProvider = config.getDescriptorProvider() descriptorProvider = config.getDescriptorProvider()
extras = []
for t in types: for t in types:
if isImportable(t): # Importing these types in the same module that defines them is an error.
if t in dictionaries or t in enums:
continue
if t.isInterface():
descriptor = descriptorProvider.getDescriptor(getIdentifier(t).name) descriptor = descriptorProvider.getDescriptor(getIdentifier(t).name)
imports += ['%s' % descriptor.path] extras += [descriptor.path]
if descriptor.interface.parent:
parentName = getIdentifier(descriptor.interface.parent).name
descriptor = descriptorProvider.getDescriptor(parentName)
extras += [descriptor.path, descriptor.bindingPath]
else:
if t.isEnum():
extras += [getModuleFromObject(t) + '::' + getIdentifier(t).name + 'Values']
extras += [getModuleFromObject(t) + '::' + getIdentifier(t).name]
statements = [] statements = []
if len(ignored_warnings) > 0: if len(ignored_warnings) > 0:
statements.append('#![allow(%s)]' % ','.join(ignored_warnings)) statements.append('#![allow(%s)]' % ','.join(ignored_warnings))
statements.extend('use %s;' % i for i in sorted(set(imports))) statements.extend('use %s;' % i for i in sorted(set(imports + extras)))
CGWrapper.__init__(self, child, CGWrapper.__init__(self, child,
pre='\n'.join(statements) + '\n\n') pre='\n'.join(statements) + '\n\n')
@ -2111,7 +2148,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, config):
# Sort unionStructs by key, retrieve value # Sort unionStructs by key, retrieve value
unionStructs = (i[1] for i in sorted(unionStructs.items(), key=operator.itemgetter(0))) unionStructs = (i[1] for i in sorted(unionStructs.items(), key=operator.itemgetter(0)))
return CGImports(CGList(unionStructs, "\n\n"), [], [], imports, config, ignored_warnings=[]) return CGImports(CGList(unionStructs, "\n\n"), [], [], [], [], imports, config, ignored_warnings=[])
class Argument(): class Argument():
@ -2709,7 +2746,7 @@ class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
""" """
def __init__(self, descriptor): def __init__(self, descriptor):
CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObject", CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObject",
"PrototypeList::ID", pub=descriptor.hasDescendants()) "PrototypeList::ID", pub=True)
def definition_body(self): def definition_body(self):
return CGList([ return CGList([
@ -2727,7 +2764,7 @@ class CGGetConstructorObjectMethod(CGGetPerInterfaceObject):
def __init__(self, descriptor): def __init__(self, descriptor):
CGGetPerInterfaceObject.__init__(self, descriptor, "GetConstructorObject", CGGetPerInterfaceObject.__init__(self, descriptor, "GetConstructorObject",
"PrototypeList::Constructor", "PrototypeList::Constructor",
pub=descriptor.hasDescendants()) pub=True)
def definition_body(self): def definition_body(self):
return CGList([ return CGList([
@ -5067,6 +5104,7 @@ class CGInterfaceTrait(CGThing):
post="}") post="}")
else: else:
self.cgRoot = CGGeneric("") self.cgRoot = CGGeneric("")
self.empty = not methods
def define(self): def define(self):
return self.cgRoot.define() return self.cgRoot.define()
@ -5082,18 +5120,135 @@ class CGWeakReferenceableTrait(CGThing):
return self.code return self.code
def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries=None, enums=None):
if not callbacks:
callbacks = []
if not dictionaries:
dictionaries = []
if not enums:
enums = []
return CGImports(cgthings, descriptors, callbacks, dictionaries, enums, [
'js',
'js::{JS_CALLEE, JSCLASS_GLOBAL_SLOT_COUNT}',
'js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL, JSCLASS_RESERVED_SLOTS_MASK}',
'js::error::throw_type_error',
'js::jsapi::{JSJitInfo_AliasSet, JSJitInfo_ArgType, AutoIdVector, CallArgs, FreeOp}',
'js::jsapi::{JSITER_SYMBOLS, JSPROP_ENUMERATE, JSPROP_PERMANENT, JSPROP_READONLY, JSPROP_SHARED}',
'js::jsapi::{JSCLASS_RESERVED_SLOTS_SHIFT, JSITER_HIDDEN, JSITER_OWNONLY}',
'js::jsapi::{GetPropertyKeys, Handle}',
'js::jsapi::{HandleId, HandleObject, HandleValue, HandleValueArray}',
'js::jsapi::{INTERNED_STRING_TO_JSID, IsCallable, JS_CallFunctionValue}',
'js::jsapi::{JS_CopyPropertiesFrom, JS_ForwardGetPropertyTo}',
'js::jsapi::{JS_GetClass, JS_GetErrorPrototype, JS_GetFunctionPrototype}',
'js::jsapi::{JS_GetGlobalForObject, JS_GetObjectPrototype, JS_GetProperty}',
'js::jsapi::{JS_GetPropertyById, JS_GetPropertyDescriptorById, JS_GetReservedSlot}',
'js::jsapi::{JS_HasProperty, JS_HasPropertyById, JS_InitializePropertiesFromCompatibleNativeObject}',
'js::jsapi::{JS_AtomizeAndPinString, JS_NewObject, JS_NewObjectWithGivenProto}',
'js::jsapi::{JS_NewObjectWithoutMetadata, JS_SetProperty}',
'js::jsapi::{JS_SplicePrototype, JS_SetReservedSlot, JSAutoCompartment}',
'js::jsapi::{JSContext, JSClass, JSFreeOp, JSFunctionSpec}',
'js::jsapi::{JSJitGetterCallArgs, JSJitInfo, JSJitMethodCallArgs, JSJitSetterCallArgs}',
'js::jsapi::{JSNative, JSObject, JSNativeWrapper, JSPropertySpec}',
'js::jsapi::{JSString, JSTracer, JSType, JSTypedMethodJitInfo, JSValueType}',
'js::jsapi::{ObjectOpResult, JSJitInfo_OpType, MutableHandle, MutableHandleObject}',
'js::jsapi::{MutableHandleValue, PropertyDescriptor, RootedObject}',
'js::jsapi::{SymbolCode, jsid}',
'js::jsval::JSVal',
'js::jsval::{ObjectValue, ObjectOrNullValue, PrivateValue}',
'js::jsval::{NullValue, UndefinedValue}',
'js::glue::{CallJitMethodOp, CallJitGetterOp, CallJitSetterOp, CreateProxyHandler}',
'js::glue::{GetProxyPrivate, NewProxyObject, ProxyTraps}',
'js::glue::{RUST_JSID_IS_STRING, int_to_jsid}',
'js::glue::AppendToAutoIdVector',
'js::rust::{GCMethods, define_methods, define_properties}',
'dom',
'dom::bindings',
'dom::bindings::codegen::InterfaceObjectMap',
'dom::bindings::global::{GlobalRef, global_root_from_object, global_root_from_reflector}',
'dom::bindings::interface::{InterfaceConstructorBehavior, NonCallbackInterfaceObjectClass}',
'dom::bindings::interface::{create_callback_interface_object, create_interface_prototype_object}',
'dom::bindings::interface::{create_named_constructors, create_noncallback_interface_object}',
'dom::bindings::interface::{define_guarded_methods, define_guarded_properties}',
'dom::bindings::interface::{ConstantSpec, NonNullJSNative}',
'dom::bindings::interface::ConstantVal::{IntVal, UintVal}',
'dom::bindings::interface::is_exposed_in',
'dom::bindings::js::{JS, Root, RootedReference}',
'dom::bindings::js::{OptionalRootedReference}',
'dom::bindings::reflector::{Reflectable}',
'dom::bindings::utils::{DOMClass, DOMJSClass}',
'dom::bindings::utils::{DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, JSCLASS_DOM_GLOBAL}',
'dom::bindings::utils::{ProtoOrIfaceArray, create_dom_global}',
'dom::bindings::utils::{enumerate_global, finalize_global, find_enum_string_index}',
'dom::bindings::utils::{generic_getter, generic_lenient_getter, generic_lenient_setter}',
'dom::bindings::utils::{generic_method, generic_setter, get_array_index_from_id}',
'dom::bindings::utils::{get_dictionary_property, get_property_on_prototype}',
'dom::bindings::utils::{get_proto_or_iface_array, has_property_on_prototype}',
'dom::bindings::utils::{is_platform_object, resolve_global, set_dictionary_property, trace_global}',
'dom::bindings::trace::{JSTraceable, RootedTraceable}',
'dom::bindings::callback::{CallbackContainer,CallbackInterface,CallbackFunction}',
'dom::bindings::callback::{CallSetup,ExceptionHandling}',
'dom::bindings::callback::wrap_call_this_object',
'dom::bindings::conversions::{ConversionBehavior, ConversionResult, DOM_OBJECT_SLOT}',
'dom::bindings::conversions::{IDLInterface, is_array_like}',
'dom::bindings::conversions::{FromJSValConvertible, StringificationBehavior}',
'dom::bindings::conversions::{ToJSValConvertible, jsid_to_str, native_from_handlevalue}',
'dom::bindings::conversions::{native_from_object, private_from_object, root_from_object}',
'dom::bindings::conversions::{root_from_handleobject, root_from_handlevalue}',
'dom::bindings::codegen::{PrototypeList, RegisterBindings, UnionTypes}',
'dom::bindings::error::{Fallible, Error, ErrorResult}',
'dom::bindings::error::Error::JSFailed',
'dom::bindings::error::throw_dom_exception',
'dom::bindings::guard::{Condition, Guard}',
'dom::bindings::proxyhandler',
'dom::bindings::proxyhandler::{ensure_expando_object, fill_property_descriptor}',
'dom::bindings::proxyhandler::{get_expando_object, get_property_descriptor}',
'dom::bindings::num::Finite',
'dom::bindings::str::{ByteString, DOMString, USVString}',
'dom::bindings::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable}',
'dom::browsingcontext::BrowsingContext',
'mem::heap_size_of_raw_self_and_children',
'libc',
'util::prefs::PREFS',
'script_runtime::{store_panic_result, maybe_take_panic_result}',
'std::borrow::ToOwned',
'std::cmp',
'std::mem',
'std::num',
'std::os',
'std::panic::{self, AssertUnwindSafe}',
'std::ptr',
'std::str',
'std::rc',
'std::rc::Rc',
'std::default::Default',
'std::ffi::CString',
], config)
class CGDescriptor(CGThing): class CGDescriptor(CGThing):
def __init__(self, descriptor): def __init__(self, descriptor, config, soleDescriptor):
CGThing.__init__(self) CGThing.__init__(self)
assert not descriptor.concrete or not descriptor.interface.isCallback() assert not descriptor.concrete or not descriptor.interface.isCallback()
reexports = []
def reexportedName(name):
if name.startswith(descriptor.name):
return name
if not soleDescriptor:
return '%s as %s%s' % (name, descriptor.name, name)
return name
cgThings = [] cgThings = []
if not descriptor.interface.isCallback(): if not descriptor.interface.isCallback():
cgThings.append(CGGetProtoObjectMethod(descriptor)) cgThings.append(CGGetProtoObjectMethod(descriptor))
reexports.append('GetProtoObject')
if (descriptor.interface.hasInterfaceObject() and if (descriptor.interface.hasInterfaceObject() and
descriptor.shouldHaveGetConstructorObjectMethod()): descriptor.shouldHaveGetConstructorObjectMethod()):
cgThings.append(CGGetConstructorObjectMethod(descriptor)) cgThings.append(CGGetConstructorObjectMethod(descriptor))
reexports.append('GetConstructorObject')
unscopableNames = [] unscopableNames = []
for m in descriptor.interface.members: for m in descriptor.interface.members:
@ -5155,9 +5310,11 @@ class CGDescriptor(CGThing):
cgThings.append(CGNamespace.build([descriptor.name + "Constants"], cgThings.append(CGNamespace.build([descriptor.name + "Constants"],
CGConstant(constMembers), CGConstant(constMembers),
public=True)) public=True))
reexports.append(descriptor.name + 'Constants')
if descriptor.interface.hasInterfaceObject(): if descriptor.interface.hasInterfaceObject():
cgThings.append(CGDefineDOMInterfaceMethod(descriptor)) cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
reexports.append('DefineDOMInterface')
cgThings.append(CGConstructorEnabled(descriptor)) cgThings.append(CGConstructorEnabled(descriptor))
if descriptor.proxy: if descriptor.proxy:
@ -5193,6 +5350,7 @@ class CGDescriptor(CGThing):
pass pass
cgThings.append(CGWrapMethod(descriptor)) cgThings.append(CGWrapMethod(descriptor))
reexports.append('Wrap')
haveUnscopables = False haveUnscopables = False
if not descriptor.interface.isCallback(): if not descriptor.interface.isCallback():
@ -5205,7 +5363,12 @@ class CGDescriptor(CGThing):
CGGeneric("];\n")], "\n")) CGGeneric("];\n")], "\n"))
if descriptor.concrete or descriptor.hasDescendants(): if descriptor.concrete or descriptor.hasDescendants():
cgThings.append(CGIDLInterface(descriptor)) cgThings.append(CGIDLInterface(descriptor))
cgThings.append(CGInterfaceTrait(descriptor))
interfaceTrait = CGInterfaceTrait(descriptor)
cgThings.append(interfaceTrait)
if not interfaceTrait.empty:
reexports.append('%sMethods' % descriptor.name)
if descriptor.weakReferenceable: if descriptor.weakReferenceable:
cgThings.append(CGWeakReferenceableTrait(descriptor)) cgThings.append(CGWeakReferenceableTrait(descriptor))
@ -5213,11 +5376,13 @@ class CGDescriptor(CGThing):
cgThings.append(CGGeneric(str(properties))) cgThings.append(CGGeneric(str(properties)))
cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties, haveUnscopables)) cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties, haveUnscopables))
cgThings = CGList(cgThings, "\n") cgThings = generate_imports(config, CGList(cgThings, '\n'), [descriptor])
# self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name), cgThings = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),
# cgThings), cgThings, public=True),
# post='\n') post='\n')
self.cgRoot = cgThings reexports = ', '.join(map(lambda name: reexportedName(name), reexports))
self.cgRoot = CGList([CGGeneric('pub use self::%sBinding::{%s};' % (descriptor.name, reexports)),
cgThings], '\n')
def define(self): def define(self):
return self.cgRoot.define() return self.cgRoot.define()
@ -5467,8 +5632,8 @@ class CGRegisterProxyHandlersMethod(CGAbstractMethod):
def definition_body(self): def definition_body(self):
return CGList([ return CGList([
CGGeneric("proxy_handlers[Proxies::%s as usize] = codegen::Bindings::%sBinding::DefineProxyHandler();" CGGeneric("proxy_handlers[Proxies::%s as usize] = Bindings::%s::DefineProxyHandler();"
% (desc.name, desc.name)) % (desc.name, '::'.join([desc.name + 'Binding'] * 2)))
for desc in self.descriptors for desc in self.descriptors
], "\n") ], "\n")
@ -5541,7 +5706,7 @@ class CGBindingRoot(CGThing):
for c in mainCallbacks) for c in mainCallbacks)
# Do codegen for all the descriptors # Do codegen for all the descriptors
cgthings.extend([CGDescriptor(x) for x in descriptors]) cgthings.extend([CGDescriptor(x, config, len(descriptors) == 1) for x in descriptors])
# Do codegen for all the callback interfaces. # Do codegen for all the callback interfaces.
cgthings.extend(CGList([CGCallbackInterface(x), cgthings.extend(CGList([CGCallbackInterface(x),
@ -5552,102 +5717,8 @@ class CGBindingRoot(CGThing):
curr = CGWrapper(CGList(cgthings, "\n\n"), post="\n\n") curr = CGWrapper(CGList(cgthings, "\n\n"), post="\n\n")
# Add imports # Add imports
curr = CGImports(curr, descriptors + callbackDescriptors, mainCallbacks, [ curr = generate_imports(config, curr, callbackDescriptors, mainCallbacks,
'js', dictionaries, enums)
'js::{JS_CALLEE, JSCLASS_GLOBAL_SLOT_COUNT}',
'js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL, JSCLASS_RESERVED_SLOTS_MASK}',
'js::error::throw_type_error',
'js::jsapi::{JSJitInfo_AliasSet, JSJitInfo_ArgType, AutoIdVector, CallArgs, FreeOp}',
'js::jsapi::{JSITER_SYMBOLS, JSPROP_ENUMERATE, JSPROP_PERMANENT, JSPROP_READONLY, JSPROP_SHARED}',
'js::jsapi::{JSCLASS_RESERVED_SLOTS_SHIFT, JSITER_HIDDEN, JSITER_OWNONLY}',
'js::jsapi::{GetPropertyKeys, Handle}',
'js::jsapi::{HandleId, HandleObject, HandleValue, HandleValueArray}',
'js::jsapi::{INTERNED_STRING_TO_JSID, IsCallable, JS_CallFunctionValue}',
'js::jsapi::{JS_CopyPropertiesFrom, JS_ForwardGetPropertyTo}',
'js::jsapi::{JS_GetClass, JS_GetErrorPrototype, JS_GetFunctionPrototype}',
'js::jsapi::{JS_GetGlobalForObject, JS_GetObjectPrototype, JS_GetProperty}',
'js::jsapi::{JS_GetPropertyById, JS_GetPropertyDescriptorById, JS_GetReservedSlot}',
'js::jsapi::{JS_HasProperty, JS_HasPropertyById, JS_InitializePropertiesFromCompatibleNativeObject}',
'js::jsapi::{JS_AtomizeAndPinString, JS_NewObject, JS_NewObjectWithGivenProto}',
'js::jsapi::{JS_NewObjectWithoutMetadata, JS_SetProperty}',
'js::jsapi::{JS_SplicePrototype, JS_SetReservedSlot, JSAutoCompartment}',
'js::jsapi::{JSContext, JSClass, JSFreeOp, JSFunctionSpec}',
'js::jsapi::{JSJitGetterCallArgs, JSJitInfo, JSJitMethodCallArgs, JSJitSetterCallArgs}',
'js::jsapi::{JSNative, JSObject, JSNativeWrapper, JSPropertySpec}',
'js::jsapi::{JSString, JSTracer, JSType, JSTypedMethodJitInfo, JSValueType}',
'js::jsapi::{ObjectOpResult, JSJitInfo_OpType, MutableHandle, MutableHandleObject}',
'js::jsapi::{MutableHandleValue, PropertyDescriptor, RootedObject}',
'js::jsapi::{SymbolCode, jsid}',
'js::jsval::JSVal',
'js::jsval::{ObjectValue, ObjectOrNullValue, PrivateValue}',
'js::jsval::{NullValue, UndefinedValue}',
'js::glue::{CallJitMethodOp, CallJitGetterOp, CallJitSetterOp, CreateProxyHandler}',
'js::glue::{GetProxyPrivate, NewProxyObject, ProxyTraps}',
'js::glue::{RUST_JSID_IS_STRING, int_to_jsid}',
'js::glue::AppendToAutoIdVector',
'js::rust::{GCMethods, define_methods, define_properties}',
'dom::bindings',
'dom::bindings::codegen::InterfaceObjectMap',
'dom::bindings::global::{GlobalRef, global_root_from_object, global_root_from_reflector}',
'dom::bindings::interface::{InterfaceConstructorBehavior, NonCallbackInterfaceObjectClass}',
'dom::bindings::interface::{create_callback_interface_object, create_interface_prototype_object}',
'dom::bindings::interface::{create_named_constructors, create_noncallback_interface_object}',
'dom::bindings::interface::{define_guarded_methods, define_guarded_properties}',
'dom::bindings::interface::{ConstantSpec, NonNullJSNative}',
'dom::bindings::interface::ConstantVal::{IntVal, UintVal}',
'dom::bindings::interface::is_exposed_in',
'dom::bindings::js::{JS, Root, RootedReference}',
'dom::bindings::js::{OptionalRootedReference}',
'dom::bindings::reflector::{Reflectable}',
'dom::bindings::utils::{DOMClass, DOMJSClass}',
'dom::bindings::utils::{DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, JSCLASS_DOM_GLOBAL}',
'dom::bindings::utils::{ProtoOrIfaceArray, create_dom_global}',
'dom::bindings::utils::{enumerate_global, finalize_global, find_enum_string_index}',
'dom::bindings::utils::{generic_getter, generic_lenient_getter, generic_lenient_setter}',
'dom::bindings::utils::{generic_method, generic_setter, get_array_index_from_id}',
'dom::bindings::utils::{get_dictionary_property, get_property_on_prototype}',
'dom::bindings::utils::{get_proto_or_iface_array, has_property_on_prototype}',
'dom::bindings::utils::{is_platform_object, resolve_global, set_dictionary_property, trace_global}',
'dom::bindings::trace::{JSTraceable, RootedTraceable}',
'dom::bindings::callback::{CallbackContainer,CallbackInterface,CallbackFunction}',
'dom::bindings::callback::{CallSetup,ExceptionHandling}',
'dom::bindings::callback::wrap_call_this_object',
'dom::bindings::conversions::{ConversionBehavior, ConversionResult, DOM_OBJECT_SLOT}',
'dom::bindings::conversions::{IDLInterface, is_array_like}',
'dom::bindings::conversions::{FromJSValConvertible, StringificationBehavior}',
'dom::bindings::conversions::{ToJSValConvertible, jsid_to_str, native_from_handlevalue}',
'dom::bindings::conversions::{native_from_object, private_from_object, root_from_object}',
'dom::bindings::conversions::{root_from_handleobject, root_from_handlevalue}',
'dom::bindings::codegen::{PrototypeList, RegisterBindings, UnionTypes}',
'dom::bindings::codegen::Bindings::*',
'dom::bindings::error::{Fallible, Error, ErrorResult}',
'dom::bindings::error::Error::JSFailed',
'dom::bindings::error::throw_dom_exception',
'dom::bindings::guard::{Condition, Guard}',
'dom::bindings::proxyhandler',
'dom::bindings::proxyhandler::{ensure_expando_object, fill_property_descriptor}',
'dom::bindings::proxyhandler::{get_expando_object, get_property_descriptor}',
'dom::bindings::num::Finite',
'dom::bindings::str::{ByteString, DOMString, USVString}',
'dom::bindings::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable}',
'dom::browsingcontext::BrowsingContext',
'mem::heap_size_of_raw_self_and_children',
'libc',
'util::prefs::PREFS',
'script_runtime::{store_panic_result, maybe_take_panic_result}',
'std::borrow::ToOwned',
'std::cmp',
'std::mem',
'std::num',
'std::os',
'std::panic::{self, AssertUnwindSafe}',
'std::ptr',
'std::str',
'std::rc',
'std::rc::Rc',
'std::default::Default',
'std::ffi::CString',
], config)
# Add the auto-generated comment. # Add the auto-generated comment.
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
@ -6285,12 +6356,12 @@ class GlobalGenRoots():
pairs = [] pairs = []
for d in config.getDescriptors(hasInterfaceObject=True): for d in config.getDescriptors(hasInterfaceObject=True):
binding = toBindingNamespace(d.name) binding = toBindingNamespace(d.name)
pairs.append((d.name, binding)) pairs.append((d.name, binding, binding))
for ctor in d.interface.namedConstructors: for ctor in d.interface.namedConstructors:
pairs.append((ctor.identifier.name, binding)) pairs.append((ctor.identifier.name, binding, binding))
pairs.sort(key=operator.itemgetter(0)) pairs.sort(key=operator.itemgetter(0))
mappings = [ mappings = [
CGGeneric('b"%s" => codegen::Bindings::%s::DefineDOMInterface as unsafe fn(_, _),' % pair) CGGeneric('b"%s" => codegen::Bindings::%s::%s::DefineDOMInterface as unsafe fn(_, _),' % pair)
for pair in pairs for pair in pairs
] ]
mapType = "phf::Map<&'static [u8], unsafe fn(*mut JSContext, HandleObject)>" mapType = "phf::Map<&'static [u8], unsafe fn(*mut JSContext, HandleObject)>"
@ -6339,8 +6410,8 @@ class GlobalGenRoots():
CGRegisterProxyHandlers(config), CGRegisterProxyHandlers(config),
], "\n") ], "\n")
return CGImports(code, [], [], [ return CGImports(code, [], [], [], [], [
'dom::bindings::codegen', 'dom::bindings::codegen::Bindings',
'dom::bindings::codegen::PrototypeList::Proxies', 'dom::bindings::codegen::PrototypeList::Proxies',
'libc', 'libc',
], config, ignored_warnings=[]) ], config, ignored_warnings=[])
@ -6355,9 +6426,13 @@ class GlobalGenRoots():
@staticmethod @staticmethod
def Bindings(config): def Bindings(config):
descriptors = (set(d.name + "Binding" for d in config.getDescriptors(register=True)) | def leafModule(d):
set(getModuleFromObject(d) for d in config.callbacks) | return getModuleFromObject(d).split('::')[-1]
set(getModuleFromObject(d) for d in config.getDictionaries()))
descriptors = config.getDescriptors(register=True)
descriptors = (set(d.name + "Binding" for d in descriptors) |
set(leafModule(d) for d in config.callbacks) |
set(leafModule(d) for d in config.getDictionaries()))
curr = CGList([CGGeneric("pub mod %s;\n" % name) for name in sorted(descriptors)]) curr = CGList([CGGeneric("pub mod %s;\n" % name) for name in sorted(descriptors)])
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
return curr return curr

View file

@ -4,7 +4,7 @@
import os import os
from WebIDL import IDLExternalInterface, IDLInterface, WebIDLError from WebIDL import IDLExternalInterface, IDLInterface, IDLWrapperType, WebIDLError
class Configuration: class Configuration:
@ -183,7 +183,8 @@ class Descriptor(DescriptorProvider):
# built-in rooting mechanisms for them. # built-in rooting mechanisms for them.
if self.interface.isCallback(): if self.interface.isCallback():
self.needsRooting = False self.needsRooting = False
ty = "%sBinding::%s" % (ifaceName, ifaceName) ty = 'dom::bindings::codegen::Bindings::%sBinding::%s' % (ifaceName, ifaceName)
pathDefault = ty
self.returnType = "Rc<%s>" % ty self.returnType = "Rc<%s>" % ty
self.argumentType = "???" self.argumentType = "???"
self.nativeType = ty self.nativeType = ty
@ -192,10 +193,12 @@ class Descriptor(DescriptorProvider):
self.returnType = "Root<%s>" % typeName self.returnType = "Root<%s>" % typeName
self.argumentType = "&%s" % typeName self.argumentType = "&%s" % typeName
self.nativeType = "*const %s" % typeName self.nativeType = "*const %s" % typeName
pathDefault = 'dom::types::%s' % typeName
self.concreteType = typeName self.concreteType = typeName
self.register = desc.get('register', True) self.register = desc.get('register', True)
self.path = desc.get('path', 'dom::types::%s' % typeName) self.path = desc.get('path', pathDefault)
self.bindingPath = 'dom::bindings::codegen::Bindings::%s' % ('::'.join([ifaceName + 'Binding'] * 2))
self.outerObjectHook = desc.get('outerObjectHook', 'None') self.outerObjectHook = desc.get('outerObjectHook', 'None')
self.proxy = False self.proxy = False
self.weakReferenceable = desc.get('weakReferenceable', False) self.weakReferenceable = desc.get('weakReferenceable', False)
@ -377,7 +380,8 @@ class Descriptor(DescriptorProvider):
# Some utility methods # Some utility methods
def getModuleFromObject(object): def getModuleFromObject(object):
return os.path.basename(object.location.filename()).split('.webidl')[0] + 'Binding' return ('dom::bindings::codegen::Bindings::' +
os.path.basename(object.location.filename()).split('.webidl')[0] + 'Binding')
def getTypesFromDescriptor(descriptor): def getTypesFromDescriptor(descriptor):
@ -404,6 +408,8 @@ def getTypesFromDictionary(dictionary):
""" """
Get all member types for this dictionary Get all member types for this dictionary
""" """
if isinstance(dictionary, IDLWrapperType):
dictionary = dictionary.inner
types = [] types = []
curDict = dictionary curDict = dictionary
while curDict: while curDict:

View file

@ -2170,7 +2170,7 @@ class IDLUnresolvedType(IDLType):
return typedefType.complete(scope) return typedefType.complete(scope)
elif obj.isCallback() and not obj.isInterface(): elif obj.isCallback() and not obj.isInterface():
assert self.name.name == obj.identifier.name assert self.name.name == obj.identifier.name
return IDLCallbackType(self.location, obj) return IDLCallbackType(obj.location, obj)
if self._promiseInnerType and not self._promiseInnerType.isComplete(): if self._promiseInnerType and not self._promiseInnerType.isComplete():
self._promiseInnerType = self._promiseInnerType.complete(scope) self._promiseInnerType = self._promiseInnerType.complete(scope)
@ -6534,7 +6534,7 @@ class Parser(Tokenizer):
type = IDLTypedefType(self.getLocation(p, 1), obj.innerType, type = IDLTypedefType(self.getLocation(p, 1), obj.innerType,
obj.identifier.name) obj.identifier.name)
elif obj.isCallback() and not obj.isInterface(): elif obj.isCallback() and not obj.isInterface():
type = IDLCallbackType(self.getLocation(p, 1), obj) type = IDLCallbackType(obj.location, obj)
else: else:
type = IDLWrapperType(self.getLocation(p, 1), p[1]) type = IDLWrapperType(self.getLocation(p, 1), p[1])
p[0] = self.handleModifiers(type, p[2]) p[0] = self.handleModifiers(type, p[2])

View file

@ -0,0 +1,22 @@
diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py
index da32340..81c52b7 100644
--- a/components/script/dom/bindings/codegen/parser/WebIDL.py
+++ b/components/script/dom/bindings/codegen/parser/WebIDL.py
@@ -2170,7 +2170,7 @@ class IDLUnresolvedType(IDLType):
return typedefType.complete(scope)
elif obj.isCallback() and not obj.isInterface():
assert self.name.name == obj.identifier.name
- return IDLCallbackType(self.location, obj)
+ return IDLCallbackType(obj.location, obj)
if self._promiseInnerType and not self._promiseInnerType.isComplete():
self._promiseInnerType = self._promiseInnerType.complete(scope)
@@ -6521,7 +6521,7 @@ class Parser(Tokenizer):
type = IDLTypedefType(self.getLocation(p, 1), obj.innerType,
obj.identifier.name)
elif obj.isCallback() and not obj.isInterface():
- type = IDLCallbackType(self.getLocation(p, 1), obj)
+ type = IDLCallbackType(obj.location, obj)
else:
type = IDLWrapperType(self.getLocation(p, 1), p[1])
p[0] = self.handleModifiers(type, p[2])

View file

@ -2,6 +2,7 @@ wget https://hg.mozilla.org/mozilla-central/raw-file/tip/dom/bindings/parser/Web
patch < abstract.patch patch < abstract.patch
patch < debug.patch patch < debug.patch
patch < pref-main-thread.patch patch < pref-main-thread.patch
patch < callback-location.patch
wget https://hg.mozilla.org/mozilla-central/archive/tip.tar.gz/dom/bindings/parser/tests/ -O tests.tar.gz wget https://hg.mozilla.org/mozilla-central/archive/tip.tar.gz/dom/bindings/parser/tests/ -O tests.tar.gz
rm -r tests rm -r tests