Bug 1419221 - Introduce a new argument for getUnanimatedComputedStyle to be able to flush pending styles. r?birtles
Even with this patch, in Gecko getUnanimatedComputedStyle flushes pendings
styles somehow. Also in Stylo the function flushes pending styles if the
target element hasn't yet styled or Servo style data has cleared for some
reasons (e.g. the element is in display:none subtree).
MozReview-Commit-ID: HCizzM0JnFz
--- a/devtools/server/actors/animation.js
+++ b/devtools/server/actors/animation.js
@@ -504,17 +504,20 @@ var AnimationPlayerActor = protocol.Acto
let pseudo = null;
let target = this.player.effect.target;
if (target.type) {
// This target is a pseudo element.
pseudo = target.type;
target = target.parentElement;
}
const value =
- DOMWindowUtils.getUnanimatedComputedStyle(target, pseudo, property.name);
+ DOMWindowUtils.getUnanimatedComputedStyle(target,
+ pseudo,
+ property.name,
+ DOMWindowUtils.FLUSH_NONE);
const animationType = DOMWindowUtils.getAnimationTypeForLonghand(property.name);
underlyingValue = animationType === "float" ? parseFloat(value, 10) : value;
}
values.value = underlyingValue;
});
}
// Calculate the distance.
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2965,30 +2965,45 @@ nsDOMWindowUtils::GetAnimationTypeForLon
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetUnanimatedComputedStyle(nsIDOMElement* aElement,
const nsAString& aPseudoElement,
const nsAString& aProperty,
+ int32_t aFlushType,
nsAString& aResult)
{
nsCOMPtr<Element> element = do_QueryInterface(aElement);
if (!element) {
return NS_ERROR_INVALID_ARG;
}
nsCSSPropertyID propertyID =
nsCSSProps::LookupProperty(aProperty, CSSEnabledState::eForAllContent);
if (propertyID == eCSSProperty_UNKNOWN ||
nsCSSProps::IsShorthand(propertyID)) {
return NS_ERROR_INVALID_ARG;
}
+ switch (aFlushType) {
+ case FLUSH_NONE:
+ break;
+ case FLUSH_STYLE: {
+ nsIDocument* doc = element->GetComposedDoc();
+ if (doc) {
+ doc->FlushPendingNotifications(FlushType::Style);
+ }
+ break;
+ }
+ default:
+ return NS_ERROR_INVALID_ARG;
+ }
+
nsIPresShell* shell = GetPresShell();
if (!shell) {
return NS_ERROR_FAILURE;
}
RefPtr<nsAtom> pseudo = nsCSSPseudoElements::GetPseudoAtom(aPseudoElement);
RefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetUnanimatedStyleContextNoFlush(element,
--- a/dom/base/test/file_domwindowutils_animation.html
+++ b/dom/base/test/file_domwindowutils_animation.html
@@ -97,30 +97,55 @@ function test_getUnanimatedComputedStyle
deleteStyle();
});
});
const div = document.createElement("div");
document.body.appendChild(div);
SimpleTest.doesThrow(
- () => utils.getUnanimatedComputedStyle(div, null, "background"),
+ () => utils.getUnanimatedComputedStyle(div, null, "background", utils.FLUSH_NONE),
"NS_ERROR_INVALID_ARG",
"Shorthand property should throw");
SimpleTest.doesThrow(
- () => utils.getUnanimatedComputedStyle(div, null, "invalid"),
+ () => utils.getUnanimatedComputedStyle(div, null, "invalid", utils.FLUSH_NONE),
"NS_ERROR_INVALID_ARG",
"Invalid property should throw");
SimpleTest.doesThrow(
- () => utils.getUnanimatedComputedStyle(null, null, "opacity"),
+ () => utils.getUnanimatedComputedStyle(null, null, "opacity", utils.FLUSH_NONE),
"NS_ERROR_INVALID_ARG",
"Null element should throw");
+ SimpleTest.doesThrow(
+ () => utils.getUnanimatedComputedStyle(div, null, "opacity", utils.FLUSH_LAYOUT),
+ "NS_ERROR_INVALID_ARG",
+ "FLUSH_LAYOUT option should throw");
+
+ SimpleTest.doesThrow(
+ () => utils.getUnanimatedComputedStyle(div, null, "opacity", utils.FLUSH_DISPLAY),
+ "NS_ERROR_INVALID_ARG",
+ "FLUSH_DISPLAY option should throw");
+
+ if (utils.isStyledByServo) {
+ // Flush styles since getUnanimatedComputedStyle flushes pending styles even
+ // with FLUSH_NONE option if the element hasn't yet styled.
+ getComputedStyle(div).opacity;
+
+ div.style.opacity = "0";
+ is(utils.getUnanimatedComputedStyle(div, null, "opacity", utils.FLUSH_NONE),
+ "1",
+ "getUnanimatedComputedStyle with FLUSH_NONE should not flush pending styles");
+
+ is(utils.getUnanimatedComputedStyle(div, null, "opacity", utils.FLUSH_STYLE),
+ "0",
+ "getUnanimatedComputedStyle with FLUSH_STYLE should flush pending styles");
+ }
+
div.remove();
next();
window.close();
}
function checkUnanimatedComputedStyle(property, initialStyle, pseudoType,
expectedBeforeAnimation,
@@ -131,25 +156,25 @@ function checkUnanimatedComputedStyle(pr
if (initialStyle) {
div.style[property] = initialStyle;
}
if (pseudoType) {
div.classList.add("pseudo");
}
- is(utils.getUnanimatedComputedStyle(div, pseudoType, property),
+ is(utils.getUnanimatedComputedStyle(div, pseudoType, property, utils.FLUSH_STYLE),
expectedBeforeAnimation,
`'${ property }' property with '${ initialStyle }' style `
+ `should be '${ expectedBeforeAnimation }' `
+ `before animating by ${ animationType }`);
const animation = animate(div);
animation.currentTime = 500;
- is(utils.getUnanimatedComputedStyle(div, pseudoType, property),
+ is(utils.getUnanimatedComputedStyle(div, pseudoType, property, utils.FLUSH_STYLE),
expectedDuringAnimation,
`'${ property }' property with '${ initialStyle }' style `
+ `should be '${ expectedDuringAnimation }' `
+ `even while animating by ${ animationType }`);
div.remove();
}
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -985,16 +985,17 @@ interface nsIDOMWindowUtils : nsISupport
*/
void getScrollbarSize(in boolean aFlushLayout, out long aWidth, out long aHeight);
/**
* Returns the given element's bounds without flushing pending layout changes.
*/
nsIDOMClientRect getBoundsWithoutFlushing(in nsIDOMElement aElement);
+ const long FLUSH_NONE = -1;
const long FLUSH_STYLE = 0;
const long FLUSH_LAYOUT = 1;
const long FLUSH_DISPLAY = 2;
/**
* Returns true if a flush of the given type is needed.
*/
bool needsFlush(in long aFlushtype);
@@ -1576,20 +1577,23 @@ interface nsIDOMWindowUtils : nsISupport
AString getAnimationTypeForLonghand(in AString aProperty);
/**
* Returns the computed style for the specified property of given pseudo type
* on the given element after removing styles from declarative animations.
* @param aElement - A target element
* @param aPseudoElement - A pseudo type (e.g. '::before' or null)
* @param aProperty - A longhand CSS property (e.g. 'background-color')
+ * @param aFlushType - FLUSH_NONE if any pending styles should not happen,
+ * FLUSH_STYLE to flush pending styles.
*/
AString getUnanimatedComputedStyle(in nsIDOMElement aElement,
in AString aPseudoElement,
- in AString aProperty);
+ in AString aProperty,
+ in long aFlushType);
/**
* Get the type of the currently focused html input, if any.
*/
readonly attribute string focusedInputType;
/**
* Find the view ID for a given element. This is the reverse of