Merge latest green birch changeset and mozilla-central
authorEd Morley <emorley@mozilla.com>
Mon, 10 Jun 2013 10:06:11 +0100
changeset 145978 252b1ac4d537267abe953b79957b308b00e6f032
parent 145977 1b54057a41ccb383aa23b0cba8978c63fb4702f5 (current diff)
parent 145963 625de2ded691992e28f4ece11a54b6691dc11f26 (diff)
child 145979 7f45910089be6d2c84f1bb45cce669328e41955c
child 145980 8a05d7dc509f1d5c2518a26d36b6ad6f8447f2a9
child 145991 deb589f7e2dcd56c90433df2747be5f920a1d030
child 169990 92c047e2be67d3470137705ff3875b56adbb3130
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone24.0a1
first release with
nightly linux32
252b1ac4d537 / 24.0a1 / 20130610031147 / files
nightly linux64
252b1ac4d537 / 24.0a1 / 20130610031147 / files
nightly mac
252b1ac4d537 / 24.0a1 / 20130610031147 / files
nightly win32
252b1ac4d537 / 24.0a1 / 20130610031147 / files
nightly win64
252b1ac4d537 / 24.0a1 / 20130610031147 / 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 latest green birch changeset and mozilla-central
browser/installer/package-manifest.in
build/manifestparser.py
build/tests/filter-example.ini
build/tests/fleem
build/tests/include-example.ini
build/tests/include/bar.ini
build/tests/include/crash-handling
build/tests/include/flowers
build/tests/include/foo.ini
build/tests/mozmill-example.ini
build/tests/mozmill-restart-example.ini
build/tests/path-example.ini
build/tests/test.py
build/tests/test_expressionparser.txt
build/tests/test_manifestparser.txt
build/tests/test_testmanifest.txt
content/media/webaudio/GainProcessor.h
content/media/webaudio/test/test_audioBufferSourceNodeGain.html
content/media/webaudio/test/test_audioBufferSourceNodeGainInLoop.html
content/media/webaudio/test/test_delayNodeWithGainAlternate.html
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -1734,20 +1734,43 @@ DocAccessible::UpdateTree(Accessible* aC
   }
 #endif
 
   nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(aContainer);
 
   if (child) {
     updateFlags |= UpdateTreeInternal(child, aIsInsert, reorderEvent);
   } else {
-    TreeWalker walker(aContainer, aChildNode, true);
+    if (aIsInsert) {
+      TreeWalker walker(aContainer, aChildNode, true);
 
-    while ((child = walker.NextChild()))
-      updateFlags |= UpdateTreeInternal(child, aIsInsert, reorderEvent);
+      while ((child = walker.NextChild()))
+        updateFlags |= UpdateTreeInternal(child, aIsInsert, reorderEvent);
+    } else {
+      // aChildNode may not coorespond to a particular accessible, to handle
+      // this we go through all the children of aContainer.  Then if a child
+      // has aChildNode as an ancestor, or does not have the node for
+      // aContainer as an ancestor remove that child of aContainer.  Note that
+      // when we are called aChildNode may already have been removed
+      // from the DOM so we can't expect it to have a parent or what was it's
+      // parent to have it as a child.
+      nsINode* containerNode = aContainer->GetNode();
+      for (uint32_t idx = 0; idx < aContainer->ContentChildCount();) {
+        Accessible* child = aContainer->ContentChildAt(idx);
+        nsINode* childNode = child->GetContent();
+        while (childNode != aChildNode && childNode != containerNode &&
+               (childNode = childNode->GetParentNode()));
+
+        if (childNode != containerNode) {
+          updateFlags |= UpdateTreeInternal(child, false, reorderEvent);
+        } else {
+          idx++;
+        }
+      }
+    }
   }
 
   // Content insertion/removal is not cause of accessible tree change.
   if (updateFlags == eNoAccessible)
     return;
 
   // Check to see if change occurred inside an alert, and fire an EVENT_ALERT
   // if it did.
--- a/accessible/tests/mochitest/treeupdate/Makefile.in
+++ b/accessible/tests/mochitest/treeupdate/Makefile.in
@@ -25,14 +25,15 @@ MOCHITEST_A11Y_FILES =\
 		test_list_editabledoc.html \
 		test_list.html \
 		test_listbox.xul \
 		test_menu.xul \
 		test_menubutton.xul \
 	test_optgroup.html \
 		test_recreation.html \
 		test_select.html \
+		test_bug852150.xhtml \
 		test_textleaf.html \
 		test_visibility.html \
 		test_whitespace.html \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/test_bug852150.xhtml
@@ -0,0 +1,59 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+  <title>Canvas subdom mutation</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+
+  <script>
+  <![CDATA[
+    function doTest()
+    {
+      var the_displayNone = getNode("the_displaynone");
+      var the_table = getNode("the_table");
+      var the_row = getNode("the_row");
+      ok(isAccessible(the_table), "table should be accessible");
+      the_displayNone.appendChild(the_table);
+      ok(!isAccessible(the_table), "table in display none tree shouldn't be accessible");
+
+      setTimeout(function() {
+        document.body.removeChild(the_row);
+        // make sure no accessibles have stuck around.
+        ok(!isAccessible(the_row), "row shouldn't be accessible");
+        ok(!isAccessible(the_table), "table shouldn't be accessible");
+        ok(!isAccessible(the_displayNone), "display none things shouldn't be accessible");
+        SimpleTest.finish();
+      }, 0);
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  ]]>
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="test accessible removal when reframe root isn't accessible"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=852150">
+    Mozilla Bug 852150
+  </a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <div id="the_displaynone" style="display: none;"></div>
+  <table id="the_table"></table>
+  <tr id="the_row"></tr>
+</body>
+</html>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "repo": "http://hg.mozilla.org/integration/gaia-central/",
-    "revision": "8c7dcb64cafd"
+    "repo_path": "/integration/gaia-central",
+    "revision": "3f5bb84585fc"
 }
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1369693795000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1370548649000">
   <emItems>
       <emItem  blockID="i350" id="sqlmoz@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i58" id="webmaster@buzzzzvideos.info">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
@@ -44,16 +44,20 @@
       <emItem  blockID="i117" id="{ce7e73df-6a44-4028-8079-5927a588c948}">
                         <versionRange  minVersion="0" maxVersion="1.0.8" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i348" id="{13c9f1f9-2322-4d5c-81df-6d4bf8476ba4}">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i6" id="{3f963a5b-e555-4543-90e2-c3908898db71}">
+                        <versionRange  minVersion=" " maxVersion="8.5">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i236" id="{EEE6C361-6118-11DC-9C72-001320C79847}">
                         <versionRange  minVersion="0" maxVersion="1.7.999" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i24" id="{6E19037A-12E3-4295-8915-ED48BC341614}">
                         <versionRange  minVersion="0.1" maxVersion="1.3.328.4" severity="1">
                       <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="3.7a1pre" maxVersion="*" />
@@ -98,16 +102,20 @@
       <emItem  blockID="i172" id="info@bflix.info">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i140" id="mozillahmpg@mozilla.org">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i360" id="ytd@mybrowserbar.com">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i5" id="support@daemon-tools.cc">
                         <versionRange  minVersion=" " maxVersion="1.0.0.5">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i97" id="support3_en@adobe122.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
@@ -369,18 +377,18 @@
                         <versionRange  minVersion="1.0" maxVersion="1.3.1">
                       <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="3.0a1" maxVersion="*" />
                           </targetApplication>
                     </versionRange>
                                 <versionRange  minVersion="1.5.7.5" maxVersion="1.5.7.5" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i6" id="{3f963a5b-e555-4543-90e2-c3908898db71}">
-                        <versionRange  minVersion=" " maxVersion="8.5">
+      <emItem  blockID="i362" id="addon@defaulttab.com">
+                        <versionRange  minVersion="0" maxVersion="1.4.4" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i12" id="masterfiler@gmail.com">
                         <versionRange  severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i20" id="{AB2CE124-6272-4b12-94A9-7303C7397BD1}">
                         <versionRange  minVersion="0.1" maxVersion="5.2.0.7164" severity="1">
@@ -717,45 +725,45 @@
       <pluginItem  blockID="p178">
                   <match name="filename" exp="(NPSWF[0-9_]*\.dll)|(Flash\ Player\.plugin)" />                                    <versionRange  minVersion="11.0" maxVersion="11.6.602.175" severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0.4" maxVersion="17.0.*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p180">
-                  <match name="filename" exp="JavaAppletPlugin\.plugin" />                                    <versionRange  minVersion="Java 7 Update 0" maxVersion="Java 7 Update 11" severity="0" vulnerabilitystatus="2">
+                  <match name="filename" exp="JavaAppletPlugin\.plugin" />                                    <versionRange  minVersion="Java 7 Update 0" maxVersion="Java 7 Update 11" severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p182">
-      <match name="name" exp="Java\(TM\) Platform SE 7 U([0-9]|(1[0-1]))(\s[^\d\._U]|$)" />            <match name="filename" exp="npjp2\.dll" />                                    <versionRange  severity="0" vulnerabilitystatus="2">
+      <match name="name" exp="Java\(TM\) Platform SE 7 U([0-9]|(1[0-1]))(\s[^\d\._U]|$)" />            <match name="filename" exp="npjp2\.dll" />                                    <versionRange  severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p184">
-      <match name="name" exp="Java\(TM\) Plug-in 1\.7\.0(_0?([0-9]|(1[0-1]))?)?([^\d\._]|$)" />            <match name="filename" exp="libnpjp2\.so" />                                    <versionRange  severity="0" vulnerabilitystatus="2">
+      <match name="name" exp="Java\(TM\) Plug-in 1\.7\.0(_0?([0-9]|(1[0-1]))?)?([^\d\._]|$)" />            <match name="filename" exp="libnpjp2\.so" />                                    <versionRange  severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p186">
-      <match name="name" exp="Java\(TM\) Platform SE 6 U3[1-8](\s[^\d\._U]|$)" />            <match name="filename" exp="npjp2\.dll" />                                    <versionRange  severity="0" vulnerabilitystatus="2">
+      <match name="name" exp="Java\(TM\) Platform SE 6 U3[1-8](\s[^\d\._U]|$)" />            <match name="filename" exp="npjp2\.dll" />                                    <versionRange  severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p188">
-                  <match name="filename" exp="JavaAppletPlugin\.plugin" />                                    <versionRange  minVersion="Java 6 Update 0" maxVersion="Java 6 Update 38" severity="0" vulnerabilitystatus="2">
+                  <match name="filename" exp="JavaAppletPlugin\.plugin" />                                    <versionRange  minVersion="Java 6 Update 0" maxVersion="Java 6 Update 38" severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p190">
       <match name="name" exp="Java\(TM\) Plug-in 1\.6\.0_3[1-8]([^\d\._]|$)" />            <match name="filename" exp="libnpjp2\.so" />                                    <versionRange  severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
@@ -834,52 +842,52 @@
       <pluginItem  blockID="p290">
                   <match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" />                                    <versionRange  minVersion="10.3.183.19" maxVersion="10.3.183.66" severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0.4" maxVersion="17.0.*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p292">
-                  <match name="filename" exp="JavaAppletPlugin\.plugin" />                                    <versionRange  minVersion="Java 7 Update 12" maxVersion="Java 7 Update 15" severity="0" vulnerabilitystatus="2">
+                  <match name="filename" exp="JavaAppletPlugin\.plugin" />                                    <versionRange  minVersion="Java 7 Update 12" maxVersion="Java 7 Update 15" severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p294">
-      <match name="name" exp="Java\(TM\) Platform SE 7 U1[2-5](\s[^\d\._U]|$)" />            <match name="filename" exp="npjp2\.dll" />                                    <versionRange  severity="0" vulnerabilitystatus="2">
+      <match name="name" exp="Java\(TM\) Platform SE 7 U1[2-5](\s[^\d\._U]|$)" />            <match name="filename" exp="npjp2\.dll" />                                    <versionRange  severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p296">
-      <match name="name" exp="Java\(TM\) Plug-in 1\.7\.0_1[2-5]([^\d\._]|$)" />            <match name="filename" exp="libnpjp2\.so" />                                    <versionRange  severity="0" vulnerabilitystatus="2">
+      <match name="name" exp="Java\(TM\) Plug-in 1\.7\.0_1[2-5]([^\d\._]|$)" />            <match name="filename" exp="libnpjp2\.so" />                                    <versionRange  severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p298">
-                  <match name="filename" exp="JavaAppletPlugin\.plugin" />                                    <versionRange  minVersion="Java 6 Update 39" maxVersion="Java 6 Update 41" severity="0" vulnerabilitystatus="2">
+                  <match name="filename" exp="JavaAppletPlugin\.plugin" />                                    <versionRange  minVersion="Java 6 Update 39" maxVersion="Java 6 Update 41" severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p300">
-      <match name="name" exp="Java\(TM\) Platform SE 6 U(39|40|41)(\s[^\d\._U]|$)" />            <match name="filename" exp="npjp2\.dll" />                                    <versionRange  severity="0" vulnerabilitystatus="2">
+      <match name="name" exp="Java\(TM\) Platform SE 6 U(39|40|41)(\s[^\d\._U]|$)" />            <match name="filename" exp="npjp2\.dll" />                                    <versionRange  severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p302">
-      <match name="name" exp="Java\(TM\) Plug-in 1\.6\.0_(39|40|41)([^\d\._]|$)" />            <match name="filename" exp="libnpjp2\.so" />                                    <versionRange  severity="0" vulnerabilitystatus="2">
+      <match name="name" exp="Java\(TM\) Plug-in 1\.6\.0_(39|40|41)([^\d\._]|$)" />            <match name="filename" exp="libnpjp2\.so" />                                    <versionRange  severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p328">
                   <match name="filename" exp="Silverlight\.plugin" />                                    <versionRange  minVersion="5.1" maxVersion="5.1.20124.9999" severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
--- a/browser/components/search/test/browser_contextmenu.js
+++ b/browser/components/search/test/browser_contextmenu.js
@@ -25,28 +25,30 @@ function test() {
         break;
       case "engine-removed":
         Services.obs.removeObserver(observer, "browser-search-engine-modified");
         finish();
         break;
     }
   }
 
-  registerCleanupFunction(finalize);
   Services.obs.addObserver(observer, "browser-search-engine-modified", false);
   ss.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine_mozsearch.xml",
                Ci.nsISearchEngine.DATA_XML, "data:image/x-icon,%00",
                false);
 
   function startTest() {
     contextMenu = document.getElementById("contentAreaContextMenu");
     ok(contextMenu, "Got context menu XUL");
 
     doOnloadOnce(testContextMenu);
-    gBrowser.selectedTab = gBrowser.addTab("data:text/plain;charset=utf8,test%20search");
+    let tab = gBrowser.selectedTab = gBrowser.addTab("data:text/plain;charset=utf8,test%20search");
+    registerCleanupFunction(function () {
+      gBrowser.removeTab(tab);
+    });
   }
 
   function testContextMenu() {
     function rightClickOnDocument() {
       info("rightClickOnDocument: " + content.window.location);
       waitForBrowserContextMenu(checkContextMenu);
       var clickTarget = content.document.body;
       var eventDetails = { type: "contextmenu", button: 2 };
@@ -64,17 +66,19 @@ function test() {
       searchItem.click();
       contextMenu.hidePopup();
     }
 
     function checkSearchURL(event) {
       is(event.originalTarget.URL,
          "http://mochi.test:8888/browser/browser/components/search/test/?test=test+search&ie=utf-8&client=app&channel=contextsearch",
          "Checking context menu search URL");
-      finalize();
+      // Remove the tab opened by the search
+      gBrowser.removeCurrentTab();
+      ss.removeEngine(ss.currentEngine);
     }
 
     var selectionListener = {
       notifySelectionChanged: function(doc, sel, reason) {
         if (reason != Ci.nsISelectionListener.SELECTALL_REASON || sel.toString() != "test search")
           return;
         info("notifySelectionChanged: Text selected");
         content.window.getSelection().QueryInterface(Ci.nsISelectionPrivate).
@@ -88,19 +92,9 @@ function test() {
       info("delaySelectAll: " + content.window.location.toString());
       // add a listener to know when the selection takes effect
       content.window.getSelection().QueryInterface(Ci.nsISelectionPrivate).
                                     addSelectionListener(selectionListener);
       // select the text on the page
       goDoCommand('cmd_selectAll');
     }, 500);
   }
-
-  function finalize() {
-    while (gBrowser.tabs.length != 1) {
-      gBrowser.removeTab(gBrowser.tabs[0]);
-    }
-    content.location.href = "about:blank";
-    var engine = ss.getEngineByName(ENGINE_NAME);
-    if (engine)
-      ss.removeEngine(engine);
-  }
 }
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -524,22 +524,20 @@
 @BINPATH@/components/AppProtocolHandler.js
 @BINPATH@/components/AppProtocolHandler.manifest
 
 #ifdef MOZ_WEBRTC
 @BINPATH@/components/PeerConnection.js
 @BINPATH@/components/PeerConnection.manifest
 #endif
 
-#ifdef ENABLE_MARIONETTE
 @BINPATH@/chrome/marionette@JAREXT@
 @BINPATH@/chrome/marionette.manifest
 @BINPATH@/components/MarionetteComponents.manifest
 @BINPATH@/components/marionettecomponent.js
-#endif
 
 #ifdef MOZ_WEBSPEECH
 @BINPATH@/components/dom_webspeechsynth.xpt
 #endif
 
 ; Modules
 @BINPATH@/browser/modules/*
 @BINPATH@/modules/*
--- a/browser/metro/base/tests/mochitest/browser_history.js
+++ b/browser/metro/base/tests/mochitest/browser_history.js
@@ -7,28 +7,37 @@
 
 let gStartView = HistoryStartView._view;
 let gPanelView = HistoryPanelView._view;
 
 function test() {
   runTests();
 }
 
+function scrollToEnd() {
+  let startBox = document.getElementById("start-scrollbox");
+  let [, scrollInterface] = ScrollUtils.getScrollboxFromElement(startBox);
+
+  scrollInterface.scrollBy(50000, 0);
+}
+
 function setup() {
   PanelUI.hide();
   HistoryTestHelper.setup();
 
-  if (StartUI.isStartPageVisible)
-    return;
+  if (!StartUI.isStartPageVisible) {
+    yield addTab("about:start");
+
+    yield waitForCondition(() => StartUI.isStartPageVisible);
 
-  yield addTab("about:start");
+    yield hideContextUI();
+  }
 
-  yield waitForCondition(() => StartUI.isStartPageVisible);
-
-  yield hideContextUI();
+  // Scroll to make sure all tiles are visible.
+  scrollToEnd();
 }
 
 function tearDown() {
   PanelUI.hide();
   HistoryTestHelper.restore();
 }
 
 var HistoryTestHelper = {
@@ -161,16 +170,17 @@ gTests.push({
     ok(gStartView._set.itemCount === gStartView._limit, "Grid repopulated");
 
     // --------- unpin multiple items
 
     let item1 = gStartView._set.getItemsByUrl(uriFromIndex(0))[0];
     let item2 = gStartView._set.getItemsByUrl(uriFromIndex(5))[0];
     let item3 = gStartView._set.getItemsByUrl(uriFromIndex(12))[0];
 
+    scrollToEnd();
     let promise = waitForEvent(Elements.contextappbar, "transitionend", null, Elements.contextappbar);
     sendContextMenuClickToElement(window, item1, 10, 10);
     sendContextMenuClickToElement(window, item2, 10, 10);
     sendContextMenuClickToElement(window, item3, 10, 10);
     yield promise;
 
     ok(!unpinButton.hidden, "Unpin button is visible.");
 
@@ -264,16 +274,17 @@ gTests.push({
     let item1 = gStartView._set.getItemsByUrl(uriFromIndex(0))[0];
     let item2 = gStartView._set.getItemsByUrl(uriFromIndex(5))[0];
     let item3 = gStartView._set.getItemsByUrl(uriFromIndex(12))[0];
 
     let initialLocation1 = gStartView._set.getIndexOfItem(item1);
     let initialLocation2 = gStartView._set.getIndexOfItem(item2);
     let initialLocation3 = gStartView._set.getIndexOfItem(item3);
 
+    scrollToEnd();
     let promise = waitForEvent(Elements.contextappbar, "transitionend", null, Elements.contextappbar);
     sendContextMenuClickToElement(window, item1, 10, 10);
     sendContextMenuClickToElement(window, item2, 10, 10);
     sendContextMenuClickToElement(window, item3, 10, 10);
     yield promise;
 
     yield waitForCondition(() => !deleteButton.hidden);
 
@@ -308,16 +319,17 @@ gTests.push({
     ok(gStartView._set.itemCount === gStartView._limit, "Grid repopulated");
 
     // --------- delete multiple items for good
 
     let item1 = gStartView._set.getItemsByUrl(uriFromIndex(0))[0];
     let item2 = gStartView._set.getItemsByUrl(uriFromIndex(5))[0];
     let item3 = gStartView._set.getItemsByUrl(uriFromIndex(12))[0];
 
+    scrollToEnd();
     let promise = waitForEvent(Elements.contextappbar, "transitionend", null, Elements.contextappbar);
     sendContextMenuClickToElement(window, item1, 10, 10);
     sendContextMenuClickToElement(window, item2, 10, 10);
     sendContextMenuClickToElement(window, item3, 10, 10);
     yield promise;
 
     yield waitForCondition(() => !deleteButton.hidden);
 
@@ -386,16 +398,17 @@ gTests.push({
     ok(!gPanelView._pinHelper.isPinned(uriFromIndex(2)), "Item unpinned");
 
     // --------- unpin multiple items
 
     let item1 = gPanelView._set.getItemsByUrl(uriFromIndex(0))[0];
     let item2 = gPanelView._set.getItemsByUrl(uriFromIndex(5))[0];
     let item3 = gPanelView._set.getItemsByUrl(uriFromIndex(12))[0];
 
+    scrollToEnd();
     let promise = waitForEvent(Elements.contextappbar, "transitionend", null, Elements.contextappbar);
     sendContextMenuClickToElement(window, item1, 10, 10);
     sendContextMenuClickToElement(window, item2, 10, 10);
     sendContextMenuClickToElement(window, item3, 10, 10);
     yield promise;
 
     ok(!unpinButton.hidden, "Unpin button is visible.");
 
@@ -439,16 +452,17 @@ gTests.push({
     ok(gPanelView._pinHelper.isPinned(uriFromIndex(2)), "Item pinned");
 
     // --------- pin multiple items
 
     let item1 = gPanelView._set.getItemsByUrl(uriFromIndex(0))[0];
     let item2 = gPanelView._set.getItemsByUrl(uriFromIndex(5))[0];
     let item3 = gPanelView._set.getItemsByUrl(uriFromIndex(12))[0];
 
+    scrollToEnd();
     let promise = waitForEvent(Elements.contextappbar, "transitionend", null, Elements.contextappbar);
     sendContextMenuClickToElement(window, item1, 10, 10);
     sendContextMenuClickToElement(window, item2, 10, 10);
     sendContextMenuClickToElement(window, item3, 10, 10);
     yield promise;
 
     // Make sure app bar is updated
     yield waitForCondition(() => !pinButton.hidden);
@@ -516,16 +530,17 @@ gTests.push({
     ok(!HistoryTestHelper._nodes[uriFromIndex(2)], "Item RIP");
 
     // --------- delete multiple items
 
     let item1 = gPanelView._set.getItemsByUrl(uriFromIndex(0))[0];
     let item2 = gPanelView._set.getItemsByUrl(uriFromIndex(5))[0];
     let item3 = gPanelView._set.getItemsByUrl(uriFromIndex(12))[0];
 
+    scrollToEnd();
     let promise = waitForEvent(Elements.contextappbar, "transitionend", null, Elements.contextappbar);
     sendContextMenuClickToElement(window, item1, 10, 10);
     sendContextMenuClickToElement(window, item2, 10, 10);
     sendContextMenuClickToElement(window, item3, 10, 10);
     yield promise;
 
     ok(!deleteButton.hidden, "Delete button is visible.");
 
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -3837,33 +3837,50 @@ toolbar[mode="icons"] > *|* > .toolbarbu
 #social-share-panel {
   margin-top: 3px;
   max-height: 600px;
   min-height: 100px;
   max-width: 800px;
   min-width: 300px;
 }
 
-.social-share-frame {
-  border-top-left-radius: none;
-  border-bottom-left-radius: none;
+.social-share-frame:-moz-locale-dir(ltr) {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
   border-top-right-radius: inherit;
   border-bottom-right-radius: inherit;
 }
 
-#social-share-panel > .social-share-toolbar {
+.social-share-frame:-moz-locale-dir(rtl) {
+  border-top-left-radius: inherit;
+  border-bottom-left-radius: inherit;
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+
+#social-share-panel > .social-share-toolbar:-moz-locale-dir(ltr) {
   border-top-left-radius: inherit;
   border-bottom-left-radius: inherit;
 }
 
-#social-share-provider-buttons {
+#social-share-panel > .social-share-toolbar:-moz-locale-dir(rtl) {
+  border-top-right-radius: inherit;
+  border-bottom-right-radius: inherit;
+}
+
+#social-share-provider-buttons:-moz-locale-dir(ltr) {
   border-top-left-radius: inherit;
   border-bottom-left-radius: inherit;
 }
 
+#social-share-provider-buttons:-moz-locale-dir(rtl) {
+  border-top-right-radius: inherit;
+  border-bottom-right-radius: inherit;
+}
+
 /* === end of social toolbar provider menu === */
 
 %include ../shared/social/chat.inc.css
 
 .chat-titlebar {
   background-color: #d9d9d9;
   background-image: linear-gradient(rgba(255,255,255,.43), rgba(255,255,255,0));
 }
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -1790,34 +1790,54 @@ richlistitem[type~="action"][actiontype=
   max-width: 800px;
   min-width: 300px;
 }
 
 .social-share-frame {
   background: linear-gradient(to bottom, #f0f4f7, #fafbfc);
   width: 330px;
   height: 150px;
-  border-top-left-radius: none;
-  border-bottom-left-radius: none;
-  border-top-right-radius: inherit;
-  border-bottom-right-radius: inherit;
   /* we resize our panels dynamically, make it look nice */
   transition: height 100ms ease-out, width 100ms ease-out;
 }
 
-#social-share-panel > .social-share-toolbar {
+.social-share-frame:-moz-locale-dir(ltr) {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+  border-top-right-radius: inherit;
+  border-bottom-right-radius: inherit;
+}
+
+.social-share-frame:-moz-locale-dir(rtl) {
   border-top-left-radius: inherit;
   border-bottom-left-radius: inherit;
-}
-
-#social-share-provider-buttons {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+
+#social-share-panel > .social-share-toolbar:-moz-locale-dir(ltr) {
   border-top-left-radius: inherit;
   border-bottom-left-radius: inherit;
 }
 
+#social-share-panel > .social-share-toolbar:-moz-locale-dir(rtl) {
+  border-top-right-radius: inherit;
+  border-bottom-right-radius: inherit;
+}
+
+#social-share-provider-buttons:-moz-locale-dir(ltr) {
+  border-top-left-radius: inherit;
+  border-bottom-left-radius: inherit;
+}
+
+#social-share-provider-buttons:-moz-locale-dir(rtl) {
+  border-top-right-radius: inherit;
+  border-bottom-right-radius: inherit;
+}
+
 /* social recommending panel */
 
 #social-mark-button {
   -moz-image-region: rect(0, 16px, 16px, 0);
 }
 
 /* star button */
 
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -73,20 +73,16 @@ endif
 
 # Put a useful .gdbinit in the bin directory, to be picked up automatically
 # by GDB when we debug executables there.
 # NOTE: Keep .gdbinit in the topsrcdir for people who run gdb from the topsrcdir.
 GDBINIT_FILES := $(topsrcdir)/.gdbinit
 GDBINIT_DEST = $(FINAL_TARGET)
 INSTALL_TARGETS += GDBINIT
 
-PYTHON_UNIT_TESTS := \
-  tests/test.py \
-  $(NULL)
-
 include $(topsrcdir)/config/rules.mk
 
 # we install to _leaktest/
 TARGET_DEPTH = ..
 include $(srcdir)/automation-build.mk
 
 _LEAKTEST_DIR = $(DEPTH)/_leaktest
 
deleted file mode 100644
--- a/build/manifestparser.py
+++ /dev/null
@@ -1,1079 +0,0 @@
-#!/usr/bin/env 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/.
-
-"""
-Mozilla universal manifest parser
-"""
-
-# this file lives at
-# http://hg.mozilla.org/automation/ManifestDestiny/raw-file/tip/manifestparser.py
-
-__all__ = ['read_ini', # .ini reader
-           'ManifestParser', 'TestManifest', 'convert', # manifest handling
-           'parse', 'ParseError', 'ExpressionParser'] # conditional expression parser
-
-import os
-import re
-import shutil
-import sys
-from fnmatch import fnmatch
-from optparse import OptionParser
-
-version = '0.5.3' # package version
-try:
-    from setuptools import setup
-except:
-    setup = None
-
-# we need relpath, but it is introduced in python 2.6
-# http://docs.python.org/library/os.path.html
-try:
-    relpath = os.path.relpath
-except AttributeError:
-    def relpath(path, start):
-        """
-        Return a relative version of a path
-        from /usr/lib/python2.6/posixpath.py
-        """
-
-        if not path:
-            raise ValueError("no path specified")
-
-        start_list = os.path.abspath(start).split(os.path.sep)
-        path_list = os.path.abspath(path).split(os.path.sep)
-
-        # Work out how much of the filepath is shared by start and path.
-        i = len(os.path.commonprefix([start_list, path_list]))
-
-        rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
-        if not rel_list:
-            return os.curdir
-        return os.path.join(*rel_list)
-
-# expr.py
-# from:
-# http://k0s.org/mozilla/hg/expressionparser
-# http://hg.mozilla.org/users/tmielczarek_mozilla.com/expressionparser
-
-# Implements a top-down parser/evaluator for simple boolean expressions.
-# ideas taken from http://effbot.org/zone/simple-top-down-parsing.htm
-#
-# Rough grammar:
-# expr := literal
-#       | '(' expr ')'
-#       | expr '&&' expr
-#       | expr '||' expr
-#       | expr '==' expr
-#       | expr '!=' expr
-# literal := BOOL
-#          | INT
-#          | STRING
-#          | IDENT
-# BOOL   := true|false
-# INT    := [0-9]+
-# STRING := "[^"]*"
-# IDENT  := [A-Za-z_]\w*
-
-# Identifiers take their values from a mapping dictionary passed as the second
-# argument.
-
-# Glossary (see above URL for details):
-# - nud: null denotation
-# - led: left detonation
-# - lbp: left binding power
-# - rbp: right binding power
-
-class ident_token(object):
-    def __init__(self, value):
-        self.value = value
-    def nud(self, parser):
-        # identifiers take their value from the value mappings passed
-        # to the parser
-        return parser.value(self.value)
-
-class literal_token(object):
-    def __init__(self, value):
-        self.value = value
-    def nud(self, parser):
-        return self.value
-
-class eq_op_token(object):
-    "=="
-    def led(self, parser, left):
-        return left == parser.expression(self.lbp)
-    
-class neq_op_token(object):
-    "!="
-    def led(self, parser, left):
-        return left != parser.expression(self.lbp)
-
-class not_op_token(object):
-    "!"
-    def nud(self, parser):
-        return not parser.expression()
-
-class and_op_token(object):
-    "&&"
-    def led(self, parser, left):
-        right = parser.expression(self.lbp)
-        return left and right
-    
-class or_op_token(object):
-    "||"
-    def led(self, parser, left):
-        right = parser.expression(self.lbp)
-        return left or right
-
-class lparen_token(object):
-    "("
-    def nud(self, parser):
-        expr = parser.expression()
-        parser.advance(rparen_token)
-        return expr
-
-class rparen_token(object):
-    ")"
-
-class end_token(object):
-    """always ends parsing"""
-
-### derived literal tokens
-
-class bool_token(literal_token):
-    def __init__(self, value):
-        value = {'true':True, 'false':False}[value]
-        literal_token.__init__(self, value)
-
-class int_token(literal_token):
-    def __init__(self, value):
-        literal_token.__init__(self, int(value))
-
-class string_token(literal_token):
-    def __init__(self, value):
-        literal_token.__init__(self, value[1:-1])
-
-precedence = [(end_token, rparen_token),
-              (or_op_token,),
-              (and_op_token,),
-              (eq_op_token, neq_op_token),
-              (lparen_token,),
-              ]
-for index, rank in enumerate(precedence):
-    for token in rank:
-        token.lbp = index # lbp = lowest left binding power
-
-class ParseError(Exception):
-    """errror parsing conditional expression"""
-
-class ExpressionParser(object):
-    def __init__(self, text, valuemapping, strict=False):
-        """
-        Initialize the parser with input |text|, and |valuemapping| as
-        a dict mapping identifier names to values.
-        """
-        self.text = text
-        self.valuemapping = valuemapping
-        self.strict = strict
-
-    def _tokenize(self):
-        """
-        Lex the input text into tokens and yield them in sequence.
-        """
-        # scanner callbacks
-        def bool_(scanner, t): return bool_token(t)
-        def identifier(scanner, t): return ident_token(t)
-        def integer(scanner, t): return int_token(t)
-        def eq(scanner, t): return eq_op_token()
-        def neq(scanner, t): return neq_op_token()
-        def or_(scanner, t): return or_op_token()
-        def and_(scanner, t): return and_op_token()
-        def lparen(scanner, t): return lparen_token()
-        def rparen(scanner, t): return rparen_token()
-        def string_(scanner, t): return string_token(t)
-        def not_(scanner, t): return not_op_token()
-
-        scanner = re.Scanner([
-            (r"true|false", bool_),
-            (r"[a-zA-Z_]\w*", identifier),
-            (r"[0-9]+", integer),
-            (r'("[^"]*")|(\'[^\']*\')', string_),
-            (r"==", eq),
-            (r"!=", neq),
-            (r"\|\|", or_),
-            (r"!", not_),
-            (r"&&", and_),
-            (r"\(", lparen),
-            (r"\)", rparen),
-            (r"\s+", None), # skip whitespace
-            ])
-        tokens, remainder = scanner.scan(self.text)
-        for t in tokens:
-            yield t
-        yield end_token()
-
-    def value(self, ident):
-        """
-        Look up the value of |ident| in the value mapping passed in the
-        constructor.
-        """
-        if self.strict:
-            return self.valuemapping[ident]
-        else:
-            return self.valuemapping.get(ident, None)
-
-    def advance(self, expected):
-        """
-        Assert that the next token is an instance of |expected|, and advance
-        to the next token.
-        """
-        if not isinstance(self.token, expected):
-            raise Exception, "Unexpected token!"
-        self.token = self.iter.next()
-        
-    def expression(self, rbp=0):
-        """
-        Parse and return the value of an expression until a token with
-        right binding power greater than rbp is encountered.
-        """
-        t = self.token
-        self.token = self.iter.next()
-        left = t.nud(self)
-        while rbp < self.token.lbp:
-            t = self.token
-            self.token = self.iter.next()
-            left = t.led(self, left)
-        return left
-
-    def parse(self):
-        """
-        Parse and return the value of the expression in the text
-        passed to the constructor. Raises a ParseError if the expression
-        could not be parsed.
-        """
-        try:
-            self.iter = self._tokenize()
-            self.token = self.iter.next()
-            return self.expression()
-        except:
-            raise ParseError("could not parse: %s; variables: %s" % (self.text, self.valuemapping))
-
-    __call__ = parse
-
-def parse(text, **values):
-    """
-    Parse and evaluate a boolean expression in |text|. Use |values| to look
-    up the value of identifiers referenced in the expression. Returns the final
-    value of the expression. A ParseError will be raised if parsing fails.
-    """
-    return ExpressionParser(text, values).parse()
-
-def normalize_path(path):
-    """normalize a relative path"""
-    if sys.platform.startswith('win'):
-        return path.replace('/', os.path.sep)
-    return path
-
-def denormalize_path(path):
-    """denormalize a relative path"""
-    if sys.platform.startswith('win'):
-        return path.replace(os.path.sep, '/')
-    return path
-    
-
-def read_ini(fp, variables=None, default='DEFAULT',
-             comments=';#', separators=('=', ':'),
-             strict=True):
-    """
-    read an .ini file and return a list of [(section, values)]
-    - fp : file pointer or path to read
-    - variables : default set of variables
-    - default : name of the section for the default section
-    - comments : characters that if they start a line denote a comment
-    - separators : strings that denote key, value separation in order
-    - strict : whether to be strict about parsing
-    """
-
-    if variables is None:
-        variables = {}
-
-    if isinstance(fp, basestring):
-        fp = file(fp)
-
-    sections = []
-    key = value = None
-    section_names = set([])
-
-    # read the lines
-    for line in fp.readlines():
-
-        stripped = line.strip()
-
-        # ignore blank lines
-        if not stripped:
-            # reset key and value to avoid continuation lines
-            key = value = None
-            continue
-
-        # ignore comment lines
-        if stripped[0] in comments:
-            continue
-
-        # check for a new section
-        if len(stripped) > 2 and stripped[0] == '[' and stripped[-1] == ']':
-            section = stripped[1:-1].strip()
-            key = value = None
-
-            # deal with DEFAULT section
-            if section.lower() == default.lower():
-                if strict:
-                    assert default not in section_names
-                section_names.add(default)
-                current_section = variables
-                continue
-
-            if strict:
-                # make sure this section doesn't already exist
-                assert section not in section_names
-
-            section_names.add(section)
-            current_section = {}
-            sections.append((section, current_section))
-            continue
-
-        # if there aren't any sections yet, something bad happen
-        if not section_names:
-            raise Exception('No sections found')
-
-        # (key, value) pair
-        for separator in separators:
-            if separator in stripped:
-                key, value = stripped.split(separator, 1)
-                key = key.strip()
-                value = value.strip()
-
-                if strict:
-                    # make sure this key isn't already in the section or empty
-                    assert key
-                    if current_section is not variables:
-                        assert key not in current_section
-
-                current_section[key] = value
-                break
-        else:
-            # continuation line ?
-            if line[0].isspace() and key:
-                value = '%s%s%s' % (value, os.linesep, stripped)
-                current_section[key] = value
-            else:
-                # something bad happen!
-                raise Exception("Not sure what you're trying to do")
-
-    # interpret the variables
-    def interpret_variables(global_dict, local_dict):
-        variables = global_dict.copy()
-        variables.update(local_dict)
-        return variables
-
-    sections = [(i, interpret_variables(variables, j)) for i, j in sections]
-    return sections
-
-
-### objects for parsing manifests
-
-class ManifestParser(object):
-    """read .ini manifests"""
-
-    ### methods for reading manifests
-
-    def __init__(self, manifests=(), defaults=None, strict=True):
-        self._defaults = defaults or {}
-        self.tests = []
-        self.strict = strict
-        self.rootdir = None
-        self.relativeRoot = None
-        if manifests:
-            self.read(*manifests)
-
-    def getRelativeRoot(self, root):
-        return root
-
-    def read(self, *filenames, **defaults):
-
-        # ensure all files exist
-        missing = [ filename for filename in filenames
-                    if not os.path.exists(filename) ]
-        if missing:
-            raise IOError('Missing files: %s' % ', '.join(missing))
-
-        # process each file
-        for filename in filenames:
-
-            # set the per file defaults
-            defaults = defaults.copy() or self._defaults.copy()
-            here = os.path.dirname(os.path.abspath(filename))
-            defaults['here'] = here
-
-            if self.rootdir is None:
-                # set the root directory
-                # == the directory of the first manifest given
-                self.rootdir = here
-
-            # read the configuration
-            sections = read_ini(fp=filename, variables=defaults, strict=self.strict)
-
-            # get the tests
-            for section, data in sections:
-
-                # a file to include
-                # TODO: keep track of included file structure:
-                # self.manifests = {'manifest.ini': 'relative/path.ini'}
-                if section.startswith('include:'):
-                    include_file = section.split('include:', 1)[-1]
-                    include_file = normalize_path(include_file)
-                    if not os.path.isabs(include_file):
-                        include_file = os.path.join(self.getRelativeRoot(here), include_file)
-                    if not os.path.exists(include_file):
-                        if self.strict:
-                            raise IOError("File '%s' does not exist" % include_file)
-                        else:
-                            continue
-                    include_defaults = data.copy()
-                    self.read(include_file, **include_defaults)
-                    continue
-
-                # otherwise an item
-                test = data
-                test['name'] = section
-                test['manifest'] = os.path.abspath(filename)
-
-                # determine the path
-                path = test.get('path', section)
-                if '://' not in path: # don't futz with URLs
-                    path = normalize_path(path)
-                    if not os.path.isabs(path):
-                        path = os.path.join(here, path)
-                test['path'] = path
-
-                # append the item
-                self.tests.append(test)
-
-    ### methods for querying manifests
-
-    def query(self, *checks, **kw):
-        """
-        general query function for tests
-        - checks : callable conditions to test if the test fulfills the query
-        """
-        tests = kw.get('tests', None)
-        if tests is None:
-            tests = self.tests
-        retval = []
-        for test in tests:
-            for check in checks:
-                if not check(test):
-                    break
-            else:
-                retval.append(test)
-        return retval
-
-    def get(self, _key=None, inverse=False, tags=None, tests=None, **kwargs):
-        # TODO: pass a dict instead of kwargs since you might hav
-        # e.g. 'inverse' as a key in the dict
-
-        # TODO: tags should just be part of kwargs with None values
-        # (None == any is kinda weird, but probably still better)
-
-        # fix up tags
-        if tags:
-            tags = set(tags)
-        else:
-            tags = set()
-
-        # make some check functions
-        if inverse:
-            has_tags = lambda test: not tags.intersection(test.keys())
-            def dict_query(test):
-                for key, value in kwargs.items():
-                    if test.get(key) == value:
-                        return False
-                return True
-        else:
-            has_tags = lambda test: tags.issubset(test.keys())
-            def dict_query(test):
-                for key, value in kwargs.items():
-                    if test.get(key) != value:
-                        return False
-                return True
-
-        # query the tests
-        tests = self.query(has_tags, dict_query, tests=tests)
-
-        # if a key is given, return only a list of that key
-        # useful for keys like 'name' or 'path'
-        if _key:
-            return [test[_key] for test in tests]
-
-        # return the tests
-        return tests
-
-    def missing(self, tests=None):
-        """return list of tests that do not exist on the filesystem"""
-        if tests is None:
-            tests = self.tests
-        return [test for test in tests
-                if not os.path.exists(test['path'])]
-
-    def manifests(self, tests=None):
-        """
-        return manifests in order in which they appear in the tests
-        """
-        if tests is None:
-            tests = self.tests
-        manifests = []
-        for test in tests:
-            manifest = test.get('manifest')
-            if not manifest:
-                continue
-            if manifest not in manifests:
-                manifests.append(manifest)
-        return manifests
-
-    ### methods for outputting from manifests
-
-    def write(self, fp=sys.stdout, rootdir=None,
-              global_tags=None, global_kwargs=None,
-              local_tags=None, local_kwargs=None):
-        """
-        write a manifest given a query
-        global and local options will be munged to do the query
-        globals will be written to the top of the file
-        locals (if given) will be written per test
-        """
-
-        # root directory
-        if rootdir is None:
-            rootdir = self.rootdir
-
-        # sanitize input
-        global_tags = global_tags or set()
-        local_tags = local_tags or set()
-        global_kwargs = global_kwargs or {}
-        local_kwargs = local_kwargs or {}
-        
-        # create the query
-        tags = set([])
-        tags.update(global_tags)
-        tags.update(local_tags)
-        kwargs = {}
-        kwargs.update(global_kwargs)
-        kwargs.update(local_kwargs)
-
-        # get matching tests
-        tests = self.get(tags=tags, **kwargs)
-
-        # print the .ini manifest
-        if global_tags or global_kwargs:
-            print >> fp, '[DEFAULT]'
-            for tag in global_tags:
-                print >> fp, '%s =' % tag
-            for key, value in global_kwargs.items():
-                print >> fp, '%s = %s' % (key, value)
-            print >> fp
-
-        for test in tests:
-            test = test.copy() # don't overwrite
-
-            path = test['name']
-            if not os.path.isabs(path):
-                path = denormalize_path(relpath(test['path'], self.rootdir))
-            print >> fp, '[%s]' % path
-          
-            # reserved keywords:
-            reserved = ['path', 'name', 'here', 'manifest']
-            for key in sorted(test.keys()):
-                if key in reserved:
-                    continue
-                if key in global_kwargs:
-                    continue
-                if key in global_tags and not test[key]:
-                    continue
-                print >> fp, '%s = %s' % (key, test[key])
-            print >> fp
-
-    def copy(self, directory, rootdir=None, *tags, **kwargs):
-        """
-        copy the manifests and associated tests
-        - directory : directory to copy to
-        - rootdir : root directory to copy to (if not given from manifests)
-        - tags : keywords the tests must have
-        - kwargs : key, values the tests must match
-        """
-        # XXX note that copy does *not* filter the tests out of the
-        # resulting manifest; it just stupidly copies them over.
-        # ideally, it would reread the manifests and filter out the
-        # tests that don't match *tags and **kwargs
-        
-        # destination
-        if not os.path.exists(directory):
-            os.path.makedirs(directory)
-        else:
-            # sanity check
-            assert os.path.isdir(directory)
-
-        # tests to copy
-        tests = self.get(tags=tags, **kwargs)
-        if not tests:
-            return # nothing to do!
-
-        # root directory
-        if rootdir is None:
-            rootdir = self.rootdir
-
-        # copy the manifests + tests
-        manifests = [relpath(manifest, rootdir) for manifest in self.manifests()]
-        for manifest in manifests:
-            destination = os.path.join(directory, manifest)
-            dirname = os.path.dirname(destination)
-            if not os.path.exists(dirname):
-                os.makedirs(dirname)
-            else:
-                # sanity check
-                assert os.path.isdir(dirname)
-            shutil.copy(os.path.join(rootdir, manifest), destination)
-        for test in tests:
-            if os.path.isabs(test['name']):
-                continue
-            source = test['path']
-            if not os.path.exists(source):
-                print >> sys.stderr, "Missing test: '%s' does not exist!" % source
-                continue
-                # TODO: should err on strict
-            destination = os.path.join(directory, relpath(test['path'], rootdir))
-            shutil.copy(source, destination)
-            # TODO: ensure that all of the tests are below the from_dir
-
-    def update(self, from_dir, rootdir=None, *tags, **kwargs):
-        """
-        update the tests as listed in a manifest from a directory
-        - from_dir : directory where the tests live
-        - rootdir : root directory to copy to (if not given from manifests)
-        - tags : keys the tests must have
-        - kwargs : key, values the tests must match
-        """
-    
-        # get the tests
-        tests = self.get(tags=tags, **kwargs)
-
-        # get the root directory
-        if not rootdir:
-            rootdir = self.rootdir
-
-        # copy them!
-        for test in tests:
-            if not os.path.isabs(test['name']):
-                _relpath = relpath(test['path'], rootdir)
-                source = os.path.join(from_dir, _relpath)
-                if not os.path.exists(source):
-                    # TODO err on strict
-                    print >> sys.stderr, "Missing test: '%s'; skipping" % test['name']
-                    continue
-                destination = os.path.join(rootdir, _relpath)
-                shutil.copy(source, destination)
-
-
-class TestManifest(ManifestParser):
-    """
-    apply logic to manifests;  this is your integration layer :)
-    specific harnesses may subclass from this if they need more logic
-    """
-
-    def filter(self, values, tests):
-        """
-        filter on a specific list tag, e.g.:
-        run-if.os = win linux
-        skip-if.os = mac
-        """
-
-        # tags:
-        run_tag = 'run-if'
-        skip_tag = 'skip-if'
-        fail_tag = 'fail-if'
-
-        # loop over test
-        for test in tests:
-            reason = None # reason to disable
-            
-            # tagged-values to run
-            if run_tag in test:
-                condition = test[run_tag]
-                if not parse(condition, **values):
-                    reason = '%s: %s' % (run_tag, condition)
-
-            # tagged-values to skip
-            if skip_tag in test:
-                condition = test[skip_tag]
-                if parse(condition, **values):
-                    reason = '%s: %s' % (skip_tag, condition)
-
-            # mark test as disabled if there's a reason
-            if reason:
-                test.setdefault('disabled', reason)        
-
-            # mark test as a fail if so indicated
-            if fail_tag in test:
-                condition = test[fail_tag]
-                if parse(condition, **values):
-                    test['expected'] = 'fail'
-
-    def active_tests(self, exists=True, disabled=True, **values):
-        """
-        - exists : return only existing tests
-        - disabled : whether to return disabled tests
-        - tags : keys and values to filter on (e.g. `os = linux mac`)
-        """
-
-        tests = [i.copy() for i in self.tests] # shallow copy
-
-        # mark all tests as passing unless indicated otherwise
-        for test in tests:
-            test['expected'] = test.get('expected', 'pass')
-        
-        # ignore tests that do not exist
-        if exists:
-            tests = [test for test in tests if os.path.exists(test['path'])]
-
-        # filter by tags
-        self.filter(values, tests)
-
-        # ignore disabled tests if specified
-        if not disabled:
-            tests = [test for test in tests
-                     if not 'disabled' in test]
-
-        # return active tests
-        return tests
-
-    def test_paths(self):
-        return [test['path'] for test in self.active_tests()]
-
-
-### utility function(s); probably belongs elsewhere
-
-def convert(directories, pattern=None, ignore=(), write=None):
-    """
-    convert directories to a simple manifest
-    """
-
-    retval = []
-    include = []
-    for directory in directories:
-        for dirpath, dirnames, filenames in os.walk(directory):
-
-            # filter out directory names
-            dirnames = [ i for i in dirnames if i not in ignore ]
-            dirnames.sort()
-
-            # reference only the subdirectory
-            _dirpath = dirpath
-            dirpath = dirpath.split(directory, 1)[-1].strip(os.path.sep)
-
-            if dirpath.split(os.path.sep)[0] in ignore:
-                continue
-
-            # filter by glob
-            if pattern:
-                filenames = [filename for filename in filenames
-                             if fnmatch(filename, pattern)]
-
-            filenames.sort()
-
-            # write a manifest for each directory
-            if write and (dirnames or filenames):
-                manifest = file(os.path.join(_dirpath, write), 'w')
-                for dirname in dirnames:
-                    print >> manifest, '[include:%s]' % os.path.join(dirname, write)
-                for filename in filenames:
-                    print >> manifest, '[%s]' % filename
-                manifest.close()
-
-            # add to the list
-            retval.extend([denormalize_path(os.path.join(dirpath, filename))
-                           for filename in filenames])
-
-    if write:
-        return # the manifests have already been written!
-  
-    retval.sort()
-    retval = ['[%s]' % filename for filename in retval]
-    return '\n'.join(retval)
-
-### command line attributes
-
-class ParserError(Exception):
-  """error for exceptions while parsing the command line"""
-
-def parse_args(_args):
-    """
-    parse and return:
-    --keys=value (or --key value)
-    -tags
-    args
-    """
-
-    # return values
-    _dict = {}
-    tags = []
-    args = []
-
-    # parse the arguments
-    key = None
-    for arg in _args:
-        if arg.startswith('---'):
-            raise ParserError("arguments should start with '-' or '--' only")
-        elif arg.startswith('--'):
-            if key:
-                raise ParserError("Key %s still open" % key)
-            key = arg[2:]
-            if '=' in key:
-                key, value = key.split('=', 1)
-                _dict[key] = value
-                key = None
-                continue
-        elif arg.startswith('-'):
-            if key:
-                raise ParserError("Key %s still open" % key)
-            tags.append(arg[1:])
-            continue
-        else:
-            if key:
-                _dict[key] = arg
-                continue
-            args.append(arg)
-
-    # return values
-    return (_dict, tags, args)
-
-
-### classes for subcommands
-
-class CLICommand(object):
-    usage = '%prog [options] command'
-    def __init__(self, parser):
-      self._parser = parser # master parser
-    def parser(self):
-      return OptionParser(usage=self.usage, description=self.__doc__,
-                          add_help_option=False)
-
-class Copy(CLICommand):
-    usage = '%prog [options] copy manifest directory -tag1 -tag2 --key1=value1 --key2=value2 ...'
-    def __call__(self, options, args):
-      # parse the arguments
-      try:
-        kwargs, tags, args = parse_args(args)
-      except ParserError, e:
-        self._parser.error(e.message)
-
-      # make sure we have some manifests, otherwise it will
-      # be quite boring
-      if not len(args) == 2:
-        HelpCLI(self._parser)(options, ['copy'])
-        return
-
-      # read the manifests
-      # TODO: should probably ensure these exist here
-      manifests = ManifestParser()
-      manifests.read(args[0])
-
-      # print the resultant query
-      manifests.copy(args[1], None, *tags, **kwargs)
-
-
-class CreateCLI(CLICommand):
-    """
-    create a manifest from a list of directories
-    """
-    usage = '%prog [options] create directory <directory> <...>'
-
-    def parser(self):
-        parser = CLICommand.parser(self)
-        parser.add_option('-p', '--pattern', dest='pattern',
-                          help="glob pattern for files")
-        parser.add_option('-i', '--ignore', dest='ignore',
-                          default=[], action='append',
-                          help='directories to ignore')
-        parser.add_option('-w', '--in-place', dest='in_place',
-                          help='Write .ini files in place; filename to write to')
-        return parser
-
-    def __call__(self, _options, args):
-        parser = self.parser()
-        options, args = parser.parse_args(args)
-
-        # need some directories
-        if not len(args):
-            parser.print_usage()
-            return
-
-        # add the directories to the manifest
-        for arg in args:
-            assert os.path.exists(arg)
-            assert os.path.isdir(arg)
-            manifest = convert(args, pattern=options.pattern, ignore=options.ignore,
-                               write=options.in_place)
-        if manifest:
-            print manifest
-
-
-class WriteCLI(CLICommand):
-    """
-    write a manifest based on a query
-    """
-    usage = '%prog [options] write manifest <manifest> -tag1 -tag2 --key1=value1 --key2=value2 ...'
-    def __call__(self, options, args):
-
-        # parse the arguments
-        try:
-            kwargs, tags, args = parse_args(args)
-        except ParserError, e:
-            self._parser.error(e.message)
-
-        # make sure we have some manifests, otherwise it will
-        # be quite boring
-        if not args:
-            HelpCLI(self._parser)(options, ['write'])
-            return
-
-        # read the manifests
-        # TODO: should probably ensure these exist here
-        manifests = ManifestParser()
-        manifests.read(*args)
-
-        # print the resultant query
-        manifests.write(global_tags=tags, global_kwargs=kwargs)
-      
-
-class HelpCLI(CLICommand):
-    """
-    get help on a command
-    """
-    usage = '%prog [options] help [command]'
-
-    def __call__(self, options, args):
-        if len(args) == 1 and args[0] in commands:
-            commands[args[0]](self._parser).parser().print_help()
-        else:
-            self._parser.print_help()
-            print '\nCommands:'
-            for command in sorted(commands):
-                print '  %s : %s' % (command, commands[command].__doc__.strip())
-
-class SetupCLI(CLICommand):
-    """
-    setup using setuptools
-    """
-    # use setup.py from the repo when you want to distribute to python!
-    # otherwise setuptools will complain that it can't find setup.py
-    # and result in a useless package
-    
-    usage = '%prog [options] setup [setuptools options]'
-    
-    def __call__(self, options, args):
-        sys.argv = [sys.argv[0]] + args
-        assert setup is not None, "You must have setuptools installed to use SetupCLI"
-        here = os.path.dirname(os.path.abspath(__file__))
-        try:
-            filename = os.path.join(here, 'README.txt')
-            description = file(filename).read()
-        except:    
-            description = ''
-        os.chdir(here)
-
-        setup(name='ManifestDestiny',
-              version=version,
-              description="Universal manifests for Mozilla test harnesses",
-              long_description=description,
-              classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
-              keywords='mozilla manifests',
-              author='Jeff Hammel',
-              author_email='jhammel@mozilla.com',
-              url='https://wiki.mozilla.org/Auto-tools/Projects/ManifestDestiny',
-              license='MPL',
-              zip_safe=False,
-              py_modules=['manifestparser'],
-              install_requires=[
-                  # -*- Extra requirements: -*-
-                  ],
-              entry_points="""
-              [console_scripts]
-              manifestparser = manifestparser:main
-              """,
-              )
-
-
-class UpdateCLI(CLICommand):
-    """
-    update the tests as listed in a manifest from a directory
-    """
-    usage = '%prog [options] update manifest directory -tag1 -tag2 --key1=value1 --key2=value2 ...'
-
-    def __call__(self, options, args):
-        # parse the arguments
-        try:
-            kwargs, tags, args = parse_args(args)
-        except ParserError, e:
-            self._parser.error(e.message)
-
-        # make sure we have some manifests, otherwise it will
-        # be quite boring
-        if not len(args) == 2:
-            HelpCLI(self._parser)(options, ['update'])
-            return
-
-        # read the manifests
-        # TODO: should probably ensure these exist here
-        manifests = ManifestParser()
-        manifests.read(args[0])
-
-        # print the resultant query
-        manifests.update(args[1], None, *tags, **kwargs)
-
-
-# command -> class mapping
-commands = { 'create': CreateCLI,
-             'help': HelpCLI,
-             'update': UpdateCLI,
-             'write': WriteCLI }
-if setup is not None:
-    commands['setup'] = SetupCLI
-
-def main(args=sys.argv[1:]):
-    """console_script entry point"""
-
-    # set up an option parser
-    usage = '%prog [options] [command] ...'
-    description = __doc__
-    parser = OptionParser(usage=usage, description=description)
-    parser.add_option('-s', '--strict', dest='strict',
-                      action='store_true', default=False,
-                      help='adhere strictly to errors')
-    parser.disable_interspersed_args()
-
-    options, args = parser.parse_args(args)
-
-    if not args:
-        HelpCLI(parser)(options, args)
-        parser.exit()
-
-    # get the command
-    command = args[0]
-    if command not in commands:
-        parser.error("Command must be one of %s (you gave '%s')" % (', '.join(sorted(commands.keys())), command))
-
-    handler = commands[command](parser)
-    handler(options, args[1:])
-
-if __name__ == '__main__':
-    main()
deleted file mode 100644
--- a/build/tests/filter-example.ini
+++ /dev/null
@@ -1,11 +0,0 @@
-# illustrate test filters based on various categories
-
-[windowstest]
-run-if = os == 'win'
-
-[fleem]
-skip-if = os == 'mac'
-
-[linuxtest]
-skip-if = (os == 'mac') || (os == 'win')
-fail-if = toolkit == 'cocoa'
deleted file mode 100644
--- a/build/tests/fleem
+++ /dev/null
@@ -1,1 +0,0 @@
-# dummy spot for "fleem" test
deleted file mode 100644
--- a/build/tests/include-example.ini
+++ /dev/null
@@ -1,11 +0,0 @@
-[DEFAULT]
-foo = bar
-
-[include:include/bar.ini]
-
-[fleem]
-
-[include:include/foo.ini]
-red = roses
-blue = violets
-yellow = daffodils
\ No newline at end of file
deleted file mode 100644
--- a/build/tests/include/bar.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[DEFAULT]
-foo = fleem
-
-[crash-handling]
\ No newline at end of file
deleted file mode 100644
--- a/build/tests/include/crash-handling
+++ /dev/null
@@ -1,1 +0,0 @@
-# dummy spot for "crash-handling" test
deleted file mode 100644
--- a/build/tests/include/flowers
+++ /dev/null
@@ -1,1 +0,0 @@
-# dummy spot for "flowers" test
deleted file mode 100644
--- a/build/tests/include/foo.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[DEFAULT]
-blue = ocean
-
-[flowers]
-yellow = submarine
\ No newline at end of file
deleted file mode 100644
--- a/build/tests/mozmill-example.ini
+++ /dev/null
@@ -1,80 +0,0 @@
-[testAddons/testDisableEnablePlugin.js]
-[testAddons/testGetAddons.js]
-[testAddons/testSearchAddons.js]
-[testAwesomeBar/testAccessLocationBar.js]
-[testAwesomeBar/testCheckItemHighlight.js]
-[testAwesomeBar/testEscapeAutocomplete.js]
-[testAwesomeBar/testFaviconInAutocomplete.js]
-[testAwesomeBar/testGoButton.js]
-[testAwesomeBar/testLocationBarSearches.js]
-[testAwesomeBar/testPasteLocationBar.js]
-[testAwesomeBar/testSuggestHistoryBookmarks.js]
-[testAwesomeBar/testVisibleItemsMax.js]
-[testBookmarks/testAddBookmarkToMenu.js]
-[testCookies/testDisableCookies.js]
-[testCookies/testEnableCookies.js]
-[testCookies/testRemoveAllCookies.js]
-[testCookies/testRemoveCookie.js]
-[testDownloading/testCloseDownloadManager.js]
-[testDownloading/testDownloadStates.js]
-[testDownloading/testOpenDownloadManager.js]
-[testFindInPage/testFindInPage.js]
-[testFormManager/testAutoCompleteOff.js]
-[testFormManager/testBasicFormCompletion.js]
-[testFormManager/testClearFormHistory.js]
-[testFormManager/testDisableFormManager.js]
-[testGeneral/testGoogleSuggestions.js]
-[testGeneral/testStopReloadButtons.js]
-[testInstallation/testBreakpadInstalled.js]
-[testLayout/testNavigateFTP.js]
-[testPasswordManager/testPasswordNotSaved.js]
-[testPasswordManager/testPasswordSavedAndDeleted.js]
-[testPopups/testPopupsAllowed.js]
-[testPopups/testPopupsBlocked.js]
-[testPreferences/testPaneRetention.js]
-[testPreferences/testPreferredLanguage.js]
-[testPreferences/testRestoreHomepageToDefault.js]
-[testPreferences/testSetToCurrentPage.js]
-[testPreferences/testSwitchPanes.js]
-[testPrivateBrowsing/testAboutPrivateBrowsing.js]
-[testPrivateBrowsing/testCloseWindow.js]
-[testPrivateBrowsing/testDisabledElements.js]
-[testPrivateBrowsing/testDisabledPermissions.js]
-[testPrivateBrowsing/testDownloadManagerClosed.js]
-[testPrivateBrowsing/testGeolocation.js]
-[testPrivateBrowsing/testStartStopPBMode.js]
-[testPrivateBrowsing/testTabRestoration.js]
-[testPrivateBrowsing/testTabsDismissedOnStop.js]
-[testSearch/testAddMozSearchProvider.js]
-[testSearch/testFocusAndSearch.js]
-[testSearch/testGetMoreSearchEngines.js]
-[testSearch/testOpenSearchAutodiscovery.js]
-[testSearch/testRemoveSearchEngine.js]
-[testSearch/testReorderSearchEngines.js]
-[testSearch/testRestoreDefaults.js]
-[testSearch/testSearchSelection.js]
-[testSearch/testSearchSuggestions.js]
-[testSecurity/testBlueLarry.js]
-[testSecurity/testDefaultPhishingEnabled.js]
-[testSecurity/testDefaultSecurityPrefs.js]
-[testSecurity/testEncryptedPageWarning.js]
-[testSecurity/testGreenLarry.js]
-[testSecurity/testGreyLarry.js]
-[testSecurity/testIdentityPopupOpenClose.js]
-[testSecurity/testSSLDisabledErrorPage.js]
-[testSecurity/testSafeBrowsingNotificationBar.js]
-[testSecurity/testSafeBrowsingWarningPages.js]
-[testSecurity/testSecurityInfoViaMoreInformation.js]
-[testSecurity/testSecurityNotification.js]
-[testSecurity/testSubmitUnencryptedInfoWarning.js]
-[testSecurity/testUnknownIssuer.js]
-[testSecurity/testUntrustedConnectionErrorPage.js]
-[testSessionStore/testUndoTabFromContextMenu.js]
-[testTabbedBrowsing/testBackgroundTabScrolling.js]
-[testTabbedBrowsing/testCloseTab.js]
-[testTabbedBrowsing/testNewTab.js]
-[testTabbedBrowsing/testNewWindow.js]
-[testTabbedBrowsing/testOpenInBackground.js]
-[testTabbedBrowsing/testOpenInForeground.js]
-[testTechnicalTools/testAccessPageInfoDialog.js]
-[testToolbar/testBackForwardButtons.js]
deleted file mode 100644
--- a/build/tests/mozmill-restart-example.ini
+++ /dev/null
@@ -1,26 +0,0 @@
-[DEFAULT]
-type = restart
-
-[restartTests/testExtensionInstallUninstall/test2.js]
-foo = bar
-
-[restartTests/testExtensionInstallUninstall/test1.js]
-foo = baz
-
-[restartTests/testExtensionInstallUninstall/test3.js]
-[restartTests/testSoftwareUpdateAutoProxy/test2.js]
-[restartTests/testSoftwareUpdateAutoProxy/test1.js]
-[restartTests/testMasterPassword/test1.js]
-[restartTests/testExtensionInstallGetAddons/test2.js]
-[restartTests/testExtensionInstallGetAddons/test1.js]
-[restartTests/testMultipleExtensionInstallation/test2.js]
-[restartTests/testMultipleExtensionInstallation/test1.js]
-[restartTests/testThemeInstallUninstall/test2.js]
-[restartTests/testThemeInstallUninstall/test1.js]
-[restartTests/testThemeInstallUninstall/test3.js]
-[restartTests/testDefaultBookmarks/test1.js]
-[softwareUpdate/testFallbackUpdate/test2.js]
-[softwareUpdate/testFallbackUpdate/test1.js]
-[softwareUpdate/testFallbackUpdate/test3.js]
-[softwareUpdate/testDirectUpdate/test2.js]
-[softwareUpdate/testDirectUpdate/test1.js]
deleted file mode 100644
--- a/build/tests/path-example.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[foo]
-path = fleem
\ No newline at end of file
deleted file mode 100755
--- a/build/tests/test.py
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/usr/bin/env 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/.
-
-"""tests for ManifestDestiny"""
-
-import doctest
-import os
-import sys
-from optparse import OptionParser
-
-def run_tests(raise_on_error=False, report_first=False):
-
-    # add results here
-    results = {}
-
-    # doctest arguments
-    directory = os.path.dirname(os.path.abspath(__file__))
-    extraglobs = {}
-    doctest_args = dict(extraglobs=extraglobs,
-                        module_relative=False,
-                        raise_on_error=raise_on_error)
-    if report_first:
-        doctest_args['optionflags'] = doctest.REPORT_ONLY_FIRST_FAILURE
-                                
-    # gather tests
-    directory = os.path.dirname(os.path.abspath(__file__))
-    tests =  [ test for test in os.listdir(directory)
-               if test.endswith('.txt') and test.startswith('test_')]
-    os.chdir(directory)
-
-    # run the tests
-    for test in tests:
-        try:
-            results[test] = doctest.testfile(test, **doctest_args)
-        except doctest.DocTestFailure, failure:
-            raise
-        except doctest.UnexpectedException, failure:
-            raise failure.exc_info[0], failure.exc_info[1], failure.exc_info[2]
-        
-    return results
-                                
-
-def main(args=sys.argv[1:]):
-
-    # parse command line options
-    parser = OptionParser(description=__doc__)
-    parser.add_option('--raise', dest='raise_on_error',
-                      default=False, action='store_true',
-                      help="raise on first error")
-    parser.add_option('--report-first', dest='report_first',
-                      default=False, action='store_true',
-                      help="report the first error only (all tests will still run)")
-    parser.add_option('-q', '--quiet', dest='quiet',
-                      default=False, action='store_true',
-                      help="minimize output")
-    options, args = parser.parse_args(args)
-    quiet = options.__dict__.pop('quiet')
-
-    # run the tests
-    results = run_tests(**options.__dict__)
-
-    # check for failure
-    failed = False
-    for result in results.values():
-        if result[0]: # failure count; http://docs.python.org/library/doctest.html#basic-api
-            failed = True
-            break
-    if failed:
-        sys.exit(1) # error
-    if not quiet:
-        # print results
-        print "manifestparser.py: All tests pass!"
-        for test in sorted(results.keys()):
-            result = results[test]
-            print "%s: failed=%s, attempted=%s" % (test, result[0], result[1])
-               
-if __name__ == '__main__':
-    main()
deleted file mode 100644
--- a/build/tests/test_expressionparser.txt
+++ /dev/null
@@ -1,120 +0,0 @@
-Test Expressionparser
-=====================
-
-Test the conditional expression parser.
-
-Boilerplate::
-
-    >>> from manifestparser import parse
-
-Test basic values::
-
-    >>> parse("1")
-    1
-    >>> parse("100")
-    100
-    >>> parse("true")
-    True
-    >>> parse("false")
-    False
-    >>> '' == parse('""')
-    True
-    >>> parse('"foo bar"')
-    'foo bar'
-    >>> parse("'foo bar'")
-    'foo bar'
-    >>> parse("foo", foo=1)
-    1
-    >>> parse("bar", bar=True)
-    True
-    >>> parse("abc123", abc123="xyz")
-    'xyz'
-
-Test equality::
-
-    >>> parse("true == true")
-    True
-    >>> parse("false == false")
-    True
-    >>> parse("false == false")
-    True
-    >>> parse("1 == 1")
-    True
-    >>> parse("100 == 100")
-    True
-    >>> parse('"some text" == "some text"')
-    True
-    >>> parse("true != false")
-    True
-    >>> parse("1 != 2")
-    True
-    >>> parse('"text" != "other text"')
-    True
-    >>> parse("foo == true", foo=True)
-    True
-    >>> parse("foo == 1", foo=1)
-    True
-    >>> parse('foo == "bar"', foo='bar')
-    True
-    >>> parse("foo == bar", foo=True, bar=True)
-    True
-    >>> parse("true == foo", foo=True)
-    True
-    >>> parse("foo != true", foo=False)
-    True
-    >>> parse("foo != 2", foo=1)
-    True
-    >>> parse('foo != "bar"', foo='abc')
-    True
-    >>> parse("foo != bar", foo=True, bar=False)
-    True
-    >>> parse("true != foo", foo=False)
-    True
-    >>> parse("!false")
-    True
-
-Test conjunctions::
-    
-    >>> parse("true && true")
-    True
-    >>> parse("true || false")
-    True
-    >>> parse("false || false")
-    False
-    >>> parse("true && false")
-    False
-    >>> parse("true || false && false")
-    True
-
-Test parentheses::
-    
-    >>> parse("(true)")
-    True
-    >>> parse("(10)")
-    10
-    >>> parse('("foo")')
-    'foo'
-    >>> parse("(foo)", foo=1)
-    1
-    >>> parse("(true == true)")
-    True
-    >>> parse("(true != false)")
-    True
-    >>> parse("(true && true)")
-    True
-    >>> parse("(true || false)")
-    True
-    >>> parse("(true && true || false)")
-    True
-    >>> parse("(true || false) && false")
-    False
-    >>> parse("(true || false) && true")
-    True
-    >>> parse("true && (true || false)")
-    True
-    >>> parse("true && (true || false)")
-    True
-    >>> parse("(true && false) || (true && (true || false))")
-    True
-        
-
deleted file mode 100644
--- a/build/tests/test_manifestparser.txt
+++ /dev/null
@@ -1,217 +0,0 @@
-Test the manifest parser
-========================
-
-You must have ManifestDestiny installed before running these tests.
-Run ``python manifestparser.py setup develop`` with setuptools installed.
-
-Ensure basic parser is sane::
-
-    >>> from manifestparser import ManifestParser
-    >>> parser = ManifestParser()
-    >>> parser.read('mozmill-example.ini')
-    >>> tests = parser.tests
-    >>> len(tests) == len(file('mozmill-example.ini').read().strip().splitlines())
-    True
-    
-Ensure that capitalization and order aren't an issue:
-
-    >>> lines = ['[%s]' % test['name'] for test in tests]
-    >>> lines == file('mozmill-example.ini').read().strip().splitlines()
-    True
-
-Show how you select subsets of tests:
-
-    >>> parser.read('mozmill-restart-example.ini')
-    >>> restart_tests = parser.get(type='restart')
-    >>> len(restart_tests) < len(parser.tests)
-    True
-    >>> import os
-    >>> len(restart_tests) == len(parser.get(manifest=os.path.abspath('mozmill-restart-example.ini')))
-    True
-    >>> assert not [test for test in restart_tests if test['manifest'] != os.path.abspath('mozmill-restart-example.ini')]
-    >>> parser.get('name', tags=['foo'])
-    ['restartTests/testExtensionInstallUninstall/test2.js', 'restartTests/testExtensionInstallUninstall/test1.js']
-    >>> parser.get('name', foo='bar')
-    ['restartTests/testExtensionInstallUninstall/test2.js']
-
-Illustrate how include works::
-
-    >>> parser = ManifestParser(manifests=('include-example.ini',))
-
-All of the tests should be included, in order::
-
-    >>> parser.get('name')
-    ['crash-handling', 'fleem', 'flowers']
-    >>> [(test['name'], os.path.basename(test['manifest'])) for test in parser.tests]
-    [('crash-handling', 'bar.ini'), ('fleem', 'include-example.ini'), ('flowers', 'foo.ini')]
-
-The manifests should be there too::
-
-    >>> len(parser.manifests())
-    3
-
-We're already in the root directory::
-
-    >>> os.getcwd() == parser.rootdir
-    True
-
-DEFAULT values should persist across includes, unless they're
-overwritten.  In this example, include-example.ini sets foo=bar, but
-its overridden to fleem in bar.ini::
-
-    >>> parser.get('name', foo='bar')
-    ['fleem', 'flowers']
-    >>> parser.get('name', foo='fleem')
-    ['crash-handling']
-
-Passing parameters in the include section allows defining variables in
-the submodule scope:
-
-    >>> parser.get('name', tags=['red'])
-    ['flowers']
-
-However, this should be overridable from the DEFAULT section in the
-included file and that overridable via the key directly connected to
-the test::
-
-    >>> parser.get(name='flowers')[0]['blue']
-    'ocean'
-    >>> parser.get(name='flowers')[0]['yellow']
-    'submarine'
-
-You can query multiple times if you need to::
-
-    >>> flowers = parser.get(foo='bar')
-    >>> len(flowers)
-    2
-    >>> roses = parser.get(tests=flowers, red='roses')
-
-Using the inverse flag should invert the set of tests returned::
-
-    >>> parser.get('name', inverse=True, tags=['red'])
-    ['crash-handling', 'fleem']
-
-All of the included tests actually exist::
-
-    >>> [i['name'] for i in parser.missing()]
-    []
-
-Write the output to a manifest:
-
-    >>> from StringIO import StringIO
-    >>> buffer = StringIO()
-    >>> parser.write(fp=buffer, global_kwargs={'foo': 'bar'})
-    >>> buffer.getvalue().strip()
-    '[DEFAULT]\nfoo = bar\n\n[fleem]\n\n[include/flowers]\nblue = ocean\nred = roses\nyellow = submarine'
-
-Test our ability to convert a static directory structure to a
-manifest. First, stub out a directory with files in it::
-
-    >>> import shutil, tempfile
-    >>> def create_stub():
-    ...     directory = tempfile.mkdtemp()
-    ...     for i in 'foo', 'bar', 'fleem':
-    ...         file(os.path.join(directory, i), 'w').write(i)
-    ...     subdir = os.path.join(directory, 'subdir')
-    ...     os.mkdir(subdir)
-    ...     file(os.path.join(subdir, 'subfile'), 'w').write('baz')
-    ...     return directory
-    >>> stub = create_stub()
-    >>> os.path.exists(stub) and os.path.isdir(stub)
-    True
-
-Make a manifest for it::
-
-    >>> from manifestparser import convert
-    >>> print convert([stub])
-    [bar]
-    [fleem]
-    [foo]
-    [subdir/subfile]
-    >>> shutil.rmtree(stub)
-
-Now do the same thing but keep the manifests in place::
-
-    >>> stub = create_stub()
-    >>> convert([stub], write='manifest.ini')
-    >>> sorted(os.listdir(stub))
-    ['bar', 'fleem', 'foo', 'manifest.ini', 'subdir']
-    >>> parser = ManifestParser()
-    >>> parser.read(os.path.join(stub, 'manifest.ini'))
-    >>> [i['name'] for i in parser.tests]
-    ['subfile', 'bar', 'fleem', 'foo']
-    >>> parser = ManifestParser()
-    >>> parser.read(os.path.join(stub, 'subdir', 'manifest.ini'))
-    >>> len(parser.tests)
-    1
-    >>> parser.tests[0]['name']
-    'subfile'
-    >>> shutil.rmtree(stub)
-
-Test our ability to copy a set of manifests::
-
-    >>> tempdir = tempfile.mkdtemp()
-    >>> manifest = ManifestParser(manifests=('include-example.ini',))
-    >>> manifest.copy(tempdir)
-    >>> sorted(os.listdir(tempdir))
-    ['fleem', 'include', 'include-example.ini']
-    >>> sorted(os.listdir(os.path.join(tempdir, 'include')))
-    ['bar.ini', 'crash-handling', 'flowers', 'foo.ini']
-    >>> from_manifest = ManifestParser(manifests=('include-example.ini',))
-    >>> to_manifest = os.path.join(tempdir, 'include-example.ini')
-    >>> to_manifest = ManifestParser(manifests=(to_manifest,))
-    >>> to_manifest.get('name') == from_manifest.get('name')
-    True
-    >>> shutil.rmtree(tempdir)
-
-Test our ability to update tests from a manifest and a directory of
-files::
-
-    >>> tempdir = tempfile.mkdtemp()
-    >>> for i in range(10):
-    ...     file(os.path.join(tempdir, str(i)), 'w').write(str(i))
-
-First, make a manifest::
-
-    >>> manifest = convert([tempdir])
-    >>> newtempdir = tempfile.mkdtemp()
-    >>> manifest_file = os.path.join(newtempdir, 'manifest.ini')
-    >>> file(manifest_file,'w').write(manifest)
-    >>> manifest = ManifestParser(manifests=(manifest_file,))
-    >>> manifest.get('name') == [str(i) for i in range(10)]
-    True
-
-All of the tests are initially missing::
-
-    >>> [i['name'] for i in manifest.missing()] == [str(i) for i in range(10)]
-    True
-
-But then we copy one over::
-
-    >>> manifest.get('name', name='1')
-    ['1']
-    >>> manifest.update(tempdir, name='1')
-    >>> sorted(os.listdir(newtempdir))
-    ['1', 'manifest.ini']
-
-Update that one file and copy all the "tests"::
-   
-    >>> file(os.path.join(tempdir, '1'), 'w').write('secret door')
-    >>> manifest.update(tempdir)
-    >>> sorted(os.listdir(newtempdir))
-    ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'manifest.ini']
-    >>> file(os.path.join(newtempdir, '1')).read().strip()
-    'secret door'
-
-Clean up::
-
-    >>> shutil.rmtree(tempdir)
-    >>> shutil.rmtree(newtempdir)
-
-You can override the path in the section too.  This shows that you can
-use a relative path::
-
-    >>> manifest = ManifestParser(manifests=('path-example.ini',))
-    >>> manifest.tests[0]['path'] == os.path.abspath('fleem')
-    True
-
deleted file mode 100644
--- a/build/tests/test_testmanifest.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-Test the Test Manifest
-======================
-
-Boilerplate::
-
-    >>> import os
-
-Test filtering based on platform::
-
-    >>> from manifestparser import TestManifest
-    >>> manifest = TestManifest(manifests=('filter-example.ini',))
-    >>> [i['name'] for i in manifest.active_tests(os='win', disabled=False, exists=False)]
-    ['windowstest', 'fleem']
-    >>> [i['name'] for i in manifest.active_tests(os='linux', disabled=False, exists=False)]
-    ['fleem', 'linuxtest']
-
-Look for existing tests.  There is only one::
-
-    >>> [i['name'] for i in manifest.active_tests()]
-    ['fleem']
-
-You should be able to expect failures::
-
-    >>> last_test = manifest.active_tests(exists=False, toolkit='gtk2')[-1]
-    >>> last_test['name']
-    'linuxtest'
-    >>> last_test['expected']
-    'pass'
-    >>> last_test = manifest.active_tests(exists=False, toolkit='cocoa')[-1]
-    >>> last_test['expected']
-    'fail'
-
--- a/configure.in
+++ b/configure.in
@@ -9127,18 +9127,18 @@ if test -n "$ARM_ARCH"; then
         else
             dnl CPU detection for ARM works on Android only.  armv7 always uses CPU detection, so
             dnl we have to set armv7=0 for non-Android target
             EXTRA_GYP_DEFINES="${EXTRA_GYP_DEFINES} -D armv7=0 "
         fi
     fi
 fi
 
-# Don't try to compile sse4.1 code if toolchain doesn't support
-if test -z "$HAVE_TOOLCHAIN_SUPPORT_MSSE4_1"; then
+# Don't try to compile ssse3/sse4.1 code if toolchain doesn't support
+if test -z "$HAVE_TOOLCHAIN_SUPPORT_SSSE3" || test -z "$HAVE_TOOLCHAIN_SUPPORT_MSSE4_1"; then
   EXTRA_GYP_DEFINES="$EXTRA_GYP_DEFINES -D yuv_disable_asm=1"
 fi
 
 if test -n "$MOZ_WEBRTC"; then
    AC_MSG_RESULT("generating WebRTC Makefiles...")
 
    if test "${MOZ_WIDGET_TOOLKIT}" = "gonk"; then
       EXTRA_GYP_DEFINES="${EXTRA_GYP_DEFINES} -D build_with_gonk=1 -D include_internal_audio_device=0"
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -99,16 +99,19 @@ enum {
                                   ELEMENT_HAS_PENDING_ANIMATION_RESTYLE,
 
   // Remaining bits are for subclasses
   ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = NODE_TYPE_SPECIFIC_BITS_OFFSET + 4
 };
 
 #undef ELEMENT_FLAG_BIT
 
+// Make sure we have space for our bits
+ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET);
+
 namespace mozilla {
 namespace dom {
 
 class Link;
 class UndoManager;
 
 // IID for the dom::Element interface
 #define NS_ELEMENT_IID \
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -628,27 +628,16 @@ public:
    * @note The out param, aURI, is guaranteed to be set to a non-null pointer
    *   when the return value is true.
    *
    * XXXjwatt: IMO IsInteractiveLink would be a better name.
    */
   virtual bool IsLink(nsIURI** aURI) const = 0;
 
   /**
-   * Get the cached state of the link.  If the state is unknown, 
-   * return eLinkState_Unknown.
-   *
-   * @return The cached link state of the link.
-   */
-  virtual nsLinkState GetLinkState() const
-  {
-    return eLinkState_NotLink;
-  }
-
-  /**
     * Get a pointer to the full href URI (fully resolved and canonicalized,
     * since it's an nsIURI object) for link elements.
     *
     * @return A pointer to the URI or null if the element is not a link or it
     *         has no HREF attribute.
     */
   virtual already_AddRefed<nsIURI> GetHrefURI() const
   {
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -66,17 +66,17 @@ template<typename T> class Optional;
 } // namespace dom
 } // namespace mozilla
 
 namespace JS {
 class Value;
 template<typename T> class Handle;
 }
 
-#define NODE_FLAG_BIT(n_) (1U << (n_))
+#define NODE_FLAG_BIT(n_) (1U << (WRAPPER_CACHE_FLAGS_BITS_USED + (n_)))
 
 enum {
   // This bit will be set if the node has a listener manager.
   NODE_HAS_LISTENERMANAGER =              NODE_FLAG_BIT(0),
 
   // Whether this node has had any properties set on it
   NODE_HAS_PROPERTIES =                   NODE_FLAG_BIT(1),
 
@@ -150,39 +150,37 @@ enum {
   // At least one descendant in the flattened tree has NODE_NEEDS_FRAME set.
   // This should be set on every node on the flattened tree path between the
   // node(s) with NODE_NEEDS_FRAME and the root content.
   NODE_DESCENDANTS_NEED_FRAMES =          NODE_FLAG_BIT(16),
 
   // Set if the node has the accesskey attribute set.
   NODE_HAS_ACCESSKEY =                    NODE_FLAG_BIT(17),
 
-  // Set if the node is handling a click.
-  NODE_HANDLING_CLICK =                   NODE_FLAG_BIT(18),
-
-  // Set if the node has had :hover selectors matched against it
-  NODE_HAS_RELEVANT_HOVER_RULES =         NODE_FLAG_BIT(19),
-
   // Set if the node has right-to-left directionality
-  NODE_HAS_DIRECTION_RTL =                NODE_FLAG_BIT(20),
+  NODE_HAS_DIRECTION_RTL =                NODE_FLAG_BIT(18),
 
   // Set if the node has left-to-right directionality
-  NODE_HAS_DIRECTION_LTR =                NODE_FLAG_BIT(21),
+  NODE_HAS_DIRECTION_LTR =                NODE_FLAG_BIT(19),
 
   NODE_ALL_DIRECTION_FLAGS =              NODE_HAS_DIRECTION_LTR |
                                           NODE_HAS_DIRECTION_RTL,
 
-  NODE_CHROME_ONLY_ACCESS =               NODE_FLAG_BIT(22),
+  NODE_CHROME_ONLY_ACCESS =               NODE_FLAG_BIT(20),
 
-  NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS =    NODE_FLAG_BIT(23),
+  NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS =    NODE_FLAG_BIT(21),
 
   // Remaining bits are node type specific.
-  NODE_TYPE_SPECIFIC_BITS_OFFSET =        24
+  NODE_TYPE_SPECIFIC_BITS_OFFSET =        22
 };
 
+// Make sure we have space for our bits
+#define ASSERT_NODE_FLAGS_SPACE(n) PR_STATIC_ASSERT(WRAPPER_CACHE_FLAGS_BITS_USED + (n) <= 32)
+ASSERT_NODE_FLAGS_SPACE(NODE_TYPE_SPECIFIC_BITS_OFFSET);
+
 /**
  * Class used to detect unexpected mutations. To use the class create an
  * nsMutationGuard on the stack before unexpected mutations could occur.
  * You can then at any time call Mutated to check if any unexpected mutations
  * have occurred.
  *
  * When a guard is instantiated sMutationCount is set to 300. It is then
  * decremented by every mutation (capped at 0). This means that we can only
@@ -314,17 +312,16 @@ public:
 #ifdef _MSC_VER
 #pragma warning(push)
 // Disable annoying warning about 'this' in initializers.
 #pragma warning(disable:4355)
 #endif
   nsINode(already_AddRefed<nsINodeInfo> aNodeInfo)
   : mNodeInfo(aNodeInfo),
     mParent(nullptr),
-    mFlags(0),
     mBoolFlags(0),
     mNextSibling(nullptr),
     mPreviousSibling(nullptr),
     mFirstChild(nullptr),
     mSubtreeRoot(this),
     mSlots(nullptr)
   {
   }
@@ -926,48 +923,38 @@ public:
    */
 #ifdef DEBUG
   nsSlots* DebugGetSlots()
   {
     return Slots();
   }
 #endif
 
-  bool HasFlag(uintptr_t aFlag) const
-  {
-    return !!(GetFlags() & aFlag);
-  }
-
-  uint32_t GetFlags() const
-  {
-    return mFlags;
-  }
-
   void SetFlags(uint32_t aFlagsToSet)
   {
     NS_ASSERTION(!(aFlagsToSet & (NODE_IS_ANONYMOUS |
                                   NODE_IS_NATIVE_ANONYMOUS_ROOT |
                                   NODE_IS_IN_ANONYMOUS_SUBTREE |
                                   NODE_ATTACH_BINDING_ON_POSTCREATE |
                                   NODE_DESCENDANTS_NEED_FRAMES |
                                   NODE_NEEDS_FRAME |
                                   NODE_CHROME_ONLY_ACCESS)) ||
                  IsNodeOfType(eCONTENT),
                  "Flag only permitted on nsIContent nodes");
-    mFlags |= aFlagsToSet;
+    nsWrapperCache::SetFlags(aFlagsToSet);
   }
 
   void UnsetFlags(uint32_t aFlagsToUnset)
   {
     NS_ASSERTION(!(aFlagsToUnset &
                    (NODE_IS_ANONYMOUS |
                     NODE_IS_IN_ANONYMOUS_SUBTREE |
                     NODE_IS_NATIVE_ANONYMOUS_ROOT)),
                  "Trying to unset write-only flags");
-    mFlags &= ~aFlagsToUnset;
+    nsWrapperCache::UnsetFlags(aFlagsToUnset);
   }
 
   void SetEditableFlag(bool aEditable)
   {
     if (aEditable) {
       SetFlags(NODE_IS_EDITABLE);
     }
     else {
@@ -1332,16 +1319,20 @@ private:
     NodeHasDirAuto,
     // Set if a node in the node's parent chain has dir=auto.
     NodeAncestorHasDirAuto,
     // Set if the element is in the scope of a scoped style sheet; this flag is
     // only accurate for elements bounds to a document
     ElementIsInStyleScope,
     // Set if the element is a scoped style sheet root
     ElementIsScopedStyleRoot,
+    // Set if the node is handling a click.
+    NodeHandlingClick,
+    // Set if the node has had :hover selectors matched against it
+    NodeHasRelevantHoverRules,
     // Guard value
     BooleanFlagCount
   };
 
   void SetBoolFlag(BooleanFlag name, bool value) {
     PR_STATIC_ASSERT(BooleanFlagCount <= 8*sizeof(mBoolFlags));
     mBoolFlags = (mBoolFlags & ~(1 << name)) | (value << name);
   }
@@ -1466,16 +1457,18 @@ public:
     MOZ_ASSERT(IsElement(), "ClearIsInStyleScope on a non-Element node");
     ClearBoolFlag(ElementIsInStyleScope);
   }
   bool IsElementInStyleScope() const { return GetBoolFlag(ElementIsInStyleScope); }
 
   void SetIsScopedStyleRoot() { SetBoolFlag(ElementIsScopedStyleRoot); }
   void ClearIsScopedStyleRoot() { ClearBoolFlag(ElementIsScopedStyleRoot); }
   bool IsScopedStyleRoot() { return GetBoolFlag(ElementIsScopedStyleRoot); }
+  bool HasRelevantHoverRules() const { return GetBoolFlag(NodeHasRelevantHoverRules); }
+  void SetHasRelevantHoverRules() { SetBoolFlag(NodeHasRelevantHoverRules); }
 protected:
   void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
   void SetInDocument() { SetBoolFlag(IsInDocument); }
   void SetNodeIsContent() { SetBoolFlag(NodeIsContent); }
   void ClearInDocument() { ClearBoolFlag(IsInDocument); }
   void SetIsElement() { SetBoolFlag(NodeIsElement); }
   void SetHasID() { SetBoolFlag(ElementHasID); }
   void ClearHasID() { ClearBoolFlag(ElementHasID); }
@@ -1485,16 +1478,19 @@ protected:
   void SetMayHaveContentEditableAttr()
     { SetBoolFlag(ElementMayHaveContentEditableAttr); }
   bool HasExplicitBaseURI() const { return GetBoolFlag(NodeHasExplicitBaseURI); }
   void SetHasExplicitBaseURI() { SetBoolFlag(NodeHasExplicitBaseURI); }
   void SetHasLockedStyleStates() { SetBoolFlag(ElementHasLockedStyleStates); }
   void ClearHasLockedStyleStates() { ClearBoolFlag(ElementHasLockedStyleStates); }
   bool HasLockedStyleStates() const
     { return GetBoolFlag(ElementHasLockedStyleStates); }
+  bool HandlingClick() const { return GetBoolFlag(NodeHandlingClick); }
+  void SetHandlingClick() { SetBoolFlag(NodeHandlingClick); }
+  void ClearHandlingClick() { ClearBoolFlag(NodeHandlingClick); }
 
   void SetSubtreeRootPointer(nsINode* aSubtreeRoot)
   {
     NS_ASSERTION(aSubtreeRoot, "aSubtreeRoot can never be null!");
     NS_ASSERTION(!(IsNodeOfType(eCONTENT) && IsInDoc()), "Shouldn't be here!");
     mSubtreeRoot = aSubtreeRoot;
   }
 
@@ -1733,18 +1729,16 @@ public:
 protected:
   static bool Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb);
   static void Unlink(nsINode *tmp);
 
   nsCOMPtr<nsINodeInfo> mNodeInfo;
 
   nsINode* mParent;
 
-  uint32_t mFlags;
-
 private:
   // Boolean flags.
   uint32_t mBoolFlags;
 
 protected:
   nsIContent* mNextSibling;
   nsIContent* mPreviousSibling;
   nsIContent* mFirstChild;
--- a/content/base/src/Link.cpp
+++ b/content/base/src/Link.cpp
@@ -38,24 +38,16 @@ Link::~Link()
 
 bool
 Link::ElementHasHref() const
 {
   return ((!mElement->IsSVG() && mElement->HasAttr(kNameSpaceID_None, nsGkAtoms::href))
         || (!mElement->IsHTML() && mElement->HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)));
 }
 
-nsLinkState
-Link::GetLinkState() const
-{
-  NS_ASSERTION(mRegistered,
-               "Getting the link state of an unregistered Link!");
-  return nsLinkState(mLinkState);
-}
-
 void
 Link::SetLinkState(nsLinkState aState)
 {
   NS_ASSERTION(mRegistered,
                "Setting the link state of an unregistered Link!");
   NS_ASSERTION(mLinkState != aState,
                "Setting state to the currently set state!");
 
--- a/content/base/src/Link.h
+++ b/content/base/src/Link.h
@@ -27,17 +27,16 @@ class Link : public nsISupports
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOM_LINK_IMPLEMENTATION_IID)
 
   /**
    * aElement is the element pointer corresponding to this link.
    */
   Link(Element* aElement);
-  nsLinkState GetLinkState() const;
   virtual void SetLinkState(nsLinkState aState);
 
   /**
    * @return NS_EVENT_STATE_VISITED if this link is visited,
    *         NS_EVENT_STATE_UNVISTED if this link is not visited, or 0 if this
    *         link is not actually a link.
    */
   nsEventStates LinkState() const;
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -89,16 +89,20 @@ MarkUserDataHandler(void* aNode, nsIAtom
   if (d && nsCCUncollectableMarker::InGeneration(d->GetMarkedCCGeneration())) {
     Element::MarkUserDataHandler(aNode, aKey, aValue, aData);
   }
 }
 
 static void
 MarkMessageManagers()
 {
+  // The global message manager only exists in the root process.
+  if (XRE_GetProcessType() != GeckoProcessType_Default) {
+    return;
+  }
   nsCOMPtr<nsIMessageBroadcaster> strongGlobalMM =
     do_GetService("@mozilla.org/globalmessagemanager;1");
   if (!strongGlobalMM) {
     return;
   }
   nsIMessageBroadcaster* globalMM = strongGlobalMM;
   strongGlobalMM = nullptr;
 
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -671,17 +671,17 @@ nsContentList::NamedItem(JSContext* cx, 
 {
   nsIContent *item = NamedItem(name, true);
   if (!item) {
     return nullptr;
   }
   JS::Rooted<JSObject*> wrapper(cx, GetWrapper());
   JSAutoCompartment ac(cx, wrapper);
   JS::Rooted<JS::Value> v(cx);
-  if (!mozilla::dom::WrapObject(cx, wrapper, item, item, nullptr, v.address())) {
+  if (!mozilla::dom::WrapObject(cx, wrapper, item, item, nullptr, &v)) {
     error.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
   return &v.toObject();
 }
 
 void
 nsContentList::AttributeChanged(nsIDocument *aDocument, Element* aElement,
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -49,16 +49,17 @@
 #include "nsCOMPtr.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentDLF.h"
 #include "nsContentList.h"
 #include "nsContentPolicyUtils.h"
 #include "nsCPrefetchService.h"
 #include "nsCRT.h"
 #include "nsCycleCollectionParticipant.h"
+#include "nsCycleCollector.h"
 #include "nsDataHashtable.h"
 #include "nsDocShellCID.h"
 #include "nsDOMCID.h"
 #include "nsDOMDataTransfer.h"
 #include "nsDOMJSUtils.h"
 #include "nsDOMMutationObserver.h"
 #include "nsDOMTouchEvent.h"
 #include "nsError.h"
@@ -4320,37 +4321,32 @@ nsContentUtils::DestroyAnonymousContent(
   }
 }
 
 /* static */
 void
 nsContentUtils::HoldJSObjects(void* aScriptObjectHolder,
                               nsScriptObjectTracer* aTracer)
 {
-  MOZ_ASSERT(sXPConnect, "Tried to HoldJSObjects when there was no XPConnect");
-  if (sXPConnect) {
-    sXPConnect->AddJSHolder(aScriptObjectHolder, aTracer);
-  }
+  cyclecollector::AddJSHolder(aScriptObjectHolder, aTracer);
 }
 
 /* static */
 void
 nsContentUtils::DropJSObjects(void* aScriptObjectHolder)
 {
-  if (sXPConnect) {
-    sXPConnect->RemoveJSHolder(aScriptObjectHolder);
-  }
+  cyclecollector::RemoveJSHolder(aScriptObjectHolder);
 }
 
 #ifdef DEBUG
 /* static */
 bool
-nsContentUtils::AreJSObjectsHeld(void* aScriptHolder)
-{
-  return sXPConnect->TestJSHolder(aScriptHolder);
+nsContentUtils::AreJSObjectsHeld(void* aScriptObjectHolder)
+{
+  return cyclecollector::TestJSHolder(aScriptObjectHolder);
 }
 #endif
 
 /* static */
 void
 nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling)
 {
   nsIMEStateManager::OnInstalledMenuKeyboardListener(aInstalling);
--- a/content/base/src/nsGenericDOMDataNode.h
+++ b/content/base/src/nsGenericDOMDataNode.h
@@ -40,17 +40,17 @@ enum {
   NS_CREATE_FRAME_IF_NON_WHITESPACE =     DATA_NODE_FLAG_BIT(0),
 
   // This bit is set to indicate that if the text node changes to
   // whitespace, we may need to reframe it (or its ancestors).
   NS_REFRAME_IF_WHITESPACE =              DATA_NODE_FLAG_BIT(1)
 };
 
 // Make sure we have enough space for those bits
-PR_STATIC_ASSERT(NODE_TYPE_SPECIFIC_BITS_OFFSET + 1 < 32);
+ASSERT_NODE_FLAGS_SPACE(NODE_TYPE_SPECIFIC_BITS_OFFSET + 2);
 
 #undef DATA_NODE_FLAG_BIT
 
 class nsGenericDOMDataNode : public nsIContent
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
--- a/content/canvas/public/nsICanvasRenderingContextInternal.h
+++ b/content/canvas/public/nsICanvasRenderingContextInternal.h
@@ -14,17 +14,16 @@
 #include "mozilla/RefPtr.h"
 
 #define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID \
 { 0x8b8da863, 0xd151, 0x4014, \
   { 0x8b, 0xdc, 0x62, 0xb5, 0x0d, 0xc0, 0x2b, 0x62 } }
 
 class gfxContext;
 class gfxASurface;
-class nsIPropertyBag;
 class nsDisplayListBuilder;
 
 namespace mozilla {
 namespace layers {
 class CanvasLayer;
 class LayerManager;
 }
 namespace ipc {
@@ -105,19 +104,17 @@ public:
   // an accelerated CanvasLayer.
   virtual bool ShouldForceInactiveLayer(LayerManager *aManager) { return false; }
 
   virtual void MarkContextClean() = 0;
 
   // Redraw the dirty rectangle of this canvas.
   NS_IMETHOD Redraw(const gfxRect &dirty) = 0;
 
-  // Passes a generic nsIPropertyBag options argument, along with the
-  // previous one, if any.  Optional.
-  NS_IMETHOD SetContextOptions(nsIPropertyBag *aNewOptions) { return NS_OK; }
+  NS_IMETHOD SetContextOptions(JSContext* aCx, JS::Handle<JS::Value> aOptions) { return NS_OK; }
 
   //
   // shmem support
   //
 
   // If this context can be set to use Mozilla's Shmem segments as its backing
   // store, this will set it to that state. Note that if you have drawn
   // anything into this canvas before changing the shmem state, it will be
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -117,20 +117,16 @@ using namespace mozilla::gfx;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
 
 namespace mgfx = mozilla::gfx;
 
 namespace mozilla {
 namespace dom {
 
-static float kDefaultFontSize = 10.0;
-static NS_NAMED_LITERAL_STRING(kDefaultFontName, "sans-serif");
-static NS_NAMED_LITERAL_STRING(kDefaultFontStyle, "10px sans-serif");
-
 // Cap sigma to avoid overly large temp surfaces.
 const Float SIGMA_MAX = 100;
 
 /* Memory reporter stuff */
 static int64_t gCanvasAzureMemoryUsed = 0;
 
 static int64_t GetCanvasAzureMemoryUsed() {
   return gCanvasAzureMemoryUsed;
@@ -1302,17 +1298,17 @@ WrapStyle(JSContext* cx, JSObject* objAr
     {
       ok = xpc::StringToJsval(cx, str, v.address());
       break;
     }
     case CanvasRenderingContext2D::CMG_STYLE_PATTERN:
     case CanvasRenderingContext2D::CMG_STYLE_GRADIENT:
     {
       JS::Rooted<JSObject*> obj(cx, objArg);
-      ok = dom::WrapObject(cx, obj, supports, v.address());
+      ok = dom::WrapObject(cx, obj, supports, &v);
       break;
     }
     default:
       MOZ_NOT_REACHED("unexpected CanvasMultiGetterType");
   }
   if (!ok) {
     error.Throw(NS_ERROR_FAILURE);
   }
@@ -2691,22 +2687,24 @@ CanvasRenderingContext2D::DrawOrMeasureT
   return NS_OK;
 }
 
 gfxFontGroup *CanvasRenderingContext2D::GetCurrentFontStyle()
 {
   // use lazy initilization for the font group since it's rather expensive
   if (!CurrentState().fontGroup) {
     ErrorResult err;
+    NS_NAMED_LITERAL_STRING(kDefaultFontStyle, "10px sans-serif");
+    static float kDefaultFontSize = 10.0;
     SetFont(kDefaultFontStyle, err);
     if (err.Failed()) {
       gfxFontStyle style;
       style.size = kDefaultFontSize;
       CurrentState().fontGroup =
-        gfxPlatform::GetPlatform()->CreateFontGroup(kDefaultFontName,
+        gfxPlatform::GetPlatform()->CreateFontGroup(NS_LITERAL_STRING("sans-serif"),
                                                     &style,
                                                     nullptr);
       if (CurrentState().fontGroup) {
         CurrentState().font = kDefaultFontStyle;
       } else {
         NS_ERROR("Default canvas font is invalid");
       }
     }
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -13,17 +13,16 @@
 #include "nsServiceManagerUtils.h"
 #include "nsIClassInfoImpl.h"
 #include "nsContentUtils.h"
 #include "nsIXPConnect.h"
 #include "nsError.h"
 #include "nsIGfxInfo.h"
 #include "nsIWidget.h"
 
-#include "nsIPropertyBag.h"
 #include "nsIVariant.h"
 
 #include "imgIEncoder.h"
 
 #include "gfxContext.h"
 #include "gfxPattern.h"
 #include "gfxUtils.h"
 
@@ -303,48 +302,32 @@ WebGLContext::Invalidate()
     mInvalidated = true;
     mCanvasElement->InvalidateCanvasContent(nullptr);
 }
 
 //
 // nsICanvasRenderingContextInternal
 //
 
-static bool
-GetBoolFromPropertyBag(nsIPropertyBag *bag, const char *propName, bool *boolResult)
+NS_IMETHODIMP
+WebGLContext::SetContextOptions(JSContext* aCx, JS::Handle<JS::Value> aOptions)
 {
-    nsCOMPtr<nsIVariant> vv;
-    bool bv;
-
-    nsresult rv = bag->GetProperty(NS_ConvertASCIItoUTF16(propName), getter_AddRefs(vv));
-    if (NS_FAILED(rv) || !vv)
-        return false;
-
-    rv = vv->GetAsBool(&bv);
-    if (NS_FAILED(rv))
-        return false;
-
-    *boolResult = bv ? true : false;
-    return true;
-}
-
-NS_IMETHODIMP
-WebGLContext::SetContextOptions(nsIPropertyBag *aOptions)
-{
-    if (!aOptions)
-        return NS_OK;
+    WebGLContextAttributes attributes;
+    attributes.Init(aCx, aOptions);
 
     WebGLContextOptions newOpts;
 
-    GetBoolFromPropertyBag(aOptions, "stencil", &newOpts.stencil);
-    GetBoolFromPropertyBag(aOptions, "depth", &newOpts.depth);
-    GetBoolFromPropertyBag(aOptions, "premultipliedAlpha", &newOpts.premultipliedAlpha);
-    GetBoolFromPropertyBag(aOptions, "antialias", &newOpts.antialias);
-    GetBoolFromPropertyBag(aOptions, "preserveDrawingBuffer", &newOpts.preserveDrawingBuffer);
-    GetBoolFromPropertyBag(aOptions, "alpha", &newOpts.alpha);
+    newOpts.stencil = attributes.mStencil;
+    newOpts.depth = attributes.mDepth;
+    newOpts.premultipliedAlpha = attributes.mPremultipliedAlpha;
+    newOpts.antialias = attributes.mAntialias;
+    newOpts.preserveDrawingBuffer = attributes.mPreserveDrawingBuffer;
+    if (attributes.mAlpha.WasPassed()) {
+      newOpts.alpha = attributes.mAlpha.Value();
+    }
 
     // enforce that if stencil is specified, we also give back depth
     newOpts.depth |= newOpts.stencil;
 
 #if 0
     GenerateWarning("aaHint: %d stencil: %d depth: %d alpha: %d premult: %d preserve: %d\n",
                newOpts.antialias ? 1 : 0,
                newOpts.stencil ? 1 : 0,
@@ -920,17 +903,17 @@ WebGLContext::GetContextAttributes(Nulla
     retval.SetNull();
     if (!IsContextStable())
         return;
 
     dom::WebGLContextAttributes& result = retval.SetValue();
 
     const PixelBufferFormat& format = gl->GetPixelFormat();
 
-    result.mAlpha = format.alpha > 0;
+    result.mAlpha.Construct(format.alpha > 0);
     result.mDepth = format.depth > 0;
     result.mStencil = format.stencil > 0;
     result.mAntialias = format.samples > 1;
     result.mPremultipliedAlpha = mOptions.premultipliedAlpha;
     result.mPreserveDrawingBuffer = mOptions.preserveDrawingBuffer;
 }
 
 bool
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -64,18 +64,16 @@
 #define MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS      16    // Page 164
 #define MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS        128   // Page 164
 #define MINVALUE_GL_MAX_VARYING_VECTORS               8     // Page 164
 #define MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS           8     // Page 164
 #define MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS    0     // Page 164
 #define MINVALUE_GL_MAX_RENDERBUFFER_SIZE             1024  // Different from the spec, which sets it to 1 on page 164
 #define MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS  8     // Page 164
 
-class nsIPropertyBag;
-
 namespace mozilla {
 
 class WebGLMemoryPressureObserver;
 class WebGLContextBoundObject;
 class WebGLActiveInfo;
 class WebGLExtensionBase;
 
 namespace dom {
@@ -214,17 +212,18 @@ public:
     NS_IMETHOD GetInputStream(const char* aMimeType,
                               const PRUnichar* aEncoderOptions,
                               nsIInputStream **aStream) MOZ_OVERRIDE;
     NS_IMETHOD GetThebesSurface(gfxASurface **surface) MOZ_OVERRIDE;
     mozilla::TemporaryRef<mozilla::gfx::SourceSurface> GetSurfaceSnapshot() MOZ_OVERRIDE
         { return nullptr; }
 
     NS_IMETHOD SetIsOpaque(bool b) MOZ_OVERRIDE { return NS_OK; };
-    NS_IMETHOD SetContextOptions(nsIPropertyBag *aOptions) MOZ_OVERRIDE;
+    NS_IMETHOD SetContextOptions(JSContext* aCx,
+                                 JS::Handle<JS::Value> aOptions) MOZ_OVERRIDE;
 
     NS_IMETHOD SetIsIPC(bool b) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Redraw(const gfxRect&) { return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Swap(mozilla::ipc::Shmem& aBack,
                     int32_t x, int32_t y, int32_t w, int32_t h)
                     { return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Swap(uint32_t nativeID,
                     int32_t x, int32_t y, int32_t w, int32_t h)
--- a/content/canvas/src/WebGLContextUtils.h
+++ b/content/canvas/src/WebGLContextUtils.h
@@ -18,17 +18,17 @@ WebGLContext::WebGLObjectAsJSValue(JSCon
 {
     if (!object) {
         return JS::NullValue();
     }
     MOZ_ASSERT(this == object->Context());
     JS::Rooted<JS::Value> v(cx);
     JS::Rooted<JSObject*> wrapper(cx, GetWrapper());
     JSAutoCompartment ac(cx, wrapper);
-    if (!dom::WrapNewBindingObject(cx, wrapper, const_cast<WebGLObjectType*>(object), v.address())) {
+    if (!dom::WrapNewBindingObject(cx, wrapper, const_cast<WebGLObjectType*>(object), &v)) {
         rv.Throw(NS_ERROR_FAILURE);
         return JS::NullValue();
     }
     return v;
 }
 
 template <typename WebGLObjectType>
 JSObject*
--- a/content/events/src/TextComposition.cpp
+++ b/content/events/src/TextComposition.cpp
@@ -40,23 +40,16 @@ TextComposition::TextComposition(const T
 }
 
 bool
 TextComposition::MatchesNativeContext(nsIWidget* aWidget) const
 {
   return mNativeContext == aWidget->GetInputContext().mNativeIMEContext;
 }
 
-bool
-TextComposition::MatchesEventTarget(nsPresContext* aPresContext,
-                                    nsINode* aNode) const
-{
-  return mPresContext == aPresContext && mNode == aNode;
-}
-
 void
 TextComposition::DispatchEvent(nsGUIEvent* aEvent,
                                nsEventStatus* aStatus,
                                nsDispatchingCallback* aCallBack)
 {
   if (aEvent->message == NS_COMPOSITION_UPDATE) {
     mLastData = static_cast<nsCompositionEvent*>(aEvent)->data;
   }
@@ -194,23 +187,16 @@ TextCompositionArray::IndexOf(nsPresCont
 TextComposition*
 TextCompositionArray::GetCompositionFor(nsIWidget* aWidget)
 {
   index_type i = IndexOf(aWidget);
   return i != NoIndex ? &ElementAt(i) : nullptr;
 }
 
 TextComposition*
-TextCompositionArray::GetCompositionFor(nsPresContext* aPresContext)
-{
-  index_type i = IndexOf(aPresContext);
-  return i != NoIndex ? &ElementAt(i) : nullptr;
-}
-
-TextComposition*
 TextCompositionArray::GetCompositionFor(nsPresContext* aPresContext,
                                            nsINode* aNode)
 {
   index_type i = IndexOf(aPresContext, aNode);
   return i != NoIndex ? &ElementAt(i) : nullptr;
 }
 
 TextComposition*
--- a/content/events/src/TextComposition.h
+++ b/content/events/src/TextComposition.h
@@ -48,18 +48,16 @@ public:
   nsINode* GetEventTargetNode() const { return mNode; }
   // The latest CompositionEvent.data value except compositionstart event.
   const nsString& GetLastData() const { return mLastData; }
   // Returns true if the composition is started with synthesized event which
   // came from nsDOMWindowUtils.
   bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; }
 
   bool MatchesNativeContext(nsIWidget* aWidget) const;
-  bool MatchesEventTarget(nsPresContext* aPresContext,
-                          nsINode* aNode) const;
 
   /**
    * SynthesizeCommit() dispatches compositionupdate, text and compositionend
    * events for emulating commit on the content.
    *
    * @param aDiscard true when committing with empty string.  Otherwise, false.
    */
   void SynthesizeCommit(bool aDiscard);
@@ -153,17 +151,16 @@ private:
 class TextCompositionArray MOZ_FINAL : public nsAutoTArray<TextComposition, 2>
 {
 public:
   index_type IndexOf(nsIWidget* aWidget);
   index_type IndexOf(nsPresContext* aPresContext);
   index_type IndexOf(nsPresContext* aPresContext, nsINode* aNode);
 
   TextComposition* GetCompositionFor(nsIWidget* aWidget);
-  TextComposition* GetCompositionFor(nsPresContext* aPresContext);
   TextComposition* GetCompositionFor(nsPresContext* aPresContext,
                                      nsINode* aNode);
   TextComposition* GetCompositionInContent(nsPresContext* aPresContext,
                                            nsIContent* aContent);
 };
 
 } // namespace mozilla
 
--- a/content/events/src/nsDOMUIEvent.cpp
+++ b/content/events/src/nsDOMUIEvent.cpp
@@ -172,39 +172,16 @@ nsDOMUIEvent::InitUIEvent(const nsAStrin
   
   mDetail = detailArg;
   mView = viewArg;
 
   return NS_OK;
 }
 
 // ---- nsDOMNSUIEvent implementation -------------------
-nsIntPoint
-nsDOMUIEvent::GetPagePoint()
-{
-  if (mPrivateDataDuplicated) {
-    return mPagePoint;
-  }
-
-  nsIntPoint pagePoint = GetClientPoint();
-
-  // If there is some scrolling, add scroll info to client point.
-  if (mPresContext && mPresContext->GetPresShell()) {
-    nsIPresShell* shell = mPresContext->GetPresShell();
-    nsIScrollableFrame* scrollframe = shell->GetRootScrollFrameAsScrollable();
-    if (scrollframe) {
-      nsPoint pt = scrollframe->GetScrollPosition();
-      pagePoint += nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(pt.x),
-                              nsPresContext::AppUnitsToIntCSSPixels(pt.y));
-    }
-  }
-
-  return pagePoint;
-}
-
 NS_IMETHODIMP
 nsDOMUIEvent::GetPageX(int32_t* aPageX)
 {
   NS_ENSURE_ARG_POINTER(aPageX);
   *aPageX = PageX();
   return NS_OK;
 }
 
--- a/content/events/src/nsDOMUIEvent.h
+++ b/content/events/src/nsDOMUIEvent.h
@@ -139,17 +139,16 @@ public:
 
   bool IsChar() const;
 
 protected:
   // Internal helper functions
   nsIntPoint GetClientPoint();
   nsIntPoint GetMovementPoint();
   nsIntPoint GetLayerPoint() const;
-  nsIntPoint GetPagePoint();
 
   nsCOMPtr<nsIDOMWindow> mView;
   int32_t mDetail;
   nsIntPoint mClientPoint;
   // Screenpoint is mEvent->refPoint.
   nsIntPoint mLayerPoint;
   nsIntPoint mPagePoint;
   nsIntPoint mMovementPoint;
--- a/content/html/content/public/HTMLCanvasElement.h
+++ b/content/html/content/public/HTMLCanvasElement.h
@@ -16,17 +16,16 @@
 
 #include "nsICanvasElementExternal.h"
 #include "nsLayoutUtils.h"
 #include "mozilla/gfx/Rect.h"
 
 class nsICanvasRenderingContextInternal;
 class nsIDOMFile;
 class nsITimerCallback;
-class nsIPropertyBag;
 
 namespace mozilla {
 
 namespace layers {
 class CanvasLayer;
 class LayerManager;
 }
 
@@ -85,26 +84,18 @@ public:
     return GetUnsignedIntAttr(nsGkAtoms::width, DEFAULT_CANVAS_WIDTH);
   }
   void SetWidth(uint32_t aWidth, ErrorResult& aRv)
   {
     SetUnsignedIntAttr(nsGkAtoms::width, aWidth, aRv);
   }
   already_AddRefed<nsISupports>
   GetContext(JSContext* aCx, const nsAString& aContextId,
-             const Optional<JS::Handle<JS::Value> >& aContextOptions,
-             ErrorResult& aRv)
-  {
-    JS::Value contextOptions = aContextOptions.WasPassed()
-                             ? aContextOptions.Value()
-                             : JS::UndefinedValue();
-    nsCOMPtr<nsISupports> context;
-    aRv = GetContext(aContextId, contextOptions, aCx, getter_AddRefs(context));
-    return context.forget();
-  }
+             JS::Handle<JS::Value> aContextOptions,
+             ErrorResult& aRv);
   void ToDataURL(JSContext* aCx, const nsAString& aType,
                  const Optional<JS::Handle<JS::Value> >& aParams,
                  nsAString& aDataURL, ErrorResult& aRv)
   {
     JS::Value params = aParams.WasPassed()
                      ? aParams.Value()
                      : JS::UndefinedValue();
     aRv = ToDataURL(aType, params, aCx, aDataURL);
@@ -230,17 +221,17 @@ public:
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
 protected:
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   nsIntSize GetWidthHeight();
 
-  nsresult UpdateContext(nsIPropertyBag *aNewContextOptions = nullptr);
+  nsresult UpdateContext(JSContext* aCx, JS::Handle<JS::Value> options);
   nsresult ExtractData(const nsAString& aType,
                        const nsAString& aOptions,
                        nsIInputStream** aStream,
                        bool& aFellBackToPNG);
   nsresult ToDataURLImpl(JSContext* aCx,
                          const nsAString& aMimeType,
                          const JS::Value& aEncoderOptions,
                          nsAString& aDataURL);
--- a/content/html/content/public/nsILink.h
+++ b/content/html/content/public/nsILink.h
@@ -22,17 +22,17 @@ class nsIURI;
  * It is needed for performance reasons (to prevent copying of
  * strings and excessive calls to history).
  */
 class nsILink : public nsISupports {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ILINK_IID)
 
   /**
-   * GetLinkState/SetLinkState/GetHrefURI were moved to nsIContent.
+   * SetLinkState/GetHrefURI were moved to nsIContent.
    * @see nsIContent
    */
 
   /**
    * Dispatch a LinkAdded event to the chrome event handler for this document.
    * This is used to notify the chrome listeners when restoring a page
    * presentation.  Currently, this only applies to HTML <link> elements.
    */
--- a/content/html/content/src/HTMLAnchorElement.cpp
+++ b/content/html/content/src/HTMLAnchorElement.cpp
@@ -26,18 +26,17 @@ namespace dom {
 enum {
   // Indicates that a DNS Prefetch has been requested from this Anchor elem
   HTML_ANCHOR_DNS_PREFETCH_REQUESTED =    ANCHOR_ELEMENT_FLAG_BIT(0),
 
   // Indicates that a DNS Prefetch was added to the deferral queue
   HTML_ANCHOR_DNS_PREFETCH_DEFERRED =     ANCHOR_ELEMENT_FLAG_BIT(1)
 };
 
-// Make sure we have enough space for those bits
-PR_STATIC_ASSERT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 1 < 32);
+ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
 
 #undef ANCHOR_ELEMENT_FLAG_BIT
 
 HTMLAnchorElement::~HTMLAnchorElement()
 {
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLAnchorElement, Element)
@@ -325,22 +324,16 @@ HTMLAnchorElement::GetPing(nsAString& aV
 }
 
 NS_IMETHODIMP
 HTMLAnchorElement::SetPing(const nsAString& aValue)
 {
   return SetAttr(kNameSpaceID_None, nsGkAtoms::ping, aValue, true);
 }
 
-nsLinkState
-HTMLAnchorElement::GetLinkState() const
-{
-  return Link::GetLinkState();
-}
-
 already_AddRefed<nsIURI>
 HTMLAnchorElement::GetHrefURI() const
 {
   nsCOMPtr<nsIURI> uri = Link::GetCachedURI();
   if (uri) {
     return uri.forget();
   }
 
--- a/content/html/content/src/HTMLAnchorElement.h
+++ b/content/html/content/src/HTMLAnchorElement.h
@@ -65,17 +65,16 @@ public:
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) MOZ_OVERRIDE;
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) MOZ_OVERRIDE;
 
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
   virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor) MOZ_OVERRIDE;
   virtual bool IsLink(nsIURI** aURI) const MOZ_OVERRIDE;
   virtual void GetLinkTarget(nsAString& aTarget) MOZ_OVERRIDE;
-  virtual nsLinkState GetLinkState() const MOZ_OVERRIDE;
   virtual already_AddRefed<nsIURI> GetHrefURI() const MOZ_OVERRIDE;
 
   nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                    const nsAString& aValue, bool aNotify)
   {
     return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
   }
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
--- a/content/html/content/src/HTMLAreaElement.cpp
+++ b/content/html/content/src/HTMLAreaElement.cpp
@@ -214,22 +214,16 @@ HTMLAreaElement::GetPing(nsAString& aVal
 }
 
 NS_IMETHODIMP
 HTMLAreaElement::SetPing(const nsAString& aValue)
 {
   return SetAttr(kNameSpaceID_None, nsGkAtoms::ping, aValue, true);
 }
 
-nsLinkState
-HTMLAreaElement::GetLinkState() const
-{
-  return Link::GetLinkState();
-}
-
 already_AddRefed<nsIURI>
 HTMLAreaElement::GetHrefURI() const
 {
   return GetHrefURIForAnchors();
 }
 
 nsEventStates
 HTMLAreaElement::IntrinsicState() const
--- a/content/html/content/src/HTMLAreaElement.h
+++ b/content/html/content/src/HTMLAreaElement.h
@@ -52,17 +52,16 @@ public:
   // nsILink
   NS_IMETHOD LinkAdded() MOZ_OVERRIDE { return NS_OK; }
   NS_IMETHOD LinkRemoved() MOZ_OVERRIDE { return NS_OK; }
 
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
   virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor) MOZ_OVERRIDE;
   virtual bool IsLink(nsIURI** aURI) const MOZ_OVERRIDE;
   virtual void GetLinkTarget(nsAString& aTarget) MOZ_OVERRIDE;
-  virtual nsLinkState GetLinkState() const MOZ_OVERRIDE;
   virtual already_AddRefed<nsIURI> GetHrefURI() const MOZ_OVERRIDE;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) MOZ_OVERRIDE;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) MOZ_OVERRIDE;
   nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
--- a/content/html/content/src/HTMLCanvasElement.cpp
+++ b/content/html/content/src/HTMLCanvasElement.cpp
@@ -205,17 +205,17 @@ HTMLCanvasElement::SetAttr(int32_t aName
                            nsIAtom* aPrefix, const nsAString& aValue,
                            bool aNotify)
 {
   nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
                                               aNotify);
   if (NS_SUCCEEDED(rv) && mCurrentContext &&
       (aName == nsGkAtoms::width || aName == nsGkAtoms::height || aName == nsGkAtoms::moz_opaque))
   {
-    rv = UpdateContext();
+    rv = UpdateContext(nullptr, JS::NullHandleValue);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return rv;
 }
 
 void
 HTMLCanvasElement::HandlePrintCallback(nsPresContext::nsPresContextType aType)
@@ -719,106 +719,57 @@ HTMLCanvasElement::GetContextHelper(cons
   ctx.forget(aContext);
   return NS_OK;
 }
 
 nsresult
 HTMLCanvasElement::GetContext(const nsAString& aContextId,
                               nsISupports** aContext)
 {
-  return GetContext(aContextId, JS::UndefinedHandleValue, nullptr, aContext);
+  ErrorResult rv;
+  *aContext = GetContext(nullptr, aContextId, JS::NullHandleValue, rv).get();
+  return rv.ErrorCode();
 }
 
-NS_IMETHODIMP
-HTMLCanvasElement::GetContext(const nsAString& aContextId,
-                              const JS::Value& aContextOptions,
-                              JSContext* aCx,
-                              nsISupports **aContext)
+already_AddRefed<nsISupports>
+HTMLCanvasElement::GetContext(JSContext* aCx,
+                              const nsAString& aContextId,
+                              JS::Handle<JS::Value> aContextOptions,
+                              ErrorResult& rv)
 {
-  MOZ_ASSERT_IF(!aCx, aContextOptions.isUndefined());
-
-  nsresult rv;
-
   if (mCurrentContextId.IsEmpty()) {
     rv = GetContextHelper(aContextId, getter_AddRefs(mCurrentContext));
-    NS_ENSURE_SUCCESS(rv, rv);
-    if (!mCurrentContext) {
-      return NS_OK;
+    if (rv.Failed() || !mCurrentContext) {
+      return nullptr;
     }
 
     // Ensure that the context participates in CC.  Note that returning a
     // CC participant from QI doesn't addref.
     nsXPCOMCycleCollectionParticipant *cp = nullptr;
     CallQueryInterface(mCurrentContext, &cp);
     if (!cp) {
       mCurrentContext = nullptr;
-      return NS_ERROR_FAILURE;
+      rv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
     }
 
-    // note: if any contexts end up supporting something other
-    // than objects, e.g. plain strings, then we'll need to expand
-    // this to know how to create nsISupportsStrings etc.
-
-    nsCOMPtr<nsIWritablePropertyBag2> contextProps;
-    if (aContextOptions.isObject()) {
-      MOZ_ASSERT(aCx);
-      contextProps = do_CreateInstance("@mozilla.org/hash-property-bag;1");
-
-      JS::Rooted<JSObject*> opts(aCx, &aContextOptions.toObject());
-      JS::AutoIdArray props(aCx, JS_Enumerate(aCx, opts));
-      for (size_t i = 0; !!props && i < props.length(); ++i) {
-        jsid propid = props[i];
-        JS::Rooted<JS::Value> propname(aCx), propval(aCx);
-        if (!JS_IdToValue(aCx, propid, propname.address()) ||
-            !JS_GetPropertyById(aCx, opts, propid, propval.address())) {
-          return NS_ERROR_FAILURE;
-        }
-
-        JSString *propnameString = JS_ValueToString(aCx, propname);
-        nsDependentJSString pstr;
-        if (!propnameString || !pstr.init(aCx, propnameString)) {
-          mCurrentContext = nullptr;
-          return NS_ERROR_FAILURE;
-        }
-
-        if (JSVAL_IS_BOOLEAN(propval)) {
-          contextProps->SetPropertyAsBool(pstr, JSVAL_TO_BOOLEAN(propval));
-        } else if (JSVAL_IS_INT(propval)) {
-          contextProps->SetPropertyAsInt32(pstr, JSVAL_TO_INT(propval));
-        } else if (JSVAL_IS_DOUBLE(propval)) {
-          contextProps->SetPropertyAsDouble(pstr, JSVAL_TO_DOUBLE(propval));
-        } else if (JSVAL_IS_STRING(propval)) {
-          JSString *propvalString = JS_ValueToString(aCx, propval);
-          nsDependentJSString vstr;
-          if (!propvalString || !vstr.init(aCx, propvalString)) {
-            mCurrentContext = nullptr;
-            return NS_ERROR_FAILURE;
-          }
-
-          contextProps->SetPropertyAsAString(pstr, vstr);
-        }
-
-      }
+    rv = UpdateContext(aCx, aContextOptions);
+    if (rv.Failed()) {
+      return nullptr;
     }
-
-    rv = UpdateContext(contextProps);
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
-
     mCurrentContextId.Assign(aContextId);
   }
 
   if (!mCurrentContextId.Equals(aContextId)) {
     //XXX eventually allow for more than one active context on a given canvas
-    return NS_OK;
+    return nullptr;
   }
 
-  NS_ADDREF (*aContext = mCurrentContext);
-  return NS_OK;
+  nsCOMPtr<nsICanvasRenderingContextInternal> context = mCurrentContext;
+  return context.forget();
 }
 
 NS_IMETHODIMP
 HTMLCanvasElement::MozGetIPCContext(const nsAString& aContextId,
                                     nsISupports **aContext)
 {
   if(!nsContentUtils::IsCallerChrome()) {
     // XXX ERRMSG we need to report an error to developers here! (bug 329026)
@@ -833,45 +784,45 @@ HTMLCanvasElement::MozGetIPCContext(cons
     nsresult rv = GetContextHelper(aContextId, getter_AddRefs(mCurrentContext));
     NS_ENSURE_SUCCESS(rv, rv);
     if (!mCurrentContext) {
       return NS_OK;
     }
 
     mCurrentContext->SetIsIPC(true);
 
-    rv = UpdateContext();
+    rv = UpdateContext(nullptr, JS::NullHandleValue);
     NS_ENSURE_SUCCESS(rv, rv);
 
     mCurrentContextId.Assign(aContextId);
   } else if (!mCurrentContextId.Equals(aContextId)) {
     //XXX eventually allow for more than one active context on a given canvas
     return NS_ERROR_INVALID_ARG;
   }
 
   NS_ADDREF (*aContext = mCurrentContext);
   return NS_OK;
 }
 
 nsresult
-HTMLCanvasElement::UpdateContext(nsIPropertyBag *aNewContextOptions)
+HTMLCanvasElement::UpdateContext(JSContext* aCx, JS::Handle<JS::Value> aNewContextOptions)
 {
   if (!mCurrentContext)
     return NS_OK;
 
   nsIntSize sz = GetWidthHeight();
 
   nsresult rv = mCurrentContext->SetIsOpaque(GetIsOpaque());
   if (NS_FAILED(rv)) {
     mCurrentContext = nullptr;
     mCurrentContextId.Truncate();
     return rv;
   }
 
-  rv = mCurrentContext->SetContextOptions(aNewContextOptions);
+  rv = mCurrentContext->SetContextOptions(aCx, aNewContextOptions);
   if (NS_FAILED(rv)) {
     mCurrentContext = nullptr;
     mCurrentContextId.Truncate();
     return rv;
   }
 
   rv = mCurrentContext->SetDimensions(sz.width, sz.height);
   if (NS_FAILED(rv)) {
--- a/content/html/content/src/HTMLLinkElement.cpp
+++ b/content/html/content/src/HTMLLinkElement.cpp
@@ -313,22 +313,16 @@ void
 HTMLLinkElement::GetLinkTarget(nsAString& aTarget)
 {
   GetAttr(kNameSpaceID_None, nsGkAtoms::target, aTarget);
   if (aTarget.IsEmpty()) {
     GetBaseTarget(aTarget);
   }
 }
 
-nsLinkState
-HTMLLinkElement::GetLinkState() const
-{
-  return Link::GetLinkState();
-}
-
 already_AddRefed<nsIURI>
 HTMLLinkElement::GetHrefURI() const
 {
   return GetHrefURIForAnchors();
 }
 
 already_AddRefed<nsIURI>
 HTMLLinkElement::GetStyleSheetURL(bool* aIsInline)
--- a/content/html/content/src/HTMLLinkElement.h
+++ b/content/html/content/src/HTMLLinkElement.h
@@ -74,17 +74,16 @@ public:
     return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
   }
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            bool aNotify) MOZ_OVERRIDE;
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify) MOZ_OVERRIDE;
   virtual bool IsLink(nsIURI** aURI) const MOZ_OVERRIDE;
-  virtual nsLinkState GetLinkState() const MOZ_OVERRIDE;
   virtual already_AddRefed<nsIURI> GetHrefURI() const MOZ_OVERRIDE;
 
   // Element
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) MOZ_OVERRIDE;
   virtual void GetLinkTarget(nsAString& aTarget) MOZ_OVERRIDE;
--- a/content/html/content/src/HTMLOptionsCollection.cpp
+++ b/content/html/content/src/HTMLOptionsCollection.cpp
@@ -286,18 +286,17 @@ HTMLOptionsCollection::NamedItem(JSConte
 {
   nsINode* item = GetNamedItem(name);
   if (!item) {
     return nullptr;
   }
   JS::Rooted<JSObject*> wrapper(cx, nsWrapperCache::GetWrapper());
   JSAutoCompartment ac(cx, wrapper);
   JS::Rooted<JS::Value> v(cx);
-  if (!mozilla::dom::WrapObject(cx, wrapper, item, item, nullptr,
-                                v.address())) {
+  if (!mozilla::dom::WrapObject(cx, wrapper, item, item, nullptr, &v)) {
     error.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
   return &v.toObject();
 }
 
 void
 HTMLOptionsCollection::GetSupportedNames(nsTArray<nsString>& aNames)
--- a/content/html/content/src/HTMLTableElement.cpp
+++ b/content/html/content/src/HTMLTableElement.cpp
@@ -230,17 +230,17 @@ TableRowsCollection::NamedItem(JSContext
       error = collection->NamedItem(name, getter_AddRefs(item));
       if (error.Failed()) {
         return nullptr;
       }
       if (item) {
         JS::Rooted<JSObject*> wrapper(cx, nsWrapperCache::GetWrapper());
         JSAutoCompartment ac(cx, wrapper);
         JS::Rooted<JS::Value> v(cx);
-        if (!mozilla::dom::WrapObject(cx, wrapper, item, v.address())) {
+        if (!mozilla::dom::WrapObject(cx, wrapper, item, &v)) {
           error.Throw(NS_ERROR_FAILURE);
           return nullptr;
         }
         return &v.toObject();
       }
     }
   );
   return nullptr;
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -2803,43 +2803,43 @@ nsGenericHTMLElement::Focus(ErrorResult&
     nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(this);
     aError = fm->SetFocus(elem, 0);
   }
 }
 
 void
 nsGenericHTMLElement::Click()
 {
-  if (HasFlag(NODE_HANDLING_CLICK))
+  if (HandlingClick())
     return;
 
   // Strong in case the event kills it
   nsCOMPtr<nsIDocument> doc = GetCurrentDoc();
 
   nsCOMPtr<nsIPresShell> shell;
   nsRefPtr<nsPresContext> context;
   if (doc) {
     shell = doc->GetShell();
     if (shell) {
       context = shell->GetPresContext();
     }
   }
 
-  SetFlags(NODE_HANDLING_CLICK);
+  SetHandlingClick();
 
   // Click() is never called from native code, but it may be
   // called from chrome JS. Mark this event trusted if Click()
   // is called from chrome code.
   nsMouseEvent event(nsContentUtils::IsCallerChrome(),
                      NS_MOUSE_CLICK, nullptr, nsMouseEvent::eReal);
   event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
 
   nsEventDispatcher::Dispatch(this, context, &event);
 
-  UnsetFlags(NODE_HANDLING_CLICK);
+  ClearHandlingClick();
 }
 
 bool
 nsGenericHTMLElement::IsHTMLFocusable(bool aWithMouse,
                                       bool *aIsFocusable,
                                       int32_t *aTabIndex)
 {
   nsIDocument *doc = GetCurrentDoc();
@@ -3120,17 +3120,17 @@ nsGenericHTMLElement::GetItemValue(JSCon
 {
   JS::Rooted<JSObject*> scope(aCx, aScope);
   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop)) {
     return JS::NullValue();
   }
 
   if (ItemScope()) {
     JS::Rooted<JS::Value> v(aCx);
-    if (!mozilla::dom::WrapObject(aCx, scope, this, v.address())) {
+    if (!mozilla::dom::WrapObject(aCx, scope, this, &v)) {
       aError.Throw(NS_ERROR_FAILURE);
       return JS::UndefinedValue();
     }
     return v;
   }
 
   nsString string;
   GetItemValueText(string);
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -1058,18 +1058,17 @@ enum {
   // hasn't re-found its form in nsGenericHTMLFormElement::UnbindFromTree yet.
   MAYBE_ORPHAN_FORM_ELEMENT =             FORM_ELEMENT_FLAG_BIT(1)
 };
 
 // NOTE: I don't think it's possible to have the above two flags set at the
 // same time, so if it becomes an issue we can probably merge them into the
 // same bit.  --bz
 
-// Make sure we have enough space for those bits
-PR_STATIC_ASSERT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 1 < 32);
+ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
 
 #undef FORM_ELEMENT_FLAG_BIT
 
 /**
  * A helper class for form elements that can contain children
  */
 class nsGenericHTMLFormElement : public nsGenericHTMLElement,
                                  public nsIFormControl
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -2551,17 +2551,17 @@ nsFormControlList::NamedItem(JSContext* 
 {
   nsISupports *item = NamedItemInternal(name, true);
   if (!item) {
     return nullptr;
   }
   JS::Rooted<JSObject*> wrapper(cx, nsWrapperCache::GetWrapper());
   JSAutoCompartment ac(cx, wrapper);
   JS::Rooted<JS::Value> v(cx);
-  if (!mozilla::dom::WrapObject(cx, wrapper, item, v.address())) {
+  if (!mozilla::dom::WrapObject(cx, wrapper, item, &v)) {
     error.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
   return &v.toObject();
 }
 
 static PLDHashOperator
 CollectNames(const nsAString& aName,
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2319,17 +2319,17 @@ nsHTMLDocument::NamedGetter(JSContext* c
   }
 
   JS::Rooted<JS::Value> val(cx);
   { // Scope for auto-compartment
     JS::Rooted<JSObject*> wrapper(cx, GetWrapper());
     JSAutoCompartment ac(cx, wrapper);
     // XXXbz Should we call the (slightly misnamed, really) WrapNativeParent
     // here?
-    if (!dom::WrapObject(cx, wrapper, supp, cache, nullptr, val.address())) {
+    if (!dom::WrapObject(cx, wrapper, supp, cache, nullptr, &val)) {
       rv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return nullptr;
     }
   }
   aFound = true;
   return &val.toObject();
 }
 
--- a/content/mathml/content/src/nsMathMLElement.cpp
+++ b/content/mathml/content/src/nsMathMLElement.cpp
@@ -933,22 +933,16 @@ nsMathMLElement::GetLinkTarget(nsAString
       return;
     case 1:
       return;
     }
     OwnerDoc()->GetBaseTarget(aTarget);
   }
 }
 
-nsLinkState
-nsMathMLElement::GetLinkState() const
-{
-  return Link::GetLinkState();
-}
-
 already_AddRefed<nsIURI>
 nsMathMLElement::GetHrefURI() const
 {
   nsCOMPtr<nsIURI> hrefURI;
   return IsLink(getter_AddRefs(hrefURI)) ? hrefURI.forget() : nullptr;
 }
 
 nsresult
--- a/content/mathml/content/src/nsMathMLElement.h
+++ b/content/mathml/content/src/nsMathMLElement.h
@@ -81,17 +81,16 @@ public:
   }
 
   NS_IMETHOD LinkAdded() MOZ_OVERRIDE { return NS_OK; }
   NS_IMETHOD LinkRemoved() MOZ_OVERRIDE { return NS_OK; }
   virtual bool IsFocusable(int32_t *aTabIndex = nullptr,
                              bool aWithMouse = false) MOZ_OVERRIDE;
   virtual bool IsLink(nsIURI** aURI) const MOZ_OVERRIDE;
   virtual void GetLinkTarget(nsAString& aTarget) MOZ_OVERRIDE;
-  virtual nsLinkState GetLinkState() const MOZ_OVERRIDE;
   virtual already_AddRefed<nsIURI> GetHrefURI() const MOZ_OVERRIDE;
   nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                    const nsAString& aValue, bool aNotify)
   {
     return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
   }
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
--- a/content/media/gstreamer/GStreamerReader.cpp
+++ b/content/media/gstreamer/GStreamerReader.cpp
@@ -432,20 +432,39 @@ bool GStreamerReader::DecodeAudioData()
   {
     ReentrantMonitorAutoEnter mon(mGstThreadsMonitor);
 
     if (mReachedEos) {
       mAudioQueue.Finish();
       return false;
     }
 
+    /* Wait something to be decoded before return or continue */
     if (!mAudioSinkBufferCount) {
-      return true;
+      if(!mVideoSinkBufferCount) {
+        /* We have nothing decoded so it makes no sense to return to the state machine
+         * as it will call us back immediately, we'll return again and so on, wasting
+         * CPU cycles for no job done. So, block here until there is either video or
+         * audio data available 
+        */
+        mon.Wait();
+        if (!mAudioSinkBufferCount) {
+          /* There is still no audio data available, so either there is video data or 
+           * something else has happened (Eos, etc...). Return to the state machine
+           * to process it.
+           */
+          return true;
+        }
+      }
+      else {
+        return true;
+      }
     }
 
+    NotifyBytesConsumed();
     buffer = gst_app_sink_pull_buffer(mAudioAppSink);
     mAudioSinkBufferCount--;
   }
 
   int64_t timestamp = GST_BUFFER_TIMESTAMP(buffer);
   timestamp = gst_segment_to_stream_time(&mAudioSegment,
       GST_FORMAT_TIME, timestamp);
   timestamp = GST_TIME_AS_USECONDS(timestamp);
@@ -478,20 +497,39 @@ bool GStreamerReader::DecodeVideoFrame(b
   {
     ReentrantMonitorAutoEnter mon(mGstThreadsMonitor);
 
     if (mReachedEos) {
       mVideoQueue.Finish();
       return false;
     }
 
+    /* Wait something to be decoded before return or continue */
     if (!mVideoSinkBufferCount) {
-      return true;
+      if (!mAudioSinkBufferCount) {
+        /* We have nothing decoded so it makes no sense to return to the state machine
+         * as it will call us back immediately, we'll return again and so on, wasting
+         * CPU cycles for no job done. So, block here until there is either video or
+         * audio data available 
+        */
+        mon.Wait();
+        if (!mVideoSinkBufferCount) {
+          /* There is still no video data available, so either there is audio data or 
+           * something else has happened (Eos, etc...). Return to the state machine
+           * to process it
+           */
+          return true;
+        }
+      }
+      else {
+        return true;
+      }
     }
 
+    NotifyBytesConsumed();
     mDecoder->NotifyDecodedFrames(0, 1);
 
     buffer = gst_app_sink_pull_buffer(mVideoAppSink);
     mVideoSinkBufferCount--;
   }
 
   bool isKeyframe = !GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DISCONT);
   if ((aKeyFrameSkip && !isKeyframe)) {
new file mode 100644
--- /dev/null
+++ b/content/media/test/crashtests/880724.html
@@ -0,0 +1,13 @@
+<script>
+o1 = new window.AudioContext();
+o5 = o1.createConvolver();
+o5.buffer = function() {
+    var buffer = o1.createBuffer(2, 3, 33120);
+    for(var c=0; c<2; c++) {
+        for(var i=0; i<3; i++) {
+            buffer.getChannelData(c)[i] = -1;
+        }
+    }
+    return buffer;
+}();
+</script>
\ No newline at end of file
--- a/content/media/test/crashtests/crashtests.list
+++ b/content/media/test/crashtests/crashtests.list
@@ -39,8 +39,9 @@ load 878407.html
 load 878478.html
 load 877527.html
 load 880129.html
 skip-if(B2G) load 880202.html # load failed, bug 833371 for B2G
 load 880342-1.html
 load 880342-2.html
 load 880384.html
 load 880404.html
+load 880724.html
--- a/content/media/webaudio/AudioBufferSourceNode.cpp
+++ b/content/media/webaudio/AudioBufferSourceNode.cpp
@@ -3,64 +3,62 @@
 /* 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 "AudioBufferSourceNode.h"
 #include "mozilla/dom/AudioBufferSourceNodeBinding.h"
 #include "nsMathUtils.h"
 #include "AudioNodeEngine.h"
+#include "AudioNodeStream.h"
+#include "AudioDestinationNode.h"
 #include "PannerNode.h"
-#include "GainProcessor.h"
 #include "speex/speex_resampler.h"
 #include <limits>
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioBufferSourceNode)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mBuffer)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlaybackRate)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mGain)
   if (tmp->Context()) {
     // AudioNode's Unlink implementation disconnects us from the graph
     // too, but we need to do this right here to make sure that
     // UnregisterAudioBufferSourceNode can properly untangle us from
     // the possibly connected PannerNodes.
     tmp->DisconnectFromGraph();
     tmp->Context()->UnregisterAudioBufferSourceNode(tmp);
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(AudioNode)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AudioBufferSourceNode, AudioNode)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBuffer)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlaybackRate)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGain)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioBufferSourceNode)
 NS_INTERFACE_MAP_END_INHERITING(AudioNode)
 
 NS_IMPL_ADDREF_INHERITED(AudioBufferSourceNode, AudioNode)
 NS_IMPL_RELEASE_INHERITED(AudioBufferSourceNode, AudioNode)
 
-class AudioBufferSourceNodeEngine : public AudioNodeEngine,
-                                    public GainProcessor
+class AudioBufferSourceNodeEngine : public AudioNodeEngine
 {
 public:
   explicit AudioBufferSourceNodeEngine(AudioNode* aNode,
                                        AudioDestinationNode* aDestination) :
     AudioNodeEngine(aNode),
-    GainProcessor(aDestination),
     mStart(0), mStop(TRACK_TICKS_MAX),
     mResampler(nullptr),
     mOffset(0), mDuration(0),
     mLoopStart(0), mLoopEnd(0),
     mBufferSampleRate(0), mPosition(0), mChannels(0), mPlaybackRate(1.0f),
     mDopplerShift(1.0f),
+    mDestination(static_cast<AudioNodeStream*>(aDestination->Stream())),
     mPlaybackRateTimeline(1.0f), mLoop(false)
   {}
 
   ~AudioBufferSourceNodeEngine()
   {
     if (mResampler) {
       speex_resampler_destroy(mResampler);
     }
@@ -79,19 +77,16 @@ public:
       if (mResampler && mPlaybackRateTimeline.HasSimpleValue() &&
           mPlaybackRateTimeline.GetValue() == 1.0 &&
           mBufferSampleRate == aSampleRate) {
         speex_resampler_destroy(mResampler);
         mResampler = nullptr;
       }
       WebAudioUtils::ConvertAudioParamToTicks(mPlaybackRateTimeline, nullptr, mDestination);
       break;
-    case AudioBufferSourceNode::GAIN:
-      SetGainParameter(aValue);
-      break;
     default:
       NS_ERROR("Bad AudioBufferSourceNodeEngine TimelineParameter");
     }
   }
   virtual void SetStreamTimeParameter(uint32_t aIndex, TrackTicks aParam)
   {
     switch (aIndex) {
     case AudioBufferSourceNode::START: mStart = aParam; break;
@@ -396,31 +391,16 @@ public:
         if (mOffset + t < mDuration) {
           CopyFromBuffer(aStream, aOutput, channels, &written, &currentPosition, mOffset + t, mDuration);
         } else {
           FillWithZeroes(aOutput, channels, &written, &currentPosition, TRACK_TICKS_MAX);
         }
       }
     }
 
-    // Process the gain on the AudioBufferSourceNode
-    if (!aOutput->IsNull()) {
-      if (!mGain.HasSimpleValue() &&
-          aOutput->mBuffer == mBuffer) {
-        // If we have borrowed out buffer, make sure to allocate a new one in case
-        // the gain value is not a simple value.
-        nsTArray<const void*> oldChannels;
-        oldChannels.AppendElements(aOutput->mChannelData);
-        AllocateAudioBlock(channels, aOutput);
-        ProcessGain(aStream, 1.0f, oldChannels, aOutput);
-      } else {
-        ProcessGain(aStream, 1.0f, aOutput->mChannelData, aOutput);
-      }
-    }
-
     // We've finished if we've gone past mStop, or if we're past mDuration when
     // looping is disabled.
     if (currentPosition >= mStop ||
         (!mLoop && currentPosition - mStart + mOffset > mDuration)) {
       *aFinished = true;
     }
   }
 
@@ -432,39 +412,38 @@ public:
   int32_t mDuration;
   int32_t mLoopStart;
   int32_t mLoopEnd;
   int32_t mBufferSampleRate;
   uint32_t mPosition;
   uint32_t mChannels;
   float mPlaybackRate;
   float mDopplerShift;
+  AudioNodeStream* mDestination;
   AudioParamTimeline mPlaybackRateTimeline;
   bool mLoop;
 };
 
 AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* aContext)
   : AudioNode(aContext,
               2,
               ChannelCountMode::Max,
               ChannelInterpretation::Speakers)
   , mLoopStart(0.0)
   , mLoopEnd(0.0)
   , mOffset(0.0)
   , mDuration(std::numeric_limits<double>::min())
   , mPlaybackRate(new AudioParam(this, SendPlaybackRateToStream, 1.0f))
-  , mGain(new AudioParam(this, SendGainToStream, 1.0f))
   , mLoop(false)
   , mStartCalled(false)
   , mStopped(false)
 {
-  AudioBufferSourceNodeEngine* engine =
-      new AudioBufferSourceNodeEngine(this, aContext->Destination());
-  mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
-  engine->SetSourceStream(static_cast<AudioNodeStream*> (mStream.get()));
+  mStream = aContext->Graph()->CreateAudioNodeStream(
+      new AudioBufferSourceNodeEngine(this, aContext->Destination()),
+      MediaStreamGraph::INTERNAL_STREAM);
   mStream->AddMainThreadListener(this);
 }
 
 AudioBufferSourceNode::~AudioBufferSourceNode()
 {
   if (Context()) {
     Context()->UnregisterAudioBufferSourceNode(this);
   }
@@ -638,23 +617,16 @@ AudioBufferSourceNode::NotifyMainThreadS
 void
 AudioBufferSourceNode::SendPlaybackRateToStream(AudioNode* aNode)
 {
   AudioBufferSourceNode* This = static_cast<AudioBufferSourceNode*>(aNode);
   SendTimelineParameterToStream(This, PLAYBACKRATE, *This->mPlaybackRate);
 }
 
 void
-AudioBufferSourceNode::SendGainToStream(AudioNode* aNode)
-{
-  AudioBufferSourceNode* This = static_cast<AudioBufferSourceNode*>(aNode);
-  SendTimelineParameterToStream(This, GAIN, *This->mGain);
-}
-
-void
 AudioBufferSourceNode::SendDopplerShiftToStream(double aDopplerShift)
 {
   SendDoubleParameterToStream(DOPPLERSHIFT, aDopplerShift);
 }
 
 void
 AudioBufferSourceNode::SendLoopParametersToStream()
 {
--- a/content/media/webaudio/AudioBufferSourceNode.h
+++ b/content/media/webaudio/AudioBufferSourceNode.h
@@ -71,20 +71,16 @@ public:
     mBuffer = aBuffer;
     SendBufferParameterToStream(aCx);
     SendLoopParametersToStream();
   }
   AudioParam* PlaybackRate() const
   {
     return mPlaybackRate;
   }
-  AudioParam* Gain() const
-  {
-    return mGain;
-  }
   bool Loop() const
   {
     return mLoop;
   }
   void SetLoop(bool aLoop)
   {
     mLoop = aLoop;
     SendLoopParametersToStream();
@@ -123,36 +119,33 @@ private:
     START,
     STOP,
     OFFSET,
     DURATION,
     LOOP,
     LOOPSTART,
     LOOPEND,
     PLAYBACKRATE,
-    GAIN,
     DOPPLERSHIFT
   };
 
   void SendLoopParametersToStream();
   void SendBufferParameterToStream(JSContext* aCx);
   void SendOffsetAndDurationParametersToStream(AudioNodeStream* aStream,
                                                double aOffset,
                                                double aDuration);
   static void SendPlaybackRateToStream(AudioNode* aNode);
-  static void SendGainToStream(AudioNode* aNode);
 
 private:
   double mLoopStart;
   double mLoopEnd;
   double mOffset;
   double mDuration;
   nsRefPtr<AudioBuffer> mBuffer;
   nsRefPtr<AudioParam> mPlaybackRate;
-  nsRefPtr<AudioParam> mGain;
   SelfReference<AudioBufferSourceNode> mPlayingRef; // a reference to self while playing
   bool mLoop;
   bool mStartCalled;
   bool mStopped;
 };
 
 }
 }
--- a/content/media/webaudio/GainNode.cpp
+++ b/content/media/webaudio/GainNode.cpp
@@ -2,78 +2,108 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "GainNode.h"
 #include "mozilla/dom/GainNodeBinding.h"
 #include "AudioNodeEngine.h"
-#include "GainProcessor.h"
+#include "AudioNodeStream.h"
+#include "AudioDestinationNode.h"
+#include "WebAudioUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED_1(GainNode, AudioNode,
                                      mGain)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(GainNode)
 NS_INTERFACE_MAP_END_INHERITING(AudioNode)
 
 NS_IMPL_ADDREF_INHERITED(GainNode, AudioNode)
 NS_IMPL_RELEASE_INHERITED(GainNode, AudioNode)
 
-class GainNodeEngine : public AudioNodeEngine,
-                       public GainProcessor
+class GainNodeEngine : public AudioNodeEngine
 {
 public:
   GainNodeEngine(AudioNode* aNode, AudioDestinationNode* aDestination)
     : AudioNodeEngine(aNode)
-    , GainProcessor(aDestination)
+    , mSource(nullptr)
+    , mDestination(static_cast<AudioNodeStream*> (aDestination->Stream()))
+    // Keep the default value in sync with the default value in GainNode::GainNode.
+    , mGain(1.f)
   {
   }
 
+  void SetSourceStream(AudioNodeStream* aSource)
+  {
+    mSource = aSource;
+  }
+
   enum Parameters {
     GAIN
   };
   void SetTimelineParameter(uint32_t aIndex,
                             const AudioParamTimeline& aValue,
                             TrackRate aSampleRate) MOZ_OVERRIDE
   {
     switch (aIndex) {
     case GAIN:
-      SetGainParameter(aValue);
+      MOZ_ASSERT(mSource && mDestination);
+      mGain = aValue;
+      WebAudioUtils::ConvertAudioParamToTicks(mGain, mSource, mDestination);
       break;
     default:
       NS_ERROR("Bad GainNodeEngine TimelineParameter");
     }
   }
 
   virtual void ProduceAudioBlock(AudioNodeStream* aStream,
                                  const AudioChunk& aInput,
                                  AudioChunk* aOutput,
                                  bool* aFinished)
   {
     MOZ_ASSERT(mSource == aStream, "Invalid source stream");
 
     if (aInput.IsNull()) {
       // If input is silent, so is the output
       aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
+    } else if (mGain.HasSimpleValue()) {
+      // Optimize the case where we only have a single value set as the volume
+      *aOutput = aInput;
+      aOutput->mVolume *= mGain.GetValue();
     } else {
-      if (mGain.HasSimpleValue()) {
-        // Copy the input chunk to the output chunk, since we will only be
-        // changing the mVolume member.
-        *aOutput = aInput;
-      } else {
-        // Create a new output chunk to avoid modifying the input chunk.
-        AllocateAudioBlock(aInput.mChannelData.Length(), aOutput);
+      // First, compute a vector of gains for each track tick based on the
+      // timeline at hand, and then for each channel, multiply the values
+      // in the buffer with the gain vector.
+      AllocateAudioBlock(aInput.mChannelData.Length(), aOutput);
+
+      // Compute the gain values for the duration of the input AudioChunk
+      // XXX we need to add a method to AudioEventTimeline to compute this buffer directly.
+      float computedGain[WEBAUDIO_BLOCK_SIZE];
+      for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
+        TrackTicks tick = aStream->GetCurrentPosition();
+        computedGain[counter] = mGain.GetValueAtTime(tick, counter) * aInput.mVolume;
       }
-      ProcessGain(aStream, aInput.mVolume, aInput.mChannelData, aOutput);
+
+      // Apply the gain to the output buffer
+      for (size_t channel = 0; channel < aOutput->mChannelData.Length(); ++channel) {
+        const float* inputBuffer = static_cast<const float*> (aInput.mChannelData[channel]);
+        float* buffer = static_cast<float*> (const_cast<void*>
+                          (aOutput->mChannelData[channel]));
+        AudioBlockCopyChannelWithScale(inputBuffer, computedGain, buffer);
+      }
     }
   }
+
+  AudioNodeStream* mSource;
+  AudioNodeStream* mDestination;
+  AudioParamTimeline mGain;
 };
 
 GainNode::GainNode(AudioContext* aContext)
   : AudioNode(aContext,
               2,
               ChannelCountMode::Max,
               ChannelInterpretation::Speakers)
   , mGain(new AudioParam(this, SendGainToStream, 1.0f))
deleted file mode 100644
--- a/content/media/webaudio/GainProcessor.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef GainProcessor_h_
-#define GainProcessor_h_
-
-#include "AudioNodeStream.h"
-#include "AudioDestinationNode.h"
-#include "WebAudioUtils.h"
-
-namespace mozilla {
-namespace dom {
-
-// This class implements the gain processing logic used by GainNodeEngine
-// and AudioBufferSourceNodeEngine.
-class GainProcessor
-{
-public:
-  explicit GainProcessor(AudioDestinationNode* aDestination)
-    : mSource(nullptr)
-    , mDestination(static_cast<AudioNodeStream*> (aDestination->Stream()))
-    , mGain(1.f)
-  {
-  }
-
-  void SetSourceStream(AudioNodeStream* aSource)
-  {
-    mSource = aSource;
-  }
-
-  void SetGainParameter(const AudioParamTimeline& aValue)
-  {
-    MOZ_ASSERT(mSource && mDestination);
-    mGain = aValue;
-    WebAudioUtils::ConvertAudioParamToTicks(mGain, mSource, mDestination);
-  }
-
-  void ProcessGain(AudioNodeStream* aStream,
-                   float aInputVolume,
-                   const nsTArray<const void*>& aInputChannelData,
-                   AudioChunk* aOutput)
-  {
-    MOZ_ASSERT(mSource == aStream, "Invalid source stream");
-
-    if (mGain.HasSimpleValue()) {
-      // Optimize the case where we only have a single value set as the volume
-      aOutput->mVolume *= mGain.GetValue();
-    } else {
-      // First, compute a vector of gains for each track tick based on the
-      // timeline at hand, and then for each channel, multiply the values
-      // in the buffer with the gain vector.
-
-      // Compute the gain values for the duration of the input AudioChunk
-      // XXX we need to add a method to AudioEventTimeline to compute this buffer directly.
-      float computedGain[WEBAUDIO_BLOCK_SIZE];
-      for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
-        TrackTicks tick = aStream->GetCurrentPosition();
-        computedGain[counter] = mGain.GetValueAtTime(tick, counter) * aInputVolume;
-      }
-
-      // Apply the gain to the output buffer
-      MOZ_ASSERT(aInputChannelData.Length() == aOutput->mChannelData.Length());
-      for (size_t channel = 0; channel < aOutput->mChannelData.Length(); ++channel) {
-        const float* inputBuffer = static_cast<const float*> (aInputChannelData[channel]);
-        float* buffer = static_cast<float*> (const_cast<void*>
-                          (aOutput->mChannelData[channel]));
-        AudioBlockCopyChannelWithScale(inputBuffer, computedGain, buffer);
-      }
-    }
-  }
-
-protected:
-  AudioNodeStream* mSource;
-  AudioNodeStream* mDestination;
-  AudioParamTimeline mGain;
-};
-
-}
-}
-
-#endif
-
--- a/content/media/webaudio/test/Makefile.in
+++ b/content/media/webaudio/test/Makefile.in
@@ -7,16 +7,17 @@ topsrcdir      := @top_srcdir@
 srcdir         := @srcdir@
 VPATH          := @srcdir@
 relativesrcdir := @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_FILES := \
   webaudio.js \
+  layouttest-glue.js \
   test_bug808374.html \
   test_bug827541.html \
   test_bug839753.html \
   test_bug845960.html \
   test_bug856771.html \
   test_bug866570.html \
   test_bug866737.html \
   test_bug867089.html \
@@ -34,44 +35,42 @@ MOCHITEST_FILES := \
   test_audioParamLinearRamp.html \
   test_audioParamSetCurveAtTime.html \
   test_audioParamSetCurveAtTimeZeroDuration.html \
   test_audioParamSetTargetAtTime.html \
   test_audioParamSetValueAtTime.html \
   test_audioParamTimelineDestinationOffset.html \
   test_audioBufferSourceNode.html \
   test_audioBufferSourceNodeEnded.html \
-  test_audioBufferSourceNodeGain.html \
-  test_audioBufferSourceNodeGainInLoop.html \
   test_audioBufferSourceNodeLazyLoopParam.html \
   test_audioBufferSourceNodeLoop.html \
   test_audioBufferSourceNodeLoopStartEnd.html \
   test_audioBufferSourceNodeLoopStartEndSame.html \
   test_audioBufferSourceNodeNullBuffer.html \
   test_badConnect.html \
   test_biquadFilterNode.html \
   test_channelMergerNode.html \
   test_channelMergerNodeWithVolume.html \
   test_channelSplitterNode.html \
   test_channelSplitterNodeWithVolume.html \
   test_currentTime.html \
   test_delayNode.html \
   test_delayNodeSmallMaxDelay.html \
   test_delayNodeWithGain.html \
-  test_delayNodeWithGainAlternate.html \
   test_dynamicsCompressorNode.html \
   test_gainNode.html \
   test_gainNodeInLoop.html \
   test_mediaDecoding.html \
   test_mixingRules.html \
   test_nodeToParamConnection.html \
   test_OfflineAudioContext.html \
   test_offlineDestinationChannelCountLess.html \
   test_offlineDestinationChannelCountMore.html \
   test_pannerNode.html \
+  test_pannerNode_equalPower.html \
   test_scriptProcessorNode.html \
   test_scriptProcessorNodeChannelCount.html \
   test_scriptProcessorNodeZeroInputOutput.html \
   test_singleSourceDest.html \
   test_waveShaper.html \
   test_waveShaperNoCurve.html \
   test_waveShaperZeroLengthCurve.html \
   test_waveTable.html \
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/blink/Makefile.in
@@ -0,0 +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/.
+
+DEPTH          := @DEPTH@
+topsrcdir      := @top_srcdir@
+srcdir         := @srcdir@
+VPATH          := @srcdir@
+relativesrcdir := @relativesrcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MOCHITEST_FILES := \
+  panner-model-testing.js \
+  audio-testing.js \
+  $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/blink/README
@@ -0,0 +1,9 @@
+This directory contains tests originally borrowed from the Blink Web Audio test
+suite.
+
+The process of borrowing tests from Blink is as follows:
+
+* Import the pristine file from the Blink repo, noting the revision in the
+  commit message.
+* Modify the test files to turn the LayoutTest into a mochitest-plain and add
+* them to the test suite in a separate commit.
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/blink/audio-testing.js
@@ -0,0 +1,192 @@
+if (window.testRunner)
+    testRunner.overridePreference("WebKitWebAudioEnabled", "1");
+
+function writeString(s, a, offset) {
+    for (var i = 0; i < s.length; ++i) {
+        a[offset + i] = s.charCodeAt(i);
+    }
+}
+
+function writeInt16(n, a, offset) {
+    n = Math.floor(n);
+   
+    var b1 = n & 255;
+    var b2 = (n >> 8) & 255;
+
+    a[offset + 0] = b1;
+    a[offset + 1] = b2;
+}
+
+function writeInt32(n, a, offset) {
+    n = Math.floor(n);
+    var b1 = n & 255;
+    var b2 = (n >> 8) & 255;
+    var b3 = (n >> 16) & 255;
+    var b4 = (n >> 24) & 255;
+
+    a[offset + 0] = b1;
+    a[offset + 1] = b2;
+    a[offset + 2] = b3;
+    a[offset + 3] = b4;
+}
+
+function writeAudioBuffer(audioBuffer, a, offset) {
+    var n = audioBuffer.length;
+    var channels = audioBuffer.numberOfChannels;
+   
+    for (var i = 0; i < n; ++i) {
+        for (var k = 0; k < channels; ++k) {
+            var buffer = audioBuffer.getChannelData(k);
+            var sample = buffer[i] * 32768.0;
+
+            // Clip samples to the limitations of 16-bit.
+            // If we don't do this then we'll get nasty wrap-around distortion.
+            if (sample < -32768)
+                sample = -32768;
+            if (sample > 32767)
+                sample = 32767;
+
+            writeInt16(sample, a, offset);
+            offset += 2;
+        }
+    }
+}
+
+function createWaveFileData(audioBuffer) {
+    var frameLength = audioBuffer.length;
+    var numberOfChannels = audioBuffer.numberOfChannels;
+    var sampleRate = audioBuffer.sampleRate;
+    var bitsPerSample = 16;
+    var byteRate = sampleRate * numberOfChannels * bitsPerSample/8;
+    var blockAlign = numberOfChannels * bitsPerSample/8;
+    var wavDataByteLength = frameLength * numberOfChannels * 2; // 16-bit audio
+    var headerByteLength = 44;
+    var totalLength = headerByteLength + wavDataByteLength;
+
+    var waveFileData = new Uint8Array(totalLength);
+   
+    var subChunk1Size = 16; // for linear PCM
+    var subChunk2Size = wavDataByteLength;
+    var chunkSize = 4 + (8 + subChunk1Size) + (8 + subChunk2Size);
+
+    writeString("RIFF", waveFileData, 0);
+    writeInt32(chunkSize, waveFileData, 4);
+    writeString("WAVE", waveFileData, 8);
+    writeString("fmt ", waveFileData, 12);
+   
+    writeInt32(subChunk1Size, waveFileData, 16);      // SubChunk1Size (4)
+    writeInt16(1, waveFileData, 20);                  // AudioFormat (2)
+    writeInt16(numberOfChannels, waveFileData, 22);   // NumChannels (2)
+    writeInt32(sampleRate, waveFileData, 24);         // SampleRate (4)
+    writeInt32(byteRate, waveFileData, 28);           // ByteRate (4)
+    writeInt16(blockAlign, waveFileData, 32);         // BlockAlign (2)
+    writeInt32(bitsPerSample, waveFileData, 34);      // BitsPerSample (4)
+                                                     
+    writeString("data", waveFileData, 36);            
+    writeInt32(subChunk2Size, waveFileData, 40);      // SubChunk2Size (4)
+   
+    // Write actual audio data starting at offset 44.
+    writeAudioBuffer(audioBuffer, waveFileData, 44);
+   
+    return waveFileData;
+}
+
+function createAudioData(audioBuffer) {
+    return createWaveFileData(audioBuffer);
+}
+
+function finishAudioTest(event) {
+    var audioData = createAudioData(event.renderedBuffer);
+    testRunner.setAudioData(audioData);
+    testRunner.notifyDone();
+}
+
+// Create an impulse in a buffer of length sampleFrameLength
+function createImpulseBuffer(context, sampleFrameLength) {
+    var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleRate);
+    var n = audioBuffer.length;
+    var dataL = audioBuffer.getChannelData(0);
+
+    for (var k = 0; k < n; ++k) {
+        dataL[k] = 0;
+    }
+    dataL[0] = 1;
+
+    return audioBuffer;
+}
+
+// Create a buffer of the given length with a linear ramp having values 0 <= x < 1.
+function createLinearRampBuffer(context, sampleFrameLength) {
+    var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleRate);
+    var n = audioBuffer.length;
+    var dataL = audioBuffer.getChannelData(0);
+
+    for (var i = 0; i < n; ++i)
+        dataL[i] = i / n;
+
+    return audioBuffer;
+}
+
+// Create a buffer of the given length having a constant value.
+function createConstantBuffer(context, sampleFrameLength, constantValue) {
+    var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleRate);
+    var n = audioBuffer.length;
+    var dataL = audioBuffer.getChannelData(0);
+
+    for (var i = 0; i < n; ++i)
+        dataL[i] = constantValue;
+
+    return audioBuffer;
+}
+
+// Create a stereo impulse in a buffer of length sampleFrameLength
+function createStereoImpulseBuffer(context, sampleFrameLength) {
+    var audioBuffer = context.createBuffer(2, sampleFrameLength, context.sampleRate);
+    var n = audioBuffer.length;
+    var dataL = audioBuffer.getChannelData(0);
+    var dataR = audioBuffer.getChannelData(1);
+
+    for (var k = 0; k < n; ++k) {
+        dataL[k] = 0;
+        dataR[k] = 0;
+    }
+    dataL[0] = 1;
+    dataR[0] = 1;
+
+    return audioBuffer;
+}
+
+// Convert time (in seconds) to sample frames.
+function timeToSampleFrame(time, sampleRate) {
+    return Math.floor(0.5 + time * sampleRate);
+}
+
+// Compute the number of sample frames consumed by noteGrainOn with
+// the specified |grainOffset|, |duration|, and |sampleRate|.
+function grainLengthInSampleFrames(grainOffset, duration, sampleRate) {
+    var startFrame = timeToSampleFrame(grainOffset, sampleRate);
+    var endFrame = timeToSampleFrame(grainOffset + duration, sampleRate);
+
+    return endFrame - startFrame;
+}
+
+// True if the number is not an infinity or NaN
+function isValidNumber(x) {
+    return !isNaN(x) && (x != Infinity) && (x != -Infinity);
+}
+
+function shouldThrowTypeError(func, text) {
+    var ok = false;
+    try {
+        func();
+    } catch (e) {
+        if (e instanceof TypeError) {
+            ok = true;
+        }
+    }
+    if (ok) {
+        testPassed(text + " threw TypeError.");
+    } else {
+        testFailed(text + " should throw TypeError.");
+    }
+}
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/blink/panner-model-testing.js
@@ -0,0 +1,209 @@
+var sampleRate = 48000.0;
+
+var numberOfChannels = 1;
+
+// Time step when each panner node starts.
+var timeStep = 0.001;
+
+// Length of the impulse signal.
+var pulseLengthFrames = Math.round(timeStep * sampleRate);
+
+// How many panner nodes to create for the test
+var nodesToCreate = 100;
+
+// Be sure we render long enough for all of our nodes.
+var renderLengthSeconds = timeStep * (nodesToCreate + 1);
+
+// These are global mostly for debugging.
+var context;
+var impulse;
+var bufferSource;
+var panner;
+var position;
+var time;
+      
+var renderedBuffer;
+var renderedLeft;
+var renderedRight;
+
+function createGraph(context, nodeCount) {
+    bufferSource = new Array(nodeCount);
+    panner = new Array(nodeCount);
+    position = new Array(nodeCount);
+    time = new Array(nodeCount);
+    // Angle between panner locations.  (nodeCount - 1 because we want
+    // to include both 0 and 180 deg.
+    var angleStep = Math.PI / (nodeCount - 1);
+
+    if (numberOfChannels == 2) {
+        impulse = createStereoImpulseBuffer(context, pulseLengthFrames);
+    }
+    else
+        impulse = createImpulseBuffer(context, pulseLengthFrames);
+
+    for (var k = 0; k < nodeCount; ++k) {
+        bufferSource[k] = context.createBufferSource();
+        bufferSource[k].buffer = impulse;
+
+        panner[k] = context.createPanner();
+        panner[k].panningModel = "equalpower";
+        panner[k].distanceModel = "linear";
+
+        var angle = angleStep * k;
+        position[k] = {angle : angle, x : Math.cos(angle), z : Math.sin(angle)};
+        panner[k].setPosition(position[k].x, 0, position[k].z);
+
+        bufferSource[k].connect(panner[k]);
+        panner[k].connect(context.destination);
+
+        // Start the source
+        time[k] = k * timeStep;
+        bufferSource[k].noteOn(time[k]);
+    }
+}
+
+function createTestAndRun(context, nodeCount, numberOfSourceChannels) {
+    numberOfChannels = numberOfSourceChannels;
+
+    createGraph(context, nodeCount);
+
+    context.oncomplete = checkResult;
+    context.startRendering();
+}
+
+// Map our position angle to the azimuth angle (in degrees).
+//
+// An angle of 0 corresponds to an azimuth of 90 deg; pi, to -90 deg.
+function angleToAzimuth(angle) {
+    return 90 - angle * 180 / Math.PI;
+}
+
+// The gain caused by the EQUALPOWER panning model
+function equalPowerGain(angle) {
+    var azimuth = angleToAzimuth(angle);
+
+    if (numberOfChannels == 1) {
+        var panPosition = (azimuth + 90) / 180;
+
+        var gainL = Math.cos(0.5 * Math.PI * panPosition);
+        var gainR = Math.sin(0.5 * Math.PI * panPosition);
+
+        return { left : gainL, right : gainR };
+    } else {
+        if (azimuth <= 0) {
+            var panPosition = (azimuth + 90) / 90;
+    
+            var gainL = 1 + Math.cos(0.5 * Math.PI * panPosition);
+            var gainR = Math.sin(0.5 * Math.PI * panPosition);
+    
+            return { left : gainL, right : gainR };
+        } else {
+            var panPosition = azimuth / 90;
+    
+            var gainL = Math.cos(0.5 * Math.PI * panPosition);
+            var gainR = 1 + Math.sin(0.5 * Math.PI * panPosition);
+    
+            return { left : gainL, right : gainR };
+        }
+    }
+}
+
+function checkResult(event) {
+    renderedBuffer = event.renderedBuffer;
+    renderedLeft = renderedBuffer.getChannelData(0);
+    renderedRight = renderedBuffer.getChannelData(1);
+
+    // The max error we allow between the rendered impulse and the
+    // expected value.  This value is experimentally determined.  Set
+    // to 0 to make the test fail to see what the actual error is.
+    var maxAllowedError = 1.3e-6;
+  
+    var success = true;
+
+    // Number of impulses found in the rendered result.
+    var impulseCount = 0;
+
+    // Max (relative) error and the index of the maxima for the left
+    // and right channels.
+    var maxErrorL = 0;
+    var maxErrorIndexL = 0;
+    var maxErrorR = 0;
+    var maxErrorIndexR = 0;
+
+    // Number of impulses that don't match our expected locations.
+    var timeCount = 0;
+
+    // Locations of where the impulses aren't at the expected locations.
+    var timeErrors = new Array();
+
+    for (var k = 0; k < renderedLeft.length; ++k) {
+        // We assume that the left and right channels start at the same instant.
+        if (renderedLeft[k] != 0 || renderedRight[k] != 0) {
+            // The expected gain for the left and right channels.
+            var pannerGain = equalPowerGain(position[impulseCount].angle);
+            var expectedL = pannerGain.left;
+            var expectedR = pannerGain.right;
+
+            // Absolute error in the gain.
+            var errorL = Math.abs(renderedLeft[k] - expectedL);
+            var errorR = Math.abs(renderedRight[k] - expectedR);
+
+            if (Math.abs(errorL) > maxErrorL) {
+                maxErrorL = Math.abs(errorL);
+                maxErrorIndexL = impulseCount;
+            }
+            if (Math.abs(errorR) > maxErrorR) {
+                maxErrorR = Math.abs(errorR);
+                maxErrorIndexR = impulseCount;
+            }
+
+            // Keep track of the impulses that didn't show up where we
+            // expected them to be.
+            var expectedOffset = timeToSampleFrame(time[impulseCount], sampleRate);
+            if (k != expectedOffset) {
+                timeErrors[timeCount] = { actual : k, expected : expectedOffset};
+                ++timeCount;
+            }
+            ++impulseCount;
+        }
+    }
+
+    if (impulseCount == nodesToCreate) {
+        testPassed("Number of impulses matches the number of panner nodes.");
+    } else {
+        testFailed("Number of impulses is incorrect.  (Found " + impulseCount + " but expected " + nodesToCreate + ")");
+        success = false;
+    }
+
+    if (timeErrors.length > 0) {
+        success = false;
+        testFailed(timeErrors.length + " timing errors found in " + nodesToCreate + " panner nodes.");
+        for (var k = 0; k < timeErrors.length; ++k) {
+            testFailed("Impulse at sample " + timeErrors[k].actual + " but expected " + timeErrors[k].expected);
+        }
+    } else {
+        testPassed("All impulses at expected offsets.");
+    }
+
+    if (maxErrorL <= maxAllowedError) {
+        testPassed("Left channel gain values are correct.");
+    } else {
+        testFailed("Left channel gain values are incorrect.  Max error = " + maxErrorL + " at time " + time[maxErrorIndexL] + " (threshold = " + maxAllowedError + ")");
+        success = false;
+    }
+
+    if (maxErrorR <= maxAllowedError) {
+        testPassed("Right channel gain values are correct.");
+    } else {
+        testFailed("Right channel gain values are incorrect.  Max error = " + maxErrorR + " at time " + time[maxErrorIndexR] + " (threshold = " + maxAllowedError + ")");
+        success = false;
+    }
+
+    if (success) {
+        testPassed("EqualPower panner test passed");
+    } else {
+        testFailed("EqualPower panner test failed");
+    }
+
+    finishJSTest();
+}
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/layouttest-glue.js
@@ -0,0 +1,15 @@
+// Reimplementation of the LayoutTest API from Blink so we can easily port
+// WebAudio tests to Simpletest, without touching the internals of the test.
+
+function testFailed(msg) {
+  ok(false, msg);
+}
+
+function testPassed(msg) {
+  ok(true, msg);
+}
+
+function finishJSTest() {
+  SimpleTest.finish();
+}
+
--- a/content/media/webaudio/test/moz.build
+++ b/content/media/webaudio/test/moz.build
@@ -1,5 +1,7 @@
 # -*- Mode: python; c-basic-offset: 4; 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/.
+
+PARALLEL_DIRS += ['blink']
--- a/content/media/webaudio/test/test_audioBufferSourceNode.html
+++ b/content/media/webaudio/test/test_audioBufferSourceNode.html
@@ -14,18 +14,16 @@ var gTest = {
   length: 4096,
   createGraph: function(context) {
     var buffer = context.createBuffer(1, 2048, context.sampleRate);
     for (var i = 0; i < 2048; ++i) {
       buffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * i / context.sampleRate);
     }
 
     var source = context.createBufferSource();
-    ok("gain" in source, "AudioBufferSourceNode.gain must exist");
-    is(source.gain.value, 1, "AudioBufferSourceNode.gain's default value must be 1");
 
     var sp = context.createScriptProcessor(2048);
     source.start(0);
     source.buffer = buffer;
     return source;
   },
   createExpectedBuffers: function(context) {
     var buffers = [];
deleted file mode 100644
--- a/content/media/webaudio/test/test_audioBufferSourceNodeGain.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test AudioBufferSourceNode.gain</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="webaudio.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-var gTest = {
-  length: 2048,
-  numberOfChannels: 1,
-  createGraph: function(context) {
-    var buffer = context.createBuffer(1, 2048, context.sampleRate);
-    for (var i = 0; i < 2048; ++i) {
-      buffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * i / context.sampleRate);
-    }
-
-    var source = context.createBufferSource();
-
-    source.buffer = buffer;
-
-    source.gain.value = 0.5;
-
-    source.start(0);
-    return source;
-  },
-  createExpectedBuffers: function(context) {
-    var expectedBuffer = context.createBuffer(1, 2048, context.sampleRate);
-    for (var i = 0; i < 2048; ++i) {
-      expectedBuffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * i / context.sampleRate) / 2;
-    }
-    return expectedBuffer;
-  },
-};
-
-runTest();
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/content/media/webaudio/test/test_audioBufferSourceNodeGainInLoop.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test AudioBufferSourceNode.gain in presence of loops</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="webaudio.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-var gTest = {
-  length: 4096,
-  numberOfChannels: 1,
-  createGraph: function(context) {
-    var sourceBuffer = context.createBuffer(1, 2048, context.sampleRate);
-    for (var i = 0; i < 2048; ++i) {
-      sourceBuffer.getChannelData(0)[i] = 1;
-    }
-
-    var source = context.createBufferSource();
-    source.buffer = sourceBuffer;
-    source.loop = true;
-    source.start(0);
-    source.stop(sourceBuffer.duration * 2);
-
-    // Adjust the gain in a way that we don't just end up modifying AudioChunk::mVolume
-    source.gain.setValueAtTime(0.5, 0);
-    return source;
-  },
-  createExpectedBuffers: function(context) {
-    var expectedBuffer = context.createBuffer(1, 4096, context.sampleRate);
-    for (var i = 0; i < 4096; ++i) {
-      expectedBuffer.getChannelData(0)[i] = 0.5;
-    }
-    return expectedBuffer;
-  },
-};
-
-runTest();
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/content/media/webaudio/test/test_delayNodeWithGainAlternate.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test DelayNode with an AudioBufferSourceNode.gain value</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<pre id="test">
-<script src="webaudio.js" type="text/javascript"></script>
-<script class="testbody" type="text/javascript">
-
-var gTest = {
-  length: 4096,
-  numberOfChannels: 1,
-  createGraph: function(context) {
-    var buffer = context.createBuffer(1, 2048, context.sampleRate);
-    for (var i = 0; i < 2048; ++i) {
-      buffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * i / context.sampleRate);
-    }
-
-    var source = context.createBufferSource();
-
-    var delay = context.createDelay();
-
-    source.buffer = buffer;
-    source.gain.value = 0.5;
-
-    source.connect(delay);
-
-    // Delay the source stream by 2048 frames
-    delay.delayTime.value = 2048 / context.sampleRate;
-
-    source.start(0);
-    return delay;
-  },
-  createExpectedBuffers: function(context) {
-    var expectedBuffer = context.createBuffer(1, 2048 * 2, context.sampleRate);
-    for (var i = 2048; i < 2048 * 2; ++i) {
-      expectedBuffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * (i - 2048) / context.sampleRate) / 2;
-    }
-    return expectedBuffer;
-  },
-};
-
-runTest();
-
-</script>
-</pre>
-</body>
-</html>
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/test_pannerNode_equalPower.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test PannerNode</title>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="webaudio.js"></script>
+<script type="text/javascript" src="layouttest-glue.js"></script>
+<script type="text/javascript" src="blink/audio-testing.js"></script>
+<script type="text/javascript" src="blink/panner-model-testing.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+  SpecialPowers.setBoolPref("media.webaudio.enabled", true);
+  function checkFinished() {
+    SpecialPowers.clearUserPref("media.webaudio.enabled");
+    SimpleTest.finish();
+  }
+  var ctx = new OfflineAudioContext(2, sampleRate * renderLengthSeconds, sampleRate);
+  createTestAndRun(ctx, nodesToCreate, 2, checkFinished);
+});
+</script>
+</pre>
+</body>
+</html>
--- a/content/smil/SMILBoolType.cpp
+++ b/content/smil/SMILBoolType.cpp
@@ -5,32 +5,30 @@
 
 #include "SMILBoolType.h"
 #include "nsSMILValue.h"
 #include "nsDebug.h"
 #include <math.h>
 
 namespace mozilla {
 
-/*static*/ SMILBoolType SMILBoolType::sSingleton;
-
 void
 SMILBoolType::Init(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.IsNull(), "Unexpected value type");
   aValue.mU.mBool = false;
   aValue.mType = this;
 }
 
 void
 SMILBoolType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value");
   aValue.mU.mBool = false;
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 SMILBoolType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
   aDest.mU.mBool = aSrc.mU.mBool;
--- a/content/smil/SMILBoolType.h
+++ b/content/smil/SMILBoolType.h
@@ -10,17 +10,21 @@
 #include "nsISMILType.h"
 
 namespace mozilla {
 
 class SMILBoolType : public nsISMILType
 {
 public:
   // Singleton for nsSMILValue objects to hold onto.
-  static SMILBoolType sSingleton;
+  static SMILBoolType* Singleton()
+  {
+    static SMILBoolType sSingleton;
+    return &sSingleton;
+  }
 
 protected:
   // nsISMILType Methods
   // -------------------
   virtual void     Init(nsSMILValue& aValue) const MOZ_OVERRIDE;
   virtual void     Destroy(nsSMILValue&) const;
   virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const MOZ_OVERRIDE;
   virtual nsresult Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd,
--- a/content/smil/SMILEnumType.cpp
+++ b/content/smil/SMILEnumType.cpp
@@ -5,32 +5,30 @@
 
 #include "SMILEnumType.h"
 #include "nsSMILValue.h"
 #include "nsDebug.h"
 #include <math.h>
 
 namespace mozilla {
 
-/*static*/ SMILEnumType SMILEnumType::sSingleton;
-
 void
 SMILEnumType::Init(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.IsNull(), "Unexpected value type");
   aValue.mU.mUint = 0;
   aValue.mType = this;
 }
 
 void
 SMILEnumType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value");
   aValue.mU.mUint = 0;
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 SMILEnumType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
   aDest.mU.mUint = aSrc.mU.mUint;
--- a/content/smil/SMILEnumType.h
+++ b/content/smil/SMILEnumType.h
@@ -10,17 +10,22 @@
 #include "nsISMILType.h"
 
 namespace mozilla {
 
 class SMILEnumType : public nsISMILType
 {
 public:
   // Singleton for nsSMILValue objects to hold onto.
-  static SMILEnumType sSingleton;
+  static SMILEnumType*
+  Singleton()
+  {
+    static SMILEnumType sSingleton;
+    return &sSingleton;
+  }
 
 protected:
   // nsISMILType Methods
   // -------------------
   virtual void     Init(nsSMILValue& aValue) const MOZ_OVERRIDE;
   virtual void     Destroy(nsSMILValue&) const;
   virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const MOZ_OVERRIDE;
   virtual bool     IsEqual(const nsSMILValue& aLeft,
--- a/content/smil/SMILIntegerType.cpp
+++ b/content/smil/SMILIntegerType.cpp
@@ -5,32 +5,30 @@
 
 #include "SMILIntegerType.h"
 #include "nsSMILValue.h"
 #include "nsDebug.h"
 #include <math.h>
 
 namespace mozilla {
 
-/*static*/ SMILIntegerType SMILIntegerType::sSingleton;
-
 void
 SMILIntegerType::Init(nsSMILValue& aValue) const
 {
   NS_ABORT_IF_FALSE(aValue.IsNull(), "Unexpected value type");
   aValue.mU.mInt = 0;
   aValue.mType = this;
 }
 
 void
 SMILIntegerType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value");
   aValue.mU.mInt = 0;
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 SMILIntegerType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
   aDest.mU.mInt = aSrc.mU.mInt;
--- a/content/smil/SMILIntegerType.h
+++ b/content/smil/SMILIntegerType.h
@@ -24,17 +24,22 @@ public:
   virtual nsresult ComputeDistance(const nsSMILValue& aFrom,
                                    const nsSMILValue& aTo,
                                    double& aDistance) const MOZ_OVERRIDE;
   virtual nsresult Interpolate(const nsSMILValue& aStartVal,
                                const nsSMILValue& aEndVal,
                                double aUnitDistance,
                                nsSMILValue& aResult) const MOZ_OVERRIDE;
 
-  static SMILIntegerType sSingleton;
+  static SMILIntegerType*
+  Singleton()
+  {
+    static SMILIntegerType sSingleton;
+    return &sSingleton;
+  }
 
 private:
   SMILIntegerType() {}
 };
 
 } // namespace mozilla
 
 #endif // MOZILLA_SMILINTEGERTYPE_H_
--- a/content/smil/SMILStringType.cpp
+++ b/content/smil/SMILStringType.cpp
@@ -5,33 +5,31 @@
 
 #include "SMILStringType.h"
 #include "nsSMILValue.h"
 #include "nsDebug.h"
 #include "nsString.h"
 
 namespace mozilla {
 
-/*static*/ SMILStringType SMILStringType::sSingleton;
-
 void
 SMILStringType::Init(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.IsNull(), "Unexpected value type");
   aValue.mU.mPtr = new nsString();
   aValue.mType = this;
 }
 
 void
 SMILStringType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value");
   delete static_cast<nsAString*>(aValue.mU.mPtr);
   aValue.mU.mPtr = nullptr;
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 SMILStringType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
 
--- a/content/smil/SMILStringType.h
+++ b/content/smil/SMILStringType.h
@@ -10,17 +10,22 @@
 #include "nsISMILType.h"
 
 namespace mozilla {
 
 class SMILStringType : public nsISMILType
 {
 public:
   // Singleton for nsSMILValue objects to hold onto.
-  static SMILStringType sSingleton;
+  static SMILStringType*
+  Singleton()
+  {
+    static SMILStringType sSingleton;
+    return &sSingleton;
+  }
 
 protected:
   // nsISMILType Methods
   // -------------------
   virtual void     Init(nsSMILValue& aValue) const MOZ_OVERRIDE;
   virtual void     Destroy(nsSMILValue&) const;
   virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const MOZ_OVERRIDE;
   virtual bool     IsEqual(const nsSMILValue& aLeft,
--- a/content/smil/nsSMILCSSValueType.cpp
+++ b/content/smil/nsSMILCSSValueType.cpp
@@ -146,17 +146,17 @@ nsSMILCSSValueType::Init(nsSMILValue& aV
   aValue.mType = this;
 }
 
 void
 nsSMILCSSValueType::Destroy(nsSMILValue& aValue) const
 {
   NS_ABORT_IF_FALSE(aValue.mType == this, "Unexpected SMIL value type");
   delete static_cast<ValueWrapper*>(aValue.mU.mPtr);
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 nsSMILCSSValueType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
 {
   NS_ABORT_IF_FALSE(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_ABORT_IF_FALSE(aDest.mType == this, "Unexpected SMIL value type");
   const ValueWrapper* srcWrapper = ExtractValueWrapper(aSrc);
--- a/content/smil/nsSMILFloatType.cpp
+++ b/content/smil/nsSMILFloatType.cpp
@@ -3,32 +3,30 @@
  * 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 "nsSMILFloatType.h"
 #include "nsSMILValue.h"
 #include "nsDebug.h"
 #include <math.h>
 
-/*static*/ nsSMILFloatType nsSMILFloatType::sSingleton;
-
 void
 nsSMILFloatType::Init(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.IsNull(), "Unexpected value type");
   aValue.mU.mDouble = 0.0;
   aValue.mType = this;
 }
 
 void
 nsSMILFloatType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value");
   aValue.mU.mDouble = 0.0;
-  aValue.mType      = &nsSMILNullType::sSingleton;
+  aValue.mType      = nsSMILNullType::Singleton();
 }
 
 nsresult
 nsSMILFloatType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
   aDest.mU.mDouble = aSrc.mU.mDouble;
--- a/content/smil/nsSMILFloatType.h
+++ b/content/smil/nsSMILFloatType.h
@@ -8,17 +8,22 @@
 
 #include "mozilla/Attributes.h"
 #include "nsISMILType.h"
 
 class nsSMILFloatType : public nsISMILType
 {
 public:
   // Singleton for nsSMILValue objects to hold onto.
-  static nsSMILFloatType sSingleton;
+  static nsSMILFloatType*
+  Singleton()
+  {
+    static nsSMILFloatType sSingleton;
+    return &sSingleton;
+  }
 
 protected:
   // nsISMILType Methods
   // -------------------
   virtual void     Init(nsSMILValue& aValue) const MOZ_OVERRIDE;
   virtual void     Destroy(nsSMILValue&) const;
   virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const MOZ_OVERRIDE;
   virtual bool     IsEqual(const nsSMILValue& aLeft,
--- a/content/smil/nsSMILNullType.cpp
+++ b/content/smil/nsSMILNullType.cpp
@@ -2,25 +2,23 @@
 /* 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 "nsSMILNullType.h"
 #include "nsSMILValue.h"
 #include "nsDebug.h"
 
-/*static*/ nsSMILNullType nsSMILNullType::sSingleton;
-
 nsresult
 nsSMILNullType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aSrc.mType == this, "Unexpected source type");
   aDest.mU    = aSrc.mU;
-  aDest.mType = &sSingleton;
+  aDest.mType = Singleton();
   return NS_OK;
 }
 
 bool
 nsSMILNullType::IsEqual(const nsSMILValue& aLeft,
                         const nsSMILValue& aRight) const
 {
   NS_PRECONDITION(aLeft.mType == aRight.mType, "Incompatible SMIL types");
--- a/content/smil/nsSMILNullType.h
+++ b/content/smil/nsSMILNullType.h
@@ -8,17 +8,22 @@
 
 #include "mozilla/Attributes.h"
 #include "nsISMILType.h"
 
 class nsSMILNullType : public nsISMILType
 {
 public:
   // Singleton for nsSMILValue objects to hold onto.
-  static nsSMILNullType sSingleton;
+  static nsSMILNullType*
+  Singleton()
+  {
+    static nsSMILNullType sSingleton;
+    return &sSingleton;
+  }
 
 protected:
   // nsISMILType Methods
   // -------------------
   virtual void Init(nsSMILValue& aValue) const MOZ_OVERRIDE {}
   virtual void Destroy(nsSMILValue& aValue) const MOZ_OVERRIDE {}
   virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const MOZ_OVERRIDE;
 
--- a/content/smil/nsSMILValue.cpp
+++ b/content/smil/nsSMILValue.cpp
@@ -6,28 +6,28 @@
 #include "nsSMILValue.h"
 #include "nsDebug.h"
 #include <string.h>
 
 //----------------------------------------------------------------------
 // Public methods
 
 nsSMILValue::nsSMILValue(const nsISMILType* aType)
-  : mType(&nsSMILNullType::sSingleton)
+  : mType(nsSMILNullType::Singleton())
 {
   if (!aType) {
     NS_ERROR("Trying to construct nsSMILValue with null mType pointer");
     return;
   }
 
   InitAndCheckPostcondition(aType);
 }
 
 nsSMILValue::nsSMILValue(const nsSMILValue& aVal)
-  : mType(&nsSMILNullType::sSingleton)
+  : mType(nsSMILNullType::Singleton())
 {
   InitAndCheckPostcondition(aVal.mType);
   mType->Assign(*this, aVal);
 }
 
 const nsSMILValue&
 nsSMILValue::operator=(const nsSMILValue& aVal)
 {
@@ -57,17 +57,17 @@ nsSMILValue::Swap(nsSMILValue& aOther)
 {
   nsSMILValue tmp;
   memcpy(&tmp,    &aOther, sizeof(nsSMILValue));  // tmp    = aOther
   memcpy(&aOther, this,    sizeof(nsSMILValue));  // aOther = this
   memcpy(this,    &tmp,    sizeof(nsSMILValue));  // this   = tmp
 
   // |tmp| is about to die -- we need to clear its mType, so that its
   // destructor doesn't muck with the data we just transferred out of it.
-  tmp.mType = &nsSMILNullType::sSingleton;
+  tmp.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 nsSMILValue::Add(const nsSMILValue& aValueToAdd, uint32_t aCount)
 {
   if (aValueToAdd.mType != mType) {
     NS_ERROR("Trying to add incompatible types");
     return NS_ERROR_FAILURE;
--- a/content/smil/nsSMILValue.h
+++ b/content/smil/nsSMILValue.h
@@ -16,17 +16,17 @@
  * cached so that the SMIL engine can make certain optimizations during a
  * sample if the base value has not changed since the last sample (potentially
  * avoiding recomposing). These nsSMILValue objects typically live much longer
  * than a single sample.
  */
 class nsSMILValue
 {
 public:
-  nsSMILValue() : mU(), mType(&nsSMILNullType::sSingleton) { }
+  nsSMILValue() : mU(), mType(nsSMILNullType::Singleton()) { }
   explicit nsSMILValue(const nsISMILType* aType);
   nsSMILValue(const nsSMILValue& aVal);
 
   ~nsSMILValue()
   {
     mType->Destroy(*this);
   }
 
@@ -36,17 +36,17 @@ public:
   // more than you'd expect) - see comment above nsISMILType::IsEqual.
   bool operator==(const nsSMILValue& aVal) const;
   bool operator!=(const nsSMILValue& aVal) const {
     return !(*this == aVal);
   }
 
   bool IsNull() const
   {
-    return (mType == &nsSMILNullType::sSingleton);
+    return (mType == nsSMILNullType::Singleton());
   }
 
   // Swaps the member data (mU & mPtr) of |this| with |aOther|
   void     Swap(nsSMILValue& aOther);
 
   nsresult Add(const nsSMILValue& aValueToAdd, uint32_t aCount = 1);
   nsresult SandwichAdd(const nsSMILValue& aValueToAdd);
   nsresult ComputeDistance(const nsSMILValue& aTo, double& aDistance) const;
--- a/content/svg/content/src/DOMSVGAnimatedLengthList.cpp
+++ b/content/svg/content/src/DOMSVGAnimatedLengthList.cpp
@@ -11,18 +11,24 @@
 #include "nsSVGAttrTearoffTable.h"
 #include "mozilla/dom/SVGAnimatedLengthListBinding.h"
 #include "nsContentUtils.h"
 
 // See the architecture comment in this file's header.
 
 namespace mozilla {
 
-static nsSVGAttrTearoffTable<SVGAnimatedLengthList, DOMSVGAnimatedLengthList>
-  sSVGAnimatedLengthListTearoffTable;
+static inline
+nsSVGAttrTearoffTable<SVGAnimatedLengthList, DOMSVGAnimatedLengthList>&
+SVGAnimatedLengthListTearoffTable()
+{
+  static nsSVGAttrTearoffTable<SVGAnimatedLengthList, DOMSVGAnimatedLengthList>
+    sSVGAnimatedLengthListTearoffTable;
+  return sSVGAnimatedLengthListTearoffTable;
+}
 
 NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(DOMSVGAnimatedLengthList, mElement)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGAnimatedLengthList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGAnimatedLengthList)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGAnimatedLengthList)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
@@ -57,35 +63,35 @@ DOMSVGAnimatedLengthList::AnimVal()
 
 /* static */ already_AddRefed<DOMSVGAnimatedLengthList>
 DOMSVGAnimatedLengthList::GetDOMWrapper(SVGAnimatedLengthList *aList,
                                         nsSVGElement *aElement,
                                         uint8_t aAttrEnum,
                                         uint8_t aAxis)
 {
   nsRefPtr<DOMSVGAnimatedLengthList> wrapper =
-    sSVGAnimatedLengthListTearoffTable.GetTearoff(aList);
+    SVGAnimatedLengthListTearoffTable().GetTearoff(aList);
   if (!wrapper) {
     wrapper = new DOMSVGAnimatedLengthList(aElement, aAttrEnum, aAxis);
-    sSVGAnimatedLengthListTearoffTable.AddTearoff(aList, wrapper);
+    SVGAnimatedLengthListTearoffTable().AddTearoff(aList, wrapper);
   }
   return wrapper.forget();
 }
 
 /* static */ DOMSVGAnimatedLengthList*
 DOMSVGAnimatedLengthList::GetDOMWrapperIfExists(SVGAnimatedLengthList *aList)
 {
-  return sSVGAnimatedLengthListTearoffTable.GetTearoff(aList);
+  return SVGAnimatedLengthListTearoffTable().GetTearoff(aList);
 }
 
 DOMSVGAnimatedLengthList::~DOMSVGAnimatedLengthList()
 {
   // Script no longer has any references to us, to our base/animVal objects, or
   // to any of their list items.
-  sSVGAnimatedLengthListTearoffTable.RemoveTearoff(&InternalAList());
+  SVGAnimatedLengthListTearoffTable().RemoveTearoff(&InternalAList());
 }
 
 void
 DOMSVGAnimatedLengthList::InternalBaseValListWillChangeTo(const SVGLengthList& aNewValue)
 {
   // When the number of items in our internal counterpart's baseVal changes,
   // we MUST keep our baseVal in sync. If we don't, script will either see a
   // list that is too short and be unable to access indexes that should be
--- a/content/svg/content/src/DOMSVGAnimatedNumberList.cpp
+++ b/content/svg/content/src/DOMSVGAnimatedNumberList.cpp
@@ -11,18 +11,24 @@
 #include "nsSVGAttrTearoffTable.h"
 #include "mozilla/dom/SVGAnimatedNumberListBinding.h"
 #include "nsContentUtils.h"
 
 // See the architecture comment in this file's header.
 
 namespace mozilla {
 
-static nsSVGAttrTearoffTable<SVGAnimatedNumberList, DOMSVGAnimatedNumberList>
-  sSVGAnimatedNumberListTearoffTable;
+  static inline
+nsSVGAttrTearoffTable<SVGAnimatedNumberList, DOMSVGAnimatedNumberList>&
+SVGAnimatedNumberListTearoffTable()
+{
+  static nsSVGAttrTearoffTable<SVGAnimatedNumberList, DOMSVGAnimatedNumberList>
+    sSVGAnimatedNumberListTearoffTable;
+  return sSVGAnimatedNumberListTearoffTable;
+}
 
 NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(DOMSVGAnimatedNumberList, mElement)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGAnimatedNumberList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGAnimatedNumberList)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGAnimatedNumberList)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
@@ -56,35 +62,35 @@ DOMSVGAnimatedNumberList::AnimVal()
 }
 
 /* static */ already_AddRefed<DOMSVGAnimatedNumberList>
 DOMSVGAnimatedNumberList::GetDOMWrapper(SVGAnimatedNumberList *aList,
                                         nsSVGElement *aElement,
                                         uint8_t aAttrEnum)
 {
   nsRefPtr<DOMSVGAnimatedNumberList> wrapper =
-    sSVGAnimatedNumberListTearoffTable.GetTearoff(aList);
+    SVGAnimatedNumberListTearoffTable().GetTearoff(aList);
   if (!wrapper) {
     wrapper = new DOMSVGAnimatedNumberList(aElement, aAttrEnum);
-    sSVGAnimatedNumberListTearoffTable.AddTearoff(aList, wrapper);
+    SVGAnimatedNumberListTearoffTable().AddTearoff(aList, wrapper);
   }
   return wrapper.forget();
 }
 
 /* static */ DOMSVGAnimatedNumberList*
 DOMSVGAnimatedNumberList::GetDOMWrapperIfExists(SVGAnimatedNumberList *aList)
 {
-  return sSVGAnimatedNumberListTearoffTable.GetTearoff(aList);
+  return SVGAnimatedNumberListTearoffTable().GetTearoff(aList);
 }
 
 DOMSVGAnimatedNumberList::~DOMSVGAnimatedNumberList()
 {
   // Script no longer has any references to us, to our base/animVal objects, or
   // to any of their list items.
-  sSVGAnimatedNumberListTearoffTable.RemoveTearoff(&InternalAList());
+  SVGAnimatedNumberListTearoffTable().RemoveTearoff(&InternalAList());
 }
 
 void
 DOMSVGAnimatedNumberList::InternalBaseValListWillChangeTo(const SVGNumberList& aNewValue)
 {
   // When the number of items in our internal counterpart's baseVal changes,
   // we MUST keep our baseVal in sync. If we don't, script will either see a
   // list that is too short and be unable to access indexes that should be
--- a/content/svg/content/src/DOMSVGPathSegList.cpp
+++ b/content/svg/content/src/DOMSVGPathSegList.cpp
@@ -13,18 +13,24 @@
 #include "SVGPathSegUtils.h"
 #include "mozilla/dom/SVGPathSegListBinding.h"
 #include "nsContentUtils.h"
 
 // See the comment in this file's header.
 
 namespace mozilla {
 
-static nsSVGAttrTearoffTable<void, DOMSVGPathSegList>
-  sSVGPathSegListTearoffTable;
+  static inline
+nsSVGAttrTearoffTable<void, DOMSVGPathSegList>&
+SVGPathSegListTearoffTable()
+{
+  static nsSVGAttrTearoffTable<void, DOMSVGPathSegList>
+    sSVGPathSegListTearoffTable;
+  return sSVGPathSegListTearoffTable;
+}
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPathSegList)
   // No unlinking of mElement, we'd need to null out the value pointer (the
   // object it points to is held by the element) and null-check it everywhere.
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPathSegList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement)
@@ -44,38 +50,38 @@ NS_INTERFACE_MAP_END
 
 
 /* static */ already_AddRefed<DOMSVGPathSegList>
 DOMSVGPathSegList::GetDOMWrapper(void *aList,
                                  nsSVGElement *aElement,
                                  bool aIsAnimValList)
 {
   nsRefPtr<DOMSVGPathSegList> wrapper =
-    sSVGPathSegListTearoffTable.GetTearoff(aList);
+    SVGPathSegListTearoffTable().GetTearoff(aList);
   if (!wrapper) {
     wrapper = new DOMSVGPathSegList(aElement, aIsAnimValList);
-    sSVGPathSegListTearoffTable.AddTearoff(aList, wrapper);
+    SVGPathSegListTearoffTable().AddTearoff(aList, wrapper);
   }
   return wrapper.forget();
 }
 
 /* static */ DOMSVGPathSegList*
 DOMSVGPathSegList::GetDOMWrapperIfExists(void *aList)
 {
-  return sSVGPathSegListTearoffTable.GetTearoff(aList);
+  return SVGPathSegListTearoffTable().GetTearoff(aList);
 }
 
 DOMSVGPathSegList::~DOMSVGPathSegList()
 {
   // There are now no longer any references to us held by script or list items.
   // Note we must use GetAnimValKey/GetBaseValKey here, NOT InternalList()!
   void *key = mIsAnimValList ?
     InternalAList().GetAnimValKey() :
     InternalAList().GetBaseValKey();
-  sSVGPathSegListTearoffTable.RemoveTearoff(key);
+  SVGPathSegListTearoffTable().RemoveTearoff(key);
 }
 
 JSObject*
 DOMSVGPathSegList::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope)
 {
   return mozilla::dom::SVGPathSegListBinding::Wrap(cx, scope, this);
 }
 
--- a/content/svg/content/src/DOMSVGPointList.cpp
+++ b/content/svg/content/src/DOMSVGPointList.cpp
@@ -31,18 +31,24 @@ UpdateListIndicesFromIndex(FallibleTArra
     }
   }
 }
 
 } // namespace
 
 namespace mozilla {
 
-static nsSVGAttrTearoffTable<void, DOMSVGPointList>
-  sSVGPointListTearoffTable;
+  static inline
+nsSVGAttrTearoffTable<void, DOMSVGPointList>&
+SVGPointListTearoffTable()
+{
+  static nsSVGAttrTearoffTable<void, DOMSVGPointList>
+    sSVGPointListTearoffTable;
+  return sSVGPointListTearoffTable;
+}
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPointList)
   // No unlinking of mElement, we'd need to null out the value pointer (the
   // object it points to is held by the element) and null-check it everywhere.
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPointList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement)
@@ -62,38 +68,38 @@ NS_INTERFACE_MAP_END
 
 
 /* static */ already_AddRefed<DOMSVGPointList>
 DOMSVGPointList::GetDOMWrapper(void *aList,
                                nsSVGElement *aElement,
                                bool aIsAnimValList)
 {
   nsRefPtr<DOMSVGPointList> wrapper =
-    sSVGPointListTearoffTable.GetTearoff(aList);
+    SVGPointListTearoffTable().GetTearoff(aList);
   if (!wrapper) {
     wrapper = new DOMSVGPointList(aElement, aIsAnimValList);
-    sSVGPointListTearoffTable.AddTearoff(aList, wrapper);
+    SVGPointListTearoffTable().AddTearoff(aList, wrapper);
   }
   return wrapper.forget();
 }
 
 /* static */ DOMSVGPointList*
 DOMSVGPointList::GetDOMWrapperIfExists(void *aList)
 {
-  return sSVGPointListTearoffTable.GetTearoff(aList);
+  return SVGPointListTearoffTable().GetTearoff(aList);
 }
 
 DOMSVGPointList::~DOMSVGPointList()
 {
   // There are now no longer any references to us held by script or list items.
   // Note we must use GetAnimValKey/GetBaseValKey here, NOT InternalList()!
   void *key = mIsAnimValList ?
     InternalAList().GetAnimValKey() :
     InternalAList().GetBaseValKey();
-  sSVGPointListTearoffTable.RemoveTearoff(key);
+  SVGPointListTearoffTable().RemoveTearoff(key);
 }
 
 JSObject*
 DOMSVGPointList::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope)
 {
   return mozilla::dom::SVGPointListBinding::Wrap(cx, scope, this);
 }
 
--- a/content/svg/content/src/DOMSVGStringList.cpp
+++ b/content/svg/content/src/DOMSVGStringList.cpp
@@ -13,18 +13,24 @@
 #include <algorithm>
 
 // See the architecture comment in this file's header.
 
 namespace mozilla {
 
 using namespace dom;
 
-static nsSVGAttrTearoffTable<SVGStringList, DOMSVGStringList>
-  sSVGStringListTearoffTable;
+static inline
+nsSVGAttrTearoffTable<SVGStringList, DOMSVGStringList>&
+SVGStringListTearoffTable()
+{
+  static nsSVGAttrTearoffTable<SVGStringList, DOMSVGStringList>
+    sSVGStringListTearoffTable;
+  return sSVGStringListTearoffTable;
+}
 
 NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(DOMSVGStringList, mElement)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGStringList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGStringList)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGStringList)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
@@ -33,30 +39,30 @@ NS_INTERFACE_MAP_END
 
 /* static */ already_AddRefed<DOMSVGStringList>
 DOMSVGStringList::GetDOMWrapper(SVGStringList *aList,
                                 nsSVGElement *aElement,
                                 bool aIsConditionalProcessingAttribute,
                                 uint8_t aAttrEnum)
 {
   nsRefPtr<DOMSVGStringList> wrapper =
-    sSVGStringListTearoffTable.GetTearoff(aList);
+    SVGStringListTearoffTable().GetTearoff(aList);
   if (!wrapper) {
     wrapper = new DOMSVGStringList(aElement, 
                                    aIsConditionalProcessingAttribute,
                                    aAttrEnum);
-    sSVGStringListTearoffTable.AddTearoff(aList, wrapper);
+    SVGStringListTearoffTable().AddTearoff(aList, wrapper);
   }
   return wrapper.forget();
 }
 
 DOMSVGStringList::~DOMSVGStringList()
 {
   // Script no longer has any references to us.
-  sSVGStringListTearoffTable.RemoveTearoff(&InternalList());
+  SVGStringListTearoffTable().RemoveTearoff(&InternalList());
 }
 
 /* virtual */ JSObject*
 DOMSVGStringList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return SVGStringListBinding::Wrap(aCx, aScope, this);
 }
 
--- a/content/svg/content/src/SVGAElement.cpp
+++ b/content/svg/content/src/SVGAElement.cpp
@@ -129,22 +129,16 @@ SVGAElement::UnbindFromTree(bool aDeep, 
   nsIDocument* doc = GetCurrentDoc();
   if (doc) {
     doc->UnregisterPendingLinkUpdate(this);
   }
 
   SVGAElementBase::UnbindFromTree(aDeep, aNullParent);
 }
 
-nsLinkState
-SVGAElement::GetLinkState() const
-{
-  return Link::GetLinkState();
-}
-
 already_AddRefed<nsIURI>
 SVGAElement::GetHrefURI() const
 {
   nsCOMPtr<nsIURI> hrefURI;
   return IsLink(getter_AddRefs(hrefURI)) ? hrefURI.forget() : nullptr;
 }
 
 
--- a/content/svg/content/src/SVGAElement.h
+++ b/content/svg/content/src/SVGAElement.h
@@ -47,17 +47,16 @@ public:
                               nsIContent *aBindingParent,
                               bool aCompileEventHandlers) MOZ_OVERRIDE;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
   virtual bool IsFocusable(int32_t *aTabIndex = nullptr, bool aWithMouse = false) MOZ_OVERRIDE;
   virtual bool IsLink(nsIURI** aURI) const MOZ_OVERRIDE;
   virtual void GetLinkTarget(nsAString& aTarget) MOZ_OVERRIDE;
-  virtual nsLinkState GetLinkState() const MOZ_OVERRIDE;
   virtual already_AddRefed<nsIURI> GetHrefURI() const MOZ_OVERRIDE;
   virtual nsEventStates IntrinsicState() const MOZ_OVERRIDE;
   nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                    const nsAString& aValue, bool aNotify)
   {
     return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
   }
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
--- a/content/svg/content/src/SVGAnimatedPathSegList.cpp
+++ b/content/svg/content/src/SVGAnimatedPathSegList.cpp
@@ -149,17 +149,17 @@ SVGAnimatedPathSegList::ToSMILAttr(nsSVG
 
 nsresult
 SVGAnimatedPathSegList::
   SMILAnimatedPathSegList::ValueFromString(const nsAString& aStr,
                                const dom::SVGAnimationElement* /*aSrcElement*/,
                                nsSMILValue& aValue,
                                bool& aPreventCachingOfSandwich) const
 {
-  nsSMILValue val(&SVGPathSegListSMILType::sSingleton);
+  nsSMILValue val(SVGPathSegListSMILType::Singleton());
   SVGPathDataAndOwner *list = static_cast<SVGPathDataAndOwner*>(val.mU.mPtr);
   nsresult rv = list->SetValueFromString(aStr);
   if (NS_SUCCEEDED(rv)) {
     list->SetElement(mElement);
     aValue.Swap(val);
   }
   aPreventCachingOfSandwich = false;
   return rv;
@@ -168,32 +168,32 @@ SVGAnimatedPathSegList::
 nsSMILValue
 SVGAnimatedPathSegList::SMILAnimatedPathSegList::GetBaseValue() const
 {
   // To benefit from Return Value Optimization and avoid copy constructor calls
   // due to our use of return-by-value, we must return the exact same object
   // from ALL return points. This function must only return THIS variable:
   nsSMILValue val;
 
-  nsSMILValue tmp(&SVGPathSegListSMILType::sSingleton);
+  nsSMILValue tmp(SVGPathSegListSMILType::Singleton());
   SVGPathDataAndOwner *list = static_cast<SVGPathDataAndOwner*>(tmp.mU.mPtr);
   nsresult rv = list->CopyFrom(mVal->mBaseVal);
   if (NS_SUCCEEDED(rv)) {
     list->SetElement(mElement);
     val.Swap(tmp);
   }
   return val;
 }
 
 nsresult
 SVGAnimatedPathSegList::SMILAnimatedPathSegList::SetAnimValue(const nsSMILValue& aValue)
 {
-  NS_ASSERTION(aValue.mType == &SVGPathSegListSMILType::sSingleton,
+  NS_ASSERTION(aValue.mType == SVGPathSegListSMILType::Singleton(),
                "Unexpected type to assign animated value");
-  if (aValue.mType == &SVGPathSegListSMILType::sSingleton) {
+  if (aValue.mType == SVGPathSegListSMILType::Singleton()) {
     mVal->SetAnimValue(*static_cast<SVGPathDataAndOwner*>(aValue.mU.mPtr),
                        mElement);
   }
   return NS_OK;
 }
 
 void
 SVGAnimatedPathSegList::SMILAnimatedPathSegList::ClearAnimValue()
--- a/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp
+++ b/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp
@@ -316,27 +316,27 @@ SMILPreserveAspectRatio::ValueFromString
                                          const SVGAnimationElement* /*aSrcElement*/,
                                          nsSMILValue& aValue,
                                          bool& aPreventCachingOfSandwich) const
 {
   SVGPreserveAspectRatio par;
   nsresult res = ToPreserveAspectRatio(aStr, &par);
   NS_ENSURE_SUCCESS(res, res);
 
-  nsSMILValue val(&SMILEnumType::sSingleton);
+  nsSMILValue val(SMILEnumType::Singleton());
   val.mU.mUint = PackPreserveAspectRatio(par);
   aValue = val;
   aPreventCachingOfSandwich = false;
   return NS_OK;
 }
 
 nsSMILValue
 SMILPreserveAspectRatio::GetBaseValue() const
 {
-  nsSMILValue val(&SMILEnumType::sSingleton);
+  nsSMILValue val(SMILEnumType::Singleton());
   val.mU.mUint = PackPreserveAspectRatio(mVal->GetBaseValue());
   return val;
 }
 
 void
 SMILPreserveAspectRatio::ClearAnimValue()
 {
   if (mVal->mIsAnimated) {
@@ -344,15 +344,15 @@ SMILPreserveAspectRatio::ClearAnimValue(
     mVal->mAnimVal = mVal->mBaseVal;
     mSVGElement->DidAnimatePreserveAspectRatio();
   }
 }
 
 nsresult
 SMILPreserveAspectRatio::SetAnimValue(const nsSMILValue& aValue)
 {
-  NS_ASSERTION(aValue.mType == &SMILEnumType::sSingleton,
+  NS_ASSERTION(aValue.mType == SMILEnumType::Singleton(),
                "Unexpected type to assign animated value");
-  if (aValue.mType == &SMILEnumType::sSingleton) {
+  if (aValue.mType == SMILEnumType::Singleton()) {
     mVal->SetAnimValue(aValue.mU.mUint, mSVGElement);
   }
   return NS_OK;
 }
--- a/content/svg/content/src/SVGIntegerPairSMILType.cpp
+++ b/content/svg/content/src/SVGIntegerPairSMILType.cpp
@@ -5,35 +5,33 @@
 
 #include "SVGIntegerPairSMILType.h"
 #include "nsSMILValue.h"
 #include "nsMathUtils.h"
 #include "nsDebug.h"
 
 namespace mozilla {
 
-/*static*/ SVGIntegerPairSMILType SVGIntegerPairSMILType::sSingleton;
-
 void
 SVGIntegerPairSMILType::Init(nsSMILValue& aValue) const
 {
   NS_ABORT_IF_FALSE(aValue.IsNull(), "Unexpected value type");
 
   aValue.mU.mIntPair[0] = 0;
   aValue.mU.mIntPair[1] = 0;
   aValue.mType = this;
 }
 
 void
 SVGIntegerPairSMILType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value");
   aValue.mU.mIntPair[0] = 0;
   aValue.mU.mIntPair[1] = 0;
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 SVGIntegerPairSMILType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
 
--- a/content/svg/content/src/SVGIntegerPairSMILType.h
+++ b/content/svg/content/src/SVGIntegerPairSMILType.h
@@ -12,17 +12,22 @@
 class nsSMILValue;
 
 namespace mozilla {
 
 class SVGIntegerPairSMILType : public nsISMILType
 {
 public:
   // Singleton for nsSMILValue objects to hold onto.
-  static SVGIntegerPairSMILType sSingleton;
+  static SVGIntegerPairSMILType*
+  Singleton()
+  {
+    static SVGIntegerPairSMILType sSingleton;
+    return &sSingleton;
+  }
 
 protected:
   // nsISMILType Methods
   // -------------------
   virtual void     Init(nsSMILValue& aValue) const MOZ_OVERRIDE;
   virtual void     Destroy(nsSMILValue&) const;
   virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const MOZ_OVERRIDE;
   virtual bool     IsEqual(const nsSMILValue& aLeft,
--- a/content/svg/content/src/SVGLengthListSMILType.cpp
+++ b/content/svg/content/src/SVGLengthListSMILType.cpp
@@ -32,17 +32,17 @@ SVGLengthListSMILType::Init(nsSMILValue 
 }
 
 void
 SVGLengthListSMILType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value type");
   delete static_cast<SVGLengthListAndInfo*>(aValue.mU.mPtr);
   aValue.mU.mPtr = nullptr;
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 SVGLengthListSMILType::Assign(nsSMILValue& aDest,
                               const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
--- a/content/svg/content/src/SVGMotionSMILType.cpp
+++ b/content/svg/content/src/SVGMotionSMILType.cpp
@@ -174,17 +174,17 @@ void
 SVGMotionSMILType::Destroy(nsSMILValue& aValue) const
 {
   NS_ABORT_IF_FALSE(aValue.mType == this, "Unexpected SMIL type");
 
   MotionSegmentArray* arr = static_cast<MotionSegmentArray*>(aValue.mU.mPtr);
   delete arr;
 
   aValue.mU.mPtr = nullptr;
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 SVGMotionSMILType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
 {
   NS_ABORT_IF_FALSE(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_ABORT_IF_FALSE(aDest.mType == this, "Unexpected SMIL type");
 
--- a/content/svg/content/src/SVGNumberListSMILType.cpp
+++ b/content/svg/content/src/SVGNumberListSMILType.cpp
@@ -45,17 +45,17 @@ SVGNumberListSMILType::Init(nsSMILValue 
 }
 
 void
 SVGNumberListSMILType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value type");
   delete static_cast<SVGNumberListAndInfo*>(aValue.mU.mPtr);
   aValue.mU.mPtr = nullptr;
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 SVGNumberListSMILType::Assign(nsSMILValue& aDest,
                               const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
--- a/content/svg/content/src/SVGNumberPairSMILType.cpp
+++ b/content/svg/content/src/SVGNumberPairSMILType.cpp
@@ -23,17 +23,17 @@ SVGNumberPairSMILType::Init(nsSMILValue&
 }
 
 void
 SVGNumberPairSMILType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value");
   aValue.mU.mNumberPair[0] = 0;
   aValue.mU.mNumberPair[1] = 0;
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 SVGNumberPairSMILType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
 
--- a/content/svg/content/src/SVGOrientSMILType.cpp
+++ b/content/svg/content/src/SVGOrientSMILType.cpp
@@ -25,17 +25,17 @@ SVGOrientSMILType::Init(nsSMILValue& aVa
   aValue.mType = this;
 }
 
 void
 SVGOrientSMILType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value.");
   aValue.mU.mPtr = nullptr;
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 SVGOrientSMILType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types.");
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value.");
 
--- a/content/svg/content/src/SVGPathSegListSMILType.cpp
+++ b/content/svg/content/src/SVGPathSegListSMILType.cpp
@@ -12,18 +12,16 @@
 
 // Indices of boolean flags within 'arc' segment chunks in path-data arrays
 // (where '0' would correspond to the index of the encoded segment type):
 #define LARGE_ARC_FLAG_IDX 4
 #define SWEEP_FLAG_IDX     5
 
 namespace mozilla {
 
-/*static*/ SVGPathSegListSMILType SVGPathSegListSMILType::sSingleton;
-
 //----------------------------------------------------------------------
 // nsISMILType implementation
 
 void
 SVGPathSegListSMILType::Init(nsSMILValue &aValue) const
 {
   NS_ABORT_IF_FALSE(aValue.IsNull(), "Unexpected value type");
   aValue.mU.mPtr = new SVGPathDataAndOwner();
@@ -31,17 +29,17 @@ SVGPathSegListSMILType::Init(nsSMILValue
 }
 
 void
 SVGPathSegListSMILType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value type");
   delete static_cast<SVGPathDataAndOwner*>(aValue.mU.mPtr);
   aValue.mU.mPtr = nullptr;
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 SVGPathSegListSMILType::Assign(nsSMILValue& aDest,
                                const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
--- a/content/svg/content/src/SVGPathSegListSMILType.h
+++ b/content/svg/content/src/SVGPathSegListSMILType.h
@@ -17,17 +17,21 @@ namespace mozilla {
 // SVGPathSegListSMILType
 //
 // Operations for animating an SVGPathData.
 //
 class SVGPathSegListSMILType : public nsISMILType
 {
 public:
   // Singleton for nsSMILValue objects to hold onto.
-  static SVGPathSegListSMILType sSingleton;
+  static SVGPathSegListSMILType* Singleton()
+  {
+    static SVGPathSegListSMILType sSingleton;
+    return &sSingleton;
+  }
 
 protected:
   // nsISMILType Methods
   // -------------------
 
   virtual void     Init(nsSMILValue& aValue) const MOZ_OVERRIDE;
 
   virtual void     Destroy(nsSMILValue& aValue) const MOZ_OVERRIDE;
--- a/content/svg/content/src/SVGPointListSMILType.cpp
+++ b/content/svg/content/src/SVGPointListSMILType.cpp
@@ -28,17 +28,17 @@ SVGPointListSMILType::Init(nsSMILValue &
 }
 
 void
 SVGPointListSMILType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value type");
   delete static_cast<SVGPointListAndInfo*>(aValue.mU.mPtr);
   aValue.mU.mPtr = nullptr;
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 SVGPointListSMILType::Assign(nsSMILValue& aDest,
                               const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
--- a/content/svg/content/src/SVGTransform.cpp
+++ b/content/svg/content/src/SVGTransform.cpp
@@ -11,17 +11,22 @@
 #include "nsAttrValueInlines.h"
 #include "nsSVGAnimatedTransformList.h"
 #include "nsSVGAttrTearoffTable.h"
 #include "mozilla/dom/SVGTransformBinding.h"
 
 namespace mozilla {
 namespace dom {
 
-static nsSVGAttrTearoffTable<SVGTransform, SVGMatrix> sSVGMatrixTearoffTable;
+static nsSVGAttrTearoffTable<SVGTransform, SVGMatrix>&
+SVGMatrixTearoffTable()
+{
+  static nsSVGAttrTearoffTable<SVGTransform, SVGMatrix> sSVGMatrixTearoffTable;
+  return sSVGMatrixTearoffTable;
+}
 
 //----------------------------------------------------------------------
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our list's weak ref to us to be safe. (The other option would be to
 // not unlink and rely on the breaking of the other edges in the cycle, as
 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SVGTransform)
@@ -31,17 +36,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SV
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(SVGTransform)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList)
   SVGMatrix* matrix =
-    sSVGMatrixTearoffTable.GetTearoff(tmp);
+    SVGMatrixTearoffTable().GetTearoff(tmp);
   CycleCollectionNoteChild(cb, matrix, "matrix");
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(SVGTransform)
 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
@@ -99,19 +104,19 @@ SVGTransform::SVGTransform(const nsSVGTr
   , mIsAnimValItem(false)
   , mTransform(new nsSVGTransform(aTransform))
 {
   SetIsDOMBinding();
 }
 
 SVGTransform::~SVGTransform()
 {
-  SVGMatrix* matrix = sSVGMatrixTearoffTable.GetTearoff(this);
+  SVGMatrix* matrix = SVGMatrixTearoffTable().GetTearoff(this);
   if (matrix) {
-    sSVGMatrixTearoffTable.RemoveTearoff(this);
+    SVGMatrixTearoffTable().RemoveTearoff(this);
     NS_RELEASE(matrix);
   }
   // Our mList's weak ref to us must be nulled out when we die. If GC has
   // unlinked us using the cycle collector code, then that has already
   // happened, and mList is null.
   if (mList) {
     mList->mItems[mListIndex] = nullptr;
   }
@@ -122,20 +127,20 @@ SVGTransform::Type() const
 {
   return Transform().Type();
 }
 
 SVGMatrix*
 SVGTransform::Matrix()
 {
   SVGMatrix* wrapper =
-    sSVGMatrixTearoffTable.GetTearoff(this);
+    SVGMatrixTearoffTable().GetTearoff(this);
   if (!wrapper) {
     NS_ADDREF(wrapper = new SVGMatrix(*this));
-    sSVGMatrixTearoffTable.AddTearoff(this, wrapper);
+    SVGMatrixTearoffTable().AddTearoff(this, wrapper);
   }
   return wrapper;
 }
 
 float
 SVGTransform::Angle() const
 {
   return Transform().Angle();
--- a/content/svg/content/src/SVGTransformListSMILType.cpp
+++ b/content/svg/content/src/SVGTransformListSMILType.cpp
@@ -7,18 +7,16 @@
 #include "SVGTransformList.h"
 #include "nsSVGTransform.h"
 #include "nsSMILValue.h"
 #include "nsCRT.h"
 #include <math.h>
 
 using namespace mozilla;
 
-/*static*/ SVGTransformListSMILType SVGTransformListSMILType::sSingleton;
-
 typedef FallibleTArray<SVGTransformSMILData> TransformArray;
 
 //----------------------------------------------------------------------
 // nsISMILType implementation
 
 void
 SVGTransformListSMILType::Init(nsSMILValue &aValue) const
 {
@@ -31,17 +29,17 @@ SVGTransformListSMILType::Init(nsSMILVal
 
 void
 SVGTransformListSMILType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value type");
   TransformArray* params = static_cast<TransformArray*>(aValue.mU.mPtr);
   delete params;
   aValue.mU.mPtr = nullptr;
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 SVGTransformListSMILType::Assign(nsSMILValue& aDest,
                                const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
@@ -316,29 +314,29 @@ SVGTransformListSMILType::Interpolate(co
 // Transform array accessors
 
 // static
 nsresult
 SVGTransformListSMILType::AppendTransform(
   const SVGTransformSMILData& aTransform,
   nsSMILValue& aValue)
 {
-  NS_PRECONDITION(aValue.mType == &sSingleton, "Unexpected SMIL value type");
+  NS_PRECONDITION(aValue.mType == Singleton(), "Unexpected SMIL value type");
 
   TransformArray& transforms = *static_cast<TransformArray*>(aValue.mU.mPtr);
   return transforms.AppendElement(aTransform) ?
     NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
 // static
 bool
 SVGTransformListSMILType::AppendTransforms(const SVGTransformList& aList,
                                            nsSMILValue& aValue)
 {
-  NS_PRECONDITION(aValue.mType == &sSingleton, "Unexpected SMIL value type");
+  NS_PRECONDITION(aValue.mType == Singleton(), "Unexpected SMIL value type");
 
   TransformArray& transforms = *static_cast<TransformArray*>(aValue.mU.mPtr);
 
   if (!transforms.SetCapacity(transforms.Length() + aList.Length()))
     return false;
 
   for (uint32_t i = 0; i < aList.Length(); ++i) {
     // No need to check the return value below since we have already allocated
@@ -348,17 +346,17 @@ SVGTransformListSMILType::AppendTransfor
   return true;
 }
 
 // static
 bool
 SVGTransformListSMILType::GetTransforms(const nsSMILValue& aValue,
                                         FallibleTArray<nsSVGTransform>& aTransforms)
 {
-  NS_PRECONDITION(aValue.mType == &sSingleton, "Unexpected SMIL value type");
+  NS_PRECONDITION(aValue.mType == Singleton(), "Unexpected SMIL value type");
 
   const TransformArray& smilTransforms =
     *static_cast<const TransformArray*>(aValue.mU.mPtr);
 
   aTransforms.Clear();
   if (!aTransforms.SetCapacity(smilTransforms.Length()))
       return false;
 
--- a/content/svg/content/src/SVGTransformListSMILType.h
+++ b/content/svg/content/src/SVGTransformListSMILType.h
@@ -76,17 +76,22 @@ class SVGTransformSMILData;
 // may have use a start-value the base value of the target attribute (which as
 // we have seen above can contain 0..n elements) whilst the end-value comes from
 // the <animateTransform> and so can only hold 1 transform.
 //
 class SVGTransformListSMILType : public nsISMILType
 {
 public:
   // Singleton for nsSMILValue objects to hold onto.
-  static SVGTransformListSMILType sSingleton;
+  static SVGTransformListSMILType*
+  Singleton()
+  {
+    static SVGTransformListSMILType sSingleton;
+    return &sSingleton;
+  }
 
 protected:
   // nsISMILType Methods
   // -------------------
   virtual void     Init(nsSMILValue& aValue) const MOZ_OVERRIDE;
   virtual void     Destroy(nsSMILValue& aValue) const MOZ_OVERRIDE;
   virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const MOZ_OVERRIDE;
   virtual bool     IsEqual(const nsSMILValue& aLeft,
--- a/content/svg/content/src/SVGViewBoxSMILType.cpp
+++ b/content/svg/content/src/SVGViewBoxSMILType.cpp
@@ -23,17 +23,17 @@ SVGViewBoxSMILType::Init(nsSMILValue& aV
 }
 
 void
 SVGViewBoxSMILType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value");
   delete static_cast<nsSVGViewBoxRect*>(aValue.mU.mPtr);
   aValue.mU.mPtr = nullptr;
-  aValue.mType = &nsSMILNullType::sSingleton;
+  aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 SVGViewBoxSMILType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
 
--- a/content/svg/content/src/nsSVGAnimatedTransformList.cpp
+++ b/content/svg/content/src/nsSVGAnimatedTransformList.cpp
@@ -220,17 +220,17 @@ nsSVGAnimatedTransformList::SMILAnimated
     // y-angle
     if (numParsed != 1)
       return;
     transformType = SVG_TRANSFORM_SKEWY;
   } else {
     return;
   }
 
-  nsSMILValue val(&SVGTransformListSMILType::sSingleton);
+  nsSMILValue val(SVGTransformListSMILType::Singleton());
   SVGTransformSMILData transform(transformType, params);
   if (NS_FAILED(SVGTransformListSMILType::AppendTransform(transform, val))) {
     return; // OOM
   }
 
   // Success! Populate our outparam with parsed value.
   aResult.Swap(val);
 }
@@ -287,30 +287,30 @@ nsSVGAnimatedTransformList::SMILAnimated
 }
 
 nsSMILValue
 nsSVGAnimatedTransformList::SMILAnimatedTransformList::GetBaseValue() const
 {
   // To benefit from Return Value Optimization and avoid copy constructor calls
   // due to our use of return-by-value, we must return the exact same object
   // from ALL return points. This function must only return THIS variable:
-  nsSMILValue val(&SVGTransformListSMILType::sSingleton);
+  nsSMILValue val(SVGTransformListSMILType::Singleton());
   if (!SVGTransformListSMILType::AppendTransforms(mVal->mBaseVal, val)) {
     val = nsSMILValue();
   }
 
   return val;
 }
 
 nsresult
 nsSVGAnimatedTransformList::SMILAnimatedTransformList::SetAnimValue(
   const nsSMILValue& aNewAnimValue)
 {
   NS_ABORT_IF_FALSE(
-    aNewAnimValue.mType == &SVGTransformListSMILType::sSingleton,
+    aNewAnimValue.mType == SVGTransformListSMILType::Singleton(),
     "Unexpected type to assign animated value");
   SVGTransformList animVal;
   if (!SVGTransformListSMILType::GetTransforms(aNewAnimValue,
                                                animVal.mItems)) {
     return NS_ERROR_FAILURE;
   }
 
   return mVal->SetAnimValue(animVal, mElement);
--- a/content/svg/content/src/nsSVGBoolean.cpp
+++ b/content/svg/content/src/nsSVGBoolean.cpp
@@ -10,18 +10,24 @@
 #include "SMILBoolType.h"
 #include "SVGAnimatedBoolean.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 /* Implementation */
 
-static nsSVGAttrTearoffTable<nsSVGBoolean, SVGAnimatedBoolean>
-  sSVGAnimatedBooleanTearoffTable;
+static inline
+nsSVGAttrTearoffTable<nsSVGBoolean, SVGAnimatedBoolean>&
+SVGAnimatedBooleanTearoffTable()
+{
+  static nsSVGAttrTearoffTable<nsSVGBoolean, SVGAnimatedBoolean>
+    sSVGAnimatedBooleanTearoffTable;
+  return sSVGAnimatedBooleanTearoffTable;
+}
 
 static nsresult
 GetValueFromString(const nsAString &aValueAsString,
                    bool *aValue)
 {
   if (aValueAsString.EqualsLiteral("true")) {
     *aValue = true;
     return NS_OK;
@@ -103,28 +109,28 @@ nsSVGBoolean::SetAnimValue(bool aValue, 
   mIsAnimated = true;
   aSVGElement->DidAnimateBoolean(mAttrEnum);
 }
 
 already_AddRefed<SVGAnimatedBoolean>
 nsSVGBoolean::ToDOMAnimatedBoolean(nsSVGElement* aSVGElement)
 {
   nsRefPtr<SVGAnimatedBoolean> domAnimatedBoolean =
-    sSVGAnimatedBooleanTearoffTable.GetTearoff(this);
+    SVGAnimatedBooleanTearoffTable().GetTearoff(this);
   if (!domAnimatedBoolean) {
     domAnimatedBoolean = new SVGAnimatedBoolean(this, aSVGElement);
-    sSVGAnimatedBooleanTearoffTable.AddTearoff(this, domAnimatedBoolean);
+    SVGAnimatedBooleanTearoffTable().AddTearoff(this, domAnimatedBoolean);
   }
 
   return domAnimatedBoolean.forget();
 }
 
 SVGAnimatedBoolean::~SVGAnimatedBoolean()
 {
-  sSVGAnimatedBooleanTearoffTable.RemoveTearoff(mVal);
+  SVGAnimatedBooleanTearoffTable().RemoveTearoff(mVal);
 }
 
 nsISMILAttr*
 nsSVGBoolean::ToSMILAttr(nsSVGElement *aSVGElement)
 {
   return new SMILBool(this, aSVGElement);
 }
 
@@ -135,28 +141,28 @@ nsSVGBoolean::SMILBool::ValueFromString(
                                         bool& aPreventCachingOfSandwich) const
 {
   bool value;
   nsresult rv = GetValueFromString(aStr, &value);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  nsSMILValue val(&SMILBoolType::sSingleton);
+  nsSMILValue val(SMILBoolType::Singleton());
   val.mU.mBool = value;
   aValue = val;
   aPreventCachingOfSandwich = false;
 
   return NS_OK;
 }
 
 nsSMILValue
 nsSVGBoolean::SMILBool::GetBaseValue() const
 {
-  nsSMILValue val(&SMILBoolType::sSingleton);
+  nsSMILValue val(SMILBoolType::Singleton());
   val.mU.mBool = mVal->mBaseVal;
   return val;
 }
 
 void
 nsSVGBoolean::SMILBool::ClearAnimValue()
 {
   if (mVal->mIsAnimated) {
@@ -164,15 +170,15 @@ nsSVGBoolean::SMILBool::ClearAnimValue()
     mVal->mAnimVal = mVal->mBaseVal;
     mSVGElement->DidAnimateBoolean(mVal->mAttrEnum);
   }
 }
 
 nsresult
 nsSVGBoolean::SMILBool::SetAnimValue(const nsSMILValue& aValue)
 {
-  NS_ASSERTION(aValue.mType == &SMILBoolType::sSingleton,
+  NS_ASSERTION(aValue.mType == SMILBoolType::Singleton(),
                "Unexpected type to assign animated value");
-  if (aValue.mType == &SMILBoolType::sSingleton) {
+  if (aValue.mType == SMILBoolType::Singleton()) {
     mVal->SetAnimValue(uint16_t(aValue.mU.mBool), mSVGElement);
   }
   return NS_OK;
 }
--- a/content/svg/content/src/nsSVGClass.cpp
+++ b/content/svg/content/src/nsSVGClass.cpp
@@ -87,28 +87,28 @@ nsSVGClass::ToSMILAttr(nsSVGElement *aSV
 }
 
 nsresult
 nsSVGClass::SMILString::ValueFromString(const nsAString& aStr,
                                         const dom::SVGAnimationElement* /*aSrcElement*/,
                                         nsSMILValue& aValue,
                                         bool& aPreventCachingOfSandwich) const
 {
-  nsSMILValue val(&SMILStringType::sSingleton);
+  nsSMILValue val(SMILStringType::Singleton());
 
   *static_cast<nsAString*>(val.mU.mPtr) = aStr;
   aValue.Swap(val);
   aPreventCachingOfSandwich = false;
   return NS_OK;
 }
 
 nsSMILValue
 nsSVGClass::SMILString::GetBaseValue() const
 {
-  nsSMILValue val(&SMILStringType::sSingleton);
+  nsSMILValue val(SMILStringType::Singleton());
   mSVGElement->GetAttr(kNameSpaceID_None, nsGkAtoms::_class,
                        *static_cast<nsAString*>(val.mU.mPtr));
   return val;
 }
 
 void
 nsSVGClass::SMILString::ClearAnimValue()
 {
@@ -116,15 +116,15 @@ nsSVGClass::SMILString::ClearAnimValue()
     mVal->mAnimVal = nullptr;
     mSVGElement->DidAnimateClass();
   }
 }
 
 nsresult
 nsSVGClass::SMILString::SetAnimValue(const nsSMILValue& aValue)
 {
-  NS_ASSERTION(aValue.mType == &SMILStringType::sSingleton,
+  NS_ASSERTION(aValue.mType == SMILStringType::Singleton(),
                "Unexpected type to assign animated value");
-  if (aValue.mType == &SMILStringType::sSingleton) {
+  if (aValue.mType == SMILStringType::Singleton()) {
     mVal->SetAnimValue(*static_cast<nsAString*>(aValue.mU.mPtr), mSVGElement);
   }
   return NS_OK;
 }
--- a/content/svg/content/src/nsSVGEnum.cpp
+++ b/content/svg/content/src/nsSVGEnum.cpp
@@ -161,17 +161,17 @@ nsSVGEnum::SMILEnum::ValueFromString(con
                                      bool& aPreventCachingOfSandwich) const
 {
   nsIAtom *valAtom = NS_GetStaticAtom(aStr);
   if (valAtom) {
     nsSVGEnumMapping *mapping = mVal->GetMapping(mSVGElement);
 
     while (mapping && mapping->mKey) {
       if (valAtom == *(mapping->mKey)) {
-        nsSMILValue val(&SMILEnumType::sSingleton);
+        nsSMILValue val(SMILEnumType::Singleton());
         val.mU.mUint = mapping->mVal;
         aValue = val;
         aPreventCachingOfSandwich = false;
         return NS_OK;
       }
       mapping++;
     }
   }
@@ -179,17 +179,17 @@ nsSVGEnum::SMILEnum::ValueFromString(con
   // only a warning since authors may mistype attribute values
   NS_WARNING("unknown enumeration key");
   return NS_ERROR_FAILURE;
 }
 
 nsSMILValue
 nsSVGEnum::SMILEnum::GetBaseValue() const
 {
-  nsSMILValue val(&SMILEnumType::sSingleton);
+  nsSMILValue val(SMILEnumType::Singleton());
   val.mU.mUint = mVal->mBaseVal;
   return val;
 }
 
 void
 nsSVGEnum::SMILEnum::ClearAnimValue()
 {
   if (mVal->mIsAnimated) {
@@ -197,17 +197,17 @@ nsSVGEnum::SMILEnum::ClearAnimValue()
     mVal->mAnimVal = mVal->mBaseVal;
     mSVGElement->DidAnimateEnum(mVal->mAttrEnum);
   }
 }
 
 nsresult
 nsSVGEnum::SMILEnum::SetAnimValue(const nsSMILValue& aValue)
 {
-  NS_ASSERTION(aValue.mType == &SMILEnumType::sSingleton,
+  NS_ASSERTION(aValue.mType == SMILEnumType::Singleton(),
                "Unexpected type to assign animated value");
-  if (aValue.mType == &SMILEnumType::sSingleton) {
+  if (aValue.mType == SMILEnumType::Singleton()) {
     NS_ABORT_IF_FALSE(aValue.mU.mUint <= USHRT_MAX,
                       "Very large enumerated value - too big for uint16_t");
     mVal->SetAnimValue(uint16_t(aValue.mU.mUint), mSVGElement);
   }
   return NS_OK;
 }
--- a/content/svg/content/src/nsSVGInteger.cpp
+++ b/content/svg/content/src/nsSVGInteger.cpp
@@ -152,27 +152,27 @@ nsSVGInteger::SMILInteger::ValueFromStri
 {
   int32_t val;
 
   nsresult rv = GetValueFromString(aStr, &val);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  nsSMILValue smilVal(&SMILIntegerType::sSingleton);
+  nsSMILValue smilVal(SMILIntegerType::Singleton());
   smilVal.mU.mInt = val;
   aValue = smilVal;
   aPreventCachingOfSandwich = false;
   return NS_OK;
 }
 
 nsSMILValue
 nsSVGInteger::SMILInteger::GetBaseValue() const
 {
-  nsSMILValue val(&SMILIntegerType::sSingleton);
+  nsSMILValue val(SMILIntegerType::Singleton());
   val.mU.mInt = mVal->mBaseVal;
   return val;
 }
 
 void
 nsSVGInteger::SMILInteger::ClearAnimValue()
 {
   if (mVal->mIsAnimated) {
@@ -180,15 +180,15 @@ nsSVGInteger::SMILInteger::ClearAnimValu
     mVal->mAnimVal = mVal->mBaseVal;
     mSVGElement->DidAnimateInteger(mVal->mAttrEnum);
   }
 }
 
 nsresult
 nsSVGInteger::SMILInteger::SetAnimValue(const nsSMILValue& aValue)
 {
-  NS_ASSERTION(aValue.mType == &SMILIntegerType::sSingleton,
+  NS_ASSERTION(aValue.mType == SMILIntegerType::Singleton(),
                "Unexpected type to assign animated value");
-  if (aValue.mType == &SMILIntegerType::sSingleton) {
+  if (aValue.mType == SMILIntegerType::Singleton()) {
     mVal->SetAnimValue(int(aValue.mU.mInt), mSVGElement);
   }
   return NS_OK;
 }
--- a/content/svg/content/src/nsSVGIntegerPair.cpp
+++ b/content/svg/content/src/nsSVGIntegerPair.cpp
@@ -219,29 +219,29 @@ nsSVGIntegerPair::SMILIntegerPair::Value
 {
   int32_t values[2];
 
   nsresult rv = ParseIntegerOptionalInteger(aStr, values);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  nsSMILValue val(&SVGIntegerPairSMILType::sSingleton);
+  nsSMILValue val(SVGIntegerPairSMILType::Singleton());
   val.mU.mIntPair[0] = values[0];
   val.mU.mIntPair[1] = values[1];
   aValue = val;
   aPreventCachingOfSandwich = false;
 
   return NS_OK;
 }
 
 nsSMILValue
 nsSVGIntegerPair::SMILIntegerPair::GetBaseValue() const
 {
-  nsSMILValue val(&SVGIntegerPairSMILType::sSingleton);
+  nsSMILValue val(SVGIntegerPairSMILType::Singleton());
   val.mU.mIntPair[0] = mVal->mBaseVal[0];
   val.mU.mIntPair[1] = mVal->mBaseVal[1];
   return val;
 }
 
 void
 nsSVGIntegerPair::SMILIntegerPair::ClearAnimValue()
 {
@@ -251,15 +251,15 @@ nsSVGIntegerPair::SMILIntegerPair::Clear
     mVal->mAnimVal[1] = mVal->mBaseVal[1];
     mSVGElement->DidAnimateIntegerPair(mVal->mAttrEnum);
   }
 }
 
 nsresult
 nsSVGIntegerPair::SMILIntegerPair::SetAnimValue(const nsSMILValue& aValue)
 {
-  NS_ASSERTION(aValue.mType == &SVGIntegerPairSMILType::sSingleton,
+  NS_ASSERTION(aValue.mType == SVGIntegerPairSMILType::Singleton(),
                "Unexpected type to assign animated value");
-  if (aValue.mType == &SVGIntegerPairSMILType::sSingleton) {
+  if (aValue.mType == SVGIntegerPairSMILType::Singleton()) {
     mVal->SetAnimValue(aValue.mU.mIntPair, mSVGElement);
   }
   return NS_OK;
 }
--- a/content/svg/content/src/nsSVGLength2.cpp
+++ b/content/svg/content/src/nsSVGLength2.cpp
@@ -512,31 +512,31 @@ nsSVGLength2::SMILLength::ValueFromStrin
   float value;
   uint16_t unitType;
   
   nsresult rv = GetValueFromString(aStr, &value, &unitType);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  nsSMILValue val(&nsSMILFloatType::sSingleton);
+  nsSMILValue val(nsSMILFloatType::Singleton());
   val.mU.mDouble = value / mVal->GetUnitScaleFactor(mSVGElement, unitType);
   aValue = val;
   aPreventCachingOfSandwich =
               (unitType == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE ||
                unitType == nsIDOMSVGLength::SVG_LENGTHTYPE_EMS ||
                unitType == nsIDOMSVGLength::SVG_LENGTHTYPE_EXS);
 
   return NS_OK;
 }
 
 nsSMILValue
 nsSVGLength2::SMILLength::GetBaseValue() const
 {
-  nsSMILValue val(&nsSMILFloatType::sSingleton);
+  nsSMILValue val(nsSMILFloatType::Singleton());
   val.mU.mDouble = mVal->GetBaseValue(mSVGElement);
   return val;
 }
 
 void
 nsSVGLength2::SMILLength::ClearAnimValue()
 {
   if (mVal->mIsAnimated) {
@@ -544,15 +544,15 @@ nsSVGLength2::SMILLength::ClearAnimValue
     mVal->mAnimVal = mVal->mBaseVal;
     mSVGElement->DidAnimateLength(mVal->mAttrEnum);
   }  
 }
 
 nsresult
 nsSVGLength2::SMILLength::SetAnimValue(const nsSMILValue& aValue)
 {
-  NS_ASSERTION(aValue.mType == &nsSMILFloatType::sSingleton,
+  NS_ASSERTION(aValue.mType == nsSMILFloatType::Singleton(),
     "Unexpected type to assign animated value");
-  if (aValue.mType == &nsSMILFloatType::sSingleton) {
+  if (aValue.mType == nsSMILFloatType::Singleton()) {
     mVal->SetAnimValue(float(aValue.mU.mDouble), mSVGElement);
   }
   return NS_OK;
 }
--- a/content/svg/content/src/nsSVGNumber2.cpp
+++ b/content/svg/content/src/nsSVGNumber2.cpp
@@ -192,28 +192,28 @@ nsSVGNumber2::SMILNumber::ValueFromStrin
 
   nsresult rv = GetValueFromString(
     aStr, mSVGElement->NumberAttrAllowsPercentage(mVal->mAttrEnum), &value);
 
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  nsSMILValue val(&nsSMILFloatType::sSingleton);
+  nsSMILValue val(nsSMILFloatType::Singleton());
   val.mU.mDouble = value;
   aValue = val;
   aPreventCachingOfSandwich = false;
 
   return NS_OK;
 }
 
 nsSMILValue
 nsSVGNumber2::SMILNumber::GetBaseValue() const
 {
-  nsSMILValue val(&nsSMILFloatType::sSingleton);
+  nsSMILValue val(nsSMILFloatType::Singleton());
   val.mU.mDouble = mVal->mBaseVal;
   return val;
 }
 
 void
 nsSVGNumber2::SMILNumber::ClearAnimValue()
 {
   if (mVal->mIsAnimated) {
@@ -221,15 +221,15 @@ nsSVGNumber2::SMILNumber::ClearAnimValue
     mVal->mAnimVal = mVal->mBaseVal;
     mSVGElement->DidAnimateNumber(mVal->mAttrEnum);
   }
 }
 
 nsresult
 nsSVGNumber2::SMILNumber::SetAnimValue(const nsSMILValue& aValue)
 {
-  NS_ASSERTION(aValue.mType == &nsSMILFloatType::sSingleton,
+  NS_ASSERTION(aValue.mType == nsSMILFloatType::Singleton(),
                "Unexpected type to assign animated value");
-  if (aValue.mType == &nsSMILFloatType::sSingleton) {
+  if (aValue.mType == nsSMILFloatType::Singleton()) {
     mVal->SetAnimValue(float(aValue.mU.mDouble), mSVGElement);
   }
   return NS_OK;
 }
--- a/content/svg/content/src/nsSVGString.cpp
+++ b/content/svg/content/src/nsSVGString.cpp
@@ -18,18 +18,24 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGSt
 DOMCI_DATA(SVGAnimatedString, nsSVGString::DOMAnimatedString)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGString::DOMAnimatedString)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedString)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedString)
 NS_INTERFACE_MAP_END
 
-static nsSVGAttrTearoffTable<nsSVGString, nsSVGString::DOMAnimatedString>
-  sSVGAnimatedStringTearoffTable;
+static inline
+nsSVGAttrTearoffTable<nsSVGString, nsSVGString::DOMAnimatedString>&
+SVGAnimatedStringTearoffTable()
+{
+  static nsSVGAttrTearoffTable<nsSVGString, nsSVGString::DOMAnimatedString>
+    sSVGAnimatedStringTearoffTable;
+  return sSVGAnimatedStringTearoffTable;
+}
 
 /* Implementation */
 
 void
 nsSVGString::SetBaseValue(const nsAString& aValue,
                           nsSVGElement *aSVGElement,
                           bool aDoSetAttr)
 {
@@ -79,69 +85,69 @@ nsSVGString::ToDOMAnimatedString(nsIDOMS
   *aResult = ToDOMAnimatedString(aSVGElement).get();
   return NS_OK;
 }
 
 already_AddRefed<nsIDOMSVGAnimatedString>
 nsSVGString::ToDOMAnimatedString(nsSVGElement* aSVGElement)
 {
   nsRefPtr<DOMAnimatedString> domAnimatedString =
-    sSVGAnimatedStringTearoffTable.GetTearoff(this);
+    SVGAnimatedStringTearoffTable().GetTearoff(this);
   if (!domAnimatedString) {
     domAnimatedString = new DOMAnimatedString(this, aSVGElement);
-    sSVGAnimatedStringTearoffTable.AddTearoff(this, domAnimatedString);
+    SVGAnimatedStringTearoffTable().AddTearoff(this, domAnimatedString);
   }
 
   return domAnimatedString.forget();
 }
 
 nsSVGString::DOMAnimatedString::~DOMAnimatedString()
 {
-  sSVGAnimatedStringTearoffTable.RemoveTearoff(mVal);
+  SVGAnimatedStringTearoffTable().RemoveTearoff(mVal);
 }
 
 nsISMILAttr*
 nsSVGString::ToSMILAttr(nsSVGElement *aSVGElement)
 {
   return new SMILString(this, aSVGElement);
 }
 
 nsresult
 nsSVGString::SMILString::ValueFromString(const nsAString& aStr,
                                          const dom::SVGAnimationElement* /*aSrcElement*/,
                                          nsSMILValue& aValue,
                                          bool& aPreventCachingOfSandwich) const
 {
-  nsSMILValue val(&SMILStringType::sSingleton);
+  nsSMILValue val(SMILStringType::Singleton());
 
   *static_cast<nsAString*>(val.mU.mPtr) = aStr;
   aValue.Swap(val);
   aPreventCachingOfSandwich = false;
   return NS_OK;
 }
 
 nsSMILValue
 nsSVGString::SMILString::GetBaseValue() const
 {
-  nsSMILValue val(&SMILStringType::sSingleton);
+  nsSMILValue val(SMILStringType::Singleton());
   mSVGElement->GetStringBaseValue(mVal->mAttrEnum, *static_cast<nsAString*>(val.mU.mPtr));
   return val;
 }
 
 void
 nsSVGString::SMILString::ClearAnimValue()
 {
   if (mVal->mAnimVal) {
     mVal->mAnimVal = nullptr;
     mSVGElement->DidAnimateString(mVal->mAttrEnum);
   }
 }
 
 nsresult
 nsSVGString::SMILString::SetAnimValue(const nsSMILValue& aValue)
 {
-  NS_ASSERTION(aValue.mType == &SMILStringType::sSingleton,
+  NS_ASSERTION(aValue.mType == SMILStringType::Singleton(),
                "Unexpected type to assign animated value");
-  if (aValue.mType == &SMILStringType::sSingleton) {
+  if (aValue.mType == SMILStringType::Singleton()) {
     mVal->SetAnimValue(*static_cast<nsAString*>(aValue.mU.mPtr), mSVGElement);
   }
   return NS_OK;
 }
--- a/content/xslt/src/xml/txXMLUtils.cpp
+++ b/content/xslt/src/xml/txXMLUtils.cpp
@@ -131,28 +131,16 @@ XMLUtils::splitQName(const nsAString& aN
     else {
         *aPrefix = nullptr;
         *aLocalName = NS_NewAtom(aName).get();
     }
 
     return NS_OK;
 }
 
-const nsDependentSubstring XMLUtils::getLocalPart(const nsAString& src)
-{
-    // Anything after ':' is the local part of the name
-    int32_t idx = src.FindChar(':');
-    if (idx == kNotFound) {
-        return Substring(src, 0, src.Length());
-    }
-
-    NS_ASSERTION(idx > 0, "This QName looks invalid.");
-    return Substring(src, idx + 1, src.Length() - (idx + 1));
-}
-
 /**
  * Returns true if the given string has only whitespace characters
  */
 bool XMLUtils::isWhitespace(const nsAFlatString& aText)
 {
     nsAFlatString::const_char_iterator start, end;
     aText.BeginReading(start);
     aText.EndReading(end);
--- a/content/xslt/src/xml/txXMLUtils.h
+++ b/content/xslt/src/xml/txXMLUtils.h
@@ -82,17 +82,16 @@ public:
 class XMLUtils {
 
 public:
     static nsresult splitExpatName(const PRUnichar *aExpatName,
                                    nsIAtom **aPrefix, nsIAtom **aLocalName,
                                    int32_t* aNameSpaceID);
     static nsresult splitQName(const nsAString& aName, nsIAtom** aPrefix,
                                nsIAtom** aLocalName);
-    static const nsDependentSubstring getLocalPart(const nsAString& src);
 
     /*
      * Returns true if the given character is whitespace.
      */
     static bool isWhitespace(const PRUnichar& aChar)
     {
         return (aChar <= ' ' &&
                 (aChar == ' ' || aChar == '\r' ||
--- a/content/xul/content/src/nsXULElement.h
+++ b/content/xul/content/src/nsXULElement.h
@@ -339,18 +339,17 @@ public:
 
 // XUL element specific bits
 enum {
   XUL_ELEMENT_TEMPLATE_GENERATED =        XUL_ELEMENT_FLAG_BIT(0),
   XUL_ELEMENT_HAS_CONTENTMENU_LISTENER =  XUL_ELEMENT_FLAG_BIT(1),
   XUL_ELEMENT_HAS_POPUP_LISTENER =        XUL_ELEMENT_FLAG_BIT(2)
 };
 
-// Make sure we have space for our bits
-PR_STATIC_ASSERT((ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2) < 32);
+ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 3);
 
 #undef XUL_ELEMENT_FLAG_BIT
 
 class nsScriptEventHandlerOwnerTearoff;
 
 class nsXULElement : public nsStyledElement,
                      public nsIDOMXULElement
 {
--- a/dom/base/nsDOMException.cpp
+++ b/dom/base/nsDOMException.cpp
@@ -1,24 +1,28 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "nsDOMException.h"
+
+#include "mozilla/Util.h"
 #include "nsCOMPtr.h"
 #include "nsCRTGlue.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfoID.h"
 #include "nsError.h"
-#include "nsDOMException.h"
 #include "nsIDOMDOMException.h"
 #include "nsIDocument.h"
 #include "nsString.h"
 #include "prprf.h"
 
+using namespace mozilla;
+
 enum DOM4ErrorTypeCodeMap {
   /* DOM4 errors from http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#domexception */
   IndexSizeError             = nsIDOMDOMException::INDEX_SIZE_ERR,
   HierarchyRequestError      = nsIDOMDOMException::HIERARCHY_REQUEST_ERR,
   WrongDocumentError         = nsIDOMDOMException::WRONG_DOCUMENT_ERR,
   InvalidCharacterError      = nsIDOMDOMException::INVALID_CHARACTER_ERR,
   NoModificationAllowedError = nsIDOMDOMException::NO_MODIFICATION_ALLOWED_ERR,
   NotFoundError              = nsIDOMDOMException::NOT_FOUND_ERR,
@@ -58,50 +62,45 @@ enum DOM4ErrorTypeCodeMap {
 
   /* FileHandle API errors */
   LockedFileInactiveError = 0,
 };
 
 #define DOM4_MSG_DEF(name, message, nsresult) {(nsresult), name, #name, message},
 #define DOM_MSG_DEF(val, message) {(val), NS_ERROR_GET_CODE(val), #val, message},
 
-static struct ResultStruct
+static const struct ResultStruct
 {
   nsresult mNSResult;
   uint16_t mCode;
   const char* mName;
   const char* mMessage;
-} gDOMErrorMsgMap[] = {
+} sDOMErrorMsgMap[] = {
 #include "domerr.msg"
-  {NS_OK, 0, nullptr, nullptr}   // sentinel to mark end of array
 };
 
 #undef DOM4_MSG_DEF
 #undef DOM_MSG_DEF
 
 static void
 NSResultToNameAndMessage(nsresult aNSResult,
                          const char** aName,
                          const char** aMessage,
                          uint16_t* aCode)
 {
   *aName = nullptr;
   *aMessage = nullptr;
   *aCode = 0;
-  ResultStruct* result_struct = gDOMErrorMsgMap;
-
-  while (result_struct->mName) {
-    if (aNSResult == result_struct->mNSResult) {
-      *aName = result_struct->mName;
-      *aMessage = result_struct->mMessage;
-      *aCode = result_struct->mCode;
+  for (uint32_t idx = 0; idx < ArrayLength(sDOMErrorMsgMap); idx++) {
+    if (aNSResult == sDOMErrorMsgMap[idx].mNSResult) {
+      *aName = sDOMErrorMsgMap[idx].mName;
+      *aMessage = sDOMErrorMsgMap[idx].mMessage;
+      *aCode = sDOMErrorMsgMap[idx].mCode;
       return;
     }
-
-    ++result_struct;
   }
 
   NS_WARNING("Huh, someone is throwing non-DOM errors using the DOM module!");
 
   return;
 }
 
 nsresult
--- a/dom/base/nsWrapperCache.h
+++ b/dom/base/nsWrapperCache.h
@@ -60,17 +60,17 @@ class DOMBindingBase;
  */
 class nsWrapperCache
 {
   friend class mozilla::dom::workers::DOMBindingBase;
 
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_WRAPPERCACHE_IID)
 
-  nsWrapperCache() : mWrapperPtrBits(0)
+  nsWrapperCache() : mWrapper(nullptr), mFlags(0)
   {
   }
   ~nsWrapperCache()
   {
     MOZ_ASSERT(!PreservingWrapper(),
                "Destroying cache with a preserved wrapper!");
   }
 
@@ -89,74 +89,74 @@ public:
    * object returned is not guaranteed to be kept alive past the next CC.
    *
    * This should only be called if you are certain that the return value won't
    * be passed into a JS API function and that it won't be stored without being
    * rooted (or otherwise signaling the stored value to the CC).
    */
   JSObject* GetWrapperPreserveColor() const
   {
-    return GetJSObjectFromBits();
+    return GetWrapperJSObject();
   }
 
   void SetWrapper(JSObject* aWrapper)
   {
     MOZ_ASSERT(!PreservingWrapper(), "Clearing a preserved wrapper!");
     MOZ_ASSERT(aWrapper, "Use ClearWrapper!");
 
-    SetWrapperBits(aWrapper);
+    SetWrapperJSObject(aWrapper);
   }
 
   /**
    * Clear the wrapper. This should be called from the finalizer for the
    * wrapper.
    */
   void ClearWrapper()
   {
     MOZ_ASSERT(!PreservingWrapper(), "Clearing a preserved wrapper!");
 
-    SetWrapperBits(NULL);
+    SetWrapperJSObject(nullptr);
   }
 
   bool PreservingWrapper()
   {
-    return (mWrapperPtrBits & WRAPPER_BIT_PRESERVED) != 0;
+    return HasWrapperFlag(WRAPPER_BIT_PRESERVED);
   }
 
   void SetIsDOMBinding()
   {
-    MOZ_ASSERT(!mWrapperPtrBits,
+    MOZ_ASSERT(!mWrapper && !GetWrapperFlags(),
                "This flag should be set before creating any wrappers.");
-    mWrapperPtrBits = WRAPPER_IS_DOM_BINDING;
+    SetWrapperFlags(WRAPPER_IS_DOM_BINDING);
   }
 
   bool IsDOMBinding() const
   {
-    return (mWrapperPtrBits & WRAPPER_IS_DOM_BINDING) != 0;
+    return HasWrapperFlag(WRAPPER_IS_DOM_BINDING);
   }
 
   void SetHasSystemOnlyWrapper()
   {
     MOZ_ASSERT(GetWrapperPreserveColor(),
                "This flag should be set after wrapper creation.");
     MOZ_ASSERT(IsDOMBinding(),
                "This flag should only be set for DOM bindings.");
-    mWrapperPtrBits |= WRAPPER_HAS_SOW;
+    SetWrapperFlags(WRAPPER_HAS_SOW);
   }
 
   bool HasSystemOnlyWrapper() const
   {
-    return (mWrapperPtrBits & WRAPPER_HAS_SOW) != 0;
+    return HasWrapperFlag(WRAPPER_HAS_SOW);
   }
 
   /**
    * Wrap the object corresponding to this wrapper cache. If non-null is
    * returned, the object has already been stored in the wrapper cache.
    */
-  virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> scope)
+  virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> scope)
   {
     MOZ_ASSERT(!IsDOMBinding(), "Someone forgot to override WrapObject");
     return nullptr;
   }
 
   /**
    * Returns true if the object has a non-gray wrapper.
    */
@@ -167,47 +167,94 @@ public:
    * and all the GC things it is keeping alive are black too.
    */
   bool IsBlackAndDoesNotNeedTracing(nsISupports* aThis);
 
   // Only meant to be called by code that preserves a wrapper.
   void SetPreservingWrapper(bool aPreserve)
   {
     if(aPreserve) {
-      mWrapperPtrBits |= WRAPPER_BIT_PRESERVED;
+      SetWrapperFlags(WRAPPER_BIT_PRESERVED);
     }
     else {
-      mWrapperPtrBits &= ~WRAPPER_BIT_PRESERVED;
+      UnsetWrapperFlags(WRAPPER_BIT_PRESERVED);
     }
   }
 
   void TraceWrapper(const TraceCallbacks& aCallbacks, void* aClosure)
   {
-    if (PreservingWrapper()) {
-      JSObject *wrapper = GetWrapperPreserveColor();
-      if (wrapper) {
-        uintptr_t flags = mWrapperPtrBits & kWrapperBitMask;
-        aCallbacks.Trace(&wrapper, "Preserved wrapper", aClosure);
-        mWrapperPtrBits = reinterpret_cast<uintptr_t>(wrapper) | flags;
-      }
+    if (PreservingWrapper() && mWrapper) {
+        aCallbacks.Trace(&mWrapper, "Preserved wrapper", aClosure);
     }
   }
 
+  /* 
+   * The following methods for getting and manipulating flags allow the unused
+   * bits of mFlags to be used by derived classes.
+   */
+
+  uint32_t GetFlags() const
+  {
+    return mFlags & ~kWrapperFlagsMask;
+  }
+
+  bool HasFlag(uint32_t aFlag) const
+  {
+    MOZ_ASSERT((aFlag & kWrapperFlagsMask) == 0, "Bad flag mask");
+    return !!(mFlags & aFlag);
+  }
+
+  void SetFlags(uint32_t aFlagsToSet)
+  {
+    MOZ_ASSERT((aFlagsToSet & kWrapperFlagsMask) == 0, "Bad flag mask");
+    mFlags |= aFlagsToSet;
+  }
+
+  void UnsetFlags(uint32_t aFlagsToUnset)
+  {
+    MOZ_ASSERT((aFlagsToUnset & kWrapperFlagsMask) == 0, "Bad flag mask");
+    mFlags &= ~aFlagsToUnset;
+  }
+
 private:
-  JSObject *GetJSObjectFromBits() const
+  JSObject *GetWrapperJSObject() const
   {
-    return reinterpret_cast<JSObject*>(mWrapperPtrBits & ~kWrapperBitMask);
+    return mWrapper;
   }
-  void SetWrapperBits(void *aWrapper)
+
+  void SetWrapperJSObject(JSObject* aWrapper)
   {
-    mWrapperPtrBits = reinterpret_cast<uintptr_t>(aWrapper) |
-                      (mWrapperPtrBits & WRAPPER_IS_DOM_BINDING);
+    mWrapper = aWrapper;
+    UnsetWrapperFlags(kWrapperFlagsMask & ~WRAPPER_IS_DOM_BINDING);
+  }
+
+  void TraceWrapperJSObject(JSTracer* aTrc, const char* aName);
+
+  uint32_t GetWrapperFlags() const
+  {
+    return mFlags & kWrapperFlagsMask;
   }
 
-  void TraceJSObjectFromBits(JSTracer *aTrc, const char *aName);
+  bool HasWrapperFlag(uint32_t aFlag) const
+  {
+    MOZ_ASSERT((aFlag & ~kWrapperFlagsMask) == 0, "Bad wrapper flag bits");
+    return !!(mFlags & aFlag);
+  }
+
+  void SetWrapperFlags(uint32_t aFlagsToSet)
+  {
+    MOZ_ASSERT((aFlagsToSet & ~kWrapperFlagsMask) == 0, "Bad wrapper flag bits");
+    mFlags |= aFlagsToSet;
+  }
+
+  void UnsetWrapperFlags(uint32_t aFlagsToUnset)
+  {
+    MOZ_ASSERT((aFlagsToUnset & ~kWrapperFlagsMask) == 0, "Bad wrapper flag bits");
+    mFlags &= ~aFlagsToUnset;
+  }
 
   /**
    * If this bit is set then we're preserving the wrapper, which in effect ties
    * the lifetime of the JS object stored in the cache to the lifetime of the
    * native object. We rely on the cycle collector to break the cycle that this
    * causes between the native object and the JS object, so it is important that
    * any native object that supports preserving of its wrapper
    * traces/traverses/unlinks the cached JS object (see
@@ -225,22 +272,25 @@ private:
 
   /**
    * If this bit is set then the wrapper for the native object is a DOM binding
    * (regular JS object or proxy) that has a system only wrapper for same-origin
    * access.
    */
   enum { WRAPPER_HAS_SOW = 1 << 2 };
 
-  enum { kWrapperBitMask = (WRAPPER_BIT_PRESERVED | WRAPPER_IS_DOM_BINDING |
-                            WRAPPER_HAS_SOW) };
+  enum { kWrapperFlagsMask = (WRAPPER_BIT_PRESERVED | WRAPPER_IS_DOM_BINDING |
+                              WRAPPER_HAS_SOW) };
 
-  uintptr_t mWrapperPtrBits;
+  JSObject* mWrapper;
+  uint32_t  mFlags;
 };
 
+enum { WRAPPER_CACHE_FLAGS_BITS_USED = 3 };
+
 NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperCache, NS_WRAPPERCACHE_IID)
 
 #define NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY                                   \
   if ( aIID.Equals(NS_GET_IID(nsWrapperCache)) ) {                            \
     *aInstancePtr = static_cast<nsWrapperCache*>(this);                       \
     return NS_OK;                                                             \
   }
 
--- a/dom/base/nsWrapperCacheInlines.h
+++ b/dom/base/nsWrapperCacheInlines.h
@@ -5,26 +5,16 @@
 
 #ifndef nsWrapperCacheInline_h___
 #define nsWrapperCacheInline_h___
 
 #include "nsWrapperCache.h"
 #include "xpcpublic.h"
 #include "jsapi.h"
 
-// We want to encode 3 bits into mWrapperPtrBits, so anything we store in it
-// needs to be aligned on 8 byte boundaries.
-// JS arenas are aligned on 4k boundaries and padded so that the array of
-// JSObjects ends on the end of the arena. If the size of a JSObject is a
-// multiple of 8 then the start of every JSObject in an arena should be aligned
-// on 8 byte boundaries.
-MOZ_STATIC_ASSERT(sizeof(js::shadow::Object) % 8 == 0 && sizeof(JS::Value) == 8,
-                  "We want to rely on JSObject being aligned on 8 byte "
-                  "boundaries.");
-
 inline JSObject*
 nsWrapperCache::GetWrapper() const
 {
     JSObject* obj = GetWrapperPreserveColor();
     xpc_UnmarkGrayObject(obj);
     return obj;
 }
 
@@ -53,14 +43,14 @@ nsWrapperCache::IsBlackAndDoesNotNeedTra
     bool hasGrayObjects = false;
     participant->Trace(aThis, TraceCallbackFunc(SearchGray), &hasGrayObjects);
     return !hasGrayObjects;
   }
   return false;
 }
 
 inline void
-nsWrapperCache::TraceJSObjectFromBits(JSTracer* aTrc, const char* aName)
+nsWrapperCache::TraceWrapperJSObject(JSTracer* aTrc, const char* aName)
 {
-  JS_CallMaskedObjectTracer(aTrc, &mWrapperPtrBits, kWrapperBitMask, aName);
+  JS_CallObjectTracer(aTrc, &mWrapper, aName);
 }
 
 #endif /* nsWrapperCache_h___ */
--- a/dom/bindings/BindingDeclarations.h
+++ b/dom/bindings/BindingDeclarations.h
@@ -557,17 +557,17 @@ public:
   void SetTimeStamp(double aMilliseconds)
   {
     mMsecSinceEpoch = aMilliseconds;
   }
   // Can return false if CheckedUnwrap fails.  This will NOT throw;
   // callers should do it as needed.
   bool SetTimeStamp(JSContext* cx, JSObject* obj);
 
-  bool ToDateObject(JSContext* cx, JS::Value* vp) const;
+  bool ToDateObject(JSContext* cx, JS::MutableHandle<JS::Value> rval) const;
 
 private:
   double mMsecSinceEpoch;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -663,16 +663,17 @@ VariantToJsval(JSContext* aCx, JS::Handl
   }
 
   return true;
 }
 
 JSBool
 QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp)
 {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   JS::Rooted<JS::Value> thisv(cx, JS_THIS(cx, vp));
   if (thisv.isNull())
     return false;
 
   // Get the object. It might be a security wrapper, in which case we do a checked
   // unwrap.
   JS::Rooted<JSObject*> origObj(cx, &thisv.toObject());
   JSObject* obj = js::CheckedUnwrap(origObj);
@@ -705,17 +706,17 @@ QueryInterface(JSContext* cx, unsigned a
 
   if (iid->GetID()->Equals(NS_GET_IID(nsIClassInfo))) {
     nsresult rv;
     nsCOMPtr<nsIClassInfo> ci = do_QueryInterface(native, &rv);
     if (NS_FAILED(rv)) {
       return Throw<true>(cx, rv);
     }
 
-    return WrapObject(cx, origObj, ci, &NS_GET_IID(nsIClassInfo), vp);
+    return WrapObject(cx, origObj, ci, &NS_GET_IID(nsIClassInfo), args.rval());
   }
 
   nsCOMPtr<nsISupports> unused;
   nsresult rv = native->QueryInterface(*iid->GetID(), getter_AddRefs(unused));
   if (NS_FAILED(rv)) {
     return Throw<true>(cx, rv);
   }
 
@@ -1778,23 +1779,23 @@ Date::SetTimeStamp(JSContext* cx, JSObje
   if (!obj) {
     return false;
   }
   mMsecSinceEpoch = js_DateGetMsecSinceEpoch(obj);
   return true;
 }
 
 bool
-Date::ToDateObject(JSContext* cx, JS::Value* vp) const
+Date::ToDateObject(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
 {
   JSObject* obj = JS_NewDateObjectMsec(cx, mMsecSinceEpoch);
   if (!obj) {
     return false;
   }
-  *vp = JS::ObjectValue(*obj);
+  rval.set(JS::ObjectValue(*obj));
   return true;
 }
 
 bool
 GetWindowForJSImplementedObject(JSContext* cx, JS::Handle<JSObject*> obj,
                                 nsPIDOMWindow** window)
 {
   // Be very careful to not get tricked here.
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -516,83 +516,84 @@ GetSameCompartmentWrapperForDOMBinding(J
 
 inline void
 SetSystemOnlyWrapper(JSObject* obj, nsWrapperCache* cache, JSObject& wrapper)
 {
   SetSystemOnlyWrapperSlot(obj, JS::ObjectValue(wrapper));
   cache->SetHasSystemOnlyWrapper();
 }
 
-// If *vp is a gcthing and is not in the compartment of cx, wrap *vp
+// If rval is a gcthing and is not in the compartment of cx, wrap rval
 // into the compartment of cx (typically by replacing it with an Xray or
 // cross-compartment wrapper around the original object).
 MOZ_ALWAYS_INLINE bool
-MaybeWrapValue(JSContext* cx, JS::Value* vp)
+MaybeWrapValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
 {
-  if (vp->isString()) {
-    JSString* str = vp->toString();
+  if (rval.isString()) {
+    JSString* str = rval.toString();
     if (JS::GetGCThingZone(str) != js::GetContextZone(cx)) {
-      return JS_WrapValue(cx, vp);
+      return JS_WrapValue(cx, rval.address());
     }
     return true;
   }
 
-  if (vp->isObject()) {
-    JSObject* obj = &vp->toObject();
+  if (rval.isObject()) {
+    JSObject* obj = &rval.toObject();
     if (js::GetObjectCompartment(obj) != js::GetContextCompartment(cx)) {
-      return JS_WrapValue(cx, vp);
+      return JS_WrapValue(cx, rval.address());
     }
 
     // We're same-compartment, but even then we might need to wrap
     // objects specially.  Check for that.
     if (GetSameCompartmentWrapperForDOMBinding(obj)) {
       // We're a new-binding object, and "obj" now points to the right thing
-      *vp = JS::ObjectValue(*obj);
+      rval.set(JS::ObjectValue(*obj));
       return true;
     }
 
     if (!IS_SLIM_WRAPPER(obj)) {
       // We might need a SOW
-      return JS_WrapValue(cx, vp);
+      return JS_WrapValue(cx, rval.address());
     }
 
     // Fall through to returning true
   }
 
   return true;
 }
 
 static inline void
 WrapNewBindingForSameCompartment(JSContext* cx, JSObject* obj, void* value,
-                                 JS::Value* vp)
+                                 JS::MutableHandle<JS::Value> rval)
 {
-  *vp = JS::ObjectValue(*obj);
+  rval.set(JS::ObjectValue(*obj));
 }
 
 static inline void
 WrapNewBindingForSameCompartment(JSContext* cx, JSObject* obj,
-                                 nsWrapperCache* value, JS::Value* vp)
+                                 nsWrapperCache* value,
+                                 JS::MutableHandle<JS::Value> rval)
 {
   if (value->HasSystemOnlyWrapper()) {
-    *vp = GetSystemOnlyWrapperSlot(obj);
-    MOZ_ASSERT(vp->isObject());
+    rval.set(GetSystemOnlyWrapperSlot(obj));
+    MOZ_ASSERT(rval.isObject());
   } else {
-    *vp = JS::ObjectValue(*obj);
+    rval.set(JS::ObjectValue(*obj));
   }
 }
 
 // Create a JSObject wrapping "value", if there isn't one already, and store it
-// in *vp.  "value" must be a concrete class that implements a
+// in rval.  "value" must be a concrete class that implements a
 // GetWrapperPreserveColor() which can return its existing wrapper, if any, and
 // a WrapObject() which will try to create a wrapper. Typically, this is done by
 // having "value" inherit from nsWrapperCache.
 template <class T>
 MOZ_ALWAYS_INLINE bool
 WrapNewBindingObject(JSContext* cx, JS::Handle<JSObject*> scope, T* value,
-                     JS::Value* vp)
+                     JS::MutableHandle<JS::Value> rval)
 {
   MOZ_ASSERT(value);
   JSObject* obj = value->GetWrapperPreserveColor();
   bool couldBeDOMBinding = CouldBeDOMBinding(value);
   if (obj) {
     xpc_UnmarkNonNullGrayObject(obj);
   } else {
     // Inline this here while we have non-dom objects in wrapper caches.
@@ -631,32 +632,33 @@ WrapNewBindingObject(JSContext* cx, JS::
   // make sure it's correctly wrapped for the compartment of |scope|.
   // cx should already be in the compartment of |scope| here.
   MOZ_ASSERT(js::IsObjectInContextCompartment(scope, cx));
 #endif
 
   bool sameCompartment =
     js::GetObjectCompartment(obj) == js::GetContextCompartment(cx);
   if (sameCompartment && couldBeDOMBinding) {
-    WrapNewBindingForSameCompartment(cx, obj, value, vp);
+    WrapNewBindingForSameCompartment(cx, obj, value, rval);
     return true;
   }
 
-  *vp = JS::ObjectValue(*obj);
-  return (sameCompartment && IS_SLIM_WRAPPER(obj)) || JS_WrapValue(cx, vp);
+  rval.set(JS::ObjectValue(*obj));
+  return (sameCompartment && IS_SLIM_WRAPPER(obj)) || JS_WrapValue(cx, rval.address());
 }
 
 // Create a JSObject wrapping "value", for cases when "value" is a
 // non-wrapper-cached object using WebIDL bindings.  "value" must implement a
 // WrapObject() method taking a JSContext and a scope.
 template <class T>
 inline bool
 WrapNewBindingNonWrapperCachedObject(JSContext* cx,
                                      JS::Handle<JSObject*> scopeArg,
-                                     T* value, JS::Value* vp)
+                                     T* value,
+                                     JS::MutableHandle<JS::Value> rval)
 {
   MOZ_ASSERT(value);
   // We try to wrap in the compartment of the underlying object of "scope"
   JS::Rooted<JSObject*> obj(cx);
   {
     // scope for the JSAutoCompartment so that we restore the compartment
     // before we call JS_WrapValue.
     Maybe<JSAutoCompartment> ac;
@@ -675,29 +677,30 @@ WrapNewBindingNonWrapperCachedObject(JSC
   }
 
   if (!obj) {
     return false;
   }
 
   // We can end up here in all sorts of compartments, per above.  Make
   // sure to JS_WrapValue!
-  *vp = JS::ObjectValue(*obj);
-  return JS_WrapValue(cx, vp);
+  rval.set(JS::ObjectValue(*obj));
+  return JS_WrapValue(cx, rval.address());
 }
 
 // Create a JSObject wrapping "value", for cases when "value" is a
 // non-wrapper-cached owned object using WebIDL bindings.  "value" must implement a
 // WrapObject() method taking a JSContext, a scope, and a boolean outparam that
 // is true if the JSObject took ownership
 template <class T>
 inline bool
 WrapNewBindingNonWrapperCachedOwnedObject(JSContext* cx,
                                           JS::Handle<JSObject*> scopeArg,
-                                          nsAutoPtr<T>& value, JS::Value* vp)
+                                          nsAutoPtr<T>& value,
+                                          JS::MutableHandle<JS::Value> rval)
 {
   // We do a runtime check on value, because otherwise we might in
   // fact end up wrapping a null and invoking methods on it later.
   if (!value) {
     NS_RUNTIMEABORT("Don't try to wrap null objects");
   }
   // We try to wrap in the compartment of the underlying object of "scope"
   JS::Rooted<JSObject*> obj(cx);
@@ -725,27 +728,28 @@ WrapNewBindingNonWrapperCachedOwnedObjec
   }
 
   if (!obj) {
     return false;
   }
 
   // We can end up here in all sorts of compartments, per above.  Make
   // sure to JS_WrapValue!
-  *vp = JS::ObjectValue(*obj);
-  return JS_WrapValue(cx, vp);
+  rval.set(JS::ObjectValue(*obj));
+  return JS_WrapValue(cx, rval.address());
 }
 
 // Helper for smart pointers (nsAutoPtr/nsRefPtr/nsCOMPtr).
 template <template <typename> class SmartPtr, typename T>
 inline bool
 WrapNewBindingNonWrapperCachedObject(JSContext* cx, JS::Handle<JSObject*> scope,
-                                     const SmartPtr<T>& value, JS::Value* vp)
+                                     const SmartPtr<T>& value,
+                                     JS::MutableHandle<JS::Value> rval)
 {
-  return WrapNewBindingNonWrapperCachedObject(cx, scope, value.get(), vp);
+  return WrapNewBindingNonWrapperCachedObject(cx, scope, value.get(), rval);
 }
 
 // Only set allowNativeWrapper to false if you really know you need it, if in
 // doubt use true. Setting it to false disables security wrappers.
 bool
 NativeInterface2JSObjectAndThrowIfFailed(JSContext* aCx,
                                          JS::Handle<JSObject*> aScope,
                                          JS::Value* aRetval,
@@ -755,57 +759,57 @@ NativeInterface2JSObjectAndThrowIfFailed
 
 /**
  * A method to handle new-binding wrap failure, by possibly falling back to
  * wrapping as a non-new-binding object.
  */
 template <class T>
 MOZ_ALWAYS_INLINE bool
 HandleNewBindingWrappingFailure(JSContext* cx, JS::Handle<JSObject*> scope,
-                                T* value, JS::Value* vp)
+                                T* value, JS::MutableHandle<JS::Value> rval)
 {
   if (JS_IsExceptionPending(cx)) {
     return false;
   }
 
   qsObjectHelper helper(value, GetWrapperCache(value));
-  return NativeInterface2JSObjectAndThrowIfFailed(cx, scope, vp, helper,
-                                                  nullptr, true);
+  return NativeInterface2JSObjectAndThrowIfFailed(cx, scope, rval.address(),
+                                                  helper, nullptr, true);
 }
 
 // Helper for calling HandleNewBindingWrappingFailure with smart pointers
 // (nsAutoPtr/nsRefPtr/nsCOMPtr) or references.
 HAS_MEMBER(get)
 
 template <class T, bool isSmartPtr=HasgetMember<T>::Value>
 struct HandleNewBindingWrappingFailureHelper
 {
   static inline bool Wrap(JSContext* cx, JS::Handle<JSObject*> scope,
-                          const T& value, JS::Value* vp)
+                          const T& value, JS::MutableHandle<JS::Value> rval)
   {
-    return HandleNewBindingWrappingFailure(cx, scope, value.get(), vp);
+    return HandleNewBindingWrappingFailure(cx, scope, value.get(), rval);
   }
 };
 
 template <class T>
 struct HandleNewBindingWrappingFailureHelper<T, false>
 {
   static inline bool Wrap(JSContext* cx, JS::Handle<JSObject*> scope, T& value,
-                          JS::Value* vp)
+                          JS::MutableHandle<JS::Value> rval)
   {
-    return HandleNewBindingWrappingFailure(cx, scope, &value, vp);
+    return HandleNewBindingWrappingFailure(cx, scope, &value, rval);
   }
 };
 
 template<class T>
 inline bool
 HandleNewBindingWrappingFailure(JSContext* cx, JS::Handle<JSObject*> scope,
-                                T& value, JS::Value* vp)
+                                T& value, JS::MutableHandle<JS::Value> rval)
 {
-  return HandleNewBindingWrappingFailureHelper<T>::Wrap(cx, scope, value, vp);
+  return HandleNewBindingWrappingFailureHelper<T>::Wrap(cx, scope, value, rval);
 }
 
 template<bool Fatal>
 inline bool
 EnumValueNotFound(JSContext* cx, const jschar* chars, size_t length,
                   const char* type)
 {
   return false;
@@ -940,108 +944,111 @@ VariantToJsval(JSContext* aCx, JS::Handl
 
 // Wrap an object "p" which is not using WebIDL bindings yet.  This _will_
 // actually work on WebIDL binding objects that are wrappercached, but will be
 // much slower than WrapNewBindingObject.  "cache" must either be null or be the
 // nsWrapperCache for "p".
 template<class T>
 inline bool
 WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, T* p,
-           nsWrapperCache* cache, const nsIID* iid, JS::Value* vp)
+           nsWrapperCache* cache, const nsIID* iid,
+           JS::MutableHandle<JS::Value> rval)
 {
-  if (xpc_FastGetCachedWrapper(cache, scope, vp))
+  if (xpc_FastGetCachedWrapper(cache, scope, rval.address()))
     return true;
   qsObjectHelper helper(p, cache);
-  return XPCOMObjectToJsval(cx, scope, helper, iid, true, vp);
+  return XPCOMObjectToJsval(cx, scope, helper, iid, true, rval.address());
 }
 
 // A specialization of the above for nsIVariant, because that needs to
 // do something different.
 template<>
 inline bool
 WrapObject<nsIVariant>(JSContext* cx, JS::Handle<JSObject*> scope, nsIVariant* p,
-                       nsWrapperCache* cache, const nsIID* iid, JS::Value* vp)
+                       nsWrapperCache* cache, const nsIID* iid,
+                       JS::MutableHandle<JS::Value> rval)
 {
   MOZ_ASSERT(iid);
   MOZ_ASSERT(iid->Equals(NS_GET_IID(nsIVariant)));
-  return VariantToJsval(cx, scope, p, vp);
+  return VariantToJsval(cx, scope, p, rval.address());
 }
 
 // Wrap an object "p" which is not using WebIDL bindings yet.  Just like the
 // variant that takes an nsWrapperCache above, but will try to auto-derive the
 // nsWrapperCache* from "p".
 template<class T>
 inline bool
 WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, T* p, const nsIID* iid,
-           JS::Value* vp)
+           JS::MutableHandle<JS::Value> rval)
 {
-  return WrapObject(cx, scope, p, GetWrapperCache(p), iid, vp);
+  return WrapObject(cx, scope, p, GetWrapperCache(p), iid, rval);
 }
 
 // Just like the WrapObject above, but without requiring you to pick which
 // interface you're wrapping as.  This should only be used for objects that have
 // classinfo, for which it doesn't matter what IID is used to wrap.
 template<class T>
 inline bool
-WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, T* p, JS::Value* vp)
+WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, T* p,
+           JS::MutableHandle<JS::Value> rval)
 {
-  return WrapObject(cx, scope, p, NULL, vp);
+  return WrapObject(cx, scope, p, NULL, rval);
 }
 
 // Helper to make it possible to wrap directly out of an nsCOMPtr
 template<class T>
 inline bool
 WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, const nsCOMPtr<T>& p,
-           const nsIID* iid, JS::Value* vp)
+           const nsIID* iid, JS::MutableHandle<JS::Value> rval)
 {
-  return WrapObject(cx, scope, p.get(), iid, vp);
+  return WrapObject(cx, scope, p.get(), iid, rval);
 }
 
 // Helper to make it possible to wrap directly out of an nsCOMPtr
 template<class T>
 inline bool
 WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, const nsCOMPtr<T>& p,
-           JS::Value* vp)
+           JS::MutableHandle<JS::Value> rval)
 {
-  return WrapObject(cx, scope, p, NULL, vp);
+  return WrapObject(cx, scope, p, NULL, rval);
 }
 
 // Helper to make it possible to wrap directly out of an nsRefPtr
 template<class T>
 inline bool
 WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, const nsRefPtr<T>& p,
-           const nsIID* iid, JS::Value* vp)
+           const nsIID* iid, JS::MutableHandle<JS::Value> rval)
 {
-  return WrapObject(cx, scope, p.get(), iid, vp);
+  return WrapObject(cx, scope, p.get(), iid, rval);
 }
 
 // Helper to make it possible to wrap directly out of an nsRefPtr
 template<class T>
 inline bool
 WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, const nsRefPtr<T>& p,
-           JS::Value* vp)
+           JS::MutableHandle<JS::Value> rval)
 {
-  return WrapObject(cx, scope, p, NULL, vp);
+  return WrapObject(cx, scope, p, NULL, rval);
 }
 
 // Specialization to make it easy to use WrapObject in codegen.
 template<>
 inline bool
 WrapObject<JSObject>(JSContext* cx, JS::Handle<JSObject*> scope, JSObject* p,
-                     JS::Value* vp)
+                     JS::MutableHandle<JS::Value> rval)
 {
-  vp->setObjectOrNull(p);
+  rval.set(JS::ObjectOrNullValue(p));
   return true;
 }
 
 inline bool
 WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, JSObject& p,
-           JS::Value* vp)
+           JS::MutableHandle<JS::Value> rval)
 {
-  vp->setObject(p);
+  rval.set(JS::ObjectValue(p));
   return true;
 }
 
 // Given an object "p" that inherits from nsISupports, wrap it and return the
 // result.  Null is returned on wrapping failure.  This is somewhat similar to
 // WrapObject() above, but does NOT allow Xrays around the result, since we
 // don't want those for our parent object.
 template<typename T>
@@ -1227,38 +1234,38 @@ WrapCallThisObject(JSContext* cx, JS::Ha
 }
 
 // Helper for calling WrapNewBindingObject with smart pointers
 // (nsAutoPtr/nsRefPtr/nsCOMPtr) or references.
 template <class T, bool isSmartPtr=HasgetMember<T>::Value>
 struct WrapNewBindingObjectHelper
 {
   static inline bool Wrap(JSContext* cx, JS::Handle<JSObject*> scope,
-                          const T& value, JS::Value* vp)
+                          const T& value, JS::MutableHandle<JS::Value> rval)
   {
-    return WrapNewBindingObject(cx, scope, value.get(), vp);
+    return WrapNewBindingObject(cx, scope, value.get(), rval);
   }
 };
 
 template <class T>
 struct WrapNewBindingObjectHelper<T, false>
 {
   static inline bool Wrap(JSContext* cx, JS::Handle<JSObject*> scope, T& value,
-                          JS::Value* vp)
+                          JS::MutableHandle<JS::Value> rval)
   {
-    return WrapNewBindingObject(cx, scope, &value, vp);
+    return WrapNewBindingObject(cx, scope, &value, rval);
   }
 };
 
 template<class T>
 inline bool
 WrapNewBindingObject(JSContext* cx, JS::Handle<JSObject*> scope, T& value,
-                     JS::Value* vp)
+                     JS::MutableHandle<JS::Value> rval)
 {
-  return WrapNewBindingObjectHelper<T>::Wrap(cx, scope, value, vp);
+  return WrapNewBindingObjectHelper<T>::Wrap(cx, scope, value, rval);
 }
 
 template <class T>
 inline JSObject*
 GetCallbackFromCallbackObject(T* aObj)
 {
   return aObj->Callback();
 }
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -102,17 +102,17 @@ DOMInterfaces = {
 'AudioContext': {
     'implicitJSContext': [ 'createBuffer' ],
     'nativeOwnership': 'refcounted',
     'resultNotAddRefed': [ 'destination', 'listener' ],
 },
 
 'AudioBufferSourceNode': {
     'implicitJSContext': [ 'buffer' ],
-    'resultNotAddRefed': [ 'gain', 'playbackRate' ],
+    'resultNotAddRefed': [ 'playbackRate' ],
 },
 
 'AudioListener' : {
     'nativeOwnership': 'refcounted'
 },
 
 'AudioNode' : {
     'concrete': False,
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1071,16 +1071,17 @@ class CGClassConstructor(CGAbstractStati
             return ""
         return CGAbstractStaticMethod.define(self)
 
     def definition_body(self):
         return self.generate_code()
 
     def generate_code(self):
         preamble = """
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   JS::Rooted<JSObject*> obj(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
 """
         name = self._ctor.identifier.name
         nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
         callGenerator = CGMethodCall(nativeName, True, self.descriptor,
                                      self._ctor, isConstructor=True)
         return preamble + callGenerator.define();
 
@@ -1120,17 +1121,17 @@ class CGConstructNavigatorObject(CGAbstr
   ErrorResult rv;
   nsRefPtr<mozilla::dom::${descriptorName}> result = ConstructNavigatorObjectHelper(aCx, global, rv);
   rv.WouldReportJSException();
   if (rv.Failed()) {
     ThrowMethodFailedWithDetails<${mainThread}>(aCx, rv, "${descriptorName}", "navigatorConstructor");
     return nullptr;
   }
   JS::Rooted<JS::Value> v(aCx);
-  if (!WrapNewBindingObject(aCx, aObj, result, v.address())) {
+  if (!WrapNewBindingObject(aCx, aObj, result, &v)) {
     MOZ_ASSERT(JS_IsExceptionPending(aCx));
     return nullptr;
   }
   return &v.toObject();""").substitute(
     {
         'descriptorName' : self.descriptor.name,
         'mainThread' : toStringBool(not self.descriptor.workers),
     })
@@ -2420,20 +2421,18 @@ class JSToNativeConversionInfo():
     """
     def __init__(self, template, declType=None, holderType=None,
                  dealWithOptional=False, declArgs=None,
                  holderArgs=None):
         """
         template: A string representing the conversion code.  This will have
                   template substitution performed on it as follows:
 
-          ${val} replaced by an expression for the JS::Value in question
-          ${valPtr} is a pointer to the JS::Value in question
-          ${valHandle} is a handle to the JS::Value in question
-          ${valMutableHandle} is a mutable handle to the JS::Value in question
+          ${val} is a handle to the JS::Value in question
+          ${mutableVal} is a mutable handle to the JS::Value in question
           ${holderName} replaced by the holder's name, if any
           ${declName} replaced by the declaration's name
           ${haveValue} replaced by an expression that evaluates to a boolean
                        for whether we have a JS::Value.  Only used when
                        defaultValue is not None or when True is passed for
                        checkForValue to instantiateJSToNativeConversion.
 
         declType: A CGThing representing the native C++ type we're converting
@@ -2452,22 +2451,22 @@ class JSToNativeConversionInfo():
                           both declType and holderType to be wrapped in
                           Optional<>, with ${declName} and ${holderName}
                           adjusted to point to the Value() of the Optional, and
                           Construct() calls to be made on the Optional<>s as
                           needed.
 
         declArgs: If not None, the arguments to pass to the ${declName}
                   constructor.  These will have template substitution performed
-                  on them so you can use things like ${valHandle}.  This is a
+                  on them so you can use things like ${val}.  This is a
                   single string, not a list of strings.
 
         holderArgs: If not None, the arguments to pass to the ${holderName}
                     constructor.  These will have template substitution
-                    performed on them so you can use things like ${valHandle}.
+                    performed on them so you can use things like ${val}.
                     This is a single string, not a list of strings.
 
         ${declName} must be in scope before the code from 'template' is entered.
 
         If holderType is not None then ${holderName} must be in scope before
         the code from 'template' is entered.
         """
         assert isinstance(template, str)
@@ -2654,17 +2653,17 @@ def getJSToNativeConversionInfo(type, de
                 declType = CGGeneric("JS::Handle<JSObject*>")
             else:
                 declType = CGGeneric("JS::Rooted<JSObject*>")
         else:
             assert (isMember == "Sequence" or isMember == "Variadic" or
                     isMember == "Dictionary")
             # We'll get traced by the sequence or dictionary tracer
             declType = CGGeneric("JSObject*")
-        templateBody = "${declName} = &${valHandle}.toObject();"
+        templateBody = "${declName} = &${val}.toObject();"
         setToNullCode = "${declName} = nullptr;"
         template = wrapObjectTemplate(templateBody, type, setToNullCode,
                                       failureCode)
         return JSToNativeConversionInfo(template, declType=declType,
                                         dealWithOptional=isOptional,
                                         declArgs="cx")
 
     assert not (isEnforceRange and isClamp) # These are mutually exclusive
@@ -2752,20 +2751,18 @@ for (uint32_t i = 0; i < length; ++i) {
        arrayRef,
        exceptionCodeIndented.define(),
        CGIndenter(exceptionCodeIndented).define(),
        elementInfo.declType.define()))
 
         templateBody += CGIndenter(CGGeneric(
                 string.Template(elementInfo.template).substitute(
                     {
-                        "val" : "temp",
-                        "valPtr": "temp.address()",
-                        "valHandle": "temp",
-                        "valMutableHandle": "&temp",
+                        "val": "temp",
+                        "mutableVal": "&temp",
                         "declName" : "slot",
                         # We only need holderName here to handle isExternal()
                         # interfaces, which use an internal holder for the
                         # conversion even when forceOwningType ends up true.
                         "holderName": "tempHolder",
                         }
                     ))).define()
 
@@ -2807,51 +2804,51 @@ for (uint32_t i = 0; i < length; ++i) {
         interfaceMemberTypes = filter(lambda t: t.isNonCallbackInterface(), memberTypes)
         if len(interfaceMemberTypes) > 0:
             interfaceObject = []
             for memberType in interfaceMemberTypes:
                 if type.isGeckoInterface():
                     name = memberType.inner.identifier.name
                 else:
                     name = memberType.name
-                interfaceObject.append(CGGeneric("(failed = !%s.TrySetTo%s(cx, ${valHandle}, ${valPtr}, tryNext)) || !tryNext" % (unionArgumentObj, name)))
+                interfaceObject.append(CGGeneric("(failed = !%s.TrySetTo%s(cx, ${val}, ${mutableVal}, tryNext)) || !tryNext" % (unionArgumentObj, name)))
                 names.append(name)
             interfaceObject = CGWrapper(CGList(interfaceObject, " ||\n"), pre="done = ", post=";\n", reindent=True)
         else:
             interfaceObject = None
 
         arrayObjectMemberTypes = filter(lambda t: t.isArray() or t.isSequence(), memberTypes)
         if len(arrayObjectMemberTypes) > 0:
             assert len(arrayObjectMemberTypes) == 1
             memberType = arrayObjectMemberTypes[0]
             name = memberType.name
-            arrayObject = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${valHandle}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
+            arrayObject = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${val}, ${mutableVal}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
             arrayObject = CGIfWrapper(arrayObject, "IsArrayLike(cx, argObj)")
             names.append(name)
         else:
             arrayObject = None
 
         dateObjectMemberTypes = filter(lambda t: t.isDate(), memberTypes)
         if len(dateObjectMemberTypes) > 0:
             assert len(dateObjectMemberTypes) == 1
             memberType = dateObjectMemberTypes[0]
             name = memberType.name
-            dateObject = CGGeneric("%s.SetTo%s(cx, ${val}, ${valPtr});\n"
+            dateObject = CGGeneric("%s.SetTo%s(cx, ${val}, ${mutableVal});\n"
                                    "done = true;" % (unionArgumentObj, name))
             dateObject = CGIfWrapper(dateObject, "JS_ObjectIsDate(cx, argObj)");
             names.append(name)
         else:
             dateObject = None
 
         callbackMemberTypes = filter(lambda t: t.isCallback() or t.isCallbackInterface(), memberTypes)
         if len(callbackMemberTypes) > 0:
             assert len(callbackMemberTypes) == 1
             memberType = callbackMemberTypes[0]
             name = memberType.name
-            callbackObject = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${valHandle}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
+            callbackObject = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${val}, ${mutableVal}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
             names.append(name)
         else:
             callbackObject = None
 
         dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes)
         if len(dictionaryMemberTypes) > 0:
             raise TypeError("No support for unwrapping dictionaries as member "
                             "of a union")
@@ -2885,32 +2882,32 @@ for (uint32_t i = 0; i < length; ++i) {
                 if templateBody:
                     templateBody = CGIfWrapper(templateBody, "!done")
                 templateBody = CGList([interfaceObject, templateBody], "\n")
             else:
                 templateBody = CGList([templateBody, object], "\n")
 
             if any([arrayObject, dateObject, callbackObject, dictionaryObject,
                     object]):
-                templateBody.prepend(CGGeneric("JS::Rooted<JSObject*> argObj(cx, &${valHandle}.toObject());"))
-            templateBody = CGIfWrapper(templateBody, "${valHandle}.isObject()")
+                templateBody.prepend(CGGeneric("JS::Rooted<JSObject*> argObj(cx, &${val}.toObject());"))
+            templateBody = CGIfWrapper(templateBody, "${val}.isObject()")
         else:
             templateBody = CGGeneric()
 
         otherMemberTypes = filter(lambda t: t.isString() or t.isEnum(),
                                   memberTypes)
         otherMemberTypes.extend(t for t in memberTypes if t.isPrimitive())
         if len(otherMemberTypes) > 0:
             assert len(otherMemberTypes) == 1
             memberType = otherMemberTypes[0]
             if memberType.isEnum():
                 name = memberType.inner.identifier.name
             else:
                 name = memberType.name
-            other = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${valHandle}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
+            other = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${val}, ${mutableVal}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
             names.append(name)
             if hasObjectTypes:
                 other = CGWrapper(CGIndenter(other), "{\n", post="\n}")
                 if object:
                     join = " else "
                 else:
                     other = CGWrapper(other, pre="if (!done) ")
                     join = "\n"
@@ -3064,17 +3061,17 @@ for (uint32_t i = 0; i < length; ++i) {
             callbackConversion = str(CallbackObjectUnwrapper(
                     descriptor,
                     "callbackObj",
                     "${declName}",
                     exceptionCode,
                     codeOnFailure=failureCode))
             templateBody += (
                 "{ // Scope for callbackObj\n"
-                "  JS::Rooted<JSObject*> callbackObj(cx, &${valHandle}.toObject());\n" +
+                "  JS::Rooted<JSObject*> callbackObj(cx, &${val}.toObject());\n" +
                 CGIndenter(CGGeneric(callbackConversion)).define() +
                 "\n}")
         elif not descriptor.skipGen and not descriptor.interface.isConsequential() and not descriptor.interface.isExternal():
             if failureCode is not None:
                 templateBody += str(CastableObjectUnwrapper(
                         descriptor,
                         "&${val}.toObject()",
                         "${declName}",
@@ -3210,17 +3207,17 @@ for (uint32_t i = 0; i < length; ++i) {
             # specified otherwise.
             if treatUndefinedAs == "Default":
                 treatUndefinedAs = "Null"
         nullBehavior = treatAs[treatNullAs]
         undefinedBehavior = treatAs[treatUndefinedAs]
 
         def getConversionCode(varName):
             conversionCode = (
-                "if (!ConvertJSValueToString(cx, ${valHandle}, ${valMutableHandle}, %s, %s, %s)) {\n"
+                "if (!ConvertJSValueToString(cx, ${val}, ${mutableVal}, %s, %s, %s)) {\n"
                 "%s\n"
                 "}" % (nullBehavior, undefinedBehavior, varName,
                        exceptionCodeIndented.define()))
             if defaultValue is None:
                 return conversionCode
 
             if isinstance(defaultValue, IDLNullValue):
                 assert(type.nullable())
@@ -3326,17 +3323,17 @@ for (uint32_t i = 0; i < length; ++i) {
         assert not type.treatNonCallableAsNull() or type.nullable()
 
         if descriptorProvider.workers:
             if isMember:
                 raise NoSuchDescriptorError("Can't handle member callbacks in "
                                             "workers; need to sort out rooting"
                                             "issues")
             declType = CGGeneric("JS::Rooted<JSObject*>")
-            conversion = "  ${declName} = &${valHandle}.toObject();\n"
+            conversion = "  ${declName} = &${val}.toObject();\n"
             declArgs = "cx"
         else:
             name = type.unroll().identifier.name
             if type.nullable():
                 declType = CGGeneric("nsRefPtr<%s>" % name);
             else:
                 declType = CGGeneric("OwningNonNull<%s>" % name)
             conversion = (
@@ -3421,27 +3418,27 @@ for (uint32_t i = 0; i < length; ++i) {
         # We do manual default value handling here, because we
         # actually do want a jsval, and we only handle null anyway
         # NOTE: if isNullOrUndefined or isDefinitelyObject are true,
         # we know we have a value, so we don't have to worry about the
         # default value.
         if (not isNullOrUndefined and not isDefinitelyObject and
             defaultValue is not None):
             assert(isinstance(defaultValue, IDLNullValue))
-            val = "(${haveValue}) ? ${valHandle} : JS::NullHandleValue"
-        else:
-            val = "${valHandle}"
+            val = "(${haveValue}) ? ${val} : JS::NullHandleValue"
+        else:
+            val = "${val}"
 
         if failureCode is not None:
             assert isDefinitelyObject
             # Check that the value we have can in fact be converted to
             # a dictionary, and return failureCode if not.
             template = CGIfWrapper(
                 CGGeneric(failureCode),
-                "!IsObjectValueConvertibleToDictionary(cx, ${valHandle})").define() + "\n\n"
+                "!IsObjectValueConvertibleToDictionary(cx, ${val})").define() + "\n\n"
         else:
             template = ""
 
         template += ("if (!${declName}.Init(cx, %s)) {\n"
                      "%s\n"
                      "}" % (val, exceptionCodeIndented.define()))
 
         # Dictionary arguments that might contain traceable things need to get
@@ -3508,27 +3505,27 @@ for (uint32_t i = 0; i < length; ++i) {
         writeLoc = "${declName}.SetValue()"
         readLoc = "${declName}.Value()"
         nullCondition = "${val}.isNullOrUndefined()"
         if defaultValue is not None and isinstance(defaultValue, IDLNullValue):
             nullCondition = "!(${haveValue}) || " + nullCondition
         template = (
             "if (%s) {\n"
             "  ${declName}.SetNull();\n"
-            "} else if (!ValueToPrimitive<%s, %s>(cx, ${valHandle}, &%s)) {\n"
+            "} else if (!ValueToPrimitive<%s, %s>(cx, ${val}, &%s)) {\n"
             "%s\n"
             "}" % (nullCondition, typeName, conversionBehavior,
                    writeLoc, exceptionCodeIndented.define()))
     else:
         assert(defaultValue is None or
                not isinstance(defaultValue, IDLNullValue))
         writeLoc = "${declName}"
         readLoc = writeLoc
         template = (
-            "if (!ValueToPrimitive<%s, %s>(cx, ${valHandle}, &%s)) {\n"
+            "if (!ValueToPrimitive<%s, %s>(cx, ${val}, &%s)) {\n"
             "%s\n"
             "}" % (typeName, conversionBehavior, writeLoc,
                    exceptionCodeIndented.define()))
         declType = CGGeneric(typeName)
 
     if type.isFloat() and not type.isUnrestricted():
         if lenientFloatCode is not None:
             nonFiniteCode = CGIndenter(CGGeneric(lenientFloatCode)).define()
@@ -3674,53 +3671,45 @@ def convertConstIDLValueToJSVal(value):
     if tag == IDLType.Tags.bool:
         return "JSVAL_TRUE" if value.value else "JSVAL_FALSE"
     if tag in [IDLType.Tags.float, IDLType.Tags.double]:
         return "DOUBLE_TO_JSVAL(%s)" % (value.value)
     raise TypeError("Const value of unhandled type: " + value.type)
 
 class CGArgumentConverter(CGThing):
     """
-    A class that takes an IDL argument object, its index in the
-    argument list, and the argv and argc strings and generates code to
-    unwrap the argument to the right native type.
-    """
-    def __init__(self, argument, index, argv, argc, descriptorProvider,
+    A class that takes an IDL argument object and its index in the
+    argument list and generates code to unwrap the argument to the
+    right native type.
+    """
+    def __init__(self, argument, index, descriptorProvider,
                  invalidEnumValueFatal=True, lenientFloatCode=None,
                  allowTreatNonCallableAsNull=False):
         CGThing.__init__(self)
         self.argument = argument
         assert(not argument.defaultValue or argument.optional)
 
         replacer = {
             "index" : index,
-            "argc" : argc,
-            "argv" : argv
+            "argc" : "args.length()"
             }
         self.replacementVariables = {
             "declName" : "arg%d" % index,
             "holderName" : ("arg%d" % index) + "_holder",
             "obj" : "obj"
             }
         self.replacementVariables["val"] = string.Template(
-            "${argv}[${index}]"
+            "args.handleAt(${index})"
             ).substitute(replacer)
-        self.replacementVariables["valPtr"] = (
-            "&" + self.replacementVariables["val"])
-        self.replacementVariables["valHandle"] = (
-            "JS::Handle<JS::Value>::fromMarkedLocation(%s)" %
-            self.replacementVariables["valPtr"])
-        self.replacementVariables["valMutableHandle"] = (
-            "JS::MutableHandle<JS::Value>::fromMarkedLocation(%s)" %
-            self.replacementVariables["valPtr"])
-        haveValueCheck = string.Template("${index} < ${argc}").substitute(replacer)
+        self.replacementVariables["mutableVal"] = self.replacementVariables["val"]
         if argument.treatUndefinedAs == "Missing":
-            haveValueCheck = (haveValueCheck +
-                              (" && !%s.isUndefined()" %
-                               self.replacementVariables["valHandle"]))
+            haveValueCheck = "args.hasDefined(${index})"
+        else:
+            haveValueCheck = "${index} < args.length()"
+        haveValueCheck = string.Template(haveValueCheck).substitute(replacer)
         self.replacementVariables["haveValue"] = haveValueCheck
         self.descriptorProvider = descriptorProvider
         if self.argument.optional and not self.argument.defaultValue:
             self.argcAndIndex = replacer
         else:
             self.argcAndIndex = None
         self.invalidEnumValueFatal = invalidEnumValueFatal
         self.lenientFloatCode = lenientFloatCode
@@ -3771,26 +3760,22 @@ class CGArgumentConverter(CGThing):
   if (!${declName}.SetCapacity(${argc} - ${index})) {
     JS_ReportOutOfMemory(cx);
     return false;
   }
   for (uint32_t variadicArg = ${index}; variadicArg < ${argc}; ++variadicArg) {
     ${elemType}& slot = *${declName}.AppendElement();
 """).substitute(replacer)
 
-        val = string.Template("${argv}[variadicArg]").substitute(replacer)
+        val = string.Template("args.handleAt(variadicArg)").substitute(replacer)
         variadicConversion += CGIndenter(CGGeneric(
                 string.Template(typeConversion.template).substitute(
                     {
                         "val" : val,
-                        "valPtr": "&" + val,
-                        "valHandle" : ("JS::Handle<JS::Value>::fromMarkedLocation(&%s)" %
-                                       val),
-                        "valMutableHandle" : ("JS::MutableHandle<JS::Value>::fromMarkedLocation(&%s)" %
-                                              val),
+                        "mutableVal" : val,
                         "declName" : "slot",
                         # We only need holderName here to handle isExternal()
                         # interfaces, which use an internal holder for the
                         # conversion even when forceOwningType ends up true.
                         "holderName": "tempHolder",
                         # Use the same ${obj} as for the variadic arg itself
                         "obj": replacer["obj"]
                         }
@@ -3809,17 +3794,26 @@ def getWrapTemplateForType(type, descrip
     Reflect a C++ value stored in "result", of IDL type "type" into JS.  The
     "successCode" is the code to run once we have successfully done the
     conversion and must guarantee that execution of the conversion template
     stops once the successCode has executed (e.g. by doing a 'return', or by
     doing a 'break' if the entire conversion template is inside a block that
     the 'break' will exit).
 
     The resulting string should be used with string.Template.  It
-    needs the following keys when substituting: jsvalPtr/jsvalRef/obj.
+    needs the following keys when substituting:
+
+      jsvalHandle: something that can be passed to methods taking a
+                   JS::MutableHandle<JS::Value>.  This can be a
+                   JS::MutableHandle<JS::Value> or a JS::Rooted<JS::Value>*.
+      jsvalRef: something that can have .address() called on it to get a
+                JS::Value* and .set() called on it to set it to a JS::Value.
+                This can be a JS::MutableHandle<JS::Value> or a
+                JS::Rooted<JS::Value>.
+      obj: a JS::Handle<JSObject*>.
 
     Returns (templateString, infallibility of conversion template)
     """
     if successCode is None:
         successCode = "return true;"
 
     # We often want exceptionCode to be indented, since it often appears in an
     # if body.
@@ -3828,21 +3822,21 @@ def getWrapTemplateForType(type, descrip
     def setValue(value, callWrapValue=False):
         """
         Returns the code to set the jsval to value. If "callWrapValue" is true
         MaybeWrapValue will be called on the jsval.
         """
         if not callWrapValue:
             tail = successCode
         else:
-            tail = ("if (!MaybeWrapValue(cx, ${jsvalPtr})) {\n" +
+            tail = ("if (!MaybeWrapValue(cx, ${jsvalHandle})) {\n" +
                     ("%s\n" % exceptionCodeIndented.define()) +
                     "}\n" +
                     successCode)
-        return ("${jsvalRef} = %s;\n" +
+        return ("${jsvalRef}.set(%s);\n" +
                 tail) % (value)
 
     def wrapAndSetPtr(wrapCall, failureCode=None):
         """
         Returns the code to set the jsval by calling "wrapCall". "failureCode"
         is the code to run if calling "wrapCall" fails 
         """
         if failureCode is None:
@@ -3879,17 +3873,17 @@ if (%s.IsNull()) {
         index = "sequenceIdx%d" % sequenceWrapLevel
         sequenceWrapLevel += 1
         innerTemplate = wrapForType(
             type.inner, descriptorProvider,
             {
                 'result' :  "%s[%s]" % (result, index),
                 'successCode': "break;",
                 'jsvalRef': "tmp",
-                'jsvalPtr': "tmp.address()",
+                'jsvalHandle': "&tmp",
                 'isCreator': isCreator,
                 'exceptionCode': exceptionCode,
                 'obj': "returnArray"
                 }
             )
         sequenceWrapLevel -= 1
         innerTemplate = CGIndenter(CGGeneric(innerTemplate), 6).define()
         return (("""
@@ -3935,45 +3929,45 @@ if (!returnArray) {
                 wrapMethod = "WrapNewBindingObject"
             else:
                 if not isCreator:
                     raise MethodNotCreatorError(descriptor.interface.identifier.name)
                 if descriptor.nativeOwnership == 'owned':
                     wrapMethod = "WrapNewBindingNonWrapperCachedOwnedObject"
                 else:
                     wrapMethod = "WrapNewBindingNonWrapperCachedObject"
-            wrap = "%s(cx, ${obj}, %s, ${jsvalPtr})" % (wrapMethod, result)
+            wrap = "%s(cx, ${obj}, %s, ${jsvalHandle})" % (wrapMethod, result)
             if not descriptor.hasXPConnectImpls:
                 # Can only fail to wrap as a new-binding object
                 # if they already threw an exception.
                 failed = ("MOZ_ASSERT(JS_IsExceptionPending(cx));\n" +
                           "%s" % exceptionCode)
             else:
                 if descriptor.notflattened:
                     raise TypeError("%s has XPConnect impls but not flattened; "
                                     "fallback won't work correctly" %
                                     descriptor.interface.identifier.name)
                 # Try old-style wrapping for bindings which might be XPConnect impls.
-                failed = wrapAndSetPtr("HandleNewBindingWrappingFailure(cx, ${obj}, %s, ${jsvalPtr})" % result)
+                failed = wrapAndSetPtr("HandleNewBindingWrappingFailure(cx, ${obj}, %s, ${jsvalHandle})" % result)
         else:
             if descriptor.notflattened:
                 getIID = "&NS_GET_IID(%s), " % descriptor.nativeType
             else:
                 getIID = ""
-            wrap = "WrapObject(cx, ${obj}, %s, %s${jsvalPtr})" % (result, getIID)
+            wrap = "WrapObject(cx, ${obj}, %s, %s${jsvalHandle})" % (result, getIID)
             failed = None
 
         wrappingCode += wrapAndSetPtr(wrap, failed)
         return (wrappingCode, False)
 
     if type.isString():
         if type.nullable():
-            return (wrapAndSetPtr("xpc::StringToJsval(cx, %s, ${jsvalPtr})" % result), False)
-        else:
-            return (wrapAndSetPtr("xpc::NonVoidStringToJsval(cx, %s, ${jsvalPtr})" % result), False)
+            return (wrapAndSetPtr("xpc::StringToJsval(cx, %s, ${jsvalRef}.address())" % result), False)
+        else:
+            return (wrapAndSetPtr("xpc::NonVoidStringToJsval(cx, %s, ${jsvalRef}.address())" % result), False)
 
     if type.isEnum():
         if type.nullable():
             resultLoc = "%s.Value()" % result
         else:
             resultLoc = result
         conversion = ("""{
   // Scope for resultStr
@@ -4032,35 +4026,35 @@ if (!returnArray) {
         return (setValue(toValue % result, True), False)
 
     if type.isUnion():
         if type.nullable():
             prefix = "%s->"
         else:
             prefix = "%s."
         return (wrapAndSetPtr((prefix % result) +
-                              "ToJSVal(cx, ${obj}, ${jsvalPtr})"), False)
+                              "ToJSVal(cx, ${obj}, ${jsvalHandle})"), False)
 
     if not (type.isPrimitive() or type.isDictionary() or type.isDate()):
         raise TypeError("Need to learn to wrap %s" % type)
 
     if type.nullable():
         (recTemplate, recInfal) = getWrapTemplateForType(type.inner, descriptorProvider,
                                                          "%s.Value()" % result, successCode,
                                                          isCreator, exceptionCode)
         return ("if (%s.IsNull()) {\n" % result +
                 CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
                 "}\n" + recTemplate, recInfal)
 
     if type.isDictionary():
-        return (wrapAndSetPtr("%s.ToObject(cx, ${obj}, ${jsvalPtr})" % result),
+        return (wrapAndSetPtr("%s.ToObject(cx, ${obj}, ${jsvalHandle})" % result),
                 False)
 
     if type.isDate():
-        return (wrapAndSetPtr("%s.ToDateObject(cx, ${jsvalPtr})" % result),
+        return (wrapAndSetPtr("%s.ToDateObject(cx, ${jsvalHandle})" % result),
                 False)
 
     tag = type.tag()
 
     if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, IDLType.Tags.int16,
                IDLType.Tags.uint16, IDLType.Tags.int32]:
         return (setValue("INT_TO_JSVAL(int32_t(%s))" % result), True)
 
@@ -4080,20 +4074,23 @@ if (!returnArray) {
     else:
         raise TypeError("Need to learn to wrap primitive: %s" % type)
 
 def wrapForType(type, descriptorProvider, templateValues):
     """
     Reflect a C++ value of IDL type "type" into JS.  TemplateValues is a dict
     that should contain:
 
-      * 'jsvalRef': a C++ reference to the jsval in which to store the result of
-                    the conversion
-      * 'jsvalPtr': a C++ pointer to the jsval in which to store the result of
-                    the conversion
+      * 'jsvalRef': something that can have .address() called on it to get a
+                    JS::Value* and .set() called on it to set it to a JS::Value.
+                    This can be a JS::MutableHandle<JS::Value> or a
+                    JS::Rooted<JS::Value>.
+      * 'jsvalHandle': something that can be passed to methods taking a
+                       JS::MutableHandle<JS::Value>.  This can be a
+                       JS::MutableHandle<JS::Value> or a JS::Rooted<JS::Value>*.
       * 'obj' (optional): the name of the variable that contains the JSObject to
                           use as a scope when wrapping, if not supplied 'obj'
                           will be used as the name
       * 'result' (optional): the name of the variable in which the C++ value is
                              stored, if not supplied 'result' will be used as
                              the name
       * 'successCode' (optional): the code to run once we have successfully
                                   done the conversion, if not supplied 'return
@@ -4486,27 +4483,23 @@ class CGPerSignatureCall(CGThing):
         self.returnType = returnType
         self.descriptor = descriptor
         self.idlNode = idlNode
         self.extendedAttributes = descriptor.getExtendedAttributes(idlNode,
                                                                    getter=getter,
                                                                    setter=setter)
         self.arguments = arguments
         self.argCount = len(arguments)
-        if self.argCount > argConversionStartsAt:
-            # Insert our argv in there
-            cgThings = [CGGeneric(self.getArgvDecl())]
-        else:
-            cgThings = []
+        cgThings = []
         lenientFloatCode = None
         if idlNode.getExtendedAttribute('LenientFloat') is not None:
             if setter:
                 lenientFloatCode = "return true;"
             elif idlNode.isMethod():
-                lenientFloatCode = ("*vp = JSVAL_VOID;\n"
+                lenientFloatCode = ("args.rval().set(JSVAL_VOID);\n"
                                     "return true;")
 
         argsPre = []
         if static:
             nativeMethodName = "%s::%s" % (descriptor.nativeType,
                                            nativeMethodName)
             globalObjectType = "GlobalObject"
             if descriptor.workers:
@@ -4529,18 +4522,17 @@ if (global.Failed()) {
         if idlNode.isMethod() and idlNode.isLegacycaller():
             # If we can have legacycaller with identifier, we can't
             # just use the idlNode to determine whether we're
             # generating code for the legacycaller or not.
             assert idlNode.isIdentifierLess()
             # Pass in our thisVal
             argsPre.append("args.thisv()")
 
-        cgThings.extend([CGArgumentConverter(arguments[i], i, self.getArgv(),
-                                             self.getArgc(), self.descriptor,
+        cgThings.extend([CGArgumentConverter(arguments[i], i, self.descriptor,
                                              invalidEnumValueFatal=not setter,
                                              allowTreatNonCallableAsNull=setter,
                                              lenientFloatCode=lenientFloatCode) for
                          i in range(argConversionStartsAt, self.argCount)])
 
         if isConstructor:
             # If we're called via an xray, we need to enter the underlying
             # object's compartment and then wrap up all of our arguments into
@@ -4567,22 +4559,16 @@ if (global.Failed()) {
 
         cgThings.append(CGCallGenerator(
                     self.getErrorReport() if self.isFallible() else None,
                     self.getArguments(), argsPre, returnType,
                     self.extendedAttributes, descriptor, nativeMethodName,
                     static))
         self.cgRoot = CGList(cgThings, "\n")
 
-    def getArgv(self):
-        return "argv" if self.argCount > 0 else ""
-    def getArgvDecl(self):
-        return "\nJS::Value* argv = JS_ARGV(cx, vp);\n"
-    def getArgc(self):
-        return "argc"
     def getArguments(self):
         return [(a, "arg" + str(i)) for (i, a) in enumerate(self.arguments)]
 
     def isFallible(self):
         return not 'infallible' in self.extendedAttributes
 
     def wrap_return_value(self):
         isCreator = memberIsCreator(self.idlNode)
@@ -4592,17 +4578,18 @@ if (global.Failed()) {
                                            self.extendedAttributes) or
                    # Creators can return raw pointers to owned objects
                    (self.returnType.isGeckoInterface() and
                     self.descriptor.getDescriptor(self.returnType.unroll().inner.identifier.name).nativeOwnership == 'owned') or
                    # Workers use raw pointers for new-object return
                    # values or something
                    self.descriptor.workers)
 
-        resultTemplateValues = { 'jsvalRef': '*vp', 'jsvalPtr': 'vp',
+        resultTemplateValues = { 'jsvalRef': 'args.rval()',
+                                 'jsvalHandle': 'args.rval()',
                                  'isCreator': isCreator}
         try:
             return wrapForType(self.returnType, self.descriptor,
                                resultTemplateValues)
         except MethodNotCreatorError, err:
             assert not isCreator
             raise TypeError("%s being returned from non-creator method or property %s.%s" %
                             (err.typename,
@@ -4699,17 +4686,17 @@ class CGMethodCall(CGThing):
             # on anything.
             signature = signatures[0]
             self.cgRoot = CGList([ CGIndenter(getPerSignatureCall(signature)) ])
             requiredArgs = requiredArgCount(signature)
 
 
             if requiredArgs > 0:
                 code = (
-                    "if (argc < %d) {\n"
+                    "if (args.length() < %d) {\n"
                     "  return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, %s);\n"
                     "}" % (requiredArgs, methodName))
                 self.cgRoot.prepend(
                     CGWrapper(CGIndenter(CGGeneric(code)), pre="\n", post="\n"))
             return
 
         # We don't handle [TreatUndefinedAs=Missing] arguments in overload
         # resolution yet.
@@ -4787,24 +4774,22 @@ class CGMethodCall(CGThing):
                     raise TypeError("No support for variadics as distinguishing "
                                     "arguments yet: %s" %
                                     distinguishingArgument(sig).location)
 
             # Convert all our arguments up to the distinguishing index.
             # Doesn't matter which of the possible signatures we use, since
             # they all have the same types up to that point; just use
             # possibleSignatures[0]
-            caseBody = [CGGeneric("JS::Value* argv_start = JS_ARGV(cx, vp);")]
-            caseBody.extend([ CGArgumentConverter(possibleSignatures[0][1][i],
-                                                  i, "argv_start", "argc",
-                                                  descriptor) for i in
-                              range(0, distinguishingIndex) ])
+            caseBody = [ CGArgumentConverter(possibleSignatures[0][1][i],
+                                             i, descriptor) for i in
+                         range(0, distinguishingIndex) ]
 
             # Select the right overload from our set.
-            distinguishingArg = "argv_start[%d]" % distinguishingIndex
+            distinguishingArg = "args.handleAt(%d)" % distinguishingIndex
 
             def pickFirstSignature(condition, filterLambda):
                 sigs = filter(filterLambda, possibleSignatures)
                 assert len(sigs) < 2
                 if len(sigs) > 0:
                     if condition is None:
                         caseBody.append(
                             getPerSignatureCall(sigs[0], distinguishingIndex))
@@ -4832,20 +4817,17 @@ class CGMethodCall(CGThing):
                     getJSToNativeConversionInfo(type, descriptor,
                                                 failureCode=failureCode,
                                                 isDefinitelyObject=isDefinitelyObject,
                                                 isNullOrUndefined=isNullOrUndefined),
                     {
                         "declName" : "arg%d" % distinguishingIndex,
                         "holderName" : ("arg%d" % distinguishingIndex) + "_holder",
                         "val" : distinguishingArg,
-                        "valHandle" : ("JS::Handle<JS::Value>::fromMarkedLocation(&%s)" %
-                                       distinguishingArg),
-                        "valMutableHandle" : ("JS::MutableHandle<JS::Value>::fromMarkedLocation(&%s)" %
-                                       distinguishingArg),
+                        "mutableVal" : distinguishingArg,
                         "obj" : "obj"
                         })
                 caseBody.append(CGIndenter(testCode, indent));
                 # If we got this far, we know we unwrapped to the right
                 # C++ type, so just do the call.  Start conversion with
                 # distinguishingIndex + 1, since we already converted
                 # distinguishingIndex.
                 caseBody.append(CGIndenter(
@@ -4962,17 +4944,17 @@ class CGMethodCall(CGThing):
                   'return ThrowErrorMessage(cx, MSG_INVALID_ARG, "%s", "%s");'
                   % (str(distinguishingIndex), str(argCount))))
 
             argCountCases.append(CGCase(str(argCount),
                                         CGList(caseBody, "\n")))
 
         overloadCGThings = []
         overloadCGThings.append(
-            CGGeneric("unsigned argcount = std::min(argc, %du);" %
+            CGGeneric("unsigned argcount = std::min(args.length(), %du);" %
                       maxArgCount))
         overloadCGThings.append(
             CGSwitch("argcount",
                      argCountCases,
                      CGGeneric("return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, %s);\n" % methodName)))
         overloadCGThings.append(
             CGGeneric('MOZ_NOT_REACHED("We have an always-returning default case");\n'
                       'return false;'))
@@ -5018,32 +5000,27 @@ class CGSetterCall(CGPerSignatureCall):
     """
     def __init__(self, argType, nativeMethodName, descriptor, attr):
         CGPerSignatureCall.__init__(self, None, [FakeArgument(argType, attr)],
                                     nativeMethodName, attr.isStatic(),
                                     descriptor, attr, setter=True)
     def wrap_return_value(self):
         # We have no return value
         return "\nreturn true;"
-    def getArgc(self):
-        return "1"
-    def getArgvDecl(self):
-        # We just get our stuff from our last arg no matter what
-        return ""
 
 class CGAbstractBindingMethod(CGAbstractStaticMethod):
     """
     Common class to generate the JSNatives for all our methods, getters, and
     setters.  This will generate the function declaration and unwrap the
     |this| object.  Subclasses are expected to override the generate_code
     function to do the rest of the work.  This function should return a
     CGThing which is already properly indented.
     """
     def __init__(self, descriptor, name, args, unwrapFailureCode=None,
-                 getThisObj="&args.computeThis(cx).toObject()",
+                 getThisObj="args.computeThis(cx).toObjectOrNull()",
                  callArgs="JS::CallArgs args = JS::CallArgsFromVp(argc, vp);"):
         CGAbstractStaticMethod.__init__(self, descriptor, name, "JSBool", args)
 
         if unwrapFailureCode is None:
             self.unwrapFailureCode = 'return ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "%s");' % self.descriptor.name
         else:
             self.unwrapFailureCode = unwrapFailureCode
         self.getThisObj = getThisObj
@@ -5074,25 +5051,27 @@ if (!obj) {
 class CGAbstractStaticBindingMethod(CGAbstractStaticMethod):
     """
     Common class to generate the JSNatives for all our static methods, getters
     and setters.  This will generate the function declaration and unwrap the
     global object.  Subclasses are expected to override the generate_code
     function to do the rest of the work.  This function should return a
     CGThing which is already properly indented.
     """
-    def __init__(self, descriptor, name, args):
+    def __init__(self, descriptor, name):
+        args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
+                Argument('JS::Value*', 'vp')]
         CGAbstractStaticMethod.__init__(self, descriptor, name, "JSBool", args)
 
     def definition_body(self):
-        unwrap = CGGeneric("""JS::RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
+        unwrap = CGGeneric("""JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+JS::RootedObject obj(cx, args.computeThis(cx).toObjectOrNull());
 if (!obj) {
   return false;
-}
-""")
+}""")
         return CGList([ CGIndenter(unwrap),
                         self.generate_code() ], "\n\n").define()
 
     def generate_code(self):
         assert(False) # Override me
 
 def MakeNativeName(name):
     return name[0].upper() + name[1:]
@@ -5106,29 +5085,29 @@ class CGGenericMethod(CGAbstractBindingM
                 Argument('JS::Value*', 'vp')]
         CGAbstractBindingMethod.__init__(self, descriptor, 'genericMethod', args)
 
     def generate_code(self):
         return CGIndenter(CGGeneric(
             "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
             "MOZ_ASSERT(info->type == JSJitInfo::Method);\n"
             "JSJitMethodOp method = info->method;\n"
-            "return method(cx, obj, self, argc, vp);"))
+            "return method(cx, obj, self, JSJitMethodCallArgs(args));"))
 
 class CGSpecializedMethod(CGAbstractStaticMethod):
     """
     A class for generating the C++ code for a specialized method that the JIT
     can call with lower overhead.
     """
     def __init__(self, descriptor, method):
         self.method = method
         name = CppKeywords.checkMethodName(method.identifier.name)
         args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
                 Argument('%s*' % descriptor.nativeType, 'self'),
-                Argument('unsigned', 'argc'), Argument('JS::Value*', 'vp')]
+                Argument('const JSJitMethodCallArgs&', 'args')]
         CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', args)
 
     def definition_body(self):
         nativeName = CGSpecializedMethod.makeNativeName(self.descriptor,
                                                         self.method)
         return CGMethodCall(nativeName, self.method.isStatic(), self.descriptor,
                             self.method).define()
 
@@ -5206,19 +5185,17 @@ class CppKeywords():
 
 class CGStaticMethod(CGAbstractStaticBindingMethod):
     """
     A class for generating the C++ code for an IDL static method.
     """
     def __init__(self, descriptor, method):
         self.method = method
         name = method.identifier.name
-        args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
-                Argument('JS::Value*', 'vp')]
-        CGAbstractStaticBindingMethod.__init__(self, descriptor, name, args)
+        CGAbstractStaticBindingMethod.__init__(self, descriptor, name)
 
     def generate_code(self):
         nativeName = CGSpecializedMethod.makeNativeName(self.descriptor,
                                                         self.method)
         return CGMethodCall(nativeName, True, self.descriptor, self.method)
 
 class CGGenericGetter(CGAbstractBindingMethod):
     """
@@ -5229,43 +5206,43 @@ class CGGenericGetter(CGAbstractBindingM
                 Argument('JS::Value*', 'vp')]
         if lenientThis:
             name = "genericLenientGetter"
             unwrapFailureCode = (
                 "MOZ_ASSERT(!JS_IsExceptionPending(cx));\n"
                 "if (!ReportLenientThisUnwrappingFailure(cx, obj)) {\n"
                 "  return false;\n"
                 "}\n"
-                "JS_SET_RVAL(cx, vp, JS::UndefinedValue());\n"
+                "args.rval().set(JS::UndefinedValue());\n"
                 "return true;")
         else:
             name = "genericGetter"
             unwrapFailureCode = None
         CGAbstractBindingMethod.__init__(self, descriptor, name, args,
                                          unwrapFailureCode)
 
     def generate_code(self):
         return CGIndenter(CGGeneric(
             "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
             "MOZ_ASSERT(info->type == JSJitInfo::Getter);\n"
             "JSJitGetterOp getter = info->getter;\n"
-            "return getter(cx, obj, self, vp);"))
+            "return getter(cx, obj, self, JSJitGetterCallArgs(args));"))
 
 class CGSpecializedGetter(CGAbstractStaticMethod):
     """
     A class for generating the code for a specialized attribute getter
     that the JIT can call with lower overhead.
     """
     def __init__(self, descriptor, attr):
         self.attr = attr
         name = 'get_' + attr.identifier.name
         args = [ Argument('JSContext*', 'cx'),
                  Argument('JSHandleObject', 'obj'),
                  Argument('%s*' % descriptor.nativeType, 'self'),
-                 Argument('JS::Value*', 'vp') ]
+                 Argument('JSJitGetterCallArgs', 'args') ]
         CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args)
 
     def definition_body(self):
         nativeName = CGSpecializedGetter.makeNativeName(self.descriptor,
                                                         self.attr)
         return CGIndenter(CGGetterCall(self.attr.type, nativeName,
                                        self.descriptor, self.attr)).define()
 
@@ -5285,19 +5262,17 @@ class CGSpecializedGetter(CGAbstractStat
 
 class CGStaticGetter(CGAbstractStaticBindingMethod):
     """
     A class for generating the C++ code for an IDL static attribute getter.
     """
     def __init__(self, descriptor, attr):
         self.attr = attr
         name = 'get_' + attr.identifier.name
-        args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
-                Argument('JS::Value*', 'vp')]
-        CGAbstractStaticBindingMethod.__init__(self, descriptor, name, args)
+        CGAbstractStaticBindingMethod.__init__(self, descriptor, name)
 
     def generate_code(self):
         nativeName = CGSpecializedGetter.makeNativeName(self.descriptor,
                                                         self.attr)
         return CGIndenter(CGGetterCall(self.attr.type, nativeName,
                                        self.descriptor, self.attr))
 
 class CGGenericSetter(CGAbstractBindingMethod):
@@ -5309,51 +5284,50 @@ class CGGenericSetter(CGAbstractBindingM
                 Argument('JS::Value*', 'vp')]
         if lenientThis:
             name = "genericLenientSetter"
             unwrapFailureCode = (
                 "MOZ_ASSERT(!JS_IsExceptionPending(cx));\n"
                 "if (!ReportLenientThisUnwrappingFailure(cx, obj)) {\n"
                 "  return false;\n"
                 "}\n"
-                "JS_SET_RVAL(cx, vp, JS::UndefinedValue());\n"
+                "args.rval().set(JS::UndefinedValue());\n"
                 "return true;")
         else:
             name = "genericSetter"
             unwrapFailureCode = None
         CGAbstractBindingMethod.__init__(self, descriptor, name, args,
                                          unwrapFailureCode)
 
     def generate_code(self):
         return CGIndenter(CGGeneric(
-                "if (argc == 0) {\n"
+                "if (args.length() == 0) {\n"
                 '  return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "%s attribute setter");\n'
                 "}\n"
-                "JS::Value* argv = JS_ARGV(cx, vp);\n"
                 "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
                 "MOZ_ASSERT(info->type == JSJitInfo::Setter);\n"
                 "JSJitSetterOp setter = info->setter;\n"
-                "if (!setter(cx, obj, self, argv)) {\n"
+                "if (!setter(cx, obj, self, JSJitSetterCallArgs(args))) {\n"
                 "  return false;\n"
                 "}\n"
-                "*vp = JSVAL_VOID;\n"
+                "args.rval().set(JSVAL_VOID);\n"
                 "return true;" % self.descriptor.interface.identifier.name))
 
 class CGSpecializedSetter(CGAbstractStaticMethod):
     """
     A class for generating the code for a specialized attribute setter
     that the JIT can call with lower overhead.
     """
     def __init__(self, descriptor, attr):
         self.attr = attr
         name = 'set_' + attr.identifier.name
         args = [ Argument('JSContext*', 'cx'),
                  Argument('JSHandleObject', 'obj'),
                  Argument('%s*' % descriptor.nativeType, 'self'),
-                 Argument('JS::Value*', 'argv')]
+                 Argument('JSJitSetterCallArgs', 'args')]
         CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args)
 
     def definition_body(self):
         nativeName = CGSpecializedSetter.makeNativeName(self.descriptor,
                                                         self.attr)
         return CGIndenter(CGSetterCall(self.attr.type, nativeName,
                                        self.descriptor, self.attr)).define()
 
@@ -5364,31 +5338,27 @@ class CGSpecializedSetter(CGAbstractStat
 
 class CGStaticSetter(CGAbstractStaticBindingMethod):
     """
     A class for generating the C++ code for an IDL static attribute setter.
     """
     def __init__(self, descriptor, attr):
         self.attr = attr
         name = 'set_' + attr.identifier.name
-        args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
-                Argument('JS::Value*', 'vp')]
-        CGAbstractStaticBindingMethod.__init__(self, descriptor, name, args)
+        CGAbstractStaticBindingMethod.__init__(self, descriptor, name)
 
     def generate_code(self):
         nativeName = CGSpecializedSetter.makeNativeName(self.descriptor,
                                                         self.attr)
-        argv = CGGeneric("""JS::Value* argv = JS_ARGV(cx, vp);
-JS::Rooted<JS::Value> undef(cx, JS::UndefinedValue());
-if (argc == 0) {
-  argv = undef.address();
-}""")
+        checkForArg = CGGeneric("""if (args.length() == 0) {
+  return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "%s setter");
+}""" % self.attr.identifier.name)
         call = CGSetterCall(self.attr.type, nativeName, self.descriptor,
                             self.attr)
-        return CGIndenter(CGList([ argv, call ], "\n"))
+        return CGIndenter(CGList([ checkForArg, call ], "\n"))
 
 class CGSpecializedForwardingSetter(CGSpecializedSetter):
     """
     A class for generating the code for a specialized attribute setter with
     PutForwards that the JIT can call with lower overhead.
     """
     def __init__(self, descriptor, attr):
         CGSpecializedSetter.__init__(self, descriptor, attr)
@@ -5403,17 +5373,17 @@ class CGSpecializedForwardingSetter(CGSp
 if (!JS_GetProperty(cx, obj, "%s", v.address())) {
   return false;
 }
 
 if (!v.isObject()) {
   return ThrowErrorMessage(cx, MSG_NOT_OBJECT);
 }
 
-return JS_SetProperty(cx, &v.toObject(), "%s", argv);""" % (attrName, forwardToAttrName))).define()
+return JS_SetProperty(cx, &v.toObject(), "%s", args.handleAt(0).address());""" % (attrName, forwardToAttrName))).define()
 
 def memberIsCreator(member):
     return member.getExtendedAttribute("Creator") is not None
 
 class CGMemberJITInfo(CGThing):
     """
     A class for generating the JITInfo for a property that points to
     our specialized getter and setter.
@@ -5758,28 +5728,26 @@ return true;"""
                            "{\n"
                            "  mUnion.mValue.mObject.SetValue(cx, obj);\n"
                            "  mUnion.mType = mUnion.eObject;\n"
                            "}")
     else:
         jsConversion = string.Template(conversionInfo.template).substitute(
             {
                 "val": "value",
-                "valHandle": "value",
-                "valMutableHandle": "JS::MutableHandle<JS::Value>::fromMarkedLocation(pvalue)",
-                "valPtr": "pvalue",
+                "mutableVal": "pvalue",
                 "declName": "SetAs" + name + "()",
                 "holderName": "m" + name + "Holder",
                 }
             )
         jsConversion = CGWrapper(CGGeneric(jsConversion),
                                  post="\n"
                                       "return true;")
         setter = CGWrapper(CGIndenter(jsConversion),
-                           pre="bool TrySetTo" + name + "(JSContext* cx, JS::Handle<JS::Value> value, JS::Value* pvalue, bool& tryNext)\n"
+                           pre="bool TrySetTo" + name + "(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)\n"
                                "{\n"
                                "  tryNext = false;\n",
                            post="\n"
                                 "}")
 
     return {
                 "name": name,
                 "structType": structType,
@@ -5860,17 +5828,18 @@ public:
 ${callDestructors}
       case eUninitialized:
         break;
     }
   }
 
 ${methods}
 
-  bool ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::Value* vp) const;
+  bool ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj,
+               JS::MutableHandle<JS::Value> rval) const;
 
 private:
   friend class ${structName}Argument;
 
 ${destructors}
 
   enum Type {
     eUninitialized,
@@ -5895,25 +5864,26 @@ private:
        })
 
     def define(self):
         templateVars = self.templateVars
         conversionsToJS = []
         if self.type.hasNullableType:
             conversionsToJS.append("    case eNull:\n"
                                    "    {\n"
-                                   "      *vp = JS::NullValue();\n"
+                                   "      rval.set(JS::NullValue());\n"
                                    "      return true;\n"
                                    "    }")
         conversionsToJS.extend(
             map(self.getConversionToJS,
                 zip(templateVars, self.type.flatMemberTypes)))
 
         return string.Template("""bool
-${structName}::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::Value* vp) const
+${structName}::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj,
+                       JS::MutableHandle<JS::Value> rval) const
 {
   switch (mType) {
 ${doConversionsToJS}
 
     case eUninitialized:
     {
       break;
     }
@@ -5932,18 +5902,18 @@ private:
         if type.isSpiderMonkeyInterface():
             # We have a NonNull<TypedArray> object while the wrapping code
             # wants a JSObject*.  Cheat with .get() so we don't have to
             # figure out the right reference type to cast to.
             val = "%s.get()->Obj()" % val
         wrapCode = wrapForType(
             type, self.descriptorProvider,
             {
-                "jsvalRef": "*vp",
-                "jsvalPtr": "vp",
+                "jsvalRef": "rval",
+                "jsvalHandle": "rval",
                 "obj": "scopeObj",
                 "result": val,
                 "objectCanBeNonNull": True
                 })
         return CGIndenter(CGList([CGGeneric("case e%(name)s:" % templateVars),
                                   CGWrapper(CGIndenter(CGGeneric(wrapCode)),
                                             pre="{\n",
                                             post="\n}")],
@@ -6617,20 +6587,18 @@ class CGProxySpecialOperation(CGPerSigna
             # arguments[0] is the index or name of the item that we're setting.
             argument = arguments[1]
             info = getJSToNativeConversionInfo(argument.type, descriptor,
                                                treatNullAs=argument.treatNullAs,
                                                treatUndefinedAs=argument.treatUndefinedAs)
             templateValues = {
                 "declName": argument.identifier.name,
                 "holderName": argument.identifier.name + "_holder",
-                "val": "desc->value",
-                "valPtr": "&desc->value",
-                "valHandle" : "JS::Handle<JS::Value>::fromMarkedLocation(&desc->value)",
-                "valMutableHandle" : "JS::MutableHandle<JS::Value>::fromMarkedLocation(&desc->value)",
+                "val" : "JS::Handle<JS::Value>::fromMarkedLocation(&desc->value)",
+                "mutableVal" : "JS::MutableHandle<JS::Value>::fromMarkedLocation(&desc->value)",
                 "obj": "obj"
             }
             self.cgRoot.prepend(instantiateJSToNativeConversion(info, templateValues))
         elif operation.isGetter() or operation.isDeleter():
             self.cgRoot.prepend(CGGeneric("bool found;"))
 
     def getArguments(self):
         args = [(a, a.identifier.name) for a in self.arguments]
@@ -6696,31 +6664,56 @@ class CGProxyNamedOperation(CGProxySpeci
     """
     Class to generate a call to a named operation.
 
     'value' is the jsval to use for the name; None indicates that it should be
     gotten from the property id.
     """
     def __init__(self, descriptor, name, value=None):
         CGProxySpecialOperation.__init__(self, descriptor, name)
-        if value is None:
-            value = "js::IdToValue(id)"
         self.value = value
     def define(self):
         # Our first argument is the id we're getting.
         argName = self.arguments[0].identifier.name
-        return (("JS::Rooted<JS::Value> nameVal(cx, %s);\n"
-                 "FakeDependentString %s;\n"
-                 "if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n"
-                 "                            eStringify, eStringify, %s)) {\n"
-                 "  return false;\n"
-                 "}\n"
+        if argName == "id":
+            # deal with the name collision
+            idDecl = "JS::Rooted<jsid> id_(cx, id);\n"
+            idName = "id_"
+        else:
+            idDecl = ""
+            idName = "id"
+        unwrapString = (
+            "if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n"
+            "                            eStringify, eStringify, %s)) {\n"
+            "  return false;\n"
+            "}" % argName)
+        if self.value is None:
+            # We're just using 'id', and if it's an atom we can take a
+            # fast path here.
+            unwrapString = CGIfElseWrapper(
+                ("MOZ_LIKELY(JSID_IS_ATOM(%s))" % idName),
+                CGGeneric(
+                    "%s.SetData(js::GetAtomChars(JSID_TO_ATOM(%s)), js::GetAtomLength(JSID_TO_ATOM(%s)));" % (argName, idName, idName)),
+                CGGeneric(("nameVal = js::IdToValue(%s);\n" % idName) +
+                          unwrapString)).define()
+        else:
+            unwrapString = ("nameVal = %s;\n" % self.value) + unwrapString
+
+        # Sadly, we have to set up nameVal even if we have an atom id,
+        # because we don't know for sure, and we can end up needing it
+        # so it needs to be higher up the stack.  Using a Maybe here
+        # seems like probable overkill.
+        return ("JS::Rooted<JS::Value> nameVal(cx);\n" +
+                idDecl +
+                ("FakeDependentString %s;\n" % argName) +
+                unwrapString +
+                ("\n"
                  "\n"
                  "%s* self = UnwrapProxy(proxy);\n" %
-                 (self.value, argName, argName, self.descriptor.nativeType)) +
+                 self.descriptor.nativeType) +
                 CGProxySpecialOperation.define(self))
 
 class CGProxyNamedGetter(CGProxyNamedOperation):
     """
     Class to generate a call to an named getter. If templateValues is not None
     the returned value will be wrapped with wrapForType using templateValues.
     'value' is the jsval to use for the name; None indicates that it should be
     gotten from the property id.
@@ -6812,17 +6805,18 @@ class CGDOMJSProxyHandler_getOwnProperty
         indexedGetter = self.descriptor.operations['IndexedGetter']
         indexedSetter = self.descriptor.operations['IndexedSetter']
 
         setOrIndexedGet = "bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);\n"
         if self.descriptor.supportsIndexedProperties():
             setOrIndexedGet += "int32_t index = GetArrayIndexFromId(cx, id);\n"
             readonly = toStringBool(indexedSetter is None)
             fillDescriptor = "FillPropertyDescriptor(desc, proxy, %s);\nreturn true;" % readonly
-            templateValues = {'jsvalRef': 'desc->value', 'jsvalPtr': '&desc->value',
+            templateValues = {'jsvalRef': 'JS::MutableHandle<JS::Value>::fromMarkedLocation(&desc->value)',
+                              'jsvalHandle': 'JS::MutableHandle<JS::Value>::fromMarkedLocation(&desc->value)',
                               'obj': 'proxy', 'successCode': fillDescriptor}
             get = ("if (IsArrayIndex(index)) {\n" +
                    CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define() + "\n" +
                    "}\n") % (self.descriptor.nativeType)
 
         if UseHolderForUnforgeable(self.descriptor):
             getUnforgeable = """if (!JS_GetPropertyDescriptorById(cx, ${holder}, id, flags, desc)) {
   return false;
@@ -6879,17 +6873,18 @@ MOZ_ASSERT_IF(desc->obj, desc->obj == ${
                 setOrIndexedGet += ("if (!(flags & JSRESOLVE_ASSIGNING)) {\n" +
                                     CGIndenter(CGGeneric(get)).define() +
                                     "}\n\n")
             setOrIndexedGet += getUnforgeable
 
         if self.descriptor.supportsNamedProperties():
             readonly = toStringBool(self.descriptor.operations['NamedSetter'] is None)
             fillDescriptor = "FillPropertyDescriptor(desc, proxy, %s);\nreturn true;" % readonly
-            templateValues = {'jsvalRef': 'desc->value', 'jsvalPtr': '&desc->value',
+            templateValues = {'jsvalRef': 'JS::MutableHandle<JS::Value>::fromMarkedLocation(&desc->value)',
+                              'jsvalHandle': 'JS::MutableHandle<JS::Value>::fromMarkedLocation(&desc->value)',
                               'obj': 'proxy', 'successCode': fillDescriptor}
             condition = "!HasPropertyOnPrototype(cx, proxy, this, id)"
             if self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
                 condition = "(!isXray || %s)" % condition
             condition = "!(flags & JSRESOLVE_ASSIGNING) && " + condition
             if self.descriptor.supportsIndexedProperties():
                 condition = "!IsArrayIndex(index) && " + condition
             namedGet = ("\n" +
@@ -7210,17 +7205,17 @@ if (expando) {
     return false;
   }
 
   if (hasProp) {
     return JS_GetPropertyById(cx, expando, id, vp.address());
   }
 }"""
 
-        templateValues = {'jsvalRef': '*vp.address()', 'jsvalPtr': 'vp.address()', 'obj': 'proxy'}
+        templateValues = {'jsvalRef': 'vp', 'jsvalHandle': 'vp', 'obj': 'proxy'}
 
         if self.descriptor.supportsIndexedProperties():
             getIndexedOrExpando = ("int32_t index = GetArrayIndexFromId(cx, id);\n" +
                                    "if (IsArrayIndex(index)) {\n" +
                                    CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define()) % (self.descriptor.nativeType)
             getIndexedOrExpando += """
   // Even if we don't have this index, we don't forward the
   // get on to our expando object.
@@ -7295,17 +7290,17 @@ class CGDOMJSProxyHandler_getElementIfPr
                 Argument('uint32_t', 'index'),
                 Argument('JS::MutableHandle<JS::Value>', 'vp'),
                 Argument('bool*', 'present')]
         ClassMethod.__init__(self, "getElementIfPresent", "bool", args)
         self.descriptor = descriptor
     def getBody(self):
         successCode = ("*present = found;\n"
                        "return true;")
-        templateValues = {'jsvalRef': '*vp.address()', 'jsvalPtr': 'vp.address()',
+        templateValues = {'jsvalRef': 'vp', 'jsvalHandle': 'vp',
                           'obj': 'proxy', 'successCode': successCode}
         if self.descriptor.supportsIndexedProperties():
             get = (CGProxyIndexedGetter(self.descriptor, templateValues).define() + "\n"
                    "// We skip the expando object and any named getters if\n"
                    "// there is an indexed getter.\n" +
                    "\n") % (self.descriptor.nativeType)
         else:
             if self.descriptor.supportsNamedProperties():
@@ -7690,38 +7685,38 @@ class CGDictionary(CGThing):
             body += (
                 "if (!initedIds && !InitIds(cx)) {\n"
                 "  return false;\n"
                 "}\n")
 
         if self.dictionary.parent:
             body += (
                 "// Per spec, we define the parent's members first\n"
-                "if (!%s::ToObject(cx, parentObject, vp)) {\n"
+                "if (!%s::ToObject(cx, parentObject, rval)) {\n"
                 "  return false;\n"
                 "}\n"
-                "JS::Rooted<JSObject*> obj(cx, &vp->toObject());\n"
+                "JS::Rooted<JSObject*> obj(cx, &rval.toObject());\n"
                 "\n") % self.makeClassName(self.dictionary.parent)
         else:
             body += (
                 "JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, nullptr, nullptr, nullptr));\n"
                 "if (!obj) {\n"
                 "  return false;\n"
                 "}\n"
-                "*vp = JS::ObjectValue(*obj);\n"
+                "rval.set(JS::ObjectValue(*obj));\n"
                 "\n")
 
         body += "\n\n".join(self.getMemberDefinition(m).define()
                             for m in self.memberInfo)
         body += "\n\nreturn true;"
 
         return ClassMethod("ToObject", "bool", [
             Argument('JSContext*', 'cx'),
             Argument('JS::Handle<JSObject*>', 'parentObject'),
-            Argument('JS::Value*', 'vp'),
+            Argument('JS::MutableHandle<JS::Value>', 'rval'),
         ], const=True, body=body)
 
     def initIdsMethod(self):
         assert self.needToInitIds
         idinit = [CGGeneric('!InternJSString(cx, %s, "%s")' %
                             (m.identifier.name + "_id", m.identifier.name))
                   for m in self.dictionary.members]
         idinit = CGList(idinit, " ||\n")
@@ -7826,19 +7821,17 @@ class CGDictionary(CGThing):
         declType = conversionInfo.declType
         if conversionInfo.dealWithOptional:
             declType = CGTemplatedType("Optional", declType)
         return declType.define()
 
     def getMemberConversion(self, memberInfo):
         (member, conversionInfo) = memberInfo
         replacements = { "val": "temp",
-                         "valPtr": "temp.address()",
-                         "valHandle": "temp",
-                         "valMutableHandle": "&temp",
+                         "mutableVal": "&temp",
                          "declName": self.makeMemberName(member.identifier.name),
                          # We need a holder name for external interfaces, but
                          # it's scoped down to the conversion so we can just use
                          # anything we want.
                          "holderName": "holder" }
         # We can't handle having a holderType here
         assert conversionInfo.holderType is None
         if conversionInfo.dealWithOptional:
@@ -7918,17 +7911,17 @@ class CGDictionary(CGThing):
             member.type, self.descriptorProvider,
             {
                 'result' : "currentValue",
                 'successCode' : ("if (!%s) {\n"
                                  "  return false;\n"
                                  "}\n"
                                  "break;" % propDef),
                 'jsvalRef': "temp",
-                'jsvalPtr': "temp.address()",
+                'jsvalHandle': "&temp",
                 'isCreator': False,
                 'obj': "parentObject"
             })
         conversion = CGGeneric(innerTemplate)
         conversion = CGWrapper(conversion,
                                pre=("JS::Rooted<JS::Value> temp(cx);\n"
                                     "%s const & currentValue = %s;\n" %
                                     (declType.define(), memberData)
@@ -9039,17 +9032,17 @@ class CGJSImplMethod(CGNativeMember):
             assert args[1].argType == 'JSContext*'
             args = args[2:]
             constructorArgs = [arg.name for arg in args]
             initCall = """
   // Wrap the object before calling __Init so that __DOM_IMPL__ is available.
   nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(window);
   JS::Rooted<JSObject*> scopeObj(cx, globalHolder->GetGlobalJSObject());
   JS::Rooted<JS::Value> wrappedVal(cx);
-  if (!WrapNewBindingObject(cx, scopeObj, impl, wrappedVal.address())) {
+  if (!WrapNewBindingObject(cx, scopeObj, impl, &wrappedVal)) {
     MOZ_ASSERT(JS_IsExceptionPending(cx));
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
   // Initialize the object with the constructor arguments.
   impl->mImpl->__Init(%s);
   if (aRv.Failed()) {
     return nullptr;
@@ -9448,19 +9441,17 @@ class CallbackMember(CGNativeMember):
             "${argvDecl}"
             "${convertArgs}"
             "${doCall}"
             "${returnResult}").substitute(replacements)
 
     def getResultConversion(self):
         replacements = {
             "val": "rval",
-            "valPtr": "rval.address()",
-            "valHandle": "rval",
-            "valMutableHandle": "&rval",
+            "mutableVal": "&rval",
             "holderName" : "rvalHolder",
             "declName" : "rvalDecl",
             # We actually want to pass in a null scope object here, because
             # wrapping things into our current compartment (that of mCallback)
             # is what we want.
             "obj": "nullptr"
             }
 
@@ -9519,18 +9510,18 @@ class CallbackMember(CGNativeMember):
             result = argval
             prepend = ""
 
         conversion = prepend + wrapForType(
             arg.type, self.descriptorProvider,
             {
                 'result' : result,
                 'successCode' : "continue;" if arg.variadic else "break;",
-                'jsvalRef' : "argv[%s]" % jsvalIndex,
-                'jsvalPtr' : "&argv[%s]" % jsvalIndex,
+                'jsvalRef' : "argv.handleAt(%s)" % jsvalIndex,
+                'jsvalHandle' : "argv.handleAt(%s)" % jsvalIndex,
                 # XXXbz we don't have anything better to use for 'obj',
                 # really...  It's OK to use CallbackPreserveColor because
                 # CallSetup already handled the unmark-gray bits for us.
                 'obj' : 'CallbackPreserveColor()',
                 'isCreator': False,
                 'exceptionCode' : self.exceptionCode
                 })
         if arg.variadic:
--- a/dom/encoding/EncodingUtils.cpp
+++ b/dom/encoding/EncodingUtils.cpp
@@ -9,54 +9,16 @@
 
 namespace mozilla {
 namespace dom {
 
 static const char* labelsEncodings[][3] = {
 #include "labelsencodings.properties.h"
 };
 
-uint32_t
-EncodingUtils::IdentifyDataOffset(const char* aData,
-                                  const uint32_t aLength,
-                                  nsACString& aRetval)
-{
-  // Truncating to pre-clear return value in case of failure.
-  aRetval.Truncate();
-
-  // Minimum bytes in input stream data that represents
-  // the Byte Order Mark is 2. Max is 3.
-  if (aLength < 2) {
-    return 0;
-  }
-
-  if (aData[0] == '\xFF' && aData[1] == '\xFE') {
-    aRetval.AssignLiteral("UTF-16LE");
-    return 2;
-  }
-
-  if (aData[0] == '\xFE' && aData[1] == '\xFF') {
-    aRetval.AssignLiteral("UTF-16BE");
-    return 2;
-  }
-
-  // Checking utf-8 byte order mark.
-  // Minimum bytes in input stream data that represents
-  // the Byte Order Mark for utf-8 is 3.
-  if (aLength < 3) {
-    return 0;
-  }
-
-  if (aData[0] == '\xEF' && aData[1] == '\xBB' && aData[2] == '\xBF') {
-    aRetval.AssignLiteral("UTF-8");
-    return 3;
-  }
-  return 0;
-}
-
 bool
 EncodingUtils::FindEncodingForLabel(const nsACString& aLabel,
                                     nsACString& aOutEncoding)
 {
   // Save aLabel first because it may refer the same string as aOutEncoding.
   nsCString label(aLabel);
 
   EncodingUtils::TrimSpaceCharacters(label);
--- a/dom/encoding/EncodingUtils.h
+++ b/dom/encoding/EncodingUtils.h
@@ -11,33 +11,16 @@
 namespace mozilla {
 namespace dom {
 
 class EncodingUtils
 {
 public:
 
   /**
-   * Implements decode algorithm's step 1 & 2 from Encoding spec.
-   * http://encoding.spec.whatwg.org/#decode
-   * The returned name may not be lowercased due to compatibility with
-   * our internal implementations.
-   *
-   * @param     aData, incoming byte stream of data.
-   * @param     aLength, incoming byte stream length.
-   * @param     aRetval, outgoing encoding corresponding to valid data
-   *            byte order mark.
-   * @return    offset after the BOM bytes in byte stream
-   *            where the actual data starts.
-   */
-  static uint32_t IdentifyDataOffset(const char* aData,
-                                     const uint32_t aLength,
-                                     nsACString& aRetval);
-
-  /**
    * Implements get an encoding algorithm from Encoding spec.
    * http://encoding.spec.whatwg.org/#concept-encoding-get
    * Given a label, this function returns the corresponding encoding or a
    * false.
    * The returned name may not be lowercased due to compatibility with
    * our internal implementations.
    *
    * @param      aLabel, incoming label describing charset to be decoded.
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -80,18 +80,16 @@ NS_IMETHODIMP_(nsrefcnt) StartTransactio
 
 NS_IMETHODIMP_(nsrefcnt) StartTransactionRunnable::Release()
 {
   return 1;
 }
 
 NS_IMPL_QUERY_INTERFACE1(StartTransactionRunnable, nsIRunnable)
 
-StartTransactionRunnable gStartTransactionRunnable;
-
 } // anonymous namespace
 
 
 // static
 already_AddRefed<IDBTransaction>
 IDBTransaction::CreateInternal(IDBDatabase* aDatabase,
                                nsTArray<nsString>& aObjectStoreNames,
                                Mode aMode,
@@ -123,17 +121,18 @@ IDBTransaction::CreateInternal(IDBDataba
 
   if (IndexedDatabaseManager::IsMainProcess()) {
     transaction->mCachedStatements.Init();
 
     if (aMode != IDBTransaction::VERSION_CHANGE) {
       TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate();
       NS_ENSURE_TRUE(pool, nullptr);
 
-      pool->Dispatch(transaction, &gStartTransactionRunnable, false, nullptr);
+      static StartTransactionRunnable sStartTransactionRunnable;
+      pool->Dispatch(transaction, &sStartTransactionRunnable, false, nullptr);
     }
   }
   else if (!aIsVersionChangeTransactionChild) {
     IndexedDBDatabaseChild* dbActor = aDatabase->GetActorChild();
     NS_ASSERTION(dbActor, "Must have an actor here!");
 
     ipc::NormalTransactionParams params;
     params.names().AppendElements(aObjectStoreNames);
--- a/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl
@@ -41,28 +41,23 @@ interface nsIPrintCallback : nsISupports
   void render(in nsIDOMMozCanvasPrintState ctx);
 };
 
 [scriptable, function, uuid(6e9ffb59-2067-4aef-a51c-65e65a3e0d81)]
 interface nsIFileCallback : nsISupports {
   void receive(in nsIDOMBlob file);
 };
 
-[scriptable, uuid(11feba7e-73d5-49fc-a368-c3ef16ef4fc1)]
+[scriptable, uuid(350fddae-4476-4dcd-bccf-9c9c356354a6)]
 interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement
 {
   attribute unsigned long width;
   attribute unsigned long height;
   attribute boolean mozOpaque;
 
-  [implicit_jscontext]
-  nsISupports getContext(in DOMString contextId,
-                         [optional] in jsval contextOptions);
-
-
   // Valid calls are:
   //  toDataURL();              -- defaults to image/png
   //  toDataURL(type);          -- uses given type
   //  toDataURL(type, params);  -- uses given type, and any valid parameters
   [implicit_jscontext]
   DOMString toDataURL([optional] in DOMString type,
                       [optional] in jsval params);
 
--- a/dom/locales/en-US/chrome/plugins.properties
+++ b/dom/locales/en-US/chrome/plugins.properties
@@ -9,11 +9,13 @@
 title_label=About Plugins
 installedplugins_label=Installed plugins
 nopluginsareinstalled_label=No installed plugins found
 findpluginupdates_label=Find updates for installed plugins at
 file_label=File:
 path_label=Path:
 version_label=Version:
 state_label=State:
+state_enabled=Enabled
+state_disabled=Disabled
 mimetype_label=MIME Type
 description_label=Description
 suffixes_label=Suffixes
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -933,17 +933,17 @@ nsGeolocationService::StopDevice()
   mHigherAccuracy = false;
 
   mProvider->Shutdown();
   obs->NotifyObservers(mProvider,
                        "geolocation-device-events",
                        NS_LITERAL_STRING("shutdown").get());
 }
 
-nsRefPtr<nsGeolocationService> nsGeolocationService::sService;
+StaticRefPtr<nsGeolocationService> nsGeolocationService::sService;
 
 already_AddRefed<nsGeolocationService>
 nsGeolocationService::GetGeolocationService()
 {
   nsRefPtr<nsGeolocationService> result;
   if (nsGeolocationService::sService) {
     result = nsGeolocationService::sService;
     return result.forget();
--- a/dom/src/geolocation/nsGeolocation.h
+++ b/dom/src/geolocation/nsGeolocation.h
@@ -4,16 +4,17 @@
 
 #ifndef nsGeoLocation_h
 #define nsGeoLocation_h
 
 #include "mozilla/dom/PContentPermissionRequestChild.h"
 // Microsoft's API Name hackery sucks
 #undef CreateEvent
 
+#include "mozilla/StaticPtr.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsCOMArray.h"
 #include "nsTArray.h"
 #include "nsITimer.h"
 #include "nsIObserver.h"
 #include "nsIURI.h"
 #include "nsWrapperCache.h"
@@ -107,17 +108,17 @@ class nsGeolocationRequest
 /**
  * Singleton that manages the geolocation provider
  */
 class nsGeolocationService MOZ_FINAL : public nsIGeolocationUpdate, public nsIObserver
 {
 public:
 
   static already_AddRefed<nsGeolocationService> GetGeolocationService();
-  static nsRefPtr<nsGeolocationService> sService;
+  static mozilla::StaticRefPtr<nsGeolocationService> sService;
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIGEOLOCATIONUPDATE
   NS_DECL_NSIOBSERVER
 
   nsGeolocationService() {
       mHigherAccuracy = false;
   }
--- a/dom/webidl/AudioBufferSourceNode.webidl
+++ b/dom/webidl/AudioBufferSourceNode.webidl
@@ -11,17 +11,16 @@
  */
 
 [PrefControlled]
 interface AudioBufferSourceNode : AudioNode {
 
     attribute AudioBuffer? buffer;
 
     readonly attribute AudioParam playbackRate;
-    readonly attribute AudioParam gain;
 
     attribute boolean loop;
     attribute double loopStart;
     attribute double loopEnd;
 
     [Throws]
     void start(optional double when = 0, optional double grainOffset = 0,
                optional double grainDuration);
--- a/dom/webidl/HTMLCanvasElement.webidl
+++ b/dom/webidl/HTMLCanvasElement.webidl
@@ -19,17 +19,17 @@ interface Variant;
 
 interface HTMLCanvasElement : HTMLElement {
   [Pure, SetterThrows]
            attribute unsigned long width;
   [Pure, SetterThrows]
            attribute unsigned long height;
 
   [Throws]
-  nsISupports? getContext(DOMString contextId, optional any contextOptions);
+  nsISupports? getContext(DOMString contextId, optional any contextOptions = null);
 
   [Throws]
   DOMString toDataURL(optional DOMString type = "",
                       optional any encoderOptions);
   [Throws]
   void toBlob(FileCallback _callback, optional DOMString type = "");
 };
 
--- a/dom/webidl/WebGLRenderingContext.webidl
+++ b/dom/webidl/WebGLRenderingContext.webidl
@@ -27,17 +27,20 @@ typedef long long      GLsizeiptr;
 // Ideally the typedef below would use 'unsigned byte', but that doesn't currently exist in Web IDL.
 typedef octet          GLubyte;        /* 'octet' should be an unsigned 8 bit type. */
 typedef unsigned short GLushort;
 typedef unsigned long  GLuint;
 typedef unrestricted float GLfloat;
 typedef unrestricted float GLclampf;  
 
 dictionary WebGLContextAttributes {
-    boolean alpha = true;
+    // boolean alpha = true;
+    // We deviate from the spec here.
+    // If alpha isn't specified, we rely on a pref ("webgl.default-no-alpha")
+    boolean alpha;
     boolean depth = true;
     boolean stencil = false;
     boolean antialias = true;
     boolean premultipliedAlpha = true;
     boolean preserveDrawingBuffer = false;
 };
 
 interface WebGLBuffer {
--- a/dom/workers/DOMBindingBase.cpp
+++ b/dom/workers/DOMBindingBase.cpp
@@ -55,26 +55,26 @@ DOMBindingBase::GetJSContext() const {
 }
 
 #ifdef DEBUG
 JSObject*
 DOMBindingBase::GetJSObject() const
 {
   // Make sure that the public method results in the same bits as our private
   // method.
-  MOZ_ASSERT(GetJSObjectFromBits() == GetWrapperPreserveColor());
-  return GetJSObjectFromBits();
+  MOZ_ASSERT(GetWrapperJSObject() == GetWrapperPreserveColor());
+  return GetWrapperJSObject();
 }
 
 void
 DOMBindingBase::SetJSObject(JSObject* aObject)
 {
   // Make sure that the public method results in the same bits as our private
   // method.
   SetWrapper(aObject);
 
-  uintptr_t oldWrapperPtrBits = mWrapperPtrBits;
+  uint8_t oldFlags = mFlags;
 
-  SetWrapperBits(aObject);
+  SetWrapperJSObject(aObject);
 
-  MOZ_ASSERT(oldWrapperPtrBits == mWrapperPtrBits);
+  MOZ_ASSERT(oldFlags == mFlags && aObject == mWrapper);
 }
 #endif
--- a/dom/workers/DOMBindingBase.h
+++ b/dom/workers/DOMBindingBase.h
@@ -44,39 +44,38 @@ public:
   NS_DECL_ISUPPORTS
 
   JSContext*
   GetJSContext() const;
 
   void
   TraceJSObject(JSTracer* aTrc, const char* aName)
   {
-      if (GetJSObject())
-          TraceJSObjectFromBits(aTrc, aName);
+    if (GetJSObject()) {
+      TraceWrapperJSObject(aTrc, aName);
+    }
   }
 
 #ifdef DEBUG
   JSObject*
   GetJSObject() const;
 
   void
   SetJSObject(JSObject* aObject);
 #else
   JSObject*
   GetJSObject() const
   {
-    // Reach in and grab the bits directly.
-    return GetJSObjectFromBits();
+    return GetWrapperJSObject();
   }
 
   void
   SetJSObject(JSObject* aObject)
   {
-    // Set the bits directly.
-    SetWrapperBits(aObject);
+    SetWrapperJSObject(aObject);
   }
 #endif
 };
 
 template <class T>
 class DOMBindingAnchor
 {
   T* mBinding;
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -1010,16 +1010,18 @@ mozInlineSpellChecker::IgnoreWord(const 
 }
 
 // mozInlineSpellChecker::IgnoreWords
 
 NS_IMETHODIMP
 mozInlineSpellChecker::IgnoreWords(const PRUnichar **aWordsToIgnore,
                                    uint32_t aCount)
 {
+  NS_ENSURE_TRUE(mSpellCheck, NS_ERROR_NOT_INITIALIZED);
+
   // add each word to the ignore list and then recheck the document
   for (uint32_t index = 0; index < aCount; index++)
     mSpellCheck->IgnoreWordAllOccurrences(aWordsToIgnore[index]);
 
   mozInlineSpellStatus status(this);
   nsresult rv = status.InitForSelection();
   NS_ENSURE_SUCCESS(rv, rv);
   return ScheduleSpellCheck(status);
@@ -1408,16 +1410,18 @@ mozInlineSpellChecker::DoSpellCheckSelec
 
 nsresult mozInlineSpellChecker::DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
                                              nsISelection *aSpellCheckSelection,
                                              mozInlineSpellStatus* aStatus,
                                              bool* aDoneChecking)
 {
   *aDoneChecking = true;
 
+  NS_ENSURE_TRUE(mSpellCheck, NS_ERROR_NOT_INITIALIZED);
+
   // get the editor for SkipSpellCheckForNode, this may fail in reasonable
   // circumstances since the editor could have gone away
   nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
   if (! editor)
     return NS_ERROR_FAILURE;
 
   bool iscollapsed;
   nsresult rv = aStatus->mRange->GetCollapsed(&iscollapsed);
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -488,18 +488,17 @@ Layer::SnapTransformTranslation(const gf
                                 gfxMatrix* aResidualTransform)
 {
   if (aResidualTransform) {
     *aResidualTransform = gfxMatrix();
   }
 
   gfxMatrix matrix2D;
   gfx3DMatrix result;
-  if (!(mContentFlags & CONTENT_DISABLE_TRANSFORM_SNAPPING) &&
-      mManager->IsSnappingEffectiveTransforms() &&
+  if (mManager->IsSnappingEffectiveTransforms() &&
       aTransform.Is2D(&matrix2D) &&
       !matrix2D.HasNonTranslation() &&
       matrix2D.HasNonIntegerTranslation()) {
     gfxPoint snappedTranslation(matrix2D.GetTranslation());
     snappedTranslation.Round();
     gfxMatrix snappedMatrix = gfxMatrix().Translate(snappedTranslation);
     result = gfx3DMatrix::From2D(snappedMatrix);
     if (aResidualTransform) {
@@ -521,18 +520,17 @@ Layer::SnapTransform(const gfx3DMatrix& 
                      gfxMatrix* aResidualTransform)
 {
   if (aResidualTransform) {
     *aResidualTransform = gfxMatrix();
   }
 
   gfxMatrix matrix2D;
   gfx3DMatrix result;
-  if (!(mContentFlags & CONTENT_DISABLE_TRANSFORM_SNAPPING) &&
-      mManager->IsSnappingEffectiveTransforms() &&
+  if (mManager->IsSnappingEffectiveTransforms() &&
       aTransform.Is2D(&matrix2D) &&
       gfxSize(1.0, 1.0) <= aSnapRect.Size() &&
       matrix2D.PreservesAxisAlignedRectangles()) {
     gfxPoint transformedTopLeft = matrix2D.Transform(aSnapRect.TopLeft());
     transformedTopLeft.Round();
     gfxPoint transformedTopRight = matrix2D.Transform(aSnapRect.TopRight());
     transformedTopRight.Round();
     gfxPoint transformedBottomRight = matrix2D.Transform(aSnapRect.BottomRight());
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -635,22 +635,17 @@ public:
      * be sorted with sibling layers that are also part of the same group.
      */
     CONTENT_PRESERVE_3D = 0x04,
     /**
      * This indicates that the transform may be changed on during an empty
      * transaction where there is no possibility of redrawing the content, so the
      * implementation should be ready for that.
      */
-    CONTENT_MAY_CHANGE_TRANSFORM = 0x08,
-    /**
-     * This indicates that the content does not want to be snapped to pixel
-     * boundaries, so the layers code should not do transform snapping.
-     */
-    CONTENT_DISABLE_TRANSFORM_SNAPPING = 0x10
+    CONTENT_MAY_CHANGE_TRANSFORM = 0x08
   };
   /**
    * CONSTRUCTION PHASE ONLY
    * This lets layout make some promises about what will be drawn into the
    * visible region of the ThebesLayer. This enables internal quality
    * and performance optimizations.
    */
   void SetContentFlags(uint32_t aFlags)
--- a/gfx/layers/YCbCrImageDataSerializer.cpp
+++ b/gfx/layers/YCbCrImageDataSerializer.cpp
@@ -45,17 +45,16 @@ static YCbCrBufferInfo* GetYCbCrBufferIn
   return reinterpret_cast<YCbCrBufferInfo*>(aData);
 }
 
 bool YCbCrImageDataDeserializerBase::IsValid()
 {
   if (mData == nullptr) {
     return false;
   }
-  size_t bufferInfoSize = MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
   return true;
 }
 
 uint8_t* YCbCrImageDataDeserializerBase::GetYData()
 {
   YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
   return reinterpret_cast<uint8_t*>(info) + info->mYOffset;
 }
--- a/image/decoders/nsGIFDecoder2.cpp
+++ b/image/decoders/nsGIFDecoder2.cpp
@@ -811,39 +811,41 @@ nsGIFDecoder2::WriteInternal(const char 
         GETN(1, gif_netscape_extension_block);
       else
         GETN(1, gif_consume_block);
       break;
 
     /* Netscape-specific GIF extension: animation looping */
     case gif_netscape_extension_block:
       if (*q)
-        GETN(*q, gif_consume_netscape_extension);
+        // We might need to consume 3 bytes in
+        // gif_consume_netscape_extension, so make sure we have at least that.
+        GETN(std::max(3, static_cast<int>(*q)), gif_consume_netscape_extension);
       else
         GETN(1, gif_image_start);
       break;
 
     /* Parse netscape-specific application extensions */
     case gif_consume_netscape_extension:
       switch (q[0] & 7) {
         case 1:
           /* Loop entire animation specified # of times.  Only read the
              loop count during the first iteration. */
           mGIFStruct.loop_count = GETINT16(q + 1);
           GETN(1, gif_netscape_extension_block);
           break;
-        
+
         case 2:
           /* Wait for specified # of bytes to enter buffer */
-          // Don't do this, this extension doesn't exist (isn't used at all) 
+          // Don't do this, this extension doesn't exist (isn't used at all)
           // and doesn't do anything, as our streaming/buffering takes care of it all...
           // See: http://semmix.pl/color/exgraf/eeg24.htm
           GETN(1, gif_netscape_extension_block);
           break;