diff options
Diffstat (limited to 'components/script/dom/bindings/codegen')
7 files changed, 469 insertions, 261 deletions
diff --git a/components/script/dom/bindings/codegen/BindingGen.py b/components/script/dom/bindings/codegen/BindingGen.py index 408280dacfb..f4d4fcdae2a 100644 --- a/components/script/dom/bindings/codegen/BindingGen.py +++ b/components/script/dom/bindings/codegen/BindingGen.py @@ -1,16 +1,16 @@ # This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this file, -# You can obtain one at http://mozilla.org/MPL/2.0/. +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. import sys sys.path.append("./parser/") sys.path.append("./ply/") import os import cPickle -import WebIDL -from Configuration import * +from Configuration import Configuration from CodegenRust import CGBindingRoot, replaceFileIfChanged + def generate_binding_rs(config, outputprefix, webidlfile): """ |config| Is the configuration object. @@ -22,6 +22,7 @@ def generate_binding_rs(config, outputprefix, webidlfile): if replaceFileIfChanged(filename, root.define()): print "Generating binding implementation: %s" % (filename) + def main(): # Parse arguments. from optparse import OptionParser @@ -46,7 +47,7 @@ def main(): config = Configuration(configFile, parserData) # Generate the prototype classes. - generate_binding_rs(config, outputPrefix, webIDLFile); + generate_binding_rs(config, outputPrefix, webIDLFile) if __name__ == '__main__': main() diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 46be7290187..8b7b427f689 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -1,6 +1,6 @@ # This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this file, -# You can obtain one at http://mozilla.org/MPL/2.0/. +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. # Common codegen classes. @@ -30,26 +30,27 @@ TRACE_HOOK_NAME = '_trace' CONSTRUCT_HOOK_NAME = '_constructor' HASINSTANCE_HOOK_NAME = '_hasInstance' + def replaceFileIfChanged(filename, newContents): """ Read a copy of the old file, so that we don't touch it if it hasn't changed. Returns True if the file was updated, false otherwise. """ - #XXXjdm This doesn't play well with make right now. + # XXXjdm This doesn't play well with make right now. # Force the file to always be updated, or else changing CodegenRust.py # will cause many autogenerated bindings to be regenerated perpetually # until the result is actually different. - #oldFileContents = "" - #try: - # oldFile = open(filename, 'rb') - # oldFileContents = ''.join(oldFile.readlines()) - # oldFile.close() - #except: - # pass + # oldFileContents = "" + # try: + # oldFile = open(filename, 'rb') + # oldFileContents = ''.join(oldFile.readlines()) + # oldFile.close() + # except: + # pass - #if newContents == oldFileContents: - # return False + # if newContents == oldFileContents: + # return False f = open(filename, 'wb') f.write(newContents) @@ -57,11 +58,14 @@ def replaceFileIfChanged(filename, newContents): return True + def toStringBool(arg): return str(not not arg).lower() + def toBindingNamespace(arg): - return re.sub("((_workers)?$)", "Binding\\1", arg); + return re.sub("((_workers)?$)", "Binding\\1", arg) + def stripTrailingWhitespace(text): tail = '\n' if text.endswith('\n') else '' @@ -70,6 +74,7 @@ def stripTrailingWhitespace(text): lines[i] = lines[i].rstrip() return '\n'.join(lines) + tail + def MakeNativeName(name): return name[0].upper() + name[1:] @@ -96,7 +101,8 @@ numericTags = [ IDLType.Tags.int64, IDLType.Tags.uint64, IDLType.Tags.unrestricted_float, IDLType.Tags.float, IDLType.Tags.unrestricted_double, IDLType.Tags.double - ] +] + class CastableObjectUnwrapper(): """ @@ -150,6 +156,7 @@ def memoize(fn): grows without bound. """ cache = {} + @functools.wraps(fn) def wrapper(arg): retval = cache.get(arg) @@ -158,6 +165,7 @@ def memoize(fn): return retval return wrapper + @memoize def dedent(s): """ @@ -215,6 +223,7 @@ def compile_fill_template(template): t = re.sub(fill_multiline_substitution_re, replace, t) return (string.Template(t), argModList) + def fill(template, **args): """ Convenience function for filling in a multiline template. @@ -253,16 +262,17 @@ def fill(template, **args): return t.substitute(args) + class CGThing(): """ Abstract base class for things that spit out code. """ def __init__(self): - pass # Nothing for now + pass # Nothing for now def define(self): """Produce code for a Rust file.""" - assert(False) # Override me! + assert(False) # Override me! class CGNativePropertyHooks(CGThing): @@ -277,7 +287,8 @@ class CGNativePropertyHooks(CGThing): def define(self): parent = self.descriptor.interface.parent if parent: - parentHooks = "Some(&::dom::bindings::codegen::Bindings::%sBinding::sNativePropertyHooks)" % parent.identifier.name + parentHooks = ("Some(&::dom::bindings::codegen::Bindings::%sBinding::sNativePropertyHooks)" + % parent.identifier.name) else: parentHooks = "None" @@ -307,16 +318,16 @@ class CGMethodCall(CGThing): if len(arguments) == 0: return 0 requiredArgs = len(arguments) - while requiredArgs and arguments[requiredArgs-1].optional: + while requiredArgs and arguments[requiredArgs - 1].optional: requiredArgs -= 1 return requiredArgs - signatures = method.signatures() + def getPerSignatureCall(signature, argConversionStartsAt=0): signatureIndex = signatures.index(signature) return CGPerSignatureCall(signature[0], argsPre, signature[1], - nativeMethodName + '_'*signatureIndex, + nativeMethodName + '_' * signatureIndex, static, descriptor, method, argConversionStartsAt) @@ -328,7 +339,6 @@ class CGMethodCall(CGThing): self.cgRoot = CGList([getPerSignatureCall(signature)]) requiredArgs = requiredArgCount(signature) - if requiredArgs > 0: code = ( "if argc < %d {\n" @@ -366,10 +376,10 @@ class CGMethodCall(CGThing): # Doesn't matter which of the possible signatures we use, since # they all have the same types up to that point; just use # possibleSignatures[0] - caseBody = [ CGArgumentConverter(possibleSignatures[0][1][i], - i, "args", "argc", - descriptor) for i in - range(0, distinguishingIndex) ] + caseBody = [ + CGArgumentConverter(possibleSignatures[0][1][i], + i, "args", "argc", descriptor) + for i in range(0, distinguishingIndex)] # Select the right overload from our set. distinguishingArg = "args.get(%d)" % distinguishingIndex @@ -399,7 +409,7 @@ class CGMethodCall(CGThing): interfacesSigs = [ s for s in possibleSignatures if (s[1][distinguishingIndex].type.isObject() or - s[1][distinguishingIndex].type.isNonCallbackInterface()) ] + s[1][distinguishingIndex].type.isNonCallbackInterface())] # There might be more than one of these; we need to check # which ones we unwrap to. @@ -418,7 +428,7 @@ class CGMethodCall(CGThing): caseBody.append(CGGeneric("if %s.get().is_object() {" % (distinguishingArg))) for idx, sig in enumerate(interfacesSigs): - caseBody.append(CGIndenter(CGGeneric("loop {"))); + caseBody.append(CGIndenter(CGGeneric("loop {"))) type = sig[1][distinguishingIndex].type # The argument at index distinguishingIndex can't possibly @@ -438,13 +448,13 @@ class CGMethodCall(CGThing): needsRooting) # Indent by 4, since we need to indent further than our "do" statement - caseBody.append(CGIndenter(testCode, 4)); + caseBody.append(CGIndenter(testCode, 4)) # If we got this far, we know we unwrapped to the right # interface, so just do the call. Start conversion with # distinguishingIndex + 1, since we already converted # distinguishingIndex. caseBody.append(CGIndenter( - getPerSignatureCall(sig, distinguishingIndex + 1), 4)) + getPerSignatureCall(sig, distinguishingIndex + 1), 4)) caseBody.append(CGIndenter(CGGeneric("}"))) caseBody.append(CGGeneric("}")) @@ -507,31 +517,35 @@ class CGMethodCall(CGThing): argCountCases, CGGeneric("throw_type_error(cx, \"Not enough arguments to %s.\");\n" "return 0;" % methodName))) - #XXXjdm Avoid unreachable statement warnings - #overloadCGThings.append( - # CGGeneric('panic!("We have an always-returning default case");\n' - # 'return 0;')) + # XXXjdm Avoid unreachable statement warnings + # overloadCGThings.append( + # CGGeneric('panic!("We have an always-returning default case");\n' + # 'return 0;')) self.cgRoot = CGWrapper(CGList(overloadCGThings, "\n"), pre="\n") def define(self): return self.cgRoot.define() + class FakeCastableDescriptor(): def __init__(self, descriptor): self.nativeType = "*const %s" % descriptor.concreteType self.name = descriptor.name + class FakeInterface: def inheritanceDepth(self): return descriptor.interface.inheritanceDepth() self.interface = FakeInterface() + def dictionaryHasSequenceMember(dictionary): return (any(typeIsSequenceOrHasSequenceMember(m.type) for m in dictionary.members) or (dictionary.parent and dictionaryHasSequenceMember(dictionary.parent))) + def typeIsSequenceOrHasSequenceMember(type): if type.nullable(): type = type.inner @@ -547,6 +561,7 @@ def typeIsSequenceOrHasSequenceMember(type): type.flatMemberTypes) return False + def typeNeedsRooting(type, descriptorProvider): return (type.isGeckoInterface() and descriptorProvider.getDescriptor(type.unroll().inner.identifier.name).needsRooting) @@ -679,6 +694,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, ('throw_type_error(cx, "%s is not an object.");\n' '%s' % (firstCap(sourceDescription), exceptionCode))), post="\n") + def onFailureBadType(failureCode, typeName): return CGWrapper( CGGeneric( @@ -687,6 +703,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, '%s' % (firstCap(sourceDescription), typeName, exceptionCode))), post="\n") + def onFailureNotCallable(failureCode): return CGWrapper( CGGeneric( @@ -726,7 +743,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, "}") return templateBody - assert not (isEnforceRange and isClamp) # These are mutually exclusive + assert not (isEnforceRange and isClamp) # These are mutually exclusive if type.isArray(): raise TypeError("Can't handle array arguments yet") @@ -789,11 +806,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, else: unwrapFailureCode = failureCode - templateBody = str(CastableObjectUnwrapper( - descriptor, - "${val}", - unwrapFailureCode, - "value")) + templateBody = str( + CastableObjectUnwrapper(descriptor, "${val}", unwrapFailureCode, "value")) declType = CGGeneric(descriptorType) if type.nullable(): @@ -906,9 +920,9 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, " //XXXjdm need some range checks up in here.\n" " unsafe { mem::transmute(index) }\n" " },\n" - "}" % { "values" : enum + "Values::strings", - "exceptionCode" : exceptionCode, -"handleInvalidEnumValueCode" : handleInvalidEnumValueCode }) + "}" % {"values": enum + "Values::strings", + "exceptionCode": exceptionCode, + "handleInvalidEnumValueCode": handleInvalidEnumValueCode}) if defaultValue is not None: assert(defaultValue.type.tag() == IDLType.Tags.domstring) @@ -1041,7 +1055,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, if type.nullable(): declType = CGWrapper(declType, pre="Option<", post=">") - #XXXjdm support conversionBehavior here + # XXXjdm support conversionBehavior here template = ( "match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n" " Ok(v) => v,\n" @@ -1067,6 +1081,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, return handleOptional(template, declType, defaultStr) + def instantiateJSToNativeConversionTemplate(templateBody, replacements, declType, declName, needsRooting): """ @@ -1077,9 +1092,7 @@ def instantiateJSToNativeConversionTemplate(templateBody, replacements, """ result = CGList([], "\n") - conversion = CGGeneric( - string.Template(templateBody).substitute(replacements) - ) + conversion = CGGeneric(string.Template(templateBody).substitute(replacements)) if declType is not None: newDecl = [ @@ -1099,7 +1112,8 @@ def instantiateJSToNativeConversionTemplate(templateBody, replacements, # conversion. result.append(CGGeneric("")) - return result; + return result + def convertConstIDLValueToJSVal(value): if isinstance(value, IDLNullValue): @@ -1119,6 +1133,7 @@ def convertConstIDLValueToJSVal(value): return "DoubleVal(%s)" % (value.value) raise TypeError("Const value of unhandled type: " + value.type) + class CGArgumentConverter(CGThing): """ A class that takes an IDL argument object, its index in the @@ -1241,6 +1256,7 @@ def typeNeedsCx(type, retVal=False): return True return type.isAny() or type.isObject() + def typeRetValNeedsRooting(type): if type is None: return False @@ -1248,9 +1264,11 @@ def typeRetValNeedsRooting(type): type = type.inner return type.isGeckoInterface() and not type.isCallback() and not type.isCallbackInterface() + def memberIsCreator(member): return member.getExtendedAttribute("Creator") is not None + # Returns a CGThing containing the type of the return value. def getRetvalDeclarationForType(returnType, descriptorProvider): if returnType is None or returnType.isVoid(): @@ -1320,6 +1338,7 @@ def getRetvalDeclarationForType(returnType, descriptorProvider): raise TypeError("Don't know how to declare return value for %s" % returnType) + class PropertyDefiner: """ A common superclass for defining things on prototype objects. @@ -1375,11 +1394,15 @@ class PropertyDefiner: ",\n".join(specs) + "\n" + "];\n") % (name, specType)) + # The length of a method is the minimum of the lengths of the # argument lists of all its overloads. def methodLength(method): signatures = method.signatures() - return min(len([arg for arg in arguments if not arg.optional and not arg.variadic]) for (_, arguments) in signatures) + return min( + len([arg for arg in arguments if not arg.optional and not arg.variadic]) + for (_, arguments) in signatures) + class MethodDefiner(PropertyDefiner): """ @@ -1402,8 +1425,7 @@ class MethodDefiner(PropertyDefiner): self.regular = [{"name": m.identifier.name, "methodInfo": not m.isStatic(), "length": methodLength(m), - "flags": "JSPROP_ENUMERATE" } - for m in methods] + "flags": "JSPROP_ENUMERATE"} for m in methods] # FIXME Check for an existing iterator on the interface first. if any(m.isGetter() and m.isIndexed() for m in methods): @@ -1411,7 +1433,7 @@ class MethodDefiner(PropertyDefiner): "methodInfo": False, "selfHostedName": "ArrayValues", "length": 0, - "flags": "JSPROP_ENUMERATE" }) + "flags": "JSPROP_ENUMERATE"}) if not static: stringifier = descriptor.operations['Stringifier'] @@ -1423,7 +1445,6 @@ class MethodDefiner(PropertyDefiner): "flags": "JSPROP_ENUMERATE" }) - def generateArray(self, array, name): if len(array) == 0: return "" @@ -1446,17 +1467,30 @@ class MethodDefiner(PropertyDefiner): jitinfo = "0 as *const JSJitInfo" accessor = 'Some(%s)' % m.get("nativeName", m["name"]) if m["name"].startswith("@@"): - return ('(SymbolCode::%s as i32 + 1)' % m["name"][2:], accessor, jitinfo, m["length"], m["flags"], selfHostedName) + return ('(SymbolCode::%s as i32 + 1)' + % m["name"][2:], accessor, jitinfo, m["length"], m["flags"], selfHostedName) return (str_to_const_array(m["name"]), accessor, jitinfo, m["length"], m["flags"], selfHostedName) - return self.generatePrefableArray( array, name, - ' JSFunctionSpec { name: %s as *const u8 as *const libc::c_char, call: JSNativeWrapper {op: %s, info: %s}, nargs: %s, flags: %s as u16, selfHostedName: %s }', - ' JSFunctionSpec { name: 0 as *const i8, call: JSNativeWrapper { op: None, info: 0 as *const JSJitInfo }, nargs: 0, flags: 0, selfHostedName: 0 as *const i8 }', + ' JSFunctionSpec {\n' + ' name: %s as *const u8 as *const libc::c_char,\n' + ' call: JSNativeWrapper {op: %s, info: %s},\n' + ' nargs: %s,\n' + ' flags: %s as u16,\n' + ' selfHostedName: %s\n' + ' }', + ' JSFunctionSpec {\n' + ' name: 0 as *const i8,\n' + ' call: JSNativeWrapper { op: None, info: 0 as *const JSJitInfo },\n' + ' nargs: 0,\n' + ' flags: 0,\n' + ' selfHostedName: 0 as *const i8\n' + ' }', 'JSFunctionSpec', specData) + class AttrDefiner(PropertyDefiner): def __init__(self, descriptor, name, static): PropertyDefiner.__init__(self, descriptor, name) @@ -1487,8 +1521,8 @@ class AttrDefiner(PropertyDefiner): jitinfo = "&%s_getterinfo" % attr.identifier.name return ("JSNativeWrapper { op: Some(%(native)s), info: %(info)s }" - % {"info" : jitinfo, - "native" : accessor}) + % {"info": jitinfo, + "native": accessor}) def setter(attr): if attr.readonly and not attr.getExtendedAttribute("PutForwards"): @@ -1505,8 +1539,8 @@ class AttrDefiner(PropertyDefiner): jitinfo = "&%s_setterinfo" % attr.identifier.name return ("JSNativeWrapper { op: Some(%(native)s), info: %(info)s }" - % {"info" : jitinfo, - "native" : accessor}) + % {"info": jitinfo, + "native": accessor}) def specData(attr): return (str_to_const_array(attr.identifier.name), flags(attr), getter(attr), @@ -1514,11 +1548,22 @@ class AttrDefiner(PropertyDefiner): return self.generatePrefableArray( array, name, - ' JSPropertySpec { name: %s as *const u8 as *const libc::c_char, flags: ((%s) & 0xFF) as u8, getter: %s, setter: %s }', - ' JSPropertySpec { name: 0 as *const i8, flags: 0, getter: JSNativeWrapper { op: None, info: 0 as *const JSJitInfo }, setter: JSNativeWrapper { op: None, info: 0 as *const JSJitInfo } }', + ' JSPropertySpec {\n' + ' name: %s as *const u8 as *const libc::c_char,\n' + ' flags: ((%s) & 0xFF) as u8,\n' + ' getter: %s,\n' + ' setter: %s\n' + ' }', + ' JSPropertySpec {\n' + ' name: 0 as *const i8,\n' + ' flags: 0,\n' + ' getter: JSNativeWrapper { op: None, info: 0 as *const JSJitInfo },\n' + ' setter: JSNativeWrapper { op: None, info: 0 as *const JSJitInfo }\n' + ' }', 'JSPropertySpec', specData) + class ConstDefiner(PropertyDefiner): """ A class for definining constants on the interface object @@ -1547,6 +1592,8 @@ class ConstDefiner(PropertyDefiner): # don't want to indent empty lines. So only indent lines that have a # non-newline character on them. lineStartDetector = re.compile("^(?=[^\n])", re.MULTILINE) + + class CGIndenter(CGThing): """ A class that takes another CGThing and generates code that indents that @@ -1564,6 +1611,7 @@ class CGIndenter(CGThing): else: return defn + class CGWrapper(CGThing): """ Generic CGThing that wraps other CGThings with pre and post text. @@ -1584,6 +1632,7 @@ class CGWrapper(CGThing): defn.replace("\n", "\n" + (" " * len(self.pre)))) return self.pre + defn + self.post + class CGImports(CGWrapper): """ Generates the appropriate import/use statements. @@ -1674,6 +1723,7 @@ class CGImports(CGWrapper): basename = os.path.basename(decl.filename()) return basename.replace('.webidl', 'Binding.rs') + class CGIfWrapper(CGWrapper): def __init__(self, child, condition): pre = CGWrapper(CGGeneric(condition), pre="if ", post=" {\n", @@ -1681,10 +1731,12 @@ class CGIfWrapper(CGWrapper): CGWrapper.__init__(self, CGIndenter(child), pre=pre.define(), post="\n}") + class CGTemplatedType(CGWrapper): def __init__(self, templateName, child): CGWrapper.__init__(self, child, pre=templateName + "<", post=">") + class CGNamespace(CGWrapper): def __init__(self, namespace, child, public=False): pre = "%smod %s {\n" % ("pub " if public else "", namespace) @@ -1701,6 +1753,7 @@ class CGNamespace(CGWrapper): inner = CGNamespace.build(namespaces[1:], child, public=public) return CGNamespace(namespaces[0], inner, public=public) + def DOMClass(descriptor): protoList = ['PrototypeList::ID::' + proto for proto in descriptor.prototypeChain] # Pad out the list to the right length with ID::Count so we @@ -1715,6 +1768,7 @@ DOMClass { native_hooks: &sNativePropertyHooks, }""" % prototypeChainString + class CGDOMJSClass(CGThing): """ Generate a DOMJSClass for a given descriptor @@ -1736,7 +1790,9 @@ class CGDOMJSClass(CGThing): static Class: DOMJSClass = DOMJSClass { base: js::jsapi::Class { name: %s as *const u8 as *const libc::c_char, - flags: JSCLASS_IS_DOMJSCLASS | JSCLASS_IMPLEMENTS_BARRIERS | %s | (((%s) & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT), //JSCLASS_HAS_RESERVED_SLOTS(%s), + flags: JSCLASS_IS_DOMJSCLASS | JSCLASS_IMPLEMENTS_BARRIERS | %s | + (((%s) & JSCLASS_RESERVED_SLOTS_MASK) << + JSCLASS_RESERVED_SLOTS_SHIFT), //JSCLASS_HAS_RESERVED_SLOTS(%s), addProperty: None, delProperty: None, getProperty: None, @@ -1785,17 +1841,18 @@ static Class: DOMJSClass = DOMJSClass { }, }, dom_class: %s -}; -""" % (str_to_const_array(self.descriptor.interface.identifier.name), - flags, slots, slots, - FINALIZE_HOOK_NAME, traceHook, - self.descriptor.outerObjectHook, - self.descriptor.outerObjectHook, - CGGeneric(DOMClass(self.descriptor)).define()) +};""" % (str_to_const_array(self.descriptor.interface.identifier.name), + flags, slots, slots, + FINALIZE_HOOK_NAME, traceHook, + self.descriptor.outerObjectHook, + self.descriptor.outerObjectHook, + CGGeneric(DOMClass(self.descriptor)).define()) + def str_to_const_array(s): return "b\"%s\\0\"" % s + class CGPrototypeJSClass(CGThing): def __init__(self, descriptor): CGThing.__init__(self) @@ -1822,6 +1879,7 @@ static PrototypeClass: JSClass = JSClass { }; """ % str_to_const_array(self.descriptor.interface.identifier.name + "Prototype") + class CGInterfaceObjectJSClass(CGThing): def __init__(self, descriptor): CGThing.__init__(self) @@ -1852,6 +1910,7 @@ const InterfaceObjectClass: JSClass = { }; """ % (str_to_const_array("Function"), ctorname, hasinstance, ctorname) + class CGList(CGThing): """ Generate code for a list of GCThings. Just concatenates them together, with @@ -1861,10 +1920,13 @@ class CGList(CGThing): CGThing.__init__(self) self.children = children self.joiner = joiner + def append(self, child): self.children.append(child) + def prepend(self, child): self.children.insert(0, child) + def join(self, generator): return self.joiner.join(filter(lambda s: len(s) > 0, (child for child in generator))) @@ -1874,8 +1936,8 @@ class CGList(CGThing): class CGIfElseWrapper(CGList): def __init__(self, condition, ifTrue, ifFalse): - kids = [ CGIfWrapper(ifTrue, condition), - CGWrapper(CGIndenter(ifFalse), pre=" else {\n", post="\n}") ] + kids = [CGIfWrapper(ifTrue, condition), + CGWrapper(CGIndenter(ifFalse), pre=" else {\n", post="\n}")] CGList.__init__(self, kids) @@ -1890,6 +1952,7 @@ class CGGeneric(CGThing): def define(self): return self.text + class CGCallbackTempRoot(CGGeneric): def __init__(self, name): CGGeneric.__init__(self, "%s::new(${val}.get().to_object())" % name) @@ -1912,12 +1975,14 @@ def getAllTypes(descriptors, dictionaries, callbacks): for t in getTypesFromCallback(callback): yield (t, None, None) + def SortedTuples(l): """ Sort a list of tuples based on the first item in the tuple """ return sorted(l, key=operator.itemgetter(0)) + def SortedDictValues(d): """ Returns a list of values from the dict sorted by key. @@ -1927,6 +1992,7 @@ def SortedDictValues(d): # We're only interested in the values. return (i[1] for i in d) + def UnionTypes(descriptors, dictionaries, callbacks, config): """ Returns a CGList containing CGUnionStructs for every union. @@ -1956,7 +2022,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, config): if not t.isUnion(): continue name = str(t) - if not name in unionStructs: + if name not in unionStructs: provider = descriptor or config.getDescriptorProvider() unionStructs[name] = CGList([ CGUnionStruct(t, provider), @@ -1975,15 +2041,18 @@ class Argument(): self.name = name self.default = default self.mutable = mutable + def declare(self): string = ('mut ' if self.mutable else '') + self.name + ((': ' + self.argType) if self.argType else '') - #XXXjdm Support default arguments somehow :/ - #if self.default is not None: - # string += " = " + self.default + # XXXjdm Support default arguments somehow :/ + # if self.default is not None: + # string += " = " + self.default return string + def define(self): return self.argType + ' ' + self.name + class CGAbstractMethod(CGThing): """ An abstract class for generating code for a method. Subclasses @@ -2007,7 +2076,9 @@ class CGAbstractMethod(CGThing): template arguments, and the function will be templatized using those arguments. """ - def __init__(self, descriptor, name, returnType, args, inline=False, alwaysInline=False, extern=False, pub=False, templateArgs=None, unsafe=True): + def __init__(self, descriptor, name, returnType, args, inline=False, + alwaysInline=False, extern=False, pub=False, templateArgs=None, + unsafe=True): CGThing.__init__(self) self.descriptor = descriptor self.name = name @@ -2016,10 +2087,12 @@ class CGAbstractMethod(CGThing): self.alwaysInline = alwaysInline self.extern = extern self.templateArgs = templateArgs - self.pub = pub; + self.pub = pub self.unsafe = unsafe + def _argstring(self): return ', '.join([a.declare() for a in self.args]) + def _template(self): if self.templateArgs is None: return '' @@ -2055,11 +2128,14 @@ class CGAbstractMethod(CGThing): def definition_prologue(self): return "%sfn %s%s(%s)%s {\n" % (self._decorators(), self.name, self._template(), - self._argstring(), self._returnType()) + self._argstring(), self._returnType()) + def definition_epilogue(self): return "\n}\n" + def definition_body(self): - assert(False) # Override me! + assert(False) # Override me! + def CreateBindingJSObject(descriptor, parent=None): create = "let mut raw = Box::into_raw(object);\nlet _rt = RootedTraceable::new(&*raw);\n" @@ -2080,11 +2156,18 @@ let obj = RootedObject::new(cx, obj);\ """ % (descriptor.name, parent) else: if descriptor.isGlobal(): - create += "let obj = RootedObject::new(cx, create_dom_global(cx, &Class.base as *const js::jsapi::Class as *const JSClass, Some(%s)));\n" % TRACE_HOOK_NAME + create += ("let obj = RootedObject::new(\n" + " cx,\n" + " create_dom_global(\n" + " cx,\n" + " &Class.base as *const js::jsapi::Class as *const JSClass,\n" + " Some(%s))\n" + ");\n" % TRACE_HOOK_NAME) else: create += ("let obj = {\n" " let _ac = JSAutoCompartment::new(cx, proto.ptr);\n" - " JS_NewObjectWithGivenProto(cx, &Class.base as *const js::jsapi::Class as *const JSClass, proto.handle())\n" + " JS_NewObjectWithGivenProto(\n" + " cx, &Class.base as *const js::jsapi::Class as *const JSClass, proto.handle())\n" "};\n" "let obj = RootedObject::new(cx, obj);\n") create += """\ @@ -2094,6 +2177,7 @@ JS_SetReservedSlot(obj.ptr, DOM_OBJECT_SLOT, PrivateValue(raw as *const libc::c_void));""" return create + class CGWrapMethod(CGAbstractMethod): """ Class that generates the FooBinding::Wrap function for non-callback @@ -2183,6 +2267,7 @@ class CGAbstractExternMethod(CGAbstractMethod): CGAbstractMethod.__init__(self, descriptor, name, returnType, args, inline=False, extern=True) + class PropertyArrays(): def __init__(self, descriptor): self.static_methods = MethodDefiner(descriptor, "StaticMethods", @@ -2203,6 +2288,7 @@ class PropertyArrays(): for array in self.arrayNames(): names[array] = getattr(self, array).variableName() return names + def __str__(self): define = "" for array in self.arrayNames(): @@ -2246,6 +2332,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod): Argument('MutableHandleObject', 'rval')] CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args) self.properties = properties + def definition_body(self): protoChain = self.descriptor.prototypeChain if len(protoChain) == 1: @@ -2297,7 +2384,7 @@ do_create_interface_objects(cx, receiver, parent_proto.handle(), let named_constructors: [(NonNullJSNative, &'static str, u32); %d] = [ """ % len(self.descriptor.interface.namedConstructors) for ctor in self.descriptor.interface.namedConstructors: - constructHook = CONSTRUCT_HOOK_NAME + "_" + ctor.identifier.name; + constructHook = CONSTRUCT_HOOK_NAME + "_" + ctor.identifier.name constructArgs = methodLength(ctor) constructor = '(%s as NonNullJSNative, "%s", %d)' % ( constructHook, ctor.identifier.name, constructArgs) @@ -2311,6 +2398,7 @@ let named_constructors: [(NonNullJSNative, &'static str, u32); %d] = [ CGGeneric(call % self.properties.variableNames()) ], "\n") + class CGGetPerInterfaceObject(CGAbstractMethod): """ A method for getting a per-interface object (a prototype object or interface @@ -2323,6 +2411,7 @@ class CGGetPerInterfaceObject(CGAbstractMethod): CGAbstractMethod.__init__(self, descriptor, name, 'void', args, pub=pub) self.id = idPrefix + "ID::" + self.descriptor.name + def definition_body(self): return CGGeneric(""" @@ -2349,6 +2438,7 @@ if <*mut JSObject>::needs_post_barrier(rval.get()) { } """ % (self.id, self.id, self.id)) + class CGGetProtoObjectMethod(CGGetPerInterfaceObject): """ A method for getting the interface prototype object. @@ -2356,6 +2446,7 @@ class CGGetProtoObjectMethod(CGGetPerInterfaceObject): def __init__(self, descriptor): CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObject", "PrototypeList::", pub=True) + def definition_body(self): return CGList([ CGGeneric("""\ @@ -2364,6 +2455,7 @@ class CGGetProtoObjectMethod(CGGetPerInterfaceObject): CGGetPerInterfaceObject.definition_body(self), ]) + class CGGetConstructorObjectMethod(CGGetPerInterfaceObject): """ A method for getting the interface constructor object. @@ -2371,6 +2463,7 @@ class CGGetConstructorObjectMethod(CGGetPerInterfaceObject): def __init__(self, descriptor): CGGetPerInterfaceObject.__init__(self, descriptor, "GetConstructorObject", "constructors::") + def definition_body(self): return CGList([ CGGeneric("""\ @@ -2433,8 +2526,7 @@ let traps = ProxyTraps { }; CreateProxyHandler(&traps, &Class as *const _ as *const _)\ -""" % (customDefineProperty, customDelete, TRACE_HOOK_NAME, - FINALIZE_HOOK_NAME) +""" % (customDefineProperty, customDelete, TRACE_HOOK_NAME, FINALIZE_HOOK_NAME) return CGGeneric(body) @@ -2468,11 +2560,13 @@ assert!(!proto.ptr.is_null()); """ return CGGeneric("assert!(!global.get().is_null());\n" + code) + def needCx(returnType, arguments, considerTypes): return (considerTypes and (typeNeedsCx(returnType, True) or any(typeNeedsCx(a.type) for a in arguments))) + class CGCallGenerator(CGThing): """ A class to generate an actual call to a C++ object. Assumes that the C++ @@ -2496,14 +2590,14 @@ class CGCallGenerator(CGThing): args = CGList([CGGeneric(arg) for arg in argsPre], ", ") for (a, name) in arguments: - #XXXjdm Perhaps we should pass all nontrivial types by borrowed pointer + # XXXjdm Perhaps we should pass all nontrivial types by borrowed pointer if a.type.isDictionary(): name = "&" + name args.append(CGGeneric(name)) needsCx = needCx(returnType, (a for (a, _) in arguments), True) - if not "cx" in argsPre and needsCx: + if "cx" not in argsPre and needsCx: args.prepend(CGGeneric("cx")) # Build up our actual call @@ -2543,10 +2637,12 @@ class CGCallGenerator(CGThing): def define(self): return self.cgRoot.define() + class MethodNotCreatorError(Exception): def __init__(self, typename): self.typename = typename + class CGPerSignatureCall(CGThing): """ This class handles the guts of generating code for a particular @@ -2594,16 +2690,18 @@ class CGPerSignatureCall(CGThing): errorResult = " JSFalse" cgThings.append(CGCallGenerator( - errorResult, - self.getArguments(), self.argsPre, returnType, - self.extendedAttributes, descriptor, nativeMethodName, - static)) + errorResult, + self.getArguments(), self.argsPre, returnType, + self.extendedAttributes, descriptor, nativeMethodName, + static)) self.cgRoot = CGList(cgThings, "\n") def getArgs(self): return "args" if self.argCount > 0 else "" + def getArgc(self): return "argc" + def getArguments(self): def process(arg, i): argVal = "arg" + str(i) @@ -2613,7 +2711,7 @@ class CGPerSignatureCall(CGThing): return [(a, process(a, i)) for (i, a) in enumerate(self.arguments)] def isFallible(self): - return not 'infallible' in self.extendedAttributes + return 'infallible' not in self.extendedAttributes def wrap_return_value(self): return wrapForType('args.rval()') @@ -2621,6 +2719,7 @@ class CGPerSignatureCall(CGThing): def define(self): return (self.cgRoot.define() + "\n" + self.wrap_return_value()) + class CGSwitch(CGList): """ A class to generate code for a switch statement. @@ -2634,7 +2733,7 @@ class CGSwitch(CGList): def __init__(self, expression, cases, default=None): CGList.__init__(self, [CGIndenter(c) for c in cases], "\n") self.prepend(CGWrapper(CGGeneric(expression), - pre="match ", post=" {")); + pre="match ", post=" {")) if default is not None: self.append( CGIndenter( @@ -2642,12 +2741,13 @@ class CGSwitch(CGList): CGIndenter(default), pre="_ => {\n", post="\n}" - ) ) ) + ) self.append(CGGeneric("}")) + class CGCase(CGList): """ A class to generate code for a case statement. @@ -2662,10 +2762,11 @@ class CGCase(CGList): bodyList = CGList([body], "\n") if fallThrough: raise TypeError("fall through required but unsupported") - #bodyList.append(CGGeneric('panic!("fall through unsupported"); /* Fall through */')) - self.append(CGIndenter(bodyList)); + # bodyList.append(CGGeneric('panic!("fall through unsupported"); /* Fall through */')) + self.append(CGIndenter(bodyList)) self.append(CGGeneric("}")) + class CGGetterCall(CGPerSignatureCall): """ A class to generate a native object getter call for a particular IDL @@ -2676,6 +2777,7 @@ class CGGetterCall(CGPerSignatureCall): nativeMethodName, attr.isStatic(), descriptor, attr, getter=True) + class FakeArgument(): """ A class that quacks like an IDLArgument. This is used to make @@ -2694,6 +2796,7 @@ class FakeArgument(): def allowTreatNonCallableAsNull(self): return self._allowTreatNonObjectAsNull + class CGSetterCall(CGPerSignatureCall): """ A class to generate a native object setter call for a particular IDL @@ -2704,15 +2807,19 @@ class CGSetterCall(CGPerSignatureCall): [FakeArgument(argType, attr, allowTreatNonObjectAsNull=True)], nativeMethodName, attr.isStatic(), descriptor, attr, setter=True) + def wrap_return_value(self): # We have no return value return "\nreturn 1;" + def getArgc(self): return "1" + def getArgvDecl(self): # We just get our stuff from our last arg no matter what return "" + class CGAbstractStaticBindingMethod(CGAbstractMethod): """ Common class to generate the JSNatives for all our static methods, getters @@ -2738,6 +2845,7 @@ let global = global_object_for_js_object(JS_CALLEE(cx, vp).to_object()); def generate_code(self): assert False # Override me + class CGSpecializedMethod(CGAbstractExternMethod): """ A class for generating the C++ code for a specialized method that the JIT @@ -2765,6 +2873,7 @@ class CGSpecializedMethod(CGAbstractExternMethod): name = method.identifier.name return MakeNativeName(descriptor.binaryNameFor(name)) + class CGStaticMethod(CGAbstractStaticBindingMethod): """ A class for generating the Rust code for an IDL static method. @@ -2781,6 +2890,7 @@ class CGStaticMethod(CGAbstractStaticBindingMethod): call = CGMethodCall(["global.r()"], nativeName, True, self.descriptor, self.method) return CGList([setupArgs, call]) + class CGSpecializedGetter(CGAbstractExternMethod): """ A class for generating the code for a specialized attribute getter @@ -2789,10 +2899,10 @@ class CGSpecializedGetter(CGAbstractExternMethod): def __init__(self, descriptor, attr): self.attr = attr name = 'get_' + attr.identifier.name - args = [ Argument('*mut JSContext', 'cx'), - Argument('HandleObject', '_obj'), - Argument('*const %s' % descriptor.concreteType, 'this'), - Argument('JSJitGetterCallArgs', 'args') ] + args = [Argument('*mut JSContext', 'cx'), + Argument('HandleObject', '_obj'), + Argument('*const %s' % descriptor.concreteType, 'this'), + Argument('JSJitGetterCallArgs', 'args')] CGAbstractExternMethod.__init__(self, descriptor, name, "u8", args) def definition_body(self): @@ -2832,6 +2942,7 @@ class CGStaticGetter(CGAbstractStaticBindingMethod): self.attr) return CGList([setupArgs, call]) + class CGSpecializedSetter(CGAbstractExternMethod): """ A class for generating the code for a specialized attribute setter @@ -2840,10 +2951,10 @@ class CGSpecializedSetter(CGAbstractExternMethod): def __init__(self, descriptor, attr): self.attr = attr name = 'set_' + attr.identifier.name - args = [ Argument('*mut JSContext', 'cx'), - Argument('HandleObject', 'obj'), - Argument('*const %s' % descriptor.concreteType, 'this'), - Argument('JSJitSetterCallArgs', 'args')] + args = [Argument('*mut JSContext', 'cx'), + Argument('HandleObject', 'obj'), + Argument('*const %s' % descriptor.concreteType, 'this'), + Argument('JSJitSetterCallArgs', 'args')] CGAbstractExternMethod.__init__(self, descriptor, name, "u8", args) def definition_body(self): @@ -2881,6 +2992,7 @@ class CGStaticSetter(CGAbstractStaticBindingMethod): self.attr) return CGList([checkForArg, call]) + class CGSpecializedForwardingSetter(CGSpecializedSetter): """ A class for generating the code for an IDL attribute forwarding setter. @@ -2907,6 +3019,7 @@ let target_obj = RootedObject::new(cx, v.ptr.to_object()); JS_SetProperty(cx, target_obj.handle(), %s as *const u8 as *const i8, args.get(0)) """ % (str_to_const_array(attrName), attrName, str_to_const_array(forwardToAttrName))) + class CGMemberJITInfo(CGThing): """ A class for generating the JITInfo for a property that points to @@ -2979,7 +3092,7 @@ class CGMemberJITInfo(CGThing): if self.member.slotIndex is not None: assert isAlwaysInSlot or self.member.getExtendedAttribute("Cached") isLazilyCachedInSlot = not isAlwaysInSlot - slotIndex = memberReservedSlot(self.member) + slotIndex = memberReservedSlot(self.member) # noqa:FIXME: memberReservedSlot is not defined # We'll statically assert that this is not too big in # CGUpdateMemberSlotsMethod, in the case when # isAlwaysInSlot is true. @@ -2992,8 +3105,7 @@ class CGMemberJITInfo(CGThing): isAlwaysInSlot, isLazilyCachedInSlot, slotIndex, [self.member.type], None) - if (not self.member.readonly or - self.member.getExtendedAttribute("PutForwards")): + if (not self.member.readonly or self.member.getExtendedAttribute("PutForwards")): setterinfo = ("%s_setterinfo" % self.member.identifier.name) setter = ("set_%s" % self.member.identifier.name) # Setters are always fallible, since they have to do a typed unwrap. @@ -3163,6 +3275,7 @@ class CGMemberJITInfo(CGThing): # Different types return "JSVAL_TYPE_UNKNOWN" + def getEnumValueName(value): # Some enum values can be empty strings. Others might have weird # characters in them. Deal with the former by returning "_empty", @@ -3183,6 +3296,7 @@ def getEnumValueName(value): return "_empty" return MakeNativeName(value) + class CGEnum(CGThing): def __init__(self, enum): CGThing.__init__(self) @@ -3236,6 +3350,7 @@ def convertConstIDLValueToRust(value): raise TypeError("Const value of unhandled type: " + value.type) + class CGConstant(CGThing): def __init__(self, constants): CGThing.__init__(self) @@ -3249,6 +3364,7 @@ class CGConstant(CGThing): return CGIndenter(CGList(stringDecl(m) for m in self.constants)).define() + def getUnionTypeTemplateVars(type, descriptorProvider): # For dictionaries and sequences we need to pass None as the failureCode # for getJSToNativeConversionInfo. @@ -3265,7 +3381,7 @@ def getUnionTypeTemplateVars(type, descriptorProvider): typeName = name elif type.isArray() or type.isSequence(): name = str(type) - #XXXjdm dunno about typeName here + # XXXjdm dunno about typeName here typeName = "/*" + type.name + "*/" elif type.isDOMString(): name = type.name @@ -3295,6 +3411,7 @@ def getUnionTypeTemplateVars(type, descriptorProvider): "jsConversion": jsConversion, } + class CGUnionStruct(CGThing): def __init__(self, type, descriptorProvider): assert not type.nullable() @@ -3311,7 +3428,8 @@ class CGUnionStruct(CGThing): " e%s(%s)," % (v["name"], v["typeName"]) for v in templateVars ] enumConversions = [ - " %s::e%s(ref inner) => inner.to_jsval(cx, rval)," % (self.type, v["name"]) for v in templateVars + " %s::e%s(ref inner) => inner.to_jsval(cx, rval)," + % (self.type, v["name"]) for v in templateVars ] # XXXManishearth The following should be #[must_root], # however we currently allow it till #2661 is fixed @@ -3328,8 +3446,7 @@ impl ToJSValConvertible for %s { } } } -""") % (self.type, "\n".join(enumValues), - self.type, "\n".join(enumConversions)) +""") % (self.type, "\n".join(enumValues), self.type, "\n".join(enumConversions)) class CGUnionConversionStruct(CGThing): @@ -3424,11 +3541,11 @@ class CGUnionConversionStruct(CGThing): else: name = memberType.name match = ( - "match %s::TryConvertTo%s(cx, value) {\n" - " Err(_) => return Err(()),\n" - " Ok(Some(value)) => return Ok(%s::e%s(value)),\n" - " Ok(None) => (),\n" - "}\n") % (self.type, name, self.type, name) + "match %s::TryConvertTo%s(cx, value) {\n" + " Err(_) => return Err(()),\n" + " Ok(Some(value)) => return Ok(%s::e%s(value)),\n" + " Ok(None) => (),\n" + "}\n") % (self.type, name, self.type, name) conversions.append(CGGeneric(match)) names.append(name) @@ -3437,7 +3554,8 @@ class CGUnionConversionStruct(CGThing): "Err(())" % ", ".join(names))) method = CGWrapper( CGIndenter(CGList(conversions, "\n\n")), - pre="fn from_jsval(cx: *mut JSContext, value: HandleValue, _option: ()) -> Result<%s, ()> {\n" % self.type, + pre="fn from_jsval(cx: *mut JSContext,\n" + " value: HandleValue, _option: ()) -> Result<%s, ()> {\n" % self.type, post="\n}") return CGWrapper( CGIndenter(CGList([ @@ -3476,20 +3594,26 @@ class ClassItem: def __init__(self, name, visibility): self.name = name self.visibility = visibility + def declare(self, cgClass): assert False + def define(self, cgClass): assert False + class ClassBase(ClassItem): def __init__(self, name, visibility='pub'): ClassItem.__init__(self, name, visibility) + def declare(self, cgClass): return '%s %s' % (self.visibility, self.name) + def define(self, cgClass): # Only in the header return '' + class ClassMethod(ClassItem): def __init__(self, name, returnType, args, inline=False, static=False, virtual=False, const=False, bodyInHeader=False, @@ -3541,26 +3665,28 @@ class ClassMethod(ClassItem): body = CGIndenter(CGGeneric(self.getBody())).define() body = ' {\n' + body + '\n}' else: - body = ';' - - return string.Template("${decorators}%s" - "${visibility}fn ${name}${templateClause}(${args})${returnType}${const}${override}${body}%s" % - (self.breakAfterReturnDecl, self.breakAfterSelf) - ).substitute({ - 'templateClause': templateClause, - 'decorators': self.getDecorators(True), - 'returnType': (" -> %s" % self.returnType) if self.returnType else "", - 'name': self.name, - 'const': ' const' if self.const else '', - 'override': ' MOZ_OVERRIDE' if self.override else '', - 'args': args, - 'body': body, - 'visibility': self.visibility + ' ' if self.visibility is not 'priv' else '' - }) + body = ';' + + return string.Template( + "${decorators}%s" + "${visibility}fn ${name}${templateClause}(${args})${returnType}${const}${override}${body}%s" % + (self.breakAfterReturnDecl, self.breakAfterSelf) + ).substitute({ + 'templateClause': templateClause, + 'decorators': self.getDecorators(True), + 'returnType': (" -> %s" % self.returnType) if self.returnType else "", + 'name': self.name, + 'const': ' const' if self.const else '', + 'override': ' MOZ_OVERRIDE' if self.override else '', + 'args': args, + 'body': body, + 'visibility': self.visibility + ' ' if self.visibility is not 'priv' else '' + }) def define(self, cgClass): pass + class ClassUsingDeclaration(ClassItem): """" Used for importing a name from a base class into a CGClass @@ -3579,12 +3705,13 @@ class ClassUsingDeclaration(ClassItem): def declare(self, cgClass): return string.Template("""\ using ${baseClass}::${name}; -""").substitute({ 'baseClass': self.baseClass, - 'name': self.name }) +""").substitute({'baseClass': self.baseClass, + 'name': self.name}) def define(self, cgClass): return '' + class ClassConstructor(ClassItem): """ Used for adding a constructor to a CGClass. @@ -3655,7 +3782,7 @@ class ClassConstructor(ClassItem): def declare(self, cgClass): args = ', '.join([a.declare() for a in self.args]) - body = ' ' + self.getBody(cgClass); + body = ' ' + self.getBody(cgClass) body = stripTrailingWhitespace(body.replace('\n', '\n ')) if len(body) > 0: body += '\n' @@ -3663,10 +3790,10 @@ class ClassConstructor(ClassItem): return string.Template("""\ pub fn ${decorators}new(${args}) -> Rc<${className}>${body} -""").substitute({ 'decorators': self.getDecorators(True), - 'className': cgClass.getNameString(), - 'args': args, - 'body': body }) +""").substitute({'decorators': self.getDecorators(True), + 'className': cgClass.getNameString(), + 'args': args, + 'body': body}) def define(self, cgClass): if self.bodyInHeader: @@ -3683,11 +3810,12 @@ pub fn ${decorators}new(${args}) -> Rc<${className}>${body} ${decorators} ${className}::${className}(${args})${initializationList} {${body}} -""").substitute({ 'decorators': self.getDecorators(False), - 'className': cgClass.getNameString(), - 'args': args, - 'initializationList': self.getInitializationList(cgClass), - 'body': body }) +""").substitute({'decorators': self.getDecorators(False), + 'className': cgClass.getNameString(), + 'args': args, + 'initializationList': self.getInitializationList(cgClass), + 'body': body}) + class ClassDestructor(ClassItem): """ @@ -3728,7 +3856,7 @@ class ClassDestructor(ClassItem): def declare(self, cgClass): if self.bodyInHeader: - body = ' ' + self.getBody(); + body = ' ' + self.getBody() body = stripTrailingWhitespace(body.replace('\n', '\n ')) if len(body) > 0: body += '\n' @@ -3738,9 +3866,9 @@ class ClassDestructor(ClassItem): return string.Template("""\ ${decorators}~${className}()${body} -""").substitute({ 'decorators': self.getDecorators(True), - 'className': cgClass.getNameString(), - 'body': body }) +""").substitute({'decorators': self.getDecorators(True), + 'className': cgClass.getNameString(), + 'body': body}) def define(self, cgClass): if self.bodyInHeader: @@ -3755,14 +3883,15 @@ ${decorators}~${className}()${body} ${decorators} ${className}::~${className}() {${body}} -""").substitute({ 'decorators': self.getDecorators(False), - 'className': cgClass.getNameString(), - 'body': body }) +""").substitute({'decorators': self.getDecorators(False), + 'className': cgClass.getNameString(), + 'body': body}) + class ClassMember(ClassItem): def __init__(self, name, type, visibility="priv", static=False, body=None): - self.type = type; + self.type = type self.static = static self.body = body ClassItem.__init__(self, name, visibility) @@ -3778,7 +3907,8 @@ class ClassMember(ClassItem): else: body = "" return '%s %s::%s%s;\n' % (self.type, cgClass.getNameString(), - self.name, body) + self.name, body) + class ClassTypedef(ClassItem): def __init__(self, name, type, visibility="public"): @@ -3792,6 +3922,7 @@ class ClassTypedef(ClassItem): # Only goes in the header return '' + class ClassEnum(ClassItem): def __init__(self, name, entries, values=None, visibility="public"): self.entries = entries @@ -3813,6 +3944,7 @@ class ClassEnum(ClassItem): # Only goes in the header return '' + class ClassUnion(ClassItem): def __init__(self, name, entries, visibility="public"): self.entries = [entry + ";" for entry in entries] @@ -3825,10 +3957,11 @@ class ClassUnion(ClassItem): # Only goes in the header return '' + class CGClass(CGThing): def __init__(self, name, bases=[], members=[], constructors=[], destructor=None, methods=[], - typedefs = [], enums=[], unions=[], templateArgs=[], + typedefs=[], enums=[], unions=[], templateArgs=[], templateSpecialization=[], isStruct=False, disallowCopyConstruction=False, indent='', decorators='', @@ -3868,8 +4001,7 @@ class CGClass(CGThing): if self.templateArgs: templateArgs = [a.declare() for a in self.templateArgs] templateArgs = templateArgs[len(self.templateSpecialization):] - result = result + self.indent + 'template <%s>\n' \ - % ','.join([str(a) for a in templateArgs]) + result = result + self.indent + 'template <%s>\n' % ','.join([str(a) for a in templateArgs]) if self.templateSpecialization: specialization = \ @@ -3883,7 +4015,7 @@ class CGClass(CGThing): myself += '%spub struct %s%s' % (self.indent, self.name, specialization) result += myself - assert len(self.bases) == 1 #XXjdm Can we support multiple inheritance? + assert len(self.bases) == 1 # XXjdm Can we support multiple inheritance? result += ' {\n' @@ -3906,6 +4038,7 @@ class CGClass(CGThing): class DisallowedCopyConstructor(object): def __init__(self): self.visibility = "private" + def declare(self, cgClass): name = cgClass.getNameString() return ("%s(const %s&) MOZ_DELETE;\n" @@ -3939,6 +4072,7 @@ class CGClass(CGThing): result += "}" return result + class CGProxySpecialOperation(CGPerSignatureCall): """ Base class for classes for calling an indexed or named special operation @@ -3972,8 +4106,8 @@ class CGProxySpecialOperation(CGPerSignatureCall): "val": "value.handle()", } self.cgRoot.prepend(instantiateJSToNativeConversionTemplate( - template, templateValues, declType, argument.identifier.name, - needsRooting)) + template, templateValues, declType, argument.identifier.name, + needsRooting)) self.cgRoot.prepend(CGGeneric("let value = RootedValue::new(cx, desc.get().value);")) elif operation.isGetter(): self.cgRoot.prepend(CGGeneric("let mut found = false;")) @@ -3999,6 +4133,7 @@ class CGProxySpecialOperation(CGPerSignatureCall): wrap = CGIfWrapper(wrap, "found") return "\n" + wrap.define() + class CGProxyIndexedGetter(CGProxySpecialOperation): """ Class to generate a call to an indexed getter. If templateValues is not None @@ -4008,6 +4143,7 @@ class CGProxyIndexedGetter(CGProxySpecialOperation): self.templateValues = templateValues CGProxySpecialOperation.__init__(self, descriptor, 'IndexedGetter') + class CGProxyIndexedSetter(CGProxySpecialOperation): """ Class to generate a call to an indexed setter. @@ -4015,6 +4151,7 @@ class CGProxyIndexedSetter(CGProxySpecialOperation): def __init__(self, descriptor): CGProxySpecialOperation.__init__(self, descriptor, 'IndexedSetter') + class CGProxyNamedGetter(CGProxySpecialOperation): """ Class to generate a call to an named getter. If templateValues is not None @@ -4024,6 +4161,7 @@ class CGProxyNamedGetter(CGProxySpecialOperation): self.templateValues = templateValues CGProxySpecialOperation.__init__(self, descriptor, 'NamedGetter') + class CGProxyNamedPresenceChecker(CGProxyNamedGetter): """ Class to generate a call that checks whether a named property exists. @@ -4032,6 +4170,7 @@ class CGProxyNamedPresenceChecker(CGProxyNamedGetter): def __init__(self, descriptor): CGProxyNamedGetter.__init__(self, descriptor) + class CGProxyNamedSetter(CGProxySpecialOperation): """ Class to generate a call to a named setter. @@ -4039,6 +4178,7 @@ class CGProxyNamedSetter(CGProxySpecialOperation): def __init__(self, descriptor): CGProxySpecialOperation.__init__(self, descriptor, 'NamedSetter') + class CGProxyNamedDeleter(CGProxySpecialOperation): """ Class to generate a call to a named deleter. @@ -4050,7 +4190,8 @@ class CGProxyNamedDeleter(CGProxySpecialOperation): class CGProxyUnwrap(CGAbstractMethod): def __init__(self, descriptor): args = [Argument('HandleObject', 'obj')] - CGAbstractMethod.__init__(self, descriptor, "UnwrapProxy", '*const ' + descriptor.concreteType, args, alwaysInline=True) + CGAbstractMethod.__init__(self, descriptor, "UnwrapProxy", + '*const ' + descriptor.concreteType, args, alwaysInline=True) def definition_body(self): return CGGeneric("""\ @@ -4061,6 +4202,7 @@ class CGProxyUnwrap(CGAbstractMethod): let box_ = GetProxyPrivate(*obj.ptr).to_private() as *const %s; return box_;""" % self.descriptor.concreteType) + class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod): def __init__(self, descriptor): args = [Argument('*mut JSContext', 'cx'), Argument('HandleObject', 'proxy'), @@ -4069,6 +4211,7 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod): CGAbstractExternMethod.__init__(self, descriptor, "getOwnPropertyDescriptor", "u8", args) self.descriptor = descriptor + def getBody(self): indexedGetter = self.descriptor.operations['IndexedGetter'] indexedSetter = self.descriptor.operations['IndexedSetter'] @@ -4079,12 +4222,14 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod): if indexedGetter: readonly = toStringBool(self.descriptor.operations['IndexedSetter'] is None) - fillDescriptor = "desc.get().value = result_root.ptr;\nfill_property_descriptor(&mut *desc.ptr, *proxy.ptr, %s);\nreturn JSTrue;" % readonly + fillDescriptor = ("desc.get().value = result_root.ptr;\n" + "fill_property_descriptor(&mut *desc.ptr, *proxy.ptr, %s);\n" + "return JSTrue;" % readonly) templateValues = { 'jsvalRef': 'result_root.handle_mut()', 'successCode': fillDescriptor, 'pre': 'let mut result_root = RootedValue::new(cx, UndefinedValue());' - } + } get += ("if index.is_some() {\n" + " let index = index.unwrap();\n" + " let this = UnwrapProxy(proxy);\n" + @@ -4095,12 +4240,14 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod): namedGetter = self.descriptor.operations['NamedGetter'] if namedGetter: readonly = toStringBool(self.descriptor.operations['NamedSetter'] is None) - fillDescriptor = "desc.get().value = result_root.ptr;\nfill_property_descriptor(&mut *desc.ptr, *proxy.ptr, %s);\nreturn JSTrue;" % readonly + fillDescriptor = ("desc.get().value = result_root.ptr;\n" + "fill_property_descriptor(&mut *desc.ptr, *proxy.ptr, %s);\n" + "return JSTrue;" % readonly) templateValues = { 'jsvalRef': 'result_root.handle_mut()', 'successCode': fillDescriptor, 'pre': 'let mut result_root = RootedValue::new(cx, UndefinedValue());' - } + } # Once we start supporting OverrideBuiltins we need to make # ResolveOwnProperty or EnumerateOwnProperties filter out named # properties that shadow prototype properties. @@ -4134,6 +4281,7 @@ return JSTrue;""" def definition_body(self): return CGGeneric(self.getBody()) + # TODO(Issue 5876) class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod): def __init__(self, descriptor): @@ -4143,6 +4291,7 @@ class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod): Argument('*mut ObjectOpResult', 'opresult')] CGAbstractExternMethod.__init__(self, descriptor, "defineProperty", "u8", args) self.descriptor = descriptor + def getBody(self): set = "" @@ -4201,6 +4350,7 @@ class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod): def definition_body(self): return CGGeneric(self.getBody()) + class CGDOMJSProxyHandler_delete(CGAbstractExternMethod): def __init__(self, descriptor): args = [Argument('*mut JSContext', 'cx'), Argument('HandleObject', 'proxy'), @@ -4222,12 +4372,14 @@ class CGDOMJSProxyHandler_delete(CGAbstractExternMethod): def definition_body(self): return CGGeneric(self.getBody()) + class CGDOMJSProxyHandler_hasOwn(CGAbstractExternMethod): def __init__(self, descriptor): args = [Argument('*mut JSContext', 'cx'), Argument('HandleObject', 'proxy'), Argument('HandleId', 'id'), Argument('*mut u8', 'bp')] CGAbstractExternMethod.__init__(self, descriptor, "hasOwn", "u8", args) self.descriptor = descriptor + def getBody(self): indexedGetter = self.descriptor.operations['IndexedGetter'] if indexedGetter: @@ -4274,6 +4426,7 @@ return JSTrue;""" def definition_body(self): return CGGeneric(self.getBody()) + class CGDOMJSProxyHandler_get(CGAbstractExternMethod): def __init__(self, descriptor): args = [Argument('*mut JSContext', 'cx'), Argument('HandleObject', 'proxy'), @@ -4281,6 +4434,7 @@ class CGDOMJSProxyHandler_get(CGAbstractExternMethod): Argument('MutableHandleValue', 'vp')] CGAbstractExternMethod.__init__(self, descriptor, "get", "u8", args) self.descriptor = descriptor + def getBody(self): getFromExpando = """\ let expando = RootedObject::new(cx, get_expando_object(proxy)); @@ -4349,17 +4503,20 @@ return JSTrue;""" % (getIndexedOrExpando, getNamed) def definition_body(self): return CGGeneric(self.getBody()) + class CGDOMJSProxyHandler_className(CGAbstractExternMethod): def __init__(self, descriptor): args = [Argument('*mut JSContext', 'cx'), Argument('HandleObject', '_proxy')] CGAbstractExternMethod.__init__(self, descriptor, "className", "*const i8", args) self.descriptor = descriptor + def getBody(self): return '%s as *const u8 as *const i8' % str_to_const_array(self.descriptor.name) def definition_body(self): return CGGeneric(self.getBody()) + class CGAbstractClassHook(CGAbstractExternMethod): """ Meant for implementing JSClass hooks, like Finalize or Trace. Does very raw @@ -4384,6 +4541,7 @@ let this: *const %s = native_from_reflector::<%s>(obj); # Override me assert(False) + def finalizeHook(descriptor, hookName, context): release = "" if descriptor.isGlobal(): @@ -4396,6 +4554,7 @@ debug!("%s finalize: {:p}", this);\ """ % (descriptor.concreteType, descriptor.concreteType) return release + class CGClassTraceHook(CGAbstractClassHook): """ A hook to trace through our native object; used for GC and CC @@ -4413,6 +4572,7 @@ class CGClassTraceHook(CGAbstractClassHook): body += [CGGeneric("trace_global(trc, obj);")] return CGList(body, "\n") + class CGClassConstructHook(CGAbstractExternMethod): """ JS-visible constructor for our objects @@ -4439,6 +4599,7 @@ let args = CallArgs::from_vp(vp, argc); self.descriptor, self._ctor) return CGList([preamble, callGenerator]) + class CGClassNameConstructHook(CGAbstractExternMethod): """ JS-visible named constructor for our objects @@ -4448,7 +4609,7 @@ class CGClassNameConstructHook(CGAbstractExternMethod): self._ctor = ctor CGAbstractExternMethod.__init__(self, descriptor, CONSTRUCT_HOOK_NAME + "_" + - self._ctor.identifier.name, + self._ctor.identifier.name, 'u8', args) def definition_body(self): @@ -4475,6 +4636,7 @@ class CGClassFinalizeHook(CGAbstractClassHook): def generate_code(self): return CGGeneric(finalizeHook(self.descriptor, self.name, self.args[0].name)) + class CGDOMJSProxyHandlerDOMClass(CGThing): def __init__(self, descriptor): CGThing.__init__(self) @@ -4488,7 +4650,6 @@ class CGInterfaceTrait(CGThing): def __init__(self, descriptor): CGThing.__init__(self) - def attribute_arguments(needCx, argument=None): if needCx: yield "cx", "*mut JSContext" @@ -4496,11 +4657,10 @@ class CGInterfaceTrait(CGThing): if argument: yield "value", argument_type(descriptor, argument) - def members(): for m in descriptor.interface.members: if (m.isMethod() and not m.isStatic() and - (not m.isIdentifierLess() or m.isStringifier())): + (not m.isIdentifierLess() or m.isStringifier())): name = CGSpecializedMethod.makeNativeName(descriptor, m) infallible = 'infallible' in descriptor.getExtendedAttributes(m) for idx, (rettype, arguments) in enumerate(m.signatures()): @@ -4510,7 +4670,9 @@ class CGInterfaceTrait(CGThing): elif m.isAttr() and not m.isStatic(): name = CGSpecializedGetter.makeNativeName(descriptor, m) infallible = 'infallible' in descriptor.getExtendedAttributes(m, getter=True) - yield name, attribute_arguments(typeNeedsCx(m.type, True)), return_type(descriptor, m.type, infallible) + yield (name, + attribute_arguments(typeNeedsCx(m.type, True)), + return_type(descriptor, m.type, infallible)) if not m.readonly: name = CGSpecializedSetter.makeNativeName(descriptor, m) @@ -4571,7 +4733,7 @@ class CGDescriptor(CGThing): for m in descriptor.interface.members: if (m.isMethod() and - (not m.isIdentifierLess() or m == descriptor.operations["Stringifier"])): + (not m.isIdentifierLess() or m == descriptor.operations["Stringifier"])): if m.isStatic(): assert descriptor.interface.hasInterfaceObject() cgThings.append(CGStaticMethod(descriptor, m)) @@ -4599,8 +4761,7 @@ class CGDescriptor(CGThing): elif m.getExtendedAttribute("PutForwards"): cgThings.append(CGSpecializedForwardingSetter(descriptor, m)) - if (not m.isStatic() and - not descriptor.interface.isCallback()): + if (not m.isStatic() and not descriptor.interface.isCallback()): cgThings.append(CGMemberJITInfo(descriptor, m)) if descriptor.concrete: @@ -4634,7 +4795,7 @@ class CGDescriptor(CGThing): if descriptor.concrete: if descriptor.proxy: - #cgThings.append(CGProxyIsProxy(descriptor)) + # cgThings.append(CGProxyIsProxy(descriptor)) cgThings.append(CGProxyUnwrap(descriptor)) cgThings.append(CGDOMJSProxyHandlerDOMClass(descriptor)) cgThings.append(CGDOMJSProxyHandler_getOwnPropertyDescriptor(descriptor)) @@ -4651,8 +4812,8 @@ class CGDescriptor(CGThing): if descriptor.operations['NamedDeleter']: cgThings.append(CGDOMJSProxyHandler_delete(descriptor)) - #cgThings.append(CGDOMJSProxyHandler(descriptor)) - #cgThings.append(CGIsMethod(descriptor)) + # cgThings.append(CGDOMJSProxyHandler(descriptor)) + # cgThings.append(CGIsMethod(descriptor)) pass else: cgThings.append(CGDOMJSClass(descriptor)) @@ -4665,14 +4826,15 @@ class CGDescriptor(CGThing): cgThings.append(CGInterfaceTrait(descriptor)) cgThings = CGList(cgThings, "\n") - #self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name), - # cgThings), - # post='\n') + # self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name), + # cgThings), + # post='\n') self.cgRoot = cgThings def define(self): return self.cgRoot.define() + class CGNonNamespacedEnum(CGThing): def __init__(self, enumName, names, values, comment="", deriving="", repr=""): @@ -4703,11 +4865,11 @@ class CGNonNamespacedEnum(CGThing): curr = CGGeneric(enumstr) # Add some whitespace padding. - curr = CGWrapper(curr, pre='\n',post='\n') + curr = CGWrapper(curr, pre='\n', post='\n') # Add the typedef - #typedef = '\ntypedef %s::%s %s;\n\n' % (namespace, enumName, enumName) - #curr = CGList([curr, CGGeneric(typedef)]) + # typedef = '\ntypedef %s::%s %s;\n\n' % (namespace, enumName, enumName) + # curr = CGList([curr, CGGeneric(typedef)]) # Save the result. self.node = curr @@ -4715,9 +4877,10 @@ class CGNonNamespacedEnum(CGThing): def define(self): return self.node.define() + class CGDictionary(CGThing): def __init__(self, dictionary, descriptorProvider): - self.dictionary = dictionary; + self.dictionary = dictionary if all(CGDictionary(d, descriptorProvider).generatable for d in CGDictionary.getDictionaryDependencies(dictionary)): self.generatable = True @@ -4734,7 +4897,7 @@ class CGDictionary(CGThing): defaultValue=member.defaultValue, failureCode="return Err(());", exceptionCode="return Err(());")) - for member in dictionary.members ] + for member in dictionary.members] def define(self): if not self.generatable: @@ -4757,8 +4920,8 @@ class CGDictionary(CGThing): "pub struct ${selfName} {\n" + "${inheritance}" + "\n".join(memberDecls) + "\n" + - "}").substitute( { "selfName": self.makeClassName(d), - "inheritance": inheritance })) + "}").substitute({"selfName": self.makeClassName(d), + "inheritance": inheritance})) def impl(self): d = self.dictionary @@ -4778,7 +4941,10 @@ class CGDictionary(CGThing): def memberInsert(memberInfo): member, _ = memberInfo name = self.makeMemberName(member.identifier.name) - insertion = ("let mut %s = RootedValue::new(cx, UndefinedValue());\nself.%s.to_jsval(cx, %s.handle_mut());\nset_dictionary_property(cx, obj.handle(), \"%s\", %s.handle()).unwrap();" % (name, name, name, name, name)) + insertion = ("let mut %s = RootedValue::new(cx, UndefinedValue());\n" + "self.%s.to_jsval(cx, %s.handle_mut());\n" + "set_dictionary_property(cx, obj.handle(), \"%s\", %s.handle()).unwrap();" + % (name, name, name, name, name)) return CGGeneric("%s\n" % insertion) memberInits = CGList([memberInit(m) for m in self.memberInfo]) @@ -4816,7 +4982,7 @@ class CGDictionary(CGThing): "initParent": CGIndenter(CGGeneric(initParent), indentLevel=12).define(), "initMembers": CGIndenter(memberInits, indentLevel=12).define(), "insertMembers": CGIndenter(memberInserts, indentLevel=8).define(), - }) + }) @staticmethod def makeDictionaryName(dictionary): @@ -4843,8 +5009,7 @@ class CGDictionary(CGThing): member, info = memberInfo templateBody = info.template default = info.default - declType = info.declType - replacements = { "val": "rval.handle()" } + replacements = {"val": "rval.handle()"} conversion = string.Template(templateBody).substitute(replacements) if memberType.isAny(): conversion = "%s.get()" % conversion @@ -4868,7 +5033,6 @@ class CGDictionary(CGThing): return CGGeneric(conversion) - @staticmethod def makeIdName(name): return name + "_id" @@ -4882,7 +5046,7 @@ class CGDictionary(CGThing): @staticmethod def getDictionaryDependencies(dictionary): - deps = set(); + deps = set() if dictionary.parent: deps.add(dictionary.parent) for member in dictionary.members: @@ -4890,6 +5054,7 @@ class CGDictionary(CGThing): deps.add(member.type.unroll().inner) return deps + class CGRegisterProtos(CGAbstractMethod): def __init__(self, config): arguments = [ @@ -4915,7 +5080,8 @@ class CGRegisterProxyHandlersMethod(CGAbstractMethod): def definition_body(self): return CGList([ - CGGeneric("proxy_handlers[Proxies::%s as usize] = codegen::Bindings::%sBinding::DefineProxyHandler();" % (desc.name, desc.name)) + CGGeneric("proxy_handlers[Proxies::%s as usize] = codegen::Bindings::%sBinding::DefineProxyHandler();" + % (desc.name, desc.name)) for desc in self.descriptors ], "\n") @@ -4925,7 +5091,8 @@ class CGRegisterProxyHandlers(CGThing): descriptors = config.getDescriptors(proxy=True) length = len(descriptors) self.root = CGList([ - CGGeneric("pub static mut proxy_handlers: [*const libc::c_void; %d] = [0 as *const libc::c_void; %d];" % (length, length)), + CGGeneric("pub static mut proxy_handlers: [*const libc::c_void; %d] = [0 as *const libc::c_void; %d];" + % (length, length)), CGRegisterProxyHandlersMethod(descriptors), ], "\n") @@ -4979,8 +5146,8 @@ class CGBindingRoot(CGThing): curr = CGWrapper(CGList(cgthings, "\n\n"), post="\n\n") # Wrap all of that in our namespaces. - #curr = CGNamespace.build(['dom'], - # CGWrapper(curr, pre="\n")) + # curr = CGNamespace.build(['dom'], + # CGWrapper(curr, pre="\n")) # Add imports curr = CGImports(curr, descriptors + callbackDescriptors, mainCallbacks, [ @@ -4997,8 +5164,8 @@ class CGBindingRoot(CGThing): 'js::jsapi::{JS_NewObjectWithGivenProto, JS_NewObject, IsCallable, JS_SetProperty, JS_SetPrototype}', 'js::jsapi::{JS_SetReservedSlot, JS_WrapValue, JSContext}', 'js::jsapi::{JSClass, FreeOp, JSFreeOp, JSFunctionSpec, jsid}', - 'js::jsapi::{MutableHandleValue, MutableHandleObject, HandleObject, HandleValue, RootedObject, RootedValue}', - 'js::jsapi::{JSNativeWrapper, JSNative, JSObject, JSPropertyDescriptor}', + 'js::jsapi::{MutableHandleValue, MutableHandleObject, HandleObject, HandleValue, RootedObject}', + 'js::jsapi::{RootedValue, JSNativeWrapper, JSNative, JSObject, JSPropertyDescriptor}', 'js::jsapi::{JSPropertySpec}', 'js::jsapi::{JSString, JSTracer, JSJitInfo, JSJitInfo_OpType, JSJitInfo_AliasSet}', 'js::jsapi::{MutableHandle, Handle, HandleId, JSType, JSValueType}', @@ -5085,6 +5252,7 @@ class CGBindingRoot(CGThing): def define(self): return stripTrailingWhitespace(self.root.define()) + def argument_type(descriptorProvider, ty, optional=False, defaultValue=None, variadic=False): info = getJSToNativeConversionInfo( ty, descriptorProvider, isArgument=True) @@ -5100,24 +5268,27 @@ def argument_type(descriptorProvider, ty, optional=False, defaultValue=None, var return declType.define() + def method_arguments(descriptorProvider, returnType, arguments, passJSBits=True, trailing=None): if needCx(returnType, arguments, passJSBits): yield "cx", "*mut JSContext" for argument in arguments: ty = argument_type(descriptorProvider, argument.type, argument.optional, - argument.defaultValue, argument.variadic) + argument.defaultValue, argument.variadic) yield CGDictionary.makeMemberName(argument.identifier.name), ty if trailing: yield trailing + def return_type(descriptorProvider, rettype, infallible): result = getRetvalDeclarationForType(rettype, descriptorProvider) if not infallible: result = CGWrapper(result, pre="Fallible<", post=">") return result.define() + class CGNativeMember(ClassMethod): def __init__(self, descriptorProvider, member, name, signature, extendedAttrs, breakAfter=True, passJSBitsAsNeeded=True, visibility="public", @@ -5158,6 +5329,7 @@ class CGNativeMember(ClassMethod): argList, self.passJSBitsAsNeeded)] + class CGCallback(CGClass): def __init__(self, idlObject, descriptorProvider, baseName, methods, getters=[], setters=[]): @@ -5179,7 +5351,7 @@ class CGCallback(CGClass): CGClass.__init__(self, name, bases=[ClassBase(baseName)], constructors=self.getConstructors(), - methods=realMethods+getters+setters, + methods=realMethods + getters + setters, decorators="#[derive(JSTraceable, PartialEq)]") def getConstructors(self): @@ -5190,7 +5362,7 @@ class CGCallback(CGClass): explicit=False, baseConstructors=[ "%s::new()" % self.baseName - ])] + ])] def getMethodImpls(self, method): assert method.needThisHandling @@ -5213,7 +5385,7 @@ class CGCallback(CGClass): # And now insert our template argument. argsWithoutThis = list(args) - args.insert(0, Argument("&T", "thisObj")) + args.insert(0, Argument("&T", "thisObj")) # And the self argument method.args.insert(0, Argument(None, "&self")) @@ -5226,29 +5398,29 @@ class CGCallback(CGClass): "}\n") bodyWithThis = string.Template( - setupCall+ + setupCall + "let mut thisObjJS = RootedObject::new(s.get_context(), ptr::null_mut());\n" "wrap_call_this_object(s.get_context(), thisObj, thisObjJS.handle_mut());\n" "if thisObjJS.ptr.is_null() {\n" " return Err(JSFailed);\n" "}\n" "return ${methodName}(${callArgs});").substitute({ - "callArgs" : ", ".join(argnamesWithThis), + "callArgs": ", ".join(argnamesWithThis), "methodName": 'self.' + method.name, - }) + }) bodyWithoutThis = string.Template( setupCall + "let thisObjJS = RootedObject::new(s.get_context(), ptr::null_mut());" "return ${methodName}(${callArgs});").substitute({ - "callArgs" : ", ".join(argnamesWithoutThis), + "callArgs": ", ".join(argnamesWithoutThis), "methodName": 'self.' + method.name, - }) - return [ClassMethod(method.name+'_', method.returnType, args, + }) + return [ClassMethod(method.name + '_', method.returnType, args, bodyInHeader=True, templateArgs=["T: Reflectable"], body=bodyWithThis, visibility='pub'), - ClassMethod(method.name+'__', method.returnType, argsWithoutThis, + ClassMethod(method.name + '__', method.returnType, argsWithoutThis, bodyInHeader=True, body=bodyWithoutThis, visibility='pub'), @@ -5257,6 +5429,7 @@ class CGCallback(CGClass): def deps(self): return self._deps + # We're always fallible def callbackGetterName(attr, descriptor): return "Get" + MakeNativeName( @@ -5277,6 +5450,7 @@ class CGCallbackFunction(CGCallback): def getConstructors(self): return CGCallback.getConstructors(self) + class CGCallbackFunctionImpl(CGGeneric): def __init__(self, callback): impl = string.Template("""\ @@ -5298,6 +5472,7 @@ impl ToJSValConvertible for ${type} { """).substitute({"type": callback.name}) CGGeneric.__init__(self, impl) + class CGCallbackInterface(CGCallback): def __init__(self, descriptor): iface = descriptor.interface @@ -5313,18 +5488,24 @@ class CGCallbackInterface(CGCallback): CGCallback.__init__(self, iface, descriptor, "CallbackInterface", methods, getters=getters, setters=setters) + class FakeMember(): def __init__(self): self.treatNullAs = "Default" + def isStatic(self): return False + def isAttr(self): return False + def isMethod(self): return False + def getExtendedAttribute(self, name): return None + class CallbackMember(CGNativeMember): def __init__(self, sig, name, descriptorProvider, needThisHandling): """ @@ -5338,7 +5519,7 @@ class CallbackMember(CGNativeMember): self.argCount = len(args) if self.argCount > 0: # Check for variadic arguments - lastArg = args[self.argCount-1] + lastArg = args[self.argCount - 1] if lastArg.variadic: self.argCountStr = ( "(%d - 1) + %s.len()" % (self.argCount, @@ -5370,12 +5551,12 @@ class CallbackMember(CGNativeMember): "convertArgs": self.getArgConversions(), "doCall": self.getCall(), "setupCall": self.getCallSetup(), - } + } if self.argCount > 0: replacements["argCount"] = self.argCountStr replacements["argvDecl"] = string.Template( "let mut argv = repeat(UndefinedValue()).take(${argCount}).collect::<Vec<_>>();\n" - ).substitute(replacements) + ).substitute(replacements) else: # Avoid weird 0-sized arrays replacements["argvDecl"] = "" @@ -5430,7 +5611,7 @@ class CallbackMember(CGNativeMember): in enumerate(self.originalSig[1])] # Do them back to front, so our argc modifications will work # correctly, because we examine trailing arguments first. - argConversions.reverse(); + argConversions.reverse() argConversions = [CGGeneric(c) for c in argConversions] if self.argCount > 0: argConversions.insert(0, self.getArgcDecl()) @@ -5457,7 +5638,7 @@ class CallbackMember(CGNativeMember): "for idx in 0..${arg}.len() {\n" + CGIndenter(CGGeneric(conversion)).define() + "\n" "}" - ).substitute({ "arg": arg.identifier.name }) + ).substitute({"arg": arg.identifier.name}) elif arg.optional and not arg.defaultValue: conversion = ( CGIfWrapper(CGGeneric(conversion), @@ -5467,7 +5648,7 @@ class CallbackMember(CGNativeMember): " argc -= 1;\n" "} else {\n" " argv[%d] = UndefinedValue();\n" - "}" % (i+1, i)) + "}" % (i + 1, i)) return conversion def getArgs(self, returnType, argList): @@ -5495,7 +5676,7 @@ class CallbackMember(CGNativeMember): "}\n") def getArgcDecl(self): - return CGGeneric("let mut argc = %s;" % self.argCountStr); + return CGGeneric("let mut argc = %s;" % self.argCountStr) @staticmethod def ensureASCIIName(idlObject): @@ -5512,10 +5693,12 @@ class CallbackMember(CGNativeMember): (type, idlObject.identifier.name, idlObject.location)) + class CallbackMethod(CallbackMember): def __init__(self, sig, name, descriptorProvider, needThisHandling): CallbackMember.__init__(self, sig, name, descriptorProvider, needThisHandling) + def getRvalDecl(self): return "let mut rval = RootedValue::new(cx, UndefinedValue());\n" @@ -5523,22 +5706,28 @@ class CallbackMethod(CallbackMember): replacements = { "thisObj": self.getThisObj(), "getCallable": self.getCallableDecl() - } + } if self.argCount > 0: replacements["argv"] = "argv.as_ptr()" replacements["argc"] = "argc" else: replacements["argv"] = "ptr::null_mut()" replacements["argc"] = "0" - return string.Template("${getCallable}" - "let ok = unsafe {\n" - " let rootedThis = RootedObject::new(cx, ${thisObj});\n" - " JS_CallFunctionValue(cx, rootedThis.handle(), callable.handle(),\n" - " &HandleValueArray { length_: ${argc} as ::libc::size_t, elements_: ${argv} }, rval.handle_mut())\n" - "};\n" - "if ok == 0 {\n" - " return Err(JSFailed);\n" - "}\n").substitute(replacements) + return string.Template( + "${getCallable}" + "let ok = unsafe {\n" + " let rootedThis = RootedObject::new(cx, ${thisObj});\n" + " JS_CallFunctionValue(\n" + " cx, rootedThis.handle(), callable.handle(),\n" + " &HandleValueArray {\n" + " length_: ${argc} as ::libc::size_t,\n" + " elements_: ${argv}\n" + " }, rval.handle_mut())\n" + "};\n" + "if ok == 0 {\n" + " return Err(JSFailed);\n" + "}\n").substitute(replacements) + class CallCallback(CallbackMethod): def __init__(self, callback, descriptorProvider): @@ -5551,6 +5740,7 @@ class CallCallback(CallbackMethod): def getCallableDecl(self): return "let callable = RootedValue::new(cx, ObjectValue(unsafe {&*self.parent.callback()}));\n" + class CallbackOperationBase(CallbackMethod): """ Common class for implementing various callback operations. @@ -5585,6 +5775,7 @@ class CallbackOperationBase(CallbackMethod): CGGeneric('unsafe { RootedValue::new(cx, ObjectValue(&*self.parent.callback())) }'), CGGeneric(getCallableFromProp))).define() + ';\n') + class CallbackOperation(CallbackOperationBase): """ Codegen actual WebIDL operations on callback interfaces. @@ -5597,6 +5788,7 @@ class CallbackOperation(CallbackOperationBase): MakeNativeName(descriptor.binaryNameFor(jsName)), descriptor, descriptor.interface.isSingleOperationInterface()) + class CallbackGetter(CallbackMember): def __init__(self, attr, descriptor): self.ensureASCIIName(attr) @@ -5617,7 +5809,8 @@ class CallbackGetter(CallbackMember): return string.Template( 'if (!JS_GetProperty(cx, mCallback, "${attrName}", &rval)) {\n' ' return Err(JSFailed);\n' - '}\n').substitute(replacements); + '}\n').substitute(replacements) + class CallbackSetter(CallbackMember): def __init__(self, attr, descriptor): @@ -5638,7 +5831,7 @@ class CallbackSetter(CallbackMember): replacements = { "attrName": self.attrName, "argv": "argv.handleAt(0)", - } + } return string.Template( 'MOZ_ASSERT(argv.length() == 1);\n' 'if (!JS_SetProperty(cx, mCallback, "${attrName}", ${argv})) {\n' @@ -5648,6 +5841,7 @@ class CallbackSetter(CallbackMember): def getArgcDecl(self): return None + class GlobalGenRoots(): """ Roots for global codegen. @@ -5678,7 +5872,6 @@ class GlobalGenRoots(): CGNonNamespacedEnum('Proxies', proxies, [0], deriving="PartialEq, Copy, Clone"), ]) - @staticmethod def RegisterBindings(config): # TODO - Generate the methods we want diff --git a/components/script/dom/bindings/codegen/Configuration.py b/components/script/dom/bindings/codegen/Configuration.py index 6e4bcbed34c..436823a9329 100644 --- a/components/script/dom/bindings/codegen/Configuration.py +++ b/components/script/dom/bindings/codegen/Configuration.py @@ -1,11 +1,12 @@ # This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this file, -# You can obtain one at http://mozilla.org/MPL/2.0/. +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. from WebIDL import IDLInterface autogenerated_comment = "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n" + class Configuration: """ Represents global configuration state based on IDL parse data and @@ -22,7 +23,7 @@ class Configuration: # |parseData|. self.descriptors = [] self.interfaces = {} - self.maxProtoChainLength = 0; + self.maxProtoChainLength = 0 for thing in parseData: # Some toplevel things are sadly types, and those have an # isInterface that doesn't mean the same thing as IDLObject's @@ -44,7 +45,8 @@ class Configuration: if not isinstance(entry, list): assert isinstance(entry, dict) entry = [entry] - self.descriptors.extend([Descriptor(self, iface, x) for x in entry]) + self.descriptors.extend( + [Descriptor(self, iface, x) for x in entry]) # Mark the descriptors for which only a single nativeType implements # an interface. @@ -60,10 +62,11 @@ class Configuration: c.isCallback() and not c.isInterface()] # Keep the descriptor list sorted for determinism. - self.descriptors.sort(lambda x,y: cmp(x.name, y.name)) + self.descriptors.sort(lambda x, y: cmp(x.name, y.name)) def getInterface(self, ifname): return self.interfaces[ifname] + def getDescriptors(self, **filters): """Gets the descriptors that match the given filters.""" curr = self.descriptors @@ -80,6 +83,7 @@ class Configuration: getter = lambda x: getattr(x, key) curr = filter(lambda x: getter(x) == val, curr) return curr + def getEnums(self, webIDLFile): return filter(lambda e: e.filename() == webIDLFile, self.enums) @@ -93,6 +97,7 @@ class Configuration: def getDictionaries(self, webIDLFile=""): return self._filterForFile(self.dictionaries, webIDLFile=webIDLFile) + def getCallbacks(self, webIDLFile=""): return self._filterForFile(self.callbacks, webIDLFile=webIDLFile) @@ -104,20 +109,23 @@ class Configuration: descriptors = self.getDescriptors(interface=iface) # We should have exactly one result. - if len(descriptors) is not 1: + if len(descriptors) != 1: raise NoSuchDescriptorError("For " + interfaceName + " found " + - str(len(matches)) + " matches"); + str(len(descriptors)) + " matches") return descriptors[0] + def getDescriptorProvider(self): """ Gets a descriptor provider that can provide descriptors as needed. """ return DescriptorProvider(self) + class NoSuchDescriptorError(TypeError): def __init__(self, str): TypeError.__init__(self, str) + class DescriptorProvider: """ A way of getting descriptors for interface names @@ -132,6 +140,7 @@ class DescriptorProvider: """ return self.config.getDescriptor(interfaceName) + class Descriptor(DescriptorProvider): """ Represents a single descriptor for an interface. See Bindings.conf. @@ -148,7 +157,7 @@ class Descriptor(DescriptorProvider): if self.interface.isCallback(): self.needsRooting = False ty = "%sBinding::%s" % (ifaceName, ifaceName) - self.returnType = "Rc<%s>"% ty + self.returnType = "Rc<%s>" % ty self.argumentType = "???" self.memberType = "???" self.nativeType = ty @@ -230,7 +239,7 @@ class Descriptor(DescriptorProvider): # self.extendedAttributes is a dict of dicts, keyed on # all/getterOnly/setterOnly and then on member name. Values are an # array of extended attributes. - self.extendedAttributes = { 'all': {}, 'getterOnly': {}, 'setterOnly': {} } + self.extendedAttributes = {'all': {}, 'getterOnly': {}, 'setterOnly': {}} def addExtendedAttribute(attribute, config): def add(key, members, attribute): @@ -334,6 +343,7 @@ def getTypesFromDescriptor(descriptor): types.extend(a.type for a in members if a.isAttr()) return types + def getFlatTypes(types): retval = set() for type in types: @@ -344,6 +354,7 @@ def getFlatTypes(types): retval.add(type) return retval + def getTypesFromDictionary(dictionary): """ Get all member types for this dictionary @@ -355,12 +366,13 @@ def getTypesFromDictionary(dictionary): curDict = curDict.parent return types + def getTypesFromCallback(callback): """ Get the types this callback depends on: its return type and the types of its arguments. """ sig = callback.signatures()[0] - types = [sig[0]] # Return type - types.extend(arg.type for arg in sig[1]) # Arguments + types = [sig[0]] # Return type + types.extend(arg.type for arg in sig[1]) # Arguments return types diff --git a/components/script/dom/bindings/codegen/GenerateCSS2PropertiesWebIDL.py b/components/script/dom/bindings/codegen/GenerateCSS2PropertiesWebIDL.py index 1bb50afaee7..55303f6c55b 100644 --- a/components/script/dom/bindings/codegen/GenerateCSS2PropertiesWebIDL.py +++ b/components/script/dom/bindings/codegen/GenerateCSS2PropertiesWebIDL.py @@ -1,6 +1,6 @@ # This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this file, -# You can obtain one at http://mozilla.org/MPL/2.0/. +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. import sys import string @@ -18,9 +18,9 @@ for [prop, pref] in propList: props += " [%s] attribute DOMString %s;\n" % (", ".join(extendedAttrs), prop) -idlFile = open(sys.argv[1], "r"); -idlTemplate = idlFile.read(); -idlFile.close(); +idlFile = open(sys.argv[1], "r") +idlTemplate = idlFile.read() +idlFile.close() print ("/* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT */\n\n" + - string.Template(idlTemplate).substitute({ "props": props })) + string.Template(idlTemplate).substitute({"props": props})) diff --git a/components/script/dom/bindings/codegen/GlobalGen.py b/components/script/dom/bindings/codegen/GlobalGen.py index e596ea44f51..1bebc213e38 100644 --- a/components/script/dom/bindings/codegen/GlobalGen.py +++ b/components/script/dom/bindings/codegen/GlobalGen.py @@ -1,6 +1,6 @@ # This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this file, -# You can obtain one at http://mozilla.org/MPL/2.0/. +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. # We do one global pass over all the WebIDL to generate our prototype enum # and generate information for subsequent phases. @@ -9,12 +9,12 @@ import sys sys.path.append("./parser/") sys.path.append("./ply/") import os -import cStringIO import WebIDL import cPickle -from Configuration import * +from Configuration import Configuration from CodegenRust import GlobalGenRoots, replaceFileIfChanged + def generate_file(config, name, filename): root = getattr(GlobalGenRoots, name)(config) code = root.define() @@ -24,6 +24,7 @@ def generate_file(config, name, filename): else: print "%s hasn't changed - not touching it" % (filename) + def main(): # Parse arguments. from optparse import OptionParser diff --git a/components/script/dom/bindings/codegen/pythonpath.py b/components/script/dom/bindings/codegen/pythonpath.py index 49b2d2f740f..793089551b5 100644 --- a/components/script/dom/bindings/codegen/pythonpath.py +++ b/components/script/dom/bindings/codegen/pythonpath.py @@ -54,7 +54,8 @@ def main(args): # Freeze scope here ... why this makes things work I have no idea ... frozenglobals = globals() -import sys, os +import sys +import os if __name__ == '__main__': main(sys.argv[1:]) diff --git a/components/script/dom/bindings/codegen/test/TestBindingHeader.h b/components/script/dom/bindings/codegen/test/TestBindingHeader.h index 1fbab0a9fb8..20e01813119 100644 --- a/components/script/dom/bindings/codegen/test/TestBindingHeader.h +++ b/components/script/dom/bindings/codegen/test/TestBindingHeader.h @@ -1,8 +1,7 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef TestBindingHeader_h #define TestBindingHeader_h @@ -126,7 +125,7 @@ public: const TestInterfaceOrOnlyForUseInConstructor&, ErrorResult&); */ - + // Integer types int8_t ReadonlyByte(); int8_t WritableByte(); @@ -215,7 +214,8 @@ public: void ReceiveNonWrapperCacheInterfaceSequence(nsTArray<nsRefPtr<TestNonWrapperCacheInterface> >&); void ReceiveNullableNonWrapperCacheInterfaceSequence(nsTArray<nsRefPtr<TestNonWrapperCacheInterface> >&); void ReceiveNonWrapperCacheInterfaceNullableSequence(Nullable<nsTArray<nsRefPtr<TestNonWrapperCacheInterface> > >&); - void ReceiveNullableNonWrapperCacheInterfaceNullableSequence(Nullable<nsTArray<nsRefPtr<TestNonWrapperCacheInterface> > >&); + void ReceiveNullableNonWrapperCacheInterfaceNullableSequence( + Nullable<nsTArray<nsRefPtr<TestNonWrapperCacheInterface> > >&); already_AddRefed<TestNonCastableInterface> ReceiveOther(); already_AddRefed<TestNonCastableInterface> ReceiveNullableOther(); |