Merge m-c to m-i
authorPhil Ringnalda <philringnalda@gmail.com>
Fri, 02 Dec 2016 22:28:05 -0800
changeset 325203 1b2237e0b5e010ae3b182e4dbe79037635ee7997
parent 325202 237ba7e9c898fe41563b04afb2e4e16f1b96cf9a (current diff)
parent 325191 557548714db55136b51e1129d649e2599797985f (diff)
child 325204 bee6662585ed87109cb2ab1b05a16984025c95af
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
milestone53.0a1
Merge m-c to m-i MozReview-Commit-ID: 5bYzmy6C41c
--- a/build/moz.configure/rust.configure
+++ b/build/moz.configure/rust.configure
@@ -51,26 +51,35 @@ set_config('MOZ_CARGO_SUPPORTS_FROZEN', 
 @imports(_from='textwrap', _import='dedent')
 def rust_compiler(value, rustc, rustc_info):
     if value:
         if not rustc:
             die(dedent('''\
             Rust compiler not found.
             To compile rust language sources, you must have 'rustc' in your path.
             See https//www.rust-lang.org/ for more information.
+
+            You can install rust by running './mach bootstrap'
+            or by directly running the installer from https://rustup.rs/
             '''))
         version = rustc_info.version
-        min_version = Version('1.10')
+        min_version = Version('1.13')
         if version < min_version:
             die(dedent('''\
             Rust compiler {} is too old.
+
             To compile Rust language sources please install at least
             version {} of the 'rustc' toolchain and make sure it is
             first in your path.
+
             You can verify this by typing 'rustc --version'.
+
+            If you have the 'rustup' tool installed you can upgrade
+            to the latest release by typing 'rustup update'. The
+            installer is available from https://rustup.rs/
             '''.format(version, min_version)))
         return True
 
 set_config('MOZ_RUST', rust_compiler)
 
 @template
 def rust_triple_alias(host_or_target):
     """Template defining the alias used for rustc's --target flag.
--- a/config/config.mk
+++ b/config/config.mk
@@ -349,18 +349,16 @@ ifeq (,$(filter $(COLOR_CFLAGS:-f%=-fno-
 endif
 endef
 
 color_flags_vars := \
   COMPILE_CFLAGS \
   COMPILE_CXXFLAGS \
   COMPILE_CMFLAGS \
   COMPILE_CMMFLAGS \
-  HOST_CFLAGS \
-  HOST_CXXFLAGS \
   LDFLAGS \
   $(NULL)
 
 ifdef MACH_STDOUT_ISATTY
 ifdef COLOR_CFLAGS
 # TODO Bug 1319166 - iTerm2 interprets some bytes  sequences as a
 # request to show a print dialog. Don't enable color on iTerm2 until
 # a workaround is in place.
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -335,16 +335,30 @@ IsAnonymousFlexOrGridItem(const nsIFrame
 static inline bool
 IsFlexOrGridContainer(const nsIFrame* aFrame)
 {
   const nsIAtom* t = aFrame->GetType();
   return t == nsGkAtoms::flexContainerFrame ||
          t == nsGkAtoms::gridContainerFrame;
 }
 
+// Returns true IFF the given nsIFrame is a nsFlexContainerFrame and
+// represents a -webkit-{inline-}box container. The frame's GetType() result is
+// passed as a separate argument, since in most cases, the caller will have
+// looked it up already, and we'd rather not make redundant calls to the
+// virtual GetType() method.
+static inline bool
+IsFlexContainerForLegacyBox(const nsIFrame* aFrame,
+                            const nsIAtom* aFrameType)
+{
+  MOZ_ASSERT(aFrame->GetType() == aFrameType, "wrong aFrameType was passed");
+  return aFrameType == nsGkAtoms::flexContainerFrame &&
+    aFrame->HasAnyStateBits(NS_STATE_FLEX_IS_LEGACY_WEBKIT_BOX);
+}
+
 #if DEBUG
 static void
 AssertAnonymousFlexOrGridItemParent(const nsIFrame* aChild,
                                     const nsIFrame* aParent)
 {
   MOZ_ASSERT(IsAnonymousFlexOrGridItem(aChild),
              "expected an anonymous flex or grid item child frame");
   MOZ_ASSERT(aParent, "expected a parent frame");
@@ -9916,23 +9930,27 @@ nsCSSFrameConstructor::sPseudoParentData
 };
 
 void
 nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
   nsFrameConstructorState& aState,
   FrameConstructionItemList& aItems,
   nsIFrame* aParentFrame)
 {
-  if (aItems.IsEmpty() ||
-      !::IsFlexOrGridContainer(aParentFrame)) {
+  if (aItems.IsEmpty()) {
     return;
   }
-
-  const bool isWebkitBox = nsFlexContainerFrame::IsLegacyBox(aParentFrame);
-
+  const nsIAtom* parentType = aParentFrame->GetType();
+  if (parentType != nsGkAtoms::flexContainerFrame &&
+      parentType != nsGkAtoms::gridContainerFrame) {
+    return;
+  }
+
+  const bool isWebkitBox = IsFlexContainerForLegacyBox(aParentFrame,
+                                                       parentType);
   FCItemIterator iter(aItems);
   do {
     // Advance iter past children that don't want to be wrapped
     if (iter.SkipItemsThatDontNeedAnonFlexOrGridItem(aState, isWebkitBox)) {
       // Hit the end of the items without finding any remaining children that
       // need to be wrapped. We're finished!
       return;
     }
@@ -12214,22 +12232,24 @@ nsCSSFrameConstructor::WipeContainingBlo
     return true;
   }
 
   nsIFrame* nextSibling = ::GetInsertNextSibling(aFrame, aPrevSibling);
 
   // Situation #2 is a flex or grid container frame into which we're inserting
   // new inline non-replaced children, adjacent to an existing anonymous
   // flex or grid item.
-  if (::IsFlexOrGridContainer(aFrame)) {
+  nsIAtom* frameType = aFrame->GetType();
+  if (frameType == nsGkAtoms::flexContainerFrame ||
+      frameType == nsGkAtoms::gridContainerFrame) {
     FCItemIterator iter(aItems);
 
     // Check if we're adding to-be-wrapped content right *after* an existing
     // anonymous flex or grid item (which would need to absorb this content).
-    const bool isWebkitBox = nsFlexContainerFrame::IsLegacyBox(aFrame);
+    const bool isWebkitBox = IsFlexContainerForLegacyBox(aFrame, frameType);
     if (aPrevSibling && IsAnonymousFlexOrGridItem(aPrevSibling) &&
         iter.item().NeedsAnonFlexOrGridItem(aState, isWebkitBox)) {
       RecreateFramesForContent(aFrame->GetContent(), true,
                                REMOVE_FOR_RECONSTRUCTION, nullptr);
       return true;
     }
 
     // Check if we're adding to-be-wrapped content right *before* an existing
@@ -12259,17 +12279,18 @@ nsCSSFrameConstructor::WipeContainingBlo
     // _flex/grid container_ as its parent in the content tree.
     nsFrameConstructorSaveState floatSaveState;
     aState.PushFloatContainingBlock(nullptr, floatSaveState);
 
     FCItemIterator iter(aItems);
     // Skip over things that _do_ need an anonymous flex item, because
     // they're perfectly happy to go here -- they won't cause a reframe.
     nsIFrame* containerFrame = aFrame->GetParent();
-    const bool isWebkitBox = nsFlexContainerFrame::IsLegacyBox(containerFrame);
+    const bool isWebkitBox =
+      IsFlexContainerForLegacyBox(containerFrame, containerFrame->GetType());
     if (!iter.SkipItemsThatNeedAnonFlexOrGridItem(aState,
                                                   isWebkitBox)) {
       // We hit something that _doesn't_ need an anonymous flex item!
       // Rebuild the flex container to bust it out.
       RecreateFramesForContent(containerFrame->GetContent(), true,
                                REMOVE_FOR_RECONSTRUCTION, nullptr);
       return true;
     }
@@ -12283,17 +12304,16 @@ nsCSSFrameConstructor::WipeContainingBlo
   // spaces. It containes these two special cases apart from tables:
   // 1) There are effectively three types of white spaces in ruby frames
   //    we handle differently: leading/tailing/inter-level space,
   //    inter-base/inter-annotation space, and inter-segment space.
   //    These three types of spaces can be converted to each other when
   //    their sibling changes.
   // 2) The first effective child of a ruby frame must always be a ruby
   //    base container. It should be created or destroyed accordingly.
-  nsIAtom* frameType = aFrame->GetType();
   if (IsRubyPseudo(aFrame) ||
       frameType == nsGkAtoms::rubyFrame ||
       RubyUtils::IsRubyContainerBox(frameType)) {
     // We want to optimize it better, and avoid reframing as much as
     // possible. But given the cases above, and the fact that a ruby
     // usually won't be very large, it should be fine to reframe it.
     RecreateFramesForContent(aFrame->GetContent(), true,
                              REMOVE_FOR_RECONSTRUCTION, nullptr);
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -82,43 +82,26 @@ kAxisOrientationToSidesMap[eNumAxisOrien
 // Returns true iff the given nsStyleDisplay has display:-webkit-{inline-}-box.
 static inline bool
 IsDisplayValueLegacyBox(const nsStyleDisplay* aStyleDisp)
 {
   return aStyleDisp->mDisplay == mozilla::StyleDisplay::WebkitBox ||
     aStyleDisp->mDisplay == mozilla::StyleDisplay::WebkitInlineBox;
 }
 
-/* static */ bool
-nsFlexContainerFrame::IsLegacyBox(const nsIFrame* aFrame)
+// Returns true if aFlexContainer is the frame for an element with
+// "display:-webkit-box" or "display:-webkit-inline-box". aFlexContainer is
+// expected to be an instance of nsFlexContainerFrame (enforced with an assert);
+// otherwise, this function's state-bit-check here is bogus.
+static bool
+IsLegacyBox(const nsIFrame* aFlexContainer)
 {
-  nsStyleContext* styleContext = aFrame->StyleContext();
-  const nsStyleDisplay* styleDisp = styleContext->StyleDisplay();
-
-  // Trivial case: just check "display" directly.
-  bool isLegacyBox = IsDisplayValueLegacyBox(styleDisp);
-
-  // If this frame is for a scrollable element, then it will actually have
-  // "display:block", and its *parent* will have the real flex-flavored display
-  // value. So in that case, check the parent to find out if we're legacy.
-  if (!isLegacyBox && styleDisp->mDisplay == mozilla::StyleDisplay::Block) {
-    nsStyleContext* parentStyleContext = styleContext->GetParent();
-    NS_ASSERTION(parentStyleContext &&
-                 (styleContext->GetPseudo() == nsCSSAnonBoxes::buttonContent ||
-                  styleContext->GetPseudo() == nsCSSAnonBoxes::scrolledContent),
-                 "The only way a nsFlexContainerFrame can have 'display:block' "
-                 "should be if it's the inner part of a scrollable or button "
-                 "element");
-    isLegacyBox = IsDisplayValueLegacyBox(parentStyleContext->StyleDisplay());
-  }
-
-  NS_ASSERTION(!isLegacyBox ||
-               aFrame->GetType() == nsGkAtoms::flexContainerFrame,
-               "legacy box with unexpected frame type");
-  return isLegacyBox;
+  MOZ_ASSERT(aFlexContainer->GetType() == nsGkAtoms::flexContainerFrame,
+             "only flex containers may be passed to this function");
+  return aFlexContainer->HasAnyStateBits(NS_STATE_FLEX_IS_LEGACY_WEBKIT_BOX);
 }
 
 // Returns the "align-items" value that's equivalent to the legacy "box-align"
 // value in the given style struct.
 static uint8_t
 ConvertLegacyStyleToAlignItems(const nsStyleXUL* aStyleXUL)
 {
   // -[moz|webkit]-box-align corresponds to modern "align-items"
@@ -1126,17 +1109,17 @@ IsOrderLEQWithDOMFallback(nsIFrame* aFra
   if (aFrame1->GetType() == nsGkAtoms::placeholderFrame ||
       aFrame2->GetType() == nsGkAtoms::placeholderFrame) {
     // Treat placeholders (for abspos/fixedpos frames) as LEQ everything.  This
     // ensures we don't reorder them w.r.t. one another, which is sufficient to
     // prevent them from noticeably participating in "order" reordering.
     return true;
   }
 
-  bool isInLegacyBox = nsFlexContainerFrame::IsLegacyBox(aFrame1->GetParent());
+  const bool isInLegacyBox = IsLegacyBox(aFrame1->GetParent());
 
   int32_t order1 = GetOrderOrBoxOrdinalGroup(aFrame1, isInLegacyBox);
   int32_t order2 = GetOrderOrBoxOrdinalGroup(aFrame2, isInLegacyBox);
 
   if (order1 != order2) {
     return order1 < order2;
   }
 
@@ -1204,17 +1187,17 @@ IsOrderLEQ(nsIFrame* aFrame1,
   if (aFrame1->GetType() == nsGkAtoms::placeholderFrame ||
       aFrame2->GetType() == nsGkAtoms::placeholderFrame) {
     // Treat placeholders (for abspos/fixedpos frames) as LEQ everything.  This
     // ensures we don't reorder them w.r.t. one another, which is sufficient to
     // prevent them from noticeably participating in "order" reordering.
     return true;
   }
 
-  bool isInLegacyBox = nsFlexContainerFrame::IsLegacyBox(aFrame1->GetParent());
+  const bool isInLegacyBox = IsLegacyBox(aFrame1->GetParent());
 
   int32_t order1 = GetOrderOrBoxOrdinalGroup(aFrame1, isInLegacyBox);
   int32_t order2 = GetOrderOrBoxOrdinalGroup(aFrame2, isInLegacyBox);
 
   return order1 <= order2;
 }
 
 uint8_t
@@ -2269,16 +2252,50 @@ NS_NewFlexContainerFrame(nsIPresShell* a
 // nsFlexContainerFrame Method Implementations
 // ===========================================
 
 /* virtual */
 nsFlexContainerFrame::~nsFlexContainerFrame()
 {
 }
 
+/* virtual */
+void
+nsFlexContainerFrame::Init(nsIContent*       aContent,
+                           nsContainerFrame* aParent,
+                           nsIFrame*         aPrevInFlow)
+{
+  nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
+
+  const nsStyleDisplay* styleDisp = StyleContext()->StyleDisplay();
+
+  // Figure out if we should set a frame state bit to indicate that this frame
+  // represents a legacy -webkit-{inline-}box container.
+  // First, the trivial case: just check "display" directly.
+  bool isLegacyBox = IsDisplayValueLegacyBox(styleDisp);
+
+  // If this frame is for a scrollable element, then it will actually have
+  // "display:block", and its *parent* will have the real flex-flavored display
+  // value. So in that case, check the parent to find out if we're legacy.
+  if (!isLegacyBox && styleDisp->mDisplay == mozilla::StyleDisplay::Block) {
+    nsStyleContext* parentStyleContext = mStyleContext->GetParent();
+    NS_ASSERTION(parentStyleContext &&
+                 (mStyleContext->GetPseudo() == nsCSSAnonBoxes::buttonContent ||
+                  mStyleContext->GetPseudo() == nsCSSAnonBoxes::scrolledContent),
+                 "The only way a nsFlexContainerFrame can have 'display:block' "
+                 "should be if it's the inner part of a scrollable or button "
+                 "element");
+    isLegacyBox = IsDisplayValueLegacyBox(parentStyleContext->StyleDisplay());
+  }
+
+  if (isLegacyBox) {
+    AddStateBits(NS_STATE_FLEX_IS_LEGACY_WEBKIT_BOX);
+  }
+}
+
 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
 /* static */ bool
 nsFlexContainerFrame::SortChildrenIfNeeded()
 {
   if (nsIFrame::IsFrameListSorted<IsLessThanOrEqual>(mFrames)) {
     return false;
   }
 
--- a/layout/generic/nsFlexContainerFrame.h
+++ b/layout/generic/nsFlexContainerFrame.h
@@ -53,16 +53,20 @@ public:
 
   // Forward-decls of helper classes
   class FlexItem;
   class FlexLine;
   class FlexboxAxisTracker;
   struct StrutInfo;
 
   // nsIFrame overrides
+  void Init(nsIContent*       aContent,
+            nsContainerFrame* aParent,
+            nsIFrame*         aPrevInFlow) override;
+
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
   virtual void Reflow(nsPresContext*           aPresContext,
                       ReflowOutput&     aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus&          aStatus) override;
@@ -102,22 +106,16 @@ public:
     *                                     space to be divided up.
     */
   static void CalculatePackingSpace(uint32_t aNumThingsToPack,
                                     uint8_t aAlignVal,
                                     nscoord* aFirstSubjectOffset,
                                     uint32_t* aNumPackingSpacesRemaining,
                                     nscoord* aPackingSpaceRemaining);
 
-  /**
-   * Returns true if aFrame is the frame for an element with
-   * "display:-webkit-box" or "display:-webkit-inline-box".
-   */
-  static bool IsLegacyBox(const nsIFrame* aFrame);
-
 protected:
   // Protected constructor & destructor
   explicit nsFlexContainerFrame(nsStyleContext* aContext)
     : nsContainerFrame(aContext)
     , mBaselineFromLastReflow(NS_INTRINSIC_WIDTH_UNKNOWN)
   {}
   virtual ~nsFlexContainerFrame();
 
--- a/layout/generic/nsFrameStateBits.h
+++ b/layout/generic/nsFrameStateBits.h
@@ -302,16 +302,20 @@ FRAME_STATE_BIT(Box, 61, NS_FRAME_MOUSE_
 // == Frame state bits that apply to flex container frames ====================
 
 FRAME_STATE_GROUP(FlexContainer, nsFlexContainerFrame)
 
 // Set for a flex container whose children have been reordered due to 'order'.
 // (Means that we have to be more thorough about checking them for sortedness.)
 FRAME_STATE_BIT(FlexContainer, 20, NS_STATE_FLEX_CHILDREN_REORDERED)
 
+// Set for a flex container that is emulating a legacy
+// 'display:-webkit-{inline-}box' container.
+FRAME_STATE_BIT(FlexContainer, 21, NS_STATE_FLEX_IS_LEGACY_WEBKIT_BOX)
+
 // == Frame state bits that apply to grid container frames ====================
 
 FRAME_STATE_GROUP(GridContainer, nsGridContainerFrame)
 
 // True iff the normal flow children are already in CSS 'order' in the
 // order they occur in the child frame list.
 FRAME_STATE_BIT(GridContainer, 20, NS_STATE_GRID_NORMAL_FLOW_CHILDREN_IN_CSS_ORDER)
 
--- a/layout/style/CSSLexer.h
+++ b/layout/style/CSSLexer.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef CSSLexer_h___
 #define CSSLexer_h___
 
 #include "mozilla/UniquePtr.h"
 #include "nsCSSScanner.h"
 #include "mozilla/dom/CSSLexerBinding.h"
+#include "mozilla/dom/NonRefcountedDOMObject.h"
 
 namespace mozilla {
 namespace dom {
 
 class CSSLexer : public NonRefcountedDOMObject
 {
 public:
   explicit CSSLexer(const nsAString&);
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -18,16 +18,17 @@
 #include "mozilla/css/ImportRule.h"
 #include "nsCSSRules.h"
 #include "nsIMediaList.h"
 #include "nsIDocument.h"
 #include "nsPresContext.h"
 #include "nsGkAtoms.h"
 #include "nsQueryObject.h"
 #include "nsString.h"
+#include "nsStyleSet.h"
 #include "nsTArray.h"
 #include "nsIDOMCSSStyleSheet.h"
 #include "mozilla/dom/CSSRuleList.h"
 #include "nsIDOMMediaList.h"
 #include "nsIDOMNode.h"
 #include "nsError.h"
 #include "nsCSSParser.h"
 #include "mozilla/css/Loader.h"
--- a/layout/style/Declaration.cpp
+++ b/layout/style/Declaration.cpp
@@ -7,16 +7,17 @@
  * representation of a declaration block (or style attribute) in a CSS
  * stylesheet
  */
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/MemoryReporting.h"
 
 #include "mozilla/css/Declaration.h"
+#include "mozilla/css/Rule.h"
 #include "nsPrintfCString.h"
 #include "gfxFontConstants.h"
 #include "nsStyleUtil.h"
 
 namespace mozilla {
 namespace css {
 
 NS_IMPL_QUERY_INTERFACE(ImportantStyleData, nsIStyleRule)
--- a/layout/style/RuleProcessorCache.cpp
+++ b/layout/style/RuleProcessorCache.cpp
@@ -6,16 +6,17 @@
 
 /*
  * cache of re-usable nsCSSRuleProcessors for given sets of style sheets
  */
 
 #include "RuleProcessorCache.h"
 
 #include <algorithm>
+#include "mozilla/CSSStyleSheet.h"
 #include "nsCSSRuleProcessor.h"
 #include "nsThreadUtils.h"
 
 using namespace mozilla;
 
 NS_IMPL_ISUPPORTS(RuleProcessorCache, nsIMemoryReporter)
 
 MOZ_DEFINE_MALLOC_SIZE_OF(RuleProcessorCacheMallocSizeOf)
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -27,16 +27,17 @@
 #include "nsTArray.h"
 
 #include "mozilla/EventStates.h"
 #include "mozilla/ServoElementSnapshot.h"
 #include "mozilla/ServoRestyleManager.h"
 #include "mozilla/StyleAnimationValue.h"
 #include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/dom/ElementInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #define SERVO_ARC_TYPE(name_, type_) \
   already_AddRefed<type_>            \
   type_##Strong::Consume() {         \
     RefPtr<type_> result;            \
--- a/layout/style/ServoCSSRuleList.h
+++ b/layout/style/ServoCSSRuleList.h
@@ -14,17 +14,17 @@
 
 namespace mozilla {
 
 class ServoStyleSheet;
 namespace css {
 class Rule;
 } // namespace css
 
-class ServoCSSRuleList final : public CSSRuleList
+class ServoCSSRuleList final : public dom::CSSRuleList
 {
 public:
   ServoCSSRuleList(ServoStyleSheet* aStyleSheet,
                    already_AddRefed<ServoCssRules> aRawRules);
 
   ServoStyleSheet* GetParentObject() final { return mStyleSheet; }
 
   nsIDOMCSSRule* IndexedGetter(uint32_t aIndex, bool& aFound) final;
--- a/layout/style/ServoStyleRule.cpp
+++ b/layout/style/ServoStyleRule.cpp
@@ -3,16 +3,17 @@
 /* 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/. */
 
 /* representation of CSSStyleRule for stylo */
 
 #include "mozilla/ServoStyleRule.h"
 
+#include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/ServoDeclarationBlock.h"
 
 #include "nsDOMClassInfoID.h"
 #include "mozAutoDocUpdate.h"
 
 namespace mozilla {
 
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -1,22 +1,26 @@
 /* -*- 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 "mozilla/ServoStyleSheet.h"
+
+#include "mozilla/css/Rule.h"
 #include "mozilla/StyleBackendType.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/ServoCSSRuleList.h"
 #include "mozilla/dom/CSSRuleList.h"
 
 #include "mozAutoDocUpdate.h"
 
+using namespace mozilla::dom;
+
 namespace mozilla {
 
 ServoStyleSheet::ServoStyleSheet(css::SheetParsingMode aParsingMode,
                                  CORSMode aCORSMode,
                                  net::ReferrerPolicy aReferrerPolicy,
                                  const dom::SRIMetadata& aIntegrity)
   : StyleSheet(StyleBackendType::Servo, aParsingMode)
   , mSheetInfo(aCORSMode, aReferrerPolicy, aIntegrity)
--- a/layout/style/nsCSSPseudoClasses.cpp
+++ b/layout/style/nsCSSPseudoClasses.cpp
@@ -3,16 +3,17 @@
  * 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/. */
 
 /* atom list for CSS pseudo-classes */
 
 #include "mozilla/ArrayUtils.h"
 
 #include "nsCSSPseudoClasses.h"
+#include "nsCSSPseudoElements.h"
 #include "nsStaticAtom.h"
 #include "mozilla/Preferences.h"
 #include "nsString.h"
 
 using namespace mozilla;
 
 // define storage for all atoms
 #define CSS_PSEUDO_CLASS(_name, _value, _flags, _pref) \
--- a/layout/style/nsCSSPseudoClasses.h
+++ b/layout/style/nsCSSPseudoClasses.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* atom list for CSS pseudo-classes */
 
 #ifndef nsCSSPseudoClasses_h___
 #define nsCSSPseudoClasses_h___
 
 #include "nsStringFwd.h"
+#include "mozilla/CSSEnabledState.h"
 
 // The following two flags along with the pref defines where this pseudo
 // class can be used:
 // * If none of the two flags is presented, the pref completely controls
 //   the availability of this pseudo class. And in that case, if it has
 //   no pref, this property is usable everywhere.
 // * If any of the flags is set, this pseudo class is always enabled in
 //   the specific contexts regardless of the value of the pref. If there
--- a/layout/style/nsCSSScanner.cpp
+++ b/layout/style/nsCSSScanner.cpp
@@ -9,16 +9,18 @@
 #include "nsCSSScanner.h"
 #include "nsStyleUtil.h"
 #include "nsISupportsImpl.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/css/ErrorReporter.h"
 #include "mozilla/Likely.h"
 #include <algorithm>
 
+using namespace mozilla;
+
 /* Character class tables and related helper functions. */
 
 static const uint8_t IS_HEX_DIGIT  = 0x01;
 static const uint8_t IS_IDSTART    = 0x02;
 static const uint8_t IS_IDCHAR     = 0x04;
 static const uint8_t IS_URL_CHAR   = 0x08;
 static const uint8_t IS_HSPACE     = 0x10;
 static const uint8_t IS_VSPACE     = 0x20;
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -23,16 +23,17 @@
 #include "nsNetUtil.h"
 #include "nsPresContext.h"
 #include "nsStyleUtil.h"
 #include "nsDeviceContext.h"
 #include "nsStyleSet.h"
 #include "nsContentUtils.h"
 
 using namespace mozilla;
+using namespace mozilla::css;
 
 static bool
 IsLocalRefURL(nsStringBuffer* aString)
 {
   // Find the first non-"C0 controls + space" character.
   char16_t* current = static_cast<char16_t*>(aString->Data());
   for (; *current != '\0'; current++) {
     if (*current > 0x20) {
--- a/layout/style/nsDOMCSSAttrDeclaration.cpp
+++ b/layout/style/nsDOMCSSAttrDeclaration.cpp
@@ -4,17 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* DOM object for element.style */
 
 #include "nsDOMCSSAttrDeclaration.h"
 
 #include "mozilla/css/Declaration.h"
 #include "mozilla/css/StyleRule.h"
+#include "mozilla/DeclarationBlock.h"
+#include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/ServoDeclarationBlock.h"
 #include "nsIDocument.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsIURI.h"
 #include "nsNodeUtils.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsIFrame.h"
 #include "ActiveLayerTracker.h"
 
--- a/layout/style/nsMediaFeatures.cpp
+++ b/layout/style/nsMediaFeatures.cpp
@@ -14,16 +14,17 @@
 #include "nsCSSValue.h"
 #ifdef XP_WIN
 #include "mozilla/LookAndFeel.h"
 #endif
 #include "nsCSSRuleProcessor.h"
 #include "nsDeviceContext.h"
 #include "nsIBaseWindow.h"
 #include "nsIDocument.h"
+#include "nsIWidget.h"
 #include "nsContentUtils.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 
 using namespace mozilla;
 
 static const nsCSSProps::KTableEntry kOrientationKeywords[] = {
   { eCSSKeyword_portrait,                 NS_STYLE_ORIENTATION_PORTRAIT },
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -6,17 +6,20 @@
 /* the interface (to internal code) for retrieving computed style data */
 
 #include "CSSVariableImageTable.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Maybe.h"
 
 #include "nsCSSAnonBoxes.h"
 #include "nsCSSPseudoElements.h"
+#include "nsFontMetrics.h"
 #include "nsStyleConsts.h"
+#include "nsStyleStruct.h"
+#include "nsStyleStructInlines.h"
 #include "nsString.h"
 #include "nsPresContext.h"
 #include "nsIStyleRule.h"
 
 #include "nsCOMPtr.h"
 #include "nsStyleSet.h"
 #include "nsIPresShell.h"
 
--- a/layout/style/nsStyleCoord.cpp
+++ b/layout/style/nsStyleCoord.cpp
@@ -4,16 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* representation of length values in computed style data */
 
 #include "nsStyleCoord.h"
 #include "mozilla/HashFunctions.h"
 #include "mozilla/PodOperations.h"
 
+using namespace mozilla;
+
 nsStyleCoord::nsStyleCoord(nsStyleUnit aUnit)
   : mUnit(aUnit)
 {
   NS_ASSERTION(aUnit < eStyleUnit_Percent, "not a valueless unit");
   if (aUnit >= eStyleUnit_Percent) {
     mUnit = eStyleUnit_Null;
   }
   mValue.mInt = 0;
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -35,16 +35,17 @@
 #include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for PlaybackDirection
 #include "mozilla/dom/ImageTracker.h"
 #include "mozilla/Likely.h"
 #include "nsIURI.h"
 #include "nsIDocument.h"
 #include <algorithm>
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 static_assert((((1 << nsStyleStructID_Length) - 1) &
                ~(NS_STYLE_INHERIT_MASK)) == 0,
               "Not enough bits in NS_STYLE_INHERIT_MASK");
 
 /* static */ const int32_t nsStyleGridLine::kMinLine;
 /* static */ const int32_t nsStyleGridLine::kMaxLine;
 
--- a/taskcluster/ci/desktop-test/test-sets.yml
+++ b/taskcluster/ci/desktop-test/test-sets.yml
@@ -95,25 +95,25 @@ asan-tests:
     - xpcshell
 
 windows-vm-tests:
     - cppunit
     #- crashtest
     - external-media-tests
     #- gtest
     #- jittest
-    #- jsreftest
+    - jsreftest
     #- marionette
     #- mochitest
     #- mochitest-browser-chrome
-    #- mochitest-devtools-chrome
-    #- mochitest-jetpack
+    - mochitest-devtools-chrome
+    - mochitest-jetpack
     #- mochitest-media
     #- web-platform-tests
-    #- web-platform-tests-reftests
+    - web-platform-tests-reftests
     #- xpcshell
 
 # windows-gpu-tests:
 #    - reftest
 #    - reftest-no-accel
 #    - mochitest-webgl
 
 # these tests currently run on hardware, but may migrate above when validated
--- a/taskcluster/ci/desktop-test/tests.yml
+++ b/taskcluster/ci/desktop-test/tests.yml
@@ -152,16 +152,21 @@ jittest:
 jsreftest:
     description: "JS Reftest run"
     suite: reftest/jsreftest
     treeherder-symbol: tc-R(J)
     chunks:
         by-test-platform:
             win.*: 1
             default: 2
+    e10s:
+        by-test-platform:
+            # Bug 1321782
+            win.*: false
+            default: both
     mozharness:
         script: desktop_unittest.py
         no-read-buildbot-config: true
         config:
             by-test-platform:
                 win.*:
                     - unittests/win_taskcluster_unittest.py
                 macosx.*:
@@ -384,16 +389,18 @@ mochitest-devtools-chrome:
             linux64-jsdcov/opt: []
             default: ['all']
     e10s:
         by-test-platform:
             # Bug 1242986: linux64/debug mochitest-devtools-chrome e10s is not greened up yet
             linux64/debug: false
             linux64-ccov/opt: false
             linux64-jsdcov/opt: false
+            # Bug 1304433: mochitest-devtools-chrome (e10s) not greened on windows
+            win.*: false
             default: both
     mozharness:
         script: desktop_unittest.py
         no-read-buildbot-config: true
         config:
             by-test-platform:
                 win.*:
                     - unittests/win_taskcluster_unittest.py
@@ -661,16 +668,21 @@ web-platform-tests:
             - --test-type=testharness
 
 web-platform-tests-reftests:
     description: "Web platform reftest run"
     suite: web-platform-tests-reftests
     treeherder-symbol: tc-W(Wr)
     max-run-time: 5400
     instance-size: xlarge
+    e10s:
+        by-test-platform:
+            # Bug 1304438
+            win.*: false
+            default: both
     docker-image: {"in-tree": "desktop1604-test"}
     checkout: true
     mozharness:
         script: web_platform_tests.py
         no-read-buildbot-config: true
         config:
             by-test-platform:
                 win.*:
--- a/taskcluster/taskgraph/transforms/tests/all_kinds.py
+++ b/taskcluster/taskgraph/transforms/tests/all_kinds.py
@@ -42,16 +42,18 @@ def set_tier(config, tests):
     for test in tests:
         # only override if not set for the test
         if 'tier' not in test:
             if test['test-platform'] in ['linux64/debug',
                                          'linux64-asan/opt',
                                          'android-4.3-arm7-api-15/debug',
                                          'android-x86/opt']:
                 test['tier'] = 1
+            elif test['test-platform'].startswith('win'):
+                test['tier'] = 3
             else:
                 test['tier'] = 2
         yield test
 
 
 @transforms.add
 def set_expires_after(config, tests):
     """Try jobs expire after 2 weeks; everything else lasts 1 year.  This helps
@@ -86,16 +88,17 @@ def resolve_keyed_by(config, tests):
     """Resolve fields that can be keyed by platform, etc."""
     fields = [
         'instance-size',
         'max-run-time',
         'chunks',
         'e10s',
         'suite',
         'run-on-projects',
+        'tier',
     ]
     for test in tests:
         for field in fields:
             test[field] = get_keyed_by(item=test, field=field, item_name=test['test-name'])
         test['mozharness']['config'] = get_keyed_by(item=test,
                                                     field='mozharness',
                                                     subfield='config',
                                                     item_name=test['test-name'])
--- a/taskcluster/taskgraph/transforms/tests/test_description.py
+++ b/taskcluster/taskgraph/transforms/tests/test_description.py
@@ -61,17 +61,20 @@ test_description_schema = Schema({
     # projects on which this task should be included in the target task set.
     # See the attributes documentation for details.
     Optional('run-on-projects', default=['all']): Any(
         [basestring],
         {'by-test-platform': {basestring: [basestring]}},
     ),
 
     # the sheriffing tier for this task (default: set based on test platform)
-    Optional('tier'): int,
+    Optional('tier'): Any(
+        int,
+        {'by-test-platform': {basestring: int}},
+    ),
 
     # number of chunks to create for this task.  This can be keyed by test
     # platform by passing a dictionary in the `by-test-platform` key.  If the
     # test platform is not found, the key 'default' will be tried.
     Required('chunks', default=1): Any(
         int,
         {'by-test-platform': {basestring: int}},
     ),
--- a/testing/marionette/client/marionette_driver/marionette.py
+++ b/testing/marionette/client/marionette_driver/marionette.py
@@ -565,16 +565,17 @@ class Marionette(object):
         :param app: Type of ``instance_class`` to use for managing app
             instance. See ``marionette_driver.geckoinstance``.
         :param instance_args: Arguments to pass to ``instance_class``.
 
         """
         self.host = host
         self.port = self.local_port = int(port)
         self.bin = bin
+        self.client = None
         self.instance = None
         self.session = None
         self.session_id = None
         self.process_id = None
         self.profile = None
         self.window = None
         self.chrome_window = None
         self.baseurl = baseurl
@@ -1303,17 +1304,19 @@ class Marionette(object):
                 self._send_message("deleteSession")
         finally:
             if reset_session_id:
                 self.session_id = None
             self.session = None
             self.process_id = None
             self.profile = None
             self.window = None
-            self.client.close()
+
+            if self.client is not None:
+                self.client.close()
 
     @property
     def session_capabilities(self):
         """A JSON dictionary representing the capabilities of the
         current session.
 
         """
         return self.session
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -2867,52 +2867,42 @@ GeckoDriver.prototype.commands = {
   "isElementEnabled": GeckoDriver.prototype.isElementEnabled,
   "isElementSelected": GeckoDriver.prototype.isElementSelected,
   "sendKeysToElement": GeckoDriver.prototype.sendKeysToElement,
   "clearElement": GeckoDriver.prototype.clearElement,
   "getTitle": GeckoDriver.prototype.getTitle,
   "getWindowType": GeckoDriver.prototype.getWindowType,
   "getPageSource": GeckoDriver.prototype.getPageSource,
   "get": GeckoDriver.prototype.get,
-  "goUrl": GeckoDriver.prototype.get,  // deprecated
   "getCurrentUrl": GeckoDriver.prototype.getCurrentUrl,
-  "getUrl": GeckoDriver.prototype.getCurrentUrl,  // deprecated
   "goBack": GeckoDriver.prototype.goBack,
   "goForward": GeckoDriver.prototype.goForward,
   "refresh":  GeckoDriver.prototype.refresh,
   "getWindowHandle": GeckoDriver.prototype.getWindowHandle,
-  "getCurrentWindowHandle":  GeckoDriver.prototype.getWindowHandle,  // Selenium 2 compat
   "getChromeWindowHandle": GeckoDriver.prototype.getChromeWindowHandle,
   "getCurrentChromeWindowHandle": GeckoDriver.prototype.getChromeWindowHandle,
-  "getWindow":  GeckoDriver.prototype.getWindowHandle,  // deprecated
   "getWindowHandles": GeckoDriver.prototype.getWindowHandles,
   "getChromeWindowHandles": GeckoDriver.prototype.getChromeWindowHandles,
-  "getCurrentWindowHandles": GeckoDriver.prototype.getWindowHandles,  // Selenium 2 compat
-  "getWindows":  GeckoDriver.prototype.getWindowHandles,  // deprecated
   "getWindowPosition": GeckoDriver.prototype.getWindowPosition,
   "setWindowPosition": GeckoDriver.prototype.setWindowPosition,
   "getActiveFrame": GeckoDriver.prototype.getActiveFrame,
   "switchToFrame": GeckoDriver.prototype.switchToFrame,
   "switchToParentFrame": GeckoDriver.prototype.switchToParentFrame,
   "switchToWindow": GeckoDriver.prototype.switchToWindow,
   "switchToShadowRoot": GeckoDriver.prototype.switchToShadowRoot,
   "deleteSession": GeckoDriver.prototype.deleteSession,
   "importScript": GeckoDriver.prototype.importScript,
   "clearImportedScripts": GeckoDriver.prototype.clearImportedScripts,
   "getAppCacheStatus": GeckoDriver.prototype.getAppCacheStatus,
   "close": GeckoDriver.prototype.close,
-  "closeWindow": GeckoDriver.prototype.close,  // deprecated
   "closeChromeWindow": GeckoDriver.prototype.closeChromeWindow,
   "setTestName": GeckoDriver.prototype.setTestName,
   "takeScreenshot": GeckoDriver.prototype.takeScreenshot,
-  "screenShot": GeckoDriver.prototype.takeScreenshot,  // deprecated
-  "screenshot": GeckoDriver.prototype.takeScreenshot,  // Selenium 2 compat
   "addCookie": GeckoDriver.prototype.addCookie,
   "getCookies": GeckoDriver.prototype.getCookies,
-  "getAllCookies": GeckoDriver.prototype.getCookies,  // deprecated
   "deleteAllCookies": GeckoDriver.prototype.deleteAllCookies,
   "deleteCookie": GeckoDriver.prototype.deleteCookie,
   "getActiveElement": GeckoDriver.prototype.getActiveElement,
   "getScreenOrientation": GeckoDriver.prototype.getScreenOrientation,
   "setScreenOrientation": GeckoDriver.prototype.setScreenOrientation,
   "getWindowSize": GeckoDriver.prototype.getWindowSize,
   "setWindowSize": GeckoDriver.prototype.setWindowSize,
   "maximizeWindow": GeckoDriver.prototype.maximizeWindow,
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_debug.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_debug.py
@@ -11,16 +11,17 @@ config = {
     # - taskcluster_firefox_win32_opt
     # - taskcluster_firefox_win64_debug
     # - taskcluster_firefox_win64_opt
 
     'default_actions': [
         'clone-tools',
         'build',
         'check-test',
+        'generate-build-stats'
     ],
     'exes': {
         'python2.7': sys.executable,
         'make': [
             sys.executable,
             os.path.join(
                 os.getcwd(), 'build', 'src', 'build', 'pymake', 'make.py'
             )
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_opt.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_opt.py
@@ -11,16 +11,17 @@ config = {
     # - taskcluster_firefox_win32_opt
     # - taskcluster_firefox_win64_debug
     # - taskcluster_firefox_win64_opt
 
     'default_actions': [
         'clone-tools',
         'build',
         'check-test',
+        'generate-build-stats'
     ],
     'exes': {
         'python2.7': sys.executable,
         'make': [
             sys.executable,
             os.path.join(
                 os.getcwd(), 'build', 'src', 'build', 'pymake', 'make.py'
             )
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_debug.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_debug.py
@@ -11,16 +11,17 @@ config = {
     # - taskcluster_firefox_win32_opt
     # - taskcluster_firefox_win64_debug
     # - taskcluster_firefox_win64_opt
 
     'default_actions': [
         'clone-tools',
         'build',
         'check-test',
+        'generate-build-stats'
     ],
     'exes': {
         'python2.7': sys.executable,
         'make': [
             sys.executable,
             os.path.join(
                 os.getcwd(), 'build', 'src', 'build', 'pymake', 'make.py'
             )
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_opt.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_opt.py
@@ -11,16 +11,17 @@ config = {
     # - taskcluster_firefox_win32_opt
     # - taskcluster_firefox_win64_debug
     # - taskcluster_firefox_win64_opt
 
     'default_actions': [
         'clone-tools',
         'build',
         'check-test',
+        'generate-build-stats'
     ],
     'exes': {
         'python2.7': sys.executable,
         'make': [
             sys.executable,
             os.path.join(
                 os.getcwd(), 'build', 'src', 'build', 'pymake', 'make.py'
             )
--- a/testing/mozharness/mozharness/mozilla/building/buildbase.py
+++ b/testing/mozharness/mozharness/mozilla/building/buildbase.py
@@ -1883,16 +1883,22 @@ or run without that action (ie: --no-{ac
                 continue
             data['subtests'].append({
                 'name': phase['name'],
                 'value': phase['duration'],
             })
 
         return data
 
+    def get_firefox_version(self):
+        versionFilePath = os.path.join(
+            self.query_abs_dirs()['abs_src_dir'], 'browser/config/version.txt')
+        with open(versionFilePath, 'r') as versionFile:
+            return versionFile.readline().strip()
+
     def generate_build_stats(self):
         """grab build stats following a compile.
 
         This action handles all statistics from a build: 'count_ctors'
         and then posts to graph server the results.
         We only post to graph server for non nightly build
         """
         if self.config.get('forced_artifact_build'):
@@ -1913,22 +1919,30 @@ or run without that action (ie: --no-{ac
 
         dirs = self.query_abs_dirs()
         packageName = self.query_buildbot_property('packageFilename')
 
         # if packageName is not set because we are not running in Buildbot,
         # then assume we are using MOZ_SIMPLE_PACKAGE_NAME, which means the
         # package is named one of target.{tar.bz2,zip,dmg}.
         if not packageName:
+            firefox_version = self.get_firefox_version()
             dist_dir = os.path.join(dirs['abs_obj_dir'], 'dist')
             for ext in ['apk', 'dmg', 'tar.bz2', 'zip']:
                 name = 'target.' + ext
                 if os.path.exists(os.path.join(dist_dir, name)):
                     packageName = name
                     break
+                # if we are not using MOZ_SIMPLE_PACKAGE_NAME, check for the
+                # default package naming convention
+                name = 'firefox-{}.en-US.{}.{}'.format(
+                    firefox_version, c.get('platform'), ext)
+                if os.path.exists(os.path.join(dist_dir, name)):
+                    packageName = name
+                    break
             else:
                 self.fatal("could not determine packageName")
 
         interests = ['libxul.so', 'classes.dex', 'omni.ja']
         installer = os.path.join(dirs['abs_obj_dir'], 'dist', packageName)
         installer_size = 0
         size_measurements = []
 
--- a/toolkit/components/extensions/ExtensionStorage.jsm
+++ b/toolkit/components/extensions/ExtensionStorage.jsm
@@ -13,17 +13,30 @@ const Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
                                   "resource://gre/modules/osfile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown",
                                   "resource://gre/modules/AsyncShutdown.jsm");
 
-function jsonReplacer(key, value) {
+/**
+ * Helper function used to sanitize the objects that have to be saved in the ExtensionStorage.
+ *
+ * @param {BaseContext} context
+ *   The current extension context.
+ * @param {string} key
+ *   The key of the current JSON property.
+ * @param {any} value
+ *   The value of the current JSON property.
+ *
+ * @returns {any}
+ *   The sanitized value of the property.
+ */
+function jsonReplacer(context, key, value) {
   switch (typeof(value)) {
     // Serialize primitive types as-is.
     case "string":
     case "number":
     case "boolean":
       return value;
 
     case "object":
@@ -44,17 +57,17 @@ function jsonReplacer(key, value) {
           return String(value);
       }
       break;
   }
 
   if (!key) {
     // If this is the root object, and we can't serialize it, serialize
     // the value to an empty object.
-    return {};
+    return new context.cloneScope.Object();
   }
 
   // Everything else, omit entirely.
   return undefined;
 }
 
 this.ExtensionStorage = {
   cache: new Map(),
@@ -67,17 +80,17 @@ this.ExtensionStorage = {
    * @param {value} value
    *        The value to sanitize.
    * @param {Context} context
    *        The extension context in which to sanitize the value
    * @returns {value}
    *        The sanitized value.
    */
   sanitize(value, context) {
-    let json = context.jsonStringify(value, jsonReplacer);
+    let json = context.jsonStringify(value, jsonReplacer.bind(null, context));
     return JSON.parse(json);
   },
 
   getExtensionDir(extensionId) {
     return OS.Path.join(this.extensionDir, extensionId);
   },
 
   getStorageFile(extensionId) {