mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 115199 - CSS2 @page rule style support. r=dbaron
This commit is contained in:
parent
416d875170
commit
ec5ca0d279
@ -285,6 +285,7 @@
|
||||
#include "nsIDOMCSSSupportsRule.h"
|
||||
#include "nsIDOMMozCSSKeyframeRule.h"
|
||||
#include "nsIDOMMozCSSKeyframesRule.h"
|
||||
#include "nsIDOMCSSPageRule.h"
|
||||
#include "nsIDOMCSSPrimitiveValue.h"
|
||||
#include "nsIDOMCSSStyleRule.h"
|
||||
#include "nsIDOMCSSStyleSheet.h"
|
||||
@ -1616,6 +1617,9 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframesRule, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(CSSPageRule, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(MediaQueryList, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(MutationObserver, nsDOMMutationObserverSH,
|
||||
@ -4325,6 +4329,10 @@ nsDOMClassInfo::Init()
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframesRule)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(CSSPageRule, nsIDOMCSSPageRule)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSPageRule)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(MediaQueryList, nsIDOMMediaQueryList)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMediaQueryList)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
@ -478,6 +478,8 @@ DOMCI_CLASS(TouchEvent)
|
||||
DOMCI_CLASS(MozCSSKeyframeRule)
|
||||
DOMCI_CLASS(MozCSSKeyframesRule)
|
||||
|
||||
DOMCI_CLASS(CSSPageRule)
|
||||
|
||||
DOMCI_CLASS(MediaQueryList)
|
||||
|
||||
DOMCI_CLASS(MutationObserver)
|
||||
|
@ -5,10 +5,10 @@
|
||||
|
||||
#include "nsIDOMCSSRule.idl"
|
||||
|
||||
[scriptable, uuid(a6cf90bd-15b3-11d2-932e-00805f8add32)]
|
||||
[scriptable, uuid(6126024d-d716-4ad8-bc53-24dd6d5846b1)]
|
||||
interface nsIDOMCSSPageRule : nsIDOMCSSRule
|
||||
{
|
||||
attribute DOMString selectorText;
|
||||
//attribute DOMString selectorText;
|
||||
// raises(DOMException) on setting
|
||||
|
||||
readonly attribute nsIDOMCSSStyleDeclaration style;
|
||||
|
@ -400,12 +400,18 @@ protected:
|
||||
eParseDeclaration_InBraces = 1 << 0,
|
||||
eParseDeclaration_AllowImportant = 1 << 1
|
||||
};
|
||||
enum nsCSSContextType {
|
||||
eCSSContext_General,
|
||||
eCSSContext_Page
|
||||
};
|
||||
|
||||
css::Declaration* ParseDeclarationBlock(uint32_t aFlags);
|
||||
css::Declaration* ParseDeclarationBlock(uint32_t aFlags,
|
||||
nsCSSContextType aContext = eCSSContext_General);
|
||||
bool ParseDeclaration(css::Declaration* aDeclaration,
|
||||
uint32_t aFlags,
|
||||
bool aMustCallValueAppended,
|
||||
bool* aChanged);
|
||||
bool* aChanged,
|
||||
nsCSSContextType aContext = eCSSContext_General);
|
||||
|
||||
bool ParseProperty(nsCSSProperty aPropID);
|
||||
bool ParsePropertyByFunction(nsCSSProperty aPropID);
|
||||
@ -2260,13 +2266,6 @@ CSSParserImpl::ParseFontDescriptor(nsCSSFontFaceRule* aRule)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CSSParserImpl::ParsePageRule(RuleAppendFunc aAppendFunc, void* aData)
|
||||
{
|
||||
// XXX not yet implemented
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CSSParserImpl::ParseKeyframesRule(RuleAppendFunc aAppendFunc, void* aData)
|
||||
{
|
||||
@ -2303,6 +2302,26 @@ CSSParserImpl::ParseKeyframesRule(RuleAppendFunc aAppendFunc, void* aData)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CSSParserImpl::ParsePageRule(RuleAppendFunc aAppendFunc, void* aData)
|
||||
{
|
||||
// TODO: There can be page selectors after @page such as ":first", ":left".
|
||||
uint32_t parseFlags = eParseDeclaration_InBraces |
|
||||
eParseDeclaration_AllowImportant;
|
||||
nsAutoPtr<css::Declaration> declaration(
|
||||
ParseDeclarationBlock(parseFlags,
|
||||
eCSSContext_Page));
|
||||
if (!declaration) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Takes ownership of declaration.
|
||||
nsRefPtr<nsCSSPageRule> rule = new nsCSSPageRule(declaration);
|
||||
|
||||
(*aAppendFunc)(rule, aData);
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<nsCSSKeyframeRule>
|
||||
CSSParserImpl::ParseKeyframeRule()
|
||||
{
|
||||
@ -2316,7 +2335,6 @@ CSSParserImpl::ParseKeyframeRule()
|
||||
uint32_t parseFlags = eParseDeclaration_InBraces;
|
||||
nsAutoPtr<css::Declaration> declaration(ParseDeclarationBlock(parseFlags));
|
||||
if (!declaration) {
|
||||
REPORT_UNEXPECTED(PEBadSelectorKeyframeRuleIgnored);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -3892,7 +3910,7 @@ CSSParserImpl::ParseSelector(nsCSSSelectorList* aList,
|
||||
}
|
||||
|
||||
css::Declaration*
|
||||
CSSParserImpl::ParseDeclarationBlock(uint32_t aFlags)
|
||||
CSSParserImpl::ParseDeclarationBlock(uint32_t aFlags, nsCSSContextType aContext)
|
||||
{
|
||||
bool checkForBraces = (aFlags & eParseDeclaration_InBraces) != 0;
|
||||
|
||||
@ -3908,7 +3926,7 @@ CSSParserImpl::ParseDeclarationBlock(uint32_t aFlags)
|
||||
if (declaration) {
|
||||
for (;;) {
|
||||
bool changed;
|
||||
if (!ParseDeclaration(declaration, aFlags, true, &changed)) {
|
||||
if (!ParseDeclaration(declaration, aFlags, true, &changed, aContext)) {
|
||||
if (!SkipDeclaration(checkForBraces)) {
|
||||
break;
|
||||
}
|
||||
@ -4299,8 +4317,12 @@ bool
|
||||
CSSParserImpl::ParseDeclaration(css::Declaration* aDeclaration,
|
||||
uint32_t aFlags,
|
||||
bool aMustCallValueAppended,
|
||||
bool* aChanged)
|
||||
bool* aChanged,
|
||||
nsCSSContextType aContext)
|
||||
{
|
||||
NS_PRECONDITION(aContext == eCSSContext_General ||
|
||||
aContext == eCSSContext_Page,
|
||||
"Must be page or general context");
|
||||
bool checkForBraces = (aFlags & eParseDeclaration_InBraces) != 0;
|
||||
|
||||
mTempData.AssertInitialState();
|
||||
@ -4344,7 +4366,9 @@ CSSParserImpl::ParseDeclaration(css::Declaration* aDeclaration,
|
||||
// Map property name to its ID and then parse the property
|
||||
nsCSSProperty propID = nsCSSProps::LookupProperty(propertyName,
|
||||
nsCSSProps::eEnabled);
|
||||
if (eCSSProperty_UNKNOWN == propID) { // unknown property
|
||||
if (eCSSProperty_UNKNOWN == propID ||
|
||||
(aContext == nsCSSContextType::eCSSContext_Page &&
|
||||
!nsCSSProps::PropHasFlags(propID, CSS_PROPERTY_APPLIES_TO_PAGE_RULE))) { // unknown property
|
||||
if (!NonMozillaVendorIdentifier(propertyName)) {
|
||||
const PRUnichar *params[] = {
|
||||
propertyName.get()
|
||||
|
@ -1919,7 +1919,8 @@ CSS_PROP_SHORTHAND(
|
||||
margin,
|
||||
Margin,
|
||||
CSS_PROPERTY_PARSE_FUNCTION |
|
||||
CSS_PROPERTY_UNITLESS_LENGTH_QUIRK,
|
||||
CSS_PROPERTY_UNITLESS_LENGTH_QUIRK |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"")
|
||||
CSS_PROP_MARGIN(
|
||||
margin-bottom,
|
||||
@ -1928,7 +1929,8 @@ CSS_PROP_MARGIN(
|
||||
CSS_PROPERTY_PARSE_VALUE |
|
||||
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER |
|
||||
CSS_PROPERTY_STORES_CALC |
|
||||
CSS_PROPERTY_UNITLESS_LENGTH_QUIRK,
|
||||
CSS_PROPERTY_UNITLESS_LENGTH_QUIRK |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"",
|
||||
VARIANT_AHLP | VARIANT_CALC,
|
||||
nullptr,
|
||||
@ -1938,7 +1940,8 @@ CSS_PROP_SHORTHAND(
|
||||
-moz-margin-end,
|
||||
margin_end,
|
||||
CSS_PROP_DOMPROP_PREFIXED(MarginEnd),
|
||||
CSS_PROPERTY_PARSE_FUNCTION,
|
||||
CSS_PROPERTY_PARSE_FUNCTION |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"")
|
||||
#ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL
|
||||
CSS_PROP_MARGIN(
|
||||
@ -1947,7 +1950,8 @@ CSS_PROP_MARGIN(
|
||||
MarginEndValue,
|
||||
CSS_PROPERTY_PARSE_INACCESSIBLE |
|
||||
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER |
|
||||
CSS_PROPERTY_STORES_CALC,
|
||||
CSS_PROPERTY_STORES_CALC |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"",
|
||||
VARIANT_AHLP | VARIANT_CALC, // for internal use
|
||||
nullptr,
|
||||
@ -1959,7 +1963,8 @@ CSS_PROP_SHORTHAND(
|
||||
margin_left,
|
||||
MarginLeft,
|
||||
CSS_PROPERTY_PARSE_FUNCTION |
|
||||
CSS_PROPERTY_UNITLESS_LENGTH_QUIRK,
|
||||
CSS_PROPERTY_UNITLESS_LENGTH_QUIRK |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"")
|
||||
#ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL
|
||||
CSS_PROP_MARGIN(
|
||||
@ -1969,7 +1974,8 @@ CSS_PROP_MARGIN(
|
||||
CSS_PROPERTY_PARSE_INACCESSIBLE |
|
||||
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER |
|
||||
CSS_PROPERTY_REPORT_OTHER_NAME |
|
||||
CSS_PROPERTY_STORES_CALC,
|
||||
CSS_PROPERTY_STORES_CALC |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"",
|
||||
VARIANT_AHLP | VARIANT_CALC, // for internal use
|
||||
nullptr,
|
||||
@ -1981,7 +1987,8 @@ CSS_PROP_MARGIN(
|
||||
MarginLeftLTRSource,
|
||||
CSS_PROPERTY_PARSE_INACCESSIBLE |
|
||||
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER |
|
||||
CSS_PROPERTY_DIRECTIONAL_SOURCE,
|
||||
CSS_PROPERTY_DIRECTIONAL_SOURCE |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"",
|
||||
0,
|
||||
kBoxPropSourceKTable,
|
||||
@ -1993,7 +2000,8 @@ CSS_PROP_MARGIN(
|
||||
MarginLeftRTLSource,
|
||||
CSS_PROPERTY_PARSE_INACCESSIBLE |
|
||||
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER |
|
||||
CSS_PROPERTY_DIRECTIONAL_SOURCE,
|
||||
CSS_PROPERTY_DIRECTIONAL_SOURCE |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"",
|
||||
0,
|
||||
kBoxPropSourceKTable,
|
||||
@ -2005,7 +2013,8 @@ CSS_PROP_SHORTHAND(
|
||||
margin_right,
|
||||
MarginRight,
|
||||
CSS_PROPERTY_PARSE_FUNCTION |
|
||||
CSS_PROPERTY_UNITLESS_LENGTH_QUIRK,
|
||||
CSS_PROPERTY_UNITLESS_LENGTH_QUIRK |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"")
|
||||
#ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL
|
||||
CSS_PROP_MARGIN(
|
||||
@ -2015,7 +2024,8 @@ CSS_PROP_MARGIN(
|
||||
CSS_PROPERTY_PARSE_INACCESSIBLE |
|
||||
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER |
|
||||
CSS_PROPERTY_REPORT_OTHER_NAME |
|
||||
CSS_PROPERTY_STORES_CALC,
|
||||
CSS_PROPERTY_STORES_CALC |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"",
|
||||
VARIANT_AHLP | VARIANT_CALC, // for internal use
|
||||
nullptr,
|
||||
@ -2027,7 +2037,8 @@ CSS_PROP_MARGIN(
|
||||
MarginRightLTRSource,
|
||||
CSS_PROPERTY_PARSE_INACCESSIBLE |
|
||||
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER |
|
||||
CSS_PROPERTY_DIRECTIONAL_SOURCE,
|
||||
CSS_PROPERTY_DIRECTIONAL_SOURCE |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"",
|
||||
0,
|
||||
kBoxPropSourceKTable,
|
||||
@ -2039,7 +2050,8 @@ CSS_PROP_MARGIN(
|
||||
MarginRightRTLSource,
|
||||
CSS_PROPERTY_PARSE_INACCESSIBLE |
|
||||
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER |
|
||||
CSS_PROPERTY_DIRECTIONAL_SOURCE,
|
||||
CSS_PROPERTY_DIRECTIONAL_SOURCE |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"",
|
||||
0,
|
||||
kBoxPropSourceKTable,
|
||||
@ -2050,7 +2062,8 @@ CSS_PROP_SHORTHAND(
|
||||
-moz-margin-start,
|
||||
margin_start,
|
||||
CSS_PROP_DOMPROP_PREFIXED(MarginStart),
|
||||
CSS_PROPERTY_PARSE_FUNCTION,
|
||||
CSS_PROPERTY_PARSE_FUNCTION |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"")
|
||||
#ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL
|
||||
CSS_PROP_MARGIN(
|
||||
@ -2059,7 +2072,8 @@ CSS_PROP_MARGIN(
|
||||
MarginStartValue,
|
||||
CSS_PROPERTY_PARSE_INACCESSIBLE |
|
||||
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER |
|
||||
CSS_PROPERTY_STORES_CALC,
|
||||
CSS_PROPERTY_STORES_CALC |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"",
|
||||
VARIANT_AHLP | VARIANT_CALC, // for internal use
|
||||
nullptr,
|
||||
@ -2073,7 +2087,8 @@ CSS_PROP_MARGIN(
|
||||
CSS_PROPERTY_PARSE_VALUE |
|
||||
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER |
|
||||
CSS_PROPERTY_STORES_CALC |
|
||||
CSS_PROPERTY_UNITLESS_LENGTH_QUIRK,
|
||||
CSS_PROPERTY_UNITLESS_LENGTH_QUIRK |
|
||||
CSS_PROPERTY_APPLIES_TO_PAGE_RULE,
|
||||
"",
|
||||
VARIANT_AHLP | VARIANT_CALC,
|
||||
nullptr,
|
||||
|
@ -104,6 +104,9 @@ MOZ_STATIC_ASSERT((CSS_PROPERTY_PARSE_PROPERTY_MASK &
|
||||
// Does the property apply to ::-moz-placeholder?
|
||||
#define CSS_PROPERTY_APPLIES_TO_PLACEHOLDER (1<<18)
|
||||
|
||||
// This property is allowed in an @page rule.
|
||||
#define CSS_PROPERTY_APPLIES_TO_PAGE_RULE (1<<19)
|
||||
|
||||
/**
|
||||
* Types of animatable values.
|
||||
*/
|
||||
|
@ -979,6 +979,7 @@ struct RuleCascadeData {
|
||||
|
||||
nsTArray<nsFontFaceRuleContainer> mFontFaceRules;
|
||||
nsTArray<nsCSSKeyframesRule*> mKeyframesRules;
|
||||
nsTArray<nsCSSPageRule*> mPageRules;
|
||||
|
||||
// Looks up or creates the appropriate list in |mAttributeSelectors|.
|
||||
// Returns null only on allocation failure.
|
||||
@ -1029,6 +1030,7 @@ RuleCascadeData::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
|
||||
|
||||
n += mFontFaceRules.SizeOfExcludingThis(aMallocSizeOf);
|
||||
n += mKeyframesRules.SizeOfExcludingThis(aMallocSizeOf);
|
||||
n += mPageRules.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
return n;
|
||||
}
|
||||
@ -2681,6 +2683,24 @@ nsCSSRuleProcessor::AppendKeyframesRules(
|
||||
return true;
|
||||
}
|
||||
|
||||
// Append all the currently-active page rules to aArray. Return
|
||||
// true for success and false for failure.
|
||||
bool
|
||||
nsCSSRuleProcessor::AppendPageRules(
|
||||
nsPresContext* aPresContext,
|
||||
nsTArray<nsCSSPageRule*>& aArray)
|
||||
{
|
||||
RuleCascadeData* cascade = GetRuleCascade(aPresContext);
|
||||
|
||||
if (cascade) {
|
||||
if (!aArray.AppendElements(cascade->mPageRules)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCSSRuleProcessor::ClearRuleCascades()
|
||||
{
|
||||
@ -2979,11 +2999,13 @@ struct CascadeEnumData {
|
||||
CascadeEnumData(nsPresContext* aPresContext,
|
||||
nsTArray<nsFontFaceRuleContainer>& aFontFaceRules,
|
||||
nsTArray<nsCSSKeyframesRule*>& aKeyframesRules,
|
||||
nsTArray<nsCSSPageRule*>& aPageRules,
|
||||
nsMediaQueryResultCacheKey& aKey,
|
||||
uint8_t aSheetType)
|
||||
: mPresContext(aPresContext),
|
||||
mFontFaceRules(aFontFaceRules),
|
||||
mKeyframesRules(aKeyframesRules),
|
||||
mPageRules(aPageRules),
|
||||
mCacheKey(aKey),
|
||||
mSheetType(aSheetType)
|
||||
{
|
||||
@ -3006,6 +3028,7 @@ struct CascadeEnumData {
|
||||
nsPresContext* mPresContext;
|
||||
nsTArray<nsFontFaceRuleContainer>& mFontFaceRules;
|
||||
nsTArray<nsCSSKeyframesRule*>& mKeyframesRules;
|
||||
nsTArray<nsCSSPageRule*>& mPageRules;
|
||||
nsMediaQueryResultCacheKey& mCacheKey;
|
||||
PLArenaPool mArena;
|
||||
// Hooray, a manual PLDHashTable since nsClassHashtable doesn't
|
||||
@ -3022,6 +3045,7 @@ struct CascadeEnumData {
|
||||
* but kept in order per-weight, and
|
||||
* (2) add any @font-face rules, in order, into data->mFontFaceRules.
|
||||
* (3) add any @keyframes rules, in order, into data->mKeyframesRules.
|
||||
* (4) add any @page rules, in order, into data->mPageRules.
|
||||
*/
|
||||
static bool
|
||||
CascadeRuleEnumFunc(css::Rule* aRule, void* aData)
|
||||
@ -3074,7 +3098,12 @@ CascadeRuleEnumFunc(css::Rule* aRule, void* aData)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
else if (css::Rule::PAGE_RULE == type) {
|
||||
nsCSSPageRule* pageRule = static_cast<nsCSSPageRule*>(aRule);
|
||||
if (!data->mPageRules.AppendElement(pageRule)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3175,6 +3204,7 @@ nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext)
|
||||
if (newCascade) {
|
||||
CascadeEnumData data(aPresContext, newCascade->mFontFaceRules,
|
||||
newCascade->mKeyframesRules,
|
||||
newCascade->mPageRules,
|
||||
newCascade->mCacheKey,
|
||||
mSheetType);
|
||||
if (!data.mRulesByWeight.ops)
|
||||
|
@ -121,6 +121,9 @@ public:
|
||||
bool AppendKeyframesRules(nsPresContext* aPresContext,
|
||||
nsTArray<nsCSSKeyframesRule*>& aArray);
|
||||
|
||||
bool AppendPageRules(nsPresContext* aPresContext,
|
||||
nsTArray<nsCSSPageRule*>& aArray);
|
||||
|
||||
#ifdef DEBUG
|
||||
void AssertQuirksChangeOK() {
|
||||
NS_ASSERTION(!mRuleCascades, "can't toggle quirks style sheet without "
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "mozilla/dom/CSSStyleDeclarationBinding.h"
|
||||
#include "StyleRule.h"
|
||||
|
||||
namespace css = mozilla::css;
|
||||
|
||||
@ -2326,6 +2327,212 @@ nsCSSKeyframesRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
|
||||
return n;
|
||||
}
|
||||
|
||||
// -------------------------------------------
|
||||
// nsCSSPageStyleDeclaration
|
||||
//
|
||||
|
||||
nsCSSPageStyleDeclaration::nsCSSPageStyleDeclaration(nsCSSPageRule* aRule)
|
||||
: mRule(aRule)
|
||||
{
|
||||
}
|
||||
|
||||
nsCSSPageStyleDeclaration::~nsCSSPageStyleDeclaration()
|
||||
{
|
||||
NS_ASSERTION(!mRule, "DropReference not called.");
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSPageStyleDeclaration)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSPageStyleDeclaration)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsCSSPageStyleDeclaration)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSPageStyleDeclaration)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
|
||||
|
||||
css::Declaration*
|
||||
nsCSSPageStyleDeclaration::GetCSSDeclaration(bool aAllocate)
|
||||
{
|
||||
if (mRule) {
|
||||
return mRule->Declaration();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSPageStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
|
||||
{
|
||||
GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCSSPageStyleDeclaration::GetParentRule(nsIDOMCSSRule** aParent)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aParent);
|
||||
|
||||
NS_IF_ADDREF(*aParent = mRule);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCSSPageStyleDeclaration::SetCSSDeclaration(css::Declaration* aDecl)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aDecl, "must be non-null");
|
||||
mRule->ChangeDeclaration(aDecl);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
nsCSSPageStyleDeclaration::DocToUpdate()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsINode*
|
||||
nsCSSPageStyleDeclaration::GetParentObject()
|
||||
{
|
||||
return mRule ? mRule->GetDocument() : nullptr;
|
||||
}
|
||||
|
||||
// -------------------------------------------
|
||||
// nsCSSPageRule
|
||||
//
|
||||
|
||||
nsCSSPageRule::nsCSSPageRule(const nsCSSPageRule& aCopy)
|
||||
// copy everything except our reference count and mDOMDeclaration
|
||||
: Rule(aCopy)
|
||||
, mDeclaration(new css::Declaration(*aCopy.mDeclaration))
|
||||
{
|
||||
}
|
||||
|
||||
nsCSSPageRule::~nsCSSPageRule()
|
||||
{
|
||||
if (mDOMDeclaration) {
|
||||
mDOMDeclaration->DropReference();
|
||||
}
|
||||
}
|
||||
|
||||
/* virtual */ already_AddRefed<css::Rule>
|
||||
nsCSSPageRule::Clone() const
|
||||
{
|
||||
nsRefPtr<css::Rule> clone = new nsCSSPageRule(*this);
|
||||
return clone.forget();
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsCSSPageRule)
|
||||
NS_IMPL_RELEASE(nsCSSPageRule)
|
||||
|
||||
DOMCI_DATA(CSSPageRule, nsCSSPageRule)
|
||||
|
||||
// QueryInterface implementation for nsCSSPageRule
|
||||
NS_INTERFACE_MAP_BEGIN(nsCSSPageRule)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSPageRule)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSPageRule)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(nsCSSPageRule, Rule)
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
nsCSSPageRule::List(FILE* out, int32_t aIndent) const
|
||||
{
|
||||
// FIXME: WRITE ME
|
||||
}
|
||||
#endif
|
||||
|
||||
/* virtual */ int32_t
|
||||
nsCSSPageRule::GetType() const
|
||||
{
|
||||
return Rule::PAGE_RULE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCSSPageRule::GetType(uint16_t* aType)
|
||||
{
|
||||
*aType = nsIDOMCSSRule::PAGE_RULE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCSSPageRule::GetCssText(nsAString& aCssText)
|
||||
{
|
||||
aCssText.AppendLiteral("@page { ");
|
||||
nsAutoString tmp;
|
||||
mDeclaration->ToString(tmp);
|
||||
aCssText.Append(tmp);
|
||||
aCssText.AppendLiteral(" }");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCSSPageRule::SetCssText(const nsAString& aCssText)
|
||||
{
|
||||
// FIXME: implement???
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCSSPageRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
|
||||
{
|
||||
return Rule::GetParentStyleSheet(aSheet);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCSSPageRule::GetParentRule(nsIDOMCSSRule** aParentRule)
|
||||
{
|
||||
return Rule::GetParentRule(aParentRule);
|
||||
}
|
||||
|
||||
css::ImportantRule*
|
||||
nsCSSPageRule::GetImportantRule()
|
||||
{
|
||||
if (!mDeclaration->HasImportantData()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!mImportantRule) {
|
||||
mImportantRule = new css::ImportantRule(mDeclaration);
|
||||
}
|
||||
return mImportantRule;
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsCSSPageRule::MapRuleInfoInto(nsRuleData* aRuleData)
|
||||
{
|
||||
mDeclaration->MapNormalRuleInfoInto(aRuleData);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCSSPageRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
|
||||
{
|
||||
if (!mDOMDeclaration) {
|
||||
mDOMDeclaration = new nsCSSPageStyleDeclaration(this);
|
||||
}
|
||||
NS_ADDREF(*aStyle = mDOMDeclaration);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSPageRule::ChangeDeclaration(css::Declaration* aDeclaration)
|
||||
{
|
||||
mImportantRule = nullptr;
|
||||
mDeclaration = aDeclaration;
|
||||
|
||||
nsCSSStyleSheet* sheet = GetStyleSheet();
|
||||
if (sheet) {
|
||||
sheet->SetModifiedByChildRule();
|
||||
}
|
||||
}
|
||||
|
||||
/* virtual */ size_t
|
||||
nsCSSPageRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
|
||||
{
|
||||
return aMallocSizeOf(this);
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
CSSSupportsRule::CSSSupportsRule(bool aConditionMet,
|
||||
|
@ -28,12 +28,8 @@
|
||||
#include "nsTArray.h"
|
||||
#include "nsDOMCSSDeclaration.h"
|
||||
#include "Declaration.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
class StyleRule;
|
||||
}
|
||||
}
|
||||
#include "nsIDOMCSSPageRule.h"
|
||||
#include "StyleRule.h"
|
||||
|
||||
class nsMediaList;
|
||||
|
||||
@ -433,6 +429,79 @@ private:
|
||||
nsString mName;
|
||||
};
|
||||
|
||||
class nsCSSPageRule;
|
||||
|
||||
class nsCSSPageStyleDeclaration MOZ_FINAL : public nsDOMCSSDeclaration
|
||||
{
|
||||
public:
|
||||
nsCSSPageStyleDeclaration(nsCSSPageRule *aRule);
|
||||
virtual ~nsCSSPageStyleDeclaration();
|
||||
|
||||
NS_IMETHOD GetParentRule(nsIDOMCSSRule **aParent) MOZ_OVERRIDE;
|
||||
void DropReference() { mRule = nullptr; }
|
||||
virtual mozilla::css::Declaration* GetCSSDeclaration(bool aAllocate) MOZ_OVERRIDE;
|
||||
virtual nsresult SetCSSDeclaration(mozilla::css::Declaration* aDecl) MOZ_OVERRIDE;
|
||||
virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) MOZ_OVERRIDE;
|
||||
virtual nsIDocument* DocToUpdate() MOZ_OVERRIDE;
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsCSSPageStyleDeclaration,
|
||||
nsICSSDeclaration)
|
||||
|
||||
virtual nsINode *GetParentObject();
|
||||
|
||||
protected:
|
||||
// This reference is not reference-counted. The rule object tells us
|
||||
// when it's about to go away.
|
||||
nsCSSPageRule *mRule;
|
||||
};
|
||||
|
||||
class nsCSSPageRule MOZ_FINAL : public mozilla::css::Rule,
|
||||
public nsIDOMCSSPageRule
|
||||
{
|
||||
public:
|
||||
// WARNING: Steals the contents of aDeclaration
|
||||
nsCSSPageRule(nsAutoPtr<mozilla::css::Declaration> aDeclaration)
|
||||
: mDeclaration(aDeclaration),
|
||||
mImportantRule(nullptr)
|
||||
{
|
||||
}
|
||||
private:
|
||||
nsCSSPageRule(const nsCSSPageRule& aCopy);
|
||||
~nsCSSPageRule();
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIStyleRule methods
|
||||
#ifdef DEBUG
|
||||
virtual void List(FILE* out = stdout, int32_t aIndent = 0) const;
|
||||
#endif
|
||||
|
||||
// Rule methods
|
||||
DECL_STYLE_RULE_INHERIT
|
||||
virtual int32_t GetType() const;
|
||||
virtual already_AddRefed<mozilla::css::Rule> Clone() const;
|
||||
|
||||
// nsIDOMCSSRule interface
|
||||
NS_DECL_NSIDOMCSSRULE
|
||||
|
||||
// nsIDOMCSSPageRule interface
|
||||
NS_DECL_NSIDOMCSSPAGERULE
|
||||
|
||||
mozilla::css::Declaration* Declaration() { return mDeclaration; }
|
||||
|
||||
void ChangeDeclaration(mozilla::css::Declaration* aDeclaration);
|
||||
|
||||
mozilla::css::ImportantRule* GetImportantRule();
|
||||
|
||||
virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
|
||||
private:
|
||||
nsAutoPtr<mozilla::css::Declaration> mDeclaration;
|
||||
// lazily created when needed:
|
||||
nsRefPtr<nsCSSPageStyleDeclaration> mDOMDeclaration;
|
||||
nsRefPtr<mozilla::css::ImportantRule> mImportantRule;
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class CSSSupportsRule : public css::GroupRule,
|
||||
|
@ -1165,6 +1165,24 @@ nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag,
|
||||
FileRules(EnumRulesMatching<AnonBoxRuleProcessorData>, &data, nullptr,
|
||||
&ruleWalker);
|
||||
|
||||
if (aPseudoTag == nsCSSAnonBoxes::pageContent) {
|
||||
// Add any @page rules that are specified.
|
||||
nsTArray<nsCSSPageRule*> rules;
|
||||
nsTArray<css::ImportantRule*> importantRules;
|
||||
nsPresContext* presContext = PresContext();
|
||||
presContext->StyleSet()->AppendPageRules(presContext, rules);
|
||||
for (uint32_t i = 0, i_end = rules.Length(); i != i_end; ++i) {
|
||||
ruleWalker.Forward(rules[i]);
|
||||
css::ImportantRule* importantRule = rules[i]->GetImportantRule();
|
||||
if (importantRule) {
|
||||
importantRules.AppendElement(importantRule);
|
||||
}
|
||||
}
|
||||
for (uint32_t i = 0, i_end = importantRules.Length(); i != i_end; ++i) {
|
||||
ruleWalker.Forward(importantRules[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return GetContext(aParentContext, ruleWalker.CurrentNode(), nullptr,
|
||||
false, false,
|
||||
aPseudoTag, nsCSSPseudoElements::ePseudo_AnonBox,
|
||||
@ -1242,6 +1260,21 @@ nsStyleSet::AppendKeyframesRules(nsPresContext* aPresContext,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsStyleSet::AppendPageRules(nsPresContext* aPresContext,
|
||||
nsTArray<nsCSSPageRule*>& aArray)
|
||||
{
|
||||
NS_ENSURE_FALSE(mInShutdown, false);
|
||||
|
||||
for (uint32_t i = 0; i < NS_ARRAY_LENGTH(gCSSSheetTypes); ++i) {
|
||||
nsCSSRuleProcessor* ruleProc = static_cast<nsCSSRuleProcessor*>
|
||||
(mRuleProcessors[gCSSSheetTypes[i]].get());
|
||||
if (ruleProc && !ruleProc->AppendPageRules(aPresContext, aArray))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleSet::BeginShutdown(nsPresContext* aPresContext)
|
||||
{
|
||||
|
@ -29,6 +29,7 @@
|
||||
class nsIURI;
|
||||
class nsCSSFontFaceRule;
|
||||
class nsCSSKeyframesRule;
|
||||
class nsCSSPageRule;
|
||||
class nsRuleWalker;
|
||||
struct RuleProcessorData;
|
||||
struct TreeMatchContext;
|
||||
@ -152,6 +153,11 @@ class nsStyleSet
|
||||
bool AppendKeyframesRules(nsPresContext* aPresContext,
|
||||
nsTArray<nsCSSKeyframesRule*>& aArray);
|
||||
|
||||
// Append all the currently-active page rules to aArray. Return
|
||||
// true for success and false for failure.
|
||||
bool AppendPageRules(nsPresContext* aPresContext,
|
||||
nsTArray<nsCSSPageRule*>& aArray);
|
||||
|
||||
// Begin ignoring style context destruction, to avoid lots of unnecessary
|
||||
// work on document teardown.
|
||||
void BeginShutdown(nsPresContext* aPresContext);
|
||||
|
@ -187,6 +187,7 @@ MOCHITEST_FILES = test_acid3_test46.html \
|
||||
visited_image_loading_frame_empty.html \
|
||||
test_load_events_on_stylesheets.html \
|
||||
test_bug721136.html \
|
||||
test_page_parser.html \
|
||||
test_bug732153.html \
|
||||
test_bug732209.html \
|
||||
bug732209-css.sjs \
|
||||
|
109
layout/style/test/test_page_parser.html
Normal file
109
layout/style/test/test_page_parser.html
Normal file
@ -0,0 +1,109 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=115199 -->
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Test of @page parser</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<p>@page parsing (<a
|
||||
target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=115199"
|
||||
>bug 115199</a>)</p>
|
||||
<pre id="display"></pre>
|
||||
<style type="text/css" id="testbox"></style>
|
||||
<script class="testbody" type="text/javascript">
|
||||
function _(b) { return "@page { " + b + " }"; };
|
||||
|
||||
var testset = [
|
||||
// CSS 2.1 only allows margin properties in the page rule.
|
||||
|
||||
// Check a bad property.
|
||||
{ rule: "position: absolute;" },
|
||||
|
||||
// Check good properties.
|
||||
// NOTE: The margin-*-value and margin-*-source properties are not really
|
||||
// expected and will need to be removed once bug 241234 is addressed.
|
||||
{ rule: _("margin: 2in;"), expected: {
|
||||
"margin-top": "2in",
|
||||
"margin-right-value": "2in",
|
||||
"margin-bottom": "2in",
|
||||
"margin-left-value": "2in",
|
||||
"margin-left-ltr-source": "physical",
|
||||
"margin-left-rtl-source": "physical",
|
||||
"margin-right-ltr-source": "physical",
|
||||
"margin-right-rtl-source": "physical"
|
||||
}},
|
||||
{ rule: _("margin-top: 2in;"), expected: {"margin-top": "2in"}},
|
||||
{ rule: _("margin-left: 2in;"), expected: {
|
||||
"margin-left-value": "2in",
|
||||
"margin-left-ltr-source": "physical",
|
||||
"margin-left-rtl-source": "physical",
|
||||
}},
|
||||
{ rule: _("margin-bottom: 2in;"), expected: {"margin-bottom": "2in"}},
|
||||
{ rule: _("margin-right: 2in;"), expected: {
|
||||
"margin-right-value": "2in",
|
||||
"margin-right-ltr-source": "physical",
|
||||
"margin-right-rtl-source": "physical",
|
||||
}}
|
||||
];
|
||||
|
||||
var display = document.getElementById("display");
|
||||
var sheet = document.styleSheets[1];
|
||||
|
||||
for (var curTest = 0; curTest < testset.length; curTest++) {
|
||||
try {
|
||||
while(sheet.cssRules.length > 0)
|
||||
sheet.deleteRule(0);
|
||||
sheet.insertRule(testset[curTest].rule, 0);
|
||||
} catch (e) {
|
||||
ok(e.name == "SyntaxError"
|
||||
&& e instanceof DOMException
|
||||
&& e.code == DOMException.SYNTAX_ERR
|
||||
&& !('expected' in testset[curTest]),
|
||||
testset[curTest].rule + " syntax error thrown", e);
|
||||
}
|
||||
|
||||
try {
|
||||
if (testset[curTest].expected) {
|
||||
is(sheet.cssRules.length, 1,
|
||||
testset[curTest].rule + " rule count");
|
||||
is(sheet.cssRules[0].type, CSSRule.PAGE_RULE,
|
||||
testset[curTest].rule + " rule type");
|
||||
|
||||
var expected = testset[curTest].expected;
|
||||
var s = sheet.cssRules[0].style;
|
||||
var n = 0;
|
||||
|
||||
// everything is set that should be
|
||||
for (var name in expected) {
|
||||
is(s.getPropertyValue(name), expected[name],
|
||||
testset[curTest].rule + " (prop " + name + ")");
|
||||
n++;
|
||||
}
|
||||
// nothing else is set
|
||||
is(s.length, n, testset[curTest].rule + "prop count");
|
||||
for (var i = 0; i < s.length; i++) {
|
||||
ok(s[i] in expected, testset[curTest].rule,
|
||||
"Unexpected item #" + i + ": " + s[i]);
|
||||
}
|
||||
} else {
|
||||
if (sheet.cssRules.length == 0) {
|
||||
is(sheet.cssRules.length, 0,
|
||||
testset[curTest].rule + " rule count (0)");
|
||||
} else {
|
||||
is(sheet.cssRules.length, 1,
|
||||
testset[curTest].rule + " rule count (1 non-page)");
|
||||
isnot(sheet.cssRules[0].type, CSSRule.PAGE_RULE,
|
||||
testset[curTest].rule + " rule type (1 non-page)");
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
ok(false, testset[curTest].rule, "During test: " + e);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -193,6 +193,7 @@
|
||||
|
||||
*|*::-moz-pagecontent {
|
||||
display: block !important;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
*|*::-moz-pagebreak {
|
||||
|
Loading…
Reference in New Issue
Block a user