merge autoland to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 20 Apr 2017 11:11:13 +0200
changeset 353979 20325547884af3bd8c66ef543358692b5cccf5b0
parent 353962 f6be27f5457ffd75b3763db09a139e24bc2155dc (current diff)
parent 353978 182ed00b19e357ee3f6ca686e3be66e004087e51 (diff)
child 354003 27311156637f9b5d4504373967e01c4241902ae7
push id31683
push usercbook@mozilla.com
push dateThu, 20 Apr 2017 09:11:32 +0000
treeherdermozilla-central@20325547884a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone55.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 autoland to mozilla-central a=merge
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -141,17 +141,17 @@
                     showAllTooltipText="&appMenuRemoteTabs.showAll.tooltip;"
                     showMoreLabel="&appMenuRemoteTabs.showMore.label;"
                     showMoreTooltipText="&appMenuRemoteTabs.showMore.tooltip;"
                     notabsforclientlabel="&appMenuRemoteTabs.notabs.label;"
                     />
             </vbox>
             <!-- Sync is ready to Sync but the "tabs" engine isn't enabled-->
             <hbox id="PanelUI-remotetabs-tabsdisabledpane" pack="center" flex="1">
-              <vbox class="PanelUI-remotetabs-instruction-box">
+              <vbox class="PanelUI-remotetabs-instruction-box" align="center">
                 <hbox pack="center">
                   <html:img class="fxaSyncIllustration" src="chrome://browser/skin/fxa/sync-illustration.svg"/>
                 </hbox>
                 <label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.tabsnotsyncing.label;</label>
                 <hbox pack="center">
                   <toolbarbutton class="PanelUI-remotetabs-prefs-button"
                                  label="&appMenuRemoteTabs.openprefs.label;"
                                  oncommand="gSyncUI.openPrefs('synced-tabs');"/>
--- a/browser/components/preferences/in-content/advanced.xul
+++ b/browser/components/preferences/in-content/advanced.xul
@@ -42,17 +42,16 @@
   <stringbundle id="bundleBrand" src="chrome://branding/locale/brand.properties"/>
 #endif
 
 <hbox id="header-advanced"
       class="header"
       hidden="true"
       data-category="paneAdvanced">
   <label class="header-name" flex="1">&paneUpdates.title;</label>
-  <html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a>
 </hbox>
 
 <!-- Update -->
 <groupbox id="updateApp" data-category="paneAdvanced" hidden="true">
   <caption><label>&updateApplication.label;</label></caption>
   <description>&updateApplication.description;</description>
   <hbox align="start">
     <vbox flex="1">
--- a/browser/components/preferences/in-content/applications.xul
+++ b/browser/components/preferences/in-content/applications.xul
@@ -59,17 +59,16 @@
   <key key="&focusSearch2.key;" modifiers="accel" id="focusSearch2" oncommand=";"/>
 </keyset>
 
 <hbox id="header-applications"
       class="header"
       hidden="true"
       data-category="paneApplications">
   <label class="header-name" flex="1">&paneFilesApplications.title;</label>
-  <html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a>
 </hbox>
 
 <vbox id="applicationsContent"
       data-category="paneApplications"
       hidden="true"
       flex="1">
 
   <!--Downloads-->
--- a/browser/components/preferences/in-content/containers.xul
+++ b/browser/components/preferences/in-content/containers.xul
@@ -21,18 +21,16 @@
   <label class="text-link" id="backContainersLink" value="&backLink.label;" />
 </hbox>
 
 <hbox id="header-containers"
       class="header"
       hidden="true"
       data-category="paneContainers">
   <label class="header-name" flex="1">&paneContainers.title;</label>
-  <button class="help-button"
-          aria-label="&helpButton.label;"/>
 </hbox>
 
 <!-- Containers -->
 <groupbox id="browserContainersGroup" data-category="paneContainers" hidden="true">
   <vbox id="browserContainersbox">
 
     <richlistbox id="containersView" orient="vertical" persist="lastSelectedType"
                  flex="1">
--- a/browser/components/preferences/in-content/findInPage.js
+++ b/browser/components/preferences/in-content/findInPage.js
@@ -226,22 +226,19 @@ var gSearchResultsPane = {
 
       if (!resultsFound) {
         let noResultsEl = document.querySelector(".no-results-message");
         noResultsEl.hidden = false;
 
         let strings = this.strings;
         document.getElementById("sorry-message").textContent =
           strings.getFormattedString("searchResults.sorryMessage", [query]);
-
         let brandName = document.getElementById("bundleBrand").getString("brandShortName");
         document.getElementById("need-help").innerHTML =
           strings.getFormattedString("searchResults.needHelp", [brandName]);
-
-        document.getElementById("need-help-link").setAttribute("href", getHelpLinkURL("search"));
       }
     } else {
       this.searchResultsCategory.hidden = true;
       document.getElementById("sorry-message").textContent = "";
       // Going back to General when cleared
       gotoPref("paneGeneral");
     }
   },
--- a/browser/components/preferences/in-content/main.xul
+++ b/browser/components/preferences/in-content/main.xul
@@ -198,17 +198,16 @@
 #endif
 </preferences>
 
 <hbox id="header-general"
       class="header"
       hidden="true"
       data-category="paneGeneral">
   <label class="header-name" flex="1">&paneGeneral.title;</label>
-  <html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a>
 </hbox>
 
 <!-- Startup -->
 <groupbox id="startupGroup"
           data-category="paneGeneral"
           hidden="true">
   <caption><label>&startup.label;</label></caption>
 
--- a/browser/components/preferences/in-content/preferences.js
+++ b/browser/components/preferences/in-content/preferences.js
@@ -81,39 +81,45 @@ function init_all() {
   init_dynamic_padding();
 
   var initFinished = new CustomEvent("Initialized", {
     "bubbles": true,
     "cancelable": true
   });
   document.dispatchEvent(initFinished);
 
-  categories = categories.querySelectorAll("richlistitem.category");
-  for (let category of categories) {
-    let name = internalPrefCategoryNameToFriendlyName(category.value);
-    let helpSelector = `#header-${name} > .help-button`;
-    let helpButton = document.querySelector(helpSelector);
-    helpButton.setAttribute("href", getHelpLinkURL(category.getAttribute("helpTopic")));
-  }
-
   // Wait until initialization of all preferences are complete before
   // notifying observers that the UI is now ready.
   Services.obs.notifyObservers(window, "advanced-pane-loaded");
 }
 
 // Make the space above the categories list shrink on low window heights
 function init_dynamic_padding() {
   let categories = document.getElementById("categories");
   let catPadding = Number.parseInt(getComputedStyle(categories)
                                      .getPropertyValue("padding-top"));
-  let fullHeight = categories.lastElementChild.getBoundingClientRect().bottom;
+  let helpButton = document.querySelector(".help-button");
+  let helpButtonCS = getComputedStyle(helpButton);
+  let helpHeight = Number.parseInt(helpButtonCS.height);
+  let helpBottom = Number.parseInt(helpButtonCS.bottom);
+  // Reduce the padding to account for less space, but due
+  // to bug 1357841, the status panel will overlap the link.
+  const reducedHelpButtonBottomFactor = .75;
+  let reducedHelpButtonBottom = helpBottom * reducedHelpButtonBottomFactor;
+  let fullHelpHeight = helpHeight + reducedHelpButtonBottom;
+  let fullHeight = categories.lastElementChild.getBoundingClientRect().bottom +
+                   fullHelpHeight;
   let mediaRule = `
   @media (max-height: ${fullHeight}px) {
     #categories {
       padding-top: calc(100vh - ${fullHeight - catPadding}px);
+      padding-bottom: ${fullHelpHeight}px;
+    }
+    .help-button {
+      bottom: ${reducedHelpButtonBottom / 2}px;
     }
   }
   `;
   let mediaStyle = document.createElementNS("http://www.w3.org/1999/xhtml", "html:style");
   mediaStyle.setAttribute("type", "text/css");
   mediaStyle.appendChild(document.createCDATASection(mediaRule));
   document.documentElement.appendChild(mediaStyle);
 }
@@ -157,16 +163,19 @@ function gotoPref(aCategory) {
   if (gLastHash == category && !subcategory)
     return;
   let item = categories.querySelector(".category[value=" + category + "]");
   if (!item) {
     category = kDefaultCategoryInternalName;
     item = categories.querySelector(".category[value=" + category + "]");
   }
 
+  let helpButton = document.querySelector(".help-button");
+  helpButton.setAttribute("href", getHelpLinkURL(item.getAttribute("helpTopic")));
+
   try {
     init_category_if_required(category);
   } catch (ex) {
     Cu.reportError("Error initializing preference category " + category + ": " + ex);
     throw ex;
   }
 
   let friendlyName = internalPrefCategoryNameToFriendlyName(category);
--- a/browser/components/preferences/in-content/preferences.xul
+++ b/browser/components/preferences/in-content/preferences.xul
@@ -163,16 +163,18 @@
 
     <keyset>
       <!-- Disable the findbar because it doesn't work properly.
            Remove this keyset once bug 1094240 ("disablefastfind" attribute
            broken in e10s mode) is fixed. -->
       <key key="&focusSearch1.key;" modifiers="accel" id="focusSearch1" oncommand=";"/>
     </keyset>
 
+    <html:a class="help-button" target="_blank" aria-label="&helpButton2.label;">&helpButton2.label;</html:a>
+
     <vbox class="main-content" flex="1">
       <hbox pack="end">
         <textbox type="search" id="searchInput" placeholder="&searchInput.label;" hidden="true"/>
       </hbox>
       <prefpane id="mainPrefPane">
 #include searchResults.xul
 #include main.xul
 #include privacy.xul
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -954,16 +954,37 @@ var gPrivacyPane = {
     if (!checkbox.checked)
       this._removeMasterPassword();
     else
       this.changeMasterPassword();
 
     this._initMasterPasswordUI();
   },
 
+  /**
+   * Displays the "remove master password" dialog to allow the user to remove
+   * the current master password.  When the dialog is dismissed, master password
+   * UI is automatically updated.
+   */
+  _removeMasterPassword() {
+    var secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].
+                   getService(Ci.nsIPKCS11ModuleDB);
+    if (secmodDB.isFIPSEnabled) {
+      var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
+                          getService(Ci.nsIPromptService);
+      var bundle = document.getElementById("bundlePreferences");
+      promptService.alert(window,
+                          bundle.getString("pw_change_failed_title"),
+                          bundle.getString("pw_change2empty_in_fips_mode"));
+      this._initMasterPasswordUI();
+    } else {
+      gSubDialog.open("chrome://mozapps/content/preferences/removemp.xul",
+                      null, null, this._initMasterPasswordUI.bind(this));
+    }
+  },
 
   /**
    * Displays a dialog in which the master password may be changed.
    */
   changeMasterPassword() {
     gSubDialog.open("chrome://mozapps/content/preferences/changemp.xul",
                     "resizable=no", null, this._initMasterPasswordUI.bind(this));
   },
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -172,17 +172,16 @@
 
 <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
 
 <hbox id="header-privacy"
       class="header"
       hidden="true"
       data-category="panePrivacy">
   <label class="header-name" flex="1">&panePrivacySecurity.title;</label>
-  <html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a>
 </hbox>
 
 
 <!-- History -->
 <groupbox id="historyGroup" data-category="panePrivacy" hidden="true">
   <caption><label>&history.label;</label></caption>
   <hbox align="center">
     <label id="historyModeLabel"
--- a/browser/components/preferences/in-content/searchResults.xul
+++ b/browser/components/preferences/in-content/searchResults.xul
@@ -4,15 +4,14 @@
 
 <stringbundle id="searchResultBundle" src="chrome://browser/locale/preferences/preferences.properties"/>
 
 <hbox id="header-searchResults"
       class="header"
       hidden="true"
       data-category="paneSearchResults">
   <label class="header-name" flex="1">&paneSearchResults.title;</label>
-  <html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a>
 </hbox>
 
 <groupbox class="no-results-message" align="start" data-category="paneSearchResults" hidden="true">
   <label id="sorry-message"></label>
   <label id="need-help"></label>
 </groupbox>
--- a/browser/components/preferences/in-content/sync.xul
+++ b/browser/components/preferences/in-content/sync.xul
@@ -28,17 +28,16 @@
 <script type="application/javascript"
         src="chrome://browser/content/preferences/in-content/sync.js"/>
 
 <hbox id="header-sync"
       class="header"
       hidden="true"
       data-category="paneSync">
   <label class="header-name" flex="1">&paneSync1.title;</label>
-  <html:a class="help-button text-link" target="_blank" aria-label="&helpButton.label;"></html:a>
 </hbox>
 
 <deck id="weavePrefsDeck" data-category="paneSync" hidden="true">
   <vbox id="noFxaAccount">
     <hbox>
       <vbox id="fxaContentWrapper">
         <groupbox id="noFxaGroup">
           <vbox>
--- a/browser/components/preferences/in-content/tests/browser.ini
+++ b/browser/components/preferences/in-content/tests/browser.ini
@@ -24,16 +24,17 @@ skip-if = os != "win" # This test tests 
 [browser_connection.js]
 [browser_connection_bug388287.js]
 [browser_cookies_exceptions.js]
 [browser_defaultbrowser_alwayscheck.js]
 [browser_healthreport.js]
 skip-if = true || !healthreport # Bug 1185403 for the "true"
 [browser_homepages_filter_aboutpreferences.js]
 [browser_layersacceleration.js]
+[browser_masterpassword.js]
 [browser_notifications_do_not_disturb.js]
 [browser_permissions_urlFieldHidden.js]
 [browser_proxy_backup.js]
 [browser_privacypane_1.js]
 [browser_privacypane_3.js]
 [browser_privacypane_4.js]
 [browser_privacypane_5.js]
 [browser_privacypane_8.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_masterpassword.js
@@ -0,0 +1,54 @@
+add_task(function*() {
+  let prefs = yield openPreferencesViaOpenPreferencesAPI("panePrivacy", {leaveOpen: true});
+  is(prefs.selectedPane, "panePrivacy", "Privacy pane was selected");
+
+  let doc = gBrowser.contentDocument;
+  // Fake the subdialog and LoginHelper
+  let win = doc.defaultView;
+  let dialogURL = "";
+  win.gSubDialog = {
+    open(aDialogURL, unused, unused2, aCallback) {
+      dialogURL = aDialogURL;
+      masterPasswordSet = masterPasswordNextState;
+      aCallback();
+    }
+  };
+  let masterPasswordSet = false;
+  win.LoginHelper = {
+    isMasterPasswordSet() {
+      return masterPasswordSet;
+    }
+  };
+
+  let checkbox = doc.querySelector("#useMasterPassword");
+  ok(!checkbox.checked, "master password checkbox should be unchecked by default");
+  let button = doc.getElementById("changeMasterPassword");
+  ok(button.disabled, "master password button should be disabled by default");
+
+  let masterPasswordNextState = true;
+  checkbox.click();
+  is(dialogURL,
+     "chrome://mozapps/content/preferences/changemp.xul",
+     "clicking on the checkbox should open the masterpassword dialog");
+  ok(!button.disabled, "master password button should now be enabled");
+  ok(checkbox.checked, "master password checkbox should be checked now");
+
+  dialogURL = "";
+  button.doCommand();
+  is(dialogURL,
+     "chrome://mozapps/content/preferences/changemp.xul",
+     "clicking on the button should open the masterpassword dialog");
+  ok(!button.disabled, "master password button should still be enabled");
+  ok(checkbox.checked, "master password checkbox should be checked still");
+
+  masterPasswordNextState = false;
+  dialogURL = "";
+  checkbox.click();
+  is(dialogURL,
+     "chrome://mozapps/content/preferences/removemp.xul",
+     "clicking on the checkbox to uncheck master password should show the removal dialog");
+  ok(button.disabled, "master password button should now be disabled");
+  ok(!checkbox.checked, "master password checkbox should now be unchecked");
+
+  yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
--- a/browser/locales/en-US/chrome/browser/preferences/preferences.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/preferences.dtd
@@ -18,11 +18,11 @@
 <!ENTITY  paneFilesApplications.title   "Files &amp; Applications">
 <!ENTITY  panePrivacySecurity.title     "Privacy &amp; Security">
 <!ENTITY  paneContainers.title          "Container Tabs">
 <!ENTITY  paneUpdates.title             "Updates">
 
 <!-- LOCALIZATION NOTE (paneSync1.title): This should match syncBrand.fxAccount.label in ../syncBrand.dtd -->
 <!ENTITY  paneSync1.title          "Firefox Account">
 
-<!ENTITY  helpButton.label        "Help">
+<!ENTITY  helpButton2.label        "&brandShortName; Support">
 
-<!ENTITY searchInput.label        "Search">
+<!ENTITY  searchInput.label        "Search">
--- a/browser/themes/shared/incontentprefs/preferences.inc.css
+++ b/browser/themes/shared/incontentprefs/preferences.inc.css
@@ -96,16 +96,19 @@ treecol {
 #category-search-results > .category-icon {
   list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#searchResults");
 }
 
 @media (max-width: 800px) {
   .category-name {
     display: none;
   }
+  .help-button {
+    font-size: 0 !important;
+  }
 }
 
 /* header */
 .header {
   display: flex;
   align-items: center;
   justify-content: space-between;
 }
@@ -559,8 +562,34 @@ description > html|a {
   }
   .iOSLink {
     background-image: url("chrome://browser/skin/fxa/ios@2x.png");
   }
   .fxaFirefoxLogo {
     list-style-image: url(chrome://browser/skin/fxa/logo@2x.png);
   }
 }
+
+.help-button {
+  position: fixed;
+  left: 0;
+  /* Needs to have enough gap from the bottom to not
+     get behind the status panel (bug 1357841). */
+  bottom: 2rem;
+  font-size: 13px;
+  line-height: 13px;
+  height: 14px;
+  background-position: 15px;
+  padding-inline-start: 35px;
+  white-space: nowrap;
+}
+
+.help-button:-moz-locale-dir(rtl) {
+  left: auto;
+  right: 0;
+  background-position: right 15px top 0;
+}
+
+.help-button:link,
+.help-button:visited {
+  color: var(--in-content-category-text);
+  text-decoration: none;
+}
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -962,13 +962,15 @@ def wrap_system_includes(target, visibil
 
 set_define('HAVE_VISIBILITY_HIDDEN_ATTRIBUTE',
            depends(visibility_flags)(lambda v: bool(v) or None))
 set_define('HAVE_VISIBILITY_ATTRIBUTE',
            depends(visibility_flags)(lambda v: bool(v) or None))
 set_config('WRAP_SYSTEM_INCLUDES', wrap_system_includes)
 set_config('VISIBILITY_FLAGS', visibility_flags)
 
-@depends(target)
-def is_windows(target):
-    return target.kernel == 'WINNT'
+# We only want to include windows.configure when we are compiling on
+# Windows, for Windows.
+@depends(target, host)
+def is_windows(target, host):
+    return host.kernel == 'WINNT' and target.kernel == 'WINNT'
 
 include('windows.configure', when=is_windows)
--- a/dom/plugins/test/reftest/reftest-stylo.list
+++ b/dom/plugins/test/reftest/reftest-stylo.list
@@ -8,20 +8,20 @@ fails == plugin-sanity.html plugin-sanit
 # fuzzy because of anti-aliasing in dashed border
 == border-padding-1.html border-padding-1.html
 == border-padding-2.html border-padding-2.html
 == border-padding-3.html border-padding-3.html
 # The following two "pluginproblemui-direction" tests are unreliable on all platforms. They should be re-written or replaced.
 random-if(cocoaWidget||d2d||/^Windows\x20NT\x205\.1/.test(http.oscpu)) fails-if(!haveTestPlugin&&!Android) skip-if(stylo) == pluginproblemui-direction-1.html pluginproblemui-direction-1.html
 random-if(cocoaWidget) fails-if(!haveTestPlugin&&!Android) skip-if(stylo) == pluginproblemui-direction-2.html pluginproblemui-direction-2.html
 == plugin-canvas-alpha-zindex.html plugin-canvas-alpha-zindex.html
-fails == plugin-transform-alpha-zindex.html plugin-transform-alpha-zindex.html
+== plugin-transform-alpha-zindex.html plugin-transform-alpha-zindex.html
 == plugin-busy-alpha-zindex.html plugin-busy-alpha-zindex.html
 == plugin-background.html plugin-background.html
 == plugin-background-1-step.html plugin-background-1-step.html
 == plugin-background-2-step.html plugin-background-2-step.html
 == plugin-background-5-step.html plugin-background-5-step.html
 == plugin-background-10-step.html plugin-background-10-step.html
 == plugin-transform-1.html plugin-transform-1.html
-fails == plugin-transform-2.html plugin-transform-2.html
+== plugin-transform-2.html plugin-transform-2.html
 == shrink-1.html shrink-1.html
 == update-1.html update-1.html
 skip-if(!haveTestPlugin) == windowless-layers.html windowless-layers.html
--- a/gfx/layers/LayerMetricsWrapper.h
+++ b/gfx/layers/LayerMetricsWrapper.h
@@ -349,28 +349,16 @@ public:
     MOZ_ASSERT(IsValid());
 
     if (AtBottomLayer()) {
       return mLayer->AsRefLayer();
     }
     return nullptr;
   }
 
-  LayerIntRegion GetVisibleRegion() const
-  {
-    MOZ_ASSERT(IsValid());
-
-    if (AtBottomLayer()) {
-      return mLayer->GetVisibleRegion();
-    }
-    LayerIntRegion region = mLayer->GetVisibleRegion();
-    region.Transform(mLayer->GetTransform());
-    return region;
-  }
-
   Maybe<ParentLayerIntRect> GetClipRect() const
   {
     MOZ_ASSERT(IsValid());
 
     Maybe<ParentLayerIntRect> result;
 
     // The layer can have a clip rect and a scrolled clip, which are considered
     // to apply only to the bottommost LayerMetricsWrapper.
@@ -461,44 +449,16 @@ public:
         && mIndex == aOther.mIndex;
   }
 
   bool operator!=(const LayerMetricsWrapper& aOther) const
   {
     return !(*this == aOther);
   }
 
-  static const FrameMetrics& TopmostScrollableMetrics(Layer* aLayer)
-  {
-    for (uint32_t i = aLayer->GetScrollMetadataCount(); i > 0; i--) {
-      if (aLayer->GetFrameMetrics(i - 1).IsScrollable()) {
-        return aLayer->GetFrameMetrics(i - 1);
-      }
-    }
-    return ScrollMetadata::sNullMetadata->GetMetrics();
-  }
-
-  static const FrameMetrics& BottommostScrollableMetrics(Layer* aLayer)
-  {
-    for (uint32_t i = 0; i < aLayer->GetScrollMetadataCount(); i++) {
-      if (aLayer->GetFrameMetrics(i).IsScrollable()) {
-        return aLayer->GetFrameMetrics(i);
-      }
-    }
-    return ScrollMetadata::sNullMetadata->GetMetrics();
-  }
-
-  static const FrameMetrics& BottommostMetrics(Layer* aLayer)
-  {
-    if (aLayer->GetScrollMetadataCount() > 0) {
-      return aLayer->GetFrameMetrics(0);
-    }
-    return ScrollMetadata::sNullMetadata->GetMetrics();
-  }
-
 private:
   bool AtBottomLayer() const
   {
     return mIndex == 0;
   }
 
   bool AtTopLayer() const
   {
--- a/layout/reftests/backgrounds/reftest-stylo.list
+++ b/layout/reftests/backgrounds/reftest-stylo.list
@@ -127,17 +127,17 @@ fails == background-size-monster-rem.htm
 # the image aren't the issue, because they're being obscured to avoid sampling
 # algorithm dependencies (at least assuming the sampling algorithm in use
 # doesn't sample too far astray from the boundaries).
 == background-size-zoom-repeat.html background-size-zoom-repeat.html
 
 # -moz-default-background-color and -moz-default-color (bug 591341)
 == background-moz-default-background-color.html background-moz-default-background-color.html
 
-fails == fixed-bg-with-transform-outside-viewport-1.html fixed-bg-with-transform-outside-viewport-1.html
+== fixed-bg-with-transform-outside-viewport-1.html fixed-bg-with-transform-outside-viewport-1.html
 fuzzy(2,83) == fixed-bg-border-radius.html fixed-bg-border-radius.html
 
 HTTP == root-background-1.html root-background-1.html
 HTTP == root-background-1.html root-background-1.html
 
 fails == really-big-background.html really-big-background.html # Bug 1341690
 == body-background.html body-background.html # Bug 1339711
 == table-background.html table-background.html # Bug 1339711
--- a/layout/reftests/bugs/reftest-stylo.list
+++ b/layout/reftests/bugs/reftest-stylo.list
@@ -1190,18 +1190,18 @@ fails pref(dom.use_xbl_scopes_for_remote
 == 451168-1.html 451168-1.html
 == 451876-1.html 451876-1.html
 == 451876-2.html 451876-2.html
 == 452915-1.html 452915-1.html
 == 452964-1.html 452964-1.html
 == 454361.html 454361.html
 == 455105-1.html 455105-1.html
 == 455105-2.html 455105-2.html
-fails == 455171-5.html 455171-5.html
-fails == 455280-1.xhtml 455280-1.xhtml
+== 455171-5.html 455171-5.html
+== 455280-1.xhtml 455280-1.xhtml
 fails == 455826-1.html 455826-1.html
 fails-if(cocoaWidget) fails-if(Android) == 456147.xul 456147.xul
 == 456219-1a.html 456219-1a.html
 == 456219-1b.html 456219-1b.html
 == 456219-1c.html 456219-1c.html
 == 456219-2.html 456219-2.html
 fails == 456330-1.gif 456330-1.gif
 == 456484-1.html 456484-1.html
@@ -1250,20 +1250,20 @@ fails == 467460-1.html 467460-1.html
 == 468473-1.xul 468473-1.xul
 fails == 468546-1.xhtml 468546-1.xhtml
 == 471356-1.html 471356-1.html
 == 471594-1.xhtml 471594-1.xhtml
 fuzzy(255,15) == 472020-1a.xul 472020-1a.xul
 == 472020-1b.xul 472020-1b.xul
 == 472020-2.xul 472020-2.xul
 == 472500-1.xul 472500-1.xul
-fails == 472769-1a.html 472769-1a.html
+== 472769-1a.html 472769-1a.html
 == 472769-1b.html 472769-1b.html
-fails == 472769-2.html 472769-2.html
-fails == 472769-3.html 472769-3.html
+== 472769-2.html 472769-2.html
+== 472769-3.html 472769-3.html
 == 473847-1.xul 473847-1.xul
 fuzzy-if(skiaContent,1,16) == 474336-1.xul 474336-1.xul
 fails == 474417-1.html 474417-1.html
 == 474472-1.html 474472-1.html
 == 475986-1a.html 475986-1a.html
 == 475986-1b.html 475986-1b.html
 == 475986-1c.html 475986-1c.html
 == 475986-1d.html 475986-1d.html
@@ -1281,20 +1281,20 @@ fails == 474417-1.html 474417-1.html
 == 475986-1-ref.html 475986-1-ref.html
 == 475986-1-ref.html 475986-1-ref.html
 == 475986-2-ref.html 475986-2-ref.html
 == 476063-1.html 476063-1.html
 == 476063-2.html 476063-2.html
 == 476063-3.html 476063-3.html
 == 476063-4.xhtml 476063-4.xhtml
 == 476357-1.html 476357-1.html
-fails == 476598-1a.html 476598-1a.html # Bug 1341785
-fails == 476598-1a.html 476598-1a.html # Bug 1341785
-fails == 476598-1b.html 476598-1b.html # Bug 1341785
-fails == 476598-1b.html 476598-1b.html # Bug 1341785
+== 476598-1a.html 476598-1a.html # Bug 1341785
+== 476598-1a.html 476598-1a.html # Bug 1341785
+== 476598-1b.html 476598-1b.html # Bug 1341785
+== 476598-1b.html 476598-1b.html # Bug 1341785
 == 476598-1-ref.html 476598-1-ref.html
 == 476856-1.html 476856-1.html
 random-if(d2d) == 478377-1.xul 478377-1.xul
 == 478614-1.html 478614-1.html
 == 478614-2.html 478614-2.html
 == 478614-3.html 478614-3.html
 == 478614-4.html 478614-4.html
 == 478614-5.html 478614-5.html
@@ -1329,17 +1329,17 @@ fails == 482592-1b.xhtml 482592-1b.xhtml
 == 482659-1a.html 482659-1a.html
 == 482659-1b.html 482659-1b.html
 == 482659-1c.html 482659-1c.html
 == 482659-1d.html 482659-1d.html
 == 483565.xul 483565.xul
 == 484256-1.html 484256-1.html
 == 484256-2.html 484256-2.html
 == 485012-1.html 485012-1.html
-fails == 485275-1.html 485275-1.html
+== 485275-1.html 485275-1.html
 == 485275-1.svg 485275-1.svg
 == 486052-1.html 486052-1.html
 == 486052-2a.html 486052-2a.html
 == 486052-2b.html 486052-2b.html
 == 486052-2c.html 486052-2c.html
 == 486052-2d.html 486052-2d.html
 == 486052-2e.html 486052-2e.html
 == 486052-2f.html 486052-2f.html
@@ -1423,20 +1423,20 @@ fails == 512410.html 512410.html
 == 512631-1.html 512631-1.html
 fails == 513153-1a.html 513153-1a.html
 fails == 513153-1b.html 513153-1b.html
 fails == 513153-2a.html 513153-2a.html
 fails == 513153-2b.html 513153-2b.html
 == 513318-1.xul 513318-1.xul
 fails-if(Android&&(!asyncPan)) == 513318-2.xul 513318-2.xul
 == 514917-1.html 514917-1.html
-fails HTTP(..) == 518172-1a.html 518172-1a.html
-fails == 518172-1b.html 518172-1b.html
-fails HTTP(..) == 518172-2a.html 518172-2a.html
-fails == 518172-2b.html 518172-2b.html
+HTTP(..) == 518172-1a.html 518172-1a.html
+== 518172-1b.html 518172-1b.html
+HTTP(..) == 518172-2a.html 518172-2a.html
+== 518172-2b.html 518172-2b.html
 == 520421-1.html 520421-1.html
 == 520563-1.xhtml 520563-1.xhtml
 == 521525-1.html 521525-1.html
 == 521525-2.html 521525-2.html
 fails == 521539-1.html 521539-1.html
 == 521542-1.xhtml 521542-1.xhtml
 == 521602.html 521602.html
 == 521685-1.html 521685-1.html
@@ -1479,17 +1479,17 @@ fails == 538909-1.html 538909-1.html
 fails == 539949-1.html#test2 539949-1-ref.html#test2
 fails == 541382-1.html 541382-1.html
 == 541406-1.html 541406-1.html
 needs-focus == 542116-1.html 542116-1.html
 needs-focus == 542116-2.html 542116-2.html
 needs-focus == 542116-3.html 542116-3.html
 == 542317-1.html 542317-1.html
 == 542620-1.html 542620-1.html
-fails == 545049-1.html 545049-1.html # Bug 1341785
+== 545049-1.html 545049-1.html # Bug 1341785
 == 546033-1.html 546033-1.html
 == 546071-1.html 546071-1.html
 == 549184-1.html 549184-1.html
 == 550325-1.html 550325-1.html
 == 550325-2.html 550325-2.html
 == 550325-3.html 550325-3.html
 == 550716-1.html 550716-1.html
 fails == 551463-1.html 551463-1.html
@@ -1611,50 +1611,50 @@ skip-if(stylo) == 598726-1.html 598726-1
 == 600045-1.html 600045-1.html
 fails == 600803-1.html 600803-1.html
 == 600974-1.html 600974-1.html
 == 600974-2.html 600974-2.html
 == 600974-3.html 600974-3.html
 == 602200-1.html 602200-1.html
 == 602200-2.html 602200-2.html
 fuzzy-if(Android,8,20) == 602200-3.html 602200-3.html
-fails == 602200-4.html 602200-4.html
+== 602200-4.html 602200-4.html
 == 603423-1.html 603423-1.html
 fails == 604737.html 604737.html
 fails == 605138-1.html 605138-1.html
 == 605157-1.xhtml 605157-1.xhtml
 == 607267-1.html 607267-1.html
-fails == 608636-1.html 608636-1.html
+== 608636-1.html 608636-1.html
 == 608756-1a.html 608756-1a.html
 == 608756-1b.html 608756-1b.html
 == 608756-2.html 608756-2.html
 == 609272-1.html 609272-1.html
 == 613433-1.html 613433-1.html
 == 613433-1.html 613433-1.html
 == 613433-1.html 613433-1.html
 == 613433-2.html 613433-2.html
 == 613433-2.html 613433-2.html
 == 613433-2.html 613433-2.html
 == 613433-3.html 613433-3.html
 == 613433-3.html 613433-3.html
 == 613433-3.html 613433-3.html
 == 614272-1.svg 614272-1.svg
 HTTP(..) == 615121-1.html 615121-1.html
 HTTP(..) == 615121-2.html 615121-2.html
-fails == 617242-1.html 617242-1.html
+== 617242-1.html 617242-1.html
 fails == 618071.html 618071.html
 == 619117-1.html 619117-1.html
 HTTP(..) == 619511-1.html 619511-1.html
 == 621253-1-externalFilter.html 621253-1-externalFilter.html
 == 621253-1-internalFilter.html 621253-1-internalFilter.html
 HTTP(..) == 621253-2-externalFilter.html 621253-2-externalFilter.html
 == 621253-2-internalFilter.html 621253-2-internalFilter.html
 random-if(winWidget) fuzzy-if(OSX==1008,19,17) == 621918-1.svg 621918-1.svg
 random-if(winWidget) HTTP(..) == 621918-2.svg 621918-2.svg
-fails == 622585-1.html 622585-1.html
+== 622585-1.html 622585-1.html
 == 625409-1.html 625409-1.html
 == 627393-1.html 627393-1.html
 fuzzy-if(skiaContent,1,500) == 630835-1.html 630835-1.html
 fails == 631352-1.html 631352-1.html
 == 632423-1.html 632423-1.html
 skip-if(Android) random-if(winWidget||OSX==1010) == 632781-verybig.html 632781-verybig.html
 == 632781-normalsize.html 632781-normalsize.html
 == 633344-1.html 633344-1.html
@@ -1662,34 +1662,34 @@ skip-if(Android) random-if(winWidget||OS
 skip-if(stylo) == 635302-1.html 635302-1.html # Too intermittent.
 == 635373-1.html 635373-1.html
 == 635373-2.html 635373-2.html
 == 635373-3.html 635373-3.html
 HTTP(..) == 635639-1.html 635639-1.html
 HTTP(..) == 635639-2.html 635639-2.html
 fails random == 637597-1.html 637597-1.html
 fails == 637852-1.html 637852-1.html
-fails == 637852-2.html 637852-2.html
-fails == 637852-3.html 637852-3.html
+== 637852-2.html 637852-2.html
+== 637852-3.html 637852-3.html
 fails == 641770-1.html 641770-1.html
 == 641856-1.html 641856-1.html
 fails == 645491-1.html 645491-1.html
 fails == 645647-1.html 645647-1.html
 == 645647-2.html 645647-2.html
 == 645768-1.html 645768-1.html
 == 650228-1.html 650228-1.html
 needs-focus == 652301-1a.html 652301-1a.html
 needs-focus == 652301-1b.html 652301-1b.html
 fails == 652775-1.html 652775-1.html
 == 653930-1.html 653930-1.html
 HTTP(..) == 654057-1.html 654057-1.html
-fails == 654950-1.html 654950-1.html
+== 654950-1.html 654950-1.html
 == 655549-1.html 655549-1.html
 == 655836-1.html 655836-1.html
-fails == 656875.html 656875.html
+== 656875.html 656875.html
 == 658952.html 658952.html
 == 660682-1.html 660682-1.html
 fuzzy-if(d2d,1,256) skip-if(Android) fuzzy-if(skiaContent,1,68000) == 664127-1.xul 664127-1.xul
 fails == 665597-1.html 665597-1.html
 == 665597-2.html 665597-2.html
 == 668319-1.xul 668319-1.xul
 == 669015-1.xul 669015-1.xul
 == 670442-1.html 670442-1.html
@@ -1727,17 +1727,17 @@ fails == 735481-1.html 735481-1.html
 == 748692-1b.html 748692-1b.html
 fails == 748803-1.html 748803-1.html
 == 750551-1.html 750551-1.html
 fails == 751012-1a.html 751012-1a.html
 fails == 751012-1b.html 751012-1b.html
 == 753329-1.html 753329-1.html
 == 758561-1.html 758561-1.html
 == 759036-1.html 759036-1.html
-fails == 759036-2.html 759036-2.html
+== 759036-2.html 759036-2.html
 fails == 776265-1a.html 776265-1a.html
 fails == 776265-1b.html 776265-1b.html
 fails == 776265-1c.html 776265-1c.html
 fails == 776265-1d.html 776265-1d.html
 fails == 776265-2a.html 776265-2a.html
 fails == 776265-2b.html 776265-2b.html
 fails == 776265-2c.html 776265-2c.html
 fails == 776265-2d.html 776265-2d.html
--- a/layout/reftests/font-inflation/reftest-stylo.list
+++ b/layout/reftests/font-inflation/reftest-stylo.list
@@ -32,17 +32,17 @@ fails pref(font.size.inflation.emPerLine
 fails pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) == input-text-2-height.html input-text-2-height.html
 fails pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) == input-text-2-noheight.html input-text-2-noheight.html
 fails pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) == input-text-3-height.html input-text-3-height.html
 fails pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) == input-text-3-noheight.html input-text-3-noheight.html
 fails pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) == textarea-1.html textarea-1.html
 fails pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) == textarea-2.html textarea-2.html
 fails pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) == textarea-3.html textarea-3.html
 pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) == css-transform-1.html css-transform-1.html
-fails pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) == css-transform-2.html css-transform-2.html
+pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) == css-transform-2.html css-transform-2.html
 fails == container-with-clamping.html container-with-clamping.html
 skip pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) load video-1.html
 fails pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-min-1.html intrinsic-min-1.html
 fails pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-max-1.html intrinsic-max-1.html
 fails pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-fit-1a.html intrinsic-fit-1a.html
 fails pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-fit-1b.html intrinsic-fit-1b.html
 pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-fit-1c.html intrinsic-fit-1c.html
 pref(font.size.inflation.emPerLine,15) pref(font.size.inflation.forceEnabled,true) pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-fit-2a.html intrinsic-fit-2a.html
--- a/layout/reftests/forms/meter/reftest-stylo.list
+++ b/layout/reftests/forms/meter/reftest-stylo.list
@@ -12,17 +12,17 @@ fails == bar-pseudo-element.html bar-pse
 == margin-padding-vertical.html margin-padding-vertical.html
 == margin-padding-vertical-rtl.html margin-padding-vertical-rtl.html
 fails == bar-pseudo-element-vertical.html bar-pseudo-element-vertical.html # Bug 1341095
 == bar-pseudo-element-vertical-rtl.html bar-pseudo-element-vertical-rtl.html
 
 # The following test is disabled but kept in the repository because the
 # transformations will not behave exactly the same for <meter> and two divs.
 # However, it would be possible to manually check those.
-fails == transformations.html transformations.html # Bug 1341785
+== transformations.html transformations.html # Bug 1341785
 
 # default style
 include default-style/reftest-stylo.list
 
 # Tests for bugs:
 == block-invalidate.html block-invalidate.html
 == in-cells.html in-cells.html
 fails == max-height.html max-height.html
--- a/layout/reftests/image-element/reftest-stylo.list
+++ b/layout/reftests/image-element/reftest-stylo.list
@@ -7,22 +7,22 @@ random == bug-364968.html bug-364968.htm
 == image-outside-document-invalidate.html image-outside-document-invalidate.html
 == canvas-outside-document-invalidate-01.html canvas-outside-document-invalidate-01.html
 == canvas-outside-document-invalidate-02.html canvas-outside-document-invalidate-02.html
 #fails with Skia due to Skia bug http://code.google.com/p/skia/issues/detail?id=568
 == element-paint-simple.html element-paint-simple.html # Bug 1341761
 == element-paint-repeated.html element-paint-repeated.html
 == element-paint-recursion.html element-paint-recursion.html
 HTTP(..) == element-paint-continuation.html element-paint-continuation.html
-fails == element-paint-transform-01.html element-paint-transform-01.html
-fails == element-paint-transform-02.html element-paint-transform-02.html
+== element-paint-transform-01.html element-paint-transform-01.html
+== element-paint-transform-02.html element-paint-transform-02.html
 == element-paint-background-size-01.html element-paint-background-size-01.html
 == element-paint-background-size-02.html element-paint-background-size-02.html
-fails == element-paint-transform-repeated.html element-paint-transform-repeated.html
-fails == element-paint-transform-03.html element-paint-transform-03.html
+== element-paint-transform-repeated.html element-paint-transform-repeated.html
+== element-paint-transform-03.html element-paint-transform-03.html
 fails == element-paint-native-widget.html element-paint-native-widget.html
 fails-if(usesRepeatResampling) == element-paint-subimage-sampling-restriction.html element-paint-subimage-sampling-restriction.html
 == element-paint-clippath.html element-paint-clippath.html
 == element-paint-sharpness-01a.html element-paint-sharpness-01a.html
 fuzzy-if(skiaContent,1,326) == element-paint-sharpness-01b.html element-paint-sharpness-01b.html
 == element-paint-sharpness-01c.html element-paint-sharpness-01c.html
 == element-paint-sharpness-02a.html element-paint-sharpness-02a.html
 == element-paint-sharpness-02b.html element-paint-sharpness-02b.html
@@ -39,10 +39,10 @@ random-if(!cocoaWidget) == gradient-html
 fuzzy(1,9674) random-if(!cocoaWidget) == gradient-html-06a.html gradient-html-06a.html
 fuzzy(1,9674) random-if(!cocoaWidget) == gradient-html-06b.html gradient-html-06b.html
 == gradient-html-06c.html gradient-html-06c.html
 == gradient-html-06d.html gradient-html-06d.html
 random-if(!cocoaWidget) fuzzy-if(cocoaWidget,2,42305) == gradient-html-07a.html gradient-html-07a.html
 == gradient-html-07c.html gradient-html-07c.html
 HTTP == invalidate-1.html invalidate-1.html
 == pattern-html-01.html pattern-html-01.html
-fails == pattern-html-02.html pattern-html-02.html
+== pattern-html-02.html pattern-html-02.html
 == referenced-from-binding-01.html referenced-from-binding-01.html
--- a/layout/reftests/invalidation/reftest-stylo.list
+++ b/layout/reftests/invalidation/reftest-stylo.list
@@ -1,17 +1,17 @@
 == table-repaint-a.html table-repaint-a.html
 == table-repaint-b.html table-repaint-b.html
 == table-repaint-c.html table-repaint-c.html
 == table-repaint-d.html table-repaint-d.html
 == 540247-1.xul 540247-1.xul
 fails == 543681-1.html 543681-1.html
 fails-if(stylo&&!browserIsRemote) == 1243409-1.html 1243409-1.html
-fails == test-image-layers.html test-image-layers.html
-fails == test-image-layers-multiple-displayitem.html test-image-layers-multiple-displayitem.html
+== test-image-layers.html test-image-layers.html
+== test-image-layers-multiple-displayitem.html test-image-layers-multiple-displayitem.html
 pref(layout.animated-image-layers.enabled,true) skip-if(Android||gtkWidget) == test-animated-image-layers.html test-animated-image-layers.html
 skip-if(stylo) == test-animated-image-layers-background.html test-animated-image-layers-background.html
 == box-shadow-border-radius.html box-shadow-border-radius.html
 == filter-userspace-offset.svg?offsetContainer=rect filter-userspace-offset.svg?offsetContainer=rect
 == filter-userspace-offset.svg?offsetContainer=use filter-userspace-offset.svg?offsetContainer=use
 == filter-userspace-offset.svg?offsetContainer=innerSVG filter-userspace-offset.svg?offsetContainer=innerSVG
 == filter-userspace-offset.svg?offsetContainer=foreignObject filter-userspace-offset.svg?offsetContainer=foreignObject
 == filter-userspace-offset.svg?offsetContainer=rect&filter=flood-boundingBox filter-userspace-offset.svg?offsetContainer=rect&filter=flood-boundingBox
--- a/layout/reftests/transform-3d/reftest-stylo.list
+++ b/layout/reftests/transform-3d/reftest-stylo.list
@@ -1,67 +1,67 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
-fails == scalez-1a.html scalez-1a.html
-fails == rotatey-1a.html rotatey-1a.html
-fails == rotatex-1a.html rotatex-1a.html
+== scalez-1a.html scalez-1a.html
+== rotatey-1a.html rotatey-1a.html
+== rotatex-1a.html rotatex-1a.html
 # Check that scaleZ(-1) rotateX(180deg) is the same as rotateY(180deg)
-fails == scalezrotatex-1.html scalezrotatex-1.html
+== scalezrotatex-1.html scalezrotatex-1.html
 # Check that the perspectve() transform function results in some visual changes
-fails == rotatex-perspective-1a.html rotatex-perspective-1a.html
+== rotatex-perspective-1a.html rotatex-perspective-1a.html
 # Check that -moz-perspective results in visual changes to child transformed elements
-fails == rotatex-perspective-1b.html rotatex-perspective-1b.html
+== rotatex-perspective-1b.html rotatex-perspective-1b.html
 # -moz-perspective should only apply to child elements
-fails == rotatex-perspective-1c.html rotatex-perspective-1c.html
-fails == rotatex-perspective-3a.html rotatex-perspective-3a.html
-fails == scalez-1a.html scalez-1a.html
-fails == preserve3d-1a.html preserve3d-1a.html
-fails == preserve3d-1b.html preserve3d-1b.html
-fails == preserve3d-clipped.html preserve3d-clipped.html
-fails == preserve3d-2a.html preserve3d-2a.html
-fails == preserve3d-2b.html preserve3d-2b.html
-fails == preserve3d-2c.html preserve3d-2c.html
+== rotatex-perspective-1c.html rotatex-perspective-1c.html
+== rotatex-perspective-3a.html rotatex-perspective-3a.html
+== scalez-1a.html scalez-1a.html
+== preserve3d-1a.html preserve3d-1a.html
+== preserve3d-1b.html preserve3d-1b.html
+== preserve3d-clipped.html preserve3d-clipped.html
+== preserve3d-2a.html preserve3d-2a.html
+== preserve3d-2b.html preserve3d-2b.html
+== preserve3d-2c.html preserve3d-2c.html
 == preserve3d-2d.html preserve3d-2d.html
-fails == preserve3d-3a.html preserve3d-3a.html
-fails == preserve3d-4a.html preserve3d-4a.html
-fails == preserve3d-5a.html preserve3d-5a.html
+== preserve3d-3a.html preserve3d-3a.html
+== preserve3d-4a.html preserve3d-4a.html
+== preserve3d-5a.html preserve3d-5a.html
 == preserve3d-6a.html preserve3d-6a.html
-fails == scale3d-z.html scale3d-z.html
-fails == scale3d-all.html scale3d-all.html
-fails == scale3d-all-separate.html scale3d-all-separate.html
-fails == scale3d-xz.html scale3d-xz.html
-fails == translatez-1a.html translatez-1a.html
-fails == translatez-1b.html translatez-1b.html
-fails == translate3d-1a.html translate3d-1a.html
-fails == matrix3d-1a.html matrix3d-1a.html
-fails == matrix3d-2a.html matrix3d-2a.html
-fails == rotate3d-1a.html rotate3d-1a.html
-fails == rotate3d-2a.html rotate3d-2a.html
-fails == backface-visibility-1a.html backface-visibility-1a.html
-fails == backface-visibility-1b.html backface-visibility-1b.html
-fails == backface-visibility-1c.html backface-visibility-1c.html
-fails == backface-visibility-2.html backface-visibility-2.html
+== scale3d-z.html scale3d-z.html
+== scale3d-all.html scale3d-all.html
+== scale3d-all-separate.html scale3d-all-separate.html
+== scale3d-xz.html scale3d-xz.html
+== translatez-1a.html translatez-1a.html
+== translatez-1b.html translatez-1b.html
+== translate3d-1a.html translate3d-1a.html
+== matrix3d-1a.html matrix3d-1a.html
+== matrix3d-2a.html matrix3d-2a.html
+== rotate3d-1a.html rotate3d-1a.html
+== rotate3d-2a.html rotate3d-2a.html
+== backface-visibility-1a.html backface-visibility-1a.html
+== backface-visibility-1b.html backface-visibility-1b.html
+== backface-visibility-1c.html backface-visibility-1c.html
+== backface-visibility-2.html backface-visibility-2.html
 == backface-visibility-3.html backface-visibility-3.html
 == perspective-clipping-1.html perspective-clipping-1.html
-fails == perspective-origin-1a.html perspective-origin-1a.html
-fails == perspective-origin-1b.html perspective-origin-1b.html
-fails == perspective-origin-2a.html perspective-origin-2a.html
+== perspective-origin-1a.html perspective-origin-1a.html
+== perspective-origin-1b.html perspective-origin-1b.html
+== perspective-origin-2a.html perspective-origin-2a.html
 == perspective-origin-3a.html perspective-origin-3a.html
-fails == perspective-origin-4a.html perspective-origin-4a.html
+== perspective-origin-4a.html perspective-origin-4a.html
 == perspective-zindex.html perspective-zindex.html
 == perspective-zindex-2.html perspective-zindex-2.html
 fails == sorting-1a.html sorting-1a.html
 # Parallel planes, different z depth
-fails == sorting-2a.html sorting-2a.html
+== sorting-2a.html sorting-2a.html
 # Parallel planes, same z depth (shouldn't be sorted!)
-fails == sorting-2b.html sorting-2b.html
-fails == sorting-3a.html sorting-3a.html
+== sorting-2b.html sorting-2b.html
+== sorting-3a.html sorting-3a.html
 # Different, but equivalent (for the given transform) transform origins
-fails == rotatex-transformorigin-1a.html rotatex-transformorigin-1a.html
-fails == overflow-hidden-1a.html overflow-hidden-1a.html
-fails == transform-style-flat-1a.html transform-style-flat-1a.html
+== rotatex-transformorigin-1a.html rotatex-transformorigin-1a.html
+== overflow-hidden-1a.html overflow-hidden-1a.html
+== transform-style-flat-1a.html transform-style-flat-1a.html
 fails == willchange-containing-block.html?willchange willchange-containing-block.html?willchange
 fails == willchange-containing-block.html?willchange willchange-containing-block.html?willchange
 fails == scroll-perspective-1.html scroll-perspective-1.html
 # Bugs
 == 1035611-1.html 1035611-1.html
 == 1157984-1.html 1157984-1.html
 fails == animate-cube-radians.html animate-cube-radians.html
 fails == animate-cube-radians-zoom.html animate-cube-radians-zoom.html
--- a/layout/reftests/transform/reftest-stylo.list
+++ b/layout/reftests/transform/reftest-stylo.list
@@ -1,37 +1,37 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 # Transforms specifying singular matrices shouldn't display at all.
 # NOTE: Regressions might manifest themselves as reftest timeouts on
 # this test.
-fails == singular-1a.html singular-1a.html
+== singular-1a.html singular-1a.html
 # Multiple transforms should act identically to nested divs.
-fails == compound-1a.html compound-1a.html # Bug 1341785
-fails == compound-1a.html compound-1a.html # Bug 1341785
-fails == dynamic-inherit-1.html dynamic-inherit-1.html # Bug 1341785
+== compound-1a.html compound-1a.html # Bug 1341785
+== compound-1a.html compound-1a.html # Bug 1341785
+== dynamic-inherit-1.html dynamic-inherit-1.html # Bug 1341785
 == dynamic-addremove-1a.html dynamic-addremove-1a.html
 == dynamic-addremove-1b.html dynamic-addremove-1b.html
 == dynamic-addremove-1c.html dynamic-addremove-1c.html
 == dynamic-addremove-2.html dynamic-addremove-2.html
 # translatex should act like position: relative
 fails == translatex-1a.html translatex-1a.html # Bug 1341785
 fails == translatex-1b.html translatex-1b.html
 fails == translatex-1c.html translatex-1c.html
 fails == translatex-1d.html translatex-1d.html
 fails == translatex-1e.html translatex-1e.html
 fails == translatex-1a.html translatex-1a.html # Bug 1341785
 # translatey should act like position: relative
-fails == translatey-1a.html translatey-1a.html
-fails == translatey-1b.html translatey-1b.html
-fails == translatey-1c.html translatey-1c.html
-fails == translatey-1d.html translatey-1d.html
-fails == translatey-1e.html translatey-1e.html
+== translatey-1a.html translatey-1a.html
+== translatey-1b.html translatey-1b.html
+== translatey-1c.html translatey-1c.html
+== translatey-1d.html translatey-1d.html
+== translatey-1e.html translatey-1e.html
 # matrices defined to be translations should act like position: relative
 fails == translatex-2.html translatex-2.html
-fails == translatey-2.html translatey-2.html
+== translatey-2.html translatey-2.html
 # translate should act like position: relative
 fails == translate-1a.html translate-1a.html
 fails == translate-1b.html translate-1b.html
 fails == translate-1c.html translate-1c.html
 fails == translate-1d.html translate-1d.html
 fails == translate-1e.html translate-1e.html
 fails == translate-2a.html translate-2a.html
 # rotate: Several rotations of the same object should be idempotent.  These
@@ -40,95 +40,95 @@ fails == translate-2a.html translate-2a.
 random == rotate-1a.html rotate-1a.html
 random == rotate-1b.html rotate-1b.html
 random == rotate-1c.html rotate-1c.html
 random == rotate-1d.html rotate-1d.html
 random == rotate-1e.html rotate-1e.html
 random == rotate-1f.html rotate-1f.html
 # rotate: 90deg rotations should be indistinguishable from objects constructed
 # to look the same.
-fails == rotate-2a.html rotate-2a.html
-fails == rotate-2b.html rotate-2b.html
+== rotate-2a.html rotate-2a.html
+== rotate-2b.html rotate-2b.html
 # -transform-origin: We should NOT get the same images when using different
 # -transform-origins.
-fails == origin-1a.html origin-1a.html
-fails == origin-1b.html origin-1b.html
+== origin-1a.html origin-1a.html
+== origin-1b.html origin-1b.html
 # -transform-origin: We should get the same images when using equivalent
 # -transform-origins.
-fails == origin-2a.html origin-2a.html
-fails == origin-2b.html origin-2b.html
-fails == origin-2c.html origin-2c.html
+== origin-2a.html origin-2a.html
+== origin-2b.html origin-2b.html
+== origin-2c.html origin-2c.html
 # "Translate" with percentages should be indistinguishable from translate with
 # equivalent values.
-fails == percent-1a.html percent-1a.html
-fails == percent-1b.html percent-1b.html
-fails == percent-1c.html percent-1c.html
-fails == percent-1d.html percent-1d.html
-fails == percent-1e.html percent-1e.html
-fails == percent-1f.html percent-1f.html
-fails == percent-1g.html percent-1g.html
+== percent-1a.html percent-1a.html
+== percent-1b.html percent-1b.html
+== percent-1c.html percent-1c.html
+== percent-1d.html percent-1d.html
+== percent-1e.html percent-1e.html
+== percent-1f.html percent-1f.html
+== percent-1g.html percent-1g.html
 # Transformed elements are abs-pos and fixed-pos containing blocks.
-fails == abspos-1a.html abspos-1a.html
-fails == abspos-1b.html abspos-1b.html
-fails == abspos-1c.html abspos-1c.html
-fails == abspos-1d.html abspos-1d.html
-fails == abspos-1e.html abspos-1e.html
-fails == abspos-1f.html abspos-1f.html
-fails == abspos-1g.html abspos-1g.html
+== abspos-1a.html abspos-1a.html
+== abspos-1b.html abspos-1b.html
+== abspos-1c.html abspos-1c.html
+== abspos-1d.html abspos-1d.html
+== abspos-1e.html abspos-1e.html
+== abspos-1f.html abspos-1f.html
+== abspos-1g.html abspos-1g.html
 # Origin can use "top" "right" etc.
-fails == origin-name-1a.html origin-name-1a.html
-fails == origin-name-1b.html origin-name-1b.html
-fails == origin-name-2a.html origin-name-2a.html
-fails == origin-name-2b.html origin-name-2b.html
-fails == origin-name-2c.html origin-name-2c.html
-fails == origin-name-3a.html origin-name-3a.html
-fails == origin-name-3b.html origin-name-3b.html
+== origin-name-1a.html origin-name-1a.html
+== origin-name-1b.html origin-name-1b.html
+== origin-name-2a.html origin-name-2a.html
+== origin-name-2b.html origin-name-2b.html
+== origin-name-2c.html origin-name-2c.html
+== origin-name-3a.html origin-name-3a.html
+== origin-name-3b.html origin-name-3b.html
 # Snapping still applies after 90 degree rotations.
 == snapping-1.html snapping-1.html
 # SVG effects should work on transforms.
-fails == transform-svg-1a.xhtml transform-svg-1a.xhtml
-fails == transform-svg-2a.xhtml transform-svg-2a.xhtml
-fails == transform-svg-2a.xhtml transform-svg-2a.xhtml
+== transform-svg-1a.xhtml transform-svg-1a.xhtml
+== transform-svg-2a.xhtml transform-svg-2a.xhtml
+== transform-svg-2a.xhtml transform-svg-2a.xhtml
 # skew should allow a mix of one and two parameters.
-fails == skew-1a.html skew-1a.html
-fails == skew-1b.html skew-1b.html
-fails == skew-2a.html skew-2a.html
+== skew-1a.html skew-1a.html
+== skew-1b.html skew-1b.html
+== skew-2a.html skew-2a.html
 # matrix with values equal to other transforms should behave indistinguishably
-fails == matrix-1a.html matrix-1a.html
-fails == matrix-2a.html matrix-2a.html
-fails == matrix-3a.html matrix-3a.html
-fails == matrix-4a.html matrix-4a.html
-fails == matrix-5a.html matrix-5a.html
-fails == matrix-6a.html matrix-6a.html
-fails == matrix-7a.html matrix-7a.html
+== matrix-1a.html matrix-1a.html
+== matrix-2a.html matrix-2a.html
+== matrix-3a.html matrix-3a.html
+== matrix-4a.html matrix-4a.html
+== matrix-5a.html matrix-5a.html
+== matrix-6a.html matrix-6a.html
+== matrix-7a.html matrix-7a.html
 # ensure matrix 3d does not break us - should do nothing
 == matrix3d-1.html matrix3d-1.html
 # Test that complex transform can be reversed
 == stresstest-1.html stresstest-1.html
 # Test scale transforms
-fails == scalex-1.html scalex-1.html
-fails == scaley-1.html scaley-1.html
-fails == scale-1a.html scale-1a.html
-fails == scale-1b.html scale-1b.html
+== scalex-1.html scalex-1.html
+== scaley-1.html scaley-1.html
+== scale-1a.html scale-1a.html
+== scale-1b.html scale-1b.html
 == scale-percent-1.html scale-percent-1.html
 # Some simple checks that it obeys selector operations
-fails == descendant-1.html descendant-1.html
-fails == propagate-inherit-boolean.html propagate-inherit-boolean.html
+== descendant-1.html descendant-1.html
+== propagate-inherit-boolean.html propagate-inherit-boolean.html
 # Ensure you can't move outside an iframe
-fails == iframe-1.html iframe-1.html
+== iframe-1.html iframe-1.html
 # Bugs
 fails == 601894-1.html 601894-1.html
 fails == 601894-2.html 601894-2.html
 == 830299-1.html 830299-1.html
 # Bug 722777
-fails == table-1a.html table-1a.html
-fails == table-1b.html table-1b.html
-fails == table-1c.html table-1c.html
-fails == table-2a.html table-2a.html
-fails == table-2b.html table-2b.html
+== table-1a.html table-1a.html
+== table-1b.html table-1b.html
+== table-1c.html table-1c.html
+== table-2a.html table-2a.html
+== table-2b.html table-2b.html
 # Bug 722463
 == inline-1a.html inline-1a.html
 pref(svg.transform-box.enabled,true) == transform-box-svg-1a.svg transform-box-svg-1a.svg
 pref(svg.transform-box.enabled,true) == transform-box-svg-1b.svg transform-box-svg-1b.svg
 pref(svg.transform-box.enabled,true) == transform-box-svg-2a.svg transform-box-svg-2a.svg
 pref(svg.transform-box.enabled,true) == transform-box-svg-2b.svg transform-box-svg-2b.svg
 == transform-origin-svg-1a.svg transform-origin-svg-1a.svg
 == transform-origin-svg-1b.svg transform-origin-svg-1b.svg
--- a/layout/style/test/stylo-failures.md
+++ b/layout/style/test/stylo-failures.md
@@ -31,17 +31,17 @@ to mochitest command.
 
 * Media query support:
   * test_media_queries.html [156]
   * test_media_queries_dynamic.html [11]
   * test_media_queries_dynamic_xbl.html [2]
   * test_webkit_device_pixel_ratio.html: -webkit-device-pixel-ratio [3]
   * browser_bug453896.js [8]
 * Animation support:
-  * test_animations.html [22]
+  * test_animations.html [19]
   * test_animations_dynamic_changes.html [1]
   * test_bug716226.html [1]
   * OMTA
     * test_animations_effect_timing_duration.html [1]
     * test_animations_effect_timing_enddelay.html [1]
     * test_animations_effect_timing_iterations.html [1]
     * test_animations_iterationstart.html [1]
     * test_animations_omta.html [1]
@@ -145,32 +145,27 @@ to mochitest command.
   * -moz-force-broken-image-icon servo/servo#16001
     * test_compute_data_with_start_struct.html `-moz-force-broken-image-icon` [2]
     * test_inherit_computation.html `-moz-force-broken-image-icon` [2]
     * test_inherit_storage.html `-moz-force-broken-image-icon` [2]
     * test_initial_computation.html `-moz-force-broken-image-icon` [4]
     * test_initial_storage.html `-moz-force-broken-image-icon` [4]
     * test_value_storage.html `-moz-force-broken-image-icon` [4]
   * -moz-transform: need different parsing rules servo/servo#16003
-    * test_inherit_computation.html `-moz-transform`: need different parsing rules [2]
-    * test_inherit_storage.html `transform`: for -moz-transform [3]
-    * test_initial_computation.html `-moz-transform`: need different parsing rules [4]
-    * test_initial_storage.html `transform`: for -moz-transform [6]
-    * test_value_storage.html `-moz-transform`: need different parsing rules [280]
-    * test_specified_value_serialization.html `bug-721136` [26]
-    * test_units_angle.html [3]
+    * test_value_storage.html `-moz-transform`: need different parsing rules bug 1357906 [72]
   * test_variables.html `var(--var6)`: -x-system-font [1]
 * Unimplemented CSS properties:
   * place-{content,items,self} shorthands servo/servo#16391
     * test_property_syntax_errors.html `place-` [30]
     * test_align_shorthand_serialization.html [8]
     * test_value_storage.html `place-` [7]
   * font-variant-{alternates,east-asian,ligatures,numeric} properties servo/servo#15957
     * test_property_syntax_errors.html `font-variant-alternates` [2]
     * test_value_storage.html `font-variant` [176]
+    * test_specified_value_serialization.html `bug-721136` [1]
   * touch-action property servo/servo#16372
     * test_compute_data_with_start_struct.html `touch-action` [2]
     * test_inherit_computation.html `touch-action` [2]
     * test_inherit_storage.html `touch-action` [2]
     * test_initial_computation.html `touch-action` [4]
     * test_initial_storage.html `touch-action` [4]
     * test_value_storage.html `touch-action` [14]
 * Properties implemented but not in geckolib:
--- a/media/mtransport/test/moz.build
+++ b/media/mtransport/test/moz.build
@@ -23,27 +23,25 @@ if CONFIG['OS_TARGET'] != 'WINNT':
     ]
 
     if CONFIG['MOZ_SCTP']:
         SOURCES += [
             'sctp_unittest.cpp',
         ]
 
 
-for var in ('HAVE_STRDUP', 'NR_SOCKET_IS_VOID_PTR', 'SCTP_DEBUG', 'INET'):
+for var in ('HAVE_STRDUP', 'NR_SOCKET_IS_VOID_PTR', 'SCTP_DEBUG'):
     DEFINES[var] = True
 
 if CONFIG['OS_TARGET'] == 'Android':
     DEFINES['LINUX'] = True
     DEFINES['ANDROID'] = True
     LOCAL_INCLUDES += [
         '/media/mtransport/third_party/nrappkit/src/port/android/include',
     ]
-else:
-    DEFINES['INET6'] = True
 
 if CONFIG['OS_TARGET'] == 'Linux':
     DEFINES['LINUX'] = True
     LOCAL_INCLUDES += [
         '/media/mtransport/third_party/nrappkit/src/port/linux/include',
     ]
 
 if CONFIG['OS_TARGET'] == 'Darwin':
--- a/mfbt/Assertions.h
+++ b/mfbt/Assertions.h
@@ -439,17 +439,17 @@ struct AssertionConditionType
     (__VA_ARGS__))
 
 #ifdef DEBUG
 #  define MOZ_ASSERT(...) MOZ_RELEASE_ASSERT(__VA_ARGS__)
 #else
 #  define MOZ_ASSERT(...) do { } while (0)
 #endif /* DEBUG */
 
-#ifdef RELEASE_OR_BETA
+#if defined(RELEASE_OR_BETA) && !defined(EARLY_BETA_OR_EARLIER)
 #  define MOZ_DIAGNOSTIC_ASSERT MOZ_ASSERT
 #else
 #  define MOZ_DIAGNOSTIC_ASSERT MOZ_RELEASE_ASSERT
 #endif
 
 /*
  * MOZ_ASSERT_IF(cond1, cond2) is equivalent to MOZ_ASSERT(cond2) if cond1 is
  * true.
--- a/netwerk/sctp/datachannel/moz.build
+++ b/netwerk/sctp/datachannel/moz.build
@@ -18,22 +18,18 @@ include('/ipc/chromium/chromium-config.m
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/media/mtransport',
     '/netwerk/sctp/src',
 ]
 
-DEFINES['INET'] = 1
 DEFINES['SCTP_DEBUG'] = 1
 
-if CONFIG['OS_TARGET'] != 'Android':
-    DEFINES['INET6'] = 1
-
 if CONFIG['OS_TARGET'] == 'WINNT':
     DEFINES['__Userspace_os_Windows'] = 1
 else:
     DEFINES['__Userspace_os_%s' % CONFIG['OS_TARGET']] = 1
 
 NO_PGO = True # Don't PGO
 
 if CONFIG['GNU_CXX']:
--- a/netwerk/sctp/src/moz.build
+++ b/netwerk/sctp/src/moz.build
@@ -49,25 +49,20 @@ ALLOW_COMPILER_WARNINGS = True
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/netwerk/base',
 ]
 
 for var in ('SCTP_SIMPLE_ALLOCATOR',
-            'SCTP_PROCESS_LEVEL_LOCKS', '__Userspace__', 'INET',
+            'SCTP_PROCESS_LEVEL_LOCKS', '__Userspace__',
             'CALLBACK_API', 'SCTP_DEBUG'):
     DEFINES[var] = 1
 
-# Android NDK r5c, used on the builders at the time of this writing, doesn't
-# have the headers we need for IPv6
-if CONFIG['OS_TARGET'] != 'Android':
-    DEFINES['INET6'] = 1
-
 if CONFIG['OS_TARGET'] == 'WINNT':
     DEFINES['__Userspace_os_Windows'] = 1
     DEFINES['_LIB'] = 1
 elif CONFIG['OS_TARGET'] == 'Android':
     DEFINES['__Userspace_os_Linux'] = 1
 else:
     DEFINES['__Userspace_os_%s' % CONFIG['OS_TARGET']] = 1
 
--- a/old-configure.in
+++ b/old-configure.in
@@ -3112,29 +3112,31 @@ dnl ====================================
 MOZ_ARG_DISABLE_BOOL(universalchardet,
 [  --disable-universalchardet
                           Disable universal encoding detection],
   MOZ_UNIVERSALCHARDET=,
   MOZ_UNIVERSALCHARDET=1 )
 
 dnl ========================================================
 dnl = ANGLE OpenGL->D3D translator for WebGL
-dnl = * only applies to win32
+dnl = * only applies to win32 (and then, not MINGW)
 dnl ========================================================
 
 MOZ_ANGLE_RENDERER=
 MOZ_D3D_CPU_SUFFIX=
 MOZ_HAS_WINSDK_WITH_D3D=
 MOZ_D3DCOMPILER_VISTA_DLL=
 MOZ_D3DCOMPILER_VISTA_DLL_PATH=
 
 if test "$COMPILE_ENVIRONMENT" ; then
 case "$target_os" in
 *mingw*)
-    MOZ_ANGLE_RENDERER=1
+    if test "$OS_ARCH" = "$HOST_OS_ARCH"; then
+      MOZ_ANGLE_RENDERER=1
+    fi
     ;;
 esac
 
 # The DirectX SDK libraries are split into x86 and x64 sub-directories
 case "${target_cpu}" in
 i*86)
   MOZ_D3D_CPU_SUFFIX=x86
   ;;
--- a/servo/components/compositing/compositor.rs
+++ b/servo/components/compositing/compositor.rs
@@ -792,17 +792,22 @@ impl<Window: WindowMethods> IOCompositor
         self.delayed_composition_timer.schedule_composite(timestamp);
         self.composition_request = CompositionRequest::DelayedComposite(timestamp);
     }
 
     fn scroll_fragment_to_point(&mut self,
                                 pipeline_id: PipelineId,
                                 scroll_root_id: ScrollRootId,
                                 point: Point2D<f32>) {
-        let id = ClipId::new(scroll_root_id.0 as u64, pipeline_id.to_webrender());
+        let id = if scroll_root_id.0 == 0 {
+            ClipId::root_scroll_node(pipeline_id.to_webrender())
+        } else {
+            ClipId::new(scroll_root_id.0 as u64, pipeline_id.to_webrender())
+        };
+
         self.webrender_api.scroll_node_with_id(LayoutPoint::from_untyped(&point), id);
     }
 
     fn handle_window_message(&mut self, event: WindowEvent) {
         match event {
             WindowEvent::Idle => {}
 
             WindowEvent::Refresh => {
--- a/servo/components/layout/fragment.rs
+++ b/servo/components/layout/fragment.rs
@@ -2897,16 +2897,20 @@ impl Fragment {
                     let ty =
                         model::specified(ty, stacking_relative_border_box.size.height).to_f32_px();
                     let tz = tz.to_f32_px();
                     Matrix4D::create_translation(tx, ty, tz)
                 }
                 transform::ComputedOperation::Matrix(m) => {
                     m.to_gfx_matrix()
                 }
+                transform::ComputedOperation::MatrixWithPercents(_) => {
+                    // `-moz-transform` is not implemented in Servo yet.
+                    unreachable!()
+                }
                 transform::ComputedOperation::Skew(theta_x, theta_y) => {
                     Matrix4D::create_skew(Radians::new(theta_x.radians()),
                                           Radians::new(theta_y.radians()))
                 }
             };
 
             transform = transform.pre_mul(&matrix);
         }
--- a/servo/components/style/properties/data.py
+++ b/servo/components/style/properties/data.py
@@ -123,18 +123,17 @@ def arg_to_bool(arg):
 
 
 class Longhand(object):
     def __init__(self, style_struct, name, spec=None, animation_type=None, derived_from=None, keyword=None,
                  predefined_type=None, custom_cascade=False, experimental=False, internal=False,
                  need_clone=False, need_index=False, gecko_ffi_name=None, depend_on_viewport_size=False,
                  allowed_in_keyframe_block=True, complex_color=False, cast_type='u8',
                  has_uncacheable_values=False, logical=False, alias=None, extra_prefixes=None, boxed=False,
-                 creates_stacking_context=False, fixpos_cb=False, abspos_cb=False,
-                 allowed_in_page_rule=False):
+                 flags=None, allowed_in_page_rule=False):
         self.name = name
         if not spec:
             raise TypeError("Spec should be specified for %s" % name)
         self.spec = spec
         self.keyword = keyword
         self.predefined_type = predefined_type
         self.ident = to_rust_ident(name)
         self.camel_case = to_camel_case(self.ident)
@@ -148,19 +147,17 @@ class Longhand(object):
         self.depend_on_viewport_size = depend_on_viewport_size
         self.derived_from = (derived_from or "").split()
         self.complex_color = complex_color
         self.cast_type = cast_type
         self.logical = arg_to_bool(logical)
         self.alias = alias.split() if alias else []
         self.extra_prefixes = extra_prefixes.split() if extra_prefixes else []
         self.boxed = arg_to_bool(boxed)
-        self.creates_stacking_context = arg_to_bool(creates_stacking_context)
-        self.fixpos_cb = arg_to_bool(fixpos_cb)
-        self.abspos_cb = arg_to_bool(abspos_cb)
+        self.flags = flags.split() if flags else []
         self.allowed_in_page_rule = arg_to_bool(allowed_in_page_rule)
 
         # https://drafts.csswg.org/css-animations/#keyframes
         # > The <declaration-list> inside of <keyframe-block> accepts any CSS property
         # > except those defined in this specification,
         # > but does accept the `animation-play-state` property and interprets it specially.
         self.allowed_in_keyframe_block = allowed_in_keyframe_block \
             and allowed_in_keyframe_block != "False"
@@ -185,30 +182,31 @@ class Longhand(object):
         #
         # See components/style/helpers/animated_properties.mako.rs.
         self.need_clone = need_clone or self.animatable
 
 
 class Shorthand(object):
     def __init__(self, name, sub_properties, spec=None, experimental=False, internal=False,
                  allowed_in_keyframe_block=True, alias=None, extra_prefixes=None,
-                 allowed_in_page_rule=False):
+                 allowed_in_page_rule=False, flags=None):
         self.name = name
         if not spec:
             raise TypeError("Spec should be specified for %s" % name)
         self.spec = spec
         self.ident = to_rust_ident(name)
         self.camel_case = to_camel_case(self.ident)
         self.derived_from = None
         self.experimental = ("layout.%s.enabled" % name) if experimental else None
         self.sub_properties = sub_properties
         self.internal = internal
         self.alias = alias.split() if alias else []
         self.extra_prefixes = extra_prefixes.split() if extra_prefixes else []
         self.allowed_in_page_rule = arg_to_bool(allowed_in_page_rule)
+        self.flags = flags.split() if flags else []
 
         # https://drafts.csswg.org/css-animations/#keyframes
         # > The <declaration-list> inside of <keyframe-block> accepts any CSS property
         # > except those defined in this specification,
         # > but does accept the `animation-play-state` property and interprets it specially.
         self.allowed_in_keyframe_block = allowed_in_keyframe_block \
             and allowed_in_keyframe_block != "False"
 
--- a/servo/components/style/properties/declaration_block.rs
+++ b/servo/components/style/properties/declaration_block.rs
@@ -474,22 +474,33 @@ impl ToCss for PropertyDeclarationBlock 
                             AppendableValue::Css {
                                 css: &value,
                                 with_variables: false,
                             }
                         }
                     };
 
                     // Substeps 7 and 8
-                    append_serialization::<_, Cloned<slice::Iter< _>>, _>(
-                         dest,
-                         &shorthand,
-                         value,
-                         importance,
-                         &mut is_first_serialization)?;
+                    // We need to check the shorthand whether it's an alias property or not.
+                    // If it's an alias property, it should be serialized like its longhand.
+                    if shorthand.flags().contains(ALIAS_PROPERTY) {
+                        append_serialization::<_, Cloned<slice::Iter< _>>, _>(
+                             dest,
+                             &property,
+                             value,
+                             importance,
+                             &mut is_first_serialization)?;
+                    } else {
+                        append_serialization::<_, Cloned<slice::Iter< _>>, _>(
+                             dest,
+                             &shorthand,
+                             value,
+                             importance,
+                             &mut is_first_serialization)?;
+                    }
 
                     for current_longhand in &current_longhands {
                         // Substep 9
                         already_serialized.push(current_longhand.id());
                         let index_to_remove = longhands.iter().position(|l| l.0 == **current_longhand);
                         if let Some(index) = index_to_remove {
                             // Substep 10
                             longhands.remove(index);
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -1829,37 +1829,39 @@ fn static_assert() {
         longhands::scroll_snap_coordinate::computed_value::T(vec)
     }
 
     ${impl_css_url('_moz_binding', 'mBinding.mPtr')}
 
     <%def name="transform_function_arm(name, keyword, items)">
         <%
             pattern = None
-            if name == "matrix":
-                # m11, m12, m13, ..
-                indices = [str(i) + str(j) for i in range(1, 5) for j in range(1, 5)]
+            if keyword == "matrix3d":
                 # m11: number1, m12: number2, ..
-                single_patterns = ["m%s: number%s" % (index, i + 1) for (i, index) in enumerate(indices)]
-                pattern = "ComputedMatrix { %s }" % ", ".join(single_patterns)
+                single_patterns = ["m%s: %s" % (str(a / 4 + 1) + str(a % 4 + 1), b + str(a + 1)) for (a, b)
+                                   in enumerate(items)]
+                if name == "Matrix":
+                    pattern = "ComputedMatrix { %s }" % ", ".join(single_patterns)
+                else:
+                    pattern = "ComputedMatrixWithPercents { %s }" % ", ".join(single_patterns)
             else:
                 # Generate contents of pattern from items
                 pattern = ", ".join([b + str(a+1) for (a,b) in enumerate(items)])
 
             # First %s substituted with the call to GetArrayItem, the second
             # %s substituted with the corresponding variable
             css_value_setters = {
                 "length" : "bindings::Gecko_CSSValue_SetAbsoluteLength(%s, %s.0)",
                 "percentage" : "bindings::Gecko_CSSValue_SetPercentage(%s, %s)",
                 "lop" : "%s.set_lop(%s)",
                 "angle" : "bindings::Gecko_CSSValue_SetAngle(%s, %s.radians())",
                 "number" : "bindings::Gecko_CSSValue_SetNumber(%s, %s)",
             }
         %>
-        longhands::transform::computed_value::ComputedOperation::${name.title()}(${pattern}) => {
+        longhands::transform::computed_value::ComputedOperation::${name}(${pattern}) => {
             bindings::Gecko_CSSValue_SetFunction(gecko_value, ${len(items) + 1});
             bindings::Gecko_CSSValue_SetKeyword(
                 bindings::Gecko_CSSValue_GetArrayItem(gecko_value, 0),
                 eCSSKeyword_${keyword}
             );
             % for index, item in enumerate(items):
                 ${css_value_setters[item] % (
                     "bindings::Gecko_CSSValue_GetArrayItem(gecko_value, %d)" % (index + 1),
@@ -1868,37 +1870,40 @@ fn static_assert() {
             % endfor
         }
     </%def>
     pub fn convert_transform(input: Vec<longhands::transform::computed_value::ComputedOperation>,
                              output: &mut structs::root::RefPtr<structs::root::nsCSSValueSharedList>) {
         use gecko_bindings::structs::nsCSSKeyword::*;
         use gecko_bindings::sugar::refptr::RefPtr;
         use properties::longhands::transform::computed_value::ComputedMatrix;
+        use properties::longhands::transform::computed_value::ComputedMatrixWithPercents;
 
         unsafe { output.clear() };
 
         let list = unsafe {
             RefPtr::from_addrefed(bindings::Gecko_NewCSSValueSharedList(input.len() as u32))
         };
 
         let mut cur = list.mHead;
         let mut iter = input.into_iter();
         while !cur.is_null() {
             let gecko_value = unsafe { &mut (*cur).mValue };
             let servo = iter.next().expect("Gecko_NewCSSValueSharedList should create a shared \
                                             value list of the same length as the transform vector");
             unsafe {
                 match servo {
-                    ${transform_function_arm("matrix", "matrix3d", ["number"] * 16)}
-                    ${transform_function_arm("skew", "skew", ["angle"] * 2)}
-                    ${transform_function_arm("translate", "translate3d", ["lop", "lop", "length"])}
-                    ${transform_function_arm("scale", "scale3d", ["number"] * 3)}
-                    ${transform_function_arm("rotate", "rotate3d", ["number"] * 3 + ["angle"])}
-                    ${transform_function_arm("perspective", "perspective", ["length"])}
+                    ${transform_function_arm("Matrix", "matrix3d", ["number"] * 16)}
+                    ${transform_function_arm("MatrixWithPercents", "matrix3d", ["number"] * 12 + ["lop"] * 2
+                                             + ["length"] + ["number"])}
+                    ${transform_function_arm("Skew", "skew", ["angle"] * 2)}
+                    ${transform_function_arm("Translate", "translate3d", ["lop", "lop", "length"])}
+                    ${transform_function_arm("Scale", "scale3d", ["number"] * 3)}
+                    ${transform_function_arm("Rotate", "rotate3d", ["number"] * 3 + ["angle"])}
+                    ${transform_function_arm("Perspective", "perspective", ["length"])}
                 }
                 cur = (*cur).mNext;
             }
         }
         debug_assert!(iter.next().is_none());
         unsafe { output.set_move(list) };
     }
 
@@ -1924,29 +1929,29 @@ fn static_assert() {
             css_value_getters = {
                 "length" : "Au(bindings::Gecko_CSSValue_GetAbsoluteLength(%s))",
                 "lop" : "%s.get_lop()",
                 "angle" : "Angle::from_radians(bindings::Gecko_CSSValue_GetAngle(%s))",
                 "number" : "bindings::Gecko_CSSValue_GetNumber(%s)",
             }
         %>
         eCSSKeyword_${keyword} => {
-            ComputedOperation::${name.title()}(
-            % if name == "matrix":
+            ComputedOperation::${name}(
+            % if keyword == "matrix3d":
                 ComputedMatrix {
             % endif
             % for index, item in enumerate(items):
-                % if name == "matrix":
+                % if keyword == "matrix3d":
                     m${index / 4 + 1}${index % 4 + 1}:
                 % endif
                 ${css_value_getters[item] % (
                     "bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, %d)" % (index + 1)
                 )},
             % endfor
-            % if name == "matrix":
+            % if keyword == "matrix3d":
                 }
             % endif
             )
         },
     </%def>
     pub fn clone_transform(&self) -> longhands::transform::computed_value::T {
         use app_units::Au;
         use gecko_bindings::structs::nsCSSKeyword::*;
@@ -1963,22 +1968,22 @@ fn static_assert() {
         let mut cur = unsafe { (*self.gecko.mSpecifiedTransform.to_safe().get()).mHead };
         while !cur.is_null() {
             let gecko_value = unsafe { &(*cur).mValue };
             let transform_function = unsafe {
                 bindings::Gecko_CSSValue_GetKeyword(bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, 0))
             };
             let servo = unsafe {
                 match transform_function {
-                    ${computed_operation_arm("matrix", "matrix3d", ["number"] * 16)}
-                    ${computed_operation_arm("skew", "skew", ["angle"] * 2)}
-                    ${computed_operation_arm("translate", "translate3d", ["lop", "lop", "length"])}
-                    ${computed_operation_arm("scale", "scale3d", ["number"] * 3)}
-                    ${computed_operation_arm("rotate", "rotate3d", ["number"] * 3 + ["angle"])}
-                    ${computed_operation_arm("perspective", "perspective", ["length"])}
+                    ${computed_operation_arm("Matrix", "matrix3d", ["number"] * 16)}
+                    ${computed_operation_arm("Skew", "skew", ["angle"] * 2)}
+                    ${computed_operation_arm("Translate", "translate3d", ["lop", "lop", "length"])}
+                    ${computed_operation_arm("Scale", "scale3d", ["number"] * 3)}
+                    ${computed_operation_arm("Rotate", "rotate3d", ["number"] * 3 + ["angle"])}
+                    ${computed_operation_arm("Perspective", "perspective", ["length"])}
                     _ => panic!("We shouldn't set any other transform function types"),
                 }
             };
             result.push(servo);
             unsafe { cur = (&*cur).mNext };
         }
         computed_value::T(Some(result))
     }
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -1122,16 +1122,17 @@ fn build_identity_transform_list(list: &
     let mut result = vec!();
 
     for operation in list {
         match *operation {
             TransformOperation::Matrix(..) => {
                 let identity = ComputedMatrix::identity();
                 result.push(TransformOperation::Matrix(identity));
             }
+            TransformOperation::MatrixWithPercents(..) => {}
             TransformOperation::Skew(..) => {
                 result.push(TransformOperation::Skew(Angle::zero(), Angle::zero()))
             }
             TransformOperation::Translate(..) => {
                 result.push(TransformOperation::Translate(LengthOrPercentage::zero(),
                                                           LengthOrPercentage::zero(),
                                                           Au(0)));
             }
@@ -1162,16 +1163,22 @@ fn interpolate_transform_list(from_list:
     if can_interpolate_list(from_list, to_list) {
         for (from, to) in from_list.iter().zip(to_list) {
             match (from, to) {
                 (&TransformOperation::Matrix(from),
                  &TransformOperation::Matrix(_to)) => {
                     let interpolated = from.interpolate(&_to, progress).unwrap();
                     result.push(TransformOperation::Matrix(interpolated));
                 }
+                (&TransformOperation::MatrixWithPercents(_),
+                 &TransformOperation::MatrixWithPercents(_)) => {
+                    // We don't interpolate `-moz-transform` matrices yet.
+                    // They contain percentage values.
+                    {}
+                }
                 (&TransformOperation::Skew(fx, fy),
                  &TransformOperation::Skew(tx, ty)) => {
                     let ix = fx.interpolate(&tx, progress).unwrap();
                     let iy = fy.interpolate(&ty, progress).unwrap();
                     result.push(TransformOperation::Skew(ix, iy));
                 }
                 (&TransformOperation::Translate(fx, fy, fz),
                  &TransformOperation::Translate(tx, ty, tz)) => {
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -102,18 +102,17 @@
                          gecko_ffi_name="mTopLayer", need_clone=True,
                          products="gecko", animation_type="none", internal=True,
                          spec="Internal (not web-exposed)")}
 
 ${helpers.single_keyword("position", "static absolute relative fixed",
                          need_clone="True",
                          extra_gecko_values="sticky",
                          animation_type="none",
-                         creates_stacking_context="True",
-                         abspos_cb="True",
+                         flags="CREATES_STACKING_CONTEXT ABSPOS_CB",
                          spec="https://drafts.csswg.org/css-position/#position-property")}
 
 <%helpers:single_keyword_computed name="float"
                                   values="none left right"
                                   // https://drafts.csswg.org/css-logical-props/#float-clear
                                   extra_specified="inline-start inline-end"
                                   needs_conversion="True"
                                   animation_type="none"
@@ -1104,58 +1103,85 @@
                           products="gecko",
                           spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-destination)",
                           animation_type="normal",
                           allow_empty=True,
                           delegate_animate=True)}
 
 
 
-<%helpers:longhand name="transform" products="gecko servo" extra_prefixes="webkit"
+<%helpers:longhand name="transform" extra_prefixes="webkit"
                    animation_type="normal"
-                   creates_stacking_context="True"
-                   fixpos_cb="True"
+                   flags="CREATES_STACKING_CONTEXT FIXPOS_CB"
                    spec="https://drafts.csswg.org/css-transforms/#propdef-transform">
     use app_units::Au;
-    use values::specified::{Angle, Length, LengthOrPercentage, Number};
+    use values::computed::{LengthOrPercentageOrNumber as ComputedLoPoNumber, LengthOrNumber as ComputedLoN};
+    use values::computed::{LengthOrPercentage as ComputedLoP, Length as ComputedLength};
+    use values::specified::{Angle, Length, LengthOrPercentage};
+    use values::specified::{LengthOrNumber, LengthOrPercentageOrNumber as LoPoNumber, Number};
     use style_traits::ToCss;
     use style_traits::values::Css;
-    use values::CSSFloat;
     use values::HasViewportPercentage;
 
     use std::fmt::{self, Display};
 
     pub mod computed_value {
+        use app_units::Au;
         use values::CSSFloat;
         use values::computed;
+        use values::computed::{Length, LengthOrPercentage};
 
         #[derive(Clone, Copy, Debug, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub struct ComputedMatrix {
             pub m11: CSSFloat, pub m12: CSSFloat, pub m13: CSSFloat, pub m14: CSSFloat,
             pub m21: CSSFloat, pub m22: CSSFloat, pub m23: CSSFloat, pub m24: CSSFloat,
             pub m31: CSSFloat, pub m32: CSSFloat, pub m33: CSSFloat, pub m34: CSSFloat,
             pub m41: CSSFloat, pub m42: CSSFloat, pub m43: CSSFloat, pub m44: CSSFloat,
         }
 
+        #[derive(Clone, Copy, Debug, PartialEq)]
+        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+        pub struct ComputedMatrixWithPercents {
+            pub m11: CSSFloat, pub m12: CSSFloat, pub m13: CSSFloat, pub m14: CSSFloat,
+            pub m21: CSSFloat, pub m22: CSSFloat, pub m23: CSSFloat, pub m24: CSSFloat,
+            pub m31: CSSFloat, pub m32: CSSFloat, pub m33: CSSFloat, pub m34: CSSFloat,
+            pub m41: LengthOrPercentage, pub m42: LengthOrPercentage,
+            pub m43: Length, pub m44: CSSFloat,
+        }
+
         impl ComputedMatrix {
             pub fn identity() -> ComputedMatrix {
                 ComputedMatrix {
                     m11: 1.0, m12: 0.0, m13: 0.0, m14: 0.0,
                     m21: 0.0, m22: 1.0, m23: 0.0, m24: 0.0,
                     m31: 0.0, m32: 0.0, m33: 1.0, m34: 0.0,
                     m41: 0.0, m42: 0.0, m43: 0.0, m44: 1.0
                 }
             }
         }
 
+        impl ComputedMatrixWithPercents {
+            pub fn identity() -> ComputedMatrixWithPercents {
+                ComputedMatrixWithPercents {
+                    m11: 1.0, m12: 0.0, m13: 0.0, m14: 0.0,
+                    m21: 0.0, m22: 1.0, m23: 0.0, m24: 0.0,
+                    m31: 0.0, m32: 0.0, m33: 1.0, m34: 0.0,
+                    m41: LengthOrPercentage::zero(), m42: LengthOrPercentage::zero(),
+                    m43: Au(0), m44: 1.0
+                }
+            }
+        }
+
         #[derive(Clone, Debug, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub enum ComputedOperation {
             Matrix(ComputedMatrix),
+            // For `-moz-transform` matrix and matrix3d.
+            MatrixWithPercents(ComputedMatrixWithPercents),
             Skew(computed::Angle, computed::Angle),
             Translate(computed::LengthOrPercentage,
                       computed::LengthOrPercentage,
                       computed::Length),
             Scale(CSSFloat, CSSFloat, CSSFloat),
             Rotate(CSSFloat, CSSFloat, CSSFloat, computed::Angle),
             Perspective(computed::Length),
         }
@@ -1171,23 +1197,34 @@
     /// Multiple transform functions compose a transformation.
     ///
     /// Some transformations can be expressed by other more general functions.
     #[derive(Clone, Debug, PartialEq)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub enum SpecifiedOperation {
         /// Represents a 2D 2x3 matrix.
         Matrix { a: Number, b: Number, c: Number, d: Number, e: Number, f: Number },
+        /// Represents a 3D 4x4 matrix with percentage and length values.
+        /// For `moz-transform`.
+        PrefixedMatrix { a: Number, b: Number, c: Number, d: Number, e: LoPoNumber, f: LoPoNumber },
         /// Represents a 3D 4x4 matrix.
         Matrix3D {
             m11: Number, m12: Number, m13: Number, m14: Number,
             m21: Number, m22: Number, m23: Number, m24: Number,
             m31: Number, m32: Number, m33: Number, m34: Number,
             m41: Number, m42: Number, m43: Number, m44: Number,
         },
+        /// Represents a 3D 4x4 matrix with percentage and length values.
+        /// For `moz-transform`.
+        PrefixedMatrix3D {
+            m11: Number,     m12: Number,     m13: Number,         m14: Number,
+            m21: Number,     m22: Number,     m23: Number,         m24: Number,
+            m31: Number,     m32: Number,     m33: Number,         m34: Number,
+            m41: LoPoNumber, m42: LoPoNumber, m43: LengthOrNumber, m44: Number,
+        },
         /// A 2D skew.
         ///
         /// If the second angle is not provided it is assumed zero.
         Skew(Angle, Option<Angle>),
         SkewX(Angle),
         SkewY(Angle),
         Translate(LengthOrPercentage, Option<LengthOrPercentage>),
         TranslateX(LengthOrPercentage),
@@ -1251,38 +1288,60 @@
                     l2.has_viewport_percentage()
                 }
                 SpecifiedOperation::Translate3D(ref l1, ref l2, ref l3) => {
                     l1.has_viewport_percentage() ||
                     l2.has_viewport_percentage() ||
                     l3.has_viewport_percentage()
                 },
                 SpecifiedOperation::Perspective(ref length) => length.has_viewport_percentage(),
+                SpecifiedOperation::PrefixedMatrix{ ref e, ref f, .. } => {
+                    e.has_viewport_percentage() ||
+                    f.has_viewport_percentage()
+                },
+                SpecifiedOperation::PrefixedMatrix3D{ ref m41, ref m42, ref m43, .. } => {
+                    m41.has_viewport_percentage() ||
+                    m42.has_viewport_percentage() ||
+                    m43.has_viewport_percentage()
+                },
                 _ => false
             }
         }
     }
 
     impl ToCss for SpecifiedOperation {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             use self::SpecifiedOperation::*;
             match *self {
                 Matrix { a, b, c, d, e, f} => write!(
                     dest, "matrix({}, {}, {}, {}, {}, {})",
                     Css(a), Css(b), Css(c), Css(d), Css(e), Css(f)),
+                PrefixedMatrix { a, b, c, d, ref e, ref f} => write!(
+                    dest, "matrix({}, {}, {}, {}, {}, {})",
+                    Css(a), Css(b), Css(c), Css(d), Css(e), Css(f)),
                 Matrix3D {
                     m11, m12, m13, m14,
                     m21, m22, m23, m24,
                     m31, m32, m33, m34,
                     m41, m42, m43, m44 } => write!(
                         dest, "matrix3d({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {})",
                         Css(m11), Css(m12), Css(m13), Css(m14),
                         Css(m21), Css(m22), Css(m23), Css(m24),
                         Css(m31), Css(m32), Css(m33), Css(m34),
                         Css(m41), Css(m42), Css(m43), Css(m44)),
+                PrefixedMatrix3D {
+                    m11, m12, m13, m14,
+                    m21, m22, m23, m24,
+                    m31, m32, m33, m34,
+                    ref m41, ref m42, ref m43, m44 } => write!(
+                        dest, "matrix3d({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {})",
+                        Css(m11), Css(m12), Css(m13), Css(m14),
+                        Css(m21), Css(m22), Css(m23), Css(m24),
+                        Css(m31), Css(m32), Css(m33), Css(m34),
+                        Css(m41), Css(m42), Css(m43), Css(m44)),
                 Skew(ax, None) => write!(dest, "skew({})", Css(ax)),
                 Skew(ax, Some(ay)) => write!(dest, "skew({}, {})", Css(ax), Css(ay)),
                 SkewX(angle) => write!(dest, "skewX({})", Css(angle)),
                 SkewY(angle) => write!(dest, "skewY({})", Css(angle)),
                 Translate(ref tx, None) => write!(dest, "translate({})", Css(tx)),
                 Translate(ref tx, Some(ref ty)) => write!(dest, "translate({}, {})", Css(tx), Css(ty)),
                 TranslateX(ref tx) => write!(dest, "translateX({})", Css(tx)),
                 TranslateY(ref ty) => write!(dest, "translateY({})", Css(ty)),
@@ -1338,59 +1397,136 @@
     }
 
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
         computed_value::T(None)
     }
 
     // Allow unitless zero angle for rotate() and skew() to align with gecko
-    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
+    fn parse_internal(context: &ParserContext, input: &mut Parser, prefixed: bool)
+        -> Result<SpecifiedValue,()> {
         if input.try(|input| input.expect_ident_matching("none")).is_ok() {
             return Ok(SpecifiedValue(Vec::new()))
         }
 
         let mut result = Vec::new();
         loop {
             let name = match input.expect_function() {
                 Ok(name) => name,
                 Err(_) => break,
             };
             match_ignore_ascii_case! {
                 &name,
                 "matrix" => {
                     try!(input.parse_nested_block(|input| {
-                        let values = try!(input.parse_comma_separated(|input| {
-                            specified::parse_number(context, input)
-                        }));
-                        if values.len() != 6 {
-                            return Err(())
+                        // Standard matrix parsing.
+                        if !prefixed {
+                            let values = try!(input.parse_comma_separated(|input| {
+                                specified::parse_number(context, input)
+                            }));
+                            if values.len() != 6 {
+                                return Err(())
+                            }
+
+                            result.push(SpecifiedOperation::Matrix {
+                                a: values[0],
+                                b: values[1],
+                                c: values[2],
+                                d: values[3],
+                                e: values[4],
+                                f: values[5],
+                            });
+                            return Ok(());
                         }
-                        result.push(SpecifiedOperation::Matrix {
+
+                        // Non-standard prefixed matrix parsing.
+                        //
+                        // -moz-transform accepts LengthOrPercentageOrNumber in the
+                        //  nondiagonal homogeneous components. transform accepts only number.
+                        let mut values = Vec::with_capacity(4);
+                        let mut lengths = Vec::with_capacity(2);
+
+                        // Consume first number
+                        values.push(specified::parse_number(context, input)?);
+
+                        // Parse other 5 number/LengthOrPercentageOrNumber
+                        for i in 0..5 {
+                            input.expect_comma()?;
+                            if i < 3 {
+                                values.push(specified::parse_number(context, input)?);
+                            } else {
+                                // -moz-transform accepts LengthOrPercentageOrNumber in the nondiagonal
+                                // homogeneous components. transform accepts only number.
+                                lengths.push(LoPoNumber::parse(context, input)?)
+                            }
+                        }
+
+                        result.push(SpecifiedOperation::PrefixedMatrix {
                             a: values[0],
                             b: values[1],
                             c: values[2],
                             d: values[3],
-                            e: values[4],
-                            f: values[5]
+                            e: lengths[0].clone(),
+                            f: lengths[1].clone(),
                         });
                         Ok(())
                     }))
                 },
                 "matrix3d" => {
                     try!(input.parse_nested_block(|input| {
-                        let values = try!(input.parse_comma_separated(|i| specified::parse_number(context, i)));
-                        if values.len() != 16 {
-                            return Err(())
+                        // Standard matrix3d parsing.
+                        if !prefixed {
+                            let values = try!(input.parse_comma_separated(|i| specified::parse_number(context, i)));
+                            if values.len() != 16 {
+                                return Err(())
+                            }
+
+                            result.push(SpecifiedOperation::Matrix3D {
+                                m11: values[ 0], m12: values[ 1], m13: values[ 2], m14: values[ 3],
+                                m21: values[ 4], m22: values[ 5], m23: values[ 6], m24: values[ 7],
+                                m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11],
+                                m41: values[12], m42: values[13], m43: values[14], m44: values[15]
+                            });
+                            return Ok(());
                         }
-                        result.push(SpecifiedOperation::Matrix3D {
+
+                        // Non-standard prefixed matrix3d parsing.
+                        //
+                        // -moz-transform accepts LengthOrPercentageOrNumber in the
+                        //  nondiagonal homogeneous components. transform accepts only number.
+                        let mut values = Vec::with_capacity(13);
+                        let mut lops = Vec::with_capacity(2);
+                        let mut length_or_number = None;
+
+                        // Parse first number
+                        values.push(specified::parse_number(context, input)?);
+
+                        // Parse other 15 number/LengthOrPercentageOrNumber
+                        for i in 0..15 {
+                            input.expect_comma()?;
+                            // -moz-transform accepts LengthOrPercentageOrNumber in the nondiagonal
+                            // homogeneous components. transform accepts only number.
+                            if i < 11 || i > 13 {
+                                values.push(specified::parse_number(context, input)?);
+                            } else if i == 13 {
+                                // m43
+                                length_or_number = Some(LengthOrNumber::parse(context, input)?);
+                            } else {
+                                // m41 and m42
+                                lops.push(LoPoNumber::parse(context, input)?);
+                            }
+                        }
+
+                        result.push(SpecifiedOperation::PrefixedMatrix3D {
                             m11: values[ 0], m12: values[ 1], m13: values[ 2], m14: values[ 3],
                             m21: values[ 4], m22: values[ 5], m23: values[ 6], m24: values[ 7],
                             m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11],
-                            m41: values[12], m42: values[13], m43: values[14], m44: values[15]
+                            m41: lops[0].clone(), m42: lops[1].clone(), m43: length_or_number.unwrap(),
+                            m44: values[12]
                         });
                         Ok(())
                     }))
                 },
                 "translate" => {
                     try!(input.parse_nested_block(|input| {
                         let sx = try!(specified::LengthOrPercentage::parse(context, input));
                         if input.try(|input| input.expect_comma()).is_ok() {
@@ -1559,22 +1695,36 @@
 
         if !result.is_empty() {
             Ok(SpecifiedValue(result))
         } else {
             Err(())
         }
     }
 
+    /// Parses `transform` property.
+    #[inline]
+    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
+        parse_internal(context, input, false)
+    }
+
+    /// Parses `-moz-transform` property. This prefixed property also accepts LengthOrPercentage
+    /// in the nondiagonal homogeneous components of matrix and matrix3d.
+    #[inline]
+    pub fn parse_prefixed(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
+        parse_internal(context, input, true)
+    }
+
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
         fn to_computed_value(&self, context: &Context) -> computed_value::T {
             use self::SpecifiedOperation::*;
+
             if self.0.is_empty() {
                 return computed_value::T(None)
             }
 
             let mut result = vec!();
             for operation in &self.0 {
                 match *operation {
                     Matrix { a, b, c, d, e, f } => {
@@ -1582,21 +1732,31 @@
                         comp.m11 = a.to_computed_value(context);
                         comp.m12 = b.to_computed_value(context);
                         comp.m21 = c.to_computed_value(context);
                         comp.m22 = d.to_computed_value(context);
                         comp.m41 = e.to_computed_value(context);
                         comp.m42 = f.to_computed_value(context);
                         result.push(computed_value::ComputedOperation::Matrix(comp));
                     }
+                    PrefixedMatrix { a, b, c, d, ref e, ref f } => {
+                        let mut comp = computed_value::ComputedMatrixWithPercents::identity();
+                        comp.m11 = a.to_computed_value(context);
+                        comp.m12 = b.to_computed_value(context);
+                        comp.m21 = c.to_computed_value(context);
+                        comp.m22 = d.to_computed_value(context);
+                        comp.m41 = lopon_to_lop(&e.to_computed_value(context));
+                        comp.m42 = lopon_to_lop(&f.to_computed_value(context));
+                        result.push(computed_value::ComputedOperation::MatrixWithPercents(comp));
+                    }
                     Matrix3D {
                         m11, m12, m13, m14,
                         m21, m22, m23, m24,
                         m31, m32, m33, m34,
-                        m41, m42, m43, m44 } => {
+                        ref m41, ref m42, ref m43, m44 } => {
                             let comp = computed_value::ComputedMatrix {
                                 m11: m11.to_computed_value(context),
                                 m12: m12.to_computed_value(context),
                                 m13: m13.to_computed_value(context),
                                 m14: m14.to_computed_value(context),
                                 m21: m21.to_computed_value(context),
                                 m22: m22.to_computed_value(context),
                                 m23: m23.to_computed_value(context),
@@ -1607,16 +1767,41 @@
                                 m34: m34.to_computed_value(context),
                                 m41: m41.to_computed_value(context),
                                 m42: m42.to_computed_value(context),
                                 m43: m43.to_computed_value(context),
                                 m44: m44.to_computed_value(context),
                             };
                         result.push(computed_value::ComputedOperation::Matrix(comp));
                     }
+                    PrefixedMatrix3D {
+                        m11, m12, m13, m14,
+                        m21, m22, m23, m24,
+                        m31, m32, m33, m34,
+                        ref m41, ref m42, ref m43, m44 } => {
+                            let comp = computed_value::ComputedMatrixWithPercents {
+                                m11: m11.to_computed_value(context),
+                                m12: m12.to_computed_value(context),
+                                m13: m13.to_computed_value(context),
+                                m14: m14.to_computed_value(context),
+                                m21: m21.to_computed_value(context),
+                                m22: m22.to_computed_value(context),
+                                m23: m23.to_computed_value(context),
+                                m24: m24.to_computed_value(context),
+                                m31: m31.to_computed_value(context),
+                                m32: m32.to_computed_value(context),
+                                m33: m33.to_computed_value(context),
+                                m34: m34.to_computed_value(context),
+                                m41: lopon_to_lop(&m41.to_computed_value(context)),
+                                m42: lopon_to_lop(&m42.to_computed_value(context)),
+                                m43: lon_to_length(&m43.to_computed_value(context)),
+                                m44: m44.to_computed_value(context),
+                            };
+                        result.push(computed_value::ComputedOperation::MatrixWithPercents(comp));
+                    }
                     Translate(ref tx, None) => {
                         let tx = tx.to_computed_value(context);
                         result.push(computed_value::ComputedOperation::Translate(
                             tx,
                             computed::length::LengthOrPercentage::zero(),
                             computed::length::Length::new(0)));
                     }
                     Translate(ref tx, Some(ref ty)) => {
@@ -1752,16 +1937,36 @@
                                 m33: Number::from_computed_value(&computed.m33),
                                 m34: Number::from_computed_value(&computed.m34),
                                 m41: Number::from_computed_value(&computed.m41),
                                 m42: Number::from_computed_value(&computed.m42),
                                 m43: Number::from_computed_value(&computed.m43),
                                 m44: Number::from_computed_value(&computed.m44),
                             });
                         }
+                        computed_value::ComputedOperation::MatrixWithPercents(ref computed) => {
+                            result.push(SpecifiedOperation::PrefixedMatrix3D {
+                                m11: Number::from_computed_value(&computed.m11),
+                                m12: Number::from_computed_value(&computed.m12),
+                                m13: Number::from_computed_value(&computed.m13),
+                                m14: Number::from_computed_value(&computed.m14),
+                                m21: Number::from_computed_value(&computed.m21),
+                                m22: Number::from_computed_value(&computed.m22),
+                                m23: Number::from_computed_value(&computed.m23),
+                                m24: Number::from_computed_value(&computed.m24),
+                                m31: Number::from_computed_value(&computed.m31),
+                                m32: Number::from_computed_value(&computed.m32),
+                                m33: Number::from_computed_value(&computed.m33),
+                                m34: Number::from_computed_value(&computed.m34),
+                                m41: Either::First(LengthOrPercentage::from_computed_value(&computed.m41)),
+                                m42: Either::First(LengthOrPercentage::from_computed_value(&computed.m42)),
+                                m43: LengthOrNumber::from_computed_value(&Either::First(computed.m43)),
+                                m44: Number::from_computed_value(&computed.m44),
+                            });
+                        }
                         computed_value::ComputedOperation::Translate(ref tx, ref ty, ref tz) => {
                             // XXXManishearth we lose information here; perhaps we should try to
                             // recover the original function? Not sure if this can be observed.
                             result.push(SpecifiedOperation::Translate3D(
                                               ToComputedValue::from_computed_value(tx),
                                               ToComputedValue::from_computed_value(ty),
                                               ToComputedValue::from_computed_value(tz)));
                         }
@@ -1789,16 +1994,34 @@
                             ));
                         }
                     };
                 }
                 result
             }).unwrap_or(Vec::new()))
         }
     }
+
+    // Converts computed LengthOrPercentageOrNumber into computed
+    // LengthOrPercentage. Number maps into Length
+    fn lopon_to_lop(value: &ComputedLoPoNumber) -> ComputedLoP {
+        match *value {
+            Either::First(length_or_percentage) => length_or_percentage,
+            Either::Second(number) => ComputedLoP::Length(Au::from_f32_px(number)),
+        }
+    }
+
+    // Converts computed LengthOrNumber into computed Length.
+    // Number maps into Length.
+    fn lon_to_length(value: &ComputedLoN) -> ComputedLength {
+        match *value {
+            Either::First(length) => length,
+            Either::Second(number) => Au::from_f32_px(number),
+        }
+    }
 </%helpers:longhand>
 
 // CSSOM View Module
 // https://www.w3.org/TR/cssom-view-1/
 ${helpers.single_keyword("scroll-behavior",
                          "auto smooth",
                          products="gecko",
                          spec="https://drafts.csswg.org/cssom-view/#propdef-scroll-behavior",
@@ -1820,17 +2043,17 @@
 </%helpers:longhand>
 
 // Compositing and Blending Level 1
 // http://www.w3.org/TR/compositing-1/
 ${helpers.single_keyword("isolation",
                          "auto isolate",
                          products="gecko",
                          spec="https://drafts.fxtf.org/compositing/#isolation",
-                         creates_stacking_context=True,
+                         flags="CREATES_STACKING_CONTEXT",
                          animation_type="none")}
 
 // TODO add support for logical values recto and verso
 ${helpers.single_keyword("page-break-after",
                          "auto always avoid left right",
                          products="gecko",
                          spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-after",
                          animation_type="none")}
@@ -1859,18 +2082,17 @@
 
 ${helpers.predefined_type("perspective",
                           "LengthOrNone",
                           "Either::Second(None_)",
                           "parse_non_negative_length",
                           gecko_ffi_name="mChildPerspective",
                           spec="https://drafts.csswg.org/css-transforms/#perspective",
                           extra_prefixes="moz webkit",
-                          creates_stacking_context=True,
-                          fixpos_cb=True,
+                          flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
                           animation_type="normal")}
 
 <%helpers:longhand name="perspective-origin" boxed="True" animation_type="normal" extra_prefixes="moz webkit"
                    spec="https://drafts.csswg.org/css-transforms/#perspective-origin-property">
     use std::fmt;
     use style_traits::ToCss;
     use values::HasViewportPercentage;
     use values::specified::{LengthOrPercentage, Percentage};
@@ -1958,18 +2180,17 @@
                          animation_type="none")}
 
 // `auto` keyword is not supported in gecko yet.
 ${helpers.single_keyword("transform-style",
                          "auto flat preserve-3d" if product == "servo" else
                          "flat preserve-3d",
                          spec="https://drafts.csswg.org/css-transforms/#transform-style-property",
                          extra_prefixes="moz webkit",
-                         creates_stacking_context=True,
-                         fixpos_cb=True,
+                         flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
                          animation_type="none")}
 
 <%helpers:longhand name="transform-origin" animation_type="normal" extra_prefixes="moz webkit" boxed="True"
                    spec="https://drafts.csswg.org/css-transforms/#transform-origin-property">
     use app_units::Au;
     use std::fmt;
     use style_traits::ToCss;
     use values::HasViewportPercentage;
--- a/servo/components/style/properties/longhand/effects.mako.rs
+++ b/servo/components/style/properties/longhand/effects.mako.rs
@@ -6,17 +6,17 @@
 
 // Box-shadow, etc.
 <% data.new_style_struct("Effects", inherited=False) %>
 
 ${helpers.predefined_type("opacity",
                           "Opacity",
                           "1.0",
                           animation_type="normal",
-                          creates_stacking_context=True,
+                          flags="CREATES_STACKING_CONTEXT",
                           spec="https://drafts.csswg.org/css-color/#opacity")}
 
 <%helpers:vector_longhand name="box-shadow" allow_empty="True"
                           animation_type="normal" extra_prefixes="webkit"
                           spec="https://drafts.csswg.org/css-backgrounds/#box-shadow">
     use cssparser;
     use std::fmt;
     use style_traits::ToCss;
@@ -82,18 +82,17 @@
                           "ClipRectOrAuto",
                           "computed::ClipRectOrAuto::auto()",
                           animation_type="none",
                           boxed="True",
                           spec="https://drafts.fxtf.org/css-masking/#clip-property")}
 
 // FIXME: This prop should be animatable
 <%helpers:longhand name="filter" animation_type="none" extra_prefixes="webkit"
-                    creates_stacking_context="True"
-                    fixpos_cb="True"
+                   flags="CREATES_STACKING_CONTEXT FIXPOS_CB"
                    spec="https://drafts.fxtf.org/filters/#propdef-filter">
     //pub use self::computed_value::T as SpecifiedValue;
     use cssparser;
     use std::fmt;
     use style_traits::{self, ToCss};
     use values::{CSSFloat, HasViewportPercentage};
     use values::specified::{Angle, CSSColor, Length, Shadow};
     use values::specified::url::SpecifiedUrl;
@@ -521,10 +520,10 @@ pub fn parse_origin(context: &ParserCont
     }
 }
 
 ${helpers.single_keyword("mix-blend-mode",
                          """normal multiply screen overlay darken lighten color-dodge
                             color-burn hard-light soft-light difference exclusion hue
                             saturation color luminosity""", gecko_constant_prefix="NS_STYLE_BLEND",
                          animation_type="none",
-                         creates_stacking_context=True,
+                         flags="CREATES_STACKING_CONTEXT",
                          spec="https://drafts.fxtf.org/compositing/#propdef-mix-blend-mode")}
--- a/servo/components/style/properties/longhand/position.mako.rs
+++ b/servo/components/style/properties/longhand/position.mako.rs
@@ -21,19 +21,20 @@
                               "computed::LengthOrPercentageOrAuto::Auto",
                               spec="https://drafts.csswg.org/css-logical-props/#propdef-offset-%s" % side,
                               animation_type="normal", logical=True)}
 % endfor
 
 ${helpers.predefined_type("z-index", "IntegerOrAuto",
                           "Either::Second(Auto)",
                           spec="https://www.w3.org/TR/CSS2/visuren.html#z-index",
-                          creates_stacking_context=True,
+                          flags="CREATES_STACKING_CONTEXT",
                           animation_type="normal")}
 
+
 // CSS Flexible Box Layout Module Level 1
 // http://www.w3.org/TR/css3-flexbox/
 
 // Flex container properties
 ${helpers.single_keyword("flex-direction", "row row-reverse column column-reverse",
                          spec="https://drafts.csswg.org/css-flexbox/#flex-direction-property",
                          extra_prefixes="webkit", animation_type="none")}
 
--- a/servo/components/style/properties/longhand/svg.mako.rs
+++ b/servo/components/style/properties/longhand/svg.mako.rs
@@ -54,17 +54,17 @@
 
 // CSS Masking Module Level 1
 // https://drafts.fxtf.org/css-masking
 ${helpers.single_keyword("mask-type", "luminance alpha",
                          products="gecko", animation_type="none",
                          spec="https://drafts.fxtf.org/css-masking/#propdef-mask-type")}
 
 <%helpers:longhand name="clip-path" animation_type="none" products="gecko" boxed="True"
-                   creates_stacking_context="True"
+                   flags="CREATES_STACKING_CONTEXT"
                    spec="https://drafts.fxtf.org/css-masking/#propdef-clip-path">
     use std::fmt;
     use style_traits::ToCss;
     use values::HasViewportPercentage;
     use values::specified::basic_shape::{ShapeSource, GeometryBox};
 
     pub mod computed_value {
         use app_units::Au;
@@ -195,17 +195,17 @@
                          vector=True,
                          products="gecko",
                          extra_prefixes="webkit",
                          animation_type="none",
                          spec="https://drafts.fxtf.org/css-masking/#propdef-mask-composite")}
 
 <%helpers:vector_longhand name="mask-image" products="gecko" animation_type="none" extra_prefixes="webkit"
                           has_uncacheable_values="${product == 'gecko'}"
-                          creates_stacking_context="True"
+                          flags="CREATES_STACKING_CONTEXT",
                           spec="https://drafts.fxtf.org/css-masking/#propdef-mask-image">
     use std::fmt;
     use style_traits::ToCss;
     use std::sync::Arc;
     use values::specified::Image;
     use values::specified::url::SpecifiedUrl;
     use values::HasViewportPercentage;
 
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -464,23 +464,25 @@ impl Parse for CSSWideKeyword {
         CSSWideKeyword::from_ident(&ident).ok_or(())
     }
 }
 
 bitflags! {
     /// A set of flags for properties.
     pub flags PropertyFlags: u8 {
         /// This property requires a stacking context.
-        const CREATES_STACKING_CONTEXT = 0x01,
+        const CREATES_STACKING_CONTEXT = 1 << 0,
         /// This property has values that can establish a containing block for
         /// fixed positioned and absolutely positioned elements.
-        const FIXPOS_CB = 0x02,
+        const FIXPOS_CB = 1 << 1,
         /// This property has values that can establish a containing block for
         /// absolutely positioned elements.
-        const ABSPOS_CB = 0x04,
+        const ABSPOS_CB = 1 << 2,
+        /// This property(shorthand) is an alias of another property.
+        const ALIAS_PROPERTY = 1 << 3,
     }
 }
 
 /// An identifier for a given longhand property.
 #[derive(Clone, Copy, Eq, PartialEq, Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub enum LonghandId {
     % for i, property in enumerate(data.longhands):
@@ -513,30 +515,24 @@ impl LonghandId {
                         </%helpers:logical_setter_helper>
                     }
                 % endif
             % endfor
             _ => *self
         }
     }
 
-    /// Returns PropertyFlags for given property.
+    /// Returns PropertyFlags for given longhand property.
     pub fn flags(&self) -> PropertyFlags {
         match *self {
             % for property in data.longhands:
                 LonghandId::${property.camel_case} =>
-                    %if property.creates_stacking_context:
-                        CREATES_STACKING_CONTEXT |
-                    %endif
-                    %if property.fixpos_cb:
-                        FIXPOS_CB |
-                    %endif
-                    %if property.abspos_cb:
-                        ABSPOS_CB |
-                    %endif
+                    % for flag in property.flags:
+                        ${flag} |
+                    % endfor
                     PropertyFlags::empty(),
             % endfor
         }
     }
 }
 
 /// An identifier for a given shorthand property.
 #[derive(Clone, Copy, Eq, PartialEq, Debug)]
@@ -653,16 +649,29 @@ impl ShorthandId {
 
         // Check whether all declarations can be serialized as part of shorthand.
         if declarations3.all(|d| d.may_serialize_as_part_of_shorthand()) {
             return Some(AppendableValue::DeclarationsForShorthand(self, declarations));
         }
 
         None
     }
+
+    /// Returns PropertyFlags for given shorthand property.
+    pub fn flags(&self) -> PropertyFlags {
+        match *self {
+            % for property in data.shorthands:
+                ShorthandId::${property.camel_case} =>
+                    % for flag in property.flags:
+                        ${flag} |
+                    % endfor
+                    PropertyFlags::empty(),
+            % endfor
+        }
+    }
 }
 
 /// Servo's representation of a declared value for a given `T`, which is the
 /// declared value for that property.
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub enum DeclaredValue<'a, T: 'a> {
     /// A known specified value from the stylesheet.
     Value(&'a T),
--- a/servo/components/style/properties/shorthand/box.mako.rs
+++ b/servo/components/style/properties/shorthand/box.mako.rs
@@ -283,8 +283,28 @@ macro_rules! try_parse_one {
             if self.scroll_snap_type_x == self.scroll_snap_type_y {
                 self.scroll_snap_type_x.to_css(dest)
             } else {
                 Ok(())
             }
         }
     }
 </%helpers:shorthand>
+
+
+<%helpers:shorthand name="-moz-transform" products="gecko"
+                    sub_properties="transform"
+                    flags="ALIAS_PROPERTY"
+                    spec="Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/transform">
+    use properties::longhands::transform;
+
+    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
+        Ok(Longhands {
+            transform: transform::parse_prefixed(context, input)?,
+        })
+    }
+
+    impl<'a> ToCss for LonghandsToSerialize<'a>  {
+        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+            self.transform.to_css(dest)
+        }
+    }
+</%helpers:shorthand>
--- a/toolkit/components/telemetry/TelemetryEnvironment.jsm
+++ b/toolkit/components/telemetry/TelemetryEnvironment.jsm
@@ -619,16 +619,17 @@ EnvironmentAddonBuilder.prototype = {
           scope: addon.scope,
           type: addon.type,
           foreignInstall: enforceBoolean(addon.foreignInstall),
           hasBinaryComponents: addon.hasBinaryComponents,
           installDay: Utils.millisecondsToDays(installDate.getTime()),
           updateDay: Utils.millisecondsToDays(updateDate.getTime()),
           signedState: addon.signedState,
           isSystem: addon.isSystem,
+          isWebExtension: addon.isWebExtension,
         };
 
         if (addon.signedState !== undefined)
           activeAddons[addon.id].signedState = addon.signedState;
 
       } catch (ex) {
         this._environment._log.error("_getActiveAddons - An addon was discarded due to an error", ex);
         continue;
--- a/toolkit/components/telemetry/docs/data/environment.rst
+++ b/toolkit/components/telemetry/docs/data/environment.rst
@@ -208,16 +208,17 @@ Structure:
             scope: <integer>,
             type: <string>, // "extension", "service", ...
             foreignInstall: <bool>,
             hasBinaryComponents: <bool>
             installDay: <number>, // days since UNIX epoch, 0 on failure
             updateDay: <number>, // days since UNIX epoch, 0 on failure
             signedState: <integer>, // whether the add-on is signed by AMO, only present for extensions
             isSystem: <bool>, // true if this is a System Add-on
+            isWebExtension: <bool>, // true if this is a WebExtension
           },
           ...
         },
         theme: { // the active theme
           id: <string>,
           blocklisted: <bool>,
           description: <string>,
           name: <string>,
--- a/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
@@ -17,16 +17,19 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 
 // Lazy load |LightweightThemeManager|.
 XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
                                   "resource://gre/modules/LightweightThemeManager.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ProfileAge",
                                   "resource://gre/modules/ProfileAge.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "ExtensionTestUtils",
+                                  "resource://testing-common/ExtensionXPCShellUtils.jsm");
+
 // The webserver hosting the addons.
 var gHttpServer = null;
 // The URL of the webserver root.
 var gHttpRoot = null;
 // The URL of the data directory, on the webserver.
 var gDataRoot = null;
 
 const PLATFORM_VERSION = "1.9.2";
@@ -667,16 +670,17 @@ function checkActiveAddon(data) {
     scope: "number",
     type: "string",
     foreignInstall: "boolean",
     hasBinaryComponents: "boolean",
     installDay: "number",
     updateDay: "number",
     signedState,
     isSystem: "boolean",
+    isWebExtension: "boolean",
   };
 
   for (let f in EXPECTED_ADDON_FIELDS_TYPES) {
     Assert.ok(f in data, f + " must be available.");
     Assert.equal(typeof data[f], EXPECTED_ADDON_FIELDS_TYPES[f],
                  f + " must have the correct type.");
   }
 
@@ -1121,16 +1125,17 @@ add_task(function* test_addonsAndPlugins
     scope: 1,
     type: "extension",
     foreignInstall: false,
     hasBinaryComponents: false,
     installDay: ADDON_INSTALL_DATE,
     updateDay: ADDON_INSTALL_DATE,
     signedState: mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED,
     isSystem: false,
+    isWebExtension: false,
   };
   const SYSTEM_ADDON_ID = "tel-system-xpi@tests.mozilla.org";
   const EXPECTED_SYSTEM_ADDON_DATA = {
     blocklisted: false,
     description: "A system addon which is shipped with Firefox.",
     name: "XPI Telemetry System Add-on Test",
     userDisabled: false,
     appDisabled: false,
@@ -1138,30 +1143,80 @@ add_task(function* test_addonsAndPlugins
     scope: 1,
     type: "extension",
     foreignInstall: false,
     hasBinaryComponents: false,
     installDay: truncateToDays(SYSTEM_ADDON_INSTALL_DATE),
     updateDay: truncateToDays(SYSTEM_ADDON_INSTALL_DATE),
     signedState: undefined,
     isSystem: true,
+    isWebExtension: false,
+  };
+
+  const WEBEXTENSION_ADDON_ID = "tel-webextension-xpi@tests.mozilla.org";
+  const WEBEXTENSION_ADDON_INSTALL_DATE = truncateToDays(Date.now());
+  const EXPECTED_WEBEXTENSION_ADDON_DATA = {
+    blocklisted: false,
+    description: "A webextension addon.",
+    name: "XPI Telemetry WebExtension Add-on Test",
+    userDisabled: false,
+    appDisabled: false,
+    version: "1.0",
+    scope: 1,
+    type: "extension",
+    foreignInstall: false,
+    hasBinaryComponents: false,
+    installDay: WEBEXTENSION_ADDON_INSTALL_DATE,
+    updateDay: WEBEXTENSION_ADDON_INSTALL_DATE,
+    signedState: mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_SIGNED : AddonManager.SIGNEDSTATE_NOT_REQUIRED,
+    isSystem: false,
+    isWebExtension: true,
   };
 
   const EXPECTED_PLUGIN_DATA = {
     name: FLASH_PLUGIN_NAME,
     version: FLASH_PLUGIN_VERSION,
     description: FLASH_PLUGIN_DESC,
     blocklisted: false,
     disabled: false,
     clicktoplay: true,
   };
 
-  // Install an addon so we have some data.
+  let deferred = PromiseUtils.defer();
+  TelemetryEnvironment.registerChangeListener("test_WebExtension",
+    (reason, data) => {
+      Assert.equal(reason, "addons-changed");
+      deferred.resolve();
+    }
+  );
+
+  // Install an add-on so we have some data.
   yield AddonManagerTesting.installXPIFromURL(ADDON_INSTALL_URL);
 
+  // Install a webextension as well.
+  ExtensionTestUtils.init(this);
+
+  let webextension = ExtensionTestUtils.loadExtension({
+    useAddonManager: "permanent",
+    manifest: {
+      "name": "XPI Telemetry WebExtension Add-on Test",
+      "description": "A webextension addon.",
+      "version": "1.0",
+      "applications": {
+        "gecko": {
+          "id": WEBEXTENSION_ADDON_ID,
+        },
+      },
+    },
+  });
+
+  yield webextension.startup();
+  yield deferred.promise;
+  TelemetryEnvironment.unregisterChangeListener("test_WebExtension");
+
   let data = TelemetryEnvironment.currentEnvironment;
   checkEnvironmentData(data);
 
   // Check addon data.
   Assert.ok(ADDON_ID in data.addons.activeAddons, "We must have one active addon.");
   let targetAddon = data.addons.activeAddons[ADDON_ID];
   for (let f in EXPECTED_ADDON_DATA) {
     Assert.equal(targetAddon[f], EXPECTED_ADDON_DATA[f], f + " must have the correct value.");
@@ -1169,16 +1224,25 @@ add_task(function* test_addonsAndPlugins
 
   // Check system add-on data.
   Assert.ok(SYSTEM_ADDON_ID in data.addons.activeAddons, "We must have one active system addon.");
   let targetSystemAddon = data.addons.activeAddons[SYSTEM_ADDON_ID];
   for (let f in EXPECTED_SYSTEM_ADDON_DATA) {
     Assert.equal(targetSystemAddon[f], EXPECTED_SYSTEM_ADDON_DATA[f], f + " must have the correct value.");
   }
 
+  // Check webextension add-on data.
+  Assert.ok(WEBEXTENSION_ADDON_ID in data.addons.activeAddons, "We must have one active webextension addon.");
+  let targetWebExtensionAddon = data.addons.activeAddons[WEBEXTENSION_ADDON_ID];
+  for (let f in EXPECTED_WEBEXTENSION_ADDON_DATA) {
+    Assert.equal(targetWebExtensionAddon[f], EXPECTED_WEBEXTENSION_ADDON_DATA[f], f + " must have the correct value.");
+  }
+
+  yield webextension.unload();
+
   // Check theme data.
   let theme = data.addons.theme;
   Assert.equal(theme.id, (PERSONA_ID + PERSONA_ID_SUFFIX));
   Assert.equal(theme.name, PERSONA_NAME);
   Assert.equal(theme.description, PERSONA_DESCRIPTION);
 
   // Check plugin data.
   Assert.equal(data.addons.activePlugins.length, 1, "We must have only one active plugin.");
--- a/toolkit/mozapps/extensions/internal/AddonRepository.jsm
+++ b/toolkit/mozapps/extensions/internal/AddonRepository.jsm
@@ -116,37 +116,47 @@ function convertHTMLToPlainText(html) {
   converter.convert("text/html", input, input.data.length, "text/unicode",
                     output, {});
 
   if (output.value instanceof Ci.nsISupportsString)
     return output.value.data.replace(/\r\n/g, "\n");
   return html;
 }
 
-function getAddonsToCache(aIds) {
+async function getAddonsToCache(aIds) {
   let types = Preferences.get(PREF_GETADDONS_CACHE_TYPES) || DEFAULT_CACHE_TYPES;
 
   types = types.split(",");
 
-  return AddonManager.getAddonsByIDs(aIds).then(addons => {
-    let enabledIds = [];
-    for (let [i, addon] of addons.entries()) {
-      var preference = PREF_GETADDONS_CACHE_ID_ENABLED.replace("%ID%", aIds[i]);
-      // If the preference doesn't exist caching is enabled by default
-      if (!Preferences.get(preference, true))
-        continue;
+  let addons = await AddonManager.getAddonsByIDs(aIds)
+  let enabledIds = [];
 
-      // The add-ons manager may not know about this ID yet if it is a pending
-      // install. In that case we'll just cache it regardless
-      if (!addon || types.includes(addon.type))
-        enabledIds.push(aIds[i]);
+  for (let [i, addon] of addons.entries()) {
+    var preference = PREF_GETADDONS_CACHE_ID_ENABLED.replace("%ID%", aIds[i]);
+    // If the preference doesn't exist caching is enabled by default
+    if (!Preferences.get(preference, true))
+      continue;
+
+    // The add-ons manager may not know about this ID yet if it is a pending
+    // install. In that case we'll just cache it regardless
+
+    // Don't cache add-ons of the wrong types
+    if (addon && !types.includes(addon.type)) {
+      continue;
     }
 
-    return enabledIds;
-  });
+    // Don't cache system add-ons
+    if (addon && addon.isSystem) {
+      continue;
+    }
+
+    enabledIds.push(aIds[i]);
+  }
+
+  return enabledIds;
 }
 
 function AddonSearchResult(aId) {
   this.id = aId;
   this.icons = {};
   this._unsupportedProperties = {};
 }
 
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_repository.js
@@ -0,0 +1,52 @@
+// Tests that AddonRepository doesn't download results for system add-ons
+
+const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled";
+
+BootstrapMonitor.init();
+
+Components.utils.import("resource://testing-common/httpd.js");
+var gServer = new HttpServer();
+gServer.start(-1);
+
+// Build the test set
+var distroDir = FileUtils.getDir("ProfD", ["sysfeatures"], true);
+do_get_file("data/system_addons/system1_1.xpi").copyTo(distroDir, "system1@tests.mozilla.org.xpi");
+do_get_file("data/system_addons/system2_1.xpi").copyTo(distroDir, "system2@tests.mozilla.org.xpi");
+do_get_file("data/system_addons/system3_1.xpi").copyTo(distroDir, "system3@tests.mozilla.org.xpi");
+registerDirectory("XREAppFeat", distroDir);
+
+createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "0");
+
+function getCachedAddon(id) {
+  return new Promise(resolve => AddonRepository.getCachedAddonByID(id, resolve));
+}
+
+// Test with a missing features directory
+add_task(function* test_app_addons() {
+  Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true);
+  Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, `http://localhost:${gServer.identity.primaryPort}/get?%IDS%`);
+
+  gServer.registerPathHandler("/get", (request, response) => {
+    do_throw("Unexpected request to server.");
+  });
+
+  startupManager();
+
+  yield new Promise((resolve) => {
+    AddonRepository.cacheAddons(["system1@tests.mozilla.org",
+                                 "system2@tests.mozilla.org",
+                                 "system3@tests.mozilla.org"], resolve);
+  });
+
+  let cached = yield getCachedAddon("system1@tests.mozilla.org");
+  do_check_eq(cached, null);
+
+  cached = yield getCachedAddon("system2@tests.mozilla.org");
+  do_check_eq(cached, null);
+
+  cached = yield getCachedAddon("system3@tests.mozilla.org");
+  do_check_eq(cached, null);
+
+  yield promiseShutdownManager();
+  yield new Promise(resolve => gServer.stop(resolve));
+});
--- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
+++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
@@ -27,16 +27,17 @@ tags = blocklist
 [test_provider_markSafe.js]
 [test_provider_shutdown.js]
 [test_provider_unsafe_access_shutdown.js]
 [test_provider_unsafe_access_startup.js]
 [test_ProductAddonChecker.js]
 [test_shutdown.js]
 [test_system_update.js]
 [test_system_update_fail.js]
+[test_system_repository.js]
 [test_system_reset.js]
 [test_XPIcancel.js]
 [test_XPIStates.js]
 [test_temporary.js]
 tags = webextensions
 [test_install_from_sources.js]
 [test_proxies.js]
 [test_proxy.js]