Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE HTML>
<html>
<!--
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1131371</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<style>
#elemWithScrollbars { overflow: scroll }
.flexScrollerWithTransformedItems {
display: flex;
overflow: hidden;
width: 200px;
position: relative;
}
.flexScrollerWithTransformedItems div {
min-width: 50px;
min-height: 50px;
margin: 10px;
will-change: transform;
}
.absposFlexItem {
left: 250px;
top: 0;
position: absolute;
}
#tableCell,
#tableCellWithAbsPosChild {
display: table-cell;
}
.blockmargin {
margin: 25px 0;
}
</style>
<div id="display">
<div id="content">
</div>
<div id="elemWithAbsPosChild"><div style="position:absolute"></div></div>
<div id="elemWithFixedPosChild"><div style="position:fixed"></div></div>
<div id="elemWithScrollbars"></div>
<div id="elemWithoutScrollbars"></div>
<div class="flexScrollerWithTransformedItems">
<div></div>
<div></div>
<div></div>
<div></div>
<div id="flexItemMovementTarget"></div>
</div>
<div class="flexScrollerWithTransformedItems">
<div></div>
<div></div>
<div></div>
<div id="flexItemMovementTarget2"></div>
<div class="absposFlexItem"></div>
</div>
<input id="inputElem" type="image">
<textarea id="textareaElem">
Some
lines
of
text
</textarea>
<select id="selectElem">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<button id="buttonElem">
Something
</button>
<button id="buttonElemWithAbsPosChild"><div style="position:absolute"></div></button>
<div id="tableCell"></div>
<div id="tableCellWithAbsPosChild">
<div style="position: absolute"></div>
</div>
<div id="containNode">
<div></div>
</div>
<div id="containNodeWithAbsPosChild">
<div style="position: absolute"></div>
</div>
<div id="containNodeWithFixedPosChild">
<div style="position: fixed"></div>
</div>
<div id="containNodeWithFloatingChild">
<div style="float: left"></div>
</div>
<div id="containNodeWithMarginCollapsing" class="blockmargin">
<div class="blockmargin"></div>
</div>
<div id="contentVisibilityNode">
<div></div>
</div>
</div>
<pre id="test">
<script>
"use strict";
/** Test for Bug 1131371 **/
const elemWithAbsPosChild = document.getElementById("elemWithAbsPosChild");
const elemWithFixedPosChild = document.getElementById("elemWithFixedPosChild");
const elemWithScrollbars = document.getElementById("elemWithScrollbars");
const elemWithoutScrollbars = document.getElementById("elemWithoutScrollbars");
const inputElem = document.getElementById("inputElem");
const textareaElem = document.getElementById("textareaElem");
const selectElem = document.getElementById("selectElem");
const buttonElem = document.getElementById("buttonElem");
const buttonElemWithAbsPosChild = document.getElementById("buttonElemWithAbsPosChild");
const tableCell = document.getElementById("tableCell");
const tableCellWithAbsPosChild = document.getElementById("tableCellWithAbsPosChild");
for (let scroller of document.querySelectorAll(".flexScrollerWithTransformedItems")) {
scroller.scrollLeft = 10000;
}
const flexItemMovementTarget = document.getElementById("flexItemMovementTarget");
const flexItemMovementTarget2 = document.getElementById("flexItemMovementTarget2");
/**
* This test verifies that certain style changes do or don't cause reflow
* and/or frame construction. We do this by checking the framesReflowed &
* framesConstructed counts, before & after a style-change, and verifying
* that any change to these counts is in line with our expectations.
*
* Each entry in gTestcases contains these member-values:
* - beforeStyle (optional): initial value to use for "style" attribute.
* - afterStyle: value to change the "style" attribute to.
*
* Testcases may also include two optional member-values to express that reflow
* and/or frame construction *are* in fact expected:
* - expectConstruction (optional): if set to something truthy, then we expect
* frame construction to occur when afterStyle is set. Otherwise, we
* expect that frame construction should *not* occur.
* - expectReflow (optional): if set to something truthy, then we expect
* reflow to occur when afterStyle is set. Otherwise, we expect that
* reflow should *not* occur.
*/
const gTestcases = [
// Things that shouldn't cause reflow:
// -----------------------------------
// * Adding an outline (e.g. for focus ring).
{
afterStyle: "outline: 1px dotted black",
},
// * Changing between completely different outlines.
{
beforeStyle: "outline: 2px solid black",
afterStyle: "outline: 6px dashed yellow",
},
// * Adding a box-shadow.
{
afterStyle: "box-shadow: inset 3px 3px gray",
},
{
afterStyle: "box-shadow: 0px 0px 10px 30px blue"
},
// * Changing between completely different box-shadow values,
// e.g. from an upper-left shadow to a bottom-right shadow:
{
beforeStyle: "box-shadow: -15px -20px teal",
afterStyle: "box-shadow: 30px 40px yellow",
},
// * Adding a text-shadow.
{
afterStyle: "text-shadow: 3px 3px gray",
},
{
afterStyle: "text-shadow: 0px 0px 10px blue"
},
// * Changing between completely different text-shadow values,
// e.g. from an upper-left shadow to a bottom-right shadow:
{
beforeStyle: "text-shadow: -15px -20px teal",
afterStyle: "text-shadow: 30px 40px yellow",
},
// * switching overflow between things that shouldn't create scrollframes.
{
beforeStyle: "overflow: visible",
afterStyle: "overflow: clip",
},
// Things that *should* cause reflow:
// ----------------------------------
// (e.g. to make sure our counts are actually measuring something)
// * Changing 'height' should cause reflow, but not frame construction.
{
beforeStyle: "height: 10px",
afterStyle: "height: 15px",
expectReflow: true,
},
// * Changing 'shape-outside' on a non-floating box should not cause anything to happen.
{
beforeStyle: "shape-outside: none",
afterStyle: "shape-outside: circle()",
},
// * Changing 'shape-outside' should cause reflow, but not frame construction.
{
beforeStyle: "float: left; shape-outside: none",
afterStyle: "float: left; shape-outside: circle()",
expectReflow: true,
},
// * Changing 'overflow' on <body> should cause reflow,
// but not frame reconstruction
{
elem: document.body,
/* beforeStyle: implicitly 'overflow:visible' */
afterStyle: "overflow: hidden",
expectConstruction: false,
expectReflow: true,
},
{
elem: document.body,
/* beforeStyle: implicitly 'overflow:visible' */
afterStyle: "overflow: scroll",
expectConstruction: false,
expectReflow: true,
},
{
elem: document.body,
beforeStyle: "overflow: hidden",
afterStyle: "overflow: auto",
expectConstruction: false,
expectReflow: true,
},
{
elem: document.body,
beforeStyle: "overflow: hidden",
afterStyle: "overflow: scroll",
expectConstruction: false,
expectReflow: true,
},
{
elem: document.body,
beforeStyle: "overflow: hidden",
afterStyle: "overflow: visible",
expectConstruction: false,
expectReflow: true,
},
{
elem: document.body,
beforeStyle: "overflow: auto",
afterStyle: "overflow: hidden",
expectConstruction: false,
expectReflow: true,
},
{
elem: document.body,
beforeStyle: "overflow: visible",
afterStyle: "overflow: hidden",
expectConstruction: false,
expectReflow: true,
},
// * Changing 'overflow' on <html> should cause reflow,
// but not frame reconstruction
{
elem: document.documentElement,
/* beforeStyle: implicitly 'overflow:visible' */
afterStyle: "overflow: auto",
expectConstruction: false,
expectReflow: true,
},
{
elem: document.documentElement,
beforeStyle: "overflow: visible",
afterStyle: "overflow: auto",
expectConstruction: false,
expectReflow: true,
},
// * Setting 'overflow' on arbitrary node should cause reflow as well as
// frame reconstruction
{
/* beforeStyle: implicitly 'overflow:visible' */
afterStyle: "overflow: auto",
expectConstruction: true,
expectReflow: true,
},
{
beforeStyle: "overflow: auto",
afterStyle: "overflow: visible",
expectConstruction: true,
expectReflow: true,
},
// * but only reflow if we don't need to construct / unconstruct a new frame.
{
beforeStyle: "overflow: scroll",
afterStyle: "overflow: auto",
expectConstruction: false,
expectReflow: true,
},
{
beforeStyle: "overflow: auto",
afterStyle: "overflow: scroll",
expectConstruction: false,
expectReflow: true,
},
{
beforeStyle: "overflow: hidden",
afterStyle: "overflow: auto",
expectConstruction: true,
expectReflow: true,
},
{
beforeStyle: "overflow: auto",
afterStyle: "overflow: hidden",
expectConstruction: false,
expectReflow: true,
},
{
beforeStyle: "overflow: hidden",
afterStyle: "overflow: scroll",
expectConstruction: true,
expectReflow: true,
},
{
beforeStyle: "overflow: scroll",
afterStyle: "overflow: hidden",
expectConstruction: false,
expectReflow: true,
},
{
elem: elemWithoutScrollbars,
beforeStyle: "scrollbar-width: auto",
afterStyle: "scrollbar-width: none",
expectConstruction: false,
expectReflow: false,
},
{
elem: elemWithScrollbars,
beforeStyle: "scrollbar-width: auto",
afterStyle: "scrollbar-width: none",
expectConstruction: false,
expectReflow: true,
},
{
// Not the scrolling element, so nothing should happen.
elem: document.body,
beforeStyle: "scrollbar-width: none",
afterStyle: "scrollbar-width: auto",
expectConstruction: false,
expectReflow: false,
},
{
// Not the scrolling element, so nothing should happen.
elem: document.body,
beforeStyle: "scrollbar-width: auto",
afterStyle: "scrollbar-width: none",
expectConstruction: false,
expectReflow: false,
},
{
elem: document.documentElement,
beforeStyle: "scrollbar-width: none;",
afterStyle: "scrollbar-width: auto",
expectConstruction: false,
expectReflow: true,
},
{
elem: document.documentElement,
beforeStyle: "overflow: scroll; scrollbar-width: none;",
afterStyle: "overflow: scroll; scrollbar-width: auto",
expectConstruction: false,
expectReflow: true,
},
{
elem: document.documentElement,
beforeStyle: "overflow: scroll; scrollbar-width: auto;",
afterStyle: "overflow: scroll; scrollbar-width: none",
expectConstruction: false,
expectReflow: true,
},
// * Changing 'display' should cause frame construction and reflow.
{
beforeStyle: "display: inline",
afterStyle: "display: table",
expectConstruction: true,
expectReflow: true,
},
// * Position changes trigger a reframe, unless whether we're a containing
// block doesn't change, in which case we just need to reflow.
{
beforeStyle: "position: static",
afterStyle: "position: absolute",
expectConstruction: true,
expectReflow: true,
},
{
beforeStyle: "position: absolute",
afterStyle: "position: fixed",
expectConstruction: true,
expectReflow: true,
},
{
beforeStyle: "position: relative",
afterStyle: "position: fixed",
expectConstruction: true,
expectReflow: true,
},
// This doesn't change whether we're a containing block because there are no
// abspos descendants.
{
afterStyle: "position: static",
beforeStyle: "position: relative",
expectReflow: true,
},
// This doesn't change whether we're a containing block, shouldn't reframe.
{
afterStyle: "position: sticky",
beforeStyle: "position: relative",
expectReflow: true,
},
// These don't change whether we're a containing block for our
// absolutely-positioned child, so shouldn't reframe.
{
elem: elemWithAbsPosChild,
afterStyle: "position: sticky",
beforeStyle: "position: relative",
expectReflow: true,
},
{
elem: elemWithFixedPosChild,
afterStyle: "position: sticky",
beforeStyle: "position: relative",
expectReflow: true,
},
{
elem: elemWithFixedPosChild,
afterStyle: "position: static",
beforeStyle: "position: relative",
expectReflow: true,
},
{
elem: elemWithFixedPosChild,
afterStyle: "position: static",
beforeStyle: "position: sticky",
expectReflow: true,
},
{
// Even if we're a scroll frame.
elem: elemWithFixedPosChild,
afterStyle: "position: static; overflow: auto;",
beforeStyle: "position: relative; overflow: auto;",
expectReflow: true,
},
{
elem: tableCell,
afterStyle: "position: static;",
beforeStyle: "position: relative;",
expectReflow: true,
},
{
elem: tableCell,
afterStyle: "filter: none",
beforeStyle: "filter: saturate(1)",
expectReflow: false,
},
// These ones do though.
{
elem: elemWithAbsPosChild,
afterStyle: "position: static",
beforeStyle: "position: relative",
expectConstruction: true,
expectReflow: true,
},
{
elem: elemWithAbsPosChild,
afterStyle: "position: static",
beforeStyle: "position: sticky",
expectConstruction: true,
expectReflow: true,
},
{
elem: elemWithAbsPosChild,
afterStyle: "position: static; overflow: auto;",
beforeStyle: "position: relative; overflow: auto;",
expectConstruction: true,
expectReflow: true,
},
{
elem: tableCellWithAbsPosChild,
afterStyle: "position: static;",
beforeStyle: "position: relative;",
expectConstruction: true,
expectReflow: true,
},
// Adding transform to a scrollframe without abspos / fixedpos children shouldn't reframe.
{
elem: elemWithScrollbars,
afterStyle: "transform: translateX(1px)",
expectConstruction: false,
expectReflow: false,
},
// <select> can't contain abspos / floating children so shouldn't reframe
// when changing containing block-ness.
{
elem: selectElem,
afterStyle: "transform: translateX(1px)",
expectConstruction: false,
expectReflow: false,
},
{
elem: selectElem,
afterStyle: "position: relative",
expectConstruction: false,
expectReflow: true,
},
// <button> shouldn't be reframed either in the absence of positioned descendants.
{
elem: buttonElem,
afterStyle: "transform: translateX(1px)",
expectConstruction: false,
expectReflow: false,
},
{
elem: buttonElem,
afterStyle: "position: relative",
expectConstruction: false,
expectReflow: true,
},
{
elem: buttonElemWithAbsPosChild,
afterStyle: "position: relative",
expectConstruction: true,
expectReflow: true,
},
// changing scroll-behavior should not cause reflow or frame construction
{
elem: document.documentElement,
/* beforeStyle: implicitly 'scroll-behavior: auto' */
afterStyle: "scroll-behavior: smooth",
expectConstruction: false,
expectReflow: false,
},
{
elem: document.documentElement,
beforeStyle: "scroll-behavior: smooth",
afterStyle: "scroll-behavior: auto",
expectConstruction: false,
expectReflow: false,
},
{
elem: document.body,
/* beforeStyle: implicitly 'scroll-behavior: auto' */
afterStyle: "scroll-behavior: smooth",
expectConstruction: false,
expectReflow: false,
},
{
elem: document.body,
beforeStyle: "scroll-behavior: smooth",
afterStyle: "scroll-behavior: auto",
expectConstruction: false,
expectReflow: false,
},
// changing scroll-snap-type should not cause reflow or frame construction
{
elem: document.documentElement,
/* beforeStyle: implicitly 'scroll-snap-type: none' */
afterStyle: "scroll-snap-type: y mandatory",
expectConstruction: false,
expectReflow: false,
},
{
elem: document.documentElement,
/* beforeStyle: implicitly 'scroll-snap-type: none' */
afterStyle: "scroll-snap-type: x proximity",
expectConstruction: false,
expectReflow: false,
},
{
elem: document.documentElement,
beforeStyle: "scroll-snap-type: y mandatory",
afterStyle: "scroll-snap-type: none",
expectConstruction: false,
expectReflow: false,
},
{
elem: document.body,
/* beforeStyle: implicitly 'scroll-snap-type: none' */
afterStyle: "scroll-snap-type: y mandatory",
expectConstruction: false,
expectReflow: false,
},
{
elem: document.body,
/* beforeStyle: implicitly 'scroll-snap-type: none' */
afterStyle: "scroll-snap-type: x proximity",
expectConstruction: false,
expectReflow: false,
},
{
elem: document.body,
beforeStyle: "scroll-snap-type: y mandatory",
afterStyle: "scroll-snap-type: none",
expectConstruction: false,
expectReflow: false,
},
{
elem: inputElem,
beforeStyle: "overflow: auto",
afterStyle: "overflow: hidden",
expectConstruction: false,
expectReflow: true,
},
{
elem: textareaElem,
beforeStyle: "overflow: auto",
afterStyle: "overflow: hidden",
expectConstruction: false,
expectReflow: true,
},
{
elem: flexItemMovementTarget,
beforeStyle: "transform: translateX(0)",
afterStyle: "transform: translateX(-100px)",
expectConstruction: false,
expectReflow: false,
},
{
elem: flexItemMovementTarget2,
beforeStyle: "transform: translateX(0)",
afterStyle: "transform: translateX(-100px)",
expectConstruction: false,
expectReflow: false,
},
// Style containment affects counters so we need to re-frame.
// For other containments, we only need to reflow.
{
elem: containNode,
beforeStyle: "contain: none",
afterStyle: "contain: style",
expectConstruction: true,
expectReflow: true,
},
{
elem: containNode,
beforeStyle: "contain: style",
afterStyle: "contain: none",
expectConstruction: true,
expectReflow: true,
},
{
elem: containNode,
beforeStyle: "contain: none",
afterStyle: "contain: paint",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNode,
beforeStyle: "contain: paint",
afterStyle: "contain: none",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNode,
beforeStyle: "contain: none",
afterStyle: "contain: layout",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNode,
beforeStyle: "contain: layout",
afterStyle: "contain: none",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNode,
beforeStyle: "contain: none",
afterStyle: "contain: size",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNode,
beforeStyle: "contain: size",
afterStyle: "contain: none",
expectConstruction: false,
expectReflow: true,
},
// paint/layout containment boxes establish an absolute positioning
// containing block, so need a re-frame to handle abs/fixed positioned boxes.
{
elem: containNodeWithAbsPosChild,
beforeStyle: "contain: none",
afterStyle: "contain: paint",
expectConstruction: true,
expectReflow: true,
},
{
elem: containNodeWithAbsPosChild,
beforeStyle: "contain: paint",
afterStyle: "contain: none",
expectConstruction: true,
expectReflow: true,
},
{
elem: containNodeWithAbsPosChild,
beforeStyle: "contain: none",
afterStyle: "contain: layout",
expectConstruction: true,
expectReflow: true,
},
{
elem: containNodeWithAbsPosChild,
beforeStyle: "contain: layout",
afterStyle: "contain: none",
expectConstruction: true,
expectReflow: true,
},
{
elem: containNodeWithAbsPosChild,
beforeStyle: "contain: none",
afterStyle: "contain: size",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNodeWithAbsPosChild,
beforeStyle: "contain: size",
afterStyle: "contain: none",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNodeWithFixedPosChild,
beforeStyle: "contain: none",
afterStyle: "contain: paint",
expectConstruction: true,
expectReflow: true,
},
{
elem: containNodeWithFixedPosChild,
beforeStyle: "contain: paint",
afterStyle: "contain: none",
expectConstruction: true,
expectReflow: true,
},
{
elem: containNodeWithFixedPosChild,
beforeStyle: "contain: none",
afterStyle: "contain: layout",
expectConstruction: true,
expectReflow: true,
},
{
elem: containNodeWithFixedPosChild,
beforeStyle: "contain: layout",
afterStyle: "contain: none",
expectConstruction: true,
expectReflow: true,
},
{
elem: containNodeWithFixedPosChild,
beforeStyle: "contain: none",
afterStyle: "contain: size",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNodeWithFixedPosChild,
beforeStyle: "contain: size",
afterStyle: "contain: none",
expectConstruction: false,
expectReflow: true,
},
// paint/layout containment boxes establish an independent formatting context
// but floats and margin collapsing can be handled without reconstruction.
{
elem: containNodeWithFloatingChild,
beforeStyle: "contain: none",
afterStyle: "contain: paint",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNodeWithFloatingChild,
beforeStyle: "contain: paint",
afterStyle: "contain: none",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNodeWithFloatingChild,
beforeStyle: "contain: none",
afterStyle: "contain: layout",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNodeWithFloatingChild,
beforeStyle: "contain: layout",
afterStyle: "contain: none",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNodeWithFloatingChild,
beforeStyle: "contain: none",
afterStyle: "contain: size",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNodeWithFloatingChild,
beforeStyle: "contain: size",
afterStyle: "contain: none",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNodeWithMarginCollapsing,
beforeStyle: "contain: none",
afterStyle: "contain: paint",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNodeWithMarginCollapsing,
beforeStyle: "contain: paint",
afterStyle: "contain: none",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNodeWithMarginCollapsing,
beforeStyle: "contain: none",
afterStyle: "contain: layout",
expectConstruction: false,
expectReflow: true,
},
{
elem: containNodeWithMarginCollapsing,
beforeStyle: "contain: layout",
afterStyle: "contain: none",
expectConstruction: false,
expectReflow: true,
},
// content-visibility: auto/hidden implies style containment contrary to
// content-visibility: visible, so we generally need a re-frame (see above)
// when going from one case to the other.
{
elem: contentVisibilityNode,
beforeStyle: "content-visibility: visible",
afterStyle: "content-visibility: hidden",
expectConstruction: true,
expectReflow: true,
},
{
elem: contentVisibilityNode,
beforeStyle: "content-visibility: hidden",
afterStyle: "content-visibility: visible",
expectConstruction: true,
expectReflow: true,
},
{
elem: contentVisibilityNode,
beforeStyle: "content-visibility: visible",
afterStyle: "content-visibility: auto",
expectConstruction: true,
expectReflow: true,
},
{
elem: contentVisibilityNode,
beforeStyle: "content-visibility: auto",
afterStyle: "content-visibility: visible",
expectConstruction: true,
expectReflow: true,
},
{
elem: contentVisibilityNode,
beforeStyle: "content-visibility: hidden",
afterStyle: "content-visibility: auto",
expectConstruction: false,
expectReflow: true,
},
{
elem: contentVisibilityNode,
beforeStyle: "content-visibility: auto",
afterStyle: "content-visibility: hidden",
expectConstruction: false,
expectReflow: true,
},
// However that's not the case if we force style containment explicitly.
{
elem: contentVisibilityNode,
beforeStyle: "content-visibility: visible; contain: style",
afterStyle: "content-visibility: hidden; contain: style",
expectConstruction: false,
expectReflow: true,
},
{
elem: contentVisibilityNode,
beforeStyle: "content-visibility: hidden; contain: style",
afterStyle: "content-visibility: visible; contain: style",
expectConstruction: false,
expectReflow: true,
},
];
// Helper function to let us call either "is" or "isnot" & assemble
// the failure message, based on the provided parameters.
function checkFinalCount(aFinalCount, aExpectedCount,
aExpectChange, aMsgPrefix, aCountDescription)
{
let compareFunc;
let msg = aMsgPrefix;
if (aExpectChange) {
compareFunc = isnot;
msg += "should cause " + aCountDescription;
} else {
compareFunc = is;
msg += "should not cause " + aCountDescription;
}
compareFunc(aFinalCount, aExpectedCount, msg);
}
// Vars used in runOneTest that we really only have to look up once:
const gUtils = SpecialPowers.getDOMWindowUtils(window);
const gElem = document.getElementById("content");
function runOneTest(aTestcase)
{
// sanity-check that we have the one main thing we need:
if (!aTestcase.afterStyle) {
ok(false, "testcase is missing an 'afterStyle' to change to");
return;
}
// Figure out which element we'll be tweaking (defaulting to gElem)
let elem = aTestcase.elem ? aTestcase.elem : gElem;
// Verify that 'style' attribute is unset (avoid causing ourselves trouble):
const oldStyle = elem.getAttribute("style");
// Set the "before" style, and compose the first part of the message
// to be used in our "is"/"isnot" invocations:
let msgPrefix = "Changing style ";
if (aTestcase.beforeStyle) {
elem.setAttribute("style", aTestcase.beforeStyle);
msgPrefix += "from '" + aTestcase.beforeStyle + "' ";
}
msgPrefix += "to '" + aTestcase.afterStyle + "' ";
msgPrefix += "on " + elem.nodeName + " ";
// Establish initial counts:
let unusedVal = elem.offsetHeight; // flush layout
let origFramesConstructed = gUtils.framesConstructed;
let origFramesReflowed = gUtils.framesReflowed;
// Make the change and flush:
elem.setAttribute("style", aTestcase.afterStyle);
unusedVal = elem.offsetHeight; // flush layout
// Make our is/isnot assertions about whether things should have changed:
checkFinalCount(gUtils.framesConstructed, origFramesConstructed,
aTestcase.expectConstruction, msgPrefix,
"frame construction");
checkFinalCount(gUtils.framesReflowed, origFramesReflowed,
aTestcase.expectReflow, msgPrefix,
"reflow");
// Clean up!
if (oldStyle) {
elem.setAttribute("style", oldStyle);
} else {
elem.removeAttribute("style");
}
unusedVal = elem.offsetHeight; // flush layout
}
gTestcases.forEach(runOneTest);
</script>
</pre>
</body>
</html>