Removing Slotted Content Crashes Safari

It seems that removing slotted content *after* removing the slot is tripping Safari.

by David Iglesias

HTML

<div id="container">
  <div id="slotted" slot="something">Some content (DOM)</div>
</div>

CSS

html, body {
  width: 100%;
  height: 100%;
  margin: 0px;
  padding: 0px;
}

body {
  background: red;
}

#container {
  width: 100%;
  height: 100%;
  background: yellow;
}

JavaScript

const slotName = 'something';
const timeoutMs = 1000;

// Attach shadow DOM on #container...
const container = document.querySelector('#container');
const shadow = container.attachShadow({
  mode: 'open',
});

// A named slot for the shadow DOM
const slot = document.createElement('slot');
slot.setAttribute('name', slotName);

const tombstoneSlotName = 'tombstone';
// tombstone.setAttribute('name', tombstoneSlotName);

// Populate the contents of the shadow DOM of #container.
window.setTimeout(() => {
  // Put slot into a green div...
  const bg = document.createElement('div');
  bg.style.backgroundColor = 'green';
  bg.style.width = '100%';
  bg.style.height = '100%';

  bg.appendChild(slot);
  shadow.appendChild(bg);
}, timeoutMs);


// Removing this element *after* removing the slot, will trigger the issue.
const slotted = document.querySelector('#slotted');

// (You can also dynamically add the content, it doesn't seem to matter)
/*
let slotted = document.createElement('div');
slotted.innerText = 'Some content...';
slotted.setAttribute('slot', slotName);

container.appendChild(slotted);
*/

// This needs to happen first. Then...
window.setTimeout(() => {
  slot.remove();
}, 2 * timeoutMs);

// This will make the whole #container lose layout/disappear. WAT?
window.setTimeout(() => {
  const tombstone = document.createElement('slot');
  shadow.appendChild(tombstone);

  slotted.setAttribute('name', tombstoneSlotName);
  slotted.remove();
  tombstone.remove();
}, 3 * timeoutMs);

// If slot.remove and slotted.remove happen in the same timeout, the issue doesn't happen, regardless of their order
// If slotted.remove happens *before* slot.remove, the issue doesn't happen.