Bug 1068740 - Consider putting union types in the binding files where they're used. r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Wed, 01 Oct 2014 20:43:26 +0200
changeset 211247 18d8629e20c9f73dbe025650106786bb466f4fe6
parent 211246 f76047f574306287f4331ebb7ff4f90f3b81cba1
child 211248 62ac7c28ddae3742c32daafe3198a9c6965ead83
push id9454
push usercbook@mozilla.com
push dateMon, 20 Oct 2014 13:36:14 +0000
treeherderfx-team@95f15176c6b3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1068740
milestone36.0a1
Bug 1068740 - Consider putting union types in the binding files where they're used. r=bz.
content/base/public/File.h
content/base/src/MultipartFileImpl.cpp
content/html/content/public/HTMLMediaElement.h
content/html/content/src/HTMLCanvasElement.cpp
content/html/content/src/HTMLFormControlsCollection.cpp
content/html/content/src/HTMLOptionsCollection.h
content/html/content/src/HTMLSelectElement.cpp
content/html/content/src/HTMLTableElement.cpp
content/html/document/src/HTMLAllCollection.cpp
content/media/TextTrackCue.h
content/media/eme/MediaKeySession.h
content/media/eme/MediaKeys.cpp
content/media/eme/MediaKeys.h
dom/base/Console.h
dom/base/SubtleCrypto.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/bindings/Codegen.py
dom/bindings/Configuration.py
dom/bindings/parser/WebIDL.py
dom/bindings/test/TestBindingHeader.h
dom/bindings/test/TestCodeGen.webidl
dom/bindings/test/TestExampleGen.webidl
dom/canvas/CanvasRenderingContext2D.cpp
dom/events/JSEventHandler.cpp
dom/events/MessageEvent.cpp
dom/fetch/Fetch.h
dom/fetch/Headers.h
dom/fetch/InternalRequest.h
dom/fetch/Request.h
dom/fetch/Response.cpp
dom/fetch/Response.h
dom/filesystem/Directory.cpp
dom/icc/Icc.h
dom/indexedDB/IDBRequest.cpp
dom/ipc/StructuredCloneUtils.cpp
dom/mobilemessage/DOMMobileMessageError.cpp
dom/mobilemessage/MobileMessageManager.h
dom/telephony/Telephony.cpp
dom/workers/WorkerScope.h
--- a/content/base/public/File.h
+++ b/content/base/public/File.h
@@ -11,17 +11,16 @@
 #include "mozilla/GuardObjects.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/StaticMutex.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/dom/Date.h"
 #include "mozilla/dom/indexedDB/FileInfo.h"
 #include "mozilla/dom/indexedDB/FileManager.h"
 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCOMPtr.h"
 #include "nsIDOMFile.h"
 #include "nsIDOMFileList.h"
 #include "nsIFile.h"
 #include "nsIMutable.h"
 #include "nsIXMLHttpRequest.h"
@@ -53,16 +52,17 @@ namespace dom {
 namespace indexedDB {
 class FileInfo;
 };
 
 struct BlobPropertyBag;
 struct ChromeFilePropertyBag;
 struct FilePropertyBag;
 class FileImpl;
+class OwningArrayBufferOrArrayBufferViewOrBlobOrString;
 
 class File MOZ_FINAL : public nsIDOMFile
                      , public nsIXHRSendable
                      , public nsIMutable
                      , public nsSupportsWeakReference
                      , public nsWrapperCache
 {
 public:
--- a/content/base/src/MultipartFileImpl.cpp
+++ b/content/base/src/MultipartFileImpl.cpp
@@ -2,16 +2,17 @@
 /* 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/. */
 
 #include "MultipartFileImpl.h"
 #include "jsfriendapi.h"
 #include "mozilla/dom/BlobSet.h"
 #include "mozilla/dom/FileBinding.h"
+#include "mozilla/dom/UnionTypes.h"
 #include "nsAutoPtr.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIMultiplexInputStream.h"
 #include "nsStringStream.h"
 #include "nsTArray.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
 #include "nsIScriptError.h"
--- a/content/html/content/public/HTMLMediaElement.h
+++ b/content/html/content/public/HTMLMediaElement.h
@@ -12,23 +12,23 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsIObserver.h"
 #include "mozilla/CORSMode.h"
 #include "DOMMediaStream.h"
 #include "AudioChannelCommon.h"
 #include "DecoderTraits.h"
 #include "nsIAudioChannelAgent.h"
 #include "mozilla/Attributes.h"
-#include "mozilla/dom/AudioChannelBinding.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/TextTrackManager.h"
 #include "MediaDecoder.h"
 #ifdef MOZ_EME
 #include "mozilla/dom/MediaKeys.h"
 #endif
+#include "nsGkAtoms.h"
 
 // Something on Linux #defines None, which is an entry in the
 // MediaWaitingFor enum, so undef it here before including the binfing,
 // so that the build doesn't fail...
 #ifdef None
 #undef None
 #endif
 
--- a/content/html/content/src/HTMLCanvasElement.cpp
+++ b/content/html/content/src/HTMLCanvasElement.cpp
@@ -9,17 +9,16 @@
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "Layers.h"
 #include "mozilla/Base64.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/CanvasRenderingContext2D.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/HTMLCanvasElementBinding.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/MouseEvent.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "nsAttrValueInlines.h"
 #include "nsContentUtils.h"
--- a/content/html/content/src/HTMLFormControlsCollection.cpp
+++ b/content/html/content/src/HTMLFormControlsCollection.cpp
@@ -6,17 +6,16 @@
 
 #include "mozilla/dom/HTMLFormControlsCollection.h"
 
 #include "mozFlushType.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLFormControlsCollectionBinding.h"
 #include "mozilla/dom/HTMLFormElement.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "nsGenericHTMLElement.h" // nsGenericHTMLFormElement
 #include "nsIDocument.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsIFormControl.h"
 #include "RadioNodeList.h"
 #include "jsfriendapi.h"
 
--- a/content/html/content/src/HTMLOptionsCollection.h
+++ b/content/html/content/src/HTMLOptionsCollection.h
@@ -6,28 +6,29 @@
 #define mozilla_dom_HTMLOptionsCollection_h
 
 #include "mozilla/Attributes.h"
 #include "nsIHTMLCollection.h"
 #include "nsIDOMHTMLOptionsCollection.h"
 #include "nsWrapperCache.h"
 
 #include "mozilla/dom/HTMLOptionElement.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "mozilla/ErrorResult.h"
 #include "nsCOMPtr.h"
 #include "nsError.h"
 #include "nsGenericHTMLElement.h"
 #include "nsTArray.h"
 
 class nsIDOMHTMLOptionElement;
 
 namespace mozilla {
 namespace dom {
 
+class HTMLElementOrLong;
+class HTMLOptionElementOrHTMLOptGroupElement;
 class HTMLSelectElement;
 
 /**
  * The collection of options in the select (what you get back when you do
  * select.options in DOM)
  */
 class HTMLOptionsCollection MOZ_FINAL : public nsIHTMLCollection
                                       , public nsIDOMHTMLOptionsCollection
--- a/content/html/content/src/HTMLSelectElement.cpp
+++ b/content/html/content/src/HTMLSelectElement.cpp
@@ -9,16 +9,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLOptGroupElement.h"
 #include "mozilla/dom/HTMLOptionElement.h"
 #include "mozilla/dom/HTMLSelectElementBinding.h"
+#include "mozilla/dom/UnionTypes.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentList.h"
 #include "nsError.h"
 #include "nsFormSubmission.h"
 #include "nsGkAtoms.h"
 #include "nsIComboboxControlFrame.h"
 #include "nsIDocument.h"
 #include "nsIFormControlFrame.h"
--- a/content/html/content/src/HTMLTableElement.cpp
+++ b/content/html/content/src/HTMLTableElement.cpp
@@ -3,17 +3,16 @@
  * 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/. */
 
 #include "mozilla/dom/HTMLTableElement.h"
 #include "nsAttrValueInlines.h"
 #include "nsRuleData.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsMappedAttributes.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/HTMLCollectionBinding.h"
 #include "mozilla/dom/HTMLTableElementBinding.h"
 #include "nsContentUtils.h"
 #include "jsfriendapi.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Table)
 
 namespace mozilla {
--- a/content/html/document/src/HTMLAllCollection.cpp
+++ b/content/html/document/src/HTMLAllCollection.cpp
@@ -3,17 +3,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/. */
 
 #include "mozilla/dom/HTMLAllCollection.h"
 
 #include "mozilla/dom/HTMLAllCollectionBinding.h"
 #include "mozilla/dom/Nullable.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "nsHTMLDocument.h"
 
 namespace mozilla {
 namespace dom {
 
 HTMLAllCollection::HTMLAllCollection(nsHTMLDocument* aDocument)
   : mDocument(aDocument)
 {
--- a/content/media/TextTrackCue.h
+++ b/content/media/TextTrackCue.h
@@ -10,17 +10,16 @@
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/VTTCueBinding.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIWebVTTParserWrapper.h"
 #include "mozilla/StaticPtr.h"
 #include "nsIDocument.h"
 #include "mozilla/dom/HTMLDivElement.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/TextTrack.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLTrackElement;
 class TextTrackRegion;
 
--- a/content/media/eme/MediaKeySession.h
+++ b/content/media/eme/MediaKeySession.h
@@ -13,26 +13,26 @@
 #include "mozilla/DOMEventTargetHelper.h"
 #include "nsCOMPtr.h"
 #include "mozilla/dom/TypedArray.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/dom/Date.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/MediaKeySessionBinding.h"
 #include "mozilla/dom/MediaKeysBinding.h"
-#include "mozilla/dom/UnionTypes.h"
 
 struct JSContext;
 
 namespace mozilla {
 
 class CDMProxy;
 
 namespace dom {
 
+class ArrayBufferViewOrArrayBuffer;
 class MediaKeyError;
 
 class MediaKeySession MOZ_FINAL : public DOMEventTargetHelper
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaKeySession,
                                            DOMEventTargetHelper)
--- a/content/media/eme/MediaKeys.cpp
+++ b/content/media/eme/MediaKeys.cpp
@@ -6,16 +6,17 @@
 
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/MediaKeys.h"
 #include "mozilla/dom/MediaKeysBinding.h"
 #include "mozilla/dom/MediaKeyMessageEvent.h"
 #include "mozilla/dom/MediaKeyError.h"
 #include "mozilla/dom/MediaKeySession.h"
 #include "mozilla/dom/DOMException.h"
+#include "mozilla/dom/UnionTypes.h"
 #include "mozilla/CDMProxy.h"
 #include "mozilla/EMELog.h"
 #include "nsContentUtils.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "mozilla/Preferences.h"
 #include "nsContentTypeParser.h"
 #ifdef MOZ_FMP4
 #include "MP4Decoder.h"
--- a/content/media/eme/MediaKeys.h
+++ b/content/media/eme/MediaKeys.h
@@ -12,25 +12,25 @@
 #include "nsISupports.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/RefPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsRefPtrHashtable.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/MediaKeysBinding.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "mozIGeckoMediaPluginService.h"
 
 namespace mozilla {
 
 class CDMProxy;
 
 namespace dom {
 
+class ArrayBufferViewOrArrayBuffer;
 class MediaKeySession;
 class HTMLMediaElement;
 
 typedef nsRefPtrHashtable<nsStringHashKey, MediaKeySession> KeySessionHashMap;
 typedef nsRefPtrHashtable<nsUint32HashKey, dom::Promise> PromiseHashMap;
 typedef nsRefPtrHashtable<nsUint32HashKey, MediaKeySession> PendingKeySessionsHashMap;
 typedef uint32_t PromiseId;
 
--- a/dom/base/Console.h
+++ b/dom/base/Console.h
@@ -2,24 +2,25 @@
 /* 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/. */
 
 #ifndef mozilla_dom_Console_h
 #define mozilla_dom_Console_h
 
 #include "mozilla/dom/BindingDeclarations.h"
-#include "mozilla/dom/UnionConversions.h"
 #include "mozilla/ErrorResult.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsIObserver.h"
 #include "nsITimer.h"
 #include "nsWrapperCache.h"
+#include "nsDOMNavigationTiming.h"
+#include "nsPIDOMWindow.h"
 
 class nsIConsoleAPIStorage;
 
 namespace mozilla {
 namespace dom {
 
 class ConsoleCallData;
 struct ConsoleStackEntry;
--- a/dom/base/SubtleCrypto.h
+++ b/dom/base/SubtleCrypto.h
@@ -5,23 +5,23 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SubtleCrypto_h
 #define mozilla_dom_SubtleCrypto_h
 
 #include "nsCycleCollectionParticipant.h"
 #include "nsWrapperCache.h"
 #include "nsPIDOMWindow.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/CryptoKey.h"
 #include "js/TypeDecls.h"
 
 namespace mozilla {
 namespace dom {
 
+class ObjectOrString;
 class Promise;
 
 typedef ArrayBufferViewOrArrayBuffer CryptoOperationData;
 
 class SubtleCrypto MOZ_FINAL : public nsISupports,
                                public nsWrapperCache
 {
   ~SubtleCrypto() {}
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -198,16 +198,17 @@
 #include "nsLocation.h"
 #include "nsHTMLDocument.h"
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "prrng.h"
 #include "nsSandboxFlags.h"
 #include "TimeChangeObserver.h"
 #include "mozilla/dom/AudioContext.h"
+#include "mozilla/dom/BlobBinding.h"
 #include "mozilla/dom/BrowserElementDictionariesBinding.h"
 #include "mozilla/dom/Console.h"
 #include "mozilla/dom/FunctionBinding.h"
 #include "mozilla/dom/HashChangeEvent.h"
 #include "mozilla/dom/MozSelfSupportBinding.h"
 #include "mozilla/dom/PopStateEvent.h"
 #include "mozilla/dom/PopupBlockedEvent.h"
 #include "mozilla/dom/WindowBinding.h"
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -33,17 +33,16 @@
 #include "nsIScriptObjectPrincipal.h"
 #include "nsITimer.h"
 #include "nsIDOMModalContentWindow.h"
 #include "mozilla/EventListenerManager.h"
 #include "nsIPrincipal.h"
 #include "nsSize.h"
 #include "mozFlushType.h"
 #include "prclist.h"
-#include "mozilla/dom/RequestBinding.h"
 #include "mozilla/dom/StorageEvent.h"
 #include "mozilla/dom/StorageEventBinding.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "nsFrameMessageManager.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/TimeStamp.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsIIdleObserver.h"
@@ -105,16 +104,18 @@ class Console;
 class External;
 class Function;
 class Gamepad;
 class MediaQueryList;
 class MozSelfSupport;
 class Navigator;
 class OwningExternalOrWindowProxy;
 class Promise;
+struct RequestInit;
+class RequestOrScalarValueString;
 class Selection;
 class SpeechSynthesis;
 class WakeLock;
 namespace indexedDB {
 class IDBFactory;
 } // namespace indexedDB
 } // namespace dom
 } // namespace mozilla
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -5,18 +5,18 @@
 # Common codegen classes.
 
 import os
 import re
 import string
 import math
 import textwrap
 
-from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType, IDLAttribute, IDLUndefinedValue, IDLEmptySequenceValue
-from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, Descriptor
+from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType, IDLAttribute, IDLUndefinedValue, IDLEmptySequenceValue, IDLDictionary
+from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, getAllTypes, Descriptor
 
 AUTOGENERATED_WARNING_COMMENT = \
     "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
 ADDPROPERTY_HOOK_NAME = '_addProperty'
 FINALIZE_HOOK_NAME = '_finalize'
 OBJECT_MOVED_HOOK_NAME = '_objectMoved'
 CONSTRUCT_HOOK_NAME = '_constructor'
 LEGACYCALLER_HOOK_NAME = '_legacycaller'
@@ -1003,36 +1003,16 @@ def getRelevantProviders(descriptor, con
         return [descriptor]
     # Do both the non-worker and worker versions
     return [
         config.getDescriptorProvider(False),
         config.getDescriptorProvider(True)
     ]
 
 
-def getAllTypes(descriptors, dictionaries, callbacks):
-    """
-    Generate all the types we're dealing with.  For each type, a tuple
-    containing type, descriptor, dictionary is yielded.  The
-    descriptor and dictionary can be None if the type does not come
-    from a descriptor or dictionary; they will never both be non-None.
-    """
-    for d in descriptors:
-        if d.interface.isExternal():
-            continue
-        for t in getTypesFromDescriptor(d):
-            yield (t, d, None)
-    for dictionary in dictionaries:
-        for t in getTypesFromDictionary(dictionary):
-            yield (t, None, dictionary)
-    for callback in callbacks:
-        for t in getTypesFromCallback(callback):
-            yield (t, None, None)
-
-
 class CGHeaders(CGWrapper):
     """
     Generates the appropriate include statements.
     """
     def __init__(self, descriptors, dictionaries, callbacks,
                  callbackDescriptors,
                  declareIncludes, defineIncludes, prefix, child,
                  config=None, jsImplementedDescriptors=[]):
@@ -1100,22 +1080,21 @@ class CGHeaders(CGWrapper):
             else:
                 headerSet = bindingHeaders
             if t.nullable():
                 # Need to make sure that Nullable as a dictionary
                 # member works.
                 headerSet.add("mozilla/dom/Nullable.h")
             unrolled = t.unroll()
             if unrolled.isUnion():
-                # UnionConversions.h includes UnionTypes.h
+                if len(config.filenamesPerUnion[unrolled.name]) > 1:
+                    headerSet.add("mozilla/dom/UnionTypes.h")
+                else:
+                    headerSet.add(self.getDeclarationFilename(unrolled))
                 bindingHeaders.add("mozilla/dom/UnionConversions.h")
-                if dictionary:
-                    # Our dictionary definition is in the header and
-                    # needs the union type.
-                    declareIncludes.add("mozilla/dom/UnionTypes.h")
             elif unrolled.isDate():
                 if dictionary or jsImplementedDescriptors:
                     declareIncludes.add("mozilla/dom/Date.h")
                 else:
                     bindingHeaders.add("mozilla/dom/Date.h")
             elif unrolled.isInterface():
                 if unrolled.isSpiderMonkeyInterface():
                     bindingHeaders.add("jsfriendapi.h")
@@ -1251,53 +1230,52 @@ class CGHeaders(CGWrapper):
 
 
 def SortedDictValues(d):
     """
     Returns a list of values from the dict sorted by key.
     """
     return [v for k, v in sorted(d.items())]
 
-
-def UnionTypes(descriptors, dictionaries, callbacks, config):
-    """
+def UnionsForFile(config, webIDLFile):
+    """
+    Returns a list of tuples each containing two elements (type and descriptor)
+    for all union types that are only used in webIDLFile. If webIDLFile is None
+    this will return the list of tuples for union types that are used in more
+    than one WebIDL file.
+    """
+    return config.unionsPerFilename.get(webIDLFile, [])
+
+def UnionTypes(unionTypes, config):
+    """
+    The unionTypes argument should be a list of tuples, each containing two
+    elements: a union type and a descriptor. This is typically the list
+    generated by UnionsForFile.
+
     Returns a tuple containing a set of header filenames to include in
-    UnionTypes.h, a set of header filenames to include in UnionTypes.cpp, a set
+    the header for the types in unionTypes, a set of header filenames to
+    include in the implementation file for the types in unionTypes, a set
     of tuples containing a type declaration and a boolean if the type is a
-    struct for member types of the unions and a CGList containing CGUnionStructs
-    for every union.
-    """
-
-    # Now find all the things we'll need as arguments and return values because
-    # we need to wrap or unwrap them.
+    struct for member types of the union, a list of traverse methods,
+    unlink methods and a list of union types. These last three lists only
+    contain unique union types.
+    """
+
     headers = set()
-    implheaders = set(["UnionTypes.h"])
+    implheaders = set()
     declarations = set()
     unionStructs = dict()
-    owningUnionStructs = dict()
     traverseMethods = dict()
     unlinkMethods = dict()
 
-    for t, descriptor, dictionary in getAllTypes(descriptors, dictionaries, callbacks):
-        # Add info for the given type.  descriptor and dictionary, if present, are
-        # used to figure out what to do with interface types.
-        assert not descriptor or not dictionary
-
-        t = t.unroll()
-        while t.isMozMap():
-            t = t.inner.unroll()
-        if not t.isUnion():
-            continue
+    for (t, descriptor) in unionTypes:
         name = str(t)
         if name not in unionStructs:
             providers = getRelevantProviders(descriptor, config)
-            # FIXME: Unions are broken in workers.  See bug 809899.
-            unionStructs[name] = CGUnionStruct(t, providers[0])
-            owningUnionStructs[name] = CGUnionStruct(t, providers[0],
-                                                     ownsMembers=True)
+            unionStructs[name] = t
 
             def addHeadersForType(f):
                 if f.nullable():
                     headers.add("mozilla/dom/Nullable.h")
                 isSequence = f.isSequence()
                 f = f.unroll()
                 if f.isInterface():
                     if f.isSpiderMonkeyInterface():
@@ -1338,55 +1316,51 @@ def UnionTypes(descriptors, dictionaries
                     # the right header to be able to Release() in our inlined
                     # code.
                     headers.add(CGHeaders.getDeclarationFilename(f))
                 elif f.isMozMap():
                     headers.add("mozilla/dom/MozMap.h")
                     # And add headers for the type we're parametrized over
                     addHeadersForType(f.inner)
 
+            if len(config.filenamesPerUnion[t.name]) > 1:
+                implheaders.add("mozilla/dom/UnionTypes.h")
+            else:
+                implheaders.add(CGHeaders.getDeclarationFilename(t))
             for f in t.flatMemberTypes:
                 assert not f.nullable()
                 addHeadersForType(f)
 
             if idlTypeNeedsCycleCollection(t):
                 declarations.add(("mozilla::dom::%s" % CGUnionStruct.unionTypeName(t, True), False))
                 traverseMethods[name] = CGCycleCollectionTraverseForOwningUnionMethod(t)
                 unlinkMethods[name] = CGCycleCollectionUnlinkForOwningUnionMethod(t)
 
     # The order of items in CGList is important.
     # Since the union structs friend the unlinkMethods, the forward-declaration
     # for these methods should come before the class declaration. Otherwise
     # some compilers treat the friend declaration as a forward-declaration in
     # the class scope.
     return (headers, implheaders, declarations,
-            CGList(SortedDictValues(traverseMethods) +
-                   SortedDictValues(unlinkMethods) +
-                   SortedDictValues(unionStructs) +
-                   SortedDictValues(owningUnionStructs),
-                   "\n"))
-
-
-def UnionConversions(descriptors, dictionaries, callbacks, config):
-    """
-    Returns a CGThing to declare all union argument conversion helper structs.
-    """
-    # Now find all the things we'll need as arguments because we
-    # need to unwrap them.
+            SortedDictValues(traverseMethods), SortedDictValues(unlinkMethods),
+            SortedDictValues(unionStructs))
+
+def UnionConversions(unionTypes, config):
+    """
+    The unionTypes argument should be a list of tuples, each containing two
+    elements: a union type and a descriptor. This is typically the list
+    generated by UnionsForFile.
+
+    Returns a tuple containing a list of headers and a CGThing to declare all
+    union argument conversion helper structs.
+    """
     headers = set()
     unionConversions = dict()
 
-    for t, descriptor, dictionary in getAllTypes(descriptors, dictionaries, callbacks):
-        # Add info for the given type.  descriptor and dictionary, if passed, are
-        # used to figure out what to do with interface types.
-        assert not descriptor or not dictionary
-
-        t = t.unroll()
-        if not t.isUnion():
-            continue
+    for (t, descriptor) in unionTypes:
         name = str(t)
         if name not in unionConversions:
             providers = getRelevantProviders(descriptor, config)
             unionConversions[name] = CGUnionConversionStruct(t, providers[0])
             def addHeadersForType(f, providers):
                 f = f.unroll()
                 if f.isInterface():
                     if f.isSpiderMonkeyInterface():
@@ -1413,16 +1387,19 @@ def UnionConversions(descriptors, dictio
                     headers.add(CGHeaders.getDeclarationFilename(f.inner))
                 elif f.isPrimitive():
                     headers.add("mozilla/dom/PrimitiveConversions.h")
                 elif f.isMozMap():
                     headers.add("mozilla/dom/MozMap.h")
                     # And the internal type of the MozMap
                     addHeadersForType(f.inner, providers)
 
+            if len(config.filenamesPerUnion[t.name]) == 1:
+                headers.add(CGHeaders.getDeclarationFilename(t))
+
             for f in t.flatMemberTypes:
                 addHeadersForType(f, providers)
 
     return (headers,
             CGWrapper(CGList(SortedDictValues(unionConversions), "\n"),
                       post="\n\n"))
 
 
@@ -3588,16 +3565,19 @@ class CGCycleCollectionTraverseForOwning
     def __init__(self, type):
         self.type = type
         args = [Argument("nsCycleCollectionTraversalCallback&", "aCallback"),
                 Argument("%s&" % CGUnionStruct.unionTypeName(type, True), "aUnion"),
                 Argument("const char*", "aName"),
                 Argument("uint32_t", "aFlags", "0")]
         CGAbstractMethod.__init__(self, None, "ImplCycleCollectionTraverse", "void", args)
 
+    def deps(self):
+        return self.type.getDeps()
+
     def definition_body(self):
         memberNames = [getUnionMemberName(t)
                        for t in self.type.flatMemberTypes
                        if idlTypeNeedsCycleCollection(t)]
         assert memberNames
 
         conditionTemplate = 'aUnion.Is%s()'
         functionCallTemplate = 'ImplCycleCollectionTraverse(aCallback, aUnion.GetAs%s(), "m%s", aFlags);\n'
@@ -3609,19 +3589,23 @@ class CGCycleCollectionTraverseForOwning
         return CGElseChain(ifStaments).define()
 
 
 class CGCycleCollectionUnlinkForOwningUnionMethod(CGAbstractMethod):
     """
     ImplCycleCollectionUnlink for owning union type.
     """
     def __init__(self, type):
+        self.type = type
         args = [Argument("%s&" % CGUnionStruct.unionTypeName(type, True), "aUnion")]
         CGAbstractMethod.__init__(self, None, "ImplCycleCollectionUnlink", "void", args)
 
+    def deps(self):
+        return self.type.getDeps()
+
     def definition_body(self):
         return "aUnion.Uninit();\n"
 
 
 builtinNames = {
     IDLType.Tags.bool: 'bool',
     IDLType.Tags.int8: 'int8_t',
     IDLType.Tags.int16: 'int16_t',
@@ -8684,16 +8668,19 @@ class CGUnionStruct(CGThing):
         self.struct = self.getStruct()
 
     def declare(self):
         return self.struct.declare()
 
     def define(self):
         return self.struct.define()
 
+    def deps(self):
+        return self.type.getDeps()
+
     def getStruct(self):
 
         members = [ClassMember("mType", "Type", body="eUninitialized"),
                    ClassMember("mValue", "Value")]
         ctor = ClassConstructor([], bodyInHeader=True, visibility="public",
                                 explicit=True)
 
         methods = []
@@ -9041,17 +9028,19 @@ class CGUnionConversionStruct(CGThing):
 
         return CGClass(structName + "Argument",
                        members=members,
                        constructors=[ctor],
                        methods=methods,
                        disallowCopyConstruction=True).declare()
 
     def define(self):
-        return "\n"
+        return ""
+    def deps(self):
+        return set()
 
 
 class ClassItem:
     """ Use with CGClass """
     def __init__(self, name, visibility):
         self.name = name
         self.visibility = visibility
 
@@ -11852,33 +11841,16 @@ class CGDictionary(CGThing):
         return ("'%s' member of %s" %
                 (member.identifier.name, self.dictionary.identifier.name))
 
     @staticmethod
     def makeIdName(name):
         return IDLToCIdentifier(name) + "_id"
 
     @staticmethod
-    def getDictionaryDependenciesFromType(type):
-        if type.isDictionary():
-            return set([type.unroll().inner])
-        if type.isSequence() or type.isArray():
-            return CGDictionary.getDictionaryDependenciesFromType(type.unroll())
-        return set()
-
-    @staticmethod
-    def getDictionaryDependencies(dictionary):
-        deps = set()
-        if dictionary.parent:
-            deps.add(dictionary.parent)
-        for member in dictionary.members:
-            deps |= CGDictionary.getDictionaryDependenciesFromType(member.type)
-        return deps
-
-    @staticmethod
     def isDictionaryCopyConstructible(dictionary):
         if (dictionary.parent and
             not CGDictionary.isDictionaryCopyConstructible(dictionary.parent)):
             return False
         return all(isTypeCopyConstructible(m.type) for m in dictionary.members)
 
 
 class CGRegisterWorkerBindings(CGAbstractMethod):
@@ -12122,19 +12094,22 @@ class ForwardDeclarationBuilder:
 
     def build(self):
         return self._build(atTopLevel=True)
 
 
 class CGForwardDeclarations(CGWrapper):
     """
     Code generate the forward declarations for a header file.
+    additionalDeclarations is a list of tuples containing a classname and a
+    boolean. If the boolean is true we will declare a struct, otherwise we'll
+    declare a class.
     """
     def __init__(self, config, descriptors, mainCallbacks, workerCallbacks,
-                 dictionaries, callbackInterfaces):
+                 dictionaries, callbackInterfaces, additionalDeclarations=[]):
         builder = ForwardDeclarationBuilder()
 
         def forwardDeclareForType(t, workerness='both'):
             t = t.unroll()
             if t.isGeckoInterface():
                 name = t.inner.identifier.name
                 # Find and add the non-worker implementation, if any.
                 if workerness != 'workeronly':
@@ -12196,16 +12171,19 @@ class CGForwardDeclarations(CGWrapper):
                 forwardDeclareForType(t)
 
         for d in dictionaries:
             if len(d.members) > 0:
                 builder.addInMozillaDom(d.identifier.name + "Atoms", isStruct=True)
             for t in getTypesFromDictionary(d):
                 forwardDeclareForType(t)
 
+        for className, isStruct in additionalDeclarations:
+            builder.add(className, isStruct=isStruct)
+
         CGWrapper.__init__(self, builder.build())
 
 
 class CGBindingRoot(CGThing):
     """
     Root codegen class for binding generation. Instantiate the class, and call
     declare or define to generate header or cpp code (respectively).
     """
@@ -12217,16 +12195,27 @@ class CGBindingRoot(CGThing):
             'mozilla/ErrorResult.h',
             ),
             True)
 
         descriptors = config.getDescriptors(webIDLFile=webIDLFile,
                                             hasInterfaceOrInterfacePrototypeObject=True,
                                             skipGen=False)
 
+        unionTypes = UnionsForFile(config, webIDLFile)
+
+        (unionHeaders, unionImplheaders, unionDeclarations, traverseMethods,
+         unlinkMethods, unionStructs) = UnionTypes(unionTypes, config)
+
+        bindingDeclareHeaders.update(dict.fromkeys(unionHeaders, True))
+        bindingHeaders.update(dict.fromkeys(unionImplheaders, True))
+
+        bindingDeclareHeaders["mozilla/dom/UnionMember.h"] = len(unionStructs) > 0
+        bindingDeclareHeaders["mozilla/dom/BindingUtils.h"] = len(unionStructs) > 0
+
         def descriptorHasCrossOriginProperties(desc):
             def hasCrossOriginProperty(m):
                 props = memberProperties(m, desc)
                 return (props.isCrossOriginMethod or
                         props.isCrossOriginGetter or
                         props.isCrossOriginSetter)
 
             return any(hasCrossOriginProperty(m) for m in desc.interface.members)
@@ -12328,25 +12317,63 @@ class CGBindingRoot(CGThing):
         bindingHeaders["mozilla/dom/BindingDeclarations.h"] = (
             not hasCode and enums)
 
         bindingHeaders["WrapperFactory.h"] = descriptors
         bindingHeaders["mozilla/dom/DOMJSClass.h"] = descriptors
         bindingHeaders["mozilla/dom/ScriptSettings.h"] = dictionaries # AutoJSAPI
         bindingHeaders["xpcpublic.h"] = dictionaries ## xpc::UnprivilegedJunkScope
 
+        cgthings.extend(traverseMethods)
+        cgthings.extend(unlinkMethods)
+
         # Do codegen for all the dictionaries.  We have to be a bit careful
         # here, because we have to generate these in order from least derived
         # to most derived so that class inheritance works out.  We also have to
         # generate members before the dictionary that contains them.
-        cgthings.extend([CGDictionary(d, config.getDescriptorProvider(False))
-                         for d in
-                         dependencySortObjects(dictionaries,
-                                               CGDictionary.getDictionaryDependencies,
-                                               lambda d: d.identifier.name)])
+
+        def getDependenciesFromType(type):
+            if type.isDictionary():
+                return set([type.unroll().inner])
+            if type.isSequence() or type.isArray():
+                return getDependenciesFromType(type.unroll())
+            if type.isUnion():
+                return set([type.unroll()])
+            return set()
+
+        def getDependencies(unionTypeOrDictionary):
+            if isinstance(unionTypeOrDictionary, IDLDictionary):
+                deps = set()
+                if unionTypeOrDictionary.parent:
+                    deps.add(unionTypeOrDictionary.parent)
+                for member in unionTypeOrDictionary.members:
+                    deps |= getDependenciesFromType(member.type)
+                return deps
+
+            assert unionTypeOrDictionary.isType() and unionTypeOrDictionary.isUnion()
+            deps = set()
+            for member in unionTypeOrDictionary.flatMemberTypes:
+                deps |= getDependenciesFromType(member)
+            return deps
+
+        def getName(unionTypeOrDictionary):
+            if isinstance(unionTypeOrDictionary, IDLDictionary):
+                return unionTypeOrDictionary.identifier.name
+
+            assert unionTypeOrDictionary.isType() and unionTypeOrDictionary.isUnion()
+            return unionTypeOrDictionary.name
+
+        for t in dependencySortObjects(dictionaries + unionStructs, getDependencies, getName):
+            if t.isDictionary():
+                cgthings.append(CGDictionary(t, config.getDescriptorProvider(False)))
+            else:
+                assert t.isUnion()
+                # FIXME: Unions are broken in workers.  See bug 809899.
+                cgthings.append(CGUnionStruct(t, config.getDescriptorProvider(False)))
+                cgthings.append(CGUnionStruct(t, config.getDescriptorProvider(False), True))
 
         # Do codegen for all the callbacks.
         cgthings.extend(CGCallbackFunction(c, config.getDescriptorProvider(False))
                         for c in mainCallbacks)
 
         cgthings.extend(CGCallbackFunction(c, config.getDescriptorProvider(True))
                         for c in workerCallbacks if c not in mainCallbacks)
 
@@ -12372,17 +12399,18 @@ class CGBindingRoot(CGThing):
 
         # Wrap all of that in our namespaces.
         curr = CGNamespace.build(['mozilla', 'dom'],
                                  CGWrapper(curr, pre="\n"))
 
         curr = CGList([CGForwardDeclarations(config, descriptors,
                                              mainCallbacks, workerCallbacks,
                                              dictionaries,
-                                             callbackDescriptors + jsImplemented),
+                                             callbackDescriptors + jsImplemented,
+                                             additionalDeclarations=unionDeclarations),
                        curr],
                       "\n")
 
         # Add header includes.
         bindingHeaders = [header
                           for header, include in bindingHeaders.iteritems()
                           if include]
         bindingDeclareHeaders = [header
@@ -14479,78 +14507,61 @@ class GlobalGenRoots():
         # Add include guards.
         curr = CGIncludeGuard('ResolveSystemBinding', curr)
 
         # Done.
         return curr
 
     @staticmethod
     def UnionTypes(config):
-
-        (includes, implincludes,
-         declarations, unions) = UnionTypes(config.getDescriptors(),
-                                            config.getDictionaries(),
-                                            config.getCallbacks(),
-                                            config)
+        unionTypes = UnionsForFile(config, None)
+        (includes, implincludes, declarations,
+         traverseMethods, unlinkMethods,
+         unionStructs) = UnionTypes(unionTypes, config)
+
+        unions = CGList(traverseMethods +
+                        unlinkMethods +
+                        [CGUnionStruct(t, config.getDescriptorProvider(False)) for t in unionStructs] +
+                        [CGUnionStruct(t, config.getDescriptorProvider(False), True) for t in unionStructs],
+                        "\n")
+
         includes.add("mozilla/dom/OwningNonNull.h")
         includes.add("mozilla/dom/UnionMember.h")
         includes.add("mozilla/dom/BindingDeclarations.h")
         # Need BindingUtils.h for FakeString
         includes.add("mozilla/dom/BindingUtils.h")
         implincludes.add("mozilla/dom/PrimitiveConversions.h")
 
         # Wrap all of that in our namespaces.
         curr = CGNamespace.build(['mozilla', 'dom'], unions)
 
         curr = CGWrapper(curr, post='\n')
 
-        namespaces = []
-        stack = [CGList([])]
-        for clazz, isStruct in sorted(declarations):
-            elements = clazz.split("::")
-            clazz = CGClassForwardDeclare(elements.pop(), isStruct=isStruct)
-            i = 0
-            if len(elements) > 0:
-                common = min(len(namespaces), len(elements))
-                while i < common and namespaces[i] == elements[i]:
-                    i += 1
-
-            # pop all the namespaces that should be closed
-            namespaces = namespaces[:i]
-
-            # add all the namespaces that should be opened
-            for j, namespace in enumerate(elements[i:]):
-                namespaces.append(namespace)
-                # every CGNamespace that we add holds a CGList
-                list = CGList([])
-                # add the new namespace to the list on top of the stack
-                stack[i + j].append(CGNamespace(namespace, list))
-                # set the top of the namespace stack to the list of the new
-                # namespace
-                stack[i + j + 1:] = [list]
-
-            stack[len(elements)].append(clazz)
-
-        curr = CGList([stack[0], curr], "\n")
+        builder = ForwardDeclarationBuilder()
+        for className, isStruct in declarations:
+            builder.add(className, isStruct=isStruct)
+
+        curr = CGList([builder.build(), curr], "\n")
 
         curr = CGHeaders([], [], [], [], includes, implincludes, 'UnionTypes',
                          curr)
 
         # Add include guards.
         curr = CGIncludeGuard('UnionTypes', curr)
 
         # Done.
         return curr
 
     @staticmethod
     def UnionConversions(config):
-
-        headers, unions = UnionConversions(config.getDescriptors(),
-                                           config.getDictionaries(),
-                                           config.getCallbacks(),
+        unionTypes = []
+        for l in config.unionsPerFilename.itervalues():
+            unionTypes.extend(l)
+        unionTypes.sort(key=lambda u: u[0].name)
+        headers, unions = UnionConversions(unionTypes,
                                            config)
 
         # Wrap all of that in our namespaces.
         curr = CGNamespace.build(['mozilla', 'dom'], unions)
 
         curr = CGWrapper(curr, post='\n')
 
         headers.update(["nsDebug.h", "mozilla/dom/UnionTypes.h"])
@@ -15061,17 +15072,17 @@ class CGEventRoot(CGThing):
                                   'mozilla/dom/BindingUtils.h',
                               ],
                               [
                                   "%s.h" % interfaceName,
                                   "js/GCAPI.h",
                                   'mozilla/dom/Nullable.h',
                                   'nsDOMQS.h'
                               ],
-                              "", self.root)
+                              "", self.root, config)
 
         # And now some include guards
         self.root = CGIncludeGuard(interfaceName, self.root)
 
         self.root = CGWrapper(self.root, pre=AUTOGENERATED_WARNING_COMMENT)
 
         self.root = CGWrapper(self.root, pre=dedent("""
             /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -1,14 +1,15 @@
 # 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/.
 
 from WebIDL import IDLInterface, IDLExternalInterface, IDLImplementsStatement
 import os
+from collections import defaultdict
 
 autogenerated_comment = "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n"
 
 class Configuration:
     """
     Represents global configuration state based on IDL parse data and
     the configuration file.
     """
@@ -112,16 +113,62 @@ class Configuration:
                            self.getDescriptors(workers=True, isExternal=False, skipGen=False)):
             workerTypes |= set(getFlatTypes(getTypesFromDescriptor(descriptor)))
         (workerCallbacks, workerDictionaries) = findCallbacksAndDictionaries(workerTypes)
 
         self.dictionaries = [d for d in parseData if d.isDictionary()]
         self.callbacks = [c for c in parseData if
                           c.isCallback() and not c.isInterface()]
 
+        # Dictionary mapping from a union type name to a set of filenames where
+        # union types with that name are used.
+        self.filenamesPerUnion = defaultdict(set)
+
+        # Dictionary mapping from a filename to a list of tuples containing a
+        # type and descriptor for the union types used in that file. If a union
+        # type is used in multiple files then it will be added to the list
+        # for the None key. Note that the list contains a tuple for every use of
+        # a union type, so there can be multiple tuples with union types that
+        # have the same name.
+        self.unionsPerFilename = defaultdict(list)
+
+        for (t, descriptor, _) in getAllTypes(self.descriptors, self.dictionaries, self.callbacks):
+            if t.isMozMap():
+                t = t.inner
+            t = t.unroll()
+            if t.isUnion():
+                filenamesForUnion = self.filenamesPerUnion[t.name]
+                if t.filename() not in filenamesForUnion:
+                    if len(filenamesForUnion) == 0:
+                        # This is the first file that we found a union with this
+                        # name in, record the union as part of the file.
+                        uniqueFilenameForUnion = t.filename()
+                    else:
+                        # We already found a file that contains a union with
+                        # this name.
+                        if len(filenamesForUnion) == 1:
+                            # This is the first time we found a union with this
+                            # name in another file.
+                            for f in filenamesForUnion:
+                                # Filter out unions with this name from the
+                                # unions for the file where we previously found
+                                # them.
+                                unionsForFilename = self.unionsPerFilename[f]
+                                unionsForFilename = filter(lambda u: u[0].name != t.name,
+                                                           unionsForFilename)
+                                if len(unionsForFilename) == 0:
+                                    del self.unionsPerFilename[f]
+                                else:
+                                    self.unionsPerFilename[f] = unionsForFilename
+                        # Unions with this name appear in multiple files, record
+                        # the filename as None, so that we can detect that.
+                        uniqueFilenameForUnion = None
+                    self.unionsPerFilename[uniqueFilenameForUnion].append((t, descriptor))
+                    filenamesForUnion.add(t.filename())
+
         def flagWorkerOrMainThread(items, main, worker):
             for item in items:
                 if item in main:
                     item.setUserData("mainThread", True)
                 if item in worker:
                     item.setUserData("workers", True)
         flagWorkerOrMainThread(self.callbacks, mainCallbacks, workerCallbacks)
 
@@ -720,8 +767,27 @@ def findCallbacksAndDictionaries(inputTy
                     d = d.parent
         if len(unhandledTypes) != 0:
             doFindCallbacksAndDictionaries(unhandledTypes, callbacks, dictionaries)
 
     retCallbacks = set()
     retDictionaries = set()
     doFindCallbacksAndDictionaries(inputTypes, retCallbacks, retDictionaries)
     return (retCallbacks, retDictionaries)
+
+def getAllTypes(descriptors, dictionaries, callbacks):
+    """
+    Generate all the types we're dealing with.  For each type, a tuple
+    containing type, descriptor, dictionary is yielded.  The
+    descriptor and dictionary can be None if the type does not come
+    from a descriptor or dictionary; they will never both be non-None.
+    """
+    for d in descriptors:
+        if d.interface.isExternal():
+            continue
+        for t in getTypesFromDescriptor(d):
+            yield (t, d, None)
+    for dictionary in dictionaries:
+        for t in getTypesFromDictionary(dictionary):
+            yield (t, None, dictionary)
+    for callback in callbacks:
+        for t in getTypesFromCallback(callback):
+            yield (t, None, None)
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -2056,16 +2056,20 @@ class IDLUnionType(IDLType):
         self.hasNullableType = False
         self.hasDictionaryType = False
         self.flatMemberTypes = None
         self.builtin = False
 
     def __eq__(self, other):
         return isinstance(other, IDLUnionType) and self.memberTypes == other.memberTypes
 
+    def __hash__(self):
+        assert self.isComplete()
+        return self.name.__hash__()
+
     def isVoid(self):
         return False
 
     def isUnion(self):
         return True
 
     def isSerializable(self):
         return all(m.isSerializable() for m in self.memberTypes)
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -6,17 +6,16 @@
 
 #ifndef TestBindingHeader_h
 #define TestBindingHeader_h
 
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Date.h"
 #include "mozilla/dom/MozMap.h"
 #include "mozilla/dom/TypedArray.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "mozilla/ErrorResult.h"
 #include "nsCOMPtr.h"
 #include "nsGenericHTMLElement.h"
 #include "nsWrapperCache.h"
 
 // Forward declare this before we include TestCodeGenBinding.h, because that header relies on including
 // this one for it, for ParentDict. Hopefully it won't begin to rely on it in more fundamental ways.
 namespace mozilla {
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -941,17 +941,17 @@ dictionary Dict : ParentDict {
   unrestricted double  negativeInfUrDouble = -Infinity;
   unrestricted double  nanUrDouble = NaN;
 
   (float or DOMString) floatOrString = "str";
   (object or long) objectOrLong;
 #ifdef DEBUG
   (EventInit or long) eventInitOrLong;
   (EventInit or long)? nullableEventInitOrLong;
-  (Node or long)? nullableNodeOrLong;
+  (HTMLElement or long)? nullableHTMLElementOrLong;
   // CustomEventInit is useful to test because it needs rooting.
   (CustomEventInit or long) eventInitOrLong2;
   (CustomEventInit or long)? nullableEventInitOrLong2;
   (EventInit or long) eventInitOrLongWithDefaultValue = null;
   (CustomEventInit or long) eventInitOrLongWithDefaultValue2 = null;
   (EventInit or long) eventInitOrLongWithDefaultValue3 = 5;
   (CustomEventInit or long) eventInitOrLongWithDefaultValue4 = 5;
   (sequence<object> or long) objectSequenceOrLong;
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -8,17 +8,18 @@
  Constructor(unsigned long num, boolean? boolArg),
  Constructor(TestInterface? iface),
  Constructor(long arg1, IndirectlyImplementedInterface iface),
  // Constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3),
  NamedConstructor=Example,
  NamedConstructor=Example(DOMString str),
  NamedConstructor=Example2(DictForConstructor dict, any any1, object obj1,
                            object? obj2, sequence<Dict> seq, optional any any2,
-                           optional object obj3, optional object? obj4)
+                           optional object obj3, optional object? obj4),
+ NamedConstructor=Example2((long or MozMap<any>) arg1)
  ]
 interface TestExampleInterface {
   // Integer types
   // XXXbz add tests for throwing versions of all the integer stuff
   readonly attribute byte readonlyByte;
   attribute byte writableByte;
   void passByte(byte arg);
   byte receiveByte();
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -93,17 +93,16 @@
 #include "mozilla/unused.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 #include "mozilla/dom/HTMLImageElement.h"
 #include "mozilla/dom/HTMLVideoElement.h"
 #include "mozilla/dom/SVGMatrix.h"
 #include "mozilla/dom/TextMetrics.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/SVGMatrix.h"
 #include "mozilla/FloatingPoint.h"
 #include "nsGlobalWindow.h"
 #include "GLContext.h"
 #include "GLContextProvider.h"
 #include "SVGContentUtils.h"
 #include "SVGImageContext.h"
 #include "nsIScreenManager.h"
--- a/dom/events/JSEventHandler.cpp
+++ b/dom/events/JSEventHandler.cpp
@@ -18,17 +18,16 @@
 #include "nsDOMJSUtils.h"
 #include "WorkerPrivate.h"
 #include "mozilla/ContentEvents.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/HoldDropJSObjects.h"
 #include "mozilla/JSEventHandler.h"
 #include "mozilla/Likely.h"
 #include "mozilla/dom/ErrorEvent.h"
-#include "mozilla/dom/UnionTypes.h"
 
 namespace mozilla {
 
 using namespace dom;
 
 JSEventHandler::JSEventHandler(nsISupports* aTarget,
                                nsIAtom* aType,
                                const TypedEventHandler& aTypedHandler)
--- a/dom/events/MessageEvent.cpp
+++ b/dom/events/MessageEvent.cpp
@@ -3,17 +3,16 @@
  * 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/. */
 
 #include "mozilla/dom/MessageEvent.h"
 #include "mozilla/dom/MessageEventBinding.h"
 #include "mozilla/dom/MessagePort.h"
 #include "mozilla/dom/MessagePortBinding.h"
 #include "mozilla/dom/MessagePortList.h"
-#include "mozilla/dom/UnionTypes.h"
 
 #include "mozilla/HoldDropJSObjects.h"
 #include "jsapi.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(MessageEvent)
--- a/dom/fetch/Fetch.h
+++ b/dom/fetch/Fetch.h
@@ -1,23 +1,28 @@
 /* -*- 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/. */
 
 #ifndef mozilla_dom_Fetch_h
 #define mozilla_dom_Fetch_h
 
-#include "mozilla/dom/UnionTypes.h"
+#include "nsCOMPtr.h"
+#include "nsError.h"
+#include "nsString.h"
+#include "mozilla/ErrorResult.h"
 
 class nsIInputStream;
 
 namespace mozilla {
 namespace dom {
 
+class ArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams;
+class OwningArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams;
 class Promise;
 
 /*
  * Creates an nsIInputStream based on the fetch specifications 'extract a byte
  * stream algorithm' - http://fetch.spec.whatwg.org/#concept-bodyinit-extract.
  * Stores content type in out param aContentType.
  */
 nsresult
--- a/dom/fetch/Headers.h
+++ b/dom/fetch/Headers.h
@@ -3,33 +3,33 @@
 /* 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/. */
 
 #ifndef mozilla_dom_Headers_h
 #define mozilla_dom_Headers_h
 
 #include "mozilla/dom/HeadersBinding.h"
-#include "mozilla/dom/UnionTypes.h"
 
 #include "nsClassHashtable.h"
 #include "nsWrapperCache.h"
 
 #include "InternalHeaders.h"
 
 class nsPIDOMWindow;
 
 namespace mozilla {
 
 class ErrorResult;
 
 namespace dom {
 
 template<typename T> class MozMap;
 class HeadersOrByteStringSequenceSequenceOrByteStringMozMap;
+class OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap;
 
 /**
  * This Headers class is only used to represent the content facing Headers
  * object. It is actually backed by an InternalHeaders implementation. Gecko
  * code should NEVER use this, except in the Request and Response
  * implementations, where they must always be created from the backing
  * InternalHeaders object.
  */
--- a/dom/fetch/InternalRequest.h
+++ b/dom/fetch/InternalRequest.h
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_InternalRequest_h
 #define mozilla_dom_InternalRequest_h
 
 #include "mozilla/dom/HeadersBinding.h"
 #include "mozilla/dom/InternalHeaders.h"
 #include "mozilla/dom/RequestBinding.h"
-#include "mozilla/dom/UnionTypes.h"
 
 #include "nsIContentPolicy.h"
 #include "nsIInputStream.h"
 #include "nsISupportsImpl.h"
 
 class nsIDocument;
 class nsPIDOMWindow;
 
--- a/dom/fetch/Request.h
+++ b/dom/fetch/Request.h
@@ -9,26 +9,26 @@
 #include "nsISupportsImpl.h"
 #include "nsWrapperCache.h"
 
 #include "mozilla/dom/Fetch.h"
 #include "mozilla/dom/InternalRequest.h"
 // Required here due to certain WebIDL enums/classes being declared in both
 // files.
 #include "mozilla/dom/RequestBinding.h"
-#include "mozilla/dom/UnionTypes.h"
 
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 
 class Headers;
 class InternalHeaders;
 class Promise;
+class RequestOrScalarValueString;
 
 class Request MOZ_FINAL : public nsISupports
                         , public nsWrapperCache
                         , public FetchBody<Request>
 {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Request)
 
--- a/dom/fetch/Response.cpp
+++ b/dom/fetch/Response.cpp
@@ -5,16 +5,17 @@
 
 #include "Response.h"
 
 #include "nsISupportsImpl.h"
 #include "nsIURI.h"
 #include "nsPIDOMWindow.h"
 
 #include "mozilla/ErrorResult.h"
+#include "mozilla/dom/FetchBinding.h"
 #include "mozilla/dom/Headers.h"
 #include "mozilla/dom/Promise.h"
 
 #include "nsDOMString.h"
 
 #include "InternalResponse.h"
 
 namespace mozilla {
--- a/dom/fetch/Response.h
+++ b/dom/fetch/Response.h
@@ -6,25 +6,25 @@
 #ifndef mozilla_dom_Response_h
 #define mozilla_dom_Response_h
 
 #include "nsWrapperCache.h"
 #include "nsISupportsImpl.h"
 
 #include "mozilla/dom/Fetch.h"
 #include "mozilla/dom/ResponseBinding.h"
-#include "mozilla/dom/UnionTypes.h"
 
 #include "InternalResponse.h"
 
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 
+class ArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams;
 class Headers;
 class InternalHeaders;
 class Promise;
 
 class Response MOZ_FINAL : public nsISupports
                          , public nsWrapperCache
                          , public FetchBody<Response>
 {
--- a/dom/filesystem/Directory.cpp
+++ b/dom/filesystem/Directory.cpp
@@ -12,17 +12,16 @@
 #include "GetFileOrDirectoryTask.h"
 #include "RemoveTask.h"
 
 #include "nsCharSeparatedTokenizer.h"
 #include "nsString.h"
 #include "mozilla/dom/DirectoryBinding.h"
 #include "mozilla/dom/FileSystemBase.h"
 #include "mozilla/dom/FileSystemUtils.h"
-#include "mozilla/dom/UnionTypes.h"
 
 // Resolve the name collision of Microsoft's API name with macros defined in
 // Windows header files. Undefine the macro of CreateDirectory to avoid
 // Directory#CreateDirectory being replaced by Directory#CreateDirectoryW.
 #ifdef CreateDirectory
 #undef CreateDirectory
 #endif
 // Undefine the macro of CreateFile to avoid Directory#CreateFile being replaced
--- a/dom/icc/Icc.h
+++ b/dom/icc/Icc.h
@@ -1,26 +1,26 @@
 /* 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/. */
 
 #ifndef mozilla_dom_Icc_h
 #define mozilla_dom_Icc_h
 
 #include "mozilla/dom/MozIccBinding.h" // For IccCardState
-#include "mozilla/dom/UnionTypes.h"
 #include "mozilla/DOMEventTargetHelper.h"
 
 class nsIIccInfo;
 class nsIIccProvider;
 
 namespace mozilla {
 namespace dom {
 
 class DOMRequest;
+class OwningMozIccInfoOrMozGsmIccInfoOrMozCdmaIccInfo;
 
 class Icc MOZ_FINAL : public DOMEventTargetHelper
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Icc, DOMEventTargetHelper)
   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper)
 
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -16,17 +16,16 @@
 #include "IDBTransaction.h"
 #include "mozilla/ContentEvents.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/dom/DOMError.h"
 #include "mozilla/dom/ErrorEventBinding.h"
 #include "mozilla/dom/IDBOpenDBRequestBinding.h"
 #include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsIScriptContext.h"
 #include "nsJSUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsString.h"
 #include "ReportInternalError.h"
 
--- a/dom/ipc/StructuredCloneUtils.cpp
+++ b/dom/ipc/StructuredCloneUtils.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "StructuredCloneUtils.h"
 
 #include "nsIDOMDOMException.h"
 #include "nsIMutable.h"
 #include "nsIXPConnect.h"
 
+#include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/BlobBinding.h"
 #include "mozilla/dom/File.h"
 #include "nsContentUtils.h"
 #include "nsJSEnvironment.h"
 #include "MainThreadUtils.h"
 #include "StructuredCloneTags.h"
 #include "jsapi.h"
 
--- a/dom/mobilemessage/DOMMobileMessageError.cpp
+++ b/dom/mobilemessage/DOMMobileMessageError.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "DOMMobileMessageError.h"
 #include "mozilla/dom/DOMMobileMessageErrorBinding.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "nsIDOMMozMmsMessage.h"
 #include "nsIDOMMozSmsMessage.h"
 
 using namespace mozilla::dom;
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMMobileMessageError)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMMobileMessageError, DOMError)
--- a/dom/mobilemessage/MobileMessageManager.h
+++ b/dom/mobilemessage/MobileMessageManager.h
@@ -2,32 +2,32 @@
 /* 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/. */
 
 #ifndef mozilla_dom_mobilemessage_MobileMessageManager_h
 #define mozilla_dom_mobilemessage_MobileMessageManager_h
 
 #include "mozilla/Attributes.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "nsIObserver.h"
 
 class nsISmsService;
 class nsIDOMMozSmsMessage;
 class nsIDOMMozMmsMessage;
 
 namespace mozilla {
 namespace dom {
 
 class DOMRequest;
 class DOMCursor;
 struct MmsParameters;
 struct MmsSendParameters;
 struct MobileMessageFilter;
+class OwningLongOrMozSmsMessageOrMozMmsMessage;
 struct SmsSendParameters;
 
 class MobileMessageManager MOZ_FINAL : public DOMEventTargetHelper
                                      , public nsIObserver
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIOBSERVER
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -6,17 +6,16 @@
 
 #include "Telephony.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/CallEvent.h"
 #include "mozilla/dom/MozMobileConnectionBinding.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/TelephonyBinding.h"
-#include "mozilla/dom/UnionTypes.h"
 
 #include "nsCharSeparatedTokenizer.h"
 #include "nsContentUtils.h"
 #include "nsIPermissionManager.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsPIDOMWindow.h"
 #include "nsServiceManagerUtils.h"
--- a/dom/workers/WorkerScope.h
+++ b/dom/workers/WorkerScope.h
@@ -5,24 +5,24 @@
 
 #ifndef mozilla_dom_workerscope_h__
 #define mozilla_dom_workerscope_h__
 
 #include "Workers.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/dom/Headers.h"
 #include "mozilla/dom/RequestBinding.h"
-#include "mozilla/dom/UnionTypes.h"
 
 namespace mozilla {
 namespace dom {
 
 class Console;
 class Function;
 class Promise;
+class RequestOrScalarValueString;
 
 } // namespace dom
 } // namespace mozilla
 
 BEGIN_WORKERS_NAMESPACE
 
 class WorkerPrivate;
 class WorkerLocation;