mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
Implement pair iterators in WebIDL interfaces.
This commit is contained in:
parent
34bb937aee
commit
812a761abf
9 changed files with 390 additions and 13 deletions
|
@ -30,6 +30,7 @@ from Configuration import (
|
|||
getTypesFromCallback,
|
||||
getTypesFromDescriptor,
|
||||
getTypesFromDictionary,
|
||||
iteratorNativeType
|
||||
)
|
||||
|
||||
AUTOGENERATED_WARNING_COMMENT = \
|
||||
|
@ -720,7 +721,9 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
raise TypeError("Can't handle array arguments yet")
|
||||
|
||||
if type.isSequence():
|
||||
innerInfo = getJSToNativeConversionInfo(innerSequenceType(type), descriptorProvider)
|
||||
innerInfo = getJSToNativeConversionInfo(innerSequenceType(type),
|
||||
descriptorProvider,
|
||||
isMember=isMember)
|
||||
declType = CGWrapper(innerInfo.declType, pre="Vec<", post=">")
|
||||
config = getConversionConfigForType(type, isEnforceRange, isClamp, treatNullAs)
|
||||
|
||||
|
@ -1839,6 +1842,9 @@ class CGImports(CGWrapper):
|
|||
if not d.interface.isCallback():
|
||||
types += [d.interface]
|
||||
|
||||
if d.interface.isIteratorInterface():
|
||||
types += [d.interface.iterableInterface]
|
||||
|
||||
members = d.interface.members + d.interface.namedConstructors
|
||||
constructor = d.interface.ctor()
|
||||
if constructor:
|
||||
|
@ -1945,7 +1951,7 @@ def DOMClass(descriptor):
|
|||
# padding.
|
||||
protoList.extend(['PrototypeList::ID::Last'] * (descriptor.config.maxProtoChainLength - len(protoList)))
|
||||
prototypeChainString = ', '.join(protoList)
|
||||
heapSizeOf = 'heap_size_of_raw_self_and_children::<%s>' % descriptor.interface.identifier.name
|
||||
heapSizeOf = 'heap_size_of_raw_self_and_children::<%s>' % descriptor.concreteType
|
||||
if descriptor.isGlobal():
|
||||
globals_ = camel_to_upper_snake(descriptor.name)
|
||||
else:
|
||||
|
@ -2519,7 +2525,7 @@ class CGIDLInterface(CGThing):
|
|||
|
||||
def define(self):
|
||||
interface = self.descriptor.interface
|
||||
name = self.descriptor.name
|
||||
name = self.descriptor.concreteType
|
||||
if (interface.getUserData("hasConcreteDescendant", False) or
|
||||
interface.getUserData("hasProxyDescendant", False)):
|
||||
depth = self.descriptor.prototypeDepth
|
||||
|
@ -3043,11 +3049,21 @@ class CGPerSignatureCall(CGThing):
|
|||
if self.isFallible():
|
||||
errorResult = " false"
|
||||
|
||||
cgThings.append(CGCallGenerator(
|
||||
errorResult,
|
||||
self.getArguments(), self.argsPre, returnType,
|
||||
self.extendedAttributes, descriptor, nativeMethodName,
|
||||
static))
|
||||
if idlNode.isMethod() and idlNode.isMaplikeOrSetlikeOrIterableMethod():
|
||||
if idlNode.maplikeOrSetlikeOrIterable.isMaplike() or \
|
||||
idlNode.maplikeOrSetlikeOrIterable.isSetlike():
|
||||
raise TypeError('Maplike/Setlike methods are not supported yet')
|
||||
else:
|
||||
cgThings.append(CGIterableMethodGenerator(descriptor,
|
||||
idlNode.maplikeOrSetlikeOrIterable,
|
||||
idlNode.identifier.name))
|
||||
else:
|
||||
cgThings.append(CGCallGenerator(
|
||||
errorResult,
|
||||
self.getArguments(), self.argsPre, returnType,
|
||||
self.extendedAttributes, descriptor, nativeMethodName,
|
||||
static))
|
||||
|
||||
self.cgRoot = CGList(cgThings, "\n")
|
||||
|
||||
def getArgs(self):
|
||||
|
@ -5084,6 +5100,7 @@ class CGInterfaceTrait(CGThing):
|
|||
def members():
|
||||
for m in descriptor.interface.members:
|
||||
if (m.isMethod() and not m.isStatic() and
|
||||
not m.isMaplikeOrSetlikeOrIterableMethod() and
|
||||
(not m.isIdentifierLess() or m.isStringifier())):
|
||||
name = CGSpecializedMethod.makeNativeName(descriptor, m)
|
||||
infallible = 'infallible' in descriptor.getExtendedAttributes(m)
|
||||
|
@ -5213,6 +5230,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
|
|||
'dom::bindings::interface::{ConstantSpec, NonNullJSNative}',
|
||||
'dom::bindings::interface::ConstantVal::{IntVal, UintVal}',
|
||||
'dom::bindings::interface::is_exposed_in',
|
||||
'dom::bindings::iterable::{IteratorType, Iterable}',
|
||||
'dom::bindings::js::{JS, Root, RootedReference}',
|
||||
'dom::bindings::js::{OptionalRootedReference}',
|
||||
'dom::bindings::reflector::{Reflectable}',
|
||||
|
@ -5352,7 +5370,7 @@ class CGDescriptor(CGThing):
|
|||
public=True))
|
||||
reexports.append(descriptor.name + 'Constants')
|
||||
|
||||
if descriptor.interface.hasInterfaceObject():
|
||||
if descriptor.interface.hasInterfaceObject() and descriptor.register:
|
||||
cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
|
||||
reexports.append('DefineDOMInterface')
|
||||
cgThings.append(CGConstructorEnabled(descriptor))
|
||||
|
@ -6360,6 +6378,53 @@ class CallbackSetter(CallbackMember):
|
|||
return None
|
||||
|
||||
|
||||
class CGIterableMethodGenerator(CGGeneric):
|
||||
"""
|
||||
Creates methods for iterable interfaces. Unwrapping/wrapping
|
||||
will be taken care of by the usual method generation machinery in
|
||||
CGMethodCall/CGPerSignatureCall. Functionality is filled in here instead of
|
||||
using CGCallGenerator.
|
||||
"""
|
||||
def __init__(self, descriptor, iterable, methodName):
|
||||
if methodName == "forEach":
|
||||
CGGeneric.__init__(self, fill(
|
||||
"""
|
||||
if !IsCallable(arg0) {
|
||||
throw_type_error(cx, "Argument 1 of ${ifaceName}.forEach is not callable.");
|
||||
return false;
|
||||
}
|
||||
rooted!(in(cx) let arg0 = ObjectValue(&*arg0));
|
||||
rooted!(in(cx) let mut call_arg1 = UndefinedValue());
|
||||
rooted!(in(cx) let mut call_arg2 = UndefinedValue());
|
||||
let mut call_args = vec![UndefinedValue(), UndefinedValue(), ObjectValue(&**_obj)];
|
||||
rooted!(in(cx) let mut ignoredReturnVal = UndefinedValue());
|
||||
for i in 0..(*this).get_iterable_length() {
|
||||
(*this).get_value_at_index(i).to_jsval(cx, call_arg1.handle_mut());
|
||||
(*this).get_key_at_index(i).to_jsval(cx, call_arg2.handle_mut());
|
||||
call_args[0] = call_arg1.handle().get();
|
||||
call_args[1] = call_arg2.handle().get();
|
||||
let call_args = HandleValueArray { length_: 3, elements_: call_args.as_ptr() };
|
||||
if !Call(cx, arg1, arg0.handle(), &call_args,
|
||||
ignoredReturnVal.handle_mut()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let result = ();
|
||||
""",
|
||||
ifaceName=descriptor.interface.identifier.name))
|
||||
return
|
||||
CGGeneric.__init__(self, fill(
|
||||
"""
|
||||
let result = ${iterClass}::new(&*this,
|
||||
IteratorType::${itrMethod},
|
||||
super::${ifaceName}IteratorBinding::Wrap);
|
||||
""",
|
||||
iterClass=iteratorNativeType(descriptor, True),
|
||||
ifaceName=descriptor.interface.identifier.name,
|
||||
itrMethod=methodName.title()))
|
||||
|
||||
|
||||
def camel_to_upper_snake(s):
|
||||
return "_".join(m.group(0).upper() for m in re.finditer("[A-Z][a-z]*", s))
|
||||
|
||||
|
@ -6458,7 +6523,9 @@ class GlobalGenRoots():
|
|||
|
||||
@staticmethod
|
||||
def InterfaceTypes(config):
|
||||
descriptors = [d.name for d in config.getDescriptors(register=True, isCallback=False)]
|
||||
descriptors = [d.name for d in config.getDescriptors(register=True,
|
||||
isCallback=False,
|
||||
isIteratorInterface=False)]
|
||||
curr = CGList([CGGeneric("pub use dom::%s::%s;\n" % (name.lower(), name)) for name in descriptors])
|
||||
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
|
||||
return curr
|
||||
|
@ -6469,7 +6536,7 @@ class GlobalGenRoots():
|
|||
def leafModule(d):
|
||||
return getModuleFromObject(d).split('::')[-1]
|
||||
|
||||
descriptors = config.getDescriptors(register=True)
|
||||
descriptors = config.getDescriptors(register=True, isIteratorInterface=False)
|
||||
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()))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue