Merge mozilla-inbound to mozilla-central. a=merge
authorDorel Luca <dluca@mozilla.com>
Wed, 23 May 2018 12:51:22 +0300
changeset 419471 d36cd8bdbc5c0df1d1d7a167f5fedb95c3a3648e
parent 419470 bdb0b4d7712dc14d3a5f0d0b644adbedd40144b2 (current diff)
parent 419469 133a13c44abedac2e448d315a32068ce1a5568f4 (diff)
child 419472 36f53876b1394117627154d711973da14a1d0163
child 419619 925d7213d2f7ef0f6fc0859634b7eed19b34054f
push id64331
push userdluca@mozilla.com
push dateWed, 23 May 2018 10:03:55 +0000
treeherderautoland@36f53876b139 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone62.0a1
first release with
nightly linux32
d36cd8bdbc5c / 62.0a1 / 20180523100147 / files
nightly linux64
d36cd8bdbc5c / 62.0a1 / 20180523100147 / files
nightly mac
d36cd8bdbc5c / 62.0a1 / 20180523100147 / files
nightly win32
d36cd8bdbc5c / 62.0a1 / 20180523100147 / files
nightly win64
d36cd8bdbc5c / 62.0a1 / 20180523100147 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-inbound to mozilla-central. a=merge
browser/components/preferences/handlers.xml
dom/file/nsIDOMBlob.idl
editor/libeditor/HTMLEditorDataTransfer.cpp
gfx/angle/checkout/src/compiler/translator/AddAndTrueToLoopCondition.cpp
gfx/angle/checkout/src/compiler/translator/AddAndTrueToLoopCondition.h
gfx/angle/checkout/src/compiler/translator/AddDefaultReturnStatements.cpp
gfx/angle/checkout/src/compiler/translator/AddDefaultReturnStatements.h
gfx/angle/checkout/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
gfx/angle/checkout/src/compiler/translator/ArrayReturnValueToOutParameter.h
gfx/angle/checkout/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
gfx/angle/checkout/src/compiler/translator/BreakVariableAliasingInInnerLoops.h
gfx/angle/checkout/src/compiler/translator/ClampFragDepth.cpp
gfx/angle/checkout/src/compiler/translator/ClampFragDepth.h
gfx/angle/checkout/src/compiler/translator/ClampPointSize.cpp
gfx/angle/checkout/src/compiler/translator/ClampPointSize.h
gfx/angle/checkout/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp
gfx/angle/checkout/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h
gfx/angle/checkout/src/compiler/translator/DeferGlobalInitializers.cpp
gfx/angle/checkout/src/compiler/translator/DeferGlobalInitializers.h
gfx/angle/checkout/src/compiler/translator/EmulateGLFragColorBroadcast.cpp
gfx/angle/checkout/src/compiler/translator/EmulateGLFragColorBroadcast.h
gfx/angle/checkout/src/compiler/translator/EmulatePrecision.cpp
gfx/angle/checkout/src/compiler/translator/EmulatePrecision.h
gfx/angle/checkout/src/compiler/translator/ExpandIntegerPowExpressions.cpp
gfx/angle/checkout/src/compiler/translator/ExpandIntegerPowExpressions.h
gfx/angle/checkout/src/compiler/translator/FindMain.cpp
gfx/angle/checkout/src/compiler/translator/FindMain.h
gfx/angle/checkout/src/compiler/translator/FindSymbolNode.cpp
gfx/angle/checkout/src/compiler/translator/FindSymbolNode.h
gfx/angle/checkout/src/compiler/translator/FoldExpressions.cpp
gfx/angle/checkout/src/compiler/translator/FoldExpressions.h
gfx/angle/checkout/src/compiler/translator/InitializeVariables.cpp
gfx/angle/checkout/src/compiler/translator/InitializeVariables.h
gfx/angle/checkout/src/compiler/translator/IntermNodePatternMatcher.cpp
gfx/angle/checkout/src/compiler/translator/IntermNodePatternMatcher.h
gfx/angle/checkout/src/compiler/translator/IntermNode_util.cpp
gfx/angle/checkout/src/compiler/translator/IntermNode_util.h
gfx/angle/checkout/src/compiler/translator/IntermTraverse.cpp
gfx/angle/checkout/src/compiler/translator/IntermTraverse.h
gfx/angle/checkout/src/compiler/translator/NodeSearch.h
gfx/angle/checkout/src/compiler/translator/ParamType.h
gfx/angle/checkout/src/compiler/translator/PruneNoOps.cpp
gfx/angle/checkout/src/compiler/translator/PruneNoOps.h
gfx/angle/checkout/src/compiler/translator/RecordConstantPrecision.cpp
gfx/angle/checkout/src/compiler/translator/RecordConstantPrecision.h
gfx/angle/checkout/src/compiler/translator/RegenerateStructNames.cpp
gfx/angle/checkout/src/compiler/translator/RegenerateStructNames.h
gfx/angle/checkout/src/compiler/translator/RemoveArrayLengthMethod.cpp
gfx/angle/checkout/src/compiler/translator/RemoveArrayLengthMethod.h
gfx/angle/checkout/src/compiler/translator/RemoveDynamicIndexing.cpp
gfx/angle/checkout/src/compiler/translator/RemoveDynamicIndexing.h
gfx/angle/checkout/src/compiler/translator/RemoveEmptySwitchStatements.cpp
gfx/angle/checkout/src/compiler/translator/RemoveEmptySwitchStatements.h
gfx/angle/checkout/src/compiler/translator/RemoveInvariantDeclaration.cpp
gfx/angle/checkout/src/compiler/translator/RemoveInvariantDeclaration.h
gfx/angle/checkout/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp
gfx/angle/checkout/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h
gfx/angle/checkout/src/compiler/translator/RemovePow.cpp
gfx/angle/checkout/src/compiler/translator/RemovePow.h
gfx/angle/checkout/src/compiler/translator/RemoveSwitchFallThrough.cpp
gfx/angle/checkout/src/compiler/translator/RemoveSwitchFallThrough.h
gfx/angle/checkout/src/compiler/translator/RemoveUnreferencedVariables.cpp
gfx/angle/checkout/src/compiler/translator/RemoveUnreferencedVariables.h
gfx/angle/checkout/src/compiler/translator/ReplaceVariable.cpp
gfx/angle/checkout/src/compiler/translator/ReplaceVariable.h
gfx/angle/checkout/src/compiler/translator/RewriteDoWhile.cpp
gfx/angle/checkout/src/compiler/translator/RewriteDoWhile.h
gfx/angle/checkout/src/compiler/translator/RewriteElseBlocks.cpp
gfx/angle/checkout/src/compiler/translator/RewriteElseBlocks.h
gfx/angle/checkout/src/compiler/translator/RewriteTexelFetchOffset.cpp
gfx/angle/checkout/src/compiler/translator/RewriteTexelFetchOffset.h
gfx/angle/checkout/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp
gfx/angle/checkout/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h
gfx/angle/checkout/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp
gfx/angle/checkout/src/compiler/translator/RewriteUnaryMinusOperatorInt.h
gfx/angle/checkout/src/compiler/translator/RunAtTheEndOfShader.cpp
gfx/angle/checkout/src/compiler/translator/RunAtTheEndOfShader.h
gfx/angle/checkout/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
gfx/angle/checkout/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
gfx/angle/checkout/src/compiler/translator/SeparateArrayConstructorStatements.cpp
gfx/angle/checkout/src/compiler/translator/SeparateArrayConstructorStatements.h
gfx/angle/checkout/src/compiler/translator/SeparateArrayInitialization.cpp
gfx/angle/checkout/src/compiler/translator/SeparateArrayInitialization.h
gfx/angle/checkout/src/compiler/translator/SeparateDeclarations.cpp
gfx/angle/checkout/src/compiler/translator/SeparateDeclarations.h
gfx/angle/checkout/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
gfx/angle/checkout/src/compiler/translator/SeparateExpressionsReturningArrays.h
gfx/angle/checkout/src/compiler/translator/SimplifyLoopConditions.cpp
gfx/angle/checkout/src/compiler/translator/SimplifyLoopConditions.h
gfx/angle/checkout/src/compiler/translator/SplitSequenceOperator.cpp
gfx/angle/checkout/src/compiler/translator/SplitSequenceOperator.h
gfx/angle/checkout/src/compiler/translator/StaticType.cpp
gfx/angle/checkout/src/compiler/translator/UnfoldShortCircuitAST.cpp
gfx/angle/checkout/src/compiler/translator/UnfoldShortCircuitAST.h
gfx/angle/checkout/src/compiler/translator/UnfoldShortCircuitToIf.cpp
gfx/angle/checkout/src/compiler/translator/UnfoldShortCircuitToIf.h
gfx/angle/checkout/src/compiler/translator/UseInterfaceBlockFields.cpp
gfx/angle/checkout/src/compiler/translator/UseInterfaceBlockFields.h
gfx/angle/checkout/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp
gfx/angle/checkout/src/compiler/translator/VectorizeVectorScalarArithmetic.h
gfx/angle/checkout/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp
gfx/angle/checkout/src/compiler/translator/WrapSwitchStatementsInBlocks.h
gfx/angle/checkout/src/libANGLE/signal_utils.cpp
gfx/angle/checkout/src/libANGLE/signal_utils.h
gfx/angle/cherries.log
js/src/wasm/WasmCompartment.cpp
js/src/wasm/WasmCompartment.h
layout/generic/nsFrame.cpp
testing/mozharness/external_tools/clobberer.py
testing/mozharness/mozharness/mozilla/blob_upload.py
testing/mozharness/mozharness/mozilla/purge.py
testing/mozharness/scripts/desktop_partner_repacks.py
testing/mozharness/test/test_mozilla_blob_upload.py
testing/web-platform/meta/beacon/beacon-navigate.html.ini
testing/web-platform/meta/console/console-counting-label-conversion.any.js.ini
testing/web-platform/meta/content-security-policy/navigate-to/child-navigates-parent-blocked.html.ini
testing/web-platform/meta/content-security-policy/navigate-to/form-blocked.html.ini
testing/web-platform/meta/content-security-policy/navigate-to/href-location-blocked.html.ini
testing/web-platform/meta/content-security-policy/navigate-to/link-click-blocked.html.ini
testing/web-platform/meta/content-security-policy/navigate-to/meta-refresh-blocked.html.ini
testing/web-platform/meta/svg/foreignobject/position-svg-root-in-foreign-object.html.ini
testing/web-platform/tests/content-security-policy/navigate-to/child-navigates-parent-blocked.html
testing/web-platform/tests/content-security-policy/navigate-to/child-navigates-parent-blocked.html.headers
testing/web-platform/tests/content-security-policy/navigate-to/form-blocked.html
testing/web-platform/tests/content-security-policy/navigate-to/href-location-blocked.html
testing/web-platform/tests/content-security-policy/navigate-to/link-click-blocked.html
testing/web-platform/tests/content-security-policy/navigate-to/meta-refresh-blocked.html
testing/web-platform/tests/content-security-policy/navigate-to/parent-navigates-child-blocked.html.headers
testing/web-platform/tests/css/css-color/t451-system-colors-a.xht
testing/web-platform/tests/svg/foreignobject/foreign-object-circular-filter-reference-crash.html
testing/web-platform/tests/svg/foreignobject/position-svg-root-in-foreign-object-ref.html
testing/web-platform/tests/svg/foreignobject/position-svg-root-in-foreign-object.html
testing/web-platform/tests/workers/semantics/structured-clone/common.js
testing/web-platform/tests/workers/semantics/structured-clone/dedicated.js
testing/web-platform/tests/workers/semantics/structured-clone/shared.js
testing/web-platform/tests/workers/semantics/structured-clone/worker-common.js
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -93,19 +93,17 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(Accessibl
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Accessible)
   tmp->Shutdown();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Accessible)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent, mDoc)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Accessible)
-  if (aIID.Equals(NS_GET_IID(Accessible)))
-    foundInterface = this;
-  else
+  NS_INTERFACE_MAP_ENTRY_CONCRETE(Accessible)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, Accessible)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Accessible)
 NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(Accessible, LastRelease())
 
 Accessible::Accessible(nsIContent* aContent, DocAccessible* aDoc) :
   mContent(aContent), mDoc(aDoc),
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -1243,38 +1243,47 @@ toolbarpaletteitem[dragover] {
   flex-shrink: 0;
   flex-wrap: wrap;
 }
 
 #customization-toolbar-visibility-button > .box-inherit > .button-menu-dropmarker {
   display: -moz-box;
 }
 
+toolbarpaletteitem {
+  -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbarpaletteitem");
+}
+
 toolbarpaletteitem[place="palette"] {
-  -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbarpaletteitem-palette-wrapping-label");
+  -moz-box-orient: vertical;
   width: 7em;
   /* icon (16) + margin (9 + 12) + 3 lines of text: */
   height: calc(39px + 3em);
   margin-bottom: 5px;
   margin-inline-end: 24px;
   overflow: visible;
   display: inline-block;
   vertical-align: top;
 }
 
+toolbarpaletteitem:not([place="palette"]) > .toolbarpaletteitem-label,
 toolbarpaletteitem[place="palette"][hidden] {
   display: none;
 }
 
-#customization-palette .toolbarpaletteitem-box {
+toolbarpaletteitem[place="palette"] > .toolbarpaletteitem-box {
   -moz-box-pack: center;
   width: 7em;
   max-width: 7em;
 }
 
+toolbarpaletteitem:not([place="palette"]) > .toolbarpaletteitem-box {
+  -moz-box-flex: 1;
+}
+
 #main-window[customizing=true] .addon-banner-item,
 #main-window[customizing=true] .panel-banner-item {
   display: none;
 }
 
 /* UI Tour */
 
 @keyframes uitour-wobble {
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -148,19 +148,21 @@ var whitelist = [
   {file: "resource://gre/modules/PerfMeasurement.jsm"},
   // Bug 1356045
   {file: "chrome://global/content/test-ipc.xul"},
   // Bug 1356036
   {file: "resource://gre/modules/PerformanceWatcher-content.js"},
   {file: "resource://gre/modules/PerformanceWatcher.jsm"},
   // Bug 1378173 (warning: still used by devtools)
   {file: "resource://gre/modules/Promise.jsm"},
-
   // Still used by WebIDE, which is going away but not entirely gone.
   {file: "resource://gre/modules/ZipUtils.jsm"},
+  // Bug 1463225 (on Mac this is only used by a test)
+  {file: "chrome://global/content/bindings/toolbar.xml",
+   platforms: ["macosx"]},
 ];
 
 whitelist = new Set(whitelist.filter(item =>
   ("isFromDevTools" in item) == isDevtools &&
   (!item.skipUnofficial || !AppConstants.MOZILLA_OFFICIAL) &&
   (!item.platforms || item.platforms.includes(AppConstants.platform))
 ).map(item => item.file));
 
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -814,19 +814,17 @@ CustomizeMode.prototype = {
 
   createOrUpdateWrapper(aNode, aPlace, aIsUpdate) {
     let wrapper;
     if (aIsUpdate && aNode.parentNode && aNode.parentNode.localName == "toolbarpaletteitem") {
       wrapper = aNode.parentNode;
       aPlace = wrapper.getAttribute("place");
     } else {
       wrapper = this.document.createElement("toolbarpaletteitem");
-      // "place" is used by toolkit to add the toolbarpaletteitem-palette
-      // binding to a toolbarpaletteitem, which gives it a label node for when
-      // it's sitting in the palette.
+      // "place" is used to show the label when it's sitting in the palette.
       wrapper.setAttribute("place", aPlace);
     }
 
 
     // Ensure the wrapped item doesn't look like it's in any special state, and
     // can't be interactved with when in the customization palette.
     // Note that some buttons opt out of this with the
     // keepbroadcastattributeswhencustomizing attribute.
--- a/browser/components/customizableui/content/toolbar.xml
+++ b/browser/components/customizableui/content/toolbar.xml
@@ -317,9 +317,18 @@
             draggableThis.mouseDownCheck = function(e) {
               return this._dragBindingAlive;
             };
           } catch (e) {}
         }
       ]]></constructor>
     </implementation>
   </binding>
+
+  <binding id="toolbarpaletteitem">
+    <content>
+      <xul:hbox class="toolbarpaletteitem-box">
+        <children/>
+      </xul:hbox>
+      <xul:label class="toolbarpaletteitem-label" xbl:inherits="xbl:text=title"/>
+    </content>
+  </binding>
 </bindings>
--- a/browser/components/migration/FirefoxProfileMigrator.js
+++ b/browser/components/migration/FirefoxProfileMigrator.js
@@ -243,17 +243,17 @@ FirefoxProfileMigrator.prototype._getRes
       let dataReportingDir = this._getFileObject(sourceProfileDir, "datareporting");
       if (dataReportingDir && dataReportingDir.isDirectory()) {
         // Copy only specific files.
         let toCopy = ["state.json", "session-state.json"];
 
         let dest = createSubDir("datareporting");
         let enumerator = dataReportingDir.directoryEntries;
         while (enumerator.hasMoreElements()) {
-          let file = enumerator.getNext().QueryInterface(Ci.nsIFile);
+          let file = enumerator.nextFile;
           if (file.isDirectory() || !toCopy.includes(file.leafName)) {
             continue;
           }
           file.copyTo(dest, "");
         }
       }
 
       aCallback(true);
--- a/browser/components/migration/MSMigrationUtils.jsm
+++ b/browser/components/migration/MSMigrationUtils.jsm
@@ -286,18 +286,17 @@ function getEdgeLocalDataFolder() {
     if (edgeDir.exists() && edgeDir.isReadable() && edgeDir.isDirectory()) {
       gEdgeDir = edgeDir;
       return edgeDir.clone();
     }
 
     // Let's try the long way:
     let dirEntries = packages.directoryEntries;
     while (dirEntries.hasMoreElements()) {
-      let subDir = dirEntries.getNext();
-      subDir.QueryInterface(Ci.nsIFile);
+      let subDir = dirEntries.nextFile;
       if (subDir.leafName.startsWith("Microsoft.MicrosoftEdge") && subDir.isReadable() &&
           subDir.isDirectory()) {
         gEdgeDir = subDir;
         return subDir.clone();
       }
     }
   } catch (ex) {
     Cu.reportError("Exception trying to find the Edge favorites directory: " + ex);
@@ -383,17 +382,17 @@ Bookmarks.prototype = {
   async _getBookmarksInFolder(aSourceFolder) {
     // TODO (bug 741993): the favorites order is stored in the Registry, at
     // HCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MenuOrder\Favorites
     // for IE, and in a similar location for Edge.
     // Until we support it, bookmarks are imported in alphabetical order.
     let entries = aSourceFolder.directoryEntries;
     let rv = [];
     while (entries.hasMoreElements()) {
-      let entry = entries.getNext().QueryInterface(Ci.nsIFile);
+      let entry = entries.nextFile;
       try {
         // Make sure that entry.path == entry.target to not follow .lnk folder
         // shortcuts which could lead to infinite cycles.
         // Don't use isSymlink(), since it would throw for invalid
         // lnk files pointing to URLs or to unresolvable paths.
         if (entry.path == entry.target && entry.isDirectory()) {
           let isBookmarksFolder = entry.leafName == this._toolbarFolderName &&
                                   entry.parent.equals(this._favoritesFolder);
@@ -504,17 +503,17 @@ Cookies.prototype = {
 
     let cookiesGenerator = (function* genCookie() {
       let success = false;
       let folders = this._migrationType == MSMigrationUtils.MIGRATION_TYPE_EDGE ?
                       this.__cookiesFolders : [this.__cookiesFolder];
       for (let folder of folders) {
         let entries = folder.directoryEntries;
         while (entries.hasMoreElements()) {
-          let entry = entries.getNext().QueryInterface(Ci.nsIFile);
+          let entry = entries.nextFile;
           // Skip eventual bogus entries.
           if (!entry.isFile() || !/\.(cookie|txt)$/.test(entry.leafName))
             continue;
 
           this._readCookieFile(entry, function(aSuccess) {
             // Importing even a single cookie file is considered a success.
             if (aSuccess)
               success = true;
--- a/browser/components/preferences/handlers.css
+++ b/browser/components/preferences/handlers.css
@@ -1,16 +1,12 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#handlersView > richlistitem {
-  -moz-binding: url("chrome://browser/content/preferences/handlers.xml#handler");
-}
-
 #containersView > richlistitem {
   -moz-binding: none;
 }
 
 /**
  * Make the icons appear.
  * Note: we display the icon box for every item whether or not it has an icon
  * so the labels of all the items align vertically.
deleted file mode 100644
--- a/browser/components/preferences/handlers.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<!-- import-globals-from in-content/main.js -->
-
-<bindings id="handlerBindings"
-          xmlns="http://www.mozilla.org/xbl"
-          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-          xmlns:xbl="http://www.mozilla.org/xbl">
-
-  <binding id="handler" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
-    <implementation>
-      <property name="type" readonly="true">
-        <getter>
-          return this.getAttribute("type");
-        </getter>
-      </property>
-      <!-- Overriding listitem -->
-      <property name="selected" onget="return this.getAttribute('selected') == 'true';">
-        <setter><![CDATA[
-          if (val) {
-            this.setAttribute("selected", "true");
-            gMainPane.rebuildActionsMenu();
-          } else {
-            this.removeAttribute("selected");
-          }
-
-          document.getAnonymousElementByAttribute(this, "anonid", "selected").setAttribute("hidden", !val);
-          document.getAnonymousElementByAttribute(this, "anonid", "not-selected").setAttribute("hidden", !!val);
-
-          return val;
-        ]]></setter>
-      </property>
-    </implementation>
-    <content>
-      <xul:hbox flex="1" equalsize="always">
-        <xul:hbox flex="1" align="center" xbl:inherits="tooltiptext=typeDescription">
-          <xul:image src="moz-icon://goat?size=16" class="typeIcon"
-                     xbl:inherits="src=typeIcon" height="16" width="16"/>
-          <xul:label flex="1" crop="end" xbl:inherits="value=typeDescription"/>
-        </xul:hbox>
-        <xul:hbox anonid="not-selected" flex="1" align="center" xbl:inherits="tooltiptext=actionDescription">
-          <xul:image xbl:inherits="src=actionIcon" height="16" width="16" class="actionIcon"/>
-          <xul:label flex="1" crop="end" xbl:inherits="value=actionDescription"/>
-        </xul:hbox>
-        <xul:hbox hidden="true" anonid="selected" flex="1">
-          <xul:menulist class="actionsMenu" flex="1" crop="end" selectedIndex="1"
-                        xbl:inherits="tooltiptext=actionDescription"
-                        oncommand="gMainPane.onSelectAction(event.originalTarget)">
-            <xul:menupopup/>
-          </xul:menulist>
-        </xul:hbox>
-      </xul:hbox>
-    </content>
-  </binding>
-
-</bindings>
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -578,16 +578,17 @@ var gMainPane = {
 
   preInit() {
     promiseLoadHandlersList = new Promise((resolve, reject) => {
       // Load the data and build the list of handlers for applications pane.
       // By doing this after pageshow, we ensure it doesn't delay painting
       // of the preferences page.
       window.addEventListener("pageshow", async () => {
         try {
+          this._initListEventHandlers();
           this._loadData();
           await this._rebuildVisibleTypes();
           this._sortVisibleTypes();
           this._rebuildView();
           resolve();
         } catch (ex) {
           reject(ex);
         }
@@ -1443,16 +1444,41 @@ var gMainPane = {
 
       handlerInfoWrapper.handledOnlyByPlugin = false;
     }
   },
 
 
   // View Construction
 
+  selectedHandlerListItem: null,
+
+  _initListEventHandlers() {
+    this._list.addEventListener("select", event => {
+      if (event.target != this._list) {
+        return;
+      }
+
+      let handlerListItem = this._list.selectedItem &&
+                            HandlerListItem.forNode(this._list.selectedItem);
+      if (this.selectedHandlerListItem == handlerListItem) {
+        return;
+      }
+
+      if (this.selectedHandlerListItem) {
+        this.selectedHandlerListItem.showActionsMenu = false;
+      }
+      this.selectedHandlerListItem = handlerListItem;
+      if (handlerListItem) {
+        this.rebuildActionsMenu();
+        handlerListItem.showActionsMenu = true;
+      }
+    });
+  },
+
   async _rebuildVisibleTypes() {
     this._visibleTypes = [];
 
     // Map whose keys are string descriptions and values are references to the
     // first visible HandlerInfoWrapper that has this description. We use this
     // to determine whether or not to annotate descriptions with their types to
     // distinguish duplicate descriptions from each other.
     let visibleDescriptions = new Map();
@@ -1501,32 +1527,33 @@ var gMainPane = {
         // add the type to the description on both HandlerInfoWrapper objects.
         handlerInfo.disambiguateDescription = true;
         otherHandlerInfo.disambiguateDescription = true;
       }
     }
   },
 
   _rebuildView() {
-    let lastSelectedType = this._list.selectedItem &&
-      HandlerListItem.forNode(this._list.selectedItem).handlerInfoWrapper.type;
+    let lastSelectedType = this.selectedHandlerListItem &&
+                           this.selectedHandlerListItem.handlerInfoWrapper.type;
+    this.selectedHandlerListItem = null;
 
     // Clear the list of entries.
     while (this._list.childNodes.length > 1)
       this._list.removeChild(this._list.lastChild);
 
     var visibleTypes = this._visibleTypes;
 
     // If the user is filtering the list, then only show matching types.
     if (this._filter.value)
       visibleTypes = visibleTypes.filter(this._matchesFilter, this);
 
     for (let visibleType of visibleTypes) {
       let item = new HandlerListItem(visibleType);
-      this._list.appendChild(item.node);
+      item.connectAndAppendToList(this._list);
 
       if (visibleType.type === lastSelectedType) {
         this._list.selectedItem = item.node;
       }
     }
   },
 
   _matchesFilter(aType) {
@@ -1580,19 +1607,18 @@ var gMainPane = {
   },
 
   /**
    * Rebuild the actions menu for the selected entry.  Gets called by
    * the richlistitem constructor when an entry in the list gets selected.
    */
   rebuildActionsMenu() {
     var typeItem = this._list.selectedItem;
-    var handlerInfo = this._handledTypes[typeItem.type];
-    var menu =
-      document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
+    var handlerInfo = this.selectedHandlerListItem.handlerInfoWrapper;
+    var menu = typeItem.querySelector(".actionsMenu");
     var menuPopup = menu.menupopup;
 
     // Clear out existing items.
     while (menuPopup.hasChildNodes())
       menuPopup.removeChild(menuPopup.lastChild);
 
     let internalMenuItem;
     // Add the "Preview in Firefox" option for optional internal handlers.
@@ -1694,17 +1720,17 @@ var gMainPane = {
 
       menuPopup.appendChild(menuItem);
       possibleAppMenuItems.push(menuItem);
     }
     // Add gio handlers
     if (Cc["@mozilla.org/gio-service;1"]) {
       let gIOSvc = Cc["@mozilla.org/gio-service;1"].
                    getService(Ci.nsIGIOService);
-      var gioApps = gIOSvc.getAppsForURIScheme(typeItem.type);
+      var gioApps = gIOSvc.getAppsForURIScheme(handlerInfo.type);
       let enumerator = gioApps.enumerate();
       let possibleHandlers = handlerInfo.possibleApplicationHandlers;
       while (enumerator.hasMoreElements()) {
         let handler = enumerator.getNext().QueryInterface(Ci.nsIHandlerApp);
         // OS handler share the same name, it's most likely the same app, skipping...
         if (handler.name == handlerInfo.defaultDescription) {
           continue;
         }
@@ -1901,18 +1927,17 @@ var gMainPane = {
     try {
       this._storeAction(aActionItem);
     } finally {
       this._storingAction = false;
     }
   },
 
   _storeAction(aActionItem) {
-    var typeItem = this._list.selectedItem;
-    var handlerInfo = this._handledTypes[typeItem.type];
+    var handlerInfo = this.selectedHandlerListItem.handlerInfoWrapper;
 
     let action = parseInt(aActionItem.getAttribute("action"));
 
     // Set the plugin state if we're enabling or disabling a plugin.
     if (action == kActionUsePlugin)
       handlerInfo.enablePluginType();
     else if (handlerInfo.pluginName && !handlerInfo.isDisabledPluginType)
       handlerInfo.disablePluginType();
@@ -1937,34 +1962,33 @@ var gMainPane = {
 
     handlerInfo.store();
 
     // Make sure the handler info object is flagged to indicate that there is
     // now some user configuration for the type.
     handlerInfo.handledOnlyByPlugin = false;
 
     // Update the action label and image to reflect the new preferred action.
-    HandlerListItem.forNode(typeItem).refreshAction();
+    this.selectedHandlerListItem.refreshAction();
   },
 
   manageApp(aEvent) {
     // Don't let the normal "on select action" handler get this event,
     // as we handle it specially ourselves.
     aEvent.stopPropagation();
 
-    var typeItem = this._list.selectedItem;
-    var handlerInfo = this._handledTypes[typeItem.type];
+    var handlerInfo = this.selectedHandlerListItem.handlerInfoWrapper;
 
     let onComplete = () => {
       // Rebuild the actions menu so that we revert to the previous selection,
       // or "Always ask" if the previous default application has been removed
       this.rebuildActionsMenu();
 
       // update the richlistitem too. Will be visible when selecting another row
-      HandlerListItem.forNode(typeItem).refreshAction();
+      this.selectedHandlerListItem.refreshAction();
     };
 
     gSubDialog.open("chrome://browser/content/preferences/applicationManager.xul",
       "resizable=no", handlerInfo, onComplete);
 
   },
 
   chooseApp(aEvent) {
@@ -1977,33 +2001,32 @@ var gMainPane = {
       // Rebuild the actions menu whether the user picked an app or canceled.
       // If they picked an app, we want to add the app to the menu and select it.
       // If they canceled, we want to go back to their previous selection.
       this.rebuildActionsMenu();
 
       // If the user picked a new app from the menu, select it.
       if (aHandlerApp) {
         let typeItem = this._list.selectedItem;
-        let actionsMenu =
-          document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
+        let actionsMenu = typeItem.querySelector(".actionsMenu");
         let menuItems = actionsMenu.menupopup.childNodes;
         for (let i = 0; i < menuItems.length; i++) {
           let menuItem = menuItems[i];
           if (menuItem.handlerApp && menuItem.handlerApp.equals(aHandlerApp)) {
             actionsMenu.selectedIndex = i;
             this.onSelectAction(menuItem);
             break;
           }
         }
       }
     };
 
     if (AppConstants.platform == "win") {
       var params = {};
-      var handlerInfo = this._handledTypes[this._list.selectedItem.type];
+      var handlerInfo = this.selectedHandlerListItem.handlerInfoWrapper;
 
       if (isFeedType(handlerInfo.type)) {
         // MIME info will be null, create a temp object.
         params.mimeInfo = gMIMEService.getFromTypeAndExtension(handlerInfo.type,
           handlerInfo.primaryExtension);
       } else {
         params.mimeInfo = handlerInfo.wrappedHandlerInfo;
       }
@@ -2033,17 +2056,17 @@ var gMainPane = {
         if (aResult == Ci.nsIFilePicker.returnOK && fp.file &&
           this._isValidHandlerExecutable(fp.file)) {
           handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
             createInstance(Ci.nsILocalHandlerApp);
           handlerApp.name = getFileDisplayName(fp.file);
           handlerApp.executable = fp.file;
 
           // Add the app to the type's list of possible handlers.
-          let handler = this._handledTypes[this._list.selectedItem.type];
+          let handler = this.selectedHandlerListItem.handlerInfoWrapper;
           handler.addPossibleApplicationHandler(handlerApp);
 
           chooseAppCallback(handlerApp);
         }
       };
 
       // Prompt the user to pick an app.  If they pick one, and it's a valid
       // selection, then add it to the list of possible handlers.
@@ -2422,52 +2445,96 @@ ArrayEnumerator.prototype = {
     return this._contents[this._index++];
   }
 };
 
 function isFeedType(t) {
   return t == TYPE_MAYBE_FEED || t == TYPE_MAYBE_VIDEO_FEED || t == TYPE_MAYBE_AUDIO_FEED;
 }
 
+// eslint-disable-next-line no-undef
+let gHandlerListItemFragment = MozXULElement.parseXULToFragment(`
+  <richlistitem>
+    <hbox flex="1" equalsize="always">
+      <hbox class="typeContainer" flex="1" align="center">
+        <image class="typeIcon" width="16" height="16"
+               src="moz-icon://goat?size=16"/>
+        <label class="typeDescription" flex="1" crop="end"/>
+      </hbox>
+      <hbox class="actionContainer" flex="1" align="center">
+        <image class="actionIcon" width="16" height="16"/>
+        <label class="actionDescription" flex="1" crop="end"/>
+      </hbox>
+      <hbox class="actionsMenuContainer" flex="1">
+        <menulist class="actionsMenu" flex="1" crop="end" selectedIndex="1">
+          <menupopup/>
+        </menulist>
+      </hbox>
+    </hbox>
+  </richlistitem>
+`);
+
 /**
  * This is associated to <richlistitem> elements in the handlers view.
  */
 class HandlerListItem {
   static forNode(node) {
     return gNodeToObjectMap.get(node);
   }
 
   constructor(handlerInfoWrapper) {
     this.handlerInfoWrapper = handlerInfoWrapper;
-    this.node = document.createElement("richlistitem");
+  }
+
+  setOrRemoveAttributes(iterable) {
+    for (let [selector, name, value] of iterable) {
+      let node = selector ? this.node.querySelector(selector) : this.node;
+      if (value) {
+        node.setAttribute(name, value);
+      } else {
+        node.removeAttribute(name);
+      }
+    }
+  }
+
+  connectAndAppendToList(list) {
+    list.appendChild(document.importNode(gHandlerListItemFragment, true));
+    this.node = list.lastChild;
     gNodeToObjectMap.set(this.node, this);
 
-    this.node.setAttribute("type", this.handlerInfoWrapper.type);
-    this.node.setAttribute("typeDescription",
-                           this.handlerInfoWrapper.typeDescription);
-    if (this.handlerInfoWrapper.smallIcon) {
-      this.node.setAttribute("typeIcon", this.handlerInfoWrapper.smallIcon);
-    } else {
-      this.node.removeAttribute("typeIcon");
-    }
-
+    this.node.querySelector(".actionsMenu").addEventListener("command",
+      event => gMainPane.onSelectAction(event.originalTarget));
+
+    let typeDescription = this.handlerInfoWrapper.typeDescription;
+    this.setOrRemoveAttributes([
+      [null, "type", this.handlerInfoWrapper.type],
+      [".typeContainer", "tooltiptext", typeDescription],
+      [".typeDescription", "value", typeDescription],
+      [".typeIcon", "src", this.handlerInfoWrapper.smallIcon],
+    ]);
     this.refreshAction();
+    this.showActionsMenu = false;
   }
 
   refreshAction() {
-    this.node.setAttribute("actionDescription",
-                           this.handlerInfoWrapper.actionDescription);
-    if (this.handlerInfoWrapper.actionIconClass) {
-      this.node.setAttribute(APP_ICON_ATTR_NAME,
-                             this.handlerInfoWrapper.actionIconClass);
-      this.node.removeAttribute("actionIcon");
-    } else {
-      this.node.removeAttribute(APP_ICON_ATTR_NAME);
-      this.node.setAttribute("actionIcon", this.handlerInfoWrapper.actionIcon);
-    }
+    let { actionIconClass, actionDescription } = this.handlerInfoWrapper;
+    this.setOrRemoveAttributes([
+      [null, APP_ICON_ATTR_NAME, actionIconClass],
+      [".actionContainer", "tooltiptext", actionDescription],
+      [".actionDescription", "value", actionDescription],
+      [".actionIcon", "src", actionIconClass ? null :
+                             this.handlerInfoWrapper.actionIcon],
+    ]);
+  }
+
+  set showActionsMenu(value) {
+    this.setOrRemoveAttributes([
+      [".actionContainer", "hidden", value],
+      [".actionsMenuContainer", "hidden", !value],
+    ]);
   }
 }
 
 /**
  * This object wraps nsIHandlerInfo with some additional functionality
  * the Applications prefpane needs to display and allow modification of
  * the list of handled types.
  *
--- a/browser/components/preferences/jar.mn
+++ b/browser/components/preferences/jar.mn
@@ -11,17 +11,16 @@ browser.jar:
     content/browser/preferences/clearSiteData.js
     content/browser/preferences/clearSiteData.xul
 *   content/browser/preferences/colors.xul
     content/browser/preferences/colors.js
     content/browser/preferences/connection.xul
     content/browser/preferences/connection.js
     content/browser/preferences/fonts.xul
     content/browser/preferences/fonts.js
-    content/browser/preferences/handlers.xml
     content/browser/preferences/handlers.css
     content/browser/preferences/languages.xul
     content/browser/preferences/languages.js
     content/browser/preferences/permissions.xul
     content/browser/preferences/sitePermissions.xul
     content/browser/preferences/sitePermissions.js
     content/browser/preferences/sitePermissions.css
     content/browser/preferences/containers.xul
--- a/browser/extensions/mortar/host/common/ppapi-runtime.jsm
+++ b/browser/extensions/mortar/host/common/ppapi-runtime.jsm
@@ -2843,17 +2843,17 @@ dump(`callFromJSON: < ${JSON.stringify(c
       json.path.split("/").forEach((pathItem) => directory.appendRelativePath(pathItem));
       if (!directory.exists() || !directory.isDirectory()) {
         return [PP_ERROR_FILENOTFOUND, { contents: null }];
       }
 
       let entries = [];
       let enumerator = directory.directoryEntries;
       while (enumerator.hasMoreElements()) {
-        let file = enumerator.getNext().QueryInterface(Ci.nsIFile);
+        let file = enumerator.nextFile;
         entries.push({ name: file.leafName, is_dir: file.isDirectory() });
       }
       return [PP_OK, { contents: { count: entries.length, entries } }];
     },
 
     /**
      * int32_t CreateTemporaryFile(
      *     [in] PP_Instance instance,
--- a/browser/modules/test/browser/browser_UnsubmittedCrashHandler.js
+++ b/browser/modules/test/browser/browser_UnsubmittedCrashHandler.js
@@ -37,17 +37,17 @@ function getPendingCrashReportDir() {
  * Synchronously deletes all entries inside the pending
  * crash report directory.
  */
 function clearPendingCrashReports() {
   let dir = getPendingCrashReportDir();
   let entries = dir.directoryEntries;
 
   while (entries.hasMoreElements()) {
-    let entry = entries.getNext().QueryInterface(Ci.nsIFile);
+    let entry = entries.nextFile;
     if (entry.isFile()) {
       entry.remove(false);
     }
   }
 }
 
 /**
  * Randomly generates howMany crash report .dmp and .extra files
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -456,16 +456,33 @@ BasePrincipal::CloneStrippingUserContext
 
   nsCOMPtr<nsIURI> uri;
   rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
   NS_ENSURE_SUCCESS(rv, nullptr);
 
   return BasePrincipal::CreateCodebasePrincipal(uri, attrs);
 }
 
+extensions::WebExtensionPolicy*
+BasePrincipal::ContentScriptAddonPolicy()
+{
+  if (!Is<ExpandedPrincipal>()) {
+    return nullptr;
+  }
+
+  auto expanded = As<ExpandedPrincipal>();
+  for (auto& prin : expanded->WhiteList()) {
+    if (auto policy = BasePrincipal::Cast(prin)->AddonPolicy()) {
+      return policy;
+    }
+  }
+
+  return nullptr;
+}
+
 bool
 BasePrincipal::AddonAllowsLoad(nsIURI* aURI, bool aExplicit /* = false */)
 {
   if (Is<ExpandedPrincipal>()) {
     return As<ExpandedPrincipal>()->AddonAllowsLoad(aURI, aExplicit);
   }
   if (auto policy = AddonPolicy()) {
     return policy->CanAccessURI(aURI, aExplicit);
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -108,16 +108,20 @@ public:
   uint32_t UserContextId() const { return mOriginAttributes.mUserContextId; }
   uint32_t PrivateBrowsingId() const { return mOriginAttributes.mPrivateBrowsingId; }
   bool IsInIsolatedMozBrowserElement() const { return mOriginAttributes.mInIsolatedMozBrowser; }
 
   PrincipalKind Kind() const { return mKind; }
 
   already_AddRefed<BasePrincipal> CloneStrippingUserContextIdAndFirstPartyDomain();
 
+  // If this is an add-on content script principal, returns its AddonPolicy.
+  // Otherwise returns null.
+  extensions::WebExtensionPolicy* ContentScriptAddonPolicy();
+
   // Helper to check whether this principal is associated with an addon that
   // allows unprivileged code to load aURI.  aExplicit == true will prevent
   // use of all_urls permission, requiring the domain in its permissions.
   bool AddonAllowsLoad(nsIURI* aURI, bool aExplicit = false);
 
   // Call these to avoid the cost of virtual dispatch.
   inline bool FastEquals(nsIPrincipal* aOther);
   inline bool FastEqualsConsideringDomain(nsIPrincipal* aOther);
--- a/config/system-headers.mozbuild
+++ b/config/system-headers.mozbuild
@@ -1265,21 +1265,16 @@ if CONFIG['MOZ_ENABLE_STARTUP_NOTIFICATI
         'libsn/sn-common.h',
         'libsn/sn.h',
         'libsn/sn-launchee.h',
         'libsn/sn-launcher.h',
         'libsn/sn-monitor.h',
         'libsn/sn-util.h',
     ]
 
-if CONFIG['MOZ_SYSTEM_HUNSPELL']:
-    system_headers += [
-        'hunspell.hxx',
-    ]
-
 if CONFIG['MOZ_SYSTEM_LIBEVENT']:
     system_headers += [
         'event2/event_compat.h',
         'event2/event.h',
         'event2/event_struct.h',
         'event.h',
     ]
 else:
--- a/devtools/client/debugger/new/README.mozilla
+++ b/devtools/client/debugger/new/README.mozilla
@@ -1,13 +1,13 @@
 This is the debugger.html project output.
 See https://github.com/devtools-html/debugger.html
 
-Version 56
+Version 57
 
-Comparison: https://github.com/devtools-html/debugger.html/compare/release-55...release-56
+Comparison: https://github.com/devtools-html/debugger.html/compare/release-56...release-57
 
 Packages:
 - babel-plugin-transform-es2015-modules-commonjs @6.26.2
 - babel-preset-react @6.24.1
 - react @16.2.0
 - react-dom @16.2.0
 - webpack @3.12.0
--- a/devtools/client/debugger/new/dist/vendors.js
+++ b/devtools/client/debugger/new/dist/vendors.js
@@ -7970,21 +7970,22 @@ class Tree extends Component {
       onKeyDown: this._onKeyDown,
       onKeyPress: this._preventArrowKeyScrolling,
       onKeyUp: this._preventArrowKeyScrolling,
       onFocus: ({ nativeEvent }) => {
         if (focused || !nativeEvent || !this.treeRef) {
           return;
         }
 
-        const { explicitOriginalTarget } = nativeEvent;
+        const { relatedTarget } = nativeEvent;
+
         // Only set default focus to the first tree node if the focus came
         // from outside the tree (e.g. by tabbing to the tree from other
         // external elements).
-        if (explicitOriginalTarget !== this.treeRef && !this.treeRef.contains(explicitOriginalTarget)) {
+        if (relatedTarget !== this.treeRef && !this.treeRef.contains(relatedTarget)) {
           this._focus(traversal[0].item);
         }
       },
       onBlur: this._onBlur,
       "aria-label": this.props.label,
       "aria-labelledby": this.props.labelledby,
       "aria-activedescendant": focused && this.props.getKey(focused),
       style
@@ -8039,39 +8040,32 @@ module.exports = "<!-- This Source Code 
 /***/ }),
 
 /***/ 3721:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 /* WEBPACK VAR INJECTION */(function(process) {
 
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-exports.isDevelopment = isDevelopment;
-exports.isTesting = isTesting;
-exports.isFirefoxPanel = isFirefoxPanel;
-exports.isFirefox = isFirefox;
 /* 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/>. */
 
 const flag = __webpack_require__(52);
 
 function isBrowser() {
   return typeof window == "object";
 }
 
 function isNode() {
   return process && process.release && process.release.name == 'node';
 }
 
 function isDevelopment() {
-  if (!isNode && isBrowser()) {
+  if (!isNode() && isBrowser()) {
     const href = window.location ? window.location.href : "";
     return href.match(/^file:/) || href.match(/localhost:/);
   }
 
   return "production" != "production";
 }
 
 function isTesting() {
@@ -8081,16 +8075,23 @@ function isTesting() {
 function isFirefoxPanel() {
   return !isDevelopment();
 }
 
 function isFirefox() {
   return (/firefox/i.test(navigator.userAgent)
   );
 }
+
+module.exports = {
+  isDevelopment,
+  isTesting,
+  isFirefoxPanel,
+  isFirefox
+};
 /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(120)))
 
 /***/ }),
 
 /***/ 3728:
 /***/ (function(module, exports, __webpack_require__) {
 
 module.exports = __webpack_require__(3729);
--- a/devtools/client/debugger/new/src/components/Editor/Footer.js
+++ b/devtools/client/debugger/new/src/components/Editor/Footer.js
@@ -144,18 +144,17 @@ class SourceFooter extends _react.PureCo
   renderSourceSummary() {
     const {
       mappedSource,
       jumpToMappedLocation,
       selectedSource
     } = this.props;
 
     if (mappedSource) {
-      const bundleSource = mappedSource.toJS();
-      const filename = (0, _source.getFilename)(bundleSource);
+      const filename = (0, _source.getFilename)(mappedSource);
       const tooltip = L10N.getFormatStr("sourceFooter.mappedSourceTooltip", filename);
       const title = L10N.getFormatStr("sourceFooter.mappedSource", filename);
       const mappedSourceLocation = {
         sourceId: selectedSource.get("id"),
         line: 1,
         column: 1
       };
       return _react2.default.createElement("button", {
--- a/devtools/client/debugger/new/src/components/Editor/Tab.js
+++ b/devtools/client/debugger/new/src/components/Editor/Tab.js
@@ -132,18 +132,17 @@ class Tab extends _react.PureComponent {
 
   render() {
     const {
       selectedSource,
       selectSpecificSource,
       closeTab,
       source
     } = this.props;
-    const src = source.toJS();
-    const filename = (0, _source.getFilename)(src);
+    const filename = (0, _source.getFilename)(source);
     const sourceId = source.id;
     const active = selectedSource && sourceId == selectedSource.get("id") && !this.isProjectSearchEnabled() && !this.isSourceSearchEnabled();
     const isPrettyCode = (0, _source.isPretty)(source);
 
     function onClickClose(e) {
       e.stopPropagation();
       closeTab(source.url);
     }
@@ -163,17 +162,17 @@ class Tab extends _react.PureComponent {
       active,
       pretty: isPrettyCode
     });
     return _react2.default.createElement("div", {
       className: className,
       key: sourceId,
       onMouseUp: handleTabClick,
       onContextMenu: e => this.onTabContextMenu(e, sourceId),
-      title: (0, _source.getFileURL)(src)
+      title: (0, _source.getFileURL)(source)
     }, _react2.default.createElement(_SourceIcon2.default, {
       source: source,
       shouldHide: icon => ["file", "javascript"].includes(icon)
     }), _react2.default.createElement("div", {
       className: "filename"
     }, filename), _react2.default.createElement(_Button.CloseButton, {
       handleClick: onClickClose,
       tooltip: L10N.getStr("sourceTabs.closeTabButtonTooltip")
--- a/devtools/client/debugger/new/src/components/Editor/Tabs.js
+++ b/devtools/client/debugger/new/src/components/Editor/Tabs.js
@@ -66,29 +66,29 @@ class Tabs extends _react.PureComponent 
         return moveTab(selectedSource.url, 0);
       }
 
       this.setState({
         hiddenTabs
       });
     };
 
-    this.renderDropdownSource = source => {
+    this.renderDropdownSource = sourceRecord => {
       const {
         selectSpecificSource
       } = this.props;
-      const filename = (0, _source.getFilename)(source.toJS());
+      const filename = (0, _source.getFilename)(sourceRecord);
 
-      const onClick = () => selectSpecificSource(source.id);
+      const onClick = () => selectSpecificSource(sourceRecord.id);
 
       return _react2.default.createElement("li", {
-        key: source.id,
+        key: sourceRecord.id,
         onClick: onClick
       }, _react2.default.createElement("img", {
-        className: `dropdown-icon ${this.getIconClass(source)}`
+        className: `dropdown-icon ${this.getIconClass(sourceRecord)}`
       }), filename);
     };
 
     this.state = {
       dropdownShown: false,
       hiddenTabs: I.List()
     };
     this.onResize = (0, _lodash.debounce)(() => {
@@ -117,22 +117,22 @@ class Tabs extends _react.PureComponent 
 
 
   toggleSourcesDropdown(e) {
     this.setState(prevState => ({
       dropdownShown: !prevState.dropdownShown
     }));
   }
 
-  getIconClass(source) {
-    if ((0, _source.isPretty)(source)) {
+  getIconClass(sourceRecord) {
+    if ((0, _source.isPretty)(sourceRecord)) {
       return "prettyPrint";
     }
 
-    if (source.isBlackBoxed) {
+    if (sourceRecord.isBlackBoxed) {
       return "blackBox";
     }
 
     return "file";
   }
 
   renderTabs() {
     const {
--- a/devtools/client/debugger/new/src/components/Editor/index.js
+++ b/devtools/client/debugger/new/src/components/Editor/index.js
@@ -626,13 +626,13 @@ const mapStateToProps = state => {
   const sourceId = selectedSource ? selectedSource.get("id") : "";
   return {
     selectedLocation: (0, _selectors.getSelectedLocation)(state),
     selectedSource,
     searchOn: (0, _selectors.getActiveSearch)(state) === "file",
     hitCount: (0, _selectors.getHitCountForSource)(state, sourceId),
     coverageOn: (0, _selectors.getCoverageEnabled)(state),
     conditionalPanelLine: (0, _selectors.getConditionalPanelLine)(state),
-    symbols: (0, _selectors.getSymbols)(state, selectedSource && selectedSource.toJS())
+    symbols: (0, _selectors.getSymbols)(state, selectedSource)
   };
 };
 
 exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Editor);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints.js
@@ -135,17 +135,17 @@ class Breakpoints extends _react.Compone
   renderExceptionsOptions() {
     const {
       breakpoints,
       shouldPauseOnExceptions,
       shouldPauseOnCaughtExceptions,
       pauseOnExceptions
     } = this.props;
     const isEmpty = breakpoints.size == 0;
-    const exceptionsBox = createExceptionOption(L10N.getStr("pauseOnExceptionsItem"), shouldPauseOnExceptions, () => pauseOnExceptions(!shouldPauseOnExceptions, false), "breakpoints-exceptions");
+    const exceptionsBox = createExceptionOption(L10N.getStr("pauseOnExceptionsItem2"), shouldPauseOnExceptions, () => pauseOnExceptions(!shouldPauseOnExceptions, false), "breakpoints-exceptions");
     const ignoreCaughtBox = createExceptionOption(L10N.getStr("pauseOnCaughtExceptionsItem"), shouldPauseOnCaughtExceptions, () => pauseOnExceptions(true, !shouldPauseOnCaughtExceptions), "breakpoints-exceptions-caught");
     return _react2.default.createElement("div", {
       className: (0, _classnames2.default)("breakpoints-exceptions-options", {
         empty: isEmpty
       })
     }, exceptionsBox, shouldPauseOnExceptions ? ignoreCaughtBox : null);
   }
 
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/CommandBar.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/CommandBar.js
@@ -175,18 +175,20 @@ class CommandBar extends _react.Componen
     } = this.props;
 
     if (!canRewind || !isPaused) {
       return null;
     }
 
     const isDisabled = !isPaused;
     return [(0, _CommandBarButton.debugBtn)(this.props.rewind, "rewind", "active", "Rewind Execution"), (0, _CommandBarButton.debugBtn)(() => this.props.resume, "resume", "active", L10N.getFormatStr("resumeButtonTooltip", formatKey("resume"))), _react2.default.createElement("div", {
+      key: "divider-1",
       className: "divider"
     }), (0, _CommandBarButton.debugBtn)(this.props.reverseStepOver, "reverseStepOver", "active", "Reverse step over"), (0, _CommandBarButton.debugBtn)(this.props.stepOver, "stepOver", "active", L10N.getFormatStr("stepOverTooltip", formatKey("stepOver")), isDisabled), _react2.default.createElement("div", {
+      key: "divider-2",
       className: "divider"
     }), (0, _CommandBarButton.debugBtn)(this.props.stepOut, "stepOut", "active", L10N.getFormatStr("stepOutTooltip", formatKey("stepOut")), isDisabled), (0, _CommandBarButton.debugBtn)(this.props.stepIn, "stepIn", "active", L10N.getFormatStr("stepInTooltip", formatKey("stepIn")), isDisabled)];
   }
 
   replayPreviousButton() {
     const {
       history,
       historyPosition,
--- a/devtools/client/debugger/new/src/utils/source.js
+++ b/devtools/client/debugger/new/src/utils/source.js
@@ -418,16 +418,21 @@ function isLoading(source) {
 
 function getTextAtPosition(source, location) {
   if (!source || !source.text) {
     return "";
   }
 
   const line = location.line;
   const column = location.column || 0;
+
+  if (source.isWasm) {
+    return "";
+  }
+
   const lineText = source.text.split("\n")[line - 1];
 
   if (!lineText) {
     return "";
   }
 
   return lineText.slice(column, column + 100).trim();
 }
--- a/devtools/client/debugger/test/mochitest/browser2.ini
+++ b/devtools/client/debugger/test/mochitest/browser2.ini
@@ -529,17 +529,17 @@ skip-if = e10s && debug
 [browser_dbg_variables-view-popup-07.js]
 uses-unsafe-cpows = true
 skip-if = e10s && debug
 [browser_dbg_variables-view-popup-08.js]
 uses-unsafe-cpows = true
 skip-if = e10s && debug
 [browser_dbg_variables-view-popup-09.js]
 uses-unsafe-cpows = true
-skip-if = e10s && debug
+skip-if = (e10s && debug) || (os == "mac" || (os == "linux" && bits == 64)) # bug 1373127 for frequent timeouts
 [browser_dbg_variables-view-popup-10.js]
 uses-unsafe-cpows = true
 skip-if = e10s && debug
 [browser_dbg_variables-view-popup-11.js]
 uses-unsafe-cpows = true
 skip-if = e10s && debug
 [browser_dbg_variables-view-popup-12.js]
 uses-unsafe-cpows = true
--- a/devtools/client/inspector/rules/rules.js
+++ b/devtools/client/inspector/rules/rules.js
@@ -816,17 +816,17 @@ CssRuleView.prototype = {
    *        Update the view even if the element is the same as last time.
    */
   selectElement: function(element, allowRefresh = false) {
     let refresh = (this._viewedElement === element);
     if (refresh && !allowRefresh) {
       return promise.resolve(undefined);
     }
 
-    if (this.popup.isOpen) {
+    if (this._popup && this.popup.isOpen) {
       this.popup.hidePopup();
     }
 
     this.clear(false);
     this._viewedElement = element;
 
     this.clearPseudoClassPanel();
     this.refreshAddRuleButtonState();
--- a/devtools/client/locales/en-US/debugger.properties
+++ b/devtools/client/locales/en-US/debugger.properties
@@ -92,19 +92,19 @@ pauseButtonItem=Pause on Next Statement
 # LOCALIZATION NOTE (ignoreExceptionsItem): The pause on exceptions button description
 # when the debugger will not pause on exceptions.
 ignoreExceptionsItem=Ignore exceptions
 
 # LOCALIZATION NOTE (pauseOnUncaughtExceptionsItem): The pause on exceptions dropdown
 # item shown when a user is adding a new breakpoint.
 pauseOnUncaughtExceptionsItem=Pause on uncaught exceptions
 
-# LOCALIZATION NOTE (pauseOnExceptionsItem): The pause on exceptions checkbox description
+# LOCALIZATION NOTE (pauseOnExceptionsItem2): The pause on exceptions checkbox description
 # when the debugger will pause on all exceptions.
-pauseOnExceptionsItem=Pause on exceptions
+pauseOnExceptionsItem2=Pause on exceptions
 
 # LOCALIZATION NOTE (ignoreCaughtExceptionsItem): The pause on exceptions checkbox description
 # when the debugger will not pause on any caught exception
 ignoreCaughtExceptionsItem=Ignore caught exceptions
 
 # LOCALIZATION NOTE (pauseOnCaughtExceptionsItem): The pause on exceptions checkbox description
 # when the debugger should pause on caught exceptions
 pauseOnCaughtExceptionsItem=Pause on caught exceptions
--- a/devtools/client/shared/components/reps/reps.js
+++ b/devtools/client/shared/components/reps/reps.js
@@ -4437,21 +4437,22 @@ class Tree extends Component {
       onKeyDown: this._onKeyDown,
       onKeyPress: this._preventArrowKeyScrolling,
       onKeyUp: this._preventArrowKeyScrolling,
       onFocus: ({ nativeEvent }) => {
         if (focused || !nativeEvent || !this.treeRef) {
           return;
         }
 
-        const { explicitOriginalTarget } = nativeEvent;
+        const { relatedTarget } = nativeEvent;
+
         // Only set default focus to the first tree node if the focus came
         // from outside the tree (e.g. by tabbing to the tree from other
         // external elements).
-        if (explicitOriginalTarget !== this.treeRef && !this.treeRef.contains(explicitOriginalTarget)) {
+        if (relatedTarget !== this.treeRef && !this.treeRef.contains(relatedTarget)) {
           this._focus(traversal[0].item);
         }
       },
       onBlur: this._onBlur,
       "aria-label": this.props.label,
       "aria-labelledby": this.props.labelledby,
       "aria-activedescendant": focused && this.props.getKey(focused),
       style
--- a/devtools/server/actors/accessibility.js
+++ b/devtools/server/actors/accessibility.js
@@ -601,22 +601,16 @@ const AccessibleWalkerActor = ActorClass
         events.emit(this, "document-ready", rawAccessible);
       }
     }
 
     switch (event.eventType) {
       case EVENT_STATE_CHANGE:
         let { state, isEnabled } = event.QueryInterface(nsIAccessibleStateChangeEvent);
         let isBusy = state & Ci.nsIAccessibleStates.STATE_BUSY;
-        // Accessible document is recreated.
-        if (isBusy && !isEnabled && rawAccessible instanceof Ci.nsIAccessibleDocument) {
-          // Remove its existing cache from tree.
-          this.purgeSubtree(rawAccessible, event.DOMNode);
-        }
-
         if (accessible) {
           // Only propagate state change events for active accessibles.
           if (isBusy && isEnabled) {
             if (rawAccessible instanceof Ci.nsIAccessibleDocument) {
               // Remove its existing cache from tree.
               this.purgeSubtree(rawAccessible, event.DOMNode);
             }
             return;
--- a/devtools/server/actors/highlighters/css-grid.js
+++ b/devtools/server/actors/highlighters/css-grid.js
@@ -1144,17 +1144,17 @@ class CssGridHighlighter extends AutoRef
    * @param  {Boolean||undefined} isStackedLine
    *         Boolean indicating if the line is stacked.
    */
   renderGridLineNumber(lineNumber, linePos, startPos, breadth, dimensionType,
     isStackedLine) {
     let displayPixelRatio = getDisplayPixelRatio(this.win);
     let { devicePixelRatio } = this.win;
     let offset = (displayPixelRatio / 2) % 1;
-    let fontSize = GRID_FONT_SIZE * displayPixelRatio;
+    let fontSize = GRID_FONT_SIZE * devicePixelRatio;
     let canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
     let canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
 
     linePos = Math.round(linePos);
     startPos = Math.round(startPos);
     breadth = Math.round(breadth);
 
     if (linePos + breadth < 0) {
@@ -1168,18 +1168,18 @@ class CssGridHighlighter extends AutoRef
 
     // For a general grid box, the height of the character "m" will be its minimum width
     // and height. If line number's text width is greater, then use the grid box's text
     // width instead.
     let textHeight = this.ctx.measureText("m").width;
     let textWidth = Math.max(textHeight, this.ctx.measureText(lineNumber).width);
 
     // Padding in pixels for the line number text inside of the line number container.
-    let padding = 3 * displayPixelRatio;
-    let offsetFromEdge = 2 * displayPixelRatio;
+    let padding = 3 * devicePixelRatio;
+    let offsetFromEdge = 2 * devicePixelRatio;
 
     let boxWidth = textWidth + 2 * padding;
     let boxHeight = textHeight + 2 * padding;
 
     // Calculate the x & y coordinates for the line number container, so that its arrow
     // tip is centered on the line (or the gap if there is one), and is offset by the
     // calculated padding value from the grid container edge.
     let x, y;
--- a/dom/asmjscache/AsmJSCache.cpp
+++ b/dom/asmjscache/AsmJSCache.cpp
@@ -1869,36 +1869,25 @@ Client::GetUsageForOrigin(PersistenceTyp
   rv = directory->Append(NS_LITERAL_STRING(ASMJSCACHE_DIRECTORY_NAME));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   DebugOnly<bool> exists;
   MOZ_ASSERT(NS_SUCCEEDED(directory->Exists(&exists)) && exists);
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  bool hasMore;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
-         hasMore && !aCanceled) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
-    if (NS_WARN_IF(!file)) {
-      return NS_NOINTERFACE;
-    }
-
+  nsCOMPtr<nsIFile> file;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) &&
+         file && !aCanceled) {
     int64_t fileSize;
     rv = file->GetFileSize(&fileSize);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     MOZ_ASSERT(fileSize >= 0, "Negative size?!");
 
--- a/dom/base/UseCounters.conf
+++ b/dom/base/UseCounters.conf
@@ -90,16 +90,17 @@ attribute DataTransfer.mozSourceNode
 // JavaScript feature usage
 custom JS_asmjs uses asm.js
 custom JS_wasm uses WebAssembly
 
 // Console API
 method console.assert
 method console.clear
 method console.count
+method console.countReset
 method console.debug
 method console.error
 method console.info
 method console.log
 method console.table
 method console.trace
 method console.warn
 method console.dir
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -149,21 +149,17 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ns
                                       mChildMessageManager,
                                       mOpener,
                                       mParentSHistory)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameLoader)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameLoader)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameLoader)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  if (aIID.Equals(NS_GET_IID(nsFrameLoader))) {
-      // We want to end up with a pointer that can then be reinterpret_cast
-      // from nsISupports* to nsFrameLoader* and end up with |this|.
-      foundInterface = reinterpret_cast<nsISupports*>(this);
-  } else
+  NS_INTERFACE_MAP_ENTRY_CONCRETE(nsFrameLoader)
   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 nsFrameLoader::nsFrameLoader(Element* aOwner, nsPIDOMWindowOuter* aOpener,
                              bool aNetworkCreated, int32_t aJSPluginID)
   : mOwnerContent(aOwner)
   , mDetachedSubdocFrame(nullptr)
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -1329,25 +1329,19 @@ nsGlobalWindowInner::FreeInnerObjects()
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindowInner)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, EventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIDOMWindow)
   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(mozilla::dom::EventTarget)
-  if (aIID.Equals(NS_GET_IID(nsPIDOMWindowInner))) {
-    foundInterface = static_cast<nsPIDOMWindowInner*>(this);
-  } else
-  if (aIID.Equals(NS_GET_IID(mozIDOMWindow))) {
-    foundInterface = static_cast<mozIDOMWindow*>(this);
-  } else
-  if (aIID.Equals(NS_GET_IID(nsIDOMChromeWindow)) && IsChromeWindow()) {
-    foundInterface = static_cast<nsIDOMChromeWindow*>(this);
-  } else
+  NS_INTERFACE_MAP_ENTRY(nsPIDOMWindowInner)
+  NS_INTERFACE_MAP_ENTRY(mozIDOMWindow)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMChromeWindow, IsChromeWindow())
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
 NS_INTERFACE_MAP_END
 
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGlobalWindowInner)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGlobalWindowInner)
 
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -1083,25 +1083,19 @@ nsGlobalWindowOuter::ClearControllers()
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindowOuter)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, EventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIDOMWindow)
   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(mozilla::dom::EventTarget)
-  if (aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter))) {
-    foundInterface = static_cast<nsPIDOMWindowOuter*>(this);
-  } else
-  if (aIID.Equals(NS_GET_IID(mozIDOMWindowProxy))) {
-    foundInterface = static_cast<mozIDOMWindowProxy*>(this);
-  } else
-  if (aIID.Equals(NS_GET_IID(nsIDOMChromeWindow)) && IsChromeWindow()) {
-    foundInterface = static_cast<nsIDOMChromeWindow*>(this);
-  } else
+  NS_INTERFACE_MAP_ENTRY(nsPIDOMWindowOuter)
+  NS_INTERFACE_MAP_ENTRY(mozIDOMWindowProxy)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMChromeWindow, IsChromeWindow())
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
 NS_INTERFACE_MAP_END
 
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGlobalWindowOuter)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGlobalWindowOuter)
 
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -139,17 +139,17 @@ DOMInterfaces = {
     'concrete': False
 },
 
 'console': {
     'nativeType': 'mozilla::dom::Console',
 },
 
 'ConsoleInstance': {
-    'implicitJSContext': ['clear', 'count', 'groupEnd', 'time', 'timeEnd'],
+    'implicitJSContext': ['clear', 'count', 'countReset', 'groupEnd', 'time', 'timeEnd'],
 },
 
 'ContentProcessMessageManager': {
     'nativeType': 'mozilla::dom::ProcessGlobal'
 },
 
 'ConvolverNode': {
     'implicitJSContext': [ 'buffer' ],
--- a/dom/cache/FileUtils.cpp
+++ b/dom/cache/FileUtils.cpp
@@ -445,54 +445,42 @@ BodyDeleteOrphanedFiles(const QuotaInfo&
   nsCOMPtr<nsIFile> dir;
   nsresult rv = aBaseDir->Clone(getter_AddRefs(dir));
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   // Add the root morgue directory
   rv = dir->Append(NS_LITERAL_STRING("morgue"));
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   rv = dir->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   // Iterate over all the intermediate morgue subdirs
-  bool hasMore = false;
-  while (NS_SUCCEEDED(rv = entries->HasMoreElements(&hasMore)) && hasMore) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
-
-    nsCOMPtr<nsIFile> subdir = do_QueryInterface(entry);
-
+  nsCOMPtr<nsIFile> subdir;
+  while (NS_SUCCEEDED(rv = entries->GetNextFile(getter_AddRefs(subdir))) && subdir) {
     bool isDir = false;
     rv = subdir->IsDirectory(&isDir);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     // If a file got in here somehow, try to remove it and move on
     if (NS_WARN_IF(!isDir)) {
       rv = RemoveNsIFile(aQuotaInfo, subdir);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
       continue;
     }
 
-    nsCOMPtr<nsISimpleEnumerator> subEntries;
+    nsCOMPtr<nsIDirectoryEnumerator> subEntries;
     rv = subdir->GetDirectoryEntries(getter_AddRefs(subEntries));
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     // Now iterate over all the files in the subdir
-    bool subHasMore = false;
-    while(NS_SUCCEEDED(rv = subEntries->HasMoreElements(&subHasMore)) &&
-          subHasMore) {
-      nsCOMPtr<nsISupports> subEntry;
-      rv = subEntries->GetNext(getter_AddRefs(subEntry));
-      if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
-
-      nsCOMPtr<nsIFile> file = do_QueryInterface(subEntry);
-
+    nsCOMPtr<nsIFile> file;
+    while(NS_SUCCEEDED(rv = subEntries->GetNextFile(getter_AddRefs(file))) &&
+          file) {
       nsAutoCString leafName;
       rv = file->GetNativeLeafName(leafName);
       if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
       // Delete all tmp files regardless of known bodies.  These are
       // all considered orphans.
       if (StringEndsWith(leafName, NS_LITERAL_CSTRING(".tmp"))) {
         // remove recursively in case its somehow a directory
@@ -620,29 +608,22 @@ RemoveNsIFileRecursively(const QuotaInfo
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   if (!isDirectory) {
     return RemoveNsIFile(aQuotaInfo, aFile);
   }
 
   // Unfortunately, we need to traverse all the entries and delete files one by
   // one to update their usages to the QuotaManager.
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   rv = aFile->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
-  bool hasMore = false;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
-
-    nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
-    MOZ_ASSERT(file);
-
+  nsCOMPtr<nsIFile> file;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) && file) {
     rv = RemoveNsIFileRecursively(aQuotaInfo, file);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
   }
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   // In the end, remove the folder
   rv = aFile->Remove(/* recursive */ false);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
--- a/dom/cache/QuotaClient.cpp
+++ b/dom/cache/QuotaClient.cpp
@@ -34,29 +34,23 @@ using mozilla::MutexAutoLock;
 using mozilla::Unused;
 
 static nsresult
 GetBodyUsage(nsIFile* aDir, const Atomic<bool>& aCanceled,
              UsageInfo* aUsageInfo)
 {
   AssertIsOnIOThread();
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   nsresult rv = aDir->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
-  bool hasMore;
-  while (NS_SUCCEEDED(rv = entries->HasMoreElements(&hasMore)) && hasMore &&
-         !aCanceled) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
-
-    nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
-
+  nsCOMPtr<nsIFile> file;
+  while (NS_SUCCEEDED(rv = entries->GetNextFile(getter_AddRefs(file))) &&
+         file && !aCanceled) {
     bool isDir;
     rv = file->IsDirectory(&isDir);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     if (isDir) {
       rv = GetBodyUsage(file, aCanceled, aUsageInfo);
       if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
       continue;
@@ -182,29 +176,23 @@ public:
                                                          &paddingSize)))) {
         rv = LockedGetPaddingSizeFromDB(dir, aGroup, aOrigin, &paddingSize);
         if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
       }
     }
 
     aUsageInfo->AppendToFileUsage(paddingSize);
 
-    nsCOMPtr<nsISimpleEnumerator> entries;
+    nsCOMPtr<nsIDirectoryEnumerator> entries;
     rv = dir->GetDirectoryEntries(getter_AddRefs(entries));
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
-    bool hasMore;
-    while (NS_SUCCEEDED(rv = entries->HasMoreElements(&hasMore)) && hasMore &&
-           !aCanceled) {
-      nsCOMPtr<nsISupports> entry;
-      rv = entries->GetNext(getter_AddRefs(entry));
-      if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
-
-      nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
-
+    nsCOMPtr<nsIFile> file;
+    while (NS_SUCCEEDED(rv = entries->GetNextFile(getter_AddRefs(file))) &&
+           file && !aCanceled) {
       nsAutoString leafName;
       rv = file->GetLeafName(leafName);
       if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
       bool isDir;
       rv = file->IsDirectory(&isDir);
       if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
--- a/dom/cache/test/xpcshell/make_profile.js
+++ b/dom/cache/test/xpcshell/make_profile.js
@@ -14,17 +14,17 @@
 function enumerate_tree(entryList) {
   for (var index = 0; index < entryList.length; ++index) {
     var path = entryList[index].path;
     var file = entryList[index].file;
 
     if (file.isDirectory()) {
       var dirList = file.directoryEntries;
       while (dirList.hasMoreElements()) {
-        var dirFile = dirList.getNext().QueryInterface(Ci.nsIFile);
+        var dirFile = dirList.nextFile;
         entryList.push({ path: path + '/' + dirFile.leafName, file: dirFile });
       }
     }
   }
 }
 
 function zip_profile(zipFile, profileDir) {
   var zipWriter = Cc['@mozilla.org/zipwriter;1']
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -4660,69 +4660,76 @@ CanvasRenderingContext2D::SetLineDashOff
 }
 
 double
 CanvasRenderingContext2D::LineDashOffset() const {
   return CurrentState().dashOffset;
 }
 
 bool
-CanvasRenderingContext2D::IsPointInPath(JSContext* aCx, double aX, double aY, const CanvasWindingRule& aWinding)
+CanvasRenderingContext2D::IsPointInPath(JSContext* aCx, double aX, double aY,
+                                        const CanvasWindingRule& aWinding,
+                                        nsIPrincipal& aSubjectPrincipal)
 {
   if (!FloatValidate(aX, aY)) {
     return false;
   }
 
   // Check for site-specific permission and return false if no permission.
   if (mCanvasElement) {
     nsCOMPtr<nsIDocument> ownerDoc = mCanvasElement->OwnerDoc();
-    if (!CanvasUtils::IsImageExtractionAllowed(ownerDoc, aCx)) {
+    if (!CanvasUtils::IsImageExtractionAllowed(ownerDoc, aCx, aSubjectPrincipal)) {
       return false;
     }
   }
 
   EnsureUserSpacePath(aWinding);
   if (!mPath) {
     return false;
   }
 
   if (mPathTransformWillUpdate) {
     return mPath->ContainsPoint(Point(aX, aY), mPathToDS);
   }
 
   return mPath->ContainsPoint(Point(aX, aY), mTarget->GetTransform());
 }
 
-bool CanvasRenderingContext2D::IsPointInPath(JSContext* aCx, const CanvasPath& aPath, double aX, double aY, const CanvasWindingRule& aWinding)
+bool
+CanvasRenderingContext2D::IsPointInPath(JSContext* aCx, const CanvasPath& aPath,
+                                        double aX, double aY,
+                                        const CanvasWindingRule& aWinding,
+                                        nsIPrincipal&)
 {
   if (!FloatValidate(aX, aY)) {
     return false;
   }
 
   EnsureTarget();
   if (!IsTargetValid()) {
     return false;
   }
 
   RefPtr<gfx::Path> tempPath = aPath.GetPath(aWinding, mTarget);
 
   return tempPath->ContainsPoint(Point(aX, aY), mTarget->GetTransform());
 }
 
 bool
-CanvasRenderingContext2D::IsPointInStroke(JSContext* aCx, double aX, double aY)
+CanvasRenderingContext2D::IsPointInStroke(JSContext* aCx, double aX, double aY,
+                                          nsIPrincipal& aSubjectPrincipal)
 {
   if (!FloatValidate(aX, aY)) {
     return false;
   }
 
   // Check for site-specific permission and return false if no permission.
   if (mCanvasElement) {
     nsCOMPtr<nsIDocument> ownerDoc = mCanvasElement->OwnerDoc();
-    if (!CanvasUtils::IsImageExtractionAllowed(ownerDoc, aCx)) {
+    if (!CanvasUtils::IsImageExtractionAllowed(ownerDoc, aCx, aSubjectPrincipal)) {
       return false;
     }
   }
 
   EnsureUserSpacePath();
   if (!mPath) {
     return false;
   }
@@ -4738,17 +4745,19 @@ CanvasRenderingContext2D::IsPointInStrok
                               state.dashOffset);
 
   if (mPathTransformWillUpdate) {
     return mPath->StrokeContainsPoint(strokeOptions, Point(aX, aY), mPathToDS);
   }
   return mPath->StrokeContainsPoint(strokeOptions, Point(aX, aY), mTarget->GetTransform());
 }
 
-bool CanvasRenderingContext2D::IsPointInStroke(JSContext* aCx, const CanvasPath& aPath, double aX, double aY)
+bool
+CanvasRenderingContext2D::IsPointInStroke(JSContext* aCx, const CanvasPath& aPath,
+                                          double aX, double aY, nsIPrincipal&)
 {
   if (!FloatValidate(aX, aY)) {
     return false;
   }
 
   EnsureTarget();
   if (!IsTargetValid()) {
     return false;
@@ -5430,18 +5439,19 @@ CanvasRenderingContext2D::DrawWindow(nsG
 }
 
 //
 // device pixel getting/setting
 //
 
 already_AddRefed<ImageData>
 CanvasRenderingContext2D::GetImageData(JSContext* aCx, double aSx,
-                                       double aSy, double aSw,
-                                       double aSh, ErrorResult& aError)
+                                       double aSy, double aSw, double aSh,
+                                       nsIPrincipal& aSubjectPrincipal,
+                                       ErrorResult& aError)
 {
   if (mDrawObserver) {
     mDrawObserver->DidDrawCall(CanvasDrawObserver::DrawCallType::GetImageData);
   }
 
   if (!mCanvasElement && !mDocShell) {
     NS_ERROR("No canvas element and no docshell in GetImageData!!!");
     aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
@@ -5497,32 +5507,33 @@ CanvasRenderingContext2D::GetImageData(J
   if (w == 0) {
     w = 1;
   }
   if (h == 0) {
     h = 1;
   }
 
   JS::Rooted<JSObject*> array(aCx);
-  aError = GetImageDataArray(aCx, x, y, w, h, array.address());
+  aError = GetImageDataArray(aCx, x, y, w, h, aSubjectPrincipal, array.address());
   if (aError.Failed()) {
     return nullptr;
   }
   MOZ_ASSERT(array);
 
   RefPtr<ImageData> imageData = new ImageData(w, h, *array);
   return imageData.forget();
 }
 
 nsresult
 CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
                                             int32_t aX,
                                             int32_t aY,
                                             uint32_t aWidth,
                                             uint32_t aHeight,
+                                            nsIPrincipal& aSubjectPrincipal,
                                             JSObject** aRetval)
 {
   if (mDrawObserver) {
     mDrawObserver->DidDrawCall(CanvasDrawObserver::DrawCallType::GetImageData);
   }
 
   MOZ_ASSERT(aWidth && aHeight);
 
@@ -5585,17 +5596,17 @@ CanvasRenderingContext2D::GetImageDataAr
   dstWriteRect.MoveBy(-aX, -aY);
 
   // Check for site-specific permission.  This check is not needed if the
   // canvas was created with a docshell (that is only done for special
   // internal uses).
   bool usePlaceholder = false;
   if (mCanvasElement) {
     nsCOMPtr<nsIDocument> ownerDoc = mCanvasElement->OwnerDoc();
-    usePlaceholder = !CanvasUtils::IsImageExtractionAllowed(ownerDoc, aCx);
+    usePlaceholder = !CanvasUtils::IsImageExtractionAllowed(ownerDoc, aCx, aSubjectPrincipal);
   }
 
   do {
     JS::AutoCheckCannotGC nogc;
     bool isShared;
     uint8_t* data = JS_GetUint8ClampedArrayData(darray, &isShared, nogc);
     MOZ_ASSERT(!isShared);        // Should not happen, data was created above
 
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -198,20 +198,26 @@ public:
   void Fill(const CanvasWindingRule& aWinding);
   void Fill(const CanvasPath& aPath, const CanvasWindingRule& aWinding);
   void Stroke();
   void Stroke(const CanvasPath& aPath);
   void DrawFocusIfNeeded(mozilla::dom::Element& aElement, ErrorResult& aRv);
   bool DrawCustomFocusRing(mozilla::dom::Element& aElement);
   void Clip(const CanvasWindingRule& aWinding);
   void Clip(const CanvasPath& aPath, const CanvasWindingRule& aWinding);
-  bool IsPointInPath(JSContext* aCx, double aX, double aY, const CanvasWindingRule& aWinding);
-  bool IsPointInPath(JSContext* aCx, const CanvasPath& aPath, double aX, double aY, const CanvasWindingRule& aWinding);
-  bool IsPointInStroke(JSContext* aCx, double aX, double aY);
-  bool IsPointInStroke(JSContext* aCx, const CanvasPath& aPath, double aX, double aY);
+  bool IsPointInPath(JSContext* aCx, double aX, double aY,
+                     const CanvasWindingRule& aWinding,
+                     nsIPrincipal& aSubjectPrincipal);
+  bool IsPointInPath(JSContext* aCx, const CanvasPath& aPath,
+                     double aX, double aY,
+                     const CanvasWindingRule& aWinding, nsIPrincipal&);
+  bool IsPointInStroke(JSContext* aCx, double aX, double aY,
+                       nsIPrincipal& aSubjectPrincipal);
+  bool IsPointInStroke(JSContext* aCx, const CanvasPath& aPath,
+                       double aX, double aY, nsIPrincipal&);
   void FillText(const nsAString& aText, double aX, double aY,
                 const Optional<double>& aMaxWidth,
                 mozilla::ErrorResult& aError);
   void StrokeText(const nsAString& aText, double aX, double aY,
                   const Optional<double>& aMaxWidth,
                   mozilla::ErrorResult& aError);
   TextMetrics*
     MeasureText(const nsAString& aRawText, mozilla::ErrorResult& aError);
@@ -243,17 +249,17 @@ public:
   already_AddRefed<ImageData>
     CreateImageData(JSContext* aCx, double aSw, double aSh,
                     mozilla::ErrorResult& aError);
   already_AddRefed<ImageData>
     CreateImageData(JSContext* aCx, ImageData& aImagedata,
                     mozilla::ErrorResult& aError);
   already_AddRefed<ImageData>
     GetImageData(JSContext* aCx, double aSx, double aSy, double aSw, double aSh,
-                 mozilla::ErrorResult& aError);
+                 nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& aError);
   void PutImageData(ImageData& aImageData,
                     double aDx, double aDy, mozilla::ErrorResult& aError);
   void PutImageData(ImageData& aImageData,
                     double aDx, double aDy, double aDirtyX, double aDirtyY,
                     double aDirtyWidth, double aDirtyHeight,
                     mozilla::ErrorResult& aError);
 
   double LineWidth() override
@@ -554,16 +560,17 @@ public:
   void OnShutdown();
 
   // Check the global setup, as well as the compositor type:
   bool AllowOpenGLCanvas() const;
 
 protected:
   nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY,
                              uint32_t aWidth, uint32_t aHeight,
+                             nsIPrincipal& aSubjectPrincipal,
                              JSObject** aRetval);
 
   nsresult PutImageData_explicit(int32_t aX, int32_t aY, uint32_t aW, uint32_t aH,
                                  dom::Uint8ClampedArray* aArray,
                                  bool aHasDirtyRect, int32_t aDirtyX, int32_t aDirtyY,
                                  int32_t aDirtyWidth, int32_t aDirtyHeight);
 
   bool CopyBufferProvider(layers::PersistentBufferProvider& aOld,
--- a/dom/canvas/CanvasUtils.cpp
+++ b/dom/canvas/CanvasUtils.cpp
@@ -38,50 +38,36 @@
 #define TOPIC_CANVAS_PERMISSIONS_PROMPT "canvas-permissions-prompt"
 #define PERMISSION_CANVAS_EXTRACT_DATA "canvas"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace CanvasUtils {
 
-bool IsImageExtractionAllowed(nsIDocument *aDocument, JSContext *aCx)
+bool IsImageExtractionAllowed(nsIDocument *aDocument, JSContext *aCx, nsIPrincipal& aPrincipal)
 {
     // Do the rest of the checks only if privacy.resistFingerprinting is on.
     if (!nsContentUtils::ShouldResistFingerprinting()) {
         return true;
     }
 
     // Don't proceed if we don't have a document or JavaScript context.
     if (!aDocument || !aCx) {
         return false;
     }
 
-    nsPIDOMWindowOuter *win = aDocument->GetWindow();
-    nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win));
-
-    if (sop) {
-        // Documents with system principal can always extract canvas data.
-        nsIPrincipal *principal = sop->GetPrincipal();
-        if (nsContentUtils::IsSystemPrincipal(principal)) {
-            return true;
-        }
-
-        if (principal) {
-            // Allow extension principals
-            nsAutoString addonId;
-            Unused << NS_WARN_IF(NS_FAILED(principal->GetAddonId(addonId)));
-            if (!addonId.IsEmpty()) {
-                return true;
-            }
-        }
+    // The system principal can always extract canvas data.
+    if (nsContentUtils::IsSystemPrincipal(&aPrincipal)) {
+        return true;
     }
 
-    // Always give permission to chrome scripts (e.g. Page Inspector).
-    if (nsContentUtils::ThreadsafeIsCallerChrome()) {
+    // Allow extension principals.
+    auto principal = BasePrincipal::Cast(&aPrincipal);
+    if (principal->AddonPolicy() || principal->ContentScriptAddonPolicy()) {
         return true;
     }
 
     // Get the document URI and its spec.
     nsIURI *docURI = aDocument->GetDocumentURI();
     nsCString docURISpec;
     docURI->GetSpec(docURISpec);
 
@@ -173,16 +159,17 @@ bool IsImageExtractionAllowed(nsIDocumen
     message.AppendPrintf("Blocked %s in page %s from extracting canvas data, but prompting the user.",
                          docURISpec.get(), topLevelDocURISpec.get());
     if (isScriptKnown) {
         message.AppendPrintf(" %s:%u.", scriptFile.get(), scriptLine);
     }
     nsContentUtils::LogMessageToConsole(message.get());
 
     // Prompt the user (asynchronous).
+    nsPIDOMWindowOuter *win = aDocument->GetWindow();
     if (XRE_IsContentProcess()) {
         TabChild* tabChild = TabChild::GetFrom(win);
         if (tabChild) {
             tabChild->SendShowCanvasPermissionPrompt(topLevelDocURISpec);
         }
     } else {
         nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
         if (obs) {
--- a/dom/canvas/CanvasUtils.h
+++ b/dom/canvas/CanvasUtils.h
@@ -45,17 +45,17 @@ void DoDrawImageSecurityCheck(dom::HTMLC
                               nsIPrincipal *aPrincipal,
                               bool forceWriteOnly,
                               bool CORSUsed);
 
 // Check if the context is chrome or has the permission to drawWindow
 bool HasDrawWindowPrivilege(JSContext* aCx, JSObject* aObj);
 
 // Check site-specific permission and display prompt if appropriate.
-bool IsImageExtractionAllowed(nsIDocument *aDocument, JSContext *aCx);
+bool IsImageExtractionAllowed(nsIDocument *aDocument, JSContext *aCx, nsIPrincipal& aPrincipal);
 
 // Make a double out of |v|, treating undefined values as 0.0 (for
 // the sake of sparse arrays).  Return true iff coercion
 // succeeded.
 bool CoerceDouble(const JS::Value& v, double* d);
 
     /* Float validation stuff */
 #define VALIDATE(_f)  if (!IsFinite(_f)) return false
--- a/dom/canvas/test/webgl-conf/generated-mochitest.ini
+++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini
@@ -4952,17 +4952,17 @@ support-files = always-fail.html
                 checkout/test-guidelines.md
                 checkout/webgl-conformance-tests.html
                 iframe-passthrough.css
                 mochi-single.html
 
 [generated/test_..__always-fail.html]
 fail-if = 1
 [generated/test_2_conformance2__attribs__gl-bindAttribLocation-aliasing-inactive.html]
-fail-if = 1
+fail-if = (os != 'win')
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__attribs__gl-vertex-attrib-i-render.html]
 skip-if = (os == 'win') || (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__attribs__gl-vertex-attrib-normalized-int.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__attribs__gl-vertex-attrib.html]
 skip-if = (os == 'win') || (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__attribs__gl-vertexattribipointer-offsets.html]
@@ -5090,20 +5090,18 @@ skip-if = (os == 'android' || os == 'lin
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__shader-with-invalid-characters.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__shader-with-mis-matching-uniform-block.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__short-circuiting-in-loop-condition.html]
 skip-if = (os == 'win' && os_version == '6.1') || (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__switch-case.html]
-fail-if = (os == 'win')
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__texture-offset-non-constant-offset.html]
-fail-if = (os == 'win')
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__texture-offset-out-of-range.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__texture-offset-uniform-texture-coordinate.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__tricky-loop-conditions.html]
 fail-if = (os == 'win')
 skip-if = (os == 'android' || os == 'linux')
@@ -7274,18 +7272,17 @@ skip-if = (os == 'android' || os == 'lin
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__non-existent-varying.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__simultaneous_binding.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__switching-objects.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__too-small-buffers.html]
-fail-if = 1
-skip-if = (os == 'android' || os == 'linux')
+skip-if = 1 || (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__transform_feedback.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__two-unreferenced-varyings.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__unwritten-output-defaults-to-zero.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__uniforms__dependent-buffer-change.html]
 skip-if = (os == 'android' || os == 'linux')
--- a/dom/canvas/test/webgl-conf/mochitest-errata.ini
+++ b/dom/canvas/test/webgl-conf/mochitest-errata.ini
@@ -84,21 +84,22 @@ skip-if = (os == 'win')
 skip-if = 1
 [generated/test_2_conformance2__rendering__depth-stencil-feedback-loop.html]
 fail-if = 1
 [generated/test_2_conformance2__rendering__instanced-arrays.html]
 fail-if = 1
 [generated/test_2_conformance2__rendering__read-draw-when-missing-image.html]
 fail-if = 1
 [generated/test_2_conformance2__transform_feedback__too-small-buffers.html]
-fail-if = 1
+# ABORT_ON_ERROR
+skip-if = 1
 [generated/test_2_conformance2__uniforms__incompatible-texture-type-for-sampler.html]
 fail-if = 1
 [generated/test_2_conformance2__attribs__gl-bindAttribLocation-aliasing-inactive.html]
-fail-if = 1
+fail-if = (os != 'win')
 
 [generated/test_conformance__rendering__texture-switch-performance.html]
 # Frequent orange on linux+asan, but likely intermittant:
 # Texture switching significantly hurt performance - achieved 77 frames in 2.016 seconds (0.79 times baseline performance)
 skip-if = 1
 [generated/test_2_conformance__rendering__texture-switch-performance.html]
 # Orange on win10+debug
 # Texture switching significantly hurt performance - achieved 3 frames in 2.164
@@ -1192,20 +1193,16 @@ fail-if = (os == 'win')
 [generated/test_2_conformance__rendering__preservedrawingbuffer-leak.html]
 skip-if = (os == 'win')
 [generated/test_conformance__context__context-size-change.html]
 skip-if = (os == 'win')
 [generated/test_conformance__rendering__preservedrawingbuffer-leak.html]
 skip-if = (os == 'win')
 [generated/test_2_conformance2__glsl3__array-initialize-with-same-name-array.html]
 fail-if = (os == 'win')
-[generated/test_2_conformance2__glsl3__switch-case.html]
-fail-if = (os == 'win')
-[generated/test_2_conformance2__glsl3__texture-offset-non-constant-offset.html]
-fail-if = (os == 'win')
 [generated/test_2_conformance__misc__webgl-specific-stencil-settings.html]
 # [gl:0D6DE000] mozilla::gl::GLContext::raw_fDrawArrays: Generated unexpected GL_INVALID_OPERATION error. (0x0502)
 # ERR: gl::ValidateDrawBase(2519): This ANGLE implementation does not support separate front/back stencil writemasks, reference values, or stencil mask values.
 # Hit MOZ_CRASH(Unexpected error with MOZ_GL_DEBUG_ABORT_ON_ERROR. (Run with MOZ_GL_DEBUG_ABORT_ON_ERROR=0 to disable)) at z:/build/build/src/gfx/gl/GLContext.cpp:3030
 skip-if = (os == 'win')
 [generated/test_conformance__misc__webgl-specific-stencil-settings.html]
 skip-if = (os == 'win')
 [generated/test_conformance__textures__misc__tex-video-using-tex-unit-non-zero.html]
--- a/dom/canvas/test/webgl-mochitest/mochitest.ini
+++ b/dom/canvas/test/webgl-mochitest/mochitest.ini
@@ -8,27 +8,27 @@ support-files =
   webgl-util.js
   test_video_fastpath.js
   red-green.mp4
   red-green.theora.ogv
   red-green.webmvp8.webm
   red-green.webmvp9.webm
 
 [ensure-exts/test_ANGLE_instanced_arrays.html]
-fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6')
+fail-if = (os == 'android')
 [ensure-exts/test_EXT_blend_minmax.html]
 fail-if = (os == 'android')
 [ensure-exts/test_EXT_color_buffer_half_float.html]
 fail-if = (os == 'android')
 [ensure-exts/test_EXT_disjoint_timer_query.html]
 fail-if = 1
 [ensure-exts/test_EXT_frag_depth.html]
 fail-if = (os == 'android')
 [ensure-exts/test_EXT_sRGB.html]
-fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6')
+fail-if = (os == 'android')
 [ensure-exts/test_EXT_shader_texture_lod.html]
 fail-if = (os == 'android')
 [ensure-exts/test_EXT_texture_filter_anisotropic.html]
 fail-if = (os == 'android') || (os == 'linux')
 [ensure-exts/test_OES_standard_derivatives.html]
 fail-if = (os == 'android')
 [ensure-exts/test_WEBGL_color_buffer_float.html]
 fail-if = (os == 'android')
@@ -38,17 +38,16 @@ fail-if = (os == 'android') || (os == 'l
 fail-if = (os == 'android') || (os == 'mac') || (os == 'win')
 [ensure-exts/test_WEBGL_compressed_texture_etc1.html]
 fail-if = (os == 'linux') || (os == 'mac') || (os == 'win')
 [ensure-exts/test_WEBGL_compressed_texture_pvrtc.html]
 fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win')
 [ensure-exts/test_WEBGL_compressed_texture_s3tc.html]
 fail-if = (os == 'android')
 [ensure-exts/test_WEBGL_depth_texture.html]
-fail-if = (os == 'mac' && os_version == '10.6')
 [ensure-exts/test_WEBGL_draw_buffers.html]
 fail-if = (os == 'android') || (os == 'win' && os_version == '5.1')
 
 [ensure-exts/test_common.html]
 
 
 [regress/test_bug_1268096.html]
 
--- a/dom/chrome-webidl/MatchPattern.webidl
+++ b/dom/chrome-webidl/MatchPattern.webidl
@@ -120,9 +120,15 @@ interface MatchPatternSet {
 };
 
 dictionary MatchPatternOptions {
   /**
    * If true, the path portion of the pattern is ignored, and replaced with a
    * wildcard. The `pattern` property is updated to reflect this.
    */
   boolean ignorePath = false;
+
+  /**
+   * If true, the set of schemes this pattern can match is restricted to
+   * those accessible by WebExtensions.
+   */
+  boolean restrictSchemes = true;
 };
--- a/dom/console/Console.cpp
+++ b/dom/console/Console.cpp
@@ -225,18 +225,19 @@ public:
   // something went wrong. They will be set on the owning thread and never
   // touched again on that thread. They will be used in order to create a
   // ConsoleTimerLogOrEnd dictionary. This members are set when
   // console.timeEnd() or console.timeLog() are called.
   double mLogTimerDuration;
   nsString mLogTimerLabel;
   Console::TimerStatus mLogTimerStatus;
 
-  // These 2 values are set by IncreaseCounter on the owning thread and they are
-  // used CreateCounterValue. These members are set when console.count() is
+  // These 2 values are set by IncreaseCounter or ResetCounter on the owning
+  // thread and they are used by CreateCounterOrResetCounterValue.
+  // These members are set when console.count() or console.countReset() are
   // called.
   nsString mCountLabel;
   uint32_t mCountValue;
 
   // The concept of outerID and innerID is misleading because when a
   // ConsoleCallData is created from a window, these are the window IDs, but
   // when the object is created from a SharedWorker, a ServiceWorker or a
   // subworker of a ChromeWorker these IDs are the type of worker and the
@@ -1439,16 +1440,23 @@ Console::Assert(const GlobalObject& aGlo
 
 /* static */ void
 Console::Count(const GlobalObject& aGlobal, const nsAString& aLabel)
 {
   StringMethod(aGlobal, aLabel, Sequence<JS::Value>(), MethodCount,
                NS_LITERAL_STRING("count"));
 }
 
+/* static */ void
+Console::CountReset(const GlobalObject& aGlobal, const nsAString& aLabel)
+{
+  StringMethod(aGlobal, aLabel, Sequence<JS::Value>(), MethodCountReset,
+               NS_LITERAL_STRING("countReset"));
+}
+
 namespace {
 
 void
 StackFrameToStackEntry(JSContext* aCx, nsIStackFrame* aStackFrame,
                        ConsoleStackEntry& aStackEntry)
 {
   MOZ_ASSERT(aStackFrame);
 
@@ -1626,16 +1634,23 @@ Console::MethodInternal(JSContext* aCx, 
 
   else if (aMethodName == MethodCount) {
     callData->mCountValue = IncreaseCounter(aCx, aData, callData->mCountLabel);
     if (!callData->mCountValue) {
       return;
     }
   }
 
+  else if (aMethodName == MethodCountReset) {
+    callData->mCountValue = ResetCounter(aCx, aData, callData->mCountLabel);
+    if (callData->mCountLabel.IsEmpty()) {
+      return;
+    }
+  }
+
   // Before processing this CallData differently, it's time to call the dump
   // function.
   if (aMethodName == MethodTrace || aMethodName == MethodAssert) {
     MaybeExecuteDumpFunction(aCx, aMethodString, aData, stack);
   } else if ((aMethodName == MethodTime ||
               aMethodName == MethodTimeEnd) &&
              !aData.IsEmpty()) {
     MaybeExecuteDumpFunctionForTime(aCx, aMethodName, aMethodString,
@@ -1894,19 +1909,20 @@ Console::PopulateConsoleNotificationInTh
 
   else if ((aData->mMethodName == MethodTimeEnd ||
             aData->mMethodName == MethodTimeLog) && !aArguments.IsEmpty()) {
     event.mTimer = CreateLogOrEndTimerValue(aCx, aData->mLogTimerLabel,
                                             aData->mLogTimerDuration,
                                             aData->mLogTimerStatus);
   }
 
-  else if (aData->mMethodName == MethodCount) {
-    event.mCounter = CreateCounterValue(aCx, aData->mCountLabel,
-                                        aData->mCountValue);
+  else if (aData->mMethodName == MethodCount ||
+           aData->mMethodName == MethodCountReset) {
+    event.mCounter = CreateCounterOrResetCounterValue(aCx, aData->mCountLabel,
+                                                      aData->mCountValue);
   }
 
   JSAutoRealm ar2(aCx, targetScope);
 
   if (NS_WARN_IF(!ToJSValue(aCx, event, aEventValue))) {
     return false;
   }
 
@@ -2499,24 +2515,58 @@ Console::IncreaseCounter(JSContext* aCx,
       // oops, we speculatively added an entry even though we shouldn't
       mCounterRegistry.Remove(aCountLabel);
       return MAX_PAGE_COUNTERS;
     }
   }
   return entry.Data();
 }
 
+uint32_t
+Console::ResetCounter(JSContext* aCx, const Sequence<JS::Value>& aArguments,
+                      nsAString& aCountLabel)
+{
+  AssertIsOnOwningThread();
+
+  ConsoleCommon::ClearException ce(aCx);
+
+  MOZ_ASSERT(!aArguments.IsEmpty());
+
+  JS::Rooted<JS::Value> labelValue(aCx, aArguments[0]);
+  JS::Rooted<JSString*> jsString(aCx, JS::ToString(aCx, labelValue));
+  if (!jsString) {
+    return 0; // We cannot continue.
+  }
+
+  nsAutoJSString string;
+  if (!string.init(aCx, jsString)) {
+    return 0; // We cannot continue.
+  }
+
+  aCountLabel = string;
+
+  if (mCounterRegistry.Remove(aCountLabel)) {
+    return 0;
+  }
+
+  // Let's return something different than 0 if the key doesn't exist.
+  return MAX_PAGE_COUNTERS;
+}
+
 JS::Value
-Console::CreateCounterValue(JSContext* aCx, const nsAString& aCountLabel,
-                            uint32_t aCountValue) const
+Console::CreateCounterOrResetCounterValue(JSContext* aCx,
+                                          const nsAString& aCountLabel,
+                                          uint32_t aCountValue) const
 {
   ConsoleCommon::ClearException ce(aCx);
 
   if (aCountValue == MAX_PAGE_COUNTERS) {
     RootedDictionary<ConsoleCounterError> error(aCx);
+    error.mLabel = aCountLabel;
+    error.mError.AssignLiteral("counterDoesntExist");
 
     JS::Rooted<JS::Value> value(aCx);
     if (!ToJSValue(aCx, error, &value)) {
       return JS::UndefinedValue();
     }
 
     return value;
   }
@@ -3073,16 +3123,17 @@ Console::InternalLogLevelToInteger(Metho
     case MethodGroupCollapsed: return 3;
     case MethodGroupEnd: return 3;
     case MethodTime: return 3;
     case MethodTimeLog: return 3;
     case MethodTimeEnd: return 3;
     case MethodTimeStamp: return 3;
     case MethodAssert: return 3;
     case MethodCount: return 3;
+    case MethodCountReset: return 3;
     case MethodClear: return 3;
     case MethodProfile: return 3;
     case MethodProfileEnd: return 3;
     default:
       MOZ_CRASH("MethodName is out of sync with the Console implementation!");
       return 0;
   }
 
--- a/dom/console/Console.h
+++ b/dom/console/Console.h
@@ -115,16 +115,19 @@ public:
   static void
   Assert(const GlobalObject& aGlobal, bool aCondition,
          const Sequence<JS::Value>& aData);
 
   static void
   Count(const GlobalObject& aGlobal, const nsAString& aLabel);
 
   static void
+  CountReset(const GlobalObject& aGlobal, const nsAString& aLabel);
+
+  static void
   Clear(const GlobalObject& aGlobal);
 
   static already_AddRefed<ConsoleInstance>
   CreateInstance(const GlobalObject& aGlobal,
                  const ConsoleInstanceOptions& aOptions);
 
   void
   ClearStorage();
@@ -163,16 +166,17 @@ private:
     MethodGroupCollapsed,
     MethodGroupEnd,
     MethodTime,
     MethodTimeLog,
     MethodTimeEnd,
     MethodTimeStamp,
     MethodAssert,
     MethodCount,
+    MethodCountReset,
     MethodClear,
     MethodProfile,
     MethodProfileEnd,
   };
 
   static already_AddRefed<Console>
   GetConsole(const GlobalObject& aGlobal);
 
@@ -355,39 +359,53 @@ private:
                            TimerStatus aTimerStatus) const;
 
   // The method populates a Sequence from an array of JS::Value.
   bool
   ArgumentsToValueList(const Sequence<JS::Value>& aData,
                        Sequence<JS::Value>& aSequence) const;
 
   // This method follows the same pattern as StartTimer: its runs on the owning
-  // thread and populate aCountLabel, used by CreateCounterValue. Returns
-  // 3 possible values:
+  // thread and populate aCountLabel, used by CreateCounterOrResetCounterValue.
+  // Returns 3 possible values:
   // * MAX_PAGE_COUNTERS in case of error that has to be reported;
   // * 0 in case of a CX exception. The operation cannot continue;
   // * the incremented counter value.
   // Params:
   // * aCx - the JSContext rooting aData.
   // * aData - the arguments received by the console.count() method.
   // * aCountLabel - the label that will be populated by this method.
   uint32_t
   IncreaseCounter(JSContext* aCx, const Sequence<JS::Value>& aData,
                   nsAString& aCountLabel);
 
+  // This method follows the same pattern as StartTimer: its runs on the owning
+  // thread and populate aCountLabel, used by CreateCounterResetValue. Returns
+  // 3 possible values:
+  // * MAX_PAGE_COUNTERS in case of error that has to be reported;
+  // * 0 elsewhere. In case of a CX exception, aCountLabel will be an empty
+  // string.
+  // Params:
+  // * aCx - the JSContext rooting aData.
+  // * aData - the arguments received by the console.count() method.
+  // * aCountLabel - the label that will be populated by this method.
+  uint32_t
+  ResetCounter(JSContext* aCx, const Sequence<JS::Value>& aData,
+               nsAString& aCountLabel);
+
   // This method generates a ConsoleCounter dictionary as JS::Value. If
   // aCountValue is == MAX_PAGE_COUNTERS it generates a ConsoleCounterError
   // instead. See IncreaseCounter.
   // * aCx - this is the context that will root the returned value.
   // * aCountLabel - this label must be what IncreaseCounter received as
   //                 aTimerLabel.
   // * aCountValue - the return value of IncreaseCounter.
   JS::Value
-  CreateCounterValue(JSContext* aCx, const nsAString& aCountLabel,
-                     uint32_t aCountValue) const;
+  CreateCounterOrResetCounterValue(JSContext* aCx, const nsAString& aCountLabel,
+                                   uint32_t aCountValue) const;
 
   bool
   ShouldIncludeStackTrace(MethodName aMethodName) const;
 
   JSObject*
   GetOrCreateSandbox(JSContext* aCx, nsIPrincipal* aPrincipal);
 
   void
--- a/dom/console/ConsoleInstance.cpp
+++ b/dom/console/ConsoleInstance.cpp
@@ -212,16 +212,24 @@ void
 ConsoleInstance::Count(JSContext* aCx, const nsAString& aLabel)
 {
   mConsole->StringMethodInternal(aCx, aLabel, Sequence<JS::Value>(),
                                  Console::MethodCount,
                                  NS_LITERAL_STRING("count"));
 }
 
 void
+ConsoleInstance::CountReset(JSContext* aCx, const nsAString& aLabel)
+{
+  mConsole->StringMethodInternal(aCx, aLabel, Sequence<JS::Value>(),
+                                 Console::MethodCountReset,
+                                 NS_LITERAL_STRING("countReset"));
+}
+
+void
 ConsoleInstance::Clear(JSContext* aCx)
 {
   const Sequence<JS::Value> data;
   mConsole->MethodInternal(aCx, Console::MethodClear,
                            NS_LITERAL_STRING("clear"), data);
 }
 
 void
--- a/dom/console/ConsoleInstance.h
+++ b/dom/console/ConsoleInstance.h
@@ -92,16 +92,19 @@ public:
 
   void
   Assert(JSContext* aCx, bool aCondition, const Sequence<JS::Value>& aData);
 
   void
   Count(JSContext* aCx, const nsAString& aLabel);
 
   void
+  CountReset(JSContext* aCx, const nsAString& aLabel);
+
+  void
   Clear(JSContext* aCx);
 
   // For testing only.
   void ReportForServiceWorkerScope(const nsAString& aScope,
                                    const nsAString& aMessage,
                                    const nsAString& aFilename,
                                    uint32_t aLineNumber,
                                    uint32_t aColumnNumber,
--- a/dom/console/tests/mochitest.ini
+++ b/dom/console/tests/mochitest.ini
@@ -6,8 +6,9 @@ support-files =
 [test_bug978522.html]
 [test_bug979109.html]
 [test_bug989665.html]
 [test_consoleEmptyStack.html]
 [test_console_binding.html]
 [test_console_proto.html]
 [test_devtools_pref.html]
 [test_timer.html]
+[test_count.html]
new file mode 100644
--- /dev/null
+++ b/dom/console/tests/test_count.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test for count/countReset in console</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+  <script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function ConsoleListener() {
+  SpecialPowers.addObserver(this, "console-api-log-event");
+}
+
+ConsoleListener.prototype = {
+  observe(aSubject, aTopic, aData) {
+    let obj = aSubject.wrappedJSObject;
+    if (obj.arguments[0] != 'test') {
+      return;
+    }
+
+    if (!this._cb) {
+      ok(false, "Callback not set!");
+      return;
+    }
+
+    if (!this._cb(obj)) {
+      return;
+    }
+
+    this._cb = null;
+    this._resolve();
+  },
+
+  shutdown() {
+    SpecialPowers.removeObserver(this, "console-api-log-event");
+  },
+
+  waitFor(cb) {
+    return new Promise(resolve => {
+      this._cb = cb;
+      this._resolve = resolve;
+    });
+  },
+};
+
+let listener = new ConsoleListener();
+
+async function runTest() {
+  // First count.
+  let cl = listener.waitFor(obj => {
+    return ("counter" in obj) &&
+           ("label" in obj.counter) &&
+           obj.counter.label == "test" &&
+           obj.counter.count == 1;
+  });
+  console.count("test");
+  await cl;
+  ok(true, "Console.count == 1 received!");
+
+  // Second count.
+  cl = listener.waitFor(obj => {
+    return ("counter" in obj) &&
+           ("label" in obj.counter) &&
+           obj.counter.label == "test" &&
+           obj.counter.count == 2;
+  });
+  console.count("test");
+  await cl;
+  ok(true, "Console.count == 2 received!");
+
+  // Counter reset.
+  cl = listener.waitFor(obj => {
+    return ("counter" in obj) &&
+           ("label" in obj.counter) &&
+           obj.counter.label == "test" &&
+           obj.counter.count == 0;
+  });
+  console.countReset("test");
+  await cl;
+  ok(true, "Console.countReset == 0 received!");
+
+  // Counter reset with error.
+  cl = listener.waitFor(obj => {
+    return ("counter" in obj) &&
+           ("label" in obj.counter) &&
+           obj.counter.label == "test" &&
+           obj.counter.error == "counterDoesntExist";
+  });
+  console.countReset("test");
+  await cl;
+  ok(true, "Console.countReset with error received!");
+
+  // First again!
+  cl = listener.waitFor(obj => {
+    return ("counter" in obj) &&
+           ("label" in obj.counter) &&
+           obj.counter.label == "test" &&
+           obj.counter.count == 1;
+  });
+  console.count("test");
+  await cl;
+  ok(true, "Console.count == 1 received!");
+}
+
+runTest().then(SimpleTest.finish);
+
+  </script>
+</body>
+</html>
--- a/dom/events/DataTransferItem.cpp
+++ b/dom/events/DataTransferItem.cpp
@@ -104,17 +104,17 @@ DataTransferItem::SetData(nsIVariant* aD
 
 /* static */ DataTransferItem::eKind
 DataTransferItem::KindFromData(nsIVariant* aData)
 {
   nsCOMPtr<nsISupports> supports;
   nsresult rv = aData->GetAsISupports(getter_AddRefs(supports));
   if (NS_SUCCEEDED(rv) && supports) {
     // Check if we have one of the supported file data formats
-    if (nsCOMPtr<nsIDOMBlob>(do_QueryInterface(supports)) ||
+    if (RefPtr<Blob>(do_QueryObject(supports)) ||
         nsCOMPtr<BlobImpl>(do_QueryInterface(supports)) ||
         nsCOMPtr<nsIFile>(do_QueryInterface(supports))) {
       return KIND_FILE;
     }
   }
 
   nsAutoString string;
   // If we can't get the data type as a string, that means that the object
@@ -287,18 +287,17 @@ DataTransferItem::GetAsFile(nsIPrincipal
     nsCOMPtr<nsISupports> supports;
     aRv = data->GetAsISupports(getter_AddRefs(supports));
     MOZ_ASSERT(!aRv.Failed() && supports,
                "File objects should be stored as nsISupports variants");
     if (aRv.Failed() || !supports) {
       return nullptr;
     }
 
-    if (nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(supports)) {
-      Blob* blob = static_cast<Blob*>(domBlob.get());
+    if (RefPtr<Blob> blob = do_QueryObject(supports)) {
       mCachedFile = blob->ToFile();
     } else if (nsCOMPtr<BlobImpl> blobImpl = do_QueryInterface(supports)) {
       MOZ_ASSERT(blobImpl->IsFile());
       mCachedFile = File::Create(mDataTransfer, blobImpl);
     } else if (nsCOMPtr<nsIFile> ifile = do_QueryInterface(supports)) {
       mCachedFile = File::CreateFromFile(mDataTransfer, ifile);
     } else {
       MOZ_ASSERT(false, "One of the above code paths should be taken");
--- a/dom/file/Blob.cpp
+++ b/dom/file/Blob.cpp
@@ -29,18 +29,18 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Blob)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Blob)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMBlob)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMutable)
+  NS_INTERFACE_MAP_ENTRY_CONCRETE(Blob)
   NS_INTERFACE_MAP_ENTRY(nsIMutable)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Blob)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Blob)
 
 void
--- a/dom/file/Blob.h
+++ b/dom/file/Blob.h
@@ -8,41 +8,44 @@
 #define mozilla_dom_Blob_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/BlobImpl.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCOMPtr.h"
-#include "nsIDOMBlob.h"
 #include "nsIMutable.h"
 #include "nsWrapperCache.h"
 #include "nsWeakReference.h"
 
 class nsIInputStream;
 
 namespace mozilla {
 namespace dom {
 
 struct BlobPropertyBag;
 class File;
 class OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString;
 
-class Blob : public nsIDOMBlob
-           , public nsIMutable
+#define NS_DOM_BLOB_IID \
+{ 0x648c2a83, 0xbdb1, 0x4a7d, \
+  { 0xb5, 0x0a, 0xca, 0xcd, 0x92, 0x87, 0x45, 0xc2 } }
+
+
+class Blob : public nsIMutable
            , public nsSupportsWeakReference
            , public nsWrapperCache
 {
 public:
-  NS_DECL_NSIDOMBLOB
   NS_DECL_NSIMUTABLE
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Blob, nsIDOMBlob)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Blob, nsIMutable)
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOM_BLOB_IID)
 
   typedef OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString BlobPart;
 
   // This creates a Blob or a File based on the type of BlobImpl.
   static Blob*
   Create(nsISupports* aParent, BlobImpl* aImpl);
 
   static already_AddRefed<Blob>
@@ -142,16 +145,24 @@ protected:
   // between threads.
   // Note: we should not store any other state in this class!
   RefPtr<BlobImpl> mImpl;
 
 private:
   nsCOMPtr<nsISupports> mParent;
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(Blob, NS_DOM_BLOB_IID)
+
 // Override BindingJSObjectMallocBytes for blobs to tell the JS GC how much
 // memory is held live by the binding object.
 size_t BindingJSObjectMallocBytes(Blob* aBlob);
 
 } // namespace dom
 } // namespace mozilla
 
+inline nsISupports*
+ToSupports(mozilla::dom::Blob* aBlob)
+{
+  return static_cast<nsIMutable*>(aBlob);
+}
+
 #endif // mozilla_dom_Blob_h
--- a/dom/file/moz.build
+++ b/dom/file/moz.build
@@ -4,22 +4,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/.
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "DOM: File")
 
 DIRS += ['ipc']
 
-XPIDL_SOURCES += [
-    'nsIDOMBlob.idl',
-]
-
-XPIDL_MODULE = 'dom_file'
-
 EXPORTS += [
     'nsHostObjectProtocolHandler.h',
     'nsHostObjectURI.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'BaseBlobImpl.h',
     'Blob.h',
--- a/dom/file/nsHostObjectProtocolHandler.cpp
+++ b/dom/file/nsHostObjectProtocolHandler.cpp
@@ -414,68 +414,79 @@ class BlobURLsReporter final : public ns
     } else {
       path += url;
     }
   }
 };
 
 NS_IMPL_ISUPPORTS(BlobURLsReporter, nsIMemoryReporter)
 
-class ReleasingTimerHolder final : public nsITimerCallback
-                                 , public nsINamed
+class ReleasingTimerHolder final : public Runnable
+                                 , public nsITimerCallback
                                  , public nsIAsyncShutdownBlocker
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_ISUPPORTS_INHERITED
 
   static void
   Create(const nsACString& aURI, bool aBroadcastToOtherProcesses)
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     RefPtr<ReleasingTimerHolder> holder =
       new ReleasingTimerHolder(aURI, aBroadcastToOtherProcesses);
 
     auto raii = mozilla::MakeScopeExit([holder] {
       holder->CancelTimerAndRevokeURI();
     });
 
-    nsresult rv = NS_NewTimerWithCallback(getter_AddRefs(holder->mTimer),
-                                          holder, RELEASING_TIMER,
+    nsresult rv =
+      SystemGroup::EventTargetFor(TaskCategory::Other)->Dispatch(holder.forget());
+    NS_ENSURE_SUCCESS_VOID(rv);
+ 
+    raii.release();
+  }
+
+  // Runnable interface
+
+  NS_IMETHOD
+  Run() override
+  {
+    RefPtr<ReleasingTimerHolder> self = this;
+    auto raii = mozilla::MakeScopeExit([self] {
+      self->CancelTimerAndRevokeURI();
+    });
+
+    nsresult rv = NS_NewTimerWithCallback(getter_AddRefs(mTimer),
+                                          this, RELEASING_TIMER,
                                           nsITimer::TYPE_ONE_SHOT,
                                           SystemGroup::EventTargetFor(TaskCategory::Other));
-    NS_ENSURE_SUCCESS_VOID(rv);
+    NS_ENSURE_SUCCESS(rv, NS_OK);
 
     nsCOMPtr<nsIAsyncShutdownClient> phase = GetShutdownPhase();
-    NS_ENSURE_TRUE_VOID(!!phase);
+    NS_ENSURE_TRUE(!!phase, NS_OK);
 
-    rv = phase->AddBlocker(holder, NS_LITERAL_STRING(__FILE__), __LINE__,
+    rv = phase->AddBlocker(this, NS_LITERAL_STRING(__FILE__), __LINE__,
                            NS_LITERAL_STRING("ReleasingTimerHolder shutdown"));
-    NS_ENSURE_SUCCESS_VOID(rv);
+    NS_ENSURE_SUCCESS(rv, NS_OK);
 
     raii.release();
+    return NS_OK;
   }
 
   // nsITimerCallback interface
 
   NS_IMETHOD
   Notify(nsITimer* aTimer) override
   {
     RevokeURI(mBroadcastToOtherProcesses);
     return NS_OK;
   }
 
-  // nsINamed interface
-
-  NS_IMETHOD
-  GetName(nsACString& aName) override
-  {
-    aName.AssignLiteral("ReleasingTimerHolder");
-    return NS_OK;
-  }
+  using nsINamed::GetName;
 
   // nsIAsyncShutdownBlocker interface
 
   NS_IMETHOD
   GetName(nsAString& aName) override
   {
     aName.AssignLiteral("ReleasingTimerHolder for blobURL: ");
     aName.Append(NS_ConvertUTF8toUTF16(mURI));
@@ -492,17 +503,18 @@ public:
   NS_IMETHOD
   GetState(nsIPropertyBag**) override
   {
     return NS_OK;
   }
 
 private:
   ReleasingTimerHolder(const nsACString& aURI, bool aBroadcastToOtherProcesses)
-    : mURI(aURI)
+    : Runnable("ReleasingTimerHolder")
+    , mURI(aURI)
     , mBroadcastToOtherProcesses(aBroadcastToOtherProcesses)
   {}
 
   ~ReleasingTimerHolder()
   {}
 
   void
   RevokeURI(bool aBroadcastToOtherProcesses)
@@ -558,18 +570,18 @@ private:
   }
 
   nsCString mURI;
   bool mBroadcastToOtherProcesses;
 
   nsCOMPtr<nsITimer> mTimer;
 };
 
-NS_IMPL_ISUPPORTS(ReleasingTimerHolder, nsITimerCallback, nsINamed,
-                  nsIAsyncShutdownBlocker)
+NS_IMPL_ISUPPORTS_INHERITED(ReleasingTimerHolder, Runnable, nsITimerCallback,
+                            nsIAsyncShutdownBlocker)
 
 } // namespace mozilla
 
 template<typename T>
 static nsresult
 AddDataEntryInternal(const nsACString& aURI, T aObject,
                      nsIPrincipal* aPrincipal)
 {
deleted file mode 100644
--- a/dom/file/nsIDOMBlob.idl
+++ /dev/null
@@ -1,12 +0,0 @@
-/* -*- Mode: IDL; 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/. */
-
-#include "nsISupports.idl"
-
-[scriptable, builtinclass, uuid(f344146a-ee1f-417e-8a68-6984ca56f0ae)]
-interface nsIDOMBlob : nsISupports
-{
-  // Just an empty interface.
-};
--- a/dom/file/tests/test_ipc_messagemanager_blob.html
+++ b/dom/file/tests/test_ipc_messagemanager_blob.html
@@ -14,18 +14,20 @@
 
     SimpleTest.waitForExplicitFinish();
 
     const childFrameURL = "file_ipc_messagemanager_blob.html";
 
     function childFrameScript() {
       "use strict";
 
+      Cu.importGlobalProperties(["Blob"]);
+
       addMessageListener("test:ipcClonedMessage", function(message) {
-        if (!(message.json instanceof Ci.nsIDOMBlob)) {
+        if (!Blob.isInstance(message.json)) {
           sendAsyncMessage(message.name, message.json);
           return;
         }
 
         let reader = new FileReader();
         reader.addEventListener("load", function() {
           let response = reader.result == "this is a great success!" ?
                          message.json :
--- a/dom/filesystem/GetDirectoryListingTask.cpp
+++ b/dom/filesystem/GetDirectoryListingTask.cpp
@@ -303,17 +303,17 @@ GetDirectoryListingTaskParent::IOWork()
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (!isDir) {
     return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
   }
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   rv = mTargetPath->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   bool filterOutSensitive = false;
   {
     HTMLSplitOnSpacesTokenizer tokenizer(mFilters, ';');
@@ -324,28 +324,20 @@ GetDirectoryListingTaskParent::IOWork()
         filterOutSensitive = true;
       } else {
         MOZ_CRASH("Unrecognized filter");
       }
     }
   }
 
   for (;;) {
-    bool hasMore = false;
-    if (NS_WARN_IF(NS_FAILED(entries->HasMoreElements(&hasMore))) || !hasMore) {
+    nsCOMPtr<nsIFile> currFile;
+    if (NS_WARN_IF(NS_FAILED(entries->GetNextFile(getter_AddRefs(currFile)))) || !currFile) {
       break;
     }
-    nsCOMPtr<nsISupports> supp;
-    if (NS_WARN_IF(NS_FAILED(entries->GetNext(getter_AddRefs(supp))))) {
-      break;
-    }
-
-    nsCOMPtr<nsIFile> currFile = do_QueryInterface(supp);
-    MOZ_ASSERT(currFile);
-
     bool isSpecial, isFile;
     if (NS_WARN_IF(NS_FAILED(currFile->IsSpecial(&isSpecial))) ||
         isSpecial) {
       continue;
     }
     if (NS_WARN_IF(NS_FAILED(currFile->IsFile(&isFile)) ||
                    NS_FAILED(currFile->IsDirectory(&isDir))) ||
         !(isFile || isDir)) {
--- a/dom/filesystem/GetFilesHelper.cpp
+++ b/dom/filesystem/GetFilesHelper.cpp
@@ -333,36 +333,27 @@ GetFilesHelperBase::ExploreDirectory(con
     return NS_OK;
   }
 
   nsresult rv = AddExploredDirectory(aFile);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   rv = aFile->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   for (;;) {
-    bool hasMore = false;
-    if (NS_WARN_IF(NS_FAILED(entries->HasMoreElements(&hasMore))) || !hasMore) {
+    nsCOMPtr<nsIFile> currFile;
+    if (NS_WARN_IF(NS_FAILED(entries->GetNextFile(getter_AddRefs(currFile)))) || !currFile) {
       break;
     }
-
-    nsCOMPtr<nsISupports> supp;
-    if (NS_WARN_IF(NS_FAILED(entries->GetNext(getter_AddRefs(supp))))) {
-      break;
-    }
-
-    nsCOMPtr<nsIFile> currFile = do_QueryInterface(supp);
-    MOZ_ASSERT(currFile);
-
     bool isLink, isSpecial, isFile, isDir;
     if (NS_WARN_IF(NS_FAILED(currFile->IsSymlink(&isLink)) ||
                    NS_FAILED(currFile->IsSpecial(&isSpecial))) ||
         isSpecial) {
       continue;
     }
 
     if (NS_WARN_IF(NS_FAILED(currFile->IsFile(&isFile)) ||
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -665,26 +665,27 @@ HTMLCanvasElement::ParseAttribute(int32_
 }
 
 
 
 void
 HTMLCanvasElement::ToDataURL(JSContext* aCx, const nsAString& aType,
                              JS::Handle<JS::Value> aParams,
                              nsAString& aDataURL,
+                             nsIPrincipal& aSubjectPrincipal,
                              ErrorResult& aRv)
 {
   // do a trust check if this is a write-only canvas
   if (mWriteOnly &&
       !nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::all_urlsPermission)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
-  aRv = ToDataURLImpl(aCx, aType, aParams, aDataURL);
+  aRv = ToDataURLImpl(aCx, aSubjectPrincipal, aType, aParams, aDataURL);
 }
 
 void
 HTMLCanvasElement::SetMozPrintCallback(PrintCallback* aCallback)
 {
   mPrintCallback = aCallback;
 }
 
@@ -745,16 +746,17 @@ NS_IMPL_RELEASE_INHERITED(CanvasCaptureT
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CanvasCaptureTrackSource)
 NS_INTERFACE_MAP_END_INHERITING(MediaStreamTrackSource)
 NS_IMPL_CYCLE_COLLECTION_INHERITED(CanvasCaptureTrackSource,
                                    MediaStreamTrackSource,
                                    mCaptureStream)
 
 already_AddRefed<CanvasCaptureMediaStream>
 HTMLCanvasElement::CaptureStream(const Optional<double>& aFrameRate,
+                                 nsIPrincipal& aSubjectPrincipal,
                                  ErrorResult& aRv)
 {
   if (IsWriteOnly()) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return nullptr;
   }
 
   nsPIDOMWindowInner* window = OwnerDoc()->GetInnerWindow();
@@ -789,47 +791,51 @@ HTMLCanvasElement::CaptureStream(const O
                          new CanvasCaptureTrackSource(principal, stream));
   stream->AddTrackInternal(track);
 
   // Check site-specific permission and display prompt if appropriate.
   // If no permission, arrange for the frame capture listener to return
   // all-white, opaque image data.
   bool usePlaceholder = !CanvasUtils::IsImageExtractionAllowed(
     OwnerDoc(),
-    nsContentUtils::GetCurrentJSContext());
+    nsContentUtils::GetCurrentJSContext(),
+    aSubjectPrincipal);
 
   rv = RegisterFrameCaptureListener(stream->FrameCaptureListener(), usePlaceholder);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
   return stream.forget();
 }
 
 nsresult
 HTMLCanvasElement::ExtractData(JSContext* aCx,
+                               nsIPrincipal& aSubjectPrincipal,
                                nsAString& aType,
                                const nsAString& aOptions,
                                nsIInputStream** aStream)
 {
   // Check site-specific permission and display prompt if appropriate.
   // If no permission, return all-white, opaque image data.
-  bool usePlaceholder = !CanvasUtils::IsImageExtractionAllowed(OwnerDoc(), aCx);
+  bool usePlaceholder = !CanvasUtils::IsImageExtractionAllowed(
+    OwnerDoc(), aCx, aSubjectPrincipal);
   return ImageEncoder::ExtractData(aType,
                                    aOptions,
                                    GetSize(),
                                    usePlaceholder,
                                    mCurrentContext,
                                    mAsyncCanvasRenderer,
                                    aStream);
 }
 
 nsresult
 HTMLCanvasElement::ToDataURLImpl(JSContext* aCx,
+                                 nsIPrincipal& aSubjectPrincipal,
                                  const nsAString& aMimeType,
                                  const JS::Value& aEncoderOptions,
                                  nsAString& aDataURL)
 {
   nsIntSize size = GetWidthHeight();
   if (size.height == 0 || size.width == 0) {
     aDataURL = NS_LITERAL_STRING("data:,");
     return NS_OK;
@@ -842,22 +848,24 @@ HTMLCanvasElement::ToDataURLImpl(JSConte
   bool usingCustomParseOptions;
   nsresult rv =
     ParseParams(aCx, type, aEncoderOptions, params, &usingCustomParseOptions);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   nsCOMPtr<nsIInputStream> stream;
-  rv = ExtractData(aCx, type, params, getter_AddRefs(stream));
+  rv = ExtractData(aCx, aSubjectPrincipal, type, params,
+                   getter_AddRefs(stream));
 
   // If there are unrecognized custom parse options, we should fall back to
   // the default values for the encoder without any options at all.
   if (rv == NS_ERROR_INVALID_ARG && usingCustomParseOptions) {
-    rv = ExtractData(aCx, type, EmptyString(), getter_AddRefs(stream));
+    rv = ExtractData(aCx, aSubjectPrincipal, type, EmptyString(),
+                     getter_AddRefs(stream));
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // build data URL string
   aDataURL = NS_LITERAL_STRING("data:") + type + NS_LITERAL_STRING(";base64,");
 
   uint64_t count;
@@ -868,16 +876,17 @@ HTMLCanvasElement::ToDataURLImpl(JSConte
   return Base64EncodeInputStream(stream, aDataURL, (uint32_t)count, aDataURL.Length());
 }
 
 void
 HTMLCanvasElement::ToBlob(JSContext* aCx,
                           BlobCallback& aCallback,
                           const nsAString& aType,
                           JS::Handle<JS::Value> aParams,
+                          nsIPrincipal& aSubjectPrincipal,
                           ErrorResult& aRv)
 {
   // do a trust check if this is a write-only canvas
   if (mWriteOnly &&
       !nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::all_urlsPermission)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
@@ -899,17 +908,18 @@ HTMLCanvasElement::ToBlob(JSContext* aCx
           &BlobCallback::Call),
         nullptr,
         nullptr));
     return;
   }
 
   // Check site-specific permission and display prompt if appropriate.
   // If no permission, return all-white, opaque image data.
-  bool usePlaceholder = !CanvasUtils::IsImageExtractionAllowed(OwnerDoc(), aCx);
+  bool usePlaceholder = !CanvasUtils::IsImageExtractionAllowed(
+    OwnerDoc(), aCx, aSubjectPrincipal);
   CanvasRenderingContextHelper::ToBlob(aCx, global, aCallback, aType,
                                        aParams, usePlaceholder, aRv);
 
 }
 
 OffscreenCanvas*
 HTMLCanvasElement::TransferControlToOffscreen(ErrorResult& aRv)
 {
@@ -947,45 +957,47 @@ HTMLCanvasElement::TransferControlToOffs
   }
 
   return mOffscreenCanvas;
 }
 
 already_AddRefed<File>
 HTMLCanvasElement::MozGetAsFile(const nsAString& aName,
                                 const nsAString& aType,
-                                CallerType aCallerType,
+                                nsIPrincipal& aSubjectPrincipal,
                                 ErrorResult& aRv)
 {
   OwnerDoc()->WarnOnceAbout(nsIDocument::eMozGetAsFile);
 
   // do a trust check if this is a write-only canvas
-  if (mWriteOnly && aCallerType != CallerType::System) {
+  if (mWriteOnly && !nsContentUtils::IsSystemPrincipal(&aSubjectPrincipal)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return nullptr;
   }
 
 
   RefPtr<File> file;
-  aRv = MozGetAsFileImpl(aName, aType, getter_AddRefs(file));
+  aRv = MozGetAsFileImpl(aName, aType, aSubjectPrincipal, getter_AddRefs(file));
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
   return file.forget();
 }
 
 nsresult
 HTMLCanvasElement::MozGetAsFileImpl(const nsAString& aName,
                                     const nsAString& aType,
+                                    nsIPrincipal& aSubjectPrincipal,
                                     File** aResult)
 {
   nsCOMPtr<nsIInputStream> stream;
   nsAutoString type(aType);
   nsresult rv = ExtractData(nsContentUtils::GetCurrentJSContext(),
-                            type, EmptyString(), getter_AddRefs(stream));
+                            aSubjectPrincipal, type, EmptyString(),
+                            getter_AddRefs(stream));
   NS_ENSURE_SUCCESS(rv, rv);
 
   uint64_t imgSize;
   void* imgData = nullptr;
   rv = NS_ReadInputStreamToBuffer(stream, &imgData, -1, &imgSize);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(OwnerDoc()->GetScopeObject());
--- a/dom/html/HTMLCanvasElement.h
+++ b/dom/html/HTMLCanvasElement.h
@@ -173,22 +173,24 @@ public:
   virtual already_AddRefed<nsISupports>
   GetContext(JSContext* aCx, const nsAString& aContextId,
              JS::Handle<JS::Value> aContextOptions,
              ErrorResult& aRv) override;
 
   void ToDataURL(JSContext* aCx, const nsAString& aType,
                  JS::Handle<JS::Value> aParams,
                  nsAString& aDataURL,
+                 nsIPrincipal& aSubjectPrincipal,
                  ErrorResult& aRv);
 
   void ToBlob(JSContext* aCx,
               BlobCallback& aCallback,
               const nsAString& aType,
               JS::Handle<JS::Value> aParams,
+              nsIPrincipal& aSubjectPrincipal,
               ErrorResult& aRv);
 
   OffscreenCanvas* TransferControlToOffscreen(ErrorResult& aRv);
 
   bool MozOpaque() const
   {
     return GetBoolAttr(nsGkAtoms::moz_opaque);
   }
@@ -198,25 +200,25 @@ public:
       aRv.Throw(NS_ERROR_FAILURE);
       return;
     }
 
     SetHTMLBoolAttr(nsGkAtoms::moz_opaque, aValue, aRv);
   }
   already_AddRefed<File> MozGetAsFile(const nsAString& aName,
                                       const nsAString& aType,
-                                      CallerType aCallerType,
+                                      nsIPrincipal& aSubjectPrincipal,
                                       ErrorResult& aRv);
   already_AddRefed<nsISupports> MozGetIPCContext(const nsAString& aContextId,
                                                  ErrorResult& aRv);
   PrintCallback* GetMozPrintCallback() const;
   void SetMozPrintCallback(PrintCallback* aCallback);
 
   already_AddRefed<CanvasCaptureMediaStream>
-  CaptureStream(const Optional<double>& aFrameRate, ErrorResult& aRv);
+  CaptureStream(const Optional<double>& aFrameRate, nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
 
   /**
    * Get the size in pixels of this canvas element
    */
   nsIntSize GetSize();
 
   /**
    * Determine whether the canvas is write-only.
@@ -349,25 +351,28 @@ protected:
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   virtual nsIntSize GetWidthHeight() override;
 
   virtual already_AddRefed<nsICanvasRenderingContextInternal>
   CreateContext(CanvasContextType aContextType) override;
 
   nsresult ExtractData(JSContext* aCx,
+                       nsIPrincipal& aSubjectPrincipal,
                        nsAString& aType,
                        const nsAString& aOptions,
                        nsIInputStream** aStream);
   nsresult ToDataURLImpl(JSContext* aCx,
+                         nsIPrincipal& aSubjectPrincipal,
                          const nsAString& aMimeType,
                          const JS::Value& aEncoderOptions,
                          nsAString& aDataURL);
   nsresult MozGetAsFileImpl(const nsAString& aName,
                             const nsAString& aType,
+                            nsIPrincipal& aSubjectPrincipal,
                             File** aResult);
   void CallPrintCallback();
 
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -13,16 +13,17 @@
 #include "mozilla/dom/Directory.h"
 #include "mozilla/dom/DOMPrefs.h"
 #include "mozilla/dom/HTMLFormSubmission.h"
 #include "mozilla/dom/FileSystemUtils.h"
 #include "mozilla/dom/GetFilesHelper.h"
 #include "mozilla/dom/WheelEventBinding.h"
 #include "nsAttrValueInlines.h"
 #include "nsCRTGlue.h"
+#include "nsQueryObject.h"
 
 #include "nsITextControlElement.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIRadioVisitor.h"
 #include "InputType.h"
 
 #include "HTMLFormSubmissionConstants.h"
 #include "mozilla/Telemetry.h"
@@ -503,36 +504,36 @@ HTMLInputElement::nsFilePickerShownCallb
       return NS_OK;
     }
 
     nsCOMPtr<nsISupports> tmp;
     bool hasMore = true;
 
     while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
       iter->GetNext(getter_AddRefs(tmp));
-      nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(tmp);
+      RefPtr<Blob> domBlob = do_QueryObject(tmp);
       MOZ_ASSERT(domBlob,
                  "Null file object from FilePicker's file enumerator?");
       if (!domBlob) {
         continue;
       }
 
       OwningFileOrDirectory* element = newFilesOrDirectories.AppendElement();
-      element->SetAsFile() = static_cast<File*>(domBlob.get());
+      element->SetAsFile() = domBlob->ToFile();
     }
   } else {
     MOZ_ASSERT(mode == static_cast<int16_t>(nsIFilePicker::modeOpen) ||
                mode == static_cast<int16_t>(nsIFilePicker::modeGetFolder));
     nsCOMPtr<nsISupports> tmp;
     nsresult rv = mFilePicker->GetDomFileOrDirectory(getter_AddRefs(tmp));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(tmp);
+    RefPtr<Blob> blob = do_QueryObject(tmp);
     if (blob) {
-      RefPtr<File> file = static_cast<Blob*>(blob.get())->ToFile();
+      RefPtr<File> file = blob->ToFile();
       MOZ_ASSERT(file);
 
       OwningFileOrDirectory* element = newFilesOrDirectories.AppendElement();
       element->SetAsFile() = file;
     } else if (tmp) {
       RefPtr<Directory> directory = static_cast<Directory*>(tmp.get());
       OwningFileOrDirectory* element = newFilesOrDirectories.AppendElement();
       element->SetAsDirectory() = directory;
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -17399,35 +17399,26 @@ FileManager::GetUsage(nsIFile* aDirector
     return rv;
   }
 
   if (!exists) {
     *aUsage = 0;
     return NS_OK;
   }
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   uint64_t usage = 0;
 
-  bool hasMore;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
-    MOZ_ASSERT(file);
-
+  nsCOMPtr<nsIFile> file;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) && file) {
     nsString leafName;
     rv = file->GetLeafName(leafName);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     if (leafName.EqualsLiteral(JOURNAL_DIRECTORY_NAME)) {
       continue;
@@ -17979,45 +17970,36 @@ QuotaClient::GetDatabaseFilenames(
                               const AtomicBool& aCanceled,
                               bool aForUpgrade,
                               nsTArray<nsString>& aSubdirsToProcess,
                               nsTHashtable<nsStringHashKey>& aDatabaseFilenames)
 {
   AssertIsOnIOThread();
   MOZ_ASSERT(aDirectory);
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   const NS_ConvertASCIItoUTF16 sqliteSuffix(kSQLiteSuffix,
                                             LiteralStringLength(kSQLiteSuffix));
   const NS_ConvertASCIItoUTF16 journalSuffix(
     kSQLiteJournalSuffix,
     LiteralStringLength(kSQLiteJournalSuffix));
   const NS_ConvertASCIItoUTF16 shmSuffix(kSQLiteSHMSuffix,
                                          LiteralStringLength(kSQLiteSHMSuffix));
   const NS_ConvertASCIItoUTF16 walSuffix(kSQLiteWALSuffix,
                                          LiteralStringLength(kSQLiteWALSuffix));
 
-  bool hasMore;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
-         hasMore &&
+  nsCOMPtr<nsIFile> file;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) &&
+         file &&
          !aCanceled) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
-    MOZ_ASSERT(file);
-
     nsString leafName;
     rv = file->GetLeafName(leafName);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     bool isDirectory;
     rv = file->IsDirectory(&isDirectory);
@@ -18082,45 +18064,36 @@ QuotaClient::GetUsageForDirectoryInterna
                                           const AtomicBool& aCanceled,
                                           UsageInfo* aUsageInfo,
                                           bool aDatabaseFiles)
 {
   AssertIsOnIOThread();
   MOZ_ASSERT(aDirectory);
   MOZ_ASSERT(aUsageInfo);
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (!entries) {
     return NS_OK;
   }
 
   const NS_ConvertASCIItoUTF16 journalSuffix(
     kSQLiteJournalSuffix,
     LiteralStringLength(kSQLiteJournalSuffix));
   const NS_ConvertASCIItoUTF16 shmSuffix(kSQLiteSHMSuffix,
                                          LiteralStringLength(kSQLiteSHMSuffix));
 
-  bool hasMore;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
-         hasMore &&
+  nsCOMPtr<nsIFile> file;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) &&
+         file &&
          !aCanceled) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
-    MOZ_ASSERT(file);
-
     nsString leafName;
     rv = file->GetLeafName(leafName);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     // Journal files and sqlite-shm files don't count towards usage.
     if (StringEndsWith(leafName, journalSuffix) ||
@@ -18433,53 +18406,43 @@ Maintenance::DirectoryWork()
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     if (NS_WARN_IF(!isDirectory)) {
       continue;
     }
 
-    nsCOMPtr<nsISimpleEnumerator> persistenceDirEntries;
+    nsCOMPtr<nsIDirectoryEnumerator> persistenceDirEntries;
     rv = persistenceDir->GetDirectoryEntries(
                                          getter_AddRefs(persistenceDirEntries));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     if (!persistenceDirEntries) {
       continue;
     }
 
     while (true) {
       // Loop over "<origin>/idb" directories.
       if (IsAborted()) {
         return NS_ERROR_ABORT;
       }
 
-      bool persistenceDirHasMoreEntries;
-      rv = persistenceDirEntries->HasMoreElements(
-                                                 &persistenceDirHasMoreEntries);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
-      }
-
-      if (!persistenceDirHasMoreEntries) {
+      nsCOMPtr<nsIFile> originDir;
+      rv = persistenceDirEntries->GetNextFile(getter_AddRefs(originDir));
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+
+      if (!originDir) {
         break;
       }
 
-      nsCOMPtr<nsISupports> persistenceDirEntry;
-      rv = persistenceDirEntries->GetNext(getter_AddRefs(persistenceDirEntry));
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
-      }
-
-      nsCOMPtr<nsIFile> originDir = do_QueryInterface(persistenceDirEntry);
-      MOZ_ASSERT(originDir);
-
       rv = originDir->Exists(&exists);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       MOZ_ASSERT(exists);
 
       rv = originDir->IsDirectory(&isDirectory);
@@ -18515,17 +18478,17 @@ Maintenance::DirectoryWork()
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       if (NS_WARN_IF(!isDirectory)) {
         continue;
       }
 
-      nsCOMPtr<nsISimpleEnumerator> idbDirEntries;
+      nsCOMPtr<nsIDirectoryEnumerator> idbDirEntries;
       rv = idbDir->GetDirectoryEntries(getter_AddRefs(idbDirEntries));
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       if (!idbDirEntries) {
         continue;
       }
@@ -18536,35 +18499,26 @@ Maintenance::DirectoryWork()
       nsTArray<nsString> databasePaths;
 
       while (true) {
         // Loop over files in the "idb" directory.
         if (IsAborted()) {
           return NS_ERROR_ABORT;
         }
 
-        bool idbDirHasMoreEntries;
-        rv = idbDirEntries->HasMoreElements(&idbDirHasMoreEntries);
+        nsCOMPtr<nsIFile> idbDirFile;
+        rv = idbDirEntries->GetNextFile(getter_AddRefs(idbDirFile));
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
 
-        if (!idbDirHasMoreEntries) {
+        if (!idbDirFile) {
           break;
         }
 
-        nsCOMPtr<nsISupports> idbDirEntry;
-        rv = idbDirEntries->GetNext(getter_AddRefs(idbDirEntry));
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return rv;
-        }
-
-        nsCOMPtr<nsIFile> idbDirFile = do_QueryInterface(idbDirEntry);
-        MOZ_ASSERT(idbDirFile);
-
         nsString idbFilePath;
         rv = idbDirFile->GetPath(idbFilePath);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
 
         if (!StringEndsWith(idbFilePath, sqliteExtension)) {
           continue;
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -910,18 +910,17 @@ IDBDatabase::GetOrCreateFileActorForBlob
   AssertIsOnOwningThread();
   MOZ_ASSERT(aBlob);
   MOZ_ASSERT(mBackgroundActor);
 
   // We use the File's nsIWeakReference as the key to the table because
   // a) it is unique per blob, b) it is reference-counted so that we can
   // guarantee that it stays alive, and c) it doesn't hold the actual File
   // alive.
-  nsCOMPtr<nsIDOMBlob> blob = aBlob;
-  nsCOMPtr<nsIWeakReference> weakRef = do_GetWeakReference(blob);
+  nsCOMPtr<nsIWeakReference> weakRef = do_GetWeakReference(aBlob);
   MOZ_ASSERT(weakRef);
 
   PBackgroundIDBDatabaseFileChild* actor = nullptr;
 
   if (!mFileActors.Get(weakRef, &actor)) {
     BlobImpl* blobImpl = aBlob->Impl();
     MOZ_ASSERT(blobImpl);
 
--- a/dom/indexedDB/test/file.js
+++ b/dom/indexedDB/test/file.js
@@ -105,18 +105,18 @@ function getWasmModule(binary)
 function verifyBuffers(buffer1, buffer2)
 {
   ok(compareBuffers(buffer1, buffer2), "Correct buffer data");
 }
 
 function verifyBlob(blob1, blob2, fileId, blobReadHandler)
 {
   // eslint-disable-next-line mozilla/use-cc-etc
-  is(blob1 instanceof Components.interfaces.nsIDOMBlob, true,
-     "Instance of nsIDOMBlob");
+  is(SpecialPowers.wrap(Blob).isInstance(blob1), true,
+     "Instance of Blob");
   is(blob1 instanceof File, blob2 instanceof File,
      "Instance of DOM File");
   is(blob1.size, blob2.size, "Correct size");
   is(blob1.type, blob2.type, "Correct type");
   if (blob2 instanceof File) {
     is(blob1.name, blob2.name, "Correct name");
   }
   is(utils.getFileId(blob1), fileId, "Correct file id");
--- a/dom/indexedDB/test/test_message_manager_ipc.html
+++ b/dom/indexedDB/test/test_message_manager_ipc.html
@@ -20,17 +20,17 @@ function childFrameScript() {
   const dbVersion = 1;
   const objStoreName = "bar";
   const key = 1;
 
   const blobData = ["So", " ", "many", " ", "blobs!"];
   const blobText = blobData.join("");
   const blobType = "text/plain";
 
-  Cu.importGlobalProperties(["indexedDB"]);
+  Cu.importGlobalProperties(["indexedDB", "Blob"]);
 
   function info(msg) {
     sendAsyncMessage(mmName, { op: "info", msg });
   }
 
   function ok(condition, name, diag) {
     sendAsyncMessage(mmName,
                      { op: "ok",
@@ -61,33 +61,33 @@ function childFrameScript() {
   }
 
   function* testSteps() {
     addMessageListener(mmName, grabAndContinue);
     let message = yield undefined;
 
     let blob = message.data;
 
-    ok(blob instanceof Ci.nsIDOMBlob, "Message manager sent a blob");
+    ok(Blob.isInstance(blob), "Message manager sent a blob");
     is(blob.size, blobText.length, "Blob has correct length");
     is(blob.type, blobType, "Blob has correct type");
 
     info("Reading blob");
 
     let reader = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(blob);
 
     yield undefined;
 
     is(reader.result, blobText, "Blob has correct data");
 
     let slice = blob.slice(0, blobData[0].length, blobType);
 
-    ok(slice instanceof Ci.nsIDOMBlob, "Slice returned a blob");
+    ok(Blob.isInstance(slice), "Slice returned a blob");
     is(slice.size, blobData[0].length, "Slice has correct length");
     is(slice.type, blobType, "Slice has correct type");
 
     info("Reading slice");
 
     reader = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(slice);
@@ -138,17 +138,17 @@ function childFrameScript() {
     req = objectStore.get(key);
     req.onerror = errorHandler;
     req.onsuccess = grabAndContinue;
 
     event = yield undefined;
 
     blob = event.target.result;
 
-    ok(blob instanceof Ci.nsIDOMBlob, "Database gave us a blob");
+    ok(Blob.isInstance(blob), "Database gave us a blob");
     is(blob.size, blobText.length, "Blob has correct length");
     is(blob.type, blobType, "Blob has correct type");
 
     info("Reading blob");
 
     reader = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(blob);
@@ -173,17 +173,17 @@ function childFrameScript() {
     req = objectStore.get(key);
     req.onerror = errorHandler;
     req.onsuccess = grabAndContinue;
 
     event = yield undefined;
 
     slice = event.target.result;
 
-    ok(slice instanceof Ci.nsIDOMBlob, "Database gave us a blob");
+    ok(Blob.isInstance(slice), "Database gave us a blob");
     is(slice.size, blobData[0].length, "Slice has correct length");
     is(slice.type, blobType, "Slice has correct type");
 
     info("Reading Slice");
 
     reader = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(slice);
--- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
+++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
@@ -5,16 +5,18 @@
 
 // Tests using testGenerator are expected to define it themselves.
 /* global testGenerator */
 
 var { "classes": Cc, "interfaces": Ci, "utils": Cu } = Components;
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
+Cu.importGlobalProperties(["Blob"]);
+
 if (!("self" in this)) {
   this.self = this;
 }
 
 var bufferCache = [];
 
 function is(a, b, msg) {
   Assert.equal(a, b, msg);
@@ -335,18 +337,17 @@ function getChromeFilesDir()
   let idbDir = profileDir.clone();
   idbDir.append("storage");
   idbDir.append("permanent");
   idbDir.append("chrome");
   idbDir.append("idb");
 
   let idbEntries = idbDir.directoryEntries;
   while (idbEntries.hasMoreElements()) {
-    let entry = idbEntries.getNext();
-    let file = entry.QueryInterface(Ci.nsIFile);
+    let file = idbEntries.nextFile;
     if (file.isDirectory()) {
       return file;
     }
   }
 
   throw new Error("files directory doesn't exist!");
 }
 
@@ -422,17 +423,17 @@ function compareBuffers(buffer1, buffer2
 
 function verifyBuffers(buffer1, buffer2)
 {
   ok(compareBuffers(buffer1, buffer2), "Correct buffer data");
 }
 
 function verifyBlob(blob1, blob2)
 {
-  is(blob1 instanceof Ci.nsIDOMBlob, true,
+  is(Blob.isInstance(blob1), true,
      "Instance of nsIDOMBlob");
   is(blob1 instanceof File, blob2 instanceof File,
      "Instance of DOM File");
   is(blob1.size, blob2.size, "Correct size");
   is(blob1.type, blob2.type, "Correct type");
   if (blob2 instanceof File) {
     is(blob1.name, blob2.name, "Correct name");
   }
--- a/dom/interfaces/base/nsIDOMWindow.idl
+++ b/dom/interfaces/base/nsIDOMWindow.idl
@@ -1,17 +1,16 @@
 /* -*- Mode: IDL; 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/. */
 
 #include "domstubs.idl"
 
 interface nsIControllers;
-interface nsIDOMBlob;
 interface nsIDOMOfflineResourceList;
 interface nsIPrompt;
 interface nsIVariant;
 
 /**
  * Empty interface for compatibility with older versions.
  * @deprecated Use WebIDL for script visible features,
  *             nsPIDOMWindow for C++ callers.
--- a/dom/ipc/tests/test_blob_sliced_from_parent_process.html
+++ b/dom/ipc/tests/test_blob_sliced_from_parent_process.html
@@ -47,17 +47,17 @@ function childFrameScript() {
   }
 
   function* testSteps() {
     addMessageListener(messageName, grabAndContinue);
     let message = yield undefined;
 
     let blob = message.data;
 
-    ok(blob instanceof Ci.nsIDOMBlob, "Received a Blob");
+    ok(Blob.isInstance(blob), "Received a Blob");
     is(blob.size, blobText.length, "Blob has correct length");
     is(blob.type, blobType, "Blob has correct type");
 
     info("Reading blob");
 
     let reader = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(blob);
@@ -66,17 +66,17 @@ function childFrameScript() {
 
     is(reader.result, blobText, "Blob has correct data");
 
     let firstSliceStart = blobData[0].length + blobData[1].length;
     let firstSliceEnd = firstSliceStart + blobData[2].length;
 
     let slice = blob.slice(firstSliceStart, firstSliceEnd, blobType);
 
-    ok(slice instanceof Ci.nsIDOMBlob, "Slice returned a Blob");
+    ok(Blob.isInstance(slice), "Slice returned a Blob");
     is(slice.size, blobData[2].length, "Slice has correct length");
     is(slice.type, blobType, "Slice has correct type");
 
     info("Reading slice");
 
     reader = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(slice);
@@ -85,17 +85,17 @@ function childFrameScript() {
 
     is(reader.result, blobData[2], "Slice has correct data");
 
     let secondSliceStart = blobData[2].indexOf("a");
     let secondSliceEnd = secondSliceStart + sliceText.length;
 
     slice = slice.slice(secondSliceStart, secondSliceEnd, blobType);
 
-    ok(slice instanceof Ci.nsIDOMBlob, "Second slice returned a Blob");
+    ok(Blob.isInstance(slice), "Second slice returned a Blob");
     is(slice.size, sliceText.length, "Second slice has correct length");
     is(slice.type, blobType, "Second slice has correct type");
 
     info("Sending second slice");
     finish(slice);
   }
 
   let testGenerator = testSteps();
--- a/dom/media/gtest/TestCDMStorage.cpp
+++ b/dom/media/gtest/TestCDMStorage.cpp
@@ -39,35 +39,24 @@ GetAbstractGMPThread()
 }
 /**
  * Enumerate files under |aPath| (non-recursive).
  */
 template<typename T>
 static nsresult
 EnumerateDir(nsIFile* aPath, T&& aDirIter)
 {
-  nsCOMPtr<nsISimpleEnumerator> iter;
+  nsCOMPtr<nsIDirectoryEnumerator> iter;
   nsresult rv = aPath->GetDirectoryEntries(getter_AddRefs(iter));
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  bool hasMore = false;
-  while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
-    nsCOMPtr<nsISupports> supports;
-    rv = iter->GetNext(getter_AddRefs(supports));
-    if (NS_FAILED(rv)) {
-      continue;
-    }
-
-    nsCOMPtr<nsIFile> entry(do_QueryInterface(supports, &rv));
-    if (NS_FAILED(rv)) {
-      continue;
-    }
-
+  nsCOMPtr<nsIFile> entry;
+  while (NS_SUCCEEDED(iter->GetNextFile(getter_AddRefs(entry))) && entry) {
     aDirIter(entry);
   }
   return NS_OK;
 }
 
 /**
  * Enumerate files under $profileDir/gmp/$platform/gmp-fake/$aDir/ (non-recursive).
  */
--- a/dom/media/nsIDOMNavigatorUserMedia.idl
+++ b/dom/media/nsIDOMNavigatorUserMedia.idl
@@ -21,17 +21,17 @@ interface nsIGetUserMediaDevicesSuccessC
 {
   void onSuccess(in nsIVariant devices);
 };
 
 [scriptable, function, uuid(f2a144fc-3534-4761-8c5d-989ae720f89a)]
 interface nsIDOMGetUserMediaSuccessCallback : nsISupports
 {
   /*
-   * value must be a nsIDOMBlob if picture is true and a
+   * value must be a Blob if picture is true and a
    * DOMLocalMediaStream if either audio or video are true.
    */
   void onSuccess(in nsISupports value);
 };
 
 [scriptable, function, uuid(39e96c61-2636-4f0e-918e-9bb64276492a)]
 interface nsIDOMGetUserMediaErrorCallback : nsISupports
 {
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -2089,33 +2089,25 @@ nsresult nsPluginHost::ScanPluginsDirect
   nsAutoCString dirPath;
   pluginsDir->GetNativePath(dirPath);
   PLUGIN_LOG(PLUGIN_LOG_BASIC,
   ("nsPluginHost::ScanPluginsDirectory dir=%s\n", dirPath.get()));
 #endif
 
   bool flashOnly = Preferences::GetBool("plugin.load_flash_only", true);
 
-  nsCOMPtr<nsISimpleEnumerator> iter;
+  nsCOMPtr<nsIDirectoryEnumerator> iter;
   rv = pluginsDir->GetDirectoryEntries(getter_AddRefs(iter));
   if (NS_FAILED(rv))
     return rv;
 
   AutoTArray<nsCOMPtr<nsIFile>, 6> pluginFiles;
 
-  bool hasMore;
-  while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
-    nsCOMPtr<nsISupports> supports;
-    rv = iter->GetNext(getter_AddRefs(supports));
-    if (NS_FAILED(rv))
-      continue;
-    nsCOMPtr<nsIFile> dirEntry(do_QueryInterface(supports, &rv));
-    if (NS_FAILED(rv))
-      continue;
-
+  nsCOMPtr<nsIFile> dirEntry;
+  while (NS_SUCCEEDED(iter->GetNextFile(getter_AddRefs(dirEntry))) && dirEntry) {
     // Sun's JRE 1.3.1 plugin must have symbolic links resolved or else it'll crash.
     // See bug 197855.
     dirEntry->Normalize();
 
     if (nsPluginsDir::IsPluginFile(dirEntry)) {
       pluginFiles.AppendElement(dirEntry);
     }
   }
--- a/dom/presentation/PresentationService.cpp
+++ b/dom/presentation/PresentationService.cpp
@@ -803,17 +803,17 @@ PresentationService::SendSessionBinaryMs
   }
 
   return info->SendBinaryMsg(aData);
 }
 
 NS_IMETHODIMP
 PresentationService::SendSessionBlob(const nsAString& aSessionId,
                                      uint8_t aRole,
-                                     nsIDOMBlob* aBlob)
+                                     Blob* aBlob)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!aSessionId.IsEmpty());
   MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
              aRole == nsIPresentationService::ROLE_RECEIVER);
   MOZ_ASSERT(aBlob);
 
   RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole);
--- a/dom/presentation/PresentationSessionInfo.cpp
+++ b/dom/presentation/PresentationSessionInfo.cpp
@@ -286,17 +286,17 @@ PresentationSessionInfo::SendBinaryMsg(c
   if (NS_WARN_IF(!mTransport)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   return mTransport->SendBinaryMsg(aData);
 }
 
 nsresult
-PresentationSessionInfo::SendBlob(nsIDOMBlob* aBlob)
+PresentationSessionInfo::SendBlob(Blob* aBlob)
 {
   if (NS_WARN_IF(!IsSessionReady())) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   if (NS_WARN_IF(!mTransport)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
--- a/dom/presentation/PresentationSessionInfo.h
+++ b/dom/presentation/PresentationSessionInfo.h
@@ -97,17 +97,17 @@ public:
       mControlChannel->SetListener(this);
     }
   }
 
   nsresult Send(const nsAString& aData);
 
   nsresult SendBinaryMsg(const nsACString& aData);
 
-  nsresult SendBlob(nsIDOMBlob* aBlob);
+  nsresult SendBlob(Blob* aBlob);
 
   nsresult Close(nsresult aReason,
                  uint32_t aState);
 
   nsresult OnTerminate(nsIPresentationControlChannel* aControlChannel);
 
   nsresult ReplyError(nsresult aReason);
 
--- a/dom/presentation/PresentationTCPSessionTransport.cpp
+++ b/dom/presentation/PresentationTCPSessionTransport.cpp
@@ -419,17 +419,17 @@ PresentationTCPSessionTransport::Send(co
 
 NS_IMETHODIMP
 PresentationTCPSessionTransport::SendBinaryMsg(const nsACString& aData)
 {
   return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
 }
 
 NS_IMETHODIMP
-PresentationTCPSessionTransport::SendBlob(nsIDOMBlob* aBlob)
+PresentationTCPSessionTransport::SendBlob(Blob* aBlob)
 {
   return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
 }
 
 NS_IMETHODIMP
 PresentationTCPSessionTransport::Close(nsresult aReason)
 {
   PRES_DEBUG("%s:reason[%" PRIx32 "]\n", __func__, static_cast<uint32_t>(aReason));
--- a/dom/presentation/interfaces/nsIPresentationService.idl
+++ b/dom/presentation/interfaces/nsIPresentationService.idl
@@ -1,22 +1,22 @@
 /* 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 "nsISupports.idl"
 
-interface nsIDOMBlob;
 interface nsIInputStream;
 interface nsIPresentationAvailabilityListener;
 interface nsIPresentationRespondingListener;
 interface nsIPresentationSessionListener;
 interface nsIPresentationTransportBuilderConstructor;
 interface nsIPrincipal;
 
+webidl Blob;
 webidl EventTarget;
 
 %{C++
 #define PRESENTATION_SERVICE_CID \
   { 0x1d9bb10c, 0xc0ab, 0x4fe8, \
     { 0x9e, 0x4f, 0x40, 0x58, 0xb8, 0x51, 0x98, 0x32 } }
 #define PRESENTATION_SERVICE_CONTRACTID \
   "@mozilla.org/presentation/presentationservice;1"
@@ -115,17 +115,17 @@ interface nsIPresentationService : nsISu
    * Send the blob to the session.
    *
    * @param sessionId: An ID to identify presentation session.
    * @param role: Identify the function called by controller or receiver.
    * @param blob: The input blob to be sent.
    */
   void sendSessionBlob(in DOMString sessionId,
                        in uint8_t role,
-                       in nsIDOMBlob blob);
+                       in Blob blob);
 
   /*
    * Close the session.
    *
    * @param sessionId: An ID to identify presentation session.
    * @param role: Identify the function called by controller or receiver.
    */
   void closeSession(in DOMString sessionId,
--- a/dom/presentation/interfaces/nsIPresentationSessionTransport.idl
+++ b/dom/presentation/interfaces/nsIPresentationSessionTransport.idl
@@ -1,18 +1,19 @@
 /* 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 "nsISupports.idl"
 
-interface nsIDOMBlob;
 interface nsIInputStream;
 interface nsINetAddr;
 
+webidl Blob;
+
 %{C++
 #define PRESENTATION_TCP_SESSION_TRANSPORT_CONTRACTID \
   "@mozilla.org/presentation/presentationtcpsessiontransport;1"
 %}
 
 /*
  * The callback for session transport events.
  */
@@ -54,16 +55,16 @@ interface nsIPresentationSessionTranspor
    * @param data: the message being sent out.
    */
   void sendBinaryMsg(in ACString data);
 
   /*
    * Send the blob to the remote endpoint.
    * @param blob: The input blob to be sent.
    */
-  void sendBlob(in nsIDOMBlob blob);
+  void sendBlob(in Blob blob);
 
   /*
    * Close this session transport.
    * @param reason The reason for closing this session transport.
    */
   void close(in nsresult reason);
 };
--- a/dom/presentation/ipc/PresentationBuilderParent.cpp
+++ b/dom/presentation/ipc/PresentationBuilderParent.cpp
@@ -79,17 +79,17 @@ PresentationSessionTransportIPC::Send(co
 
 NS_IMETHODIMP
 PresentationSessionTransportIPC::SendBinaryMsg(const nsACString& aData)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PresentationSessionTransportIPC::SendBlob(nsIDOMBlob* aBlob)
+PresentationSessionTransportIPC::SendBlob(Blob* aBlob)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PresentationSessionTransportIPC::Close(nsresult aReason)
 {
   if (NS_WARN_IF(!mParent->SendNotifyCloseSessionTransport(mSessionId,
--- a/dom/presentation/ipc/PresentationContentSessionInfo.cpp
+++ b/dom/presentation/ipc/PresentationContentSessionInfo.cpp
@@ -41,17 +41,17 @@ PresentationContentSessionInfo::SendBina
   if (NS_WARN_IF(!mTransport)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   return mTransport->SendBinaryMsg(aData);
 }
 
 nsresult
-PresentationContentSessionInfo::SendBlob(nsIDOMBlob* aBlob)
+PresentationContentSessionInfo::SendBlob(Blob* aBlob)
 {
   if (NS_WARN_IF(!mTransport)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   return mTransport->SendBlob(aBlob);
 }
 
--- a/dom/presentation/ipc/PresentationContentSessionInfo.h
+++ b/dom/presentation/ipc/PresentationContentSessionInfo.h
@@ -39,17 +39,17 @@ public:
   }
 
   nsresult Init();
 
   nsresult Send(const nsAString& aData);
 
   nsresult SendBinaryMsg(const nsACString& aData);
 
-  nsresult SendBlob(nsIDOMBlob* aBlob);
+  nsresult SendBlob(Blob* aBlob);
 
   nsresult Close(nsresult aReason);
 
 private:
   virtual ~PresentationContentSessionInfo() {}
 
   nsString mSessionId;
   uint8_t mRole;
--- a/dom/presentation/ipc/PresentationIPCService.cpp
+++ b/dom/presentation/ipc/PresentationIPCService.cpp
@@ -124,17 +124,17 @@ PresentationIPCService::SendSessionBinar
   }
 
   return NS_ERROR_NOT_AVAILABLE;
 }
 
 NS_IMETHODIMP
 PresentationIPCService::SendSessionBlob(const nsAString& aSessionId,
                                         uint8_t aRole,
-                                        nsIDOMBlob* aBlob)
+                                        Blob* aBlob)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!aSessionId.IsEmpty());
   MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
              aRole == nsIPresentationService::ROLE_RECEIVER);
   MOZ_ASSERT(aBlob);
 
   RefPtr<PresentationContentSessionInfo> info =
--- a/dom/quota/ActorsParent.cpp
+++ b/dom/quota/ActorsParent.cpp
@@ -1966,33 +1966,24 @@ GetLastModifiedTime(nsIFile* aFile, bool
         timestamp *= int64_t(PR_USEC_PER_MSEC);
 
         if (timestamp > *aTimestamp) {
           *aTimestamp = timestamp;
         }
         return NS_OK;
       }
 
-      nsCOMPtr<nsISimpleEnumerator> entries;
+      nsCOMPtr<nsIDirectoryEnumerator> entries;
       rv = aFile->GetDirectoryEntries(getter_AddRefs(entries));
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
-      bool hasMore;
-      while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
-        nsCOMPtr<nsISupports> entry;
-        rv = entries->GetNext(getter_AddRefs(entry));
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return rv;
-        }
-
-        nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
-        MOZ_ASSERT(file);
-
+      nsCOMPtr<nsIFile> file;
+      while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) && file) {
         rv = GetLastModifiedTime(file, aTimestamp);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
@@ -4223,33 +4214,24 @@ QuotaManager::InitializeRepository(Persi
   }
 
   bool created;
   rv = EnsureDirectory(directory, &created);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  bool hasMore;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    nsCOMPtr<nsIFile> childDirectory = do_QueryInterface(entry);
-    MOZ_ASSERT(childDirectory);
-
+  nsCOMPtr<nsIFile> childDirectory;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(childDirectory)))) && childDirectory) {
     bool isDirectory;
     rv = childDirectory->IsDirectory(&isDirectory);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     if (!isDirectory) {
       nsString leafName;
@@ -4311,29 +4293,22 @@ QuotaManager::InitializeOrigin(Persisten
 
   // We need to initialize directories of all clients if they exists and also
   // get the total usage to initialize the quota.
   nsAutoPtr<UsageInfo> usageInfo;
   if (trackQuota) {
     usageInfo = new UsageInfo();
   }
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  bool hasMore;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
-    NS_ENSURE_TRUE(file, NS_NOINTERFACE);
-
+  nsCOMPtr<nsIFile> file;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) && file) {
     bool isDirectory;
     rv = file->IsDirectory(&isDirectory);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     nsString leafName;
     rv = file->GetLeafName(leafName);
@@ -6733,30 +6708,23 @@ QuotaUsageRequestBase::GetUsageForOrigin
     bool initialized;
 
     if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
       initialized = aQuotaManager->IsOriginInitialized(aOrigin);
     } else {
       initialized = aQuotaManager->IsTemporaryStorageInitialized();
     }
 
-    nsCOMPtr<nsISimpleEnumerator> entries;
+    nsCOMPtr<nsIDirectoryEnumerator> entries;
     rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    bool hasMore;
-    while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
-           hasMore && !mCanceled) {
-      nsCOMPtr<nsISupports> entry;
-      rv = entries->GetNext(getter_AddRefs(entry));
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
-      NS_ENSURE_TRUE(file, NS_NOINTERFACE);
-
+    nsCOMPtr<nsIFile> file;
+    while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) &&
+           file && !mCanceled) {
       bool isDirectory;
       rv = file->IsDirectory(&isDirectory);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       nsString leafName;
       rv = file->GetLeafName(leafName);
@@ -6899,36 +6867,27 @@ GetUsageOp::TraverseRepository(QuotaMana
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (!exists) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   bool persistent = aPersistenceType == PERSISTENCE_TYPE_PERSISTENT;
 
-  bool hasMore;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
-         hasMore && !mCanceled) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    nsCOMPtr<nsIFile> originDir = do_QueryInterface(entry);
-    MOZ_ASSERT(originDir);
-
+  nsCOMPtr<nsIFile> originDir;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(originDir)))) &&
+         originDir && !mCanceled) {
     bool isDirectory;
     rv = originDir->IsDirectory(&isDirectory);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     if (!isDirectory) {
       nsString leafName;
@@ -7401,44 +7360,35 @@ ClearRequestBase::DeleteFiles(QuotaManag
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv = NS_NewLocalFile(aQuotaManager->GetStoragePath(aPersistenceType),
                                 false, getter_AddRefs(directory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   if (NS_WARN_IF(NS_FAILED(
         directory->GetDirectoryEntries(getter_AddRefs(entries)))) || !entries) {
     return;
   }
 
   OriginScope originScope = mOriginScope.Clone();
   if (originScope.IsOrigin()) {
     nsCString originSanitized(originScope.GetOrigin());
     SanitizeOriginString(originSanitized);
     originScope.SetOrigin(originSanitized);
   } else if (originScope.IsPrefix()) {
     nsCString prefixSanitized(originScope.GetPrefix());
     SanitizeOriginString(prefixSanitized);
     originScope.SetPrefix(prefixSanitized);
   }
 
-  bool hasMore;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return;
-    }
-
-    nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
-    MOZ_ASSERT(file);
-
+  nsCOMPtr<nsIFile> file;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) && file) {
     bool isDirectory;
     rv = file->IsDirectory(&isDirectory);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return;
     }
 
     nsString leafName;
     rv = file->GetLeafName(leafName);
@@ -8571,33 +8521,25 @@ CreateOrUpgradeDirectoryMetadataHelper::
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (!exists) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   rv = mDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  bool hasMore;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    nsCOMPtr<nsIFile> originDir = do_QueryInterface(entry);
-    MOZ_ASSERT(originDir);
-
+  nsCOMPtr<nsIFile> originDir;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(originDir)))) &&
+         originDir) {
     nsString leafName;
     rv = originDir->GetLeafName(leafName);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     bool isDirectory;
     rv = originDir->IsDirectory(&isDirectory);
@@ -8737,35 +8679,25 @@ CreateOrUpgradeDirectoryMetadataHelper::
       }
     }
     else {
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
 
-    nsCOMPtr<nsISimpleEnumerator> entries;
+    nsCOMPtr<nsIDirectoryEnumerator> entries;
     rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
-    bool hasMore;
-    while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
-      nsCOMPtr<nsISupports> entry;
-      rv = entries->GetNext(getter_AddRefs(entry));
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
-      }
-
-      nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
-      if (NS_WARN_IF(!file)) {
-        return rv;
-      }
-
+    nsCOMPtr<nsIFile> file;
+    while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) &&
+           file) {
       nsString leafName;
       rv = file->GetLeafName(leafName);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       if (!leafName.Equals(idbDirectoryName)) {
         rv = file->MoveTo(idbDirectory, EmptyString());
@@ -8903,33 +8835,25 @@ UpgradeStorageFrom0_0To1_0Helper::DoUpgr
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (!exists) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   rv = mDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  bool hasMore;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    nsCOMPtr<nsIFile> originDir = do_QueryInterface(entry);
-    MOZ_ASSERT(originDir);
-
+  nsCOMPtr<nsIFile> originDir;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(originDir)))) &&
+         originDir) {
     bool isDirectory;
     rv = originDir->IsDirectory(&isDirectory);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     if (!isDirectory) {
       nsString leafName;
@@ -9036,33 +8960,24 @@ nsresult
 UpgradeStorageFrom1_0To2_0Helper::DoUpgrade()
 {
   AssertIsOnIOThread();
 
   DebugOnly<bool> exists;
   MOZ_ASSERT(NS_SUCCEEDED(mDirectory->Exists(&exists)));
   MOZ_ASSERT(exists);
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   nsresult rv = mDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  bool hasMore;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    nsCOMPtr<nsIFile> originDir = do_QueryInterface(entry);
-    MOZ_ASSERT(originDir);
-
+  nsCOMPtr<nsIFile> originDir;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(originDir)))) && originDir) {
     bool isDirectory;
     rv = originDir->IsDirectory(&isDirectory);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     if (!isDirectory) {
       nsString leafName;
@@ -9148,36 +9063,25 @@ UpgradeStorageFrom1_0To2_0Helper::MaybeU
                                                 const OriginProps& aOriginProps)
 {
   AssertIsOnIOThread();
   MOZ_ASSERT(aOriginProps.mDirectory);
 
   QuotaManager* quotaManager = QuotaManager::Get();
   MOZ_ASSERT(quotaManager);
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   nsresult rv =
     aOriginProps.mDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  bool hasMore;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
-    if (NS_WARN_IF(!file)) {
-      return rv;
-    }
-
+  nsCOMPtr<nsIFile> file;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) && file) {
     bool isDirectory;
     rv = file->IsDirectory(&isDirectory);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     nsString leafName;
     rv = file->GetLeafName(leafName);
@@ -9374,33 +9278,24 @@ nsresult
 UpgradeStorageFrom2_0To2_1Helper::DoUpgrade()
 {
   AssertIsOnIOThread();
 
   DebugOnly<bool> exists;
   MOZ_ASSERT(NS_SUCCEEDED(mDirectory->Exists(&exists)));
   MOZ_ASSERT(exists);
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   nsresult rv = mDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  bool hasMore;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    nsCOMPtr<nsIFile> originDir = do_QueryInterface(entry);
-    MOZ_ASSERT(originDir);
-
+  nsCOMPtr<nsIFile> originDir;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(originDir)))) && originDir) {
     bool isDirectory;
     rv = originDir->IsDirectory(&isDirectory);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     if (!isDirectory) {
       nsString leafName;
@@ -9478,36 +9373,25 @@ UpgradeStorageFrom2_0To2_1Helper::MaybeU
                                                 const OriginProps& aOriginProps)
 {
   AssertIsOnIOThread();
   MOZ_ASSERT(aOriginProps.mDirectory);
 
   QuotaManager* quotaManager = QuotaManager::Get();
   MOZ_ASSERT(quotaManager);
 
-  nsCOMPtr<nsISimpleEnumerator> entries;
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
   nsresult rv =
     aOriginProps.mDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  bool hasMore;
-  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
-    nsCOMPtr<nsISupports> entry;
-    rv = entries->GetNext(getter_AddRefs(entry));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
-    if (NS_WARN_IF(!file)) {
-      return rv;
-    }
-
+  nsCOMPtr<nsIFile> file;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) && file) {
     bool isDirectory;
     rv = file->IsDirectory(&isDirectory);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     nsString leafName;
     rv = file->GetLeafName(leafName);
--- a/dom/svg/nsSVGFilters.cpp
+++ b/dom/svg/nsSVGFilters.cpp
@@ -61,21 +61,17 @@ nsSVGElement::LengthInfo nsSVGFE::sLengt
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGFE,nsSVGFEBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGFE,nsSVGFEBase)
 
 NS_INTERFACE_MAP_BEGIN(nsSVGFE)
-   // nsISupports is an ambiguous base of nsSVGFE so we have to work
-   // around that
-   if ( aIID.Equals(NS_GET_IID(nsSVGFE)) )
-     foundInterface = static_cast<nsISupports*>(static_cast<void*>(this));
-   else
+   NS_INTERFACE_MAP_ENTRY_CONCRETE(nsSVGFE)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGFEBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 void
 nsSVGFE::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
 {
@@ -240,21 +236,17 @@ nsSVGElement::EnumInfo SVGComponentTrans
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(SVGComponentTransferFunctionElement,SVGComponentTransferFunctionElementBase)
 NS_IMPL_RELEASE_INHERITED(SVGComponentTransferFunctionElement,SVGComponentTransferFunctionElementBase)
 
 NS_INTERFACE_MAP_BEGIN(SVGComponentTransferFunctionElement)
-   // nsISupports is an ambiguous base of nsSVGFE so we have to work
-   // around that
-   if ( aIID.Equals(NS_GET_IID(SVGComponentTransferFunctionElement)) )
-     foundInterface = static_cast<nsISupports*>(static_cast<void*>(this));
-   else
+   NS_INTERFACE_MAP_ENTRY_CONCRETE(SVGComponentTransferFunctionElement)
 NS_INTERFACE_MAP_END_INHERITING(SVGComponentTransferFunctionElementBase)
 
 
 //----------------------------------------------------------------------
 // nsFEUnstyledElement methods
 
 bool
 SVGComponentTransferFunctionElement::AttributeAffectsRendering(int32_t aNameSpaceID,
--- a/dom/tests/mochitest/general/test_consoleAPI.html
+++ b/dom/tests/mochitest/general/test_consoleAPI.html
@@ -33,16 +33,17 @@ function doTest() {
     "groupEnd": "function",
     "time": "function",
     "timeLog": "function",
     "timeEnd": "function",
     "profile": "function",
     "profileEnd": "function",
     "assert": "function",
     "count": "function",
+    "countReset": "function",
     "table": "function",
     "clear": "function",
     "dirxml": "function",
     "timeStamp": "function",
   };
 
   var foundProps = 0;
   for (var prop in console) {
--- a/dom/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/dom/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -1881,63 +1881,51 @@ void nsWebBrowserPersist::CleanupLocalFi
                 // children looking for files. Any files created by the
                 // persist object would have been deleted by the first
                 // pass so if there are any there at this stage, the dir
                 // cannot be deleted because it has someone else's files
                 // in it. Empty child dirs are deleted but they must be
                 // recursed through to ensure they are actually empty.
 
                 bool isEmptyDirectory = true;
-                nsCOMArray<nsISimpleEnumerator> dirStack;
+                nsCOMArray<nsIDirectoryEnumerator> dirStack;
                 int32_t stackSize = 0;
 
                 // Push the top level enum onto the stack
-                nsCOMPtr<nsISimpleEnumerator> pos;
+                nsCOMPtr<nsIDirectoryEnumerator> pos;
                 if (NS_SUCCEEDED(file->GetDirectoryEntries(getter_AddRefs(pos))))
                     dirStack.AppendObject(pos);
 
                 while (isEmptyDirectory && (stackSize = dirStack.Count()))
                 {
                     // Pop the last element
-                    nsCOMPtr<nsISimpleEnumerator> curPos;
+                    nsCOMPtr<nsIDirectoryEnumerator> curPos;
                     curPos = dirStack[stackSize-1];
                     dirStack.RemoveObjectAt(stackSize - 1);
 
-                    // Test if the enumerator has any more files in it
-                    bool hasMoreElements = false;
-                    curPos->HasMoreElements(&hasMoreElements);
-                    if (!hasMoreElements)
+                    nsCOMPtr<nsIFile> child;
+                    if (NS_FAILED(curPos->GetNextFile(getter_AddRefs(child))) || !child)
                     {
                         continue;
                     }
 
-                    // Child files automatically make this code drop out,
-                    // while child dirs keep the loop going.
-                    nsCOMPtr<nsISupports> child;
-                    curPos->GetNext(getter_AddRefs(child));
-                    NS_ASSERTION(child, "No child element, but hasMoreElements says otherwise");
-                    if (!child)
-                        continue;
-                    nsCOMPtr<nsIFile> childAsFile = do_QueryInterface(child);
-                    NS_ASSERTION(childAsFile, "This should be a file but isn't");
-
                     bool childIsSymlink = false;
-                    childAsFile->IsSymlink(&childIsSymlink);
+                    child->IsSymlink(&childIsSymlink);
                     bool childIsDir = false;
-                    childAsFile->IsDirectory(&childIsDir);
+                    child->IsDirectory(&childIsDir);
                     if (!childIsDir || childIsSymlink)
                     {
                         // Some kind of file or symlink which means dir
                         // is not empty so just drop out.
                         isEmptyDirectory = false;
                         break;
                     }
                     // Push parent enumerator followed by child enumerator
-                    nsCOMPtr<nsISimpleEnumerator> childPos;
-                    childAsFile->GetDirectoryEntries(getter_AddRefs(childPos));
+                    nsCOMPtr<nsIDirectoryEnumerator> childPos;
+                    child->GetDirectoryEntries(getter_AddRefs(childPos));
                     dirStack.AppendObject(curPos);
                     if (childPos)
                         dirStack.AppendObject(childPos);
 
                 }
                 dirStack.Clear();
 
                 // If after all that walking the dir is deemed empty, delete it
--- a/dom/webidl/CanvasRenderingContext2D.webidl
+++ b/dom/webidl/CanvasRenderingContext2D.webidl
@@ -225,19 +225,23 @@ interface CanvasDrawPath {
   void beginPath();
   void fill(optional CanvasWindingRule winding = "nonzero");
   void fill(Path2D path, optional CanvasWindingRule winding = "nonzero");
   void stroke();
   void stroke(Path2D path);
   void clip(optional CanvasWindingRule winding = "nonzero");
   void clip(Path2D path, optional CanvasWindingRule winding = "nonzero");
 // NOT IMPLEMENTED  void resetClip();
+  [NeedsSubjectPrincipal]
   boolean isPointInPath(unrestricted double x, unrestricted double y, optional CanvasWindingRule winding = "nonzero");
+  [NeedsSubjectPrincipal] // Only required because overloads can't have different extended attributes.
   boolean isPointInPath(Path2D path, unrestricted double x, unrestricted double y, optional CanvasWindingRule winding = "nonzero");
+  [NeedsSubjectPrincipal]
   boolean isPointInStroke(double x, double y);
+  [NeedsSubjectPrincipal] // Only required because overloads can't have different extended attributes.
   boolean isPointInStroke(Path2D path, unrestricted double x, unrestricted double y);
 };
 
 [NoInterfaceObject]
 interface CanvasUserInterface {
   [Pref="canvas.focusring.enabled", Throws] void drawFocusIfNeeded(Element element);
 // NOT IMPLEMENTED  void drawSystemFocusRing(Path path, HTMLElement element);
   [Pref="canvas.customfocusring.enabled"] boolean drawCustomFocusRing(Element element);
@@ -269,17 +273,17 @@ interface CanvasDrawImage {
 
 [NoInterfaceObject]
 interface CanvasImageData {
   // pixel manipulation
   [NewObject, Throws]
   ImageData createImageData(double sw, double sh);
   [NewObject, Throws]
   ImageData createImageData(ImageData imagedata);
-  [NewObject, Throws]
+  [NewObject, Throws, NeedsSubjectPrincipal]
   ImageData getImageData(double sx, double sy, double sw, double sh);
   [Throws]
   void putImageData(ImageData imagedata, double dx, double dy);
   [Throws]
   void putImageData(ImageData imagedata, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight);
 };
 
 [NoInterfaceObject]
--- a/dom/webidl/Console.webidl
+++ b/dom/webidl/Console.webidl
@@ -19,16 +19,18 @@ namespace console {
   // Logging
   [UseCounter]
   void assert(optional boolean condition = false, any... data);
   [UseCounter]
   void clear();
   [UseCounter]
   void count(optional DOMString label = "default");
   [UseCounter]
+  void countReset(optional DOMString label = "default");
+  [UseCounter]
   void debug(any... data);
   [UseCounter]
   void error(any... data);
   [UseCounter]
   void info(any... data);
   [UseCounter]
   void log(any... data);
   [UseCounter]
@@ -134,27 +136,29 @@ dictionary ConsoleTimerError {
 };
 
 dictionary ConsoleCounter {
   DOMString label = "";
   unsigned long count = 0;
 };
 
 dictionary ConsoleCounterError {
-  DOMString error = "maxCountersExceeded";
+  DOMString label = "";
+  DOMString error = "";
 };
 
 [ChromeOnly,
  Exposed=(Window,Worker,WorkerDebugger,Worklet,System)]
 // This is basically a copy of the console namespace.
 interface ConsoleInstance {
   // Logging
   void assert(optional boolean condition = false, any... data);
   void clear();
   void count(optional DOMString label = "default");
+  void countReset(optional DOMString label = "default");
   void debug(any... data);
   void error(any... data);
   void info(any... data);
   void log(any... data);
   void table(any... data); // FIXME: The spec is still unclear about this.
   void trace(any... data);
   void warn(any... data);
   void dir(any... data); // FIXME: This doesn't follow the spec yet.
--- a/dom/webidl/HTMLCanvasElement.webidl
+++ b/dom/webidl/HTMLCanvasElement.webidl
@@ -18,39 +18,39 @@ interface HTMLCanvasElement : HTMLElemen
   [CEReactions, Pure, SetterThrows]
            attribute unsigned long width;
   [CEReactions, Pure, SetterThrows]
            attribute unsigned long height;
 
   [Throws]
   nsISupports? getContext(DOMString contextId, optional any contextOptions = null);
 
-  [Throws]
+  [Throws, NeedsSubjectPrincipal]
   DOMString toDataURL(optional DOMString type = "",
                       optional any encoderOptions);
-  [Throws]
+  [Throws, NeedsSubjectPrincipal]
   void toBlob(BlobCallback _callback,
               optional DOMString type = "",
               optional any encoderOptions);
 };
 
 // Mozilla specific bits
 partial interface HTMLCanvasElement {
   [Pure, SetterThrows]
            attribute boolean mozOpaque;
-  [Throws, NeedsCallerType]
+  [Throws, NeedsSubjectPrincipal]
   File mozGetAsFile(DOMString name, optional DOMString? type = null);
   // A Mozilla-only extension to get a canvas context backed by double-buffered
   // shared memory. Only privileged callers can call this.
   [ChromeOnly, Throws]
   nsISupports? MozGetIPCContext(DOMString contextId);
 
            attribute PrintCallback? mozPrintCallback;
 
-  [Throws, Pref="canvas.capturestream.enabled"]
+  [Throws, Pref="canvas.capturestream.enabled", NeedsSubjectPrincipal]
   CanvasCaptureMediaStream captureStream(optional double frameRate);
 };
 
 // For OffscreenCanvas
 // Reference: https://wiki.whatwg.org/wiki/OffscreenCanvas
 partial interface HTMLCanvasElement {
   [Pref="gfx.offscreencanvas.enabled", Throws]
   OffscreenCanvas transferControlToOffscreen();
--- a/editor/libeditor/CompositionTransaction.cpp
+++ b/editor/libeditor/CompositionTransaction.cpp
@@ -77,19 +77,17 @@ CompositionTransaction::~CompositionTran
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(CompositionTransaction, EditTransactionBase,
                                    mEditorBase,
                                    mTextNode)
 // mRangeList can't lead to cycles
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CompositionTransaction)
-  if (aIID.Equals(NS_GET_IID(CompositionTransaction))) {
-    foundInterface = static_cast<nsITransaction*>(this);
-  } else
+  NS_INTERFACE_MAP_ENTRY_CONCRETE(CompositionTransaction)
 NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
 
 NS_IMPL_ADDREF_INHERITED(CompositionTransaction, EditTransactionBase)
 NS_IMPL_RELEASE_INHERITED(CompositionTransaction, EditTransactionBase)
 
 NS_IMETHODIMP
 CompositionTransaction::DoTransaction()
 {
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -1040,17 +1040,17 @@ HTMLEditor::InsertObject(const nsACStrin
                                            aDoDeleteSelection);
     nsCOMPtr<nsIEditorUtils> utils =
       do_GetService("@mozilla.org/editor-utils;1");
     NS_ENSURE_TRUE(utils, NS_ERROR_FAILURE);
 
     nsCOMPtr<nsINode> node = do_QueryInterface(aDestinationNode);
     MOZ_ASSERT(node);
 
-    nsCOMPtr<nsIDOMBlob> domBlob = Blob::Create(node->GetOwnerGlobal(), blob);
+    RefPtr<Blob> domBlob = Blob::Create(node->GetOwnerGlobal(), blob);
     NS_ENSURE_TRUE(domBlob, NS_ERROR_FAILURE);
 
     return utils->SlurpBlob(domBlob, node->OwnerDoc()->GetWindow(), br);
   }
 
   nsAutoCString type(aType);
 
   // Check to see if we can insert an image file
--- a/editor/libeditor/InsertTextTransaction.cpp
+++ b/editor/libeditor/InsertTextTransaction.cpp
@@ -47,19 +47,17 @@ InsertTextTransaction::~InsertTextTransa
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertTextTransaction, EditTransactionBase,
                                    mEditorBase,
                                    mTextNode)
 
 NS_IMPL_ADDREF_INHERITED(InsertTextTransaction, EditTransactionBase)
 NS_IMPL_RELEASE_INHERITED(InsertTextTransaction, EditTransactionBase)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertTextTransaction)
-  if (aIID.Equals(NS_GET_IID(InsertTextTransaction))) {
-    foundInterface = static_cast<nsITransaction*>(this);
-  } else
+  NS_INTERFACE_MAP_ENTRY_CONCRETE(InsertTextTransaction)
 NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
 
 
 NS_IMETHODIMP
 InsertTextTransaction::DoTransaction()
 {
   if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode)) {
     return NS_ERROR_NOT_AVAILABLE;
--- a/editor/nsIEditorUtils.idl
+++ b/editor/nsIEditorUtils.idl
@@ -2,19 +2,20 @@
  *
  * 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 "nsISupports.idl"
 #include "domstubs.idl"
 
-interface nsIDOMBlob;
 interface mozIDOMWindowProxy;
 
+webidl Blob;
+
 [scriptable, builtinclass, uuid(eb8b8ad9-5d8f-43bd-8ce5-5b943c180d56)]
 interface nsIEditorBlobListener : nsISupports
 {
   void onResult(in ACString aResult);
   void onError(in AString aErrorName);
 };
 
 /**
@@ -22,11 +23,11 @@ interface nsIEditorBlobListener : nsISup
  * done in JavaScript.
  */
 [scriptable, uuid(4bf94928-575e-4bd1-8321-a2c4b3d0119e)]
 interface nsIEditorUtils : nsISupports
 {
   /**
    * Given a blob, returns the data from that blob, asynchronously.
    */
-  void slurpBlob(in nsIDOMBlob aBlob, in mozIDOMWindowProxy aScope,
+  void slurpBlob(in Blob aBlob, in mozIDOMWindowProxy aScope,
                  in nsIEditorBlobListener aListener);
 };
--- a/extensions/spellcheck/hunspell/glue/moz.build
+++ b/extensions/spellcheck/hunspell/glue/moz.build
@@ -8,32 +8,28 @@ UNIFIED_SOURCES += [
     'mozHunspell.cpp',
     'mozHunspellFileMgr.cpp',
     'RemoteSpellCheckEngineChild.cpp',
     'RemoteSpellCheckEngineParent.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
 
-if CONFIG['MOZ_SYSTEM_HUNSPELL']:
-    CXXFLAGS += CONFIG['MOZ_HUNSPELL_CFLAGS']
-else:
-    LOCAL_INCLUDES += ['../src']
-
 LOCAL_INCLUDES += [
+    '../src',
     '/dom/base',
     '/extensions/spellcheck/src',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 IPDL_SOURCES = [
     'PRemoteSpellcheckEngine.ipdl',
 ]
 
 EXPORTS.mozilla += [
      'RemoteSpellCheckEngineChild.h',
      'RemoteSpellCheckEngineParent.h',
 ]
 
-# This variable is referenced in configure.in.  Make sure to change that file
-# too if you need to change this variable.
+# This variable is referenced in mozilla-config.h.in.  Make sure to change
+# that file too if you need to change this variable.
 DEFINES['HUNSPELL_STATIC'] = True
--- a/extensions/spellcheck/hunspell/glue/mozHunspell.cpp
+++ b/extensions/spellcheck/hunspell/glue/mozHunspell.cpp
@@ -416,25 +416,21 @@ mozHunspell::LoadDictionariesFromDir(nsI
   rv = aDir->Exists(&check);
   if (NS_FAILED(rv) || !check)
     return NS_ERROR_UNEXPECTED;
 
   rv = aDir->IsDirectory(&check);
   if (NS_FAILED(rv) || !check)
     return NS_ERROR_UNEXPECTED;
 
-  nsCOMPtr<nsISimpleEnumerator> e;
-  rv = aDir->GetDirectoryEntries(getter_AddRefs(e));
+  nsCOMPtr<nsIDirectoryEnumerator> files;
+  rv = aDir->GetDirectoryEntries(getter_AddRefs(files));
   if (NS_FAILED(rv))
     return NS_ERROR_UNEXPECTED;
 
-  nsCOMPtr<nsIDirectoryEnumerator> files(do_QueryInterface(e));
-  if (!files)
-    return NS_ERROR_UNEXPECTED;
-
   nsCOMPtr<nsIFile> file;
   while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(file))) && file) {
     nsAutoString leafName;
     file->GetLeafName(leafName);
     if (!StringEndsWith(leafName, NS_LITERAL_STRING(".dic")))
       continue;
 
     nsAutoString dict(leafName);
--- a/extensions/spellcheck/hunspell/moz.build
+++ b/extensions/spellcheck/hunspell/moz.build
@@ -1,12 +1,10 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-DIRS += ['glue']
-if not CONFIG['MOZ_SYSTEM_HUNSPELL']:
-    DIRS += ['src']
+DIRS += ['glue', 'src']
 
 if CONFIG['ENABLE_TESTS']:
     XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']    
--- a/extensions/spellcheck/hunspell/src/hunvisapi.h
+++ b/extensions/spellcheck/hunspell/src/hunvisapi.h
@@ -1,18 +1,6 @@
 #ifndef HUNSPELL_VISIBILITY_H_
 #define HUNSPELL_VISIBILITY_H_
 
-#if defined(HUNSPELL_STATIC)
-#  define LIBHUNSPELL_DLL_EXPORTED
-#elif defined(_MSC_VER)
-#  if defined(BUILDING_LIBHUNSPELL)
-#    define LIBHUNSPELL_DLL_EXPORTED __declspec(dllexport)
-#  else
-#    define LIBHUNSPELL_DLL_EXPORTED __declspec(dllimport)
-#  endif
-#elif defined(BUILDING_LIBHUNSPELL) && 1
-#  define LIBHUNSPELL_DLL_EXPORTED __attribute__((__visibility__("default")))
-#else
-#  define LIBHUNSPELL_DLL_EXPORTED
-#endif
+#define LIBHUNSPELL_DLL_EXPORTED
 
 #endif
--- a/extensions/spellcheck/hunspell/src/moz.build
+++ b/extensions/spellcheck/hunspell/src/moz.build
@@ -10,18 +10,18 @@ UNIFIED_SOURCES += [
     'csutil.cxx',
     'hashmgr.cxx',
     'hunspell.cxx',
     'phonet.cxx',
     'replist.cxx',
     'suggestmgr.cxx',
 ]
 
-# This variable is referenced in configure.in.  Make sure to change that file
-# too if you need to change this variable.
+# This variable is referenced in mozilla-config.h.in.  Make sure to change
+# that file too if you need to change this variable.
 DEFINES['HUNSPELL_STATIC'] = True
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../glue',
 ]
 
--- a/extensions/spellcheck/src/moz.build
+++ b/extensions/spellcheck/src/moz.build
@@ -12,23 +12,19 @@ UNIFIED_SOURCES += [
     'mozPersonalDictionary.cpp',
     'mozSpellChecker.cpp',
     'mozSpellCheckerFactory.cpp',
     'mozSpellI18NManager.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
 
-if CONFIG['MOZ_SYSTEM_HUNSPELL']:
-    CXXFLAGS += CONFIG['MOZ_HUNSPELL_CFLAGS']
-else:
-    LOCAL_INCLUDES += ['../hunspell/src']
-
 LOCAL_INCLUDES += [
     '../hunspell/glue',
+    '../hunspell/src',
     '/dom/base',
 ]
 EXPORTS.mozilla += [
      'mozInlineSpellChecker.h',
      'mozSpellChecker.h',
 ]
 
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
--- a/gfx/angle/checkout/include/EGL/eglext_angle.h
+++ b/gfx/angle/checkout/include/EGL/eglext_angle.h
@@ -170,11 +170,16 @@ EGLAPI EGLint EGLAPIENTRY eglProgramCach
 #define EGL_ANGLE_iosurface_client_buffer 1
 #define EGL_IOSURFACE_ANGLE 0x3454
 #define EGL_IOSURFACE_PLANE_ANGLE 0x345A
 #define EGL_TEXTURE_RECTANGLE_ANGLE 0x345B
 #define EGL_TEXTURE_TYPE_ANGLE 0x345C
 #define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D
 #endif /* EGL_ANGLE_iosurface_client_buffer */
 
+#ifndef EGL_ANGLE_create_context_extensions_enabled
+#define EGL_ANGLE_create_context_extensions_enabled 1
+#define EGL_EXTENSIONS_ENABLED_ANGLE 0x345F
+#endif /* EGL_ANGLE_create_context_extensions_enabled */
+
 // clang-format on
 
 #endif  // INCLUDE_EGL_EGLEXT_ANGLE_
--- a/gfx/angle/checkout/include/GLSLANG/ShaderLang.h
+++ b/gfx/angle/checkout/include/GLSLANG/ShaderLang.h
@@ -20,17 +20,17 @@
 // and the shading language compiler.
 //
 
 // Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h
 #include "ShaderVars.h"
 
 // Version number for shader translation API.
 // It is incremented every time the API changes.
-#define ANGLE_SH_VERSION 196
+#define ANGLE_SH_VERSION 197
 
 enum ShShaderSpec
 {
     SH_GLES2_SPEC,
     SH_WEBGL_SPEC,
 
     SH_GLES3_SPEC,
     SH_WEBGL2_SPEC,
--- a/gfx/angle/checkout/include/GLSLANG/ShaderVars.h
+++ b/gfx/angle/checkout/include/GLSLANG/ShaderVars.h
@@ -121,17 +121,22 @@ struct ShaderVariable
     // Offset of this variable in parent arrays. In case the parent is an array of arrays, the
     // offset is outerArrayElement * innerArraySize + innerArrayElement.
     // For example, if there's a variable declared as size 3 array of size 4 array of int:
     //   int a[3][4];
     // then the flattenedOffsetInParentArrays of a[2] would be 2.
     // and flattenedOffsetInParentArrays of a[2][1] would be 2*4 + 1 = 9.
     unsigned int flattenedOffsetInParentArrays;
 
+    // Static use means that the variable is accessed somewhere in the shader source.
     bool staticUse;
+    // A variable is active unless the compiler determined that it is not accessed by the shader.
+    // All active variables are statically used, but not all statically used variables are
+    // necessarily active. GLES 3.0.5 section 2.12.6. GLES 3.1 section 7.3.1.
+    bool active;
     std::vector<ShaderVariable> fields;
     std::string structName;
 
   protected:
     bool isSameVariableAtLinkTime(const ShaderVariable &other,
                                   bool matchPrecision,
                                   bool matchName) const;
 
@@ -274,16 +279,17 @@ struct InterfaceBlock
     BlockLayoutType layout;
 
     // Deprecated. Matrix packing should only be queried from individual fields of the block.
     // TODO(oetuaho): Remove this once it is no longer used in Chromium.
     bool isRowMajorLayout;
 
     int binding;
     bool staticUse;
+    bool active;
     BlockType blockType;
     std::vector<InterfaceBlockField> fields;
 };
 
 struct WorkGroupSize
 {
     // Must have a trivial default constructor since it is used in YYSTYPE.
     WorkGroupSize() = default;
--- a/gfx/angle/checkout/include/KHR/khrplatform.h
+++ b/gfx/angle/checkout/include/KHR/khrplatform.h
@@ -1,13 +1,13 @@
 #ifndef __khrplatform_h_
 #define __khrplatform_h_
 
 /*
-** Copyright (c) 2008-2009 The Khronos Group Inc.
+** Copyright (c) 2008-2018 The Khronos Group Inc.
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a
 ** copy of this software and/or associated documentation files (the
 ** "Materials"), to deal in the Materials without restriction, including
 ** without limitation the rights to use, copy, modify, merge, publish,
 ** distribute, sublicense, and/or sell copies of the Materials, and to
 ** permit persons to whom the Materials are furnished to do so, subject to
 ** the following conditions:
@@ -21,28 +21,26 @@
 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 */
 
 /* Khronos platform-specific types and definitions.
  *
- * $Revision: 32517 $ on $Date: 2016-03-11 02:41:19 -0800 (Fri, 11 Mar 2016) $
+ * The master copy of khrplatform.h is maintained in the Khronos EGL
+ * Registry repository at https://github.com/KhronosGroup/EGL-Registry
+ * The last semantic modification to khrplatform.h was at commit ID:
+ *      67a3e0864c2d75ea5287b9f3d2eb74a745936692
  *
  * Adopters may modify this file to suit their platform. Adopters are
  * encouraged to submit platform specific modifications to the Khronos
  * group so that they can be included in future versions of this file.
- * Please submit changes by sending them to the public Khronos Bugzilla
- * (http://khronos.org/bugzilla) by filing a bug against product
- * "Khronos (general)" component "Registry".
- *
- * A predefined template which fills in some of the bug fields can be
- * reached using http://tinyurl.com/khrplatform-h-bugreport, but you
- * must create a Bugzilla login first.
+ * Please submit changes by filing pull requests or issues on
+ * the EGL Registry repository linked above.
  *
  *
  * See the Implementer's Guidelines for information about where this file
  * should be located on your system and for more details of its use:
  *    http://www.khronos.org/registry/implementers_guide.pdf
  *
  * This file should be included as
  *        #include <KHR/khrplatform.h>
@@ -97,18 +95,17 @@
  *-------------------------------------------------------------------------
  * This precedes the return type of the function in the function prototype.
  */
 #if defined(_WIN32) && !defined(__SCITECH_SNAP__)
 #   define KHRONOS_APICALL __declspec(dllimport)
 #elif defined (__SYMBIAN32__)
 #   define KHRONOS_APICALL IMPORT_C
 #elif defined(__ANDROID__)
-#   include <sys/cdefs.h>
-#   define KHRONOS_APICALL __attribute__((visibility("default"))) __NDK_FPABI__
+#   define KHRONOS_APICALL __attribute__((visibility("default")))
 #else
 #   define KHRONOS_APICALL
 #endif
 
 /*-------------------------------------------------------------------------
  * Definition of KHRONOS_APIENTRY
  *-------------------------------------------------------------------------
  * This follows the return type of the function  and precedes the function
@@ -277,9 +274,9 @@ typedef khronos_int64_t        khronos_s
  * comparisons should not be made against KHRONOS_TRUE.
  */
 typedef enum {
     KHRONOS_FALSE = 0,
     KHRONOS_TRUE  = 1,
     KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
 } khronos_boolean_enum_t;
 
-#endif /* __khrplatform_h_ */
\ No newline at end of file
+#endif /* __khrplatform_h_ */
--- a/gfx/angle/checkout/out/gen/angle/id/commit.h
+++ b/gfx/angle/checkout/out/gen/angle/id/commit.h
@@ -1,3 +1,3 @@
-#define ANGLE_COMMIT_HASH "fcbca0e873c3"
+#define ANGLE_COMMIT_HASH "2426b097472f"
 #define ANGLE_COMMIT_HASH_SIZE 12
-#define ANGLE_COMMIT_DATE "2018-04-20 16:07:35 -0700"
+#define ANGLE_COMMIT_DATE "2018-05-22 15:14:46 -0700"
--- a/gfx/angle/checkout/src/common/Color.h
+++ b/gfx/angle/checkout/src/common/Color.h
@@ -10,23 +10,26 @@
 #define COMMON_COLOR_H_
 
 namespace angle
 {
 
 template <typename T>
 struct Color
 {
+    Color();
+    Color(T r, T g, T b, T a);
+
+    const T *data() const { return &red; }
+    T *ptr() { return &red; }
+
     T red;
     T green;
     T blue;
     T alpha;
-
-    Color();
-    Color(T r, T g, T b, T a);
 };
 
 template <typename T>
 bool operator==(const Color<T> &a, const Color<T> &b);
 
 template <typename T>
 bool operator!=(const Color<T> &a, const Color<T> &b);
 
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/common/FixedVector.h
@@ -0,0 +1,331 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FixedVector.h:
+//   A vector class with a maximum size and fixed storage.
+//
+
+#ifndef COMMON_FIXEDVECTOR_H_
+#define COMMON_FIXEDVECTOR_H_
+
+#include "common/debug.h"
+
+#include <algorithm>
+#include <array>
+#include <initializer_list>
+
+namespace angle
+{
+template <class T, size_t N, class Storage = std::array<T, N>>
+class FixedVector final
+{
+  public:
+    using value_type             = typename Storage::value_type;
+    using size_type              = typename Storage::size_type;
+    using reference              = typename Storage::reference;
+    using const_reference        = typename Storage::const_reference;
+    using pointer                = typename Storage::pointer;
+    using const_pointer          = typename Storage::const_pointer;
+    using iterator               = typename Storage::iterator;
+    using const_iterator         = typename Storage::const_iterator;
+    using reverse_iterator       = typename Storage::reverse_iterator;
+    using const_reverse_iterator = typename Storage::const_reverse_iterator;
+
+    FixedVector();
+    FixedVector(size_type count, const value_type &value);
+    FixedVector(size_type count);
+
+    FixedVector(const FixedVector<T, N, Storage> &other);
+    FixedVector(FixedVector<T, N, Storage> &&other);
+    FixedVector(std::initializer_list<value_type> init);
+
+    FixedVector<T, N, Storage> &operator=(const FixedVector<T, N, Storage> &other);
+    FixedVector<T, N, Storage> &operator=(FixedVector<T, N, Storage> &&other);
+    FixedVector<T, N, Storage> &operator=(std::initializer_list<value_type> init);
+
+    ~FixedVector();
+
+    reference at(size_type pos);
+    const_reference at(size_type pos) const;
+
+    reference operator[](size_type pos);
+    const_reference operator[](size_type pos) const;
+
+    pointer data();
+    const_pointer data() const;
+
+    iterator begin();
+    const_iterator begin() const;
+
+    iterator end();
+    const_iterator end() const;
+
+    bool empty() const;
+    size_type size() const;
+    size_type max_size() const;
+
+    void clear();
+
+    void push_back(const value_type &value);
+    void push_back(value_type &&value);
+
+    void pop_back();
+    reference back();
+    const_reference back() const;
+
+    void swap(FixedVector<T, N, Storage> &other);
+
+    void resize(size_type count);
+    void resize(size_type count, const value_type &value);
+
+    bool full() const;
+
+  private:
+    void assign_from_initializer_list(std::initializer_list<value_type> init);
+
+    Storage mStorage;
+    size_type mSize = 0;
+};
+
+template <class T, size_t N, class Storage>
+bool operator==(const FixedVector<T, N, Storage> &a, const FixedVector<T, N, Storage> &b)
+{
+    return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
+}
+
+template <class T, size_t N, class Storage>
+bool operator!=(const FixedVector<T, N, Storage> &a, const FixedVector<T, N, Storage> &b)
+{
+    return !(a == b);
+}
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage>::FixedVector() = default;
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage>::FixedVector(size_type count, const value_type &value) : mSize(count)
+{
+    ASSERT(count <= N);
+    std::fill(mStorage.begin(), mStorage.begin() + count, value);
+}
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage>::FixedVector(size_type count) : mSize(count)
+{
+    ASSERT(count <= N);
+}
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage>::FixedVector(const FixedVector<T, N, Storage> &other) = default;
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage>::FixedVector(FixedVector<T, N, Storage> &&other) = default;
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage>::FixedVector(std::initializer_list<value_type> init)
+{
+    ASSERT(init.size() <= N);
+    assign_from_initializer_list(init);
+}
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=(
+    const FixedVector<T, N, Storage> &other) = default;
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=(
+    FixedVector<T, N, Storage> &&other) = default;
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=(
+    std::initializer_list<value_type> init)
+{
+    clear();
+    ASSERT(init.size() <= N);
+    assign_from_initializer_list(init);
+    return this;
+}
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage>::~FixedVector()
+{
+    clear();
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::at(size_type pos)
+{
+    ASSERT(pos < N);
+    return mStorage.at(pos);
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::at(
+    size_type pos) const
+{
+    ASSERT(pos < N);
+    return mStorage.at(pos);
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::operator[](size_type pos)
+{
+    ASSERT(pos < N);
+    return mStorage[pos];
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::operator[](
+    size_type pos) const
+{
+    ASSERT(pos < N);
+    return mStorage[pos];
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::const_pointer angle::FixedVector<T, N, Storage>::data() const
+{
+    return mStorage.data();
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::pointer angle::FixedVector<T, N, Storage>::data()
+{
+    return mStorage.data();
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::iterator FixedVector<T, N, Storage>::begin()
+{
+    return mStorage.begin();
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::const_iterator FixedVector<T, N, Storage>::begin() const
+{
+    return mStorage.begin();
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::iterator FixedVector<T, N, Storage>::end()
+{
+    return mStorage.begin() + mSize;
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::const_iterator FixedVector<T, N, Storage>::end() const
+{
+    return mStorage.begin() + mSize;
+}
+
+template <class T, size_t N, class Storage>
+bool FixedVector<T, N, Storage>::empty() const
+{
+    return mSize == 0;
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::size_type FixedVector<T, N, Storage>::size() const
+{
+    return mSize;
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::size_type FixedVector<T, N, Storage>::max_size() const
+{
+    return N;
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::clear()
+{
+    resize(0);
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::push_back(const value_type &value)
+{
+    ASSERT(mSize < N);
+    mStorage[mSize] = value;
+    mSize++;
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::push_back(value_type &&value)
+{
+    ASSERT(mSize < N);
+    mStorage[mSize] = std::move(value);
+    mSize++;
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::pop_back()
+{
+    ASSERT(mSize > 0);
+    mSize--;
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::back()
+{
+    ASSERT(mSize > 0);
+    return mStorage[mSize - 1];
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::back() const
+{
+    ASSERT(mSize > 0);
+    return mStorage[mSize - 1];
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::swap(FixedVector<T, N, Storage> &other)
+{
+    std::swap(mSize, other.mSize);
+    std::swap(mStorage, other.mStorage);
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::resize(size_type count)
+{
+    resize(count, value_type());
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::resize(size_type count, const value_type &value)
+{
+    ASSERT(count <= N);
+    while (mSize > count)
+    {
+        mSize--;
+        mStorage[mSize] = T();
+    }
+    while (mSize < count)
+    {
+        mStorage[mSize] = value;
+        mSize++;
+    }
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::assign_from_initializer_list(
+    std::initializer_list<value_type> init)
+{
+    for (auto element : init)
+    {
+        mStorage[mSize] = std::move(element);
+        mSize++;
+    }
+}
+
+template <class T, size_t N, class Storage>
+bool FixedVector<T, N, Storage>::full() const
+{
+    return (mSize == N);
+}
+}  // namespace angle
+
+#endif  // COMMON_FIXEDVECTOR_H_
--- a/gfx/angle/checkout/src/common/angleutils.h
+++ b/gfx/angle/checkout/src/common/angleutils.h
@@ -186,16 +186,17 @@ std::string ToString(const T &value)
     return o.str();
 }
 
 // snprintf is not defined with MSVC prior to to msvc14
 #if defined(_MSC_VER) && _MSC_VER < 1900
 #define snprintf _snprintf
 #endif
 
+#define GL_A1RGB5_ANGLEX 0x6AC5
 #define GL_BGRX8_ANGLEX 0x6ABA
 #define GL_BGR565_ANGLEX 0x6ABB
 #define GL_BGRA4_ANGLEX 0x6ABC
 #define GL_BGR5_A1_ANGLEX 0x6ABD
 #define GL_INT_64_ANGLEX 0x6ABE
 #define GL_UINT_64_ANGLEX 0x6ABF
 #define GL_BGRA8_SRGB_ANGLEX 0x6AC0
 
--- a/gfx/angle/checkout/src/common/bitset_utils.h
+++ b/gfx/angle/checkout/src/common/bitset_utils.h
@@ -35,20 +35,20 @@ class BitSetT final
             mParent->set(mBit, x);
             return *this;
         }
         explicit operator bool() const { return mParent->test(mBit); }
 
       private:
         friend class BitSetT;
 
-        Reference(BitSetT *parent, std::size_t bit) : mParent(parent), mBit(bit) {}
+        Reference(BitSetT *parent, ParamT bit) : mParent(parent), mBit(bit) {}
 
         BitSetT *mParent;
-        std::size_t mBit;
+        ParamT mBit;
     };
 
     class Iterator final
     {
       public:
         Iterator(const BitSetT &bits);
         Iterator &operator++();
 
@@ -59,18 +59,17 @@ class BitSetT final
       private:
         std::size_t getNextBit();
 
         BitSetT mBitsCopy;
         std::size_t mCurrentBit;
     };
 
     BitSetT();
-    BitSetT(BitsT value);
-    ~BitSetT();
+    constexpr explicit BitSetT(BitsT value);
 
     BitSetT(const BitSetT &other);
     BitSetT &operator=(const BitSetT &other);
 
     bool operator==(const BitSetT &other) const;
     bool operator!=(const BitSetT &other) const;
 
     constexpr bool operator[](ParamT pos) const;
@@ -85,16 +84,20 @@ class BitSetT final
 
     constexpr std::size_t size() const { return N; }
 
     BitSetT &operator&=(const BitSetT &other);
     BitSetT &operator|=(const BitSetT &other);
     BitSetT &operator^=(const BitSetT &other);
     BitSetT operator~() const;
 
+    BitSetT &operator&=(BitsT value);
+    BitSetT &operator|=(BitsT value);
+    BitSetT &operator^=(BitsT value);
+
     BitSetT operator<<(std::size_t pos) const;
     BitSetT &operator<<=(std::size_t pos);
     BitSetT operator>>(std::size_t pos) const;
     BitSetT &operator>>=(std::size_t pos);
 
     BitSetT &set();
     BitSetT &set(ParamT pos, bool value = true);
 
@@ -110,17 +113,21 @@ class BitSetT final
     Iterator begin() const { return Iterator(*this); }
     Iterator end() const { return Iterator(BitSetT()); }
 
   private:
     constexpr static BitsT Bit(ParamT x)
     {
         return (static_cast<BitsT>(1) << static_cast<size_t>(x));
     }
-    constexpr static BitsT Mask(std::size_t x) { return ((Bit(x - 1) - 1) << 1) + 1; }
+    // Produces a mask of ones up to the "x"th bit.
+    constexpr static BitsT Mask(std::size_t x)
+    {
+        return ((Bit(static_cast<ParamT>(x - 1)) - 1) << 1) + 1;
+    }
 
     BitsT mBits;
 };
 
 template <size_t N>
 class IterableBitSet : public std::bitset<N>
 {
   public:
@@ -208,22 +215,17 @@ unsigned long IterableBitSet<N>::Iterato
 template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT>::BitSetT() : mBits(0)
 {
     static_assert(N > 0, "Bitset type cannot support zero bits.");
     static_assert(N <= sizeof(BitsT) * 8, "Bitset type cannot support a size this large.");
 }
 
 template <size_t N, typename BitsT, typename ParamT>
-BitSetT<N, BitsT, ParamT>::BitSetT(BitsT value) : mBits(value & Mask(N))
-{
-}
-
-template <size_t N, typename BitsT, typename ParamT>
-BitSetT<N, BitsT, ParamT>::~BitSetT()
+constexpr BitSetT<N, BitsT, ParamT>::BitSetT(BitsT value) : mBits(value & Mask(N))
 {
 }
 
 template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT>::BitSetT(const BitSetT &other) : mBits(other.mBits)
 {
 }
 
@@ -308,16 +310,37 @@ BitSetT<N, BitsT, ParamT> &BitSetT<N, Bi
 
 template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator~() const
 {
     return BitSetT<N, BitsT, ParamT>(~mBits & Mask(N));
 }
 
 template <size_t N, typename BitsT, typename ParamT>
+BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator&=(BitsT value)
+{
+    mBits &= value;
+    return *this;
+}
+
+template <size_t N, typename BitsT, typename ParamT>
+BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator|=(BitsT value)
+{
+    mBits |= value;
+    return *this;
+}
+
+template <size_t N, typename BitsT, typename ParamT>
+BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator^=(BitsT value)
+{
+    mBits ^= value;
+    return *this;
+}
+
+template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator<<(std::size_t pos) const
 {
     return BitSetT<N, BitsT, ParamT>((mBits << pos) & Mask(N));
 }
 
 template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator<<=(std::size_t pos)
 {
--- a/gfx/angle/checkout/src/common/mathutil.h
+++ b/gfx/angle/checkout/src/common/mathutil.h
@@ -4,57 +4,59 @@
 // found in the LICENSE file.
 //
 
 // mathutil.h: Math and bit manipulation functions.
 
 #ifndef COMMON_MATHUTIL_H_
 #define COMMON_MATHUTIL_H_
 
-#include <limits>
-#include <algorithm>
 #include <math.h>
-#include <string.h>
 #include <stdint.h>
 #include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <limits>
 
 #include <anglebase/numerics/safe_math.h>
 
 #include "common/debug.h"
 #include "common/platform.h"
 
 namespace angle
 {
 using base::CheckedNumeric;
 using base::IsValueInRangeForNumericType;
 }
 
 namespace gl
 {
 
-const unsigned int Float32One = 0x3F800000;
+const unsigned int Float32One   = 0x3F800000;
 const unsigned short Float16One = 0x3C00;
 
-template<typename T>
+template <typename T>
 inline bool isPow2(T x)
 {
     static_assert(std::is_integral<T>::value, "isPow2 must be called on an integer type.");
     return (x & (x - 1)) == 0 && (x != 0);
 }
 
 inline int log2(int x)
 {
     int r = 0;
-    while ((x >> r) > 1) r++;
+    while ((x >> r) > 1)
+        r++;
     return r;
 }
 
 inline unsigned int ceilPow2(unsigned int x)
 {
-    if (x != 0) x--;
+    if (x != 0)
+        x--;
     x |= x >> 1;
     x |= x >> 2;
     x |= x >> 4;
     x |= x >> 8;
     x |= x >> 16;
     x++;
 
     return x;
@@ -103,29 +105,29 @@ inline unsigned int clampCast(bool value
 }
 
 template <>
 inline int clampCast(bool value)
 {
     return static_cast<int>(value);
 }
 
-template<typename T, typename MIN, typename MAX>
+template <typename T, typename MIN, typename MAX>
 inline T clamp(T x, MIN min, MAX max)
 {
     // Since NaNs fail all comparison tests, a NaN value will default to min
     return x > min ? (x > max ? max : x) : min;
 }
 
 inline float clamp01(float x)
 {
     return clamp(x, 0.0f, 1.0f);
 }
 
-template<const int n>
+template <const int n>
 inline unsigned int unorm(float x)
 {
     const unsigned int max = 0xFFFFFFFF >> (32 - n);
 
     if (x > 1)
     {
         return max;
     }
@@ -137,17 +139,17 @@ inline unsigned int unorm(float x)
     {
         return (unsigned int)(max * x + 0.5f);
     }
 }
 
 inline bool supportsSSE2()
 {
 #if defined(ANGLE_USE_SSE)
-    static bool checked = false;
+    static bool checked  = false;
     static bool supports = false;
 
     if (checked)
     {
         return supports;
     }
 
 #if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
@@ -177,79 +179,82 @@ destType bitCast(const sourceType &sourc
     destType output;
     memcpy(&output, &source, copySize);
     return output;
 }
 
 inline unsigned short float32ToFloat16(float fp32)
 {
     unsigned int fp32i = bitCast<unsigned int>(fp32);
-    unsigned int sign = (fp32i & 0x80000000) >> 16;
-    unsigned int abs = fp32i & 0x7FFFFFFF;
+    unsigned int sign  = (fp32i & 0x80000000) >> 16;
+    unsigned int abs   = fp32i & 0x7FFFFFFF;
 
-    if(abs > 0x47FFEFFF)   // Infinity
+    if (abs > 0x47FFEFFF)  // Infinity
     {
         return static_cast<unsigned short>(sign | 0x7FFF);
     }
-    else if(abs < 0x38800000)   // Denormal
+    else if (abs < 0x38800000)  // Denormal
     {
         unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000;
-        int e = 113 - (abs >> 23);
+        int e                 = 113 - (abs >> 23);
 
-        if(e < 24)
+        if (e < 24)
         {
             abs = mantissa >> e;
         }
         else
         {
             abs = 0;
         }
 
         return static_cast<unsigned short>(sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
     }
     else
     {
-        return static_cast<unsigned short>(sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
+        return static_cast<unsigned short>(
+            sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
     }
 }
 
 float float16ToFloat32(unsigned short h);
 
 unsigned int convertRGBFloatsTo999E5(float red, float green, float blue);
 void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue);
 
 inline unsigned short float32ToFloat11(float fp32)
 {
-    const unsigned int float32MantissaMask = 0x7FFFFF;
-    const unsigned int float32ExponentMask = 0x7F800000;
-    const unsigned int float32SignMask = 0x80000000;
-    const unsigned int float32ValueMask = ~float32SignMask;
+    const unsigned int float32MantissaMask     = 0x7FFFFF;
+    const unsigned int float32ExponentMask     = 0x7F800000;
+    const unsigned int float32SignMask         = 0x80000000;
+    const unsigned int float32ValueMask        = ~float32SignMask;
     const unsigned int float32ExponentFirstBit = 23;
-    const unsigned int float32ExponentBias = 127;
+    const unsigned int float32ExponentBias     = 127;
 
-    const unsigned short float11Max = 0x7BF;
+    const unsigned short float11Max          = 0x7BF;
     const unsigned short float11MantissaMask = 0x3F;
     const unsigned short float11ExponentMask = 0x7C0;
-    const unsigned short float11BitMask = 0x7FF;
-    const unsigned int float11ExponentBias = 14;
+    const unsigned short float11BitMask      = 0x7FF;
+    const unsigned int float11ExponentBias   = 14;
 
     const unsigned int float32Maxfloat11 = 0x477E0000;
     const unsigned int float32Minfloat11 = 0x38800000;
 
     const unsigned int float32Bits = bitCast<unsigned int>(fp32);
-    const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
+    const bool float32Sign         = (float32Bits & float32SignMask) == float32SignMask;
 
     unsigned int float32Val = float32Bits & float32ValueMask;
 
     if ((float32Val & float32ExponentMask) == float32ExponentMask)
     {
         // INF or NAN
         if ((float32Val & float32MantissaMask) != 0)
         {
-            return float11ExponentMask | (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) & float11MantissaMask);
+            return float11ExponentMask |
+                   (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) &
+                    float11MantissaMask);
         }
         else if (float32Sign)
         {
             // -INF is clamped to 0 since float11 is positive only
             return 0;
         }
         else
         {
@@ -267,58 +272,62 @@ inline unsigned short float32ToFloat11(f
         return float11Max;
     }
     else
     {
         if (float32Val < float32Minfloat11)
         {
             // The number is too small to be represented as a normalized float11
             // Convert it to a denormalized value.
-            const unsigned int shift = (float32ExponentBias - float11ExponentBias) - (float32Val >> float32ExponentFirstBit);
-            float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
+            const unsigned int shift = (float32ExponentBias - float11ExponentBias) -
+                                       (float32Val >> float32ExponentFirstBit);
+            float32Val =
+                ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
         }
         else
         {
             // Rebias the exponent to represent the value as a normalized float11
             float32Val += 0xC8000000;
         }
 
         return ((float32Val + 0xFFFF + ((float32Val >> 17) & 1)) >> 17) & float11BitMask;
     }
 }
 
 inline unsigned short float32ToFloat10(float fp32)
 {
-    const unsigned int float32MantissaMask = 0x7FFFFF;
-    const unsigned int float32ExponentMask = 0x7F800000;
-    const unsigned int float32SignMask = 0x80000000;
-    const unsigned int float32ValueMask = ~float32SignMask;
+    const unsigned int float32MantissaMask     = 0x7FFFFF;
+    const unsigned int float32ExponentMask     = 0x7F800000;
+    const unsigned int float32SignMask         = 0x80000000;
+    const unsigned int float32ValueMask        = ~float32SignMask;
     const unsigned int float32ExponentFirstBit = 23;
-    const unsigned int float32ExponentBias = 127;
+    const unsigned int float32ExponentBias     = 127;
 
-    const unsigned short float10Max = 0x3DF;
+    const unsigned short float10Max          = 0x3DF;
     const unsigned short float10MantissaMask = 0x1F;
     const unsigned short float10ExponentMask = 0x3E0;
-    const unsigned short float10BitMask = 0x3FF;
-    const unsigned int float10ExponentBias = 14;
+    const unsigned short float10BitMask      = 0x3FF;
+    const unsigned int float10ExponentBias   = 14;
 
     const unsigned int float32Maxfloat10 = 0x477C0000;
     const unsigned int float32Minfloat10 = 0x38800000;
 
     const unsigned int float32Bits = bitCast<unsigned int>(fp32);
-    const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
+    const bool float32Sign         = (float32Bits & float32SignMask) == float32SignMask;
 
     unsigned int float32Val = float32Bits & float32ValueMask;
 
     if ((float32Val & float32ExponentMask) == float32ExponentMask)
     {
         // INF or NAN
         if ((float32Val & float32MantissaMask) != 0)
         {
-            return float10ExponentMask | (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) & float10MantissaMask);
+            return float10ExponentMask |
+                   (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) &
+                    float10MantissaMask);
         }
         else if (float32Sign)
         {
             // -INF is clamped to 0 since float11 is positive only
             return 0;
         }
         else
         {
@@ -336,18 +345,20 @@ inline unsigned short float32ToFloat10(f
         return float10Max;
     }
     else
     {
         if (float32Val < float32Minfloat10)
         {
             // The number is too small to be represented as a normalized float11
             // Convert it to a denormalized value.
-            const unsigned int shift = (float32ExponentBias - float10ExponentBias) - (float32Val >> float32ExponentFirstBit);
-            float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
+            const unsigned int shift = (float32ExponentBias - float10ExponentBias) -
+                                       (float32Val >> float32ExponentFirstBit);
+            float32Val =
+                ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
         }
         else
         {
             // Rebias the exponent to represent the value as a normalized float11
             float32Val += 0xC8000000;
         }
 
         return ((float32Val + 0x1FFFF + ((float32Val >> 18) & 1)) >> 18) & float10BitMask;
@@ -374,22 +385,21 @@ inline float float11ToFloat32(unsigned s
         {
             // The value is denormalized
             exponent = 1;
 
             do
             {
                 exponent--;
                 mantissa <<= 1;
-            }
-            while ((mantissa & 0x40) == 0);
+            } while ((mantissa & 0x40) == 0);
 
             mantissa = mantissa & 0x3F;
         }
-        else // The value is zero
+        else  // The value is zero
         {
             exponent = static_cast<unsigned short>(-112);
         }
 
         return bitCast<float>(((exponent + 112) << 23) | (mantissa << 17));
     }
 }
 
@@ -413,30 +423,55 @@ inline float float10ToFloat32(unsigned s
         {
             // The value is denormalized
             exponent = 1;
 
             do
             {
                 exponent--;
                 mantissa <<= 1;
-            }
-            while ((mantissa & 0x20) == 0);
+            } while ((mantissa & 0x20) == 0);
 
             mantissa = mantissa & 0x1F;
         }
-        else // The value is zero
+        else  // The value is zero
         {
             exponent = static_cast<unsigned short>(-112);
         }
 
         return bitCast<float>(((exponent + 112) << 23) | (mantissa << 18));
     }
 }
 
+// Convers to and from float and 16.16 fixed point format.
+
+inline float FixedToFloat(uint32_t fixedInput)
+{
+    return static_cast<float>(fixedInput) / 65536.0f;
+}
+
+inline uint32_t FloatToFixed(float floatInput)
+{
+    static constexpr uint32_t kHighest = 32767 * 65536 + 65535;
+    static constexpr uint32_t kLowest  = static_cast<uint32_t>(-32768 * 65536 + 65535);
+
+    if (floatInput > 32767.65535)
+    {
+        return kHighest;
+    }
+    else if (floatInput < -32768.65535)
+    {
+        return kLowest;
+    }
+    else
+    {
+        return static_cast<uint32_t>(floatInput * 65536);
+    }
+}
+
 template <typename T>
 inline float normalizedToFloat(T input)
 {
     static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
 
     const float inverseMax = 1.0f / std::numeric_limits<T>::max();
     return input * inverseMax;
 }
@@ -558,22 +593,26 @@ inline float average(float a, float b)
 
 inline unsigned short averageHalfFloat(unsigned short a, unsigned short b)
 {
     return float32ToFloat16((float16ToFloat32(a) + float16ToFloat32(b)) * 0.5f);
 }
 
 inline unsigned int averageFloat11(unsigned int a, unsigned int b)
 {
-    return float32ToFloat11((float11ToFloat32(static_cast<unsigned short>(a)) + float11ToFloat32(static_cast<unsigned short>(b))) * 0.5f);
+    return float32ToFloat11((float11ToFloat32(static_cast<unsigned short>(a)) +
+                             float11ToFloat32(static_cast<unsigned short>(b))) *
+                            0.5f);
 }
 
 inline unsigned int averageFloat10(unsigned int a, unsigned int b)
 {
-    return float32ToFloat10((float10ToFloat32(static_cast<unsigned short>(a)) + float10ToFloat32(static_cast<unsigned short>(b))) * 0.5f);
+    return float32ToFloat10((float10ToFloat32(static_cast<unsigned short>(a)) +
+                             float10ToFloat32(static_cast<unsigned short>(b))) *
+                            0.5f);
 }
 
 template <typename T>
 class Range
 {
   public:
     Range() {}
     Range(T lo, T hi) : mLow(lo), mHigh(hi) {}
@@ -682,60 +721,60 @@ inline float Ldexp(float x, int exp)
 // Then, the results are packed into the returned 32-bit unsigned integer.
 // The first float value will be written to the least significant bits of the output;
 // the last float value will be written to the most significant bits.
 // The conversion of each value to fixed point is done as follows :
 // packSnorm2x16 : round(clamp(c, -1, +1) * 32767.0)
 inline uint32_t packSnorm2x16(float f1, float f2)
 {
     int16_t leastSignificantBits = static_cast<int16_t>(roundf(clamp(f1, -1.0f, 1.0f) * 32767.0f));
-    int16_t mostSignificantBits = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
+    int16_t mostSignificantBits  = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
     return static_cast<uint32_t>(mostSignificantBits) << 16 |
            (static_cast<uint32_t>(leastSignificantBits) & 0xFFFF);
 }
 
-// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
-// component is converted to a normalized floating-point value to generate the returned two float values.
-// The first float value will be extracted from the least significant bits of the input;
-// the last float value will be extracted from the most-significant bits.
-// The conversion for unpacked fixed-point value to floating point is done as follows:
-// unpackSnorm2x16 : clamp(f / 32767.0, -1, +1)
+// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
+// each component is converted to a normalized floating-point value to generate the returned two
+// float values. The first float value will be extracted from the least significant bits of the
+// input; the last float value will be extracted from the most-significant bits. The conversion for
+// unpacked fixed-point value to floating point is done as follows: unpackSnorm2x16 : clamp(f /
+// 32767.0, -1, +1)
 inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2)
 {
     int16_t leastSignificantBits = static_cast<int16_t>(u & 0xFFFF);
-    int16_t mostSignificantBits = static_cast<int16_t>(u >> 16);
+    int16_t mostSignificantBits  = static_cast<int16_t>(u >> 16);
     *f1 = clamp(static_cast<float>(leastSignificantBits) / 32767.0f, -1.0f, 1.0f);
     *f2 = clamp(static_cast<float>(mostSignificantBits) / 32767.0f, -1.0f, 1.0f);
 }
 
 // First, both normalized floating-point values are converted into 16-bit integer values.
 // Then, the results are packed into the returned 32-bit unsigned integer.
 // The first float value will be written to the least significant bits of the output;
 // the last float value will be written to the most significant bits.
 // The conversion of each value to fixed point is done as follows:
 // packUnorm2x16 : round(clamp(c, 0, +1) * 65535.0)
 inline uint32_t packUnorm2x16(float f1, float f2)
 {
     uint16_t leastSignificantBits = static_cast<uint16_t>(roundf(clamp(f1, 0.0f, 1.0f) * 65535.0f));
-    uint16_t mostSignificantBits = static_cast<uint16_t>(roundf(clamp(f2, 0.0f, 1.0f) * 65535.0f));
-    return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
+    uint16_t mostSignificantBits  = static_cast<uint16_t>(roundf(clamp(f2, 0.0f, 1.0f) * 65535.0f));
+    return static_cast<uint32_t>(mostSignificantBits) << 16 |
+           static_cast<uint32_t>(leastSignificantBits);
 }
 
-// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
-// component is converted to a normalized floating-point value to generate the returned two float values.
-// The first float value will be extracted from the least significant bits of the input;
-// the last float value will be extracted from the most-significant bits.
-// The conversion for unpacked fixed-point value to floating point is done as follows:
-// unpackUnorm2x16 : f / 65535.0
+// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
+// each component is converted to a normalized floating-point value to generate the returned two
+// float values. The first float value will be extracted from the least significant bits of the
+// input; the last float value will be extracted from the most-significant bits. The conversion for
+// unpacked fixed-point value to floating point is done as follows: unpackUnorm2x16 : f / 65535.0
 inline void unpackUnorm2x16(uint32_t u, float *f1, float *f2)
 {
     uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
-    uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
-    *f1 = static_cast<float>(leastSignificantBits) / 65535.0f;
-    *f2 = static_cast<float>(mostSignificantBits) / 65535.0f;
+    uint16_t mostSignificantBits  = static_cast<uint16_t>(u >> 16);
+    *f1                           = static_cast<float>(leastSignificantBits) / 65535.0f;
+    *f2                           = static_cast<float>(mostSignificantBits) / 65535.0f;
 }
 
 // Helper functions intended to be used only here.
 namespace priv
 {
 
 inline uint8_t ToPackedUnorm8(float f)
 {
@@ -816,29 +855,30 @@ inline void UnpackSnorm4x8(uint32_t u, f
 // Returns an unsigned integer obtained by converting the two floating-point values to the 16-bit
 // floating-point representation found in the OpenGL ES Specification, and then packing these
 // two 16-bit integers into a 32-bit unsigned integer.
 // f1: The 16 least-significant bits of the result;
 // f2: The 16 most-significant bits.
 inline uint32_t packHalf2x16(float f1, float f2)
 {
     uint16_t leastSignificantBits = static_cast<uint16_t>(float32ToFloat16(f1));
-    uint16_t mostSignificantBits = static_cast<uint16_t>(float32ToFloat16(f2));
-    return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
+    uint16_t mostSignificantBits  = static_cast<uint16_t>(float32ToFloat16(f2));
+    return static_cast<uint32_t>(mostSignificantBits) << 16 |
+           static_cast<uint32_t>(leastSignificantBits);
 }
 
-// Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of 16-bit values,
-// interpreting those values as 16-bit floating-point numbers according to the OpenGL ES Specification,
-// and converting them to 32-bit floating-point values.
-// The first float value is obtained from the 16 least-significant bits of u;
-// the second component is obtained from the 16 most-significant bits of u.
+// Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of
+// 16-bit values, interpreting those values as 16-bit floating-point numbers according to the OpenGL
+// ES Specification, and converting them to 32-bit floating-point values. The first float value is
+// obtained from the 16 least-significant bits of u; the second component is obtained from the 16
+// most-significant bits of u.
 inline void unpackHalf2x16(uint32_t u, float *f1, float *f2)
 {
     uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
-    uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
+    uint16_t mostSignificantBits  = static_cast<uint16_t>(u >> 16);
 
     *f1 = float16ToFloat32(leastSignificantBits);
     *f2 = float16ToFloat32(mostSignificantBits);
 }
 
 inline uint8_t sRGBToLinear(uint8_t srgbValue)
 {
     float value = srgbValue / 255.0f;
@@ -999,31 +1039,35 @@ int FindMSB(T bits)
     }
     else
     {
         return static_cast<int>(ScanReverse(bits));
     }
 }
 
 // Returns whether the argument is Not a Number.
-// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) - non-zero.
+// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
+// non-zero.
 inline bool isNaN(float f)
 {
     // Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
     // Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
-    return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && (bitCast<uint32_t>(f) & 0x7fffffu);
+    return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) &&
+           (bitCast<uint32_t>(f) & 0x7fffffu);
 }
 
 // Returns whether the argument is infinity.
-// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) - zero.
+// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
+// zero.
 inline bool isInf(float f)
 {
     // Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
     // Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
-    return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && !(bitCast<uint32_t>(f) & 0x7fffffu);
+    return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) &&
+           !(bitCast<uint32_t>(f) & 0x7fffffu);
 }
 
 namespace priv
 {
 template <unsigned int N, unsigned int R>
 struct iSquareRoot
 {
     static constexpr unsigned int solve()
@@ -1112,31 +1156,30 @@ angle::CheckedNumeric<T> CheckedRoundUp(
 inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
 {
     unsigned int divided = value / divisor;
     return (divided + ((value % divisor == 0) ? 0 : 1));
 }
 
 #if defined(_MSC_VER)
 
-#define ANGLE_ROTL(x,y) _rotl(x,y)
-#define ANGLE_ROTR16(x,y) _rotr16(x,y)
+#define ANGLE_ROTL(x, y) _rotl(x, y)
+#define ANGLE_ROTR16(x, y) _rotr16(x, y)
 
 #else
 
 inline uint32_t RotL(uint32_t x, int8_t r)
 {
     return (x << r) | (x >> (32 - r));
 }
 
 inline uint16_t RotR16(uint16_t x, int8_t r)
 {
     return (x >> r) | (x << (16 - r));
 }
 
 #define ANGLE_ROTL(x, y) ::rx::RotL(x, y)
 #define ANGLE_ROTR16(x, y) ::rx::RotR16(x, y)
 
-#endif // namespace rx
-
+#endif  // namespace rx
 }
 
-#endif   // COMMON_MATHUTIL_H_
+#endif  // COMMON_MATHUTIL_H_
--- a/gfx/angle/checkout/src/common/matrix_utils.h
+++ b/gfx/angle/checkout/src/common/matrix_utils.h
@@ -89,16 +89,38 @@ class Matrix
     {
         ASSERT(columns() == m.rows());
         Matrix<T> res  = (*this) * m;
         size_t numElts = res.elements().size();
         mElements.resize(numElts);
         memcpy(mElements.data(), res.data(), numElts * sizeof(float));
     }
 
+    bool operator==(const Matrix<T> &m) const
+    {
+        ASSERT(columns() == m.columns());
+        ASSERT(rows() == m.rows());
+        return mElements == m.elements();
+    }
+
+    bool operator!=(const Matrix<T> &m) const { return !(mElements == m.elements()); }
+
+    bool nearlyEqual(T epsilon, const Matrix<T> &m) const
+    {
+        ASSERT(columns() == m.columns());
+        ASSERT(rows() == m.rows());
+        const auto &otherElts = m.elements();
+        for (size_t i = 0; i < otherElts.size(); i++)
+        {
+            if ((mElements[i] - otherElts[i] > epsilon) && (otherElts[i] - mElements[i] > epsilon))
+                return false;
+        }
+        return true;
+    }
+
     unsigned int size() const
     {
         ASSERT(rows() == columns());
         return rows();
     }
 
     unsigned int rows() const { return mRows; }
 
--- a/gfx/angle/checkout/src/common/utilities.cpp
+++ b/gfx/angle/checkout/src/common/utilities.cpp
@@ -432,60 +432,16 @@ bool IsAtomicCounterType(GLenum type)
 }
 
 bool IsOpaqueType(GLenum type)
 {
     // ESSL 3.10 section 4.1.7 defines opaque types as: samplers, images and atomic counters.
     return IsImageType(type) || IsSamplerType(type) || IsAtomicCounterType(type);
 }
 
-GLenum SamplerTypeToTextureType(GLenum samplerType)
-{
-    switch (samplerType)
-    {
-      case GL_SAMPLER_2D:
-      case GL_INT_SAMPLER_2D:
-      case GL_UNSIGNED_INT_SAMPLER_2D:
-      case GL_SAMPLER_2D_SHADOW:
-        return GL_TEXTURE_2D;
-
-      case GL_SAMPLER_EXTERNAL_OES:
-          return GL_TEXTURE_EXTERNAL_OES;
-
-      case GL_SAMPLER_CUBE:
-      case GL_INT_SAMPLER_CUBE:
-      case GL_UNSIGNED_INT_SAMPLER_CUBE:
-      case GL_SAMPLER_CUBE_SHADOW:
-        return GL_TEXTURE_CUBE_MAP;
-
-      case GL_SAMPLER_2D_ARRAY:
-      case GL_INT_SAMPLER_2D_ARRAY:
-      case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
-      case GL_SAMPLER_2D_ARRAY_SHADOW:
-        return GL_TEXTURE_2D_ARRAY;
-
-      case GL_SAMPLER_3D:
-      case GL_INT_SAMPLER_3D:
-      case GL_UNSIGNED_INT_SAMPLER_3D:
-        return GL_TEXTURE_3D;
-
-      case GL_SAMPLER_2D_MULTISAMPLE:
-      case GL_INT_SAMPLER_2D_MULTISAMPLE:
-      case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
-          return GL_TEXTURE_2D_MULTISAMPLE;
-
-      case GL_SAMPLER_2D_RECT_ANGLE:
-          return GL_TEXTURE_RECTANGLE_ANGLE;
-
-      default:
-        UNREACHABLE();
-        return 0;
-    }
-}
-
 bool IsMatrixType(GLenum type)
 {
     return VariableRowCount(type) > 1;
 }
 
 GLenum TransposeMatrixType(GLenum type)
 {
     if (!IsMatrixType(type))
@@ -540,39 +496,16 @@ int AllocateFirstFreeBits(unsigned int *
         }
 
         mask <<= 1;
     }
 
     return -1;
 }
 
-static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1, "Unexpected GL cube map enum value.");
-static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2, "Unexpected GL cube map enum value.");
-static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3, "Unexpected GL cube map enum value.");
-static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4, "Unexpected GL cube map enum value.");
-static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5, "Unexpected GL cube map enum value.");
-
-bool IsCubeMapTextureTarget(GLenum target)
-{
-    return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
-}
-
-size_t CubeMapTextureTargetToLayerIndex(GLenum target)
-{
-    ASSERT(IsCubeMapTextureTarget(target));
-    return target - static_cast<size_t>(FirstCubeMapTextureTarget);
-}
-
-GLenum LayerIndexToCubeMapTextureTarget(size_t index)
-{
-    ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
-    return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
-}
-
 IndexRange ComputeIndexRange(GLenum indexType,
                              const GLvoid *indices,
                              size_t count,
                              bool primitiveRestartEnabled)
 {
     switch (indexType)
     {
         case GL_UNSIGNED_BYTE:
@@ -991,62 +924,16 @@ const char *GetGenericErrorMessage(EGLin
             return "Unknown error.";
     }
 }
 
 }  // namespace egl
 
 namespace egl_gl
 {
-GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget)
-{
-    ASSERT(egl::IsCubeMapTextureTarget(eglTarget));
-    return gl::LayerIndexToCubeMapTextureTarget(egl::CubeMapTextureTargetToLayerIndex(eglTarget));
-}
-
-GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget)
-{
-    switch (eglTarget)
-    {
-        case EGL_GL_TEXTURE_2D_KHR:
-            return GL_TEXTURE_2D;
-
-        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
-        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
-        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
-        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
-        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
-        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
-            return EGLCubeMapTargetToGLCubeMapTarget(eglTarget);
-
-        case EGL_GL_TEXTURE_3D_KHR:
-            return GL_TEXTURE_3D;
-
-        default:
-            UNREACHABLE();
-            return GL_NONE;
-    }
-}
-
-GLenum EGLTextureTargetToGLTextureTarget(EGLenum eglTarget)
-{
-    switch (eglTarget)
-    {
-        case EGL_TEXTURE_2D:
-            return GL_TEXTURE_2D;
-
-        case EGL_TEXTURE_RECTANGLE_ANGLE:
-            return GL_TEXTURE_RECTANGLE_ANGLE;
-
-        default:
-            UNREACHABLE();
-            return GL_NONE;
-    }
-}
-
 GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer)
 {
     return static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
 }
 }  // namespace egl_gl
 
 namespace gl_egl
 {
--- a/gfx/angle/checkout/src/common/utilities.h
+++ b/gfx/angle/checkout/src/common/utilities.h
@@ -33,33 +33,26 @@ size_t VariableComponentSize(GLenum type
 size_t VariableInternalSize(GLenum type);
 size_t VariableExternalSize(GLenum type);
 int VariableRowCount(GLenum type);
 int VariableColumnCount(GLenum type);
 bool IsSamplerType(GLenum type);
 bool IsImageType(GLenum type);
 bool IsAtomicCounterType(GLenum type);
 bool IsOpaqueType(GLenum type);
-GLenum SamplerTypeToTextureType(GLenum samplerType);
 bool IsMatrixType(GLenum type);
 GLenum TransposeMatrixType(GLenum type);
 int VariableRegisterCount(GLenum type);
 int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix);
 int MatrixComponentCount(GLenum type, bool isRowMajorMatrix);
 int VariableSortOrder(GLenum type);
 GLenum VariableBoolVectorType(GLenum type);
 
 int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
 
-static const GLenum FirstCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
-static const GLenum LastCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
-bool IsCubeMapTextureTarget(GLenum target);
-size_t CubeMapTextureTargetToLayerIndex(GLenum target);
-GLenum LayerIndexToCubeMapTextureTarget(size_t index);
-
 // Parse the base resource name and array indices. Returns the base name of the resource.
 // If the provided name doesn't index an array, the outSubscripts vector will be empty.
 // If the provided name indexes an array, the outSubscripts vector will contain indices with
 // outermost array indices in the back. If an array index is invalid, GL_INVALID_INDEX is added to
 // outSubscripts.
 std::string ParseResourceName(const std::string &name, std::vector<unsigned int> *outSubscripts);
 
 // Find the child field which matches 'fullName' == var.name + "." + field.name.
@@ -156,19 +149,16 @@ EGLenum LayerIndexToCubeMapTextureTarget
 bool IsTextureTarget(EGLenum target);
 bool IsRenderbufferTarget(EGLenum target);
 
 const char *GetGenericErrorMessage(EGLint error);
 }  // namespace egl
 
 namespace egl_gl
 {
-GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget);
-GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget);
-GLenum EGLTextureTargetToGLTextureTarget(EGLenum eglTarget);
 GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer);
 }
 
 namespace gl_egl
 {
 EGLenum GLComponentTypeToEGLColorComponentType(GLenum glComponentType);
 }  // namespace gl_egl
 
--- a/gfx/angle/checkout/src/compiler/preprocessor/Tokenizer.cpp
+++ b/gfx/angle/checkout/src/compiler/preprocessor/Tokenizer.cpp
@@ -932,16 +932,17 @@ typedef pp::SourceLocation YYLTYPE;
 #define YY_USER_INIT                   \
     do {                               \
         yyfileno = 0;                  \
         yylineno = 1;                  \
         yyextra->leadingSpace = false; \
         yyextra->lineStart = true;     \
     } while(0);
 
+#define YY_NO_INPUT
 #define YY_USER_ACTION                                              \
     do                                                              \
     {                                                               \
         pp::Input* input = &yyextra->input;                         \
         pp::Input::Location* scanLoc = &yyextra->scanLoc;           \
         while ((scanLoc->sIndex < input->count()) &&                \
                (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \
         {                                                           \
--- a/gfx/angle/checkout/src/compiler/preprocessor/Tokenizer.l
+++ b/gfx/angle/checkout/src/compiler/preprocessor/Tokenizer.l
@@ -59,16 +59,17 @@ typedef pp::SourceLocation YYLTYPE;
 #define YY_USER_INIT                   \
     do {                               \
         yyfileno = 0;                  \
         yylineno = 1;                  \
         yyextra->leadingSpace = false; \
         yyextra->lineStart = true;     \
     } while(0);
 
+#define YY_NO_INPUT
 #define YY_USER_ACTION                                              \
     do                                                              \
     {                                                               \
         pp::Input* input = &yyextra->input;                         \
         pp::Input::Location* scanLoc = &yyextra->scanLoc;           \
         while ((scanLoc->sIndex < input->count()) &&                \
                (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \
         {                                                           \
--- a/gfx/angle/checkout/src/compiler/preprocessor/numeric_lex.h
+++ b/gfx/angle/checkout/src/compiler/preprocessor/numeric_lex.h
@@ -43,30 +43,17 @@ bool numeric_lex_int(const std::string &
 
     stream >> (*value);
     return !stream.fail();
 }
 
 template <typename FloatType>
 bool numeric_lex_float(const std::string &str, FloatType *value)
 {
-// On 64-bit Intel Android, istringstream is broken.  Until this is fixed in
-// a newer NDK, don't use it.  Android doesn't have locale support, so this
-// doesn't have to force the C locale.
-// TODO(thakis): Remove this once this bug has been fixed in the NDK and
-// that NDK has been rolled into chromium.
-#if defined(ANGLE_PLATFORM_ANDROID) && __x86_64__
-    *value = strtod(str.c_str(), nullptr);
-    return errno != ERANGE;
-#else
-    std::istringstream stream(str);
-    // Force "C" locale so that decimal character is always '.', and
-    // not dependent on the current locale.
-    stream.imbue(std::locale::classic());
-
-    stream >> (*value);
-    return !stream.fail() && std::isfinite(*value);
-#endif
+    // Some platforms have issues with the usage of std::locale and std::stringstream and cause
+    // crashes. Usage of strtod appears to be safe.
+    *value = static_cast<FloatType>(strtod(str.c_str(), nullptr));
+    return errno != ERANGE && std::isfinite(*value);
 }
 
 }  // namespace pp.
 
 #endif  // COMPILER_PREPROCESSOR_NUMERICLEX_H_
--- a/gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.cpp
@@ -4,18 +4,18 @@
 // found in the LICENSE file.
 //
 
 // Analysis of the AST needed for HLSL generation
 
 #include "compiler/translator/ASTMetadataHLSL.h"
 
 #include "compiler/translator/CallDAG.h"
-#include "compiler/translator/IntermTraverse.h"
 #include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
 
 namespace sh
 {
 
 namespace
 {
 
 // Class used to traverse the AST of a function definition, checking if the
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/AddAndTrueToLoopCondition.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/AddAndTrueToLoopCondition.h"
-
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-// An AST traverser that rewrites for and while loops by replacing "condition" with
-// "condition && true" to work around condition bug on Intel Mac.
-class AddAndTrueToLoopConditionTraverser : public TIntermTraverser
-{
-  public:
-    AddAndTrueToLoopConditionTraverser() : TIntermTraverser(true, false, false) {}
-
-    bool visitLoop(Visit, TIntermLoop *loop) override
-    {
-        // do-while loop doesn't have this bug.
-        if (loop->getType() != ELoopFor && loop->getType() != ELoopWhile)
-        {
-            return true;
-        }
-
-        // For loop may not have a condition.
-        if (loop->getCondition() == nullptr)
-        {
-            return true;
-        }
-
-        // Constant true.
-        TIntermTyped *trueValue = CreateBoolNode(true);
-
-        // CONDITION && true.
-        TIntermBinary *andOp = new TIntermBinary(EOpLogicalAnd, loop->getCondition(), trueValue);
-        loop->setCondition(andOp);
-
-        return true;
-    }
-};
-
-}  // anonymous namespace
-
-void AddAndTrueToLoopCondition(TIntermNode *root)
-{
-    AddAndTrueToLoopConditionTraverser traverser;
-    root->traverse(&traverser);
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/AddAndTrueToLoopCondition.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Rewrite condition in for and while loops to work around driver bug on Intel Mac.
-
-#ifndef COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
-#define COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
-
-class TIntermNode;
-namespace sh
-{
-
-void AddAndTrueToLoopCondition(TIntermNode *root);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/AddDefaultReturnStatements.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// AddDefaultReturnStatements.cpp: Add default return statements to functions that do not end in a
-//                                 return.
-//
-
-#include "compiler/translator/AddDefaultReturnStatements.h"
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/util.h"
-
-namespace sh
-{
-
-namespace
-{
-
-bool NeedsReturnStatement(TIntermFunctionDefinition *node, TType *returnType)
-{
-    *returnType = node->getFunctionPrototype()->getType();
-    if (returnType->getBasicType() == EbtVoid)
-    {
-        return false;
-    }
-
-    TIntermBlock *bodyNode    = node->getBody();
-    TIntermBranch *returnNode = bodyNode->getSequence()->back()->getAsBranchNode();
-    if (returnNode != nullptr && returnNode->getFlowOp() == EOpReturn)
-    {
-        return false;
-    }
-
-    return true;
-}
-
-}  // anonymous namespace
-
-void AddDefaultReturnStatements(TIntermBlock *root)
-{
-    TType returnType;
-    for (TIntermNode *node : *root->getSequence())
-    {
-        TIntermFunctionDefinition *definition = node->getAsFunctionDefinition();
-        if (definition != nullptr && NeedsReturnStatement(definition, &returnType))
-        {
-            TIntermBranch *branch = new TIntermBranch(EOpReturn, CreateZeroNode(returnType));
-
-            TIntermBlock *bodyNode = definition->getBody();
-            bodyNode->getSequence()->push_back(branch);
-        }
-    }
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/AddDefaultReturnStatements.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// AddDefaultReturnStatements.h: Add default return statements to functions that do not end in a
-//                               return.
-//
-
-#ifndef COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
-#define COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
-
-class TIntermBlock;
-
-namespace sh
-{
-
-void AddDefaultReturnStatements(TIntermBlock *root);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
+++ /dev/null
@@ -1,244 +0,0 @@
-//
-// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// The ArrayReturnValueToOutParameter function changes return values of an array type to out
-// parameters in function definitions, prototypes, and call sites.
-
-#include "compiler/translator/ArrayReturnValueToOutParameter.h"
-
-#include <map>
-
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/StaticType.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-namespace
-{
-
-constexpr const ImmutableString kReturnValueVariableName("angle_return");
-
-void CopyAggregateChildren(TIntermAggregateBase *from, TIntermAggregateBase *to)
-{
-    const TIntermSequence *fromSequence = from->getSequence();
-    for (size_t ii = 0; ii < fromSequence->size(); ++ii)
-    {
-        to->getSequence()->push_back(fromSequence->at(ii));
-    }
-}
-
-class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser
-{
-  public:
-    static void apply(TIntermNode *root, TSymbolTable *symbolTable);
-
-  private:
-    ArrayReturnValueToOutParameterTraverser(TSymbolTable *symbolTable);
-
-    bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
-    bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
-    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
-    bool visitBranch(Visit visit, TIntermBranch *node) override;
-    bool visitBinary(Visit visit, TIntermBinary *node) override;
-
-    TIntermAggregate *createReplacementCall(TIntermAggregate *originalCall,
-                                            TIntermTyped *returnValueTarget);
-
-    // Set when traversal is inside a function with array return value.
-    TIntermFunctionDefinition *mFunctionWithArrayReturnValue;
-
-    struct ChangedFunction
-    {
-        const TVariable *returnValueVariable;
-        const TFunction *func;
-    };
-
-    // Map from function symbol ids to the changed function.
-    std::map<int, ChangedFunction> mChangedFunctions;
-};
-
-TIntermAggregate *ArrayReturnValueToOutParameterTraverser::createReplacementCall(
-    TIntermAggregate *originalCall,
-    TIntermTyped *returnValueTarget)
-{
-    TIntermSequence *replacementArguments = new TIntermSequence();
-    TIntermSequence *originalArguments    = originalCall->getSequence();
-    for (auto &arg : *originalArguments)
-    {
-        replacementArguments->push_back(arg);
-    }
-    replacementArguments->push_back(returnValueTarget);
-    ASSERT(originalCall->getFunction());
-    const TSymbolUniqueId &originalId = originalCall->getFunction()->uniqueId();
-    TIntermAggregate *replacementCall = TIntermAggregate::CreateFunctionCall(
-        *mChangedFunctions[originalId.get()].func, replacementArguments);
-    replacementCall->setLine(originalCall->getLine());
-    return replacementCall;
-}
-
-void ArrayReturnValueToOutParameterTraverser::apply(TIntermNode *root, TSymbolTable *symbolTable)
-{
-    ArrayReturnValueToOutParameterTraverser arrayReturnValueToOutParam(symbolTable);
-    root->traverse(&arrayReturnValueToOutParam);
-    arrayReturnValueToOutParam.updateTree();
-}
-
-ArrayReturnValueToOutParameterTraverser::ArrayReturnValueToOutParameterTraverser(
-    TSymbolTable *symbolTable)
-    : TIntermTraverser(true, false, true, symbolTable), mFunctionWithArrayReturnValue(nullptr)
-{
-}
-
-bool ArrayReturnValueToOutParameterTraverser::visitFunctionDefinition(
-    Visit visit,
-    TIntermFunctionDefinition *node)
-{
-    if (node->getFunctionPrototype()->isArray() && visit == PreVisit)
-    {
-        // Replacing the function header is done on visitFunctionPrototype().
-        mFunctionWithArrayReturnValue = node;
-    }
-    if (visit == PostVisit)
-    {
-        mFunctionWithArrayReturnValue = nullptr;
-    }
-    return true;
-}
-
-bool ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(Visit visit,
-                                                                     TIntermFunctionPrototype *node)
-{
-    if (visit == PreVisit && node->isArray())
-    {
-        // Replace the whole prototype node with another node that has the out parameter
-        // added. Also set the function to return void.
-        const TSymbolUniqueId &functionId = node->getFunction()->uniqueId();
-        if (mChangedFunctions.find(functionId.get()) == mChangedFunctions.end())
-        {
-            TType *returnValueVariableType = new TType(node->getType());
-            returnValueVariableType->setQualifier(EvqOut);
-            ChangedFunction changedFunction;
-            changedFunction.returnValueVariable =
-                new TVariable(mSymbolTable, kReturnValueVariableName, returnValueVariableType,
-                              SymbolType::AngleInternal);
-            TFunction *func = new TFunction(mSymbolTable, node->getFunction()->name(),
-                                            node->getFunction()->symbolType(),
-                                            StaticType::GetBasic<EbtVoid>(), false);
-            for (size_t i = 0; i < node->getFunction()->getParamCount(); ++i)
-            {
-                func->addParameter(node->getFunction()->getParam(i));
-            }
-            func->addParameter(TConstParameter(
-                kReturnValueVariableName, static_cast<const TType *>(returnValueVariableType)));
-            changedFunction.func                = func;
-            mChangedFunctions[functionId.get()] = changedFunction;
-        }
-        TIntermFunctionPrototype *replacement =
-            new TIntermFunctionPrototype(mChangedFunctions[functionId.get()].func);
-        CopyAggregateChildren(node, replacement);
-        replacement->getSequence()->push_back(
-            new TIntermSymbol(mChangedFunctions[functionId.get()].returnValueVariable));
-        replacement->setLine(node->getLine());
-
-        queueReplacement(replacement, OriginalNode::IS_DROPPED);
-    }
-    return false;
-}
-
-bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
-{
-    ASSERT(!node->isArray() || node->getOp() != EOpCallInternalRawFunction);
-    if (visit == PreVisit && node->isArray() && node->getOp() == EOpCallFunctionInAST)
-    {
-        // Handle call sites where the returned array is not assigned.
-        // Examples where f() is a function returning an array:
-        // 1. f();
-        // 2. another_array == f();
-        // 3. another_function(f());
-        // 4. return f();
-        // Cases 2 to 4 are already converted to simpler cases by
-        // SeparateExpressionsReturningArrays, so we only need to worry about the case where a
-        // function call returning an array forms an expression by itself.
-        TIntermBlock *parentBlock = getParentNode()->getAsBlock();
-        if (parentBlock)
-        {
-            // replace
-            //   f();
-            // with
-            //   type s0[size]; f(s0);
-            TIntermSequence replacements;
-
-            // type s0[size];
-            TIntermDeclaration *returnValueDeclaration = nullptr;
-            TVariable *returnValue = DeclareTempVariable(mSymbolTable, new TType(node->getType()),
-                                                         EvqTemporary, &returnValueDeclaration);
-            replacements.push_back(returnValueDeclaration);
-
-            // f(s0);
-            TIntermSymbol *returnValueSymbol = CreateTempSymbolNode(returnValue);
-            replacements.push_back(createReplacementCall(node, returnValueSymbol));
-            mMultiReplacements.push_back(
-                NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
-        }
-        return false;
-    }
-    return true;
-}
-
-bool ArrayReturnValueToOutParameterTraverser::visitBranch(Visit visit, TIntermBranch *node)
-{
-    if (mFunctionWithArrayReturnValue && node->getFlowOp() == EOpReturn)
-    {
-        // Instead of returning a value, assign to the out parameter and then return.
-        TIntermSequence replacements;
-
-        TIntermTyped *expression = node->getExpression();
-        ASSERT(expression != nullptr);
-        const TSymbolUniqueId &functionId =
-            mFunctionWithArrayReturnValue->getFunction()->uniqueId();
-        ASSERT(mChangedFunctions.find(functionId.get()) != mChangedFunctions.end());
-        TIntermSymbol *returnValueSymbol =
-            new TIntermSymbol(mChangedFunctions[functionId.get()].returnValueVariable);
-        TIntermBinary *replacementAssignment =
-            new TIntermBinary(EOpAssign, returnValueSymbol, expression);
-        replacementAssignment->setLine(expression->getLine());
-        replacements.push_back(replacementAssignment);
-
-        TIntermBranch *replacementBranch = new TIntermBranch(EOpReturn, nullptr);
-        replacementBranch->setLine(node->getLine());
-        replacements.push_back(replacementBranch);
-
-        mMultiReplacements.push_back(
-            NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, replacements));
-    }
-    return false;
-}
-
-bool ArrayReturnValueToOutParameterTraverser::visitBinary(Visit visit, TIntermBinary *node)
-{
-    if (node->getOp() == EOpAssign && node->getLeft()->isArray())
-    {
-        TIntermAggregate *rightAgg = node->getRight()->getAsAggregate();
-        ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpCallInternalRawFunction);
-        if (rightAgg != nullptr && rightAgg->getOp() == EOpCallFunctionInAST)
-        {
-            TIntermAggregate *replacementCall = createReplacementCall(rightAgg, node->getLeft());
-            queueReplacement(replacementCall, OriginalNode::IS_DROPPED);
-        }
-    }
-    return false;
-}
-
-}  // namespace
-
-void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable)
-{
-    ArrayReturnValueToOutParameterTraverser::apply(root, symbolTable);
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/ArrayReturnValueToOutParameter.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// The ArrayReturnValueToOutParameter function changes return values of an array type to out
-// parameters in function definitions, prototypes and call sites.
-
-#ifndef COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
-#define COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
-
-namespace sh
-{
-
-class TIntermNode;
-class TSymbolTable;
-
-void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
--- a/gfx/angle/checkout/src/compiler/translator/BaseTypes.h
+++ b/gfx/angle/checkout/src/compiler/translator/BaseTypes.h
@@ -52,28 +52,22 @@ inline const char *getPrecisionString(TP
 //
 enum TBasicType
 {
     EbtVoid,
     EbtFloat,
     EbtInt,
     EbtUInt,
     EbtBool,
-    EbtGVec4,              // non type: represents vec4, ivec4, and uvec4
-    EbtGenType,            // non type: represents float, vec2, vec3, and vec4
-    EbtGenIType,           // non type: represents int, ivec2, ivec3, and ivec4
-    EbtGenUType,           // non type: represents uint, uvec2, uvec3, and uvec4
-    EbtGenBType,           // non type: represents bool, bvec2, bvec3, and bvec4
-    EbtVec,                // non type: represents vec2, vec3, and vec4
-    EbtIVec,               // non type: represents ivec2, ivec3, and ivec4
-    EbtUVec,               // non type: represents uvec2, uvec3, and uvec4
-    EbtBVec,               // non type: represents bvec2, bvec3, and bvec4
+
+    EbtAtomicCounter,
     EbtYuvCscStandardEXT,  // Only valid if EXT_YUV_target exists.
+
     EbtGuardSamplerBegin,  // non type: see implementation of IsSampler()
-    EbtSampler2D,
+    EbtSampler2D = EbtGuardSamplerBegin,
     EbtSampler3D,
     EbtSamplerCube,
     EbtSampler2DArray,
     EbtSamplerExternalOES,       // Only valid if OES_EGL_image_external exists.
     EbtSamplerExternal2DY2YEXT,  // Only valid if GL_EXT_YUV_target exists.
     EbtSampler2DRect,            // Only valid if GL_ARB_texture_rectangle exists.
     EbtSampler2DMS,
     EbtISampler2D,
@@ -84,163 +78,67 @@ enum TBasicType
     EbtUSampler2D,
     EbtUSampler3D,
     EbtUSamplerCube,
     EbtUSampler2DArray,
     EbtUSampler2DMS,
     EbtSampler2DShadow,
     EbtSamplerCubeShadow,
     EbtSampler2DArrayShadow,
-    EbtGuardSamplerEnd,  // non type: see implementation of IsSampler()
-    EbtGSampler2D,       // non type: represents sampler2D, isampler2D, and usampler2D
-    EbtGSampler3D,       // non type: represents sampler3D, isampler3D, and usampler3D
-    EbtGSamplerCube,     // non type: represents samplerCube, isamplerCube, and usamplerCube
-    EbtGSampler2DArray,  // non type: represents sampler2DArray, isampler2DArray, and
-                         // usampler2DArray
-    EbtGSampler2DMS,     // non type: represents sampler2DMS, isampler2DMS, and usampler2DMS
+    EbtGuardSamplerEnd = EbtSampler2DArrayShadow,  // non type: see implementation of IsSampler()
 
     // images
     EbtGuardImageBegin,
-    EbtImage2D,
+    EbtImage2D = EbtGuardImageBegin,
     EbtIImage2D,
     EbtUImage2D,
     EbtImage3D,
     EbtIImage3D,
     EbtUImage3D,
     EbtImage2DArray,
     EbtIImage2DArray,
     EbtUImage2DArray,
     EbtImageCube,
     EbtIImageCube,
     EbtUImageCube,
-    EbtGuardImageEnd,
+    EbtGuardImageEnd = EbtUImageCube,
 
-    EbtGuardGImageBegin,
-    EbtGImage2D,       // non type: represents image2D, uimage2D, iimage2D
-    EbtGImage3D,       // non type: represents image3D, uimage3D, iimage3D
-    EbtGImage2DArray,  // non type: represents image2DArray, uimage2DArray, iimage2DArray
-    EbtGImageCube,     // non type: represents imageCube, uimageCube, iimageCube
-    EbtGuardGImageEnd,
+    EbtLastSimpleType = EbtGuardImageEnd,
 
     EbtStruct,
     EbtInterfaceBlock,
-    EbtAddress,  // should be deprecated??
-
-    EbtAtomicCounter,
 
     // end of list
-    EbtLast
+    EbtLast = EbtInterfaceBlock
 };
 
-constexpr const char *GetBasicMangledName(TBasicType t)
+constexpr char GetBasicMangledName(TBasicType t)
 {
-    switch (t)
+    if (t > EbtLastSimpleType)
     {
-        case EbtFloat:
-            return "f";
-        case EbtInt:
-            return "i";
-        case EbtUInt:
-            return "u";
-        case EbtBool:
-            return "b";
-        case EbtYuvCscStandardEXT:
-            return "ycs";
-        case EbtSampler2D:
-            return "s2";
-        case EbtSampler3D:
-            return "s3";
-        case EbtSamplerCube:
-            return "sC";
-        case EbtSampler2DArray:
-            return "s2a";
-        case EbtSamplerExternalOES:
-            return "sext";
-        case EbtSamplerExternal2DY2YEXT:
-            return "sext2y2y";
-        case EbtSampler2DRect:
-            return "s2r";
-        case EbtSampler2DMS:
-            return "s2ms";
-        case EbtISampler2D:
-            return "is2";
-        case EbtISampler3D:
-            return "is3";
-        case EbtISamplerCube:
-            return "isC";
-        case EbtISampler2DArray:
-            return "is2a";
-        case EbtISampler2DMS:
-            return "is2ms";
-        case EbtUSampler2D:
-            return "us2";
-        case EbtUSampler3D:
-            return "us3";
-        case EbtUSamplerCube:
-            return "usC";
-        case EbtUSampler2DArray:
-            return "us2a";
-        case EbtUSampler2DMS:
-            return "us2ms";
-        case EbtSampler2DShadow:
-            return "s2s";
-        case EbtSamplerCubeShadow:
-            return "sCs";
-        case EbtSampler2DArrayShadow:
-            return "s2as";
-        case EbtImage2D:
-            return "im2";
-        case EbtIImage2D:
-            return "iim2";
-        case EbtUImage2D:
-            return "uim2";
-        case EbtImage3D:
-            return "im3";
-        case EbtIImage3D:
-            return "iim3";
-        case EbtUImage3D:
-            return "uim3";
-        case EbtImage2DArray:
-            return "im2a";
-        case EbtIImage2DArray:
-            return "iim2a";
-        case EbtUImage2DArray:
-            return "uim2a";
-        case EbtImageCube:
-            return "imc";
-        case EbtIImageCube:
-            return "iimc";
-        case EbtUImageCube:
-            return "uimc";
-        case EbtAtomicCounter:
-            return "ac";
-        case EbtStruct:
-        case EbtInterfaceBlock:
-            return nullptr;
-        default:
-            // EbtVoid, EbtAddress and non types
-            return "";
+        return '{';
     }
+    static_assert(EbtLastSimpleType < 52, "We only use alphabetic characters for mangled names");
+    if (t < 26)
+    {
+        return static_cast<char>('A' + t);
+    }
+    return static_cast<char>('a' - 26 + t);
 }
 
 const char *getBasicString(TBasicType t);
 
 inline bool IsSampler(TBasicType type)
 {
-    return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd;
+    return type >= EbtGuardSamplerBegin && type <= EbtGuardSamplerEnd;
 }
 
 inline bool IsImage(TBasicType type)
 {
-    return type > EbtGuardImageBegin && type < EbtGuardImageEnd;
-}
-
-inline bool IsGImage(TBasicType type)
-{
-    return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd;
+    return type >= EbtGuardImageBegin && type <= EbtGuardImageEnd;
 }
 
 inline bool IsAtomicCounter(TBasicType type)
 {
     return type == EbtAtomicCounter;
 }
 
 inline bool IsOpaqueType(TBasicType type)
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend
-//      may record a variable as aliasing another. Sometimes the alias information gets garbled
-//      so we work around this issue by breaking the aliasing chain in inner loops.
-
-#include "BreakVariableAliasingInInnerLoops.h"
-
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-
-// A HLSL compiler developer gave us more details on the root cause and the workaround needed:
-//     The root problem is that if the HLSL compiler is applying aliasing information even on
-//     incomplete simulations (in this case, a single pass). The bug is triggered by an assignment
-//     that comes from a series of assignments, possibly with swizzled or ternary operators with
-//     known conditionals, where the source is before the loop.
-//     So, a workaround is to add a +0 term to variables the first time they are assigned to in
-//     an inner loop (if they are declared in an outside scope, otherwise there is no need).
-//     This will break the aliasing chain.
-
-// For simplicity here we add a +0 to any assignment that is in at least two nested loops. Because
-// the bug only shows up with swizzles, and ternary assignment, whole array or whole structure
-// assignment don't need a workaround.
-
-namespace sh
-{
-
-namespace
-{
-
-class AliasingBreaker : public TIntermTraverser
-{
-  public:
-    AliasingBreaker() : TIntermTraverser(true, false, true) {}
-
-  protected:
-    bool visitBinary(Visit visit, TIntermBinary *binary)
-    {
-        if (visit != PreVisit)
-        {
-            return false;
-        }
-
-        if (mLoopLevel < 2 || !binary->isAssignment())
-        {
-            return true;
-        }
-
-        TIntermTyped *B = binary->getRight();
-        TType type      = B->getType();
-
-        if (!type.isScalar() && !type.isVector() && !type.isMatrix())
-        {
-            return true;
-        }
-
-        if (type.isArray() || IsSampler(type.getBasicType()))
-        {
-            return true;
-        }
-
-        // We have a scalar / vector / matrix assignment with loop depth 2.
-        // Transform it from
-        //    A = B
-        // to
-        //    A = (B + typeof<B>(0));
-
-        TIntermBinary *bPlusZero = new TIntermBinary(EOpAdd, B, CreateZeroNode(type));
-        bPlusZero->setLine(B->getLine());
-
-        binary->replaceChildNode(B, bPlusZero);
-
-        return true;
-    }
-
-    bool visitLoop(Visit visit, TIntermLoop *loop)
-    {
-        if (visit == PreVisit)
-        {
-            mLoopLevel++;
-        }
-        else
-        {
-            ASSERT(mLoopLevel > 0);
-            mLoopLevel--;
-        }
-
-        return true;
-    }
-
-  private:
-    int mLoopLevel = 0;
-};
-
-}  // anonymous namespace
-
-void BreakVariableAliasingInInnerLoops(TIntermNode *root)
-{
-    AliasingBreaker breaker;
-    root->traverse(&breaker);
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/BreakVariableAliasingInInnerLoops.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend
-//      may record a variable as aliasing another. Sometimes the alias information gets garbled
-//      so we work around this issue by breaking the aliasing chain in inner loops.
-
-#ifndef COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
-#define COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
-
-class TIntermNode;
-
-namespace sh
-{
-
-void BreakVariableAliasingInInnerLoops(TIntermNode *root);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
--- a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp
@@ -1,174 +1,77 @@
 //
 // Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 #include "compiler/translator/BuiltInFunctionEmulator.h"
 #include "angle_gl.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.h"
 #include "compiler/translator/StaticType.h"
+#include "compiler/translator/Symbol.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
 
 namespace sh
 {
 
 class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser
 {
   public:
     BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator &emulator)
         : TIntermTraverser(true, false, false), mEmulator(emulator)
     {
     }
 
     bool visitUnary(Visit visit, TIntermUnary *node) override
     {
-        if (visit == PreVisit)
+        if (node->getFunction())
         {
-            bool needToEmulate =
-                mEmulator.setFunctionCalled(node->getOp(), node->getOperand()->getType());
+            bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
             if (needToEmulate)
                 node->setUseEmulatedFunction();
         }
         return true;
     }
 
     bool visitAggregate(Visit visit, TIntermAggregate *node) override
     {
-        if (visit == PreVisit)
+        // Here we handle all the built-in functions mapped to ops, not just the ones that are
+        // currently identified as problematic.
+        if (node->isConstructor() || node->isFunctionCall())
         {
-            // Here we handle all the built-in functions mapped to ops, not just the ones that are
-            // currently identified as problematic.
-            if (node->isConstructor() || node->isFunctionCall())
-            {
-                return true;
-            }
-            const TIntermSequence &sequence = *(node->getSequence());
-            bool needToEmulate              = false;
-            // Right now we only handle built-in functions with two to four parameters.
-            if (sequence.size() == 2)
-            {
-                TIntermTyped *param1 = sequence[0]->getAsTyped();
-                TIntermTyped *param2 = sequence[1]->getAsTyped();
-                if (!param1 || !param2)
-                    return true;
-                needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
-                                                            param2->getType());
-            }
-            else if (sequence.size() == 3)
-            {
-                TIntermTyped *param1 = sequence[0]->getAsTyped();
-                TIntermTyped *param2 = sequence[1]->getAsTyped();
-                TIntermTyped *param3 = sequence[2]->getAsTyped();
-                if (!param1 || !param2 || !param3)
-                    return true;
-                needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
-                                                            param2->getType(), param3->getType());
-            }
-            else if (sequence.size() == 4)
-            {
-                TIntermTyped *param1 = sequence[0]->getAsTyped();
-                TIntermTyped *param2 = sequence[1]->getAsTyped();
-                TIntermTyped *param3 = sequence[2]->getAsTyped();
-                TIntermTyped *param4 = sequence[3]->getAsTyped();
-                if (!param1 || !param2 || !param3 || !param4)
-                    return true;
-                needToEmulate =
-                    mEmulator.setFunctionCalled(node->getOp(), param1->getType(), param2->getType(),
-                                                param3->getType(), param4->getType());
-            }
-            else
-            {
-                return true;
-            }
-
-            if (needToEmulate)
-                node->setUseEmulatedFunction();
+            return true;
         }
+        bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
+        if (needToEmulate)
+            node->setUseEmulatedFunction();
         return true;
     }
 
   private:
     BuiltInFunctionEmulator &mEmulator;
 };
 
 BuiltInFunctionEmulator::BuiltInFunctionEmulator()
 {
 }
 
-FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
-                                                        const TType *param,
-                                                        const char *emulatedFunctionDefinition)
-{
-    FunctionId id(op, param);
-    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
-    return id;
-}
-
-FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
-                                                        const TType *param1,
-                                                        const TType *param2,
-                                                        const char *emulatedFunctionDefinition)
+void BuiltInFunctionEmulator::addEmulatedFunction(const TSymbolUniqueId &uniqueId,
+                                                  const char *emulatedFunctionDefinition)
 {
-    FunctionId id(op, param1, param2);
-    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
-    return id;
-}
-
-FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
-    const FunctionId &dependency,
-    TOperator op,
-    const TType *param1,
-    const TType *param2,
-    const char *emulatedFunctionDefinition)
-{
-    FunctionId id(op, param1, param2);
-    mEmulatedFunctions[id]    = std::string(emulatedFunctionDefinition);
-    mFunctionDependencies[id] = dependency;
-    return id;
+    mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition);
 }
 
-FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
-                                                        const TType *param1,
-                                                        const TType *param2,
-                                                        const TType *param3,
-                                                        const char *emulatedFunctionDefinition)
-{
-    FunctionId id(op, param1, param2, param3);
-    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
-    return id;
-}
-
-FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
-                                                        const TType *param1,
-                                                        const TType *param2,
-                                                        const TType *param3,
-                                                        const TType *param4,
-                                                        const char *emulatedFunctionDefinition)
-{
-    FunctionId id(op, param1, param2, param3, param4);
-    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
-    return id;
-}
-
-FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
-    const FunctionId &dependency,
-    TOperator op,
-    const TType *param1,
-    const TType *param2,
-    const TType *param3,
-    const TType *param4,
+void BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
+    const TSymbolUniqueId &dependency,
+    const TSymbolUniqueId &uniqueId,
     const char *emulatedFunctionDefinition)
 {
-    FunctionId id(op, param1, param2, param3, param4);
-    mEmulatedFunctions[id]    = std::string(emulatedFunctionDefinition);
-    mFunctionDependencies[id] = dependency;
-    return id;
+    mEmulatedFunctions[uniqueId.get()]    = std::string(emulatedFunctionDefinition);
+    mFunctionDependencies[uniqueId.get()] = dependency.get();
 }
 
 bool BuiltInFunctionEmulator::isOutputEmpty() const
 {
     return (mFunctions.size() == 0);
 }
 
 void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const
@@ -177,86 +80,61 @@ void BuiltInFunctionEmulator::outputEmul
     {
         const char *body = findEmulatedFunction(function);
         ASSERT(body);
         out << body;
         out << "\n\n";
     }
 }
 
-bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, const TType &param)
-{
-    return setFunctionCalled(FunctionId(op, &param));
-}
-
-bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
-                                                const TType &param1,
-                                                const TType &param2)
-{
-    return setFunctionCalled(FunctionId(op, &param1, &param2));
-}
-
-bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
-                                                const TType &param1,
-                                                const TType &param2,
-                                                const TType &param3)
-{
-    return setFunctionCalled(FunctionId(op, &param1, &param2, &param3));
-}
-
-bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
-                                                const TType &param1,
-                                                const TType &param2,
-                                                const TType &param3,
-                                                const TType &param4)
-{
-    return setFunctionCalled(FunctionId(op, &param1, &param2, &param3, &param4));
-}
-
-const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &functionId) const
+const char *BuiltInFunctionEmulator::findEmulatedFunction(int uniqueId) const
 {
     for (const auto &queryFunction : mQueryFunctions)
     {
-        const char *result = queryFunction(functionId);
+        const char *result = queryFunction(uniqueId);
         if (result)
         {
             return result;
         }
     }
 
-    const auto &result = mEmulatedFunctions.find(functionId);
+    const auto &result = mEmulatedFunctions.find(uniqueId);
     if (result != mEmulatedFunctions.end())
     {
         return result->second.c_str();
     }
 
     return nullptr;
 }
 
-bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId)
+bool BuiltInFunctionEmulator::setFunctionCalled(const TFunction *function)
 {
-    if (!findEmulatedFunction(functionId))
+    ASSERT(function != nullptr);
+    return setFunctionCalled(function->uniqueId().get());
+}
+
+bool BuiltInFunctionEmulator::setFunctionCalled(int uniqueId)
+{
+    if (!findEmulatedFunction(uniqueId))
     {
         return false;
     }
 
     for (size_t i = 0; i < mFunctions.size(); ++i)
     {
-        if (mFunctions[i] == functionId)
+        if (mFunctions[i] == uniqueId)
             return true;
     }
     // If the function depends on another, mark the dependency as called.
-    auto dependency = mFunctionDependencies.find(functionId);
+    auto dependency = mFunctionDependencies.find(uniqueId);
     if (dependency != mFunctionDependencies.end())
     {
         setFunctionCalled((*dependency).second);
     }
-    // Copy the functionId if it needs to be stored, to make sure that the TType pointers inside
-    // remain valid and constant.
-    mFunctions.push_back(functionId.getCopy());
+    mFunctions.push_back(uniqueId);
     return true;
 }
 
 void BuiltInFunctionEmulator::markBuiltInFunctionsForEmulation(TIntermNode *root)
 {
     ASSERT(root);
 
     if (mEmulatedFunctions.empty() && mQueryFunctions.empty())
@@ -279,81 +157,9 @@ void BuiltInFunctionEmulator::addFunctio
 
 // static
 void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name)
 {
     ASSERT(name[strlen(name) - 1] != '(');
     out << name << "_emu";
 }
 
-FunctionId::FunctionId()
-    : mOp(EOpNull),
-      mParam1(StaticType::GetBasic<EbtVoid>()),
-      mParam2(StaticType::GetBasic<EbtVoid>()),
-      mParam3(StaticType::GetBasic<EbtVoid>()),
-      mParam4(StaticType::GetBasic<EbtVoid>())
-{
-}
-
-FunctionId::FunctionId(TOperator op, const TType *param)
-    : mOp(op),
-      mParam1(param),
-      mParam2(StaticType::GetBasic<EbtVoid>()),
-      mParam3(StaticType::GetBasic<EbtVoid>()),
-      mParam4(StaticType::GetBasic<EbtVoid>())
-{
-}
-
-FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2)
-    : mOp(op),
-      mParam1(param1),
-      mParam2(param2),
-      mParam3(StaticType::GetBasic<EbtVoid>()),
-      mParam4(StaticType::GetBasic<EbtVoid>())
-{
-}
-
-FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3)
-    : mOp(op),
-      mParam1(param1),
-      mParam2(param2),
-      mParam3(param3),
-      mParam4(StaticType::GetBasic<EbtVoid>())
-{
-}
-
-FunctionId::FunctionId(TOperator op,
-                       const TType *param1,
-                       const TType *param2,
-                       const TType *param3,
-                       const TType *param4)
-    : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(param4)
-{
-}
-
-bool FunctionId::operator==(const FunctionId &other) const
-{
-    return (mOp == other.mOp && *mParam1 == *other.mParam1 && *mParam2 == *other.mParam2 &&
-            *mParam3 == *other.mParam3 && *mParam4 == *other.mParam4);
-}
-
-bool FunctionId::operator<(const FunctionId &other) const
-{
-    if (mOp != other.mOp)
-        return mOp < other.mOp;
-    if (*mParam1 != *other.mParam1)
-        return *mParam1 < *other.mParam1;
-    if (*mParam2 != *other.mParam2)
-        return *mParam2 < *other.mParam2;
-    if (*mParam3 != *other.mParam3)
-        return *mParam3 < *other.mParam3;
-    if (*mParam4 != *other.mParam4)
-        return *mParam4 < *other.mParam4;
-    return false;  // all fields are equal
-}
-
-FunctionId FunctionId::getCopy() const
-{
-    return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3),
-                      new TType(*mParam4));
-}
-
 }  // namespace sh
--- a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.h
+++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.h
@@ -3,92 +3,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 #ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
 #define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
 
 #include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/ParamType.h"
 
 namespace sh
 {
 
-struct MiniFunctionId
-{
-    constexpr MiniFunctionId(TOperator op         = EOpNull,
-                             ParamType paramType1 = ParamType::Void,
-                             ParamType paramType2 = ParamType::Void,
-                             ParamType paramType3 = ParamType::Void,
-                             ParamType paramType4 = ParamType::Void)
-        : op(op),
-          paramType1(paramType1),
-          paramType2(paramType2),
-          paramType3(paramType3),
-          paramType4(paramType4)
-    {
-    }
-
-    TOperator op;
-    ParamType paramType1;
-    ParamType paramType2;
-    ParamType paramType3;
-    ParamType paramType4;
-};
-
-class FunctionId final
-{
-  public:
-    FunctionId();
-    FunctionId(TOperator op, const TType *param);
-    FunctionId(TOperator op, const TType *param1, const TType *param2);
-    FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3);
-    FunctionId(TOperator op,
-               const TType *param1,
-               const TType *param2,
-               const TType *param3,
-               const TType *param4);
+class TIntermNode;
+class TFunction;
+class TSymbolUniqueId;
 
-    FunctionId(const FunctionId &) = default;
-    FunctionId &operator=(const FunctionId &) = default;
-
-    bool operator==(const FunctionId &other) const;
-    bool operator<(const FunctionId &other) const;
-
-    FunctionId getCopy() const;
-
-  private:
-    friend bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId);
-    TOperator mOp;
-
-    // The memory that these TType objects use is freed by PoolAllocator. The
-    // BuiltInFunctionEmulator's lifetime can extend until after the memory pool is freed, but
-    // that's not an issue since this class never destructs these objects.
-    const TType *mParam1;
-    const TType *mParam2;
-    const TType *mParam3;
-    const TType *mParam4;
-};
-
-inline bool operator==(ParamType paramType, const TType *type)
-{
-    return SameParamType(paramType, type->getBasicType(), type->getNominalSize(),
-                         type->getSecondarySize());
-}
-
-inline bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId)
-{
-    return miniId.op == functionId.mOp && miniId.paramType1 == functionId.mParam1 &&
-           miniId.paramType2 == functionId.mParam2 && miniId.paramType3 == functionId.mParam3 &&
-           miniId.paramType4 == functionId.mParam4;
-}
-
-using BuiltinQueryFunc = const char *(const FunctionId &);
+using BuiltinQueryFunc = const char *(int);
 
 //
 // This class decides which built-in functions need to be replaced with the emulated ones. It can be
 // used to work around driver bugs or implement functions that are not natively implemented on a
 // specific platform.
 //
 class BuiltInFunctionEmulator
 {
@@ -103,81 +36,45 @@ class BuiltInFunctionEmulator
     static void WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name);
 
     bool isOutputEmpty() const;
 
     // Output function emulation definition. This should be before any other shader source.
     void outputEmulatedFunctions(TInfoSinkBase &out) const;
 
     // Add functions that need to be emulated.
-    FunctionId addEmulatedFunction(TOperator op,
-                                   const TType *param,
-                                   const char *emulatedFunctionDefinition);
-    FunctionId addEmulatedFunction(TOperator op,
-                                   const TType *param1,
-                                   const TType *param2,
-                                   const char *emulatedFunctionDefinition);
-    FunctionId addEmulatedFunction(TOperator op,
-                                   const TType *param1,
-                                   const TType *param2,
-                                   const TType *param3,
-                                   const char *emulatedFunctionDefinition);
-    FunctionId addEmulatedFunction(TOperator op,
-                                   const TType *param1,
-                                   const TType *param2,
-                                   const TType *param3,
-                                   const TType *param4,
-                                   const char *emulatedFunctionDefinition);
+    void addEmulatedFunction(const TSymbolUniqueId &uniqueId,
+                             const char *emulatedFunctionDefinition);
 
-    FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
-                                                 TOperator op,
-                                                 const TType *param1,
-                                                 const TType *param2,
-                                                 const char *emulatedFunctionDefinition);
-    FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
-                                                 TOperator op,
-                                                 const TType *param1,
-                                                 const TType *param2,
-                                                 const TType *param3,
-                                                 const TType *param4,
-                                                 const char *emulatedFunctionDefinition);
+    void addEmulatedFunctionWithDependency(const TSymbolUniqueId &dependency,
+                                           const TSymbolUniqueId &uniqueId,
+                                           const char *emulatedFunctionDefinition);
 
     void addFunctionMap(BuiltinQueryFunc queryFunc);
 
   private:
     class BuiltInFunctionEmulationMarker;
 
     // Records that a function is called by the shader and might need to be emulated. If the
     // function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function
     // call needs to be replaced with an emulated one.
-    bool setFunctionCalled(TOperator op, const TType &param);
-    bool setFunctionCalled(TOperator op, const TType &param1, const TType &param2);
-    bool setFunctionCalled(TOperator op,
-                           const TType &param1,
-                           const TType &param2,
-                           const TType &param3);
-    bool setFunctionCalled(TOperator op,
-                           const TType &param1,
-                           const TType &param2,
-                           const TType &param3,
-                           const TType &param4);
+    bool setFunctionCalled(const TFunction *function);
+    bool setFunctionCalled(int uniqueId);
 
-    bool setFunctionCalled(const FunctionId &functionId);
+    const char *findEmulatedFunction(int uniqueId) const;
 
-    const char *findEmulatedFunction(const FunctionId &functionId) const;
-
-    // Map from function id to emulated function definition
-    std::map<FunctionId, std::string> mEmulatedFunctions;
+    // Map from function unique id to emulated function definition
+    std::map<int, std::string> mEmulatedFunctions;
 
     // Map from dependent functions to their dependencies. This structure allows each function to
     // have at most one dependency.
-    std::map<FunctionId, FunctionId> mFunctionDependencies;
+    std::map<int, int> mFunctionDependencies;
 
     // Called function ids
-    std::vector<FunctionId> mFunctions;
+    std::vector<int> mFunctions;
 
     // Constexpr function tables.
     std::vector<BuiltinQueryFunc *> mQueryFunctions;
 };
 
 }  // namespace sh
 
 #endif  // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
--- a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
@@ -2,178 +2,159 @@
 // Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 #include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
 #include "angle_gl.h"
 #include "compiler/translator/BuiltInFunctionEmulator.h"
-#include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/StaticType.h"
 #include "compiler/translator/VersionGLSL.h"
+#include "compiler/translator/tree_util/BuiltIn_autogen.h"
 
 namespace sh
 {
 
 void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
                                                       sh::GLenum shaderType)
 {
     if (shaderType == GL_VERTEX_SHADER)
     {
-        const TType *int1 = StaticType::GetBasic<EbtInt>();
-        emu->addEmulatedFunction(EOpAbs, int1, "int abs_emu(int x) { return x * sign(x); }");
+        emu->addEmulatedFunction(BuiltInId::abs_Int1, "int abs_emu(int x) { return x * sign(x); }");
     }
 }
 
 void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
                                                         int targetGLSLVersion)
 {
     // isnan() is supported since GLSL 1.3.
     if (targetGLSLVersion < GLSL_VERSION_130)
         return;
 
-    const TType *float1 = StaticType::GetBasic<EbtFloat>();
-    const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
-    const TType *float3 = StaticType::GetBasic<EbtFloat, 3>();
-    const TType *float4 = StaticType::GetBasic<EbtFloat, 4>();
-
     // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false.
     emu->addEmulatedFunction(
-        EOpIsnan, float1,
+        BuiltInId::isnan_Float1,
         "bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }");
     emu->addEmulatedFunction(
-        EOpIsnan, float2,
+        BuiltInId::isnan_Float2,
         "bvec2 isnan_emu(vec2 x)\n"
         "{\n"
         "    bvec2 isnan;\n"
         "    for (int i = 0; i < 2; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
     emu->addEmulatedFunction(
-        EOpIsnan, float3,
+        BuiltInId::isnan_Float3,
         "bvec3 isnan_emu(vec3 x)\n"
         "{\n"
         "    bvec3 isnan;\n"
         "    for (int i = 0; i < 3; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
     emu->addEmulatedFunction(
-        EOpIsnan, float4,
+        BuiltInId::isnan_Float4,
         "bvec4 isnan_emu(vec4 x)\n"
         "{\n"
         "    bvec4 isnan;\n"
         "    for (int i = 0; i < 4; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
 }
 
 void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu)
 {
-    const TType *float1 = StaticType::GetBasic<EbtFloat>();
-    auto floatFuncId    = emu->addEmulatedFunction(
-        EOpAtan, float1, float1,
-        "emu_precision float atan_emu(emu_precision float y, emu_precision "
-        "float x)\n"
-        "{\n"
-        "    if (x > 0.0) return atan(y / x);\n"
-        "    else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n"
-        "    else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n"
-        "    else return 1.57079632 * sign(y);\n"
-        "}\n");
-    static const std::array<const TType *, 5> floatVecs = {
-        nullptr,
-        nullptr,
-        StaticType::GetBasic<EbtFloat, 2>(),
-        StaticType::GetBasic<EbtFloat, 3>(),
-        StaticType::GetBasic<EbtFloat, 4>(),
+    emu->addEmulatedFunction(BuiltInId::atan_Float1_Float1,
+                             "emu_precision float atan_emu(emu_precision float y, emu_precision "
+                             "float x)\n"
+                             "{\n"
+                             "    if (x > 0.0) return atan(y / x);\n"
+                             "    else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n"
+                             "    else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n"
+                             "    else return 1.57079632 * sign(y);\n"
+                             "}\n");
+    static const std::array<TSymbolUniqueId, 4> ids = {
+        BuiltInId::atan_Float1_Float1, BuiltInId::atan_Float2_Float2, BuiltInId::atan_Float3_Float3,
+        BuiltInId::atan_Float4_Float4,
     };
     for (int dim = 2; dim <= 4; ++dim)
     {
-        const TType *floatVec = floatVecs[dim];
         std::stringstream ss;
         ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim
            << " y, emu_precision vec" << dim << " x)\n"
            << "{\n"
               "    return vec"
            << dim << "(";
         for (int i = 0; i < dim; ++i)
         {
             ss << "atan_emu(y[" << i << "], x[" << i << "])";
             if (i < dim - 1)
             {
                 ss << ", ";
             }
         }
         ss << ");\n"
               "}\n";
-        emu->addEmulatedFunctionWithDependency(floatFuncId, EOpAtan, floatVec, floatVec,
+        emu->addEmulatedFunctionWithDependency(BuiltInId::atan_Float1_Float1, ids[dim - 1],
                                                ss.str().c_str());
     }
 }
 
 // Emulate built-in functions missing from GLSL 1.30 and higher
 void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu,
                                                         sh::GLenum shaderType,
                                                         int targetGLSLVersion)
 {
     // Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10)
     if (targetGLSLVersion < GLSL_VERSION_410)
     {
-        const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
-        const TType *uint1  = StaticType::GetBasic<EbtUInt>();
-
         // clang-format off
-        emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
+        emu->addEmulatedFunction(BuiltInId::packUnorm2x16_Float2,
             "uint packUnorm2x16_emu(vec2 v)\n"
             "{\n"
             "    int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n"
             "    int y = int(round(clamp(v.y, 0.0, 1.0) * 65535.0));\n"
             "    return uint((y << 16) | (x & 0xFFFF));\n"
             "}\n");
 
-        emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
+        emu->addEmulatedFunction(BuiltInId::unpackUnorm2x16_UInt1,
             "vec2 unpackUnorm2x16_emu(uint u)\n"
             "{\n"
             "    float x = float(u & 0xFFFFu) / 65535.0;\n"
             "    float y = float(u >> 16) / 65535.0;\n"
             "    return vec2(x, y);\n"
             "}\n");
         // clang-format on
     }
 
     // Emulate packSnorm2x16, packHalf2x16, unpackSnorm2x16, and unpackHalf2x16 (GLSL 4.20)
     // by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30).
     if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420)
     {
-        const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
-        const TType *uint1  = StaticType::GetBasic<EbtUInt>();
-
         // clang-format off
-        emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
+        emu->addEmulatedFunction(BuiltInId::packSnorm2x16_Float2,
             "uint packSnorm2x16_emu(vec2 v)\n"
             "{\n"
             "    #if defined(GL_ARB_shading_language_packing)\n"
             "        return packSnorm2x16(v);\n"
             "    #else\n"
             "        int x = int(round(clamp(v.x, -1.0, 1.0) * 32767.0));\n"
             "        int y = int(round(clamp(v.y, -1.0, 1.0) * 32767.0));\n"
             "        return uint((y << 16) | (x & 0xFFFF));\n"
             "    #endif\n"
             "}\n");
-        emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
+        emu->addEmulatedFunction(BuiltInId::unpackSnorm2x16_UInt1,
             "#if !defined(GL_ARB_shading_language_packing)\n"
             "    float fromSnorm(uint x)\n"
             "    {\n"
             "        int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n"
             "        return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
             "    }\n"
             "#endif\n"
             "\n"
@@ -184,17 +165,17 @@ void InitBuiltInFunctionEmulatorForGLSLM
             "    #else\n"
             "        uint y = (u >> 16);\n"
             "        uint x = u;\n"
             "        return vec2(fromSnorm(x), fromSnorm(y));\n"
             "    #endif\n"
             "}\n");
         // Functions uint f32tof16(float val) and float f16tof32(uint val) are
         // based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL".
-        emu->addEmulatedFunction(EOpPackHalf2x16, float2,
+        emu->addEmulatedFunction(BuiltInId::packHalf2x16_Float2,
             "#if !defined(GL_ARB_shading_language_packing)\n"
             "    uint f32tof16(float val)\n"
             "    {\n"
             "        uint f32 = floatBitsToUint(val);\n"
             "        uint f16 = 0u;\n"
             "        uint sign = (f32 >> 16) & 0x8000u;\n"
             "        int exponent = int((f32 >> 23) & 0xFFu) - 127;\n"
             "        uint mantissa = f32 & 0x007FFFFFu;\n"
@@ -231,17 +212,17 @@ void InitBuiltInFunctionEmulatorForGLSLM
             "    #if defined(GL_ARB_shading_language_packing)\n"
             "        return packHalf2x16(v);\n"
             "    #else\n"
             "        uint x = f32tof16(v.x);\n"
             "        uint y = f32tof16(v.y);\n"
             "        return (y << 16) | x;\n"
             "    #endif\n"
             "}\n");
-        emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
+        emu->addEmulatedFunction(BuiltInId::unpackHalf2x16_UInt1,
             "#if !defined(GL_ARB_shading_language_packing)\n"
             "    float f16tof32(uint val)\n"
             "    {\n"
             "        uint sign = (val & 0x8000u) << 16;\n"
             "        int exponent = int((val & 0x7C00u) >> 10);\n"
             "        uint mantissa = val & 0x03FFu;\n"
             "        float f32 = 0.0;\n"
             "        if(exponent == 0)\n"
--- a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
@@ -1,142 +1,131 @@
 //
 // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
+#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
 #include "angle_gl.h"
 #include "compiler/translator/BuiltInFunctionEmulator.h"
-#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
-#include "compiler/translator/SymbolTable.h"
 #include "compiler/translator/VersionGLSL.h"
+#include "compiler/translator/tree_util/BuiltIn_autogen.h"
 
 namespace sh
 {
 
 // Defined in emulated_builtin_functions_hlsl_autogen.cpp.
-const char *FindHLSLFunction(const FunctionId &functionID);
+const char *FindHLSLFunction(int uniqueId);
 
 void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
                                                         int targetGLSLVersion)
 {
     if (targetGLSLVersion < GLSL_VERSION_130)
         return;
 
-    TType *float1 = new TType(EbtFloat);
-    TType *float2 = new TType(EbtFloat, 2);
-    TType *float3 = new TType(EbtFloat, 3);
-    TType *float4 = new TType(EbtFloat, 4);
-
-    emu->addEmulatedFunction(EOpIsnan, float1,
+    emu->addEmulatedFunction(BuiltInId::isnan_Float1,
                              "bool isnan_emu(float x)\n"
                              "{\n"
                              "    return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n"
                              "}\n"
                              "\n");
 
     emu->addEmulatedFunction(
-        EOpIsnan, float2,
+        BuiltInId::isnan_Float2,
         "bool2 isnan_emu(float2 x)\n"
         "{\n"
         "    bool2 isnan;\n"
         "    for (int i = 0; i < 2; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
 
     emu->addEmulatedFunction(
-        EOpIsnan, float3,
+        BuiltInId::isnan_Float3,
         "bool3 isnan_emu(float3 x)\n"
         "{\n"
         "    bool3 isnan;\n"
         "    for (int i = 0; i < 3; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
 
     emu->addEmulatedFunction(
-        EOpIsnan, float4,
+        BuiltInId::isnan_Float4,
         "bool4 isnan_emu(float4 x)\n"
         "{\n"
         "    bool4 isnan;\n"
         "    for (int i = 0; i < 4; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
 }
 
 void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
 {
-    TType *int1   = new TType(EbtInt);
-    TType *int2   = new TType(EbtInt, 2);
-    TType *int3   = new TType(EbtInt, 3);
-    TType *int4   = new TType(EbtInt, 4);
-    TType *uint1  = new TType(EbtUInt);
-    TType *uint2  = new TType(EbtUInt, 2);
-    TType *uint3  = new TType(EbtUInt, 3);
-    TType *uint4  = new TType(EbtUInt, 4);
-
     emu->addFunctionMap(FindHLSLFunction);
 
     // (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32
     // Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because:
     // a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000
-    FunctionId umulExtendedUint1 = emu->addEmulatedFunction(
-        EOpUmulExtended, uint1, uint1, uint1, uint1,
-        "void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
-        "{\n"
-        "    lsb = x * y;\n"
-        "    uint a = (x & 0xffffu);\n"
-        "    uint b = (x >> 16);\n"
-        "    uint c = (y & 0xffffu);\n"
-        "    uint d = (y >> 16);\n"
-        "    uint ad = a * d + ((a * c) >> 16);\n"
-        "    uint bc = b * c;\n"
-        "    uint carry = uint(ad > (0xffffffffu - bc));\n"
-        "    msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
-        "}\n");
+    emu->addEmulatedFunction(BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
+                             "void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
+                             "{\n"
+                             "    lsb = x * y;\n"
+                             "    uint a = (x & 0xffffu);\n"
+                             "    uint b = (x >> 16);\n"
+                             "    uint c = (y & 0xffffu);\n"
+                             "    uint d = (y >> 16);\n"
+                             "    uint ad = a * d + ((a * c) >> 16);\n"
+                             "    uint bc = b * c;\n"
+                             "    uint carry = uint(ad > (0xffffffffu - bc));\n"
+                             "    msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
+                             "}\n");
     emu->addEmulatedFunctionWithDependency(
-        umulExtendedUint1, EOpUmulExtended, uint2, uint2, uint2, uint2,
+        BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
+        BuiltInId::umulExtended_UInt2_UInt2_UInt2_UInt2,
         "void umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n"
         "{\n"
         "    umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        umulExtendedUint1, EOpUmulExtended, uint3, uint3, uint3, uint3,
+        BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
+        BuiltInId::umulExtended_UInt3_UInt3_UInt3_UInt3,
         "void umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n"
         "{\n"
         "    umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "    umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        umulExtendedUint1, EOpUmulExtended, uint4, uint4, uint4, uint4,
+        BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
+        BuiltInId::umulExtended_UInt4_UInt4_UInt4_UInt4,
         "void umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n"
         "{\n"
         "    umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "    umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
         "    umulExtended_emu(x.w, y.w, msb.w, lsb.w);\n"
         "}\n");
 
     // The imul emulation does two's complement negation on the lsb and msb manually in case the
     // result needs to be negative.
     // TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is
     // -2^31. abs(-2^31) is undefined.
-    FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency(
-        umulExtendedUint1, EOpImulExtended, int1, int1, int1, int1,
+    emu->addEmulatedFunctionWithDependency(
+        BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
+        BuiltInId::imulExtended_Int1_Int1_Int1_Int1,
         "void imulExtended_emu(int x, int y, out int msb, out int lsb)\n"
         "{\n"
         "    uint unsignedMsb;\n"
         "    uint unsignedLsb;\n"
         "    bool negative = (x < 0) != (y < 0);\n"
         "    umulExtended_emu(uint(abs(x)), uint(abs(y)), unsignedMsb, unsignedLsb);\n"
         "    lsb = asint(unsignedLsb);\n"
         "    msb = asint(unsignedMsb);\n"
@@ -151,32 +140,32 @@ void InitBuiltInFunctionEmulatorForHLSL(
         "        }\n"
         "        else\n"
         "        {\n"
         "            lsb += 1;\n"
         "        }\n"
         "    }\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        imulExtendedInt1, EOpImulExtended, int2, int2, int2, int2,
+        BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int2_Int2_Int2_Int2,
         "void imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n"
         "{\n"
         "    imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        imulExtendedInt1, EOpImulExtended, int3, int3, int3, int3,
+        BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int3_Int3_Int3_Int3,
         "void imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n"
         "{\n"
         "    imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "    imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        imulExtendedInt1, EOpImulExtended, int4, int4, int4, int4,
+        BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int4_Int4_Int4_Int4,
         "void imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n"
         "{\n"
         "    imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "    imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
         "    imulExtended_emu(x.w, y.w, msb.w, lsb.w);\n"
         "}\n");
 }
--- a/gfx/angle/checkout/src/compiler/translator/CallDAG.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/CallDAG.cpp
@@ -6,18 +6,18 @@
 
 // CallDAG.h: Implements a call graph DAG of functions to be re-used accross
 // analyses, allows to efficiently traverse the functions in topological
 // order.
 
 #include "compiler/translator/CallDAG.h"
 
 #include "compiler/translator/Diagnostics.h"
-#include "compiler/translator/IntermTraverse.h"
 #include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
 
 namespace sh
 {
 
 // The CallDAGCreator does all the processing required to create the CallDAG
 // structure so that the latter contains only the necessary variables.
 class CallDAG::CallDAGCreator : public TIntermTraverser
 {
@@ -111,26 +111,23 @@ class CallDAG::CallDAGCreator : public T
         mCurrentFunction->name           = node->getFunction()->name();
         mCurrentFunction->definitionNode = node;
 
         node->getBody()->traverse(this);
         mCurrentFunction = nullptr;
         return false;
     }
 
-    bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override
+    void visitFunctionPrototype(TIntermFunctionPrototype *node) override
     {
         ASSERT(mCurrentFunction == nullptr);
 
         // Function declaration, create an empty record.
         auto &record = mFunctions[node->getFunction()->uniqueId().get()];
         record.name  = node->getFunction()->name();
-
-        // No need to traverse the parameters.
-        return false;
     }
 
     // Track functions called from another function.
     bool visitAggregate(Visit visit, TIntermAggregate *node) override
     {
         if (node->getOp() == EOpCallFunctionInAST)
         {
             // Function call, add the callees
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/ClampFragDepth.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// ClampFragDepth.cpp: Limit the value that is written to gl_FragDepth to the range [0.0, 1.0].
-// The clamping is run at the very end of shader execution, and is only performed if the shader
-// statically accesses gl_FragDepth.
-//
-
-#include "compiler/translator/ClampFragDepth.h"
-
-#include "compiler/translator/FindSymbolNode.h"
-#include "compiler/translator/ImmutableString.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/RunAtTheEndOfShader.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-void ClampFragDepth(TIntermBlock *root, TSymbolTable *symbolTable)
-{
-    // Only clamp gl_FragDepth if it's used in the shader.
-    if (!FindSymbolNode(root, ImmutableString("gl_FragDepth")))
-    {
-        return;
-    }
-
-    TIntermSymbol *fragDepthNode =
-        ReferenceBuiltInVariable(ImmutableString("gl_FragDepth"), *symbolTable, 300);
-
-    TIntermTyped *minFragDepthNode = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
-
-    TConstantUnion *maxFragDepthConstant = new TConstantUnion();
-    maxFragDepthConstant->setFConst(1.0);
-    TIntermConstantUnion *maxFragDepthNode =
-        new TIntermConstantUnion(maxFragDepthConstant, TType(EbtFloat, EbpHigh, EvqConst));
-
-    // clamp(gl_FragDepth, 0.0, 1.0)
-    TIntermSequence *clampArguments = new TIntermSequence();
-    clampArguments->push_back(fragDepthNode->deepCopy());
-    clampArguments->push_back(minFragDepthNode);
-    clampArguments->push_back(maxFragDepthNode);
-    TIntermTyped *clampedFragDepth =
-        CreateBuiltInFunctionCallNode("clamp", clampArguments, *symbolTable, 100);
-
-    // gl_FragDepth = clamp(gl_FragDepth, 0.0, 1.0)
-    TIntermBinary *assignFragDepth = new TIntermBinary(EOpAssign, fragDepthNode, clampedFragDepth);
-
-    RunAtTheEndOfShader(root, assignFragDepth, symbolTable);
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/ClampFragDepth.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// ClampFragDepth.h: Limit the value that is written to gl_FragDepth to the range [0.0, 1.0].
-// The clamping is run at the very end of shader execution, and is only performed if the shader
-// statically accesses gl_FragDepth.
-//
-
-#ifndef COMPILER_TRANSLATOR_CLAMPFRAGDEPTH_H_
-#define COMPILER_TRANSLATOR_CLAMPFRAGDEPTH_H_
-
-namespace sh
-{
-
-class TIntermBlock;
-class TSymbolTable;
-
-void ClampFragDepth(TIntermBlock *root, TSymbolTable *symbolTable);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_CLAMPFRAGDEPTH_H_
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/ClampPointSize.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// ClampPointSize.cpp: Limit the value that is written to gl_PointSize.
-//
-
-#include "compiler/translator/ClampPointSize.h"
-
-#include "compiler/translator/FindSymbolNode.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/RunAtTheEndOfShader.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbolTable)
-{
-    // Only clamp gl_PointSize if it's used in the shader.
-    if (!FindSymbolNode(root, ImmutableString("gl_PointSize")))
-    {
-        return;
-    }
-
-    TIntermSymbol *pointSizeNode =
-        ReferenceBuiltInVariable(ImmutableString("gl_PointSize"), *symbolTable, 100);
-
-    TConstantUnion *maxPointSizeConstant = new TConstantUnion();
-    maxPointSizeConstant->setFConst(maxPointSize);
-    TIntermConstantUnion *maxPointSizeNode =
-        new TIntermConstantUnion(maxPointSizeConstant, TType(EbtFloat, EbpHigh, EvqConst));
-
-    // min(gl_PointSize, maxPointSize)
-    TIntermSequence *minArguments = new TIntermSequence();
-    minArguments->push_back(pointSizeNode->deepCopy());
-    minArguments->push_back(maxPointSizeNode);
-    TIntermTyped *clampedPointSize =
-        CreateBuiltInFunctionCallNode("min", minArguments, *symbolTable, 100);
-
-    // gl_PointSize = min(gl_PointSize, maxPointSize)
-    TIntermBinary *assignPointSize = new TIntermBinary(EOpAssign, pointSizeNode, clampedPointSize);
-
-    RunAtTheEndOfShader(root, assignPointSize, symbolTable);
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/ClampPointSize.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// ClampPointSize.h: Limit the value that is written to gl_PointSize.
-//
-
-#ifndef COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
-#define COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
-
-namespace sh
-{
-
-class TIntermBlock;
-class TSymbolTable;
-
-void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbolTable);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
--- a/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp
@@ -5,18 +5,18 @@
 //
 // CollectVariables.cpp: Collect lists of shader interface variables based on the AST.
 
 #include "compiler/translator/CollectVariables.h"
 
 #include "angle_gl.h"
 #include "common/utilities.h"
 #include "compiler/translator/HashNames.h"
-#include "compiler/translator/IntermTraverse.h"
 #include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
 #include "compiler/translator/util.h"
 
 namespace sh
 {
 
 namespace
 {
 
@@ -63,44 +63,46 @@ VarT *FindVariable(const ImmutableString
     {
         if (name == (*infoList)[ii].name)
             return &((*infoList)[ii]);
     }
 
     return nullptr;
 }
 
-// Note that this shouldn't be called for interface blocks - static use information is collected for
+// Note that this shouldn't be called for interface blocks - active information is collected for
 // individual fields in case of interface blocks.
-void MarkStaticallyUsed(ShaderVariable *variable)
+void MarkActive(ShaderVariable *variable)
 {
-    if (!variable->staticUse)
+    if (!variable->active)
     {
         if (variable->isStruct())
         {
             // Conservatively assume all fields are statically used as well.
             for (auto &field : variable->fields)
             {
-                MarkStaticallyUsed(&field);
+                MarkActive(&field);
             }
         }
-        variable->staticUse = true;
+        ASSERT(variable->staticUse);
+        variable->active    = true;
     }
 }
 
 ShaderVariable *FindVariableInInterfaceBlock(const ImmutableString &name,
                                              const TInterfaceBlock *interfaceBlock,
                                              std::vector<InterfaceBlock> *infoList)
 {
     ASSERT(interfaceBlock);
     InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList);
     ASSERT(namedBlock);
 
     // Set static use on the parent interface block here
     namedBlock->staticUse = true;
+    namedBlock->active    = true;
     return FindVariable(name, &namedBlock->fields);
 }
 
 // Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs,
 // and interface blocks.
 class CollectVariablesTraverser : public TIntermTraverser
 {
   public:
@@ -109,50 +111,53 @@ class CollectVariablesTraverser : public
                               std::vector<Uniform> *uniforms,
                               std::vector<Varying> *inputVaryings,
                               std::vector<Varying> *outputVaryings,
                               std::vector<InterfaceBlock> *uniformBlocks,
                               std::vector<InterfaceBlock> *shaderStorageBlocks,
                               std::vector<InterfaceBlock> *inBlocks,
                               ShHashFunction64 hashFunction,
                               TSymbolTable *symbolTable,
-                              int shaderVersion,
                               GLenum shaderType,
                               const TExtensionBehavior &extensionBehavior);
 
+    bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
     void visitSymbol(TIntermSymbol *symbol) override;
     bool visitDeclaration(Visit, TIntermDeclaration *node) override;
     bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
 
   private:
     std::string getMappedName(const TSymbol *symbol) const;
 
-    void setFieldOrVariableProperties(const TType &type, ShaderVariable *variableOut) const;
+    void setFieldOrVariableProperties(const TType &type,
+                                      bool staticUse,
+                                      ShaderVariable *variableOut) const;
     void setFieldProperties(const TType &type,
                             const ImmutableString &name,
+                            bool staticUse,
                             ShaderVariable *variableOut) const;
     void setCommonVariableProperties(const TType &type,
                                      const TVariable &variable,
                                      ShaderVariable *variableOut) const;
 
     Attribute recordAttribute(const TIntermSymbol &variable) const;
     OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
     Varying recordVarying(const TIntermSymbol &variable) const;
     void recordInterfaceBlock(const char *instanceName,
                               const TType &interfaceBlockType,
                               InterfaceBlock *interfaceBlock) const;
     Uniform recordUniform(const TIntermSymbol &variable) const;
 
-    void setBuiltInInfoFromSymbolTable(const ImmutableString &name, ShaderVariable *info);
+    void setBuiltInInfoFromSymbol(const TVariable &variable, ShaderVariable *info);
 
-    void recordBuiltInVaryingUsed(const ImmutableString &name,
+    void recordBuiltInVaryingUsed(const TVariable &variable,
                                   bool *addedFlag,
                                   std::vector<Varying> *varyings);
-    void recordBuiltInFragmentOutputUsed(const ImmutableString &name, bool *addedFlag);
-    void recordBuiltInAttributeUsed(const ImmutableString &name, bool *addedFlag);
+    void recordBuiltInFragmentOutputUsed(const TVariable &variable, bool *addedFlag);
+    void recordBuiltInAttributeUsed(const TVariable &variable, bool *addedFlag);
     InterfaceBlock *recordGLInUsed(const TType &glInType);
     InterfaceBlock *findNamedInterfaceBlock(const ImmutableString &name) const;
 
     std::vector<Attribute> *mAttribs;
     std::vector<OutputVariable> *mOutputVariables;
     std::vector<Uniform> *mUniforms;
     std::vector<Varying> *mInputVaryings;
     std::vector<Varying> *mOutputVaryings;
@@ -191,33 +196,31 @@ class CollectVariablesTraverser : public
     bool mInvocationIDAdded;
 
     // Geometry Shader and Fragment Shader builtins
     bool mPrimitiveIDAdded;
     bool mLayerAdded;
 
     ShHashFunction64 mHashFunction;
 
-    int mShaderVersion;
     GLenum mShaderType;
     const TExtensionBehavior &mExtensionBehavior;
 };
 
 CollectVariablesTraverser::CollectVariablesTraverser(
     std::vector<sh::Attribute> *attribs,
     std::vector<sh::OutputVariable> *outputVariables,
     std::vector<sh::Uniform> *uniforms,
     std::vector<sh::Varying> *inputVaryings,
     std::vector<sh::Varying> *outputVaryings,
     std::vector<sh::InterfaceBlock> *uniformBlocks,
     std::vector<sh::InterfaceBlock> *shaderStorageBlocks,
     std::vector<sh::InterfaceBlock> *inBlocks,
     ShHashFunction64 hashFunction,
     TSymbolTable *symbolTable,
-    int shaderVersion,
     GLenum shaderType,
     const TExtensionBehavior &extensionBehavior)
     : TIntermTraverser(true, false, false, symbolTable),
       mAttribs(attribs),
       mOutputVariables(outputVariables),
       mUniforms(uniforms),
       mInputVaryings(inputVaryings),
       mOutputVaryings(outputVaryings),
@@ -240,112 +243,116 @@ CollectVariablesTraverser::CollectVariab
       mSecondaryFragColorEXTAdded(false),
       mSecondaryFragDataEXTAdded(false),
       mPerVertexInAdded(false),
       mPrimitiveIDInAdded(false),
       mInvocationIDAdded(false),
       mPrimitiveIDAdded(false),
       mLayerAdded(false),
       mHashFunction(hashFunction),
-      mShaderVersion(shaderVersion),
       mShaderType(shaderType),
       mExtensionBehavior(extensionBehavior)
 {
 }
 
 std::string CollectVariablesTraverser::getMappedName(const TSymbol *symbol) const
 {
     return HashName(symbol, mHashFunction, nullptr).data();
 }
 
-void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const ImmutableString &name,
-                                                              ShaderVariable *info)
+void CollectVariablesTraverser::setBuiltInInfoFromSymbol(const TVariable &variable,
+                                                         ShaderVariable *info)
 {
-    const TVariable *symbolTableVar =
-        reinterpret_cast<const TVariable *>(mSymbolTable->findBuiltIn(name, mShaderVersion));
-    ASSERT(symbolTableVar);
-    const TType &type = symbolTableVar->getType();
+    const TType &type = variable.getType();
 
-    info->name       = name.data();
-    info->mappedName = name.data();
+    info->name       = variable.name().data();
+    info->mappedName = variable.name().data();
     info->type       = GLVariableType(type);
     info->precision = GLVariablePrecision(type);
     if (auto *arraySizes = type.getArraySizes())
     {
         info->arraySizes.assign(arraySizes->begin(), arraySizes->end());
     }
 }
 
-void CollectVariablesTraverser::recordBuiltInVaryingUsed(const ImmutableString &name,
+void CollectVariablesTraverser::recordBuiltInVaryingUsed(const TVariable &variable,
                                                          bool *addedFlag,
                                                          std::vector<Varying> *varyings)
 {
     ASSERT(varyings);
     if (!(*addedFlag))
     {
         Varying info;
-        setBuiltInInfoFromSymbolTable(name, &info);
+        setBuiltInInfoFromSymbol(variable, &info);
         info.staticUse   = true;
-        info.isInvariant = mSymbolTable->isVaryingInvariant(name);
+        info.active      = true;
+        info.isInvariant = mSymbolTable->isVaryingInvariant(variable.name());
         varyings->push_back(info);
         (*addedFlag) = true;
     }
 }
 
-void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const ImmutableString &name,
+void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const TVariable &variable,
                                                                 bool *addedFlag)
 {
     if (!(*addedFlag))
     {
         OutputVariable info;
-        setBuiltInInfoFromSymbolTable(name, &info);
+        setBuiltInInfoFromSymbol(variable, &info);
         info.staticUse = true;
+        info.active    = true;
         mOutputVariables->push_back(info);
         (*addedFlag) = true;
     }
 }
 
-void CollectVariablesTraverser::recordBuiltInAttributeUsed(const ImmutableString &name,
+void CollectVariablesTraverser::recordBuiltInAttributeUsed(const TVariable &variable,
                                                            bool *addedFlag)
 {
     if (!(*addedFlag))
     {
         Attribute info;
-        setBuiltInInfoFromSymbolTable(name, &info);
+        setBuiltInInfoFromSymbol(variable, &info);
         info.staticUse = true;
+        info.active    = true;
         info.location  = -1;
         mAttribs->push_back(info);
         (*addedFlag) = true;
     }
 }
 
 InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
 {
     if (!mPerVertexInAdded)
     {
         ASSERT(glInType.getQualifier() == EvqPerVertexIn);
         InterfaceBlock info;
         recordInterfaceBlock("gl_in", glInType, &info);
-        info.staticUse = true;
 
         mPerVertexInAdded = true;
         mInBlocks->push_back(info);
         return &mInBlocks->back();
     }
     else
     {
         return FindVariable(ImmutableString("gl_PerVertex"), mInBlocks);
     }
 }
 
-// We want to check whether a uniform/varying is statically used
-// because we only count the used ones in packing computing.
-// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
-// toward varying counting if they are statically used in a fragment
-// shader.
+bool CollectVariablesTraverser::visitInvariantDeclaration(Visit visit,
+                                                          TIntermInvariantDeclaration *node)
+{
+    // We should not mark variables as active just based on an invariant declaration, so we don't
+    // traverse the symbols declared invariant.
+    return false;
+}
+
+// We want to check whether a uniform/varying is active because we need to skip updating inactive
+// ones. We also only count the active ones in packing computing. Also, gl_FragCoord, gl_PointCoord,
+// and gl_FrontFacing count toward varying counting if they are active in a fragment shader.
 void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
 {
     ASSERT(symbol != nullptr);
 
     if (symbol->variable().symbolType() == SymbolType::AngleInternal ||
         symbol->variable().symbolType() == SymbolType::Empty)
     {
         // Internal variables or nameless variables are not collected.
@@ -380,37 +387,41 @@ void CollectVariablesTraverser::visitSym
         {
             Uniform info;
             const char kName[] = "gl_DepthRange";
             info.name          = kName;
             info.mappedName    = kName;
             info.type          = GL_NONE;
             info.precision     = GL_NONE;
             info.staticUse     = true;
+            info.active        = true;
 
             ShaderVariable nearInfo(GL_FLOAT);
             const char kNearName[] = "near";
             nearInfo.name          = kNearName;
             nearInfo.mappedName    = kNearName;
             nearInfo.precision     = GL_HIGH_FLOAT;
             nearInfo.staticUse     = true;
+            nearInfo.active        = true;
 
             ShaderVariable farInfo(GL_FLOAT);
             const char kFarName[] = "far";
             farInfo.name          = kFarName;
             farInfo.mappedName    = kFarName;
             farInfo.precision     = GL_HIGH_FLOAT;
             farInfo.staticUse     = true;
+            farInfo.active        = true;
 
             ShaderVariable diffInfo(GL_FLOAT);
             const char kDiffName[] = "diff";
             diffInfo.name          = kDiffName;
             diffInfo.mappedName    = kDiffName;
             diffInfo.precision     = GL_HIGH_FLOAT;
             diffInfo.staticUse     = true;
+            diffInfo.active        = true;
 
             info.fields.push_back(nearInfo);
             info.fields.push_back(farInfo);
             info.fields.push_back(diffInfo);
 
             mUniforms->push_back(info);
             mDepthRangeAdded = true;
         }
@@ -445,148 +456,126 @@ void CollectVariablesTraverser::visitSym
             case EvqBuffer:
             {
                 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
                 var =
                     FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
             }
             break;
             case EvqFragCoord:
-                recordBuiltInVaryingUsed(ImmutableString("gl_FragCoord"), &mFragCoordAdded,
-                                         mInputVaryings);
+                recordBuiltInVaryingUsed(symbol->variable(), &mFragCoordAdded, mInputVaryings);
                 return;
             case EvqFrontFacing:
-                recordBuiltInVaryingUsed(ImmutableString("gl_FrontFacing"), &mFrontFacingAdded,
-                                         mInputVaryings);
+                recordBuiltInVaryingUsed(symbol->variable(), &mFrontFacingAdded, mInputVaryings);
                 return;
             case EvqPointCoord:
-                recordBuiltInVaryingUsed(ImmutableString("gl_PointCoord"), &mPointCoordAdded,
-                                         mInputVaryings);
+                recordBuiltInVaryingUsed(symbol->variable(), &mPointCoordAdded, mInputVaryings);
                 return;
             case EvqInstanceID:
                 // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set,
                 // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
-                // InstanceID. gl_InstanceID is not added to the symbol table for ESSL1 shaders
-                // which makes it necessary to populate the type information explicitly instead of
-                // extracting it from the symbol table.
-                if (!mInstanceIDAdded)
-                {
-                    Attribute info;
-                    const char kName[] = "gl_InstanceID";
-                    info.name          = kName;
-                    info.mappedName    = kName;
-                    info.type          = GL_INT;
-                    info.precision     = GL_HIGH_INT;  // Defined by spec.
-                    info.staticUse     = true;
-                    info.location      = -1;
-                    mAttribs->push_back(info);
-                    mInstanceIDAdded = true;
-                }
+                // InstanceID. Note that gl_InstanceID is not added to the symbol table for ESSL1
+                // shaders.
+                recordBuiltInAttributeUsed(symbol->variable(), &mInstanceIDAdded);
                 return;
             case EvqVertexID:
-                recordBuiltInAttributeUsed(ImmutableString("gl_VertexID"), &mVertexIDAdded);
+                recordBuiltInAttributeUsed(symbol->variable(), &mVertexIDAdded);
                 return;
             case EvqPosition:
-                recordBuiltInVaryingUsed(ImmutableString("gl_Position"), &mPositionAdded,
-                                         mOutputVaryings);
+                recordBuiltInVaryingUsed(symbol->variable(), &mPositionAdded, mOutputVaryings);
                 return;
             case EvqPointSize:
-                recordBuiltInVaryingUsed(ImmutableString("gl_PointSize"), &mPointSizeAdded,
-                                         mOutputVaryings);
+                recordBuiltInVaryingUsed(symbol->variable(), &mPointSizeAdded, mOutputVaryings);
                 return;
             case EvqLastFragData:
-                recordBuiltInVaryingUsed(ImmutableString("gl_LastFragData"), &mLastFragDataAdded,
-                                         mInputVaryings);
+                recordBuiltInVaryingUsed(symbol->variable(), &mLastFragDataAdded, mInputVaryings);
                 return;
             case EvqFragColor:
-                recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragColor&