mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 800983. Expose a getter for default computed style. r=dbaron
An alternative implementation strategy is to add "default-only" versions of ResolveStyleFor and ResolvePseudoElementStyle and then modify FileRules to support those, or use a cut-down custom version of FileRules for them. That would be faster, but more complicated on the style set side. We can always make that switch if we need to, I guess.
This commit is contained in:
parent
194968b6cb
commit
611fe536d0
@ -2604,8 +2604,6 @@ CanvasRenderingContext2D::SetFont(const nsAString& font,
|
||||
}
|
||||
nsIDocument* document = presShell->GetDocument();
|
||||
|
||||
nsCOMArray<nsIStyleRule> rules;
|
||||
|
||||
nsRefPtr<css::StyleRule> rule;
|
||||
error = CreateFontStyleRule(font, document, getter_AddRefs(rule));
|
||||
|
||||
@ -2629,7 +2627,8 @@ CanvasRenderingContext2D::SetFont(const nsAString& font,
|
||||
return;
|
||||
}
|
||||
|
||||
rules.AppendObject(rule);
|
||||
nsTArray< nsCOMPtr<nsIStyleRule> > rules;
|
||||
rules.AppendElement(rule);
|
||||
|
||||
nsStyleSet* styleSet = presShell->StyleSet();
|
||||
|
||||
@ -2654,8 +2653,8 @@ CanvasRenderingContext2D::SetFont(const nsAString& font,
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMArray<nsIStyleRule> parentRules;
|
||||
parentRules.AppendObject(parentRule);
|
||||
nsTArray< nsCOMPtr<nsIStyleRule> > parentRules;
|
||||
parentRules.AppendElement(parentRule);
|
||||
parentContext = styleSet->ResolveStyleForRules(nullptr, parentRules);
|
||||
}
|
||||
|
||||
|
@ -8267,7 +8267,25 @@ nsGlobalWindow::GetComputedStyle(nsIDOMElement* aElt,
|
||||
const nsAString& aPseudoElt,
|
||||
nsIDOMCSSStyleDeclaration** aReturn)
|
||||
{
|
||||
FORWARD_TO_OUTER(GetComputedStyle, (aElt, aPseudoElt, aReturn),
|
||||
return GetComputedStyleHelper(aElt, aPseudoElt, false, aReturn);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::GetDefaultComputedStyle(nsIDOMElement* aElt,
|
||||
const nsAString& aPseudoElt,
|
||||
nsIDOMCSSStyleDeclaration** aReturn)
|
||||
{
|
||||
return GetComputedStyleHelper(aElt, aPseudoElt, true, aReturn);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::GetComputedStyleHelper(nsIDOMElement* aElt,
|
||||
const nsAString& aPseudoElt,
|
||||
bool aDefaultStylesOnly,
|
||||
nsIDOMCSSStyleDeclaration** aReturn)
|
||||
{
|
||||
FORWARD_TO_OUTER(GetComputedStyleHelper, (aElt, aPseudoElt,
|
||||
aDefaultStylesOnly, aReturn),
|
||||
NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aReturn);
|
||||
@ -8310,7 +8328,9 @@ nsGlobalWindow::GetComputedStyle(nsIDOMElement* aElt,
|
||||
nsCOMPtr<dom::Element> element = do_QueryInterface(aElt);
|
||||
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
|
||||
nsRefPtr<nsComputedDOMStyle> compStyle =
|
||||
NS_NewComputedDOMStyle(element, aPseudoElt, presShell);
|
||||
NS_NewComputedDOMStyle(element, aPseudoElt, presShell,
|
||||
aDefaultStylesOnly ? nsComputedDOMStyle::eDefaultOnly :
|
||||
nsComputedDOMStyle::eAll);
|
||||
|
||||
*aReturn = compStyle.forget().get();
|
||||
|
||||
|
@ -932,6 +932,12 @@ protected:
|
||||
// Outer windows only.
|
||||
nsDOMWindowList* GetWindowList();
|
||||
|
||||
// Helper for getComputedStyle and getDefaultComputedStyle
|
||||
nsresult GetComputedStyleHelper(nsIDOMElement* aElt,
|
||||
const nsAString& aPseudoElt,
|
||||
bool aDefaultStylesOnly,
|
||||
nsIDOMCSSStyleDeclaration** aReturn);
|
||||
|
||||
// When adding new member variables, be careful not to create cycles
|
||||
// through JavaScript. If there is any chance that a member variable
|
||||
// could own objects that are implemented in JavaScript, then those
|
||||
|
@ -32,7 +32,7 @@ interface nsIDOMMozURLProperty : nsISupports
|
||||
* @see <http://www.whatwg.org/html/#window>
|
||||
*/
|
||||
|
||||
[scriptable, uuid(25404a1b-6c73-4850-af95-69aa095c8ad0)]
|
||||
[scriptable, uuid(43933989-912e-4b6a-b889-3c9fc9dd9ed4)]
|
||||
interface nsIDOMWindow : nsISupports
|
||||
{
|
||||
// the current browsing context
|
||||
@ -316,6 +316,8 @@ interface nsIDOMWindow : nsISupports
|
||||
*/
|
||||
nsIDOMCSSStyleDeclaration getComputedStyle(in nsIDOMElement elt,
|
||||
[optional] in DOMString pseudoElt);
|
||||
nsIDOMCSSStyleDeclaration getDefaultComputedStyle(in nsIDOMElement elt,
|
||||
[optional] in DOMString pseudoElt);
|
||||
|
||||
|
||||
// Mozilla extensions
|
||||
|
@ -64,7 +64,8 @@ static nsComputedDOMStyle *sCachedComputedDOMStyle;
|
||||
|
||||
already_AddRefed<nsComputedDOMStyle>
|
||||
NS_NewComputedDOMStyle(dom::Element* aElement, const nsAString& aPseudoElt,
|
||||
nsIPresShell* aPresShell)
|
||||
nsIPresShell* aPresShell,
|
||||
nsComputedDOMStyle::StyleType aStyleType)
|
||||
{
|
||||
nsRefPtr<nsComputedDOMStyle> computedStyle;
|
||||
if (sCachedComputedDOMStyle) {
|
||||
@ -73,13 +74,14 @@ NS_NewComputedDOMStyle(dom::Element* aElement, const nsAString& aPseudoElt,
|
||||
|
||||
// Oh yeah baby, placement new!
|
||||
computedStyle = new (sCachedComputedDOMStyle)
|
||||
nsComputedDOMStyle(aElement, aPseudoElt, aPresShell);
|
||||
nsComputedDOMStyle(aElement, aPseudoElt, aPresShell, aStyleType);
|
||||
|
||||
sCachedComputedDOMStyle = nullptr;
|
||||
} else {
|
||||
// No nsComputedDOMStyle cached, create a new one.
|
||||
|
||||
computedStyle = new nsComputedDOMStyle(aElement, aPseudoElt, aPresShell);
|
||||
computedStyle = new nsComputedDOMStyle(aElement, aPseudoElt, aPresShell,
|
||||
aStyleType);
|
||||
}
|
||||
|
||||
return computedStyle.forget();
|
||||
@ -95,9 +97,11 @@ GetContainingBlockFor(nsIFrame* aFrame) {
|
||||
|
||||
nsComputedDOMStyle::nsComputedDOMStyle(dom::Element* aElement,
|
||||
const nsAString& aPseudoElt,
|
||||
nsIPresShell* aPresShell)
|
||||
nsIPresShell* aPresShell,
|
||||
StyleType aStyleType)
|
||||
: mDocumentWeak(nullptr), mOuterFrame(nullptr),
|
||||
mInnerFrame(nullptr), mPresShell(nullptr),
|
||||
mStyleType(aStyleType),
|
||||
mExposeVisitedStyle(false)
|
||||
{
|
||||
MOZ_ASSERT(aElement && aPresShell);
|
||||
@ -268,7 +272,8 @@ nsComputedDOMStyle::GetPropertyValue(const nsAString& aPropertyName,
|
||||
already_AddRefed<nsStyleContext>
|
||||
nsComputedDOMStyle::GetStyleContextForElement(Element* aElement,
|
||||
nsIAtom* aPseudo,
|
||||
nsIPresShell* aPresShell)
|
||||
nsIPresShell* aPresShell,
|
||||
StyleType aStyleType)
|
||||
{
|
||||
// If the content has a pres shell, we must use it. Otherwise we'd
|
||||
// potentially mix rule trees by using the wrong pres shell's style
|
||||
@ -284,14 +289,16 @@ nsComputedDOMStyle::GetStyleContextForElement(Element* aElement,
|
||||
|
||||
presShell->FlushPendingNotifications(Flush_Style);
|
||||
|
||||
return GetStyleContextForElementNoFlush(aElement, aPseudo, presShell);
|
||||
return GetStyleContextForElementNoFlush(aElement, aPseudo, presShell,
|
||||
aStyleType);
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<nsStyleContext>
|
||||
nsComputedDOMStyle::GetStyleContextForElementNoFlush(Element* aElement,
|
||||
nsIAtom* aPseudo,
|
||||
nsIPresShell* aPresShell)
|
||||
nsIPresShell* aPresShell,
|
||||
StyleType aStyleType)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aElement, "NULL element");
|
||||
// If the content has a pres shell, we must use it. Otherwise we'd
|
||||
@ -306,7 +313,7 @@ nsComputedDOMStyle::GetStyleContextForElementNoFlush(Element* aElement,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!aPseudo) {
|
||||
if (!aPseudo && aStyleType == eAll) {
|
||||
nsIFrame* frame = aElement->GetPrimaryFrame();
|
||||
if (frame) {
|
||||
nsStyleContext* result =
|
||||
@ -322,14 +329,15 @@ nsComputedDOMStyle::GetStyleContextForElementNoFlush(Element* aElement,
|
||||
}
|
||||
}
|
||||
|
||||
// No frame has been created or we have a pseudo, so resolve the
|
||||
// style ourselves
|
||||
// No frame has been created, or we have a pseudo, or we're looking
|
||||
// for the default style, so resolve the style ourselves.
|
||||
nsRefPtr<nsStyleContext> parentContext;
|
||||
nsIContent* parent = aPseudo ? aElement : aElement->GetParent();
|
||||
// Don't resolve parent context for document fragments.
|
||||
if (parent && parent->IsElement())
|
||||
parentContext = GetStyleContextForElementNoFlush(parent->AsElement(),
|
||||
nullptr, presShell);
|
||||
nullptr, presShell,
|
||||
aStyleType);
|
||||
|
||||
nsPresContext *presContext = presShell->GetPresContext();
|
||||
if (!presContext)
|
||||
@ -337,15 +345,42 @@ nsComputedDOMStyle::GetStyleContextForElementNoFlush(Element* aElement,
|
||||
|
||||
nsStyleSet *styleSet = presShell->StyleSet();
|
||||
|
||||
nsRefPtr<nsStyleContext> sc;
|
||||
if (aPseudo) {
|
||||
nsCSSPseudoElements::Type type = nsCSSPseudoElements::GetPseudoType(aPseudo);
|
||||
if (type >= nsCSSPseudoElements::ePseudo_PseudoElementCount) {
|
||||
return nullptr;
|
||||
}
|
||||
return styleSet->ResolvePseudoElementStyle(aElement, type, parentContext);
|
||||
sc = styleSet->ResolvePseudoElementStyle(aElement, type, parentContext);
|
||||
} else {
|
||||
sc = styleSet->ResolveStyleFor(aElement, parentContext);
|
||||
}
|
||||
|
||||
return styleSet->ResolveStyleFor(aElement, parentContext);
|
||||
if (aStyleType == eDefaultOnly) {
|
||||
// We really only want the user and UA rules. Filter out the other ones.
|
||||
nsTArray< nsCOMPtr<nsIStyleRule> > rules;
|
||||
for (nsRuleNode* ruleNode = sc->GetRuleNode();
|
||||
!ruleNode->IsRoot();
|
||||
ruleNode = ruleNode->GetParent()) {
|
||||
if (ruleNode->GetLevel() == nsStyleSet::eAgentSheet ||
|
||||
ruleNode->GetLevel() == nsStyleSet::eUserSheet) {
|
||||
rules.AppendElement(ruleNode->GetRule());
|
||||
}
|
||||
}
|
||||
|
||||
// We want to build a list of user/ua rules that is in order from least to
|
||||
// most important, so we have to reverse the list.
|
||||
// Integer division to get "stop" is purposeful here: if length is odd, we
|
||||
// don't have to do anything with the middle element of the array.
|
||||
for (uint32_t i = 0, length = rules.Length(), stop = length / 2;
|
||||
i < stop; ++i) {
|
||||
rules[i].swap(rules[length - i - 1]);
|
||||
}
|
||||
|
||||
sc = styleSet->ResolveStyleForRules(parentContext, rules);
|
||||
}
|
||||
|
||||
return sc.forget();
|
||||
}
|
||||
|
||||
/* static */
|
||||
@ -454,7 +489,7 @@ nsComputedDOMStyle::GetPropertyCSSValue(const nsAString& aPropertyName,
|
||||
NS_ENSURE_TRUE(mPresShell && mPresShell->GetPresContext(),
|
||||
NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
if (!mPseudo) {
|
||||
if (!mPseudo && mStyleType == eAll) {
|
||||
mOuterFrame = mContent->GetPrimaryFrame();
|
||||
mInnerFrame = mOuterFrame;
|
||||
if (mOuterFrame) {
|
||||
@ -495,7 +530,8 @@ nsComputedDOMStyle::GetPropertyCSSValue(const nsAString& aPropertyName,
|
||||
mStyleContextHolder =
|
||||
nsComputedDOMStyle::GetStyleContextForElement(mContent->AsElement(),
|
||||
mPseudo,
|
||||
mPresShell);
|
||||
mPresShell,
|
||||
mStyleType);
|
||||
NS_ENSURE_TRUE(mStyleContextHolder, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ASSERTION(mPseudo || !mStyleContextHolder->HasPseudoElementData(),
|
||||
"should not have pseudo-element data");
|
||||
|
@ -38,9 +38,15 @@ public:
|
||||
NS_DECL_NSIDOMCSSSTYLEDECLARATION
|
||||
virtual void IndexedGetter(uint32_t aIndex, bool& aFound, nsAString& aPropName);
|
||||
|
||||
enum StyleType {
|
||||
eDefaultOnly, // Only includes UA and user sheets
|
||||
eAll // Includes all stylesheets
|
||||
};
|
||||
|
||||
nsComputedDOMStyle(mozilla::dom::Element* aElement,
|
||||
const nsAString& aPseudoElt,
|
||||
nsIPresShell* aPresShell);
|
||||
nsIPresShell* aPresShell,
|
||||
StyleType aStyleType);
|
||||
virtual ~nsComputedDOMStyle();
|
||||
|
||||
static void Shutdown();
|
||||
@ -52,12 +58,14 @@ public:
|
||||
|
||||
static already_AddRefed<nsStyleContext>
|
||||
GetStyleContextForElement(mozilla::dom::Element* aElement, nsIAtom* aPseudo,
|
||||
nsIPresShell* aPresShell);
|
||||
nsIPresShell* aPresShell,
|
||||
StyleType aStyleType = eAll);
|
||||
|
||||
static already_AddRefed<nsStyleContext>
|
||||
GetStyleContextForElementNoFlush(mozilla::dom::Element* aElement,
|
||||
nsIAtom* aPseudo,
|
||||
nsIPresShell* aPresShell);
|
||||
nsIPresShell* aPresShell,
|
||||
StyleType aStyleType = eAll);
|
||||
|
||||
static nsIPresShell*
|
||||
GetPresShellForContent(nsIContent* aContent);
|
||||
@ -505,6 +513,11 @@ private:
|
||||
*/
|
||||
nsIPresShell* mPresShell;
|
||||
|
||||
/*
|
||||
* The kind of styles we should be returning.
|
||||
*/
|
||||
StyleType mStyleType;
|
||||
|
||||
bool mExposeVisitedStyle;
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -515,7 +528,9 @@ private:
|
||||
already_AddRefed<nsComputedDOMStyle>
|
||||
NS_NewComputedDOMStyle(mozilla::dom::Element* aElement,
|
||||
const nsAString& aPseudoElt,
|
||||
nsIPresShell* aPresShell);
|
||||
nsIPresShell* aPresShell,
|
||||
nsComputedDOMStyle::StyleType aStyleType =
|
||||
nsComputedDOMStyle::eAll);
|
||||
|
||||
#endif /* nsComputedDOMStyle_h__ */
|
||||
|
||||
|
@ -969,7 +969,7 @@ nsStyleSet::ResolveStyleFor(Element* aElement,
|
||||
|
||||
already_AddRefed<nsStyleContext>
|
||||
nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext,
|
||||
const nsCOMArray<nsIStyleRule> &aRules)
|
||||
const nsTArray< nsCOMPtr<nsIStyleRule> > &aRules)
|
||||
{
|
||||
NS_ENSURE_FALSE(mInShutdown, nullptr);
|
||||
|
||||
@ -977,8 +977,8 @@ nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext,
|
||||
// FIXME: Perhaps this should be passed in, but it probably doesn't
|
||||
// matter.
|
||||
ruleWalker.SetLevel(eDocSheet, false, false);
|
||||
for (int32_t i = 0; i < aRules.Count(); i++) {
|
||||
ruleWalker.ForwardOnPossiblyCSSRule(aRules.ObjectAt(i));
|
||||
for (uint32_t i = 0; i < aRules.Length(); i++) {
|
||||
ruleWalker.ForwardOnPossiblyCSSRule(aRules.ElementAt(i));
|
||||
}
|
||||
|
||||
return GetContext(aParentContext, ruleWalker.CurrentNode(), nullptr,
|
||||
|
@ -90,7 +90,7 @@ class nsStyleSet
|
||||
// sequence of style rules in the |aRules| array.
|
||||
already_AddRefed<nsStyleContext>
|
||||
ResolveStyleForRules(nsStyleContext* aParentContext,
|
||||
const nsCOMArray<nsIStyleRule> &aRules);
|
||||
const nsTArray< nsCOMPtr<nsIStyleRule> > &aRules);
|
||||
|
||||
// Get a style context that represents aBaseContext, but as though
|
||||
// it additionally matched the rules in the aRules array (in that
|
||||
|
@ -92,6 +92,7 @@ MOCHITEST_FILES = test_acid3_test46.html \
|
||||
test_compute_data_with_start_struct.html \
|
||||
test_computed_style.html \
|
||||
test_computed_style_no_pseudo.html \
|
||||
test_default_computed_style.html \
|
||||
test_css_cross_domain.html \
|
||||
test_css_eof_handling.html \
|
||||
test_default_bidi_css.html \
|
||||
|
58
layout/style/test/test_default_computed_style.html
Normal file
58
layout/style/test/test_default_computed_style.html
Normal file
@ -0,0 +1,58 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=800983
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 800983</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
#display::before { content: "Visible"; display: block }
|
||||
#display {
|
||||
display: inline;
|
||||
margin-top: 0;
|
||||
background: yellow;
|
||||
color: blue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=800983">Mozilla Bug 800983</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 800983 **/
|
||||
var cs = getComputedStyle($("display"));
|
||||
var cs_pseudo = getComputedStyle($("display"), "::before")
|
||||
|
||||
var cs_default = getDefaultComputedStyle($("display"));
|
||||
var cs_default_pseudo = getDefaultComputedStyle($("display"), "::before");
|
||||
|
||||
// Sanity checks for normal computed style
|
||||
is(cs.display, "inline", "We have inline display");
|
||||
is(cs.marginTop, "0px", "We have 0 margin");
|
||||
is(cs.backgroundColor, "rgb(255, 255, 0)", "We have yellow background");
|
||||
is(cs.color, "rgb(0, 0, 255)", "We have blue text");
|
||||
is(cs_pseudo.content, '"Visible"', "We have some content");
|
||||
is(cs_pseudo.display, "block", "Our ::before is block");
|
||||
|
||||
// And now our actual tests
|
||||
is(cs_default.display, "block", "We have block display by default");
|
||||
is(cs_default.marginTop, "16px", "We have 16px margin by default");
|
||||
is(cs_default.backgroundColor, "transparent",
|
||||
"We have transparent background by default");
|
||||
is(cs_default.color, "rgb(0, 0, 0)", "We have black text by default");
|
||||
is(cs_default_pseudo.content, "none", "We have no content by default");
|
||||
is(cs_default_pseudo.display, "inline", "Our ::before is inline by default");
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user