Closed Bug 1752694 Opened 2 years ago Closed 2 years ago

slot fallback node remains visible

Categories

(Core :: DOM: Core & HTML, defect)

Firefox 96
defect

Tracking

()

RESOLVED FIXED
98 Branch
Tracking Status
firefox98 --- fixed

People

(Reporter: orstavik77, Assigned: emilio)

References

(Blocks 1 open bug)

Details

Attachments

(3 files, 1 obsolete file)

User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0

Steps to reproduce:

<my-details-frame>
  <span summary>one</span>
  <div>sunshine</div>
</my-details-frame>

<script>

  const myDetailsHTML = `
<style>
  slot#content{display: none;}
  b {display: inline-block;}
  :host([open]) slot#content{display: block;}
  :host([open]) b {transform: rotate(90deg);}
</style>
<span><b>&#x25BA;</b><slot id="summary" summary>***hubba**</slot></span>
<slot id="content">!!!bubba!!!</slot>`;

  class MyDetails extends HTMLElement {
    constructor() {
      super();
      console.log(this.tagName, "constructor");
      this.attachShadow({mode: 'open', slotAssignment: "manual"});
      this.shadowRoot.innerHTML = myDetailsHTML;
      this.shadowRoot.querySelector('span').addEventListener('click', e =>
        this.hasAttribute('open') ? this.removeAttribute('open') : this.setAttribute('open', ''));
      setTimeout(()=>this.childChangedCallback());
    }

    childChangedCallback() {
      let slottables = [...this.childNodes];
      slottables = slottables.filter(n => !(n instanceof Comment)); //annoying, Comments should be slottable.
      const summaryPosition = slottables.findIndex(n => n.hasAttribute && n.hasAttribute("summary"));
      let summary;
      if (summaryPosition >= 0)
        summary = slottables.splice(summaryPosition, 1)[0];
      this.shadowRoot.getElementById("summary").assign(summary);
      this.shadowRoot.getElementById("content").assign(...slottables);
    }
  }

  class MyDetailsFrame extends HTMLElement {
    constructor() {
      super();
      this.attachShadow({mode: 'open', slotAssignment: 'manual'});
      this.shadowRoot.innerHTML = `
<!--      <my-details open style="border: 2px solid green; display: block;">-->
      <my-details style="border: 2px solid green; display: block;">
        <slot summary id="summary">***hubba**</slot>
        <slot id="content">!!!bubba!!!</slot>
      </my-details>
`;
      setTimeout(()=>this.childChangedCallback());
    }

    childChangedCallback() {
      let slottables = [...this.childNodes];
      slottables = slottables.filter(n => !(n instanceof Comment)); //annoying, Comments should be slottable.
      const summaryPosition = slottables.findIndex(n => n.hasAttribute && n.hasAttribute("summary"));
      let summary;
      if (summaryPosition >= 0)
        summary = slottables.splice(summaryPosition, 1)[0];
      this.shadowRoot.getElementById("summary").assign(summary);
      this.shadowRoot.getElementById("content").assign(...slottables);
    }
  }

  customElements.define("my-details", MyDetails);
  customElements.define("my-details-frame", MyDetailsFrame);
</script>

<script>
  setTimeout(function () {
    const frame_details = document.querySelector("my-details-frame");
    const inner_details = frame_details.shadowRoot.children[0];
    frame_details.insertAdjacentHTML('afterbegin', '<div>hello</div><span summary>two</span>');

    Promise.resolve().then(()=>{
      frame_details.childChangedCallback();
      inner_details.childChangedCallback();
    });
  }, 500);
</script>

Actual results:

The view shows 'twoone' after 500ms.

Expected results:

The view should show 'one' for 0-500ms, and then only 'two' after 500ms.

But. When you click on the summary which reveals the new visible/slotted position of 'one', then 'one' is removed from the summary slot (as it should have been earlier on). It looks like the underlying view isn't alerted that the 'one' element that was previously slotted under <slot summary> is now removed, when that elements new position is display none somewhere else.

The Bugbug bot thinks this bug should belong to the 'Core::DOM: Core & HTML' component, and is moving the bug to that component. Please revert this change in case you think the bot is wrong.

Component: Untriaged → DOM: Core & HTML
Product: Firefox → Core

FWIW, I got the result ***hubba**two on Chrome.

Blocks: shadowdom

Seems like an issue with manual slotting. Sean perhaps you can take a look?

Flags: needinfo?(sefeng)
Attached file Reduced test-case. (obsolete) —
Attachment #9261912 - Attachment is obsolete: true

Ah, found it...

Assignee: nobody → emilio
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true
Flags: needinfo?(sefeng)
Flags: needinfo?(emilio)
Flags: needinfo?(emilio)

Otherwise we won't clear frames / style data from the assigned nodes.
I'm surprised there's no existing test catching this.

Pushed by ealvarez@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/4b4089d4c9d8
Invalidate layout before moving out of mAssignedNodes. r=sefeng
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/32687 for changes under testing/web-platform/tests
Status: ASSIGNED → RESOLVED
Closed: 2 years ago
Resolution: --- → FIXED
Target Milestone: --- → 98 Branch
Upstream PR merged by moz-wptsync-bot
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: