Merge mozilla-central to inbound. a=merge CLOSED TREE
authorGurzau Raul <rgurzau@mozilla.com>
Wed, 12 Sep 2018 14:43:11 +0300
changeset 436018 4d11dee9526f53ef993c2db34e03bf39f15943f0
parent 436017 066a6fb65070c913c5064ccc473cae79f27d26a6 (current diff)
parent 435859 00d89103ec836b251bfd00a3ff3d1df51d13ed59 (diff)
child 436019 bfed465371545545c4e1a79f351ddd60c92733c2
push id34625
push userdvarga@mozilla.com
push dateThu, 13 Sep 2018 02:31:40 +0000
treeherdermozilla-central@51e9e9660b3e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to inbound. a=merge CLOSED TREE
--- a/devtools/server/actors/inspector/walker.js
+++ b/devtools/server/actors/inspector/walker.js
@@ -516,20 +516,28 @@ var WalkerActor = protocol.ActorClassWit
       ? this.getNonAnonymousWalker(node.rawNode)
       : this.getDocumentWalker(node.rawNode);
     const firstChild = walker.firstChild();
 
     // Bail out if:
     // - more than one child
     // - unique child is not a text node
     // - unique child is a text node, but is too long to be inlined
+    // - we are a slot -> these are always represented on their own lines with
+    //                    a link to the original node.
+    const isAssignedSlot =
+      !!firstChild &&
+      node.rawNode.nodeName === "SLOT" &&
+      isDirectShadowHostChild(firstChild);
+
     if (!firstChild ||
         walker.nextSibling() ||
         firstChild.nodeType !== Node.TEXT_NODE ||
-        firstChild.nodeValue.length > gValueSummaryLength
+        firstChild.nodeValue.length > gValueSummaryLength ||
+        isAssignedSlot
         ) {
       return undefined;
     }
 
     return this._ref(firstChild);
   },
 
   /**
--- a/devtools/server/tests/browser/browser_inspector-shadow.js
+++ b/devtools/server/tests/browser/browser_inspector-shadow.js
@@ -110,8 +110,30 @@ add_task(async function() {
   const closedEl = await walker.querySelector(walker.rootNode, "#mode-closed");
   const closedShadowRoot = (await walker.children(closedEl)).nodes[0];
 
   is(openShadowRoot.shadowRootMode, "open",
     "#mode-open has a shadow root with open mode");
   is(closedShadowRoot.shadowRootMode, "closed",
     "#mode-closed has a shadow root with closed mode");
 });
+
+add_task(async function() {
+  info("Test that slotted inline text nodes appear in the Shadow DOM tree");
+  const { walker } = await initInspectorFront(URL);
+
+  const el = await walker.querySelector(walker.rootNode, "#slot-inline-text");
+  const hostChildren = await walker.children(el);
+  const originalSlot = hostChildren.nodes[1];
+  is(originalSlot.displayName, "#text", "Shadow host as a text node to be slotted");
+
+  const shadowRoot = hostChildren.nodes[0];
+  const shadowChildren = await walker.children(shadowRoot);
+  const slot = shadowChildren.nodes[0];
+  is(slot.displayName, "slot", "shadow-root has a slot child");
+  ok(!slot._form.inlineTextChild, "Slotted node is not an inline text");
+
+  const slotChildren = await walker.children(slot);
+  const slotted = slotChildren.nodes[0];
+  is(slotted.displayName, "#text", "Slotted node is a text node");
+  is(slotted._form.nodeValue, originalSlot._form.nodeValue,
+    "Slotted content is the same as original's");
+});
--- a/devtools/server/tests/browser/inspector-shadow.html
+++ b/devtools/server/tests/browser/inspector-shadow.html
@@ -48,16 +48,24 @@
         this.shadowRoot.innerHTML = `
         <style>
           slot::before { content: "[SLOT BEFORE]"; color: red; }
           slot::after { content: "[SLOT AFTER]"; color: blue; }
         </style>
         <slot></slot>`;
       }
     });
+
+    customElements.define("test-simple-slot", class extends HTMLElement {
+      constructor() {
+        super();
+        this.attachShadow({ mode: "open"});
+        this.shadowRoot.innerHTML = "<slot></slot>";
+      }
+    });
   };
   </script>
   <style>
     #host-pseudo::before { content: "[HOST BEFORE]"; color: red; }
     #host-pseudo::after { content: "[HOST AFTER]"; color: blue; }
   </style>
 </head>
 <body>
@@ -88,10 +96,16 @@
   <hr>
 
   <test-empty id="host-pseudo"></test-empty>
 
   <hr>
 
   <test-empty id="mode-open"></test-empty>
   <test-empty-closed id="mode-closed"></test-empty-closed>
+
+  <hr>
+
+  <test-simple-slot id="slot-inline-text">
+    Lorem ipsum
+  </test-simple-slot>
 </body>
 </html>
--- a/gfx/webrender_bindings/Moz2DImageRenderer.cpp
+++ b/gfx/webrender_bindings/Moz2DImageRenderer.cpp
@@ -405,22 +405,24 @@ static bool Moz2DRenderCallback(const Ra
       layers::BlobFont ret;
       memcpy(&ret, buf + pos, sizeof(ret));
       pos += sizeof(ret);
       return ret;
     }
 
   };
 
-  MOZ_RELEASE_ASSERT(aBlob.length() > sizeof(size_t));
+  // We try hard to not have empty blobs but we can end up with
+  // them because of CompositorHitTestInfo and merging.
+  MOZ_RELEASE_ASSERT(aBlob.length() >= sizeof(size_t));
   size_t indexOffset = *(size_t*)(aBlob.end().get()-sizeof(size_t));
   MOZ_RELEASE_ASSERT(indexOffset + sizeof(size_t) <= aBlob.length());
   Reader reader(aBlob.begin().get()+indexOffset, aBlob.length()-sizeof(size_t)-indexOffset);
 
-  bool ret;
+  bool ret = true;
   size_t offset = 0;
   auto absBounds = IntRectAbsolute::FromRect(bounds);
   while (reader.pos < reader.len) {
     size_t end = reader.ReadSize();
     size_t extra_end = reader.ReadSize();
     auto combinedBounds = absBounds.Intersect(reader.ReadBounds());
     if (combinedBounds.IsEmpty()) {
       offset = extra_end;
--- a/intl/l10n/DocumentL10n.cpp
+++ b/intl/l10n/DocumentL10n.cpp
@@ -60,16 +60,22 @@ DocumentL10n::Init(nsTArray<nsString>& a
   mDOMLocalization = domL10n;
 
   // The `aEager = true` here allows us to eagerly trigger
   // resource fetching to increase the chance that the l10n
   // resources will be ready by the time the document
   // is ready for localization.
   uint32_t ret;
   mDOMLocalization->AddResourceIds(aResourceIds, true, &ret);
+
+  // Register observers for this instance of
+  // mozDOMLocalization to allow it to retranslate
+  // the document when locale changes or pseudolocalization
+  // gets turned on.
+  mDOMLocalization->RegisterObservers();
   return true;
 }
 
 JSObject*
 DocumentL10n::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return DocumentL10n_Binding::Wrap(aCx, this, aGivenProto);
 }
--- a/intl/l10n/mozIDOMLocalization.idl
+++ b/intl/l10n/mozIDOMLocalization.idl
@@ -9,16 +9,17 @@ webidl Document;
 webidl Element;
 webidl Node;
 
 [scriptable, uuid(7c468500-541f-4fe0-98c9-92a53b63ec8d)]
 interface mozIDOMLocalization : nsISupports
 {
   unsigned long addResourceIds(in Array<AString> resourceIds, in bool aEager);
   unsigned long removeResourceIds(in Array<AString> resourceIds);
+  void registerObservers();
 
   Promise formatMessages(in Array<jsval> aKeys);
   Promise formatValues(in Array<jsval> aKeys);
   Promise formatValue(in DOMString aId, [optional] in jsval aArgs);
 
   Promise translateFragment(in Node aNode);
   Promise translateElements(in Array<Element> aElements);
 
--- a/intl/l10n/test/test_mozdomlocalization.js
+++ b/intl/l10n/test/test_mozdomlocalization.js
@@ -22,16 +22,17 @@ L10nRegistry.load = async function(url) 
 };
 
 const source = new FileSource("test", ["en-US"], "/localization/{locale}");
 L10nRegistry.registerSource(source);
 
 add_task(function test_methods_presence() {
   equal(typeof domLocalization.addResourceIds, "function");
   equal(typeof domLocalization.removeResourceIds, "function");
+  equal(typeof domLocalization.registerObservers, "function");
 
   equal(typeof domLocalization.formatMessages, "function");
   equal(typeof domLocalization.formatValues, "function");
   equal(typeof domLocalization.formatValue, "function");
 
   equal(typeof domLocalization.translateFragment, "function");
   equal(typeof domLocalization.translateElements, "function");
 
--- a/layout/svg/crashtests/crashtests.list
+++ b/layout/svg/crashtests/crashtests.list
@@ -207,11 +207,12 @@ load 1402486.html
 load 1421807-1.html
 pref(dom.webcomponents.shadowdom.enabled,true) load 1421807-2.html
 load 1422226.html
 load 1443092.html
 load 1467552-1.html
 load conditional-outer-svg-nondirty-reflow-assert.xhtml
 load extref-test-1.xhtml
 load blob-merging-and-retained-display-list.html
+load empty-blob-merging.html
 load grouping-empty-bounds.html
 load 1480275.html
 load 1480224.html
new file mode 100644
--- /dev/null
+++ b/layout/svg/crashtests/empty-blob-merging.html
@@ -0,0 +1,48 @@
+<html class="reftest-wait">
+<style>
+@keyframes spinnow {
+    100% {
+        transform: rotate(360deg) scale(.2, .2);
+    }
+}
+
+rect {
+    transform: rotate(0deg) scale(0.6, 1);
+    transform-origin: center;
+    animation: 5s spinnow infinite linear;
+}
+
+</style>
+<svg width=400 height=400>
+        <!--
+          onwheel is needed so that we get a hit test info display item
+          before the transform on the rect
+        -->
+	<g onwheel="alert(1)">
+	<g id="gr">
+	<circle r=30 fill=yellow cx=300 cy=100 />
+	<circle r=30 fill=yellow cx=10 cy=100 />
+	<circle r=30 fill=yellow cx=300 cy=300 />
+	<circle r=30 fill=yellow cx=10 cy=300 />
+	</g>
+	<rect width=100 height=100 fill=blue x=100 y=100 />
+	<g opacity=0.5>
+	<circle r=30 fill=pink cx=300 cy=100 />
+	<circle r=30 fill=pink cx=10 cy=100 />
+	<circle r=30 fill=pink cx=300 cy=300 />
+	<circle r=30 fill=pink cx=10 cy=300 />
+	</g>
+	</g>
+</svg>
+<script>
+  function blam() {
+    let gr = document.getElementById("gr");
+    gr.remove();
+    document.documentElement.removeAttribute("class");
+  }
+document.addEventListener("MozReftestInvalidate", function() {
+  requestAnimationFrame(function() {
+    blam();
+  });
+});
+</script>
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -1379,23 +1379,23 @@ ChildFPEFilter(void* context, EXCEPTION_
     PrepareChildExceptionTimeAnnotations(context);
   }
   return result;
 }
 
 static MINIDUMP_TYPE
 GetMinidumpType()
 {
-  MINIDUMP_TYPE minidump_type = MiniDumpWithFullMemoryInfo;
+  MINIDUMP_TYPE minidump_type = static_cast<MINIDUMP_TYPE>(
+      MiniDumpWithFullMemoryInfo | MiniDumpWithUnloadedModules);
 
 #ifdef NIGHTLY_BUILD
   // This is Nightly only because this doubles the size of minidumps based
   // on the experimental data.
   minidump_type = static_cast<MINIDUMP_TYPE>(minidump_type |
-      MiniDumpWithUnloadedModules |
       MiniDumpWithProcessThreadData);
 
   // dbghelp.dll on Win7 can't handle overlapping memory regions so we only
   // enable this feature on Win8 or later.
   if (IsWin8OrLater()) {
     minidump_type = static_cast<MINIDUMP_TYPE>(minidump_type |
       // This allows us to examine heap objects referenced from stack objects
       // at the cost of further doubling the size of minidumps.