Merge m-c to s-c.
authorRichard Newman <rnewman@mozilla.com>
Fri, 07 Sep 2012 14:12:07 -0700
changeset 110936 1f92079a3029bb6e97699dfd3c1d3f20d1a73fbc
parent 110935 c66677223fd860e4fc7c668c68eb6c1c9a178d80 (current diff)
parent 104563 00a552f644a21c1395909643ea44c70f313bee39 (diff)
child 110937 39f2364d486010a5ecb605b6cae84b30b9cbb4c8
push id23725
push userrnewman@mozilla.com
push dateMon, 22 Oct 2012 19:47:10 +0000
treeherdermozilla-central@acf7f73e8b18 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone18.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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%;