Merge inbound to mozilla-central. a=merge
authorNarcis Beleuzu <nbeleuzu@mozilla.com>
Sat, 12 Jan 2019 11:40:44 +0200
changeset 510726 a44934afe25e7ac1fcccc5ca63b90406a29fbee2
parent 510707 cb35977ae7a4a5a1d2fe6a543e15d49cd2fd47c8 (current diff)
parent 510725 bcb74daf647371e48fb2d3a88992f2dd17cbf4f1 (diff)
child 510729 10907464fcc25c1e2fd9b0aed806bfdea2e90ee8
child 510740 5d5711d0125dd2ba35777d6c86b1caff54771466
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone66.0a1
first release with
nightly linux32
a44934afe25e / 66.0a1 / 20190112094119 / files
nightly linux64
a44934afe25e / 66.0a1 / 20190112094119 / files
nightly mac
a44934afe25e / 66.0a1 / 20190112094119 / files
nightly win32
a44934afe25e / 66.0a1 / 20190112094119 / files
nightly win64
a44934afe25e / 66.0a1 / 20190112094119 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
gfx/layers/wr/WebRenderCommandBuilder.cpp
layout/painting/nsDisplayList.cpp
third_party/rust/block-buffer-0.3.3/src/paddings.rs
third_party/rust/byte-tools-0.2.0/src/read_single.rs
third_party/rust/byte-tools-0.2.0/src/read_slice.rs
third_party/rust/byte-tools-0.2.0/src/write_single.rs
third_party/rust/byte-tools-0.2.0/src/write_slice.rs
third_party/rust/lalrpop-snap/.cargo-checksum.json
third_party/rust/lalrpop-snap/Cargo.toml
third_party/rust/lalrpop-snap/src/build/mod.rs
third_party/rust/lalrpop-snap/src/grammar/repr.rs
third_party/rust/lalrpop-snap/src/lexer/intern_token/mod.rs
third_party/rust/lalrpop-snap/src/lr1/codegen/base.rs
third_party/rust/lalrpop-snap/src/lr1/codegen/parse_table.rs
third_party/rust/lalrpop-snap/src/lr1/codegen/test_all.rs
third_party/rust/lalrpop-snap/src/lr1/lane_table/construct/merge.rs
third_party/rust/lalrpop-snap/src/lr1/lane_table/construct/mod.rs
third_party/rust/lalrpop-snap/src/lr1/lane_table/construct/state_set.rs
third_party/rust/lalrpop-snap/src/normalize/tyinfer/mod.rs
third_party/rust/lalrpop-snap/src/normalize/tyinfer/test.rs
third_party/rust/lalrpop-snap/src/rust/mod.rs
third_party/rust/sha2-0.7.1/tests/data/sha224/test1.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha224/test2.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha224/test2.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha224/test3.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha224/test3.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha256/one_million_a.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha256/test1.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha256/test2.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha256/test2.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha256/test3.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha256/test3.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha384/test1.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha384/test2.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha384/test2.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha384/test3.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha384/test3.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512/one_million_a.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512/test1.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512/test2.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512/test2.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512/test3.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512/test3.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_224/test1.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_224/test2.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_224/test2.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_224/test3.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_224/test3.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_256/test1.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_256/test2.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_256/test2.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_256/test3.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_256/test3.output.bin
third_party/rust/strsim-0.6.0/.cargo-checksum.json
third_party/rust/strsim-0.6.0/CHANGELOG.md
third_party/rust/strsim-0.6.0/Cargo.toml
third_party/rust/strsim-0.6.0/LICENSE
third_party/rust/strsim-0.6.0/README.md
third_party/rust/strsim-0.6.0/dev
third_party/rust/strsim-0.6.0/src/lib.rs
third_party/rust/strsim-0.6.0/tests/lib.rs
--- a/browser/config/mozconfigs/win32/mingwclang
+++ b/browser/config/mozconfigs/win32/mingwclang
@@ -47,17 +47,17 @@ HOST_CC="$TOOLTOOL_DIR/clang/bin/clang"
 HOST_CXX="$TOOLTOOL_DIR/clang/bin/clang++"
 CC="$TOOLTOOL_DIR/clang/bin/i686-w64-mingw32-clang"
 CXX="$TOOLTOOL_DIR/clang/bin/i686-w64-mingw32-clang++"
 CXXFLAGS="-fms-extensions"
 AR=llvm-ar
 RANLIB=llvm-ranlib
 
 # For Stylo
-BINDGEN_CFLAGS="-I$TOOLTOOL_DIR/clang/i686-w64-mingw32/include/c++/v1 -I$TOOLTOOL_DIR/clang/lib/clang/8.0.0/include -I$TOOLTOOL_DIR/clang/i686-w64-mingw32/include"
+BINDGEN_CFLAGS="-I$TOOLTOOL_DIR/clang/i686-w64-mingw32/include/c++/v1 -I$TOOLTOOL_DIR/clang/i686-w64-mingw32/include"
 
 # Bug 1471698 - Work around binutils corrupting mingw clang binaries.
 LDFLAGS="-Wl,-S"
 STRIP=/bin/true
 OBJCOPY=/bin/true
 
 # We want to make sure we use binutils and other binaries in the tooltool
 # package.
--- a/browser/config/mozconfigs/win64/mingwclang
+++ b/browser/config/mozconfigs/win64/mingwclang
@@ -47,17 +47,17 @@ HOST_CC="$TOOLTOOL_DIR/clang/bin/clang"
 HOST_CXX="$TOOLTOOL_DIR/clang/bin/clang++"
 CC="$TOOLTOOL_DIR/clang/bin/x86_64-w64-mingw32-clang"
 CXX="$TOOLTOOL_DIR/clang/bin/x86_64-w64-mingw32-clang++"
 CXXFLAGS="-fms-extensions"
 AR=llvm-ar
 RANLIB=llvm-ranlib
 
 # For Stylo
-BINDGEN_CFLAGS="-I$TOOLTOOL_DIR/clang/x86_64-w64-mingw32/include/c++/v1 -I$TOOLTOOL_DIR/clang/lib/clang/8.0.0/include -I$TOOLTOOL_DIR/clang/x86_64-w64-mingw32/include"
+BINDGEN_CFLAGS="-I$TOOLTOOL_DIR/clang/x86_64-w64-mingw32/include/c++/v1 -I$TOOLTOOL_DIR/clang/x86_64-w64-mingw32/include"
 
 # Bug 1471698 - Work around binutils corrupting mingw clang binaries.
 LDFLAGS="-Wl,-S"
 STRIP=/bin/true
 OBJCOPY=/bin/true
 
 # We want to make sure we use binutils and other binaries in the tooltool
 # package.
--- a/devtools/client/inspector/rules/components/Declaration.js
+++ b/devtools/client/inspector/rules/components/Declaration.js
@@ -12,19 +12,112 @@ const Types = require("../types");
 
 class Declaration extends PureComponent {
   static get propTypes() {
     return {
       declaration: PropTypes.shape(Types.declaration).isRequired,
     };
   }
 
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      // Whether or not the computed property list is expanded.
+      isComputedListExpanded: false,
+    };
+
+    this.onComputedExpanderClick = this.onComputedExpanderClick.bind(this);
+  }
+
+  onComputedExpanderClick(event) {
+    event.stopPropagation();
+
+    this.setState(prevState => {
+      return { isComputedListExpanded: !prevState.isComputedListExpanded };
+    });
+  }
+
+  renderComputedPropertyList() {
+    const { computedProperties } = this.props.declaration;
+
+    if (!computedProperties.length) {
+      return null;
+    }
+
+    return (
+      dom.ul(
+        {
+          className: "ruleview-computedlist",
+          style: {
+            display: this.state.isComputedListExpanded ? "block" : "",
+          },
+        },
+        computedProperties.map(({ name, value, isOverridden }) => {
+          return (
+            dom.li(
+              {
+                key: `${name}${value}`,
+                className: "ruleview-computed" +
+                           (isOverridden ? " ruleview-overridden" : ""),
+              },
+              dom.span({ className: "ruleview-namecontainer" },
+                dom.span({ className: "ruleview-propertyname theme-fg-color5" }, name),
+                ": "
+              ),
+              dom.span({ className: "ruleview-propertyvaluecontainer" },
+                dom.span({ className: "ruleview-propertyvalue theme-fg-color1" }, value),
+                ";"
+              )
+            )
+          );
+        })
+      )
+    );
+  }
+
+  renderShorthandOverriddenList() {
+    const { declaration } = this.props;
+
+    if (this.state.isComputedListExpanded || declaration.isOverridden) {
+      return null;
+    }
+
+    return (
+      dom.ul({ className: "ruleview-overridden-items" },
+        declaration.computedProperties.map(({ name, value, isOverridden }) => {
+          if (!isOverridden) {
+            return null;
+          }
+
+          return (
+            dom.li(
+              {
+                key: `${name}${value}`,
+                className: "ruleview-overridden-item ruleview-overridden",
+              },
+              dom.span({ className: "ruleview-namecontainer" },
+                dom.span({ className: "ruleview-propertyname theme-fg-color5" }, name),
+                ": "
+              ),
+              dom.span({ className: "ruleview-propertyvaluecontainer" },
+                dom.span({ className: "ruleview-propertyvalue theme-fg-color1" }, value),
+                ";"
+              )
+            )
+          );
+        })
+      )
+    );
+  }
+
   render() {
     const { declaration } = this.props;
     const {
+      computedProperties,
       isEnabled,
       isKnownProperty,
       isOverridden,
       name,
       value,
     } = declaration;
 
     return (
@@ -39,19 +132,27 @@ class Declaration extends PureComponent 
             className: "ruleview-enableproperty theme-checkbox" +
                         (isEnabled ? " checked" : ""),
             tabIndex: -1,
           }),
           dom.span({ className: "ruleview-namecontainer" },
             dom.span({ className: "ruleview-propertyname theme-fg-color5" }, name),
             ": "
           ),
+          dom.span({
+            className: "ruleview-expander theme-twisty" +
+                       (this.state.isComputedListExpanded ? " open" : ""),
+            onClick: this.onComputedExpanderClick,
+            style: { display: computedProperties.length ? "inline-block" : "none" },
+          }),
           dom.span({ className: "ruleview-propertyvaluecontainer" },
             dom.span({ className: "ruleview-propertyvalue theme-fg-color1" }, value),
             ";"
           )
-        )
+        ),
+        this.renderComputedPropertyList(),
+        this.renderShorthandOverriddenList()
       )
     );
   }
 }
 
 module.exports = Declaration;
--- a/devtools/client/inspector/rules/components/Rule.js
+++ b/devtools/client/inspector/rules/components/Rule.js
@@ -22,25 +22,29 @@ class Rule extends PureComponent {
   }
 
   render() {
     const { rule } = this.props;
     const {
       declarations,
       selector,
       sourceLink,
+      type,
     } = rule;
 
     return (
       dom.div(
         { className: "ruleview-rule devtools-monospace" },
         SourceLink({ sourceLink }),
         dom.div({ className: "ruleview-code" },
           dom.div({},
-            Selector({ selector }),
+            Selector({
+              selector,
+              type,
+            }),
             dom.span({ className: "ruleview-ruleopen" }, " {")
           ),
           Declarations({ declarations }),
           dom.div({ className: "ruleview-ruleclose" }, "}")
         )
       )
     );
   }
--- a/devtools/client/inspector/rules/components/Selector.js
+++ b/devtools/client/inspector/rules/components/Selector.js
@@ -3,33 +3,96 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { PureComponent } = require("devtools/client/shared/vendor/react");
 const dom = require("devtools/client/shared/vendor/react-dom-factories");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 
+const {
+  parsePseudoClassesAndAttributes,
+  SELECTOR_ATTRIBUTE,
+  SELECTOR_ELEMENT,
+  SELECTOR_PSEUDO_CLASS,
+} = require("devtools/shared/css/parsing-utils");
+const {
+  ELEMENT_STYLE,
+  PSEUDO_CLASSES,
+} = require("devtools/client/inspector/rules/constants");
+
 const Types = require("../types");
 
 class Selector extends PureComponent {
   static get propTypes() {
     return {
       selector: PropTypes.shape(Types.selector).isRequired,
+      type: PropTypes.number.isRequired,
     };
   }
 
+  renderSelector() {
+    // Show the text directly for custom selector text (such as the inline "element"
+    // style and Keyframes rules).
+    if (this.props.type === ELEMENT_STYLE || this.props.type === CSSRule.KEYFRAME_RULE) {
+      return this.props.selector.selectorText;
+    }
+
+    const { matchedSelectors, selectors } = this.props.selector;
+    const output = [];
+
+    // Go through the CSS rule's selectors and highlight the selectors that actually
+    // matches.
+    for (let i = 0; i < selectors.length; i++) {
+      const selector = selectors[i];
+
+      // Parse the selector for pseudo classes and attributes, and apply different
+      // CSS classes for the parsed values.
+      // NOTE: parsePseudoClassesAndAttributes is a good candidate for memoization.
+      const parsedSelector = parsePseudoClassesAndAttributes(selector);
+      for (const parsedText of parsedSelector) {
+        let selectorSpanClass = matchedSelectors.indexOf(selector) > -1 ?
+          "ruleview-selector-matched" : "ruleview-selector-unmatched";
+
+        switch (parsedText.type) {
+          case SELECTOR_ATTRIBUTE:
+            selectorSpanClass += " ruleview-selector-attribute";
+            break;
+          case SELECTOR_ELEMENT:
+            selectorSpanClass += " ruleview-selector";
+            break;
+          case SELECTOR_PSEUDO_CLASS:
+            selectorSpanClass += PSEUDO_CLASSES.some(p => parsedText.value === p) ?
+              " ruleview-selector-pseudo-class-lock" :
+              " ruleview-selector-pseudo-class";
+            break;
+        }
+
+        output.push(
+          dom.span({ className: selectorSpanClass }, parsedText.value)
+        );
+      }
+
+      // Append a comma separator unless this is the last selector.
+      if (i < selectors.length - 1) {
+        output.push(
+          dom.span({ className: "ruleview-selector-separator" }, ", ")
+        );
+      }
+    }
+
+    return output;
+  }
+
   render() {
-    const { selectorText } = this.props.selector;
-
     return (
       dom.span(
         {
           className: "ruleview-selectorcontainer",
-          tabIndex: -1,
+          tabIndex: 0,
         },
-        selectorText
+        this.renderSelector()
       )
     );
   }
 }
 
 module.exports = Selector;
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/rules/constants.js
@@ -0,0 +1,13 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+// The PageStyle actor flattens the DOM CSS objects a little bit, merging
+// Rules and their Styles into one actor. For elements (which have a style
+// but no associated rule) we fake a rule with the following style id.
+exports.ELEMENT_STYLE = 100;
+
+// Pseudo classes in the pseudo class panel.
+exports.PSEUDO_CLASSES = [":active", ":focus", ":focus-within", ":hover"];
--- a/devtools/client/inspector/rules/models/rule.js
+++ b/devtools/client/inspector/rules/models/rule.js
@@ -76,17 +76,17 @@ Rule.prototype = {
       inheritedSource: this.inheritedSource,
     };
   },
 
   get selector() {
     return {
       matchedSelectors: this.matchedSelectors,
       selectors: this.domRule.selectors,
-      selectorText: this.selectorText,
+      selectorText: this.keyframes ? this.domRule.keyText : this.selectorText,
     };
   },
 
   get sourceLink() {
     return {
       column: this.ruleColumn,
       line: this.ruleLine,
       mediaText: this.mediaText,
--- a/devtools/client/inspector/rules/models/text-property.js
+++ b/devtools/client/inspector/rules/models/text-property.js
@@ -44,23 +44,26 @@ function TextProperty(rule, name, value,
   this.cssProperties = this.rule.elementStyle.ruleView.cssProperties;
   this.panelDoc = this.rule.elementStyle.ruleView.inspector.panelDoc;
 
   this.updateComputed();
 }
 
 TextProperty.prototype = {
   get computedProperties() {
-    return this.computed.map(computed => {
-      return {
-        name: computed.name,
-        priority: computed.priority,
-        value: computed.value,
-      };
-    });
+    return this.computed
+      .filter(computed => computed.name !== this.name)
+      .map(computed => {
+        return {
+          isOverridden: computed.overridden,
+          name: computed.name,
+          priority: computed.priority,
+          value: computed.value,
+        };
+      });
   },
 
   /**
    * See whether this property's name is known.
    *
    * @return {Boolean} true if the property name is known, false otherwise.
    */
   get isKnownProperty() {
--- a/devtools/client/inspector/rules/moz.build
+++ b/devtools/client/inspector/rules/moz.build
@@ -9,16 +9,17 @@ DIRS += [
     'components',
     'models',
     'reducers',
     'utils',
     'views',
 ]
 
 DevToolsModules(
+    'constants.js',
     'new-rules.js',
     'rules.js',
     'types.js',
 )
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
 with Files('**'):
--- a/devtools/client/inspector/rules/types.js
+++ b/devtools/client/inspector/rules/types.js
@@ -7,16 +7,18 @@
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 
 /**
  * A CSS declaration.
  */
 const declaration = exports.declaration = {
   // Array of the computed properties for a CSS declaration.
   computedProperties: PropTypes.arrayOf(PropTypes.shape({
+    // Whether or not the computed property is overridden.
+    isOverridden: PropTypes.bool,
     // The computed property name.
     name: PropTypes.string,
     // The computed priority (either "important" or an empty string).
     priority: PropTypes.string,
     // The computed property value.
     value: PropTypes.string,
   })),
 
--- a/gfx/layers/wr/AsyncImagePipelineManager.cpp
+++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp
@@ -395,17 +395,18 @@ void AsyncImagePipelineManager::ApplyAsy
   aPipeline->mIsChanged = false;
 
   wr::LayoutSize contentSize{aPipeline->mScBounds.Width(),
                              aPipeline->mScBounds.Height()};
   wr::DisplayListBuilder builder(aPipelineId, contentSize);
 
   float opacity = 1.0f;
   Maybe<wr::WrSpatialId> referenceFrameId = builder.PushStackingContext(
-      wr::ToRoundedLayoutRect(aPipeline->mScBounds), nullptr, nullptr, &opacity,
+      wr::ToRoundedLayoutRect(aPipeline->mScBounds),
+      wr::WrStackingContextClip::None(), nullptr, &opacity,
       aPipeline->mScTransform.IsIdentity() ? nullptr : &aPipeline->mScTransform,
       wr::TransformStyle::Flat, nullptr, aPipeline->mMixBlendMode,
       nsTArray<wr::FilterOp>(), true,
       // This is fine to do unconditionally because we only push images here.
       wr::RasterSpace::Screen());
 
   Maybe<wr::SpaceAndClipChainHelper> spaceAndClipChainHelper;
   if (referenceFrameId) {
--- a/gfx/layers/wr/StackingContextHelper.cpp
+++ b/gfx/layers/wr/StackingContextHelper.cpp
@@ -26,17 +26,17 @@ StackingContextHelper::StackingContextHe
     nsIFrame* aContainerFrame, nsDisplayItem* aContainerItem,
     wr::DisplayListBuilder& aBuilder, const nsTArray<wr::FilterOp>& aFilters,
     const LayoutDeviceRect& aBounds, const gfx::Matrix4x4* aBoundTransform,
     const wr::WrAnimationProperty* aAnimation, const float* aOpacityPtr,
     const gfx::Matrix4x4* aTransformPtr, const gfx::Matrix4x4* aPerspectivePtr,
     const gfx::CompositionOp& aMixBlendMode, bool aBackfaceVisible,
     bool aIsPreserve3D,
     const Maybe<nsDisplayTransform*>& aDeferredTransformItem,
-    const wr::WrClipId* aClipNodeId, bool aAnimated)
+    const wr::WrStackingContextClip& aClip, bool aAnimated)
     : mBuilder(&aBuilder),
       mScale(1.0f, 1.0f),
       mDeferredTransformItem(aDeferredTransformItem),
       mIsPreserve3D(aIsPreserve3D),
       mRasterizeLocally(aAnimated || aParentSC.mRasterizeLocally) {
   // Compute scale for fallback rendering. We don't try to guess a scale for 3d
   // transformed items
   gfx::Matrix transform2d;
@@ -63,18 +63,17 @@ StackingContextHelper::StackingContextHe
   }
 
   auto rasterSpace =
       mRasterizeLocally
           ? wr::RasterSpace::Local(std::max(mScale.width, mScale.height))
           : wr::RasterSpace::Screen();
 
   mReferenceFrameId = mBuilder->PushStackingContext(
-      wr::ToLayoutRect(aBounds), aClipNodeId, aAnimation, aOpacityPtr,
-      aTransformPtr,
+      wr::ToLayoutRect(aBounds), aClip, aAnimation, aOpacityPtr, aTransformPtr,
       aIsPreserve3D ? wr::TransformStyle::Preserve3D : wr::TransformStyle::Flat,
       aPerspectivePtr, wr::ToMixBlendMode(aMixBlendMode), aFilters,
       aBackfaceVisible, rasterSpace);
 
   if (mReferenceFrameId) {
     mSpaceAndClipChainHelper.emplace(aBuilder, mReferenceFrameId.ref());
   }
 
--- a/gfx/layers/wr/StackingContextHelper.h
+++ b/gfx/layers/wr/StackingContextHelper.h
@@ -36,17 +36,18 @@ class MOZ_RAII StackingContextHelper {
       const gfx::Matrix4x4* aBoundTransform = nullptr,
       const wr::WrAnimationProperty* aAnimation = nullptr,
       const float* aOpacityPtr = nullptr,
       const gfx::Matrix4x4* aTransformPtr = nullptr,
       const gfx::Matrix4x4* aPerspectivePtr = nullptr,
       const gfx::CompositionOp& aMixBlendMode = gfx::CompositionOp::OP_OVER,
       bool aBackfaceVisible = true, bool aIsPreserve3D = false,
       const Maybe<nsDisplayTransform*>& aDeferredTransformItem = Nothing(),
-      const wr::WrClipId* aClipNodeId = nullptr, bool aAnimated = false);
+      const wr::WrStackingContextClip& = wr::WrStackingContextClip::None(),
+      bool aAnimated = false);
   // This version of the constructor should only be used at the root level
   // of the tree, so that we have a StackingContextHelper to pass down into
   // the RenderLayer traversal, but don't actually want it to push a stacking
   // context on the display list builder.
   StackingContextHelper();
 
   // Pops the stacking context, if one was pushed during the constructor.
   ~StackingContextHelper();
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -15,17 +15,18 @@
 #include "mozilla/widget/CompositorWidget.h"
 #include "mozilla/layers/SynchronousTask.h"
 #include "TextDrawTarget.h"
 
 #define WRDL_LOG(...)
 
 //#define WRDL_LOG(...) printf_stderr("WRDL(%p): " __VA_ARGS__)
 
-//#define WRDL_LOG(...) if (XRE_IsContentProcess()) printf_stderr("WRDL(%p): " __VA_ARGS__)
+//#define WRDL_LOG(...) if (XRE_IsContentProcess()) printf_stderr("WRDL(%p): "
+//__VA_ARGS__)
 
 namespace mozilla {
 namespace wr {
 
 using layers::Stringify;
 
 MOZ_DEFINE_MALLOC_SIZE_OF(WebRenderMallocSizeOf)
 MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(WebRenderMallocEnclosingSizeOf)
@@ -667,17 +668,17 @@ usize DisplayListBuilder::Dump(usize aIn
 
 void DisplayListBuilder::Finalize(wr::LayoutSize& aOutContentSize,
                                   BuiltDisplayList& aOutDisplayList) {
   wr_api_finalize_builder(mWrState, &aOutContentSize, &aOutDisplayList.dl_desc,
                           &aOutDisplayList.dl.inner);
 }
 
 Maybe<wr::WrSpatialId> DisplayListBuilder::PushStackingContext(
-    const wr::LayoutRect& aBounds, const wr::WrClipId* aClipNodeId,
+    const wr::LayoutRect& aBounds, const wr::WrStackingContextClip& aClip,
     const WrAnimationProperty* aAnimation, const float* aOpacity,
     const gfx::Matrix4x4* aTransform, wr::TransformStyle aTransformStyle,
     const gfx::Matrix4x4* aPerspective, const wr::MixBlendMode& aMixBlendMode,
     const nsTArray<wr::FilterOp>& aFilters, bool aIsBackfaceVisible,
     const wr::RasterSpace& aRasterSpace) {
   MOZ_ASSERT(mClipChainLeaf.isNothing(),
              "Non-empty leaf from clip chain given, but not used with SC!");
 
@@ -693,18 +694,18 @@ Maybe<wr::WrSpatialId> DisplayListBuilde
 
   const wr::LayoutTransform* maybePerspective =
       aPerspective ? &perspective : nullptr;
   WRDL_LOG("PushStackingContext b=%s t=%s\n", mWrState,
            Stringify(aBounds).c_str(),
            aTransform ? Stringify(*aTransform).c_str() : "none");
 
   auto spatialId = wr_dp_push_stacking_context(
-      mWrState, aBounds, mCurrentSpaceAndClipChain.space, aClipNodeId,
-      aAnimation, aOpacity, maybeTransform, aTransformStyle, maybePerspective,
+      mWrState, aBounds, mCurrentSpaceAndClipChain.space, &aClip, aAnimation,
+      aOpacity, maybeTransform, aTransformStyle, maybePerspective,
       aMixBlendMode, aFilters.Elements(), aFilters.Length(), aIsBackfaceVisible,
       aRasterSpace);
 
   return spatialId.id != 0 ? Some(spatialId) : Nothing();
 }
 
 void DisplayListBuilder::PopStackingContext(bool aIsReferenceFrame) {
   WRDL_LOG("PopStackingContext\n", mWrState);
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -324,19 +324,18 @@ class DisplayListBuilder {
   void ClearSave();
   usize Dump(usize aIndent, const Maybe<usize>& aStart,
              const Maybe<usize>& aEnd);
 
   void Finalize(wr::LayoutSize& aOutContentSize,
                 wr::BuiltDisplayList& aOutDisplayList);
 
   Maybe<wr::WrSpatialId> PushStackingContext(
-      const wr::LayoutRect&
-          aBounds,  // TODO: We should work with strongly typed rects
-      const wr::WrClipId* aClipNodeId,
+      // TODO: We should work with strongly typed rects
+      const wr::LayoutRect& aBounds, const wr::WrStackingContextClip& aClip,
       const wr::WrAnimationProperty* aAnimation, const float* aOpacity,
       const gfx::Matrix4x4* aTransform, wr::TransformStyle aTransformStyle,
       const gfx::Matrix4x4* aPerspective, const wr::MixBlendMode& aMixBlendMode,
       const nsTArray<wr::FilterOp>& aFilters, bool aIsBackfaceVisible,
       const wr::RasterSpace& aRasterSpace);
   void PopStackingContext(bool aIsReferenceFrame);
 
   wr::WrClipChainId DefineClipChain(const Maybe<wr::WrClipChainId>& aParent,
@@ -481,16 +480,20 @@ class DisplayListBuilder {
   void PushBoxShadow(const wr::LayoutRect& aRect, const wr::LayoutRect& aClip,
                      bool aIsBackfaceVisible, const wr::LayoutRect& aBoxBounds,
                      const wr::LayoutVector2D& aOffset,
                      const wr::ColorF& aColor, const float& aBlurRadius,
                      const float& aSpreadRadius,
                      const wr::BorderRadius& aBorderRadius,
                      const wr::BoxShadowClipMode& aClipMode);
 
+  uint64_t CurrentClipChainId() const {
+    return mCurrentSpaceAndClipChain.clip_chain;
+  }
+
   // Checks to see if the innermost enclosing fixed pos item has the same
   // ASR. If so, it returns the scroll target for that fixed-pos item.
   // Otherwise, it returns Nothing().
   Maybe<layers::ScrollableLayerGuid::ViewID> GetContainingFixedPosScrollTarget(
       const ActiveScrolledRoot* aAsr);
 
   // Set the hit-test info to be used for all display items until the next call
   // to SetHitTestInfo or ClearHitTestInfo.
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -135,36 +135,57 @@ impl WrSpaceAndClip {
     fn to_webrender(&self, pipeline_id: WrPipelineId) -> SpaceAndClipInfo {
         SpaceAndClipInfo {
             spatial_id: self.space.to_webrender(pipeline_id),
             clip_id: self.clip.to_webrender(pipeline_id),
         }
     }
 }
 
+#[inline]
+fn clip_chain_id_to_webrender(id: u64, pipeline_id: WrPipelineId) -> ClipId {
+    if id == ROOT_CLIP_CHAIN {
+        ClipId::root(pipeline_id)
+    } else {
+        ClipId::ClipChain(ClipChainId(id, pipeline_id))
+    }
+}
+
 #[repr(C)]
 pub struct WrSpaceAndClipChain {
     space: WrSpatialId,
     clip_chain: u64,
 }
 
 impl WrSpaceAndClipChain {
     fn to_webrender(&self, pipeline_id: WrPipelineId) -> SpaceAndClipInfo {
         //Warning: special case here to support dummy clip chain
         SpaceAndClipInfo {
             spatial_id: self.space.to_webrender(pipeline_id),
-            clip_id: if self.clip_chain == ROOT_CLIP_CHAIN {
-                ClipId::root(pipeline_id)
-            } else {
-                ClipId::ClipChain(ClipChainId(self.clip_chain, pipeline_id))
-            },
+            clip_id: clip_chain_id_to_webrender(self.clip_chain, pipeline_id),
         }
     }
 }
 
+#[repr(C)]
+pub enum WrStackingContextClip {
+    None,
+    ClipId(WrClipId),
+    ClipChain(u64),
+}
+
+impl WrStackingContextClip {
+    fn to_webrender(&self, pipeline_id: WrPipelineId) -> Option<ClipId> {
+        match *self {
+            WrStackingContextClip::None => None,
+            WrStackingContextClip::ClipChain(id) => Some(clip_chain_id_to_webrender(id, pipeline_id)),
+            WrStackingContextClip::ClipId(id) => Some(id.to_webrender(pipeline_id)),
+        }
+    }
+}
 
 fn make_slice<'a, T>(ptr: *const T, len: usize) -> &'a [T] {
     if ptr.is_null() {
         &[]
     } else {
         unsafe { slice::from_raw_parts(ptr, len) }
     }
 }
@@ -1869,40 +1890,39 @@ pub extern "C" fn wr_dp_restore(state: &
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_clear_save(state: &mut WrState) {
     state.frame_builder.dl_builder.clear_save();
 }
 
 #[no_mangle]
-pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
-                                              mut bounds: LayoutRect,
-                                              spatial_id: WrSpatialId,
-                                              clip_node_id: *const WrClipId,
-                                              animation: *const WrAnimationProperty,
-                                              opacity: *const f32,
-                                              transform: *const LayoutTransform,
-                                              transform_style: TransformStyle,
-                                              perspective: *const LayoutTransform,
-                                              mix_blend_mode: MixBlendMode,
-                                              filters: *const FilterOp,
-                                              filter_count: usize,
-                                              is_backface_visible: bool,
-                                              glyph_raster_space: RasterSpace,
-                                              ) -> WrSpatialId {
+pub extern "C" fn wr_dp_push_stacking_context(
+    state: &mut WrState,
+    mut bounds: LayoutRect,
+    spatial_id: WrSpatialId,
+    clip: &WrStackingContextClip,
+    animation: *const WrAnimationProperty,
+    opacity: *const f32,
+    transform: *const LayoutTransform,
+    transform_style: TransformStyle,
+    perspective: *const LayoutTransform,
+    mix_blend_mode: MixBlendMode,
+    filters: *const FilterOp,
+    filter_count: usize,
+    is_backface_visible: bool,
+    glyph_raster_space: RasterSpace,
+) -> WrSpatialId {
     debug_assert!(unsafe { !is_in_render_thread() });
 
     let c_filters = make_slice(filters, filter_count);
     let mut filters : Vec<FilterOp> = c_filters.iter().map(|c_filter| {
                                                            *c_filter
     }).collect();
 
-    let clip_node_id_ref = unsafe { clip_node_id.as_ref() };
-
     let transform_ref = unsafe { transform.as_ref() };
     let mut transform_binding = match transform_ref {
         Some(transform) => Some(PropertyBinding::Value(transform.clone())),
         None => None,
     };
 
     let opacity_ref = unsafe { opacity.as_ref() };
     let mut has_opacity_animation = false;
@@ -1937,17 +1957,17 @@ pub extern "C" fn wr_dp_push_stacking_co
 
     let perspective_ref = unsafe { perspective.as_ref() };
     let perspective = match perspective_ref {
         Some(perspective) => Some(perspective.clone()),
         None => None,
     };
 
     let mut wr_spatial_id = spatial_id.to_webrender(state.pipeline_id);
-    let wr_clip_id = clip_node_id_ref.map(|id| id.to_webrender(state.pipeline_id));
+    let wr_clip_id = clip.to_webrender(state.pipeline_id);
 
     let is_reference_frame = transform_binding.is_some() || perspective.is_some();
     // Note: 0 has special meaning in WR land, standing for ROOT_REFERENCE_FRAME.
     // However, it is never returned by `push_reference_frame`, and we need to return
     // an option here across FFI, so we take that 0 value for the None semantics.
     // This is resolved into proper `Maybe<WrSpatialId>` inside `WebRenderAPI::PushStackingContext`.
     let mut result = WrSpatialId { id: 0 };
     if is_reference_frame {
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -834,16 +834,91 @@ struct Shadow {
 
   bool operator==(const Shadow& aOther) const {
     return offset == aOther.offset &&
            color == aOther.color &&
            blur_radius == aOther.blur_radius;
   }
 };
 
+struct WrStackingContextClip {
+  enum class Tag {
+    None,
+    ClipId,
+    ClipChain,
+
+    Sentinel /* this must be last for serialization purposes. */
+  };
+
+  struct ClipId_Body {
+    WrClipId _0;
+
+    bool operator==(const ClipId_Body& aOther) const {
+      return _0 == aOther._0;
+    }
+  };
+
+  struct ClipChain_Body {
+    uint64_t _0;
+
+    bool operator==(const ClipChain_Body& aOther) const {
+      return _0 == aOther._0;
+    }
+  };
+
+  Tag tag;
+  union {
+    ClipId_Body clip_id;
+    ClipChain_Body clip_chain;
+  };
+
+  static WrStackingContextClip None() {
+    WrStackingContextClip result;
+    result.tag = Tag::None;
+    return result;
+  }
+
+  static WrStackingContextClip ClipId(const WrClipId &a0) {
+    WrStackingContextClip result;
+    result.clip_id._0 = a0;
+    result.tag = Tag::ClipId;
+    return result;
+  }
+
+  static WrStackingContextClip ClipChain(const uint64_t &a0) {
+    WrStackingContextClip result;
+    result.clip_chain._0 = a0;
+    result.tag = Tag::ClipChain;
+    return result;
+  }
+
+  bool IsNone() const {
+    return tag == Tag::None;
+  }
+
+  bool IsClipId() const {
+    return tag == Tag::ClipId;
+  }
+
+  bool IsClipChain() const {
+    return tag == Tag::ClipChain;
+  }
+
+  bool operator==(const WrStackingContextClip& aOther) const {
+    if (tag != aOther.tag) {
+      return false;
+    }
+    switch (tag) {
+      case Tag::ClipId: return clip_id == aOther.clip_id;
+      case Tag::ClipChain: return clip_chain == aOther.clip_chain;
+      default: return true;
+    }
+  }
+};
+
 struct WrAnimationProperty {
   WrAnimationType effect_type;
   uint64_t id;
 
   bool operator==(const WrAnimationProperty& aOther) const {
     return effect_type == aOther.effect_type &&
            id == aOther.id;
   }
@@ -1932,17 +2007,17 @@ void wr_dp_push_shadow(WrState *aState,
                        const WrSpaceAndClipChain *aParent,
                        Shadow aShadow)
 WR_FUNC;
 
 WR_INLINE
 WrSpatialId wr_dp_push_stacking_context(WrState *aState,
                                         LayoutRect aBounds,
                                         WrSpatialId aSpatialId,
-                                        const WrClipId *aClipNodeId,
+                                        const WrStackingContextClip *aClip,
                                         const WrAnimationProperty *aAnimation,
                                         const float *aOpacity,
                                         const LayoutTransform *aTransform,
                                         TransformStyle aTransformStyle,
                                         const LayoutTransform *aPerspective,
                                         MixBlendMode aMixBlendMode,
                                         const FilterOp *aFilters,
                                         uintptr_t aFilterCount,
--- a/js/examples/jorendb.js
+++ b/js/examples/jorendb.js
@@ -859,33 +859,37 @@ while(args.length > 0) {
 print("jorendb: scriptPath = " + scriptPath);
 print("jorendb: scriptArgs = " + scriptArgs);
 print("jorendb: actualScriptArgs = " + actualScriptArgs);
 
 for (var task of todo) {
     task['scriptArgs'] = actualScriptArgs;
 }
 
-// If nothing to run, just drop into a repl
-if (todo.length == 0) {
-    todo.push({ 'action': 'repl' });
-}
+// Always drop into a repl at the end. Especially if the main script throws an
+// exception.
+todo.push({ 'action': 'repl' });
 
 while (rerun) {
     print("Top of run loop");
     rerun = false;
     for (var task of todo) {
         activeTask = task;
         if (task.action == 'eval') {
             debuggeeGlobal.eval(task.code);
         } else if (task.action == 'load') {
             debuggeeGlobal['scriptArgs'] = task.scriptArgs;
             debuggeeGlobal['scriptPath'] = task.script;
             print("Loading JavaScript file " + task.script);
-            debuggeeGlobal.evaluate(read(task.script), { 'fileName': task.script, 'lineNumber': 1 });
+            try {
+                debuggeeGlobal.evaluate(read(task.script), { 'fileName': task.script, 'lineNumber': 1 });
+            } catch (exc) {
+                print("Caught exception " + exc);
+                print(exc.stack);
+            }
         } else if (task.action == 'repl') {
             repl();
         }
         if (rerun)
             break;
     }
 }
 
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -368,24 +368,25 @@ bool IndirectBindingMap::lookup(jsid nam
 
 /* static */ ModuleNamespaceObject* ModuleNamespaceObject::create(
     JSContext* cx, HandleModuleObject module, HandleObject exports,
     UniquePtr<IndirectBindingMap> bindings) {
   RootedValue priv(cx, ObjectValue(*module));
   ProxyOptions options;
   options.setLazyProto(true);
   options.setSingleton(true);
+  Rooted<UniquePtr<IndirectBindingMap>> rootedBindings(cx, std::move(bindings));
   RootedObject object(
       cx, NewProxyObject(cx, &proxyHandler, priv, nullptr, options));
   if (!object) {
     return nullptr;
   }
 
   SetProxyReservedSlot(object, ExportsSlot, ObjectValue(*exports));
-  SetProxyReservedSlot(object, BindingsSlot, PrivateValue(bindings.release()));
+  SetProxyReservedSlot(object, BindingsSlot, PrivateValue(rootedBindings.release()));
 
   return &object->as<ModuleNamespaceObject>();
 }
 
 ModuleObject& ModuleNamespaceObject::module() {
   return GetProxyPrivate(this).toObject().as<ModuleObject>();
 }
 
--- a/js/src/devtools/rootAnalysis/explain.py
+++ b/js/src/devtools/rootAnalysis/explain.py
@@ -1,12 +1,14 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
+from __future__ import print_function
+
+import argparse
 import re
-import argparse
 
 from collections import defaultdict
 
 parser = argparse.ArgumentParser(description='Process some integers.')
 parser.add_argument('rootingHazards', nargs='?', default='rootingHazards.txt')
 parser.add_argument('gcFunctions', nargs='?', default='gcFunctions.txt')
 parser.add_argument('hazards', nargs='?', default='hazards.txt')
 parser.add_argument('extra', nargs='?', default='unnecessary.txt')
@@ -29,30 +31,30 @@ try:
         # List of tuples (gcFunction, index of hazard) used to maintain the
         # ordering of the hazards
         hazardOrder = []
 
         for line in rootingHazards:
             m = re.match(r'^Time: (.*)', line)
             mm = re.match(r'^Run on:', line)
             if m or mm:
-                print >>hazards, line
-                print >>extra, line
-                print >>refs, line
+                print(line, file=hazards)
+                print(line, file=extra)
+                print(line, file=refs)
                 continue
 
             m = re.match(r'^Function.*has unnecessary root', line)
             if m:
-                print >>extra, line
+                print(line, file=extra)
                 continue
 
             m = re.match(r'^Function.*takes unsafe address of unrooted', line)
             if m:
                 num_refs += 1
-                print >>refs, line
+                print(line, file=refs)
                 continue
 
             m = re.match(
                 r"^Function.*has unrooted.*of type.*live across GC call ('?)(.*?)('?) at \S+:\d+$", line)  # NOQA: E501
             if m:
                 # Function names are surrounded by single quotes. Field calls
                 # are unquoted.
                 current_gcFunction = m.group(2)
@@ -87,19 +89,19 @@ try:
                     explanation += line
             if current_func:
                 gcExplanations[current_func] = explanation
 
         for gcFunction, index in hazardOrder:
             gcHazards = hazardousGCFunctions[gcFunction]
 
             if gcFunction in gcExplanations:
-                print >>hazards, (gcHazards[index] + gcExplanations[gcFunction])
+                print(gcHazards[index] + gcExplanations[gcFunction], file=hazards)
             else:
-                print >>hazards, gcHazards[index]
+                print(gcHazards[index], file=hazards)
 
 except IOError as e:
     print('Failed: %s' % str(e))
 
 print("Wrote %s" % args.hazards)
 print("Wrote %s" % args.extra)
 print("Wrote %s" % args.refs)
 print("Found %d hazards and %d unsafe references" % (num_hazards, num_refs))
--- a/layout/generic/ScrollAnchorContainer.cpp
+++ b/layout/generic/ScrollAnchorContainer.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ScrollAnchorContainer.h"
 
+#include "mozilla/dom/Text.h"
 #include "mozilla/StaticPrefs.h"
 #include "nsGfxScrollFrame.h"
 #include "nsLayoutUtils.h"
 
 #define ANCHOR_LOG(...)
 // #define ANCHOR_LOG(...) printf_stderr("ANCHOR: " __VA_ARGS__)
 
 namespace mozilla {
@@ -82,17 +83,17 @@ static void SetAnchorFlags(const nsIFram
  *
  * [1]
  * https://drafts.csswg.org/css-scroll-anchoring-1/#scroll-anchoring-bounding-rect
  * [2] https://github.com/w3c/csswg-drafts/issues/3478
  */
 static nsRect FindScrollAnchoringBoundingRect(const nsIFrame* aScrollFrame,
                                               nsIFrame* aCandidate) {
   MOZ_ASSERT(nsLayoutUtils::IsProperAncestorFrame(aScrollFrame, aCandidate));
-  if (aCandidate->GetContent()->IsText()) {
+  if (!!Text::FromNodeOrNull(aCandidate->GetContent())) {
     nsRect bounding;
     for (nsIFrame* continuation = aCandidate->FirstContinuation(); continuation;
          continuation = continuation->GetNextContinuation()) {
       nsRect localRect =
           continuation->GetScrollableOverflowRectRelativeToSelf();
       nsRect transformed = nsLayoutUtils::TransformFrameRectToAncestor(
           continuation, localRect, aScrollFrame);
       bounding = bounding.Union(transformed);
@@ -341,17 +342,17 @@ ScrollAnchorContainer::ExamineAnchorCand
   // a different layout model than CSS, and the specification doesn't say it
   // should apply.
   //
   // [1] https://github.com/w3c/csswg-drafts/issues/3477
   bool canDescend = !scrollable && !aFrame->IsSVGOuterSVGFrame();
 
   // Check what kind of frame this is
   bool isBlockOutside = aFrame->IsBlockOutside();
-  bool isText = aFrame->GetContent()->IsText();
+  bool isText = !!Text::FromNodeOrNull(aFrame->GetContent());
   bool isAnonBox = aFrame->Style()->IsAnonBox() && !isText;
   bool isInlineOutside = aFrame->IsInlineOutside() && !isText;
   bool isContinuation = !!aFrame->GetPrevContinuation();
 
   // If the frame is anonymous or inline-outside, search its descendants for a
   // scroll anchor.
   if ((isAnonBox || isInlineOutside) && canDescend) {
     ANCHOR_LOG(
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2921,17 +2921,30 @@ void nsIFrame::BuildDisplayListForStacki
     eSeparatorTransforms,
     eOpacity,
     eFilter,
     eBlendContainer
   };
 
   nsDisplayListBuilder::AutoContainerASRTracker contASRTracker(aBuilder);
 
-  DisplayListClipState::AutoSaveRestore clipState(aBuilder);
+  DisplayListClipState::AutoSaveRestore cssClip(aBuilder);
+  {
+    // The clip property clips everything, including filters and what not.
+    if (auto contentClip = GetClipPropClipRect(disp, effects, GetSize())) {
+      nsPoint offset = isTransformed
+                           ? GetOffsetToCrossDoc(
+                                 aBuilder->FindReferenceFrameFor(GetParent()))
+                           : aBuilder->GetCurrentFrameOffsetToReferenceFrame();
+
+      aBuilder->IntersectDirtyRect(*contentClip);
+      aBuilder->IntersectVisibleRect(*contentClip);
+      cssClip.ClipContentDescendants(*contentClip + offset);
+    }
+  }
 
   // If there is a current clip, then depending on the container items we
   // create, different things can happen to it. Some container items simply
   // propagate the clip to their children and aren't clipped themselves.
   // But other container items, especially those that establish a different
   // geometry for their contents (e.g. transforms), capture the clip on
   // themselves and unset the clip for their contents. If we create more than
   // one of those container items, the clip will be captured on the outermost
@@ -2954,48 +2967,42 @@ void nsIFrame::BuildDisplayListForStacki
       clipCapturedBy = ContainerItemType::ePerspective;
     } else {
       clipCapturedBy = ContainerItemType::eTransform;
     }
   } else if (usingFilter) {
     clipCapturedBy = ContainerItemType::eFilter;
   }
 
+  DisplayListClipState::AutoSaveRestore clipState(aBuilder);
   if (clipCapturedBy != ContainerItemType::eNone) {
     clipState.Clear();
   }
 
-  Maybe<nsRect> clipForMask;
-  if (usingMask) {
-    clipForMask = ComputeClipForMaskItem(aBuilder, this);
-  }
-
   mozilla::UniquePtr<HitTestInfo> hitTestInfo;
 
   nsDisplayListCollection set(aBuilder);
+  Maybe<nsRect> clipForMask;
   {
     DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
     nsDisplayListBuilder::AutoInTransformSetter inTransformSetter(aBuilder,
                                                                   inTransform);
     nsDisplayListBuilder::AutoEnterFilter filterASRSetter(aBuilder,
                                                           usingFilter);
 
     CheckForApzAwareEventHandlers(aBuilder, this);
 
-    Maybe<nsRect> contentClip = GetClipPropClipRect(disp, effects, GetSize());
-
     if (usingMask) {
-      contentClip = IntersectMaybeRects(contentClip, clipForMask);
-    }
-
-    if (contentClip) {
-      aBuilder->IntersectDirtyRect(*contentClip);
-      aBuilder->IntersectVisibleRect(*contentClip);
-      nestedClipState.ClipContentDescendants(*contentClip +
-                                             aBuilder->ToReferenceFrame(this));
+      clipForMask = ComputeClipForMaskItem(aBuilder, this);
+      if (clipForMask) {
+        aBuilder->IntersectDirtyRect(*clipForMask);
+        aBuilder->IntersectVisibleRect(*clipForMask);
+        nestedClipState.ClipContentDescendants(
+            *clipForMask + aBuilder->GetCurrentFrameOffsetToReferenceFrame());
+      }
     }
 
     // extend3DContext also guarantees that applyAbsPosClipping and
     // usingSVGEffects are false We only modify the preserve-3d rect if we are
     // the top of a preserve-3d heirarchy
     if (extend3DContext) {
       // Mark these first so MarkAbsoluteFramesForDisplayList knows if we are
       // going to be forced to descend into frames.
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -7874,17 +7874,17 @@ bool nsDisplayTransform::CreateWebRender
       ActiveLayerTracker::IsStyleMaybeAnimated(Frame(), eCSSProperty_transform);
 
   StackingContextHelper sc(
       aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder, filters,
       LayoutDeviceRect(position, LayoutDeviceSize()), &newTransformMatrix,
       animationsId ? &prop : nullptr, nullptr, transformForSC, nullptr,
       gfx::CompositionOp::OP_OVER, !BackfaceIsHidden(),
       mFrame->Extend3DContext() && !mNoExtendContext, deferredTransformItem,
-      nullptr, animated);
+      wr::WrStackingContextClip::None(), animated);
 
   return mStoredList.CreateWebRenderCommands(aBuilder, aResources, sc, aManager,
                                              aDisplayListBuilder);
 }
 
 bool nsDisplayTransform::UpdateScrollData(
     mozilla::layers::WebRenderScrollData* aData,
     mozilla::layers::WebRenderLayerScrollData* aLayerData) {
@@ -9068,17 +9068,17 @@ bool nsDisplayMasksAndClipPaths::CreateW
                   /*aAnimation: */ nullptr,
                   /*aOpacity: */ opacity.ptrOr(nullptr),
                   /*aTransform: */ nullptr,
                   /*aPerspective: */ nullptr,
                   /*aMixBlendMode: */ gfx::CompositionOp::OP_OVER,
                   /*aBackfaceVisible: */ true,
                   /*aIsPreserve3D: */ false,
                   /*aTransformForScrollData: */ Nothing(),
-                  /*aClipNodeId: */ &clipId);
+                  /*aClip: */ wr::WrStackingContextClip::ClipId(clipId));
     sc = layer.ptr();
   }
 
   nsDisplayEffectsBase::CreateWebRenderCommands(aBuilder, aResources, *sc,
                                                 aManager, aDisplayListBuilder);
 
   return true;
 }
@@ -9345,25 +9345,23 @@ bool nsDisplayFilters::CreateWebRenderCo
 
   nsTArray<mozilla::wr::FilterOp> wrFilters;
   if (!CreateWebRenderCSSFilters(wrFilters) &&
       !nsSVGIntegrationUtils::BuildWebRenderFilters(
           mFrame, preFilterBounds, wrFilters, postFilterBounds)) {
     return false;
   }
 
-  wr::WrClipId clipId =
-      aBuilder.DefineClip(Nothing(), wr::ToLayoutRect(postFilterBounds));
-
   float opacity = mFrame->StyleEffects()->mOpacity;
   StackingContextHelper sc(
       aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder, wrFilters,
       LayoutDeviceRect(), nullptr, nullptr,
       opacity != 1.0f && mHandleOpacity ? &opacity : nullptr, nullptr, nullptr,
-      gfx::CompositionOp::OP_OVER, true, false, Nothing(), &clipId);
+      gfx::CompositionOp::OP_OVER, true, false, Nothing(),
+      wr::WrStackingContextClip::ClipChain(aBuilder.CurrentClipChainId()));
 
   nsDisplayEffectsBase::CreateWebRenderCommands(aBuilder, aResources, sc,
                                                 aManager, aDisplayListBuilder);
 
   return true;
 }
 
 #ifdef MOZ_DUMP_PAINTING
--- a/toolkit/modules/subprocess/test/xpcshell/test_subprocess.js
+++ b/toolkit/modules/subprocess/test/xpcshell/test_subprocess.js
@@ -177,17 +177,17 @@ add_task(async function test_subprocess_
 
 
   let {exitCode} = await proc.wait();
 
   equal(exitCode, 0, "Got expected exit code");
 });
 
 
-add_task(async function test_subprocess_round_trip_perf() {
+add_task({skip_if: () => mozinfo.ccov}, async function test_subprocess_round_trip_perf() {
   let roundTripTime = Infinity;
   for (let i = 0; i < MAX_RETRIES && roundTripTime > MAX_ROUND_TRIP_TIME_MS; i++) {
     let proc = await Subprocess.call({
       command: PYTHON,
       arguments: ["-u", TEST_SCRIPT, "echo"],
     });
 
 
--- a/tools/fuzzing/faulty/Faulty.cpp
+++ b/tools/fuzzing/faulty/Faulty.cpp
@@ -209,27 +209,22 @@ Faulty::Faulty()
   }
 }
 
 // static
 bool Faulty::IsValidProcessType(void) {
   bool isValidProcessType;
   const bool targetChildren = !!PR_GetEnv("FAULTY_CHILDREN");
   const bool targetParent = !!PR_GetEnv("FAULTY_PARENT");
-  unsigned short int currentProcessType = XRE_GetProcessType();
+  const bool isParent = XRE_IsParentProcess();
 
   if (targetChildren && !targetParent) {
     // Fuzz every child process type but not the parent process.
-    isValidProcessType = currentProcessType == GeckoProcessType_Default;
-  } else if (!targetChildren && targetParent &&
-             (currentProcessType == GeckoProcessType_Plugin ||
-              currentProcessType == GeckoProcessType_Content ||
-              currentProcessType == GeckoProcessType_GMPlugin ||
-              currentProcessType == GeckoProcessType_GPU ||
-              currentProcessType == GeckoProcessType_VR)) {
+    isValidProcessType = isParent;
+  } else if (!targetChildren && targetParent && !isParent) {
     // Fuzz inside any of the above child process only.
     isValidProcessType = true;
   } else if (targetChildren && targetParent) {
     // Fuzz every process type.
     isValidProcessType = true;
   } else {
     // Fuzz no process type at all.
     isValidProcessType = false;