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 235521 18d8629e20c9f73dbe025650106786bb466f4fe6
parent 235520 f76047f574306287f4331ebb7ff4f90f3b81cba1
child 235522 62ac7c28ddae3742c32daafe3198a9c6965ead83
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1068740
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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;