mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-26 09:45:06 +02:00
When a text node changes inside an absolutely positioned element within an SVG <foreignObject>, and the abspos element's containing block is outside the SVG subtree, the layout invalidation was incorrectly stopping at the SVG root boundary. This triggered partial SVG relayout, which cannot re-layout the abspos element since it's laid out by its containing block's formatting context (outside the SVG). The previous check only tested whether `this` (the node triggering invalidation, e.g. a text node) was absolutely positioned, missing the case where an abspos *ancestor* in the path has its containing block outside the SVG. Fix this by walking from `this` up to the SVG root and checking every abspos node in the path. If any has a containing block outside the SVG subtree, skip the SVG boundary so layout propagation continues upward and a full layout runs.
47 lines
1.4 KiB
HTML
47 lines
1.4 KiB
HTML
<!DOCTYPE html>
|
|
<script src="../include.js"></script>
|
|
<style>
|
|
html, body { margin: 0; }
|
|
.container {
|
|
position: relative;
|
|
width: 300px;
|
|
height: 200px;
|
|
}
|
|
.abspos {
|
|
position: absolute;
|
|
left: 10px;
|
|
top: 10px;
|
|
white-space: nowrap;
|
|
background: #8f8;
|
|
}
|
|
</style>
|
|
<div class="container">
|
|
<svg width="100" height="100">
|
|
<foreignObject width="100" height="100">
|
|
<div class="abspos" id="abspos"><span id="text">short</span></div>
|
|
</foreignObject>
|
|
</svg>
|
|
</div>
|
|
<script>
|
|
asyncTest(done => {
|
|
const abspos = document.getElementById("abspos");
|
|
const text = document.getElementById("text");
|
|
|
|
document.body.offsetWidth;
|
|
const before = abspos.getBoundingClientRect();
|
|
|
|
// This mutates a text node inside an abspos element whose containing
|
|
// block is outside the SVG subtree.
|
|
text.firstChild.data = "this is a much much longer text inside abspos";
|
|
|
|
requestAnimationFrame(() => {
|
|
requestAnimationFrame(() => {
|
|
const after = abspos.getBoundingClientRect();
|
|
println(`width-grew=${after.width > before.width}`);
|
|
println(`position-stable=${after.x === before.x && after.y === before.y}`);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
</script>
|