Bug 1665816 - CSSOM should respect rule-level property restrictions. r=jwatt

Differential Revision: https://phabricator.services.mozilla.com/D90729
This commit is contained in:
Emilio Cobos Álvarez 2020-09-21 09:57:46 +00:00
Родитель 7c26de15f3
Коммит 3cfb419d00
19 изменённых файлов: 161 добавлений и 81 удалений

Просмотреть файл

@ -22,6 +22,7 @@
#include "mozilla/ServoUtils.h" #include "mozilla/ServoUtils.h"
#include "mozilla/ShadowParts.h" #include "mozilla/ShadowParts.h"
#include "mozilla/DeclarationBlock.h" #include "mozilla/DeclarationBlock.h"
#include "mozilla/dom/CSSRuleBinding.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
#include "nsHTMLCSSStyleSheet.h" #include "nsHTMLCSSStyleSheet.h"
@ -1732,10 +1733,10 @@ bool nsAttrValue::ParseStyleAttribute(const nsAString& aString,
nsCOMPtr<nsIReferrerInfo> referrerInfo = nsCOMPtr<nsIReferrerInfo> referrerInfo =
dom::ReferrerInfo::CreateForInternalCSSResources(ownerDoc); dom::ReferrerInfo::CreateForInternalCSSResources(ownerDoc);
RefPtr<URLExtraData> data = auto data = MakeRefPtr<URLExtraData>(baseURI, referrerInfo, principal);
new URLExtraData(baseURI, referrerInfo, principal);
RefPtr<DeclarationBlock> decl = DeclarationBlock::FromCssText( RefPtr<DeclarationBlock> decl = DeclarationBlock::FromCssText(
aString, data, ownerDoc->GetCompatibilityMode(), ownerDoc->CSSLoader()); aString, data, ownerDoc->GetCompatibilityMode(), ownerDoc->CSSLoader(),
dom::CSSRule_Binding::STYLE_RULE);
if (!decl) { if (!decl) {
return false; return false;
} }

Просмотреть файл

@ -2182,14 +2182,9 @@ void CanvasRenderingContext2D::SetShadowColor(const nsAString& aShadowColor) {
static already_AddRefed<RawServoDeclarationBlock> CreateDeclarationForServo( static already_AddRefed<RawServoDeclarationBlock> CreateDeclarationForServo(
nsCSSPropertyID aProperty, const nsAString& aPropertyValue, nsCSSPropertyID aProperty, const nsAString& aPropertyValue,
Document* aDocument) { Document* aDocument) {
nsCOMPtr<nsIReferrerInfo> referrerInfo = ServoCSSParser::ParsingEnvironment env{aDocument->DefaultStyleAttrURLData(),
ReferrerInfo::CreateForInternalCSSResources(aDocument); aDocument->GetCompatibilityMode(),
aDocument->CSSLoader()};
RefPtr<URLExtraData> data = new URLExtraData(
aDocument->GetDocBaseURI(), referrerInfo, aDocument->NodePrincipal());
ServoCSSParser::ParsingEnvironment env(
data, aDocument->GetCompatibilityMode(), aDocument->CSSLoader());
RefPtr<RawServoDeclarationBlock> servoDeclarations = RefPtr<RawServoDeclarationBlock> servoDeclarations =
ServoCSSParser::ParseProperty(aProperty, aPropertyValue, env); ServoCSSParser::ParseProperty(aProperty, aPropertyValue, env);
@ -2203,9 +2198,9 @@ static already_AddRefed<RawServoDeclarationBlock> CreateDeclarationForServo(
if (aProperty == eCSSProperty_font) { if (aProperty == eCSSProperty_font) {
const nsCString normalString = "normal"_ns; const nsCString normalString = "normal"_ns;
Servo_DeclarationBlock_SetPropertyById( Servo_DeclarationBlock_SetPropertyById(
servoDeclarations, eCSSProperty_line_height, &normalString, false, data, servoDeclarations, eCSSProperty_line_height, &normalString, false,
ParsingMode::Default, aDocument->GetCompatibilityMode(), env.mUrlExtraData, ParsingMode::Default, env.mCompatMode, env.mLoader,
aDocument->CSSLoader(), {}); env.mRuleType, {});
} }
return servoDeclarations.forget(); return servoDeclarations.forget();

Просмотреть файл

@ -8,6 +8,7 @@
#include "mozilla/dom/MutationEventBinding.h" #include "mozilla/dom/MutationEventBinding.h"
#include "mozilla/dom/MutationObservers.h" #include "mozilla/dom/MutationObservers.h"
#include "mozilla/dom/CSSRuleBinding.h"
#include "mozilla/dom/SVGElementBinding.h" #include "mozilla/dom/SVGElementBinding.h"
#include "mozilla/dom/SVGGeometryElement.h" #include "mozilla/dom/SVGGeometryElement.h"
#include "mozilla/dom/SVGLengthBinding.h" #include "mozilla/dom/SVGLengthBinding.h"
@ -1148,12 +1149,13 @@ void MappedAttrParser::ParseMappedAttrValue(nsAtom* aMappedAttrName,
nsCOMPtr<nsIReferrerInfo> referrerInfo = nsCOMPtr<nsIReferrerInfo> referrerInfo =
ReferrerInfo::CreateForSVGResources(mElement->OwnerDoc()); ReferrerInfo::CreateForSVGResources(mElement->OwnerDoc());
RefPtr<URLExtraData> data = auto data = MakeRefPtr<URLExtraData>(mBaseURI, referrerInfo,
new URLExtraData(mBaseURI, referrerInfo, mElement->NodePrincipal()); mElement->NodePrincipal());
changed = Servo_DeclarationBlock_SetPropertyById( changed = Servo_DeclarationBlock_SetPropertyById(
mDecl->Raw(), propertyID, &value, false, data, mDecl->Raw(), propertyID, &value, false, data,
ParsingMode::AllowUnitlessLength, ParsingMode::AllowUnitlessLength,
mElement->OwnerDoc()->GetCompatibilityMode(), mLoader, {}); mElement->OwnerDoc()->GetCompatibilityMode(), mLoader,
CSSRule_Binding::STYLE_RULE, {});
// TODO(emilio): If we want to record these from CSSOM more generally, we // TODO(emilio): If we want to record these from CSSOM more generally, we
// can pass the document use counters down the FFI call. For now manually // can pass the document use counters down the FFI call. For now manually

Просмотреть файл

@ -14,6 +14,7 @@
#include "nsIDOMXULSelectCntrlItemEl.h" #include "nsIDOMXULSelectCntrlItemEl.h"
#include "mozilla/dom/BindContext.h" #include "mozilla/dom/BindContext.h"
#include "mozilla/dom/Document.h" #include "mozilla/dom/Document.h"
#include "mozilla/dom/CSSRuleBinding.h"
#include "mozilla/ClearOnShutdown.h" #include "mozilla/ClearOnShutdown.h"
#include "mozilla/EventListenerManager.h" #include "mozilla/EventListenerManager.h"
#include "mozilla/EventStateManager.h" #include "mozilla/EventStateManager.h"
@ -1506,13 +1507,12 @@ nsresult nsXULPrototypeElement::SetAttrAt(uint32_t aPos,
// as has been discussed, the CSP should be checked here to see if // as has been discussed, the CSP should be checked here to see if
// inline styles are allowed to be applied. // inline styles are allowed to be applied.
// XXX No specific specs talk about xul and referrer policy, pass Unset // XXX No specific specs talk about xul and referrer policy, pass Unset
nsCOMPtr<nsIReferrerInfo> referrerInfo = auto referrerInfo =
new ReferrerInfo(aDocumentURI, ReferrerPolicy::_empty); MakeRefPtr<ReferrerInfo>(aDocumentURI, ReferrerPolicy::_empty);
auto data = MakeRefPtr<URLExtraData>(aDocumentURI, referrerInfo, principal);
RefPtr<URLExtraData> data =
new URLExtraData(aDocumentURI, referrerInfo, principal);
RefPtr<DeclarationBlock> declaration = DeclarationBlock::FromCssText( RefPtr<DeclarationBlock> declaration = DeclarationBlock::FromCssText(
aValue, data, eCompatibility_FullStandards, nullptr); aValue, data, eCompatibility_FullStandards, nullptr,
CSSRule_Binding::STYLE_RULE);
if (declaration) { if (declaration) {
mAttributes[aPos].mValue.SetTo(declaration.forget(), &aValue); mAttributes[aPos].mValue.SetTo(declaration.forget(), &aValue);

Просмотреть файл

@ -56,7 +56,7 @@ class CSSKeyframeDeclaration : public nsDOMCSSDeclaration {
} }
ParsingEnvironment GetParsingEnvironment( ParsingEnvironment GetParsingEnvironment(
nsIPrincipal* aSubjectPrincipal) const final { nsIPrincipal* aSubjectPrincipal) const final {
return GetParsingEnvironmentForRule(mRule); return GetParsingEnvironmentForRule(mRule, CSSRule_Binding::KEYFRAME_RULE);
} }
Document* DocToUpdate() final { return nullptr; } Document* DocToUpdate() final { return nullptr; }

Просмотреть файл

@ -73,7 +73,7 @@ nsresult CSSPageRuleDeclaration::SetCSSDeclaration(
nsDOMCSSDeclaration::ParsingEnvironment nsDOMCSSDeclaration::ParsingEnvironment
CSSPageRuleDeclaration::GetParsingEnvironment( CSSPageRuleDeclaration::GetParsingEnvironment(
nsIPrincipal* aSubjectPrincipal) const { nsIPrincipal* aSubjectPrincipal) const {
return GetParsingEnvironmentForRule(Rule()); return GetParsingEnvironmentForRule(Rule(), CSSRule_Binding::PAGE_RULE);
} }
// -- CSSPageRule -------------------------------------------------- // -- CSSPageRule --------------------------------------------------

Просмотреть файл

@ -83,7 +83,7 @@ Document* CSSStyleRuleDeclaration::DocToUpdate() { return nullptr; }
nsDOMCSSDeclaration::ParsingEnvironment nsDOMCSSDeclaration::ParsingEnvironment
CSSStyleRuleDeclaration::GetParsingEnvironment( CSSStyleRuleDeclaration::GetParsingEnvironment(
nsIPrincipal* aSubjectPrincipal) const { nsIPrincipal* aSubjectPrincipal) const {
return GetParsingEnvironmentForRule(Rule()); return GetParsingEnvironmentForRule(Rule(), CSSRule_Binding::STYLE_RULE);
} }
// -- CSSStyleRule -------------------------------------------------- // -- CSSStyleRule --------------------------------------------------

Просмотреть файл

@ -7,24 +7,12 @@
#include "mozilla/DeclarationBlock.h" #include "mozilla/DeclarationBlock.h"
#include "mozilla/css/Rule.h" #include "mozilla/css/Rule.h"
#include "mozilla/ServoBindings.h"
#include "nsCSSProps.h" #include "nsCSSProps.h"
#include "nsIMemoryReporter.h" #include "nsIMemoryReporter.h"
namespace mozilla { namespace mozilla {
/* static */
already_AddRefed<DeclarationBlock> DeclarationBlock::FromCssText(
const nsAString& aCssText, URLExtraData* aExtraData, nsCompatibility aMode,
css::Loader* aLoader) {
NS_ConvertUTF16toUTF8 value(aCssText);
RefPtr<RawServoDeclarationBlock> raw =
Servo_ParseStyleAttribute(&value, aExtraData, aMode, aLoader).Consume();
RefPtr<DeclarationBlock> decl = new DeclarationBlock(raw.forget());
return decl.forget();
}
MOZ_DEFINE_MALLOC_SIZE_OF(ServoDeclarationBlockMallocSizeOf) MOZ_DEFINE_MALLOC_SIZE_OF(ServoDeclarationBlockMallocSizeOf)
MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(ServoDeclarationBlockEnclosingSizeOf) MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(ServoDeclarationBlockEnclosingSizeOf)

Просмотреть файл

@ -147,7 +147,13 @@ class DeclarationBlock final {
static already_AddRefed<DeclarationBlock> FromCssText( static already_AddRefed<DeclarationBlock> FromCssText(
const nsAString& aCssText, URLExtraData* aExtraData, const nsAString& aCssText, URLExtraData* aExtraData,
nsCompatibility aMode, css::Loader* aLoader); nsCompatibility aMode, css::Loader* aLoader, uint16_t aRuleType) {
NS_ConvertUTF16toUTF8 value(aCssText);
RefPtr<RawServoDeclarationBlock> raw =
Servo_ParseStyleAttribute(&value, aExtraData, aMode, aLoader, aRuleType)
.Consume();
return MakeAndAddRef<DeclarationBlock>(raw.forget());
}
RawServoDeclarationBlock* Raw() const { return mRaw; } RawServoDeclarationBlock* Raw() const { return mRaw; }
RawServoDeclarationBlock* const* RefRaw() const { RawServoDeclarationBlock* const* RefRaw() const {

Просмотреть файл

@ -38,7 +38,8 @@ already_AddRefed<RawServoDeclarationBlock> ServoCSSParser::ParseProperty(
NS_ConvertUTF16toUTF8 value(aValue); NS_ConvertUTF16toUTF8 value(aValue);
return Servo_ParseProperty( return Servo_ParseProperty(
aProperty, &value, aParsingEnvironment.mUrlExtraData, aParsingMode, aProperty, &value, aParsingEnvironment.mUrlExtraData, aParsingMode,
aParsingEnvironment.mCompatMode, aParsingEnvironment.mLoader) aParsingEnvironment.mCompatMode, aParsingEnvironment.mLoader,
aParsingEnvironment.mRuleType)
.Consume(); .Consume();
} }
@ -80,7 +81,6 @@ already_AddRefed<URLExtraData> ServoCSSParser::GetURLExtraData(
/* static */ ServoCSSParser::ParsingEnvironment /* static */ ServoCSSParser::ParsingEnvironment
ServoCSSParser::GetParsingEnvironment(Document* aDocument) { ServoCSSParser::GetParsingEnvironment(Document* aDocument) {
return ParsingEnvironment(GetURLExtraData(aDocument), return {GetURLExtraData(aDocument), aDocument->GetCompatibilityMode(),
aDocument->GetCompatibilityMode(), aDocument->CSSLoader()};
aDocument->CSSLoader());
} }

Просмотреть файл

@ -140,7 +140,8 @@ void nsDOMCSSDeclaration::SetCssText(const nsAString& aCssText,
} }
RefPtr<DeclarationBlock> newdecl = DeclarationBlock::FromCssText( RefPtr<DeclarationBlock> newdecl = DeclarationBlock::FromCssText(
aCssText, servoEnv.mUrlExtraData, servoEnv.mCompatMode, servoEnv.mLoader); aCssText, servoEnv.mUrlExtraData, servoEnv.mCompatMode, servoEnv.mLoader,
servoEnv.mRuleType);
aRv = SetCSSDeclaration(newdecl, &closureData); aRv = SetCSSDeclaration(newdecl, &closureData);
} }
@ -237,10 +238,17 @@ void nsDOMCSSDeclaration::RemoveProperty(const nsACString& aPropertyName,
} }
/* static */ nsDOMCSSDeclaration::ParsingEnvironment /* static */ nsDOMCSSDeclaration::ParsingEnvironment
nsDOMCSSDeclaration::GetParsingEnvironmentForRule(const css::Rule* aRule) { nsDOMCSSDeclaration::GetParsingEnvironmentForRule(const css::Rule* aRule,
StyleSheet* sheet = aRule ? aRule->GetStyleSheet() : nullptr; uint16_t aRuleType) {
if (!aRule) {
return {};
}
MOZ_ASSERT(aRule->Type() == aRuleType);
StyleSheet* sheet = aRule->GetStyleSheet();
if (!sheet) { if (!sheet) {
return {nullptr, eCompatibility_FullStandards, nullptr}; return {};
} }
if (Document* document = sheet->GetAssociatedDocument()) { if (Document* document = sheet->GetAssociatedDocument()) {
@ -248,6 +256,7 @@ nsDOMCSSDeclaration::GetParsingEnvironmentForRule(const css::Rule* aRule) {
sheet->URLData(), sheet->URLData(),
document->GetCompatibilityMode(), document->GetCompatibilityMode(),
document->CSSLoader(), document->CSSLoader(),
aRuleType,
}; };
} }
@ -255,6 +264,7 @@ nsDOMCSSDeclaration::GetParsingEnvironmentForRule(const css::Rule* aRule) {
sheet->URLData(), sheet->URLData(),
eCompatibility_FullStandards, eCompatibility_FullStandards,
nullptr, nullptr,
aRuleType,
}; };
} }
@ -311,7 +321,8 @@ nsresult nsDOMCSSDeclaration::ParsePropertyValue(
[&](DeclarationBlock* decl, ParsingEnvironment& env) { [&](DeclarationBlock* decl, ParsingEnvironment& env) {
return Servo_DeclarationBlock_SetPropertyById( return Servo_DeclarationBlock_SetPropertyById(
decl->Raw(), aPropID, &aPropValue, aIsImportant, env.mUrlExtraData, decl->Raw(), aPropID, &aPropValue, aIsImportant, env.mUrlExtraData,
ParsingMode::Default, env.mCompatMode, env.mLoader, closure); ParsingMode::Default, env.mCompatMode, env.mLoader, env.mRuleType,
closure);
}); });
} }
@ -334,7 +345,7 @@ nsresult nsDOMCSSDeclaration::ParseCustomPropertyValue(
return Servo_DeclarationBlock_SetProperty( return Servo_DeclarationBlock_SetProperty(
decl->Raw(), &aPropertyName, &aPropValue, aIsImportant, decl->Raw(), &aPropertyName, &aPropValue, aIsImportant,
env.mUrlExtraData, ParsingMode::Default, env.mCompatMode, env.mUrlExtraData, ParsingMode::Default, env.mCompatMode,
env.mLoader, closure); env.mLoader, env.mRuleType, closure);
}); });
} }

Просмотреть файл

@ -125,25 +125,15 @@ class nsDOMCSSDeclaration : public nsICSSDeclaration {
virtual void IndexedGetter(uint32_t aIndex, bool& aFound, virtual void IndexedGetter(uint32_t aIndex, bool& aFound,
nsACString& aPropName) override; nsACString& aPropName) override;
virtual JSObject* WrapObject(JSContext* aCx, JSObject* WrapObject(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
JS::Handle<JSObject*> aGivenProto) override;
// Information needed to parse a declaration for Servo side. // Information needed to parse a declaration for Servo side.
// Put this in public so other Servo parsing functions can reuse this. // Put this in public so other Servo parsing functions can reuse this.
struct MOZ_STACK_CLASS ParsingEnvironment { struct MOZ_STACK_CLASS ParsingEnvironment {
RefPtr<mozilla::URLExtraData> mUrlExtraData; RefPtr<mozilla::URLExtraData> mUrlExtraData;
nsCompatibility mCompatMode; nsCompatibility mCompatMode = eCompatibility_FullStandards;
mozilla::css::Loader* mLoader; mozilla::css::Loader* mLoader = nullptr;
uint16_t mRuleType{0};
ParsingEnvironment(mozilla::URLExtraData* aUrlData,
nsCompatibility aCompatMode,
mozilla::css::Loader* aLoader)
: mUrlExtraData(aUrlData), mCompatMode(aCompatMode), mLoader(aLoader) {}
ParsingEnvironment(already_AddRefed<mozilla::URLExtraData> aUrlData,
nsCompatibility aCompatMode,
mozilla::css::Loader* aLoader)
: mUrlExtraData(aUrlData), mCompatMode(aCompatMode), mLoader(aLoader) {}
}; };
protected: protected:
@ -189,8 +179,11 @@ class nsDOMCSSDeclaration : public nsICSSDeclaration {
// An implementation for GetParsingEnvironment for callers wrapping a // An implementation for GetParsingEnvironment for callers wrapping a
// css::Rule. // css::Rule.
//
// The RuleType argument is just to avoid a virtual call, since all callers
// know it statically. Should be equal to aRule->Type().
static ParsingEnvironment GetParsingEnvironmentForRule( static ParsingEnvironment GetParsingEnvironmentForRule(
const mozilla::css::Rule* aRule); const mozilla::css::Rule* aRule, uint16_t aRuleType);
nsresult ParsePropertyValue(const nsCSSPropertyID aPropID, nsresult ParsePropertyValue(const nsCSSPropertyID aPropID,
const nsACString& aPropValue, bool aIsImportant, const nsACString& aPropValue, bool aIsImportant,

Просмотреть файл

@ -50,6 +50,8 @@ static void ServoParsingBench(const StyleUseCounters* aCounters) {
} }
} }
static constexpr uint16_t STYLE_RULE = 1;
static void ServoSetPropertyByIdBench(const nsACString& css) { static void ServoSetPropertyByIdBench(const nsACString& css) {
RefPtr<RawServoDeclarationBlock> block = RefPtr<RawServoDeclarationBlock> block =
Servo_DeclarationBlock_CreateEmpty().Consume(); Servo_DeclarationBlock_CreateEmpty().Consume();
@ -64,7 +66,7 @@ static void ServoSetPropertyByIdBench(const nsACString& css) {
Servo_DeclarationBlock_SetPropertyById( Servo_DeclarationBlock_SetPropertyById(
block, eCSSProperty_width, &css, block, eCSSProperty_width, &css,
/* is_important = */ false, data, ParsingMode::Default, /* is_important = */ false, data, ParsingMode::Default,
eCompatibility_FullStandards, nullptr, {}); eCompatibility_FullStandards, nullptr, STYLE_RULE, {});
} }
} }
@ -82,7 +84,7 @@ static void ServoGetPropertyValueById() {
Servo_DeclarationBlock_SetPropertyById( Servo_DeclarationBlock_SetPropertyById(
block, eCSSProperty_width, &css, block, eCSSProperty_width, &css,
/* is_important = */ false, data, ParsingMode::Default, /* is_important = */ false, data, ParsingMode::Default,
eCompatibility_FullStandards, nullptr, {}); eCompatibility_FullStandards, nullptr, STYLE_RULE, {});
for (int i = 0; i < GETPROPERTY_REPETITIONS; i++) { for (int i = 0; i < GETPROPERTY_REPETITIONS; i++) {
DOMString value_; DOMString value_;

Просмотреть файл

@ -1263,11 +1263,12 @@ pub fn parse_style_attribute(
url_data: &UrlExtraData, url_data: &UrlExtraData,
error_reporter: Option<&dyn ParseErrorReporter>, error_reporter: Option<&dyn ParseErrorReporter>,
quirks_mode: QuirksMode, quirks_mode: QuirksMode,
rule_type: CssRuleType,
) -> PropertyDeclarationBlock { ) -> PropertyDeclarationBlock {
let context = ParserContext::new( let context = ParserContext::new(
Origin::Author, Origin::Author,
url_data, url_data,
Some(CssRuleType::Style), Some(rule_type),
ParsingMode::DEFAULT, ParsingMode::DEFAULT,
quirks_mode, quirks_mode,
error_reporter, error_reporter,
@ -1291,11 +1292,12 @@ pub fn parse_one_declaration_into(
error_reporter: Option<&dyn ParseErrorReporter>, error_reporter: Option<&dyn ParseErrorReporter>,
parsing_mode: ParsingMode, parsing_mode: ParsingMode,
quirks_mode: QuirksMode, quirks_mode: QuirksMode,
rule_type: CssRuleType,
) -> Result<(), ()> { ) -> Result<(), ()> {
let context = ParserContext::new( let context = ParserContext::new(
Origin::Author, Origin::Author,
url_data, url_data,
Some(CssRuleType::Style), Some(rule_type),
parsing_mode, parsing_mode,
quirks_mode, quirks_mode,
error_reporter, error_reporter,

Просмотреть файл

@ -542,10 +542,12 @@ impl NonCustomPropertyId {
false false
} }
fn allowed_in(self, context: &ParserContext) -> bool { /// Returns whether a given rule allows a given property.
#[inline]
pub fn allowed_in_rule(self, rule_type: CssRuleType) -> bool {
debug_assert!( debug_assert!(
matches!( matches!(
context.rule_type(), rule_type,
CssRuleType::Keyframe | CssRuleType::Page | CssRuleType::Style CssRuleType::Keyframe | CssRuleType::Page | CssRuleType::Style
), ),
"Declarations are only expected inside a keyframe, page, or style rule." "Declarations are only expected inside a keyframe, page, or style rule."
@ -559,14 +561,16 @@ impl NonCustomPropertyId {
"DISALLOWED_IN_PAGE_RULE", "DISALLOWED_IN_PAGE_RULE",
lambda p: not p.allowed_in_page_rule lambda p: not p.allowed_in_page_rule
)} )}
match context.rule_type() { match rule_type {
CssRuleType::Keyframe if DISALLOWED_IN_KEYFRAME_BLOCK.contains(self) => { CssRuleType::Keyframe => !DISALLOWED_IN_KEYFRAME_BLOCK.contains(self),
return false; CssRuleType::Page => !DISALLOWED_IN_PAGE_RULE.contains(self),
} _ => true
CssRuleType::Page if DISALLOWED_IN_PAGE_RULE.contains(self) => { }
return false; }
}
_ => {} fn allowed_in(self, context: &ParserContext) -> bool {
if !self.allowed_in_rule(context.rule_type()) {
return false;
} }
self.allowed_in_ignoring_rule_type(context) self.allowed_in_ignoring_rule_type(context)

Просмотреть файл

@ -299,7 +299,7 @@ impl CssRule {
} }
#[allow(missing_docs)] #[allow(missing_docs)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, FromPrimitive, PartialEq)]
pub enum CssRuleType { pub enum CssRuleType {
// https://drafts.csswg.org/cssom/#the-cssrule-interface // https://drafts.csswg.org/cssom/#the-cssrule-interface
Style = 1, Style = 1,

Просмотреть файл

@ -4050,12 +4050,19 @@ fn parse_property_into(
data: *mut URLExtraData, data: *mut URLExtraData,
parsing_mode: structs::ParsingMode, parsing_mode: structs::ParsingMode,
quirks_mode: QuirksMode, quirks_mode: QuirksMode,
rule_type: CssRuleType,
reporter: Option<&dyn ParseErrorReporter>, reporter: Option<&dyn ParseErrorReporter>,
) -> Result<(), ()> { ) -> Result<(), ()> {
let value = unsafe { value.as_str_unchecked() }; let value = unsafe { value.as_str_unchecked() };
let url_data = unsafe { UrlExtraData::from_ptr_ref(&data) }; let url_data = unsafe { UrlExtraData::from_ptr_ref(&data) };
let parsing_mode = ParsingMode::from_bits_truncate(parsing_mode); let parsing_mode = ParsingMode::from_bits_truncate(parsing_mode);
if let Some(non_custom) = property_id.non_custom_id() {
if !non_custom.allowed_in_rule(rule_type) {
return Err(());
}
}
parse_one_declaration_into( parse_one_declaration_into(
declarations, declarations,
property_id, property_id,
@ -4064,6 +4071,7 @@ fn parse_property_into(
reporter, reporter,
parsing_mode, parsing_mode,
quirks_mode, quirks_mode,
rule_type,
) )
} }
@ -4075,6 +4083,7 @@ pub extern "C" fn Servo_ParseProperty(
parsing_mode: structs::ParsingMode, parsing_mode: structs::ParsingMode,
quirks_mode: nsCompatibility, quirks_mode: nsCompatibility,
loader: *mut Loader, loader: *mut Loader,
rule_type: u16,
) -> Strong<RawServoDeclarationBlock> { ) -> Strong<RawServoDeclarationBlock> {
let id = get_property_id_from_nscsspropertyid!(property, Strong::null()); let id = get_property_id_from_nscsspropertyid!(property, Strong::null());
let mut declarations = SourcePropertyDeclaration::new(); let mut declarations = SourcePropertyDeclaration::new();
@ -4086,6 +4095,7 @@ pub extern "C" fn Servo_ParseProperty(
data, data,
parsing_mode, parsing_mode,
quirks_mode.into(), quirks_mode.into(),
to_rule_type(rule_type),
reporter.as_ref().map(|r| r as &dyn ParseErrorReporter), reporter.as_ref().map(|r| r as &dyn ParseErrorReporter),
); );
@ -4215,6 +4225,7 @@ pub unsafe extern "C" fn Servo_ParseStyleAttribute(
raw_extra_data: *mut URLExtraData, raw_extra_data: *mut URLExtraData,
quirks_mode: nsCompatibility, quirks_mode: nsCompatibility,
loader: *mut Loader, loader: *mut Loader,
rule_type: u16,
) -> Strong<RawServoDeclarationBlock> { ) -> Strong<RawServoDeclarationBlock> {
let global_style_data = &*GLOBAL_STYLE_DATA; let global_style_data = &*GLOBAL_STYLE_DATA;
let value = data.as_str_unchecked(); let value = data.as_str_unchecked();
@ -4225,6 +4236,7 @@ pub unsafe extern "C" fn Servo_ParseStyleAttribute(
url_data, url_data,
reporter.as_ref().map(|r| r as &dyn ParseErrorReporter), reporter.as_ref().map(|r| r as &dyn ParseErrorReporter),
quirks_mode.into(), quirks_mode.into(),
to_rule_type(rule_type),
))) )))
.into_strong() .into_strong()
} }
@ -4437,6 +4449,7 @@ fn set_property(
parsing_mode: structs::ParsingMode, parsing_mode: structs::ParsingMode,
quirks_mode: QuirksMode, quirks_mode: QuirksMode,
loader: *mut Loader, loader: *mut Loader,
rule_type: CssRuleType,
before_change_closure: DeclarationBlockMutationClosure, before_change_closure: DeclarationBlockMutationClosure,
) -> bool { ) -> bool {
let mut source_declarations = SourcePropertyDeclaration::new(); let mut source_declarations = SourcePropertyDeclaration::new();
@ -4448,6 +4461,7 @@ fn set_property(
data, data,
parsing_mode, parsing_mode,
quirks_mode, quirks_mode,
rule_type,
reporter.as_ref().map(|r| r as &dyn ParseErrorReporter), reporter.as_ref().map(|r| r as &dyn ParseErrorReporter),
); );
@ -4469,6 +4483,12 @@ fn set_property(
) )
} }
#[inline]
fn to_rule_type(ty: u16) -> CssRuleType {
use num_traits::FromPrimitive;
CssRuleType::from_u16(ty).unwrap_or(CssRuleType::Style)
}
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn Servo_DeclarationBlock_SetProperty( pub unsafe extern "C" fn Servo_DeclarationBlock_SetProperty(
declarations: &RawServoDeclarationBlock, declarations: &RawServoDeclarationBlock,
@ -4479,6 +4499,7 @@ pub unsafe extern "C" fn Servo_DeclarationBlock_SetProperty(
parsing_mode: structs::ParsingMode, parsing_mode: structs::ParsingMode,
quirks_mode: nsCompatibility, quirks_mode: nsCompatibility,
loader: *mut Loader, loader: *mut Loader,
rule_type: u16,
before_change_closure: DeclarationBlockMutationClosure, before_change_closure: DeclarationBlockMutationClosure,
) -> bool { ) -> bool {
set_property( set_property(
@ -4490,6 +4511,7 @@ pub unsafe extern "C" fn Servo_DeclarationBlock_SetProperty(
parsing_mode, parsing_mode,
quirks_mode.into(), quirks_mode.into(),
loader, loader,
to_rule_type(rule_type),
before_change_closure, before_change_closure,
) )
} }
@ -4521,6 +4543,7 @@ pub unsafe extern "C" fn Servo_DeclarationBlock_SetPropertyById(
parsing_mode: structs::ParsingMode, parsing_mode: structs::ParsingMode,
quirks_mode: nsCompatibility, quirks_mode: nsCompatibility,
loader: *mut Loader, loader: *mut Loader,
rule_type: u16,
before_change_closure: DeclarationBlockMutationClosure, before_change_closure: DeclarationBlockMutationClosure,
) -> bool { ) -> bool {
set_property( set_property(
@ -4532,6 +4555,7 @@ pub unsafe extern "C" fn Servo_DeclarationBlock_SetPropertyById(
parsing_mode, parsing_mode,
quirks_mode.into(), quirks_mode.into(),
loader, loader,
to_rule_type(rule_type),
before_change_closure, before_change_closure,
) )
} }
@ -5274,6 +5298,7 @@ pub unsafe extern "C" fn Servo_CSSSupports2(
DUMMY_URL_DATA, DUMMY_URL_DATA,
structs::ParsingMode_Default, structs::ParsingMode_Default,
QuirksMode::NoQuirks, QuirksMode::NoQuirks,
CssRuleType::Style,
None, None,
) )
.is_ok() .is_ok()

Просмотреть файл

@ -95,8 +95,8 @@
test(function() { test(function() {
var ruleWithPage = ruleList[3]; var ruleWithPage = ruleList[3];
ruleWithPage.style = "background-color: green;" ruleWithPage.style = "margin-top: 10px;"
assert_equals(ruleWithPage.style.cssText, "background-color: green;"); assert_equals(ruleWithPage.style.cssText, "margin-top: 10px;");
}, "CSSStyleDeclaration cssText attribute should be updated due to [PutForwards]"); }, "CSSStyleDeclaration cssText attribute should be updated due to [PutForwards]");
test(function() { test(function() {

Просмотреть файл

@ -0,0 +1,51 @@
<!doctype html>
<meta charset="utf-8">
<title>CSSOM Should correctly honor property restrictions</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="author" title="Mozilla" href="https://mozilla.org">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1665816">
<link rel="help" href="https://drafts.csswg.org/css-page-3/#conform-partial">
<link rel="help" href="https://drafts.csswg.org/css-animations/#keyframes">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
@page {
margin-top: 10px;
transform: scale(1);
}
@keyframes foo {
from {
margin-top: 10px;
animation-name: none;
}
}
</style>
<script>
test(function() {
let rule = document.styleSheets[0].cssRules[0];
assert_equals(rule.type, CSSRule.PAGE_RULE, "Should be a page rule");
assert_equals(rule.style.length, 1, "Transform doesn't quite apply to pages");
assert_equals(rule.style.marginTop, "10px", "Should have a margin-top declaration");
rule.style.setProperty("transform", "scale(1)");
assert_equals(rule.style.getPropertyValue("transform"), "", "Shouldn't have been able to set the transform property via setProperty");
assert_equals(rule.style.length, 1, "Shouldn't have been able to set transform via setProperty");
rule.style.cssText = "margin-bottom: 10px; transform: scale(1);";
assert_equals(rule.style.length, 1, "Should not have been able to set transform via cssText");
assert_equals(rule.style.marginBottom, "10px", "Should have a margin-bottom declaration");
}, "@page");
test(function() {
let rule = document.styleSheets[0].cssRules[1].cssRules[0];
assert_equals(rule.type, CSSRule.KEYFRAME_RULE, "Should be a keyframe rule");
assert_equals(rule.style.length, 1, "animation-name doesn't apply to keyframes");
assert_equals(rule.style.marginTop, "10px", "Should have a margin-top declaration");
rule.style.setProperty("animation-name", "none");
assert_equals(rule.style.getPropertyValue("animation-name"), "", "Shouldn't have been able to set the animation-nameproperty via setProperty");
assert_equals(rule.style.length, 1, "Shouldn't have been able to set animation-name via setProperty");
rule.style.cssText = "margin-bottom: 10px; animation-name: none;";
assert_equals(rule.style.length, 1, "Should not have been able to set animation-name via cssText");
assert_equals(rule.style.marginBottom, "10px", "Should have a margin-bottom declaration");
}, "@keyframe");
</script>