Merge m-c to s-c.
authorRichard Newman <rnewman@mozilla.com>
Fri, 07 Sep 2012 14:12:07 -0700
changeset 111068 1f92079a3029bb6e97699dfd3c1d3f20d1a73fbc
parent 111067 c66677223fd860e4fc7c668c68eb6c1c9a178d80 (current diff)
parent 106657 00a552f644a21c1395909643ea44c70f313bee39 (diff)
child 111069 39f2364d486010a5ecb605b6cae84b30b9cbb4c8
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
milestone18.0a1
Merge m-c to s-c.
mobile/android/themes/core/aboutMemory.css
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -704,20 +704,20 @@ window.addEventListener('ContentStart', 
       });
     }
 }, "geolocation-device-events", false);
 })();
 
 (function headphonesStatusTracker() {
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     shell.sendChromeEvent({
-      type: 'headphones-status',
+      type: 'headphones-status-changed',
       state: aData
     });
-}, "headphones-status", false);
+}, "headphones-status-changed", false);
 })();
 
 (function recordingStatusTracker() {
   let gRecordingActiveCount = 0;
 
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     let oldCount = gRecordingActiveCount;
     if (aData == "starting") {
new file mode 100644
--- /dev/null
+++ b/browser/base/content/aboutSocialError.xhtml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- 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/. -->
+
+<!DOCTYPE html [
+  <!ENTITY % htmlDTD
+    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "DTD/xhtml1-strict.dtd">
+  %htmlDTD;
+  <!ENTITY % netErrorDTD SYSTEM "chrome://global/locale/netError.dtd">
+  %netErrorDTD;
+]>
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>&loadError.label;</title>
+    <link rel="stylesheet" type="text/css" media="all"
+          href="chrome://browser/skin/aboutSocialError.css"/>
+  </head>
+
+  <body>
+    <div id="error-box">
+      <p id="main-error-msg"></p>
+      <p id="helper-error-msg"></p>
+    </div>
+    <div id="button-box">
+      <button id="btnTryAgain" onclick="tryAgainButton()"/>
+      <button id="btnCloseSidebar" onclick="closeSidebar()"/>
+    </div>
+  </body>
+
+  <script type="text/javascript;version=1.8"><![CDATA[
+    const Cu = Components.utils;
+
+    Cu.import("resource://gre/modules/Services.jsm");
+    Cu.import("resource://gre/modules/Social.jsm");
+
+    let config = {
+      tryAgainCallback: reloadProvider
+    }
+
+    function parseQueryString() {
+      let url = document.documentURI;
+      let queryString = url.replace(/^about:socialerror\??/, "");
+
+      let modeMatch = queryString.match(/mode=([^&]+)/);
+      let mode = modeMatch && modeMatch[1] ? modeMatch[1] : "";
+
+      switch (mode) {
+        case "onlyRefreshSidebar":
+          config.tryAgainCallback = refreshSidebar;
+          break;
+        default:
+          break;
+      }
+    }
+
+    function setUpStrings() {
+      let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
+      let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
+
+      let productName = brandBundle.GetStringFromName("brandShortName");
+      let providerName = Social && Social.provider && Social.provider.name;
+
+      // Sets up the error message
+      let msg = browserBundle.formatStringFromName("social.error.message", [productName, providerName], 2);
+      document.getElementById("main-error-msg").textContent = msg;
+
+      // Sets up the buttons' labels and accesskeys
+      let btnTryAgain = document.getElementById("btnTryAgain");
+      btnTryAgain.textContent = browserBundle.GetStringFromName("social.error.tryAgain.label");
+      btnTryAgain.accessKey = browserBundle.GetStringFromName("social.error.tryAgain.accesskey");
+
+      let btnCloseSidebar = document.getElementById("btnCloseSidebar");
+      btnCloseSidebar.textContent = browserBundle.GetStringFromName("social.error.closeSidebar.label");
+      btnCloseSidebar.accessKey = browserBundle.GetStringFromName("social.error.closeSidebar.accesskey");
+    }
+
+    function closeSidebar() {
+      Social.toggleSidebar();
+    }
+
+    function refreshSidebar() {
+      window.location.href = Social.provider.sidebarURL;
+    }
+
+    function reloadProvider() {
+      Social.provider.reload();
+    }
+
+    function tryAgainButton() {
+      config.tryAgainCallback();
+    }
+
+    parseQueryString();
+    setUpStrings();
+  ]]></script>
+</html>
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -303,30 +303,32 @@ let SocialShareButton = {
   init: function SSB_init() {
     this.updateButtonHiddenState();
     this.updateProfileInfo();
   },
 
   updateProfileInfo: function SSB_updateProfileInfo() {
     let profileRow = document.getElementById("editSharePopupHeader");
     let profile = Social.provider.profile;
+    this.promptImages = null;
+    this.promptMessages = null;
     if (profile && profile.displayName) {
       profileRow.hidden = false;
       let portrait = document.getElementById("socialUserPortrait");
       portrait.setAttribute("src", profile.portrait || "chrome://browser/skin/social/social.png");
       let displayName = document.getElementById("socialUserDisplayName");
       displayName.setAttribute("label", profile.displayName);
     } else {
       profileRow.hidden = true;
+      this.updateButtonHiddenState();
+      return;
     }
     // XXX - this shouldn't be done as part of updateProfileInfo, but instead
     // whenever we notice the provider has changed - but the concept of
     // "provider changed" will only exist once bug 774520 lands. 
-    this.promptImages = null;
-    this.promptMessages = null;
     // get the recommend-prompt info.
     let port = Social.provider._getWorkerPort();
     if (port) {
       port.onmessage = function(evt) {
         if (evt.data.topic == "social.user-recommend-prompt-response") {
           port.close();
           this.acceptRecommendInfo(evt.data.data);
           this.updateButtonHiddenState();
@@ -383,17 +385,18 @@ let SocialShareButton = {
 
   dismissSharePopup: function SSB_dismissSharePopup() {
     this.sharePopup.hidePopup();
   },
 
   updateButtonHiddenState: function SSB_updateButtonHiddenState() {
     let shareButton = this.shareButton;
     if (shareButton)
-      shareButton.hidden = !Social.uiVisible || this.promptImages == null;
+      shareButton.hidden = !Social.uiVisible || this.promptImages == null ||
+                           !Social.provider.profile || !Social.provider.profile.userName;
   },
 
   onClick: function SSB_onClick(aEvent) {
     if (aEvent.button != 0)
       return;
 
     // Don't bubble to the textbox, to avoid unwanted selection of the address.
     aEvent.stopPropagation();
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -225,17 +225,17 @@
            consumeoutsideclicks="true"
            level="top">
       <row id="editSharePopupHeader" align="center">
         <vbox align="center">
           <image id="socialUserPortrait" onclick="SocialUI.showProfile();"
                  aria-label="&social.sharePopup.portrait.arialabel;"/>
         </vbox>
         <vbox id="editSharePopupText">
-          <button id="socialUserDisplayName"
+          <button id="socialUserDisplayName" pack="start"
                   oncommand="SocialUI.showProfile();"/>
           <spacer flex="1"/>
           <label id="socialUserRecommendedText"
                  value="&social.sharePopup.shared.label;"/>
         </vbox>
       </row>
       <hbox id="editSharePopupBottomButtons" pack="end">
 #ifdef XP_UNIX
--- a/browser/base/content/socialchat.xml
+++ b/browser/base/content/socialchat.xml
@@ -42,17 +42,17 @@
         <getter>
           return this.iframe.docShell.isActive;
         </getter>
         <setter>
           this.iframe.docShell.isActive = !!val;
 
           // let the chat frame know if it is being shown or hidden
           let evt = this.iframe.contentDocument.createEvent("CustomEvent");
-          evt.initCustomEvent(val ? "socialFrameHide" : "socialFrameShow", true, true, {});
+          evt.initCustomEvent(val ? "socialFrameShow" : "socialFrameHide", true, true, {});
           this.iframe.contentDocument.documentElement.dispatchEvent(evt);
         </setter>
       </property>
 
       <method name="init">
         <parameter name="aProvider"/>
         <parameter name="aURL"/>
         <parameter name="aCallback"/>
--- a/browser/base/content/test/browser_social_mozSocial_API.js
+++ b/browser/base/content/test/browser_social_mozSocial_API.js
@@ -54,16 +54,18 @@ var tests = {
             ok(true, "panel hidden");
             next();
           }
           break;
         case "got-sidebar-message":
           // The sidebar message will always come first, since it loads by default
           ok(true, "got sidebar message");
           gotSidebarMessage = true;
+          // load a status panel
+          port.postMessage({topic: "test-ambient-notification"});
           checkNext();
           break;
       }
     }
     port.postMessage({topic: "test-init"});
 
     // Our worker sets up ambient notification at the same time as it responds to
     // the workerAPI initialization. If it's already initialized, we can
--- a/browser/base/content/test/browser_social_toolbar.js
+++ b/browser/base/content/test/browser_social_toolbar.js
@@ -2,18 +2,18 @@
  * 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/. */
 
 function test() {
   waitForExplicitFinish();
 
   let manifest = { // normal provider
     name: "provider 1",
-    origin: "https://example1.com",
-    workerURL: "https://example1.com/worker.js",
+    origin: "https://example.com",
+    workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
     iconURL: "chrome://branding/content/icon48.png"
   };
   runSocialTestWithProvider(manifest, function (finishcb) {
     runSocialTests(tests, undefined, undefined, finishcb);
   });
 }
 
 var tests = {
--- a/browser/base/content/test/newtab/browser_newtab_focus.js
+++ b/browser/base/content/test/newtab/browser_newtab_focus.js
@@ -1,37 +1,38 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /*
  * These tests make sure that focusing the 'New Tage Page' works as expected.
  */
 function runTests() {
+  // Handle the OSX full keyboard access setting
+  Services.prefs.setIntPref("accessibility.tabfocus", 7);
+
   // Focus count in new tab page.
   // 28 = 9 * 3 + 1 = 9 sites and 1 toggle button, each site has a link, a pin
   // and a remove button.
-  let FOCUS_COUNT = 28; 
-  if ("nsILocalFileMac" in Ci) {
-    // 19 = Mac doesn't focus links, so 9 focus targets less than Windows/Linux.
-    FOCUS_COUNT = 19;
-  }
+  let FOCUS_COUNT = 28;
 
   // Create a new tab page.
   yield setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks("");
 
   yield addNewTabPageTab();
   gURLBar.focus();
 
   // Count the focus with the enabled page.
   yield countFocus(FOCUS_COUNT);
 
   // Disable page and count the focus with the disabled page.
   NewTabUtils.allPages.enabled = false;
   yield countFocus(1);
+
+  Services.prefs.clearUserPref("accessibility.tabfocus");
 }
 
 /**
  * Focus the urlbar and count how many focus stops to return again to the urlbar.
  */
 function countFocus(aExpectedCount) {
   let focusCount = 0;
   let contentDoc = getContentDocument();
--- a/browser/base/content/test/social_worker.js
+++ b/browser/base/content/test/social_worker.js
@@ -72,23 +72,25 @@ onconnect = function(e) {
         port.postMessage({topic: "social.initialize-response"});
         let profile = {
           portrait: "https://example.com/portrait.jpg",
           userName: "trickster",
           displayName: "Kuma Lisa",
           profileURL: "http://en.wikipedia.org/wiki/Kuma_Lisa"
         };
         port.postMessage({topic: "social.user-profile", data: profile});
+        break;
+      case "test-ambient-notification":
         let icon = {
           name: "testIcon",
           iconURL: "chrome://branding/content/icon48.png",
           contentPanel: "https://example.com/browser/browser/base/content/test/social_panel.html",
           counter: 1
         };
-        port.postMessage({topic: "social.ambient-notification", data: icon});
+        apiPort.postMessage({topic: "social.ambient-notification", data: icon});
         break;
       case "test-isVisible":
         sidebarPort.postMessage({topic: "test-isVisible"});
         break;
       case "test-isVisible-response":
         testPort.postMessage({topic: "got-isVisible-response", result: event.data.result});
         break;
       case "social.user-recommend-prompt":
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -32,16 +32,17 @@ browser.jar:
         content/browser/abouthome/sync.png            (content/abouthome/sync.png)
         content/browser/abouthome/settings.png        (content/abouthome/settings.png)
         content/browser/abouthome/restore.png         (content/abouthome/restore.png)
         content/browser/abouthome/restore-large.png   (content/abouthome/restore-large.png)
         content/browser/abouthome/mozilla.png         (content/abouthome/mozilla.png)
         content/browser/abouthome/noise.png           (content/abouthome/noise.png)
         content/browser/aboutRobots-icon.png          (content/aboutRobots-icon.png)
         content/browser/aboutRobots-widget-left.png   (content/aboutRobots-widget-left.png)
+        content/browser/aboutSocialError.xhtml        (content/aboutSocialError.xhtml)
 *       content/browser/browser.css                   (content/browser.css)
 *       content/browser/browser.js                    (content/browser.js)
 *       content/browser/browser.xul                   (content/browser.xul)
 *       content/browser/browser-tabPreviews.xml       (content/browser-tabPreviews.xml)
         content/browser/content.js                    (content/content.js)
         content/browser/newtab/newTab.xul             (content/newtab/newTab.xul)
 *       content/browser/newtab/newTab.js              (content/newtab/newTab.js)
         content/browser/newtab/newTab.css             (content/newtab/newTab.css)
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -38,16 +38,19 @@ static RedirEntry kRedirMap[] = {
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
     nsIAboutModule::ALLOW_SCRIPT |
     nsIAboutModule::HIDE_FROM_ABOUTABOUT },
 #endif
   { "certerror", "chrome://browser/content/certerror/aboutCertError.xhtml",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
     nsIAboutModule::ALLOW_SCRIPT |
     nsIAboutModule::HIDE_FROM_ABOUTABOUT },
+  { "socialerror", "chrome://browser/content/aboutSocialError.xhtml",
+    nsIAboutModule::ALLOW_SCRIPT |
+    nsIAboutModule::HIDE_FROM_ABOUTABOUT },
   { "feeds", "chrome://browser/content/feeds/subscribe.xhtml",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
     nsIAboutModule::ALLOW_SCRIPT |
     nsIAboutModule::HIDE_FROM_ABOUTABOUT },
   { "privatebrowsing", "chrome://browser/content/aboutPrivateBrowsing.xhtml",
     nsIAboutModule::ALLOW_SCRIPT },
   { "rights",
 #ifdef MOZ_OFFICIAL_BRANDING
--- a/browser/components/build/nsModule.cpp
+++ b/browser/components/build/nsModule.cpp
@@ -89,16 +89,17 @@ static const mozilla::Module::ContractID
 #elif defined(MOZ_WIDGET_GTK2)
     { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
 #endif
     { NS_FEEDSNIFFER_CONTRACTID, &kNS_FEEDSNIFFER_CID },
 #ifdef MOZ_SAFE_BROWSING
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "blocked", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
 #endif
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "certerror", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
+    { NS_ABOUT_MODULE_CONTRACTID_PREFIX "socialerror", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "feeds", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "privatebrowsing", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "rights", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "robots", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "sessionrestore", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
 #ifdef MOZ_SERVICES_SYNC
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "sync-tabs", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "sync-progress", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
+++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
@@ -474,16 +474,20 @@ PrivateBrowsingService.prototype = {
           consoleService.logStringMessage(null); // trigger the listeners
           consoleService.reset();
         }
         break;
       case "command-line-startup":
         this._obs.removeObserver(this, "command-line-startup");
         aSubject.QueryInterface(Ci.nsICommandLine);
         if (aSubject.findFlag("private", false) >= 0) {
+          // Don't need to go into PB mode if it's already set to autostart
+          if (this._autoStarted)
+            aSubject.handleFlag("private", false);
+
           this.privateBrowsingEnabled = true;
           this._autoStarted = true;
           this._lastChangedByCommandLine = true;
         }
         else if (aSubject.findFlag("private-toggle", false) >= 0) {
           this._lastChangedByCommandLine = true;
         }
         break;
new file mode 100644
--- /dev/null
+++ b/browser/themes/gnomestripe/aboutSocialError.css
@@ -0,0 +1,98 @@
+body {
+  background-color: rgb(241, 244, 248);
+  margin-top: 2em;
+  font: message-box;
+  font-size: 100%;
+}
+
+p {
+  font-size: .8em;
+}
+
+#error-box {
+  background: url('chrome://global/skin/icons/information-24.png') no-repeat left 4px;
+  -moz-padding-start: 30px;
+}
+
+#error-box:-moz-locale-dir(rtl) {
+  background-position: right 4px;
+}
+
+#main-error-msg {
+  color: #4b4b4b;
+  font-weight: bold;
+}
+
+
+#button-box {
+  text-align: center;
+  width: 75%;
+  margin: 0 auto;
+}
+
+@media all and (min-width: 300px) {
+  #error-box {
+    max-width: 50%;
+    margin: 0 auto;
+    background-image: url('chrome://global/skin/icons/information-32.png');
+    min-height: 36px;
+    -moz-padding-start: 38px;
+  }
+
+  button {
+    width: auto !important;
+    min-width: 150px;
+  }
+}
+
+@media all and (min-width: 780px) {
+  #error-box {
+    max-width: 30%;
+  }
+}
+
+button {
+  font: message-box;
+  font-size: 0.6875em;
+  -moz-appearance: none;
+  -moz-user-select: none;
+  width: 100%;
+  margin: 2px 0;
+  padding: 2px 6px;
+  line-height: 1.2;
+  background-color: hsla(210,30%,95%,.1);
+  background-image: -moz-linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1));
+  background-clip: padding-box;
+  border: 1px solid hsla(210,15%,25%,.4);
+  border-color: hsla(210,15%,25%,.3) hsla(210,15%,25%,.35) hsla(210,15%,25%,.4);
+  border-radius: 3px;
+  box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
+              0 0 0 1px hsla(0,0%,100%,.3) inset,
+              0 1px 0 hsla(0,0%,100%,.1);
+
+  -moz-transition-property: background-color, border-color, box-shadow;
+  -moz-transition-duration: 150ms;
+  -moz-transition-timing-function: ease;
+
+}
+
+button:hover {
+  background-color: hsla(210,30%,95%,.8);
+  border-color: hsla(210,15%,25%,.45) hsla(210,15%,25%,.5) hsla(210,15%,25%,.55);
+  box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
+              0 0 0 1px hsla(0,0%,100%,.3) inset,
+              0 1px 0 hsla(0,0%,100%,.1),
+              0 0 3px hsla(210,15%,25%,.1);
+  -moz-transition-property: background-color, border-color, box-shadow;
+  -moz-transition-duration: 150ms;
+  -moz-transition-timing-function: ease;
+}
+
+button:hover:active {
+  background-color: hsla(210,15%,25%,.2);
+  box-shadow: 0 1px 1px hsla(210,15%,25%,.2) inset,
+              0 0 2px hsla(210,15%,25%,.4) inset;
+  -moz-transition-property: background-color, border-color, box-shadow;
+  -moz-transition-duration: 10ms;
+  -moz-transition-timing-function: linear;
+}
--- a/browser/themes/gnomestripe/jar.mn
+++ b/browser/themes/gnomestripe/jar.mn
@@ -8,16 +8,17 @@ browser.jar:
   skin/classic/browser/sanitizeDialog.css             (sanitizeDialog.css)
 * skin/classic/browser/aboutPrivateBrowsing.css             (aboutPrivateBrowsing.css)
 * skin/classic/browser/aboutSessionRestore.css        (aboutSessionRestore.css)
   skin/classic/browser/aboutSessionRestore-window-icon.png
   skin/classic/browser/aboutCertError.css
   skin/classic/browser/aboutCertError_sectionCollapsed.png
   skin/classic/browser/aboutCertError_sectionCollapsed-rtl.png
   skin/classic/browser/aboutCertError_sectionExpanded.png
+  skin/classic/browser/aboutSocialError.css
 #ifdef MOZ_SERVICES_SYNC
   skin/classic/browser/aboutSyncTabs.css
 #endif
   skin/classic/browser/actionicon-tab.png
 * skin/classic/browser/browser.css                    (browser.css)
 * skin/classic/browser/engineManager.css              (engineManager.css)
   skin/classic/browser/Geolocation-16.png
   skin/classic/browser/Geolocation-64.png
new file mode 100644
--- /dev/null
+++ b/browser/themes/pinstripe/aboutSocialError.css
@@ -0,0 +1,98 @@
+body {
+  background-color: rgb(241, 244, 248);
+  margin-top: 2em;
+  font: message-box;
+  font-size: 100%;
+}
+
+p {
+  font-size: .8em;
+}
+
+#error-box {
+  background: url('chrome://global/skin/icons/information-24.png') no-repeat left 4px;
+  -moz-padding-start: 30px;
+}
+
+#error-box:-moz-locale-dir(rtl) {
+  background-position: right 4px;
+}
+
+#main-error-msg {
+  color: #4b4b4b;
+  font-weight: bold;
+}
+
+
+#button-box {
+  text-align: center;
+  width: 75%;
+  margin: 0 auto;
+}
+
+@media all and (min-width: 300px) {
+  #error-box {
+    max-width: 50%;
+    margin: 0 auto;
+    background-image: url('chrome://global/skin/icons/information-32.png');
+    min-height: 36px;
+    -moz-padding-start: 38px;
+  }
+
+  button {
+    width: auto !important;
+    min-width: 150px;
+  }
+}
+
+@media all and (min-width: 780px) {
+  #error-box {
+    max-width: 30%;
+  }
+}
+
+button {
+  font: message-box;
+  font-size: 0.6875em;
+  -moz-appearance: none;
+  -moz-user-select: none;
+  width: 100%;
+  margin: 2px 0;
+  padding: 2px 6px;
+  line-height: 1.2;
+  background-color: hsla(210,30%,95%,.1);
+  background-image: -moz-linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1));
+  background-clip: padding-box;
+  border: 1px solid hsla(210,15%,25%,.4);
+  border-color: hsla(210,15%,25%,.3) hsla(210,15%,25%,.35) hsla(210,15%,25%,.4);
+  border-radius: 3px;
+  box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
+              0 0 0 1px hsla(0,0%,100%,.3) inset,
+              0 1px 0 hsla(0,0%,100%,.1);
+
+  -moz-transition-property: background-color, border-color, box-shadow;
+  -moz-transition-duration: 150ms;
+  -moz-transition-timing-function: ease;
+
+}
+
+button:hover {
+  background-color: hsla(210,30%,95%,.8);
+  border-color: hsla(210,15%,25%,.45) hsla(210,15%,25%,.5) hsla(210,15%,25%,.55);
+  box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
+              0 0 0 1px hsla(0,0%,100%,.3) inset,
+              0 1px 0 hsla(0,0%,100%,.1),
+              0 0 3px hsla(210,15%,25%,.1);
+  -moz-transition-property: background-color, border-color, box-shadow;
+  -moz-transition-duration: 150ms;
+  -moz-transition-timing-function: ease;
+}
+
+button:hover:active {
+  background-color: hsla(210,15%,25%,.2);
+  box-shadow: 0 1px 1px hsla(210,15%,25%,.2) inset,
+              0 0 2px hsla(210,15%,25%,.4) inset;
+  -moz-transition-property: background-color, border-color, box-shadow;
+  -moz-transition-duration: 10ms;
+  -moz-transition-timing-function: linear;
+}
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -1256,21 +1256,20 @@ window[tabsontop="false"] richlistitem[t
 
 #socialUserDisplayName,
 #socialUserPortrait {
   cursor: pointer;
 }
 
 #socialUserDisplayName {
   -moz-appearance: none;
-  color: #fff;
   border: none;
   background-color: transparent;
-  margin-top: 0;
-  padding-top: 0;
+  margin: 1px;
+  padding: 0;
   font-size: 130%;
   font-weight: bold;
 }
 
 #socialUserDisplayName > .button-box {
   -moz-padding-start: 0;
   padding-top: 0;
   border-top-width: 0;
--- a/browser/themes/pinstripe/jar.mn
+++ b/browser/themes/pinstripe/jar.mn
@@ -7,16 +7,17 @@ browser.jar:
   skin/classic/browser/sanitizeDialog.css                   (sanitizeDialog.css)
 * skin/classic/browser/aboutPrivateBrowsing.css             (aboutPrivateBrowsing.css)
 * skin/classic/browser/aboutSessionRestore.css              (aboutSessionRestore.css)
   skin/classic/browser/aboutSessionRestore-window-icon.png
   skin/classic/browser/aboutCertError.css
   skin/classic/browser/aboutCertError_sectionCollapsed.png
   skin/classic/browser/aboutCertError_sectionCollapsed-rtl.png
   skin/classic/browser/aboutCertError_sectionExpanded.png
+  skin/classic/browser/aboutSocialError.css
 #ifdef MOZ_SERVICES_SYNC
   skin/classic/browser/aboutSyncTabs.css
 #endif
   skin/classic/browser/actionicon-tab.png
 * skin/classic/browser/browser.css                          (browser.css)
 * skin/classic/browser/engineManager.css                    (engineManager.css)
   skin/classic/browser/Geolocation-16.png
   skin/classic/browser/Geolocation-64.png
new file mode 100644
--- /dev/null
+++ b/browser/themes/winstripe/aboutSocialError.css
@@ -0,0 +1,98 @@
+body {
+  background-color: rgb(241, 244, 248);
+  margin-top: 2em;
+  font: message-box;
+  font-size: 100%;
+}
+
+p {
+  font-size: .8em;
+}
+
+#error-box {
+  background: url('chrome://global/skin/icons/information-24.png') no-repeat left 4px;
+  -moz-padding-start: 30px;
+}
+
+#error-box:-moz-locale-dir(rtl) {
+  background-position: right 4px;
+}
+
+#main-error-msg {
+  color: #4b4b4b;
+  font-weight: bold;
+}
+
+
+#button-box {
+  text-align: center;
+  width: 75%;
+  margin: 0 auto;
+}
+
+@media all and (min-width: 300px) {
+  #error-box {
+    max-width: 50%;
+    margin: 0 auto;
+    background-image: url('chrome://global/skin/icons/information-32.png');
+    min-height: 36px;
+    -moz-padding-start: 38px;
+  }
+
+  button {
+    width: auto !important;
+    min-width: 150px;
+  }
+}
+
+@media all and (min-width: 780px) {
+  #error-box {
+    max-width: 30%;
+  }
+}
+
+button {
+  font: message-box;
+  font-size: 0.6875em;
+  -moz-appearance: none;
+  -moz-user-select: none;
+  width: 100%;
+  margin: 2px 0;
+  padding: 2px 6px;
+  line-height: 1.2;
+  background-color: hsla(210,30%,95%,.1);
+  background-image: -moz-linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1));
+  background-clip: padding-box;
+  border: 1px solid hsla(210,15%,25%,.4);
+  border-color: hsla(210,15%,25%,.3) hsla(210,15%,25%,.35) hsla(210,15%,25%,.4);
+  border-radius: 3px;
+  box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
+              0 0 0 1px hsla(0,0%,100%,.3) inset,
+              0 1px 0 hsla(0,0%,100%,.1);
+
+  -moz-transition-property: background-color, border-color, box-shadow;
+  -moz-transition-duration: 150ms;
+  -moz-transition-timing-function: ease;
+
+}
+
+button:hover {
+  background-color: hsla(210,30%,95%,.8);
+  border-color: hsla(210,15%,25%,.45) hsla(210,15%,25%,.5) hsla(210,15%,25%,.55);
+  box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
+              0 0 0 1px hsla(0,0%,100%,.3) inset,
+              0 1px 0 hsla(0,0%,100%,.1),
+              0 0 3px hsla(210,15%,25%,.1);
+  -moz-transition-property: background-color, border-color, box-shadow;
+  -moz-transition-duration: 150ms;
+  -moz-transition-timing-function: ease;
+}
+
+button:hover:active {
+  background-color: hsla(210,15%,25%,.2);
+  box-shadow: 0 1px 1px hsla(210,15%,25%,.2) inset,
+              0 0 2px hsla(210,15%,25%,.4) inset;
+  -moz-transition-property: background-color, border-color, box-shadow;
+  -moz-transition-duration: 10ms;
+  -moz-transition-timing-function: linear;
+}
--- a/browser/themes/winstripe/jar.mn
+++ b/browser/themes/winstripe/jar.mn
@@ -10,16 +10,17 @@ browser.jar:
         skin/classic/browser/sanitizeDialog.css                      (sanitizeDialog.css)
 *       skin/classic/browser/aboutPrivateBrowsing.css                (aboutPrivateBrowsing.css)
 *       skin/classic/browser/aboutSessionRestore.css                 (aboutSessionRestore.css)
         skin/classic/browser/aboutSessionRestore-window-icon.png     (preferences/application.png)
         skin/classic/browser/aboutCertError.css
         skin/classic/browser/aboutCertError_sectionCollapsed.png
         skin/classic/browser/aboutCertError_sectionCollapsed-rtl.png
         skin/classic/browser/aboutCertError_sectionExpanded.png
+        skin/classic/browser/aboutSocialError.css
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/browser/aboutSyncTabs.css
 #endif
         skin/classic/browser/actionicon-tab.png
         skin/classic/browser/appmenu-icons.png
         skin/classic/browser/appmenu-dropmarker.png
 *       skin/classic/browser/browser.css                             (browser.css)
 *       skin/classic/browser/engineManager.css                       (engineManager.css)
@@ -211,16 +212,17 @@ browser.jar:
         skin/classic/aero/browser/sanitizeDialog.css                       (sanitizeDialog.css)
 *       skin/classic/aero/browser/aboutPrivateBrowsing.css           (aboutPrivateBrowsing.css)
 *       skin/classic/aero/browser/aboutSessionRestore.css            (aboutSessionRestore.css)
         skin/classic/aero/browser/aboutSessionRestore-window-icon.png (aboutSessionRestore-window-icon-aero.png)
         skin/classic/aero/browser/aboutCertError.css
         skin/classic/aero/browser/aboutCertError_sectionCollapsed.png
         skin/classic/aero/browser/aboutCertError_sectionCollapsed-rtl.png
         skin/classic/aero/browser/aboutCertError_sectionExpanded.png
+        skin/classic/aero/browser/aboutSocialError.css
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/aero/browser/aboutSyncTabs.css
 #endif
         skin/classic/aero/browser/actionicon-tab.png                 (actionicon-tab.png)
         skin/classic/aero/browser/appmenu-dropmarker.png
         skin/classic/aero/browser/appmenu-icons.png
 *       skin/classic/aero/browser/browser.css                        (browser-aero.css)
 *       skin/classic/aero/browser/engineManager.css                  (engineManager.css)
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -1173,25 +1173,25 @@ nsContentSink::StartLayout(bool aIgnoreP
   // loop over the shells.
   FlushTags();
 
   mLayoutStarted = true;
   mLastNotificationTime = PR_Now();
 
   mDocument->SetMayStartLayout(true);
   nsCOMPtr<nsIPresShell> shell = mDocument->GetShell();
-  // Make sure we don't call InitialReflow() for a shell that has
+  // Make sure we don't call Initialize() for a shell that has
   // already called it. This can happen when the layout frame for
   // an iframe is constructed *between* the Embed() call for the
   // docshell in the iframe, and the content sink's call to OpenBody().
   // (Bug 153815)
-  if (shell && !shell->DidInitialReflow()) {
+  if (shell && !shell->DidInitialize()) {
     nsRect r = shell->GetPresContext()->GetVisibleArea();
     nsCOMPtr<nsIPresShell> shellGrip = shell;
-    nsresult rv = shell->InitialReflow(r.width, r.height);
+    nsresult rv = shell->Initialize(r.width, r.height);
     if (NS_FAILED(rv)) {
       return;
     }
   }
 
   // If the document we are loading has a reference or it is a
   // frameset document, disable the scroll bars on the views.
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -6284,17 +6284,17 @@ nsDocument::FlushPendingNotifications(mo
   // We need to flush the sink for non-HTML documents (because the XML
   // parser still does insertion with deferred notifications).  We
   // also need to flush the sink if this is a layout-related flush, to
   // make sure that layout is started as needed.  But we can skip that
   // part if we have no presshell or if it's already done an initial
   // reflow.
   if ((!IsHTML() ||
        (aType > Flush_ContentAndNotify && mPresShell &&
-        !mPresShell->DidInitialReflow())) &&
+        !mPresShell->DidInitialize())) &&
       (mParser || mWeakSink)) {
     nsCOMPtr<nsIContentSink> sink;
     if (mParser) {
       sink = mParser->GetContentSink();
     } else {
       sink = do_QueryReferent(mWeakSink);
       if (!sink) {
         mWeakSink = nullptr;
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -251,27 +251,27 @@ nsImageLoadingContent::OnStopDecode(imgI
   // 2) We want to block onload until all visible images are decoded. We do this
   // by blocking onload until all in-progress decodes get at least one frame
   // decoded. However, if all the data comes in while painting is suppressed
   // (ie, before the initial paint delay is finished), we fire onload without
   // doing a paint first. This means that decode-on-draw images don't start
   // decoding, so we can't wait for them to finish. See bug 512435.
   //
   // (*) IsPaintingSuppressed returns false if we haven't gotten the initial
-  // reflow yet, so we have to test !DidInitialReflow || IsPaintingSuppressed.
+  // reflow yet, so we have to test !DidInitialize || IsPaintingSuppressed.
   // It's possible for painting to be suppressed for reasons other than the
   // initial paint delay (for example, being in the bfcache), but we probably
   // aren't loading images in those situations.
 
   // XXXkhuey should this be GetOurCurrentDoc?  Decoding if we're not in
   // the document seems silly.
   nsIDocument* doc = GetOurOwnerDoc();
   nsIPresShell* shell = doc ? doc->GetShell() : nullptr;
   if (shell && shell->IsVisible() &&
-      (!shell->DidInitialReflow() || shell->IsPaintingSuppressed())) {
+      (!shell->DidInitialize() || shell->IsPaintingSuppressed())) {
 
     mCurrentRequest->RequestDecode();
   }
 
   // Fire the appropriate DOM event.
   if (NS_SUCCEEDED(aStatus)) {
     FireEvent(NS_LITERAL_STRING("load"));
   } else {
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7e3e4b53747914a3eaf1a961a5b09945da0c0337
GIT binary patch
literal 1027
zc%17D@N?(olHy`uVBq!ia0y~yU}OMc4kjRVS-{>9#48SRcVbv~PUa<$!;<dk>&U>c
zv7h@-A}f&3S>O>_%)r2R7=#&*=dVZs3QCo@MwA5Sr<If^7Ns%-BxdH7==r&ZD3lrN
znd%uD7<?&O$iTo{<muuVQW5v|f+5JxLkqt8zfI-ta7aARz{t$TBVmv*${1ygGN{Hl
az|O{~%fOgmDp?84Zw#KUelF{r5}E)KeChH4
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e64729dedf2bb2f539fcc572541fbf4f7229d394
GIT binary patch
literal 1936
zc%17D@N?(olHy`uVBq!ia0y~yU}OMc4kjRVS-{>9NU@|l`Z_W&Z0zU$lgJ9>a~60+
z7BevL9RguSQ4OyKprBNVYeY$Kep*R+Vo@qXKw@TIiJqTph(ejMo~fRpfx(xeg$xYr
zJf1F&Ar*0NuWjUIHWWDGP`d8Y*ZW6VyboJ8+Ftrp`Tbif_m+LJ4-VXJ|0llTd4C+k
z4aT1N{{^)eaukk<ANa#`!=Y!seZ4+|nZRT2ggQo`==u5k#TleKKC&9@2Z=sEf1kU7
z_s9>X8Sx;|&(Ghp9$-tVVLYP`68-u4J5vI);Xa0E;y}?qe|}aoZfKN<XZXww6s`OB
zXD<WL0{w=ctUyuw`hRhw){a^`YAq4gZs)$h8YjQ&fF{FkhP`zk!Wn+}JMi6N<yye7
zrg26b18almmLE(S4A~0H#2pwDSatU?a2=59c*z>T5aHOZ-@vqiEvbr8gdyz0BkoZx
eqgqCU7Wt5iic{7XFnk8qo(!I@elF{r5}E+jH|F60
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..02764182e5850fbc2648d8d03fcc19f003c83456
GIT binary patch
literal 1907
zc%17D@N?(olHy`uVBq!ia0y~yU}OMc4kjRVS-{>9#48SRcVbv~PUa<$!;<dk>&U>c
zv7h@-A}f&3S>O>_%)r2R7=#&*=dVZs3QCo@MwA5Sr<If^7Ns%-BxdH7==r&ZD3lrN
znd%uD7<?&O$iTq%$kW9!q$2L^^@F+2jsk}-yxspYzub}WbJLxr3y+q5+V}lW8_Nav
z2PTb|kGJ#pzYt_%aR77rZJe@NSU4IEWHK%9=a-kes0`!CSGHW?;1pnJyv*V!FK=hF
z$ejbqvH!%eQcy^NfoVDC96P(33YUHXD5vg;V34wk0|Senutjanj}IMkicrp<6Us~6
zJQ^4{=BO3?`tjkRpsf>(Gtu3ncLD>WfQ9daFCQNsR<3G+ag_TfNGUQhDHO~)@bdBD
zcK0tFFpj&NqNx+i52GF$^$_hnBrdn`xv&RkO<fREKZ9=Lm&@Y+{_}a=w|{ANLrB5l
zPkF}gkKXDGjDFD$3`_zC_A|;hUVbfYanHOVzoAjGOq9c+A+MJCB#Xj<13bIASQH$#
z?`uq95=cmBi)CdJSP*^R!HAK=z~JyYCPt16Yx5OmGO$R@NDOaeV0m%Pe1Z=H6VI6q
ztAR$Byq5M*V_;-UyAi6uz_{xxuZnO31GDiPErAAxyT8~baXO4zH)`GRv+g0g<Ckg4
UqEUsvfpsE-r>mdKI;Vst03`dC+W-In
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..348330a558b1afd0ca9bf30407a89240df1db161
GIT binary patch
literal 1358
zc%17D@N?(olHy`uVBq!ia0y~yU}OMc4kjRVS-{>9#48SRcVbv~PUa<$!;<dk>&U>c
zv7h@-A}f&3S>O>_%)r2R7=#&*=dVZs3QCo@MwA5Sr<If^7Ns%-BxdH7==r&ZD3lrN
znd%uD7<?&O2sCN0r;B4qMcmsfjhqYy0!)VA<9GeF)qB9iR#Gj@6x*0rd|JJLiOoSl
zcY@w~CQb>4#w`xJ_WV~)U|_k#^zzfc{su+?5AG$Wf7`<p{pT1}G^%J+(WoLCE7I5h
az~~jt_v!czqYuF1j=|H_&t;ucLK6TKxFTEt
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5eedbdfb1c5227d31b6039752f3d21ace0004b62
GIT binary patch
literal 1937
zc%17D@N?(olHy`uVBq!ia0y~yU}OMc4kjRVS-{>9NU@|l`Z_W&Z0zU$lgJ9>a~60+
z7BevL9RguSQ4OyKprBNVYeY$Kep*R+Vo@qXKw@TIiJqTph(ejMo~fRpfx(xeg$xYr
zyq+$OAr*0NuWjUIHWWDGP`d8Ym0R`V!aBUqS-yFket!41xZZ_dWsS`F^1tE_%(Jgz
zOkg*t`{%xbVMC)tJi}-11ZKm!e}DEe+;Hg8Z}`ay6t%Da7srsJa7_HbA10vaeEWKR
z1~Y-j+zEAzK+*H__lq+~cYI_u*bfqYe*Qjp1MiU^Of%v^qMx6?XFb4{RKs{iA0+zo
z^LHko1^XDDi33Id{P|hUIBM;vwWHP&w)T#mgLp;l3#R1^Z<xOPIvCIRz@E`ELtLYQ
zX#-nQ6{844*o8;j3mDck&WK}RZ4lk^gGqxSTVa{F17iZK?mh;t15zC?Spyg%9J}>L
gwTx;R5nAehTT6dAk@*K$=`t{Qy85}Sb4q9e08qc=VgLXD
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..838b9566119961ac8cb51095733428734d1e93fb
GIT binary patch
literal 1894
zc%17D@N?(olHy`uVBq!ia0y~yU}OMc4kjRVS-{>9NU@|l`Z_W&Z0zU$lgJ9>a~60+
z7BevL9RguSQ4OyKprBNVYeY$Kep*R+Vo@qXKw@TIiJqTph(ejMo~fRpfx(xeg$xXA
zk33x*Ln`9lUO$-Y>?m;f!rMRF^U56=KR4Z3y6|Y}r+wf5w6R=pe_+yh`FJ~j{|iAT
z76&k=-^MAcg@vQxKqk}jetvnmi^?#Ld}YfO4o(4v#>*^z^73{zi`+S&9Q#ikD+PrV
z7?_rG&atzrsc`8RfO6`d2nH#uI54pI30u_G{P@rzrwHZzIibA7&7*;VV~$$EuOA;C
z3felsI1}AHdM7Y23Rw6)`10}LVdbh87)QB(f|Md7lS09)11}#RZg>B}0pqyKDVjRL
z{4naFQ4i7HL*jA^p9_0%*3<<t^)u);ez`3E??0c{efyVYH-r=%{*-6@{^+gFz~~q4
zz`!JMU_Ya5<K@@V7Wd2>@*5f@%S1UG8uDtHPqHW+IKZ=;i$%d<`@Y5$CV_;6wpdms
zfd$d`9gG+`3=9shV`AjEur^;|CIgGajKuIp29_7s%qRFTF!7w(uo`G|$!lp3H3mku
zv>Txc42-+J@~Q|oFfbdx(GqB2xciH35~stcb)(h|KkFW{_g(K+_FU%Q4y+RyJYD@<
J);T3K0RWLuk*5Fv
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/reftest/reftest.list
@@ -0,0 +1,188 @@
+# WebGL Reftests!
+# If you add new tests, don't forget to add sanity (&nogl) tests! (if needed)
+
+# Check that disabling works:
+                           == webgl-disable-test.html?nogl  wrapper.html?green.png
+pref(webgl.disabled,true)  == webgl-disable-test.html       wrapper.html?green.png
+
+# Basic WebGL tests:
+# Do we get pixels to the screen at all?
+# Try to just hit the different rendering paths here.
+# Test: {aa, alpha, preserve, readback} = 16
+== webgl-clear-test.html?nogl  wrapper.html?green.png
+
+== webgl-clear-test.html?__&_____&________  wrapper.html?green.png
+== webgl-clear-test.html?aa&_____&________  wrapper.html?green.png
+== webgl-clear-test.html?__&alpha&________  wrapper.html?green.png
+== webgl-clear-test.html?aa&alpha&________  wrapper.html?green.png
+== webgl-clear-test.html?__&_____&preserve  wrapper.html?green.png
+== webgl-clear-test.html?aa&_____&preserve  wrapper.html?green.png
+== webgl-clear-test.html?__&alpha&preserve  wrapper.html?green.png
+== webgl-clear-test.html?aa&alpha&preserve  wrapper.html?green.png
+
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-clear-test.html?readback&__&_____&________  wrapper.html?green.png
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-clear-test.html?readback&aa&_____&________  wrapper.html?green.png
+pref(webgl.force-layers-readback,true)                         == webgl-clear-test.html?readback&__&alpha&________  wrapper.html?green.png
+pref(webgl.force-layers-readback,true)                         == webgl-clear-test.html?readback&aa&alpha&________  wrapper.html?green.png
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-clear-test.html?readback&__&_____&preserve  wrapper.html?green.png
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-clear-test.html?readback&aa&_____&preserve  wrapper.html?green.png
+pref(webgl.force-layers-readback,true)                         == webgl-clear-test.html?readback&__&alpha&preserve  wrapper.html?green.png
+pref(webgl.force-layers-readback,true)                         == webgl-clear-test.html?readback&aa&alpha&preserve  wrapper.html?green.png
+
+# Check orientation:
+== webgl-orientation-test.html?nogl  wrapper.html?white-top-left.png
+
+== webgl-orientation-test.html?__&_____&________  wrapper.html?white-top-left.png
+== webgl-orientation-test.html?aa&_____&________  wrapper.html?white-top-left.png
+== webgl-orientation-test.html?__&alpha&________  wrapper.html?white-top-left.png
+== webgl-orientation-test.html?aa&alpha&________  wrapper.html?white-top-left.png
+== webgl-orientation-test.html?__&_____&preserve  wrapper.html?white-top-left.png
+== webgl-orientation-test.html?aa&_____&preserve  wrapper.html?white-top-left.png
+== webgl-orientation-test.html?__&alpha&preserve  wrapper.html?white-top-left.png
+== webgl-orientation-test.html?aa&alpha&preserve  wrapper.html?white-top-left.png
+
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-orientation-test.html?readback&__&_____&________  wrapper.html?white-top-left.png
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-orientation-test.html?readback&aa&_____&________  wrapper.html?white-top-left.png
+pref(webgl.force-layers-readback,true)                         == webgl-orientation-test.html?readback&__&alpha&________  wrapper.html?white-top-left.png
+pref(webgl.force-layers-readback,true)                         == webgl-orientation-test.html?readback&aa&alpha&________  wrapper.html?white-top-left.png
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-orientation-test.html?readback&__&_____&preserve  wrapper.html?white-top-left.png
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-orientation-test.html?readback&aa&_____&preserve  wrapper.html?white-top-left.png
+pref(webgl.force-layers-readback,true)                         == webgl-orientation-test.html?readback&__&alpha&preserve  wrapper.html?white-top-left.png
+pref(webgl.force-layers-readback,true)                         == webgl-orientation-test.html?readback&aa&alpha&preserve  wrapper.html?white-top-left.png
+
+# Does we draw the correct color in the correct places with all context creation options?
+# (Note that our context creation option matrix is 2^6 = 64)
+== webgl-color-test.html?nogl  wrapper.html?colors.png
+
+== webgl-color-test.html?__&_____&_____&_______&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&_____&_______&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&_____&_______&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&_____&_______&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?__&_____&depth&_______&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&depth&_______&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&depth&_______&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&depth&_______&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?__&_____&_____&premult&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&_____&premult&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&_____&premult&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&_____&premult&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?__&_____&depth&premult&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&depth&premult&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&depth&premult&________&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&depth&premult&________&_______  wrapper.html?colors.png
+
+== webgl-color-test.html?__&_____&_____&_______&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&_____&_______&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&_____&_______&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&_____&_______&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?__&_____&depth&_______&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&depth&_______&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&depth&_______&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&depth&_______&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?__&_____&_____&premult&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&_____&premult&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&_____&premult&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&_____&premult&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?__&_____&depth&premult&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&depth&premult&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&depth&premult&preserve&_______  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&depth&premult&preserve&_______  wrapper.html?colors.png
+
+== webgl-color-test.html?__&_____&_____&_______&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&_____&_______&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&_____&_______&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&_____&_______&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?__&_____&depth&_______&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&depth&_______&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&depth&_______&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&depth&_______&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?__&_____&_____&premult&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&_____&premult&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&_____&premult&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&_____&premult&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?__&_____&depth&premult&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&depth&premult&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&depth&premult&________&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&depth&premult&________&stencil  wrapper.html?colors.png
+
+== webgl-color-test.html?__&_____&_____&_______&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&_____&_______&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&_____&_______&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&_____&_______&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?__&_____&depth&_______&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&depth&_______&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&depth&_______&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&depth&_______&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?__&_____&_____&premult&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&_____&premult&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&_____&premult&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&_____&premult&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?__&_____&depth&premult&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&_____&depth&premult&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?__&alpha&depth&premult&preserve&stencil  wrapper.html?colors.png
+== webgl-color-test.html?aa&alpha&depth&premult&preserve&stencil  wrapper.html?colors.png
+
+
+# Check a smaller selection for readback:
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-color-test.html?readback&__&_____&________  wrapper.html?colors.png
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-color-test.html?readback&aa&_____&________  wrapper.html?colors.png
+pref(webgl.force-layers-readback,true)                         == webgl-color-test.html?readback&__&alpha&________  wrapper.html?colors.png
+pref(webgl.force-layers-readback,true)                         == webgl-color-test.html?readback&aa&alpha&________  wrapper.html?colors.png
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-color-test.html?readback&__&_____&preserve  wrapper.html?colors.png
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-color-test.html?readback&aa&_____&preserve  wrapper.html?colors.png
+pref(webgl.force-layers-readback,true)                         == webgl-color-test.html?readback&__&alpha&preserve  wrapper.html?colors.png
+pref(webgl.force-layers-readback,true)                         == webgl-color-test.html?readback&aa&alpha&preserve  wrapper.html?colors.png
+
+
+# Check alpha behavior:
+== webgl-color-alpha-test.html?colorVal=1.0&alphaVal=1.0&nogl        wrapper.html?colors.png
+== webgl-color-alpha-test.html?colorVal=1.0&alphaVal=1.0             wrapper.html?colors.png
+== webgl-color-alpha-test.html?colorVal=0.0&alphaVal=1.0&nogl        wrapper.html?black.png
+== webgl-color-alpha-test.html?colorVal=0.0&alphaVal=1.0             wrapper.html?black.png
+
+== webgl-color-alpha-test.html?colorVal=1.0&alphaVal=0.0&nogl        wrapper.html?colors.png
+== webgl-color-alpha-test.html?colorVal=1.0&alphaVal=0.0             wrapper.html?colors.png
+== webgl-color-alpha-test.html?colorVal=1.0&alphaVal=0.0&alpha&nogl  wrapper.html?white.png
+== webgl-color-alpha-test.html?colorVal=1.0&alphaVal=0.0&alpha       wrapper.html?white.png
+
+fuzzy(1,65536) fuzzy-if(Android,9,65536) == webgl-color-alpha-test.html?colorVal=0.5&alphaVal=1.0&nogl  wrapper.html?half-colors.png
+fuzzy(1,65536) fuzzy-if(Android,9,65536) == webgl-color-alpha-test.html?colorVal=0.5&alphaVal=1.0       wrapper.html?half-colors.png
+
+# Test premult:
+fuzzy(1,65536) fuzzy-if(Android,9,65536)                                == webgl-color-alpha-test.html?colorVal=1.0&alphaVal=0.5&alpha&nogl          wrapper.html?colors-half-alpha.png
+fuzzy(1,65536) fuzzy-if(Android,9,65536)                                == webgl-color-alpha-test.html?colorVal=1.0&alphaVal=0.5&alpha               wrapper.html?colors-half-alpha.png
+fuzzy(1,65536) fuzzy-if(Android,9,65536)                                == webgl-color-alpha-test.html?colorVal=0.5&alphaVal=0.5&alpha&nogl          wrapper.html?half-colors-half-alpha.png
+fuzzy(1,65536) fuzzy-if(Android,9,65536) fails-if(cocoaWidget||Android) == webgl-color-alpha-test.html?colorVal=0.5&alphaVal=0.5&alpha               wrapper.html?half-colors-half-alpha.png
+fuzzy(1,65536) fuzzy-if(Android,9,65536)                                == webgl-color-alpha-test.html?colorVal=0.5&alphaVal=0.5&alpha&premult&nogl  wrapper.html?colors-half-alpha.png
+fuzzy(1,65536) fuzzy-if(Android,9,65536)                                == webgl-color-alpha-test.html?colorVal=0.5&alphaVal=0.5&alpha&premult       wrapper.html?colors-half-alpha.png
+
+# Test over-bright premult:
+fuzzy(1,65536) fuzzy-if(Android,9,65536) == webgl-color-alpha-test.html?colorVal=1.0&alphaVal=0.5&alpha&premult&nogl  wrapper.html?colors-half-alpha.png
+fuzzy(1,65536) fuzzy-if(Android,9,65536) == webgl-color-alpha-test.html?colorVal=1.0&alphaVal=0.5&alpha&premult       wrapper.html?colors-half-alpha.png
+
+
+# Check for hanging framebuffer bindings:
+== webgl-hanging-fb-test.html?nogl  wrapper.html?green.png
+
+== webgl-hanging-fb-test.html       wrapper.html?green.png
+== webgl-hanging-fb-test.html?aa    wrapper.html?green.png
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-hanging-fb-test.html?readback     wrapper.html?green.png
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-hanging-fb-test.html?readback&aa  wrapper.html?green.png
+
+== webgl-hanging-scissor-test.html       wrapper.html?green.png
+== webgl-hanging-scissor-test.html?aa    wrapper.html?green.png
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-hanging-scissor-test.html?readback     wrapper.html?green.png
+pref(webgl.force-layers-readback,true) fails-if(nativeFennec)  == webgl-hanging-scissor-test.html?readback&aa  wrapper.html?green.png
+
+
+# Check that our experimental prefs still work:
+
+# 16bpp:
+pref(webgl.prefer-16bpp,true)                                                               == webgl-color-test.html?16bpp           wrapper.html?colors.png
+pref(webgl.prefer-16bpp,true) pref(webgl.force-layers-readback,true) fails-if(nativeFennec) == webgl-color-test.html?16bpp&readback  wrapper.html?colors.png
+
+# Force native GL (Windows):
+skip-if(!winWidget) pref(webgl.prefer-native-gl,true)                                == webgl-clear-test.html?native-gl        wrapper.html?green.png
+skip-if(!winWidget) pref(webgl.prefer-native-gl,true)                                == webgl-orientation-test.html?native-gl  wrapper.html?white-top-left.png
+skip-if(!winWidget) pref(webgl.prefer-native-gl,true)                                == webgl-color-test.html?native-gl        wrapper.html?colors.png
+skip-if(!winWidget) pref(webgl.prefer-native-gl,true) pref(webgl.prefer-16bpp,true)  == webgl-color-test.html?native-gl&16bpp  wrapper.html?colors.png
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/reftest/webgl-clear-test.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+
+<script type="text/javascript" src="webgl-utils.js"></script>
+<script type="text/javascript">
+/* Clear Test
+ *
+ * Clear the canvas to green to test that we get pixels to the screen.
+ */
+
+"use strict";
+
+function renderGL(gl) {
+  gl.clearColor(0.0, 1.0, 0.0, 1.0);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+  gl.finish();
+}
+
+function renderBackup(canvas) {
+  var context = canvas.getContext("2d");
+  context.fillStyle = "rgba(0, 255, 0, 1.0)";
+  context.fillRect(0, 0, 256, 256);
+}
+
+function onLoad() {
+  var canvas = document.getElementById("canvas");
+  var gl = initGL(canvas);
+
+  if (gl)
+    renderGL(gl);
+  else
+    renderBackup(canvas);
+}
+</script>
+</head>
+
+<body onload="onLoad();">
+  <canvas id="canvas" width="256" height="256"></canvas>
+</body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/reftest/webgl-color-alpha-test.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+
+<script type="text/javascript" src="webgl-utils.js"></script>
+<script type="text/javascript">
+/* Color-Alpha Test
+ *
+ * Clear the four quadrants of the canvas as follows:
+ * +------+------+
+ * | red  |green |
+ * |      |      |
+ * +------+------+
+ * | blue |white |
+ * |      |      |
+ * +------+------+
+ * However, unlike the Color test, clear with a given alpha value.
+ * What effect this has depends on the context-creation args passed
+ * to this page.
+ *
+ * Here we check that we handle various combinations of alpha and
+ * premultipliedAlpha correctly.
+ */
+
+"use strict";
+
+function renderGL(gl, value, alpha) {
+  gl.enable(gl.SCISSOR_TEST);
+
+  gl.scissor(0, 128, 128, 128);
+  gl.clearColor(value, 0.0, 0.0, alpha);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+
+  gl.scissor(128, 128, 128, 128);
+  gl.clearColor(0.0, value, 0.0, alpha);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+
+  gl.scissor(0, 0, 128, 128);
+  gl.clearColor(0.0, 0.0, value, alpha);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+
+  gl.scissor(128, 0, 128, 128);
+  gl.clearColor(value, value, value, alpha);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+
+  gl.finish();
+}
+
+function renderBackup(canvas, value, alpha) {
+  if (!arg("alpha"))
+    alpha = 1.0;
+
+  if (arg("alpha") && arg("premult")) {
+    if (alpha == 0.0)
+      value = 1.0;
+    else
+      value /= alpha;
+  }
+
+  var intValue = (value * 255) | 0;
+  var context = canvas.getContext("2d");
+  context.fillStyle = "rgba(" + intValue + ", 0, 0, " + alpha + ")";
+  context.fillRect(0, 0, 128, 128);
+
+  context.fillStyle = "rgba(0, " + intValue + ", 0, " + alpha + ")";
+  context.fillRect(128, 0, 128, 128);
+
+  context.fillStyle = "rgba(0, 0, " + intValue + ", " + alpha + ")";
+  context.fillRect(0, 128, 128, 128);
+
+  context.fillStyle = "rgba(" + intValue + ", " + intValue + ", " + intValue + ", " + alpha + ")";
+  context.fillRect(128, 128, 128, 128);
+}
+
+function onLoad() {
+  var canvas = document.getElementById("canvas");
+  var gl = initGL(canvas);
+
+  var value = arg("colorVal");
+  var alpha = arg("alphaVal");
+
+  if (gl)
+    renderGL(gl, value, alpha);
+  else
+    renderBackup(canvas, value, alpha);
+}
+
+</script>
+</head>
+
+<body onload="onLoad();">
+  <canvas id="canvas" width="256" height="256"></canvas>
+</body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/reftest/webgl-color-test.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+
+<script type="text/javascript" src="webgl-utils.js"></script>
+<script type="text/javascript">
+/* Color Test
+ *
+ * Clear the four quadrants of the canvas as follows:
+ * +------+------+
+ * | red  |green |
+ * |      |      |
+ * +------+------+
+ * | blue |white |
+ * |      |      |
+ * +------+------+
+ *
+ * This is for checking that we're getting the right colors when
+ * we ask for them. This combined with the Orientation test assure
+ * that we are getting the correct colors in the correct places.
+ */
+
+"use strict";
+
+function renderGL(gl) {
+  gl.enable(gl.SCISSOR_TEST);
+
+  gl.scissor(0, 128, 128, 128);
+  gl.clearColor(1.0, 0.0, 0.0, 1.0);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+
+  gl.scissor(128, 128, 128, 128);
+  gl.clearColor(0.0, 1.0, 0.0, 1.0);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+
+  gl.scissor(0, 0, 128, 128);
+  gl.clearColor(0.0, 0.0, 1.0, 1.0);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+
+  gl.scissor(128, 0, 128, 128);
+  gl.clearColor(1.0, 1.0, 1.0, 1.0);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+
+  gl.finish();
+}
+
+function renderBackup(canvas) {
+  var context = canvas.getContext("2d");
+  context.fillStyle = "rgba(255, 0, 0, 1.0)";
+  context.fillRect(0, 0, 128, 128);
+
+  context.fillStyle = "rgba(0, 255, 0, 1.0)";
+  context.fillRect(128, 0, 128, 128);
+
+  context.fillStyle = "rgba(0, 0, 255, 1.0)";
+  context.fillRect(0, 128, 128, 128);
+
+  context.fillStyle = "rgba(255, 255, 255, 1.0)";
+  context.fillRect(128, 128, 128, 128);
+}
+
+function onLoad() {
+  var canvas = document.getElementById("canvas");
+  var gl = initGL(canvas);
+
+  if (gl)
+    renderGL(gl);
+  else
+    renderBackup(canvas);
+}
+
+</script>
+</head>
+
+<body onload="onLoad();">
+  <canvas id="canvas" width="256" height="256"></canvas>
+</body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/reftest/webgl-disable-test.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+
+<script type="text/javascript" src="webgl-utils.js"></script>
+<script type="text/javascript">
+/* Disable Test
+ *
+ * If we succeed in getting a WebGL context, we will fill
+ * the canvas with red. If we fail to acquire a WebGL context,
+ * we will use Canvas2D to instead fill it with green.
+ *
+ * Note that this test differs from the others in that
+ * it will draw differently if it receives a WebGL context.
+ * Other tests are designed to fallback silently to Canvas2D.
+ *
+ * We use this test to assure that when we disable WebGL,
+ * WebGL does not function. This is trivially true for systems
+ * that don't support WebGL. This test is not viable for testing
+ * that WebGL works, as blocklisted systems will always draw green.
+ */
+
+"use strict";
+
+function renderGL(gl) {
+  gl.clearColor(1.0, 0.0, 0.0, 1.0);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+  gl.finish();
+}
+
+function renderBackup(canvas) {
+  var context = canvas.getContext("2d");
+  context.fillStyle = "rgba(0, 255, 0, 1.0)";
+  context.fillRect(0, 0, 256, 256);
+}
+
+function onLoad() {
+  var canvas = document.getElementById("canvas");
+  var gl = initGL(canvas);
+
+  if (gl)
+    renderGL(gl);
+  else
+    renderBackup(canvas);
+}
+
+</script>
+</head>
+
+<body onload="onLoad();">
+  <canvas id="canvas" width="256" height="256"></canvas>
+</body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/reftest/webgl-hanging-fb-test.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+
+<script type="text/javascript" src="webgl-utils.js"></script>
+<script type="text/javascript">
+/* Hanging Framebuffer Test
+ *
+ * Clear the canvas to green, but create and bind a new framebuffer
+ * before returning. This will fail if we blindly read from the bound
+ * framebuffer, instead of binding to the screen and reading from that.
+ *
+ * How failure looks isn't well defined, since this is an empty framebuffer,
+ * thus is incomplete, and should cause errors if it's read from.
+ */
+
+"use strict";
+
+function renderGL(gl) {
+  gl.clearColor(0.0, 1.0, 0.0, 1.0);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+
+  var fb = gl.createFramebuffer();
+  gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+  gl.finish();
+}
+
+function renderBackup(canvas) {
+  var context = canvas.getContext("2d");
+  context.fillStyle = "rgba(0, 255, 0, 1.0)";
+  context.fillRect(0, 0, 256, 256);
+}
+
+function onLoad() {
+  var canvas = document.getElementById("canvas");
+  var gl = initGL(canvas);
+
+  if (gl)
+    renderGL(gl);
+  else
+    renderBackup(canvas);
+}
+
+</script>
+</head>
+
+<body onload="onLoad();">
+  <canvas id="canvas" width="256" height="256"></canvas>
+</body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/reftest/webgl-hanging-scissor-test.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+
+<script type="text/javascript" src="webgl-utils.js"></script>
+<script type="text/javascript">
+/* Hanging Scissor Test
+ *
+ * Clear the canvas to green, but create and enable and set scissor values
+ * before returning. This can fail if we blindly blit or read from the screen
+ * without disabling scissor-test.
+ *
+ * Failure should look like only the top-left quadrant is rendered.
+ */
+
+"use strict";
+
+function renderGL(gl) {
+  gl.clearColor(0.0, 1.0, 0.0, 1.0);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+
+  gl.enable(gl.SCISSOR_TEST);
+  gl.scissor(0, 128, 128, 128);
+
+  gl.finish();
+}
+
+function renderBackup(canvas) {
+  var context = canvas.getContext("2d");
+  context.fillStyle = "rgba(0, 255, 0, 1.0)";
+  context.fillRect(0, 0, 256, 256);
+}
+
+function onLoad() {
+  var canvas = document.getElementById("canvas");
+  var gl = initGL(canvas);
+
+  if (gl)
+    renderGL(gl);
+  else
+    renderBackup(canvas);
+}
+
+</script>
+</head>
+
+<body onload="onLoad();">
+  <canvas id="canvas" width="256" height="256"></canvas>
+</body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/reftest/webgl-orientation-test.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+
+<script type="text/javascript" src="webgl-utils.js"></script>
+<script type="text/javascript">
+/* Orientation Test
+ *
+ * Clear the canvas to black, and clear the upper-left quadrant
+ * to white. If this doesn't pass, but the Clear test does, then
+ * likely y-flip is wrong.
+ */
+
+"use strict";
+
+function renderGL(gl) {
+  gl.clearColor(0.0, 0.0, 0.0, 1.0);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+
+  gl.enable(gl.SCISSOR_TEST);
+  gl.scissor(0, 128, 128, 128);
+  gl.clearColor(1.0, 1.0, 1.0, 1.0);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+
+  gl.finish();
+}
+
+function renderBackup(canvas) {
+  var context = canvas.getContext("2d");
+  context.fillStyle = "rgba(0, 0, 0, 1.0)";
+  context.fillRect(0, 0, 256, 256);
+
+  context.fillStyle = "rgba(255, 255, 255, 1.0)";
+  context.fillRect(0, 0, 128, 128);
+}
+
+function onLoad() {
+  var canvas = document.getElementById("canvas");
+  var gl = initGL(canvas);
+
+  if (gl)
+    renderGL(gl);
+  else
+    renderBackup(canvas);
+}
+
+</script>
+</head>
+
+<body onload="onLoad();">
+  <canvas id="canvas" width="256" height="256"></canvas>
+</body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/reftest/webgl-utils.js
@@ -0,0 +1,63 @@
+"use strict";
+
+function parseArgs() {
+  var query = window.location.search.substring(1);
+
+  var split = query.split("&");
+
+  var args = {}
+  for (var i = 0; i < split.length; i++) {
+    var pair = split[i].split("=");
+
+    var key = pair[0];
+    var value = true;
+    if (pair.length >= 2) {
+      eval("value = " + decodeURIComponent(pair[1]) + ";");
+    }
+
+    args[key] = value;
+  }
+
+  return args;
+}
+
+var gArgs = null;
+function arg(key) {
+  if (gArgs === null) {
+    gArgs = parseArgs();
+  }
+
+  var ret = gArgs[key];
+  if (ret === undefined)
+    ret = false;
+
+  return ret;
+}
+
+function initGL(canvas) {
+  if (arg("nogl"))
+    return null;
+
+  var gl = null;
+
+  var withAA = arg("aa");
+  var withAlpha = arg("alpha");
+  var withDepth = arg("depth");
+  var withPremult = arg("premult");
+  var withPreserve = arg("preserve");
+  var withStencil = arg("stencil");
+
+  try {
+    var argDict = {
+      alpha: withAlpha,
+      depth: withDepth,
+      stencil: withStencil,
+      antialias: withAA,
+      premultipliedAlpha: withPremult,
+      preserveDrawingBuffer: withPreserve,
+    };
+    gl = canvas.getContext("experimental-webgl", argDict);
+  } catch(e) {}
+
+  return gl;
+}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..224b193a5ec4d4f76d7dfc5bb8fa843336970a5f
GIT binary patch
literal 1418
zc%17D@N?(olHy`uVBq!ia0y~yU}OMc4kjRVS-{>9#48SRcVbv~PUa<$!;<dk>&U>c
zv7h@-A}f&3S>O>_%)r2R7=#&*=dVZs3QCo@MwA5Sr<If^7Ns%-BxdH7==r&ZD3lrN
znd%uD7<?&O2sG)Zr;B4qMcms<j)DvZ0!)T~X74+7!>)-jjmg@RRc)=qu6>`fuV1&5
z&tZ)*5X*ReUGDt)d#urn{5`C<er`Sfd3E{0umjA=jb(LjKmK_YyFv8Bfrtfj<Ew4<
zSBdAa+Kg%$)iP4Fa0)0mG%zqSv2cts20P<`I1~TxR&S%?Es`w2qLRVW)z4*}Q$iB}
Dj==(M
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..23b21c59cb9c5138b84ade1c728d8fd61889956b
GIT binary patch
literal 1401
zc%17D@N?(olHy`uVBq!ia0y~yU}OMc4kjRVS-{>9#48SRcVbv~PUa<$!;<dk>&U>c
zv7h@-A}f&3S>O>_%)r2R7=#&*=dVZs3QCo@MwA5Sr<If^7Ns%-BxdH7==r&ZD3lrN
znd%uD7<?&O2sG)1r;B4qMcmuVj6gd%nhkzW-{&}k_d!uHPYZ9%3|T8?;RbaNX#t0-
zx(`erm@}D~JkImSG1MvKIxxKad64@6{}Nsf1zY<H#vhGa7#Wv5XV+)2pJ1lY@a4|~
z)(7mD*jOgali$Pe$Kh53!==y7;tlenhK(9FYS^e@^fl}c^PTNFR|<kpd;pe=44$rj
JF6*2UngFV23qb$?
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/reftest/wrapper.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+<title>Image reftest wrapper</title>
+<style type="text/css">
+  #image1 { background-color: rgb(10, 100, 250); }
+</style>
+<script>
+  // The image is loaded async after the page loads
+  // wait for it to finish loading
+  function onImageLoad() { 
+    document.documentElement.removeAttribute("class");
+  };
+</script>
+</head>
+<body>
+<img id="image1">
+<script>
+  // Use as "wrapper.html?image.png"
+  var imgURL = document.location.search.substr(1);
+  document.images[0].onload = onImageLoad;
+  document.images[0].onerror = onImageLoad;
+  document.images[0].src = imgURL;
+</script>
+</body>
+</html>
+
--- a/content/events/test/test_bug426082.html
+++ b/content/events/test/test_bug426082.html
@@ -26,21 +26,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 /** Test for Bug 426082 **/
 SimpleTest.waitForExplicitFinish();
 
 var normalButtonCanvas, pressedButtonCanvas, normalFocusedButtonCanvas,
     pressedFocusedButtonCanvas, currentSnapshot, button, label, outside;
 
 function runTests() {
-  normalButtonCanvas = $("normalButtonCanvas");
-  pressedButtonCanvas = $("pressedButtonCanvas");
-  normalFocusedButtonCanvas = $("normalFocusedButtonCanvas");
-  pressedFocusedButtonCanvas = $("pressedFocusedButtonCanvas");
-  currentSnapshot = $("currentSnapshot");
   button = $("button");
   label = $("label");
   outside = $("outside");
   SimpleTest.executeSoon(executeTests);
 }
 
 function isRectContainedInRectFromRegion(rect, region) {
   return Array.some(region, function (r) {
@@ -49,17 +44,17 @@ function isRectContainedInRectFromRegion
            rect.right <= r.right &&
            rect.bottom <= r.bottom;
   });
 }
 
 function paintListener(e) {
   if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
     gNeedsPaint = false;
-    takeSnapshot(currentSnapshot);
+    currentSnapshot = takeSnapshot();
   }
 }
 
 var gNeedsPaint = false;
 function executeTests() {
   var testYielder = tests();
   function execNext() {
     try {
@@ -71,41 +66,41 @@ function executeTests() {
       SimpleTest.executeSoon(execNext);
     } catch (e) {}
   }
   execNext();
 }
 
 function tests() {
   window.addEventListener("MozAfterPaint", paintListener, false);
-  takeSnapshot(normalButtonCanvas);
+  normalButtonCanvas = takeSnapshot();
   // Press the button.
   sendMouseEvent("mousemove", button);
   sendMouseEvent("mousedown", button);
   yield;
-  takeSnapshot(pressedFocusedButtonCanvas);
+  pressedFocusedButtonCanvas = takeSnapshot();
   compareSnapshots_(normalButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal buttons.");
   // Release.
   sendMouseEvent("mouseup", button);
   yield;
   // make sure the button is focused as this doesn't happen on click on Mac
   button.focus();
-  takeSnapshot(normalFocusedButtonCanvas);
+  normalFocusedButtonCanvas = takeSnapshot();
   compareSnapshots_(normalFocusedButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal focused buttons.");
   // Unfocus the button.
   sendMouseEvent("mousedown", outside);
   sendMouseEvent("mouseup", outside);
   yield;
 
   // Press the label.
   sendMouseEvent("mousemove", label);
   sendMouseEvent("mousedown", label);
   yield;
   compareSnapshots_(normalButtonCanvas, currentSnapshot, false, "Pressing the label should have pressed the button.");
-  takeSnapshot(pressedButtonCanvas);
+  pressedButtonCanvas = takeSnapshot();
   // Move the mouse down from the label.
   sendMouseEvent("mousemove", outside);
   yield;
   compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Moving the mouse down from the label should have unpressed the button.");
   // ... and up again.
   sendMouseEvent("mousemove", label);
   yield;
   compareSnapshots_(pressedButtonCanvas, currentSnapshot, true, "Moving the mouse back on top of the label should have pressed the button.");
@@ -142,37 +137,28 @@ function compareSnapshots_(c1, c2, shoul
     if (shouldBeIdentical) {
       ok(false, msg + " - expected " + c1url + " but got " + c2url);
     } else {
       ok(false, msg + " - expected something other than " + c1url);
     }
   }
 }
 
-function takeSnapshot(canvas) {
+function takeSnapshot() {
   var r = buttonRect();
-  var ctx = canvas.getContext("2d");
-  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-  canvas.width = r.width + 4;
-  canvas.height = r.height + 4;
-  ctx.clearRect(0, 0, canvas.width, canvas.height);
-  ctx.drawWindow(window, r.left - 2, r.top - 2, r.width + 4, r.height + 4, "#FFF");
+  adjustedRect = { left: r.left - 2, top: r.top - 2,
+                   width: r.width + 4, height: r.height + 4 };
+  return SpecialPowers.snapshotRect(window, adjustedRect);
 }
 
 function buttonRect() {
   return button.getBoundingClientRect();
 }
 
 
 </script>
 </pre>
 <p><input type="button" value="Button" id="button"></p>
 <p><label for="button" id="label">Label</label></p>
 <p id="outside">Something under the label</p>
 
-<canvas id="normalButtonCanvas"></canvas>
-<canvas id="pressedButtonCanvas"></canvas>
-<canvas id="normalFocusedButtonCanvas"></canvas>
-<canvas id="pressedFocusedButtonCanvas"></canvas>
-<canvas id="currentSnapshot"></canvas>
-
 </body>
 </html>
--- a/content/events/test/test_bug656379-1.html
+++ b/content/events/test/test_bug656379-1.html
@@ -46,21 +46,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 /** Test for Bug 426082 **/
 SimpleTest.waitForExplicitFinish();
 
 var normalButtonCanvas, pressedButtonCanvas, normalFocusedButtonCanvas,
     pressedFocusedButtonCanvas, currentSnapshot, button, label, outside;
 
 function runTests() {
-  normalButtonCanvas = $("normalButtonCanvas");
-  pressedButtonCanvas = $("pressedButtonCanvas");
-  normalFocusedButtonCanvas = $("normalFocusedButtonCanvas");
-  pressedFocusedButtonCanvas = $("pressedFocusedButtonCanvas");
-  currentSnapshot = $("currentSnapshot");
   button = $("button");
   label = $("label");
   outside = $("outside");
   SimpleTest.executeSoon(executeTests);
 }
 
 function isRectContainedInRectFromRegion(rect, region) {
   return Array.some(region, function (r) {
@@ -69,17 +64,17 @@ function isRectContainedInRectFromRegion
            rect.right <= r.right &&
            rect.bottom <= r.bottom;
   });
 }
 
 function paintListener(e) {
   if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
     gNeedsPaint = false;
-    takeSnapshot(currentSnapshot);
+    currentSnapshot = takeSnapshot();
   }
 }
 
 var gNeedsPaint = false;
 function executeTests() {
   var testYielder = tests();
   function execNext() {
     try {
@@ -91,41 +86,41 @@ function executeTests() {
       SimpleTest.executeSoon(execNext);
     } catch (e) {}
   }
   execNext();
 }
 
 function tests() {
   window.addEventListener("MozAfterPaint", paintListener, false);
-  takeSnapshot(normalButtonCanvas);
+  normalButtonCanvas = takeSnapshot();
   // Press the button.
   sendMouseEvent("mousemove", button);
   sendMouseEvent("mousedown", button);
   yield;
-  takeSnapshot(pressedFocusedButtonCanvas);
+  pressedFocusedButtonCanvas = takeSnapshot();
   compareSnapshots_(normalButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal buttons.");
   // Release.
   sendMouseEvent("mouseup", button);
   yield;
   // make sure the button is focused as this doesn't happen on click on Mac
   button.focus();
-  takeSnapshot(normalFocusedButtonCanvas);
+  normalFocusedButtonCanvas = takeSnapshot();
   compareSnapshots_(normalFocusedButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal focused buttons.");
   // Unfocus the button.
   sendMouseEvent("mousedown", outside);
   sendMouseEvent("mouseup", outside);
   yield;
 
   // Press the label.
   sendMouseEvent("mousemove", label);
   sendMouseEvent("mousedown", label);
   yield;
   compareSnapshots_(normalButtonCanvas, currentSnapshot, false, "Pressing the label should have pressed the button.");
-  takeSnapshot(pressedButtonCanvas);
+  pressedButtonCanvas = takeSnapshot();
   // Move the mouse down from the label.
   sendMouseEvent("mousemove", outside);
   yield;
   compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Moving the mouse down from the label should have unpressed the button.");
   // ... and up again.
   sendMouseEvent("mousemove", label);
   yield;
   compareSnapshots_(pressedButtonCanvas, currentSnapshot, true, "Moving the mouse back on top of the label should have pressed the button.");
@@ -164,35 +159,26 @@ function compareSnapshots_(c1, c2, shoul
     } else {
       ok(false, msg + " - expected something other than " + c1url);
     }
   }
 }
 
 function takeSnapshot(canvas) {
   var r = buttonRect();
-  var ctx = canvas.getContext("2d");
-  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-  canvas.width = r.width + 4;
-  canvas.height = r.height + 4;
-  ctx.clearRect(0, 0, canvas.width, canvas.height);
-  ctx.drawWindow(window, r.left - 2, r.top - 2, r.width + 4, r.height + 4, "#FFF");
+  adjustedRect = { left: r.left - 2, top: r.top - 2,
+                   width: r.width + 4, height: r.height + 4 };
+  return SpecialPowers.snapshotRect(window, adjustedRect);
 }
 
 function buttonRect() {
   return button.getBoundingClientRect();
 }
 
 
 </script>
 </pre>
 <p><input type="button" value="Button" id="button"></p>
 <p><label for="button" id="label">Label</label></p>
 <p id="outside">Something under the label</p>
 
-<canvas id="normalButtonCanvas"></canvas>
-<canvas id="pressedButtonCanvas"></canvas>
-<canvas id="normalFocusedButtonCanvas"></canvas>
-<canvas id="pressedFocusedButtonCanvas"></canvas>
-<canvas id="currentSnapshot"></canvas>
-
 </body>
 </html>
--- a/content/html/document/src/MediaDocument.cpp
+++ b/content/html/document/src/MediaDocument.cpp
@@ -275,19 +275,19 @@ MediaDocument::CreateSyntheticDocument()
 
 nsresult
 MediaDocument::StartLayout()
 {
   mMayStartLayout = true;
   nsCOMPtr<nsIPresShell> shell = GetShell();
   // Don't mess with the presshell if someone has already handled
   // its initial reflow.
-  if (shell && !shell->DidInitialReflow()) {
+  if (shell && !shell->DidInitialize()) {
     nsRect visibleArea = shell->GetPresContext()->GetVisibleArea();
-    nsresult rv = shell->InitialReflow(visibleArea.width, visibleArea.height);
+    nsresult rv = shell->Initialize(visibleArea.width, visibleArea.height);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 void
 MediaDocument::GetFileName(nsAString& aResult)
--- a/content/html/document/src/PluginDocument.cpp
+++ b/content/html/document/src/PluginDocument.cpp
@@ -234,17 +234,17 @@ PluginDocument::StartDocumentLoad(const 
   NS_ADDREF(*aDocListener = mStreamListener);
 
   return rv;
 }
 
 nsresult
 PluginDocument::CreateSyntheticPluginDocument()
 {
-  NS_ASSERTION(!GetShell() || !GetShell()->DidInitialReflow(),
+  NS_ASSERTION(!GetShell() || !GetShell()->DidInitialize(),
                "Creating synthetic plugin document content too late");
 
   // make our generic document
   nsresult rv = MediaDocument::CreateSyntheticDocument();
   NS_ENSURE_SUCCESS(rv, rv);
   // then attach our plugin
 
   Element* body = GetBodyElement();
--- a/content/smil/test/test_smilExtDoc.xhtml
+++ b/content/smil/test/test_smilExtDoc.xhtml
@@ -45,23 +45,19 @@ function pageShow()
   window.setTimeout(checkResult, 0);
 }
 
 function checkResult()
 {
   var content = document.getElementById("content");
   var bbox = content.getBoundingClientRect();
 
-  var canvas = document.createElement("canvas");
+  var canvas = SpecialPowers.snapshotRect(window, bbox);
   var ctx = canvas.getContext("2d");
 
-  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-  ctx.drawWindow(window, bbox.left, bbox.top, bbox.width, bbox.height,
-                 "rgb(255,255,255)");
-
   var imgd = ctx.getImageData(bbox.width/2, bbox.height/2, 1, 1);
   var isGreen = (imgd.data[0] == 0) &&
                 (imgd.data[1] == 255) &&
                 (imgd.data[2] == 0);
   if (isGreen) {
     ok(true, "Filter is animated as expected");
   } else if (accumulatedWaitTime >= POLL_TIMEOUT) {
     ok(false, "No animation detected after waiting " + POLL_TIMEOUT + "ms");
--- a/content/test/reftest/reftest.list
+++ b/content/test/reftest/reftest.list
@@ -1,8 +1,13 @@
+# Canvas reftests
+# From: /content/test/reftest
+# To:   /content/canvas/test/reftest
+skip-if(xulFennec) include ../../canvas/test/reftest/reftest.list
+
 == bug453105.html bug453105-ref.html
 == optiontext.html optiontext-ref.html
 == bug456008.xhtml bug456008-ref.html
 == bug439965.html bug439965-ref.html
 == bug427779.xml bug427779-ref.xml
 == bug559996.html bug559996-ref.html
 == bug591981-1.html bug591981-ref.html
 == bug591981-2.html bug591981-ref.html
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -1988,17 +1988,17 @@ nsXULDocument::StartLayout(void)
 
         nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
         NS_ASSERTION(docShell != nullptr, "container is not a docshell");
         if (! docShell)
             return NS_ERROR_UNEXPECTED;
 
         nsresult rv = NS_OK;
         nsRect r = cx->GetVisibleArea();
-        rv = shell->InitialReflow(r.width, r.height);
+        rv = shell->Initialize(r.width, r.height);
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
     return NS_OK;
 }
 
 /* static */
 bool
@@ -3860,17 +3860,17 @@ nsForwardReference::Result
 nsXULDocument::OverlayForwardReference::Resolve()
 {
     // Resolve a forward reference from an overlay element; attempt to
     // hook it up into the main document.
     nsresult rv;
     nsCOMPtr<nsIContent> target;
 
     nsIPresShell *shell = mDocument->GetShell();
-    bool notify = shell && shell->DidInitialReflow();
+    bool notify = shell && shell->DidInitialize();
 
     nsAutoString id;
     mOverlay->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
     if (id.IsEmpty()) {
         // mOverlay is a direct child of <overlay> and has no id.
         // Insert it under the root element in the base document.
         Element* root = mDocument->GetRootElement();
         if (!root) {
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1541,21 +1541,21 @@ nsGlobalWindow::SetInitialPrincipalToSub
   }
 
   GetDocShell()->CreateAboutBlankContentViewer(newWindowPrincipal);
   mDoc->SetIsInitialDocument(true);
 
   nsCOMPtr<nsIPresShell> shell;
   GetDocShell()->GetPresShell(getter_AddRefs(shell));
 
-  if (shell && !shell->DidInitialReflow()) {
+  if (shell && !shell->DidInitialize()) {
     // Ensure that if someone plays with this document they will get
     // layout happening.
     nsRect r = shell->GetPresContext()->GetVisibleArea();
-    shell->InitialReflow(r.width, r.height);
+    shell->Initialize(r.width, r.height);
   }
 }
 
 PopupControlState
 PushPopupControlState(PopupControlState aState, bool aForce)
 {
   PopupControlState oldState = gPopupControlState;
 
--- a/dom/bluetooth/BluetoothService.h
+++ b/dom/bluetooth/BluetoothService.h
@@ -225,19 +225,20 @@ public:
    *
    * @return True if path set correctly, false otherwise
    */
   virtual bool
   GetDevicePath(const nsAString& aAdapterPath,
                 const nsAString& aDeviceAddress,
                 nsAString& aDevicePath) = 0;
 
-  virtual nsTArray<uint32_t>
+  virtual bool
   AddReservedServicesInternal(const nsAString& aAdapterPath,
-                              const nsTArray<uint32_t>& aServices) = 0;
+                              const nsTArray<uint32_t>& aServices,
+                              nsTArray<uint32_t>& aServiceHandlesContainer) = 0;
 
   virtual bool
   RemoveReservedServicesInternal(const nsAString& aAdapterPath,
                                  const nsTArray<uint32_t>& aServiceHandles) = 0;
 
   virtual nsresult
   CreatePairedDeviceInternal(const nsAString& aAdapterPath,
                              const nsAString& aAddress,
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -1469,42 +1469,41 @@ ExtractHandles(DBusMessage *aReply, nsTA
         aOutHandles.AppendElement(handles[i]);
       }
     }
   } else {
     LOG_AND_FREE_DBUS_ERROR(&err);
   }
 }
 
-nsTArray<uint32_t>
+bool
 BluetoothDBusService::AddReservedServicesInternal(const nsAString& aAdapterPath,
-                                                  const nsTArray<uint32_t>& aServices)
+                                                  const nsTArray<uint32_t>& aServices, 
+                                                  nsTArray<uint32_t>& aServiceHandlesContainer)
 {
   MOZ_ASSERT(!NS_IsMainThread());
 
-  nsTArray<uint32_t> ret;
-
   int length = aServices.Length();
-  if (length == 0) return ret;
+  if (length == 0) return false;
 
   const uint32_t* services = aServices.Elements();
   DBusMessage* reply =
     dbus_func_args(gThreadConnection->GetConnection(),
                    NS_ConvertUTF16toUTF8(aAdapterPath).get(),
                    DBUS_ADAPTER_IFACE, "AddReservedServiceRecords",
                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
                    &services, length, DBUS_TYPE_INVALID);
 
   if (!reply) {
     LOG("Null DBus message. Couldn't extract handles.");
-    return ret;
+    return false;
   }
 
-  ExtractHandles(reply, ret);
-  return ret;
+  ExtractHandles(reply, aServiceHandlesContainer);
+  return true;
 }
 
 bool
 BluetoothDBusService::RemoveReservedServicesInternal(const nsAString& aAdapterPath,
                                                      const nsTArray<uint32_t>& aServiceHandles)
 {
   MOZ_ASSERT(!NS_IsMainThread());
 
--- a/dom/bluetooth/linux/BluetoothDBusService.h
+++ b/dom/bluetooth/linux/BluetoothDBusService.h
@@ -42,19 +42,20 @@ public:
               const nsAString& aPath,
               const BluetoothNamedValue& aValue,
               BluetoothReplyRunnable* aRunnable);
   virtual bool
   GetDevicePath(const nsAString& aAdapterPath,
                 const nsAString& aDeviceAddress,
                 nsAString& aDevicePath);
 
-  virtual nsTArray<uint32_t>
+  virtual bool
   AddReservedServicesInternal(const nsAString& aAdapterPath,
-                              const nsTArray<uint32_t>& aServices);
+                              const nsTArray<uint32_t>& aServices,
+                              nsTArray<uint32_t>& aServiceHandlesContainer);
 
   virtual bool
   RemoveReservedServicesInternal(const nsAString& aAdapterPath,
                                  const nsTArray<uint32_t>& aServiceHandles);
 
   virtual nsresult
   GetSocketViaService(const nsAString& aObjectPath,
                       const nsAString& aService,
--- a/dom/devicestorage/ipc/test_ipc.html
+++ b/dom/devicestorage/ipc/test_ipc.html
@@ -66,16 +66,29 @@
           default:
             info(details);
         }
       }
     }
 
     function onTestComplete() {
       let comp = SpecialPowers.wrap(Components);
+      let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
+      let spObserver = comp.classes["@mozilla.org/special-powers-observer;1"]
+                            .getService(comp.interfaces.nsIMessageListener);
+
+      mm.removeMessageListener("SPPrefService", spObserver);
+      mm.removeMessageListener("SPProcessCrashService", spObserver);
+      mm.removeMessageListener("SPPingService", spObserver);
+      mm.removeMessageListener("SpecialPowers.Quit", spObserver);
+      mm.removeMessageListener("SPPermissionManager", spObserver);
+
+      mm.removeMessageListener("test:DeviceStorage:ipcTestMessage", onTestMessage);
+      mm.removeMessageListener("test:DeviceStorage:ipcTestComplete", onTestComplete);
+
       SimpleTest.executeSoon(function () { SimpleTest.finish(); });
     }
 
     function runTests() {
       let iframe = document.createElement("iframe");
       iframe.mozbrowser = true;
       iframe.id = "iframe";
       iframe.style.width = "100%";
--- a/dom/system/gonk/AudioManager.cpp
+++ b/dom/system/gonk/AudioManager.cpp
@@ -23,16 +23,21 @@
 
 using namespace mozilla::dom::gonk;
 using namespace android;
 using namespace mozilla::hal;
 using namespace mozilla;
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "AudioManager" , ## args) 
 
+#define HEADPHONES_STATUS_CHANGED "headphones-status-changed"
+#define HEADPHONES_STATUS_ON      NS_LITERAL_STRING("on").get()
+#define HEADPHONES_STATUS_OFF     NS_LITERAL_STRING("off").get()
+#define HEADPHONES_STATUS_UNKNOWN NS_LITERAL_STRING("unknown").get()
+
 NS_IMPL_ISUPPORTS1(AudioManager, nsIAudioManager)
 
 static AudioSystem::audio_devices
 GetRoutingMode(int aType) {
   if (aType == nsIAudioManager::FORCE_SPEAKER) {
     return AudioSystem::DEVICE_OUT_SPEAKER;
   } else if (aType == nsIAudioManager::FORCE_HEADPHONES) {
     return AudioSystem::DEVICE_OUT_WIRED_HEADSET;
@@ -56,21 +61,21 @@ InternalSetAudioRoutes(SwitchState aStat
 }
 
 static void
 NotifyHeadphonesStatus(SwitchState aState)
 {
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     if (aState == SWITCH_STATE_ON) {
-      obs->NotifyObservers(nullptr, "headphones-status", NS_LITERAL_STRING("on").get());
+      obs->NotifyObservers(nullptr, HEADPHONES_STATUS_CHANGED, HEADPHONES_STATUS_ON);
     } else if (aState == SWITCH_STATE_OFF) {
-      obs->NotifyObservers(nullptr, "headphones-status", NS_LITERAL_STRING("off").get());
+      obs->NotifyObservers(nullptr, HEADPHONES_STATUS_CHANGED, HEADPHONES_STATUS_OFF);
     } else {
-      obs->NotifyObservers(nullptr, "headphones-status", NS_LITERAL_STRING("unknown").get());
+      obs->NotifyObservers(nullptr, HEADPHONES_STATUS_CHANGED, HEADPHONES_STATUS_UNKNOWN);
     }
   }
 }
 
 class HeadphoneSwitchObserver : public SwitchObserver
 {
 public:
   void Notify(const SwitchEvent& aEvent) {
--- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp
+++ b/dom/system/gonk/GonkGPSGeolocationProvider.cpp
@@ -570,26 +570,26 @@ GonkGPSGeolocationProvider::DataCallStat
   NS_ConvertUTF16toUTF8 currentApn(apn);
   const nsAdoptingCString& agpsApn = Preferences::GetCString("geo.gps.apn.name");
 
   // TODO: Bug 772748 - handle data call failed case.
   if (currentApn == agpsApn) {
     switch (callState) {
       case nsINetworkInterface::NETWORK_STATE_CONNECTED:
 #ifdef AGPS_HAVE_DUAL_APN
-        mAGpsInterface->data_conn_open(AGPS_TYPE_ANY,
+        mAGpsInterface->data_conn_open(AGPS_TYPE_SUPL,
                                        agpsApn.get(),
                                        AGPS_APN_BEARER_IPV4);
 #else
         mAGpsInterface->data_conn_open(agpsApn.get());
 #endif
         break;
       case nsINetworkInterface::NETWORK_STATE_DISCONNECTED:
 #ifdef AGPS_HAVE_DUAL_APN
-        mAGpsInterface->data_conn_closed(AGPS_TYPE_ANY);
+        mAGpsInterface->data_conn_closed(AGPS_TYPE_SUPL);
 #else
         mAGpsInterface->data_conn_closed();
 #endif
         break;
     }
   }
   return NS_OK;
 }
--- a/dom/tests/mochitest/general/test_focusrings.xul
+++ b/dom/tests/mochitest/general/test_focusrings.xul
@@ -33,24 +33,19 @@ function setOrRestoreTabFocus(newValue) 
     }
   } else {
     prefs.setIntPref("tabfocus", newValue);
   }
 }
 
 function snapShot(element) {
   var rect = element.getBoundingClientRect();
-  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-  var canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
-  canvas.setAttribute("width", rect.width + 12);
-  canvas.setAttribute("height", rect.height + 12);
-  var ctx = canvas.getContext("2d");
-  ctx.drawWindow(window, rect.left - 6, rect.top - 6, rect.width + 6, rect.height + 6,
-                 "transparent");
-  return canvas;
+  adjustedRect = { left: rect.left - 6, top: rect.top - 6,
+                   width: rect.width + 12, height: rect.height + 12 }
+  return SpecialPowers.snapshotRect(window, adjustedRect, "transparent");
 }
 
 function runTest()
 {
   setOrRestoreTabFocus(7);
 
   var isMac = (navigator.platform.indexOf("Mac") >= 0);
   var isWin = (navigator.platform.indexOf("Win") >= 0);
--- a/dom/webidl/CanvasRenderingContext2D.webidl
+++ b/dom/webidl/CanvasRenderingContext2D.webidl
@@ -140,28 +140,33 @@ interface CanvasRenderingContext2D {
   [SetterThrows]
   attribute DOMString mozTextStyle;
 
   // image smoothing mode -- if disabled, images won't be smoothed
   // if scaled.
   attribute boolean mozImageSmoothingEnabled;
 
   // Show the caret if appropriate when drawing
+  [ChromeOnly]
   const unsigned long DRAWWINDOW_DRAW_CARET   = 0x01;
   // Don't flush pending layout notifications that could otherwise
   // be batched up
+  [ChromeOnly]
   const unsigned long DRAWWINDOW_DO_NOT_FLUSH = 0x02;
   // Draw scrollbars and scroll the viewport if they are present
+  [ChromeOnly]
   const unsigned long DRAWWINDOW_DRAW_VIEW    = 0x04;
   // Use the widget layer manager if available. This means hardware
   // acceleration may be used, but it might actually be slower or
   // lower quality than normal. It will however more accurately reflect
   // the pixels rendered to the screen.
+  [ChromeOnly]
   const unsigned long DRAWWINDOW_USE_WIDGET_LAYERS = 0x08;
   // Don't synchronously decode images - draw what we have
+  [ChromeOnly]
   const unsigned long DRAWWINDOW_ASYNC_DECODE_IMAGES = 0x10;
 
   /**
    * Renders a region of a window into the canvas.  The contents of
    * the window's viewport are rendered, ignoring viewport clipping
    * and scrolling.
    *
    * @param x
@@ -188,23 +193,21 @@ interface CanvasRenderingContext2D {
    * because the user's background-color preference is applied,
    * but IFRAMEs are transparent if the page doesn't set a background.
    * -- If an opaque color is used for the background color, rendering
    * will be faster because we won't have to compute the window's
    * transparency.
    *
    * This API cannot currently be used by Web content. It is chrome
    * only.
-   * FIXME Bug 767931 - Mark drawWindow and asyncDrawXULElement as ChromeOnly
-   *                    in WebIDL
    */
-  [Throws]
+  [Throws, ChromeOnly]
   void drawWindow(Window window, double x, double y, double w, double h,
                   DOMString bgColor, optional unsigned long flags = 0);
-  [Throws]
+  [Throws, ChromeOnly]
   void asyncDrawXULElement(XULElement elem, double x, double y, double w,
                            double h, DOMString bgColor,
                            optional unsigned long flags = 0);
 };
 CanvasRenderingContext2D implements CanvasDrawingStyles;
 CanvasRenderingContext2D implements CanvasPathMethods;
 
 [NoInterfaceObject]
--- a/editor/libeditor/html/nsHTMLEditorStyle.cpp
+++ b/editor/libeditor/html/nsHTMLEditorStyle.cpp
@@ -870,19 +870,23 @@ nsresult nsHTMLEditor::RemoveStyleInside
                                                     &propertyValue,
                                                     false);
       // remove the node if it is a span or font, if its style attribute is
       // empty or absent, and if it does not have a class nor an id
       RemoveElementIfNoStyleOrIdOrClass(aNode);
     }
   }
 
-  if (aProperty == nsEditProperty::font &&    // or node is big or small and we are setting font size
+  if (!aChildrenOnly &&
+    (
+      (aProperty == nsEditProperty::font) &&    // or node is big or small and we are setting font size
       (nsHTMLEditUtils::IsBig(aNode) || nsHTMLEditUtils::IsSmall(aNode)) &&
-      aAttribute && aAttribute->LowerCaseEqualsLiteral("size")) {
+      (aAttribute && aAttribute->LowerCaseEqualsLiteral("size"))
+    )
+  ) {
     return RemoveContainer(aNode);  // if we are setting font size, remove any nested bigs and smalls
   }
   return NS_OK;
 }
 
 bool nsHTMLEditor::IsOnlyAttribute(nsIDOMNode *aNode, 
                                      const nsAString *aAttribute)
 {
--- a/gfx/2d/PathCairo.cpp
+++ b/gfx/2d/PathCairo.cpp
@@ -45,17 +45,16 @@ CairoPathContext::~CairoPathContext()
   cairo_destroy(mContext);
 }
 
 void
 CairoPathContext::DuplicateContextAndPath()
 {
   // Duplicate the path.
   cairo_path_t* path = cairo_copy_path(mContext);
-  cairo_fill_rule_t rule = cairo_get_fill_rule(mContext);
 
   // Duplicate the context.
   cairo_surface_t* surf = cairo_get_target(mContext);
   cairo_matrix_t matrix;
   cairo_get_matrix(mContext, &matrix);
   cairo_destroy(mContext);
 
   mContext = cairo_create(surf);
--- a/gfx/angle/AUTHORS
+++ b/gfx/angle/AUTHORS
@@ -10,8 +10,9 @@
 TransGaming Inc.
 
 Google Inc.
 
 3DLabs Inc. Ltd.
 
 Cloud Party, Inc.
 
+Jacek Caban <cjacek at gmail.com>
--- a/gfx/angle/README.mozilla
+++ b/gfx/angle/README.mozilla
@@ -1,11 +1,11 @@
 This is the ANGLE project, from http://code.google.com/p/angleproject/
 
-Current revision: r1242
+Current revision: r1267
 
 == Applied local patches ==
 
 In this order:
 
   angle-renaming-debug.patch
     rename debug.h to compilerdebug.h to avoid conflict in our makefiles
 
--- a/gfx/angle/build/common.gypi
+++ b/gfx/angle/build/common.gypi
@@ -1,15 +1,19 @@
 # Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
 {
   'variables': {
     'component%': 'static_library',
+    # angle_code is set to 1 for the core ANGLE targets defined in src/build_angle.gyp.
+    # angle_code is set to 0 for test code, sample code, and third party code.
+    # When angle_code is 1, we build with additional warning flags on Mac and Linux.
+    'angle_code%': 0,
     'gcc_or_clang_warnings': [
       '-Wall',
       '-Wchar-subscripts',
       '-Werror',
       '-Wextra',
       '-Wformat=2',
       '-Winit-self',
       '-Wno-sign-compare',
@@ -141,16 +145,30 @@
             'cflags': [
               '-O>(debug_optimize)',
               '-g',
             ],
           }
         },
       },
     }],
+    ['angle_code==1', {
+      'target_defaults': {
+        'conditions': [
+          ['OS=="mac"', {
+            'xcode_settings': {
+              'WARNING_CFLAGS': ['<@(gcc_or_clang_warnings)']
+            },
+          }],
+          ['OS!="win" and OS!="mac"', {
+            'cflags': ['<@(gcc_or_clang_warnings)']
+          }],
+        ]
+      }
+    }],
   ],
 }
 
 # Local Variables:
 # tab-width:2
 # indent-tabs-mode:nil
 # End:
 # vim: set expandtab tabstop=2 shiftwidth=2:
--- a/gfx/angle/src/build_angle.gyp
+++ b/gfx/angle/src/build_angle.gyp
@@ -1,13 +1,16 @@
 # Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
 {
+  'variables': {
+    'angle_code': 1,
+  },
   'target_defaults': {
     'defines': [
       'ANGLE_DISABLE_TRACE',
       'ANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL0',
       'ANGLE_USE_NEW_PREPROCESSOR=1',
     ],
   },
   'targets': [
@@ -38,26 +41,16 @@
         'compiler/preprocessor/new/Preprocessor.cpp',
         'compiler/preprocessor/new/Preprocessor.h',
         'compiler/preprocessor/new/SourceLocation.h',
         'compiler/preprocessor/new/Token.cpp',
         'compiler/preprocessor/new/Token.h',
         'compiler/preprocessor/new/Tokenizer.cpp',
         'compiler/preprocessor/new/Tokenizer.h',
       ],
-      'conditions': [
-        ['OS=="mac"', {
-          'xcode_settings': {
-            'WARNING_CFLAGS': ['<@(gcc_or_clang_warnings)']
-          },
-        }],
-        ['OS=="linux"', {
-          'cflags': ['<@(gcc_or_clang_warnings)']
-        }],
-      ],
     },
     {
       'target_name': 'translator_common',
       'type': 'static_library',
       'dependencies': ['preprocessor'],
       'include_dirs': [
         '.',
         '../include',
@@ -159,24 +152,16 @@
         'compiler/timing/RestrictVertexShaderTiming.h',
       ],
       'conditions': [
         ['OS=="win"', {
           'sources': ['compiler/ossource_win.cpp'],
         }, { # else: posix
           'sources': ['compiler/ossource_posix.cpp'],
         }],
-        ['OS=="mac"', {
-          'xcode_settings': {
-            'WARNING_CFLAGS': ['<@(gcc_or_clang_warnings)']
-          },
-        }],
-        ['OS=="linux"', {
-          'cflags': ['<@(gcc_or_clang_warnings)']
-        }],
       ],
     },
     {
       'target_name': 'translator_glsl',
       'type': '<(component)',
       'dependencies': ['translator_common'],
       'include_dirs': [
         '.',
@@ -196,26 +181,16 @@
         'compiler/ShaderLang.cpp',
         'compiler/TranslatorESSL.cpp',
         'compiler/TranslatorESSL.h',
         'compiler/TranslatorGLSL.cpp',
         'compiler/TranslatorGLSL.h',
         'compiler/VersionGLSL.cpp',
         'compiler/VersionGLSL.h',
       ],
-      'conditions': [
-        ['OS=="mac"', {
-          'xcode_settings': {
-            'WARNING_CFLAGS': ['<@(gcc_or_clang_warnings)']
-          },
-        }],
-        ['OS=="linux"', {
-          'cflags': ['<@(gcc_or_clang_warnings)']
-        }],
-      ],
     },
   ],
   'conditions': [
     ['OS=="win"', {
       'targets': [
         {
           'target_name': 'translator_hlsl',
           'type': '<(component)',
@@ -290,16 +265,17 @@
             'libGLESv2/Query.cpp',
             'libGLESv2/Renderbuffer.cpp',
             'libGLESv2/Renderbuffer.h',
             'libGLESv2/ResourceManager.cpp',
             'libGLESv2/ResourceManager.h',
             'libGLESv2/Shader.cpp',
             'libGLESv2/Shader.h',
             'libGLESv2/Texture.cpp',
+            'libGLESv2/TextureSSE2.cpp',
             'libGLESv2/Texture.h',
             'libGLESv2/utilities.cpp',
             'libGLESv2/utilities.h',
           ],
           'msvs_settings': {
             'VCLinkerTool': {
               'AdditionalLibraryDirectories': ['$(DXSDK_DIR)/lib/x86'],
               'AdditionalDependencies': [
--- a/gfx/angle/src/common/angleutils.h
+++ b/gfx/angle/src/common/angleutils.h
@@ -14,9 +14,13 @@
 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
   TypeName(const TypeName&);               \
   void operator=(const TypeName&)
 
 #if defined(_MSC_VER)
 #define snprintf _snprintf
 #endif
 
+#define VENDOR_ID_AMD 0x1002
+#define VENDOR_ID_INTEL 0x8086
+#define VENDOR_ID_NVIDIA 0x10DE
+
 #endif // COMMON_ANGLEUTILS_H_
--- a/gfx/angle/src/common/debug.h
+++ b/gfx/angle/src/common/debug.h
@@ -37,38 +37,40 @@ namespace gl
         DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper);
     };
 }
 
 // A macro to output a trace of a function call and its arguments to the debugging log
 #if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF)
 #define TRACE(message, ...) (void(0))
 #else
-#define TRACE(message, ...) gl::trace(true, "trace: %s(%d): "message"\n", __FUNCTION__, __LINE__, __VA_ARGS__)
+#define TRACE(message, ...) gl::trace(true, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
 #endif
 
 // A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing.
 #if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF)
 #define FIXME(message, ...) (void(0))
 #else
-#define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): "message"\n", __FUNCTION__, __LINE__, __VA_ARGS__)
+#define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
 #endif
 
 // A macro to output a function call and its arguments to the debugging log, in case of error.
 #if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF)
 #define ERR(message, ...) (void(0))
 #else
-#define ERR(message, ...) gl::trace(false, "err: %s(%d): "message"\n", __FUNCTION__, __LINE__, __VA_ARGS__)
+#define ERR(message, ...) gl::trace(false, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
 #endif
 
 // A macro to log a performance event around a scope.
 #if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF)
 #define EVENT(message, ...) (void(0))
+#elif defined(_MSC_VER)
+#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__(__FUNCTION__ message "\n", __VA_ARGS__);
 #else
-#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__(__FUNCTION__ message "\n", __VA_ARGS__);
+#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper(message "\n", ##__VA_ARGS__);
 #endif
 
 // A macro asserting a condition and outputting failures to the debug log
 #if !defined(NDEBUG)
 #define ASSERT(expression) do { \
     if(!(expression)) \
         ERR("\t! Assert failed in %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
         assert(expression); \
--- a/gfx/angle/src/common/version.h
+++ b/gfx/angle/src/common/version.h
@@ -1,10 +1,10 @@
 #define MAJOR_VERSION 1
 #define MINOR_VERSION 0
 #define BUILD_VERSION 0
-#define BUILD_REVISION 1242
+#define BUILD_REVISION 1267
 
 #define STRINGIFY(x) #x
 #define MACRO_STRINGIFY(x) STRINGIFY(x)
 
 #define REVISION_STRING MACRO_STRINGIFY(BUILD_REVISION)
 #define VERSION_STRING MACRO_STRINGIFY(MAJOR_VERSION) "." MACRO_STRINGIFY(MINOR_VERSION) "." MACRO_STRINGIFY(BUILD_VERSION) "." MACRO_STRINGIFY(BUILD_REVISION)
--- a/gfx/angle/src/compiler/RenameFunction.h
+++ b/gfx/angle/src/compiler/RenameFunction.h
@@ -24,13 +24,13 @@ public:
     {
         TOperator op = node->getOp();
         if ((op == EOpFunction || op == EOpFunctionCall) && node->getName() == mOldFunctionName)
             node->setName(mNewFunctionName);
         return true;
     }
 
 private:
-    const TString& mOldFunctionName;
-    const TString& mNewFunctionName;
+    const TString mOldFunctionName;
+    const TString mNewFunctionName;
 };
 
 #endif  // COMPILER_RENAME_FUNCTION
--- a/gfx/angle/src/compiler/glslang.y
+++ b/gfx/angle/src/compiler/glslang.y
@@ -332,28 +332,20 @@ postfix_expression
                 $$ = context->addConstVectorNode(fields, $1, $3.line);
                 if ($$ == 0) {
                     context->recover();
                     $$ = $1;
                 }
                 else
                     $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size()));
             } else {
-                if (fields.num == 1) {
-                    ConstantUnion *unionArray = new ConstantUnion[1];
-                    unionArray->setIConst(fields.offsets[0]);
-                    TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
-                    $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
-                    $$->setType(TType($1->getBasicType(), $1->getPrecision()));
-                } else {
-                    TString vectorString = *$3.string;
-                    TIntermTyped* index = context->intermediate.addSwizzle(fields, $3.line);
-                    $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);
-                    $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size()));
-                }
+                TString vectorString = *$3.string;
+                TIntermTyped* index = context->intermediate.addSwizzle(fields, $3.line);
+                $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);
+                $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size()));
             }
         } else if ($1->isMatrix()) {
             TMatrixFields fields;
             if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
                 fields.wholeRow = false;
                 fields.wholeCol = false;
                 fields.row = 0;
                 fields.col = 0;
--- a/gfx/angle/src/compiler/glslang_tab.cpp
+++ b/gfx/angle/src/compiler/glslang_tab.cpp
@@ -653,36 +653,36 @@ static const yytype_int16 yyrhs[] =
       82,    -1,    19,    82,    -1,   176,    -1,   175,   176,    -1,
      177,    -1,   126,    -1,    -1,   127,   178,   161,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
        0,   165,   165,   200,   203,   216,   221,   226,   232,   235,
-     314,   317,   426,   436,   449,   457,   557,   560,   568,   572,
-     579,   583,   590,   596,   605,   613,   668,   675,   685,   688,
-     698,   708,   729,   730,   731,   736,   737,   746,   758,   759,
-     767,   778,   782,   783,   793,   803,   813,   826,   827,   837,
-     850,   854,   858,   862,   863,   876,   877,   890,   891,   904,
-     905,   922,   923,   936,   937,   938,   939,   940,   944,   947,
-     958,   966,   993,   998,  1005,  1043,  1046,  1053,  1061,  1082,
-    1103,  1114,  1143,  1148,  1158,  1163,  1173,  1176,  1179,  1182,
-    1188,  1195,  1198,  1220,  1238,  1262,  1285,  1289,  1307,  1315,
-    1347,  1367,  1456,  1465,  1488,  1491,  1497,  1505,  1513,  1521,
-    1531,  1538,  1541,  1544,  1550,  1553,  1568,  1572,  1576,  1580,
-    1589,  1594,  1599,  1604,  1609,  1614,  1619,  1624,  1629,  1634,
-    1640,  1646,  1652,  1657,  1662,  1671,  1680,  1685,  1698,  1698,
-    1712,  1712,  1721,  1724,  1739,  1775,  1779,  1785,  1793,  1809,
-    1813,  1817,  1818,  1824,  1825,  1826,  1827,  1828,  1832,  1833,
-    1833,  1833,  1843,  1844,  1848,  1848,  1849,  1849,  1854,  1857,
-    1867,  1870,  1876,  1877,  1881,  1889,  1893,  1903,  1908,  1925,
-    1925,  1930,  1930,  1937,  1937,  1945,  1948,  1954,  1957,  1963,
-    1967,  1974,  1981,  1988,  1995,  2006,  2015,  2019,  2026,  2029,
-    2035,  2035
+     314,   317,   418,   428,   441,   449,   549,   552,   560,   564,
+     571,   575,   582,   588,   597,   605,   660,   667,   677,   680,
+     690,   700,   721,   722,   723,   728,   729,   738,   750,   751,
+     759,   770,   774,   775,   785,   795,   805,   818,   819,   829,
+     842,   846,   850,   854,   855,   868,   869,   882,   883,   896,
+     897,   914,   915,   928,   929,   930,   931,   932,   936,   939,
+     950,   958,   985,   990,   997,  1035,  1038,  1045,  1053,  1074,
+    1095,  1106,  1135,  1140,  1150,  1155,  1165,  1168,  1171,  1174,
+    1180,  1187,  1190,  1212,  1230,  1254,  1277,  1281,  1299,  1307,
+    1339,  1359,  1448,  1457,  1480,  1483,  1489,  1497,  1505,  1513,
+    1523,  1530,  1533,  1536,  1542,  1545,  1560,  1564,  1568,  1572,
+    1581,  1586,  1591,  1596,  1601,  1606,  1611,  1616,  1621,  1626,
+    1632,  1638,  1644,  1649,  1654,  1663,  1672,  1677,  1690,  1690,
+    1704,  1704,  1713,  1716,  1731,  1767,  1771,  1777,  1785,  1801,
+    1805,  1809,  1810,  1816,  1817,  1818,  1819,  1820,  1824,  1825,
+    1825,  1825,  1835,  1836,  1840,  1840,  1841,  1841,  1846,  1849,
+    1859,  1862,  1868,  1869,  1873,  1881,  1885,  1895,  1900,  1917,
+    1917,  1922,  1922,  1929,  1929,  1937,  1940,  1946,  1949,  1955,
+    1959,  1966,  1973,  1980,  1987,  1998,  2007,  2011,  2018,  2021,
+    2027,  2027
 };
 #endif
 
 #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
 {
@@ -2266,28 +2266,20 @@ yyreduce:
                 (yyval.interm.intermTypedNode) = context->addConstVectorNode(fields, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].lex).line);
                 if ((yyval.interm.intermTypedNode) == 0) {
                     context->recover();
                     (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
                 }
                 else
                     (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqConst, (int) (*(yyvsp[(3) - (3)].lex).string).size()));
             } else {
-                if (fields.num == 1) {
-                    ConstantUnion *unionArray = new ConstantUnion[1];
-                    unionArray->setIConst(fields.offsets[0]);
-                    TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(3) - (3)].lex).line);
-                    (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line);
-                    (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision()));
-                } else {
-                    TString vectorString = *(yyvsp[(3) - (3)].lex).string;
-                    TIntermTyped* index = context->intermediate.addSwizzle(fields, (yyvsp[(3) - (3)].lex).line);
-                    (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpVectorSwizzle, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line);
-                    (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (int) vectorString.size()));
-                }
+                TString vectorString = *(yyvsp[(3) - (3)].lex).string;
+                TIntermTyped* index = context->intermediate.addSwizzle(fields, (yyvsp[(3) - (3)].lex).line);
+                (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpVectorSwizzle, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line);
+                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (int) vectorString.size()));
             }
         } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isMatrix()) {
             TMatrixFields fields;
             if (! context->parseMatrixFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yyvsp[(3) - (3)].lex).line)) {
                 fields.wholeRow = false;
                 fields.wholeCol = false;
                 fields.row = 0;
                 fields.col = 0;
--- a/gfx/angle/src/libEGL/Display.cpp
+++ b/gfx/angle/src/libEGL/Display.cpp
@@ -191,16 +191,22 @@ bool Display::initialize()
         if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) {mMinSwapInterval = std::min(mMinSwapInterval, 0); mMaxSwapInterval = std::max(mMaxSwapInterval, 0);}
         if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)       {mMinSwapInterval = std::min(mMinSwapInterval, 1); mMaxSwapInterval = std::max(mMaxSwapInterval, 1);}
         if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)       {mMinSwapInterval = std::min(mMinSwapInterval, 2); mMaxSwapInterval = std::max(mMaxSwapInterval, 2);}
         if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)     {mMinSwapInterval = std::min(mMinSwapInterval, 3); mMaxSwapInterval = std::max(mMaxSwapInterval, 3);}
         if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)      {mMinSwapInterval = std::min(mMinSwapInterval, 4); mMaxSwapInterval = std::max(mMaxSwapInterval, 4);}
 
         mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
 
+        // ATI cards on XP have problems with non-power-of-two textures.
+        mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
+           !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
+           !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
+           !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD);
+
         const D3DFORMAT renderTargetFormats[] =
         {
             D3DFMT_A1R5G5B5,
         //  D3DFMT_A2R10G10B10,   // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
             D3DFMT_A8R8G8B8,
             D3DFMT_R5G6B5,
         //  D3DFMT_X1R5G5B5,      // Has no compatible OpenGL ES renderbuffer format
             D3DFMT_X8R8G8B8
@@ -1249,19 +1255,17 @@ bool Display::getVertexTextureSupport() 
 
     HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F);
 
     return SUCCEEDED(result);
 }
 
 bool Display::getNonPower2TextureSupport() const
 {
-    return !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
-           !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
-           !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
+    return mSupportsNonPower2Textures;
 }
 
 bool Display::getOcclusionQuerySupport() const
 {
     if (!isInitialized())
     {
         return false;
     }
--- a/gfx/angle/src/libEGL/Display.h
+++ b/gfx/angle/src/libEGL/Display.h
@@ -21,16 +21,29 @@
 #include <vector>
 
 #include "libGLESv2/Context.h"
 
 #include "libEGL/Config.h"
 #include "libEGL/ShaderCache.h"
 #include "libEGL/Surface.h"
 
+const int versionWindowsVista = MAKEWORD(0x00, 0x06);
+const int versionWindows7 = MAKEWORD(0x01, 0x06);
+
+// Return the version of the operating system in a format suitable for ordering
+// comparison.
+inline int getComparableOSVersion()
+{
+    DWORD version = GetVersion();
+    int majorVersion = LOBYTE(LOWORD(version));
+    int minorVersion = HIBYTE(LOWORD(version));
+    return MAKEWORD(minorVersion, majorVersion);
+}
+
 namespace egl
 {
 class Display
 {
   public:
     ~Display();
 
     bool initialize();
@@ -126,16 +139,17 @@ class Display
     D3DCAPS9 mDeviceCaps;
     D3DADAPTER_IDENTIFIER9 mAdapterIdentifier;
     HWND mDeviceWindow;
 
     bool mSceneStarted;
     EGLint mMaxSwapInterval;
     EGLint mMinSwapInterval;
     bool mSoftwareDevice;
+    bool mSupportsNonPower2Textures;
     
     typedef std::set<Surface*> SurfaceSet;
     SurfaceSet mSurfaceSet;
 
     ConfigSet mConfigSet;
 
     typedef std::set<gl::Context*> ContextSet;
     ContextSet mContextSet;
--- a/gfx/angle/src/libEGL/ShaderCache.h
+++ b/gfx/angle/src/libEGL/ShaderCache.h
@@ -6,17 +6,22 @@
 
 // Display.h: Defines egl::ShaderCache, a cache of Direct3D shader objects
 // keyed by their byte code.
 
 #ifndef LIBEGL_SHADER_CACHE_H_
 #define LIBEGL_SHADER_CACHE_H_
 
 #include <d3d9.h>
+
+#ifdef _MSC_VER
 #include <hash_map>
+#else
+#include <unordered_map>
+#endif
 
 namespace egl
 {
 template <typename ShaderObject>
 class ShaderCache
 {
   public:
     ShaderCache() : mDevice(NULL)
@@ -32,17 +37,17 @@ class ShaderCache
     void initialize(IDirect3DDevice9* device)
     {
         mDevice = device;
     }
 
     ShaderObject *create(const DWORD *function, size_t length)
     {
         std::string key(reinterpret_cast<const char*>(function), length);
-        Map::iterator it = mMap.find(key);
+        typename Map::iterator it = mMap.find(key);
         if (it != mMap.end())
         {
             it->second->AddRef();
             return it->second;
         }
         
         ShaderObject *shader;
         HRESULT result = createShader(function, &shader);
@@ -61,17 +66,17 @@ class ShaderCache
         shader->AddRef();
         mMap[key] = shader;
 
         return shader;
     }
 
     void clear()
     {
-        for (Map::iterator it = mMap.begin(); it != mMap.end(); ++it)
+        for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it)
         {
             it->second->Release();
         }
 
         mMap.clear();
     }
 
   private:
@@ -84,17 +89,25 @@ class ShaderCache
         return mDevice->CreateVertexShader(function, shader);
     }
 
     HRESULT createShader(const DWORD *function, IDirect3DPixelShader9 **shader)
     {
         return mDevice->CreatePixelShader(function, shader);
     }
 
-    typedef stdext::hash_map<std::string, ShaderObject*> Map;
+#ifndef HASH_MAP
+# ifdef _MSC_VER
+#  define HASH_MAP stdext::hash_map
+# else
+#  define HASH_MAP std::unordered_map
+# endif
+#endif
+
+    typedef HASH_MAP<std::string, ShaderObject*> Map;
     Map mMap;
 
     IDirect3DDevice9 *mDevice;
 };
 
 typedef ShaderCache<IDirect3DVertexShader9> VertexShaderCache;
 typedef ShaderCache<IDirect3DPixelShader9> PixelShaderCache;
 
--- a/gfx/angle/src/libEGL/Surface.cpp
+++ b/gfx/angle/src/libEGL/Surface.cpp
@@ -18,32 +18,16 @@
 #include "libEGL/main.h"
 #include "libEGL/Display.h"
 
 #include <dwmapi.h>
 
 namespace egl
 {
 
-namespace
-{
-const int versionWindowsVista = MAKEWORD(0x00, 0x06);
-const int versionWindows7 = MAKEWORD(0x01, 0x06);
-
-// Return the version of the operating system in a format suitable for ordering
-// comparison.
-int getComparableOSVersion()
-{
-    DWORD version = GetVersion();
-    int majorVersion = LOBYTE(LOWORD(version));
-    int minorVersion = HIBYTE(LOWORD(version));
-    return MAKEWORD(minorVersion, majorVersion);
-}
-}
-
 Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported) 
     : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
 {
     mSwapChain = NULL;
     mBackBuffer = NULL;
     mDepthStencil = NULL;
     mRenderTarget = NULL;
     mOffscreenTexture = NULL;
@@ -183,38 +167,18 @@ bool Surface::resetSwapChain(int backbuf
     {
         return false;
     }
 
     // Evict all non-render target textures to system memory and release all resources
     // before reallocating them to free up as much video memory as possible.
     device->EvictManagedResources();
 
-    D3DPRESENT_PARAMETERS presentParameters = {0};
     HRESULT result;
 
-    presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat;
-    // We set BackBufferCount = 1 even when we use D3DSWAPEFFECT_FLIPEX.
-    // We do this because DirectX docs are a bit vague whether to set this to 1
-    // or 2. The runtime seems to accept 1, so we speculate that either it is
-    // forcing it to 2 without telling us, or better, doing something smart
-    // behind the scenes knowing that we don't need more.
-    presentParameters.BackBufferCount = 1;
-    presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat;
-    presentParameters.EnableAutoDepthStencil = FALSE;
-    presentParameters.Flags = 0;
-    presentParameters.hDeviceWindow = getWindowHandle();
-    presentParameters.MultiSampleQuality = 0;                  // FIXME: Unimplemented
-    presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;   // FIXME: Unimplemented
-    presentParameters.PresentationInterval = mPresentInterval;
-    presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
-    presentParameters.Windowed = TRUE;
-    presentParameters.BackBufferWidth = backbufferWidth;
-    presentParameters.BackBufferHeight = backbufferHeight;
-
     // Release specific resources to free up memory for the new render target, while the
     // old render target still exists for the purpose of preserving its contents.
     if (mSwapChain)
     {
         mSwapChain->Release();
         mSwapChain = NULL;
     }
 
@@ -238,18 +202,18 @@ bool Surface::resetSwapChain(int backbuf
 
     mShareHandle = NULL;
     HANDLE *pShareHandle = NULL;
     if (!mWindow && mDisplay->shareHandleSupported())
     {
         pShareHandle = &mShareHandle;
     }
 
-    result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET,
-                                   presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle);
+    result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
+                                   mConfig->mRenderTargetFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle);
     if (FAILED(result))
     {
         ERR("Could not create offscreen texture: %08lX", result);
         release();
 
         if(isDeviceLostError(result))
         {
             mDisplay->notifyDeviceLost();
@@ -269,36 +233,65 @@ bool Surface::resetSwapChain(int backbuf
     if (oldRenderTarget)
     {
         RECT rect =
         {
             0, 0,
             mWidth, mHeight
         };
 
-        if (rect.right > static_cast<LONG>(presentParameters.BackBufferWidth))
+        if (rect.right > static_cast<LONG>(backbufferWidth))
         {
-            rect.right = presentParameters.BackBufferWidth;
+            rect.right = backbufferWidth;
         }
 
-        if (rect.bottom > static_cast<LONG>(presentParameters.BackBufferHeight))
+        if (rect.bottom > static_cast<LONG>(backbufferHeight))
         {
-            rect.bottom = presentParameters.BackBufferHeight;
+            rect.bottom = backbufferHeight;
         }
 
         mDisplay->endScene();
 
         result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
         ASSERT(SUCCEEDED(result));
 
         oldRenderTarget->Release();
     }
 
     if (mWindow)
     {
+        D3DPRESENT_PARAMETERS presentParameters = {0};
+        presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat;
+        presentParameters.BackBufferCount = 1;
+        presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat;
+        presentParameters.EnableAutoDepthStencil = FALSE;
+        presentParameters.Flags = 0;
+        presentParameters.hDeviceWindow = getWindowHandle();
+        presentParameters.MultiSampleQuality = 0;                  // FIXME: Unimplemented
+        presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;   // FIXME: Unimplemented
+        presentParameters.PresentationInterval = mPresentInterval;
+        presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+        presentParameters.Windowed = TRUE;
+        presentParameters.BackBufferWidth = backbufferWidth;
+        presentParameters.BackBufferHeight = backbufferHeight;
+
+        // http://crbug.com/140239
+        // http://crbug.com/143434
+        //
+        // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width
+        // when using the integrated Intel. This rounds the width up rather than down.
+        //
+        // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID
+        // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur.
+        D3DADAPTER_IDENTIFIER9* adapterIdentifier = mDisplay->getAdapterIdentifier();
+        if (adapterIdentifier->VendorId == VENDOR_ID_INTEL)
+        {
+            presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64;
+        }
+
         result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
 
         if (FAILED(result))
         {
             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
 
             ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
             release();
@@ -315,19 +308,18 @@ bool Surface::resetSwapChain(int backbuf
         }
 
         result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
         ASSERT(SUCCEEDED(result));
     }
 
     if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN)
     {
-        result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
-                                                   presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType,
-                                                   presentParameters.MultiSampleQuality, FALSE, &mDepthStencil, NULL);
+        result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, mConfig->mDepthStencilFormat, D3DMULTISAMPLE_NONE,
+                                                   0, FALSE, &mDepthStencil, NULL);
 
         if (FAILED(result))
         {
             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
 
             ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
             release();
 
@@ -338,18 +330,18 @@ bool Surface::resetSwapChain(int backbuf
             }
             else
             {
                 return error(EGL_BAD_ALLOC, false);
             }
         }
     }
 
-    mWidth = presentParameters.BackBufferWidth;
-    mHeight = presentParameters.BackBufferHeight;
+    mWidth = backbufferWidth;
+    mHeight = backbufferHeight;
 
     mPresentIntervalDirty = false;
     return true;
 }
 
 bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
 {
     if (!mSwapChain)
--- a/gfx/angle/src/libEGL/libEGL.cpp
+++ b/gfx/angle/src/libEGL/libEGL.cpp
@@ -177,17 +177,17 @@ const char *__stdcall eglQueryString(EGL
         {
           case EGL_CLIENT_APIS:
             return success("OpenGL_ES");
           case EGL_EXTENSIONS:
             return display->getExtensionString();
           case EGL_VENDOR:
             return success("Google Inc.");
           case EGL_VERSION:
-            return success("1.4 (ANGLE "VERSION_STRING")");
+            return success("1.4 (ANGLE " VERSION_STRING ")");
         }
 
         return error(EGL_BAD_PARAMETER, (const char*)NULL);
     }
     catch(std::bad_alloc&)
     {
         return error(EGL_BAD_ALLOC, (const char*)NULL);
     }
--- a/gfx/angle/src/libGLESv2/Context.cpp
+++ b/gfx/angle/src/libGLESv2/Context.cpp
@@ -15,21 +15,21 @@
 
 #include "libGLESv2/main.h"
 #include "libGLESv2/mathutil.h"
 #include "libGLESv2/utilities.h"
 #include "libGLESv2/Blit.h"
 #include "libGLESv2/ResourceManager.h"
 #include "libGLESv2/Buffer.h"
 #include "libGLESv2/Fence.h"
-#include "libGLESv2/FrameBuffer.h"
+#include "libGLESv2/Framebuffer.h"
 #include "libGLESv2/Program.h"
 #include "libGLESv2/ProgramBinary.h"
 #include "libGLESv2/Query.h"
-#include "libGLESv2/RenderBuffer.h"
+#include "libGLESv2/Renderbuffer.h"
 #include "libGLESv2/Shader.h"
 #include "libGLESv2/Texture.h"
 #include "libGLESv2/VertexDataManager.h"
 #include "libGLESv2/IndexDataManager.h"
 
 #undef near
 #undef far
 
@@ -364,16 +364,20 @@ void Context::makeCurrent(egl::Display *
     {
         defaultRenderTarget->Release();
     }
 
     if (depthStencil)
     {
         depthStencil->Release();
     }
+
+    // Reset pixel shader to null to work around a bug that only happens with Intel GPUs.
+    // http://crbug.com/110343
+    mDevice->SetPixelShader(NULL);
     
     markAllStateDirty();
 }
 
 // This function will set all of the state-related dirty flags, so that all state is set during next pre-draw.
 void Context::markAllStateDirty()
 {
     for (int t = 0; t < MAX_TEXTURE_IMAGE_UNITS; t++)
--- a/gfx/angle/src/libGLESv2/Context.h
+++ b/gfx/angle/src/libGLESv2/Context.h
@@ -12,18 +12,23 @@
 
 #define GL_APICALL
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 #define EGLAPI
 #include <EGL/egl.h>
 #include <d3d9.h>
 
+#include <string>
 #include <map>
+#ifdef _MSC_VER
 #include <hash_map>
+#else
+#include <unordered_map>
+#endif
 
 #include "common/angleutils.h"
 #include "common/RefCountObject.h"
 #include "libGLESv2/ResourceManager.h"
 #include "libGLESv2/HandleAllocator.h"
 
 namespace egl
 {
@@ -543,25 +548,33 @@ class Context
     egl::Display *mDisplay;
     IDirect3DDevice9 *mDevice;
 
     State mState;
 
     BindingPointer<Texture2D> mTexture2DZero;
     BindingPointer<TextureCubeMap> mTextureCubeMapZero;
 
-    typedef stdext::hash_map<GLuint, Framebuffer*> FramebufferMap;
+#ifndef HASH_MAP
+# ifdef _MSC_VER
+#  define HASH_MAP stdext::hash_map
+# else
+#  define HASH_MAP std::unordered_map
+# endif
+#endif
+
+    typedef HASH_MAP<GLuint, Framebuffer*> FramebufferMap;
     FramebufferMap mFramebufferMap;
     HandleAllocator mFramebufferHandleAllocator;
 
-    typedef stdext::hash_map<GLuint, Fence*> FenceMap;
+    typedef HASH_MAP<GLuint, Fence*> FenceMap;
     FenceMap mFenceMap;
     HandleAllocator mFenceHandleAllocator;
 
-    typedef stdext::hash_map<GLuint, Query*> QueryMap;
+    typedef HASH_MAP<GLuint, Query*> QueryMap;
     QueryMap mQueryMap;
     HandleAllocator mQueryHandleAllocator;
 
     std::string mExtensionString;
     std::string mRendererString;
 
     VertexDataManager *mVertexDataManager;
     IndexDataManager *mIndexDataManager;
--- a/gfx/angle/src/libGLESv2/Makefile.in
+++ b/gfx/angle/src/libGLESv2/Makefile.in
@@ -148,16 +148,17 @@ CPPSRCS += \
         Program.cpp \
         ProgramBinary.cpp \
         RefCountObject.cpp \
         Query.cpp \
         Renderbuffer.cpp \
         ResourceManager.cpp \
         Shader.cpp \
         Texture.cpp \
+        TextureSSE2.cpp \
         utilities.cpp \
         HandleAllocator.cpp \
         IndexDataManager.cpp \
         VertexDataManager.cpp \
         $(NULL)
 
 DEFFILE = $(srcdir)/libGLESv2.def
 RCFILE = $(srcdir)/libGLESv2.rc
--- a/gfx/angle/src/libGLESv2/ProgramBinary.cpp
+++ b/gfx/angle/src/libGLESv2/ProgramBinary.cpp
@@ -2104,19 +2104,21 @@ bool ProgramBinary::defineUniform(InfoLo
     }
 
     switch(constantDescription.Class)
     {
       case D3DXPC_STRUCT:
         {
             for (unsigned int arrayIndex = 0; arrayIndex < constantDescription.Elements; arrayIndex++)
             {
+                D3DXHANDLE elementHandle = mConstantTablePS->GetConstantElement(constantHandle, arrayIndex);
+
                 for (unsigned int field = 0; field < constantDescription.StructMembers; field++)
                 {
-                    D3DXHANDLE fieldHandle = mConstantTablePS->GetConstant(constantHandle, field);
+                    D3DXHANDLE fieldHandle = mConstantTablePS->GetConstant(elementHandle, field);
 
                     D3DXCONSTANT_DESC fieldDescription;
                     UINT descriptionCount = 1;
 
                     HRESULT result = mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount);
                     ASSERT(SUCCEEDED(result));
 
                     std::string structIndex = (constantDescription.Elements > 1) ? ("[" + str(arrayIndex) + "]") : "";
--- a/gfx/angle/src/libGLESv2/ProgramBinary.h
+++ b/gfx/angle/src/libGLESv2/ProgramBinary.h
@@ -6,18 +6,18 @@
 
 // Program.h: Defines the gl::Program class. Implements GL program objects
 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
 
 #ifndef LIBGLESV2_PROGRAM_BINARY_H_
 #define LIBGLESV2_PROGRAM_BINARY_H_
 
 #define GL_APICALL
-#include <gles2/gl2.h>
-#include <gles2/gl2ext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
 
 #include <d3dx9.h>
 #include <d3dcompiler.h>
 #include <string>
 #include <vector>
 
 #include "libGLESv2/Shader.h"
 #include "libGLESv2/Context.h"
--- a/gfx/angle/src/libGLESv2/ResourceManager.cpp
+++ b/gfx/angle/src/libGLESv2/ResourceManager.cpp
@@ -6,17 +6,17 @@
 
 // ResourceManager.cpp: Implements the gl::ResourceManager class, which tracks and 
 // retrieves objects which may be shared by multiple Contexts.
 
 #include "libGLESv2/ResourceManager.h"
 
 #include "libGLESv2/Buffer.h"
 #include "libGLESv2/Program.h"
-#include "libGLESv2/RenderBuffer.h"
+#include "libGLESv2/Renderbuffer.h"
 #include "libGLESv2/Shader.h"
 #include "libGLESv2/Texture.h"
 
 namespace gl
 {
 ResourceManager::ResourceManager()
 {
     mRefCount = 1;
--- a/gfx/angle/src/libGLESv2/ResourceManager.h
+++ b/gfx/angle/src/libGLESv2/ResourceManager.h
@@ -8,17 +8,21 @@
 // shared by multiple GL contexts.
 
 #ifndef LIBGLESV2_RESOURCEMANAGER_H_
 #define LIBGLESV2_RESOURCEMANAGER_H_
 
 #define GL_APICALL
 #include <GLES2/gl2.h>
 
+#ifdef _MSC_VER
 #include <hash_map>
+#else
+#include <unordered_map>
+#endif
 
 #include "common/angleutils.h"
 #include "libGLESv2/HandleAllocator.h"
 
 namespace gl
 {
 class Buffer;
 class Shader;
@@ -74,31 +78,39 @@ class ResourceManager
     void checkTextureAllocation(GLuint texture, TextureType type);
     void checkRenderbufferAllocation(GLuint renderbuffer);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(ResourceManager);
 
     std::size_t mRefCount;
 
-    typedef stdext::hash_map<GLuint, Buffer*> BufferMap;
+#ifndef HASH_MAP
+# ifdef _MSC_VER
+#  define HASH_MAP stdext::hash_map
+# else
+#  define HASH_MAP std::unordered_map
+# endif
+#endif
+
+    typedef HASH_MAP<GLuint, Buffer*> BufferMap;
     BufferMap mBufferMap;
     HandleAllocator mBufferHandleAllocator;
 
-    typedef stdext::hash_map<GLuint, Shader*> ShaderMap;
+    typedef HASH_MAP<GLuint, Shader*> ShaderMap;
     ShaderMap mShaderMap;
 
-    typedef stdext::hash_map<GLuint, Program*> ProgramMap;
+    typedef HASH_MAP<GLuint, Program*> ProgramMap;
     ProgramMap mProgramMap;
     HandleAllocator mProgramShaderHandleAllocator;
 
-    typedef stdext::hash_map<GLuint, Texture*> TextureMap;
+    typedef HASH_MAP<GLuint, Texture*> TextureMap;
     TextureMap mTextureMap;
     HandleAllocator mTextureHandleAllocator;
 
-    typedef stdext::hash_map<GLuint, Renderbuffer*> RenderbufferMap;
+    typedef HASH_MAP<GLuint, Renderbuffer*> RenderbufferMap;
     RenderbufferMap mRenderbufferMap;
     HandleAllocator mRenderbufferHandleAllocator;
 };
 
 }
 
 #endif // LIBGLESV2_RESOURCEMANAGER_H_
--- a/gfx/angle/src/libGLESv2/Shader.cpp
+++ b/gfx/angle/src/libGLESv2/Shader.cpp
@@ -7,17 +7,17 @@
 // Shader.cpp: Implements the gl::Shader class and its  derived classes
 // VertexShader and FragmentShader. Implements GL shader objects and related
 // functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
 
 #include "libGLESv2/Shader.h"
 
 #include <string>
 
-#include "GLSLANG/Shaderlang.h"
+#include "GLSLANG/ShaderLang.h"
 #include "libGLESv2/main.h"
 #include "libGLESv2/utilities.h"
 
 namespace gl
 {
 void *Shader::mFragmentCompiler = NULL;
 void *Shader::mVertexCompiler = NULL;
 
--- a/gfx/angle/src/libGLESv2/Shader.h
+++ b/gfx/angle/src/libGLESv2/Shader.h
@@ -10,16 +10,17 @@
 // 3.8 page 84.
 
 #ifndef LIBGLESV2_SHADER_H_
 #define LIBGLESV2_SHADER_H_
 
 #define GL_APICALL
 #include <GLES2/gl2.h>
 #include <d3dx9.h>
+#include <string>
 #include <list>
 #include <vector>
 
 #include "libGLESv2/ResourceManager.h"
 
 namespace gl
 {
 struct Varying
--- a/gfx/angle/src/libGLESv2/Texture.cpp
+++ b/gfx/angle/src/libGLESv2/Texture.cpp
@@ -8,17 +8,16 @@
 // Texture2D and TextureCubeMap. Implements GL texture objects and related
 // functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
 
 #include "libGLESv2/Texture.h"
 
 #include <d3dx9tex.h>
 
 #include <algorithm>
-#include <intrin.h>
 
 #include "common/debug.h"
 
 #include "libEGL/Display.h"
 
 #include "libGLESv2/main.h"
 #include "libGLESv2/mathutil.h"
 #include "libGLESv2/utilities.h"
@@ -469,56 +468,16 @@ void Image::loadAlphaData(GLsizei width,
             dest[4 * x + 0] = 0;
             dest[4 * x + 1] = 0;
             dest[4 * x + 2] = 0;
             dest[4 * x + 3] = source[x];
         }
     }
 }
 
-void Image::loadAlphaDataSSE2(GLsizei width, GLsizei height,
-                              int inputPitch, const void *input, size_t outputPitch, void *output) const
-{
-    const unsigned char *source = NULL;
-    unsigned int *dest = NULL;
-    __m128i zeroWide = _mm_setzero_si128();
-
-    for (int y = 0; y < height; y++)
-    {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
-
-        int x;
-        // Make output writes aligned
-        for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++)
-        {
-            dest[x] = static_cast<unsigned int>(source[x]) << 24;
-        }
-
-        for (; x + 7 < width; x += 8)
-        {
-            __m128i sourceData = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&source[x]));
-            // Interleave each byte to 16bit, make the lower byte to zero
-            sourceData = _mm_unpacklo_epi8(zeroWide, sourceData);
-            // Interleave each 16bit to 32bit, make the lower 16bit to zero
-            __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData);
-            __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData);
-
-            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo);
-            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi);
-        }
-
-        // Handle the remainder
-        for (; x < width; x++)
-        {
-            dest[x] = static_cast<unsigned int>(source[x]) << 24;
-        }
-    }
-}
-
 void Image::loadAlphaFloatData(GLsizei width, GLsizei height,
                                int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const float *source = NULL;
     float *dest = NULL;
 
     for (int y = 0; y < height; y++)
     {
@@ -766,58 +725,16 @@ void Image::loadRGBHalfFloatData(GLsizei
             dest[4 * x + 0] = source[x * 3 + 0];
             dest[4 * x + 1] = source[x * 3 + 1];
             dest[4 * x + 2] = source[x * 3 + 2];
             dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
         }
     }
 }
 
-void Image::loadRGBAUByteDataSSE2(GLsizei width, GLsizei height,
-                                  int inputPitch, const void *input, size_t outputPitch, void *output) const
-{
-    const unsigned int *source = NULL;
-    unsigned int *dest = NULL;
-    __m128i brMask = _mm_set1_epi32(0x00ff00ff);
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        int x = 0;
-
-        // Make output writes aligned
-        for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
-        {
-            unsigned int rgba = source[x];
-            dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
-        }
-
-        for (; x + 3 < width; x += 4)
-        {
-            __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x]));
-            // Mask out g and a, which don't change
-            __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
-            // Mask out b and r
-            __m128i brComponents = _mm_and_si128(sourceData, brMask);
-            // Swap b and r
-            __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
-            __m128i result = _mm_or_si128(gaComponents, brSwapped);
-            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result);
-        }
-
-        // Perform leftover writes
-        for (; x < width; x++)
-        {
-            unsigned int rgba = source[x];
-            dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
-        }
-    }
-}
-
 void Image::loadRGBAUByteData(GLsizei width, GLsizei height,
                               int inputPitch, const void *input, size_t outputPitch, void *output) const
 {
     const unsigned int *source = NULL;
     unsigned int *dest = NULL;
     for (int y = 0; y < height; y++)
     {
         source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libGLESv2/TextureSSE2.cpp
@@ -0,0 +1,100 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureSSE2.cpp: Implements SSE2-based functions of gl::Image class. It's
+// in a separated file for GCC, which can enable SSE usage only per-file,
+// not for code blocks that use SSE2 explicitly.
+
+#include "libGLESv2/Texture.h"
+
+#include <intrin.h>
+
+namespace gl
+{
+
+void Image::loadRGBAUByteDataSSE2(GLsizei width, GLsizei height,
+                                  int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned int *source = NULL;
+    unsigned int *dest = NULL;
+    __m128i brMask = _mm_set1_epi32(0x00ff00ff);
+
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
+        int x = 0;
+
+        // Make output writes aligned
+        for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
+        {
+            unsigned int rgba = source[x];
+            dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+        }
+
+        for (; x + 3 < width; x += 4)
+        {
+            __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x]));
+            // Mask out g and a, which don't change
+            __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
+            // Mask out b and r
+            __m128i brComponents = _mm_and_si128(sourceData, brMask);
+            // Swap b and r
+            __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
+            __m128i result = _mm_or_si128(gaComponents, brSwapped);
+            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result);
+        }
+
+        // Perform leftover writes
+        for (; x < width; x++)
+        {
+            unsigned int rgba = source[x];
+            dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+        }
+    }
+}
+
+void Image::loadAlphaDataSSE2(GLsizei width, GLsizei height,
+                              int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned char *source = NULL;
+    unsigned int *dest = NULL;
+    __m128i zeroWide = _mm_setzero_si128();
+
+    for (int y = 0; y < height; y++)
+    {
+        source = static_cast<const unsigned char*>(input) + y * inputPitch;
+        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
+
+        int x;
+        // Make output writes aligned
+        for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++)
+        {
+            dest[x] = static_cast<unsigned int>(source[x]) << 24;
+        }
+
+        for (; x + 7 < width; x += 8)
+        {
+            __m128i sourceData = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&source[x]));
+            // Interleave each byte to 16bit, make the lower byte to zero
+            sourceData = _mm_unpacklo_epi8(zeroWide, sourceData);
+            // Interleave each 16bit to 32bit, make the lower 16bit to zero
+            __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData);
+            __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData);
+
+            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo);
+            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi);
+        }
+
+        // Handle the remainder
+        for (; x < width; x++)
+        {
+            dest[x] = static_cast<unsigned int>(source[x]) << 24;
+        }
+    }
+}
+
+}
--- a/gfx/angle/src/libGLESv2/VertexDataManager.cpp
+++ b/gfx/angle/src/libGLESv2/VertexDataManager.cpp
@@ -385,21 +385,21 @@ template <int size> struct WidenRule<D3D
 template <int size> struct WidenRule<D3DVT_USHORT_NORM, size>    : gl::WidenToEven<size> { };
 
 // VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
 template <unsigned int d3dtype, int size>
 struct VertexTypeFlags
 {
 };
 
-template <unsigned int capflag, unsigned int declflag>
+template <unsigned int _capflag, unsigned int _declflag>
 struct VertexTypeFlagsHelper
 {
-    enum { capflag = capflag };
-    enum { declflag = declflag };
+    enum { capflag = _capflag };
+    enum { declflag = _declflag };
 };
 
 template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
 template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
 template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
 template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
 template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
 template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
--- a/gfx/angle/src/libGLESv2/libGLESv2.cpp
+++ b/gfx/angle/src/libGLESv2/libGLESv2.cpp
@@ -3785,19 +3785,19 @@ const GLubyte* __stdcall glGetString(GLe
 
         switch (name)
         {
           case GL_VENDOR:
             return (GLubyte*)"Google Inc.";
           case GL_RENDERER:
             return (GLubyte*)((context != NULL) ? context->getRendererString() : "ANGLE");
           case GL_VERSION:
-            return (GLubyte*)"OpenGL ES 2.0 (ANGLE "VERSION_STRING")";
+            return (GLubyte*)"OpenGL ES 2.0 (ANGLE " VERSION_STRING ")";
           case GL_SHADING_LANGUAGE_VERSION:
-            return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE "VERSION_STRING")";
+            return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " VERSION_STRING ")";
           case GL_EXTENSIONS:
             return (GLubyte*)((context != NULL) ? context->getExtensionString() : "");
           default:
             return error(GL_INVALID_ENUM, (GLubyte*)NULL);
         }
     }
     catch(std::bad_alloc&)
     {
--- a/gfx/angle/src/libGLESv2/libGLESv2.vcproj
+++ b/gfx/angle/src/libGLESv2/libGLESv2.vcproj
@@ -424,16 +424,20 @@
 				RelativePath=".\Shader.cpp"
 				>
 			</File>
 			<File
 				RelativePath=".\Texture.cpp"
 				>
 			</File>
 			<File
+				RelativePath=".\TextureSSE2.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\utilities.cpp"
 				>
 			</File>
 			<File
 				RelativePath=".\VertexDataManager.cpp"
 				>
 			</File>
 		</Filter>
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -2055,17 +2055,17 @@ GLContext::ReadPixelsIntoImageSurface(gf
     if (WorkAroundDriverBugs() &&
         mVendor == VendorNVIDIA &&
         dest->Format() == gfxASurface::ImageFormatARGB32 &&
         width && height)
     {
         GLint alphaBits = 0;
         fGetIntegerv(LOCAL_GL_ALPHA_BITS, &alphaBits);
         if (!alphaBits) {
-            const uint32_t alphaMask = GFX_PACKED_PIXEL_NO_PREMULTIPLY(0xff,0,0,0);
+            const uint32_t alphaMask = gfxPackedPixelNoPreMultiply(0xff,0,0,0);
 
             uint32_t* itr = (uint32_t*)dest->Data();
             uint32_t testPixel = *itr;
             if ((testPixel & alphaMask) != alphaMask) {
                 // We need to set the alpha channel to 1.0 manually.
                 uint32_t* itrEnd = itr + width*height;  // Stride is guaranteed to be width*4.
 
                 for (; itr != itrEnd; itr++) {
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -34,37 +34,48 @@
 
 #ifdef MOZ_WIDGET_GTK
 #include "gfxPlatformGtk.h"
 #endif
 
 namespace mozilla {
 namespace gl {
 
-static bool gIsATI = false;
-static bool gClientIsMesa = false;
-static int gGLXMajorVersion = 0, gGLXMinorVersion = 0;
+GLXLibrary sGLXLibrary[GLXLibrary::LIBS_MAX];
+GLXLibrary& sDefGLXLib = sGLXLibrary[GLXLibrary::OPENGL_LIB];
+
+typedef GLXLibrary::LibraryType LibType;
+
+static LibType gCurrLib = GLXLibrary::OPENGL_LIB;
+
+LibType
+GLXLibrary::SelectLibrary(const GLContext::ContextFlags& aFlags)
+{
+  return (aFlags & GLContext::ContextFlagsMesaLLVMPipe)
+          ? GLXLibrary::MESA_LLVMPIPE_LIB
+          : GLXLibrary::OPENGL_LIB;
+}
 
 // Check that we have at least version aMajor.aMinor .
-static inline bool
-GLXVersionCheck(int aMajor, int aMinor)
+bool 
+GLXLibrary::GLXVersionCheck(int aMajor, int aMinor)
 {
-    return aMajor < gGLXMajorVersion ||
-           (aMajor == gGLXMajorVersion && aMinor <= gGLXMinorVersion);
+    return aMajor < mGLXMajorVersion ||
+           (aMajor == mGLXMajorVersion && aMinor <= mGLXMinorVersion);
 }
 
 static inline bool
 HasExtension(const char* aExtensions, const char* aRequiredExtension)
 {
     return GLContext::ListHasExtension(
         reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension);
 }
 
 bool
-GLXLibrary::EnsureInitialized()
+GLXLibrary::EnsureInitialized(bool aUseMesaLLVMPipe)
 {
     if (mInitialized) {
         return true;
     }
 
     // Don't repeatedly try to initialize.
     if (mTriedInitializing) {
         return false;
@@ -74,21 +85,21 @@ GLXLibrary::EnsureInitialized()
     // Force enabling s3 texture compression (http://dri.freedesktop.org/wiki/S3TC)
     PR_SetEnv("force_s3tc_enable=true");
 
     if (!mOGLLibrary) {
         // see e.g. bug 608526: it is intrinsically interesting to know whether we have dynamically linked to libGL.so.1
         // because at least the NVIDIA implementation requires an executable stack, which causes mprotect calls,
         // which trigger glibc bug http://sourceware.org/bugzilla/show_bug.cgi?id=12225
 #ifdef __OpenBSD__
-        const char *libGLfilename = "libGL.so";
+        const char *libGLfilename = aUseMesaLLVMPipe? "mesallvmpipe.so" : "libGL.so";
 #else
-        const char *libGLfilename = "libGL.so.1";
+        const char *libGLfilename = aUseMesaLLVMPipe? "mesallvmpipe.so" : "libGL.so.1";
 #endif
-        ScopedGfxFeatureReporter reporter(libGLfilename);
+        ScopedGfxFeatureReporter reporter(libGLfilename, aUseMesaLLVMPipe);
         mOGLLibrary = PR_LoadLibrary(libGLfilename);
         if (!mOGLLibrary) {
             NS_WARNING("Couldn't load OpenGL shared library.");
             return false;
         }
         reporter.SetSuccessful();
     }
 
@@ -165,19 +176,19 @@ GLXLibrary::EnsureInitialized()
     if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &symbols[0])) {
         NS_WARNING("Couldn't find required entry point in OpenGL shared library");
         return false;
     }
 
     Display *display = DefaultXDisplay();
     int screen = DefaultScreen(display);
 
-    if (!xQueryVersion(display, &gGLXMajorVersion, &gGLXMinorVersion)) {
-        gGLXMajorVersion = 0;
-        gGLXMinorVersion = 0;
+    if (!xQueryVersion(display, &mGLXMajorVersion, &mGLXMinorVersion)) {
+        mGLXMajorVersion = 0;
+        mGLXMinorVersion = 0;
         return false;
     }
 
     if (!GLXVersionCheck(1, 1))
         // Not possible to query for extensions.
         return false;
 
     const char *clientVendor = xGetClientString(display, GLX_VENDOR);
@@ -230,27 +241,30 @@ GLXLibrary::EnsureInitialized()
         NS_WARNING("Texture from pixmap disabled");
     }
 
     if (HasExtension(extensionsStr, "GLX_ARB_create_context_robustness") &&
         GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_robustness)) {
         mHasRobustness = true;
     }
 
-    gIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI");
-    gClientIsMesa = clientVendor && DoesStringMatch(clientVendor, "Mesa");
+    mIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI");
+    mClientIsMesa = clientVendor && DoesStringMatch(clientVendor, "Mesa");
 
     mInitialized = true;
+    if(aUseMesaLLVMPipe)
+      mLibType = GLXLibrary::MESA_LLVMPIPE_LIB;
+
     return true;
 }
 
 bool
 GLXLibrary::SupportsTextureFromPixmap(gfxASurface* aSurface)
 {
-    if (!EnsureInitialized()) {
+    if (!EnsureInitialized(mLibType == MESA_LLVMPIPE_LIB)) {
         return false;
     }
     
     if (aSurface->GetType() != gfxASurface::SurfaceTypeXlib || !mUseTextureFromPixmap) {
         return false;
     }
 
     return true;
@@ -300,17 +314,17 @@ GLXLibrary::CreatePixmap(gfxASurface* aS
     unsigned long blueMask =
         static_cast<unsigned long>(direct.blueMask) << direct.blue;
     // This is true if the Pixmap has bits for alpha or unused bits.
     bool haveNonColorBits =
         ~(redMask | greenMask | blueMask) != -1UL << format->depth;
 
     for (int i = 0; i < numConfigs; i++) {
         int id = None;
-        sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &id);
+        sGLXLibrary[mLibType].xGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &id);
         Visual *visual;
         int depth;
         FindVisualAndDepth(display, id, &visual, &depth);
         if (!visual ||
             visual->c_class != TrueColor ||
             visual->red_mask != redMask ||
             visual->green_mask != greenMask ||
             visual->blue_mask != blueMask ) {
@@ -354,18 +368,18 @@ GLXLibrary::CreatePixmap(gfxASurface* aS
         // available, except perhaps with NVIDIA drivers where buffer size is
         // not the specified sum of the component sizes.
         if (haveNonColorBits) {
             // There are bits in the Pixmap format that haven't been matched
             // against the fbconfig visual.  These bits could either represent
             // alpha or be unused, so just check that the number of alpha bits
             // matches.
             int size = 0;
-            sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i],
-                                           GLX_ALPHA_SIZE, &size);
+            sGLXLibrary[mLibType].xGetFBConfigAttrib(display, cfgs[i],
+                                                     GLX_ALPHA_SIZE, &size);
             if (size != alphaSize) {
                 continue;
             }
         }
 
         matchIndex = i;
         break;
     }
@@ -403,17 +417,17 @@ void
 GLXLibrary::BindTexImage(GLXPixmap aPixmap)
 {    
     if (!mUseTextureFromPixmap) {
         return;
     }
 
     Display *display = DefaultXDisplay();
     // Make sure all X drawing to the surface has finished before binding to a texture.
-    if (gClientIsMesa) {
+    if (mClientIsMesa) {
         // Using XSync instead of Mesa's glXWaitX, because its glxWaitX is a
         // noop when direct rendering unless the current drawable is a
         // single-buffer window.
         FinishX(display);
     } else {
         xWaitX();
     }
     xBindTexImage(display, aPixmap, GLX_FRONT_LEFT_EXT, NULL);
@@ -466,21 +480,21 @@ GLXLibrary::AfterGLXCall()
                           sErrorEvent.mError.serial);
             NS_ABORT();
         }
         XSetErrorHandler(sOldErrorHandler);
     }
 }
 
 #define BEFORE_GLX_CALL do {                     \
-    sGLXLibrary.BeforeGLXCall();                 \
+    sGLXLibrary[gCurrLib].BeforeGLXCall();       \
 } while (0)
     
 #define AFTER_GLX_CALL do {                      \
-    sGLXLibrary.AfterGLXCall();                  \
+    sGLXLibrary[gCurrLib].AfterGLXCall();        \
 } while (0)
 
 #else
 
 #define BEFORE_GLX_CALL do { } while(0)
 #define AFTER_GLX_CALL do { } while(0)
 
 #endif
@@ -512,17 +526,17 @@ GLXLibrary::xGetCurrentContext()
     AFTER_GLX_CALL;
     return result;
 }
 
 /* static */ void* 
 GLXLibrary::xGetProcAddress(const char *procName)
 {
     BEFORE_GLX_CALL;
-    void* result = sGLXLibrary.xGetProcAddressInternal(procName);
+    void* result = sGLXLibrary[gCurrLib].xGetProcAddressInternal(procName);
     AFTER_GLX_CALL;
     return result;
 }
 
 GLXFBConfig*
 GLXLibrary::xChooseFBConfig(Display* display, 
                             int screen, 
                             const int *attrib_list, 
@@ -703,32 +717,31 @@ GLXLibrary::xCreateContextAttribs(Displa
                                                       config, 
                                                       share_list, 
                                                       direct,
                                                       attrib_list);
     AFTER_GLX_CALL;
     return result;
 }
 
-GLXLibrary sGLXLibrary;
-
 class GLContextGLX : public GLContext
 {
 public:
     static already_AddRefed<GLContextGLX>
     CreateGLContext(const ContextFormat& format,
                     Display *display,
                     GLXDrawable drawable,
                     GLXFBConfig cfg,
                     GLContextGLX *shareContext,
                     bool deleteDrawable,
+                    LibType lib = GLXLibrary::OPENGL_LIB,
                     gfxXlibSurface *pixmap = nullptr)
     {
         int db = 0, err;
-        err = sGLXLibrary.xGetFBConfigAttrib(display, cfg,
+        err = sGLXLibrary[lib].xGetFBConfigAttrib(display, cfg,
                                              GLX_DOUBLEBUFFER, &db);
         if (GLX_BAD_ATTRIBUTE != err) {
 #ifdef DEBUG
             if (DebugMode()) {
                 printf("[GLX] FBConfig is %sdouble-buffered\n", db ? "" : "not ");
             }
 #endif
         }
@@ -738,45 +751,46 @@ public:
         bool error;
 
         ScopedXErrorHandler xErrorHandler;
 
 TRY_AGAIN_NO_SHARING:
 
         error = false;
 
-        if (sGLXLibrary.HasRobustness()) {
+        if (sGLXLibrary[lib].HasRobustness()) {
             int attrib_list[] = {
                 LOCAL_GL_CONTEXT_FLAGS_ARB, LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
                 LOCAL_GL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_GL_LOSE_CONTEXT_ON_RESET_ARB,
                 0,
             };
 
-            context = sGLXLibrary.xCreateContextAttribs(display,
+            context = sGLXLibrary[lib].xCreateContextAttribs(display,
                                                         cfg,
                                                         shareContext ? shareContext->mContext : NULL,
                                                         True,
                                                         attrib_list);
         } else {
-            context = sGLXLibrary.xCreateNewContext(display,
+            context = sGLXLibrary[lib].xCreateNewContext(display,
                                                     cfg,
                                                     GLX_RGBA_TYPE,
                                                     shareContext ? shareContext->mContext : NULL,
                                                     True);
         }
 
         if (context) {
             glContext = new GLContextGLX(format,
                                         shareContext,
                                         display,
                                         drawable,
                                         context,
                                         deleteDrawable,
                                         db,
-                                        pixmap);
+                                        pixmap,
+                                        lib);
             if (!glContext->Init())
                 error = true;
         } else {
             error = true;
         }
 
         error |= xErrorHandler.SyncAndGetError(display);
 
@@ -797,24 +811,24 @@ TRY_AGAIN_NO_SHARING:
     ~GLContextGLX()
     {
         MarkDestroyed();
 
         // see bug 659842 comment 76
 #ifdef DEBUG
         bool success =
 #endif
-        sGLXLibrary.xMakeCurrent(mDisplay, None, nullptr);
+        sGLXLib.xMakeCurrent(mDisplay, None, nullptr);
         NS_ABORT_IF_FALSE(success,
             "glXMakeCurrent failed to release GL context before we call glXDestroyContext!");
 
-        sGLXLibrary.xDestroyContext(mDisplay, mContext);
+        sGLXLib.xDestroyContext(mDisplay, mContext);
 
         if (mDeleteDrawable) {
-            sGLXLibrary.xDestroyPixmap(mDisplay, mDrawable);
+            sGLXLib.xDestroyPixmap(mDisplay, mDrawable);
         }
     }
 
     GLContextType GetContextType() {
         return ContextTypeGLX;
     }
 
     bool Init()
@@ -838,26 +852,26 @@ TRY_AGAIN_NO_SHARING:
         bool succeeded = true;
 
         // With the ATI FGLRX driver, glxMakeCurrent is very slow even when the context doesn't change.
         // (This is not the case with other drivers such as NVIDIA).
         // So avoid calling it more than necessary. Since GLX documentation says that:
         //     "glXGetCurrentContext returns client-side information.
         //      It does not make a round trip to the server."
         // I assume that it's not worth using our own TLS slot here.
-        if (aForce || sGLXLibrary.xGetCurrentContext() != mContext) {
-            succeeded = sGLXLibrary.xMakeCurrent(mDisplay, mDrawable, mContext);
+        if (aForce || sGLXLib.xGetCurrentContext() != mContext) {
+            succeeded = sGLXLib.xMakeCurrent(mDisplay, mDrawable, mContext);
             NS_ASSERTION(succeeded, "Failed to make GL context current!");
         }
 
         return succeeded;
     }
 
     virtual bool IsCurrent() {
-        return sGLXLibrary.xGetCurrentContext() == mContext;
+        return sGLXLib.xGetCurrentContext() == mContext;
     }
 
     bool SetupLookupFunction()
     {
         mLookupFunc = (PlatformLookupFunction)&GLXLibrary::xGetProcAddress;
         return true;
     }
 
@@ -877,31 +891,31 @@ TRY_AGAIN_NO_SHARING:
 
     bool IsDoubleBuffered()
     {
         return mDoubleBuffered;
     }
 
     bool SupportsRobustness()
     {
-        return sGLXLibrary.HasRobustness();
+        return sGLXLib.HasRobustness();
     }
 
     bool SwapBuffers()
     {
         if (!mDoubleBuffered)
             return false;
-        sGLXLibrary.xSwapBuffers(mDisplay, mDrawable);
-        sGLXLibrary.xWaitGL();
+        sGLXLib.xSwapBuffers(mDisplay, mDrawable);
+        sGLXLib.xWaitGL();
         return true;
     }
 
     bool TextureImageSupportsGetBackingSurface()
     {
-        return sGLXLibrary.UseTextureFromPixmap();
+        return sGLXLib.UseTextureFromPixmap();
     }
 
     virtual already_AddRefed<TextureImage>
     CreateTextureImage(const nsIntSize& aSize,
                        TextureImage::ContentType aContentType,
                        GLenum aWrapMode,
                        TextureImage::Flags aFlags = TextureImage::NoFlags);
 
@@ -910,49 +924,55 @@ private:
 
     GLContextGLX(const ContextFormat& aFormat,
                  GLContext *aShareContext,
                  Display *aDisplay,
                  GLXDrawable aDrawable,
                  GLXContext aContext,
                  bool aDeleteDrawable,
                  bool aDoubleBuffered,
-                 gfxXlibSurface *aPixmap)
+                 gfxXlibSurface *aPixmap,
+                 LibType aLibType)
         : GLContext(aFormat, aDeleteDrawable ? true : false, aShareContext),
           mContext(aContext),
           mDisplay(aDisplay),
           mDrawable(aDrawable),
           mDeleteDrawable(aDeleteDrawable),
           mDoubleBuffered(aDoubleBuffered),
-          mPixmap(aPixmap)
-    { }
+          mLibType(aLibType),
+          mPixmap(aPixmap),
+          sGLXLib(sGLXLibrary[aLibType])
+    {
+    }
 
     GLXContext mContext;
     Display *mDisplay;
     GLXDrawable mDrawable;
     bool mDeleteDrawable;
     bool mDoubleBuffered;
+    LibType mLibType;
 
     nsRefPtr<gfxXlibSurface> mPixmap;
+    GLXLibrary& sGLXLib;
 };
 
 class TextureImageGLX : public TextureImage
 {
     friend already_AddRefed<TextureImage>
     GLContextGLX::CreateTextureImage(const nsIntSize&,
                                      ContentType,
                                      GLenum,
                                      TextureImage::Flags);
 
 public:
     virtual ~TextureImageGLX()
     {
         mGLContext->MakeCurrent();
         mGLContext->fDeleteTextures(1, &mTexture);
-        sGLXLibrary.DestroyPixmap(mPixmap);
+        sGLXLib.DestroyPixmap(mPixmap);
     }
 
     virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion)
     {
         mInUpdate = true;
         return mUpdateSurface;
     }
 
@@ -971,23 +991,23 @@ public:
         ctx->Paint();
         return true;
     }
 
     virtual void BindTexture(GLenum aTextureUnit)
     {
         mGLContext->fActiveTexture(aTextureUnit);
         mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
-        sGLXLibrary.BindTexImage(mPixmap);
+        sGLXLib.BindTexImage(mPixmap);
         mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
     }
 
     virtual void ReleaseTexture()
     {
-        sGLXLibrary.ReleaseTexImage(mPixmap);
+        sGLXLib.ReleaseTexImage(mPixmap);
     }
 
     virtual already_AddRefed<gfxASurface> GetBackingSurface()
     {
         nsRefPtr<gfxASurface> copy = mUpdateSurface;
         return copy.forget();
     }
 
@@ -1000,36 +1020,41 @@ public:
 private:
    TextureImageGLX(GLuint aTexture,
                    const nsIntSize& aSize,
                    GLenum aWrapMode,
                    ContentType aContentType,
                    GLContext* aContext,
                    gfxASurface* aSurface,
                    GLXPixmap aPixmap,
-                   TextureImage::Flags aFlags = TextureImage::NoFlags)
+                   TextureImage::Flags aFlags = TextureImage::NoFlags,
+                   LibType aLibType = GLXLibrary::OPENGL_LIB)
         : TextureImage(aSize, aWrapMode, aContentType, aFlags)
         , mGLContext(aContext)
         , mUpdateSurface(aSurface)
         , mPixmap(aPixmap)
         , mInUpdate(false)
         , mTexture(aTexture)
+        , mLibType(aLibType)
+        , sGLXLib(sGLXLibrary[aLibType])
     {
         if (aSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
             mShaderType = gl::RGBALayerProgramType;
         } else {
             mShaderType = gl::RGBXLayerProgramType;
         }
     }
 
     GLContext* mGLContext;
     nsRefPtr<gfxASurface> mUpdateSurface;
     GLXPixmap mPixmap;
     bool mInUpdate;
     GLuint mTexture;
+    LibType mLibType;
+    GLXLibrary& sGLXLib;
 
     virtual void ApplyFilter()
     {
         mGLContext->ApplyFilterToBoundTexture(mFilter);
     }
 };
 
 already_AddRefed<TextureImage>
@@ -1062,41 +1087,42 @@ GLContextGLX::CreateTextureImage(const n
 
     if (aContentType == gfxASurface::CONTENT_COLOR_ALPHA) {
         nsRefPtr<gfxContext> ctx = new gfxContext(surface);
         ctx->SetOperator(gfxContext::OPERATOR_CLEAR);
         ctx->Paint();
     }
 
     MakeCurrent();
-    GLXPixmap pixmap = sGLXLibrary.CreatePixmap(surface);
+    GLXPixmap pixmap = sGLXLib.CreatePixmap(surface);
     NS_ASSERTION(pixmap, "Failed to create pixmap!");
 
     GLuint texture;
     fGenTextures(1, &texture);
 
     fActiveTexture(LOCAL_GL_TEXTURE0);
     fBindTexture(LOCAL_GL_TEXTURE_2D, texture);
 
     nsRefPtr<TextureImageGLX> teximage =
-        new TextureImageGLX(texture, aSize, aWrapMode, aContentType, this, surface, pixmap, aFlags);
+        new TextureImageGLX(texture, aSize, aWrapMode, aContentType, 
+                            this, surface, pixmap, aFlags, mLibType);
 
     GLint texfilter = aFlags & TextureImage::UseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter);
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter);
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, aWrapMode);
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, aWrapMode);
 
     return teximage.forget();
 }
 
 static GLContextGLX *
-GetGlobalContextGLX()
+GetGlobalContextGLX(const GLContext::ContextFlags aFlags = GLContext::ContextFlagsNone)
 {
-    return static_cast<GLContextGLX*>(GLContextProviderGLX::GetGlobalContext());
+    return static_cast<GLContextGLX*>(GLContextProviderGLX::GetGlobalContext(aFlags));
 }
 
 static bool
 AreCompatibleVisuals(Visual *one, Visual *two)
 {
     if (one->c_class != two->c_class) {
         return false;
     }
@@ -1112,46 +1138,47 @@ AreCompatibleVisuals(Visual *one, Visual
     }
 
     return true;
 }
 
 already_AddRefed<GLContext>
 GLContextProviderGLX::CreateForWindow(nsIWidget *aWidget)
 {
-    if (!sGLXLibrary.EnsureInitialized()) {
+    if (!sDefGLXLib.EnsureInitialized(false)) {
         return nullptr;
     }
 
     // Currently, we take whatever Visual the window already has, and
     // try to create an fbconfig for that visual.  This isn't
     // necessarily what we want in the long run; an fbconfig may not
     // be available for the existing visual, or if it is, the GL
     // performance might be suboptimal.  But using the existing visual
     // is a relatively safe intermediate step.
 
     Display *display = (Display*)aWidget->GetNativeData(NS_NATIVE_DISPLAY); 
     int xscreen = DefaultScreen(display);
     Window window = GET_NATIVE_WINDOW(aWidget);
 
     int numConfigs;
     ScopedXFree<GLXFBConfig> cfgs;
-    if (gIsATI || !GLXVersionCheck(1, 3)) {
+    if (sDefGLXLib.IsATI() || 
+        !sDefGLXLib.GLXVersionCheck(1, 3)) {
         const int attribs[] = {
             GLX_DOUBLEBUFFER, False,
             0
         };
-        cfgs = sGLXLibrary.xChooseFBConfig(display,
-                                           xscreen,
-                                           attribs,
-                                           &numConfigs);
+        cfgs = sDefGLXLib.xChooseFBConfig(display,
+                                       xscreen,
+                                       attribs,
+                                       &numConfigs);
     } else {
-        cfgs = sGLXLibrary.xGetFBConfigs(display,
-                                         xscreen,
-                                         &numConfigs);
+        cfgs = sDefGLXLib.xGetFBConfigs(display,
+                                     xscreen,
+                                     &numConfigs);
     }
 
     if (!cfgs) {
         NS_WARNING("[GLX] glXGetFBConfigs() failed");
         return nullptr;
     }
     NS_ASSERTION(numConfigs > 0, "No FBConfigs found!");
 
@@ -1167,21 +1194,21 @@ GLContextProviderGLX::CreateForWindow(ns
 #ifdef DEBUG
     printf("[GLX] widget has VisualID 0x%lx\n", widgetVisualID);
 #endif
 
     int matchIndex = -1;
 
     for (int i = 0; i < numConfigs; i++) {
         int visid = None;
-        sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &visid);
+        sDefGLXLib.xGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &visid);
         if (!visid) {
             continue;
         }
-        if (gIsATI) {
+        if (sDefGLXLib.IsATI()) {
             int depth;
             Visual *visual;
             FindVisualAndDepth(display, visid, &visual, &depth);
             if (depth == widgetAttrs.depth &&
                 AreCompatibleVisuals(widgetAttrs.visual, visual)) {
                 matchIndex = i;
                 break;
             }
@@ -1200,27 +1227,29 @@ GLContextProviderGLX::CreateForWindow(ns
 
     GLContextGLX *shareContext = GetGlobalContextGLX();
 
     nsRefPtr<GLContextGLX> glContext = GLContextGLX::CreateGLContext(ContextFormat(ContextFormat::BasicRGB24),
                                                                      display,
                                                                      window,
                                                                      cfgs[matchIndex],
                                                                      shareContext,
-                                                                     false);
+                                                                     false,
+                                                                     GLXLibrary::OPENGL_LIB);
 
     return glContext.forget();
 }
 
 static already_AddRefed<GLContextGLX>
 CreateOffscreenPixmapContext(const gfxIntSize& aSize,
                              const ContextFormat& aFormat,
-                             bool aShare)
+                             bool aShare, LibType aLibToUse)
 {
-    if (!sGLXLibrary.EnsureInitialized()) {
+    GLXLibrary& sGLXLib = sGLXLibrary[aLibToUse];
+    if (!sGLXLib.EnsureInitialized(aLibToUse == GLXLibrary::MESA_LLVMPIPE_LIB)) {
         return nullptr;
     }
 
     Display *display = DefaultXDisplay();
     int xscreen = DefaultScreen(display);
 
     int attribs[] = {
         GLX_DOUBLEBUFFER, False,
@@ -1231,39 +1260,39 @@ CreateOffscreenPixmapContext(const gfxIn
         GLX_BLUE_SIZE, 1,
         GLX_ALPHA_SIZE, 0,
         GLX_DEPTH_SIZE, 0,
         0
     };
     int numConfigs = 0;
 
     ScopedXFree<GLXFBConfig> cfgs;
-    cfgs = sGLXLibrary.xChooseFBConfig(display,
-                                       xscreen,
-                                       attribs,
-                                       &numConfigs);
+    cfgs = sGLXLib.xChooseFBConfig(display,
+                                   xscreen,
+                                   attribs,
+                                   &numConfigs);
     if (!cfgs) {
         return nullptr;
     }
 
     NS_ASSERTION(numConfigs > 0,
                  "glXChooseFBConfig() failed to match our requested format and violated its spec (!)");
 
     int visid = None;
     int chosenIndex = 0;
 
     for (int i = 0; i < numConfigs; ++i) {
         int dtype;
 
-        if (sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], GLX_DRAWABLE_TYPE, &dtype) != Success
+        if (sGLXLib.xGetFBConfigAttrib(display, cfgs[i], GLX_DRAWABLE_TYPE, &dtype) != Success
             || !(dtype & GLX_PIXMAP_BIT))
         {
             continue;
         }
-        if (sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &visid) != Success
+        if (sGLXLib.xGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &visid) != Success
             || visid == 0)
         {
             continue;
         }
 
         chosenIndex = i;
         break;
     }
@@ -1286,59 +1315,64 @@ CreateOffscreenPixmapContext(const gfxIn
     if (xsurface->CairoStatus() != 0) {
         error = true;
         goto DONE_CREATING_PIXMAP;
     }
 
     // Handle slightly different signature between glXCreatePixmap and
     // its pre-GLX-1.3 extension equivalent (though given the ABI, we
     // might not need to).
-    if (GLXVersionCheck(1, 3)) {
-        glxpixmap = sGLXLibrary.xCreatePixmap(display,
-                                              cfgs[chosenIndex],
-                                              xsurface->XDrawable(),
-                                              NULL);
+    if (sGLXLib.GLXVersionCheck(1, 3)) {
+        glxpixmap = sGLXLib.xCreatePixmap(display,
+                                          cfgs[chosenIndex],
+                                          xsurface->XDrawable(),
+                                          NULL);
     } else {
-        glxpixmap = sGLXLibrary.xCreateGLXPixmapWithConfig(display,
-                                                           cfgs[chosenIndex],
-                                                           xsurface->
-                                                             XDrawable());
+        glxpixmap = sGLXLib.xCreateGLXPixmapWithConfig(display,
+                                                       cfgs[chosenIndex],
+                                                       xsurface->
+                                                       XDrawable());
     }
     if (glxpixmap == 0) {
         error = true;
     }
 
 DONE_CREATING_PIXMAP:
 
     nsRefPtr<GLContextGLX> glContext;
     bool serverError = xErrorHandler.SyncAndGetError(display);
 
     if (!error && // earlier recorded error
         !serverError)
     {
+      GLContext::ContextFlags flag = aLibToUse == GLXLibrary::OPENGL_LIB
+                                       ? GLContext::ContextFlagsNone
+                                       : GLContext::ContextFlagsMesaLLVMPipe;
         glContext = GLContextGLX::CreateGLContext(
                         aFormat,
                         display,
                         glxpixmap,
                         cfgs[chosenIndex],
-                        aShare ? GetGlobalContextGLX() : nullptr,
+                        aShare ? GetGlobalContextGLX(flag) : nullptr,
                         true,
+                        aLibToUse,
                         xsurface);
     }
 
     return glContext.forget();
 }
 
 already_AddRefed<GLContext>
 GLContextProviderGLX::CreateOffscreen(const gfxIntSize& aSize,
                                       const ContextFormat& aFormat,
-                                      const ContextFlags)
+                                      const ContextFlags aFlag)
 {
+    gCurrLib = GLXLibrary::SelectLibrary(aFlag);
     nsRefPtr<GLContextGLX> glContext =
-        CreateOffscreenPixmapContext(aSize, aFormat, true);
+        CreateOffscreenPixmapContext(aSize, aFormat, true, gCurrLib);
 
     if (!glContext) {
         return nullptr;
     }
 
     if (!glContext->GetSharedContext()) {
         // no point in returning anything if sharing failed, we can't
         // render from this
@@ -1349,35 +1383,37 @@ GLContextProviderGLX::CreateOffscreen(co
         // we weren't able to create the initial
         // offscreen FBO, so this is dead
         return nullptr;
     }
 
     return glContext.forget();
 }
 
-static nsRefPtr<GLContext> gGlobalContext;
+static nsRefPtr<GLContext> gGlobalContext[GLXLibrary::LIBS_MAX];
 
 GLContext *
-GLContextProviderGLX::GetGlobalContext(const ContextFlags)
+GLContextProviderGLX::GetGlobalContext(const ContextFlags aFlag)
 {
-    static bool triedToCreateContext = false;
-    if (!triedToCreateContext && !gGlobalContext) {
-        triedToCreateContext = true;
-        gGlobalContext = CreateOffscreenPixmapContext(gfxIntSize(1, 1),
+    LibType libToUse = GLXLibrary::SelectLibrary(aFlag);
+    static bool triedToCreateContext[GLXLibrary::LIBS_MAX] = {false, false};
+    if (!triedToCreateContext[libToUse] && !gGlobalContext[libToUse]) {
+        triedToCreateContext[libToUse] = true;
+        gGlobalContext[libToUse] = CreateOffscreenPixmapContext(gfxIntSize(1, 1),
                                                       ContextFormat(ContextFormat::BasicRGB24),
-                                                      false);
-        if (gGlobalContext)
-            gGlobalContext->SetIsGlobalSharedContext(true);
+                                                      false, libToUse);
+        if (gGlobalContext[libToUse])
+            gGlobalContext[libToUse]->SetIsGlobalSharedContext(true);
     }
 
-    return gGlobalContext;
+    return gGlobalContext[libToUse];
 }
 
 void
 GLContextProviderGLX::Shutdown()
 {
-    gGlobalContext = nullptr;
+    for (int i = 0; i < GLXLibrary::LIBS_MAX; ++i)
+      gGlobalContext[i] = nullptr;
 }
 
 } /* namespace gl */
 } /* namespace mozilla */
 
--- a/gfx/gl/GLXLibrary.h
+++ b/gfx/gl/GLXLibrary.h
@@ -13,22 +13,33 @@ typedef realGLboolean GLboolean;
 namespace mozilla {
 namespace gl {
 
 class GLXLibrary
 {
 public:
     GLXLibrary() : mInitialized(false), mTriedInitializing(false),
                    mUseTextureFromPixmap(false), mDebug(false),
-                   mHasRobustness(false), mOGLLibrary(nullptr) {}
+                   mHasRobustness(false), mIsATI(false),
+                   mClientIsMesa(false), mGLXMajorVersion(0),
+                   mGLXMinorVersion(0), mLibType(OPENGL_LIB),
+                   mOGLLibrary(nullptr) {}
 
     void xDestroyContext(Display* display, GLXContext context);
     Bool xMakeCurrent(Display* display, 
                       GLXDrawable drawable, 
                       GLXContext context);
+
+    enum LibraryType
+    {
+      OPENGL_LIB = 0,
+      MESA_LLVMPIPE_LIB = 1,
+      LIBS_MAX
+    };
+
     GLXContext xGetCurrentContext();
     static void* xGetProcAddress(const char *procName);
     GLXFBConfig* xChooseFBConfig(Display* display, 
                                  int screen, 
                                  const int *attrib_list, 
                                  int *nelements);
     GLXFBConfig* xGetFBConfigs(Display* display, 
                                int screen, 
@@ -71,26 +82,29 @@ public:
     void xWaitX();
 
     GLXContext xCreateContextAttribs(Display* display, 
                                      GLXFBConfig config, 
                                      GLXContext share_list, 
                                      Bool direct,
                                      const int* attrib_list);
 
-    bool EnsureInitialized();
+    bool EnsureInitialized(bool aUseMesaLLVMPipe);
 
     GLXPixmap CreatePixmap(gfxASurface* aSurface);
     void DestroyPixmap(GLXPixmap aPixmap);
     void BindTexImage(GLXPixmap aPixmap);
     void ReleaseTexImage(GLXPixmap aPixmap);
 
     bool UseTextureFromPixmap() { return mUseTextureFromPixmap; }
     bool HasRobustness() { return mHasRobustness; }
     bool SupportsTextureFromPixmap(gfxASurface* aSurface);
+    bool IsATI() { return mIsATI; }
+    bool GLXVersionCheck(int aMajor, int aMinor);
+    static LibraryType SelectLibrary(const GLContext::ContextFlags& aFlags);
 
 private:
     
     typedef void (GLAPIENTRY * PFNGLXDESTROYCONTEXTPROC) (Display*,
                                                           GLXContext);
     PFNGLXDESTROYCONTEXTPROC xDestroyContextInternal;
     typedef Bool (GLAPIENTRY * PFNGLXMAKECURRENTPROC) (Display*,
                                                        GLXDrawable,
@@ -182,18 +196,24 @@ private:
     void AfterGLXCall();
 #endif
 
     bool mInitialized;
     bool mTriedInitializing;
     bool mUseTextureFromPixmap;
     bool mDebug;
     bool mHasRobustness;
+    bool mIsATI;
+    bool mClientIsMesa;
+    int mGLXMajorVersion;
+    int mGLXMinorVersion;
+    LibraryType mLibType;
     PRLibrary *mOGLLibrary;
 };
 
 // a global GLXLibrary instance
-extern GLXLibrary sGLXLibrary;
+extern GLXLibrary sGLXLibrary[GLXLibrary::LIBS_MAX];
+extern GLXLibrary& sDefGLXLib;
 
 } /* namespace gl */
 } /* namespace mozilla */
 #endif /* GFX_GLXLIBRARY_H */
 
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -283,17 +283,17 @@ CanvasLayerOGL::RenderLayer(int aPreviou
   }
 
   if (!program) {
     program = mOGLManager->GetProgram(mLayerProgram, GetMaskLayer());
   }
 
 #if defined(MOZ_X11) && !defined(MOZ_PLATFORM_MAEMO)
   if (mPixmap && !mDelayedUpdates) {
-    sGLXLibrary.BindTexImage(mPixmap);
+    sDefGLXLib.BindTexImage(mPixmap);
   }
 #endif
 
   gl()->ApplyFilterToBoundTexture(mFilter);
 
   program->Activate();
   if (mLayerProgram == gl::RGBARectLayerProgramType) {
     // This is used by IOSurface that use 0,0...w,h coordinate rather then 0,0..1,1.
@@ -309,17 +309,17 @@ CanvasLayerOGL::RenderLayer(int aPreviou
   if (gl()->CanUploadNonPowerOfTwo()) {
     mOGLManager->BindAndDrawQuad(program, mNeedsYFlip ? true : false);
   } else {
     mOGLManager->BindAndDrawQuadWithTextureRect(program, drawRect, drawRect.Size());
   }
 
 #if defined(MOZ_X11) && !defined(MOZ_PLATFORM_MAEMO)
   if (mPixmap && !mDelayedUpdates) {
-    sGLXLibrary.ReleaseTexImage(mPixmap);
+    sDefGLXLib.ReleaseTexImage(mPixmap);
   }
 #endif
 
   if (useGLContext) {
     gl()->UnbindTex2DOffscreen(mCanvasGLContext);
   }
 }
 
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -344,20 +344,20 @@ ImageLayerOGL::RenderLayer(int,
 
     gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
     gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTexture.GetTextureID());
 
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
     GLXPixmap pixmap;
 
     if (cairoImage->mSurface) {
-        pixmap = sGLXLibrary.CreatePixmap(cairoImage->mSurface);
+        pixmap = sDefGLXLib.CreatePixmap(cairoImage->mSurface);
         NS_ASSERTION(pixmap, "Failed to create pixmap!");
         if (pixmap) {
-            sGLXLibrary.BindTexImage(pixmap);
+            sDefGLXLib.BindTexImage(pixmap);
         }
     }
 #endif
 
     ShaderProgramOGL *program = 
       mOGLManager->GetProgram(data->mLayerProgram, GetMaskLayer());
 
     gl()->ApplyFilterToBoundTexture(mFilter);
@@ -371,18 +371,18 @@ ImageLayerOGL::RenderLayer(int,
     program->SetRenderOffset(aOffset);
     program->SetTextureUnit(0);
     program->LoadMask(GetMaskLayer());
 
     mOGLManager->BindAndDrawQuad(program);
 
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
     if (cairoImage->mSurface && pixmap) {
-        sGLXLibrary.ReleaseTexImage(pixmap);
-        sGLXLibrary.DestroyPixmap(pixmap);
+        sDefGLXLib.ReleaseTexImage(pixmap);
+        sDefGLXLib.DestroyPixmap(pixmap);
     }
 #endif
 #ifdef XP_MACOSX
   } else if (image->GetFormat() == MAC_IO_SURFACE) {
      MacIOSurfaceImage *ioImage =
        static_cast<MacIOSurfaceImage*>(image);
 
      if (!mOGLManager->GetThebesLayerCallback()) {
@@ -577,17 +577,17 @@ ImageLayerOGL::AllocateTexturesCairo(Cai
   gl->MakeCurrent();
 
   GLuint tex = texture.GetTextureID();
   gl->fActiveTexture(LOCAL_GL_TEXTURE0);
 
   SetClamping(gl, tex);
 
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
-  if (sGLXLibrary.SupportsTextureFromPixmap(aImage->mSurface)) {
+  if (sDefGLXLib.SupportsTextureFromPixmap(aImage->mSurface)) {
     if (aImage->mSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
       backendData->mLayerProgram = gl::RGBALayerProgramType;
     } else {
       backendData->mLayerProgram = gl::RGBXLayerProgramType;
     }
 
     aImage->SetBackendData(LAYERS_OPENGL, backendData.forget());
     return;
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -83,20 +83,20 @@ private:
     for (size_t i = 0; i < kNumFrameTimeStamps; ++i) {
       const TimeStamp& frame = mFrames[i];
       if (!frame.IsNull() && frame > beginningOfWindow) {
         ++numFramesDrawnInWindow;
         earliestFrameInWindow = PR_MIN(earliestFrameInWindow, frame);
       }
     }
     double realWindowSecs = (aNow - earliestFrameInWindow).ToSeconds();
-    if (realWindowSecs == 0.0) {
+    if (realWindowSecs == 0.0 || numFramesDrawnInWindow == 1) {
       return 0.0;
     }
-    return double(numFramesDrawnInWindow) / realWindowSecs;
+    return double(numFramesDrawnInWindow - 1) / realWindowSecs;
   }
 };
 
 struct FPSState {
   GLuint mTexture;
   FPSCounter mCompositionFps;
   FPSCounter mTransactionFps;
 
--- a/gfx/thebes/gfxColor.h
+++ b/gfx/thebes/gfxColor.h
@@ -6,16 +6,18 @@
 #ifndef GFX_COLOR_H
 #define GFX_COLOR_H
 
 #include "gfxTypes.h"
 
 #include "prbit.h" // for PR_ROTATE_(LEFT,RIGHT)32
 #include "prio.h"  // for ntohl
 
+#include "mozilla/Attributes.h" // for MOZ_ALWAYS_INLINE
+
 #define GFX_UINT32_FROM_BPTR(pbptr,i) (((uint32_t*)(pbptr))[i])
 
 #if defined(IS_BIG_ENDIAN)
   #define GFX_NTOHL(x) (x)
   #define GFX_HAVE_CHEAP_NTOHL
 #elif defined(_WIN32)
   #if (_MSC_VER >= 1300) // also excludes MinGW
     #include <stdlib.h>
@@ -86,44 +88,50 @@
  * integer division (which is expensive on many processors).
  *
  * equivalent to ((v)/255)
  */
 #define GFX_DIVIDE_BY_255(v)  \
      (((((unsigned)(v)) << 8) + ((unsigned)(v)) + 255) >> 16)
 
 /**
- * Fast premultiply macro
+ * Fast premultiply
  *
  * equivalent to (((c)*(a))/255)
  */
-#define GFX_PREMULTIPLY(c,a) GFX_DIVIDE_BY_255((c)*(a))
+PRUint8 MOZ_ALWAYS_INLINE gfxPreMultiply(PRUint8 c, PRUint8 a) {
+    return GFX_DIVIDE_BY_255((c)*(a));
+}
 
-/** 
- * Macro to pack the 4 8-bit channels (A,R,G,B) 
- * into a 32-bit packed premultiplied pixel.
- *
- * The checks for 0 alpha or max alpha ensure that the
- * compiler selects the quicked calculation when alpha is constant.
- */
-#define GFX_PACKED_PIXEL(a,r,g,b)                                       \
-    ((a) == 0x00) ? 0x00000000 :                                        \
-    ((a) == 0xFF) ? ((0xFF << 24) | ((r) << 16) | ((g) << 8) | (b))     \
-                  : ((a) << 24) |                                       \
-                    (GFX_PREMULTIPLY(r,a) << 16) |                      \
-                    (GFX_PREMULTIPLY(g,a) << 8) |                       \
-                    (GFX_PREMULTIPLY(b,a))
-
-/** 
- * Macro to pack the 4 8-bit channels (A,R,G,B) 
+/**
+ * Pack the 4 8-bit channels (A,R,G,B)
  * into a 32-bit packed NON-premultiplied pixel.
  */
-#define GFX_PACKED_PIXEL_NO_PREMULTIPLY(a,r,g,b)                        \
-    (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+PRUint32 MOZ_ALWAYS_INLINE
+gfxPackedPixelNoPreMultiply(PRUint8 a, PRUint8 r, PRUint8 g, PRUint8 b) {
+    return (((a) << 24) | ((r) << 16) | ((g) << 8) | (b));
+}
 
+/**
+ * Pack the 4 8-bit channels (A,R,G,B)
+ * into a 32-bit packed premultiplied pixel.
+ */
+PRUint32 MOZ_ALWAYS_INLINE
+gfxPackedPixel(PRUint8 a, PRUint8 r, PRUint8 g, PRUint8 b) {
+    if (a == 0x00)
+        return 0x00000000;
+    else if (a == 0xFF) {
+        return gfxPackedPixelNoPreMultiply(a, r, g, b);
+    } else {
+        return  ((a) << 24) |
+                (gfxPreMultiply(r,a) << 16) |
+                (gfxPreMultiply(g,a) << 8)  |
+                (gfxPreMultiply(b,a));
+    }
+}
 
 /**
  * A color value, storing red, green, blue and alpha components.
  * This class does not use premultiplied alpha.
  *
  * XXX should this use doubles (instead of gfxFloat), for consistency with
  * cairo?
  */
--- a/gfx/thebes/gfxSVGGlyphs.cpp
+++ b/gfx/thebes/gfxSVGGlyphs.cpp
@@ -168,19 +168,19 @@ gfxSVGGlyphsDocument::SetupPresentation(
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
     nsCOMPtr<nsIPresShell> presShell;
     rv = viewer->GetPresShell(getter_AddRefs(presShell));
     NS_ENSURE_SUCCESS(rv, rv);
     presShell->GetPresContext()->SetIsGlyph(true);
 
-    if (!presShell->DidInitialReflow()) {
+    if (!presShell->DidInitialize()) {
         nsRect rect = presShell->GetPresContext()->GetVisibleArea();
-        rv = presShell->InitialReflow(rect.width, rect.height);
+        rv = presShell->Initialize(rect.width, rect.height);
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
     mDocument->FlushPendingNotifications(Flush_Layout);
 
     mViewer = viewer;
     mPresShell = presShell;
 
--- a/gfx/thebes/gfxXlibSurface.cpp
+++ b/gfx/thebes/gfxXlibSurface.cpp
@@ -79,17 +79,17 @@ gfxXlibSurface::gfxXlibSurface(cairo_sur
 
     Init(csurf, true);
 }
 
 gfxXlibSurface::~gfxXlibSurface()
 {
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
     if (mGLXPixmap) {
-        gl::sGLXLibrary.DestroyPixmap(mGLXPixmap);
+        gl::sDefGLXLib.DestroyPixmap(mGLXPixmap);
     }
 #endif
     // gfxASurface's destructor calls RecordMemoryFreed().
     if (mPixmapTaken) {
         XFreePixmap (mDisplay, mDrawable);
     }
 }
 
@@ -506,17 +506,17 @@ gfxXlibSurface::XRenderFormat()
     return cairo_xlib_surface_get_xrender_format(CairoSurface());
 }
 
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
 GLXPixmap
 gfxXlibSurface::GetGLXPixmap()
 {
     if (!mGLXPixmap) {
-        mGLXPixmap = gl::sGLXLibrary.CreatePixmap(this);
+        mGLXPixmap = gl::sDefGLXLib.CreatePixmap(this);
     }
     return mGLXPixmap;
 }
 #endif
 
 gfxASurface::MemoryLocation
 gfxXlibSurface::GetMemoryLocation() const
 {
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -180,40 +180,29 @@ public:
     mObservers->AddObserver(aObserver);
 
     if (mObservers->Length() == 1) {
       EnableNotifications();
     }
   }
 
   void RemoveObserver(Observer<InfoType>* aObserver) {
-    // If mObservers is null, that means there are no observers.
-    // In addition, if RemoveObserver() returns false, that means we didn't
-    // find the observer.
-    // In both cases, that is a logical error we want to make sure the developer
-    // notices.
-
-    MOZ_ASSERT(mObservers);
-
-#ifndef DEBUG
-    if (!mObservers) {
+    bool removed = mObservers && mObservers->RemoveObserver(aObserver);
+    if (!removed) {
+      NS_WARNING("RemoveObserver() called for unregistered observer");
       return;
     }
-#endif
-
-    DebugOnly<bool> removed = mObservers->RemoveObserver(aObserver);
-    MOZ_ASSERT(removed);
 
     if (mObservers->Length() == 0) {
       DisableNotifications();
 
       OnNotificationsDisabled();
 
       delete mObservers;
-      mObservers = 0;
+      mObservers = nullptr;
     }
   }
 
   void BroadcastInformation(const InfoType& aInfo) {
     // It is possible for mObservers to be NULL here on some platforms,
     // because a call to BroadcastInformation gets queued up asynchronously
     // while RemoveObserver is running (and before the notifications are
     // disabled). The queued call can then get run after mObservers has
@@ -447,24 +436,25 @@ EnableSensorNotifications(SensorType aSe
 
 void
 DisableSensorNotifications(SensorType aSensor) {
   AssertMainThread();
   PROXY_IF_SANDBOXED(DisableSensorNotifications(aSensor));
 }
 
 typedef mozilla::ObserverList<SensorData> SensorObserverList;
-static SensorObserverList* gSensorObservers = NULL;
+static SensorObserverList* gSensorObservers = nullptr;
 
 static SensorObserverList &
 GetSensorObservers(SensorType sensor_type) {
   MOZ_ASSERT(sensor_type < NUM_SENSOR_TYPE);
   
-  if(gSensorObservers == NULL)
+  if(!gSensorObservers) {
     gSensorObservers = new SensorObserverList[NUM_SENSOR_TYPE];
+  }
   return gSensorObservers[sensor_type];
 }
 
 void
 RegisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) {
   SensorObserverList &observers = GetSensorObservers(aSensor);
 
   AssertMainThread();
@@ -472,22 +462,24 @@ RegisterSensorObserver(SensorType aSenso
   observers.AddObserver(aObserver);
   if(observers.Length() == 1) {
     EnableSensorNotifications(aSensor);
   }
 }
 
 void
 UnregisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) {
-  SensorObserverList &observers = GetSensorObservers(aSensor);
+  AssertMainThread();
 
-  AssertMainThread();
-  
-  observers.RemoveObserver(aObserver);
-  if (observers.Length() > 0) {
+  if (!gSensorObservers) {
+    return;
+  }
+
+  SensorObserverList &observers = GetSensorObservers(aSensor);
+  if (!observers.RemoveObserver(aObserver) || observers.Length() > 0) {
     return;
   }
   DisableSensorNotifications(aSensor);
 
   // Destroy sSensorObservers only if all observer lists are empty.
   for (int i = 0; i < NUM_SENSOR_TYPE; i++) {
     if (gSensorObservers[i].Length() > 0) {
       return;
@@ -678,22 +670,28 @@ RegisterSwitchObserver(hal::SwitchDevice
     EnableSwitchNotifications(aDevice);
   }
 }
 
 void
 UnregisterSwitchObserver(hal::SwitchDevice aDevice, hal::SwitchObserver *aObserver)
 {
   AssertMainThread();
+
+  if (!sSwitchObserverLists) {
+    return;
+  }
+
   SwitchObserverList& observer = GetSwitchObserverList(aDevice);
-  observer.RemoveObserver(aObserver);
-  if (observer.Length() == 0) {
-    DisableSwitchNotifications(aDevice);
-    ReleaseObserversIfNeeded();
+  if (!observer.RemoveObserver(aObserver) || observer.Length() > 0) {
+    return;
   }
+
+  DisableSwitchNotifications(aDevice);
+  ReleaseObserversIfNeeded();
 }
 
 void
 NotifySwitchChange(const hal::SwitchEvent& aEvent)
 {
   // When callback this notification, main thread may call unregister function
   // first. We should check if this pointer is valid.
   if (!sSwitchObserverLists)
@@ -714,17 +712,17 @@ RegisterTheOneAlarmObserver(AlarmObserve
   sAlarmObserver = aObserver;
   RETURN_PROXY_IF_SANDBOXED(EnableAlarm());
 }
 
 void
 UnregisterTheOneAlarmObserver()
 {
   if (sAlarmObserver) {
-    sAlarmObserver = NULL;
+    sAlarmObserver = nullptr;
     PROXY_IF_SANDBOXED(DisableAlarm());
   }
 }
 
 void
 NotifyAlarmFired()
 {
   if (sAlarmObserver) {
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -299,16 +299,31 @@ class HalParent : public PHalParent
                 , public BatteryObserver
                 , public NetworkObserver
                 , public ISensorObserver
                 , public WakeLockObserver
                 , public ScreenConfigurationObserver
                 , public SwitchObserver
 {
 public:
+  virtual void
+  ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE
+  {
+    // NB: you *must* unconditionally unregister your observer here,
+    // if it *may* be registered below.
+    hal::UnregisterBatteryObserver(this);
+    hal::UnregisterNetworkObserver(this);
+    hal::UnregisterScreenConfigurationObserver(this);
+    for (int32_t sensor = SENSOR_UNKNOWN + 1;
+         sensor < NUM_SENSOR_TYPE; ++sensor) {
+      hal::UnregisterSensorObserver(SensorType(sensor), this);
+    }
+    hal::UnregisterWakeLockObserver(this);
+  }
+
   virtual bool
   RecvVibrate(const InfallibleTArray<unsigned int>& pattern,
               const InfallibleTArray<uint64_t> &id,
               PBrowserParent *browserParent) MOZ_OVERRIDE
   {
     // We give all content vibration permission.
 
     // Check whether browserParent is active.  We should have already
--- a/image/decoders/nsBMPDecoder.h
+++ b/image/decoders/nsBMPDecoder.h
@@ -98,17 +98,17 @@ private:
     bool mHaveAlphaData;
 };
 
 /** Sets the pixel data in aDecoded to the given values.
  * @param aDecoded pointer to pixel to be set, will be incremented to point to the next pixel.
  */
 static inline void SetPixel(uint32_t*& aDecoded, uint8_t aRed, uint8_t aGreen, uint8_t aBlue, uint8_t aAlpha = 0xFF)
 {
-    *aDecoded++ = GFX_PACKED_PIXEL(aAlpha, aRed, aGreen, aBlue);
+    *aDecoded++ = gfxPackedPixel(aAlpha, aRed, aGreen, aBlue);
 }
 
 static inline void SetPixel(uint32_t*& aDecoded, uint8_t idx, colorTable* aColors)
 {
     SetPixel(aDecoded, aColors[idx].red, aColors[idx].green, aColors[idx].blue);
 }
 
 /** Sets two (or one if aCount = 1) pixels
--- a/image/decoders/nsGIFDecoder2.cpp
+++ b/image/decoders/nsGIFDecoder2.cpp
@@ -553,32 +553,32 @@ static void ConvertColormap(uint32_t *aC
   // set up for loops below
   if (!aColors) return;
   uint32_t c = aColors;
 
   // copy as bytes until source pointer is 32-bit-aligned
   // NB: can't use 32-bit reads, they might read off the end of the buffer
   for (; (NS_PTR_TO_UINT32(from) & 0x3) && c; --c) {
     from -= 3;
-    *--to = GFX_PACKED_PIXEL(0xFF, from[0], from[1], from[2]);
+    *--to = gfxPackedPixel(0xFF, from[0], from[1], from[2]);
   }
 
   // bulk copy of pixels.
   while (c >= 4) {
     from -= 12;
     to   -=  4;
     c    -=  4;
     GFX_BLOCK_RGB_TO_FRGB(from,to);
   }
 
   // copy remaining pixel(s)
   // NB: can't use 32-bit reads, they might read off the end of the buffer
   while (c--) {
     from -= 3;
-    *--to = GFX_PACKED_PIXEL(0xFF, from[0], from[1], from[2]);
+    *--to = gfxPackedPixel(0xFF, from[0], from[1], from[2]);
   }
 }
 
 void
 nsGIFDecoder2::WriteInternal(const char *aBuffer, uint32_t aCount)
 {
   NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!");
 
--- a/image/decoders/nsJPEGDecoder.cpp
+++ b/image/decoders/nsJPEGDecoder.cpp
@@ -604,32 +604,32 @@ nsJPEGDecoder::OutputScanlines(bool* sus
         }
       }
 
       // counter for while() loops below
       uint32_t idx = mInfo.output_width;
 
       // copy as bytes until source pointer is 32-bit-aligned
       for (; (NS_PTR_TO_UINT32(sampleRow) & 0x3) && idx; --idx) {
-        *imageRow++ = GFX_PACKED_PIXEL(0xFF, sampleRow[0], sampleRow[1], sampleRow[2]);
+        *imageRow++ = gfxPackedPixel(0xFF, sampleRow[0], sampleRow[1], sampleRow[2]);
         sampleRow += 3;
       }
 
       // copy pixels in blocks of 4
       while (idx >= 4) {
         GFX_BLOCK_RGB_TO_FRGB(sampleRow, imageRow);
         idx       -=  4;
         sampleRow += 12;
         imageRow  +=  4;
       }
 
       // copy remaining pixel(s)
       while (idx--) {
         // 32-bit read of final pixel will exceed buffer, so read bytes
-        *imageRow++ = GFX_PACKED_PIXEL(0xFF, sampleRow[0], sampleRow[1], sampleRow[2]);
+        *imageRow++ = gfxPackedPixel(0xFF, sampleRow[0], sampleRow[1], sampleRow[2]);
         sampleRow += 3;
       }
   }
 
   if (top != mInfo.output_scanline) {
       nsIntRect r(0, top, mInfo.output_width, mInfo.output_scanline-top);
       PostInvalidation(r);
   }
--- a/image/decoders/nsPNGDecoder.cpp
+++ b/image/decoders/nsPNGDecoder.cpp
@@ -722,48 +722,48 @@ nsPNGDecoder::row_callback(png_structp p
     switch (decoder->format) {
       case gfxASurface::ImageFormatRGB24:
       {
         // counter for while() loops below
         uint32_t idx = iwidth;
 
         // copy as bytes until source pointer is 32-bit-aligned
         for (; (NS_PTR_TO_UINT32(line) & 0x3) && idx; --idx) {
-          *cptr32++ = GFX_PACKED_PIXEL(0xFF, line[0], line[1], line[2]);
+          *cptr32++ = gfxPackedPixel(0xFF, line[0], line[1], line[2]);
           line += 3;
         }
 
         // copy pixels in blocks of 4
         while (idx >= 4) {
           GFX_BLOCK_RGB_TO_FRGB(line, cptr32);
           idx    -=  4;
           line   += 12;
           cptr32 +=  4;
         }
 
         // copy remaining pixel(s)
         while (idx--) {
           // 32-bit read of final pixel will exceed buffer, so read bytes
-          *cptr32++ = GFX_PACKED_PIXEL(0xFF, line[0], line[1], line[2]);
+          *cptr32++ = gfxPackedPixel(0xFF, line[0], line[1], line[2]);
           line += 3;
         }
       }
       break;
       case gfxASurface::ImageFormatARGB32:
       {
         if (!decoder->mDisablePremultipliedAlpha) {
           for (uint32_t x=width; x>0; --x) {
-            *cptr32++ = GFX_PACKED_PIXEL(line[3], line[0], line[1], line[2]);
+            *cptr32++ = gfxPackedPixel(line[3], line[0], line[1], line[2]);
             if (line[3] != 0xff)
               rowHasNoAlpha = false;
             line += 4;
           }
         } else {
           for (uint32_t x=width; x>0; --x) {
-            *cptr32++ = GFX_PACKED_PIXEL_NO_PREMULTIPLY(line[3], line[0], line[1], line[2]);
+            *cptr32++ = gfxPackedPixelNoPreMultiply(line[3], line[0], line[1], line[2]);
             if (line[3] != 0xff)
               rowHasNoAlpha = false;
             line += 4;
           }
         }
       }
       break;
       default:
--- a/image/encoders/jpeg/nsJPEGEncoder.cpp
+++ b/image/encoders/jpeg/nsJPEGEncoder.cpp
@@ -349,19 +349,19 @@ void
 nsJPEGEncoder::ConvertRGBARow(const uint8_t* aSrc, uint8_t* aDest,
                               uint32_t aPixelWidth)
 {
   for (uint32_t x = 0; x < aPixelWidth; x++) {
     const uint8_t* pixelIn = &aSrc[x * 4];
     uint8_t* pixelOut = &aDest[x * 3];
 
     uint8_t alpha = pixelIn[3];
-    pixelOut[0] = GFX_PREMULTIPLY(pixelIn[0], alpha);
-    pixelOut[1] = GFX_PREMULTIPLY(pixelIn[1], alpha);
-    pixelOut[2] = GFX_PREMULTIPLY(pixelIn[2], alpha);
+    pixelOut[0] = gfxPreMultiply(pixelIn[0], alpha);
+    pixelOut[1] = gfxPreMultiply(pixelIn[1], alpha);
+    pixelOut[2] = gfxPreMultiply(pixelIn[2], alpha);
   }
 }
 
 // nsJPEGEncoder::initDestination
 //
 //    Initialize destination. This is called by jpeg_start_compress() before
 //    any data is actually written. It must initialize next_output_byte and
 //    free_in_buffer. free_in_buffer must be initialized to a positive value.
--- a/image/test/mochitest/test_bug490949.html
+++ b/image/test/mochitest/test_bug490949.html
@@ -4,17 +4,17 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id=490949
 -->
 <head>
   <title>Test for Bug 490949</title>
   <script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
-<body onload="checkFirst()">
+<body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=490949">Mozilla Bug 490949</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 <canvas id="canvas" width="100" height="100"> </canvas>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
@@ -49,43 +49,41 @@ RemoteCanvas.prototype.load = function(c
 };
 
 RemoteCanvas.prototype.reload = function(cb, force) {
     this.cb = cb;
     window.frames[0].location.reload(force);
 }
 
 RemoteCanvas.prototype.handleEvent = function() {
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
     // Look back up the iframe by id
     var ldrFrame = document.getElementById("test-iframe");
-    // Get a reference to the window object you need for the canvas
-    // drawWindow method
+    // Get a reference to the window object you need for the
+    // SpecialPowers.snapshotRect method
     var remoteWindow = ldrFrame.contentWindow;
 
     //Draw canvas
     canvas.style.width = RemoteCanvas.CANVAS_WIDTH + "px";
     canvas.style.height = RemoteCanvas.CANVAS_HEIGHT + "px";
     canvas.width = RemoteCanvas.CANVAS_WIDTH;
     canvas.height = RemoteCanvas.CANVAS_HEIGHT;
     var windowWidth = window.innerWidth - 25;
     var windowHeight = window.innerHeight;
 
+    var rect = { left: 0, top: 0, width: windowWidth, height: windowHeight };
+    var snapshot = SpecialPowers.snapshotRect(remoteWindow, rect, "rgb(0,0,0)");
+
     var ctx = canvas.getContext("2d");
     ctx.clearRect(0, 0,
                   RemoteCanvas.CANVAS_WIDTH,
                   RemoteCanvas.CANVAS_HEIGHT);
     ctx.save();
     ctx.scale(RemoteCanvas.CANVAS_WIDTH / windowWidth,
               RemoteCanvas.CANVAS_HEIGHT / windowHeight);
-    ctx.drawWindow(remoteWindow,
-                   0, 0,
-                   windowWidth, windowHeight,
-                   "rgb(0,0,0)");
+    ctx.drawImage(snapshot, 0, 0);
     ctx.restore();
     this.cb();
 };
 
 function checkFirst()
 {
   first = canvas.toDataURL();
   remoteCanvas.reload(checkForceReload, true);
--- a/image/test/mochitest/test_bug496292.html
+++ b/image/test/mochitest/test_bug496292.html
@@ -13,21 +13,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=496292">Mozilla Bug 496292</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 <canvas id="canvas" width="100" height="100"> </canvas>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
-netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-
 SimpleTest.waitForExplicitFinish();
 
 var canvas = document.getElementById('canvas');
 var first, second, third, ref;
 
 RemoteCanvas = function(url) {
     this.url = url;
 };
@@ -54,43 +49,41 @@ RemoteCanvas.prototype.load = function(c
 };
 
 RemoteCanvas.prototype.reload = function(cb, force) {
     this.cb = cb;
     window.frames[0].location.reload(force);
 }
 
 RemoteCanvas.prototype.handleEvent = function() {
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
     // Look back up the iframe by id
     var ldrFrame = document.getElementById("test-iframe-" + this.url);
     // Get a reference to the window object you need for the canvas
-    // drawWindow method
+    // SpecialPowers.snapshotRect method
     var remoteWindow = ldrFrame.contentWindow;
 
     //Draw canvas
     canvas.style.width = RemoteCanvas.CANVAS_WIDTH + "px";
     canvas.style.height = RemoteCanvas.CANVAS_HEIGHT + "px";
     canvas.width = RemoteCanvas.CANVAS_WIDTH;
     canvas.height = RemoteCanvas.CANVAS_HEIGHT;
     var windowWidth = window.innerWidth - 25;
     var windowHeight = window.innerHeight;
 
+    var rect = { left: 0, top: 0, width: windowWidth, height: windowHeight };
+    var snapshot = SpecialPowers.snapshotRect(remoteWindow, rect, "rgb(0,0,0)");
+
     var ctx = canvas.getContext("2d");
     ctx.clearRect(0, 0,
                   RemoteCanvas.CANVAS_WIDTH,
                   RemoteCanvas.CANVAS_HEIGHT);
     ctx.save();
     ctx.scale(RemoteCanvas.CANVAS_WIDTH / windowWidth,
               RemoteCanvas.CANVAS_HEIGHT / windowHeight);
-    ctx.drawWindow(remoteWindow,
-                   0, 0,
-                   windowWidth, windowHeight,
-                   "rgb(0,0,0)");
+    ctx.drawImage(snapshot, 0, 0);
     ctx.restore();
     this.cb();
 };
 
 function loadFirst()
 {
   ref = canvas.toDataURL();
 
@@ -98,35 +91,29 @@ function loadFirst()
   remoteCanvas.load(checkFirst);
 }
 
 function checkFirst()
 {
   first = canvas.toDataURL();
   is(first, ref, "The default Accept header used by image loader is correct");
 
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  Cc["@mozilla.org/preferences-service;1"].
-  getService(Ci.nsIPrefBranch).
-  setCharPref("image.http.accept", "image/png");
+  SpecialPowers.setCharPref("image.http.accept", "image/png");
 
   var remoteCanvas = new RemoteCanvas("bug496292-iframe-2.html");
   remoteCanvas.load(checkSecond);
 }
 
 function checkSecond()
 {
   second = canvas.toDataURL();
   is(second, ref, "The modified Accept header used by image loader is correct");
 
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   try {
-    Cc["@mozilla.org/preferences-service;1"].
-    getService(Ci.nsIPrefBranch).
-    clearUserPref("image.http.accept");
+    SpecialPowers.clearUserPref("image.http.accept");
   } catch (ex) { }
 
   var remoteCanvas = new RemoteCanvas("bug496292-iframe-1.html");
   remoteCanvas.load(checkThird);
 }
 
 function checkThird() {
   third = canvas.toDataURL();
--- a/image/test/reftest/bmp/bmp-corrupted/wrapper.html
+++ b/image/test/reftest/bmp/bmp-corrupted/wrapper.html
@@ -11,17 +11,17 @@
   function onImageLoad() { 
     document.documentElement.removeAttribute("class");
   };
 </script>
 </head>
 <body>
 <img id="image1">
 <script>
-  // Use as "wrapper.html?image.png
+  // Use as "wrapper.html?image.png"
   var imgURL = document.location.search.substr(1);
   document.images[0].onload = onImageLoad;
   document.images[0].onerror = onImageLoad;
   document.images[0].src = imgURL;
 </script>
 </body>
 </html>
 
--- a/ipc/chromium/src/base/dir_reader_bsd.h
+++ b/ipc/chromium/src/base/dir_reader_bsd.h
@@ -44,17 +44,21 @@ class DirReaderBSD {
   bool IsValid() const {
     return fd_ >= 0;
   }
 
   // Move to the next entry returning false if the iteration is complete.
   bool Next() {
     if (size_) {
       struct dirent* dirent = reinterpret_cast<struct dirent*>(&buf_[offset_]);
+#ifdef OS_DRAGONFLY
+      offset_ += _DIRENT_DIRSIZ(dirent);
+#else
       offset_ += dirent->d_reclen;
+#endif
     }
 
     if (offset_ != size_)
       return true;
 
 #ifdef OS_OPENBSD
     const int r = getdirentries(fd_, buf_, sizeof(buf_), basep_);
 #else
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -2192,16 +2192,20 @@ mips*-*)
     ENABLE_MONOIC=1
     ENABLE_POLYIC=1
     ENABLE_METHODJIT_TYPED_ARRAY=1
     AC_DEFINE(JS_CPU_MIPS)
     AC_DEFINE(JS_NUNBOX32)
     ;;
 esac
 
+MOZ_ARG_DISABLE_BOOL(ion,
+[  --disable-ion      Disable use of the IonMonkey JIT],
+  ENABLE_ION= )
+
 MOZ_ARG_DISABLE_BOOL(methodjit,
 [  --disable-methodjit           Disable method JIT support],
   ENABLE_METHODJIT= )
 
 MOZ_ARG_DISABLE_BOOL(monoic,
 [  --disable-monoic      Disable use of MICs by JIT compiler],
   ENABLE_MONOIC= )
 
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -930,17 +930,17 @@ EmitAliasedVarOp(JSContext *cx, JSOp op,
         JS_ASSERT(pn->pn_cookie.level() == bce->script->staticLevel);
     }
 
     ScopeCoordinate sc;
     if (IsArgOp(pn->getOp())) {
         sc.hops = skippedScopes + ClonedBlockDepth(bceOfDef);
         sc.slot = AliasedNameToSlot(bceOfDef->script, pn->name());
     } else {
-        JS_ASSERT(IsLocalOp(pn->getOp()) || pn->isKind(PNK_FUNCTION));
+        JS_ASSERT(IsLocalOp(pn->getOp()) || pn->isKind(PNK_FUNCTIONDECL));
         unsigned local = pn->pn_cookie.slot();
         if (local < bceOfDef->script->bindings.numVars()) {
             sc.hops = skippedScopes + ClonedBlockDepth(bceOfDef);
             sc.slot = AliasedNameToSlot(bceOfDef->script, pn->name());
         } else {
             unsigned depth = local - bceOfDef->script->bindings.numVars();
             StaticBlockObject *b = bceOfDef->blockChain;
             while (!b->containsVarAtDepth(depth)) {
@@ -954,17 +954,17 @@ EmitAliasedVarOp(JSContext *cx, JSOp op,
     }
 
     return EmitAliasedVarOp(cx, op, sc, bce);
 }
 
 static bool
 EmitVarOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
 {
-    JS_ASSERT(pn->isKind(PNK_FUNCTION) || pn->isKind(PNK_NAME));
+    JS_ASSERT(pn->isKind(PNK_FUNCTIONDECL) || pn->isKind(PNK_NAME));
     JS_ASSERT_IF(pn->isKind(PNK_NAME), IsArgOp(op) || IsLocalOp(op));
     JS_ASSERT(!pn->pn_cookie.isFree());
 
     if (!bce->isAliasedName(pn)) {
         JS_ASSERT(pn->isUsed() || pn->isDefn());
         JS_ASSERT_IF(pn->isUsed(), pn->pn_cookie.level() == 0);
         JS_ASSERT_IF(pn->isDefn(), pn->pn_cookie.level() == bce->script->staticLevel);
         return EmitUnaliasedVarOp(cx, op, pn->pn_cookie.slot(), bce);
@@ -1216,17 +1216,17 @@ TryConvertToGname(BytecodeEmitter *bce, 
  * to update the special cases in EmitFor (for-in) and EmitAssignment (= and
  * op=, e.g. +=).
  */
 static bool
 BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
 {
     JS_ASSERT(pn->isKind(PNK_NAME) || pn->isKind(PNK_INTRINSICNAME));
 
-    JS_ASSERT_IF(pn->isKind(PNK_FUNCTION), pn->isBound());
+    JS_ASSERT_IF(pn->isKind(PNK_FUNCTIONDECL), pn->isBound());
 
     /* Don't attempt if 'pn' is already bound or deoptimized or a function. */
     if (pn->isBound() || pn->isDeoptimized())
         return true;
 
     /* JSOP_CALLEE is pre-bound by definition. */
     JSOp op = pn->getOp();
     JS_ASSERT(op != JSOP_CALLEE);
@@ -1492,23 +1492,23 @@ CheckSideEffects(JSContext *cx, Bytecode
             /*
              * Non-operators along with ||, &&, ===, and !== never invoke
              * toString or valueOf.
              */
             for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next)
                 ok &= CheckSideEffects(cx, bce, pn2, answer);
         } else {
             /*
-             * All invocation operations (construct: PNK_NEW, call: PNK_LP)
+             * All invocation operations (construct: PNK_NEW, call: PNK_CALL)
              * are presumed to be useful, because they may have side effects
              * even if their main effect (their return value) is discarded.
              *
-             * PNK_LB binary trees of 3 or more nodes are flattened into lists
-             * to avoid too much recursion.  All such lists must be presumed
-             * to be useful because each index operation could invoke a getter.
+             * PNK_ELEM binary trees of 3+ nodes are flattened into lists to
+             * avoid too much recursion. All such lists must be presumed to be
+             * useful because each index operation could invoke a getter.
              *
              * Likewise, array and object initialisers may call prototype
              * setters (the __defineSetter__ built-in, and writable __proto__
              * on Array.prototype create this hazard). Initialiser list nodes
              * have JSOP_NEWINIT in their pn_op.
              */
             *answer = true;
         }
@@ -1576,18 +1576,18 @@ CheckSideEffects(JSContext *cx, Bytecode
                 /* FALL THROUGH */
               case PNK_DOT:
 #if JS_HAS_XML_SUPPORT
               case PNK_DBLDOT:
                 JS_ASSERT_IF(pn2->getKind() == PNK_DBLDOT, !bce->sc->inStrictMode());
                 /* FALL THROUGH */
 
 #endif
-              case PNK_LP:
-              case PNK_LB:
+              case PNK_CALL:
+              case PNK_ELEM:
                 /* All these delete addressing modes have effects too. */
                 *answer = true;
                 break;
               default:
                 ok = CheckSideEffects(cx, bce, pn2, answer);
                 break;
             }
             break;
@@ -2007,21 +2007,21 @@ static bool
 EmitElemOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
 {
     ParseNode *left, *right;
 
     ptrdiff_t top = bce->offset();
 
     if (pn->isArity(PN_NAME)) {
         /*
-         * Set left and right so pn appears to be a PNK_LB node, instead
-         * of a PNK_DOT node.  See the PNK_FOR/IN case in EmitTree, and
-         * EmitDestructuringOps nearer below.  In the destructuring case,
-         * the base expression (pn_expr) of the name may be null, which
-         * means we have to emit a JSOP_BINDNAME.
+         * Set left and right so pn appears to be a PNK_ELEM node, instead of
+         * a PNK_DOT node. See the PNK_FOR/IN case in EmitTree, and
+         * EmitDestructuringOps nearer below. In the destructuring case, the
+         * base expression (pn_expr) of the name may be null, which means we
+         * have to emit a JSOP_BINDNAME.
          */
         left = pn->maybeExpr();
         if (!left) {
             left = NullaryNode::create(PNK_STRING, bce->parser);
             if (!left)
                 return false;
             left->setOp(JSOP_BINDNAME);
             left->pn_pos = pn->pn_pos;
@@ -2283,19 +2283,16 @@ EmitSwitch(JSContext *cx, BytecodeEmitte
                 continue;
             }
 
             JS_ASSERT(pn3->isKind(PNK_CASE));
             if (switchOp == JSOP_CONDSWITCH)
                 continue;
 
             pn4 = pn3->pn_left;
-            while (pn4->isKind(PNK_RP))
-                pn4 = pn4->pn_kid;
-
             Value constVal;
             switch (pn4->getKind()) {
               case PNK_NUMBER:
                 constVal.setNumber(pn4->pn_dval);
                 break;
               case PNK_STRING:
                 constVal.setString(pn4->pn_atom);
                 break;
@@ -2728,28 +2725,28 @@ EmitDestructuringDecl(JSContext *cx, Byt
 }
 
 static bool
 EmitDestructuringDecls(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *pn)
 {
     ParseNode *pn2, *pn3;
     DestructuringDeclEmitter emitter;
 
-    if (pn->isKind(PNK_RB)) {
+    if (pn->isKind(PNK_ARRAY)) {
         for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
             if (pn2->isKind(PNK_COMMA))
                 continue;
             emitter = (pn2->isKind(PNK_NAME))
                       ? EmitDestructuringDecl
                       : EmitDestructuringDecls;
             if (!emitter(cx, bce, prologOp, pn2))
                 return false;
         }
     } else {
-        JS_ASSERT(pn->isKind(PNK_RC));
+        JS_ASSERT(pn->isKind(PNK_OBJECT));
         for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
             pn3 = pn2->pn_right;
             emitter = pn3->isKind(PNK_NAME) ? EmitDestructuringDecl : EmitDestructuringDecls;
             if (!emitter(cx, bce, prologOp, pn3))
                 return false;
         }
     }
     return true;
@@ -2777,17 +2774,17 @@ EmitDestructuringLHS(JSContext *cx, Byte
     JS_ASSERT(emitOption != DefineVars);
 
     /*
      * Now emit the lvalue opcode sequence.  If the lvalue is a nested
      * destructuring initialiser-form, call ourselves to handle it, then
      * pop the matched value.  Otherwise emit an lvalue bytecode sequence
      * ending with a JSOP_ENUMELEM or equivalent op.
      */
-    if (pn->isKind(PNK_RB) || pn->isKind(PNK_RC)) {
+    if (pn->isKind(PNK_ARRAY) || pn->isKind(PNK_OBJECT)) {
         if (!EmitDestructuringOpsHelper(cx, bce, pn, emitOption))
             return false;
         if (emitOption == InitializeVars) {
             /*
              * Per its post-condition, EmitDestructuringOpsHelper has left the
              * to-be-destructured value on top of the stack.
              */
             if (Emit1(cx, bce, JSOP_POP) < 0)
@@ -2884,17 +2881,17 @@ EmitDestructuringOpsHelper(JSContext *cx
     unsigned index;
     ParseNode *pn2, *pn3;
     bool doElemOp;
 
 #ifdef DEBUG
     int stackDepth = bce->stackDepth;
     JS_ASSERT(stackDepth != 0);
     JS_ASSERT(pn->isArity(PN_LIST));
-    JS_ASSERT(pn->isKind(PNK_RB) || pn->isKind(PNK_RC));
+    JS_ASSERT(pn->isKind(PNK_ARRAY) || pn->isKind(PNK_OBJECT));
 #endif
 
     if (pn->pn_count == 0) {
         /* Emit a DUP;POP sequence for the decompiler. */
         if (Emit1(cx, bce, JSOP_DUP) < 0 || Emit1(cx, bce, JSOP_POP) < 0)
             return false;
     }
 
@@ -2911,22 +2908,22 @@ EmitDestructuringOpsHelper(JSContext *cx
 
         /*
          * Now push the property name currently being matched, which is either
          * the array initialiser's current index, or the current property name
          * "label" on the left of a colon in the object initialiser.  Set pn3
          * to the lvalue node, which is in the value-initializing position.
          */
         doElemOp = true;
-        if (pn->isKind(PNK_RB)) {
+        if (pn->isKind(PNK_ARRAY)) {
             if (!EmitNumberOp(cx, index, bce))
                 return false;
             pn3 = pn2;
         } else {
-            JS_ASSERT(pn->isKind(PNK_RC));
+            JS_ASSERT(pn->isKind(PNK_OBJECT));
             JS_ASSERT(pn2->isKind(PNK_COLON));
             pn3 = pn2->pn_left;
             if (pn3->isKind(PNK_NUMBER)) {
                 /*
                  * If we are emitting an object destructuring initialiser,
                  * annotate the index op with SRC_INITPROP so we know we are
                  * not decompiling an array initialiser.
                  */
@@ -2951,17 +2948,17 @@ EmitDestructuringOpsHelper(JSContext *cx
              */
             if (!EmitElemOpBase(cx, bce, JSOP_GETELEM))
                 return false;
             JS_ASSERT(bce->stackDepth >= stackDepth + 1);
         }
 
         /* Nullary comma node makes a hole in the array destructurer. */
         if (pn3->isKind(PNK_COMMA) && pn3->isArity(PN_NULLARY)) {
-            JS_ASSERT(pn->isKind(PNK_RB));
+            JS_ASSERT(pn->isKind(PNK_ARRAY));
             JS_ASSERT(pn2 == pn3);
             if (Emit1(cx, bce, JSOP_POP) < 0)
                 return false;
         } else {
             int depthBefore = bce->stackDepth;
             if (!EmitDestructuringLHS(cx, bce, pn3, emitOption))
                 return false;
 
@@ -3173,17 +3170,17 @@ MaybeEmitGroupAssignment(JSContext *cx, 
                          GroupOption groupOption, JSOp *pop)
 {
     JS_ASSERT(pn->isKind(PNK_ASSIGN));
     JS_ASSERT(pn->isOp(JSOP_NOP));
     JS_ASSERT(*pop == JSOP_POP || *pop == JSOP_POPV);
 
     ParseNode *lhs = pn->pn_left;
     ParseNode *rhs = pn->pn_right;
-    if (lhs->isKind(PNK_RB) && rhs->isKind(PNK_RB) &&
+    if (lhs->isKind(PNK_ARRAY) && rhs->isKind(PNK_ARRAY) &&
         !(rhs->pn_xflags & PNX_HOLEY) &&
         lhs->pn_count <= rhs->pn_count)
     {
         if (groupOption == GroupIsDecl && !EmitDestructuringDecls(cx, bce, prologOp, lhs))
             return false;
         if (!EmitGroupAssignment(cx, bce, prologOp, lhs, rhs))
             return false;
         *pop = JSOP_NOP;
@@ -3206,17 +3203,17 @@ MaybeEmitLetGroupDecl(JSContext *cx, Byt
                       LetNotes *letNotes, JSOp *pop)
 {
     JS_ASSERT(pn->isKind(PNK_ASSIGN));
     JS_ASSERT(pn->isOp(JSOP_NOP));
     JS_ASSERT(*pop == JSOP_POP || *pop == JSOP_POPV);
 
     ParseNode *lhs = pn->pn_left;
     ParseNode *rhs = pn->pn_right;
-    if (lhs->isKind(PNK_RB) && rhs->isKind(PNK_RB) &&
+    if (lhs->isKind(PNK_ARRAY) && rhs->isKind(PNK_ARRAY) &&
         !(rhs->pn_xflags & PNX_HOLEY) &&
         !(lhs->pn_xflags & PNX_HOLEY) &&
         lhs->pn_count == rhs->pn_count)
     {
         for (ParseNode *l = lhs->pn_head; l; l = l->pn_next) {
             if (l->getOp() != JSOP_SETLOCAL)
                 return true;
         }
@@ -3245,17 +3242,17 @@ EmitVariables(JSContext *cx, BytecodeEmi
     ParseNode *next;
     for (ParseNode *pn2 = pn->pn_head; ; pn2 = next) {
         bool first = pn2 == pn->pn_head;
         next = pn2->pn_next;
 
         ParseNode *pn3;
         if (!pn2->isKind(PNK_NAME)) {
 #if JS_HAS_DESTRUCTURING
-            if (pn2->isKind(PNK_RB) || pn2->isKind(PNK_RC)) {
+            if (pn2->isKind(PNK_ARRAY) || pn2->isKind(PNK_OBJECT)) {
                 /*
                  * Emit variable binding ops, but not destructuring ops.  The
                  * parser (see Parser::variables) has ensured that our caller
                  * will be the PNK_FOR/PNK_FORIN case in EmitTree, and that
                  * case will emit the destructuring code only after emitting an
                  * enumerating opcode and a branch that tests whether the
                  * enumeration ended.
                  */
@@ -3469,30 +3466,30 @@ EmitAssignment(JSContext *cx, BytecodeEm
         break;
       case PNK_DOT:
         if (!EmitTree(cx, bce, lhs->expr()))
             return false;
         offset++;
         if (!bce->makeAtomIndex(lhs->pn_atom, &atomIndex))
             return false;
         break;
-      case PNK_LB:
+      case PNK_ELEM:
         JS_ASSERT(lhs->isArity(PN_BINARY));
         if (!EmitTree(cx, bce, lhs->pn_left))
             return false;
         if (!EmitTree(cx, bce, lhs->pn_right))
             return false;
         offset += 2;
         break;
 #if JS_HAS_DESTRUCTURING
-      case PNK_RB:
-      case PNK_RC:
+      case PNK_ARRAY:
+      case PNK_OBJECT:
         break;
 #endif
-      case PNK_LP:
+      case PNK_CALL:
         if (!EmitTree(cx, bce, lhs))
             return false;
         JS_ASSERT(lhs->pn_xflags & PNX_SETCALL);
         offset += 2;
         break;
 #if JS_HAS_XML_SUPPORT
       case PNK_XMLUNARY:
         JS_ASSERT(!bce->sc->inStrictMode());
@@ -3542,18 +3539,18 @@ EmitAssignment(JSContext *cx, BytecodeEm
           case PNK_DOT: {
             if (Emit1(cx, bce, JSOP_DUP) < 0)
                 return false;
             bool isLength = (lhs->pn_atom == cx->runtime->atomState.lengthAtom);
             if (!EmitIndex32(cx, isLength ? JSOP_LENGTH : JSOP_GETPROP, atomIndex, bce))
                 return false;
             break;
           }
-          case PNK_LB:
-          case PNK_LP:
+          case PNK_ELEM:
+          case PNK_CALL:
 #if JS_HAS_XML_SUPPORT
           case PNK_XMLUNARY:
 #endif
             if (Emit1(cx, bce, JSOP_DUP2) < 0)
                 return false;
             if (!EmitElemOpBase(cx, bce, JSOP_GETELEM))
                 return false;
             break;
@@ -3589,18 +3586,18 @@ EmitAssignment(JSContext *cx, BytecodeEm
         }
         if (Emit1(cx, bce, op) < 0)
             return false;
     }
 
     /* Left parts such as a.b.c and a[b].c need a decompiler note. */
     if (!lhs->isKind(PNK_NAME) &&
 #if JS_HAS_DESTRUCTURING
-        !lhs->isKind(PNK_RB) &&
-        !lhs->isKind(PNK_RC) &&
+        !lhs->isKind(PNK_ARRAY) &&
+        !lhs->isKind(PNK_OBJECT) &&
 #endif
         NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - top) < 0)
     {
         return false;
     }
 
     /* Finally, emit the specialized assignment bytecode. */
     switch (lhs->getKind()) {
@@ -3619,24 +3616,24 @@ EmitAssignment(JSContext *cx, BytecodeEm
             if (!EmitIndexOp(cx, lhs->getOp(), atomIndex, bce))
                 return false;
         }
         break;
       case PNK_DOT:
         if (!EmitIndexOp(cx, lhs->getOp(), atomIndex, bce))
             return false;
         break;
-      case PNK_LB:
-      case PNK_LP:
+      case PNK_ELEM:
+      case PNK_CALL:
         if (Emit1(cx, bce, JSOP_SETELEM) < 0)
             return false;
         break;
 #if JS_HAS_DESTRUCTURING
-      case PNK_RB:
-      case PNK_RC:
+      case PNK_ARRAY:
+      case PNK_OBJECT:
         if (!EmitDestructuringOps(cx, bce, SRC_DECL_NONE, lhs))
             return false;
         break;
 #endif
 #if JS_HAS_XML_SUPPORT
       case PNK_XMLUNARY:
         JS_ASSERT(!bce->sc->inStrictMode());
         if (Emit1(cx, bce, JSOP_SETXMLNAME) < 0)
@@ -3712,17 +3709,17 @@ ParseNode::getConstantValue(JSContext *c
       case PNK_FALSE:
         vp->setBoolean(false);
         return true;
       case PNK_NULL:
         vp->setNull();
         return true;
       case PNK_SPREAD:
         return false;
-      case PNK_RB: {
+      case PNK_ARRAY: {
         JS_ASSERT(isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
 
         RootedObject obj(cx, NewDenseAllocatedArray(cx, pn_count));
         if (!obj)
             return false;
 
         unsigned idx = 0;
         RootedId id(cx);
@@ -3735,17 +3732,17 @@ ParseNode::getConstantValue(JSContext *c
                 return false;
         }
         JS_ASSERT(idx == pn_count);
 
         types::FixArrayType(cx, obj);
         vp->setObject(*obj);
         return true;
       }
-      case PNK_RC: {
+      case PNK_OBJECT: {
         JS_ASSERT(isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
 
         gc::AllocKind kind = GuessObjectGCKind(pn_count);
         RootedObject obj(cx, NewBuiltinClassInstance(cx, &ObjectClass, kind));
         if (!obj)
             return false;
 
         for (ParseNode *pn = pn_head; pn; pn = pn->pn_next) {
@@ -3838,18 +3835,18 @@ EmitCatch(JSContext *cx, BytecodeEmitter
      * it later when rethrowing or in other catches.
      */
     if (pn->pn_kid2 && Emit1(cx, bce, JSOP_DUP) < 0)
         return false;
 
     ParseNode *pn2 = pn->pn_kid1;
     switch (pn2->getKind()) {
 #if JS_HAS_DESTRUCTURING
-      case PNK_RB:
-      case PNK_RC:
+      case PNK_ARRAY:
+      case PNK_OBJECT:
         if (!EmitDestructuringOps(cx, bce, SRC_DECL_NONE, pn2))
             return false;
         if (Emit1(cx, bce, JSOP_POP) < 0)
             return false;
         break;
 #endif
 
       case PNK_NAME:
@@ -4818,21 +4815,16 @@ EmitFor(JSContext *cx, BytecodeEmitter *
     return pn->pn_left->isKind(PNK_FORIN)
            ? EmitForIn(cx, bce, pn, top)
            : EmitNormalFor(cx, bce, pn, top);
 }
 
 static JS_NEVER_INLINE bool
 EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
 {
-#if JS_HAS_XML_SUPPORT
-    if (pn->isArity(PN_NULLARY))
-        return Emit1(cx, bce, JSOP_GETFUNNS) >= 0;
-#endif
-
     RootedFunction fun(cx, pn->pn_funbox->fun());
     JS_ASSERT(fun->isInterpreted());
     if (fun->script()) {
         /*
          * This second pass is needed to emit JSOP_NOP with a source note
          * for the already-emitted function definition prolog opcode. See
          * comments in EmitStatementList.
          */
@@ -5272,33 +5264,33 @@ EmitDelete(JSContext *cx, BytecodeEmitte
         break;
 #if JS_HAS_XML_SUPPORT
       case PNK_DBLDOT:
         JS_ASSERT(!bce->sc->inStrictMode());
         if (!EmitElemOp(cx, pn2, JSOP_DELDESC, bce))
             return false;
         break;
 #endif
-      case PNK_LB:
+      case PNK_ELEM:
         if (!EmitElemOp(cx, pn2, JSOP_DELELEM, bce))
             return false;
         break;
       default:
       {
         /*
          * If useless, just emit JSOP_TRUE; otherwise convert delete foo()
          * to foo(), true (a comma expression, requiring SRC_PCDELTA).
          */
         bool useful = false;
         if (!CheckSideEffects(cx, bce, pn2, &useful))
             return false;
 
         ptrdiff_t off, noteIndex;
         if (useful) {
-            JS_ASSERT_IF(pn2->isKind(PNK_LP), !(pn2->pn_xflags & PNX_SETCALL));
+            JS_ASSERT_IF(pn2->isKind(PNK_CALL), !(pn2->pn_xflags & PNX_SETCALL));
             if (!EmitTree(cx, bce, pn2))
                 return false;
             off = bce->offset();
             noteIndex = NewSrcNote2(cx, bce, SRC_PCDELTA, 0);
             if (noteIndex < 0 || Emit1(cx, bce, JSOP_POP) < 0)
                 return false;
         } else {
             off = noteIndex = -1;
@@ -5315,17 +5307,17 @@ EmitDelete(JSContext *cx, BytecodeEmitte
     }
 
     return true;
 }
 
 static bool
 EmitCallOrNew(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
 {
-    bool callop = pn->isKind(PNK_LP);
+    bool callop = pn->isKind(PNK_CALL);
 
     /*
      * Emit callable invocation or operator new (constructor call) code.
      * First, emit code for the left operand to evaluate the callable or
      * constructable object expression.
      *
      * For operator new applied to other expressions than E4X ones, we emit
      * JSOP_GETPROP instead of JSOP_CALLPROP, etc. This is necessary to
@@ -5384,17 +5376,17 @@ EmitCallOrNew(JSContext *cx, BytecodeEmi
         }
         if (!EmitNameOp(cx, bce, pn2, callop))
             return false;
         break;
       case PNK_DOT:
         if (!EmitPropOp(cx, pn2, pn2->getOp(), bce, callop))
             return false;
         break;
-      case PNK_LB:
+      case PNK_ELEM:
         JS_ASSERT(pn2->isOp(JSOP_GETELEM));
         if (!EmitElemOp(cx, pn2, callop ? JSOP_CALLELEM : JSOP_GETELEM, bce))
             return false;
         break;
 #if JS_HAS_XML_SUPPORT
       case PNK_XMLUNARY:
         JS_ASSERT(pn2->isOp(JSOP_XMLNAME));
         if (!EmitXMLName(cx, pn2, JSOP_CALLXMLNAME, bce))
@@ -5516,28 +5508,27 @@ EmitLogical(JSContext *cx, BytecodeEmitt
  * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr12127. See
  * the comment on EmitSwitch.
  */
 MOZ_NEVER_INLINE static bool
 EmitIncOrDec(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
 {
     /* Emit lvalue-specialized code for ++/-- operators. */
     ParseNode *pn2 = pn->pn_kid;
-    JS_ASSERT(!pn2->isKind(PNK_RP));
     JSOp op = pn->getOp();
     switch (pn2->getKind()) {
       case PNK_DOT:
         if (!EmitPropIncDec(cx, pn2, op, bce))
             return false;
         break;
-      case PNK_LB:
+      case PNK_ELEM:
         if (!EmitElemIncDec(cx, pn2, op, bce))
             return false;
         break;
-      case PNK_LP:
+      case PNK_CALL:
         if (!EmitTree(cx, bce, pn2))
             return false;
         if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - pn2->pn_offset) < 0)
             return false;
         if (Emit1(cx, bce, op) < 0)
             return false;
         /*
          * This is dead code for the decompiler, don't generate
@@ -6030,17 +6021,18 @@ frontend::EmitTree(JSContext *cx, Byteco
     ptrdiff_t top = bce->offset();
     pn->pn_offset = top;
 
     /* Emit notes to tell the current bytecode's source line number. */
     if (!UpdateLineNumberNotes(cx, bce, pn->pn_pos.begin.lineno))
         return false;
 
     switch (pn->getKind()) {
-      case PNK_FUNCTION:
+      case PNK_FUNCTIONDECL:
+      case PNK_FUNCTIONEXPR:
         ok = EmitFunc(cx, bce, pn);
         break;
 
       case PNK_ARGSBODY:
       {
         RootedFunction fun(cx, bce->sc->funbox()->fun());
         ParseNode *pnlast = pn->last();
 
@@ -6060,21 +6052,21 @@ frontend::EmitTree(JSContext *cx, Byteco
         }
         if (pnlast->pn_xflags & PNX_FUNCDEFS) {
             // This block contains top-level function definitions. To ensure
             // that we emit the bytecode defining them before the rest of code
             // in the block we use a separate pass over functions. During the
             // main pass later the emitter will add JSOP_NOP with source notes
             // for the function to preserve the original functions position
             // when decompiling.
-             
+
             // Currently this is used only for functions, as compile-as-we go
             // mode for scripts does not allow separate emitter passes.
             for (ParseNode *pn2 = pnchild; pn2; pn2 = pn2->pn_next) {
-                if (pn2->isKind(PNK_FUNCTION) && pn2->functionIsHoisted()) {
+                if (pn2->isKind(PNK_FUNCTIONDECL) && pn2->functionIsHoisted()) {
                     if (!EmitTree(cx, bce, pn2))
                         return false;
                 }
             }
         }
         if (fun->hasDefaults()) {
             ParseNode *rest = NULL;
             bool restIsDefn = false;
@@ -6156,21 +6148,21 @@ frontend::EmitTree(JSContext *cx, Byteco
         ok = EmitDo(cx, bce, pn);
         break;
 
       case PNK_FOR:
         ok = EmitFor(cx, bce, pn, top);
         break;
 
       case PNK_BREAK:
-        ok = EmitBreak(cx, bce, pn->asBreakStatement().label());
+        ok = EmitBreak(cx, bce, pn->as<BreakStatement>().label());
         break;
 
       case PNK_CONTINUE:
-        ok = EmitContinue(cx, bce, pn->asContinueStatement().label());
+        ok = EmitContinue(cx, bce, pn->as<ContinueStatement>().label());
         break;
 
       case PNK_WITH:
         ok = EmitWith(cx, bce, pn);
         break;
 
       case PNK_TRY:
         if (!EmitTry(cx, bce, pn))
@@ -6275,17 +6267,17 @@ frontend::EmitTree(JSContext *cx, Byteco
       case PNK_MULASSIGN:
       case PNK_DIVASSIGN:
       case PNK_MODASSIGN:
         if (!EmitAssignment(cx, bce, pn->pn_left, pn->getOp(), pn->pn_right))
             return false;
         break;
 
       case PNK_CONDITIONAL:
-        ok = EmitConditionalExpression(cx, bce, pn->asConditionalExpression());
+        ok = EmitConditionalExpression(cx, bce, pn->as<ConditionalExpression>());
         break;
 
       case PNK_OR:
       case PNK_AND:
         ok = EmitLogical(cx, bce, pn);
         break;
 
       case PNK_ADD:
@@ -6318,17 +6310,16 @@ frontend::EmitTree(JSContext *cx, Byteco
             while ((pn2 = pn2->pn_next) != NULL) {
                 if (!EmitTree(cx, bce, pn2))
                     return false;
                 if (Emit1(cx, bce, op) < 0)
                     return false;
             }
         } else {
 #if JS_HAS_XML_SUPPORT
-
       case PNK_DBLCOLON:
             JS_ASSERT(pn->getOp() != JSOP_XMLNAME);
             if (pn->isArity(PN_NAME)) {
                 if (!EmitTree(cx, bce, pn->expr()))
                     return false;
                 if (!EmitAtomOp(cx, pn, pn->getOp(), bce))
                     return false;
                 break;
@@ -6352,16 +6343,20 @@ frontend::EmitTree(JSContext *cx, Byteco
             bce->emittingForInit = oldEmittingForInit;
 #endif
             if (Emit1(cx, bce, pn->getOp()) < 0)
                 return false;
         }
         break;
 
 #if JS_HAS_XML_SUPPORT
+      case PNK_FUNCTIONNS:
+        ok = (Emit1(cx, bce, JSOP_GETFUNNS) >= 0);
+        break;
+
       case PNK_XMLUNARY:
         if (pn->getOp() == JSOP_XMLNAME) {
             if (!EmitXMLName(cx, pn, JSOP_XMLNAME, bce))
                 return false;
         } else {
             JSOp op = pn->getOp();
             JS_ASSERT(op == JSOP_BINDXMLNAME || op == JSOP_SETXMLNAME);
             bool oldEmittingForInit = bce->emittingForInit;
@@ -6435,28 +6430,29 @@ frontend::EmitTree(JSContext *cx, Byteco
         ok = EmitPropOp(cx, pn, pn->getOp(), bce, false);
         break;
 
 #if JS_HAS_XML_SUPPORT
       case PNK_DBLDOT:
         JS_ASSERT(!bce->sc->inStrictMode());
         /* FALL THROUGH */
 #endif
-      case PNK_LB:
+
+      case PNK_ELEM:
         /*
          * Pop two operands, convert the left one to object and the right one
          * to property name (atom or tagged int), get the named property, and
          * push its value.  Set the "obj" register to the result of ToObject
          * on the left operand.
          */
         ok = EmitElemOp(cx, pn, pn->getOp(), bce);
         break;
 
       case PNK_NEW:
-      case PNK_LP:
+      case PNK_CALL:
         ok = EmitCallOrNew(cx, bce, pn, top);
         break;
 
       case PNK_LEXICALSCOPE:
         ok = EmitLexicalScope(cx, bce, pn);
         break;
 
 #if JS_HAS_BLOCK_SCOPE
@@ -6482,24 +6478,24 @@ frontend::EmitTree(JSContext *cx, Byteco
         if (slot < 0)
             return false;
         if (!EmitUnaliasedVarOp(cx, pn->getOp(), slot, bce))
             return false;
         break;
       }
 #endif
 
-      case PNK_RB:
+      case PNK_ARRAY:
 #if JS_HAS_GENERATORS
       case PNK_ARRAYCOMP:
 #endif
         ok = EmitArray(cx, bce, pn);
         break;
 
-      case PNK_RC:
+      case PNK_OBJECT:
         ok = EmitObject(cx, bce, pn);
         break;
 
       case PNK_NAME:
         if (!EmitNameOp(cx, bce, pn, false))
             return false;
         break;
 
@@ -6611,17 +6607,17 @@ frontend::EmitTree(JSContext *cx, Byteco
             JS_ASSERT(pn->isArity(PN_NULLARY));
             ok = pn->isOp(JSOP_OBJECT)
                  ? EmitObjectOp(cx, pn->pn_objbox, pn->getOp(), bce)
                  : EmitAtomOp(cx, pn, pn->getOp(), bce);
         }
         break;
 
       case PNK_XMLPI:
-        if (!EmitXMLProcessingInstruction(cx, bce, pn->asXMLProcessingInstruction()))
+        if (!EmitXMLProcessingInstruction(cx, bce, pn->as<XMLProcessingInstruction>()))
             return false;
         break;
 #endif /* JS_HAS_XML_SUPPORT */
 
       case PNK_NOP:
         JS_ASSERT(pn->getArity() == PN_NULLARY);
         break;
 
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -240,17 +240,17 @@ FoldXMLConstants(JSContext *cx, ParseNod
 
           case PNK_XMLCOMMENT:
             str = js_MakeXMLCommentString(cx, pn2->pn_atom);
             if (!str)
                 return false;
             break;
 
           case PNK_XMLPI: {
-            XMLProcessingInstruction &pi = pn2->asXMLProcessingInstruction();
+            XMLProcessingInstruction &pi = pn2->as<XMLProcessingInstruction>();
             str = js_MakeXMLPIString(cx, pi.target(), pi.data());
             if (!str)
                 return false;
             break;
           }
 
           cantfold:
           default:
@@ -359,35 +359,16 @@ Boolish(ParseNode *pn)
 {
     switch (pn->getOp()) {
       case JSOP_DOUBLE:
         return (pn->pn_dval != 0 && !MOZ_DOUBLE_IS_NaN(pn->pn_dval)) ? Truthy : Falsy;
 
       case JSOP_STRING:
         return (pn->pn_atom->length() > 0) ? Truthy : Falsy;
 
-#if JS_HAS_GENERATOR_EXPRS
-      case JSOP_CALL:
-      {
-        /*
-         * A generator expression as an if or loop condition has no effects, it
-         * simply results in a truthy object reference. This condition folding
-         * is needed for the decompiler. See bug 442342 and bug 443074.
-         */
-        if (pn->pn_count != 1)
-            return Unknown;
-        ParseNode *pn2 = pn->pn_head;
-        if (!pn2->isKind(PNK_FUNCTION))
-            return Unknown;
-        if (!(pn2->pn_funbox->inGenexpLambda))
-            return Unknown;
-        return Truthy;
-      }
-#endif
-
       case JSOP_DEFFUN:
       case JSOP_LAMBDA:
       case JSOP_TRUE:
         return Truthy;
 
       case JSOP_NULL:
       case JSOP_FALSE:
         return Falsy;
@@ -413,17 +394,17 @@ frontend::FoldConstants(JSContext *cx, P
 
       case PN_LIST:
       {
         /* Propagate inCond through logical connectives. */
         bool cond = inCond && (pn->isKind(PNK_OR) || pn->isKind(PNK_AND));
 
         /* Don't fold a parenthesized call expression. See bug 537673. */
         pn1 = pn2 = pn->pn_head;
-        if ((pn->isKind(PNK_LP) || pn->isKind(PNK_NEW)) && pn2->isInParens())
+        if ((pn->isKind(PNK_CALL) || pn->isKind(PNK_NEW)) && pn2->isInParens())
             pn2 = pn2->pn_next;
 
         /* Save the list head in pn1 for later use. */
         for (; pn2; pn2 = pn2->pn_next) {
             if (!FoldConstants(cx, pn2, parser, inGenexpLambda, cond))
                 return false;
         }
         break;
--- a/js/src/frontend/NameFunctions.cpp
+++ b/js/src/frontend/NameFunctions.cpp
@@ -24,17 +24,17 @@ class NameResolver
 
     JSContext *cx;
     size_t nparents;                /* number of parents in the parents array */
     ParseNode *parents[MaxParents]; /* history of ParseNodes we've been looking at */
     StringBuffer *buf;              /* when resolving, buffer to append to */
 
     /* Test whether a ParseNode represents a function invocation */
     bool call(ParseNode *pn) {
-        return pn && pn->isKind(PNK_LP);
+        return pn && pn->isKind(PNK_CALL);
     }
 
     /*
      * Append a reference to a property named |name| to |buf|. If |name| is
      * a proper identifier name, then we append '.name'; otherwise, we
      * append '["name"]'.
      *
      * Note that we need the IsIdentifier check for atoms from both
@@ -70,17 +70,17 @@ class NameResolver
     bool nameExpression(ParseNode *n) {
         switch (n->getKind()) {
             case PNK_DOT:
                 return nameExpression(n->expr()) && appendPropertyReference(n->pn_atom);
 
             case PNK_NAME:
                 return buf->append(n->pn_atom);
 
-            case PNK_LB:
+            case PNK_ELEM:
                 return nameExpression(n->pn_left) &&
                        buf->append("[") &&
                        nameExpression(n->pn_right) &&
                        buf->append("]");
 
             case PNK_NUMBER:
                 return appendNumber(n->pn_dval);
 
@@ -112,17 +112,20 @@ class NameResolver
 
         for (int pos = nparents - 1; pos >= 0; pos--) {
             ParseNode *cur = parents[pos];
             if (cur->isAssignment())
                 return cur;
 
             switch (cur->getKind()) {
                 case PNK_NAME:     return cur;  /* found the initialized declaration */
-                case PNK_FUNCTION: return NULL; /* won't find an assignment or declaration */
+
+                case PNK_FUNCTIONDECL:
+                case PNK_FUNCTIONEXPR:
+                    return NULL; /* won't find an assignment or declaration */
 
                 case PNK_RETURN:
                     /*
                      * Normally the relevant parent of a node is its direct parent, but
                      * sometimes with code like:
                      *
                      *    var foo = (function() { return function() {}; })();
                      *
@@ -141,22 +144,22 @@ class NameResolver
                             break;
                         }
                         cur = parents[tmp];
                     }
                     break;
 
                 case PNK_COLON:
                     /*
-                     * If this is a PNK_COLON, but our parent is not a PNK_RC,
+                     * If this is a PNK_COLON, but our parent is not a PNK_OBJECT,
                      * then this is a label and we're done naming. Otherwise we
-                     * record the PNK_COLON but skip the PNK_RC so we're not
+                     * record the PNK_COLON but skip the PNK_OBJECT so we're not
                      * flagged as a contributor.
                      */
-                    if (pos == 0 || !parents[pos - 1]->isKind(PNK_RC))
+                    if (pos == 0 || !parents[pos - 1]->isKind(PNK_OBJECT))
                         return NULL;
                     pos--;
                     /* fallthrough */
 
                 /* Save any other nodes we encounter on the way up. */
                 default:
                     JS_ASSERT(*size < MaxParents);
                     nameable[(*size)++] = cur;
@@ -169,17 +172,17 @@ class NameResolver
     }
 
     /*
      * Resolve the name of a function. If the function already has a name
      * listed, then it is skipped. Otherwise an intelligent name is guessed to
      * assign to the function's displayAtom field
      */
     JSAtom *resolveFun(ParseNode *pn, JSAtom *prefix) {
-        JS_ASSERT(pn != NULL && pn->isKind(PNK_FUNCTION));
+        JS_ASSERT(pn->isKind(PNK_FUNCTIONDECL) || pn->isKind(PNK_FUNCTIONEXPR));
         JSFunction *fun = pn->pn_funbox->fun();
         if (nparents == 0)
             return NULL;
 
         StringBuffer buf(cx);
         this->buf = &buf;
 
         /* If the function already has a name, use that */
@@ -267,17 +270,19 @@ class NameResolver
      * Resolve all names for anonymous functions recursively within the
      * ParseNode instance given. The prefix is for each subsequent name, and
      * should initially be NULL.
      */
     void resolve(ParseNode *cur, JSAtom *prefix = NULL) {
         if (cur == NULL)
             return;
 
-        if (cur->isKind(PNK_FUNCTION) && cur->isArity(PN_FUNC)) {
+        if ((cur->isKind(PNK_FUNCTIONEXPR) || cur->isKind(PNK_FUNCTIONDECL)) &&
+            cur->isArity(PN_FUNC))
+        {
             JSAtom *prefix2 = resolveFun(cur, prefix);
             /*
              * If a function looks like (function(){})() where the parent node
              * of the definition of the function is a call, then it shouldn't
              * contribute anything to the namespace, so don't bother updating
              * the prefix to whatever was returned.
              */
             if (!isDirectCall(nparents - 1, cur))
@@ -308,17 +313,17 @@ class NameResolver
                     resolve(cur->pn_right, prefix);
                 break;
             case PN_TERNARY:
                 resolve(cur->pn_kid1, prefix);
                 resolve(cur->pn_kid2, prefix);
                 resolve(cur->pn_kid3, prefix);
                 break;
             case PN_FUNC:
-                JS_ASSERT(cur->isKind(PNK_FUNCTION));
+                JS_ASSERT(cur->isKind(PNK_FUNCTIONDECL) || cur->isKind(PNK_FUNCTIONEXPR));
                 resolve(cur->pn_body, prefix);
                 break;
             case PN_LIST:
                 for (ParseNode *nxt = cur->pn_head; nxt; nxt = nxt->pn_next)
                     resolve(nxt, prefix);
                 break;
         }
         nparents--;
--- a/js/src/frontend/ParseNode-inl.h
+++ b/js/src/frontend/ParseNode-inl.h
@@ -26,164 +26,39 @@ UpvarCookie::set(JSContext *cx, unsigned
     level_ = newLevel;
     slot_ = newSlot;
     return true;
 }
 
 inline PropertyName *
 ParseNode::name() const
 {
-    JS_ASSERT(isKind(PNK_FUNCTION) || isKind(PNK_NAME) || isKind(PNK_INTRINSICNAME));
-    JSAtom *atom = isKind(PNK_FUNCTION) ? pn_funbox->fun()->atom() : pn_atom;
+    JS_ASSERT(isKind(PNK_FUNCTIONDECL) || isKind(PNK_NAME) || isKind(PNK_INTRINSICNAME));
+    JSAtom *atom = isKind(PNK_FUNCTIONDECL) ? pn_funbox->fun()->atom() : pn_atom;
     return atom->asPropertyName();
 }
 
 inline bool
 ParseNode::isConstant()
 {
     switch (pn_type) {
       case PNK_NUMBER:
       case PNK_STRING:
       case PNK_NULL:
       case PNK_FALSE:
       case PNK_TRUE:
         return true;
-      case PNK_RB:
-      case PNK_RC:
+      case PNK_ARRAY:
+      case PNK_OBJECT:
         return isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST);
       default:
         return false;
     }
 }
 
-#ifdef DEBUG
-inline void
-IndentNewLine(int indent)
-{
-    fputc('\n', stderr);
-    for (int i = 0; i < indent; ++i)
-        fputc(' ', stderr);
-}
-
-inline void
-ParseNode::dump(int indent)
-{
-    switch (pn_arity) {
-      case PN_NULLARY:
-        ((NullaryNode *) this)->dump();
-        break;
-      case PN_UNARY:
-        ((UnaryNode *) this)->dump(indent);
-        break;
-      case PN_BINARY:
-        ((BinaryNode *) this)->dump(indent);
-        break;
-      case PN_TERNARY:
-        ((TernaryNode *) this)->dump(indent);
-        break;
-      case PN_FUNC:
-        ((FunctionNode *) this)->dump(indent);
-        break;
-      case PN_LIST:
-        ((ListNode *) this)->dump(indent);
-        break;
-      case PN_NAME:
-        ((NameNode *) this)->dump(indent);
-        break;
-      default:
-        fprintf(stderr, "?");
-        break;
-    }
-}
-
-inline void
-NullaryNode::dump()
-{
-    fprintf(stderr, "(%s)", js_CodeName[getOp()]);
-}
-
-inline void
-UnaryNode::dump(int indent)
-{
-    const char *name = js_CodeName[getOp()];
-    fprintf(stderr, "(%s ", name);
-    indent += strlen(name) + 2;
-    DumpParseTree(pn_kid, indent);
-    fprintf(stderr, ")");
-}
-
-inline void
-BinaryNode::dump(int indent)
-{
-    const char *name = js_CodeName[getOp()];
-    fprintf(stderr, "(%s ", name);
-    indent += strlen(name) + 2;
-    DumpParseTree(pn_left, indent);
-    IndentNewLine(indent);
-    DumpParseTree(pn_right, indent);
-    fprintf(stderr, ")");
-}
-
-inline void
-TernaryNode::dump(int indent)
-{
-    const char *name = js_CodeName[getOp()];
-    fprintf(stderr, "(%s ", name);
-    indent += strlen(name) + 2;
-    DumpParseTree(pn_kid1, indent);
-    IndentNewLine(indent);
-    DumpParseTree(pn_kid2, indent);
-    IndentNewLine(indent);
-    DumpParseTree(pn_kid3, indent);
-    fprintf(stderr, ")");
-}
-
-inline void
-FunctionNode::dump(int indent)
-{
-    const char *name = js_CodeName[getOp()];
-    fprintf(stderr, "(%s ", name);
-    indent += strlen(name) + 2;
-    DumpParseTree(pn_body, indent);
-    fprintf(stderr, ")");
-}
-
-inline void
-ListNode::dump(int indent)
-{
-    const char *name = js_CodeName[getOp()];
-    fprintf(stderr, "(%s ", name);
-    if (pn_head != NULL) {
-        indent += strlen(name) + 2;
-        DumpParseTree(pn_head, indent);
-        ParseNode *pn = pn_head->pn_next;
-        while (pn != NULL) {
-            IndentNewLine(indent);
-            DumpParseTree(pn, indent);
-            pn = pn->pn_next;
-        }
-    }
-    fprintf(stderr, ")");
-}
-
-inline void
-NameNode::dump(int indent)
-{
-    const char *name = js_CodeName[getOp()];
-    if (isUsed())
-        fprintf(stderr, "(%s)", name);
-    else {
-        fprintf(stderr, "(%s ", name);
-        indent += strlen(name) + 2;
-        DumpParseTree(expr(), indent);
-        fprintf(stderr, ")");
-    }
-}
-#endif
-
 struct ParseContext;
 
 inline void
 NameNode::initCommon(ParseContext *pc)
 {
     pn_expr = NULL;
     pn_cookie.makeFree();
     pn_dflags = (!pc->topStmt || pc->topStmt->type == STMT_BLOCK)
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -539,21 +539,21 @@ frontend::CloneLeftHandSide(ParseNode *o
     if (!pn)
         return NULL;
     pn->setInParens(opn->isInParens());
     pn->setDefn(opn->isDefn());
     pn->setUsed(opn->isUsed());
 
 #if JS_HAS_DESTRUCTURING
     if (opn->isArity(PN_LIST)) {
-        JS_ASSERT(opn->isKind(PNK_RB) || opn->isKind(PNK_RC));
+        JS_ASSERT(opn->isKind(PNK_ARRAY) || opn->isKind(PNK_OBJECT));
         pn->makeEmpty();
         for (ParseNode *opn2 = opn->pn_head; opn2; opn2 = opn2->pn_next) {
             ParseNode *pn2;
-            if (opn->isKind(PNK_RC)) {
+            if (opn->isKind(PNK_OBJECT)) {
                 JS_ASSERT(opn2->isArity(PN_BINARY));
                 JS_ASSERT(opn2->isKind(PNK_COLON));
 
                 ParseNode *tag = CloneParseTree(opn2->pn_left, parser);
                 if (!tag)
                     return NULL;
                 ParseNode *target = CloneLeftHandSide(opn2->pn_right, parser);
                 if (!target)
@@ -597,17 +597,208 @@ frontend::CloneLeftHandSide(ParseNode *o
 
             LinkUseToDef(pn, (Definition *) opn);
         }
     }
     return pn;
 }
 
 #ifdef DEBUG
+
+static const char *parseNodeNames[] = {
+#define STRINGIFY(name) #name,
+    FOR_EACH_PARSE_NODE_KIND(STRINGIFY)
+#undef STRINGIFY
+};
+
 void
 frontend::DumpParseTree(ParseNode *pn, int indent)
 {
     if (pn == NULL)
-        fprintf(stderr, "()");
+        fprintf(stderr, "#NULL");
     else
         pn->dump(indent);
 }
+
+static void
+IndentNewLine(int indent)
+{
+    fputc('\n', stderr);
+    for (int i = 0; i < indent; ++i)
+        fputc(' ', stderr);
+}
+
+void
+ParseNode::dump()
+{
+    dump(0);
+    fputc('\n', stderr);
+}
+
+void
+ParseNode::dump(int indent)
+{
+    switch (pn_arity) {
+      case PN_NULLARY:
+        ((NullaryNode *) this)->dump();
+        break;
+      case PN_UNARY:
+        ((UnaryNode *) this)->dump(indent);
+        break;
+      case PN_BINARY:
+        ((BinaryNode *) this)->dump(indent);
+        break;
+      case PN_TERNARY:
+        ((TernaryNode *) this)->dump(indent);
+        break;
+      case PN_FUNC:
+        ((FunctionNode *) this)->dump(indent);
+        break;
+      case PN_LIST:
+        ((ListNode *) this)->dump(indent);
+        break;
+      case PN_NAME:
+        ((NameNode *) this)->dump(indent);
+        break;
+      default:
+        fprintf(stderr, "#<BAD NODE %p, kind=%u, arity=%u>",
+                (void *) this, unsigned(getKind()), unsigned(pn_arity));
+        break;
+    }
+}
+
+void
+NullaryNode::dump()
+{
+    switch (getKind()) {
+      case PNK_TRUE:  fprintf(stderr, "#true");  break;
+      case PNK_FALSE: fprintf(stderr, "#false"); break;
+      case PNK_NULL:  fprintf(stderr, "#null");  break;
+
+      case PNK_NUMBER: {
+        ToCStringBuf cbuf;
+        const char *cstr = NumberToCString(NULL, &cbuf, pn_dval);
+        if (!MOZ_DOUBLE_IS_FINITE(pn_dval))
+            fputc('#', stderr);
+        if (cstr)
+            fprintf(stderr, "%s", cstr);
+        else
+            fprintf(stderr, "%g", pn_dval);
+        break;
+      }
+
+      case PNK_STRING:
+        JSString::dumpChars(pn_atom->chars(), pn_atom->length());
+        break;
+
+      default:
+        fprintf(stderr, "(%s)", parseNodeNames[getKind()]);
+    }
+}
+
+void
+UnaryNode::dump(int indent)
+{
+    const char *name = parseNodeNames[getKind()];
+    fprintf(stderr, "(%s ", name);
+    indent += strlen(name) + 2;
+    DumpParseTree(pn_kid, indent);
+    fprintf(stderr, ")");
+}
+
+void
+BinaryNode::dump(int indent)
+{
+    const char *name = parseNodeNames[getKind()];
+    fprintf(stderr, "(%s ", name);
+    indent += strlen(name) + 2;
+    DumpParseTree(pn_left, indent);
+    IndentNewLine(indent);
+    DumpParseTree(pn_right, indent);
+    fprintf(stderr, ")");
+}
+
+void
+TernaryNode::dump(int indent)
+{
+    const char *name = parseNodeNames[getKind()];
+    fprintf(stderr, "(%s ", name);
+    indent += strlen(name) + 2;
+    DumpParseTree(pn_kid1, indent);
+    IndentNewLine(indent);
+    DumpParseTree(pn_kid2, indent);
+    IndentNewLine(indent);
+    DumpParseTree(pn_kid3, indent);
+    fprintf(stderr, ")");
+}
+
+void
+FunctionNode::dump(int indent)
+{
+    const char *name = parseNodeNames[getKind()];
+    fprintf(stderr, "(%s ", name);
+    indent += strlen(name) + 2;
+    DumpParseTree(pn_body, indent);
+    fprintf(stderr, ")");
+}
+
+void
+ListNode::dump(int indent)
+{
+    const char *name = parseNodeNames[getKind()];
+    fprintf(stderr, "(%s [", name);
+    if (pn_head != NULL) {
+        indent += strlen(name) + 3;
+        DumpParseTree(pn_head, indent);
+        ParseNode *pn = pn_head->pn_next;
+        while (pn != NULL) {
+            IndentNewLine(indent);
+            DumpParseTree(pn, indent);
+            pn = pn->pn_next;
+        }
+    }
+    fprintf(stderr, "])");
+}
+
+void
+NameNode::dump(int indent)
+{
+    if (isKind(PNK_NAME) || isKind(PNK_DOT)) {
+        if (isKind(PNK_DOT))
+            fprintf(stderr, "(.");
+
+        if (!pn_atom) {
+            fprintf(stderr, "#<null name>");
+        } else {
+            const jschar *s = pn_atom->chars();
+            size_t len = pn_atom->length();
+            if (len == 0)
+                fprintf(stderr, "#<zero-length name>");
+            for (size_t i = 0; i < len; i++) {
+                if (s[i] > 32 && s[i] < 127)
+                    fputc(s[i], stderr);
+                else if (s[i] <= 255)
+                    fprintf(stderr, "\\x%02x", (unsigned int) s[i]);
+                else
+                    fprintf(stderr, "\\u%04x", (unsigned int) s[i]);
+            }
+        }
+
+        if (isKind(PNK_DOT)) {
+            fputc(' ', stderr);
+            DumpParseTree(expr(), indent + 2);
+            fputc(')', stderr);
+        }
+        return;
+    }
+
+    JS_ASSERT(!isUsed());
+    const char *name = parseNodeNames[getKind()];
+    if (isUsed())
+        fprintf(stderr, "(%s)", name);
+    else {
+        fprintf(stderr, "(%s ", name);
+        indent += strlen(name) + 2;
+        DumpParseTree(expr(), indent);
+        fprintf(stderr, ")");
+    }
+}
 #endif
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -54,183 +54,185 @@ class UpvarCookie
 
     void makeFree() {
         level_ = FREE_LEVEL;
         slot_ = 0;      // value doesn't matter, won't be used
         JS_ASSERT(isFree());
     }
 };
 
+#define FOR_EACH_PARSE_NODE_KIND(F) \
+    F(NOP) \
+    F(SEMI) \
+    F(COMMA) \
+    F(CONDITIONAL) \
+    F(COLON) \
+    F(OR) \
+    F(AND) \
+    F(BITOR) \
+    F(BITXOR) \
+    F(BITAND) \
+    F(POS) \
+    F(NEG) \
+    F(ADD) \
+    F(SUB) \
+    F(STAR) \
+    F(DIV) \
+    F(MOD) \
+    F(PREINCREMENT) \
+    F(POSTINCREMENT) \
+    F(PREDECREMENT) \
+    F(POSTDECREMENT) \
+    F(DOT) \
+    F(ELEM) \
+    F(ARRAY) \
+    F(STATEMENTLIST) \
+    F(XMLCURLYEXPR) \
+    F(OBJECT) \
+    F(CALL) \
+    F(NAME) \
+    F(INTRINSICNAME) \
+    F(NUMBER) \
+    F(STRING) \
+    F(REGEXP) \
+    F(TRUE) \
+    F(FALSE) \
+    F(NULL) \
+    F(THIS) \
+    F(FUNCTIONDECL) \
+    F(FUNCTIONEXPR) \
+    F(IF) \
+    F(ELSE) \
+    F(SWITCH) \
+    F(CASE) \
+    F(DEFAULT) \
+    F(WHILE) \
+    F(DOWHILE) \
+    F(FOR) \
+    F(BREAK) \
+    F(CONTINUE) \
+    F(IN) \
+    F(VAR) \
+    F(CONST) \
+    F(WITH) \
+    F(RETURN) \
+    F(NEW) \
+    F(DELETE) \
+    F(TRY) \
+    F(CATCH) \
+    F(CATCHLIST) \
+    F(FINALLY) \
+    F(THROW) \
+    F(INSTANCEOF) \
+    F(DEBUGGER) \
+    F(DEFXMLNS) \
+    F(XMLSTAGO) \
+    F(XMLETAGO) \
+    F(XMLPTAGC) \
+    F(XMLTAGC) \
+    F(XMLNAME) \
+    F(XMLATTR) \
+    F(XMLSPACE) \
+    F(XMLTEXT) \
+    F(XMLCOMMENT) \
+    F(XMLCDATA) \
+    F(XMLPI) \
+    F(XMLUNARY) \
+    F(AT) \
+    F(FUNCTIONNS) \
+    F(DBLCOLON) \
+    F(ANYNAME) \
+    F(DBLDOT) \
+    F(FILTER) \
+    F(XMLELEM) \
+    F(XMLLIST) \
+    F(YIELD) \
+    F(ARRAYCOMP) \
+    F(ARRAYPUSH) \
+    F(LEXICALSCOPE) \
+    F(LET) \
+    F(SEQ) \
+    F(FORIN) \
+    F(FORHEAD) \
+    F(ARGSBODY) \
+    F(SPREAD) \
+    \
+    /* Equality operators. */ \
+    F(STRICTEQ) \
+    F(EQ) \
+    F(STRICTNE) \
+    F(NE) \
+    \
+    /* Unary operators. */ \
+    F(TYPEOF) \
+    F(VOID) \
+    F(NOT) \
+    F(BITNOT) \
+    \
+    /* Relational operators (< <= > >=). */ \
+    F(LT) \
+    F(LE) \
+    F(GT) \
+    F(GE) \
+    \
+    /* Shift operators (<< >> >>>). */ \
+    F(LSH) \
+    F(RSH) \
+    F(URSH) \
+    \
+    /* Assignment operators (= += -= etc.). */ \
+    /* ParseNode::isAssignment assumes all these are consecutive. */ \
+    F(ASSIGN) \
+    F(ADDASSIGN) \
+    F(SUBASSIGN) \
+    F(BITORASSIGN) \
+    F(BITXORASSIGN) \
+    F(BITANDASSIGN) \
+    F(LSHASSIGN) \
+    F(RSHASSIGN) \
+    F(URSHASSIGN) \
+    F(MULASSIGN) \
+    F(DIVASSIGN) \
+    F(MODASSIGN)
+
 /*
  * Parsing builds a tree of nodes that directs code generation.  This tree is
  * not a concrete syntax tree in all respects (for example, || and && are left
  * associative, but (A && B && C) translates into the right-associated tree
  * <A && <B && C>> so that code generation can emit a left-associative branch
  * around <B && C> when A is false).  Nodes are labeled by kind, with a
  * secondary JSOp label when needed.
  *
  * The long comment after this enum block describes the kinds in detail.
  */
 enum ParseNodeKind {
-    PNK_NOP,
-    PNK_SEMI,
-    PNK_COMMA,
-    PNK_CONDITIONAL,
-    PNK_COLON,
-    PNK_OR,
-    PNK_AND,
-    PNK_BITOR,
-    PNK_BITXOR,
-    PNK_BITAND,
-    PNK_POS,
-    PNK_NEG,
-    PNK_ADD,
-    PNK_SUB,
-    PNK_STAR,
-    PNK_DIV,
-    PNK_MOD,
-    PNK_PREINCREMENT,
-    PNK_POSTINCREMENT,
-    PNK_PREDECREMENT,
-    PNK_POSTDECREMENT,
-    PNK_DOT,
-    PNK_LB,
-    PNK_RB,
-    PNK_STATEMENTLIST,
-    PNK_XMLCURLYEXPR,
-    PNK_RC,
-    PNK_LP,
-    PNK_RP,
-    PNK_NAME,
-    PNK_INTRINSICNAME,
-    PNK_NUMBER,
-    PNK_STRING,
-    PNK_REGEXP,
-    PNK_TRUE,
-    PNK_FALSE,
-    PNK_NULL,
-    PNK_THIS,
-    PNK_FUNCTION,
-    PNK_IF,
-    PNK_ELSE,
-    PNK_SWITCH,
-    PNK_CASE,
-    PNK_DEFAULT,
-    PNK_WHILE,
-    PNK_DOWHILE,
-    PNK_FOR,
-    PNK_BREAK,
-    PNK_CONTINUE,
-    PNK_IN,
-    PNK_VAR,
-    PNK_CONST,
-    PNK_WITH,
-    PNK_RETURN,
-    PNK_NEW,
-    PNK_DELETE,
-    PNK_TRY,
-    PNK_CATCH,
-    PNK_CATCHLIST,
-    PNK_FINALLY,
-    PNK_THROW,
-    PNK_INSTANCEOF,
-    PNK_DEBUGGER,
-    PNK_DEFXMLNS,
-    PNK_XMLSTAGO,
-    PNK_XMLETAGO,
-    PNK_XMLPTAGC,
-    PNK_XMLTAGC,
-    PNK_XMLNAME,
-    PNK_XMLATTR,
-    PNK_XMLSPACE,
-    PNK_XMLTEXT,
-    PNK_XMLCOMMENT,
-    PNK_XMLCDATA,
-    PNK_XMLPI,
-    PNK_XMLUNARY,
-    PNK_AT,
-    PNK_DBLCOLON,
-    PNK_ANYNAME,
-    PNK_DBLDOT,
-    PNK_FILTER,
-    PNK_XMLELEM,
-    PNK_XMLLIST,
-    PNK_YIELD,
-    PNK_ARRAYCOMP,
-    PNK_ARRAYPUSH,
-    PNK_LEXICALSCOPE,
-    PNK_LET,
-    PNK_SEQ,
-    PNK_FORIN,
-    PNK_FORHEAD,
-    PNK_ARGSBODY,
-    PNK_SPREAD,
-
-    /*
-     * The following parse node kinds occupy contiguous ranges to enable easy
-     * range-testing.
-     */
-
-    /* Equality operators. */
-    PNK_STRICTEQ,
-    PNK_EQ,
-    PNK_STRICTNE,
-    PNK_NE,
-
-    /* Unary operators. */
-    PNK_TYPEOF,
-    PNK_VOID,
-    PNK_NOT,
-    PNK_BITNOT,
-
-    /* Relational operators (< <= > >=). */
-    PNK_LT,
-    PNK_LE,
-    PNK_GT,
-    PNK_GE,
-
-    /* Shift operators (<< >> >>>). */
-    PNK_LSH,
-    PNK_RSH,
-    PNK_URSH,
-
-    /* Assignment operators (= += -= etc.). */
-    PNK_ASSIGN,
+#define EMIT_ENUM(name) PNK_##name,
+    FOR_EACH_PARSE_NODE_KIND(EMIT_ENUM)
+#undef EMIT_ENUM
+    PNK_LIMIT, /* domain size */
     PNK_ASSIGNMENT_START = PNK_ASSIGN,
-    PNK_ADDASSIGN,
-    PNK_SUBASSIGN,
-    PNK_BITORASSIGN,
-    PNK_BITXORASSIGN,
-    PNK_BITANDASSIGN,
-    PNK_LSHASSIGN,
-    PNK_RSHASSIGN,
-    PNK_URSHASSIGN,
-    PNK_MULASSIGN,
-    PNK_DIVASSIGN,
-    PNK_MODASSIGN,
-    PNK_ASSIGNMENT_LAST = PNK_MODASSIGN,
-
-    PNK_LIMIT /* domain size */
+    PNK_ASSIGNMENT_LAST = PNK_MODASSIGN
 };
 
 /*
  * Label        Variant     Members
  * -----        -------     -------
  * <Definitions>
- * PNK_FUNCTION name        pn_funbox: ptr to js::FunctionBox holding function
+ * PNK_FUNCTIONDECL
+ *              function    pn_funbox: ptr to js::FunctionBox holding function
  *                            object containing arg and var properties.  We
  *                            create the function object at parse (not emit)
  *                            time to specialize arg and var bytecodes early.
  *                          pn_body: PNK_ARGSBODY if formal parameters,
  *                                   PNK_STATEMENTLIST node for function body
  *                                     statements,
  *                                   PNK_RETURN for expression closure, or
  *                                   PNK_SEQ for expression closure with
  *                                     destructured formal parameters
- *                                   PNK_LP see isGeneratorExpr def below
+ *                                   PNK_CALL see isGeneratorExpr def below
  *                          pn_cookie: static level and var index for function
  *                          pn_dflags: PND_* definition/use flags (see below)
  *                          pn_blockid: block id number
  * PNK_ARGSBODY list        list of formal parameters followed by
  *                            PNK_STATEMENTLIST node for function body
  *                            statements as final element
  *                          pn_count: 1 + number of formal parameters
  *                          pn_tree: PNK_ARGSBODY or PNK_STATEMENTLIST node
@@ -272,18 +274,18 @@ enum ParseNodeKind {
  *                          pn_kid2:  cond expr before second ';' or NULL
  *                          pn_kid3:  update expr after second ';' or NULL
  * PNK_THROW    unary       pn_op: JSOP_THROW, pn_kid: exception
  * PNK_TRY      ternary     pn_kid1: try block
  *                          pn_kid2: null or PNK_CATCHLIST list of
  *                          PNK_LEXICALSCOPE nodes, each with pn_expr pointing
  *                          to a PNK_CATCH node
  *                          pn_kid3: null or finally block
- * PNK_CATCH    ternary     pn_kid1: PNK_NAME, PNK_RB, or PNK_RC catch var node
- *                                   (PNK_RB or PNK_RC if destructuring)
+ * PNK_CATCH    ternary     pn_kid1: PNK_NAME, PNK_ARRAY, or PNK_OBJECT catch var node
+ *                                   (PNK_ARRAY or PNK_OBJECT if destructuring)
  *                          pn_kid2: null or the catch guard expression
  *                          pn_kid3: catch block statements
  * PNK_BREAK    name        pn_atom: label or null
  * PNK_CONTINUE name        pn_atom: label or null
  * PNK_WITH     binary      pn_left: head expr, pn_right: body
  * PNK_VAR,     list        pn_head: list of PNK_NAME or PNK_ASSIGN nodes
  * PNK_CONST                         each name node has either
  *                                     pn_used: false
@@ -362,35 +364,36 @@ enum ParseNodeKind {
  * PNK_PREDECREMENT,
  * PNK_POSTDECREMENT
  * PNK_NEW      list        pn_head: list of ctor, arg1, arg2, ... argN
  *                          pn_count: 1 + N (where N is number of args)
  *                          ctor is a MEMBER expr
  * PNK_DELETE   unary       pn_kid: MEMBER expr
  * PNK_DOT,     name        pn_expr: MEMBER expr to left of .
  * PNK_DBLDOT               pn_atom: name to right of .
- * PNK_LB       binary      pn_left: MEMBER expr to left of [
+ * PNK_ELEM     binary      pn_left: MEMBER expr to left of [
  *                          pn_right: expr between [ and ]
- * PNK_LP       list        pn_head: list of call, arg1, arg2, ... argN
+ * PNK_CALL     list        pn_head: list of call, arg1, arg2, ... argN
  *                          pn_count: 1 + N (where N is number of args)
  *                          call is a MEMBER expr naming a callable object
- * PNK_RB       list        pn_head: list of pn_count array element exprs
+ * PNK_ARRAY    list        pn_head: list of pn_count array element exprs
  *                          [,,] holes are represented by PNK_COMMA nodes
  *                          pn_xflags: PN_ENDCOMMA if extra comma at end
- * PNK_RC       list        pn_head: list of pn_count binary PNK_COLON nodes
+ * PNK_OBJECT   list        pn_head: list of pn_count binary PNK_COLON nodes
  * PNK_COLON    binary      key-value pair in object initializer or
  *                          destructuring lhs
  *                          pn_left: property id, pn_right: value
  *                          var {x} = object destructuring shorthand shares
  *                          PN_NAME node for x on left and right of PNK_COLON
- *                          node in PNK_RC's list, has PNX_DESTRUCT flag
+ *                          node in PNK_OBJECT's list, has PNX_DESTRUCT flag
+ * PNK_FUNCTIONEXPR function  The same fields as PNK_FUNCTIONDECL above.
  * PNK_NAME,    name        pn_atom: name, string, or object atom
  * PNK_STRING,              pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT, or
- *                                 JSOP_REGEXP
- * PNK_REGEXP               If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR
+ * PNK_REGEXP                      JSOP_REGEXP
+ *                          If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR
  *                          with pn_cookie telling (staticLevel, slot) (see
  *                          jsscript.h's UPVAR macros) and pn_dflags telling
  *                          const-ness and static analysis results
  * PNK_NAME     name        If pn_used, PNK_NAME uses the lexdef member instead
  *                          of the expr member it overlays
  * PNK_NUMBER   dval        pn_dval: double value of numeric literal
  * PNK_TRUE,    nullary     pn_op: JSOp bytecode
  * PNK_FALSE,
@@ -402,16 +405,17 @@ enum ParseNodeKind {
  *                          pn_op: JSOP_XMLNAME, JSOP_BINDXMLNAME, or
  *                                 JSOP_SETXMLNAME
  * PNK_DEFXMLNS name        pn_kid: namespace expr
  * PNK_FILTER   binary      pn_left: container expr, pn_right: filter expr
  * PNK_DBLDOT   binary      pn_left: container expr, pn_right: selector expr
  * PNK_ANYNAME  nullary     pn_op: JSOP_ANYNAME
  *                          pn_atom: cx->runtime->atomState.starAtom
  * PNK_AT       unary       pn_op: JSOP_TOATTRNAME; pn_kid attribute id/expr
+ * PNK_FUNCTIONNS nullary   special E4X "function::" namespace
  * PNK_DBLCOLON binary      pn_op: JSOP_QNAME
  *                          pn_left: PNK_ANYNAME or PNK_NAME node
  *                          pn_right: PNK_STRING "*" node, or expr within []
  *              name        pn_op: JSOP_QNAMECONST
  *                          pn_expr: PNK_ANYNAME or PNK_NAME left operand
  *                          pn_atom: name on right of ::
  * PNK_XMLELEM  list        XML element node
  *                          pn_head: start tag, content1, ... contentN, end tag
@@ -807,29 +811,30 @@ struct ParseNode {
     bool isArrayHole() const { return isKind(PNK_COMMA) && isArity(PN_NULLARY); }
 #endif
 
 #ifdef JS_HAS_GENERATOR_EXPRS
     /*
      * True if this node is a desugared generator expression.
      */
     bool isGeneratorExpr() const {
-        if (getKind() == PNK_LP) {
+        if (isKind(PNK_CALL)) {
             ParseNode *callee = this->pn_head;
-            if (callee->getKind() == PNK_FUNCTION && callee->pn_body->getKind() == PNK_LEXICALSCOPE)
+            JS_ASSERT(!callee->isKind(PNK_FUNCTIONDECL));
+            if (callee->getKind() == PNK_FUNCTIONEXPR && callee->pn_body->getKind() == PNK_LEXICALSCOPE)
                 return true;
         }
         return false;
     }
 
     ParseNode *generatorExpr() const {
         JS_ASSERT(isGeneratorExpr());
         ParseNode *callee = this->pn_head;
         ParseNode *body = callee->pn_body;
-        JS_ASSERT(body->getKind() == PNK_LEXICALSCOPE);
+        JS_ASSERT(body->isKind(PNK_LEXICALSCOPE));
         return body->pn_expr;
     }
 #endif
 
     /*
      * Compute a pointer to the last element in a singly-linked list. NB: list
      * must be non-empty for correct PN_LAST usage -- this is asserted!
      */
@@ -874,52 +879,65 @@ struct ParseNode {
     {}
 #endif
     ;
 
     bool getConstantValue(JSContext *cx, bool strictChecks, Value *vp);
     inline bool isConstant();
 
     /* Casting operations. */
-    inline BreakStatement &asBreakStatement();
-    inline ContinueStatement &asContinueStatement();
-#if JS_HAS_XML_SUPPORT
-    inline XMLProcessingInstruction &asXMLProcessingInstruction();
-#endif
-    inline ConditionalExpression &asConditionalExpression();
-    inline PropertyAccess &asPropertyAccess();
+    template <class NodeType>
+    inline NodeType &as() {
+        JS_ASSERT(NodeType::test(*this));
+        return *static_cast<NodeType *>(this);
+    }
+
+    template <class NodeType>
+    inline const NodeType &as() const {
+        JS_ASSERT(NodeType::test(*this));
+        return *static_cast<const NodeType *>(this);
+    }
 
 #ifdef DEBUG
-    inline void dump(int indent);
+    void dump();
+    void dump(int indent);
 #endif
 };
 
 struct NullaryNode : public ParseNode {
     static inline NullaryNode *create(ParseNodeKind kind, Parser *parser) {
-        return (NullaryNode *)ParseNode::create(kind, PN_NULLARY, parser);
+        return (NullaryNode *) ParseNode::create(kind, PN_NULLARY, parser);
+    }
+
+    static bool test(const ParseNode &node) {
+        return node.isArity(PN_NULLARY);
     }
 
 #ifdef DEBUG
-    inline void dump();
+    void dump();
 #endif
 };
 
 struct UnaryNode : public ParseNode {
     UnaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, ParseNode *kid)
       : ParseNode(kind, op, PN_UNARY, pos)
     {
         pn_kid = kid;
     }
 
     static inline UnaryNode *create(ParseNodeKind kind, Parser *parser) {
-        return (UnaryNode *)ParseNode::create(kind, PN_UNARY, parser);
+        return (UnaryNode *) ParseNode::create(kind, PN_UNARY, parser);
+    }
+
+    static bool test(const ParseNode &node) {
+        return node.isArity(PN_UNARY);
     }
 
 #ifdef DEBUG
-    inline void dump(int indent);
+    void dump(int indent);
 #endif
 };
 
 struct BinaryNode : public ParseNode {
     BinaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, ParseNode *left, ParseNode *right)
       : ParseNode(kind, op, PN_BINARY, pos)
     {
         pn_left = left;
@@ -929,77 +947,97 @@ struct BinaryNode : public ParseNode {
     BinaryNode(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right)
       : ParseNode(kind, op, PN_BINARY, TokenPos::box(left->pn_pos, right->pn_pos))
     {
         pn_left = left;
         pn_right = right;
     }
 
     static inline BinaryNode *create(ParseNodeKind kind, Parser *parser) {
-        return (BinaryNode *)ParseNode::create(kind, PN_BINARY, parser);
+        return (BinaryNode *) ParseNode::create(kind, PN_BINARY, parser);
+    }
+
+    static bool test(const ParseNode &node) {
+        return node.isArity(PN_BINARY);
     }
 
 #ifdef DEBUG
-    inline void dump(int indent);
+    void dump(int indent);
 #endif
 };
 
 struct TernaryNode : public ParseNode {
     TernaryNode(ParseNodeKind kind, JSOp op, ParseNode *kid1, ParseNode *kid2, ParseNode *kid3)
       : ParseNode(kind, op, PN_TERNARY,
                   TokenPos::make((kid1 ? kid1 : kid2 ? kid2 : kid3)->pn_pos.begin,
                                  (kid3 ? kid3 : kid2 ? kid2 : kid1)->pn_pos.end))
     {
         pn_kid1 = kid1;
         pn_kid2 = kid2;
         pn_kid3 = kid3;
     }
 
     static inline TernaryNode *create(ParseNodeKind kind, Parser *parser) {
-        return (TernaryNode *)ParseNode::create(kind, PN_TERNARY, parser);
+        return (TernaryNode *) ParseNode::create(kind, PN_TERNARY, parser);
+    }
+
+    static bool test(const ParseNode &node) {
+        return node.isArity(PN_TERNARY);
     }
 
 #ifdef DEBUG
-    inline void dump(int indent);
+    void dump(int indent);
 #endif
 };
 
 struct ListNode : public ParseNode {
     static inline ListNode *create(ParseNodeKind kind, Parser *parser) {
-        return (ListNode *)ParseNode::create(kind, PN_LIST, parser);
+        return (ListNode *) ParseNode::create(kind, PN_LIST, parser);
+    }
+
+    static bool test(const ParseNode &node) {
+        return node.isArity(PN_LIST);
     }
 
 #ifdef DEBUG
-    inline void dump(int indent);
+    void dump(int indent);
 #endif
 };
 
 struct FunctionNode : public ParseNode {
     static inline FunctionNode *create(ParseNodeKind kind, Parser *parser) {
-        return (FunctionNode *)ParseNode::create(kind, PN_FUNC, parser);
+        return (FunctionNode *) ParseNode::create(kind, PN_FUNC, parser);
+    }
+
+    static bool test(const ParseNode &node) {
+        return node.isArity(PN_FUNC);
     }
 
 #ifdef DEBUG
-    inline void dump(int indent);
+    void dump(int indent);
 #endif
 };
 
 struct NameNode : public ParseNode {
     static NameNode *create(ParseNodeKind kind, JSAtom *atom, Parser *parser, ParseContext *pc);
 
     inline void initCommon(ParseContext *pc);
 
+    static bool test(const ParseNode &node) {
+        return node.isArity(PN_NAME);
+    }
+
 #ifdef DEBUG
-    inline void dump(int indent);
+    void dump(int indent);
 #endif
 };
 
 struct LexicalScopeNode : public ParseNode {
     static inline LexicalScopeNode *create(ParseNodeKind kind, Parser *parser) {
-        return (LexicalScopeNode *)ParseNode::create(kind, PN_NAME, parser);
+        return (LexicalScopeNode *) ParseNode::create(kind, PN_NAME, parser);
     }
 };
 
 class LoopControlStatement : public ParseNode {
   protected:
     LoopControlStatement(ParseNodeKind kind, PropertyName *label,
                          const TokenPtr &begin, const TokenPtr &end)
       : ParseNode(kind, JSOP_NOP, PN_NULLARY, TokenPos::make(begin, end))
@@ -1008,50 +1046,53 @@ class LoopControlStatement : public Pars
         pn_u.loopControl.label = label;
     }
 
   public:
     /* Label associated with this break/continue statement, if any. */
     PropertyName *label() const {
         return pn_u.loopControl.label;
     }
+
+    static bool test(const ParseNode &node) {
+        bool match = node.isKind(PNK_BREAK) || node.isKind(PNK_CONTINUE);
+        JS_ASSERT_IF(match, node.isArity(PN_NULLARY));
+        JS_ASSERT_IF(match, node.isOp(JSOP_NOP));
+        return match;
+    }
 };
 
 class BreakStatement : public LoopControlStatement {
   public:
     BreakStatement(PropertyName *label, const TokenPtr &begin, const TokenPtr &end)
       : LoopControlStatement(PNK_BREAK, label, begin, end)
     { }
+
+    static bool test(const ParseNode &node) {
+        bool match = node.isKind(PNK_BREAK);
+        JS_ASSERT_IF(match, node.isArity(PN_NULLARY));
+        JS_ASSERT_IF(match, node.isOp(JSOP_NOP));
+        return match;
+    }
 };
 
-inline BreakStatement &
-ParseNode::asBreakStatement()
-{
-    JS_ASSERT(isKind(PNK_BREAK));
-    JS_ASSERT(isOp(JSOP_NOP));
-    JS_ASSERT(pn_arity == PN_NULLARY);
-    return *static_cast<BreakStatement *>(this);
-}
-
 class ContinueStatement : public LoopControlStatement {
   public:
     ContinueStatement(PropertyName *label, TokenPtr &begin, TokenPtr &end)
       : LoopControlStatement(PNK_CONTINUE, label, begin, end)
     { }
+
+    static bool test(const ParseNode &node) {
+        bool match = node.isKind(PNK_CONTINUE);
+        JS_ASSERT_IF(match, node.isArity(PN_NULLARY));
+        JS_ASSERT_IF(match, node.isOp(JSOP_NOP));
+        return match;
+    }
 };
 
-inline ContinueStatement &
-ParseNode::asContinueStatement()
-{
-    JS_ASSERT(isKind(PNK_CONTINUE));
-    JS_ASSERT(isOp(JSOP_NOP));
-    JS_ASSERT(pn_arity == PN_NULLARY);
-    return *static_cast<ContinueStatement *>(this);
-}
-
 class DebuggerStatement : public ParseNode {
   public:
     DebuggerStatement(const TokenPos &pos)
       : ParseNode(PNK_DEBUGGER, JSOP_NOP, PN_NULLARY, pos)
     { }
 };
 
 #if JS_HAS_XML_SUPPORT
@@ -1059,33 +1100,31 @@ class XMLProcessingInstruction : public 
   public:
     XMLProcessingInstruction(PropertyName *target, JSAtom *data, const TokenPos &pos)
       : ParseNode(PNK_XMLPI, JSOP_NOP, PN_NULLARY, pos)
     {
         pn_u.xmlpi.target = target;
         pn_u.xmlpi.data = data;
     }
 
+    static bool test(const ParseNode &node) {
+        bool match = node.isKind(PNK_XMLPI);
+        JS_ASSERT_IF(match, node.isArity(PN_NULLARY));
+        JS_ASSERT_IF(match, node.isOp(JSOP_NOP));
+        return match;
+    }
+
     PropertyName *target() const {
         return pn_u.xmlpi.target;
     }
 
     JSAtom *data() const {
         return pn_u.xmlpi.data;
     }
 };
-
-inline XMLProcessingInstruction &
-ParseNode::asXMLProcessingInstruction()
-{
-    JS_ASSERT(isKind(PNK_XMLPI));
-    JS_ASSERT(isOp(JSOP_NOP));
-    JS_ASSERT(pn_arity == PN_NULLARY);
-    return *static_cast<XMLProcessingInstruction *>(this);
-}
 #endif
 
 class ConditionalExpression : public ParseNode {
   public:
     ConditionalExpression(ParseNode *condition, ParseNode *thenExpr, ParseNode *elseExpr)
       : ParseNode(PNK_CONDITIONAL, JSOP_NOP, PN_TERNARY,
                   TokenPos::make(condition->pn_pos.begin, elseExpr->pn_pos.end))
     {
@@ -1103,27 +1142,25 @@ class ConditionalExpression : public Par
 
     ParseNode &thenExpression() const {
         return *pn_u.ternary.kid2;
     }
 
     ParseNode &elseExpression() const {
         return *pn_u.ternary.kid3;
     }
+
+    static bool test(const ParseNode &node) {
+        bool match = node.isKind(PNK_CONDITIONAL);
+        JS_ASSERT_IF(match, node.isArity(PN_TERNARY));
+        JS_ASSERT_IF(match, node.isOp(JSOP_NOP));
+        return match;
+    }
 };
 
-inline ConditionalExpression &
-ParseNode::asConditionalExpression()
-{
-    JS_ASSERT(isKind(PNK_CONDITIONAL));
-    JS_ASSERT(isOp(JSOP_NOP));
-    JS_ASSERT(pn_arity == PN_TERNARY);
-    return *static_cast<ConditionalExpression *>(this);
-}
-
 class ThisLiteral : public ParseNode {
   public:
     ThisLiteral(const TokenPos &pos) : ParseNode(PNK_THIS, JSOP_THIS, PN_NULLARY, pos) { }
 };
 
 class NullLiteral : public ParseNode {
   public:
     NullLiteral(const TokenPos &pos) : ParseNode(PNK_NULL, JSOP_NULL, PN_NULLARY, pos) { }
@@ -1135,17 +1172,17 @@ class BooleanLiteral : public ParseNode 
       : ParseNode(b ? PNK_TRUE : PNK_FALSE, b ? JSOP_TRUE : JSOP_FALSE, PN_NULLARY, pos)
     { }
 };
 
 class XMLDoubleColonProperty : public ParseNode {
   public:
     XMLDoubleColonProperty(ParseNode *lhs, ParseNode *rhs,
                            const TokenPtr &begin, const TokenPtr &end)
-      : ParseNode(PNK_LB, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end))
+      : ParseNode(PNK_ELEM, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end))
     {
         JS_ASSERT(rhs->isKind(PNK_DBLCOLON));
         pn_u.binary.left = lhs;
         pn_u.binary.right = rhs;
     }
 
     ParseNode &left() const {
         return *pn_u.binary.left;
@@ -1174,17 +1211,17 @@ class XMLFilterExpression : public Parse
         return *pn_u.binary.right;
     }
 };
 
 class XMLProperty : public ParseNode {
   public:
     XMLProperty(ParseNode *lhs, ParseNode *propertyId,
                 const TokenPtr &begin, const TokenPtr &end)
-      : ParseNode(PNK_LB, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end))
+      : ParseNode(PNK_ELEM, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end))
     {
         pn_u.binary.left = lhs;
         pn_u.binary.right = propertyId;
     }
 
     ParseNode &left() const {
         return *pn_u.binary.left;
     }
@@ -1201,38 +1238,36 @@ class PropertyAccess : public ParseNode 
       : ParseNode(PNK_DOT, JSOP_GETPROP, PN_NAME, TokenPos::make(begin, end))
     {
         JS_ASSERT(lhs != NULL);
         JS_ASSERT(name != NULL);
         pn_u.name.expr = lhs;
         pn_u.name.atom = name;
     }
 
+    static bool test(const ParseNode &node) {
+        bool match = node.isKind(PNK_DOT);
+        JS_ASSERT_IF(match, node.isArity(PN_NAME));
+        return match;
+    }
+
     ParseNode &expression() const {
         return *pn_u.name.expr;
     }
 
     PropertyName &name() const {
         return *pn_u.name.atom->asPropertyName();
     }
 };
 
-inline PropertyAccess &
-ParseNode::asPropertyAccess()
-{
-    JS_ASSERT(isKind(PNK_DOT));
-    JS_ASSERT(pn_arity == PN_NAME);
-    return *static_cast<PropertyAccess *>(this);
-}
-
 class PropertyByValue : public ParseNode {
   public:
     PropertyByValue(ParseNode *lhs, ParseNode *propExpr,
                     const TokenPtr &begin, const TokenPtr &end)
-      : ParseNode(PNK_LB, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end))
+      : ParseNode(PNK_ELEM, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end))
     {
         pn_u.binary.left = lhs;
         pn_u.binary.right = propExpr;
     }
 };
 
 ParseNode *
 CloneLeftHandSide(ParseNode *opn, Parser *parser);
@@ -1350,17 +1385,17 @@ struct Definition : public ParseNode
 
     enum Kind { VAR, CONST, LET, ARG, NAMED_LAMBDA, PLACEHOLDER };
 
     bool canHaveInitializer() { return int(kind()) <= int(ARG); }
 
     static const char *kindString(Kind kind);
 
     Kind kind() {
-        if (getKind() == PNK_FUNCTION) {
+        if (getKind() == PNK_FUNCTIONDECL) {
             if (isOp(JSOP_GETARG))
                 return ARG;
             return VAR;
         }
         JS_ASSERT(getKind() == PNK_NAME);
         if (isOp(JSOP_CALLEE))
             return NAMED_LAMBDA;
         if (isPlaceholder())
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -958,31 +958,33 @@ MakeDefIntoUse(Definition *dn, ParseNode
         JS_ASSERT(!pnu->isDefn());
         pnu->pn_lexdef = (Definition *) pn;
         pn->pn_dflags |= pnu->pn_dflags & PND_USE2DEF_FLAGS;
     }
     pn->pn_dflags |= dn->pn_dflags & PND_USE2DEF_FLAGS;
     pn->dn_uses = dn;
 
     /*
-     * A PNK_FUNCTION node must be a definition, so convert shadowed function
-     * statements into nops. This is valid since all body-level function
-     * statement initialization happens at the beginning of the function
-     * (thus, only the last statement's effect is visible). E.g., in
+     * A PNK_FUNCTIONDECL node is always a definition, and two definition nodes
+     * in the same scope can't define the same name, so convert shadowed
+     * function declarations into nops. This is valid since all body-level
+     * function declaration initialization happens at the beginning of the
+     * function (thus, only the last declaration's effect is visible). E.g., in
      *
      *   function outer() {
      *     function g() { return 1 }
      *     assertEq(g(), 2);
      *     function g() { return 2 }
      *     assertEq(g(), 2);
      *   }
      *
      * both asserts are valid.
      */
-    if (dn->getKind() == PNK_FUNCTION) {
+    JS_ASSERT(!dn->isKind(PNK_FUNCTIONEXPR));
+    if (dn->getKind() == PNK_FUNCTIONDECL) {
         JS_ASSERT(dn->functionIsHoisted());
         pn->dn_uses = dn->pn_link;
         parser->prepareNodeForMutation(dn);
         dn->setKind(PNK_NOP);
         dn->setArity(PN_NULLARY);
         return true;
     }
 
@@ -1499,17 +1501,18 @@ Parser::functionArguments(ParseNode **li
 }
 
 ParseNode *
 Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSyntaxKind kind)
 {
     JS_ASSERT_IF(kind == Statement, funName);
 
     /* Make a TOK_FUNCTION node. */
-    ParseNode *pn = FunctionNode::create(PNK_FUNCTION, this);
+    ParseNode *pn =
+        FunctionNode::create(kind == Statement ? PNK_FUNCTIONDECL : PNK_FUNCTIONEXPR, this);
     if (!pn)
         return NULL;
     pn->pn_body = NULL;
     pn->pn_cookie.makeFree();
     pn->pn_dflags = 0;
 
     /* Function statements add a binding to the enclosing scope. */
     bool bodyLevel = pc->atBodyLevel();
@@ -1548,17 +1551,17 @@ Parser::functionDef(HandlePropertyName f
         } else if (bodyLevel) {
             /*
              * If this function was used before it was defined, claim the
              * pre-created definition node for this function that primaryExpr
              * put in pc->lexdeps on first forward reference, and recycle pn.
              */
             if (Definition *fn = pc->lexdeps.lookupDefn(funName)) {
                 JS_ASSERT(fn->isDefn());
-                fn->setKind(PNK_FUNCTION);
+                fn->setKind(PNK_FUNCTIONDECL);
                 fn->setArity(PN_FUNC);
                 fn->pn_pos.begin = pn->pn_pos.begin;
                 fn->pn_pos.end = pn->pn_pos.end;
 
                 fn->pn_body = NULL;
                 fn->pn_cookie.makeFree();
 
                 pc->lexdeps->remove(funName);
@@ -1958,17 +1961,18 @@ Parser::statements(bool *hasFunctionStmt
         }
         ParseNode *next = statement();
         if (!next) {
             if (tokenStream.isEOF())
                 tokenStream.setUnexpectedEOF();
             return NULL;
         }
 
-        if (next->isKind(PNK_FUNCTION)) {
+        JS_ASSERT(!next->isKind(PNK_FUNCTIONEXPR));
+        if (next->isKind(PNK_FUNCTIONDECL)) {
             /*
              * PNX_FUNCDEFS notifies the emitter that the block contains body-
              * level function definitions that should be processed before the
              * rest of nodes.
              *
              * |hasFunctionStmt| is for the TOK_LC case in Statement. It
              * is relevant only for function definitions not at body-level,
              * which we call function statements.
@@ -2241,18 +2245,17 @@ static bool
 MakeSetCall(JSContext *cx, ParseNode *pn, Parser *parser, unsigned msg)
 {
     JS_ASSERT(pn->isArity(PN_LIST));
     JS_ASSERT(pn->isOp(JSOP_CALL) || pn->isOp(JSOP_EVAL) ||
               pn->isOp(JSOP_FUNCALL) || pn->isOp(JSOP_FUNAPPLY));
     if (!parser->reportStrictModeError(pn, msg))
         return false;
 
-    ParseNode *pn2 = pn->pn_head;
-    if (pn2->isKind(PNK_FUNCTION) && (pn2->pn_funbox->inGenexpLambda)) {
+    if (pn->isGeneratorExpr()) {
         parser->reportError(pn, msg);
         return false;
     }
     pn->pn_xflags |= PNX_SETCALL;
     return true;
 }
 
 static void
@@ -2355,27 +2358,27 @@ static bool
 BindDestructuringLHS(JSContext *cx, ParseNode *pn, Parser *parser)
 {
     switch (pn->getKind()) {
       case PNK_NAME:
         NoteLValue(cx, pn, parser->pc->sc);
         /* FALL THROUGH */
 
       case PNK_DOT:
-      case PNK_LB:
+      case PNK_ELEM:
         /*
          * We may be called on a name node that has already been specialized,
          * in the very weird and ECMA-262-required "for (var [x] = i in o) ..."
          * case. See bug 558633.
          */
         if (!(js_CodeSpec[pn->getOp()].format & JOF_SET))
             pn->setOp(JSOP_SETNAME);
         break;
 
-      case PNK_LP:
+      case PNK_CALL:
         if (!MakeSetCall(cx, pn, parser, JSMSG_BAD_LEFTSIDE_OF_ASS))
             return false;
         break;
 
 #if JS_HAS_XML_SUPPORT
       case PNK_XMLUNARY:
         JS_ASSERT(pn->isOp(JSOP_XMLNAME));
         pn->setOp(JSOP_BINDXMLNAME);
@@ -2439,21 +2442,21 @@ CheckDestructuring(JSContext *cx, BindDa
         parser->reportError(left, JSMSG_ARRAY_COMP_LEFTSIDE);
         return false;
     }
 
     Rooted<StaticBlockObject *> blockObj(cx);
     blockObj = data && data->binder == BindLet ? data->let.blockObj.get() : NULL;
     uint32_t blockCountBefore = blockObj ? blockObj->slotCount() : 0;
 
-    if (left->isKind(PNK_RB)) {
+    if (left->isKind(PNK_ARRAY)) {
         for (ParseNode *pn = left->pn_head; pn; pn = pn->pn_next) {
             /* Nullary comma is an elision; binary comma is an expression.*/
             if (!pn->isArrayHole()) {
-                if (pn->isKind(PNK_RB) || pn->isKind(PNK_RC)) {
+                if (pn->isKind(PNK_ARRAY) || pn->isKind(PNK_OBJECT)) {
                     ok = CheckDestructuring(cx, data, pn, parser, false);
                 } else {
                     if (data) {
                         if (!pn->isKind(PNK_NAME)) {
                             parser->reportError(pn, JSMSG_NO_VARIABLE_NAME);
                             return false;
                         }
                         ok = BindDestructuringVar(cx, data, pn, parser);
@@ -2461,22 +2464,22 @@ CheckDestructuring(JSContext *cx, BindDa
                         ok = BindDestructuringLHS(cx, pn, parser);
                     }
                 }
                 if (!ok)
                     return false;
             }
         }
     } else {
-        JS_ASSERT(left->isKind(PNK_RC));
+        JS_ASSERT(left->isKind(PNK_OBJECT));
         for (ParseNode *pair = left->pn_head; pair; pair = pair->pn_next) {
             JS_ASSERT(pair->isKind(PNK_COLON));
             ParseNode *pn = pair->pn_right;
 
-            if (pn->isKind(PNK_RB) || pn->isKind(PNK_RC)) {
+            if (pn->isKind(PNK_ARRAY) || pn->isKind(PNK_OBJECT)) {
                 ok = CheckDestructuring(cx, data, pn, parser, false);
             } else if (data) {
                 if (!pn->isKind(PNK_NAME)) {
                     parser->reportError(pn, JSMSG_NO_VARIABLE_NAME);
                     return false;
                 }
                 ok = BindDestructuringVar(cx, data, pn, parser);
             } else {
@@ -3079,38 +3082,38 @@ Parser::forStatement()
 
         /* Check that the left side of the 'in' or 'of' is valid. */
         if (forDecl
             ? (pn1->pn_count > 1 || pn1->isOp(JSOP_DEFCONST)
 #if JS_HAS_DESTRUCTURING
                || (versionNumber() == JSVERSION_1_7 &&
                    pn->isOp(JSOP_ITER) &&
                    !(pn->pn_iflags & JSITER_FOREACH) &&
-                   (pn1->pn_head->isKind(PNK_RC) ||
-                    (pn1->pn_head->isKind(PNK_RB) &&
+                   (pn1->pn_head->isKind(PNK_OBJECT) ||
+                    (pn1->pn_head->isKind(PNK_ARRAY) &&
                      pn1->pn_head->pn_count != 2) ||
                     (pn1->pn_head->isKind(PNK_ASSIGN) &&
-                     (!pn1->pn_head->pn_left->isKind(PNK_RB) ||
+                     (!pn1->pn_head->pn_left->isKind(PNK_ARRAY) ||
                       pn1->pn_head->pn_left->pn_count != 2))))
 #endif
               )
             : (!pn1->isKind(PNK_NAME) &&
                !pn1->isKind(PNK_DOT) &&
 #if JS_HAS_DESTRUCTURING
                ((versionNumber() == JSVERSION_1_7 &&
                  pn->isOp(JSOP_ITER) &&
                  !(pn->pn_iflags & JSITER_FOREACH))
-                ? (!pn1->isKind(PNK_RB) || pn1->pn_count != 2)
-                : (!pn1->isKind(PNK_RB) && !pn1->isKind(PNK_RC))) &&
+                ? (!pn1->isKind(PNK_ARRAY) || pn1->pn_count != 2)
+                : (!pn1->isKind(PNK_ARRAY) && !pn1->isKind(PNK_OBJECT))) &&
 #endif
-               !pn1->isKind(PNK_LP) &&
+               !pn1->isKind(PNK_CALL) &&
 #if JS_HAS_XML_SUPPORT
                !pn1->isKind(PNK_XMLUNARY) &&
 #endif
-               !pn1->isKind(PNK_LB)))
+               !pn1->isKind(PNK_ELEM)))
         {
             reportError(pn1, JSMSG_BAD_FOR_LEFTSIDE);
             return NULL;
         }
 
         /*
          * After the following if-else, pn2 will point to the name or
          * destructuring pattern on in's left. pn1 will point to the decl, if
@@ -3158,17 +3161,17 @@ Parser::forStatement()
                 pn1->pn_xflags &= ~PNX_FORINVAR;
                 pn1->pn_xflags |= PNX_POPVAR;
                 pnseq->initList(pn1);
                 pn1 = NULL;
 
 #if JS_HAS_DESTRUCTURING
                 if (pn2->isKind(PNK_ASSIGN)) {
                     pn2 = pn2->pn_left;
-                    JS_ASSERT(pn2->isKind(PNK_RB) || pn2->isKind(PNK_RC) ||
+                    JS_ASSERT(pn2->isKind(PNK_ARRAY) || pn2->isKind(PNK_OBJECT) ||
                               pn2->isKind(PNK_NAME));
                 }
 #endif
                 pnseq->pn_pos.begin = pn->pn_pos.begin;
                 pnseq->append(pn);
                 forParent = pnseq;
             }
         } else {
@@ -3217,18 +3220,18 @@ Parser::forStatement()
             NoteLValue(context, pn2, pc->sc);
             break;
 
 #if JS_HAS_DESTRUCTURING
           case PNK_ASSIGN:
             JS_NOT_REACHED("forStatement TOK_ASSIGN");
             break;
 
-          case PNK_RB:
-          case PNK_RC:
+          case PNK_ARRAY:
+          case PNK_OBJECT:
             if (versionNumber() == JSVERSION_1_7) {
                 /*
                  * Destructuring for-in requires [key, value] enumeration
                  * in JS1.7.
                  */
                 JS_ASSERT(pn->isOp(JSOP_ITER));
                 if (!(pn->pn_iflags & JSITER_FOREACH))
                     pn->pn_iflags |= JSITER_FOREACH | JSITER_KEYVALUE;
@@ -4071,19 +4074,19 @@ Parser::statement()
 ParseNode *
 Parser::variables(ParseNodeKind kind, StaticBlockObject *blockObj, VarContext varContext)
 {
     /*
      * The four options here are:
      * - PNK_VAR:   We're parsing var declarations.
      * - PNK_CONST: We're parsing const declarations.
      * - PNK_LET:   We are parsing a let declaration.
-     * - PNK_LP:    We are parsing the head of a let block.
+     * - PNK_CALL:  We are parsing the head of a let block.
      */
-    JS_ASSERT(kind == PNK_VAR || kind == PNK_CONST || kind == PNK_LET || kind == PNK_LP);
+    JS_ASSERT(kind == PNK_VAR || kind == PNK_CONST || kind == PNK_LET || kind == PNK_CALL);
 
     ParseNode *pn = ListNode::create(kind, this);
     if (!pn)
         return NULL;
 
     pn->setOp(blockObj ? JSOP_NOP : kind == PNK_VAR ? JSOP_DEFVAR : JSOP_DEFCONST);
     pn->makeEmpty();
 
@@ -4454,31 +4457,31 @@ Parser::setAssignmentLhsOps(ParseNode *p
         if (!CheckStrictAssignment(context, this, pn))
             return false;
         pn->setOp(pn->isOp(JSOP_GETLOCAL) ? JSOP_SETLOCAL : JSOP_SETNAME);
         NoteLValue(context, pn, pc->sc);
         break;
       case PNK_DOT:
         pn->setOp(JSOP_SETPROP);
         break;
-      case PNK_LB:
+      case PNK_ELEM:
         pn->setOp(JSOP_SETELEM);
         break;
 #if JS_HAS_DESTRUCTURING
-      case PNK_RB:
-      case PNK_RC:
+      case PNK_ARRAY:
+      case PNK_OBJECT:
         if (op != JSOP_NOP) {
             reportError(NULL, JSMSG_BAD_DESTRUCT_ASS);
             return false;
         }
         if (!CheckDestructuring(context, NULL, pn, this))
             return false;
         break;
 #endif
-      case PNK_LP:
+      case PNK_CALL:
         if (!MakeSetCall(context, pn, this, JSMSG_BAD_LEFTSIDE_OF_ASS))
             return false;
         break;
 #if JS_HAS_XML_SUPPORT
       case PNK_XMLUNARY:
         JS_ASSERT(pn->isOp(JSOP_XMLNAME));
         pn->setOp(JSOP_SETXMLNAME);
         break;
@@ -4536,23 +4539,23 @@ Parser::assignExpr()
 }
 
 static bool
 SetLvalKid(JSContext *cx, Parser *parser, ParseNode *pn, ParseNode *kid,
            const char *name)
 {
     if (!kid->isKind(PNK_NAME) &&
         !kid->isKind(PNK_DOT) &&
-        (!kid->isKind(PNK_LP) ||
+        (!kid->isKind(PNK_CALL) ||
          (!kid->isOp(JSOP_CALL) && !kid->isOp(JSOP_EVAL) &&
           !kid->isOp(JSOP_FUNCALL) && !kid->isOp(JSOP_FUNAPPLY))) &&
 #if JS_HAS_XML_SUPPORT
         !kid->isKind(PNK_XMLUNARY) &&
 #endif
-        !kid->isKind(PNK_LB))
+        !kid->isKind(PNK_ELEM))
     {
         parser->reportError(NULL, JSMSG_BAD_OPERAND, name);
         return false;
     }
     if (!CheckStrictAssignment(cx, parser, kid))
         return false;
     pn->pn_kid = kid;
     return true;
@@ -4577,27 +4580,27 @@ SetIncOpKid(JSContext *cx, Parser *parse
         break;
 
       case PNK_DOT:
         op = (tt == TOK_INC)
              ? (preorder ? JSOP_INCPROP : JSOP_PROPINC)
              : (preorder ? JSOP_DECPROP : JSOP_PROPDEC);
         break;
 
-      case PNK_LP:
+      case PNK_CALL:
         if (!MakeSetCall(cx, kid, parser, JSMSG_BAD_INCOP_OPERAND))
             return false;
         /* FALL THROUGH */
 #if JS_HAS_XML_SUPPORT
       case PNK_XMLUNARY:
         if (kid->isOp(JSOP_XMLNAME))
             kid->setOp(JSOP_SETXMLNAME);
         /* FALL THROUGH */
 #endif
-      case PNK_LB:
+      case PNK_ELEM:
         op = (tt == TOK_INC)
              ? (preorder ? JSOP_INCELEM : JSOP_ELEMINC)
              : (preorder ? JSOP_DECELEM : JSOP_ELEMDEC);
         break;
 
       default:
         JS_ASSERT(0);
         op = JSOP_NOP;
@@ -4663,17 +4666,17 @@ Parser::unaryExpr()
         /*
          * Under ECMA3, deleting any unary expression is valid -- it simply
          * returns true. Here we fold constants before checking for a call
          * expression, in order to rule out delete of a generator expression.
          */
         if (foldConstants && !FoldConstants(context, pn2, this))
             return NULL;
         switch (pn2->getKind()) {
-          case PNK_LP:
+          case PNK_CALL:
             if (!(pn2->pn_xflags & PNX_SETCALL)) {
                 /*
                  * Call MakeSetCall to check for errors, but clear PNX_SETCALL
                  * because the optimizer will eliminate the useless delete.
                  */
                 if (!MakeSetCall(context, pn2, this, JSMSG_BAD_DELETE_OPERAND))
                     return NULL;
                 pn2->pn_xflags &= ~PNX_SETCALL;
@@ -5228,17 +5231,17 @@ Parser::comprehensionTail(ParseNode *kid
 #if JS_HAS_DESTRUCTURING
           case TOK_LB:
           case TOK_LC:
             if (!CheckDestructuring(context, &data, pn3, this))
                 return NULL;
 
             if (versionNumber() == JSVERSION_1_7) {
                 /* Destructuring requires [key, value] enumeration in JS1.7. */
-                if (!pn3->isKind(PNK_RB) || pn3->pn_count != 2) {
+                if (!pn3->isKind(PNK_ARRAY) || pn3->pn_count != 2) {
                     reportError(NULL, JSMSG_BAD_FOR_LEFTSIDE);
                     return NULL;
                 }
 
                 JS_ASSERT(pn2->isOp(JSOP_ITER));
                 JS_ASSERT(pn2->pn_iflags & JSITER_ENUMERATE);
                 if (!(pn2->pn_iflags & JSITER_FOREACH))
                     pn2->pn_iflags |= JSITER_FOREACH | JSITER_KEYVALUE;
@@ -5330,17 +5333,17 @@ Parser::generatorExpr(ParseNode *kid)
         return NULL;
     pn->setOp(JSOP_YIELD);
     pn->setInParens(true);
     pn->pn_pos = kid->pn_pos;
     pn->pn_kid = kid;
     pn->pn_hidden = true;
 
     /* Make a new node for the desugared generator function. */
-    ParseNode *genfn = FunctionNode::create(PNK_FUNCTION, this);
+    ParseNode *genfn = FunctionNode::create(PNK_FUNCTIONEXPR, this);
     if (!genfn)
         return NULL;
     genfn->setOp(JSOP_LAMBDA);
     JS_ASSERT(!genfn->pn_body);
     genfn->pn_dflags = 0;
 
     {
         ParseContext *outerpc = pc;
@@ -5391,17 +5394,17 @@ Parser::generatorExpr(ParseNode *kid)
         if (!LeaveFunction(genfn, this))
             return NULL;
     }
 
     /*
      * Our result is a call expression that invokes the anonymous generator
      * function object.
      */
-    ParseNode *result = ListNode::create(PNK_LP, this);
+    ParseNode *result = ListNode::create(PNK_CALL, this);
     if (!result)
         return NULL;
     result->setOp(JSOP_CALL);
     result->pn_pos.begin = genfn->pn_pos.begin;
     result->initList(genfn);
     return result;
 }
 
@@ -5670,17 +5673,17 @@ Parser::memberExpr(bool allowCallSyntax)
 
             if (name)
                 nextMember = new_<PropertyAccess>(lhs, name, begin, end);
             else
                 nextMember = new_<PropertyByValue>(lhs, propExpr, begin, end);
             if (!nextMember)
                 return NULL;
         } else if (allowCallSyntax && tt == TOK_LP) {
-            nextMember = ListNode::create(PNK_LP, this);
+            nextMember = ListNode::create(PNK_CALL, this);
             if (!nextMember)
                 return NULL;
             nextMember->setOp(JSOP_CALL);
 
             if (lhs->isOp(JSOP_NAME)) {
                 if (lhs->pn_atom == context->runtime->atomState.evalAtom) {
                     /* Select JSOP_EVAL and flag pc as heavyweight. */
                     nextMember->setOp(JSOP_EVAL);
@@ -6366,17 +6369,17 @@ Parser::checkForFunctionNode(PropertyNam
      */
     if (const KeywordInfo *ki = FindKeyword(name->charsZ(), name->length())) {
         if (ki->tokentype != TOK_FUNCTION) {
             reportError(NULL, JSMSG_KEYWORD_NOT_NS);
             return false;
         }
 
         node->setArity(PN_NULLARY);
-        node->setKind(PNK_FUNCTION);
+        node->setKind(PNK_FUNCTIONNS);
     }
 
     return true;
 }
 
 #if JS_HAS_XML_SUPPORT
 ParseNode *
 Parser::propertyQualifiedIdentifier()
@@ -6506,33 +6509,33 @@ Parser::primaryExpr(TokenKind tt, bool a
     JSOp op;
 
     JS_CHECK_RECURSION(context, return NULL);
 
     switch (tt) {
       case TOK_FUNCTION:
 #if JS_HAS_XML_SUPPORT
         if (allowsXML() && tokenStream.matchToken(TOK_DBLCOLON, TSF_KEYWORD_IS_NAME)) {
-            pn2 = NullaryNode::create(PNK_FUNCTION, this);
+            pn2 = NullaryNode::create(PNK_FUNCTIONNS, this);
             if (!pn2)
                 return NULL;
             pn = qualifiedSuffix(pn2);
             if (!pn)
                 return NULL;
             break;
         }
 #endif
         pn = functionExpr();
         if (!pn)
             return NULL;
         break;
 
       case TOK_LB:
       {
-        pn = ListNode::create(PNK_RB, this);
+        pn = ListNode::create(PNK_ARRAY, this);
         if (!pn)
             return NULL;
         pn->setOp(JSOP_NEWINIT);
         pn->makeEmpty();
 
 #if JS_HAS_GENERATORS
         pn->pn_blockid = pc->blockidGen;
 #endif
@@ -6678,17 +6681,17 @@ Parser::primaryExpr(TokenKind tt, bool a
         AtomIndexMap seen(context);
 
         enum AssignmentType {
             GET     = 0x1,
             SET     = 0x2,
             VALUE   = 0x4 | GET | SET
         };
 
-        pn = ListNode::create(PNK_RC, this);
+        pn = ListNode::create(PNK_OBJECT, this);
         if (!pn)
             return NULL;
         pn->setOp(JSOP_NEWINIT);
         pn->makeEmpty();
 
         for (;;) {
             JSAtom *atom;
             TokenKind ltok = tokenStream.getToken(TSF_KEYWORD_IS_NAME);
--- a/js/src/gc/Heap.h
+++ b/js/src/gc/Heap.h
@@ -103,17 +103,18 @@ struct Cell
 };
 
 /*
  * Page size is 4096 by default, except for SPARC, where it is 8192.
  * Note: Do not use JS_CPU_SPARC here, this header is used outside JS.
  * Bug 692267: Move page size definition to gc/Memory.h and include it
  *             directly once jsgc.h is no longer an installed header.
  */
-#if defined(SOLARIS) && (defined(__sparc) || defined(__sparcv9))
+#if (defined(SOLARIS) || defined(__FreeBSD__)) && \
+    (defined(__sparc) || defined(__sparcv9) || defined(__ia64))
 const size_t PageShift = 13;
 #else
 const size_t PageShift = 12;
 #endif
 const size_t PageSize = size_t(1) << PageShift;
 
 const size_t ChunkShift = 20;
 const size_t ChunkSize = size_t(1) << ChunkShift;
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -111,17 +111,17 @@ MarkInternal(JSTracer *trc, T **thingp)
      * Don't mark things outside a compartment if we are in a per-compartment
      * GC.
      */
     if (!trc->callback) {
         if (thing->compartment()->isCollecting())
             PushMarkStack(static_cast<GCMarker *>(trc), thing);
     } else {
         trc->callback(trc, (void **)thingp, GetGCThingTraceKind(thing));
-        JS_SET_TRACING_LOCATION(trc, NULL);
+        JS_UNSET_TRACING_LOCATION(trc);
     }
 
     trc->debugPrinter = NULL;
     trc->debugPrintArg = NULL;
 }
 
 #define JS_ROOT_MARKING_ASSERT(trc)                                     \
     JS_ASSERT_IF(IS_GC_MARKING_TRACER(trc),                             \
@@ -307,17 +307,17 @@ MarkIdInternal(JSTracer *trc, jsid *id)
         *id = NON_INTEGER_ATOM_TO_JSID(reinterpret_cast<JSAtom *>(str));
     } else if (JS_UNLIKELY(JSID_IS_OBJECT(*id))) {
         JSObject *obj = JSID_TO_OBJECT(*id);
         JS_SET_TRACING_LOCATION(trc, (void *)id);
         MarkInternal(trc, &obj);
         *id = OBJECT_TO_JSID(obj);
     } else {
         /* Unset realLocation manually if we do not call MarkInternal. */
-        JS_SET_TRACING_LOCATION(trc, NULL);
+        JS_UNSET_TRACING_LOCATION(trc);
     }
 }
 
 void
 MarkId(JSTracer *trc, EncapsulatedId *id, const char *name)
 {
     JS_SET_TRACING_NAME(trc, name);
     MarkIdInternal(trc, id->unsafeGet());
@@ -368,17 +368,17 @@ MarkValueInternal(JSTracer *trc, Value *
         JS_SET_TRACING_LOCATION(trc, (void *)v);
         MarkKind(trc, &thing, v->gcKind());
         if (v->isString())
             v->setString((JSString *)thing);
         else
             v->setObjectOrNull((JSObject *)thing);
     } else {
         /* Unset realLocation manually if we do not call MarkInternal. */
-        JS_SET_TRACING_LOCATION(trc, NULL);
+        JS_UNSET_TRACING_LOCATION(trc);
     }
 }
 
 void
 MarkValue(JSTracer *trc, EncapsulatedValue *v, const char *name)
 {
     JS_SET_TRACING_NAME(trc, name);
     MarkValueInternal(trc, v->unsafeGet());
--- a/js/src/gc/Root.h
+++ b/js/src/gc/Root.h
@@ -239,17 +239,17 @@ typedef JSString *                  RawS
 extern mozilla::ThreadLocal<JSRuntime *> TlsRuntime;
 
 /*
  * By default, pointers should use the inheritance hierarchy to find their
  * ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that
  * Rooted<T> may be used without the class definition being available.
  */
 template <typename T>
-struct RootKind<T *> { static ThingRootKind rootKind() { return T::rootKind(); }; };
+struct RootKind<T *> { static ThingRootKind rootKind() { return T::rootKind(); } };
 
 template <typename T>
 struct RootMethods<T *>
 {
     static T *initial() { return NULL; }
     static ThingRootKind kind() { return RootKind<T *>::rootKind(); }
     static bool poisoned(T *v) { return IsPoisonedPtr(v); }
 };
--- a/js/src/jit-test/tests/basic/bug633828.js
+++ b/js/src/jit-test/tests/basic/bug633828.js
@@ -1,6 +1,6 @@
-// |jit-test| error: SyntaxError
+// |jit-test| error: SyntaxError;
 (function() {
   function a() {}
   function a() {}
 }
 for
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug641563.js
@@ -0,0 +1,3 @@
+// |jit-test| error: SyntaxError;
+Function("(x)\nfor(var b,x in")
+
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3900,20 +3900,27 @@ JS_CallTracer(JSTracer *trc, void *thing
  * in-place.
  */
 #ifdef JS_GC_ZEAL
 # define JS_SET_TRACING_LOCATION(trc, location)                               \
     JS_BEGIN_MACRO                                                            \
         if (!(trc)->realLocation || !(location))                              \
             (trc)->realLocation = (location);                                 \
     JS_END_MACRO
+# define JS_UNSET_TRACING_LOCATION(trc)                                       \
+    JS_BEGIN_MACRO                                                            \
+        (trc)->realLocation = NULL;                                           \
+    JS_END_MACRO
 #else
 # define JS_SET_TRACING_LOCATION(trc, location)                               \
     JS_BEGIN_MACRO                                                            \
     JS_END_MACRO
+# define JS_UNSET_TRACING_LOCATION(trc)                                       \
+    JS_BEGIN_MACRO                                                            \
+    JS_END_MACRO
 #endif
 
 
 /*
  * Convenience macro to describe the argument of JS_CallTracer using C string
  * and index.
  */
 # define JS_SET_TRACING_INDEX(trc, name, index)                               \
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -546,46 +546,21 @@ js_DumpString(JSString *str)
 }
 
 JS_FRIEND_API(void)
 js_DumpAtom(JSAtom *atom)
 {
     atom->dump();
 }
 
-extern void
-DumpChars(const jschar *s, size_t n)
-{
-    if (n == SIZE_MAX) {
-        n = 0;
-        while (s[n])
-            n++;
-    }
-
-    fputc('"', stderr);
-    for (size_t i = 0; i < n; i++) {
-        if (s[i] == '\n')
-            fprintf(stderr, "\\n");
-        else if (s[i] == '\t')
-            fprintf(stderr, "\\t");
-        else if (s[i] >= 32 && s[i] < 127)
-            fputc(s[i], stderr);
-        else if (s[i] <= 255)
-            fprintf(stderr, "\\x%02x", (unsigned int) s[i]);
-        else
-            fprintf(stderr, "\\u%04x", (unsigned int) s[i]);
-    }
-    fputc('"', stderr);
-}
-
 JS_FRIEND_API(void)
 js_DumpChars(const jschar *s, size_t n)
 {
     fprintf(stderr, "jschar * (%p) = ", (void *) s);
-    DumpChars(s, n);
+    JSString::dumpChars(s, n);
     fputc('\n', stderr);
 }
 
 JS_FRIEND_API(void)
 js_DumpObject(JSObject *obj)
 {
     obj->dump();
 }
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -5767,26 +5767,21 @@ GetBlockChainAtPC(JSContext *cx, JSScrip
         }
     }
 
     return blockChain;
 }
 
 class PCStack
 {
-    JSContext *cx;
     jsbytecode **stack;
     int depth_;
 
   public:
-    explicit PCStack(JSContext *cx)
-        : cx(cx),
-          stack(NULL),
-          depth_(0)
-    {}
+    PCStack() : stack(NULL), depth_(0) {}
     ~PCStack();
     bool init(JSContext *cx, JSScript *script, jsbytecode *pc);
     int depth() const { return depth_; }
     jsbytecode *operator[](int i) const;
 };
 
 PCStack::~PCStack()
 {
@@ -5876,17 +5871,17 @@ struct ExpressionDecompiler
     bool getOutput(char **out);
 };
 
 bool
 ExpressionDecompiler::decompilePC(jsbytecode *pc)
 {
     JS_ASSERT(script->code <= pc && pc < script->code + script->length);
 
-    PCStack pcstack(cx);
+    PCStack pcstack;
     if (!pcstack.init(cx, script, pc))
         return false;
 
     JSOp op = (JSOp)*pc;
 
     // None of these stack-writing ops generates novel values.
     JS_ASSERT(op != JSOP_CASE && op != JSOP_DUP && op != JSOP_DUP2);
 
@@ -6129,17 +6124,17 @@ FindStartPC(JSContext *cx, JSScript *scr
 {
     jsbytecode *current = *valuepc;
 
     if (spindex == JSDVG_IGNORE_STACK)
         return true;
 
     *valuepc = NULL;
 
-    PCStack pcstack(cx);
+    PCStack pcstack;
     if (!pcstack.init(cx, script, current))
         return false;
 
     if (spindex == JSDVG_SEARCH_STACK) {
         // We search from fp->sp to base to find the most recently calculated
         // value matching v under assumption that it is it that caused
         // exception.
         Value *stackBase = cx->regs().spForStackDepth(0);
@@ -6289,17 +6284,17 @@ DecompileExpression(JSContext *cx, JSScr
 
     ptrdiff_t len = end - begin;
     if (len <= 0)
         return FAILED_EXPRESSION_DECOMPILER;
 
     struct Guard {
         jsbytecode **pcstack;
         JSPrinter *printer;
-        Guard() : pcstack(NULL), printer(NULL) {}
+        Guard() : pcstack(), printer(NULL) {}
         ~Guard() {
             if (printer)
                 js_DestroyPrinter(printer);
             js_free(pcstack);
         }
     } g;
 
     g.pcstack = js_pod_malloc<jsbytecode*>(StackDepth(script));
--- a/js/src/jsproxy.h
+++ b/js/src/jsproxy.h
@@ -46,17 +46,17 @@ class JS_FRIEND_API(Wrapper);
  * the derived traps in terms of the fundamental ones. This allows consumers of
  * this class to define any custom behavior they want.
  */
 class JS_FRIEND_API(BaseProxyHandler) {
     void *mFamily;
     bool mHasPrototype;
   protected:
     // Subclasses may set this in their constructor.
-    void setHasPrototype(bool hasPrototype) { mHasPrototype = hasPrototype; };
+    void setHasPrototype(bool hasPrototype) { mHasPrototype = hasPrototype; }
 
   public:
     explicit BaseProxyHandler(void *family);
     virtual ~BaseProxyHandler();
 
     bool hasPrototype() {
         return mHasPrototype;
     }
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -243,22 +243,28 @@ enum ThingRootKind
 template <typename T>
 struct RootKind;
 
 /*
  * Specifically mark the ThingRootKind of externally visible types, so that
  * JSAPI users may use JSRooted... types without having the class definition
  * available.
  */
-template <> struct RootKind<JSObject *> { static ThingRootKind rootKind() { return THING_ROOT_OBJECT; }; };
-template <> struct RootKind<JSFunction *> { static ThingRootKind rootKind() { return THING_ROOT_OBJECT; }; };
-template <> struct RootKind<JSString *> { static ThingRootKind rootKind() { return THING_ROOT_STRING; }; };
-template <> struct RootKind<JSScript *> { static ThingRootKind rootKind() { return THING_ROOT_SCRIPT; }; };
-template <> struct RootKind<jsid> { static ThingRootKind rootKind() { return THING_ROOT_ID; }; };
-template <> struct RootKind<Value> { static ThingRootKind rootKind() { return THING_ROOT_VALUE; }; };
+template<typename T, ThingRootKind Kind>
+struct SpecificRootKind
+{
+    static ThingRootKind rootKind() { return Kind; }
+};
+
+template <> struct RootKind<JSObject *> : SpecificRootKind<JSObject *, THING_ROOT_OBJECT> {};
+template <> struct RootKind<JSFunction *> : SpecificRootKind<JSFunction *, THING_ROOT_OBJECT> {};
+template <> struct RootKind<JSString *> : SpecificRootKind<JSString *, THING_ROOT_STRING> {};
+template <> struct RootKind<JSScript *> : SpecificRootKind<JSScript *, THING_ROOT_SCRIPT> {};
+template <> struct RootKind<jsid> : SpecificRootKind<jsid, THING_ROOT_ID> {};
+template <> struct RootKind<Value> : SpecificRootKind<Value, THING_ROOT_VALUE> {};
 
 struct ContextFriendFields {
     JSRuntime *const    runtime;
 
     ContextFriendFields(JSRuntime *rt)
       : runtime(rt) { }
 
     static const ContextFriendFields *get(const JSContext *cx) {
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -1890,23 +1890,23 @@ ASTSerializer::sourceElement(ParseNode *
 {
     /* SpiderMonkey allows declarations even in pure statement contexts. */
     return statement(pn, dst);
 }
 
 bool
 ASTSerializer::declaration(ParseNode *pn, Value *dst)
 {
-    JS_ASSERT(pn->isKind(PNK_FUNCTION) ||
+    JS_ASSERT(pn->isKind(PNK_FUNCTIONDECL) ||
               pn->isKind(PNK_VAR) ||
               pn->isKind(PNK_LET) ||
               pn->isKind(PNK_CONST));
 
     switch (pn->getKind()) {
-      case PNK_FUNCTION:
+      case PNK_FUNCTIONDECL:
         return function(pn, AST_FUNC_DECL, dst);
 
       case PNK_VAR:
       case PNK_CONST:
         return variableDeclaration(pn, false, dst);
 
       default:
         JS_ASSERT(pn->isKind(PNK_LET));
@@ -2144,17 +2144,17 @@ ASTSerializer::forOfOrIn(ParseNode *loop
          builder.forInStatement(var, expr, stmt, isForEach, &loop->pn_pos, dst));
 }
 
 bool
 ASTSerializer::statement(ParseNode *pn, Value *dst)
 {
     JS_CHECK_RECURSION(cx, return false);
     switch (pn->getKind()) {
-      case PNK_FUNCTION:
+      case PNK_FUNCTIONDECL:
       case PNK_VAR:
       case PNK_CONST:
         return declaration(pn, dst);
 
       case PNK_LET:
         return pn->isArity(PN_BINARY)
                ? let(pn, false, dst)
                : declaration(pn, dst);
@@ -2464,17 +2464,17 @@ ASTSerializer::generatorExpression(Parse
            builder.generatorExpression(body, blocks, filter, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::expression(ParseNode *pn, Value *dst)
 {
     JS_CHECK_RECURSION(cx, return false);
     switch (pn->getKind()) {
-      case PNK_FUNCTION:
+      case PNK_FUNCTIONEXPR:
         return function(pn, AST_FUNC_EXPR, dst);
 
       case PNK_COMMA:
       {
         NodeVector exprs(cx);
         return expressions(pn, exprs) &&
                builder.sequenceExpression(exprs, &pn->pn_pos, dst);
       }
@@ -2604,17 +2604,17 @@ ASTSerializer::expression(ParseNode *pn,
         LOCAL_ASSERT(op > UNOP_ERR && op < UNOP_LIMIT);
 
         Value expr;
         return expression(pn->pn_kid, &expr) &&
                builder.unaryExpression(op, expr, &pn->pn_pos, dst);
       }
 
       case PNK_NEW:
-      case PNK_LP:
+      case PNK_CALL:
       {
 #if JS_HAS_GENERATOR_EXPRS
         if (pn->isGeneratorExpr())
             return generatorExpression(pn->generatorExpr(), dst);
 #endif
 
         ParseNode *next = pn->pn_head;
         JS_ASSERT(pn->pn_pos.encloses(next->pn_pos));
@@ -2647,28 +2647,28 @@ ASTSerializer::expression(ParseNode *pn,
         JS_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos));
 
         Value expr, id;
         return expression(pn->pn_expr, &expr) &&
                identifier(pn->pn_atom, NULL, &id) &&
                builder.memberExpression(false, expr, id, &pn->pn_pos, dst);
       }
 
-      case PNK_LB:
+      case PNK_ELEM:
       {
         JS_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
         JS_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
 
         Value left, right;
         return expression(pn->pn_left, &left) &&
                expression(pn->pn_right, &right) &&
                builder.memberExpression(true, left, right, &pn->pn_pos, dst);
       }
 
-      case PNK_RB:
+      case PNK_ARRAY:
       {
         NodeVector elts(cx);
         if (!elts.reserve(pn->pn_count))
             return false;
 
         for (ParseNode *next = pn->pn_head; next; next = next->pn_next) {
             JS_ASSERT(pn->pn_pos.encloses(next->pn_pos));
 
@@ -2687,17 +2687,17 @@ ASTSerializer::expression(ParseNode *pn,
 
       case PNK_SPREAD:
       {
           Value expr;
           return expression(pn->pn_kid, &expr) &&
                  builder.spreadExpression(expr, &pn->pn_pos, dst);
       }
 
-      case PNK_RC:
+      case PNK_OBJECT:
       {
         /* The parser notes any uninitialized properties by setting the PNX_DESTRUCT flag. */
         if (pn->pn_xflags & PNX_DESTRUCT) {
             parser->reportError(pn, JSMSG_BAD_OBJECT_INIT);
             return false;
         }
         NodeVector elts(cx);
         if (!elts.reserve(pn->pn_count))
@@ -2782,17 +2782,17 @@ ASTSerializer::expression(ParseNode *pn,
             JS_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos));
 
             computed = false;
             pnleft = pn->pn_expr;
             if (!identifier(pn->pn_atom, NULL, &right))
                 return false;
         }
 
-        if (pnleft->isKind(PNK_FUNCTION))
+        if (pnleft->isKind(PNK_FUNCTIONNS))
             return builder.xmlFunctionQualifiedIdentifier(right, computed, &pn->pn_pos, dst);
 
         Value left;
         return expression(pnleft, &left) &&
                builder.xmlQualifiedIdentifier(left, right, computed, &pn->pn_pos, dst);
       }
 
       case PNK_AT:
@@ -2905,17 +2905,17 @@ ASTSerializer::xml(ParseNode *pn, Value 
 
       case PNK_XMLCDATA:
         return builder.xmlCdata(atomContents(pn->pn_atom), &pn->pn_pos, dst);
 
       case PNK_XMLCOMMENT:
         return builder.xmlComment(atomContents(pn->pn_atom), &pn->pn_pos, dst);
 
       case PNK_XMLPI: {
-        XMLProcessingInstruction &pi = pn->asXMLProcessingInstruction();
+        XMLProcessingInstruction &pi = pn->as<XMLProcessingInstruction>();
         return builder.xmlPI(atomContents(pi.target()),
                              atomContents(pi.data()),
                              &pi.pn_pos,
                              dst);
       }
 #endif
 
       default:
@@ -3008,17 +3008,17 @@ ASTSerializer::literal(ParseNode *pn, Va
     }
 
     return builder.literal(val, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::arrayPattern(ParseNode *pn, VarDeclKind *pkind, Value *dst)
 {
-    JS_ASSERT(pn->isKind(PNK_RB));
+    JS_ASSERT(pn->isKind(PNK_ARRAY));
 
     NodeVector elts(cx);
     if (!elts.reserve(pn->pn_count))
         return false;
 
     for (ParseNode *next = pn->pn_head; next; next = next->pn_next) {
         /* Comma expressions can't occur inside patterns, so no need to test pn_count. */
         JS_ASSERT_IF(next->isKind(PNK_COMMA), next->pn_count == 0);
@@ -3034,17 +3034,17 @@ ASTSerializer::arrayPattern(ParseNode *p
     }
 
     return builder.arrayPattern(elts, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::objectPattern(ParseNode *pn, VarDeclKind *pkind, Value *dst)
 {
-    JS_ASSERT(pn->isKind(PNK_RC));
+    JS_ASSERT(pn->isKind(PNK_OBJECT));
 
     NodeVector elts(cx);
     if (!elts.reserve(pn->pn_count))
         return false;
 
     for (ParseNode *next = pn->pn_head; next; next = next->pn_next) {
         LOCAL_ASSERT(next->isOp(JSOP_INITPROP));
 
@@ -3061,20 +3061,20 @@ ASTSerializer::objectPattern(ParseNode *
     return builder.objectPattern(elts, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::pattern(ParseNode *pn, VarDeclKind *pkind, Value *dst)
 {
     JS_CHECK_RECURSION(cx, return false);
     switch (pn->getKind()) {
-      case PNK_RC:
+      case PNK_OBJECT:
         return objectPattern(pn, pkind, dst);
 
-      case PNK_RB:
+      case PNK_ARRAY:
         return arrayPattern(pn, pkind, dst);
 
       case PNK_NAME:
         if (pkind && (pn->pn_dflags & PND_CONST))
             *pkind = VARDECL_CONST;
         /* FALL THROUGH */
 
       default:
--- a/js/src/jsscope.h
+++ b/js/src/jsscope.h
@@ -1130,13 +1130,15 @@ MarkNonNativePropertyFound(HandleObject 
 #pragma warning(pop)
 #pragma warning(pop)
 #endif
 
 namespace JS {
     template<> class AnchorPermitted<js::Shape *> { };
     template<> class AnchorPermitted<const js::Shape *> { };
 
-    template<> struct RootKind<js::Shape *> { static ThingRootKind rootKind() { return THING_ROOT_SHAPE; }; };
-    template<> struct RootKind<js::BaseShape *> { static ThingRootKind rootKind() { return THING_ROOT_BASE_SHAPE; }; };
+    template<>
+    struct RootKind<js::Shape *> : SpecificRootKind<js::Shape *, THING_ROOT_SHAPE> {};
+    template<>
+    struct RootKind<js::BaseShape *> : SpecificRootKind<js::BaseShape *, THING_ROOT_BASE_SHAPE> {};
 }
 
 #endif /* jsscope_h___ */
--- a/js/src/jsversion.h
+++ b/js/src/jsversion.h
@@ -1,14 +1,17 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  *
  * 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 jsversion_h___
+#define jsversion_h___
+
 /*
  * JS configuration macros.
  */
 #ifndef JS_VERSION
 #define JS_VERSION 185
 #endif
 
 /*
@@ -161,8 +164,10 @@
 #define USE_NEW_OBJECT_REPRESENTATION 0
 
 #if USE_NEW_OBJECT_REPRESENTATION
 #  define NEW_OBJECT_REPRESENTATION_ONLY() ((void)0)
 #else
 #  define NEW_OBJECT_REPRESENTATION_ONLY() \
      MOZ_NOT_REACHED("don't call this!  to be used in the new object representation")
 #endif
+
+#endif /* jsversion_h___ */
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -1573,17 +1573,17 @@ ParseNodeToXML(Parser *parser, ParseNode
       case PNK_XMLPI:
         str = pn->pn_atom;
         qn = NULL;
         if (pn->isKind(PNK_XMLCOMMENT)) {
             if (flags & XSF_IGNORE_COMMENTS)
                 goto skip_child;
             xml_class = JSXML_CLASS_COMMENT;
         } else if (pn->isKind(PNK_XMLPI)) {
-            XMLProcessingInstruction &pi = pn->asXMLProcessingInstruction();
+            XMLProcessingInstruction &pi = pn->as<XMLProcessingInstruction>();
             if (IS_XML(str)) {
                 Value v = StringValue(str);
                 JSAutoByteString bytes;
                 if (js_ValueToPrintable(cx, v, &bytes))
                     parser->reportError(&pi, JSMSG_RESERVED_ID, bytes.ptr());
                 goto fail;
             }
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3237,16 +3237,17 @@ Parse(JSContext *cx, unsigned argc, jsva
     if (!parser.init())
         return false;
 
     ParseNode *pn = parser.parse(NULL);
     if (!pn)
         return false;
 #ifdef DEBUG
     DumpParseTree(pn);
+    fputc('\n', stderr);
 #endif
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return true;
 }
 
 struct FreeOnReturn {
     JSContext *cx;
     const char *ptr;
--- a/js/src/vm/String.cpp
+++ b/js/src/vm/String.cpp
@@ -69,25 +69,51 @@ JSString::sizeOfExcludingThis(JSMallocSi
     // JSAtom, JSFixedString, JSUndependedString: measure the space for the
     // chars.  For JSUndependedString, there is no need to count the base
     // string, for the same reason as JSDependentString above.
     JSFixedString &fixed = asFixed();
     return mallocSizeOf(fixed.chars());
 }
 
 #ifdef DEBUG
+
+void
+JSString::dumpChars(const jschar *s, size_t n)
+{
+    if (n == SIZE_MAX) {
+        n = 0;
+        while (s[n])
+            n++;
+    }
+
+    fputc('"', stderr);
+    for (size_t i = 0; i < n; i++) {
+        if (s[i] == '\n')
+            fprintf(stderr, "\\n");
+        else if (s[i] == '\t')
+            fprintf(stderr, "\\t");
+        else if (s[i] >= 32 && s[i] < 127)
+            fputc(s[i], stderr);
+        else if (s[i] <= 255)
+            fprintf(stderr, "\\x%02x", (unsigned int) s[i]);
+        else
+            fprintf(stderr, "\\u%04x", (unsigned int) s[i]);
+    }
+    fputc('"', stderr);
+}
+
 void
 JSString::dump()
 {
     if (const jschar *chars = getChars(NULL)) {
         fprintf(stderr, "JSString* (%p) = jschar * (%p) = ",
                 (void *) this, (void *) chars);
 
         extern void DumpChars(const jschar *s, size_t n);
-        DumpChars(chars, length());
+        dumpChars(chars, length());
     } else {
         fprintf(stderr, "(oom in JSString::dump)");
     }
     fputc('\n', stderr);
 }
 
 bool
 JSString::equals(const char *s)
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -405,16 +405,17 @@ class JSString : public js::gc::Cell
     static inline bool needWriteBarrierPre(JSCompartment *comp);
     static inline void readBarrier(JSString *str);
 
     static inline js::ThingRootKind rootKind() { return js::THING_ROOT_STRING; }
 
 #ifdef DEBUG
     bool isShort() const;
     void dump();
+    static void dumpChars(const jschar *s, size_t len);
     bool equals(const char *s);
 #endif
 
   private:
     JSString() MOZ_DELETE;
     JSString(const JSString &other) MOZ_DELETE;
     void operator=(const JSString &other) MOZ_DELETE;
 };
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -3851,17 +3851,17 @@ class NS_STACK_CLASS AutoScriptEvaluate
 {
 public:
     /**
      * Saves the JSContext as well as initializing our state
      * @param cx The JSContext, this can be null, we don't do anything then
      */
     AutoScriptEvaluate(JSContext * cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
          : mJSContext(cx), mState(0), mErrorReporterSet(false),
-           mEvaluated(false), mContextHasThread(0) {
+           mEvaluated(false) {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
     /**
      * Does the pre script evaluation and sets the error reporter if given
      * This function should only be called once, and will assert if called
      * more than once
      * @param errorReporter the error reporter callback function to set
@@ -3873,17 +3873,16 @@ public:
      * Does the post script evaluation and resets the error reporter
      */
     ~AutoScriptEvaluate();
 private:
     JSContext* mJSContext;
     JSExceptionState* mState;
     bool mErrorReporterSet;
     bool mEvaluated;
-    intptr_t mContextHasThread;
     mozilla::Maybe<JSAutoCompartment> mAutoCompartment;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 
     // No copying or assignment allowed
     AutoScriptEvaluate(const AutoScriptEvaluate &) MOZ_DELETE;
     AutoScriptEvaluate & operator =(const AutoScriptEvaluate &) MOZ_DELETE;
 };
 
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -5506,17 +5506,17 @@ nsCSSFrameConstructor::ConstructFramesFr
     // container's frame construction item is marked with
     // mIsGeneratedContent, and we might not have an aParentFrame.)
     // We don't do it for content that may have XBL anonymous siblings,
     // because they make it difficult to correctly create the frame
     // due to dynamic changes.
     // We don't do it for SVG text, since we might need to position and
     // measure the white space glyphs due to x/y/dx/dy attributes.
     if (AtLineBoundary(aIter) &&
-        !styleContext->GetStyleText()->NewlineIsSignificant() &&
+        !styleContext->GetStyleText()->WhiteSpaceOrNewlineIsSignificant() &&
         aIter.List()->ParentHasNoXBLChildren() &&
         !(aState.mAdditionalStateBits & NS_FRAME_GENERATED_CONTENT) &&
         (item.mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT) &&
         !(item.mFCData->mBits & FCDATA_IS_SVG_TEXT) &&
         item.IsWhitespace(aState))
       return NS_OK;
 
     return ConstructTextFrame(item.mFCData, aState, item.mContent,
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -1020,17 +1020,17 @@ nsCSSRendering::FindBackgroundStyleFrame
   dom::Element* bodyContent = document->GetBodyElement();
   // We need to null check the body node (bug 118829) since
   // there are cases, thanks to the fix for bug 5569, where we
   // will reflow a document with no body.  In particular, if a
   // SCRIPT element in the head blocks the parser and then has a
   // SCRIPT that does "document.location.href = 'foo'", then
   // nsParser::Terminate will call |DidBuildModel| methods
   // through to the content sink, which will call |StartLayout|
-  // and thus |InitialReflow| on the pres shell.  See bug 119351
+  // and thus |Initialize| on the pres shell.  See bug 119351
   // for the ugly details.
   if (!bodyContent) {
     return aForFrame;
   }
 
   nsIFrame *bodyFrame = bodyContent->GetPrimaryFrame();
   if (!bodyFrame) {
     return aForFrame;
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -699,17 +699,17 @@ DocumentViewerImpl::InitPresentationStuf
     delete styleSet;
     return rv;
   }
 
   // We're done creating the style set
   styleSet->EndUpdate();
 
   if (aDoInitialReflow) {
-    // Since InitialReflow() will create frames for *all* items
+    // Since Initialize() will create frames for *all* items
     // that are currently in the document tree, we need to flush
     // any pending notifications to prevent the content sink from
     // duplicating layout frames for content it has added to the tree
     // but hasn't notified the document about. (Bug 154018)
     //
     // Note that we are flushing before we add mPresShell as an observer
     // to avoid bogus notifications.
 
@@ -725,20 +725,20 @@ DocumentViewerImpl::InitPresentationStuf
   mViewManager->SetWindowDimensions(width, height);
   mPresContext->SetTextZoom(mTextZoom);
   mPresContext->SetFullZoom(mPageZoom);
   mPresContext->SetMinFontSize(mMinFontSize);
 
   if (aDoInitialReflow) {
     nsCOMPtr<nsIPresShell> shellGrip = mPresShell;
     // Initial reflow
-    mPresShell->InitialReflow(width, height);
+    mPresShell->Initialize(width, height);
   } else {
     // Store the visible area so it's available for other callers of
-    // InitialReflow, like nsContentSink::StartLayout.
+    // Initialize, like nsContentSink::StartLayout.
     mPresContext->SetVisibleArea(nsRect(0, 0, width, height));
   }
 
   // now register ourselves as a selection listener, so that we get
   // called when the selection changes in the window
   if (!mSelectionListener) {
     nsDocViewerSelectionListener *selectionListener =
       new nsDocViewerSelectionListener();
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -349,32 +349,32 @@ public:
   // Make shell be a document observer.  If called after Destroy() has
   // been called on the shell, this will be ignored.
   virtual NS_HIDDEN_(void) BeginObservingDocument() = 0;
 
   // Make shell stop being a document observer
   virtual NS_HIDDEN_(void) EndObservingDocument() = 0;
 
   /**
-   * Return whether InitialReflow() was previously called.
+   * Return whether Initialize() was previously called.
    */
-  bool DidInitialReflow() const { return mDidInitialReflow; }
+  bool DidInitialize() const { return mDidInitialize; }
 
   /**
-   * Perform the initial reflow. Constructs the frame for the root content
-   * object and then reflows the frame model into the specified width and
-   * height.
+   * Perform initialization. Constructs the frame for the root content
+   * object and then enqueues a reflow of the frame model into the
+   * specified width and height.
    *
    * The coordinates for aWidth and aHeight must be in standard nscoords.
    *
    * Callers of this method must hold a reference to this shell that
    * is guaranteed to survive through arbitrary script execution.
-   * Calling InitialReflow can execute arbitrary script.
+   * Calling Initialize can execute arbitrary script.
    */
-  virtual NS_HIDDEN_(nsresult) InitialReflow(nscoord aWidth, nscoord aHeight) = 0;
+  virtual NS_HIDDEN_(nsresult) Initialize(nscoord aWidth, nscoord aHeight) = 0;
 
   /**
    * Reflow the frame model into a new width and height.  The
    * coordinates for aWidth and aHeight must be in standard nscoord's.
    */
   virtual NS_HIDDEN_(nsresult) ResizeReflow(nscoord aWidth, nscoord aHeight) = 0;
   /**
    * Reflow, and also change presshell state so as to only permit
@@ -1369,17 +1369,17 @@ protected:
   // Flags controlling how our document is rendered.  These persist
   // between paints and so are tied with retained layer pixels.
   // PresShell flushes retained layers when the rendering state
   // changes in a way that prevents us from being able to (usefully)
   // re-use old pixels.
   RenderFlags               mRenderFlags;
 
   bool                      mStylesHaveChanged : 1;
-  bool                      mDidInitialReflow : 1;
+  bool                      mDidInitialize : 1;
   bool                      mIsDestroying : 1;
   bool                      mIsReflowing : 1;
 
   // For all documents we initially lock down painting.
   bool                      mPaintingSuppressed : 1;
 
   // Whether or not form controls should use nsITheme in this shell.
   bool                      mIsThemeSupportDisabled : 1;
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -1612,43 +1612,43 @@ PresShell::EndObservingDocument()
   }
 }
 
 #ifdef DEBUG_kipp
 char* nsPresShell_ReflowStackPointerTop;
 #endif
 
 nsresult
-PresShell::InitialReflow(nscoord aWidth, nscoord aHeight)
+PresShell::Initialize(nscoord aWidth, nscoord aHeight)
 {
   if (mIsDestroying) {
     return NS_OK;
   }
 
   if (!mDocument) {
     // Nothing to do
     return NS_OK;
   }
 
   NS_TIME_FUNCTION_WITH_DOCURL;
   mozilla::TimeStamp timerStart = mozilla::TimeStamp::Now();
 
-  NS_ASSERTION(!mDidInitialReflow, "Why are we being called?");
+  NS_ASSERTION(!mDidInitialize, "Why are we being called?");
 
   nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
-  mDidInitialReflow = true;
+  mDidInitialize = true;
 
 #ifdef DEBUG
   if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) {
     if (mDocument) {
       nsIURI *uri = mDocument->GetDocumentURI();
       if (uri) {
         nsAutoCString url;
         uri->GetSpec(url);
-        printf("*** PresShell::InitialReflow (this=%p, url='%s')\n", (void*)this, url.get());
+        printf("*** PresShell::Initialize (this=%p, url='%s')\n", (void*)this, url.get());
       }
     }
   }
 #endif
 
   if (mCaret)
     mCaret->EraseCaret();
 
@@ -2490,17 +2490,17 @@ PresShell::FrameNeedsReflow(nsIFrame *aF
   NS_PRECONDITION(aIntrinsicDirty != eStyleChange ||
                   aBitToAdd == NS_FRAME_IS_DIRTY,
                   "bits don't correspond to style change reason");
 
   NS_ASSERTION(!mIsReflowing, "can't mark frame dirty during reflow");
 
   // If we've not yet done the initial reflow, then don't bother
   // enqueuing a reflow command yet.
-  if (! mDidInitialReflow)
+  if (! mDidInitialize)
     return;
 
   // If we're already destroying, don't bother with this either.
   if (mIsDestroying)
     return;
 
 #ifdef DEBUG
   //printf("gShellCounter: %d\n", gShellCounter++);
@@ -2701,17 +2701,17 @@ PresShell::CancelAllPendingReflows()
 }
 
 nsresult
 PresShell::RecreateFramesFor(nsIContent* aContent)
 {
   NS_TIME_FUNCTION_MIN(1.0);
 
   NS_ENSURE_TRUE(mPresContext, NS_ERROR_FAILURE);
-  if (!mDidInitialReflow) {
+  if (!mDidInitialize) {
     // Nothing to do here.  In fact, if we proceed and aContent is the
     // root we will crash.
     return NS_OK;
   }
 
   // Don't call RecreateFramesForContent since that is not exported and we want
   // to keep the number of entrypoints down.
 
@@ -2962,17 +2962,17 @@ PresShell::GoToAnchor(const nsAString& a
 }
 
 nsresult
 PresShell::ScrollToAnchor()
 {
   if (!mLastAnchorScrolledTo)
     return NS_OK;
 
-  NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now");
+  NS_ASSERTION(mDidInitialize, "should have done initial reflow by now");
 
   nsIScrollableFrame* rootScroll = GetRootScrollFrameAsScrollable();
   if (!rootScroll ||
       mLastAnchorScrollPositionY != rootScroll->GetScrollPosition().y)
     return NS_OK;
 
   nsresult rv = ScrollContentIntoView(mLastAnchorScrolledTo,
                                       ScrollAxis(SCROLL_TOP, SCROLL_ALWAYS),
@@ -3221,17 +3221,17 @@ PresShell::ScrollContentIntoView(nsICont
                                  nsIPresShell::ScrollAxis aVertical,
                                  nsIPresShell::ScrollAxis aHorizontal,
                                  uint32_t                 aFlags)
 {
   NS_ENSURE_TRUE(aContent, NS_ERROR_NULL_POINTER);
   nsCOMPtr<nsIDocument> currentDoc = aContent->GetCurrentDoc();
   NS_ENSURE_STATE(currentDoc);
 
-  NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now");
+  NS_ASSERTION(mDidInitialize, "should have done initial reflow by now");
 
   if (mContentToScrollTo) {
     mContentToScrollTo->DeleteProperty(nsGkAtoms::scrolling);
   }
   mContentToScrollTo = aContent;
   ScrollIntoViewData* data = new ScrollIntoViewData();
   data->mContentScrollVAxis = aVertical;
   data->mContentScrollHAxis = aHorizontal;
@@ -3257,17 +3257,17 @@ PresShell::ScrollContentIntoView(nsICont
     DoScrollContentIntoView();
   }
   return NS_OK;
 }
 
 void
 PresShell::DoScrollContentIntoView()
 {
-  NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now");
+  NS_ASSERTION(mDidInitialize, "should have done initial reflow by now");
 
   nsIFrame* frame = mContentToScrollTo->GetPrimaryFrame();
   if (!frame) {
     mContentToScrollTo->DeleteProperty(nsGkAtoms::scrolling);
     mContentToScrollTo = nullptr;
     return;
   }
 
@@ -3962,31 +3962,31 @@ PresShell::CharacterDataChanged(nsIDocum
 void
 PresShell::ContentStateChanged(nsIDocument* aDocument,
                                nsIContent* aContent,
                                nsEventStates aStateMask)
 {
   NS_PRECONDITION(!mIsDocumentGone, "Unexpected ContentStateChanged");
   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
 
-  if (mDidInitialReflow) {
+  if (mDidInitialize) {
     nsAutoCauseReflowNotifier crNotifier(this);
     mFrameConstructor->ContentStateChanged(aContent, aStateMask);
     VERIFY_STYLE_TREE;
   }
 }
 
 void
 PresShell::DocumentStatesChanged(nsIDocument* aDocument,
                                  nsEventStates aStateMask)
 {
   NS_PRECONDITION(!mIsDocumentGone, "Unexpected DocumentStatesChanged");
   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
 
-  if (mDidInitialReflow &&
+  if (mDidInitialize &&
       mStyleSet->HasDocumentStateDependentStyle(mPresContext,
                                                 mDocument->GetRootElement(),
                                                 aStateMask)) {
     mFrameConstructor->PostRestyleEvent(mDocument->GetRootElement(),
                                         eRestyle_Subtree, NS_STYLE_HINT_NONE);
     VERIFY_STYLE_TREE;
   }
 
@@ -4006,17 +4006,17 @@ PresShell::AttributeWillChange(nsIDocume
                                int32_t      aModType)
 {
   NS_PRECONDITION(!mIsDocumentGone, "Unexpected AttributeWillChange");
   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
 
   // XXXwaterson it might be more elegant to wait until after the
   // initial reflow to begin observing the document. That would
   // squelch any other inappropriate notifications as well.
-  if (mDidInitialReflow) {
+  if (mDidInitialize) {
     nsAutoCauseReflowNotifier crNotifier(this);
     mFrameConstructor->AttributeWillChange(aElement, aNameSpaceID,
                                            aAttribute, aModType);
     VERIFY_STYLE_TREE;
   }
 }
 
 void
@@ -4027,17 +4027,17 @@ PresShell::AttributeChanged(nsIDocument*
                             int32_t      aModType)
 {
   NS_PRECONDITION(!mIsDocumentGone, "Unexpected AttributeChanged");
   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
 
   // XXXwaterson it might be more elegant to wait until after the
   // initial reflow to begin observing the document. That would
   // squelch any other inappropriate notifications as well.
-  if (mDidInitialReflow) {
+  if (mDidInitialize) {
     nsAutoCauseReflowNotifier crNotifier(this);
     mFrameConstructor->AttributeChanged(aElement, aNameSpaceID,
                                         aAttribute, aModType);
     VERIFY_STYLE_TREE;
   }
 }
 
 void
@@ -4045,17 +4045,17 @@ PresShell::ContentAppended(nsIDocument *
                            nsIContent* aContainer,
                            nsIContent* aFirstNewContent,
                            int32_t     aNewIndexInContainer)
 {
   NS_PRECONDITION(!mIsDocumentGone, "Unexpected ContentAppended");
   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
   NS_PRECONDITION(aContainer, "must have container");
   
-  if (!mDidInitialReflow) {
+  if (!mDidInitialize) {
     return;
   }
   
   nsAutoCauseReflowNotifier crNotifier(this);
 
   // Call this here so it only happens for real content mutations and
   // not cases when the frame constructor calls its own methods to force
   // frame reconstruction.
@@ -4069,17 +4069,17 @@ void
 PresShell::ContentInserted(nsIDocument* aDocument,
                            nsIContent*  aContainer,
                            nsIContent*  aChild,
                            int32_t      aIndexInContainer)
 {
   NS_PRECONDITION(!mIsDocumentGone, "Unexpected ContentInserted");
   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
 
-  if (!mDidInitialReflow) {
+  if (!mDidInitialize) {
     return;
   }
   
   nsAutoCauseReflowNotifier crNotifier(this);
 
   // Call this here so it only happens for real content mutations and
   // not cases when the frame constructor calls its own methods to force
   // frame reconstruction.
@@ -4132,19 +4132,19 @@ PresShell::ContentRemoved(nsIDocument *a
                                     &didReconstruct);
 
   VERIFY_STYLE_TREE;
 }
 
 nsresult
 PresShell::ReconstructFrames(void)
 {
-  NS_PRECONDITION(!mFrameConstructor->GetRootFrame() || mDidInitialReflow,
+  NS_PRECONDITION(!mFrameConstructor->GetRootFrame() || mDidInitialize,
                   "Must not have root frame before initial reflow");
-  if (!mDidInitialReflow) {
+  if (!mDidInitialize) {
     // Nothing to do here
     return NS_OK;
   }
 
   nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
 
   // Have to make sure that the content notifications are flushed before we
   // start messing with the frame model; otherwise we can get content doubling.
@@ -4170,17 +4170,17 @@ nsIPresShell::ReconstructStyleDataIntern
   }
 
   if (mPresContext) {
     mPresContext->RebuildUserFontSet();
     mPresContext->AnimationManager()->KeyframesListIsDirty();
   }
 
   Element* root = mDocument->GetRootElement();
-  if (!mDidInitialReflow) {
+  if (!mDidInitialize) {
     // Nothing to do here, since we have no frames yet
     return;
   }
 
   if (!root) {
     // No content to restyle
     return;
   }
@@ -8199,17 +8199,17 @@ PresShell::VerifyIncrementalReflow()
   rv = mDocument->CreateShell(cx, vm, newSet, getter_AddRefs(sh));
   NS_ENSURE_SUCCESS(rv, false);
   newSet.forget();
   // Note that after we create the shell, we must make sure to destroy it
   sh->SetVerifyReflowEnable(false); // turn off verify reflow while we're reflowing the test frame tree
   vm->SetPresShell(sh);
   {
     nsAutoCauseReflowNotifier crNotifier(this);
-    sh->InitialReflow(r.width, r.height);
+    sh->Initialize(r.width, r.height);
   }
   mDocument->BindingManager()->ProcessAttachedQueue();
   sh->FlushPendingNotifications(Flush_Layout);
   sh->SetVerifyReflowEnable(true);  // turn on verify reflow again now that we're done reflowing the test frame tree
   // Force the non-primary presshell to unsuppress; it doesn't want to normally
   // because it thinks it's hidden
   ((PresShell*)sh.get())->mPaintingSuppressed = false;
   if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -83,17 +83,17 @@ public:
   NS_IMETHOD SetDisplaySelection(int16_t aToggle);
   NS_IMETHOD GetDisplaySelection(int16_t *aToggle);
   NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion,
                                      int16_t aFlags);
   NS_IMETHOD RepaintSelection(SelectionType aType);
 
   virtual NS_HIDDEN_(void) BeginObservingDocument();
   virtual NS_HIDDEN_(void) EndObservingDocument();
-  virtual NS_HIDDEN_(nsresult) InitialReflow(nscoord aWidth, nscoord aHeight);
+  virtual NS_HIDDEN_(nsresult) Initialize(nscoord aWidth, nscoord aHeight);
   virtual NS_HIDDEN_(nsresult) ResizeReflow(nscoord aWidth, nscoord aHeight);
   virtual NS_HIDDEN_(nsresult) ResizeReflowOverride(nscoord aWidth, nscoord aHeight);
   virtual NS_HIDDEN_(void) StyleChangeReflow();
   virtual NS_HIDDEN_(nsIPageSequenceFrame*) GetPageSequenceFrame() const;
   virtual NS_HIDDEN_(nsIFrame*) GetRealPrimaryFrameFor(nsIContent* aContent) const;
 
   virtual NS_HIDDEN_(nsIFrame*) GetPlaceholderFrameFor(nsIFrame* aFrame) const;
   virtual NS_HIDDEN_(void) FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty,
--- a/layout/base/nsStyleConsts.h
+++ b/layout/base/nsStyleConsts.h
@@ -708,21 +708,22 @@ static inline mozilla::css::Side operato
 #define NS_STYLE_VISIBILITY_HIDDEN              0
 #define NS_STYLE_VISIBILITY_VISIBLE             1
 #define NS_STYLE_VISIBILITY_COLLAPSE            2
 
 // See nsStyleText
 #define NS_STYLE_TABSIZE_INITIAL                8
 
 // See nsStyleText
-#define NS_STYLE_WHITESPACE_NORMAL              0
-#define NS_STYLE_WHITESPACE_PRE                 1
-#define NS_STYLE_WHITESPACE_NOWRAP              2
-#define NS_STYLE_WHITESPACE_PRE_WRAP            3
-#define NS_STYLE_WHITESPACE_PRE_LINE            4
+#define NS_STYLE_WHITESPACE_NORMAL               0
+#define NS_STYLE_WHITESPACE_PRE                  1
+#define NS_STYLE_WHITESPACE_NOWRAP               2
+#define NS_STYLE_WHITESPACE_PRE_WRAP             3
+#define NS_STYLE_WHITESPACE_PRE_LINE             4
+#define NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES 5
 
 // See nsStyleText
 #define NS_STYLE_WORDBREAK_NORMAL               0
 #define NS_STYLE_WORDBREAK_BREAK_ALL            1
 #define NS_STYLE_WORDBREAK_KEEP_ALL             2
 
 // See nsStyleText
 #define NS_STYLE_WORDWRAP_NORMAL                0
--- a/layout/base/tests/test_bug469170.html
+++ b/layout/base/tests/test_bug469170.html
@@ -8,36 +8,31 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body onload="runTest();">
 <p><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469170">Mozilla Bug 469170</a></p>
 
 <iframe id="source" width="50" height="50"
        src="data:text/html,%3Chtml%3E%3C%2Fhtml%3E"></iframe>
-<canvas id="scratch" width="50" height="50"></canvas>
 
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 469170 **/
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
-  var canvas = document.getElementById('scratch');
   var source = document.getElementById('source').contentWindow;
+  rect = { left: 0, top: 0,
+           width: source.innerWidth, height: source.innerHeight };
+  var canvas = SpecialPowers.snapshotRect(source, rect, "transparent");
   var context = canvas.getContext("2d");
 
-  context.clearRect(0, 0, canvas.width, canvas.height);
-  context.drawWindow(source, 0, 0, source.innerWidth, source.innerHeight,
-                     "transparent");
-
   var components = [ "red", "green", "blue", "alpha" ];
 
   var data = context.getImageData(0, 0, canvas.width, canvas.height).data;
   var failed = false;
   for (var i = 0; i < data.length; i++) {
     if (data[i] != 0) {
       is(data[i], 0, "pixel " + Math.floor(i/4) + " " + components[i%4]);
       failed = true;
--- a/layout/base/tests/test_bug514127.html
+++ b/layout/base/tests/test_bug514127.html
@@ -12,38 +12,36 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=514127">Mozilla Bug 514127</a></p>
 
 <!--
 iframe source is
 <html><body style='background: rgb(0,0,255); width: 100px; height: 50100px;'></body></html>
 -->
 <iframe id="source" width="50" height="50"
        src="data:text/html,%3Chtml%3E%3Cbody%20style%3D%27background%3A%20rgb%280%2C0%2C255%29%3B%20width%3A%20100px%3B%20height%3A%2050100px%3B%27%3E%3C%2Fbody%3E%3C%2Fhtml%3E"></iframe>
-<canvas id="scratch" width="50" height="50"></canvas>
 
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 514127 **/
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  
-  var canvas = document.getElementById('scratch');
   var source = document.getElementById('source').contentWindow;
+  var canvasWidth = 50;
+  var canvasHeight = 50;
+
+  rect = { left: 25, top: 50000,
+           width: canvasWidth, height: canvasHeight };
+  var canvas = SpecialPowers.snapshotRect(source, rect, "transparent");
   var context = canvas.getContext("2d");
   
-  context.clearRect(0, 0, canvas.width, canvas.height);
-  context.drawWindow(source, 25, 50000, canvas.width, canvas.height,
-                     "transparent");
-  
-  var data = context.getImageData(0, 0, canvas.width, canvas.height).data;
+  var data = context.getImageData(0, 0, canvasWidth, canvasHeight).data;
   var failed = false;
   for (var i = 0; i < data.length; i+=4) {
     if (data[i] != 0 || data[i+1] != 0 || data[i+2] != 255 || data[i+3] != 255) {
       failed = true;
       break;
     }
   }
   ok(!failed, "all pixels blue");
--- a/layout/base/tests/test_bug518777.html
+++ b/layout/base/tests/test_bug518777.html
@@ -7,27 +7,25 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 518777</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 
   <script>
   SimpleTest.waitForExplicitFinish();
 
   function dotest() {
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
+    var canvasWidth = 50;
+    var canvasHeight = 50;
     var source = document.getElementById("source").contentWindow;
-    var canvas = document.getElementById("scratch");
+    rect = { left: 25, top: 25,
+             width: canvasWidth, height: canvasHeight };
+    var canvas = SpecialPowers.snapshotRect(source, rect, "transparent");
     var context = canvas.getContext("2d");
 
-    context.clearRect(0, 0, canvas.width, canvas.height);
-    context.drawWindow(source, 25, 25, canvas.width, canvas.height,
-                       "transparent");
-
-    var data = context.getImageData(0, 0, canvas.width, canvas.height).data;
+    var data = context.getImageData(0, 0, canvasWidth, canvasHeight).data;
     var i;
     for (i = 0; i < data.length; i += 4) {
       if (data[i] != 0 || data[i + 1] != 0 || data[i + 2] != 255 || data[i + 3] != 255)
         break;
     }
     ok(i >= data.length, "all pixels blue");
 
     SimpleTest.finish();
@@ -38,14 +36,13 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=518777">Mozilla Bug 518777</a></p>
 
 <!--
 iframe source is
 <html><body onload='window.scrollTo(0,99999999); document.documentElement.offsetWidth; window.parent.dotest();' style='background: rgb(0,0,255); width: 100px; height: 50100px;'></body></html>
 -->
 <iframe id="source" width="50" height="50"
        src="data:text/html,%3Chtml%3E%3Cbody%20onload%3D%27window.scrollTo%280%2C99999999%29%3B%20document.documentElement.offsetWidth%3B%20window.parent.dotest%28%29%3B%27%20style%3D%27background%3A%20rgb%280%2C0%2C255%29%3B%20width%3A%20100px%3B%20height%3A%2050100px%3B%27%3E%3C%2Fbody%3E%3C%2Fhtml%3E"></iframe>
-<canvas id="scratch" width="50" height="50"></canvas>
 
 <pre id="test">
 </pre>
 </body>
 </html>
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -659,17 +659,18 @@ static bool IsCSSWordSpacingSpace(const 
 
   PRUnichar ch = aFrag->CharAt(aPos);
   switch (ch) {
   case ' ':
   case CH_NBSP:
     return !IsSpaceCombiningSequenceTail(aFrag, aPos + 1);
   case '\r':
   case '\t': return !aStyleText->WhiteSpaceIsSignificant();
-  case '\n': return !aStyleText->NewlineIsSignificant();
+  case '\n': return !aStyleText->NewlineIsSignificant() &&
+                    !aStyleText->NewlineIsDiscarded();
   default: return false;
   }
 }
 
 // Check whether the string aChars/aLength starts with space that's
 // trimmable according to CSS 'white-space:normal/nowrap'. 
 static bool IsTrimmableSpace(const PRUnichar* aChars, uint32_t aLength)
 {
@@ -691,17 +692,18 @@ static bool IsTrimmableSpace(char aCh)
 static bool IsTrimmableSpace(const nsTextFragment* aFrag, uint32_t aPos,
                                const nsStyleText* aStyleText)
 {
   NS_ASSERTION(aPos < aFrag->GetLength(), "No text for IsSpace!");
 
   switch (aFrag->CharAt(aPos)) {
   case ' ': return !aStyleText->WhiteSpaceIsSignificant() &&
                    !IsSpaceCombiningSequenceTail(aFrag, aPos + 1);
-  case '\n': return !aStyleText->NewlineIsSignificant();
+  case '\n': return !aStyleText->NewlineIsSignificant() &&
+                    !aStyleText->NewlineIsDiscarded();
   case '\t':
   case '\r':
   case '\f': return !aStyleText->WhiteSpaceIsSignificant();
   default: return false;
   }
 }
 
 static bool IsSelectionSpace(const nsTextFragment* aFrag, uint32_t aPos)
@@ -755,16 +757,31 @@ IsAllWhitespace(const nsTextFragment* aF
     char ch = str[i];
     if (ch == ' ' || ch == '\t' || ch == '\r' || (ch == '\n' && aAllowNewline))
       continue;
     return false;
   }
   return true;
 }
 
+static bool
+IsAllNewlines(const nsTextFragment* aFrag)
+{
+  if (aFrag->Is2b())
+    return false;
+  int32_t len = aFrag->GetLength();
+  const char* str = aFrag->Get1b();
+  for (int32_t i = 0; i < len; ++i) {
+    char ch = str[i];
+    if (ch != '\n')
+      return false;
+  }
+  return true;
+}
+
 /**
  * This class accumulates state as we scan a paragraph of text. It detects
  * textrun boundaries (changes from text to non-text, hard
  * line breaks, and font changes) and builds a gfxTextRun at each boundary.
  * It also detects linebreaker run boundaries (changes from text to non-text,
  * and hard line breaks) and at each boundary runs the linebreaker to compute
  * potential line breaks. It also records actual line breaks to store them in
  * the textruns.
@@ -1732,24 +1749,26 @@ GetFirstFontMetrics(gfxFontGroup* aFontG
   return font->GetMetrics();
 }
 
 PR_STATIC_ASSERT(NS_STYLE_WHITESPACE_NORMAL == 0);
 PR_STATIC_ASSERT(NS_STYLE_WHITESPACE_PRE == 1);
 PR_STATIC_ASSERT(NS_STYLE_WHITESPACE_NOWRAP == 2);
 PR_STATIC_ASSERT(NS_STYLE_WHITESPACE_PRE_WRAP == 3);
 PR_STATIC_ASSERT(NS_STYLE_WHITESPACE_PRE_LINE == 4);
+PR_STATIC_ASSERT(NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES == 5);
 
 static const nsTextFrameUtils::CompressionMode CSSWhitespaceToCompressionMode[] =
 {
   nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE, // normal
   nsTextFrameUtils::COMPRESS_NONE,               // pre
   nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE, // nowrap
   nsTextFrameUtils::COMPRESS_NONE,               // pre-wrap
-  nsTextFrameUtils::COMPRESS_WHITESPACE          // pre-line
+  nsTextFrameUtils::COMPRESS_WHITESPACE,         // pre-line
+  nsTextFrameUtils::DISCARD_NEWLINE              // -moz-pre-discard-newlines
 };
 
 gfxTextRun*
 BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
 {
   gfxSkipCharsBuilder builder;
 
   const void* textPtr = aTextBuffer;
@@ -7077,17 +7096,18 @@ nsTextFrame::AddInlinePrefWidthForFlow(n
   uint32_t loopStart = (preformatNewlines || preformatTabs) ? start : flowEndInTextRun;
   for (uint32_t i = loopStart, lineStart = start; i <= flowEndInTextRun; ++i) {
     bool preformattedNewline = false;
     bool preformattedTab = false;
     if (i < flowEndInTextRun) {
       // XXXldb Shouldn't we be including the newline as part of the
       // segment that it ends rather than part of the segment that it
       // starts?
-      NS_ASSERTION(preformatNewlines, "We can't be here unless newlines are hard breaks");
+      NS_ASSERTION(preformatNewlines || textStyle->NewlineIsDiscarded(),
+                   "We can't be here unless newlines are hard breaks or are discarded");
       preformattedNewline = preformatNewlines && textRun->CharIsNewline(i);
       preformattedTab = preformatTabs && textRun->CharIsTab(i);
       if (!preformattedNewline && !preformattedTab) {
         // we needn't break here (and it's not the end of the flow)
         continue;
       }
     }
 
@@ -8173,17 +8193,18 @@ nsTextFrame::RecomputeOverflow(const nsH
   UnionAdditionalOverflow(PresContext(), aBlockReflowState, provider,
                           &vis, true);
   return result;
 }
 static PRUnichar TransformChar(const nsStyleText* aStyle, gfxTextRun* aTextRun,
                                uint32_t aSkippedOffset, PRUnichar aChar)
 {
   if (aChar == '\n') {
-    return aStyle->NewlineIsSignificant() ? aChar : ' ';
+    return aStyle->NewlineIsSignificant() || aStyle->NewlineIsDiscarded() ?
+             aChar : ' ';
   }
   switch (aStyle->mTextTransform) {
   case NS_STYLE_TEXT_TRANSFORM_LOWERCASE:
     aChar = ToLowerCase(aChar);
     break;
   case NS_STYLE_TEXT_TRANSFORM_UPPERCASE:
     aChar = ToUpperCase(aChar);
     break;
@@ -8320,31 +8341,35 @@ nsTextFrame::GetType() const
 nsTextFrame::IsEmpty()
 {
   NS_ASSERTION(!(mState & TEXT_IS_ONLY_WHITESPACE) ||
                !(mState & TEXT_ISNOT_ONLY_WHITESPACE),
                "Invalid state");
   
   // XXXldb Should this check compatibility mode as well???
   const nsStyleText* textStyle = GetStyleText();
-  if (textStyle->WhiteSpaceIsSignificant()) {
+  if (textStyle->WhiteSpaceIsSignificant() &&
+      textStyle->mWhiteSpace != NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES) {
     // XXX shouldn't we return true if the length is zero?
     return false;
   }
 
   if (mState & TEXT_ISNOT_ONLY_WHITESPACE) {
     return false;
   }
 
   if (mState & TEXT_IS_ONLY_WHITESPACE) {
     return true;
   }
-  
-  bool isEmpty = IsAllWhitespace(mContent->GetText(),
-          textStyle->mWhiteSpace != NS_STYLE_WHITESPACE_PRE_LINE);
+
+  bool isEmpty =
+    textStyle->mWhiteSpace == NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES ?
+      IsAllNewlines(mContent->GetText()) :
+      IsAllWhitespace(mContent->GetText(),
+                      textStyle->mWhiteSpace != NS_STYLE_WHITESPACE_PRE_LINE);
   mState |= (isEmpty ? TEXT_IS_ONLY_WHITESPACE : TEXT_ISNOT_ONLY_WHITESPACE);
   return isEmpty;
 }
 
 #ifdef DEBUG
 NS_IMETHODIMP
 nsTextFrame::GetFrameName(nsAString& aResult) const
 {
--- a/layout/generic/nsTextFrameUtils.cpp
+++ b/layout/generic/nsTextFrameUtils.cpp
@@ -54,22 +54,24 @@ nsTextFrameUtils::TransformText(const PR
                                 gfxSkipCharsBuilder* aSkipChars,
                                 uint32_t* aAnalysisFlags)
 {
   uint32_t flags = 0;
   PRUnichar* outputStart = aOutput;
 
   bool lastCharArabic = false;
 
-  if (aCompression == COMPRESS_NONE) {
+  if (aCompression == COMPRESS_NONE ||
+      aCompression == DISCARD_NEWLINE) {
     // Skip discardables.
     uint32_t i;
     for (i = 0; i < aLength; ++i) {
       PRUnichar ch = *aText++;
-      if (IsDiscardable(ch, &flags)) {
+      if (IsDiscardable(ch, &flags) ||
+          (ch == '\n' && aCompression == DISCARD_NEWLINE)) {
         aSkipChars->SkipChar();
       } else {
         aSkipChars->KeepChar();
         if (ch > ' ') {
           lastCharArabic = IS_ARABIC_CHAR(ch);
         } else if (ch == '\t') {
           flags |= TEXT_HAS_TAB;
         }
@@ -152,22 +154,24 @@ nsTextFrameUtils::TransformText(const ui
                                 CompressionMode aCompression,
                                 uint8_t* aIncomingFlags,
                                 gfxSkipCharsBuilder* aSkipChars,
                                 uint32_t* aAnalysisFlags)
 {
   uint32_t flags = 0;
   uint8_t* outputStart = aOutput;
 
-  if (aCompression == COMPRESS_NONE) {
+  if (aCompression == COMPRESS_NONE ||
+      aCompression == DISCARD_NEWLINE) {
     // Skip discardables.
     uint32_t i;
     for (i = 0; i < aLength; ++i) {
       uint8_t ch = *aText++;
-      if (IsDiscardable(ch, &flags)) {
+      if (IsDiscardable(ch, &flags) || 
+          ch == '\n' && aCompression == DISCARD_NEWLINE) {
         aSkipChars->SkipChar();
       } else {
         aSkipChars->KeepChar();
         if (ch == '\t') {
           flags |= TEXT_HAS_TAB;
         }
         *aOutput++ = ch;
       }
--- a/layout/generic/nsTextFrameUtils.h
+++ b/layout/generic/nsTextFrameUtils.h
@@ -74,28 +74,30 @@ public:
   static bool
   IsSpaceCombiningSequenceTail(const PRUnichar* aChars, int32_t aLength) {
     return aLength > 0 && aChars[0] == 0x200D; // ZWJ
   }
 
   enum CompressionMode {
     COMPRESS_NONE,
     COMPRESS_WHITESPACE,
-    COMPRESS_WHITESPACE_NEWLINE
+    COMPRESS_WHITESPACE_NEWLINE,
+    DISCARD_NEWLINE
   };
 
   /**
    * Create a text run from a run of Unicode text. The text may have whitespace
    * compressed. A preformatted tab is sent to the text run as a single space.
    * (Tab spacing must be performed by textframe later.) Certain other
    * characters are discarded.
    * 
    * @param aCompressWhitespace control what is compressed to a
    * single space character: no compression, compress spaces (not followed
-   * by combining mark) and tabs, and compress those plus newlines.
+   * by combining mark) and tabs, compress those plus newlines, or
+   * no compression except newlines are discarded.
    * @param aIncomingFlags a flag indicating whether there was whitespace
    * or an Arabic character preceding this text. We set it to indicate if
    * there's an Arabic character or whitespace preceding the end of this text.
    */
   static PRUnichar* TransformText(const PRUnichar* aText, uint32_t aLength,
                                   PRUnichar* aOutput,
                                   CompressionMode aCompression,
                                   uint8_t * aIncomingFlags,
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -1947,22 +1947,22 @@ nsPrintEngine::ReflowPrintObject(nsPrint
   aPO->mPresContext->SetPrintPreviewScale(mScreenDPI / printDPI);
 
   if (mIsCreatingPrintPreview && documentIsTopLevel) {
     mDocViewerPrint->SetPrintPreviewPresentation(aPO->mViewManager,
                                                  aPO->mPresContext,
                                                  aPO->mPresShell);
   }
 
-  rv = aPO->mPresShell->InitialReflow(adjSize.width, adjSize.height);
+  rv = aPO->mPresShell->Initialize(adjSize.width, adjSize.height);
 
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ASSERTION(aPO->mPresShell, "Presshell should still be here");
 
-  // Process the reflow event InitialReflow posted
+  // Process the reflow event Initialize posted
   aPO->mPresShell->FlushPendingNotifications(Flush_Layout);
 
   nsCOMPtr<nsIPresShell> displayShell;
   aPO->mDocShell->GetPresShell(getter_AddRefs(displayShell));
   // Transfer Selection Ranges to the new Print PresShell
   nsCOMPtr<nsISelection> selection, selectionPS;
   // It's okay if there is no display shell, just skip copying the selection
   if (displayShell) {
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/pre-discard-newlines-1-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<style>
+p { font: 16px monospace; white-space: pre; }
+span { background-color: lime }
+</style>
+<p><span>a  b</span></p>
+<p><span>ab</span></p>
+<p><span>a  b</span></p>
+<p><span>  a  b</span></p>
+<p><span>a  </span></p>
+<p><span></span></p>
+<p><span>    </span></p>
+<p><span>. </span></p>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/pre-discard-newlines-1.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<style>
+p { font: 16px monospace; white-space: -moz-pre-discard-newlines; }
+span { background-color: lime }
+</style>
+<p><span>a  b</span></p>
+<p><span>a&#xA;b</span></p>
+<p><span>a &#xA; b</span></p>
+<p><span>&#xA;  a&#xA;  b&#xA;</span></p>
+<p><span>a  </span></p>
+<p><span>&#xA;&#xA;&#xA;</span></p>
+<p><span>  &#xA;&#xA;&#xA;  </span></p>
+<p><span>. &#xA;</span></p>
--- a/layout/reftests/text/reftest.list
+++ b/layout/reftests/text/reftest.list
@@ -24,16 +24,17 @@ load ligature-with-space-1.html
 == line-editing-1e.html line-editing-1-ref.html
 fails-if(cocoaWidget||winWidget) HTTP(..) == lineheight-metrics-1.html lineheight-metrics-1-ref.html # bug 657864
 == lineheight-percentage-1.html lineheight-percentage-1-ref.html
 == long-1.html long-ref.html
 == pre-line-1.html pre-line-1-ref.html
 == pre-line-2.html pre-line-2-ref.html
 == pre-line-3.html pre-line-3-ref.html
 == pre-line-4.html pre-line-4-ref.html
+== pre-discard-newlines-1.html pre-discard-newlines-1-ref.html
 == soft-hyphens-1a.html soft-hyphens-1-ref.html
 == soft-hyphens-1b.html soft-hyphens-1-ref.html
 == soft-hyphens-1c.html soft-hyphens-1-ref.html
 # Tests for soft hyphens in table cells, bug 418975
 != soft-hyphen-in-table-1.html soft-hyphen-in-table-1-notref.html
 == soft-hyphen-in-table-1.html soft-hyphen-in-table-1-ref.html
 == soft-hyphen-in-table-2.html soft-hyphen-in-table-2-ref.html
 # Cairo's FreeType and GDI backends snap glyphs to pixels, while Mac (usually)
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -135,16 +135,17 @@ CSS_KEY(-moz-objectfillopacity, _moz_obj
 CSS_KEY(-moz-objectstroke, _moz_objectstroke)
 CSS_KEY(-moz-objectstrokeopacity, _moz_objectstrokeopacity)
 CSS_KEY(-moz-objectvalue, _moz_objectvalue)
 CSS_KEY(-moz-oddtreerow, _moz_oddtreerow)
 CSS_KEY(-moz-oriya, _moz_oriya)
 CSS_KEY(-moz-persian, _moz_persian)
 CSS_KEY(-moz-plaintext, _moz_plaintext)
 CSS_KEY(-moz-popup, _moz_popup)
+CSS_KEY(-moz-pre-discard-newlines, _moz_pre_discard_newlines)
 CSS_KEY(-moz-pull-down-menu, _moz_pull_down_menu)
 CSS_KEY(-moz-right, _moz_right)
 CSS_KEY(-moz-scrollbars-horizontal, _moz_scrollbars_horizontal)
 CSS_KEY(-moz-scrollbars-none, _moz_scrollbars_none)
 CSS_KEY(-moz-scrollbars-vertical, _moz_scrollbars_vertical)
 CSS_KEY(-moz-show-background, _moz_show_background)
 CSS_KEY(-moz-simp-chinese-formal, _moz_simp_chinese_formal)
 CSS_KEY(-moz-simp-chinese-informal, _moz_simp_chinese_informal)
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -1450,16 +1450,17 @@ const int32_t nsCSSProps::kVisibilityKTa
 };
 
 const int32_t nsCSSProps::kWhitespaceKTable[] = {
   eCSSKeyword_normal, NS_STYLE_WHITESPACE_NORMAL,
   eCSSKeyword_pre, NS_STYLE_WHITESPACE_PRE,
   eCSSKeyword_nowrap, NS_STYLE_WHITESPACE_NOWRAP,
   eCSSKeyword_pre_wrap, NS_STYLE_WHITESPACE_PRE_WRAP,
   eCSSKeyword_pre_line, NS_STYLE_WHITESPACE_PRE_LINE,
+  eCSSKeyword__moz_pre_discard_newlines, NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES,
   eCSSKeyword_UNKNOWN,-1
 };
 
 const int32_t nsCSSProps::kWidthKTable[] = {
   eCSSKeyword__moz_max_content, NS_STYLE_WIDTH_MAX_CONTENT,
   eCSSKeyword__moz_min_content, NS_STYLE_WIDTH_MIN_CONTENT,
   eCSSKeyword__moz_fit_content, NS_STYLE_WIDTH_FIT_CONTENT,
   eCSSKeyword__moz_available, NS_STYLE_WIDTH_AVAILABLE,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2929,17 +2929,18 @@ nsStyleText::nsStyleText(const nsStyleTe
 
 nsStyleText::~nsStyleText(void)
 {
   MOZ_COUNT_DTOR(nsStyleText);
 }
 
 nsChangeHint nsStyleText::CalcDifference(const nsStyleText& aOther) const
 {
-  if (NewlineIsSignificant() != aOther.NewlineIsSignificant()) {
+  if (WhiteSpaceOrNewlineIsSignificant() !=
+      aOther.WhiteSpaceOrNewlineIsSignificant()) {
     // This may require construction of suppressed text frames
     return NS_STYLE_HINT_FRAMECHANGE;
   }
 
   if ((mTextAlign != aOther.mTextAlign) ||
       (mTextAlignLast != aOther.mTextAlignLast) ||
       (mTextTransform != aOther.mTextTransform) ||
       (mWhiteSpace != aOther.mWhiteSpace) ||
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1322,25 +1322,37 @@ struct nsStyleText {
   nsStyleCoord  mLetterSpacing;         // [inherited] coord, normal
   nsStyleCoord  mLineHeight;            // [inherited] coord, factor, normal
   nsStyleCoord  mTextIndent;            // [inherited] coord, percent, calc
 
   nsRefPtr<nsCSSShadowArray> mTextShadow; // [inherited] NULL in case of a zero-length
 
   bool WhiteSpaceIsSignificant() const {
     return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
-           mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP;
+           mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
+           mWhiteSpace == NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES;
   }
 
   bool NewlineIsSignificant() const {
     return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
   }
 
+  bool NewlineIsDiscarded() const {
+    return mWhiteSpace == NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES;
+  }
+
+  bool WhiteSpaceOrNewlineIsSignificant() const {
+    return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
+           mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
+           mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE ||
+           mWhiteSpace == NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES;
+  }
+
   bool WhiteSpaceCanWrap() const {
     return mWhiteSpace == NS_STYLE_WHITESPACE_NORMAL ||
            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
            mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
   }
 
   bool WordCanWrap() const {
     return WhiteSpaceCanWrap() && mWordWrap == NS_STYLE_WORDWRAP_BREAK_WORD;
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -3417,17 +3417,17 @@ var gCSSProperties = {
 		other_values: [ "hidden", "collapse" ],
 		invalid_values: []
 	},
 	"white-space": {
 		domProp: "whiteSpace",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "normal" ],
-		other_values: [ "pre", "nowrap", "pre-wrap", "pre-line" ],
+		other_values: [ "pre", "nowrap", "pre-wrap", "pre-line", "-moz-pre-discard-newlines" ],
 		invalid_values: []
 	},
 	"widows": {
 		domProp: "widows",
 		inherited: true,
 		backend_only: true,
 		type: CSS_TYPE_LONGHAND,
 		// XXX requires display:block
--- a/layout/style/test/test_bug405818.html
+++ b/layout/style/test/test_bug405818.html
@@ -38,21 +38,18 @@ addLoadEvent(function() {
      "chrome://global/skin/global.css",
      "Unexpected href for linked chrome sheet before cloning");
   is(document.styleSheets[4].href,
      "chrome://global/skin/global.css",
      "Unexpected href for later linked chrome sheet before cloning");
 
   // Force cloning of inners
   document.styleSheets[1].cssRules[0];
-  (function() {
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    document.styleSheets[2].cssRules[0];
-  })();
-  
+  SpecialPowers.wrap(document.styleSheets[2]).cssRules[0];
+
   is(document.styleSheets[1].href,
      "data:text/css,%23myDiv{color:green;}",
      "Unexpected href for linked sheet after cloning");
   is(document.styleSheets[3].href,
      "data:text/css,%23myDiv{color:green;}",
      "Unexpected href for later linked sheet after cloning");
 
   is(document.styleSheets[2].href,
--- a/layout/tools/reftest/reftest.js
+++ b/layout/tools/reftest/reftest.js
@@ -493,18 +493,18 @@ function BuildConditionSandbox(aURL) {
 
     // xr.XPCOMABI throws exception for configurations without full ABI
     // support (mobile builds on ARM)
     try {
         sandbox.xulRuntime.XPCOMABI = xr.XPCOMABI;
     } catch(e) {
         sandbox.xulRuntime.XPCOMABI = "";
     }
- 
-    
+
+
 #if REFTEST_B2G
     // XXX nsIGfxInfo isn't available in B2G
     sandbox.d2d = false;
     sandbox.azureQuartz = false;
     sandbox.azureSkia = false;
     sandbox.contentSameGfxBackendAsCanvas = false;
 #else
     var gfxInfo = (NS_GFXINFO_CONTRACTID in CC) && CC[NS_GFXINFO_CONTRACTID].getService(CI.nsIGfxInfo);
@@ -618,16 +618,20 @@ function BuildConditionSandbox(aURL) {
         return testPluginIsOOP;
     };
 
     // Tests shouldn't care about this except for when they need to
     // crash the content process
     sandbox.browserIsRemote = gBrowserIsRemote;
     sandbox.bug685516 = sandbox.browserIsRemote && sandbox.Android;
 
+    // Distinguish the Fennecs:
+    sandbox.xulFennec    = sandbox.Android &&  sandbox.browserIsRemote;
+    sandbox.nativeFennec = sandbox.Android && !sandbox.browserIsRemote;
+
     if (!gDumpedConditionSandbox) {
         dump("REFTEST INFO | Dumping JSON representation of sandbox \n");
         dump("REFTEST INFO | " + JSON.stringify(sandbox) + " \n");
         gDumpedConditionSandbox = true;
     }
     return sandbox;
 }
 
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -4,16 +4,21 @@
       package="@ANDROID_PACKAGE_NAME@"
       android:installLocation="auto"
       android:versionCode="@ANDROID_VERSION_CODE@"
       android:versionName="@MOZ_APP_VERSION@"
 #ifdef MOZ_ANDROID_SHARED_ID
       android:sharedUserId="@MOZ_ANDROID_SHARED_ID@"
 #endif
       >
+
+#ifdef ARMV7_ONLY
+    <supports-screens android:smallScreens="false" />
+#endif
+
     <uses-sdk android:minSdkVersion="8"
               android:targetSdkVersion="14"/>
 
 #include ../sync/manifests/SyncAndroidManifest_permissions.xml.in
 
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.INTERNET"/>
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -212,16 +212,17 @@ FENNEC_PP_XML_FILES = \
   res/menu-v11/titlebar_contextmenu.xml \
   res/menu-large-v11/browser_app_menu.xml \
   res/menu-xlarge-v11/browser_app_menu.xml \
   $(NULL)
 
 
 ifneq (,$(findstring -march=armv7,$(OS_CFLAGS)))
 MIN_CPU_VERSION=7
+DEFINES += -DARMV7_ONLY=1
 else
 MIN_CPU_VERSION=5
 endif
 
 MOZ_APP_BUILDID=$(shell cat $(DEPTH)/config/buildid)
 
 ifeq (,$(ANDROID_VERSION_CODE))
 ifeq ($(MIN_CPU_VERSION),7)
deleted file mode 100644
--- a/mobile/android/themes/core/aboutMemory.css
+++ /dev/null
@@ -1,101 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* This file is used for both about:memory and about:compartments. */
-
-body.verbose {
-  /* override setting in about.css */
-  max-width: 100% !important;
-}
-
-body.non-verbose pre.entries {
-  overflow-x: hidden;
-  text-overflow: ellipsis;
-}
-
-h2 {
-  background: #ddd;
-  padding-left: .1em;
-}
-
-.accuracyWarning {
-  color: #f00;
-}
-
-.treeline {
-  color: #888;
-}
-
-.mrValue {
-  font-weight: bold;
-  color: #400;
-}
-
-.mrName {
-  color: #004;
-}
-
-.mrNote {
-  color: #604;
-}
-
-.hasKids {
-  cursor: pointer;
-}
-
-.hasKids:hover {
-  text-decoration: underline;
-}
-
-.option {
-  font-size: 80%;
-  -moz-user-select: none;  /* no need to include this when cutting+pasting */
-}
-
-.legend {
-  font-size: 80%;
-  -moz-user-select: none;  /* no need to include this when cutting+pasting */
-}
-
-.legend:last-of-type {
-  display: none;
-}
-
-.debug {
-  font-size: 80%;
-}
-
-.hidden {
-  display: none;
-}
-
-.invalid {
-  color: #fff;
-  background-color: #f00;
-}
-
-#updateButton {
-  margin: 1% 2% 1% 1%;
-  padding: 2% 0;
-  width: 30%;
-}
-
-#doGCButton {
-  margin: 1% 2%;
-  padding: 2% 0;
-  width: 30%;
-}
-
-#doCCButton {
-  margin: 1% 1% 1% 2%;
-  padding: 2% 0;
-  width: 30%;
-}
-
-#minMemUseButton {
-  margin: 1%;
-  padding: 2% 0;
-  width: 98%;
-}
-
--- a/mobile/android/themes/core/jar.mn
+++ b/mobile/android/themes/core/jar.mn
@@ -7,26 +7,24 @@
 chrome.jar:
 % skin browser classic/1.0 %skin/
   skin/aboutPage.css                        (aboutPage.css)
   skin/about.css                            (about.css)
   skin/aboutAddons.css                      (aboutAddons.css)
   skin/aboutApps.css                        (aboutApps.css)
 * skin/aboutDownloads.css                   (aboutDownloads.css)
   skin/aboutFeedback.css                    (aboutFeedback.css)
-  skin/aboutMemory.css                      (aboutMemory.css)
   skin/aboutReader.css                      (aboutReader.css)
   skin/aboutSupport.css                     (aboutSupport.css)
 * skin/browser.css                          (browser.css)
 * skin/content.css                          (content.css)
   skin/config.css                           (config.css)
   skin/touchcontrols.css                    (touchcontrols.css)
   skin/netError.css                         (netError.css)
 % override chrome://global/skin/about.css chrome://browser/skin/about.css
-% override chrome://global/skin/aboutMemory.css chrome://browser/skin/aboutMemory.css
 % override chrome://global/skin/aboutSupport.css chrome://browser/skin/aboutSupport.css
 % override chrome://global/skin/media/videocontrols.css chrome://browser/skin/touchcontrols.css
 % override chrome://global/skin/netError.css chrome://browser/skin/netError.css
 
   skin/fonts/opensans-regular.ttf           (fonts/opensans-regular.ttf)
   skin/fonts/opensans-light.ttf             (fonts/opensans-light.ttf)
   skin/images/5stars.png                    (images/5stars.png)
   skin/images/addons-32.png                 (images/addons-32.png)
--- a/storage/src/TelemetryVFS.cpp
+++ b/storage/src/TelemetryVFS.cpp
@@ -1,20 +1,31 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
  * 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/. */