chromium/third_party/blink/web_tests/http/tests/intersection-observer/resources/cross-origin-display-none-subframe.html

<!DOCTYPE html>
<div id="target">target</div>
<script>
var delay = 100;
var results = [];

function waitForNotification(f, data) {
  // Note about data.raf: when a cross-origin iframe is hidden, it stops running
  // lifecycle updates, so using rAF to wait for notifications doesn't work.
  // Instead, just wait for as long as the 'delay' parameter. The
  // IntersectionObserver implementation should be aware that lifecycle udpates
  // have been stopped, and it should still generate the proper notifications.
  if (data.raf) {
    setTimeout(() => {
      requestAnimationFrame(function () {
        requestAnimationFrame(function () {
          setTimeout(f)
        })
      })
    }, delay)
  } else {
    setTimeout(() => {
      setTimeout(f);
    }, delay)
  }
}

window.addEventListener("message", event => {
  waitForNotification(() => {
    window.parent.postMessage(results.map(e => e.isVisible), "*");
    results = [];
  }, event.data);
});

onload = () => {
  var target = document.getElementById("target");
  var observer = new IntersectionObserver(entries => {
    results = entries;
  }, {trackVisibility: true, delay: delay});
  observer.observe(document.getElementById("target"));
  window.parent.postMessage("", "*");
};
</script>