Backed out 10 changesets (bug 550426) for failures in browser_css_autocompletion.js
authorWes Kocher <wkocher@mozilla.com>
Fri, 29 Apr 2016 14:47:43 -0700
changeset 295554 2e2c516bd64f8669e22660afbc76f273d6508266
parent 295553 b498e6f7c6b03c7ea7217e8cec7edb178bd0ea07
child 295555 74ad7376f37fbdbb3f5515970181548dbf1dfa2a
push id19015
push usercbook@mozilla.com
push dateMon, 02 May 2016 09:39:23 +0000
treeherderfx-team@2080375bc69d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs550426
milestone49.0a1
backs out6ff2e12738caf72a99ed0156b1da87cb1948570b
10ee68fd318edf36cace00236ec3614f70f0f855
324f4f602730ee0724b3e41e64491ebe49eb0931
81306e78ccaab15b911a55bb1a4344537c7774ae
44b820f6fb3d217edf1db7c9cfb97ee15aa17678
987b6ff7262eea42bc69b9c58b8e5369a4c298a1
d505646974c707a4464461e364b088712521e6c0
2162ecc18859471f8071fd3b499280154783731f
1a030aba3acca5c4580ec1e68f347e0e144cc012
3655883e7faf15a858aca4bc4cfed506761c26ee
Backed out 10 changesets (bug 550426) for failures in browser_css_autocompletion.js Backed out changeset 6ff2e12738ca (bug 550426) Backed out changeset 10ee68fd318e (bug 550426) Backed out changeset 324f4f602730 (bug 550426) Backed out changeset 81306e78ccaa (bug 550426) Backed out changeset 44b820f6fb3d (bug 550426) Backed out changeset 987b6ff7262e (bug 550426) Backed out changeset d505646974c7 (bug 550426) Backed out changeset 2162ecc18859 (bug 550426) Backed out changeset 1a030aba3acc (bug 550426) Backed out changeset 3655883e7faf (bug 550426) MozReview-Commit-ID: AlUihrLtlhL
devtools/client/animationinspector/test/browser_animation_animated_properties_displayed.js
layout/base/ActiveLayerTracker.cpp
layout/base/ActiveLayerTracker.h
layout/base/nsDisplayList.cpp
layout/inspector/inDOMUtils.cpp
layout/reftests/backgrounds/background-position-1d.html
layout/reftests/backgrounds/background-position-1e.html
layout/reftests/backgrounds/background-position-1f.html
layout/reftests/backgrounds/background-position-2a.html
layout/reftests/backgrounds/background-position-2c.html
layout/reftests/backgrounds/background-position-2d.html
layout/reftests/backgrounds/background-position-3c.html
layout/reftests/backgrounds/background-position-3d.html
layout/reftests/backgrounds/background-position-4d.html
layout/reftests/backgrounds/background-position-4e.html
layout/reftests/backgrounds/background-position-6.html
layout/reftests/backgrounds/background-position-6a.html
layout/reftests/backgrounds/background-position-6b.html
layout/reftests/backgrounds/reftest.list
layout/style/Declaration.cpp
layout/style/Declaration.h
layout/style/StyleAnimationValue.cpp
layout/style/StyleAnimationValue.h
layout/style/nsCSSParser.cpp
layout/style/nsCSSPropAliasList.h
layout/style/nsCSSPropList.h
layout/style/nsCSSProps.cpp
layout/style/nsCSSValue.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
layout/style/nsComputedDOMStylePropertyList.h
layout/style/nsDOMCSSAttrDeclaration.cpp
layout/style/nsDOMCSSDeclaration.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/style/test/property_database.js
layout/style/test/test_shorthand_property_getters.html
layout/style/test/test_transitions_per_property.html
--- a/devtools/client/animationinspector/test/browser_animation_animated_properties_displayed.js
+++ b/devtools/client/animationinspector/test/browser_animation_animated_properties_displayed.js
@@ -4,18 +4,17 @@
 
 "use strict";
 
 // Test that when an animation is selected, its list of animated properties is
 // displayed below it.
 
 const EXPECTED_PROPERTIES = [
   "background-color",
-  "background-position-x",
-  "background-position-y",
+  "background-position",
   "background-size",
   "border-bottom-left-radius",
   "border-bottom-right-radius",
   "border-top-left-radius",
   "border-top-right-radius",
   "filter",
   "height",
   "transform",
--- a/layout/base/ActiveLayerTracker.cpp
+++ b/layout/base/ActiveLayerTracker.cpp
@@ -80,18 +80,16 @@ public:
     case eCSSProperty_top: return ACTIVITY_TOP;
     case eCSSProperty_right: return ACTIVITY_RIGHT;
     case eCSSProperty_bottom: return ACTIVITY_BOTTOM;
     case eCSSProperty_margin_left: return ACTIVITY_MARGIN_LEFT;
     case eCSSProperty_margin_top: return ACTIVITY_MARGIN_TOP;
     case eCSSProperty_margin_right: return ACTIVITY_MARGIN_RIGHT;
     case eCSSProperty_margin_bottom: return ACTIVITY_MARGIN_BOTTOM;
     case eCSSProperty_background_position: return ACTIVITY_BACKGROUND_POSITION;
-    case eCSSProperty_background_position_x: return ACTIVITY_BACKGROUND_POSITION;
-    case eCSSProperty_background_position_y: return ACTIVITY_BACKGROUND_POSITION;
     default: MOZ_ASSERT(false); return ACTIVITY_OPACITY;
     }
   }
 
   // While tracked, exactly one of mFrame or mContent is non-null, depending
   // on whether this property is stored on a frame or on a content node.
   // When this property is expired by the layer activity tracker, both mFrame
   // and mContent are nulled-out and the property is deleted.
@@ -381,24 +379,16 @@ ActiveLayerTracker::NotifyInlineStyleRul
 }
 
 /* static */ bool
 ActiveLayerTracker::IsStyleMaybeAnimated(nsIFrame* aFrame, nsCSSProperty aProperty)
 {
   return IsStyleAnimated(nullptr, aFrame, aProperty);
 }
 
-/* static */ bool
-ActiveLayerTracker::IsBackgroundPositionAnimated(nsDisplayListBuilder* aBuilder,
-                                                 nsIFrame* aFrame)
-{
-  return IsStyleAnimated(aBuilder, aFrame, eCSSProperty_background_position_x) ||
-         IsStyleAnimated(aBuilder, aFrame, eCSSProperty_background_position_y);
-}
-
 static bool
 CheckScrollInducedActivity(LayerActivity* aLayerActivity,
                            LayerActivity::ActivityIndex aActivityIndex,
                            nsDisplayListBuilder* aBuilder)
 {
   if (!aLayerActivity->mScrollHandlerInducedActivity.contains(aActivityIndex) ||
       !aLayerActivity->mAnimatingScrollHandlerFrame.IsAlive()) {
     return false;
--- a/layout/base/ActiveLayerTracker.h
+++ b/layout/base/ActiveLayerTracker.h
@@ -82,22 +82,17 @@ public:
    */
   static bool IsStyleAnimated(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                               nsCSSProperty aProperty);
   /**
    * Return true if any of aFrame's offset property styles should be considered
    * as being animated for constructing active layers.
    */
   static bool IsOffsetOrMarginStyleAnimated(nsIFrame* aFrame);
-  /**
-   * Return true if aFrame's background-position-x or background-position-y
-   * property is animated.
-   */
-  static bool IsBackgroundPositionAnimated(nsDisplayListBuilder* aBuilder,
-                                           nsIFrame* aFrame);
+
   /**
    * Return true if aFrame either has an animated scale now, or is likely to
    * have one in the future because it has a CSS animation or transition
    * (which may not be playing right now) that affects its scale.
    */
   static bool IsScaleSubjectToAnimation(nsIFrame* aFrame);
 
   /**
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2648,18 +2648,18 @@ nsDisplayBackgroundImage::GetImage()
   return image.forget();
 }
 
 nsDisplayBackgroundImage::ImageLayerization
 nsDisplayBackgroundImage::ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder,
                                                LayerManager* aManager)
 {
   nsIFrame* backgroundStyleFrame = nsCSSRendering::FindBackgroundStyleFrame(mFrame);
-  if (ActiveLayerTracker::IsBackgroundPositionAnimated(aBuilder,
-                                                       backgroundStyleFrame)) {
+  if (ActiveLayerTracker::IsStyleAnimated(aBuilder, backgroundStyleFrame,
+                                          eCSSProperty_background_position)) {
     return WHENEVER_POSSIBLE;
   }
 
   if (nsLayoutUtils::AnimatedImageLayersEnabled() && mBackgroundStyle) {
     const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mImage.mLayers[mLayer];
     const nsStyleImage* image = &layer.mImage;
     if (image->GetType() == eStyleImageType_Image) {
       imgIRequest* imgreq = image->GetImageData();
--- a/layout/inspector/inDOMUtils.cpp
+++ b/layout/inspector/inDOMUtils.cpp
@@ -769,23 +769,19 @@ PropertySupportsVariant(nsCSSProperty aP
         supported = VARIANT_LPN;
         break;
 
       case eCSSProperty_border_top_left_radius:
       case eCSSProperty_border_top_right_radius:
       case eCSSProperty_border_bottom_left_radius:
       case eCSSProperty_border_bottom_right_radius:
       case eCSSProperty_background_position:
-      case eCSSProperty_background_position_x:
-      case eCSSProperty_background_position_y:
       case eCSSProperty_background_size:
 #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
       case eCSSProperty_mask_position:
-      case eCSSProperty_mask_position_x:
-      case eCSSProperty_mask_position_y:
       case eCSSProperty_mask_size:
 #endif
       case eCSSProperty_grid_auto_columns:
       case eCSSProperty_grid_auto_rows:
       case eCSSProperty_grid_template_columns:
       case eCSSProperty_grid_template_rows:
       case eCSSProperty_object_position:
       case eCSSProperty_scroll_snap_coordinate:
deleted file mode 100644
--- a/layout/reftests/backgrounds/background-position-1d.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>background-position: right 25% bottom 75%</title>
-  <style type="text/css">
-#outer
-{
-  border: 1px solid black;
-  width: 128px;
-  height: 128px;
-}
-#inner1
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: right 25%;
-  background-position-y: bottom 75%;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-#inner2
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: right 25%;
-  background-position-y: bottom 75%;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-#inner3
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: right 24px;
-  background-position-y: bottom 72px;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-#inner4
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: right 24px;
-  background-position-y: bottom 72px;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-  </style>
-</head>
-<body>
-<div id="outer"><div id="inner1"></div></div>
-<div id="outer"><div id="inner2"></div></div>
-<div id="outer"><div id="inner3"></div></div>
-<div id="outer"><div id="inner4"></div></div>
-</body>
-</html>
deleted file mode 100644
--- a/layout/reftests/backgrounds/background-position-1e.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>background-position: left 75% top 25%</title>
-  <style type="text/css">
-#outer
-{
-  border: 1px solid black;
-  width: 128px;
-  height: 128px;
-}
-#inner1
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: left 75%;
-  background-position-y: top 25%;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-#inner2
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: left 75%;
-  background-position-y: top 25%;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-#inner3
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: left 72px;
-  background-position-y: top 24px;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-#inner4
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: left 72px;
-  background-position-y: top 24px;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-  </style>
-</head>
-<body>
-<div id="outer"><div id="inner1"></div></div>
-<div id="outer"><div id="inner2"></div></div>
-<div id="outer"><div id="inner3"></div></div>
-<div id="outer"><div id="inner4"></div></div>
-</body>
-</html>
deleted file mode 100644
--- a/layout/reftests/backgrounds/background-position-1f.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>background-position: left 75% bottom 75%</title>
-  <style type="text/css">
-#outer
-{
-  border: 1px solid black;
-  width: 128px;
-  height: 128px;
-}
-#inner1
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: left 75%;
-  background-position-y: bottom 75%;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-#inner2
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: right 25%;
-  background-position-y: top 25%;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-#inner3
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: left 75%;
-  background-position-y: bottom 75%;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-#inner4
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: right 25%;
-  background-position-y: top 25%;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-  </style>
-</head>
-<body>
-<div id="outer"><div id="inner1"></div></div>
-<div id="outer"><div id="inner2"></div></div>
-<div id="outer"><div id="inner3"></div></div>
-<div id="outer"><div id="inner4"></div></div>
-</body>
-</html>
--- a/layout/reftests/backgrounds/background-position-2a.html
+++ b/layout/reftests/backgrounds/background-position-2a.html
@@ -1,12 +1,12 @@
 <!DOCTYPE html>
 <html>
 <head>
-  <title>background-position: left 25% bottom 75%</title>
+  <title>background-position: center bottom 75%</title>
   <style type="text/css">
 #outer
 {
   border: 1px solid black;
   width: 128px;
   height: 128px;
 }
 #inner1
deleted file mode 100644
--- a/layout/reftests/backgrounds/background-position-2c.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>background-position: left 25% bottom 75%</title>
-  <style type="text/css">
-#outer
-{
-  border: 1px solid black;
-  width: 128px;
-  height: 128px;
-}
-#inner1
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: left 25%;
-  background-position-y: bottom 75%;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-  </style>
-</head>
-<body>
-<div id="outer"><div id="inner1"></div></div>
-</body>
-</html>
deleted file mode 100644
--- a/layout/reftests/backgrounds/background-position-2d.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>background-position: 25% 25%</title>
-  <style type="text/css">
-#outer
-{
-  border: 1px solid black;
-  width: 128px;
-  height: 128px;
-}
-#inner1
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: 25%;
-  background-position-y: 25%;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-  </style>
-</head>
-<body>
-<div id="outer"><div id="inner1"></div></div>
-</body>
-</html>
deleted file mode 100644
--- a/layout/reftests/backgrounds/background-position-3c.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>background-position: center bottom 75%</title>
-  <style type="text/css">
-#outer
-{
-  border: 1px solid black;
-  width: 128px;
-  height: 128px;
-}
-#inner1
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: center;
-  background-position-y: bottom 75%;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-  </style>
-</head>
-<body>
-<div id="outer"><div id="inner1"></div></div>
-</body>
-</html>
deleted file mode 100644
--- a/layout/reftests/backgrounds/background-position-3d.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>background-position: center 25%</title>
-  <style type="text/css">
-#outer
-{
-  border: 1px solid black;
-  width: 128px;
-  height: 128px;
-}
-#inner1
-{
-  width: 128px;
-  height: 128px;
-  background-position-x: center;
-  background-position-y: 25%;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-  </style>
-</head>
-<body>
-<div id="outer"><div id="inner1"></div></div>
-</body>
-</html>
deleted file mode 100644
--- a/layout/reftests/backgrounds/background-position-4d.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>background-position-y: bottom 50%</title>
-  <style type="text/css">
-#outer
-{
-  border: 1px solid black;
-  width: 128px;
-  height: 128px;
-}
-#inner1
-{
-  width: 128px;
-  height: 128px;
-  background-position-y: bottom 50%;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-  </style>
-</head>
-<body>
-<div id="outer"><div id="inner1"></div></div>
-</body>
-</html>
deleted file mode 100644
--- a/layout/reftests/backgrounds/background-position-4e.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>background-position-y: center</title>
-  <style type="text/css">
-#outer
-{
-  border: 1px solid black;
-  width: 128px;
-  height: 128px;
-}
-#inner1
-{
-  width: 128px;
-  height: 128px;
-  background-position-y: center;
-  background-image: url(aqua-32x32.png);
-  background-repeat: no-repeat;
-}
-  </style>
-</head>
-<body>
-<div id="outer"><div id="inner1"></div></div>
-</body>
-</html>
rename from layout/reftests/backgrounds/background-position-6b.html
rename to layout/reftests/backgrounds/background-position-6.html
--- a/layout/reftests/backgrounds/background-position-6b.html
+++ b/layout/reftests/backgrounds/background-position-6.html
@@ -1,25 +1,24 @@
 <!DOCTYPE html>
 <html>
 <head>
-  <title>background-position-y: top, bottom</title>
+  <title>background-position: top, bottom</title>
   <style type="text/css">
 #outer
 {
   border: 1px solid black;
   width: 128px;
   height: 128px;
 }
 #inner1
 {
   width: 128px;
   height: 128px;
-  background-position: top; /* sets background-position-x to center */
-  background-position-y: top, bottom;
+  background-position: top, bottom;
   background-image: url(aqua-32x32.png), url(aqua-32x32.png);
   background-repeat: no-repeat, no-repeat;
 }
   </style>
 </head>
 <body>
 <div id="outer"><div id="inner1"></div></div>
 </body>
deleted file mode 100644
--- a/layout/reftests/backgrounds/background-position-6a.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>background-position: top, bottom</title>
-  <style type="text/css">
-#outer
-{
-  border: 1px solid black;
-  width: 128px;
-  height: 128px;
-}
-#inner1
-{
-  width: 128px;
-  height: 128px;
-  background-position: top, bottom;
-  background-image: url(aqua-32x32.png), url(aqua-32x32.png);
-  background-repeat: no-repeat, no-repeat;
-}
-  </style>
-</head>
-<body>
-<div id="outer"><div id="inner1"></div></div>
-</body>
-</html>
--- a/layout/reftests/backgrounds/reftest.list
+++ b/layout/reftests/backgrounds/reftest.list
@@ -30,35 +30,25 @@ skip-if(B2G||Mulet) == continuous-inline
 == background-redraw-237766.html background-redraw-237766-ref.html
 
 == background-clip-1.html background-clip-1-ref.html
 == background-clip-2.html background-clip-2-ref.html
 
 skip-if(B2G||Mulet) == background-position-1a.html background-position-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 == background-position-1b.html background-position-1-ref.html
 == background-position-1c.html background-position-1-ref.html
-skip-if(B2G||Mulet) == background-position-1d.html background-position-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
-== background-position-1e.html background-position-1-ref.html
-== background-position-1f.html background-position-1-ref.html
 == background-position-2a.html background-position-2-ref.html
 == background-position-2b.html background-position-2-ref.html
-== background-position-2c.html background-position-2-ref.html
-== background-position-2d.html background-position-2-ref.html
 == background-position-3a.html background-position-3-ref.html
 == background-position-3b.html background-position-3-ref.html
-== background-position-3c.html background-position-3-ref.html
-== background-position-3d.html background-position-3-ref.html
 == background-position-4a.html background-position-4-ref.html
 == background-position-4b.html background-position-4-ref.html
 == background-position-4c.html background-position-4-ref.html
-== background-position-4d.html background-position-4-ref.html
-== background-position-4e.html background-position-4-ref.html
 == background-position-5.html background-position-5-ref.html
-== background-position-6a.html background-position-6-ref.html
-== background-position-6b.html background-position-6-ref.html
+== background-position-6.html background-position-6-ref.html
 == background-position-7.html background-position-7-ref.html
 == background-position-8.html background-position-8-ref.html
 
 == background-size-auto-auto.html background-size-auto-ref.html
 == background-size-auto.html background-size-auto-ref.html
 == background-size-contain.html background-size-contain-ref.html
 == background-size-cover.html background-size-cover-ref.html
 == background-size-auto-length.html background-size-auto-length-ref.html
--- a/layout/style/Declaration.cpp
+++ b/layout/style/Declaration.cpp
@@ -196,51 +196,16 @@ Declaration::GetValue(nsCSSProperty aPro
 }
 
 void
 Declaration::GetAuthoredValue(nsCSSProperty aProperty, nsAString& aValue) const
 {
   GetValue(aProperty, aValue, nsCSSValue::eAuthorSpecified);
 }
 
-static void
-AppendSingleImageLayerPositionValue(const nsCSSValue& aPositionX,
-                                    const nsCSSValue& aPositionY,
-                                    const nsCSSProperty aTable[],
-                                    nsAString& aValue,
-                                    nsCSSValue::Serialization aSerialization)
-{
-  // We need to make sure that we don't serialize to an invalid 3-value form.
-  // The 3-value form is only valid if both edges are present.
-  const nsCSSValue &xEdge = aPositionX.GetArrayValue()->Item(0);
-  const nsCSSValue &xOffset = aPositionX.GetArrayValue()->Item(1);
-  const nsCSSValue &yEdge = aPositionY.GetArrayValue()->Item(0);
-  const nsCSSValue &yOffset = aPositionY.GetArrayValue()->Item(1);
-  bool xHasEdge = (eCSSUnit_Enumerated == xEdge.GetUnit());
-  bool xHasBoth = xHasEdge && (eCSSUnit_Null != xOffset.GetUnit());
-  bool yHasEdge = (eCSSUnit_Enumerated == yEdge.GetUnit());
-  bool yHasBoth = yHasEdge && (eCSSUnit_Null != yOffset.GetUnit());
-
-  if (yHasBoth && !xHasEdge) {
-    // Output 4-value form by adding the x edge.
-    aValue.AppendLiteral("left ");
-  }
-  aPositionX.AppendToString(aTable[nsStyleImageLayers::positionX],
-                            aValue, aSerialization);
-
-  aValue.Append(char16_t(' '));
-
-  if (xHasBoth && !yHasEdge) {
-    // Output 4-value form by adding the y edge.
-    aValue.AppendLiteral("top ");
-  }
-  aPositionY.AppendToString(aTable[nsStyleImageLayers::positionY],
-                            aValue, aSerialization);
-}
-
 void
 Declaration::GetImageLayerValue(
                    nsCSSCompressedDataBlock *data,
                    nsAString& aValue,
                    nsCSSValue::Serialization aSerialization,
                    const nsCSSProperty aTable[]) const
 {
   // We know from our caller that all subproperties were specified.
@@ -251,20 +216,18 @@ Declaration::GetImageLayerValue(
   // background-origin that are different and not the default
   // values.  (We omit them if they're both default.)
 
   // Common CSS properties for both background & mask layer.
   const nsCSSValueList *image =
     data->ValueFor(aTable[nsStyleImageLayers::image])->GetListValue();
   const nsCSSValuePairList *repeat =
     data->ValueFor(aTable[nsStyleImageLayers::repeat])->GetPairListValue();
-  const nsCSSValueList *positionX =
-    data->ValueFor(aTable[nsStyleImageLayers::positionX])->GetListValue();
-  const nsCSSValueList *positionY =
-    data->ValueFor(aTable[nsStyleImageLayers::positionY])->GetListValue();
+  const nsCSSValueList *position =
+    data->ValueFor(aTable[nsStyleImageLayers::position])->GetListValue();
   const nsCSSValueList *clip =
     data->ValueFor(aTable[nsStyleImageLayers::clip])->GetListValue();
   const nsCSSValueList *origin =
     data->ValueFor(aTable[nsStyleImageLayers::origin])->GetListValue();
   const nsCSSValuePairList *size =
     data->ValueFor(aTable[nsStyleImageLayers::size])->GetPairListValue();
 
   // Background layer property.
@@ -306,18 +269,18 @@ Declaration::GetImageLayerValue(
 
     if (attachment) {
       aValue.Append(char16_t(' '));
           attachment->mValue.AppendToString(aTable[nsStyleImageLayers::attachment],
                                             aValue, aSerialization);
     }
 
     aValue.Append(char16_t(' '));
-    AppendSingleImageLayerPositionValue(positionX->mValue, positionY->mValue,
-                                        aTable, aValue, aSerialization);
+    position->mValue.AppendToString(aTable[nsStyleImageLayers::position],
+                                    aValue, aSerialization);
 
     if (size->mXValue.GetUnit() != eCSSUnit_Auto ||
         size->mYValue.GetUnit() != eCSSUnit_Auto) {
       aValue.Append(char16_t(' '));
       aValue.Append(char16_t('/'));
       aValue.Append(char16_t(' '));
       size->mXValue.AppendToString(aTable[nsStyleImageLayers::size], aValue,
                                    aSerialization);
@@ -369,112 +332,75 @@ Declaration::GetImageLayerValue(
     if (mode) {
       aValue.Append(char16_t(' '));
       mode->mValue.AppendToString(aTable[nsStyleImageLayers::maskMode],
                                   aValue, aSerialization);
     }
 
     image = image->mNext;
     repeat = repeat->mNext;
-    positionX = positionX->mNext;
-    positionY = positionY->mNext;
+    position = position->mNext;
     clip = clip->mNext;
     origin = origin->mNext;
     size = size->mNext;
     attachment = attachment ? attachment->mNext : nullptr;
     composite = composite ? composite->mNext : nullptr;
     mode = mode ? mode->mNext : nullptr;
 
     if (!image) {
       // This layer is an background layer
       if (aTable == nsStyleImageLayers::kBackgroundLayerTable) {
-        if (repeat || positionX || positionY || clip || origin || size ||
-            attachment) {
+        if (repeat || position || clip || origin || size || attachment) {
           // Uneven length lists, so can't be serialized as shorthand.
           aValue.Truncate();
           return;
         }
       // This layer is an mask layer
       } else {
 #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
         MOZ_ASSERT(aTable == nsStyleImageLayers::kMaskLayerTable);
 #else
         MOZ_ASSERT_UNREACHABLE("Should never get here when mask-as-shorthand is disable");
 #endif
-        if (repeat || positionX || positionY || clip || origin || size ||
-            composite || mode) {
+        if (repeat || position || clip || origin || size || composite || mode) {
           // Uneven length lists, so can't be serialized as shorthand.
           aValue.Truncate();
           return;
         }
       }
       break;
     }
 
     // This layer is an background layer
     if (aTable == nsStyleImageLayers::kBackgroundLayerTable) {
-      if (!repeat || !positionX || !positionY || !clip || !origin || !size ||
-          !attachment) {
+      if (!repeat || !position || !clip || !origin || !size || !attachment) {
         // Uneven length lists, so can't be serialized as shorthand.
         aValue.Truncate();
         return;
       }
     // This layer is an mask layer
     } else {
 #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
       MOZ_ASSERT(aTable == nsStyleImageLayers::kMaskLayerTable);
 #else
       MOZ_ASSERT_UNREACHABLE("Should never get here when mask-as-shorthand is disable");
 #endif
-      if (!repeat || !positionX || !positionY || !clip || !origin || !size ||
+      if (!repeat || !position || !clip || !origin || !size ||
           !composite || !mode) {
         // Uneven length lists, so can't be serialized as shorthand.
         aValue.Truncate();
         return;
       }
     }
     aValue.Append(char16_t(','));
     aValue.Append(char16_t(' '));
   }
 }
 
 void
-Declaration::GetImageLayerPositionValue(
-                   nsCSSCompressedDataBlock *data,
-                   nsAString& aValue,
-                   nsCSSValue::Serialization aSerialization,
-                   const nsCSSProperty aTable[]) const
-{
-  // We know from above that all subproperties were specified.
-  // However, we still can't represent that in the shorthand unless
-  // they're all lists of the same length.  So if they're different
-  // lengths, we need to bail out.
-  const nsCSSValueList *positionX =
-    data->ValueFor(aTable[nsStyleImageLayers::positionX])->GetListValue();
-  const nsCSSValueList *positionY =
-    data->ValueFor(aTable[nsStyleImageLayers::positionY])->GetListValue();
-  for (;;) {
-    AppendSingleImageLayerPositionValue(positionX->mValue, positionY->mValue,
-                                        aTable, aValue, aSerialization);
-    positionX = positionX->mNext;
-    positionY = positionY->mNext;
-
-    if (!positionX || !positionY) {
-      if (positionX || positionY) {
-        // Uneven length lists, so can't be serialized as shorthand.
-        aValue.Truncate();
-      }
-      return;
-    }
-    aValue.Append(char16_t(','));
-    aValue.Append(char16_t(' '));
-  }
-}
-
-void
 Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue,
                       nsCSSValue::Serialization aSerialization) const
 {
   aValue.Truncate(0);
 
   // simple properties are easy.
   if (!nsCSSProps::IsShorthand(aProperty)) {
     AppendValueToString(aProperty, aValue, aSerialization);
@@ -738,32 +664,22 @@ Declaration::GetValue(nsCSSProperty aPro
       }
       break;
     }
     case eCSSProperty_background: {
       GetImageLayerValue(data, aValue, aSerialization,
                          nsStyleImageLayers::kBackgroundLayerTable);
       break;
     }
-    case eCSSProperty_background_position: {
-      GetImageLayerPositionValue(data, aValue, aSerialization,
-                                 nsStyleImageLayers::kBackgroundLayerTable);
-      break;
-    }
 #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
     case eCSSProperty_mask: {
       GetImageLayerValue(data, aValue, aSerialization,
                          nsStyleImageLayers::kMaskLayerTable);
       break;
     }
-    case eCSSProperty_mask_position: {
-      GetImageLayerPositionValue(data, aValue, aSerialization,
-                                 nsStyleImageLayers::kMaskLayerTable);
-      break;
-    }
 #endif
     case eCSSProperty_font: {
       // systemFont might not be present; other values are guaranteed to be
       // available based on the shorthand check at the beginning of the
       // function, as long as the prop is enabled
       const nsCSSValue *systemFont =
         data->ValueFor(eCSSProperty__x_system_font);
       const nsCSSValue *style =
--- a/layout/style/Declaration.h
+++ b/layout/style/Declaration.h
@@ -370,21 +370,16 @@ private:
   void AppendVariableAndValueToString(const nsAString& aName,
                                       nsAString& aResult) const;
 
   void GetImageLayerValue(nsCSSCompressedDataBlock *data,
                           nsAString& aValue,
                           nsCSSValue::Serialization aSerialization,
                           const nsCSSProperty aTable[]) const;
 
-  void GetImageLayerPositionValue(nsCSSCompressedDataBlock *data,
-                                  nsAString& aValue,
-                                  nsCSSValue::Serialization aSerialization,
-                                  const nsCSSProperty aTable[]) const;
-
 public:
   /**
    * Returns the property at the given index in the ordered list of
    * declarations.  For custom properties, eCSSPropertyExtra_variable
    * is returned.
    */
   nsCSSProperty GetPropertyAt(uint32_t aIndex) const {
     uint32_t value = mOrder[aIndex];
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -444,42 +444,16 @@ CalcPositionSquareDistance(const nsCSSVa
     float difflen = calcVal[i+2].mLength - calcVal[i].mLength;
     float diffpct = calcVal[i+2].mPercent - calcVal[i].mPercent;
     squareDistance += difflen * difflen + diffpct * diffpct;
   }
 
   return squareDistance;
 }
 
-static PixelCalcValue
-CalcBackgroundCoord(const nsCSSValue& aCoord)
-{
-  NS_ASSERTION(aCoord.GetUnit() == eCSSUnit_Array,
-               "Expected array");
-
-  nsCSSValue::Array* array = aCoord.GetArrayValue();
-  MOZ_ASSERT(array->Count() == 2 &&
-             array->Item(0).GetUnit() == eCSSUnit_Null &&
-             array->Item(1).GetUnit() != eCSSUnit_Null,
-             "Invalid position value");
-  return ExtractCalcValue(array->Item(1));
-}
-
-double
-CalcPositionCoordSquareDistance(const nsCSSValue& aPos1,
-                                const nsCSSValue& aPos2)
-{
-  PixelCalcValue calcVal1 = CalcBackgroundCoord(aPos1);
-  PixelCalcValue calcVal2 = CalcBackgroundCoord(aPos2);
-
-  float difflen = calcVal2.mLength - calcVal1.mLength;
-  float diffpct = calcVal2.mPercent - calcVal1.mPercent;
-  return difflen * difflen + diffpct * diffpct;
-}
-
 // CLASS METHODS
 // -------------
 
 bool
 StyleAnimationValue::ComputeDistance(nsCSSProperty aProperty,
                                      const StyleAnimationValue& aStartValue,
                                      const StyleAnimationValue& aEndValue,
                                      double& aDistance)
@@ -865,26 +839,26 @@ StyleAnimationValue::ComputeDistance(nsC
     case eUnit_Shape: {
       return false;
     }
     case eUnit_Filter:
       // FIXME: Support paced animations for filter function interpolation.
     case eUnit_Transform: {
       return false;
     }
-    case eUnit_BackgroundPositionCoord: {
+    case eUnit_BackgroundPosition: {
       const nsCSSValueList *position1 = aStartValue.GetCSSValueListValue();
       const nsCSSValueList *position2 = aEndValue.GetCSSValueListValue();
 
       double squareDistance = 0.0;
       MOZ_ASSERT(!position1 == !position2, "lists should be same length");
 
       while (position1 && position2) {
-        squareDistance += CalcPositionCoordSquareDistance(position1->mValue,
-                                                          position2->mValue);
+        squareDistance += CalcPositionSquareDistance(position1->mValue,
+                                                     position2->mValue);
         position1 = position1->mNext;
         position2 = position2->mNext;
       }
       // fail if lists differ in length.
       if (position1 || position2) {
         return false;
       }
 
@@ -2212,36 +2186,16 @@ AddTransformLists(double aCoeff1, const 
   } while (aList1);
   MOZ_ASSERT(!aList2, "list length mismatch");
   MOZ_ASSERT(!*resultTail,
              "resultTail isn't pointing to the tail");
 
   return result.forget();
 }
 
-static void
-AddPositionCoords(double aCoeff1, const nsCSSValue& aPos1,
-                  double aCoeff2, const nsCSSValue& aPos2,
-                  nsCSSValue& aResultPos)
-{
-  const nsCSSValue::Array* posArray1 = aPos1.GetArrayValue();
-  const nsCSSValue::Array* posArray2 = aPos2.GetArrayValue();
-  nsCSSValue::Array* resultPosArray = nsCSSValue::Array::Create(2);
-  aResultPos.SetArrayValue(resultPosArray, eCSSUnit_Array);
-
-  /* Only compute element 1. The <position-coord> is
-   * 'uncomputed' to only that element.
-   */
-  const nsCSSValue& v1 = posArray1->Item(1);
-  const nsCSSValue& v2 = posArray2->Item(1);
-  nsCSSValue& vr = resultPosArray->Item(1);
-  AddCSSValueCanonicalCalc(aCoeff1, v1,
-                           aCoeff2, v2, vr);
-}
-
 bool
 StyleAnimationValue::AddWeighted(nsCSSProperty aProperty,
                                  double aCoeff1,
                                  const StyleAnimationValue& aValue1,
                                  double aCoeff2,
                                  const StyleAnimationValue& aValue2,
                                  StyleAnimationValue& aResultValue)
 {
@@ -2706,40 +2660,40 @@ StyleAnimationValue::AddWeighted(nsCSSPr
             result = AddDifferentTransformLists(aCoeff1, list1, aCoeff2, list2);
           }
         }
       }
 
       aResultValue.SetTransformValue(new nsCSSValueSharedList(result.forget()));
       return true;
     }
-    case eUnit_BackgroundPositionCoord: {
+    case eUnit_BackgroundPosition: {
       const nsCSSValueList *position1 = aValue1.GetCSSValueListValue();
       const nsCSSValueList *position2 = aValue2.GetCSSValueListValue();
       nsAutoPtr<nsCSSValueList> result;
       nsCSSValueList **resultTail = getter_Transfers(result);
       while (position1 && position2) {
         nsCSSValueList *item = new nsCSSValueList;
         *resultTail = item;
         resultTail = &item->mNext;
 
-        AddPositionCoords(aCoeff1, position1->mValue,
-                          aCoeff2, position2->mValue, item->mValue);
+        AddPositions(aCoeff1, position1->mValue,
+                     aCoeff2, position2->mValue, item->mValue);
 
         position1 = position1->mNext;
         position2 = position2->mNext;
       }
 
       // Check for different lengths
       if (position1 || position2) {
         return false;
       }
 
       aResultValue.SetAndAdoptCSSValueListValue(result.forget(),
-                                                eUnit_BackgroundPositionCoord);
+                                                eUnit_BackgroundPosition);
       return true;
     }
     case eUnit_CSSValuePairList: {
       const nsCSSValuePairList *list1 = aValue1.GetCSSValuePairListValue();
       const nsCSSValuePairList *list2 = aValue2.GetCSSValuePairListValue();
       UniquePtr<nsCSSValuePairList> result =
         AddCSSValuePairList(aProperty, aCoeff1, list1, aCoeff2, list2);
       if (!result) {
@@ -3098,17 +3052,17 @@ StyleAnimationValue::UncomputeValue(nsCS
     } break;
     case eUnit_CSSRect: {
       nsCSSRect& rect = aSpecifiedValue.SetRectValue();
       rect = *aComputedValue.GetCSSRectValue();
     } break;
     case eUnit_Dasharray:
     case eUnit_Shadow:
     case eUnit_Filter:
-    case eUnit_BackgroundPositionCoord:
+    case eUnit_BackgroundPosition:
       {
         nsCSSValueList* computedList = aComputedValue.GetCSSValueListValue();
         if (computedList) {
           aSpecifiedValue.SetDependentListValue(computedList);
         } else {
           aSpecifiedValue.SetNoneValue();
         }
       }
@@ -3137,17 +3091,17 @@ StyleAnimationValue::UncomputeValue(nsCS
                                     StyleAnimationValue&& aComputedValue,
                                     nsCSSValue& aSpecifiedValue)
 {
   Unit unit = aComputedValue.GetUnit();
   switch (unit) {
     case eUnit_Dasharray:
     case eUnit_Shadow:
     case eUnit_Filter:
-    case eUnit_BackgroundPositionCoord:
+    case eUnit_BackgroundPosition:
       {
         UniquePtr<nsCSSValueList> computedList =
           aComputedValue.TakeCSSValueListValue();
         if (computedList) {
           aSpecifiedValue.AdoptListValue(Move(computedList));
         } else {
           aSpecifiedValue.SetNoneValue();
         }
@@ -3317,33 +3271,16 @@ SetPositionValue(const nsStyleImageLayer
   // we'll just have a normalized "x,y" position, with no edge names needed.
   nsCSSValue& xValue = posArray->Item(1);
   nsCSSValue& yValue = posArray->Item(3);
 
   SetCalcValue(&aPos.mXPosition, xValue);
   SetCalcValue(&aPos.mYPosition, yValue);
 }
 
-static void
-SetPositionCoordValue(const nsStyleImageLayers::Position::PositionCoord& aPosCoord,
-                      nsCSSValue& aCSSValue)
-{
-  RefPtr<nsCSSValue::Array> posArray = nsCSSValue::Array::Create(2);
-  aCSSValue.SetArrayValue(posArray.get(), eCSSUnit_Array);
-
-  // NOTE: Array entry #0 here is intentionally left untouched, with
-  // eCSSUnit_Null.  The purpose of this entry in our specified-style
-  // <position-coord> representation is to store edge names.  But for values
-  // extracted from computed style (which is what we're dealing with here),
-  // we'll just have a normalized "x"/"y" position, with no edge names needed.
-  nsCSSValue& value = posArray->Item(1);
-
-  SetCalcValue(&aPosCoord, value);
-}
-
 /*
  * Assign |aOutput = aInput|, except with any non-pixel lengths
  * replaced with the equivalent in pixels, and any non-canonical calc()
  * expressions replaced with canonical ones.
  */
 static void
 SubstitutePixelValues(nsStyleContext* aStyleContext,
                       const nsCSSValue& aInput, nsCSSValue& aOutput)
@@ -3377,53 +3314,32 @@ SubstitutePixelValues(nsStyleContext* aS
     aOutput.SetFloatValue(nsPresContext::AppUnitsToFloatCSSPixels(len),
                           eCSSUnit_Pixel);
   } else {
     aOutput = aInput;
   }
 }
 
 static void
-ExtractImageLayerPositionXList(const nsStyleImageLayers& aLayer,
-                               StyleAnimationValue& aComputedValue)
+ExtractImageLayerPositionList(const nsStyleImageLayers& aLayer,
+                              StyleAnimationValue& aComputedValue)
 {
-  MOZ_ASSERT(aLayer.mPositionXCount > 0, "unexpected count");
+  MOZ_ASSERT(aLayer.mPositionCount > 0, "unexpected count");
 
   nsAutoPtr<nsCSSValueList> result;
   nsCSSValueList **resultTail = getter_Transfers(result);
-  for (uint32_t i = 0, i_end = aLayer.mPositionXCount; i != i_end; ++i) {
+  for (uint32_t i = 0, i_end = aLayer.mPositionCount; i != i_end; ++i) {
     nsCSSValueList *item = new nsCSSValueList;
     *resultTail = item;
     resultTail = &item->mNext;
-    SetPositionCoordValue(aLayer.mLayers[i].mPosition.mXPosition,
-                          item->mValue);
+    SetPositionValue(aLayer.mLayers[i].mPosition, item->mValue);
   }
 
   aComputedValue.SetAndAdoptCSSValueListValue(result.forget(),
-    StyleAnimationValue::eUnit_BackgroundPositionCoord);
-}
-
-static void
-ExtractImageLayerPositionYList(const nsStyleImageLayers& aLayer,
-                               StyleAnimationValue& aComputedValue)
-{
-  MOZ_ASSERT(aLayer.mPositionYCount > 0, "unexpected count");
-
-  nsAutoPtr<nsCSSValueList> result;
-  nsCSSValueList **resultTail = getter_Transfers(result);
-  for (uint32_t i = 0, i_end = aLayer.mPositionYCount; i != i_end; ++i) {
-    nsCSSValueList *item = new nsCSSValueList;
-    *resultTail = item;
-    resultTail = &item->mNext;
-    SetPositionCoordValue(aLayer.mLayers[i].mPosition.mYPosition,
-                          item->mValue);
-  }
-
-  aComputedValue.SetAndAdoptCSSValueListValue(result.forget(),
-    StyleAnimationValue::eUnit_BackgroundPositionCoord);
+    StyleAnimationValue::eUnit_BackgroundPosition);
 }
 
 static void
 ExtractImageLayerSizePairList(const nsStyleImageLayers& aLayer,
                               StyleAnimationValue& aComputedValue)
 {
   MOZ_ASSERT(aLayer.mSizeCount > 0, "unexpected count");
 
@@ -3900,44 +3816,27 @@ StyleAnimationValue::ExtractComputedValu
           nsAutoPtr<nsCSSValue> val(new nsCSSValue);
           SetPositionValue(stylePos->mObjectPosition, *val);
 
           aComputedValue.SetAndAdoptCSSValueValue(val.forget(),
                                                   eUnit_ObjectPosition);
           break;
         }
 
-        case eCSSProperty_background_position_x: {
-          const nsStyleImageLayers& layers =
-            static_cast<const nsStyleBackground*>(styleStruct)->mImage;
-          ExtractImageLayerPositionXList(layers, aComputedValue);
-          break;
-        }
-        case eCSSProperty_background_position_y: {
+        case eCSSProperty_background_position: {
           const nsStyleImageLayers& layers =
             static_cast<const nsStyleBackground*>(styleStruct)->mImage;
-          ExtractImageLayerPositionYList(layers, aComputedValue);
+          ExtractImageLayerPositionList(layers, aComputedValue);
           break;
-
-
-
-
         }
 #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
-        case eCSSProperty_mask_position_x: {
+        case eCSSProperty_mask_position: {
           const nsStyleImageLayers& layers =
             static_cast<const nsStyleSVGReset*>(styleStruct)->mMask;
-          ExtractImageLayerPositionXList(layers, aComputedValue);
-          break;
-        }
-        case eCSSProperty_mask_position_y: {
-          const nsStyleImageLayers& layers =
-            static_cast<const nsStyleSVGReset*>(styleStruct)->mMask;
-          ExtractImageLayerPositionYList(layers, aComputedValue);
-
+          ExtractImageLayerPositionList(layers, aComputedValue);
           break;
         }
 #endif
         case eCSSProperty_background_size: {
           const nsStyleImageLayers& layers =
             static_cast<const nsStyleBackground*>(styleStruct)->mImage;
           ExtractImageLayerSizePairList(layers, aComputedValue);
           break;
@@ -4344,17 +4243,17 @@ StyleAnimationValue::operator=(const Sty
       break;
     case eUnit_CSSRect:
       MOZ_ASSERT(aOther.mValue.mCSSRect, "rects may not be null");
       mValue.mCSSRect = new nsCSSRect(*aOther.mValue.mCSSRect);
       break;
     case eUnit_Dasharray:
     case eUnit_Shadow:
     case eUnit_Filter:
-    case eUnit_BackgroundPositionCoord:
+    case eUnit_BackgroundPosition:
       MOZ_ASSERT(mUnit == eUnit_Shadow || mUnit == eUnit_Filter ||
                  aOther.mValue.mCSSValueList,
                  "value lists other than shadows and filters may not be null");
       if (aOther.mValue.mCSSValueList) {
         mValue.mCSSValueList = aOther.mValue.mCSSValueList->Clone();
       } else {
         mValue.mCSSValueList = nullptr;
       }
@@ -4608,17 +4507,17 @@ StyleAnimationValue::operator==(const St
       return *mValue.mCSSValuePair == *aOther.mValue.mCSSValuePair;
     case eUnit_CSSValueTriplet:
       return *mValue.mCSSValueTriplet == *aOther.mValue.mCSSValueTriplet;
     case eUnit_CSSRect:
       return *mValue.mCSSRect == *aOther.mValue.mCSSRect;
     case eUnit_Dasharray:
     case eUnit_Shadow:
     case eUnit_Filter:
-    case eUnit_BackgroundPositionCoord:
+    case eUnit_BackgroundPosition:
       return nsCSSValueList::Equal(mValue.mCSSValueList,
                                    aOther.mValue.mCSSValueList);
     case eUnit_Shape:
       return *mValue.mCSSValueArray == *aOther.mValue.mCSSValueArray;
     case eUnit_Transform:
       return *mValue.mCSSValueSharedList == *aOther.mValue.mCSSValueSharedList;
     case eUnit_CSSValuePairList:
       return nsCSSValuePairList::Equal(mValue.mCSSValuePairList,
--- a/layout/style/StyleAnimationValue.h
+++ b/layout/style/StyleAnimationValue.h
@@ -280,17 +280,17 @@ public:
     eUnit_CSSValuePair, // nsCSSValuePair* (never null)
     eUnit_CSSValueTriplet, // nsCSSValueTriplet* (never null)
     eUnit_CSSRect, // nsCSSRect* (never null)
     eUnit_Dasharray, // nsCSSValueList* (never null)
     eUnit_Shadow, // nsCSSValueList* (may be null)
     eUnit_Shape,  // nsCSSValue::Array* (never null)
     eUnit_Filter, // nsCSSValueList* (may be null)
     eUnit_Transform, // nsCSSValueList* (never null)
-    eUnit_BackgroundPositionCoord, // nsCSSValueList* (never null)
+    eUnit_BackgroundPosition, // nsCSSValueList* (never null)
     eUnit_CSSValuePairList, // nsCSSValuePairList* (never null)
     eUnit_UnparsedString // nsStringBuffer* (never null)
   };
 
 private:
   Unit mUnit;
   union {
     int32_t mInt;
@@ -481,17 +481,17 @@ private:
     return aUnit == eUnit_CSSRect;
   }
   static bool IsCSSValueArrayUnit(Unit aUnit) {
     return aUnit == eUnit_Shape;
   }
   static bool IsCSSValueListUnit(Unit aUnit) {
     return aUnit == eUnit_Dasharray || aUnit == eUnit_Filter ||
            aUnit == eUnit_Shadow ||
-           aUnit == eUnit_BackgroundPositionCoord;
+           aUnit == eUnit_BackgroundPosition;
   }
   static bool IsCSSValueSharedListValue(Unit aUnit) {
     return aUnit == eUnit_Transform;
   }
   static bool IsCSSValuePairListUnit(Unit aUnit) {
     return aUnit == eUnit_CSSValuePairList;
   }
   static bool IsStringUnit(Unit aUnit) {
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -860,57 +860,51 @@ protected:
 
   struct ImageLayersShorthandParseState {
     nsCSSValue&  mColor;
     nsCSSValueList* mImage;
     nsCSSValuePairList* mRepeat;
     nsCSSValueList* mAttachment;   // A property for background layer only
     nsCSSValueList* mClip;
     nsCSSValueList* mOrigin;
-    nsCSSValueList* mPositionX;
-    nsCSSValueList* mPositionY;
+    nsCSSValueList* mPosition;
     nsCSSValuePairList* mSize;
     nsCSSValueList* mComposite;    // A property for mask layer only
     nsCSSValueList* mMode;         // A property for mask layer only
     ImageLayersShorthandParseState(
         nsCSSValue& aColor, nsCSSValueList* aImage, nsCSSValuePairList* aRepeat,
         nsCSSValueList* aAttachment, nsCSSValueList* aClip,
-        nsCSSValueList* aOrigin,
-        nsCSSValueList* aPositionX, nsCSSValueList* aPositionY,
+        nsCSSValueList* aOrigin, nsCSSValueList* aPosition,
         nsCSSValuePairList* aSize, nsCSSValueList* aComposite,
         nsCSSValueList* aMode) :
         mColor(aColor), mImage(aImage), mRepeat(aRepeat),
         mAttachment(aAttachment), mClip(aClip), mOrigin(aOrigin),
-        mPositionX(aPositionX), mPositionY(aPositionY),
-        mSize(aSize), mComposite(aComposite),
+        mPosition(aPosition), mSize(aSize), mComposite(aComposite),
         mMode(aMode) {};
   };
 
   bool IsFunctionTokenValidForImageLayerImage(const nsCSSToken& aToken) const;
   bool ParseImageLayersItem(ImageLayersShorthandParseState& aState,
                             const nsCSSProperty aTable[]);
 
   bool ParseValueList(nsCSSProperty aPropID); // a single value prop-id
   bool ParseImageLayerRepeat(nsCSSProperty aPropID);
   bool ParseImageLayerRepeatValues(nsCSSValuePair& aValue);
-  bool ParseImageLayerPosition(const nsCSSProperty aTable[]);
-  bool ParseImageLayerPositionCoord(nsCSSProperty aPropID, bool aIsHorizontal);
+  bool ParseImageLayerPosition(nsCSSProperty aPropID);
 
   // ParseBoxPositionValues parses the CSS 2.1 background-position syntax,
   // which is still used by some properties. See ParsePositionValue
   // for the css3-background syntax.
   bool ParseBoxPositionValues(nsCSSValuePair& aOut, bool aAcceptsInherit,
                               bool aAllowExplicitCenter = true); // deprecated
 
   // ParsePositionValue parses a CSS <position> value, which is used by
   // the 'background-position' property.
   bool ParsePositionValue(nsCSSValue& aOut);
-  bool ParsePositionValueSeparateCoords(nsCSSValue& aOutX, nsCSSValue& aOutY);
-
-  bool ParseImageLayerPositionCoordItem(nsCSSValue& aOut, bool aIsHorizontal);
+
   bool ParseImageLayerSize(nsCSSProperty aPropID);
   bool ParseImageLayerSizeValues(nsCSSValuePair& aOut);
   bool ParseBorderColor();
   bool ParseBorderColors(nsCSSProperty aProperty);
   void SetBorderImageInitialValues();
   bool ParseBorderImageRepeat(bool aAcceptsInherit);
   // If ParseBorderImageSlice returns false, aConsumedTokens indicates
   // whether or not any tokens were consumed (in other words, was the property
@@ -11427,21 +11421,17 @@ bool
 CSSParserImpl::ParsePropertyByFunction(nsCSSProperty aPropID)
 {
   switch (aPropID) {  // handle shorthand or multiple properties
   case eCSSProperty_background:
     return ParseImageLayers(nsStyleImageLayers::kBackgroundLayerTable);
   case eCSSProperty_background_repeat:
     return ParseImageLayerRepeat(eCSSProperty_background_repeat);
   case eCSSProperty_background_position:
-    return ParseImageLayerPosition(nsStyleImageLayers::kBackgroundLayerTable);
-  case eCSSProperty_background_position_x:
-  case eCSSProperty_background_position_y:
-    return ParseImageLayerPositionCoord(aPropID,
-               aPropID == eCSSProperty_background_position_x);
+    return ParseImageLayerPosition(eCSSProperty_background_position);
   case eCSSProperty_background_size:
     return ParseImageLayerSize(eCSSProperty_background_size);
   case eCSSProperty_border:
     return ParseBorderSide(kBorderTopIDs, true);
   case eCSSProperty_border_color:
     return ParseBorderColor();
   case eCSSProperty_border_spacing:
     return ParseBorderSpacing();
@@ -11613,21 +11603,17 @@ CSSParserImpl::ParsePropertyByFunction(n
   case eCSSProperty_scroll_snap_type:
     return ParseScrollSnapType();
 #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
   case eCSSProperty_mask:
     return ParseImageLayers(nsStyleImageLayers::kMaskLayerTable);
   case eCSSProperty_mask_repeat:
     return ParseImageLayerRepeat(eCSSProperty_mask_repeat);
   case eCSSProperty_mask_position:
-    return ParseImageLayerPosition(nsStyleImageLayers::kMaskLayerTable);
-  case eCSSProperty_mask_position_x:
-  case eCSSProperty_mask_position_y:
-    return ParseImageLayerPositionCoord(aPropID,
-               aPropID == eCSSProperty_mask_position_x);
+    return ParseImageLayerPosition(eCSSProperty_mask_position);
   case eCSSProperty_mask_size:
     return ParseImageLayerSize(eCSSProperty_mask_size);
 #endif
   case eCSSProperty__webkit_text_stroke:
     return ParseWebkitTextStroke();
   case eCSSProperty_all:
     return ParseAll();
   default:
@@ -11898,23 +11884,22 @@ CSSParserImpl::ParseImageLayers(const ns
     for (const nsCSSProperty* subprops =
            nsCSSProps::SubpropertyEntryFor(aTable[nsStyleImageLayers::shorthand]);
          *subprops != eCSSProperty_UNKNOWN; ++subprops) {
       AppendValue(*subprops, color);
     }
     return true;
   }
 
-  nsCSSValue image, repeat, attachment, clip, origin, positionX, positionY, size,
+  nsCSSValue image, repeat, attachment, clip, origin, position, size,
              composite, maskMode;
   ImageLayersShorthandParseState state(color, image.SetListValue(),
                                        repeat.SetPairListValue(),
                                        attachment.SetListValue(), clip.SetListValue(),
-                                       origin.SetListValue(),
-                                       positionX.SetListValue(), positionY.SetListValue(),
+                                       origin.SetListValue(), position.SetListValue(),
                                        size.SetPairListValue(), composite.SetListValue(),
                                        maskMode.SetListValue());
 
   for (;;) {
     if (!ParseImageLayersItem(state, aTable)) {
       return false;
     }
 
@@ -11938,19 +11923,17 @@ CSSParserImpl::ParseImageLayers(const ns
     APPENDNEXT(nsStyleImageLayers::image, state.mImage,
                nsCSSValueList);
     APPENDNEXT(nsStyleImageLayers::repeat, state.mRepeat,
                nsCSSValuePairList);
     APPENDNEXT(nsStyleImageLayers::clip, state.mClip,
                nsCSSValueList);
     APPENDNEXT(nsStyleImageLayers::origin, state.mOrigin,
                nsCSSValueList);
-    APPENDNEXT(nsStyleImageLayers::positionX, state.mPositionX,
-               nsCSSValueList);
-    APPENDNEXT(nsStyleImageLayers::positionY, state.mPositionY,
+    APPENDNEXT(nsStyleImageLayers::position, state.mPosition,
                nsCSSValueList);
     APPENDNEXT(nsStyleImageLayers::size, state.mSize,
                nsCSSValuePairList);
     APPENDNEXT(nsStyleImageLayers::attachment, state.mAttachment,
                nsCSSValueList);
     APPENDNEXT(nsStyleImageLayers::maskMode, state.mMode,
                nsCSSValueList);
     APPENDNEXT(nsStyleImageLayers::composite, state.mComposite,
@@ -11969,18 +11952,17 @@ CSSParserImpl::ParseImageLayers(const ns
   if (propID_ != eCSSProperty_UNKNOWN) { \
     AppendValue(propID_,  propValue_); \
   }
 
   APPENDVALUE(aTable[nsStyleImageLayers::image],      image);
   APPENDVALUE(aTable[nsStyleImageLayers::repeat],     repeat);
   APPENDVALUE(aTable[nsStyleImageLayers::clip],       clip);
   APPENDVALUE(aTable[nsStyleImageLayers::origin],     origin);
-  APPENDVALUE(aTable[nsStyleImageLayers::positionX],  positionX);
-  APPENDVALUE(aTable[nsStyleImageLayers::positionY],  positionY);
+  APPENDVALUE(aTable[nsStyleImageLayers::position],   position);
   APPENDVALUE(aTable[nsStyleImageLayers::size],       size);
   APPENDVALUE(aTable[nsStyleImageLayers::color],      color);
   APPENDVALUE(aTable[nsStyleImageLayers::attachment], attachment);
   APPENDVALUE(aTable[nsStyleImageLayers::maskMode],   maskMode);
   APPENDVALUE(aTable[nsStyleImageLayers::composite],  composite);
 
 #undef APPENDVALUE
 
@@ -12029,23 +12011,20 @@ CSSParserImpl::ParseImageLayersItem(
                                       eCSSUnit_Enumerated);
   aState.mRepeat->mYValue.Reset();
   aState.mAttachment->mValue.SetIntValue(NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL,
                                          eCSSUnit_Enumerated);
   aState.mClip->mValue.SetIntValue(NS_STYLE_IMAGELAYER_CLIP_BORDER,
                                    eCSSUnit_Enumerated);
   aState.mOrigin->mValue.SetIntValue(NS_STYLE_IMAGELAYER_ORIGIN_PADDING,
                                      eCSSUnit_Enumerated);
-
-  RefPtr<nsCSSValue::Array> positionXArr = nsCSSValue::Array::Create(2);
-  RefPtr<nsCSSValue::Array> positionYArr = nsCSSValue::Array::Create(2);
-  aState.mPositionX->mValue.SetArrayValue(positionXArr, eCSSUnit_Array);
-  aState.mPositionY->mValue.SetArrayValue(positionYArr, eCSSUnit_Array);
-  positionXArr->Item(1).SetPercentValue(0.0f);
-  positionYArr->Item(1).SetPercentValue(0.0f);
+  RefPtr<nsCSSValue::Array> positionArr = nsCSSValue::Array::Create(4);
+  aState.mPosition->mValue.SetArrayValue(positionArr, eCSSUnit_Array);
+  positionArr->Item(1).SetPercentValue(0.0f);
+  positionArr->Item(3).SetPercentValue(0.0f);
   aState.mSize->mXValue.SetAutoValue();
   aState.mSize->mYValue.SetAutoValue();
   aState.mComposite->mValue.SetIntValue(NS_STYLE_MASK_COMPOSITE_ADD,
                                         eCSSUnit_Enumerated);
   aState.mMode->mValue.SetIntValue(NS_STYLE_MASK_MODE_MATCH_SOURCE,
                                    eCSSUnit_Enumerated);
   bool haveColor = false,
        haveImage = false,
@@ -12108,19 +12087,17 @@ CSSParserImpl::ParseImageLayersItem(
         }
         aState.mRepeat->mXValue = scratch.mXValue;
         aState.mRepeat->mYValue = scratch.mYValue;
       } else if (nsCSSProps::FindKeyword(keyword,
                    nsCSSProps::kImageLayerPositionKTable, dummy)) {
         if (havePositionAndSize)
           return false;
         havePositionAndSize = true;
-
-        if (!ParsePositionValueSeparateCoords(aState.mPositionX->mValue,
-                                              aState.mPositionY->mValue)) {
+        if (!ParsePositionValue(aState.mPosition->mValue)) {
           return false;
         }
         if (ExpectSymbol('/', true)) {
           nsCSSValuePair scratch;
           if (!ParseImageLayerSizeValues(scratch)) {
             return false;
           }
           aState.mSize->mXValue = scratch.mXValue;
@@ -12222,18 +12199,17 @@ CSSParserImpl::ParseImageLayersItem(
                tt == eCSSToken_Number ||
                tt == eCSSToken_Percentage ||
                (tt == eCSSToken_Function &&
                 (mToken.mIdent.LowerCaseEqualsLiteral("calc") ||
                  mToken.mIdent.LowerCaseEqualsLiteral("-moz-calc")))) {
       if (havePositionAndSize)
         return false;
       havePositionAndSize = true;
-      if (!ParsePositionValueSeparateCoords(aState.mPositionX->mValue,
-                                            aState.mPositionY->mValue)) {
+      if (!ParsePositionValue(aState.mPosition->mValue)) {
         return false;
       }
       if (ExpectSymbol('/', true)) {
         nsCSSValuePair scratch;
         if (!ParseImageLayerSizeValues(scratch)) {
           return false;
         }
         aState.mSize->mXValue = scratch.mXValue;
@@ -12332,73 +12308,35 @@ CSSParserImpl::ParseImageLayerRepeatValu
       yValue.Reset();
     }
     return true;
   }
 
   return false;
 }
 
-bool
-CSSParserImpl::ParseImageLayerPosition(const nsCSSProperty aTable[])
-{
-  // 'initial', 'inherit' and 'unset' stand alone, no list permitted.
-  nsCSSValue position;
-  if (ParseSingleTokenVariant(position, VARIANT_INHERIT, nullptr)) {
-    AppendValue(aTable[nsStyleImageLayers::positionX], position);
-    AppendValue(aTable[nsStyleImageLayers::positionY], position);
-    return true;
-  }
-
-  nsCSSValue itemValueX;
-  nsCSSValue itemValueY;
-  if (!ParsePositionValueSeparateCoords(itemValueX, itemValueY)) {
-    return false;
-  }
-
-  nsCSSValue valueX;
-  nsCSSValue valueY;
-  nsCSSValueList* itemX = valueX.SetListValue();
-  nsCSSValueList* itemY = valueY.SetListValue();
-  for (;;) {
-    itemX->mValue = itemValueX;
-    itemY->mValue = itemValueY;
-    if (!ExpectSymbol(',', true)) {
-      break;
-    }
-    if (!ParsePositionValueSeparateCoords(itemValueX, itemValueY)) {
-      return false;
-    }
-    itemX->mNext = new nsCSSValueList;
-    itemY->mNext = new nsCSSValueList;
-    itemX = itemX->mNext;
-    itemY = itemY->mNext;
-  }
-  AppendValue(aTable[nsStyleImageLayers::positionX], valueX);
-  AppendValue(aTable[nsStyleImageLayers::positionY], valueY);
-  return true;
-}
-
-bool
-CSSParserImpl::ParseImageLayerPositionCoord(nsCSSProperty aPropID, bool aIsHorizontal)
+// This function is very similar to ParseScrollSnapCoordinate,
+// ParseImageLayers, ParseImageLayerSize.
+bool
+CSSParserImpl::ParseImageLayerPosition(nsCSSProperty aPropID)
 {
   nsCSSValue value;
   // 'initial', 'inherit' and 'unset' stand alone, no list permitted.
   if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
     nsCSSValue itemValue;
-    if (!ParseImageLayerPositionCoordItem(itemValue, aIsHorizontal)) {
+    if (!ParsePositionValue(itemValue)) {
       return false;
     }
     nsCSSValueList* item = value.SetListValue();
     for (;;) {
       item->mValue = itemValue;
       if (!ExpectSymbol(',', true)) {
         break;
       }
-      if (!ParseImageLayerPositionCoordItem(itemValue, aIsHorizontal)) {
+      if (!ParsePositionValue(itemValue)) {
         return false;
       }
       item->mNext = new nsCSSValueList;
       item = item->mNext;
     }
   }
   AppendValue(aPropID, value);
   return true;
@@ -12688,90 +12626,16 @@ CSSParserImpl::ParsePositionValue(nsCSSV
     xOffset = yOffset;
     yEdge = swapEdge;
     yOffset = swapOffset;
   }
 
   return true;
 }
 
-bool
-CSSParserImpl::ParsePositionValueSeparateCoords(nsCSSValue& aOutX, nsCSSValue& aOutY)
-{
-  nsCSSValue scratch;
-  if (!ParsePositionValue(scratch)) {
-    return false;
-  }
-
-  // Separate the four values into two pairs of two values for X and Y.
-  RefPtr<nsCSSValue::Array> valueX = nsCSSValue::Array::Create(2);
-  RefPtr<nsCSSValue::Array> valueY = nsCSSValue::Array::Create(2);
-  aOutX.SetArrayValue(valueX, eCSSUnit_Array);
-  aOutY.SetArrayValue(valueY, eCSSUnit_Array);
-
-  RefPtr<nsCSSValue::Array> value = scratch.GetArrayValue();
-  valueX->Item(0) = value->Item(0);
-  valueX->Item(1) = value->Item(1);
-  valueY->Item(0) = value->Item(2);
-  valueY->Item(1) = value->Item(3);
-  return true;
-}
-
-// Parses one item in a list of values for the 'background-position-x' or
-// 'background-position-y' property. Does not support the start/end keywords.
-// Spec reference: https://drafts.csswg.org/css-backgrounds-4/#propdef-background-position-x
-bool
-CSSParserImpl::ParseImageLayerPositionCoordItem(nsCSSValue& aOut, bool aIsHorizontal)
-{
-  RefPtr<nsCSSValue::Array> value = nsCSSValue::Array::Create(2);
-  aOut.SetArrayValue(value, eCSSUnit_Array);
-
-  nsCSSValue &edge   = value->Item(0),
-             &offset = value->Item(1);
-
-  nsCSSValue edgeOrOffset;
-  CSSParseResult result =
-    ParseVariant(edgeOrOffset, VARIANT_LPCALC | VARIANT_KEYWORD,
-                 nsCSSProps::kImageLayerPositionKTable);
-  if (result != CSSParseResult::Ok) {
-    return false;
-  }
-
-  if (edgeOrOffset.GetUnit() == eCSSUnit_Enumerated) {
-    edge = edgeOrOffset;
-
-    // The edge can be followed by an optional offset.
-    result = ParseVariant(offset, VARIANT_LPCALC, nullptr);
-    if (result == CSSParseResult::Error) {
-      return false;
-    }
-  } else {
-    offset = edgeOrOffset;
-  }
-
-  // Keywords for horizontal properties cannot be vertical keywords, and
-  // keywords for vertical properties cannot be horizontal keywords.
-  // Also, if an offset is specified, the edge cannot be center.
-  int32_t edgeEnum =
-          edge.GetUnit() == eCSSUnit_Enumerated ? edge.GetIntValue() : 0;
-  int32_t allowedKeywords =
-    (aIsHorizontal ? (BG_LEFT | BG_RIGHT) : (BG_TOP | BG_BOTTOM)) |
-    (offset.GetUnit() == eCSSUnit_Null ? BG_CENTER : 0);
-  if (edgeEnum & ~allowedKeywords) {
-    return false;
-  }
-
-  NS_ASSERTION((eCSSUnit_Enumerated == edge.GetUnit() ||
-                eCSSUnit_Null       == edge.GetUnit()) &&
-               eCSSUnit_Enumerated != offset.GetUnit(),
-               "Unexpected units");
-
-  return true;
-}
-
 // This function is very similar to ParseScrollSnapCoordinate,
 // ParseImageLayers, and ParseImageLayerPosition.
 bool
 CSSParserImpl::ParseImageLayerSize(nsCSSProperty aPropID)
 {
   nsCSSValue value;
   // 'initial', 'inherit' and 'unset' stand alone, no list permitted.
   if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
--- a/layout/style/nsCSSPropAliasList.h
+++ b/layout/style/nsCSSPropAliasList.h
@@ -378,24 +378,16 @@ CSS_PROP_ALIAS(-webkit-mask-image,
 CSS_PROP_ALIAS(-webkit-mask-origin,
                mask_origin,
                WebkitMaskOrigin,
                WEBKIT_PREFIX_PREF)
 CSS_PROP_ALIAS(-webkit-mask-position,
                mask_position,
                WebkitMaskPosition,
                WEBKIT_PREFIX_PREF)
-CSS_PROP_ALIAS(-webkit-mask-position-x,
-               mask_position_x,
-               WebkitMaskPositionX,
-               WEBKIT_PREFIX_PREF)
-CSS_PROP_ALIAS(-webkit-mask-position-y,
-               mask_position_y,
-               WebkitMaskPositionY,
-               WEBKIT_PREFIX_PREF)
 CSS_PROP_ALIAS(-webkit-mask-repeat,
                mask_repeat,
                WebkitMaskRepeat,
                WEBKIT_PREFIX_PREF)
 CSS_PROP_ALIAS(-webkit-mask-size,
                mask_size,
                WebkitMaskSize,
                WEBKIT_PREFIX_PREF)
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -562,45 +562,25 @@ CSS_PROP_BACKGROUND(
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
         CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
     "",
     VARIANT_KEYWORD, // used by list parsing
     kImageLayerOriginKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
-CSS_PROP_SHORTHAND(
+CSS_PROP_BACKGROUND(
     background-position,
     background_position,
     BackgroundPosition,
     CSS_PROPERTY_PARSE_FUNCTION |
-        CSS_PROPERTY_UNITLESS_LENGTH_QUIRK,
-    "")
-CSS_PROP_BACKGROUND(
-    background-position-x,
-    background_position_x,
-    BackgroundPositionX,
-    CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
         CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
-        CSS_PROPERTY_STORES_CALC,
-    "",
-    0,
-    kImageLayerPositionKTable,
-    CSS_PROP_NO_OFFSET,
-    eStyleAnimType_Custom)
-CSS_PROP_BACKGROUND(
-    background-position-y,
-    background_position_y,
-    BackgroundPositionY,
-    CSS_PROPERTY_PARSE_FUNCTION |
-        CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
-        CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
-        CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
+        CSS_PROPERTY_UNITLESS_LENGTH_QUIRK |
         CSS_PROPERTY_STORES_CALC,
     "",
     0,
     kImageLayerPositionKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_Custom)
 CSS_PROP_BACKGROUND(
     background-repeat,
@@ -2729,40 +2709,21 @@ CSS_PROP_SVGRESET(
     MaskOrigin,
     CSS_PROPERTY_PARSE_VALUE_LIST |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
     "",
     VARIANT_KEYWORD, // used by list parsing
     kImageLayerOriginKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
-CSS_PROP_SHORTHAND(
+CSS_PROP_SVGRESET(
     mask-position,
     mask_position,
     MaskPosition,
     CSS_PROPERTY_PARSE_FUNCTION |
-        CSS_PROPERTY_UNITLESS_LENGTH_QUIRK,
-    "")
-CSS_PROP_SVGRESET(
-    mask-position-x,
-    mask_position_x,
-    MaskPositionX,
-    CSS_PROPERTY_PARSE_FUNCTION |
-        CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
-        CSS_PROPERTY_STORES_CALC,
-    "",
-    0,
-    kImageLayerPositionKTable,
-    CSS_PROP_NO_OFFSET,
-    eStyleAnimType_Custom)
-CSS_PROP_SVGRESET(
-    mask-position-y,
-    mask_position_y,
-    MaskPositionY,
-    CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
         CSS_PROPERTY_STORES_CALC,
     "",
     0,
     kImageLayerPositionKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_Custom)
 CSS_PROP_SVGRESET(
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -2620,30 +2620,23 @@ static const nsCSSProperty gOutlineRadiu
   eCSSProperty_UNKNOWN
 };
 
 static const nsCSSProperty gBackgroundSubpropTable[] = {
   eCSSProperty_background_color,
   eCSSProperty_background_image,
   eCSSProperty_background_repeat,
   eCSSProperty_background_attachment,
+  eCSSProperty_background_position,
   eCSSProperty_background_clip,
   eCSSProperty_background_origin,
-  eCSSProperty_background_position_x,
-  eCSSProperty_background_position_y,
   eCSSProperty_background_size,
   eCSSProperty_UNKNOWN
 };
 
-static const nsCSSProperty gBackgroundPositionSubpropTable[] = {
-  eCSSProperty_background_position_x,
-  eCSSProperty_background_position_y,
-  eCSSProperty_UNKNOWN
-};
-
 static const nsCSSProperty gBorderSubpropTable[] = {
   eCSSProperty_border_top_width,
   eCSSProperty_border_right_width,
   eCSSProperty_border_bottom_width,
   eCSSProperty_border_left_width,
   eCSSProperty_border_top_style,
   eCSSProperty_border_right_style,
   eCSSProperty_border_bottom_style,
@@ -2967,30 +2960,24 @@ static const nsCSSProperty gScrollSnapTy
   eCSSProperty_scroll_snap_type_x,
   eCSSProperty_scroll_snap_type_y,
   eCSSProperty_UNKNOWN
 };
 #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
 static const nsCSSProperty gMaskSubpropTable[] = {
   eCSSProperty_mask_image,
   eCSSProperty_mask_repeat,
-  eCSSProperty_mask_position_x,
-  eCSSProperty_mask_position_y,
+  eCSSProperty_mask_position,
   eCSSProperty_mask_clip,
   eCSSProperty_mask_origin,
   eCSSProperty_mask_size,
   eCSSProperty_mask_composite,
   eCSSProperty_mask_mode,
   eCSSProperty_UNKNOWN
 };
-static const nsCSSProperty gMaskPositionSubpropTable[] = {
-  eCSSProperty_mask_position_x,
-  eCSSProperty_mask_position_y,
-  eCSSProperty_UNKNOWN
-};
 #endif
 // FIXME: mask-border tables should be added when we implement
 // mask-border properties.
 
 const nsCSSProperty *const
 nsCSSProps::kSubpropertyTable[eCSSProperty_COUNT - eCSSProperty_COUNT_no_shorthands] = {
 #define CSS_PROP_PUBLIC_OR_PRIVATE(publicname_, privatename_) privatename_
 // Need an extra level of macro nesting to force expansion of method_
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -929,17 +929,17 @@ nsCSSValue::AppendCircleOrEllipseToStrin
                "unexpected value");
     return;
   }
 
   if (hasRadii) {
     aResult.Append(' ');
   }
   aResult.AppendLiteral("at ");
-  array->Item(count).AppendToString(eCSSProperty_object_position,
+  array->Item(count).AppendToString(eCSSProperty_background_position,
                                     aResult, aSerialization);
 }
 
 // Helper to append |aString| with the shorthand sides notation used in e.g.
 // 'padding'. |aProperties| and |aValues| are expected to have 4 elements.
 /*static*/ void
 nsCSSValue::AppendSidesShorthandToString(const nsCSSProperty aProperties[],
                                          const nsCSSValue* aValues[],
@@ -1544,22 +1544,22 @@ nsCSSValue::AppendToString(nsCSSProperty
           gradient->mBgPos.mYValue.GetUnit() != eCSSUnit_None) {
         MOZ_ASSERT(gradient->mAngle.GetUnit() == eCSSUnit_None);
         MOZ_ASSERT(gradient->mBgPos.mXValue.GetUnit() == eCSSUnit_Enumerated &&
                    gradient->mBgPos.mYValue.GetUnit() == eCSSUnit_Enumerated,
                    "unexpected unit");
         aResult.AppendLiteral("to");
         if (!(gradient->mBgPos.mXValue.GetIntValue() & NS_STYLE_IMAGELAYER_POSITION_CENTER)) {
           aResult.Append(' ');
-          gradient->mBgPos.mXValue.AppendToString(eCSSProperty_background_position_x,
+          gradient->mBgPos.mXValue.AppendToString(eCSSProperty_background_position,
                                                   aResult, aSerialization);
         }
         if (!(gradient->mBgPos.mYValue.GetIntValue() & NS_STYLE_IMAGELAYER_POSITION_CENTER)) {
           aResult.Append(' ');
-          gradient->mBgPos.mYValue.AppendToString(eCSSProperty_background_position_y,
+          gradient->mBgPos.mYValue.AppendToString(eCSSProperty_background_position,
                                                   aResult, aSerialization);
         }
         needSep = true;
       } else if (gradient->mAngle.GetUnit() != eCSSUnit_None) {
         gradient->mAngle.AppendToString(aProperty, aResult, aSerialization);
         needSep = true;
       }
     } else if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None ||
@@ -1567,22 +1567,22 @@ nsCSSValue::AppendToString(nsCSSProperty
         gradient->mAngle.GetUnit() != eCSSUnit_None) {
       if (needSep) {
         aResult.Append(' ');
       }
       if (gradient->mIsRadial && !gradient->mIsLegacySyntax) {
         aResult.AppendLiteral("at ");
       }
       if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None) {
-        gradient->mBgPos.mXValue.AppendToString(eCSSProperty_background_position_x,
+        gradient->mBgPos.mXValue.AppendToString(eCSSProperty_background_position,
                                                 aResult, aSerialization);
         aResult.Append(' ');
       }
       if (gradient->mBgPos.mYValue.GetUnit() != eCSSUnit_None) {
-        gradient->mBgPos.mYValue.AppendToString(eCSSProperty_background_position_y,
+        gradient->mBgPos.mYValue.AppendToString(eCSSProperty_background_position,
                                                 aResult, aSerialization);
         aResult.Append(' ');
       }
       if (gradient->mAngle.GetUnit() != eCSSUnit_None) {
         MOZ_ASSERT(gradient->mIsLegacySyntax,
                    "angle is allowed only for legacy syntax");
         gradient->mAngle.AppendToString(aProperty, aResult, aSerialization);
       }
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -2154,60 +2154,29 @@ nsComputedDOMStyle::DoGetImageLayerImage
   }
 
   return valueList.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetImageLayerPosition(const nsStyleImageLayers& aLayers)
 {
-  if (aLayers.mPositionXCount != aLayers.mPositionYCount) {
-    // No value to return.  We can't express this combination of
-    // values as a shorthand.
-    return nullptr;
-  }
-
   RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
-  for (uint32_t i = 0, i_end = aLayers.mPositionXCount; i < i_end; ++i) {
+
+  for (uint32_t i = 0, i_end = aLayers.mPositionCount; i < i_end; ++i) {
     RefPtr<nsDOMCSSValueList> itemList = GetROCSSValueList(false);
 
     SetValueToPosition(aLayers.mLayers[i].mPosition, itemList);
     valueList->AppendCSSValue(itemList.forget());
   }
 
   return valueList.forget();
 }
 
 already_AddRefed<CSSValue>
-nsComputedDOMStyle::DoGetImageLayerPositionX(const nsStyleImageLayers& aLayers)
-{
-  RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
-  for (uint32_t i = 0, i_end = aLayers.mPositionXCount; i < i_end; ++i) {
-    RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-    SetValueToPositionCoord(aLayers.mLayers[i].mPosition.mXPosition, val);
-    valueList->AppendCSSValue(val.forget());
-  }
-
-  return valueList.forget();
-}
-
-already_AddRefed<CSSValue>
-nsComputedDOMStyle::DoGetImageLayerPositionY(const nsStyleImageLayers& aLayers)
-{
-  RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
-  for (uint32_t i = 0, i_end = aLayers.mPositionYCount; i < i_end; ++i) {
-    RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-    SetValueToPositionCoord(aLayers.mLayers[i].mPosition.mYPosition, val);
-    valueList->AppendCSSValue(val.forget());
-  }
-
-  return valueList.forget();
-}
-
-already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetImageLayerRepeat(const nsStyleImageLayers& aLayers)
 {
   RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
 
   for (uint32_t i = 0, i_end = aLayers.mRepeatCount; i < i_end; ++i) {
     RefPtr<nsDOMCSSValueList> itemList = GetROCSSValueList(false);
     RefPtr<nsROCSSPrimitiveValue> valX = new nsROCSSPrimitiveValue;
 
@@ -2387,30 +2356,16 @@ nsComputedDOMStyle::SetValueToPosition(
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetBackgroundPosition()
 {
   const nsStyleImageLayers& layers = StyleBackground()->mImage;
   return DoGetImageLayerPosition(layers);
 }
 
 already_AddRefed<CSSValue>
-nsComputedDOMStyle::DoGetBackgroundPositionX()
-{
-  const nsStyleImageLayers& layers = StyleBackground()->mImage;
-  return DoGetImageLayerPositionX(layers);
-}
-
-already_AddRefed<CSSValue>
-nsComputedDOMStyle::DoGetBackgroundPositionY()
-{
-  const nsStyleImageLayers& layers = StyleBackground()->mImage;
-  return DoGetImageLayerPositionY(layers);
-}
-
-already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetBackgroundRepeat()
 {
   const nsStyleImageLayers& layers = StyleBackground()->mImage;
   return DoGetImageLayerRepeat(layers);
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetBackgroundSize()
@@ -6159,30 +6114,16 @@ nsComputedDOMStyle::DoGetMaskOrigin()
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetMaskPosition()
 {
   const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
   return DoGetImageLayerPosition(layers);
 }
 
 already_AddRefed<CSSValue>
-nsComputedDOMStyle::DoGetMaskPositionX()
-{
-  const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
-  return DoGetImageLayerPositionX(layers);
-}
-
-already_AddRefed<CSSValue>
-nsComputedDOMStyle::DoGetMaskPositionY()
-{
-  const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
-  return DoGetImageLayerPositionY(layers);
-}
-
-already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetMaskRepeat()
 {
   const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
   return DoGetImageLayerRepeat(layers);
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetMaskSize()
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -283,41 +283,35 @@ private:
   already_AddRefed<CSSValue> DoGetGridRowStart();
   already_AddRefed<CSSValue> DoGetGridRowEnd();
   already_AddRefed<CSSValue> DoGetGridColumnGap();
   already_AddRefed<CSSValue> DoGetGridRowGap();
 
   /* StyleImageLayer properties */
   already_AddRefed<CSSValue> DoGetImageLayerImage(const nsStyleImageLayers& aLayers);
   already_AddRefed<CSSValue> DoGetImageLayerPosition(const nsStyleImageLayers& aLayers);
-  already_AddRefed<CSSValue> DoGetImageLayerPositionX(const nsStyleImageLayers& aLayers);
-  already_AddRefed<CSSValue> DoGetImageLayerPositionY(const nsStyleImageLayers& aLayers);
   already_AddRefed<CSSValue> DoGetImageLayerRepeat(const nsStyleImageLayers& aLayers);
   already_AddRefed<CSSValue> DoGetImageLayerSize(const nsStyleImageLayers& aLayers);
 
   /* Background properties */
   already_AddRefed<CSSValue> DoGetBackgroundAttachment();
   already_AddRefed<CSSValue> DoGetBackgroundColor();
   already_AddRefed<CSSValue> DoGetBackgroundImage();
   already_AddRefed<CSSValue> DoGetBackgroundPosition();
-  already_AddRefed<CSSValue> DoGetBackgroundPositionX();
-  already_AddRefed<CSSValue> DoGetBackgroundPositionY();
   already_AddRefed<CSSValue> DoGetBackgroundRepeat();
   already_AddRefed<CSSValue> DoGetBackgroundClip();
   already_AddRefed<CSSValue> DoGetBackgroundBlendMode();
   already_AddRefed<CSSValue> DoGetBackgroundOrigin();
   already_AddRefed<CSSValue> DoGetBackgroundSize();
 
   /* Mask properties */
   already_AddRefed<CSSValue> DoGetMask();
 #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
   already_AddRefed<CSSValue> DoGetMaskImage();
   already_AddRefed<CSSValue> DoGetMaskPosition();
-  already_AddRefed<CSSValue> DoGetMaskPositionX();
-  already_AddRefed<CSSValue> DoGetMaskPositionY();
   already_AddRefed<CSSValue> DoGetMaskRepeat();
   already_AddRefed<CSSValue> DoGetMaskClip();
   already_AddRefed<CSSValue> DoGetMaskOrigin();
   already_AddRefed<CSSValue> DoGetMaskSize();
   already_AddRefed<CSSValue> DoGetMaskMode();
   already_AddRefed<CSSValue> DoGetMaskComposite();
 #endif
   /* Padding properties */
--- a/layout/style/nsComputedDOMStylePropertyList.h
+++ b/layout/style/nsComputedDOMStylePropertyList.h
@@ -55,18 +55,16 @@ COMPUTED_STYLE_PROP(backface_visibility,
 //// COMPUTED_STYLE_PROP(background,               Background)
 COMPUTED_STYLE_PROP(background_attachment,         BackgroundAttachment)
 COMPUTED_STYLE_PROP(background_blend_mode,         BackgroundBlendMode)
 COMPUTED_STYLE_PROP(background_clip,               BackgroundClip)
 COMPUTED_STYLE_PROP(background_color,              BackgroundColor)
 COMPUTED_STYLE_PROP(background_image,              BackgroundImage)
 COMPUTED_STYLE_PROP(background_origin,             BackgroundOrigin)
 COMPUTED_STYLE_PROP(background_position,           BackgroundPosition)
-COMPUTED_STYLE_PROP(background_position_x,         BackgroundPositionX)
-COMPUTED_STYLE_PROP(background_position_y,         BackgroundPositionY)
 COMPUTED_STYLE_PROP(background_repeat,             BackgroundRepeat)
 COMPUTED_STYLE_PROP(background_size,               BackgroundSize)
 //// COMPUTED_STYLE_PROP(border,                   Border)
 //// COMPUTED_STYLE_PROP(border_bottom,            BorderBottom)
 COMPUTED_STYLE_PROP(border_bottom_color,           BorderBottomColor)
 COMPUTED_STYLE_PROP(border_bottom_left_radius,     BorderBottomLeftRadius)
 COMPUTED_STYLE_PROP(border_bottom_right_radius,    BorderBottomRightRadius)
 COMPUTED_STYLE_PROP(border_bottom_style,           BorderBottomStyle)
@@ -332,18 +330,16 @@ COMPUTED_STYLE_PROP(marker_start,       
 COMPUTED_STYLE_PROP(mask,                          Mask)
 #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
 COMPUTED_STYLE_PROP(mask_clip,                     MaskClip)
 COMPUTED_STYLE_PROP(mask_composite,                MaskComposite)
 COMPUTED_STYLE_PROP(mask_image,                    MaskImage)
 COMPUTED_STYLE_PROP(mask_mode,                     MaskMode)
 COMPUTED_STYLE_PROP(mask_origin,                   MaskOrigin)
 COMPUTED_STYLE_PROP(mask_position,                 MaskPosition)
-COMPUTED_STYLE_PROP(mask_position_x,               MaskPositionX)
-COMPUTED_STYLE_PROP(mask_position_y,               MaskPositionY)
 COMPUTED_STYLE_PROP(mask_repeat,                   MaskRepeat)
 COMPUTED_STYLE_PROP(mask_size,                     MaskSize)
 #endif
 COMPUTED_STYLE_PROP(mask_type,                     MaskType)
 COMPUTED_STYLE_PROP(paint_order,                   PaintOrder)
 COMPUTED_STYLE_PROP(shape_rendering,               ShapeRendering)
 COMPUTED_STYLE_PROP(stop_color,                    StopColor)
 COMPUTED_STYLE_PROP(stop_opacity,                  StopOpacity)
--- a/layout/style/nsDOMCSSAttrDeclaration.cpp
+++ b/layout/style/nsDOMCSSAttrDeclaration.cpp
@@ -173,25 +173,21 @@ nsDOMCSSAttributeDeclaration::GetParentO
 
 NS_IMETHODIMP
 nsDOMCSSAttributeDeclaration::SetPropertyValue(const nsCSSProperty aPropID,
                                                const nsAString& aValue)
 {
   // Scripted modifications to style.opacity or style.transform
   // could immediately force us into the animated state if heuristics suggest
   // this is scripted animation.
-  // FIXME: This is missing the margin shorthand and the logical versions of
-  // the margin properties, see bug 1266287.
   if (aPropID == eCSSProperty_opacity || aPropID == eCSSProperty_transform ||
       aPropID == eCSSProperty_left || aPropID == eCSSProperty_top ||
       aPropID == eCSSProperty_right || aPropID == eCSSProperty_bottom ||
       aPropID == eCSSProperty_margin_left || aPropID == eCSSProperty_margin_top ||
       aPropID == eCSSProperty_margin_right || aPropID == eCSSProperty_margin_bottom ||
-      aPropID == eCSSProperty_background_position_x ||
-      aPropID == eCSSProperty_background_position_y ||
       aPropID == eCSSProperty_background_position) {
     nsIFrame* frame = mElement->GetPrimaryFrame();
     if (frame) {
       ActiveLayerTracker::NotifyInlineStyleRuleModified(frame, aPropID, aValue, this);
     }
   }
   return nsDOMCSSDeclaration::SetPropertyValue(aPropID, aValue);
 }
--- a/layout/style/nsDOMCSSDeclaration.cpp
+++ b/layout/style/nsDOMCSSDeclaration.cpp
@@ -75,18 +75,16 @@ nsDOMCSSDeclaration::GetCustomPropertyVa
 }
 
 NS_IMETHODIMP
 nsDOMCSSDeclaration::SetPropertyValue(const nsCSSProperty aPropID,
                                       const nsAString& aValue)
 {
   switch (aPropID) {
     case eCSSProperty_background_position:
-    case eCSSProperty_background_position_x:
-    case eCSSProperty_background_position_y:
     case eCSSProperty_transform:
     case eCSSProperty_top:
     case eCSSProperty_left:
     case eCSSProperty_bottom:
     case eCSSProperty_right:
     case eCSSProperty_margin:
     case eCSSProperty_margin_top:
     case eCSSProperty_margin_left:
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -6622,19 +6622,16 @@ ComputePositionValue(nsStyleContext* aSt
                      const nsCSSValue& aValue,
                      nsStyleImageLayers::Position& aComputedValue,
                      RuleNodeCacheConditions& aConditions)
 {
   NS_ASSERTION(aValue.GetUnit() == eCSSUnit_Array,
                "unexpected unit for CSS <position> value");
 
   RefPtr<nsCSSValue::Array> positionArray = aValue.GetArrayValue();
-  NS_ASSERTION(positionArray->Count() == 4,
-               "unexpected number of values in CSS <position> value");
-
   const nsCSSValue &xEdge   = positionArray->Item(0);
   const nsCSSValue &xOffset = positionArray->Item(1);
   const nsCSSValue &yEdge   = positionArray->Item(2);
   const nsCSSValue &yOffset = positionArray->Item(3);
 
   NS_ASSERTION((eCSSUnit_Enumerated == xEdge.GetUnit()  ||
                 eCSSUnit_Null       == xEdge.GetUnit()) &&
                (eCSSUnit_Enumerated == yEdge.GetUnit()  ||
@@ -6647,43 +6644,29 @@ ComputePositionValue(nsStyleContext* aSt
                        &aComputedValue.mXPosition,
                        aConditions);
 
   ComputePositionCoord(aStyleContext, yEdge, yOffset,
                        &aComputedValue.mYPosition,
                        aConditions);
 }
 
-/* Helper function to convert the -x or -y part of a CSS <position> specified
- * value into its computed-style form. */
-static void
-ComputePositionCoordValue(nsStyleContext* aStyleContext,
-                          const nsCSSValue& aValue,
-                          nsStyleImageLayers::Position::PositionCoord& aComputedValue,
-                          RuleNodeCacheConditions& aConditions)
-{
-  NS_ASSERTION(aValue.GetUnit() == eCSSUnit_Array,
-               "unexpected unit for position coord value");
-
-  RefPtr<nsCSSValue::Array> positionArray = aValue.GetArrayValue();
-  NS_ASSERTION(positionArray->Count() == 2,
-               "unexpected number of values, expecting one edge and one offset");
-
-  const nsCSSValue &edge   = positionArray->Item(0);
-  const nsCSSValue &offset = positionArray->Item(1);
-
-  NS_ASSERTION((eCSSUnit_Enumerated == edge.GetUnit() ||
-                eCSSUnit_Null       == edge.GetUnit()) &&
-               eCSSUnit_Enumerated != offset.GetUnit(),
-               "Invalid background position");
-
-  ComputePositionCoord(aStyleContext, edge, offset,
-                       &aComputedValue,
-                       aConditions);
-}
+template <>
+struct BackgroundItemComputer<nsCSSValueList, nsStyleImageLayers::Position>
+{
+  static void ComputeValue(nsStyleContext* aStyleContext,
+                           const nsCSSValueList* aSpecifiedValue,
+                           nsStyleImageLayers::Position& aComputedValue,
+                           RuleNodeCacheConditions& aConditions)
+  {
+    ComputePositionValue(aStyleContext, aSpecifiedValue->mValue,
+                         aComputedValue, aConditions);
+  }
+};
+
 
 struct BackgroundSizeAxis {
   nsCSSValue nsCSSValuePairList::* specified;
   nsStyleImageLayers::Size::Dimension nsStyleImageLayers::Size::* result;
   uint8_t nsStyleImageLayers::Size::* type;
 };
 
 static const BackgroundSizeAxis gBGSizeAxes[] = {
@@ -6839,86 +6822,16 @@ SetImageLayerList(nsStyleContext* aStyle
   default:
     MOZ_ASSERT(false, "unexpected unit");
   }
 
   if (aItemCount > aMaxItemCount)
     aMaxItemCount = aItemCount;
 }
 
-// The same as SetImageLayerList, but for values stored in
-// layer.mPosition.*aResultLocation instead of layer.*aResultLocation.
-// This code is duplicated because it would be annoying to make
-// SetImageLayerList generic enough to handle both cases.
-static void
-SetImageLayerPositionCoordList(
-                  nsStyleContext* aStyleContext,
-                  const nsCSSValue& aValue,
-                  nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
-                  const nsStyleAutoArray<nsStyleImageLayers::Layer>& aParentLayers,
-                  nsStyleImageLayers::Position::PositionCoord
-                      nsStyleImageLayers::Position::* aResultLocation,
-                  nsStyleImageLayers::Position::PositionCoord aInitialValue,
-                  uint32_t aParentItemCount,
-                  uint32_t& aItemCount,
-                  uint32_t& aMaxItemCount,
-                  bool& aRebuild,
-                  RuleNodeCacheConditions& aConditions)
-{
-  switch (aValue.GetUnit()) {
-  case eCSSUnit_Null:
-    break;
-
-  case eCSSUnit_Inherit:
-    aRebuild = true;
-    aConditions.SetUncacheable();
-    aLayers.EnsureLengthAtLeast(aParentItemCount);
-    aItemCount = aParentItemCount;
-    for (uint32_t i = 0; i < aParentItemCount; ++i) {
-      aLayers[i].mPosition.*aResultLocation = aParentLayers[i].mPosition.*aResultLocation;
-    }
-    break;
-
-  case eCSSUnit_Initial:
-  case eCSSUnit_Unset:
-    aRebuild = true;
-    aItemCount = 1;
-    aLayers[0].mPosition.*aResultLocation = aInitialValue;
-    break;
-
-  case eCSSUnit_List:
-  case eCSSUnit_ListDep: {
-    aRebuild = true;
-    aItemCount = 0;
-    const nsCSSValueList* item = aValue.GetListValue();
-    do {
-      NS_ASSERTION(item->mValue.GetUnit() != eCSSUnit_Null &&
-                   item->mValue.GetUnit() != eCSSUnit_Inherit &&
-                   item->mValue.GetUnit() != eCSSUnit_Initial &&
-                   item->mValue.GetUnit() != eCSSUnit_Unset,
-                   "unexpected unit");
-      ++aItemCount;
-      aLayers.EnsureLengthAtLeast(aItemCount);
-
-      ComputePositionCoordValue(aStyleContext, item->mValue,
-                                aLayers[aItemCount-1].mPosition.*aResultLocation,
-                                aConditions);
-      item = item->mNext;
-    } while (item);
-    break;
-  }
-
-  default:
-    MOZ_ASSERT(false, "unexpected unit");
-  }
-
-  if (aItemCount > aMaxItemCount)
-    aMaxItemCount = aItemCount;
-}
-
 template <class ComputedValueItem>
 static void
 SetImageLayerPairList(nsStyleContext* aStyleContext,
                       const nsCSSValue& aValue,
                       nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
                       const nsStyleAutoArray<nsStyleImageLayers::Layer>& aParentLayers,
                       ComputedValueItem nsStyleImageLayers::Layer::*
                                                                 aResultLocation,
@@ -6993,34 +6906,16 @@ FillBackgroundList(
   for (uint32_t sourceLayer = 0, destLayer = aItemCount;
        destLayer < aFillCount;
        ++sourceLayer, ++destLayer) {
     aLayers[destLayer].*aResultLocation =
       aLayers[sourceLayer].*aResultLocation;
   }
 }
 
-// The same as FillBackgroundList, but for values stored in
-// layer.mPosition.*aResultLocation instead of layer.*aResultLocation.
-static void
-FillBackgroundPositionCoordList(
-    nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
-    nsStyleImageLayers::Position::PositionCoord
-        nsStyleImageLayers::Position::* aResultLocation,
-    uint32_t aItemCount, uint32_t aFillCount)
-{
-  NS_PRECONDITION(aFillCount <= aLayers.Length(), "unexpected array length");
-  for (uint32_t sourceLayer = 0, destLayer = aItemCount;
-       destLayer < aFillCount;
-       ++sourceLayer, ++destLayer) {
-    aLayers[destLayer].mPosition.*aResultLocation =
-      aLayers[sourceLayer].mPosition.*aResultLocation;
-  }
-}
-
 const void*
 nsRuleNode::ComputeBackgroundData(void* aStartStruct,
                                   const nsRuleData* aRuleData,
                                   nsStyleContext* aContext,
                                   nsRuleNode* aHighestNode,
                                   const RuleDetail aRuleDetail,
                                   const RuleNodeCacheConditions aConditions)
 {
@@ -7095,37 +6990,25 @@ nsRuleNode::ComputeBackgroundData(void* 
                     bg->mImage.mLayers,
                     parentBG->mImage.mLayers,
                     &nsStyleImageLayers::Layer::mOrigin,
                     uint8_t(NS_STYLE_IMAGELAYER_ORIGIN_PADDING),
                     parentBG->mImage.mOriginCount,
                     bg->mImage.mOriginCount, maxItemCount, rebuild,
                     conditions);
 
-  // background-position-x/y: enum, length, percent (flags), inherit [list]
-  nsStyleImageLayers::Position::PositionCoord initialPositionCoord;
-  initialPositionCoord.mPercent = 0.0f;
-  initialPositionCoord.mLength = 0;
-  initialPositionCoord.mHasPercent = true;
-
-  SetImageLayerPositionCoordList(
-                    aContext, *aRuleData->ValueForBackgroundPositionX(),
+  // background-position: enum, length, percent (flags), inherit [pair list]
+  nsStyleImageLayers::Position initialPosition;
+  initialPosition.SetInitialPercentValues(0.0f);
+  SetImageLayerList(aContext, *aRuleData->ValueForBackgroundPosition(),
                     bg->mImage.mLayers,
                     parentBG->mImage.mLayers,
-                    &nsStyleImageLayers::Position::mXPosition,
-                    initialPositionCoord, parentBG->mImage.mPositionXCount,
-                    bg->mImage.mPositionXCount, maxItemCount, rebuild,
-                    conditions);
-  SetImageLayerPositionCoordList(
-                    aContext, *aRuleData->ValueForBackgroundPositionY(),
-                    bg->mImage.mLayers,
-                    parentBG->mImage.mLayers,
-                    &nsStyleImageLayers::Position::mYPosition,
-                    initialPositionCoord, parentBG->mImage.mPositionYCount,
-                    bg->mImage.mPositionYCount, maxItemCount, rebuild,
+                    &nsStyleImageLayers::Layer::mPosition,
+                    initialPosition, parentBG->mImage.mPositionCount,
+                    bg->mImage.mPositionCount, maxItemCount, rebuild,
                     conditions);
 
   // background-size: enum, length, auto, inherit, initial [pair list]
   nsStyleImageLayers::Size initialSize;
   initialSize.SetInitialValues();
   SetImageLayerPairList(aContext, *aRuleData->ValueForBackgroundSize(),
                         bg->mImage.mLayers,
                         parentBG->mImage.mLayers,
@@ -7153,22 +7036,19 @@ nsRuleNode::ComputeBackgroundData(void* 
                        &nsStyleImageLayers::Layer::mClip,
                        bg->mImage.mClipCount, fillCount);
     FillBackgroundList(bg->mImage.mLayers,
                        &nsStyleImageLayers::Layer::mBlendMode,
                        bg->mImage.mBlendModeCount, fillCount);
     FillBackgroundList(bg->mImage.mLayers,
                        &nsStyleImageLayers::Layer::mOrigin,
                        bg->mImage.mOriginCount, fillCount);
-    FillBackgroundPositionCoordList(bg->mImage.mLayers,
-                                    &nsStyleImageLayers::Position::mXPosition,
-                                    bg->mImage.mPositionXCount, fillCount);
-    FillBackgroundPositionCoordList(bg->mImage.mLayers,
-                                    &nsStyleImageLayers::Position::mYPosition,
-                                    bg->mImage.mPositionYCount, fillCount);
+    FillBackgroundList(bg->mImage.mLayers,
+                       &nsStyleImageLayers::Layer::mPosition,
+                       bg->mImage.mPositionCount, fillCount);
     FillBackgroundList(bg->mImage.mLayers,
                        &nsStyleImageLayers::Layer::mSize,
                        bg->mImage.mSizeCount, fillCount);
   }
 
   // Now that the dust has settled, register the images with the document
   bg->mImage.TrackImages(aContext->PresContext());
 
@@ -9907,37 +9787,25 @@ nsRuleNode::ComputeSVGResetData(void* aS
                     svgReset->mMask.mLayers,
                     parentSVGReset->mMask.mLayers,
                     &nsStyleImageLayers::Layer::mOrigin,
                     uint8_t(NS_STYLE_IMAGELAYER_ORIGIN_PADDING),
                     parentSVGReset->mMask.mOriginCount,
                     svgReset->mMask.mOriginCount, maxItemCount, rebuild,
                     conditions);
 
-  // mask-position-x/y: enum, length, percent (flags), inherit [list]
-  nsStyleImageLayers::Position::PositionCoord initialPositionCoord;
-  initialPositionCoord.mPercent = 0.0f;
-  initialPositionCoord.mLength = 0;
-  initialPositionCoord.mHasPercent = true;
-
-  SetImageLayerPositionCoordList(
-                    aContext, *aRuleData->ValueForMaskPositionX(),
+  // mask-position: enum, length, percent (flags), inherit [pair list]
+  nsStyleImageLayers::Position initialPosition;
+  initialPosition.SetInitialPercentValues(0.0f);
+  SetImageLayerList(aContext, *aRuleData->ValueForMaskPosition(),
                     svgReset->mMask.mLayers,
                     parentSVGReset->mMask.mLayers,
-                    &nsStyleImageLayers::Position::mXPosition,
-                    initialPositionCoord, parentSVGReset->mMask.mPositionXCount,
-                    svgReset->mMask.mPositionXCount, maxItemCount, rebuild,
-                    conditions);
-  SetImageLayerPositionCoordList(
-                    aContext, *aRuleData->ValueForMaskPositionY(),
-                    svgReset->mMask.mLayers,
-                    parentSVGReset->mMask.mLayers,
-                    &nsStyleImageLayers::Position::mYPosition,
-                    initialPositionCoord, parentSVGReset->mMask.mPositionYCount,
-                    svgReset->mMask.mPositionYCount, maxItemCount, rebuild,
+                    &nsStyleImageLayers::Layer::mPosition,
+                    initialPosition, parentSVGReset->mMask.mPositionCount,
+                    svgReset->mMask.mPositionCount, maxItemCount, rebuild,
                     conditions);
 
   // mask-size: enum, length, auto, inherit, initial [pair list]
   nsStyleImageLayers::Size initialSize;
   initialSize.SetInitialValues();
   SetImageLayerPairList(aContext, *aRuleData->ValueForMaskSize(),
                         svgReset->mMask.mLayers,
                         parentSVGReset->mMask.mLayers,
@@ -9981,22 +9849,19 @@ nsRuleNode::ComputeSVGResetData(void* aS
                        &nsStyleImageLayers::Layer::mRepeat,
                        svgReset->mMask.mRepeatCount, fillCount);
     FillBackgroundList(svgReset->mMask.mLayers,
                        &nsStyleImageLayers::Layer::mClip,
                        svgReset->mMask.mClipCount, fillCount);
     FillBackgroundList(svgReset->mMask.mLayers,
                        &nsStyleImageLayers::Layer::mOrigin,
                        svgReset->mMask.mOriginCount, fillCount);
-    FillBackgroundPositionCoordList(svgReset->mMask.mLayers,
-                                    &nsStyleImageLayers::Position::mXPosition,
-                                    svgReset->mMask.mPositionXCount, fillCount);
-    FillBackgroundPositionCoordList(svgReset->mMask.mLayers,
-                                    &nsStyleImageLayers::Position::mYPosition,
-                                    svgReset->mMask.mPositionYCount, fillCount);
+    FillBackgroundList(svgReset->mMask.mLayers,
+                       &nsStyleImageLayers::Layer::mPosition,
+                       svgReset->mMask.mPositionCount, fillCount);
     FillBackgroundList(svgReset->mMask.mLayers,
                        &nsStyleImageLayers::Layer::mSize,
                        svgReset->mMask.mSizeCount, fillCount);
     FillBackgroundList(svgReset->mMask.mLayers,
                        &nsStyleImageLayers::Layer::mMaskMode,
                        svgReset->mMask.mMaskModeCount, fillCount);
     FillBackgroundList(svgReset->mMask.mLayers,
                        &nsStyleImageLayers::Layer::mComposite,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2276,85 +2276,80 @@ nsStyleImage::operator==(const nsStyleIm
 // nsStyleImageLayers
 //
 
 const nsCSSProperty nsStyleImageLayers::kBackgroundLayerTable[] = {
   eCSSProperty_background,                // shorthand
   eCSSProperty_background_color,          // color
   eCSSProperty_background_image,          // image
   eCSSProperty_background_repeat,         // repeat
-  eCSSProperty_background_position_x,     // positionX
-  eCSSProperty_background_position_y,     // positionY
+  eCSSProperty_background_position,       // position
   eCSSProperty_background_clip,           // clip
   eCSSProperty_background_origin,         // origin
   eCSSProperty_background_size,           // size
   eCSSProperty_background_attachment,     // attachment
   eCSSProperty_UNKNOWN,                   // maskMode
   eCSSProperty_UNKNOWN                    // composite
 };
 
 #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
 const nsCSSProperty nsStyleImageLayers::kMaskLayerTable[] = {
   eCSSProperty_mask,                      // shorthand
   eCSSProperty_UNKNOWN,                   // color
   eCSSProperty_mask_image,                // image
   eCSSProperty_mask_repeat,               // repeat
-  eCSSProperty_mask_position_x,           // positionX
-  eCSSProperty_mask_position_y,           // positionY
+  eCSSProperty_mask_position,             // position
   eCSSProperty_mask_clip,                 // clip
   eCSSProperty_mask_origin,               // origin
   eCSSProperty_mask_size,                 // size
   eCSSProperty_UNKNOWN,                   // attachment
   eCSSProperty_mask_mode,                 // maskMode
   eCSSProperty_mask_composite             // composite
 };
 #endif
 
 nsStyleImageLayers::nsStyleImageLayers()
   : mAttachmentCount(1)
   , mClipCount(1)
   , mOriginCount(1)
   , mRepeatCount(1)
-  , mPositionXCount(1)
-  , mPositionYCount(1)
+  , mPositionCount(1)
   , mImageCount(1)
   , mSizeCount(1)
   , mMaskModeCount(1)
   , mBlendModeCount(1)
   , mCompositeCount(1)
   , mLayers(nsStyleAutoArray<Layer>::WITH_SINGLE_INITIAL_ELEMENT)
 {
   MOZ_COUNT_CTOR(nsStyleImageLayers);
 }
 
 nsStyleImageLayers::nsStyleImageLayers(const nsStyleImageLayers &aSource)
   : mAttachmentCount(aSource.mAttachmentCount)
   , mClipCount(aSource.mClipCount)
   , mOriginCount(aSource.mOriginCount)
   , mRepeatCount(aSource.mRepeatCount)
-  , mPositionXCount(aSource.mPositionXCount)
-  , mPositionYCount(aSource.mPositionYCount)
+  , mPositionCount(aSource.mPositionCount)
   , mImageCount(aSource.mImageCount)
   , mSizeCount(aSource.mSizeCount)
   , mMaskModeCount(aSource.mMaskModeCount)
   , mBlendModeCount(aSource.mBlendModeCount)
   , mCompositeCount(aSource.mCompositeCount)
   , mLayers(aSource.mLayers) // deep copy
 {
   MOZ_COUNT_CTOR(nsStyleImageLayers);
   // If the deep copy of mLayers failed, truncate the counts.
   uint32_t count = mLayers.Length();
   if (count != aSource.mLayers.Length()) {
     NS_WARNING("truncating counts due to out-of-memory");
     mAttachmentCount = std::max(mAttachmentCount, count);
     mClipCount = std::max(mClipCount, count);
     mOriginCount = std::max(mOriginCount, count);
     mRepeatCount = std::max(mRepeatCount, count);
-    mPositionXCount = std::max(mPositionXCount, count);
-    mPositionYCount = std::max(mPositionYCount, count);
+    mPositionCount = std::max(mPositionCount, count);
     mImageCount = std::max(mImageCount, count);
     mSizeCount = std::max(mSizeCount, count);
     mMaskModeCount = std::max(mMaskModeCount, count);
     mBlendModeCount = std::max(mBlendModeCount, count);
     mCompositeCount = std::max(mCompositeCount, count);
   }
 }
 
@@ -2394,18 +2389,17 @@ nsStyleImageLayers::CalcDifference(const
 
   if (mAttachmentCount != aOther.mAttachmentCount ||
       mBlendModeCount != aOther.mBlendModeCount ||
       mClipCount != aOther.mClipCount ||
       mCompositeCount != aOther.mCompositeCount ||
       mMaskModeCount != aOther.mMaskModeCount ||
       mOriginCount != aOther.mOriginCount ||
       mRepeatCount != aOther.mRepeatCount ||
-      mPositionXCount != aOther.mPositionXCount ||
-      mPositionYCount != aOther.mPositionYCount ||
+      mPositionCount != aOther.mPositionCount ||
       mSizeCount != aOther.mSizeCount) {
     NS_UpdateHint(hint, nsChangeHint_NeutralChange);
   }
 
   return hint;
 }
 
 bool
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -522,18 +522,17 @@ struct nsStyleImageLayers {
   }
 
   // Indices into kBackgroundLayerTable and kMaskLayerTable
   enum {
     shorthand = 0,
     color,
     image,
     repeat,
-    positionX,
-    positionY,
+    position,
     clip,
     origin,
     size,
     attachment,
     maskMode,
     composite
   };
 
@@ -733,18 +732,17 @@ struct nsStyleImageLayers {
   };
 
   // The (positive) number of computed values of each property, since
   // the lengths of the lists are independent.
   uint32_t mAttachmentCount,
            mClipCount,
            mOriginCount,
            mRepeatCount,
-           mPositionXCount,
-           mPositionYCount,
+           mPositionCount,
            mImageCount,
            mSizeCount,
            mMaskModeCount,
            mBlendModeCount,
            mCompositeCount;
 
   // Layers are stored in an array, matching the top-to-bottom order in
   // which they are specified in CSS.  The number of layers to be used
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -2135,17 +2135,17 @@ var gCSSProperties = {
     initial_values: [ "auto" ],
     other_values: [ "none", "text", "element", "elements", "all", "toggle", "tri-state", "-moz-all", "-moz-none" ],
     invalid_values: []
   },
   "background": {
     domProp: "background",
     inherited: false,
     type: CSS_TYPE_TRUE_SHORTHAND,
-    subproperties: [ "background-attachment", "background-color", "background-image", "background-position-x", "background-position-y", "background-repeat", "background-clip", "background-origin", "background-size" ],
+    subproperties: [ "background-attachment", "background-color", "background-image", "background-position", "background-repeat", "background-clip", "background-origin", "background-size" ],
     initial_values: [ "transparent", "none", "repeat", "scroll", "0% 0%", "top left", "left top", "0% 0% / auto", "top left / auto", "left top / auto", "0% 0% / auto auto",
       "transparent none", "top left none", "left top none", "none left top", "none top left", "none 0% 0%", "left top / auto none", "left top / auto auto none",
       "transparent none repeat scroll top left", "left top repeat none scroll transparent", "transparent none repeat scroll top left / auto", "left top / auto repeat none scroll transparent", "none repeat scroll 0% 0% / auto auto transparent" ],
     other_values: [
         /* without multiple backgrounds */
       "green",
       "none green repeat scroll left top",
       "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)",
@@ -2288,17 +2288,17 @@ var gCSSProperties = {
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "padding-box" ],
     other_values: [ "border-box", "content-box", "border-box, padding-box", "padding-box, padding-box, padding-box", "border-box, border-box" ],
     invalid_values: [ "margin-box", "padding-box padding-box" ]
   },
   "background-position": {
     domProp: "backgroundPosition",
     inherited: false,
-    type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
+    type: CSS_TYPE_LONGHAND,
     initial_values: [ "top 0% left 0%", "top 0% left", "top left", "left top", "0% 0%", "0% top", "left 0%" ],
     other_values: [ "top", "left", "right", "bottom", "center", "center bottom", "bottom center", "center right", "right center", "center top", "top center", "center left", "left center", "right bottom", "bottom right", "50%", "top left, top left", "top left, top right", "top right, top left", "left top, 0% 0%", "10% 20%, 30%, 40%", "top left, bottom right", "right bottom, left top", "0%", "0px", "30px", "0%, 10%, 20%, 30%", "top, top, top, top, top",
       "calc(20px)",
       "calc(20px) 10px",
       "10px calc(20px)",
       "calc(20px) 25%",
       "25% calc(20px)",
       "calc(20px) calc(20px)",
@@ -2320,81 +2320,28 @@ var gCSSProperties = {
       "top 3em right 10px",
       "left 15px",
       "10px top",
       "left top 15px",
       "left 10px top",
       "left 20%",
       "right 20%"
     ],
-    subproperties: [ "background-position-x", "background-position-y" ],
     invalid_values: [ "center 10px center 4px", "center 10px center",
                       "top 20%", "bottom 20%", "50% left", "top 50%",
                       "50% bottom 10%", "right 10% 50%", "left right",
                       "top bottom", "left 10% right",
                       "top 20px bottom 20px", "left left",
                       "0px calc(0px + rubbish)"],
     quirks_values: {
       "20 20": "20px 20px",
       "10 5px": "10px 5px",
       "7px 2": "7px 2px",
     },
   },
-  "background-position-x": {
-    domProp: "backgroundPositionX",
-    inherited: false,
-    type: CSS_TYPE_LONGHAND,
-    initial_values: [ "left 0%", "left", "0%" ],
-    other_values: [ "right", "center", "50%", "left, left", "left, right", "right, left", "left, 0%", "10%, 20%, 40%", "0px", "30px", "0%, 10%, 20%, 30%", "left, left, left, left, left",
-      "calc(20px)",
-      "calc(20px + 1em)",
-      "calc(20px / 2)",
-      "calc(20px + 50%)",
-      "calc(50% - 10px)",
-      "calc(-20px)",
-      "calc(-50%)",
-      "calc(-20%)",
-      "right 20px",
-      "left 20px",
-      "right -50px",
-      "left -50px",
-      "right 20px",
-      "right 3em",
-    ],
-    invalid_values: [ "center 10px", "right 10% 50%", "left right", "left left",
-                      "bottom 20px", "top 10%", "bottom 3em",
-                      "top", "bottom", "top, top", "top, bottom", "bottom, top", "top, 0%", "top, top, top, top, top",
-                      "calc(0px + rubbish)"],
-  },
-  "background-position-y": {
-    domProp: "backgroundPositionY",
-    inherited: false,
-    type: CSS_TYPE_LONGHAND,
-    initial_values: [ "top 0%", "top", "0%" ],
-    other_values: [ "bottom", "center", "50%", "top, top", "top, bottom", "bottom, top", "top, 0%", "10%, 20%, 40%", "0px", "30px", "0%, 10%, 20%, 30%", "top, top, top, top, top",
-      "calc(20px)",
-      "calc(20px + 1em)",
-      "calc(20px / 2)",
-      "calc(20px + 50%)",
-      "calc(50% - 10px)",
-      "calc(-20px)",
-      "calc(-50%)",
-      "calc(-20%)",
-      "bottom 20px",
-      "top 20px",
-      "bottom -50px",
-      "top -50px",
-      "bottom 20px",
-      "bottom 3em",
-    ],
-    invalid_values: [ "center 10px", "bottom 10% 50%", "top bottom", "top top",
-                      "right 20px", "left 10%", "right 3em",
-                      "left", "right", "left, left", "left, right", "right, left", "left, 0%", "left, left, left, left, left",
-                      "calc(0px + rubbish)"],
-  },
   "background-repeat": {
     domProp: "backgroundRepeat",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "repeat", "repeat repeat" ],
     other_values: [ "repeat-x", "repeat-y", "no-repeat",
       "repeat-x, repeat-x",
       "repeat, no-repeat",
@@ -6793,17 +6740,17 @@ function SupportsMaskShorthand() {
 }
 
 if (SupportsMaskShorthand()) {
   gCSSProperties["mask"] = {
     domProp: "mask",
     inherited: false,
     type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
     /* FIXME: All mask-border-* should be added when we implement them. */
-    subproperties: ["mask-clip", "mask-image", "mask-mode", "mask-origin", "mask-position-x", "mask-position-y", "mask-repeat", "mask-size" , "mask-composite"],
+    subproperties: ["mask-clip", "mask-image", "mask-mode", "mask-origin", "mask-position", "mask-repeat", "mask-size" , "mask-composite"],
     initial_values: [ "match-source", "none", "repeat", "add", "0% 0%", "top left", "left top", "0% 0% / auto", "top left / auto", "left top / auto", "0% 0% / auto auto",
       "top left none", "left top none", "none left top", "none top left", "none 0% 0%", "left top / auto none", "left top / auto auto none",
       "match-source none repeat add top left", "left top repeat none add", "none repeat add top left / auto", "left top / auto repeat none add match-source", "none repeat add 0% 0% / auto auto match-source" ],
     other_values: [
       "none alpha repeat add left top",
       "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)",
       "repeat url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==') alpha left top add",
       "repeat-x",
@@ -6917,17 +6864,17 @@ if (SupportsMaskShorthand()) {
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "padding-box" ],
     other_values: [ "border-box", "content-box", "border-box, padding-box", "padding-box, padding-box, padding-box", "border-box, border-box" ],
     invalid_values: [ "margin-box", "padding-box padding-box" ]
   };
   gCSSProperties["mask-position"] = {
     domProp: "maskPosition",
     inherited: false,
-    type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
+    type: CSS_TYPE_LONGHAND,
     initial_values: [ "top 0% left 0%", "top 0% left", "top left", "left top", "0% 0%", "0% top", "left 0%" ],
     other_values: [ "top", "left", "right", "bottom", "center", "center bottom", "bottom center", "center right", "right center", "center top", "top center", "center left", "left center", "right bottom", "bottom right", "50%", "top left, top left", "top left, top right", "top right, top left", "left top, 0% 0%", "10% 20%, 30%, 40%", "top left, bottom right", "right bottom, left top", "0%", "0px", "30px", "0%, 10%, 20%, 30%", "top, top, top, top, top",
       "calc(20px)",
       "calc(20px) 10px",
       "10px calc(20px)",
       "calc(20px) 25%",
       "25% calc(20px)",
       "calc(20px) calc(20px)",
@@ -6949,76 +6896,23 @@ if (SupportsMaskShorthand()) {
       "top 3em right 10px",
       "left 15px",
       "10px top",
       "left top 15px",
       "left 10px top",
       "left 20%",
       "right 20%"
     ],
-    subproperties: [ "mask-position-x", "mask-position-y" ],
     invalid_values: [ "center 10px center 4px", "center 10px center",
                       "top 20%", "bottom 20%", "50% left", "top 50%",
                       "50% bottom 10%", "right 10% 50%", "left right",
                       "top bottom", "left 10% right",
                       "top 20px bottom 20px", "left left",
                       "0px calc(0px + rubbish)"],
   };
-  gCSSProperties["mask-position-x"] = {
-    domProp: "maskPositionX",
-    inherited: false,
-    type: CSS_TYPE_LONGHAND,
-    initial_values: [ "left 0%", "left", "0%" ],
-    other_values: [ "right", "center", "50%", "left, left", "left, right", "right, left", "left, 0%", "10%, 20%, 40%", "0px", "30px", "0%, 10%, 20%, 30%", "left, left, left, left, left",
-      "calc(20px)",
-      "calc(20px + 1em)",
-      "calc(20px / 2)",
-      "calc(20px + 50%)",
-      "calc(50% - 10px)",
-      "calc(-20px)",
-      "calc(-50%)",
-      "calc(-20%)",
-      "right 20px",
-      "left 20px",
-      "right -50px",
-      "left -50px",
-      "right 20px",
-      "right 3em",
-    ],
-    invalid_values: [ "center 10px", "right 10% 50%", "left right", "left left",
-                      "bottom 20px", "top 10%", "bottom 3em",
-                      "top", "bottom", "top, top", "top, bottom", "bottom, top", "top, 0%", "top, top, top, top, top",
-                      "calc(0px + rubbish)"],
-  };
-  gCSSProperties["mask-position-y"] = {
-    domProp: "maskPositionY",
-    inherited: false,
-    type: CSS_TYPE_LONGHAND,
-    initial_values: [ "top 0%", "top", "0%" ],
-    other_values: [ "bottom", "center", "50%", "top, top", "top, bottom", "bottom, top", "top, 0%", "10%, 20%, 40%", "0px", "30px", "0%, 10%, 20%, 30%", "top, top, top, top, top",
-      "calc(20px)",
-      "calc(20px + 1em)",
-      "calc(20px / 2)",
-      "calc(20px + 50%)",
-      "calc(50% - 10px)",
-      "calc(-20px)",
-      "calc(-50%)",
-      "calc(-20%)",
-      "bottom 20px",
-      "top 20px",
-      "bottom -50px",
-      "top -50px",
-      "bottom 20px",
-      "bottom 3em",
-    ],
-    invalid_values: [ "center 10px", "bottom 10% 50%", "top bottom", "top top",
-                      "right 20px", "left 10%", "right 3em",
-                      "left", "right", "left, left", "left, right", "right, left", "left, 0%", "left, left, left, left, left",
-                      "calc(0px + rubbish)"],
-  };
   gCSSProperties["mask-repeat"] = {
     domProp: "maskRepeat",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "repeat", "repeat repeat" ],
     other_values: [ "repeat-x", "repeat-y", "no-repeat",
       "repeat-x, repeat-x",
       "repeat, no-repeat",
@@ -7424,30 +7318,16 @@ if (IsCSSPropertyPrefEnabled("layout.css
     };
     gCSSProperties["-webkit-mask-position"] = {
       domProp: "webkitMaskPosition",
       inherited: false,
       type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
       alias_for: "mask-position",
       subproperties: [ "mask-position" ],
     };
-    gCSSProperties["-webkit-mask-position-x"] = {
-      domProp: "webkitMaskPositionX",
-      inherited: false,
-      type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
-      alias_for: "mask-position-x",
-      subproperties: [ "mask-position-x" ],
-    };
-    gCSSProperties["-webkit-mask-position-y"] = {
-      domProp: "webkitMaskPositionY",
-      inherited: false,
-      type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
-      alias_for: "mask-position-y",
-      subproperties: [ "mask-position-y" ],
-    };
     gCSSProperties["-webkit-mask-repeat"] = {
       domProp: "webkitMaskRepeat",
       inherited: false,
       type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
       alias_for: "mask-repeat",
       subproperties: [ "mask-repeat" ],
     };
     gCSSProperties["-webkit-mask-size"] = {
--- a/layout/style/test/test_shorthand_property_getters.html
+++ b/layout/style/test/test_shorthand_property_getters.html
@@ -153,53 +153,16 @@ e.setAttribute("style", "background-clip
 is(e.style.background, "", "should not have background shorthand (background-attachment too short)");
 e.setAttribute("style", "background-clip: border-box, padding-box, border-box; background-origin: border-box, padding-box, padding-box; background-size: cover, auto, contain; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px, bottom; background-repeat: repeat-x, repeat, no-repeat");
 is(e.style.background, "", "should not have background shorthand (background-position too long)");
 e.setAttribute("style", "background-clip: border-box, padding-box, border-box; background-origin: border-box, padding-box, padding-box; background-size: cover, auto, contain; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat");
 is(e.style.background, "", "should not have background shorthand (background-repeat too short)");
 e.setAttribute("style", "background-clip: border-box, padding-box, border-box; background-origin: border-box, padding-box, padding-box; background-size: cover, auto, contain, contain; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
 is(e.style.background, "", "should not have background shorthand (background-size too long)");
 
-// Check that we only serialize background-position when the lists (of layers) for
-// the -x/-y subproperties are the same length.
-e.setAttribute("style", "background-position-x: 10%, left 2em, right; background-position-y: top 2em, bottom, 10%");
-is(e.style.backgroundPosition, "left 10% top 2em, left 2em bottom, right 10%", "should have background-position shorthand (both lists length 3)");
-e.setAttribute("style", "background-position-x: 10%, left 2em; background-position-y: top 2em, bottom, 10%");
-is(e.style.backgroundPosition, "", "should not have background-position shorthand (background-position-x too short)");
-e.setAttribute("style", "background-position-x: 10%, left 2em, right; background-position-y: top 2em");
-is(e.style.backgroundPosition, "", "should not have background-position shorthand (background-position-y too short)");
-
-// Check that background-position serialization doesn't produce invalid values.
-e.setAttribute("style", "background-position: 0px");
-is(e.style.backgroundPosition, "0px center", "1-value form should be accepted, with implied center value for background-position-y");
-e.setAttribute("style", "background-position: 0px center");
-is(e.style.backgroundPosition, "0px center", "2-value form 'x-offset' 'y-edge' should be accepted, and serialize to 2-value form");
-e.setAttribute("style", "background-position: left 0px center");
-is(e.style.backgroundPosition, "left 0px center", "3-value form 'x-edge' 'x-offset' 'y-edge' should be accepted and serialize to 3-value form");
-e.setAttribute("style", "background-position: left top 0px");
-is(e.style.backgroundPosition, "left top 0px", "3-value form 'x-edge' 'y-edge' 'y-offset' should be accepted and serialize to 3-value form");
-e.setAttribute("style", "background-position: left 0px top 0px");
-is(e.style.backgroundPosition, "left 0px top 0px", "4-value form should be accepted and serialize to 4-value form");
-e.setAttribute("style", "background-position-x: 0px; background-position-y: center");
-is(e.style.backgroundPosition, "0px center", "should always serialize to 2-value form if setting -x and -y with the 1-value form");
-e.setAttribute("style", "background-position-x: 0px; background-position-y: 0px");
-is(e.style.backgroundPosition, "0px 0px", "should always serialize to 2-value form if setting -x and -y with the 1-value form");
-e.setAttribute("style", "background-position-x: center; background-position-y: 0px");
-is(e.style.backgroundPosition, "center 0px", "should always serialize to 2-value form if setting -x and -y with the 1-value form");
-e.setAttribute("style", "background-position-x: left; background-position-y: top");
-is(e.style.backgroundPosition, "left top", "should always serialize to 2-value form if setting -x and -y with the 1-value form");
-e.setAttribute("style", "background-position-x: left 0px; background-position-y: center");
-is(e.style.backgroundPosition, "left 0px center", "should always serialize to 3-value form if both -x and -y specified an edge");
-e.setAttribute("style", "background-position-x: right; background-position-y: top 0px");
-is(e.style.backgroundPosition, "right top 0px", "should always serialize to 3-value form if both -x and -y specified an edge");
-e.setAttribute("style", "background-position-x: left 0px; background-position-y: 0px");
-is(e.style.backgroundPosition, "left 0px top 0px", "should serialize to 4-value form if 3-value form would only have one edge");
-e.setAttribute("style", "background-position-x: 0px; background-position-y: top 0px");
-is(e.style.backgroundPosition, "left 0px top 0px", "should serialize to 4-value form if 3-value form would only have one edge");
-
 // Check that we only serialize transition when the lists are the same length.
 e.setAttribute("style", "transition-property: color, width; transition-duration: 1s, 200ms; transition-timing-function: ease-in, linear; transition-delay: 0s, 1s");
 isnot(e.style.transition, "", "should have transition shorthand (lists same length)");
 e.setAttribute("style", "transition-property: color, width, left; transition-duration: 1s, 200ms; transition-timing-function: ease-in, linear; transition-delay: 0s, 1s");
 is(e.style.transition, "", "should not have transition shorthand (lists different lengths)");
 e.setAttribute("style", "transition-property: all; transition-duration: 1s, 200ms; transition-timing-function: ease-in, linear; transition-delay: 0s, 1s");
 is(e.style.transition, "", "should not have transition shorthand (lists different lengths)");
 e.setAttribute("style", "transition-property: color, width; transition-duration: 1s, 200ms, 300ms; transition-timing-function: ease-in, linear; transition-delay: 0s, 1s");
--- a/layout/style/test/test_transitions_per_property.html
+++ b/layout/style/test/test_transitions_per_property.html
@@ -85,30 +85,16 @@ var supported_properties = {
     "-moz-outline-radius-topright": [ test_radius_transition ],
     "background-color": [ test_color_transition,
                           test_currentcolor_transition ],
     "background-position": [ test_background_position_transition,
                              // FIXME: We don't currently test clamping,
                              // since background-position uses calc() as
                              // an intermediate form.
                              /* test_length_percent_pair_unclamped */ ],
-    "background-position-x": [ test_background_position_coord_transition,
-                               test_length_transition,
-                               test_percent_transition,
-                             // FIXME: We don't currently test clamping,
-                             // since background-position-x uses calc() as
-                             // an intermediate form.
-                             /* test_length_percent_pair_unclamped */ ],
-    "background-position-y": [ test_background_position_coord_transition,
-                               test_length_transition,
-                               test_percent_transition,
-                             // FIXME: We don't currently test clamping,
-                             // since background-position-y uses calc() as
-                             // an intermediate form.
-                             /* test_length_percent_pair_unclamped */ ],
     "background-size": [ test_background_size_transition,
                          // FIXME: We don't currently test clamping,
                          // since background-size uses calc() as an
                          // intermediate form.
                          /* test_length_percent_pair_clamped */ ],
     "border-bottom-color": [ test_color_transition,
                              test_currentcolor_transition,
                              test_border_color_transition ],
@@ -291,30 +277,16 @@ var supported_properties = {
 };
 
 if (SupportsMaskShorthand()) {
   supported_properties["mask-position"] = [ test_background_position_transition,
                                      // FIXME: We don't currently test clamping,
                                      // since mask-position uses calc() as
                                      // an intermediate form.
                                      /* test_length_percent_pair_unclamped */ ];
-  supported_properties["mask-position-x"] = [ test_background_position_coord_transition,
-                                              test_length_transition,
-                                              test_percent_transition,
-                                            // FIXME: We don't currently test clamping,
-                                            // since background-position-x uses calc() as
-                                            // an intermediate form.
-                                            /* test_length_percent_pair_unclamped */ ];
-  supported_properties["mask-position-y"] = [ test_background_position_coord_transition,
-                                              test_length_transition,
-                                              test_percent_transition,
-                                            // FIXME: We don't currently test clamping,
-                                            // since background-position-y uses calc() as
-                                            // an intermediate form.
-                                            /* test_length_percent_pair_unclamped */ ];
   supported_properties["mask-size"] = [ test_background_size_transition,
                                      // FIXME: We don't currently test clamping,
                                      // since mask-size uses calc() as an
                                      // intermediate form.
                                      /* test_length_percent_pair_clamped */ ];
 }
 
 var div = document.getElementById("display");
@@ -2116,264 +2088,171 @@ function test_background_size_transition
   div.style.setProperty("transition-property", prop, "");
   div.style.setProperty(prop, "100% 100%", "");
   is(cs.getPropertyValue(prop), "62.5% 85%",
      "property " + prop + ": interpolation of percents");
   check_distance(prop, "50% 80%", "62.5% 85%", "100% 100%");
   div.style.setProperty(prop, "contain", "");
   is(cs.getPropertyValue(prop), "contain",
      "property " + prop + ": can't interpolate 'contain'");
-  test_background_position_size_common(prop, true, true);
+  test_background_position_size_common(prop, true);
 }
 
 function test_background_position_transition(prop) {
-  var doesPropTakeListValues = (prop == "background-position");
-  var doesPropHaveDistanceComputation = (prop != "background-position");
 
   // Test interpolation between edge keywords, and between edge keyword and a
   // percent value. (Note: edge keywords are really aliases for percent vals.)
   div.style.setProperty("transition-property", "none", "");
   div.style.setProperty(prop, "center 80%", "");
   is(cs.getPropertyValue(prop), "50% 80%",
      "property " + prop + ": computed value before transition");
   div.style.setProperty("transition-property", prop, "");
   div.style.setProperty(prop, "bottom right", "");
   is(cs.getPropertyValue(prop), "62.5% 85%",
      "property " + prop + ": interpolation of edge keywords & percents");
-  if (doesPropHaveDistanceComputation) {
-    check_distance(prop, "center 80%", "62.5% 85%", "bottom right");
-  }
+  check_distance(prop, "center 80%", "62.5% 85%", "bottom right");
 
   // Test interpolation between edge keyword *with an offset* and non-keyword
   // values.
   div.style.setProperty("transition-property", "none", "");
   div.style.setProperty(prop, "right 20px bottom 30%", "");
   is(cs.getPropertyValue(prop), "calc(-20px + 100%) 70%",
      "property " + prop + ": computed value before transition");
   div.style.setProperty("transition-property", prop, "");
   div.style.setProperty(prop, "calc(40px + 20%) calc(12px + 30%)", "");
   is(cs.getPropertyValue(prop), "calc(-5px + 80%) calc(3px + 60%)",
      "property " + prop + ": interpolation of edge keywords w/ offsets & calc");
-  if (doesPropHaveDistanceComputation) {
-    check_distance(prop, "right 20px bottom 30%",
-                         "calc(-5px + 80%) calc(3px + 60%)",
-                         "calc(40px + 20%) calc(12px + 30%)");
-  }
-
-  test_background_position_size_common(prop, doesPropTakeListValues,
-                                       doesPropHaveDistanceComputation);
-}
-
-function test_background_position_coord_transition(prop) {
-  var endEdge = prop.endsWith("-x") ? "right" : "bottom";
-
-  // Test interpolation between edge keywords, and between edge keyword and a
-  // percent value. (Note: edge keywords are really aliases for percent vals.)
-  div.style.setProperty("transition-property", "none", "");
-  div.style.setProperty(prop, "center", "");
-  is(cs.getPropertyValue(prop), "50%",
-     "property " + prop + ": computed value before transition");
-  div.style.setProperty("transition-property", prop, "");
-  div.style.setProperty(prop, endEdge, "");
-  is(cs.getPropertyValue(prop), "62.5%",
-     "property " + prop + ": interpolation of edge keywords & percents");
-  check_distance(prop, "center", "62.5%", endEdge);
+  check_distance(prop, "right 20px bottom 30%",
+                       "calc(-5px + 80%) calc(3px + 60%)",
+                       "calc(40px + 20%) calc(12px + 30%)");
 
-  // Test interpolation between edge keyword *with an offset* and non-keyword
-  // values.
-  div.style.setProperty("transition-property", "none", "");
-  div.style.setProperty(prop, `${endEdge} 20px`, "");
-  is(cs.getPropertyValue(prop), "calc(-20px + 100%)",
-     "property " + prop + ": computed value before transition");
-  div.style.setProperty("transition-property", prop, "");
-  div.style.setProperty(prop, "calc(40px + 20%)", "");
-  is(cs.getPropertyValue(prop), "calc(-5px + 80%)",
-     "property " + prop + ": interpolation of edge keywords w/ offsets & calc");
-  check_distance(prop, `${endEdge} 20px`,
-                       "calc(-5px + 80%)",
-                       "calc(40px + 20%)");
+  var doesPropTakeListValues = (prop == "background-position");
 
-  div.style.setProperty(prop, "10px, 50px, 30px", "");
-  is(cs.getPropertyValue(prop), "10px, 50px, 30px",
-     "property " + prop + ": computed value before transition");
-  div.style.setProperty(prop, "50px, 70px, 30px", "");
-  is(cs.getPropertyValue(prop), "20px, 55px, 30px",
-     "property " + prop + ": interpolation of lists of lengths");
-  check_distance(prop, "10px, 50px, 30px",
-                       "20px, 55px, 30px",
-                       "50px, 70px, 30px");
-  div.style.setProperty(prop, "10px, 50%, 30%, 5px", "");
-  is(cs.getPropertyValue(prop), "10px, 50%, 30%, 5px",
-     "property " + prop + ": computed value before transition");
-  div.style.setProperty(prop, "50px, 70%, 30%, 25px", "");
-  is(cs.getPropertyValue(prop), "20px, 55%, 30%, 10px",
-     "property " + prop + ": interpolation of lists of lengths and percents");
-  check_distance(prop, "10px, 50%, 30%, 5px",
-                       "20px, 55%, 30%, 10px",
-                       "50px, 70%, 30%, 25px");
-  div.style.setProperty(prop, "20%, 8px", "");
-  is(cs.getPropertyValue(prop), "20%, 8px",
-     "property " + prop + ": computed value before transition");
-  div.style.setProperty(prop, "12px, 40%", "");
-  is(cs.getPropertyValue(prop), "calc(3px + 15%), calc(6px + 10%)",
-     "property " + prop + ": interpolation that computes to calc()");
-  check_distance(prop, "20%, 8px",
-                       "calc(3px + 15%), calc(6px + 10%)",
-                       "12px, 40%");
-  div.style.setProperty(prop, "calc(20% + 40px), 8px, calc(20px + 12%)", "");
-  is(cs.getPropertyValue(prop), "calc(40px + 20%), 8px, calc(20px + 12%)",
-     "property " + prop + ": computed value before transition");
-  div.style.setProperty(prop, "12px, calc(20%), calc(8px + 20%)", "");
-  is(cs.getPropertyValue(prop), "calc(33px + 15%), calc(6px + 5%), calc(17px + 14%)",
-     "property " + prop + ": interpolation that computes to calc()");
-  check_distance(prop, "calc(20% + 40px), 8px, calc(20px + 12%)",
-                       "calc(33px + 15%), calc(6px + 5%), calc(17px + 14%)",
-                       "12px, calc(20%), calc(8px + 20%)");
+  test_background_position_size_common(prop, doesPropTakeListValues);
 }
 
 /**
  * Common tests for 'background-position', 'background-size', and other
  * properties that take CSS value-type 'position' or 'bg-size'.
  *
  *  @arg prop The name of the property
  *  @arg doesPropTakeListValues
  *         If false, the property is assumed to just take a single 'position' or
  *         'bg-size' value. If true, the property is assumed to also accept
  *         comma-separated list of such values.
  */
-function test_background_position_size_common(prop, doesPropTakeListValues,
-                                              doesPropHaveDistanceComputation) {
+function test_background_position_size_common(prop, doesPropTakeListValues) {
   // Test non-list values
   div.style.setProperty("transition-property", "none", "");
   div.style.setProperty(prop, "40% 0%", "");
   is(cs.getPropertyValue(prop), "40% 0%",
      "property " + prop + ": computed value before transition");
   div.style.setProperty("transition-property", prop, "");
   div.style.setProperty(prop, "0% 0%", "");
   is(cs.getPropertyValue(prop), "30% 0%",
      "property " + prop + ": interpolation of percentages");
-  if (doesPropHaveDistanceComputation) {
-    check_distance(prop, "40% 0%", "30% 0%", "0% 0%");
-  }
+  check_distance(prop, "40% 0%", "30% 0%", "0% 0%");
 
   div.style.setProperty("transition-property", "none", "");
   div.style.setProperty(prop, "0% 40%", "");
   is(cs.getPropertyValue(prop), "0% 40%",
      "property " + prop + ": computed value before transition");
   div.style.setProperty("transition-property", prop, "");
   div.style.setProperty(prop, "0% 0%", "");
   is(cs.getPropertyValue(prop), "0% 30%",
      "property " + prop + ": interpolation of percentages");
-  if (doesPropHaveDistanceComputation) {
-    check_distance(prop, "0% 40%", "0% 30%", "0% 0%");
-  }
+  check_distance(prop, "0% 40%", "0% 30%", "0% 0%");
 
   div.style.setProperty("transition-property", "none", "");
   div.style.setProperty(prop, "10px 40px", "");
   is(cs.getPropertyValue(prop), "10px 40px",
      "property " + prop + ": computed value before transition");
   div.style.setProperty("transition-property", prop, "");
   div.style.setProperty(prop, "50px 0", "");
   is(cs.getPropertyValue(prop), "20px 30px",
      "property " + prop + ": interpolation of lengths");
-  if (doesPropHaveDistanceComputation) {
-    check_distance(prop, "10px 40px", "20px 30px", "50px 0");
-  }
+  check_distance(prop, "10px 40px", "20px 30px", "50px 0");
 
   // Test interpolation that computes to to calc() (transition from % to px)
   div.style.setProperty("transition-property", "none", "");
   div.style.setProperty(prop, "20% 40%", "");
   is(cs.getPropertyValue(prop), "20% 40%",
      "property " + prop + ": computed value before transition");
   div.style.setProperty("transition-property", prop, "");
   div.style.setProperty(prop, "12px 20px", "");
   is(cs.getPropertyValue(prop), "calc(3px + 15%) calc(5px + 30%)",
      "property " + prop + ": interpolation that computes to calc()");
-  if (doesPropHaveDistanceComputation) {
-    check_distance(prop, "20% 40%",
-                         "calc(3px + 15%) calc(5px + 30%)",
-                         "12px 20px");
-  }
+  check_distance(prop, "20% 40%",
+                       "calc(3px + 15%) calc(5px + 30%)",
+                       "12px 20px");
 
   // Test interpolation that computes to to calc() (transition from px to %)
   div.style.setProperty("transition-property", "none", "");
   div.style.setProperty(prop, "12px 20px", "");
   is(cs.getPropertyValue(prop), "12px 20px",
      "property " + prop + ": computed value before transition");
   div.style.setProperty("transition-property", prop, "");
   div.style.setProperty(prop, "20% 40%", "");
   is(cs.getPropertyValue(prop), "calc(9px + 5%) calc(15px + 10%)",
      "property " + prop + ": interpolation that computes to calc()");
-  if (doesPropHaveDistanceComputation) {
-    check_distance(prop, "12px 20px",
-                         "calc(9px + 5%) calc(15px + 10%)",
-                         "20% 40%");
-  }
+  check_distance(prop, "12px 20px",
+                       "calc(9px + 5%) calc(15px + 10%)",
+                       "20% 40%");
 
   // Test interpolation between calc() and non-calc()
   div.style.setProperty("transition-property", "none", "");
   div.style.setProperty(prop, "calc(40px + 10%) 16px", "");
   is(cs.getPropertyValue(prop), "calc(40px + 10%) 16px",
      "property " + prop + ": computed value before transition");
   div.style.setProperty("transition-property", prop, "");
   div.style.setProperty(prop, "30% calc(8px + 60%)", "");
   is(cs.getPropertyValue(prop), "calc(30px + 15%) calc(14px + 15%)",
      "property " + prop + ": interpolation between calc() and non-calc()");
-  if (doesPropHaveDistanceComputation) {
-    check_distance(prop, "calc(40px + 10%) 16px",
-                         "calc(30px + 15%) calc(14px + 15%)",
-                         "30% calc(8px + 60%)");
-  }
+  check_distance(prop, "calc(40px + 10%) 16px",
+                       "calc(30px + 15%) calc(14px + 15%)",
+                       "30% calc(8px + 60%)");
 
   // Test list values, if appropriate
   if (doesPropTakeListValues) {
     div.style.setProperty(prop, "10px 40px, 50px 50px, 30px 20px", "");
     is(cs.getPropertyValue(prop), "10px 40px, 50px 50px, 30px 20px",
        "property " + prop + ": computed value before transition");
     div.style.setProperty(prop, "50px 20px, 70px 50px, 30px 40px", "");
     is(cs.getPropertyValue(prop), "20px 35px, 55px 50px, 30px 25px",
        "property " + prop + ": interpolation of lists of lengths");
-    if (doesPropHaveDistanceComputation) {
-      check_distance(prop, "10px 40px, 50px 50px, 30px 20px",
-                           "20px 35px, 55px 50px, 30px 25px",
-                           "50px 20px, 70px 50px, 30px 40px");
-    }
+    check_distance(prop, "10px 40px, 50px 50px, 30px 20px",
+                         "20px 35px, 55px 50px, 30px 25px",
+                         "50px 20px, 70px 50px, 30px 40px");
     div.style.setProperty(prop, "10px 40%, 50% 50px, 30% 20%, 5px 10px", "");
     is(cs.getPropertyValue(prop), "10px 40%, 50% 50px, 30% 20%, 5px 10px",
        "property " + prop + ": computed value before transition");
     div.style.setProperty(prop, "50px 20%, 70% 50px, 30% 40%, 25px 50px", "");
     is(cs.getPropertyValue(prop), "20px 35%, 55% 50px, 30% 25%, 10px 20px",
        "property " + prop + ": interpolation of lists of lengths and percents");
-    if (doesPropHaveDistanceComputation) {
-      check_distance(prop, "10px 40%, 50% 50px, 30% 20%, 5px 10px",
-                           "20px 35%, 55% 50px, 30% 25%, 10px 20px",
-                           "50px 20%, 70% 50px, 30% 40%, 25px 50px");
-    }
+    check_distance(prop, "10px 40%, 50% 50px, 30% 20%, 5px 10px",
+                         "20px 35%, 55% 50px, 30% 25%, 10px 20px",
+                         "50px 20%, 70% 50px, 30% 40%, 25px 50px");
     div.style.setProperty(prop, "20% 40%, 8px 12px", "");
     is(cs.getPropertyValue(prop), "20% 40%, 8px 12px",
        "property " + prop + ": computed value before transition");
     div.style.setProperty(prop, "12px 20px, 40% 16%", "");
     is(cs.getPropertyValue(prop), "calc(3px + 15%) calc(5px + 30%), calc(6px + 10%) calc(9px + 4%)",
        "property " + prop + ": interpolation that computes to calc()");
-    if (doesPropHaveDistanceComputation) {
-      check_distance(prop, "20% 40%, 8px 12px",
-                           "calc(3px + 15%) calc(5px + 30%), calc(6px + 10%) calc(9px + 4%)",
-                           "12px 20px, 40% 16%");
-    }
+    check_distance(prop, "20% 40%, 8px 12px",
+                         "calc(3px + 15%) calc(5px + 30%), calc(6px + 10%) calc(9px + 4%)",
+                         "12px 20px, 40% 16%");
     div.style.setProperty(prop, "calc(20% + 40px) calc(40px + 40%), 8px 12%, calc(20px + 12%) calc(24px + 8%)", "");
     is(cs.getPropertyValue(prop), "calc(40px + 20%) calc(40px + 40%), 8px 12%, calc(20px + 12%) calc(24px + 8%)",
        "property " + prop + ": computed value before transition");
     div.style.setProperty(prop, "12px 20%, calc(20%) calc(16px + 60%), calc(8px + 20%) calc(40px + 16%)", "");
     is(cs.getPropertyValue(prop), "calc(33px + 15%) calc(30px + 35%), calc(6px + 5%) calc(4px + 24%), calc(17px + 14%) calc(28px + 10%)",
        "property " + prop + ": interpolation that computes to calc()");
-    if (doesPropHaveDistanceComputation) {
-      check_distance(prop, "calc(20% + 40px) calc(40px + 40%), 8px 12%, calc(20px + 12%) calc(24px + 8%)",
-                           "calc(33px + 15%) calc(30px + 35%), calc(6px + 5%) calc(4px + 24%), calc(17px + 14%) calc(28px + 10%)",
-                           "12px 20%, calc(20%) calc(16px + 60%), calc(8px + 20%) calc(40px + 16%)");
-    }
+    check_distance(prop, "calc(20% + 40px) calc(40px + 40%), 8px 12%, calc(20px + 12%) calc(24px + 8%)",
+                         "calc(33px + 15%) calc(30px + 35%), calc(6px + 5%) calc(4px + 24%), calc(17px + 14%) calc(28px + 10%)",
+                         "12px 20%, calc(20%) calc(16px + 60%), calc(8px + 20%) calc(40px + 16%)");
   }
 }
 
 function test_transform_transition(prop) {
   is(prop, "transform", "Unexpected transform property!  Test needs to be fixed");
   var matrix_re = /^matrix\(([^,]*), ([^,]*), ([^,]*), ([^,]*), ([^,]*), ([^,]*)\)$/;
   for (var i in transformTests) {
     var test = transformTests[i];