Implement pair iterators in WebIDL interfaces.

This commit is contained in:
Josh Matthews 2016-07-28 18:41:30 -04:00
parent 34bb937aee
commit 812a761abf
9 changed files with 390 additions and 13 deletions

View file

@ -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()))