GenericCodegen
author Ms2ger <Ms2ger@gmail.com>
Thu, 03 Dec 2015 16:40:41 +0100
changeset 104 af4731c6ac5a34f0f67b8b3ca4d10fd9924d9978
parent 97 00fa8728e63b850141a5fd1821d5dfe8418f731f
child 114 52313bd8ff4193106f736d6a72a0648e4b4c2c34
permissions -rw-r--r--
Update to m-c eec9a0bfd929.

From: Ms2ger <ms2ger@gmail.com>

diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3,21 +3,53 @@
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # Common codegen classes.
 
 import os
 import re
 import string
 import math
-import textwrap
-import functools
 
 from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType, IDLAttribute, IDLInterfaceMember, IDLUndefinedValue, IDLEmptySequenceValue, IDLDictionary
 from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, getAllTypes, Descriptor, MemberIsUnforgeable, iteratorNativeType
+from GenericCodegen import (
+    Argument,
+    CGAbstractMethod,
+    CGAbstractStaticMethod,
+    CGCase,
+    CGClass,
+    CGClassForwardDeclare,
+    CGElseChain,
+    CGGeneric,
+    CGIfElseWrapper,
+    CGIfWrapper,
+    CGIncludeGuard,
+    CGIndenter,
+    CGList,
+    CGNamespace,
+    CGNamespacedEnum,
+    CGSwitch,
+    CGTemplatedType,
+    CGThing,
+    CGWrapper,
+    ClassBase,
+    ClassConstructor,
+    ClassDestructor,
+    ClassEnum,
+    ClassMember,
+    ClassMethod,
+    ClassUnion,
+    ClassUsingDeclaration,
+    dedent,
+    fill,
+    indent,
+    stripTrailingWhitespace,
+    toStringBool,
+)
 
 AUTOGENERATED_WARNING_COMMENT = \
     "/* THIS FILE IS AUTOGENERATED BY Codegen.py - DO NOT EDIT */\n\n"
 AUTOGENERATED_WITH_SOURCE_WARNING_COMMENT = \
     "/* THIS FILE IS AUTOGENERATED FROM %s BY Codegen.py - DO NOT EDIT */\n\n"
 ADDPROPERTY_HOOK_NAME = '_addProperty'
 FINALIZE_HOOK_NAME = '_finalize'
 OBJECT_MOVED_HOOK_NAME = '_objectMoved'
@@ -30,20 +62,16 @@ ENUMERATE_HOOK_NAME = '_enumerate'
 ENUM_ENTRY_VARIABLE_NAME = 'strings'
 INSTANCE_RESERVED_SLOTS = 1
 
 
 def memberReservedSlot(member):
     return "(DOM_INSTANCE_RESERVED_SLOTS + %d)" % member.slotIndex
 
 
-def toStringBool(arg):
-    return str(not not arg).lower()
-
-
 def toBindingNamespace(arg):
     return re.sub("((_workers)?$)", "Binding\\1", arg)
 
 
 def isTypeCopyConstructible(type):
     # Nullable and sequence stuff doesn't affect copy-constructibility
     type = type.unroll()
     return (type.isPrimitive() or type.isString() or type.isEnum() or
@@ -81,175 +109,16 @@ def idlTypeNeedsCycleCollection(type):
     else:
         raise TypeError("Don't know whether to cycle-collect type %s" % type)
 
 
 def wantsAddProperty(desc):
     return (desc.concrete and desc.wrapperCache and not desc.isGlobal())
 
 
-# We'll want to insert the indent at the beginnings of lines, but we
-# 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)
-
-
-def indent(s, indentLevel=2):
-    """
-    Indent C++ code.
-
-    Weird secret feature: this doesn't indent lines that start with # (such as
-    #include lines or #ifdef/#endif).
-    """
-    if s == "":
-        return s
-    return re.sub(lineStartDetector, indentLevel * " ", s)
-
-
-# dedent() and fill() are often called on the same string multiple
-# times.  We want to memoize their return values so we don't keep
-# recomputing them all the time.
-def memoize(fn):
-    """
-    Decorator to memoize a function of one argument.  The cache just
-    grows without bound.
-    """
-    cache = {}
-
-    @functools.wraps(fn)
-    def wrapper(arg):
-        retval = cache.get(arg)
-        if retval is None:
-            retval = cache[arg] = fn(arg)
-        return retval
-    return wrapper
-
-
-@memoize
-def dedent(s):
-    """
-    Remove all leading whitespace from s, and remove a blank line
-    at the beginning.
-    """
-    if s.startswith('\n'):
-        s = s[1:]
-    return textwrap.dedent(s)
-
-
-# This works by transforming the fill()-template to an equivalent
-# string.Template.
-fill_multiline_substitution_re = re.compile(r"( *)\$\*{(\w+)}(\n)?")
-
-
-find_substitutions = re.compile(r"\${")
-
-
-@memoize
-def compile_fill_template(template):
-    """
-    Helper function for fill().  Given the template string passed to fill(),
-    do the reusable part of template processing and return a pair (t,
-    argModList) that can be used every time fill() is called with that
-    template argument.
-
-    argsModList is list of tuples that represent modifications to be
-    made to args.  Each modification has, in order: i) the arg name,
-    ii) the modified name, iii) the indent depth.
-    """
-    t = dedent(template)
-    assert t.endswith("\n") or "\n" not in t
-    argModList = []
-
-    def replace(match):
-        """
-        Replaces a line like '  $*{xyz}\n' with '${xyz_n}',
-        where n is the indent depth, and add a corresponding entry to
-        argModList.
-
-        Note that this needs to close over argModList, so it has to be
-        defined inside compile_fill_template().
-        """
-        indentation, name, nl = match.groups()
-        depth = len(indentation)
-
-        # Check that $*{xyz} appears by itself on a line.
-        prev = match.string[:match.start()]
-        if (prev and not prev.endswith("\n")) or nl is None:
-            raise ValueError("Invalid fill() template: $*{%s} must appear by itself on a line" % name)
-
-        # Now replace this whole line of template with the indented equivalent.
-        modified_name = name + "_" + str(depth)
-        argModList.append((name, modified_name, depth))
-        return "${" + modified_name + "}"
-
-    t = re.sub(fill_multiline_substitution_re, replace, t)
-    if not re.search(find_substitutions, t):
-        raise TypeError("Using fill() when dedent() would do.")
-    return (string.Template(t), argModList)
-
-
-def fill(template, **args):
-    """
-    Convenience function for filling in a multiline template.
-
-    `fill(template, name1=v1, name2=v2)` is a lot like
-    `string.Template(template).substitute({"name1": v1, "name2": v2})`.
-
-    However, it's shorter, and has a few nice features:
-
-      * If `template` is indented, fill() automatically dedents it!
-        This makes code using fill() with Python's multiline strings
-        much nicer to look at.
-
-      * If `template` starts with a blank line, fill() strips it off.
-        (Again, convenient with multiline strings.)
-
-      * fill() recognizes a special kind of substitution
-        of the form `$*{name}`.
-
-        Use this to paste in, and automatically indent, multiple lines.
-        (Mnemonic: The `*` is for "multiple lines").
-
-        A `$*` substitution must appear by itself on a line, with optional
-        preceding indentation (spaces only). The whole line is replaced by the
-        corresponding keyword argument, indented appropriately.  If the
-        argument is an empty string, no output is generated, not even a blank
-        line.
-    """
-
-    t, argModList = compile_fill_template(template)
-    # Now apply argModList to args
-    for (name, modified_name, depth) in argModList:
-        if not (args[name] == "" or args[name].endswith("\n")):
-            raise ValueError("Argument %s with value %r is missing a newline" % (name, args[name]))
-        args[modified_name] = indent(args[name], depth)
-
-    return t.substitute(args)
-
-
-class CGThing():
-    """
-    Abstract base class for things that spit out code.
-    """
-    def __init__(self):
-        pass  # Nothing for now
-
-    def declare(self):
-        """Produce code for a header file."""
-        assert False  # Override me!
-
-    def define(self):
-        """Produce code for a cpp file."""
-        assert False  # Override me!
-
-    def deps(self):
-        """Produce the deps for a pp file"""
-        assert False  # Override me!
-
-
 class CGStringTable(CGThing):
     """
     Generate a string table for the given strings with a function accessor:
 
     const char *accessorName(unsigned int index) {
       static const char table[] = "...";
       static const uint16_t indices = { ... };
       return &table[indices[index]];
@@ -754,230 +623,16 @@ class CGInterfaceObjectJSClass(CGThing):
             hasInstance=hasinstance,
             hooks=NativePropertyHooks(self.descriptor),
             name=self.descriptor.interface.identifier.name,
             prototypeID=prototypeID,
             depth=depth,
             protoGetter=protoGetter)
 
 
-class CGList(CGThing):
-    """
-    Generate code for a list of GCThings.  Just concatenates them together, with
-    an optional joiner string.  "\n" is a common joiner.
-    """
-    def __init__(self, children, joiner=""):
-        CGThing.__init__(self)
-        # Make a copy of the kids into a list, because if someone passes in a
-        # generator we won't be able to both declare and define ourselves, or
-        # define ourselves more than once!
-        self.children = list(children)
-        self.joiner = joiner
-
-    def append(self, child):
-        self.children.append(child)
-
-    def prepend(self, child):
-        self.children.insert(0, child)
-
-    def extend(self, kids):
-        self.children.extend(kids)
-
-    def join(self, iterable):
-        return self.joiner.join(s for s in iterable if len(s) > 0)
-
-    def declare(self):
-        return self.join(child.declare() for child in self.children if child is not None)
-
-    def define(self):
-        return self.join(child.define() for child in self.children if child is not None)
-
-    def deps(self):
-        deps = set()
-        for child in self.children:
-            if child is None:
-                continue
-            deps = deps.union(child.deps())
-        return deps
-
-    def __len__(self):
-        return len(self.children)
-
-
-class CGGeneric(CGThing):
-    """
-    A class that spits out a fixed string into the codegen.  Can spit out a
-    separate string for the declaration too.
-    """
-    def __init__(self, define="", declare=""):
-        self.declareText = declare
-        self.defineText = define
-
-    def declare(self):
-        return self.declareText
-
-    def define(self):
-        return self.defineText
-
-    def deps(self):
-        return set()
-
-
-class CGIndenter(CGThing):
-    """
-    A class that takes another CGThing and generates code that indents that
-    CGThing by some number of spaces.  The default indent is two spaces.
-    """
-    def __init__(self, child, indentLevel=2, declareOnly=False):
-        assert isinstance(child, CGThing)
-        CGThing.__init__(self)
-        self.child = child
-        self.indentLevel = indentLevel
-        self.declareOnly = declareOnly
-
-    def declare(self):
-        return indent(self.child.declare(), self.indentLevel)
-
-    def define(self):
-        defn = self.child.define()
-        if self.declareOnly:
-            return defn
-        else:
-            return indent(defn, self.indentLevel)
-
-
-class CGWrapper(CGThing):
-    """
-    Generic CGThing that wraps other CGThings with pre and post text.
-    """
-    def __init__(self, child, pre="", post="", declarePre=None,
-                 declarePost=None, definePre=None, definePost=None,
-                 declareOnly=False, defineOnly=False, reindent=False):
-        CGThing.__init__(self)
-        self.child = child
-        self.declarePre = declarePre or pre
-        self.declarePost = declarePost or post
-        self.definePre = definePre or pre
-        self.definePost = definePost or post
-        self.declareOnly = declareOnly
-        self.defineOnly = defineOnly
-        self.reindent = reindent
-
-    def declare(self):
-        if self.defineOnly:
-            return ''
-        decl = self.child.declare()
-        if self.reindent:
-            decl = self.reindentString(decl, self.declarePre)
-        return self.declarePre + decl + self.declarePost
-
-    def define(self):
-        if self.declareOnly:
-            return ''
-        defn = self.child.define()
-        if self.reindent:
-            defn = self.reindentString(defn, self.definePre)
-        return self.definePre + defn + self.definePost
-
-    @staticmethod
-    def reindentString(stringToIndent, widthString):
-        # We don't use lineStartDetector because we don't want to
-        # insert whitespace at the beginning of our _first_ line.
-        # Use the length of the last line of width string, in case
-        # it is a multiline string.
-        lastLineWidth = len(widthString.splitlines()[-1])
-        return stripTrailingWhitespace(
-            stringToIndent.replace("\n", "\n" + (" " * lastLineWidth)))
-
-    def deps(self):
-        return self.child.deps()
-
-
-class CGIfWrapper(CGList):
-    def __init__(self, child, condition):
-        CGList.__init__(self, [
-            CGWrapper(CGGeneric(condition), pre="if (", post=") {\n", reindent=True),
-            CGIndenter(child),
-            CGGeneric("}\n")
-        ])
-
-
-class CGIfElseWrapper(CGList):
-    def __init__(self, condition, ifTrue, ifFalse):
-        CGList.__init__(self, [
-            CGWrapper(CGGeneric(condition), pre="if (", post=") {\n", reindent=True),
-            CGIndenter(ifTrue),
-            CGGeneric("} else {\n"),
-            CGIndenter(ifFalse),
-            CGGeneric("}\n")
-        ])
-
-
-class CGElseChain(CGThing):
-    """
-    Concatenate if statements in an if-else-if-else chain.
-    """
-    def __init__(self, children):
-        self.children = [c for c in children if c is not None]
-
-    def declare(self):
-        assert False
-
-    def define(self):
-        if not self.children:
-            return ""
-        s = self.children[0].define()
-        assert s.endswith("\n")
-        for child in self.children[1:]:
-            code = child.define()
-            assert code.startswith("if") or code.startswith("{")
-            assert code.endswith("\n")
-            s = s.rstrip() + " else " + code
-        return s
-
-
-class CGTemplatedType(CGWrapper):
-    def __init__(self, templateName, child, isConst=False, isReference=False):
-        const = "const " if isConst else ""
-        pre = "%s%s<" % (const, templateName)
-        ref = "&" if isReference else ""
-        post = ">%s" % ref
-        CGWrapper.__init__(self, child, pre=pre, post=post)
-
-
-class CGNamespace(CGWrapper):
-    def __init__(self, namespace, child, declareOnly=False):
-        pre = "namespace %s {\n" % namespace
-        post = "} // namespace %s\n" % namespace
-        CGWrapper.__init__(self, child, pre=pre, post=post,
-                           declareOnly=declareOnly)
-
-    @staticmethod
-    def build(namespaces, child, declareOnly=False):
-        """
-        Static helper method to build multiple wrapped namespaces.
-        """
-        if not namespaces:
-            return CGWrapper(child, declareOnly=declareOnly)
-        inner = CGNamespace.build(namespaces[1:], child, declareOnly=declareOnly)
-        return CGNamespace(namespaces[0], inner, declareOnly=declareOnly)
-
-
-class CGIncludeGuard(CGWrapper):
-    """
-    Generates include guards for a header.
-    """
-    def __init__(self, prefix, child):
-        """|prefix| is the filename without the extension."""
-        define = 'mozilla_dom_%s_h' % prefix
-        CGWrapper.__init__(self, child,
-                           declarePre='#ifndef %s\n#define %s\n\n' % (define, define),
-                           declarePost='\n#endif // %s\n' % define)
-
-
 def getRelevantProviders(descriptor, config):
     if descriptor is not None:
         return [descriptor]
     # Do both the non-worker and worker versions
     return [
         config.getDescriptorProvider(False),
         config.getDescriptorProvider(True)
     ]
@@ -1387,138 +1042,16 @@ def UnionConversions(unionTypes, config)
             for f in t.flatMemberTypes:
                 addHeadersForType(f, providers)
 
     return (headers,
             CGWrapper(CGList(SortedDictValues(unionConversions), "\n"),
                       post="\n\n"))
 
 
-class Argument():
-    """
-    A class for outputting the type and name of an argument
-    """
-    def __init__(self, argType, name, default=None):
-        self.argType = argType
-        self.name = name
-        self.default = default
-
-    def declare(self):
-        string = self.argType + ' ' + self.name
-        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
-    should override definition_body to create the actual code.
-
-    descriptor is the descriptor for the interface the method is associated with
-
-    name is the name of the method as a string
-
-    returnType is the IDLType of the return value
-
-    args is a list of Argument objects
-
-    inline should be True to generate an inline method, whose body is
-    part of the declaration.
-
-    alwaysInline should be True to generate an inline method annotated with
-    MOZ_ALWAYS_INLINE.
-
-    static should be True to generate a static method, which only has
-    a definition.
-
-    If templateArgs is not None it should be a list of strings containing
-    template arguments, and the function will be templatized using those
-    arguments.
-    """
-    def __init__(self, descriptor, name, returnType, args, inline=False, alwaysInline=False, static=False, templateArgs=None):
-        CGThing.__init__(self)
-        self.descriptor = descriptor
-        self.name = name
-        self.returnType = returnType
-        self.args = args
-        self.inline = inline
-        self.alwaysInline = alwaysInline
-        self.static = static
-        self.templateArgs = templateArgs
-
-    def _argstring(self, declare):
-        return ', '.join([a.declare() if declare else a.define() for a in self.args])
-
-    def _template(self):
-        if self.templateArgs is None:
-            return ''
-        return 'template <%s>\n' % ', '.join(self.templateArgs)
-
-    def _decorators(self):
-        decorators = []
-        if self.alwaysInline:
-            decorators.append('MOZ_ALWAYS_INLINE')
-        elif self.inline:
-            decorators.append('inline')
-        if self.static:
-            decorators.append('static')
-        decorators.append(self.returnType)
-        maybeNewline = " " if self.inline else "\n"
-        return ' '.join(decorators) + maybeNewline
-
-    def declare(self):
-        if self.inline:
-            return self._define(True)
-        return "%s%s%s(%s);\n" % (self._template(), self._decorators(), self.name, self._argstring(True))
-
-    def indent_body(self, body):
-        """
-        Indent the code returned by self.definition_body(). Most classes
-        simply indent everything two spaces. This is here for
-        CGRegisterProtos, which needs custom indentation.
-        """
-        return indent(body)
-
-    def _define(self, fromDeclare=False):
-        return (self.definition_prologue(fromDeclare) +
-                self.indent_body(self.definition_body()) +
-                self.definition_epilogue())
-
-    def define(self):
-        return "" if self.inline else self._define()
-
-    def definition_prologue(self, fromDeclare):
-        return "%s%s%s(%s)\n{\n" % (self._template(), self._decorators(),
-                                    self.name, self._argstring(fromDeclare))
-
-    def definition_epilogue(self):
-        return "}\n"
-
-    def definition_body(self):
-        assert False  # Override me!
-
-
-class CGAbstractStaticMethod(CGAbstractMethod):
-    """
-    Abstract base class for codegen of implementation-only (no
-    declaration) static methods.
-    """
-    def __init__(self, descriptor, name, returnType, args):
-        CGAbstractMethod.__init__(self, descriptor, name, returnType, args,
-                                  inline=False, static=True)
-
-    def declare(self):
-        # We only have implementation
-        return ""
-
-
 class CGAbstractClassHook(CGAbstractStaticMethod):
     """
     Meant for implementing JSClass hooks, like Finalize or Trace. Does very raw
     'this' unwrapping as it assumes that the unwrapped type is always known.
     """
     def __init__(self, descriptor, name, returnType, args):
         CGAbstractStaticMethod.__init__(self, descriptor, name, returnType,
                                         args)
@@ -7461,60 +6994,16 @@ class CGPerSignatureCall(CGThing):
                 postSteps=postSteps,
                 maybeWrap=getMaybeWrapValueFuncForType(self.idlNode.type))
         return wrapCode
 
     def define(self):
         return (self.cgRoot.define() + self.wrap_return_value())
 
 
-class CGSwitch(CGList):
-    """
-    A class to generate code for a switch statement.
-
-    Takes three constructor arguments: an expression, a list of cases,
-    and an optional default.
-
-    Each case is a CGCase.  The default is a CGThing for the body of
-    the default case, if any.
-    """
-    def __init__(self, expression, cases, default=None):
-        CGList.__init__(self, [CGIndenter(c) for c in cases])
-        self.prepend(CGGeneric("switch (" + expression + ") {\n"))
-        if default is not None:
-            self.append(
-                CGIndenter(
-                    CGWrapper(
-                        CGIndenter(default),
-                        pre="default: {\n",
-                        post="  break;\n}\n")))
-
-        self.append(CGGeneric("}\n"))
-
-
-class CGCase(CGList):
-    """
-    A class to generate code for a case statement.
-
-    Takes three constructor arguments: an expression, a CGThing for
-    the body (allowed to be None if there is no body), and an optional
-    argument (defaulting to False) for whether to fall through.
-    """
-    def __init__(self, expression, body, fallThrough=False):
-        CGList.__init__(self, [])
-        self.append(CGGeneric("case " + expression + ": {\n"))
-        bodyList = CGList([body])
-        if fallThrough:
-            bodyList.append(CGGeneric("MOZ_FALLTHROUGH;\n"))
-        else:
-            bodyList.append(CGGeneric("break;\n"))
-        self.append(CGIndenter(bodyList))
-        self.append(CGGeneric("}\n"))
-
-
 class CGMethodCall(CGThing):
     """
     A class to generate selection of a method signature from a set of
     signatures and generation of a call to that signature.
     """
     def __init__(self, nativeMethodName, static, descriptor, method,
                  isConstructor=False, constructorName=None):
         CGThing.__init__(self)
@@ -9864,553 +9353,16 @@ class CGUnionConversionStruct(CGThing):
 
     def define(self):
         return ""
 
     def deps(self):
         return set()
 
 
-class ClassItem:
-    """ Use with CGClass """
-    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='public'):
-        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,
-                 templateArgs=None, visibility='public', body=None,
-                 breakAfterReturnDecl="\n",
-                 breakAfterSelf="\n", override=False):
-        """
-        override indicates whether to flag the method as override
-        """
-        assert not override or virtual
-        assert not (override and static)
-        self.returnType = returnType
-        self.args = args
-        self.inline = inline or bodyInHeader
-        self.static = static
-        self.virtual = virtual
-        self.const = const
-        self.bodyInHeader = bodyInHeader
-        self.templateArgs = templateArgs
-        self.body = body
-        self.breakAfterReturnDecl = breakAfterReturnDecl
-        self.breakAfterSelf = breakAfterSelf
-        self.override = override
-        ClassItem.__init__(self, name, visibility)
-
-    def getDecorators(self, declaring):
-        decorators = []
-        if self.inline:
-            decorators.append('inline')
-        if declaring:
-            if self.static:
-                decorators.append('static')
-            if self.virtual:
-                decorators.append('virtual')
-        if decorators:
-            return ' '.join(decorators) + ' '
-        return ''
-
-    def getBody(self):
-        # Override me or pass a string to constructor
-        assert self.body is not None
-        return self.body
-
-    def declare(self, cgClass):
-        templateClause = ('template <%s>\n' % ', '.join(self.templateArgs)
-                          if self.bodyInHeader and self.templateArgs else '')
-        args = ', '.join([a.declare() for a in self.args])
-        if self.bodyInHeader:
-            body = indent(self.getBody())
-            body = '\n{\n' + body + '}\n'
-        else:
-            body = ';\n'
-
-        return fill(
-            "${templateClause}${decorators}${returnType}${breakAfterReturnDecl}"
-            "${name}(${args})${const}${override}${body}"
-            "${breakAfterSelf}",
-            templateClause=templateClause,
-            decorators=self.getDecorators(True),
-            returnType=self.returnType,
-            breakAfterReturnDecl=self.breakAfterReturnDecl,
-            name=self.name,
-            args=args,
-            const=' const' if self.const else '',
-            override=' override' if self.override else '',
-            body=body,
-            breakAfterSelf=self.breakAfterSelf)
-
-    def define(self, cgClass):
-        if self.bodyInHeader:
-            return ''
-
-        templateArgs = cgClass.templateArgs
-        if templateArgs:
-            if cgClass.templateSpecialization:
-                templateArgs = \
-                    templateArgs[len(cgClass.templateSpecialization):]
-
-        if templateArgs:
-            templateClause = \
-                'template <%s>\n' % ', '.join([str(a) for a in templateArgs])
-        else:
-            templateClause = ''
-
-        return fill(
-            """
-            ${templateClause}${decorators}${returnType}
-            ${className}::${name}(${args})${const}
-            {
-              $*{body}
-            }
-            """,
-            templateClause=templateClause,
-            decorators=self.getDecorators(False),
-            returnType=self.returnType,
-            className=cgClass.getNameString(),
-            name=self.name,
-            args=', '.join([a.define() for a in self.args]),
-            const=' const' if self.const else '',
-            body=self.getBody())
-
-
-class ClassUsingDeclaration(ClassItem):
-    """
-    Used for importing a name from a base class into a CGClass
-
-    baseClass is the name of the base class to import the name from
-
-    name is the name to import
-
-    visibility determines the visibility of the name (public,
-    protected, private), defaults to public.
-    """
-    def __init__(self, baseClass, name, visibility='public'):
-        self.baseClass = baseClass
-        ClassItem.__init__(self, name, visibility)
-
-    def declare(self, cgClass):
-        return "using %s::%s;\n\n" % (self.baseClass, self.name)
-
-    def define(self, cgClass):
-        return ''
-
-
-class ClassConstructor(ClassItem):
-    """
-    Used for adding a constructor to a CGClass.
-
-    args is a list of Argument objects that are the arguments taken by the
-    constructor.
-
-    inline should be True if the constructor should be marked inline.
-
-    bodyInHeader should be True if the body should be placed in the class
-    declaration in the header.
-
-    visibility determines the visibility of the constructor (public,
-    protected, private), defaults to private.
-
-    explicit should be True if the constructor should be marked explicit.
-
-    baseConstructors is a list of strings containing calls to base constructors,
-    defaults to None.
-
-    body contains a string with the code for the constructor, defaults to empty.
-    """
-    def __init__(self, args, inline=False, bodyInHeader=False,
-                 visibility="private", explicit=False, constexpr=False, baseConstructors=None,
-                 body=""):
-        assert not (inline and constexpr)
-        assert not (bodyInHeader and constexpr)
-        self.args = args
-        self.inline = inline or bodyInHeader
-        self.bodyInHeader = bodyInHeader or constexpr
-        self.explicit = explicit
-        self.constexpr = constexpr
-        self.baseConstructors = baseConstructors or []
-        self.body = body
-        ClassItem.__init__(self, None, visibility)
-
-    def getDecorators(self, declaring):
-        decorators = []
-        if self.explicit:
-            decorators.append('explicit')
-        if self.inline and declaring:
-            decorators.append('inline')
-        if self.constexpr and declaring:
-            decorators.append('MOZ_CONSTEXPR')
-        if decorators:
-            return ' '.join(decorators) + ' '
-        return ''
-
-    def getInitializationList(self, cgClass):
-        items = [str(c) for c in self.baseConstructors]
-        for m in cgClass.members:
-            if not m.static:
-                initialize = m.body
-                if initialize:
-                    items.append(m.name + "(" + initialize + ")")
-
-        if len(items) > 0:
-            return '\n  : ' + ',\n    '.join(items)
-        return ''
-
-    def getBody(self):
-        return self.body
-
-    def declare(self, cgClass):
-        args = ', '.join([a.declare() for a in self.args])
-        if self.bodyInHeader:
-            body = self.getInitializationList(cgClass) + '\n{\n' + indent(self.getBody()) + '}\n'
-        else:
-            body = ';\n'
-
-        return fill(
-            "${decorators}${className}(${args})${body}\n",
-            decorators=self.getDecorators(True),
-            className=cgClass.getNameString(),
-            args=args,
-            body=body)
-
-    def define(self, cgClass):
-        if self.bodyInHeader:
-            return ''
-
-        return fill(
-            """
-            ${decorators}
-            ${className}::${className}(${args})${initializationList}
-            {
-              $*{body}
-            }
-            """,
-            decorators=self.getDecorators(False),
-            className=cgClass.getNameString(),
-            args=', '.join([a.define() for a in self.args]),
-            initializationList=self.getInitializationList(cgClass),
-            body=self.getBody())
-
-
-class ClassDestructor(ClassItem):
-    """
-    Used for adding a destructor to a CGClass.
-
-    inline should be True if the destructor should be marked inline.
-
-    bodyInHeader should be True if the body should be placed in the class
-    declaration in the header.
-
-    visibility determines the visibility of the destructor (public,
-    protected, private), defaults to private.
-
-    body contains a string with the code for the destructor, defaults to empty.
-
-    virtual determines whether the destructor is virtual, defaults to False.
-    """
-    def __init__(self, inline=False, bodyInHeader=False,
-                 visibility="private", body='', virtual=False):
-        self.inline = inline or bodyInHeader
-        self.bodyInHeader = bodyInHeader
-        self.body = body
-        self.virtual = virtual
-        ClassItem.__init__(self, None, visibility)
-
-    def getDecorators(self, declaring):
-        decorators = []
-        if self.virtual and declaring:
-            decorators.append('virtual')
-        if self.inline and declaring:
-            decorators.append('inline')
-        if decorators:
-            return ' '.join(decorators) + ' '
-        return ''
-
-    def getBody(self):
-        return self.body
-
-    def declare(self, cgClass):
-        if self.bodyInHeader:
-            body = '\n{\n' + indent(self.getBody()) + '}\n'
-        else:
-            body = ';\n'
-
-        return fill(
-            "${decorators}~${className}()${body}\n",
-            decorators=self.getDecorators(True),
-            className=cgClass.getNameString(),
-            body=body)
-
-    def define(self, cgClass):
-        if self.bodyInHeader:
-            return ''
-        return fill(
-            """
-            ${decorators}
-            ${className}::~${className}()
-            {
-              $*{body}
-            }
-            """,
-            decorators=self.getDecorators(False),
-            className=cgClass.getNameString(),
-            body=self.getBody())
-
-
-class ClassMember(ClassItem):
-    def __init__(self, name, type, visibility="private", static=False,
-                 body=None):
-        self.type = type
-        self.static = static
-        self.body = body
-        ClassItem.__init__(self, name, visibility)
-
-    def declare(self, cgClass):
-        return '%s%s %s;\n' % ('static ' if self.static else '', self.type,
-                               self.name)
-
-    def define(self, cgClass):
-        if not self.static:
-            return ''
-        if self.body:
-            body = " = " + self.body
-        else:
-            body = ""
-        return '%s %s::%s%s;\n' % (self.type, cgClass.getNameString(),
-                                   self.name, body)
-
-
-class ClassTypedef(ClassItem):
-    def __init__(self, name, type, visibility="public"):
-        self.type = type
-        ClassItem.__init__(self, name, visibility)
-
-    def declare(self, cgClass):
-        return 'typedef %s %s;\n' % (self.type, self.name)
-
-    def define(self, cgClass):
-        # Only goes in the header
-        return ''
-
-
-class ClassEnum(ClassItem):
-    def __init__(self, name, entries, values=None, visibility="public"):
-        self.entries = entries
-        self.values = values
-        ClassItem.__init__(self, name, visibility)
-
-    def declare(self, cgClass):
-        entries = []
-        for i in range(0, len(self.entries)):
-            if not self.values or i >= len(self.values):
-                entry = '%s' % self.entries[i]
-            else:
-                entry = '%s = %s' % (self.entries[i], self.values[i])
-            entries.append(entry)
-        name = '' if not self.name else ' ' + self.name
-        return 'enum%s\n{\n%s\n};\n' % (name, indent(',\n'.join(entries)))
-
-    def define(self, cgClass):
-        # Only goes in the header
-        return ''
-
-
-class ClassUnion(ClassItem):
-    def __init__(self, name, entries, visibility="public"):
-        self.entries = [entry + ";\n" for entry in entries]
-        ClassItem.__init__(self, name, visibility)
-
-    def declare(self, cgClass):
-        return "union %s\n{\n%s\n};\n" % (self.name, indent(''.join(self.entries)))
-
-    def define(self, cgClass):
-        # Only goes in the header
-        return ''
-
-
-class CGClass(CGThing):
-    def __init__(self, name, bases=[], members=[], constructors=[],
-                 destructor=None, methods=[],
-                 typedefs=[], enums=[], unions=[], templateArgs=[],
-                 templateSpecialization=[], isStruct=False,
-                 disallowCopyConstruction=False, indent='',
-                 decorators='',
-                 extradeclarations='',
-                 extradefinitions=''):
-        CGThing.__init__(self)
-        self.name = name
-        self.bases = bases
-        self.members = members
-        self.constructors = constructors
-        # We store our single destructor in a list, since all of our
-        # code wants lists of members.
-        self.destructors = [destructor] if destructor else []
-        self.methods = methods
-        self.typedefs = typedefs
-        self.enums = enums
-        self.unions = unions
-        self.templateArgs = templateArgs
-        self.templateSpecialization = templateSpecialization
-        self.isStruct = isStruct
-        self.disallowCopyConstruction = disallowCopyConstruction
-        self.indent = indent
-        self.defaultVisibility = 'public' if isStruct else 'private'
-        self.decorators = decorators
-        self.extradeclarations = extradeclarations
-        self.extradefinitions = extradefinitions
-
-    def getNameString(self):
-        className = self.name
-        if self.templateSpecialization:
-            className += '<%s>' % ', '.join([str(a)
-                                             for a in self.templateSpecialization])
-        return className
-
-    def declare(self):
-        result = ''
-        if self.templateArgs:
-            templateArgs = [a.declare() for a in self.templateArgs]
-            templateArgs = templateArgs[len(self.templateSpecialization):]
-            result += ('template <%s>\n' %
-                       ','.join([str(a) for a in templateArgs]))
-
-        type = 'struct' if self.isStruct else 'class'
-
-        if self.templateSpecialization:
-            specialization = \
-                '<%s>' % ', '.join([str(a) for a in self.templateSpecialization])
-        else:
-            specialization = ''
-
-        myself = '%s %s%s' % (type, self.name, specialization)
-        if self.decorators != '':
-            myself += " " + self.decorators
-        result += myself
-
-        if self.bases:
-            inherit = ' : '
-            result += inherit
-            # Grab our first base
-            baseItems = [CGGeneric(b.declare(self)) for b in self.bases]
-            bases = baseItems[:1]
-            # Indent the rest
-            bases.extend(CGIndenter(b, len(myself) + len(inherit))
-                         for b in baseItems[1:])
-            result += ",\n".join(b.define() for b in bases)
-
-        result += '\n{\n'
-
-        result += self.extradeclarations
-
-        def declareMembers(cgClass, memberList, defaultVisibility):
-            members = {'private': [], 'protected': [], 'public': []}
-
-            for member in memberList:
-                members[member.visibility].append(member)
-
-            if defaultVisibility == 'public':
-                order = ['public', 'protected', 'private']
-            else:
-                order = ['private', 'protected', 'public']
-
-            result = ''
-
-            lastVisibility = defaultVisibility
-            for visibility in order:
-                list = members[visibility]
-                if list:
-                    if visibility != lastVisibility:
-                        result += visibility + ':\n'
-                    for member in list:
-                        result += indent(member.declare(cgClass))
-                    lastVisibility = visibility
-            return (result, lastVisibility)
-
-        if self.disallowCopyConstruction:
-            class DisallowedCopyConstructor(object):
-                def __init__(self):
-                    self.visibility = "private"
-
-                def declare(self, cgClass):
-                    name = cgClass.getNameString()
-                    return ("%s(const %s&) = delete;\n"
-                            "void operator=(const %s) = delete;\n" % (name, name, name))
-
-            disallowedCopyConstructors = [DisallowedCopyConstructor()]
-        else:
-            disallowedCopyConstructors = []
-
-        order = [self.enums, self.unions,
-                 self.typedefs, self.members,
-                 self.constructors + disallowedCopyConstructors,
-                 self.destructors, self.methods]
-
-        lastVisibility = self.defaultVisibility
-        pieces = []
-        for memberList in order:
-            code, lastVisibility = declareMembers(self, memberList, lastVisibility)
-
-            if code:
-                code = code.rstrip() + "\n"  # remove extra blank lines at the end
-                pieces.append(code)
-
-        result += '\n'.join(pieces)
-        result += '};\n'
-        result = indent(result, len(self.indent))
-        return result
-
-    def define(self):
-        def defineMembers(cgClass, memberList, itemCount, separator=''):
-            result = ''
-            for member in memberList:
-                if itemCount != 0:
-                    result = result + separator
-                definition = member.define(cgClass)
-                if definition:
-                    # Member variables would only produce empty lines here.
-                    result += definition
-                    itemCount += 1
-            return (result, itemCount)
-
-        order = [(self.members, ''), (self.constructors, '\n'),
-                 (self.destructors, '\n'), (self.methods, '\n')]
-
-        result = self.extradefinitions
-        itemCount = 0
-        for memberList, separator in order:
-            memberString, itemCount = defineMembers(self, memberList,
-                                                    itemCount, separator)
-            result = result + memberString
-        return result
-
-
 class CGResolveOwnProperty(CGAbstractStaticMethod):
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'wrapper'),
                 Argument('JS::Handle<JSObject*>', 'obj'),
                 Argument('JS::Handle<jsid>', 'id'),
                 Argument('JS::MutableHandle<JSPropertyDescriptor>', 'desc'),
                 ]
@@ -10516,34 +9468,16 @@ class CGPrototypeTraitsClass(CGClass):
                          templateArgs=templateArgs,
                          templateSpecialization=templateSpecialization,
                          enums=enums, isStruct=True)
 
     def deps(self):
         return set()
 
 
-class CGClassForwardDeclare(CGThing):
-    def __init__(self, name, isStruct=False):
-        CGThing.__init__(self)
-        self.name = name
-        self.isStruct = isStruct
-
-    def declare(self):
-        type = 'struct' if self.isStruct else 'class'
-        return '%s %s;\n' % (type, self.name)
-
-    def define(self):
-        # Header only
-        return ''
-
-    def deps(self):
-        return set()
-
-
 class CGProxySpecialOperation(CGPerSignatureCall):
     """
     Base class for classes for calling an indexed or named special operation
     (don't use this directly, use the derived classes below).
 
     If checkFound is False, will just assert that the prop is found instead of
     checking that it is before wrapping the value.
 
@@ -11699,22 +10633,16 @@ class CGDOMJSProxyHandlerDefiner(CGThing
 
     def declare(self):
         return ""
 
     def define(self):
         return self.handlerThing.define()
 
 
-def stripTrailingWhitespace(text):
-    tail = '\n' if text.endswith('\n') else ''
-    lines = text.splitlines()
-    return '\n'.join(line.rstrip() for line in lines) + tail
-
-
 class MemberProperties:
     def __init__(self):
         self.isGenericMethod = False
         self.isCrossOriginMethod = False
         self.isPromiseReturningMethod = False
         self.isGenericGetter = False
         self.isLenientGetter = False
         self.isCrossOriginGetter = False
@@ -12061,61 +10989,16 @@ class CGDescriptor(CGThing):
 
     def define(self):
         return self.cgRoot.define()
 
     def deps(self):
         return self._deps
 
 
-class CGNamespacedEnum(CGThing):
-    def __init__(self, namespace, enumName, names, values, comment=""):
-
-        if not values:
-            values = []
-
-        # Account for explicit enum values.
-        entries = []
-        for i in range(0, len(names)):
-            if len(values) > i and values[i] is not None:
-                entry = "%s = %s" % (names[i], values[i])
-            else:
-                entry = names[i]
-            entries.append(entry)
-
-        # Append a Count.
-        entries.append('_' + enumName + '_Count')
-
-        # Indent.
-        entries = ['  ' + e for e in entries]
-
-        # Build the enum body.
-        enumstr = comment + 'enum %s\n{\n%s\n};\n' % (enumName, ',\n'.join(entries))
-        curr = CGGeneric(declare=enumstr)
-
-        # Add some whitespace padding.
-        curr = CGWrapper(curr, pre='\n', post='\n')
-
-        # Add the namespace.
-        curr = CGNamespace(namespace, curr)
-
-        # Add the typedef
-        typedef = '\ntypedef %s::%s %s;\n\n' % (namespace, enumName, enumName)
-        curr = CGList([curr, CGGeneric(declare=typedef)])
-
-        # Save the result.
-        self.node = curr
-
-    def declare(self):
-        return self.node.declare()
-
-    def define(self):
-        return ""
-
-
 def initIdsClassMethod(identifiers, atomCacheName):
     idinit = ['!atomsCache->%s.init(cx, "%s")' %
               (CGDictionary.makeIdName(id),
                id)
               for id in identifiers]
     idinit.reverse()
     body = fill(
         """
diff --git a/dom/bindings/GenericCodegen.py b/dom/bindings/GenericCodegen.py
new file mode 100644
--- /dev/null
+++ b/dom/bindings/GenericCodegen.py
@@ -0,0 +1,1154 @@
+# 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/.
+
+import functools
+import re
+import string
+import textwrap
+
+def toStringBool(arg):
+    return str(not not arg).lower()
+
+
+# We'll want to insert the indent at the beginnings of lines, but we
+# 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)
+
+
+def indent(s, indentLevel=2):
+    """
+    Indent C++ code.
+
+    Weird secret feature: this doesn't indent lines that start with # (such as
+    #include lines or #ifdef/#endif).
+    """
+    if s == "":
+        return s
+    return re.sub(lineStartDetector, indentLevel * " ", s)
+
+
+# dedent() and fill() are often called on the same string multiple
+# times.  We want to memoize their return values so we don't keep
+# recomputing them all the time.
+def memoize(fn):
+    """
+    Decorator to memoize a function of one argument.  The cache just
+    grows without bound.
+    """
+    cache = {}
+    @functools.wraps(fn)
+    def wrapper(arg):
+        retval = cache.get(arg)
+        if retval is None:
+            retval = cache[arg] = fn(arg)
+        return retval
+    return wrapper
+
+@memoize
+def dedent(s):
+    """
+    Remove all leading whitespace from s, and remove a blank line
+    at the beginning.
+    """
+    if s.startswith('\n'):
+        s = s[1:]
+    return textwrap.dedent(s)
+
+
+# This works by transforming the fill()-template to an equivalent
+# string.Template.
+fill_multiline_substitution_re = re.compile(r"( *)\$\*{(\w+)}(\n)?")
+
+
+find_substitutions = re.compile(r"\${")
+
+
+@memoize
+def compile_fill_template(template):
+    """
+    Helper function for fill().  Given the template string passed to fill(),
+    do the reusable part of template processing and return a pair (t,
+    argModList) that can be used every time fill() is called with that
+    template argument.
+
+    argsModList is list of tuples that represent modifications to be
+    made to args.  Each modification has, in order: i) the arg name,
+    ii) the modified name, iii) the indent depth.
+    """
+    t = dedent(template)
+    assert t.endswith("\n") or "\n" not in t
+    argModList = []
+
+    def replace(match):
+        """
+        Replaces a line like '  $*{xyz}\n' with '${xyz_n}',
+        where n is the indent depth, and add a corresponding entry to
+        argModList.
+
+        Note that this needs to close over argModList, so it has to be
+        defined inside compile_fill_template().
+        """
+        indentation, name, nl = match.groups()
+        depth = len(indentation)
+
+        # Check that $*{xyz} appears by itself on a line.
+        prev = match.string[:match.start()]
+        if (prev and not prev.endswith("\n")) or nl is None:
+            raise ValueError("Invalid fill() template: $*{%s} must appear by itself on a line" % name)
+
+        # Now replace this whole line of template with the indented equivalent.
+        modified_name = name + "_" + str(depth)
+        argModList.append((name, modified_name, depth))
+        return "${" + modified_name + "}"
+
+    t = re.sub(fill_multiline_substitution_re, replace, t)
+    if not re.search(find_substitutions, t):
+        raise TypeError("Using fill() when dedent() would do.")
+    return (string.Template(t), argModList)
+
+
+def fill(template, **args):
+    """
+    Convenience function for filling in a multiline template.
+
+    `fill(template, name1=v1, name2=v2)` is a lot like
+    `string.Template(template).substitute({"name1": v1, "name2": v2})`.
+
+    However, it's shorter, and has a few nice features:
+
+      * If `template` is indented, fill() automatically dedents it!
+        This makes code using fill() with Python's multiline strings
+        much nicer to look at.
+
+      * If `template` starts with a blank line, fill() strips it off.
+        (Again, convenient with multiline strings.)
+
+      * fill() recognizes a special kind of substitution
+        of the form `$*{name}`.
+
+        Use this to paste in, and automatically indent, multiple lines.
+        (Mnemonic: The `*` is for "multiple lines").
+
+        A `$*` substitution must appear by itself on a line, with optional
+        preceding indentation (spaces only). The whole line is replaced by the
+        corresponding keyword argument, indented appropriately.  If the
+        argument is an empty string, no output is generated, not even a blank
+        line.
+    """
+
+    t, argModList = compile_fill_template(template)
+    # Now apply argModList to args
+    for (name, modified_name, depth) in argModList:
+        if not (args[name] == "" or args[name].endswith("\n")):
+            raise ValueError("Argument %s with value %r is missing a newline" % (name, args[name]))
+        args[modified_name] = indent(args[name], depth)
+
+    return t.substitute(args)
+
+
+class CGThing():
+    """
+    Abstract base class for things that spit out code.
+    """
+    def __init__(self):
+        pass  # Nothing for now
+
+    def declare(self):
+        """Produce code for a header file."""
+        assert False  # Override me!
+
+    def define(self):
+        """Produce code for a cpp file."""
+        assert False  # Override me!
+
+    def deps(self):
+        """Produce the deps for a pp file"""
+        assert False  # Override me!
+
+
+class CGList(CGThing):
+    """
+    Generate code for a list of GCThings.  Just concatenates them together, with
+    an optional joiner string.  "\n" is a common joiner.
+    """
+    def __init__(self, children, joiner=""):
+        CGThing.__init__(self)
+        # Make a copy of the kids into a list, because if someone passes in a
+        # generator we won't be able to both declare and define ourselves, or
+        # define ourselves more than once!
+        self.children = list(children)
+        self.joiner = joiner
+
+    def append(self, child):
+        self.children.append(child)
+
+    def prepend(self, child):
+        self.children.insert(0, child)
+
+    def extend(self, kids):
+        self.children.extend(kids)
+
+    def join(self, iterable):
+        return self.joiner.join(s for s in iterable if len(s) > 0)
+
+    def declare(self):
+        return self.join(child.declare() for child in self.children if child is not None)
+
+    def define(self):
+        return self.join(child.define() for child in self.children if child is not None)
+
+    def deps(self):
+        deps = set()
+        for child in self.children:
+            if child is None:
+                continue
+            deps = deps.union(child.deps())
+        return deps
+
+    def __len__(self):
+        return len(self.children)
+
+
+class CGGeneric(CGThing):
+    """
+    A class that spits out a fixed string into the codegen.  Can spit out a
+    separate string for the declaration too.
+    """
+    def __init__(self, define="", declare=""):
+        self.declareText = declare
+        self.defineText = define
+
+    def declare(self):
+        return self.declareText
+
+    def define(self):
+        return self.defineText
+
+    def deps(self):
+        return set()
+
+
+class CGIndenter(CGThing):
+    """
+    A class that takes another CGThing and generates code that indents that
+    CGThing by some number of spaces.  The default indent is two spaces.
+    """
+    def __init__(self, child, indentLevel=2, declareOnly=False):
+        assert isinstance(child, CGThing)
+        CGThing.__init__(self)
+        self.child = child
+        self.indentLevel = indentLevel
+        self.declareOnly = declareOnly
+
+    def declare(self):
+        return indent(self.child.declare(), self.indentLevel)
+
+    def define(self):
+        defn = self.child.define()
+        if self.declareOnly:
+            return defn
+        else:
+            return indent(defn, self.indentLevel)
+
+
+class CGWrapper(CGThing):
+    """
+    Generic CGThing that wraps other CGThings with pre and post text.
+    """
+    def __init__(self, child, pre="", post="", declarePre=None,
+                 declarePost=None, definePre=None, definePost=None,
+                 declareOnly=False, defineOnly=False, reindent=False):
+        CGThing.__init__(self)
+        self.child = child
+        self.declarePre = declarePre or pre
+        self.declarePost = declarePost or post
+        self.definePre = definePre or pre
+        self.definePost = definePost or post
+        self.declareOnly = declareOnly
+        self.defineOnly = defineOnly
+        self.reindent = reindent
+
+    def declare(self):
+        if self.defineOnly:
+            return ''
+        decl = self.child.declare()
+        if self.reindent:
+            decl = self.reindentString(decl, self.declarePre)
+        return self.declarePre + decl + self.declarePost
+
+    def define(self):
+        if self.declareOnly:
+            return ''
+        defn = self.child.define()
+        if self.reindent:
+            defn = self.reindentString(defn, self.definePre)
+        return self.definePre + defn + self.definePost
+
+    @staticmethod
+    def reindentString(stringToIndent, widthString):
+        # We don't use lineStartDetector because we don't want to
+        # insert whitespace at the beginning of our _first_ line.
+        # Use the length of the last line of width string, in case
+        # it is a multiline string.
+        lastLineWidth = len(widthString.splitlines()[-1])
+        return stripTrailingWhitespace(
+            stringToIndent.replace("\n", "\n" + (" " * lastLineWidth)))
+
+    def deps(self):
+        return self.child.deps()
+
+
+class CGIfWrapper(CGList):
+    def __init__(self, child, condition):
+        CGList.__init__(self, [
+            CGWrapper(CGGeneric(condition), pre="if (", post=") {\n", reindent=True),
+            CGIndenter(child),
+            CGGeneric("}\n")
+        ])
+
+
+class CGIfElseWrapper(CGList):
+    def __init__(self, condition, ifTrue, ifFalse):
+        CGList.__init__(self, [
+            CGWrapper(CGGeneric(condition), pre="if (", post=") {\n", reindent=True),
+            CGIndenter(ifTrue),
+            CGGeneric("} else {\n"),
+            CGIndenter(ifFalse),
+            CGGeneric("}\n")
+        ])
+
+
+class CGElseChain(CGThing):
+    """
+    Concatenate if statements in an if-else-if-else chain.
+    """
+    def __init__(self, children):
+        self.children = [c for c in children if c is not None]
+
+    def declare(self):
+        assert False
+
+    def define(self):
+        if not self.children:
+            return ""
+        s = self.children[0].define()
+        assert s.endswith("\n")
+        for child in self.children[1:]:
+            code = child.define()
+            assert code.startswith("if") or code.startswith("{")
+            assert code.endswith("\n")
+            s = s.rstrip() + " else " + code
+        return s
+
+
+class CGTemplatedType(CGWrapper):
+    def __init__(self, templateName, child, isConst=False, isReference=False):
+        const = "const " if isConst else ""
+        pre = "%s%s<" % (const, templateName)
+        ref = "&" if isReference else ""
+        post = ">%s" % ref
+        CGWrapper.__init__(self, child, pre=pre, post=post)
+
+
+class CGNamespace(CGWrapper):
+    def __init__(self, namespace, child, declareOnly=False):
+        pre = "namespace %s {\n" % namespace
+        post = "} // namespace %s\n" % namespace
+        CGWrapper.__init__(self, child, pre=pre, post=post,
+                           declareOnly=declareOnly)
+
+    @staticmethod
+    def build(namespaces, child, declareOnly=False):
+        """
+        Static helper method to build multiple wrapped namespaces.
+        """
+        if not namespaces:
+            return CGWrapper(child, declareOnly=declareOnly)
+        inner = CGNamespace.build(namespaces[1:], child, declareOnly=declareOnly)
+        return CGNamespace(namespaces[0], inner, declareOnly=declareOnly)
+
+
+class CGIncludeGuard(CGWrapper):
+    """
+    Generates include guards for a header.
+    """
+    def __init__(self, prefix, child):
+        """|prefix| is the filename without the extension."""
+        define = 'mozilla_dom_%s_h' % prefix
+        CGWrapper.__init__(self, child,
+                           declarePre='#ifndef %s\n#define %s\n\n' % (define, define),
+                           declarePost='\n#endif // %s\n' % define)
+
+
+class Argument():
+    """
+    A class for outputting the type and name of an argument
+    """
+    def __init__(self, argType, name, default=None):
+        self.argType = argType
+        self.name = name
+        self.default = default
+
+    def declare(self):
+        string = self.argType + ' ' + self.name
+        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
+    should override definition_body to create the actual code.
+
+    descriptor is the descriptor for the interface the method is associated with
+
+    name is the name of the method as a string
+
+    returnType is the IDLType of the return value
+
+    args is a list of Argument objects
+
+    inline should be True to generate an inline method, whose body is
+    part of the declaration.
+
+    alwaysInline should be True to generate an inline method annotated with
+    MOZ_ALWAYS_INLINE.
+
+    static should be True to generate a static method, which only has
+    a definition.
+
+    If templateArgs is not None it should be a list of strings containing
+    template arguments, and the function will be templatized using those
+    arguments.
+    """
+    def __init__(self, descriptor, name, returnType, args, inline=False, alwaysInline=False, static=False, templateArgs=None):
+        CGThing.__init__(self)
+        self.descriptor = descriptor
+        self.name = name
+        self.returnType = returnType
+        self.args = args
+        self.inline = inline
+        self.alwaysInline = alwaysInline
+        self.static = static
+        self.templateArgs = templateArgs
+
+    def _argstring(self, declare):
+        return ', '.join([a.declare() if declare else a.define() for a in self.args])
+
+    def _template(self):
+        if self.templateArgs is None:
+            return ''
+        return 'template <%s>\n' % ', '.join(self.templateArgs)
+
+    def _decorators(self):
+        decorators = []
+        if self.alwaysInline:
+            decorators.append('MOZ_ALWAYS_INLINE')
+        elif self.inline:
+            decorators.append('inline')
+        if self.static:
+            decorators.append('static')
+        decorators.append(self.returnType)
+        maybeNewline = " " if self.inline else "\n"
+        return ' '.join(decorators) + maybeNewline
+
+    def declare(self):
+        if self.inline:
+            return self._define(True)
+        return "%s%s%s(%s);\n" % (self._template(), self._decorators(), self.name, self._argstring(True))
+
+    def indent_body(self, body):
+        """
+        Indent the code returned by self.definition_body(). Most classes
+        simply indent everything two spaces. This is here for
+        CGRegisterProtos, which needs custom indentation.
+        """
+        return indent(body)
+
+    def _define(self, fromDeclare=False):
+        return (self.definition_prologue(fromDeclare) +
+                self.indent_body(self.definition_body()) +
+                self.definition_epilogue())
+
+    def define(self):
+        return "" if self.inline else self._define()
+
+    def definition_prologue(self, fromDeclare):
+        return "%s%s%s(%s)\n{\n" % (self._template(), self._decorators(),
+                                    self.name, self._argstring(fromDeclare))
+
+    def definition_epilogue(self):
+        return "}\n"
+
+    def definition_body(self):
+        assert False  # Override me!
+
+
+class CGAbstractStaticMethod(CGAbstractMethod):
+    """
+    Abstract base class for codegen of implementation-only (no
+    declaration) static methods.
+    """
+    def __init__(self, descriptor, name, returnType, args):
+        CGAbstractMethod.__init__(self, descriptor, name, returnType, args,
+                                  inline=False, static=True)
+
+    def declare(self):
+        # We only have implementation
+        return ""
+
+
+class CGSwitch(CGList):
+    """
+    A class to generate code for a switch statement.
+
+    Takes three constructor arguments: an expression, a list of cases,
+    and an optional default.
+
+    Each case is a CGCase.  The default is a CGThing for the body of
+    the default case, if any.
+    """
+    def __init__(self, expression, cases, default=None):
+        CGList.__init__(self, [CGIndenter(c) for c in cases])
+        self.prepend(CGGeneric("switch (" + expression + ") {\n"))
+        if default is not None:
+            self.append(
+                CGIndenter(
+                    CGWrapper(
+                        CGIndenter(default),
+                        pre="default: {\n",
+                        post="  break;\n}\n")))
+
+        self.append(CGGeneric("}\n"))
+
+
+class CGCase(CGList):
+    """
+    A class to generate code for a case statement.
+
+    Takes three constructor arguments: an expression, a CGThing for
+    the body (allowed to be None if there is no body), and an optional
+    argument (defaulting to False) for whether to fall through.
+    """
+    def __init__(self, expression, body, fallThrough=False):
+        CGList.__init__(self, [])
+        self.append(CGGeneric("case " + expression + ": {\n"))
+        bodyList = CGList([body])
+        if fallThrough:
+            bodyList.append(CGGeneric("MOZ_FALLTHROUGH;\n"))
+        else:
+            bodyList.append(CGGeneric("break;\n"))
+        self.append(CGIndenter(bodyList))
+        self.append(CGGeneric("}\n"))
+
+
+class ClassItem:
+    """ Use with CGClass """
+    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='public'):
+        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,
+                 templateArgs=None, visibility='public', body=None,
+                 breakAfterReturnDecl="\n",
+                 breakAfterSelf="\n", override=False):
+        """
+        override indicates whether to flag the method as override
+        """
+        assert not override or virtual
+        assert not (override and static)
+        self.returnType = returnType
+        self.args = args
+        self.inline = inline or bodyInHeader
+        self.static = static
+        self.virtual = virtual
+        self.const = const
+        self.bodyInHeader = bodyInHeader
+        self.templateArgs = templateArgs
+        self.body = body
+        self.breakAfterReturnDecl = breakAfterReturnDecl
+        self.breakAfterSelf = breakAfterSelf
+        self.override = override
+        ClassItem.__init__(self, name, visibility)
+
+    def getDecorators(self, declaring):
+        decorators = []
+        if self.inline:
+            decorators.append('inline')
+        if declaring:
+            if self.static:
+                decorators.append('static')
+            if self.virtual:
+                decorators.append('virtual')
+        if decorators:
+            return ' '.join(decorators) + ' '
+        return ''
+
+    def getBody(self):
+        # Override me or pass a string to constructor
+        assert self.body is not None
+        return self.body
+
+    def declare(self, cgClass):
+        templateClause = ('template <%s>\n' % ', '.join(self.templateArgs)
+                          if self.bodyInHeader and self.templateArgs else '')
+        args = ', '.join([a.declare() for a in self.args])
+        if self.bodyInHeader:
+            body = indent(self.getBody())
+            body = '\n{\n' + body + '}\n'
+        else:
+            body = ';\n'
+
+        return fill(
+            "${templateClause}${decorators}${returnType}${breakAfterReturnDecl}"
+            "${name}(${args})${const}${override}${body}"
+            "${breakAfterSelf}",
+            templateClause=templateClause,
+            decorators=self.getDecorators(True),
+            returnType=self.returnType,
+            breakAfterReturnDecl=self.breakAfterReturnDecl,
+            name=self.name,
+            args=args,
+            const=' const' if self.const else '',
+            override=' override' if self.override else '',
+            body=body,
+            breakAfterSelf=self.breakAfterSelf)
+
+    def define(self, cgClass):
+        if self.bodyInHeader:
+            return ''
+
+        templateArgs = cgClass.templateArgs
+        if templateArgs:
+            if cgClass.templateSpecialization:
+                templateArgs = \
+                    templateArgs[len(cgClass.templateSpecialization):]
+
+        if templateArgs:
+            templateClause = \
+                'template <%s>\n' % ', '.join([str(a) for a in templateArgs])
+        else:
+            templateClause = ''
+
+        return fill(
+            """
+            ${templateClause}${decorators}${returnType}
+            ${className}::${name}(${args})${const}
+            {
+              $*{body}
+            }
+            """,
+            templateClause=templateClause,
+            decorators=self.getDecorators(False),
+            returnType=self.returnType,
+            className=cgClass.getNameString(),
+            name=self.name,
+            args=', '.join([a.define() for a in self.args]),
+            const=' const' if self.const else '',
+            body=self.getBody())
+
+
+class ClassUsingDeclaration(ClassItem):
+    """
+    Used for importing a name from a base class into a CGClass
+
+    baseClass is the name of the base class to import the name from
+
+    name is the name to import
+
+    visibility determines the visibility of the name (public,
+    protected, private), defaults to public.
+    """
+    def __init__(self, baseClass, name, visibility='public'):
+        self.baseClass = baseClass
+        ClassItem.__init__(self, name, visibility)
+
+    def declare(self, cgClass):
+        return "using %s::%s;\n\n" % (self.baseClass, self.name)
+
+    def define(self, cgClass):
+        return ''
+
+
+class ClassConstructor(ClassItem):
+    """
+    Used for adding a constructor to a CGClass.
+
+    args is a list of Argument objects that are the arguments taken by the
+    constructor.
+
+    inline should be True if the constructor should be marked inline.
+
+    bodyInHeader should be True if the body should be placed in the class
+    declaration in the header.
+
+    visibility determines the visibility of the constructor (public,
+    protected, private), defaults to private.
+
+    explicit should be True if the constructor should be marked explicit.
+
+    baseConstructors is a list of strings containing calls to base constructors,
+    defaults to None.
+
+    body contains a string with the code for the constructor, defaults to empty.
+    """
+    def __init__(self, args, inline=False, bodyInHeader=False,
+                 visibility="private", explicit=False, constexpr=False, baseConstructors=None,
+                 body=""):
+        assert not (inline and constexpr)
+        assert not (bodyInHeader and constexpr)
+        self.args = args
+        self.inline = inline or bodyInHeader
+        self.bodyInHeader = bodyInHeader or constexpr
+        self.explicit = explicit
+        self.constexpr = constexpr
+        self.baseConstructors = baseConstructors or []
+        self.body = body
+        ClassItem.__init__(self, None, visibility)
+
+    def getDecorators(self, declaring):
+        decorators = []
+        if self.explicit:
+            decorators.append('explicit')
+        if self.inline and declaring:
+            decorators.append('inline')
+        if self.constexpr and declaring:
+            decorators.append('MOZ_CONSTEXPR')
+        if decorators:
+            return ' '.join(decorators) + ' '
+        return ''
+
+    def getInitializationList(self, cgClass):
+        items = [str(c) for c in self.baseConstructors]
+        for m in cgClass.members:
+            if not m.static:
+                initialize = m.body
+                if initialize:
+                    items.append(m.name + "(" + initialize + ")")
+
+        if len(items) > 0:
+            return '\n  : ' + ',\n    '.join(items)
+        return ''
+
+    def getBody(self):
+        return self.body
+
+    def declare(self, cgClass):
+        args = ', '.join([a.declare() for a in self.args])
+        if self.bodyInHeader:
+            body = self.getInitializationList(cgClass) + '\n{\n' + indent(self.getBody()) + '}\n'
+        else:
+            body = ';\n'
+
+        return fill(
+            "${decorators}${className}(${args})${body}\n",
+            decorators=self.getDecorators(True),
+            className=cgClass.getNameString(),
+            args=args,
+            body=body)
+
+    def define(self, cgClass):
+        if self.bodyInHeader:
+            return ''
+
+        return fill(
+            """
+            ${decorators}
+            ${className}::${className}(${args})${initializationList}
+            {
+              $*{body}
+            }
+            """,
+            decorators=self.getDecorators(False),
+            className=cgClass.getNameString(),
+            args=', '.join([a.define() for a in self.args]),
+            initializationList=self.getInitializationList(cgClass),
+            body=self.getBody())
+
+
+class ClassDestructor(ClassItem):
+    """
+    Used for adding a destructor to a CGClass.
+
+    inline should be True if the destructor should be marked inline.
+
+    bodyInHeader should be True if the body should be placed in the class
+    declaration in the header.
+
+    visibility determines the visibility of the destructor (public,
+    protected, private), defaults to private.
+
+    body contains a string with the code for the destructor, defaults to empty.
+
+    virtual determines whether the destructor is virtual, defaults to False.
+    """
+    def __init__(self, inline=False, bodyInHeader=False,
+                 visibility="private", body='', virtual=False):
+        self.inline = inline or bodyInHeader
+        self.bodyInHeader = bodyInHeader
+        self.body = body
+        self.virtual = virtual
+        ClassItem.__init__(self, None, visibility)
+
+    def getDecorators(self, declaring):
+        decorators = []
+        if self.virtual and declaring:
+            decorators.append('virtual')
+        if self.inline and declaring:
+            decorators.append('inline')
+        if decorators:
+            return ' '.join(decorators) + ' '
+        return ''
+
+    def getBody(self):
+        return self.body
+
+    def declare(self, cgClass):
+        if self.bodyInHeader:
+            body = '\n{\n' + indent(self.getBody()) + '}\n'
+        else:
+            body = ';\n'
+
+        return fill(
+            "${decorators}~${className}()${body}\n",
+            decorators=self.getDecorators(True),
+            className=cgClass.getNameString(),
+            body=body)
+
+    def define(self, cgClass):
+        if self.bodyInHeader:
+            return ''
+        return fill(
+            """
+            ${decorators}
+            ${className}::~${className}()
+            {
+              $*{body}
+            }
+            """,
+            decorators=self.getDecorators(False),
+            className=cgClass.getNameString(),
+            body=self.getBody())
+
+
+class ClassMember(ClassItem):
+    def __init__(self, name, type, visibility="private", static=False,
+                 body=None):
+        self.type = type
+        self.static = static
+        self.body = body
+        ClassItem.__init__(self, name, visibility)
+
+    def declare(self, cgClass):
+        return '%s%s %s;\n' % ('static ' if self.static else '', self.type,
+                               self.name)
+
+    def define(self, cgClass):
+        if not self.static:
+            return ''
+        if self.body:
+            body = " = " + self.body
+        else:
+            body = ""
+        return '%s %s::%s%s;\n' % (self.type, cgClass.getNameString(),
+                                   self.name, body)
+
+
+class ClassTypedef(ClassItem):
+    def __init__(self, name, type, visibility="public"):
+        self.type = type
+        ClassItem.__init__(self, name, visibility)
+
+    def declare(self, cgClass):
+        return 'typedef %s %s;\n' % (self.type, self.name)
+
+    def define(self, cgClass):
+        # Only goes in the header
+        return ''
+
+
+class ClassEnum(ClassItem):
+    def __init__(self, name, entries, values=None, visibility="public"):
+        self.entries = entries
+        self.values = values
+        ClassItem.__init__(self, name, visibility)
+
+    def declare(self, cgClass):
+        entries = []
+        for i in range(0, len(self.entries)):
+            if not self.values or i >= len(self.values):
+                entry = '%s' % self.entries[i]
+            else:
+                entry = '%s = %s' % (self.entries[i], self.values[i])
+            entries.append(entry)
+        name = '' if not self.name else ' ' + self.name
+        return 'enum%s\n{\n%s\n};\n' % (name, indent(',\n'.join(entries)))
+
+    def define(self, cgClass):
+        # Only goes in the header
+        return ''
+
+
+class ClassUnion(ClassItem):
+    def __init__(self, name, entries, visibility="public"):
+        self.entries = [entry + ";\n" for entry in entries]
+        ClassItem.__init__(self, name, visibility)
+
+    def declare(self, cgClass):
+        return "union %s\n{\n%s\n};\n" % (self.name, indent(''.join(self.entries)))
+
+    def define(self, cgClass):
+        # Only goes in the header
+        return ''
+
+
+class CGClass(CGThing):
+    def __init__(self, name, bases=[], members=[], constructors=[],
+                 destructor=None, methods=[],
+                 typedefs=[], enums=[], unions=[], templateArgs=[],
+                 templateSpecialization=[], isStruct=False,
+                 disallowCopyConstruction=False, indent='',
+                 decorators='',
+                 extradeclarations='',
+                 extradefinitions=''):
+        CGThing.__init__(self)
+        self.name = name
+        self.bases = bases
+        self.members = members
+        self.constructors = constructors
+        # We store our single destructor in a list, since all of our
+        # code wants lists of members.
+        self.destructors = [destructor] if destructor else []
+        self.methods = methods
+        self.typedefs = typedefs
+        self.enums = enums
+        self.unions = unions
+        self.templateArgs = templateArgs
+        self.templateSpecialization = templateSpecialization
+        self.isStruct = isStruct
+        self.disallowCopyConstruction = disallowCopyConstruction
+        self.indent = indent
+        self.defaultVisibility = 'public' if isStruct else 'private'
+        self.decorators = decorators
+        self.extradeclarations = extradeclarations
+        self.extradefinitions = extradefinitions
+
+    def getNameString(self):
+        className = self.name
+        if self.templateSpecialization:
+            className += '<%s>' % ', '.join([str(a)
+                                             for a in self.templateSpecialization])
+        return className
+
+    def declare(self):
+        result = ''
+        if self.templateArgs:
+            templateArgs = [a.declare() for a in self.templateArgs]
+            templateArgs = templateArgs[len(self.templateSpecialization):]
+            result += ('template <%s>\n' %
+                       ','.join([str(a) for a in templateArgs]))
+
+        type = 'struct' if self.isStruct else 'class'
+
+        if self.templateSpecialization:
+            specialization = \
+                '<%s>' % ', '.join([str(a) for a in self.templateSpecialization])
+        else:
+            specialization = ''
+
+        myself = '%s %s%s' % (type, self.name, specialization)
+        if self.decorators != '':
+            myself += " " + self.decorators
+        result += myself
+
+        if self.bases:
+            inherit = ' : '
+            result += inherit
+            # Grab our first base
+            baseItems = [CGGeneric(b.declare(self)) for b in self.bases]
+            bases = baseItems[:1]
+            # Indent the rest
+            bases.extend(CGIndenter(b, len(myself) + len(inherit))
+                         for b in baseItems[1:])
+            result += ",\n".join(b.define() for b in bases)
+
+        result += '\n{\n'
+
+        result += self.extradeclarations
+
+        def declareMembers(cgClass, memberList, defaultVisibility):
+            members = {'private': [], 'protected': [], 'public': []}
+
+            for member in memberList:
+                members[member.visibility].append(member)
+
+            if defaultVisibility == 'public':
+                order = ['public', 'protected', 'private']
+            else:
+                order = ['private', 'protected', 'public']
+
+            result = ''
+
+            lastVisibility = defaultVisibility
+            for visibility in order:
+                list = members[visibility]
+                if list:
+                    if visibility != lastVisibility:
+                        result += visibility + ':\n'
+                    for member in list:
+                        result += indent(member.declare(cgClass))
+                    lastVisibility = visibility
+            return (result, lastVisibility)
+
+        if self.disallowCopyConstruction:
+            class DisallowedCopyConstructor(object):
+                def __init__(self):
+                    self.visibility = "private"
+
+                def declare(self, cgClass):
+                    name = cgClass.getNameString()
+                    return ("%s(const %s&) = delete;\n"
+                            "void operator=(const %s) = delete;\n" % (name, name, name))
+
+            disallowedCopyConstructors = [DisallowedCopyConstructor()]
+        else:
+            disallowedCopyConstructors = []
+
+        order = [self.enums, self.unions,
+                 self.typedefs, self.members,
+                 self.constructors + disallowedCopyConstructors,
+                 self.destructors, self.methods]
+
+        lastVisibility = self.defaultVisibility
+        pieces = []
+        for memberList in order:
+            code, lastVisibility = declareMembers(self, memberList, lastVisibility)
+
+            if code:
+                code = code.rstrip() + "\n"  # remove extra blank lines at the end
+                pieces.append(code)
+
+        result += '\n'.join(pieces)
+        result += '};\n'
+        result = indent(result, len(self.indent))
+        return result
+
+    def define(self):
+        def defineMembers(cgClass, memberList, itemCount, separator=''):
+            result = ''
+            for member in memberList:
+                if itemCount != 0:
+                    result = result + separator
+                definition = member.define(cgClass)
+                if definition:
+                    # Member variables would only produce empty lines here.
+                    result += definition
+                    itemCount += 1
+            return (result, itemCount)
+
+        order = [(self.members, ''), (self.constructors, '\n'),
+                 (self.destructors, '\n'), (self.methods, '\n')]
+
+        result = self.extradefinitions
+        itemCount = 0
+        for memberList, separator in order:
+            memberString, itemCount = defineMembers(self, memberList,
+                                                    itemCount, separator)
+            result = result + memberString
+        return result
+
+
+class CGClassForwardDeclare(CGThing):
+    def __init__(self, name, isStruct=False):
+        CGThing.__init__(self)
+        self.name = name
+        self.isStruct = isStruct
+
+    def declare(self):
+        type = 'struct' if self.isStruct else 'class'
+        return '%s %s;\n' % (type, self.name)
+
+    def define(self):
+        # Header only
+        return ''
+
+    def deps(self):
+        return set()
+
+
+def stripTrailingWhitespace(text):
+    tail = '\n' if text.endswith('\n') else ''
+    lines = text.splitlines()
+    return '\n'.join(line.rstrip() for line in lines) + tail
+
+
+class CGNamespacedEnum(CGThing):
+    def __init__(self, namespace, enumName, names, values, comment=""):
+
+        if not values:
+            values = []
+
+        # Account for explicit enum values.
+        entries = []
+        for i in range(0, len(names)):
+            if len(values) > i and values[i] is not None:
+                entry = "%s = %s" % (names[i], values[i])
+            else:
+                entry = names[i]
+            entries.append(entry)
+
+        # Append a Count.
+        entries.append('_' + enumName + '_Count')
+
+        # Indent.
+        entries = ['  ' + e for e in entries]
+
+        # Build the enum body.
+        enumstr = comment + 'enum %s\n{\n%s\n};\n' % (enumName, ',\n'.join(entries))
+        curr = CGGeneric(declare=enumstr)
+
+        # Add some whitespace padding.
+        curr = CGWrapper(curr, pre='\n', post='\n')
+
+        # Add the namespace.
+        curr = CGNamespace(namespace, curr)
+
+        # Add the typedef
+        typedef = '\ntypedef %s::%s %s;\n\n' % (namespace, enumName, enumName)
+        curr = CGList([curr, CGGeneric(declare=typedef)])
+
+        # Save the result.
+        self.node = curr
+
+    def declare(self):
+        return self.node.declare()
+
+    def define(self):
+        return ""