chromium/third_party/blink/web_tests/fast/dom/HTMLImageElement/fallback-image-moved-across-documents.html

<!DOCTYPE html>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<body>
<iframe src="about:blank" id="nested"></iframe>
<script type="text/javascript">
// Fallback content is implemented by means of shadow DOM, using a dumbed-down
// HTMLImageElement instance inside to render the broken image icon. This inner
// image element displays a hard-coded ImageResource, and has no 'src' attribute
// so normally the `update image data` [1] algorithm is never invoked.
//
// However the `update image data` algorithm will be unconditionally invoked in
// response to an image element (inner or not) being adopted [2], e.g. when a
// subtree containing an image element (potentially in a shadow tree) is moved
// across documents.
//
// In Blink, when 'src' is empty, as is the case for the inner fallback image,
// the `update image data` algorithm will synchronously fail and create the
// shadow tree to render fallback content.
//
// Therefore special care must be taken to prevent creating the shadow tree
// for the inner fallback image itself, otherwise the recursive adoption
// algorithm would reach those nodes in the newly created shadow tree next, and
// the same thing would happen again and we end up with infinite nesting.
//
// [1]: https://html.spec.whatwg.org/multipage/embedded-content.html#update-the-image-data
// [2]: https://html.spec.whatwg.org/multipage/embedded-content.html#reacting-to-dom-mutations

var nestedDocument = document.getElementById("nested").contentDocument;

promise_test(t => {
  let i = nestedDocument.createElement("img");
  i.src = "non-existent/gives-404.png";
  window.setTimeout(_ => nestedDocument.body.append(i));

  let eventWatcher = new EventWatcher(t, i, [ "load", "error" ]);
  return eventWatcher.wait_for("error").then(_ => {
    window.setTimeout(_ => document.body.append(i));
    return eventWatcher.wait_for("error").then(_ => {
      assert_equals(i.clientWidth, 0, "Fallback content will not be displayed, fallback content is treated as display:none.");
    });
  });
}, "Infinitely nested fallback content shadow trees should not be created, or this test will never terminate.");

</script>