chromium/third_party/blink/web_tests/fast/ruby/merge-base-anonymous-blocks-crash.html

<!DOCTYPE html>
<ruby>
  <div></div>
  <span id="firstInline"></span>
  <rt id="rubyText" style="display:none;"></rt>
  <span id="secondInline"></span>
  <div id="removeMe"></div>
  <div id="absPos" style="position:absolute;"></div>
  <span id="addMe" style="display:none;"></span>
</ruby>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script>
    // The comments describe what happens with crbug.com/852640 present.
    test(() => {
	// Perform 4 style changes. Relayout before and between each
	// change.
	document.body.offsetTop;
	// Remove a regular block. Its previous and next siblings are an inline
	// and an absolutely positioned object, respectively. They should be
	// placed together, i.e. the absolutely positioned object should be put
	// under the anonymous block around the inline. That's what would have
	// happened if the style were like this during initial layout. Getting
	// to the same style situation via DOM changes should result in the
	// exact same tree. With the bug present, we just leave the absolutely
	// positioned box alone, and keep it as a *sibling* (instead of making
	// it a child, which would have been the correct thing) of the
	// anonoymous wrapper around #firstInline and #secondInline.
	document.getElementById("removeMe").style.display = "none";
	document.body.offsetTop;
	// Add an inline after the absolutely positioned box. It finds no
	// adjacent anonymous wrapper block (there's just #absPos, and it's not
	// inside a wrapper), so it creates one, and puts itself and #absPos
	// inside it. Now we have two sibling anonymous wrapper blocks (one with
	// #firstInline and #secondInline, and one with #absPos and #addMe),
	// which is weird.
	document.getElementById("addMe").style.display = "inline";
	document.body.offsetTop;
	// Insert an RT object between #firstInline and #secondInline. This will
	// split the ruby column and the ruby base in two; one run and base that
	// ends with #firstChild, and one run and base that starts with
	// #secondChild. We now have a first ruby base that ends with an
	// anonymous block (to contain #firstInline), and a second ruby base
	// that starts with an anonymous block (to contain #secondInline). This
	// is fine.
	document.getElementById("rubyText").style.display = "block";
	document.body.offsetTop;
	// Remove the RT object again. This will cause the two ruby columns and
	// bases to be merged back into one. There is code that carefully makes
	// sure that the anonymous block at the end of the first base is merged
	// with the anonymous block at the start of the next base. This is the
	// right thing to do, since we want the two inlines back on one and the
	// same line. However, this will cause the first anonymous block in the
	// second base to be destroyed (because its contents,
	// i.e. #secondInline, is moved over to the anonymous block around
	// #firstInline). This in turn will leave the second base with one
	// anonymous block (around #absPos and #addMe). Our tree modification
	// machinery will detect this and unwrap #absPos and #addMe from their
	// anonymous block and destroy it. The second base will now be marked as
	// "children inline", while the first base is still marked as having
	// block children. This could be fine, but if we now just move the
	// children of the second base directly into the first base, we're going
	// to end up with a mix of block and inline children within the same
	// block, and that's not allowed.
	document.getElementById("rubyText").style.display = "none";
    }, "No crash or CHECK/DCHECK failure.");
</script>