mirror of
https://github.com/servo/servo.git
synced 2025-08-26 23:58:20 +01:00
Reuse StylesheetContent
for inline style sheets with identical content (#38540)
For duplicate style sheets with identical content, `StylesheetContents` can be reused to avoid redundant parsing of the inline style sheets. Since duplicate stylesheets is a common case with web components, this change will significantly improve performance. Additionally, the cache hit rate of stylo's `CascadeDataCache` can now be significantly improved. When shared `StylesheetContents` is modified, copy-on-write will occur to avoid affecting other sharers. And then updates the references to `CssRule` or `PropertyDeclarationBlock` stored in the CSSOMs to ensure that modifications are made only on the new copy. Signed-off-by: sharpshooter_pt <ibluegalaxy_taoj@163.com>
This commit is contained in:
parent
f6b77f94e2
commit
6e6ef513a9
25 changed files with 711 additions and 125 deletions
|
@ -2,9 +2,11 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::shared_lock::{Locked, SharedRwLock};
|
use style::shared_lock::{Locked, SharedRwLock, SharedRwLockReadGuard};
|
||||||
use style::stylesheets::CssRules as StyleCssRules;
|
use style::stylesheets::CssRules as StyleCssRules;
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::Bindings::CSSConditionRuleBinding::CSSConditionRuleMethods;
|
use crate::dom::bindings::codegen::Bindings::CSSConditionRuleBinding::CSSConditionRuleMethods;
|
||||||
|
@ -20,7 +22,7 @@ pub(crate) struct CSSConditionRule {
|
||||||
cssgroupingrule: CSSGroupingRule,
|
cssgroupingrule: CSSGroupingRule,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
rules: Arc<Locked<StyleCssRules>>,
|
rules: RefCell<Arc<Locked<StyleCssRules>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSConditionRule {
|
impl CSSConditionRule {
|
||||||
|
@ -30,7 +32,7 @@ impl CSSConditionRule {
|
||||||
) -> CSSConditionRule {
|
) -> CSSConditionRule {
|
||||||
CSSConditionRule {
|
CSSConditionRule {
|
||||||
cssgroupingrule: CSSGroupingRule::new_inherited(parent_stylesheet),
|
cssgroupingrule: CSSGroupingRule::new_inherited(parent_stylesheet),
|
||||||
rules,
|
rules: RefCell::new(rules),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +45,16 @@ impl CSSConditionRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn clone_rules(&self) -> Arc<Locked<StyleCssRules>> {
|
pub(crate) fn clone_rules(&self) -> Arc<Locked<StyleCssRules>> {
|
||||||
self.rules.clone()
|
self.rules.borrow().clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_rules(
|
||||||
|
&self,
|
||||||
|
rules: Arc<Locked<StyleCssRules>>,
|
||||||
|
guard: &SharedRwLockReadGuard,
|
||||||
|
) {
|
||||||
|
self.cssgroupingrule.update_rules(&rules, guard);
|
||||||
|
*self.rules.borrow_mut() = rules;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::shared_lock::{Locked, ToCssWithGuard};
|
use style::shared_lock::{Locked, ToCssWithGuard};
|
||||||
|
@ -20,7 +22,7 @@ pub(crate) struct CSSFontFaceRule {
|
||||||
cssrule: CSSRule,
|
cssrule: CSSRule,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
fontfacerule: Arc<Locked<FontFaceRule>>,
|
fontfacerule: RefCell<Arc<Locked<FontFaceRule>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSFontFaceRule {
|
impl CSSFontFaceRule {
|
||||||
|
@ -30,7 +32,7 @@ impl CSSFontFaceRule {
|
||||||
) -> CSSFontFaceRule {
|
) -> CSSFontFaceRule {
|
||||||
CSSFontFaceRule {
|
CSSFontFaceRule {
|
||||||
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
||||||
fontfacerule,
|
fontfacerule: RefCell::new(fontfacerule),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +52,10 @@ impl CSSFontFaceRule {
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_rule(&self, fontfacerule: Arc<Locked<FontFaceRule>>) {
|
||||||
|
*self.fontfacerule.borrow_mut() = fontfacerule;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecificCSSRule for CSSFontFaceRule {
|
impl SpecificCSSRule for CSSFontFaceRule {
|
||||||
|
@ -60,6 +66,7 @@ impl SpecificCSSRule for CSSFontFaceRule {
|
||||||
fn get_css(&self) -> DOMString {
|
fn get_css(&self) -> DOMString {
|
||||||
let guard = self.cssrule.shared_lock().read();
|
let guard = self.cssrule.shared_lock().read();
|
||||||
self.fontfacerule
|
self.fontfacerule
|
||||||
|
.borrow()
|
||||||
.read_with(&guard)
|
.read_with(&guard)
|
||||||
.to_css_string(&guard)
|
.to_css_string(&guard)
|
||||||
.into()
|
.into()
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use style::shared_lock::SharedRwLock;
|
use servo_arc::Arc;
|
||||||
use style::stylesheets::{CssRuleType, CssRuleTypes};
|
use style::shared_lock::{Locked, SharedRwLock, SharedRwLockReadGuard};
|
||||||
|
use style::stylesheets::{CssRuleType, CssRuleTypes, CssRules};
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::Bindings::CSSGroupingRuleBinding::CSSGroupingRuleMethods;
|
use crate::dom::bindings::codegen::Bindings::CSSGroupingRuleBinding::CSSGroupingRuleMethods;
|
||||||
use crate::dom::bindings::error::{ErrorResult, Fallible};
|
use crate::dom::bindings::error::{ErrorResult, Fallible};
|
||||||
|
@ -62,6 +63,16 @@ impl CSSGroupingRule {
|
||||||
pub(crate) fn shared_lock(&self) -> &SharedRwLock {
|
pub(crate) fn shared_lock(&self) -> &SharedRwLock {
|
||||||
self.cssrule.shared_lock()
|
self.cssrule.shared_lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_rules(
|
||||||
|
&self,
|
||||||
|
rules: &Arc<Locked<CssRules>>,
|
||||||
|
guard: &SharedRwLockReadGuard,
|
||||||
|
) {
|
||||||
|
if let Some(rulelist) = self.rulelist.get() {
|
||||||
|
rulelist.update_rules(RulesSource::Rules(rules.clone()), guard);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSGroupingRuleMethods<crate::DomTypeHolder> for CSSGroupingRule {
|
impl CSSGroupingRuleMethods<crate::DomTypeHolder> for CSSGroupingRule {
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::shared_lock::{Locked, ToCssWithGuard};
|
use style::shared_lock::{Locked, ToCssWithGuard};
|
||||||
|
@ -23,7 +25,7 @@ pub(crate) struct CSSImportRule {
|
||||||
cssrule: CSSRule,
|
cssrule: CSSRule,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
import_rule: Arc<Locked<ImportRule>>,
|
import_rule: RefCell<Arc<Locked<ImportRule>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSImportRule {
|
impl CSSImportRule {
|
||||||
|
@ -33,7 +35,7 @@ impl CSSImportRule {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
CSSImportRule {
|
CSSImportRule {
|
||||||
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
||||||
import_rule,
|
import_rule: RefCell::new(import_rule),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +52,10 @@ impl CSSImportRule {
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_rule(&self, import_rule: Arc<Locked<ImportRule>>) {
|
||||||
|
*self.import_rule.borrow_mut() = import_rule;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecificCSSRule for CSSImportRule {
|
impl SpecificCSSRule for CSSImportRule {
|
||||||
|
@ -60,6 +66,7 @@ impl SpecificCSSRule for CSSImportRule {
|
||||||
fn get_css(&self) -> DOMString {
|
fn get_css(&self) -> DOMString {
|
||||||
let guard = self.cssrule.shared_lock().read();
|
let guard = self.cssrule.shared_lock().read();
|
||||||
self.import_rule
|
self.import_rule
|
||||||
|
.borrow()
|
||||||
.read_with(&guard)
|
.read_with(&guard)
|
||||||
.to_css_string(&guard)
|
.to_css_string(&guard)
|
||||||
.into()
|
.into()
|
||||||
|
@ -70,7 +77,7 @@ impl CSSImportRuleMethods<crate::DomTypeHolder> for CSSImportRule {
|
||||||
/// <https://drafts.csswg.org/cssom-1/#dom-cssimportrule-layername>
|
/// <https://drafts.csswg.org/cssom-1/#dom-cssimportrule-layername>
|
||||||
fn GetLayerName(&self) -> Option<DOMString> {
|
fn GetLayerName(&self) -> Option<DOMString> {
|
||||||
let guard = self.cssrule.shared_lock().read();
|
let guard = self.cssrule.shared_lock().read();
|
||||||
match &self.import_rule.read_with(&guard).layer {
|
match &self.import_rule.borrow().read_with(&guard).layer {
|
||||||
ImportLayer::None => None,
|
ImportLayer::None => None,
|
||||||
ImportLayer::Anonymous => Some(DOMString::new()),
|
ImportLayer::Anonymous => Some(DOMString::new()),
|
||||||
ImportLayer::Named(name) => Some(DOMString::from_string(name.to_css_string())),
|
ImportLayer::Named(name) => Some(DOMString::from_string(name.to_css_string())),
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::shared_lock::{Locked, ToCssWithGuard};
|
use style::shared_lock::{Locked, SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use style::stylesheets::CssRuleType;
|
use style::stylesheets::CssRuleType;
|
||||||
use style::stylesheets::keyframes_rule::Keyframe;
|
use style::stylesheets::keyframes_rule::Keyframe;
|
||||||
|
|
||||||
|
@ -24,7 +26,7 @@ pub(crate) struct CSSKeyframeRule {
|
||||||
cssrule: CSSRule,
|
cssrule: CSSRule,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
keyframerule: Arc<Locked<Keyframe>>,
|
keyframerule: RefCell<Arc<Locked<Keyframe>>>,
|
||||||
style_decl: MutNullableDom<CSSStyleDeclaration>,
|
style_decl: MutNullableDom<CSSStyleDeclaration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +37,7 @@ impl CSSKeyframeRule {
|
||||||
) -> CSSKeyframeRule {
|
) -> CSSKeyframeRule {
|
||||||
CSSKeyframeRule {
|
CSSKeyframeRule {
|
||||||
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
||||||
keyframerule,
|
keyframerule: RefCell::new(keyframerule),
|
||||||
style_decl: Default::default(),
|
style_decl: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,6 +58,17 @@ impl CSSKeyframeRule {
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_rule(
|
||||||
|
&self,
|
||||||
|
keyframerule: Arc<Locked<Keyframe>>,
|
||||||
|
guard: &SharedRwLockReadGuard,
|
||||||
|
) {
|
||||||
|
if let Some(ref style_decl) = self.style_decl.get() {
|
||||||
|
style_decl.update_property_declaration_block(&keyframerule.read_with(guard).block);
|
||||||
|
}
|
||||||
|
*self.keyframerule.borrow_mut() = keyframerule;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSKeyframeRuleMethods<crate::DomTypeHolder> for CSSKeyframeRule {
|
impl CSSKeyframeRuleMethods<crate::DomTypeHolder> for CSSKeyframeRule {
|
||||||
|
@ -67,7 +80,7 @@ impl CSSKeyframeRuleMethods<crate::DomTypeHolder> for CSSKeyframeRule {
|
||||||
self.global().as_window(),
|
self.global().as_window(),
|
||||||
CSSStyleOwner::CSSRule(
|
CSSStyleOwner::CSSRule(
|
||||||
Dom::from_ref(self.upcast()),
|
Dom::from_ref(self.upcast()),
|
||||||
self.keyframerule.read_with(&guard).block.clone(),
|
RefCell::new(self.keyframerule.borrow().read_with(&guard).block.clone()),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
CSSModificationAccess::ReadWrite,
|
CSSModificationAccess::ReadWrite,
|
||||||
|
@ -85,6 +98,7 @@ impl SpecificCSSRule for CSSKeyframeRule {
|
||||||
fn get_css(&self) -> DOMString {
|
fn get_css(&self) -> DOMString {
|
||||||
let guard = self.cssrule.shared_lock().read();
|
let guard = self.cssrule.shared_lock().read();
|
||||||
self.keyframerule
|
self.keyframerule
|
||||||
|
.borrow()
|
||||||
.read_with(&guard)
|
.read_with(&guard)
|
||||||
.to_css_string(&guard)
|
.to_css_string(&guard)
|
||||||
.into()
|
.into()
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use cssparser::{Parser, ParserInput};
|
use cssparser::{Parser, ParserInput};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::shared_lock::{Locked, ToCssWithGuard};
|
use style::shared_lock::{Locked, SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use style::stylesheets::CssRuleType;
|
use style::stylesheets::CssRuleType;
|
||||||
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesRule};
|
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesRule};
|
||||||
use style::values::KeyframesName;
|
use style::values::KeyframesName;
|
||||||
|
@ -28,7 +30,7 @@ pub(crate) struct CSSKeyframesRule {
|
||||||
cssrule: CSSRule,
|
cssrule: CSSRule,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
keyframesrule: Arc<Locked<KeyframesRule>>,
|
keyframesrule: RefCell<Arc<Locked<KeyframesRule>>>,
|
||||||
rulelist: MutNullableDom<CSSRuleList>,
|
rulelist: MutNullableDom<CSSRuleList>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +41,7 @@ impl CSSKeyframesRule {
|
||||||
) -> CSSKeyframesRule {
|
) -> CSSKeyframesRule {
|
||||||
CSSKeyframesRule {
|
CSSKeyframesRule {
|
||||||
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
||||||
keyframesrule,
|
keyframesrule: RefCell::new(keyframesrule),
|
||||||
rulelist: MutNullableDom::new(None),
|
rulelist: MutNullableDom::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +69,7 @@ impl CSSKeyframesRule {
|
||||||
CSSRuleList::new(
|
CSSRuleList::new(
|
||||||
self.global().as_window(),
|
self.global().as_window(),
|
||||||
parent_stylesheet,
|
parent_stylesheet,
|
||||||
RulesSource::Keyframes(self.keyframesrule.clone()),
|
RulesSource::Keyframes(self.keyframesrule.borrow().clone()),
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -82,6 +84,7 @@ impl CSSKeyframesRule {
|
||||||
// This finds the *last* element matching a selector
|
// This finds the *last* element matching a selector
|
||||||
// because that's the rule that applies. Thus, rposition
|
// because that's the rule that applies. Thus, rposition
|
||||||
self.keyframesrule
|
self.keyframesrule
|
||||||
|
.borrow()
|
||||||
.read_with(&guard)
|
.read_with(&guard)
|
||||||
.keyframes
|
.keyframes
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -90,6 +93,18 @@ impl CSSKeyframesRule {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_rule(
|
||||||
|
&self,
|
||||||
|
keyframesrule: Arc<Locked<KeyframesRule>>,
|
||||||
|
guard: &SharedRwLockReadGuard,
|
||||||
|
) {
|
||||||
|
if let Some(rulelist) = self.rulelist.get() {
|
||||||
|
rulelist.update_rules(RulesSource::Keyframes(keyframesrule.clone()), guard);
|
||||||
|
}
|
||||||
|
|
||||||
|
*self.keyframesrule.borrow_mut() = keyframesrule;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSKeyframesRuleMethods<crate::DomTypeHolder> for CSSKeyframesRule {
|
impl CSSKeyframesRuleMethods<crate::DomTypeHolder> for CSSKeyframesRule {
|
||||||
|
@ -108,8 +123,10 @@ impl CSSKeyframesRuleMethods<crate::DomTypeHolder> for CSSKeyframesRule {
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Ok(rule) = rule {
|
if let Ok(rule) = rule {
|
||||||
|
self.cssrule.parent_stylesheet().will_modify();
|
||||||
let mut guard = self.cssrule.shared_lock().write();
|
let mut guard = self.cssrule.shared_lock().write();
|
||||||
self.keyframesrule
|
self.keyframesrule
|
||||||
|
.borrow()
|
||||||
.write_with(&mut guard)
|
.write_with(&mut guard)
|
||||||
.keyframes
|
.keyframes
|
||||||
.push(rule);
|
.push(rule);
|
||||||
|
@ -135,7 +152,7 @@ impl CSSKeyframesRuleMethods<crate::DomTypeHolder> for CSSKeyframesRule {
|
||||||
// https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-name
|
// https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-name
|
||||||
fn Name(&self) -> DOMString {
|
fn Name(&self) -> DOMString {
|
||||||
let guard = self.cssrule.shared_lock().read();
|
let guard = self.cssrule.shared_lock().read();
|
||||||
DOMString::from(&**self.keyframesrule.read_with(&guard).name.as_atom())
|
DOMString::from(&**self.keyframesrule.borrow().read_with(&guard).name.as_atom())
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-name
|
// https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-name
|
||||||
|
@ -143,9 +160,10 @@ impl CSSKeyframesRuleMethods<crate::DomTypeHolder> for CSSKeyframesRule {
|
||||||
// Spec deviation: https://github.com/w3c/csswg-drafts/issues/801
|
// Spec deviation: https://github.com/w3c/csswg-drafts/issues/801
|
||||||
// Setting this property to a CSS-wide keyword or `none` does not throw,
|
// Setting this property to a CSS-wide keyword or `none` does not throw,
|
||||||
// it stores a value that serializes as a quoted string.
|
// it stores a value that serializes as a quoted string.
|
||||||
|
self.cssrule.parent_stylesheet().will_modify();
|
||||||
let name = KeyframesName::from_ident(&value);
|
let name = KeyframesName::from_ident(&value);
|
||||||
let mut guard = self.cssrule.shared_lock().write();
|
let mut guard = self.cssrule.shared_lock().write();
|
||||||
self.keyframesrule.write_with(&mut guard).name = name;
|
self.keyframesrule.borrow().write_with(&mut guard).name = name;
|
||||||
self.cssrule.parent_stylesheet().notify_invalidations();
|
self.cssrule.parent_stylesheet().notify_invalidations();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -159,6 +177,7 @@ impl SpecificCSSRule for CSSKeyframesRule {
|
||||||
fn get_css(&self) -> DOMString {
|
fn get_css(&self) -> DOMString {
|
||||||
let guard = self.cssrule.shared_lock().read();
|
let guard = self.cssrule.shared_lock().read();
|
||||||
self.keyframesrule
|
self.keyframesrule
|
||||||
|
.borrow()
|
||||||
.read_with(&guard)
|
.read_with(&guard)
|
||||||
.to_css_string(&guard)
|
.to_css_string(&guard)
|
||||||
.into()
|
.into()
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::shared_lock::{Locked, ToCssWithGuard};
|
use style::shared_lock::{Locked, SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use style::stylesheets::{CssRuleType, CssRules, LayerBlockRule};
|
use style::stylesheets::{CssRuleType, CssRules, LayerBlockRule};
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
|
|
||||||
|
@ -23,7 +25,7 @@ pub(crate) struct CSSLayerBlockRule {
|
||||||
cssgroupingrule: CSSGroupingRule,
|
cssgroupingrule: CSSGroupingRule,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
layerblockrule: Arc<LayerBlockRule>,
|
layerblockrule: RefCell<Arc<LayerBlockRule>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSLayerBlockRule {
|
impl CSSLayerBlockRule {
|
||||||
|
@ -33,7 +35,7 @@ impl CSSLayerBlockRule {
|
||||||
) -> CSSLayerBlockRule {
|
) -> CSSLayerBlockRule {
|
||||||
CSSLayerBlockRule {
|
CSSLayerBlockRule {
|
||||||
cssgroupingrule: CSSGroupingRule::new_inherited(parent_stylesheet),
|
cssgroupingrule: CSSGroupingRule::new_inherited(parent_stylesheet),
|
||||||
layerblockrule,
|
layerblockrule: RefCell::new(layerblockrule),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +57,17 @@ impl CSSLayerBlockRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn clone_rules(&self) -> Arc<Locked<CssRules>> {
|
pub(crate) fn clone_rules(&self) -> Arc<Locked<CssRules>> {
|
||||||
self.layerblockrule.rules.clone()
|
self.layerblockrule.borrow().rules.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_rule(
|
||||||
|
&self,
|
||||||
|
layerblockrule: Arc<LayerBlockRule>,
|
||||||
|
guard: &SharedRwLockReadGuard,
|
||||||
|
) {
|
||||||
|
self.cssgroupingrule
|
||||||
|
.update_rules(&layerblockrule.rules, guard);
|
||||||
|
*self.layerblockrule.borrow_mut() = layerblockrule;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,14 +78,14 @@ impl SpecificCSSRule for CSSLayerBlockRule {
|
||||||
|
|
||||||
fn get_css(&self) -> DOMString {
|
fn get_css(&self) -> DOMString {
|
||||||
let guard = self.cssgroupingrule.shared_lock().read();
|
let guard = self.cssgroupingrule.shared_lock().read();
|
||||||
self.layerblockrule.to_css_string(&guard).into()
|
self.layerblockrule.borrow().to_css_string(&guard).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSLayerBlockRuleMethods<crate::DomTypeHolder> for CSSLayerBlockRule {
|
impl CSSLayerBlockRuleMethods<crate::DomTypeHolder> for CSSLayerBlockRule {
|
||||||
/// <https://drafts.csswg.org/css-cascade-5/#dom-csslayerblockrule-name>
|
/// <https://drafts.csswg.org/css-cascade-5/#dom-csslayerblockrule-name>
|
||||||
fn Name(&self) -> DOMString {
|
fn Name(&self) -> DOMString {
|
||||||
if let Some(name) = &self.layerblockrule.name {
|
if let Some(name) = &self.layerblockrule.borrow().name {
|
||||||
DOMString::from_string(name.to_css_string())
|
DOMString::from_string(name.to_css_string())
|
||||||
} else {
|
} else {
|
||||||
DOMString::new()
|
DOMString::new()
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use js::rust::MutableHandleValue;
|
use js::rust::MutableHandleValue;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
@ -24,7 +26,7 @@ pub(crate) struct CSSLayerStatementRule {
|
||||||
cssrule: CSSRule,
|
cssrule: CSSRule,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
layerstatementrule: Arc<LayerStatementRule>,
|
layerstatementrule: RefCell<Arc<LayerStatementRule>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSLayerStatementRule {
|
impl CSSLayerStatementRule {
|
||||||
|
@ -34,7 +36,7 @@ impl CSSLayerStatementRule {
|
||||||
) -> CSSLayerStatementRule {
|
) -> CSSLayerStatementRule {
|
||||||
CSSLayerStatementRule {
|
CSSLayerStatementRule {
|
||||||
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
||||||
layerstatementrule,
|
layerstatementrule: RefCell::new(layerstatementrule),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +56,10 @@ impl CSSLayerStatementRule {
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_rule(&self, layerstatementrule: Arc<LayerStatementRule>) {
|
||||||
|
*self.layerstatementrule.borrow_mut() = layerstatementrule;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecificCSSRule for CSSLayerStatementRule {
|
impl SpecificCSSRule for CSSLayerStatementRule {
|
||||||
|
@ -63,7 +69,10 @@ impl SpecificCSSRule for CSSLayerStatementRule {
|
||||||
|
|
||||||
fn get_css(&self) -> DOMString {
|
fn get_css(&self) -> DOMString {
|
||||||
let guard = self.cssrule.shared_lock().read();
|
let guard = self.cssrule.shared_lock().read();
|
||||||
self.layerstatementrule.to_css_string(&guard).into()
|
self.layerstatementrule
|
||||||
|
.borrow()
|
||||||
|
.to_css_string(&guard)
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +81,7 @@ impl CSSLayerStatementRuleMethods<crate::DomTypeHolder> for CSSLayerStatementRul
|
||||||
fn NameList(&self, cx: SafeJSContext, can_gc: CanGc, retval: MutableHandleValue) {
|
fn NameList(&self, cx: SafeJSContext, can_gc: CanGc, retval: MutableHandleValue) {
|
||||||
let names: Vec<DOMString> = self
|
let names: Vec<DOMString> = self
|
||||||
.layerstatementrule
|
.layerstatementrule
|
||||||
|
.borrow()
|
||||||
.names
|
.names
|
||||||
.iter()
|
.iter()
|
||||||
.map(|name| DOMString::from_string(name.to_css_string()))
|
.map(|name| DOMString::from_string(name.to_css_string()))
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::shared_lock::ToCssWithGuard;
|
use style::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use style::stylesheets::{CssRuleType, MediaRule};
|
use style::stylesheets::{CssRuleType, MediaRule};
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
|
|
||||||
|
@ -24,7 +26,7 @@ pub(crate) struct CSSMediaRule {
|
||||||
cssconditionrule: CSSConditionRule,
|
cssconditionrule: CSSConditionRule,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
mediarule: Arc<MediaRule>,
|
mediarule: RefCell<Arc<MediaRule>>,
|
||||||
medialist: MutNullableDom<MediaList>,
|
medialist: MutNullableDom<MediaList>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +35,7 @@ impl CSSMediaRule {
|
||||||
let list = mediarule.rules.clone();
|
let list = mediarule.rules.clone();
|
||||||
CSSMediaRule {
|
CSSMediaRule {
|
||||||
cssconditionrule: CSSConditionRule::new_inherited(parent_stylesheet, list),
|
cssconditionrule: CSSConditionRule::new_inherited(parent_stylesheet, list),
|
||||||
mediarule,
|
mediarule: RefCell::new(mediarule),
|
||||||
medialist: MutNullableDom::new(None),
|
medialist: MutNullableDom::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +59,7 @@ impl CSSMediaRule {
|
||||||
MediaList::new(
|
MediaList::new(
|
||||||
self.global().as_window(),
|
self.global().as_window(),
|
||||||
self.cssconditionrule.parent_stylesheet(),
|
self.cssconditionrule.parent_stylesheet(),
|
||||||
self.mediarule.media_queries.clone(),
|
self.mediarule.borrow().media_queries.clone(),
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -66,8 +68,21 @@ impl CSSMediaRule {
|
||||||
/// <https://drafts.csswg.org/css-conditional-3/#the-cssmediarule-interface>
|
/// <https://drafts.csswg.org/css-conditional-3/#the-cssmediarule-interface>
|
||||||
pub(crate) fn get_condition_text(&self) -> DOMString {
|
pub(crate) fn get_condition_text(&self) -> DOMString {
|
||||||
let guard = self.cssconditionrule.shared_lock().read();
|
let guard = self.cssconditionrule.shared_lock().read();
|
||||||
let list = self.mediarule.media_queries.read_with(&guard);
|
self.mediarule
|
||||||
list.to_css_string().into()
|
.borrow()
|
||||||
|
.media_queries
|
||||||
|
.read_with(&guard)
|
||||||
|
.to_css_string()
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_rule(&self, mediarule: Arc<MediaRule>, guard: &SharedRwLockReadGuard) {
|
||||||
|
self.cssconditionrule
|
||||||
|
.update_rules(mediarule.rules.clone(), guard);
|
||||||
|
if let Some(medialist) = self.medialist.get() {
|
||||||
|
medialist.update_media_list(mediarule.media_queries.clone());
|
||||||
|
}
|
||||||
|
*self.mediarule.borrow_mut() = mediarule;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +93,7 @@ impl SpecificCSSRule for CSSMediaRule {
|
||||||
|
|
||||||
fn get_css(&self) -> DOMString {
|
fn get_css(&self) -> DOMString {
|
||||||
let guard = self.cssconditionrule.shared_lock().read();
|
let guard = self.cssconditionrule.shared_lock().read();
|
||||||
self.mediarule.to_css_string(&guard).into()
|
self.mediarule.borrow().to_css_string(&guard).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::shared_lock::ToCssWithGuard;
|
use style::shared_lock::ToCssWithGuard;
|
||||||
|
@ -21,7 +23,7 @@ pub(crate) struct CSSNamespaceRule {
|
||||||
cssrule: CSSRule,
|
cssrule: CSSRule,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
namespacerule: Arc<NamespaceRule>,
|
namespacerule: RefCell<Arc<NamespaceRule>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSNamespaceRule {
|
impl CSSNamespaceRule {
|
||||||
|
@ -31,7 +33,7 @@ impl CSSNamespaceRule {
|
||||||
) -> CSSNamespaceRule {
|
) -> CSSNamespaceRule {
|
||||||
CSSNamespaceRule {
|
CSSNamespaceRule {
|
||||||
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
||||||
namespacerule,
|
namespacerule: RefCell::new(namespacerule),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,12 +53,17 @@ impl CSSNamespaceRule {
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_rule(&self, namespacerule: Arc<NamespaceRule>) {
|
||||||
|
*self.namespacerule.borrow_mut() = namespacerule;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSNamespaceRuleMethods<crate::DomTypeHolder> for CSSNamespaceRule {
|
impl CSSNamespaceRuleMethods<crate::DomTypeHolder> for CSSNamespaceRule {
|
||||||
// https://drafts.csswg.org/cssom/#dom-cssnamespacerule-prefix
|
// https://drafts.csswg.org/cssom/#dom-cssnamespacerule-prefix
|
||||||
fn Prefix(&self) -> DOMString {
|
fn Prefix(&self) -> DOMString {
|
||||||
self.namespacerule
|
self.namespacerule
|
||||||
|
.borrow()
|
||||||
.prefix
|
.prefix
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|s| s.to_string().into())
|
.map(|s| s.to_string().into())
|
||||||
|
@ -65,7 +72,7 @@ impl CSSNamespaceRuleMethods<crate::DomTypeHolder> for CSSNamespaceRule {
|
||||||
|
|
||||||
// https://drafts.csswg.org/cssom/#dom-cssnamespacerule-namespaceuri
|
// https://drafts.csswg.org/cssom/#dom-cssnamespacerule-namespaceuri
|
||||||
fn NamespaceURI(&self) -> DOMString {
|
fn NamespaceURI(&self) -> DOMString {
|
||||||
(**self.namespacerule.url).into()
|
(**self.namespacerule.borrow().url).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +83,6 @@ impl SpecificCSSRule for CSSNamespaceRule {
|
||||||
|
|
||||||
fn get_css(&self) -> DOMString {
|
fn get_css(&self) -> DOMString {
|
||||||
let guard = self.cssrule.shared_lock().read();
|
let guard = self.cssrule.shared_lock().read();
|
||||||
self.namespacerule.to_css_string(&guard).into()
|
self.namespacerule.borrow().to_css_string(&guard).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::shared_lock::{Locked, ToCssWithGuard};
|
use style::shared_lock::{Locked, SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use style::stylesheets::{CssRuleType, NestedDeclarationsRule};
|
use style::stylesheets::{CssRuleType, NestedDeclarationsRule};
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::Bindings::CSSNestedDeclarationsBinding::CSSNestedDeclarationsMethods;
|
use crate::dom::bindings::codegen::Bindings::CSSNestedDeclarationsBinding::CSSNestedDeclarationsMethods;
|
||||||
|
@ -23,7 +25,7 @@ pub(crate) struct CSSNestedDeclarations {
|
||||||
cssrule: CSSRule,
|
cssrule: CSSRule,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
nesteddeclarationsrule: Arc<Locked<NestedDeclarationsRule>>,
|
nesteddeclarationsrule: RefCell<Arc<Locked<NestedDeclarationsRule>>>,
|
||||||
style_decl: MutNullableDom<CSSStyleDeclaration>,
|
style_decl: MutNullableDom<CSSStyleDeclaration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +36,7 @@ impl CSSNestedDeclarations {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
||||||
nesteddeclarationsrule,
|
nesteddeclarationsrule: RefCell::new(nesteddeclarationsrule),
|
||||||
style_decl: Default::default(),
|
style_decl: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +57,18 @@ impl CSSNestedDeclarations {
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_rule(
|
||||||
|
&self,
|
||||||
|
nesteddeclarationsrule: Arc<Locked<NestedDeclarationsRule>>,
|
||||||
|
guard: &SharedRwLockReadGuard,
|
||||||
|
) {
|
||||||
|
if let Some(ref style_decl) = self.style_decl.get() {
|
||||||
|
style_decl
|
||||||
|
.update_property_declaration_block(&nesteddeclarationsrule.read_with(guard).block);
|
||||||
|
}
|
||||||
|
*self.nesteddeclarationsrule.borrow_mut() = nesteddeclarationsrule;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecificCSSRule for CSSNestedDeclarations {
|
impl SpecificCSSRule for CSSNestedDeclarations {
|
||||||
|
@ -65,6 +79,7 @@ impl SpecificCSSRule for CSSNestedDeclarations {
|
||||||
fn get_css(&self) -> DOMString {
|
fn get_css(&self) -> DOMString {
|
||||||
let guard = self.cssrule.shared_lock().read();
|
let guard = self.cssrule.shared_lock().read();
|
||||||
self.nesteddeclarationsrule
|
self.nesteddeclarationsrule
|
||||||
|
.borrow()
|
||||||
.read_with(&guard)
|
.read_with(&guard)
|
||||||
.to_css_string(&guard)
|
.to_css_string(&guard)
|
||||||
.into()
|
.into()
|
||||||
|
@ -80,7 +95,13 @@ impl CSSNestedDeclarationsMethods<crate::DomTypeHolder> for CSSNestedDeclaration
|
||||||
self.global().as_window(),
|
self.global().as_window(),
|
||||||
CSSStyleOwner::CSSRule(
|
CSSStyleOwner::CSSRule(
|
||||||
Dom::from_ref(self.upcast()),
|
Dom::from_ref(self.upcast()),
|
||||||
self.nesteddeclarationsrule.read_with(&guard).block.clone(),
|
RefCell::new(
|
||||||
|
self.nesteddeclarationsrule
|
||||||
|
.borrow()
|
||||||
|
.read_with(&guard)
|
||||||
|
.block
|
||||||
|
.clone(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
CSSModificationAccess::ReadWrite,
|
CSSModificationAccess::ReadWrite,
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use style::shared_lock::SharedRwLock;
|
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard};
|
||||||
use style::stylesheets::{CssRule as StyleCssRule, CssRuleType};
|
use style::stylesheets::{CssRule as StyleCssRule, CssRuleType};
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleMethods;
|
use crate::dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleMethods;
|
||||||
|
@ -157,7 +157,73 @@ impl CSSRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn shared_lock(&self) -> &SharedRwLock {
|
pub(crate) fn shared_lock(&self) -> &SharedRwLock {
|
||||||
&self.parent_stylesheet.style_stylesheet().shared_lock
|
self.parent_stylesheet.shared_lock()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_rule(&self, style_rule: &StyleCssRule, guard: &SharedRwLockReadGuard) {
|
||||||
|
match style_rule {
|
||||||
|
StyleCssRule::Import(s) => {
|
||||||
|
if let Some(rule) = self.downcast::<CSSImportRule>() {
|
||||||
|
rule.update_rule(s.clone());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
StyleCssRule::Style(s) => {
|
||||||
|
if let Some(rule) = self.downcast::<CSSStyleRule>() {
|
||||||
|
rule.update_rule(s.clone(), guard);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
StyleCssRule::FontFace(s) => {
|
||||||
|
if let Some(rule) = self.downcast::<CSSFontFaceRule>() {
|
||||||
|
rule.update_rule(s.clone());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
StyleCssRule::FontFeatureValues(_) => unimplemented!(),
|
||||||
|
StyleCssRule::CounterStyle(_) => unimplemented!(),
|
||||||
|
StyleCssRule::Keyframes(s) => {
|
||||||
|
if let Some(rule) = self.downcast::<CSSKeyframesRule>() {
|
||||||
|
rule.update_rule(s.clone(), guard);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
StyleCssRule::Media(s) => {
|
||||||
|
if let Some(rule) = self.downcast::<CSSMediaRule>() {
|
||||||
|
rule.update_rule(s.clone(), guard);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
StyleCssRule::Namespace(s) => {
|
||||||
|
if let Some(rule) = self.downcast::<CSSNamespaceRule>() {
|
||||||
|
rule.update_rule(s.clone());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
StyleCssRule::Supports(s) => {
|
||||||
|
if let Some(rule) = self.downcast::<CSSSupportsRule>() {
|
||||||
|
rule.update_rule(s.clone(), guard);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
StyleCssRule::Page(_) => unreachable!(),
|
||||||
|
StyleCssRule::Container(_) => unimplemented!(), // TODO
|
||||||
|
StyleCssRule::Document(_) => unimplemented!(), // TODO
|
||||||
|
StyleCssRule::LayerBlock(s) => {
|
||||||
|
if let Some(rule) = self.downcast::<CSSLayerBlockRule>() {
|
||||||
|
rule.update_rule(s.clone(), guard);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
StyleCssRule::LayerStatement(s) => {
|
||||||
|
if let Some(rule) = self.downcast::<CSSLayerStatementRule>() {
|
||||||
|
rule.update_rule(s.clone());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
StyleCssRule::FontPaletteValues(_) => unimplemented!(), // TODO
|
||||||
|
StyleCssRule::Property(_) => unimplemented!(), // TODO
|
||||||
|
StyleCssRule::Margin(_) => unimplemented!(), // TODO
|
||||||
|
StyleCssRule::Scope(_) => unimplemented!(), // TODO
|
||||||
|
StyleCssRule::StartingStyle(_) => unimplemented!(), // TODO
|
||||||
|
StyleCssRule::PositionTry(_) => unimplemented!(), // TODO
|
||||||
|
StyleCssRule::NestedDeclarations(s) => {
|
||||||
|
if let Some(rule) = self.downcast::<CSSNestedDeclarations>() {
|
||||||
|
rule.update_rule(s.clone(), guard);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,13 @@
|
||||||
|
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
use itertools::izip;
|
||||||
|
use script_bindings::inheritance::Castable;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::shared_lock::Locked;
|
use style::shared_lock::{Locked, SharedRwLockReadGuard};
|
||||||
use style::stylesheets::{
|
use style::stylesheets::{
|
||||||
AllowImportRules, CssRuleType, CssRuleTypes, CssRules, CssRulesHelpers, KeyframesRule,
|
AllowImportRules, CssRuleType, CssRuleTypes, CssRules, CssRulesHelpers, KeyframesRule,
|
||||||
RulesMutateError, StylesheetLoader as StyleStylesheetLoader,
|
RulesMutateError, StylesheetLoader as StyleStylesheetLoader,
|
||||||
|
@ -44,7 +48,7 @@ pub(crate) struct CSSRuleList {
|
||||||
reflector_: Reflector,
|
reflector_: Reflector,
|
||||||
parent_stylesheet: Dom<CSSStyleSheet>,
|
parent_stylesheet: Dom<CSSStyleSheet>,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
rules: RulesSource,
|
rules: RefCell<RulesSource>,
|
||||||
dom_rules: DomRefCell<Vec<MutNullableDom<CSSRule>>>,
|
dom_rules: DomRefCell<Vec<MutNullableDom<CSSRule>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +82,7 @@ impl CSSRuleList {
|
||||||
CSSRuleList {
|
CSSRuleList {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
parent_stylesheet: Dom::from_ref(parent_stylesheet),
|
parent_stylesheet: Dom::from_ref(parent_stylesheet),
|
||||||
rules,
|
rules: RefCell::new(rules),
|
||||||
dom_rules: DomRefCell::new(dom_rules),
|
dom_rules: DomRefCell::new(dom_rules),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,8 +111,9 @@ impl CSSRuleList {
|
||||||
parse_relative_rule_type: Option<CssRuleType>,
|
parse_relative_rule_type: Option<CssRuleType>,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> Fallible<u32> {
|
) -> Fallible<u32> {
|
||||||
let css_rules = if let RulesSource::Rules(ref rules) = self.rules {
|
self.parent_stylesheet.will_modify();
|
||||||
rules
|
let css_rules = if let RulesSource::Rules(rules) = &*self.rules.borrow() {
|
||||||
|
rules.clone()
|
||||||
} else {
|
} else {
|
||||||
panic!("Called insert_rule on non-CssRule-backed CSSRuleList");
|
panic!("Called insert_rule on non-CssRule-backed CSSRuleList");
|
||||||
};
|
};
|
||||||
|
@ -144,6 +149,7 @@ impl CSSRuleList {
|
||||||
.map_err(Convert::convert)?;
|
.map_err(Convert::convert)?;
|
||||||
|
|
||||||
let parent_stylesheet = &*self.parent_stylesheet;
|
let parent_stylesheet = &*self.parent_stylesheet;
|
||||||
|
parent_stylesheet.will_modify();
|
||||||
let dom_rule = CSSRule::new_specific(window, parent_stylesheet, new_rule, can_gc);
|
let dom_rule = CSSRule::new_specific(window, parent_stylesheet, new_rule, can_gc);
|
||||||
self.dom_rules
|
self.dom_rules
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
@ -154,10 +160,12 @@ impl CSSRuleList {
|
||||||
|
|
||||||
/// In case of a keyframe rule, index must be valid.
|
/// In case of a keyframe rule, index must be valid.
|
||||||
pub(crate) fn remove_rule(&self, index: u32) -> ErrorResult {
|
pub(crate) fn remove_rule(&self, index: u32) -> ErrorResult {
|
||||||
|
self.parent_stylesheet.will_modify();
|
||||||
|
|
||||||
let index = index as usize;
|
let index = index as usize;
|
||||||
let mut guard = self.parent_stylesheet.shared_lock().write();
|
let mut guard = self.parent_stylesheet.shared_lock().write();
|
||||||
|
|
||||||
match self.rules {
|
match *self.rules.borrow() {
|
||||||
RulesSource::Rules(ref css_rules) => {
|
RulesSource::Rules(ref css_rules) => {
|
||||||
css_rules
|
css_rules
|
||||||
.write_with(&mut guard)
|
.write_with(&mut guard)
|
||||||
|
@ -199,7 +207,7 @@ impl CSSRuleList {
|
||||||
rule.or_init(|| {
|
rule.or_init(|| {
|
||||||
let parent_stylesheet = &self.parent_stylesheet;
|
let parent_stylesheet = &self.parent_stylesheet;
|
||||||
let lock = parent_stylesheet.shared_lock();
|
let lock = parent_stylesheet.shared_lock();
|
||||||
match self.rules {
|
match *self.rules.borrow() {
|
||||||
RulesSource::Rules(ref rules) => {
|
RulesSource::Rules(ref rules) => {
|
||||||
let rule = {
|
let rule = {
|
||||||
let guard = lock.read();
|
let guard = lock.read();
|
||||||
|
@ -235,11 +243,48 @@ impl CSSRuleList {
|
||||||
/// Should only be called for keyframes-backed rules, use insert_rule
|
/// Should only be called for keyframes-backed rules, use insert_rule
|
||||||
/// for CssRules-backed rules
|
/// for CssRules-backed rules
|
||||||
pub(crate) fn append_lazy_dom_rule(&self) {
|
pub(crate) fn append_lazy_dom_rule(&self) {
|
||||||
if let RulesSource::Rules(..) = self.rules {
|
if let RulesSource::Rules(..) = &*self.rules.borrow() {
|
||||||
panic!("Can only call append_lazy_rule with keyframes-backed CSSRules");
|
panic!("Can only call append_lazy_rule with keyframes-backed CSSRules");
|
||||||
}
|
}
|
||||||
self.dom_rules.borrow_mut().push(MutNullableDom::new(None));
|
self.dom_rules.borrow_mut().push(MutNullableDom::new(None));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn update_rules(&self, rules: RulesSource, guard: &SharedRwLockReadGuard) {
|
||||||
|
let dom_rules = self.dom_rules.borrow();
|
||||||
|
match rules {
|
||||||
|
RulesSource::Rules(ref css_rules) => {
|
||||||
|
if let RulesSource::Keyframes(..) = &*self.rules.borrow() {
|
||||||
|
panic!("Called update_rules on non-CssRule-backed CSSRuleList with CssRules");
|
||||||
|
}
|
||||||
|
|
||||||
|
let css_rules_iter = css_rules.read_with(guard).0.iter();
|
||||||
|
for (dom_rule, css_rule) in izip!(dom_rules.iter(), css_rules_iter) {
|
||||||
|
let Some(dom_rule) = dom_rule.get() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
dom_rule.update_rule(css_rule, guard);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
RulesSource::Keyframes(ref keyframesrule) => {
|
||||||
|
if let RulesSource::Rules(..) = &*self.rules.borrow() {
|
||||||
|
panic!("Called update_rules on CssRule-backed CSSRuleList with non-CssRules");
|
||||||
|
}
|
||||||
|
|
||||||
|
let keyframerules_iter = keyframesrule.read_with(guard).keyframes.iter();
|
||||||
|
for (dom_rule, keyframerule) in izip!(dom_rules.iter(), keyframerules_iter) {
|
||||||
|
let Some(dom_rule) = dom_rule.get() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let Some(dom_rule) = dom_rule.downcast::<CSSKeyframeRule>() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
dom_rule.update_rule(keyframerule.clone(), guard);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
*self.rules.borrow_mut() = rules;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSRuleListMethods<crate::DomTypeHolder> for CSSRuleList {
|
impl CSSRuleListMethods<crate::DomTypeHolder> for CSSRuleList {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@ pub(crate) enum CSSStyleOwner {
|
||||||
Dom<CSSRule>,
|
Dom<CSSRule>,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
Arc<Locked<PropertyDeclarationBlock>>,
|
RefCell<Arc<Locked<PropertyDeclarationBlock>>>,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,9 +120,10 @@ impl CSSStyleOwner {
|
||||||
result
|
result
|
||||||
},
|
},
|
||||||
CSSStyleOwner::CSSRule(ref rule, ref pdb) => {
|
CSSStyleOwner::CSSRule(ref rule, ref pdb) => {
|
||||||
|
rule.parent_stylesheet().will_modify();
|
||||||
let result = {
|
let result = {
|
||||||
let mut guard = rule.shared_lock().write();
|
let mut guard = rule.shared_lock().write();
|
||||||
f(&mut *pdb.write_with(&mut guard), &mut changed)
|
f(&mut *pdb.borrow().write_with(&mut guard), &mut changed)
|
||||||
};
|
};
|
||||||
if changed {
|
if changed {
|
||||||
rule.parent_stylesheet().notify_invalidations();
|
rule.parent_stylesheet().notify_invalidations();
|
||||||
|
@ -152,7 +154,7 @@ impl CSSStyleOwner {
|
||||||
},
|
},
|
||||||
CSSStyleOwner::CSSRule(ref rule, ref pdb) => {
|
CSSStyleOwner::CSSRule(ref rule, ref pdb) => {
|
||||||
let guard = rule.shared_lock().read();
|
let guard = rule.shared_lock().read();
|
||||||
f(pdb.read_with(&guard))
|
f(pdb.borrow().read_with(&guard))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,6 +267,17 @@ impl CSSStyleDeclaration {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_property_declaration_block(
|
||||||
|
&self,
|
||||||
|
pdb: &Arc<Locked<PropertyDeclarationBlock>>,
|
||||||
|
) {
|
||||||
|
if let CSSStyleOwner::CSSRule(_, pdb_cell) = &self.owner {
|
||||||
|
*pdb_cell.borrow_mut() = pdb.clone();
|
||||||
|
} else {
|
||||||
|
panic!("update_rule called on CSSStyleDeclaration with a Element owner");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_computed_style(&self, property: PropertyId) -> DOMString {
|
fn get_computed_style(&self, property: PropertyId) -> DOMString {
|
||||||
match self.owner {
|
match self.owner {
|
||||||
CSSStyleOwner::CSSRule(..) => {
|
CSSStyleOwner::CSSRule(..) => {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use cssparser::{Parser as CssParser, ParserInput as CssParserInput, ToCss};
|
use cssparser::{Parser as CssParser, ParserInput as CssParserInput, ToCss};
|
||||||
|
@ -9,7 +10,7 @@ use dom_struct::dom_struct;
|
||||||
use selectors::parser::{ParseRelative, SelectorList};
|
use selectors::parser::{ParseRelative, SelectorList};
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::selector_parser::SelectorParser;
|
use style::selector_parser::SelectorParser;
|
||||||
use style::shared_lock::{Locked, ToCssWithGuard};
|
use style::shared_lock::{Locked, SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use style::stylesheets::{CssRuleType, CssRules, Origin, StyleRule};
|
use style::stylesheets::{CssRuleType, CssRules, Origin, StyleRule};
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::Bindings::CSSStyleRuleBinding::CSSStyleRuleMethods;
|
use crate::dom::bindings::codegen::Bindings::CSSStyleRuleBinding::CSSStyleRuleMethods;
|
||||||
|
@ -29,7 +30,7 @@ pub(crate) struct CSSStyleRule {
|
||||||
cssgroupingrule: CSSGroupingRule,
|
cssgroupingrule: CSSGroupingRule,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
stylerule: Arc<Locked<StyleRule>>,
|
stylerule: RefCell<Arc<Locked<StyleRule>>>,
|
||||||
style_decl: MutNullableDom<CSSStyleDeclaration>,
|
style_decl: MutNullableDom<CSSStyleDeclaration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ impl CSSStyleRule {
|
||||||
) -> CSSStyleRule {
|
) -> CSSStyleRule {
|
||||||
CSSStyleRule {
|
CSSStyleRule {
|
||||||
cssgroupingrule: CSSGroupingRule::new_inherited(parent_stylesheet),
|
cssgroupingrule: CSSGroupingRule::new_inherited(parent_stylesheet),
|
||||||
stylerule,
|
stylerule: RefCell::new(stylerule),
|
||||||
style_decl: Default::default(),
|
style_decl: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,11 +64,28 @@ impl CSSStyleRule {
|
||||||
let lock = self.cssgroupingrule.shared_lock();
|
let lock = self.cssgroupingrule.shared_lock();
|
||||||
let mut guard = lock.write();
|
let mut guard = lock.write();
|
||||||
self.stylerule
|
self.stylerule
|
||||||
|
.borrow()
|
||||||
.write_with(&mut guard)
|
.write_with(&mut guard)
|
||||||
.rules
|
.rules
|
||||||
.get_or_insert_with(|| CssRules::new(vec![], lock))
|
.get_or_insert_with(|| CssRules::new(vec![], lock))
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_rule(
|
||||||
|
&self,
|
||||||
|
stylerule: Arc<Locked<StyleRule>>,
|
||||||
|
guard: &SharedRwLockReadGuard,
|
||||||
|
) {
|
||||||
|
if let Some(ref rules) = stylerule.read_with(guard).rules {
|
||||||
|
self.cssgroupingrule.update_rules(rules, guard);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref style_decl) = self.style_decl.get() {
|
||||||
|
style_decl.update_property_declaration_block(&stylerule.read_with(guard).block);
|
||||||
|
}
|
||||||
|
|
||||||
|
*self.stylerule.borrow_mut() = stylerule;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecificCSSRule for CSSStyleRule {
|
impl SpecificCSSRule for CSSStyleRule {
|
||||||
|
@ -78,6 +96,7 @@ impl SpecificCSSRule for CSSStyleRule {
|
||||||
fn get_css(&self) -> DOMString {
|
fn get_css(&self) -> DOMString {
|
||||||
let guard = self.cssgroupingrule.shared_lock().read();
|
let guard = self.cssgroupingrule.shared_lock().read();
|
||||||
self.stylerule
|
self.stylerule
|
||||||
|
.borrow()
|
||||||
.read_with(&guard)
|
.read_with(&guard)
|
||||||
.to_css_string(&guard)
|
.to_css_string(&guard)
|
||||||
.into()
|
.into()
|
||||||
|
@ -93,7 +112,7 @@ impl CSSStyleRuleMethods<crate::DomTypeHolder> for CSSStyleRule {
|
||||||
self.global().as_window(),
|
self.global().as_window(),
|
||||||
CSSStyleOwner::CSSRule(
|
CSSStyleOwner::CSSRule(
|
||||||
Dom::from_ref(self.upcast()),
|
Dom::from_ref(self.upcast()),
|
||||||
self.stylerule.read_with(&guard).block.clone(),
|
RefCell::new(self.stylerule.borrow().read_with(&guard).block.clone()),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
CSSModificationAccess::ReadWrite,
|
CSSModificationAccess::ReadWrite,
|
||||||
|
@ -105,8 +124,13 @@ impl CSSStyleRuleMethods<crate::DomTypeHolder> for CSSStyleRule {
|
||||||
// https://drafts.csswg.org/cssom/#dom-cssstylerule-selectortext
|
// https://drafts.csswg.org/cssom/#dom-cssstylerule-selectortext
|
||||||
fn SelectorText(&self) -> DOMString {
|
fn SelectorText(&self) -> DOMString {
|
||||||
let guard = self.cssgroupingrule.shared_lock().read();
|
let guard = self.cssgroupingrule.shared_lock().read();
|
||||||
let stylerule = self.stylerule.read_with(&guard);
|
DOMString::from_string(
|
||||||
DOMString::from_string(stylerule.selectors.to_css_string())
|
self.stylerule
|
||||||
|
.borrow()
|
||||||
|
.read_with(&guard)
|
||||||
|
.selectors
|
||||||
|
.to_css_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://drafts.csswg.org/cssom/#dom-cssstylerule-selectortext
|
// https://drafts.csswg.org/cssom/#dom-cssstylerule-selectortext
|
||||||
|
@ -115,7 +139,8 @@ impl CSSStyleRuleMethods<crate::DomTypeHolder> for CSSStyleRule {
|
||||||
.cssgroupingrule
|
.cssgroupingrule
|
||||||
.parent_stylesheet()
|
.parent_stylesheet()
|
||||||
.style_stylesheet()
|
.style_stylesheet()
|
||||||
.contents;
|
.contents
|
||||||
|
.clone();
|
||||||
// It's not clear from the spec if we should use the stylesheet's namespaces.
|
// It's not clear from the spec if we should use the stylesheet's namespaces.
|
||||||
// https://github.com/w3c/csswg-drafts/issues/1511
|
// https://github.com/w3c/csswg-drafts/issues/1511
|
||||||
let namespaces = contents.namespaces.read();
|
let namespaces = contents.namespaces.read();
|
||||||
|
@ -131,10 +156,13 @@ impl CSSStyleRuleMethods<crate::DomTypeHolder> for CSSStyleRule {
|
||||||
// TODO: Maybe allow setting relative selectors from the OM, if we're in a nested style
|
// TODO: Maybe allow setting relative selectors from the OM, if we're in a nested style
|
||||||
// rule?
|
// rule?
|
||||||
if let Ok(mut s) = SelectorList::parse(&parser, &mut css_parser, ParseRelative::No) {
|
if let Ok(mut s) = SelectorList::parse(&parser, &mut css_parser, ParseRelative::No) {
|
||||||
|
self.cssgroupingrule.parent_stylesheet().will_modify();
|
||||||
// This mirrors what we do in CSSStyleOwner::mutate_associated_block.
|
// This mirrors what we do in CSSStyleOwner::mutate_associated_block.
|
||||||
let mut guard = self.cssgroupingrule.shared_lock().write();
|
let mut guard = self.cssgroupingrule.shared_lock().write();
|
||||||
let stylerule = self.stylerule.write_with(&mut guard);
|
mem::swap(
|
||||||
mem::swap(&mut stylerule.selectors, &mut s);
|
&mut self.stylerule.borrow().write_with(&mut guard).selectors,
|
||||||
|
&mut s,
|
||||||
|
);
|
||||||
self.cssgroupingrule
|
self.cssgroupingrule
|
||||||
.parent_stylesheet()
|
.parent_stylesheet()
|
||||||
.notify_invalidations();
|
.notify_invalidations();
|
||||||
|
|
|
@ -2,16 +2,17 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::{Cell, Ref};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use js::rust::HandleObject;
|
use js::rust::HandleObject;
|
||||||
|
use script_bindings::inheritance::Castable;
|
||||||
use script_bindings::realms::InRealm;
|
use script_bindings::realms::InRealm;
|
||||||
use script_bindings::root::Dom;
|
use script_bindings::root::Dom;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::media_queries::MediaList as StyleMediaList;
|
use style::media_queries::MediaList as StyleMediaList;
|
||||||
use style::shared_lock::SharedRwLock;
|
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard};
|
||||||
use style::stylesheets::{
|
use style::stylesheets::{
|
||||||
AllowImportRules, CssRuleTypes, Origin, Stylesheet as StyleStyleSheet, UrlExtraData,
|
AllowImportRules, CssRuleTypes, Origin, Stylesheet as StyleStyleSheet, UrlExtraData,
|
||||||
};
|
};
|
||||||
|
@ -33,6 +34,7 @@ use crate::dom::bindings::str::{DOMString, USVString};
|
||||||
use crate::dom::cssrulelist::{CSSRuleList, RulesSource};
|
use crate::dom::cssrulelist::{CSSRuleList, RulesSource};
|
||||||
use crate::dom::document::Document;
|
use crate::dom::document::Document;
|
||||||
use crate::dom::element::Element;
|
use crate::dom::element::Element;
|
||||||
|
use crate::dom::htmlstyleelement::HTMLStyleElement;
|
||||||
use crate::dom::medialist::MediaList;
|
use crate::dom::medialist::MediaList;
|
||||||
use crate::dom::node::NodeTraits;
|
use crate::dom::node::NodeTraits;
|
||||||
use crate::dom::stylesheet::StyleSheet;
|
use crate::dom::stylesheet::StyleSheet;
|
||||||
|
@ -55,7 +57,12 @@ pub(crate) struct CSSStyleSheet {
|
||||||
/// The inner Stylo's [Stylesheet].
|
/// The inner Stylo's [Stylesheet].
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
style_stylesheet: Arc<StyleStyleSheet>,
|
style_stylesheet: DomRefCell<Arc<StyleStyleSheet>>,
|
||||||
|
|
||||||
|
/// The inner Stylo's [SharedRwLock], stored at here to avoid referencing
|
||||||
|
/// temporary variables.
|
||||||
|
#[no_trace]
|
||||||
|
style_shared_lock: SharedRwLock,
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/cssom/#concept-css-style-sheet-origin-clean-flag>
|
/// <https://drafts.csswg.org/cssom/#concept-css-style-sheet-origin-clean-flag>
|
||||||
origin_clean: Cell<bool>,
|
origin_clean: Cell<bool>,
|
||||||
|
@ -86,7 +93,8 @@ impl CSSStyleSheet {
|
||||||
stylesheet: StyleSheet::new_inherited(type_, href, title),
|
stylesheet: StyleSheet::new_inherited(type_, href, title),
|
||||||
owner_node: MutNullableDom::new(owner),
|
owner_node: MutNullableDom::new(owner),
|
||||||
rulelist: MutNullableDom::new(None),
|
rulelist: MutNullableDom::new(None),
|
||||||
style_stylesheet: stylesheet,
|
style_shared_lock: stylesheet.shared_lock.clone(),
|
||||||
|
style_stylesheet: DomRefCell::new(stylesheet),
|
||||||
origin_clean: Cell::new(true),
|
origin_clean: Cell::new(true),
|
||||||
constructor_document: constructor_document.map(Dom::from_ref),
|
constructor_document: constructor_document.map(Dom::from_ref),
|
||||||
adopters: Default::default(),
|
adopters: Default::default(),
|
||||||
|
@ -150,7 +158,7 @@ impl CSSStyleSheet {
|
||||||
|
|
||||||
fn rulelist(&self, can_gc: CanGc) -> DomRoot<CSSRuleList> {
|
fn rulelist(&self, can_gc: CanGc) -> DomRoot<CSSRuleList> {
|
||||||
self.rulelist.or_init(|| {
|
self.rulelist.or_init(|| {
|
||||||
let rules = self.style_stylesheet.contents.rules.clone();
|
let rules = self.style_stylesheet.borrow().contents.rules.clone();
|
||||||
CSSRuleList::new(
|
CSSRuleList::new(
|
||||||
self.global().as_window(),
|
self.global().as_window(),
|
||||||
self,
|
self,
|
||||||
|
@ -161,7 +169,7 @@ impl CSSStyleSheet {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn disabled(&self) -> bool {
|
pub(crate) fn disabled(&self) -> bool {
|
||||||
self.style_stylesheet.disabled()
|
self.style_stylesheet.borrow().disabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn owner_node(&self) -> Option<DomRoot<Element>> {
|
pub(crate) fn owner_node(&self) -> Option<DomRoot<Element>> {
|
||||||
|
@ -169,7 +177,7 @@ impl CSSStyleSheet {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_disabled(&self, disabled: bool) {
|
pub(crate) fn set_disabled(&self, disabled: bool) {
|
||||||
if self.style_stylesheet.set_disabled(disabled) {
|
if self.style_stylesheet.borrow().set_disabled(disabled) {
|
||||||
self.notify_invalidations();
|
self.notify_invalidations();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,15 +187,11 @@ impl CSSStyleSheet {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn shared_lock(&self) -> &SharedRwLock {
|
pub(crate) fn shared_lock(&self) -> &SharedRwLock {
|
||||||
&self.style_stylesheet.shared_lock
|
&self.style_shared_lock
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn style_stylesheet(&self) -> &StyleStyleSheet {
|
pub(crate) fn style_stylesheet(&self) -> Ref<'_, Arc<StyleStyleSheet>> {
|
||||||
&self.style_stylesheet
|
self.style_stylesheet.borrow()
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn style_stylesheet_arc(&self) -> &Arc<StyleStyleSheet> {
|
|
||||||
&self.style_stylesheet
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_origin_clean(&self, origin_clean: bool) {
|
pub(crate) fn set_origin_clean(&self, origin_clean: bool) {
|
||||||
|
@ -231,6 +235,36 @@ impl CSSStyleSheet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn will_modify(&self) {
|
||||||
|
let Some(node) = self.owner_node.get() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(node) = node.downcast::<HTMLStyleElement>() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
node.will_modify_stylesheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_style_stylesheet(
|
||||||
|
&self,
|
||||||
|
style_stylesheet: &Arc<StyleStyleSheet>,
|
||||||
|
guard: &SharedRwLockReadGuard,
|
||||||
|
) {
|
||||||
|
// When the shared `StylesheetContents` is about to be modified,
|
||||||
|
// `CSSStyleSheet::owner_node` performs a copy-on-write to avoid
|
||||||
|
// affecting other sharers, see `CSSStyleSheet::will_modify`. And
|
||||||
|
// then updates the references to `CssRule` or `PropertyDeclarationBlock`
|
||||||
|
// stored in the CSSOMs to ensure that modifications are made only
|
||||||
|
// on the new copy.
|
||||||
|
*self.style_stylesheet.borrow_mut() = style_stylesheet.clone();
|
||||||
|
if let Some(rulelist) = self.rulelist.get() {
|
||||||
|
let rules = style_stylesheet.contents.rules.clone();
|
||||||
|
rulelist.update_rules(RulesSource::Rules(rules), guard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Invalidate all stylesheet set this stylesheet is a part on.
|
/// Invalidate all stylesheet set this stylesheet is a part on.
|
||||||
pub(crate) fn notify_invalidations(&self) {
|
pub(crate) fn notify_invalidations(&self) {
|
||||||
if let Some(owner) = self.owner_node() {
|
if let Some(owner) = self.owner_node() {
|
||||||
|
@ -402,8 +436,12 @@ impl CSSStyleSheetMethods<crate::DomTypeHolder> for CSSStyleSheet {
|
||||||
let global = sheet.global();
|
let global = sheet.global();
|
||||||
let window = global.as_window();
|
let window = global.as_window();
|
||||||
|
|
||||||
|
sheet.will_modify();
|
||||||
|
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
let _span = tracing::trace_span!("ParseStylesheet", servo_profiling = true).entered();
|
||||||
StyleStyleSheet::update_from_str(
|
StyleStyleSheet::update_from_str(
|
||||||
&sheet.style_stylesheet,
|
&sheet.style_stylesheet(),
|
||||||
&text,
|
&text,
|
||||||
UrlExtraData(window.get_url().get_arc()),
|
UrlExtraData(window.get_url().get_arc()),
|
||||||
None,
|
None,
|
||||||
|
@ -441,8 +479,12 @@ impl CSSStyleSheetMethods<crate::DomTypeHolder> for CSSStyleSheet {
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
let window = global.as_window();
|
let window = global.as_window();
|
||||||
|
|
||||||
|
self.will_modify();
|
||||||
|
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
let _span = tracing::trace_span!("ParseStylesheet", servo_profiling = true).entered();
|
||||||
StyleStyleSheet::update_from_str(
|
StyleStyleSheet::update_from_str(
|
||||||
&self.style_stylesheet,
|
&self.style_stylesheet(),
|
||||||
&text,
|
&text,
|
||||||
UrlExtraData(window.get_url().get_arc()),
|
UrlExtraData(window.get_url().get_arc()),
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::shared_lock::ToCssWithGuard;
|
use style::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use style::stylesheets::{CssRuleType, SupportsRule};
|
use style::stylesheets::{CssRuleType, SupportsRule};
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
|
|
||||||
|
@ -22,7 +24,7 @@ pub(crate) struct CSSSupportsRule {
|
||||||
cssconditionrule: CSSConditionRule,
|
cssconditionrule: CSSConditionRule,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
supportsrule: Arc<SupportsRule>,
|
supportsrule: RefCell<Arc<SupportsRule>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSSupportsRule {
|
impl CSSSupportsRule {
|
||||||
|
@ -33,7 +35,7 @@ impl CSSSupportsRule {
|
||||||
let list = supportsrule.rules.clone();
|
let list = supportsrule.rules.clone();
|
||||||
CSSSupportsRule {
|
CSSSupportsRule {
|
||||||
cssconditionrule: CSSConditionRule::new_inherited(parent_stylesheet, list),
|
cssconditionrule: CSSConditionRule::new_inherited(parent_stylesheet, list),
|
||||||
supportsrule,
|
supportsrule: RefCell::new(supportsrule),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +58,17 @@ impl CSSSupportsRule {
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/css-conditional-3/#the-csssupportsrule-interface>
|
/// <https://drafts.csswg.org/css-conditional-3/#the-csssupportsrule-interface>
|
||||||
pub(crate) fn get_condition_text(&self) -> DOMString {
|
pub(crate) fn get_condition_text(&self) -> DOMString {
|
||||||
self.supportsrule.condition.to_css_string().into()
|
self.supportsrule.borrow().condition.to_css_string().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_rule(
|
||||||
|
&self,
|
||||||
|
supportsrule: Arc<SupportsRule>,
|
||||||
|
guard: &SharedRwLockReadGuard,
|
||||||
|
) {
|
||||||
|
self.cssconditionrule
|
||||||
|
.update_rules(supportsrule.rules.clone(), guard);
|
||||||
|
*self.supportsrule.borrow_mut() = supportsrule;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +79,6 @@ impl SpecificCSSRule for CSSSupportsRule {
|
||||||
|
|
||||||
fn get_css(&self) -> DOMString {
|
fn get_css(&self) -> DOMString {
|
||||||
let guard = self.cssconditionrule.shared_lock().read();
|
let guard = self.cssconditionrule.shared_lock().read();
|
||||||
self.supportsrule.to_css_string(&guard).into()
|
self.supportsrule.borrow().to_css_string(&guard).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4021,7 +4021,7 @@ impl Document {
|
||||||
debug_assert!(cssom_stylesheet.is_constructed());
|
debug_assert!(cssom_stylesheet.is_constructed());
|
||||||
|
|
||||||
let stylesheets = &mut *self.stylesheets.borrow_mut();
|
let stylesheets = &mut *self.stylesheets.borrow_mut();
|
||||||
let sheet = cssom_stylesheet.style_stylesheet_arc().clone();
|
let sheet = cssom_stylesheet.style_stylesheet().clone();
|
||||||
|
|
||||||
let insertion_point = stylesheets
|
let insertion_point = stylesheets
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -397,7 +397,7 @@ impl DocumentOrShadowRoot {
|
||||||
if stylesheet_remove_set.insert(sheet_to_remove) {
|
if stylesheet_remove_set.insert(sheet_to_remove) {
|
||||||
owner.remove_stylesheet(
|
owner.remove_stylesheet(
|
||||||
StylesheetSource::Constructed(sheet_to_remove.clone()),
|
StylesheetSource::Constructed(sheet_to_remove.clone()),
|
||||||
sheet_to_remove.style_stylesheet_arc(),
|
&sheet_to_remove.style_stylesheet(),
|
||||||
);
|
);
|
||||||
sheet_to_remove.remove_adopter(owner);
|
sheet_to_remove.remove_adopter(owner);
|
||||||
}
|
}
|
||||||
|
@ -416,7 +416,7 @@ impl DocumentOrShadowRoot {
|
||||||
// around.
|
// around.
|
||||||
owner.remove_stylesheet(
|
owner.remove_stylesheet(
|
||||||
StylesheetSource::Constructed(sheet.clone()),
|
StylesheetSource::Constructed(sheet.clone()),
|
||||||
sheet.style_stylesheet_arc(),
|
&sheet.style_stylesheet(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
sheet.add_adopter(owner.clone());
|
sheet.add_adopter(owner.clone());
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use html5ever::{LocalName, Prefix};
|
use html5ever::{LocalName, Prefix};
|
||||||
|
@ -11,7 +12,8 @@ use net_traits::ReferrerPolicy;
|
||||||
use script_bindings::root::Dom;
|
use script_bindings::root::Dom;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::media_queries::MediaList as StyleMediaList;
|
use style::media_queries::MediaList as StyleMediaList;
|
||||||
use style::stylesheets::{AllowImportRules, Origin, Stylesheet, UrlExtraData};
|
use style::shared_lock::DeepCloneWithLock;
|
||||||
|
use style::stylesheets::{AllowImportRules, Origin, Stylesheet, StylesheetContents, UrlExtraData};
|
||||||
|
|
||||||
use crate::dom::attr::Attr;
|
use crate::dom::attr::Attr;
|
||||||
use crate::dom::bindings::cell::DomRefCell;
|
use crate::dom::bindings::cell::DomRefCell;
|
||||||
|
@ -29,6 +31,7 @@ use crate::dom::htmlelement::HTMLElement;
|
||||||
use crate::dom::medialist::MediaList;
|
use crate::dom::medialist::MediaList;
|
||||||
use crate::dom::node::{BindContext, ChildrenMutation, Node, NodeTraits, UnbindContext};
|
use crate::dom::node::{BindContext, ChildrenMutation, Node, NodeTraits, UnbindContext};
|
||||||
use crate::dom::stylesheet::StyleSheet as DOMStyleSheet;
|
use crate::dom::stylesheet::StyleSheet as DOMStyleSheet;
|
||||||
|
use crate::dom::stylesheetcontentscache::{StylesheetContentsCache, StylesheetContentsCacheKey};
|
||||||
use crate::dom::virtualmethods::VirtualMethods;
|
use crate::dom::virtualmethods::VirtualMethods;
|
||||||
use crate::script_runtime::CanGc;
|
use crate::script_runtime::CanGc;
|
||||||
use crate::stylesheet_loader::{StylesheetLoader, StylesheetOwner};
|
use crate::stylesheet_loader::{StylesheetLoader, StylesheetOwner};
|
||||||
|
@ -39,6 +42,8 @@ pub(crate) struct HTMLStyleElement {
|
||||||
#[conditional_malloc_size_of]
|
#[conditional_malloc_size_of]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
stylesheet: DomRefCell<Option<Arc<Stylesheet>>>,
|
stylesheet: DomRefCell<Option<Arc<Stylesheet>>>,
|
||||||
|
#[no_trace]
|
||||||
|
stylesheetcontents_cache_key: DomRefCell<Option<StylesheetContentsCacheKey>>,
|
||||||
cssom_stylesheet: MutNullableDom<CSSStyleSheet>,
|
cssom_stylesheet: MutNullableDom<CSSStyleSheet>,
|
||||||
/// <https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts>
|
/// <https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts>
|
||||||
parser_inserted: Cell<bool>,
|
parser_inserted: Cell<bool>,
|
||||||
|
@ -57,6 +62,7 @@ impl HTMLStyleElement {
|
||||||
HTMLStyleElement {
|
HTMLStyleElement {
|
||||||
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
|
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
|
||||||
stylesheet: DomRefCell::new(None),
|
stylesheet: DomRefCell::new(None),
|
||||||
|
stylesheetcontents_cache_key: DomRefCell::new(None),
|
||||||
cssom_stylesheet: MutNullableDom::new(None),
|
cssom_stylesheet: MutNullableDom::new(None),
|
||||||
parser_inserted: Cell::new(creator.is_parser_created()),
|
parser_inserted: Cell::new(creator.is_parser_created()),
|
||||||
in_stack_of_open_elements: Cell::new(creator.is_parser_created()),
|
in_stack_of_open_elements: Cell::new(creator.is_parser_created()),
|
||||||
|
@ -125,19 +131,41 @@ impl HTMLStyleElement {
|
||||||
let shared_lock = node.owner_doc().style_shared_lock().clone();
|
let shared_lock = node.owner_doc().style_shared_lock().clone();
|
||||||
let mq = Arc::new(shared_lock.wrap(self.create_media_list(&self.Media())));
|
let mq = Arc::new(shared_lock.wrap(self.create_media_list(&self.Media())));
|
||||||
let loader = StylesheetLoader::for_element(self.upcast());
|
let loader = StylesheetLoader::for_element(self.upcast());
|
||||||
let sheet = Stylesheet::from_str(
|
|
||||||
|
let stylesheetcontents_create_callback = || {
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
let _span = tracing::trace_span!("ParseStylesheet", servo_profiling = true).entered();
|
||||||
|
StylesheetContents::from_str(
|
||||||
&data,
|
&data,
|
||||||
UrlExtraData(window.get_url().get_arc()),
|
UrlExtraData(window.get_url().get_arc()),
|
||||||
Origin::Author,
|
Origin::Author,
|
||||||
mq,
|
&shared_lock,
|
||||||
shared_lock,
|
|
||||||
Some(&loader),
|
Some(&loader),
|
||||||
window.css_error_reporter(),
|
window.css_error_reporter(),
|
||||||
doc.quirks_mode(),
|
doc.quirks_mode(),
|
||||||
AllowImportRules::Yes,
|
AllowImportRules::Yes,
|
||||||
|
/* sanitized_output = */ None,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
// For duplicate style sheets with identical content, `StylesheetContents` can be reused
|
||||||
|
// to avoid reedundant parsing of the style sheets. Additionally, the cache hit rate of
|
||||||
|
// stylo's `CascadeDataCache` can now be significantly improved. When shared `StylesheetContents`
|
||||||
|
// is modified, copy-on-write will occur, see `CSSStyleSheet::will_modify`.
|
||||||
|
let (cache_key, contents) = StylesheetContentsCache::get_or_insert_with(
|
||||||
|
&data,
|
||||||
|
&shared_lock,
|
||||||
|
UrlExtraData(window.get_url().get_arc()),
|
||||||
|
doc.quirks_mode(),
|
||||||
|
stylesheetcontents_create_callback,
|
||||||
);
|
);
|
||||||
|
|
||||||
let sheet = Arc::new(sheet);
|
let sheet = Arc::new(Stylesheet {
|
||||||
|
contents,
|
||||||
|
shared_lock,
|
||||||
|
media: mq,
|
||||||
|
disabled: AtomicBool::new(false),
|
||||||
|
});
|
||||||
|
|
||||||
// No subresource loads were triggered, queue load event
|
// No subresource loads were triggered, queue load event
|
||||||
if self.pending_loads.get() == 0 {
|
if self.pending_loads.get() == 0 {
|
||||||
|
@ -147,22 +175,44 @@ impl HTMLStyleElement {
|
||||||
.queue_simple_event(self.upcast(), atom!("load"));
|
.queue_simple_event(self.upcast(), atom!("load"));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.set_stylesheet(sheet);
|
self.set_stylesheet(sheet, cache_key, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(emilio): This is duplicated with HTMLLinkElement::set_stylesheet.
|
// FIXME(emilio): This is duplicated with HTMLLinkElement::set_stylesheet.
|
||||||
|
//
|
||||||
|
// With the reuse of `StylesheetContent` for same stylesheet string content,
|
||||||
|
// this function has a bit difference with `HTMLLinkElement::set_stylesheet` now.
|
||||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||||
pub(crate) fn set_stylesheet(&self, s: Arc<Stylesheet>) {
|
pub(crate) fn set_stylesheet(
|
||||||
|
&self,
|
||||||
|
s: Arc<Stylesheet>,
|
||||||
|
cache_key: Option<StylesheetContentsCacheKey>,
|
||||||
|
need_clean_cssom: bool,
|
||||||
|
) {
|
||||||
let stylesheets_owner = self.stylesheet_list_owner();
|
let stylesheets_owner = self.stylesheet_list_owner();
|
||||||
if let Some(ref s) = *self.stylesheet.borrow() {
|
if let Some(ref s) = *self.stylesheet.borrow() {
|
||||||
stylesheets_owner
|
stylesheets_owner
|
||||||
.remove_stylesheet(StylesheetSource::Element(Dom::from_ref(self.upcast())), s)
|
.remove_stylesheet(StylesheetSource::Element(Dom::from_ref(self.upcast())), s);
|
||||||
}
|
}
|
||||||
*self.stylesheet.borrow_mut() = Some(s.clone());
|
|
||||||
|
if need_clean_cssom {
|
||||||
self.clean_stylesheet_ownership();
|
self.clean_stylesheet_ownership();
|
||||||
|
} else if let Some(cssom_stylesheet) = self.cssom_stylesheet.get() {
|
||||||
|
let guard = s.shared_lock.read();
|
||||||
|
cssom_stylesheet.update_style_stylesheet(&s, &guard);
|
||||||
|
}
|
||||||
|
|
||||||
|
*self.stylesheet.borrow_mut() = Some(s.clone());
|
||||||
|
*self.stylesheetcontents_cache_key.borrow_mut() = cache_key;
|
||||||
stylesheets_owner.add_owned_stylesheet(self.upcast(), s);
|
stylesheets_owner.add_owned_stylesheet(self.upcast(), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn will_modify_stylesheet(&self) {
|
||||||
|
if let Some(stylesheet_with_owned_contents) = self.create_owned_contents_stylesheet() {
|
||||||
|
self.set_stylesheet(stylesheet_with_owned_contents, None, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> {
|
pub(crate) fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> {
|
||||||
self.stylesheet.borrow().clone()
|
self.stylesheet.borrow().clone()
|
||||||
}
|
}
|
||||||
|
@ -184,18 +234,55 @@ impl HTMLStyleElement {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_owned_contents_stylesheet(&self) -> Option<Arc<Stylesheet>> {
|
||||||
|
let cache_key = self.stylesheetcontents_cache_key.borrow_mut().take()?;
|
||||||
|
if cache_key.is_uniquely_owned() {
|
||||||
|
StylesheetContentsCache::remove(cache_key);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let stylesheet_with_shared_contents = self.stylesheet.borrow().clone()?;
|
||||||
|
let lock = stylesheet_with_shared_contents.shared_lock.clone();
|
||||||
|
let guard = stylesheet_with_shared_contents.shared_lock.read();
|
||||||
|
let stylesheet_with_owned_contents = Arc::new(Stylesheet {
|
||||||
|
contents: Arc::new(
|
||||||
|
stylesheet_with_shared_contents
|
||||||
|
.contents
|
||||||
|
.deep_clone_with_lock(&lock, &guard),
|
||||||
|
),
|
||||||
|
shared_lock: lock,
|
||||||
|
media: stylesheet_with_shared_contents.media.clone(),
|
||||||
|
disabled: AtomicBool::new(
|
||||||
|
stylesheet_with_shared_contents
|
||||||
|
.disabled
|
||||||
|
.load(Ordering::SeqCst),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
Some(stylesheet_with_owned_contents)
|
||||||
|
}
|
||||||
|
|
||||||
fn clean_stylesheet_ownership(&self) {
|
fn clean_stylesheet_ownership(&self) {
|
||||||
if let Some(cssom_stylesheet) = self.cssom_stylesheet.get() {
|
if let Some(cssom_stylesheet) = self.cssom_stylesheet.get() {
|
||||||
|
// If the CSSOMs change from having an owner node to being ownerless, they may still
|
||||||
|
// potentially modify shared stylesheets. Thus, create an new `Stylesheet` with owned
|
||||||
|
// `StylesheetContents` to ensure that the potentially modifications are only made on
|
||||||
|
// the owned `StylesheetContents`.
|
||||||
|
if let Some(stylesheet) = self.create_owned_contents_stylesheet() {
|
||||||
|
let guard = stylesheet.shared_lock.read();
|
||||||
|
cssom_stylesheet.update_style_stylesheet(&stylesheet, &guard);
|
||||||
|
}
|
||||||
cssom_stylesheet.set_owner_node(None);
|
cssom_stylesheet.set_owner_node(None);
|
||||||
}
|
}
|
||||||
self.cssom_stylesheet.set(None);
|
self.cssom_stylesheet.set(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_stylesheet(&self) {
|
fn remove_stylesheet(&self) {
|
||||||
if let Some(s) = self.stylesheet.borrow_mut().take() {
|
|
||||||
self.clean_stylesheet_ownership();
|
self.clean_stylesheet_ownership();
|
||||||
|
if let Some(s) = self.stylesheet.borrow_mut().take() {
|
||||||
self.stylesheet_list_owner()
|
self.stylesheet_list_owner()
|
||||||
.remove_stylesheet(StylesheetSource::Element(Dom::from_ref(self.upcast())), &s)
|
.remove_stylesheet(StylesheetSource::Element(Dom::from_ref(self.upcast())), &s);
|
||||||
|
let _ = self.stylesheetcontents_cache_key.borrow_mut().take();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use cssparser::{Parser, ParserInput};
|
use cssparser::{Parser, ParserInput};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
@ -26,7 +28,7 @@ pub(crate) struct MediaList {
|
||||||
parent_stylesheet: Dom<CSSStyleSheet>,
|
parent_stylesheet: Dom<CSSStyleSheet>,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
#[no_trace]
|
#[no_trace]
|
||||||
media_queries: Arc<Locked<StyleMediaList>>,
|
media_queries: RefCell<Arc<Locked<StyleMediaList>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MediaList {
|
impl MediaList {
|
||||||
|
@ -38,7 +40,7 @@ impl MediaList {
|
||||||
MediaList {
|
MediaList {
|
||||||
parent_stylesheet: Dom::from_ref(parent_stylesheet),
|
parent_stylesheet: Dom::from_ref(parent_stylesheet),
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
media_queries,
|
media_queries: RefCell::new(media_queries),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +59,7 @@ impl MediaList {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shared_lock(&self) -> &SharedRwLock {
|
fn shared_lock(&self) -> &SharedRwLock {
|
||||||
&self.parent_stylesheet.style_stylesheet().shared_lock
|
self.parent_stylesheet.shared_lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/cssom/#parse-a-media-query-list>
|
/// <https://drafts.csswg.org/cssom/#parse-a-media-query-list>
|
||||||
|
@ -109,7 +111,11 @@ impl MediaList {
|
||||||
|
|
||||||
pub(crate) fn clone_media_list(&self) -> StyleMediaList {
|
pub(crate) fn clone_media_list(&self) -> StyleMediaList {
|
||||||
let guard = self.shared_lock().read();
|
let guard = self.shared_lock().read();
|
||||||
self.media_queries.read_with(&guard).clone()
|
self.media_queries.borrow().read_with(&guard).clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_media_list(&self, media_queries: Arc<Locked<StyleMediaList>>) {
|
||||||
|
*self.media_queries.borrow_mut() = media_queries;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,14 +123,21 @@ impl MediaListMethods<crate::DomTypeHolder> for MediaList {
|
||||||
/// <https://drafts.csswg.org/cssom/#dom-medialist-mediatext>
|
/// <https://drafts.csswg.org/cssom/#dom-medialist-mediatext>
|
||||||
fn MediaText(&self) -> DOMString {
|
fn MediaText(&self) -> DOMString {
|
||||||
let guard = self.shared_lock().read();
|
let guard = self.shared_lock().read();
|
||||||
DOMString::from(self.media_queries.read_with(&guard).to_css_string())
|
DOMString::from(
|
||||||
|
self.media_queries
|
||||||
|
.borrow()
|
||||||
|
.read_with(&guard)
|
||||||
|
.to_css_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/cssom/#dom-medialist-mediatext>
|
/// <https://drafts.csswg.org/cssom/#dom-medialist-mediatext>
|
||||||
fn SetMediaText(&self, value: DOMString) {
|
fn SetMediaText(&self, value: DOMString) {
|
||||||
|
self.parent_stylesheet.will_modify();
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
let mut guard = self.shared_lock().write();
|
let mut guard = self.shared_lock().write();
|
||||||
let media_queries = self.media_queries.write_with(&mut guard);
|
let media_queries_borrowed = self.media_queries.borrow();
|
||||||
|
let media_queries = media_queries_borrowed.write_with(&mut guard);
|
||||||
*media_queries = Self::parse_media_list(&value, global.as_window());
|
*media_queries = Self::parse_media_list(&value, global.as_window());
|
||||||
self.parent_stylesheet.notify_invalidations();
|
self.parent_stylesheet.notify_invalidations();
|
||||||
}
|
}
|
||||||
|
@ -132,13 +145,18 @@ impl MediaListMethods<crate::DomTypeHolder> for MediaList {
|
||||||
// https://drafts.csswg.org/cssom/#dom-medialist-length
|
// https://drafts.csswg.org/cssom/#dom-medialist-length
|
||||||
fn Length(&self) -> u32 {
|
fn Length(&self) -> u32 {
|
||||||
let guard = self.shared_lock().read();
|
let guard = self.shared_lock().read();
|
||||||
self.media_queries.read_with(&guard).media_queries.len() as u32
|
self.media_queries
|
||||||
|
.borrow()
|
||||||
|
.read_with(&guard)
|
||||||
|
.media_queries
|
||||||
|
.len() as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/cssom/#dom-medialist-item>
|
/// <https://drafts.csswg.org/cssom/#dom-medialist-item>
|
||||||
fn Item(&self, index: u32) -> Option<DOMString> {
|
fn Item(&self, index: u32) -> Option<DOMString> {
|
||||||
let guard = self.shared_lock().read();
|
let guard = self.shared_lock().read();
|
||||||
self.media_queries
|
self.media_queries
|
||||||
|
.borrow()
|
||||||
.read_with(&guard)
|
.read_with(&guard)
|
||||||
.media_queries
|
.media_queries
|
||||||
.get(index as usize)
|
.get(index as usize)
|
||||||
|
@ -160,18 +178,28 @@ impl MediaListMethods<crate::DomTypeHolder> for MediaList {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Step 3
|
// Step 3
|
||||||
|
{
|
||||||
let m_serialized = m.clone().unwrap().to_css_string();
|
let m_serialized = m.clone().unwrap().to_css_string();
|
||||||
let mut guard = self.shared_lock().write();
|
let guard = self.shared_lock().read();
|
||||||
let mq = self.media_queries.write_with(&mut guard);
|
let any = self
|
||||||
let any = mq
|
.media_queries
|
||||||
|
.borrow()
|
||||||
|
.read_with(&guard)
|
||||||
.media_queries
|
.media_queries
|
||||||
.iter()
|
.iter()
|
||||||
.any(|q| m_serialized == q.to_css_string());
|
.any(|q| m_serialized == q.to_css_string());
|
||||||
if any {
|
if any {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Step 4
|
// Step 4
|
||||||
mq.media_queries.push(m.unwrap());
|
self.parent_stylesheet.will_modify();
|
||||||
|
let mut guard = self.shared_lock().write();
|
||||||
|
self.media_queries
|
||||||
|
.borrow()
|
||||||
|
.write_with(&mut guard)
|
||||||
|
.media_queries
|
||||||
|
.push(m.unwrap());
|
||||||
self.parent_stylesheet.notify_invalidations();
|
self.parent_stylesheet.notify_invalidations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,9 +213,11 @@ impl MediaListMethods<crate::DomTypeHolder> for MediaList {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Step 3
|
// Step 3
|
||||||
|
self.parent_stylesheet.will_modify();
|
||||||
let m_serialized = m.unwrap().to_css_string();
|
let m_serialized = m.unwrap().to_css_string();
|
||||||
let mut guard = self.shared_lock().write();
|
let mut guard = self.shared_lock().write();
|
||||||
let media_list = self.media_queries.write_with(&mut guard);
|
let media_queries_borrowed = self.media_queries.borrow();
|
||||||
|
let media_list = media_queries_borrowed.write_with(&mut guard);
|
||||||
let new_vec = media_list
|
let new_vec = media_list
|
||||||
.media_queries
|
.media_queries
|
||||||
.drain(..)
|
.drain(..)
|
||||||
|
|
|
@ -562,6 +562,7 @@ pub(crate) mod storage;
|
||||||
pub(crate) mod storageevent;
|
pub(crate) mod storageevent;
|
||||||
pub(crate) mod stylepropertymapreadonly;
|
pub(crate) mod stylepropertymapreadonly;
|
||||||
pub(crate) mod stylesheet;
|
pub(crate) mod stylesheet;
|
||||||
|
pub(crate) mod stylesheetcontentscache;
|
||||||
pub(crate) mod stylesheetlist;
|
pub(crate) mod stylesheetlist;
|
||||||
pub(crate) mod submitevent;
|
pub(crate) mod submitevent;
|
||||||
pub(crate) mod subtlecrypto;
|
pub(crate) mod subtlecrypto;
|
||||||
|
|
|
@ -242,7 +242,7 @@ impl ShadowRoot {
|
||||||
debug_assert!(cssom_stylesheet.is_constructed());
|
debug_assert!(cssom_stylesheet.is_constructed());
|
||||||
|
|
||||||
let stylesheets = &mut self.author_styles.borrow_mut().stylesheets;
|
let stylesheets = &mut self.author_styles.borrow_mut().stylesheets;
|
||||||
let sheet = cssom_stylesheet.style_stylesheet_arc().clone();
|
let sheet = cssom_stylesheet.style_stylesheet().clone();
|
||||||
|
|
||||||
let insertion_point = stylesheets.iter().last().cloned();
|
let insertion_point = stylesheets.iter().last().cloned();
|
||||||
|
|
||||||
|
|
122
components/script/dom/stylesheetcontentscache.rs
Normal file
122
components/script/dom/stylesheetcontentscache.rs
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::collections::hash_map::Entry;
|
||||||
|
use std::hash::{DefaultHasher, Hash, Hasher};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use servo_arc::Arc as ServoArc;
|
||||||
|
use style::context::QuirksMode;
|
||||||
|
use style::shared_lock::SharedRwLock;
|
||||||
|
use style::stylesheets::{CssRule, StylesheetContents, UrlExtraData};
|
||||||
|
use stylo_atoms::Atom;
|
||||||
|
|
||||||
|
const MAX_LENGTH_OF_TEXT_INSERTED_INTO_TABLE: usize = 1024;
|
||||||
|
const UNIQUE_OWNED: usize = 2;
|
||||||
|
|
||||||
|
/// Using [`Atom`] as a cache key to avoid inefficient string content comparison. Although
|
||||||
|
/// the [`Atom`] is already based on reference counting, an extra [`Rc`] is introduced
|
||||||
|
/// to trace how many [`style::stylesheets::Stylesheet`]s of style elements are sharing
|
||||||
|
/// same [`StylesheetContents`], based on the following considerations:
|
||||||
|
/// * The reference count within [`Atom`] is dedicated to lifecycle management and is not
|
||||||
|
/// suitable for tracking the number of [`StylesheetContents`]s owners.
|
||||||
|
/// * The reference count within [`Atom`] is not publicly acessible.
|
||||||
|
#[derive(Clone, Eq, Hash, MallocSizeOf, PartialEq)]
|
||||||
|
pub(crate) struct StylesheetContentsCacheKey {
|
||||||
|
#[conditional_malloc_size_of]
|
||||||
|
stylesheet_text: Rc<Atom>,
|
||||||
|
base_url: Atom,
|
||||||
|
#[ignore_malloc_size_of = "defined in style crate"]
|
||||||
|
quirks_mode: QuirksMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StylesheetContentsCacheKey {
|
||||||
|
fn new(stylesheet_text: &str, base_url: &str, quirks_mode: QuirksMode) -> Self {
|
||||||
|
// The stylesheet text may be quite lengthy, exceeding hundreds of kilobytes.
|
||||||
|
// Instead of directly inserting such a huge string into AtomicString table,
|
||||||
|
// take its hash value and use that. (This is not a cryptographic hash, so a
|
||||||
|
// page could cause collisions if it wanted to.)
|
||||||
|
let contents_atom = if stylesheet_text.len() > MAX_LENGTH_OF_TEXT_INSERTED_INTO_TABLE {
|
||||||
|
let mut hasher = DefaultHasher::new();
|
||||||
|
stylesheet_text.hash(&mut hasher);
|
||||||
|
Atom::from(hasher.finish().to_string().as_str())
|
||||||
|
} else {
|
||||||
|
Atom::from(stylesheet_text)
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
stylesheet_text: Rc::new(contents_atom),
|
||||||
|
base_url: Atom::from(base_url),
|
||||||
|
quirks_mode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_uniquely_owned(&self) -> bool {
|
||||||
|
// The cache itself already holds one reference.
|
||||||
|
Rc::strong_count(&self.stylesheet_text) <= UNIQUE_OWNED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_local! {
|
||||||
|
static STYLESHEETCONTENTS_CACHE: RefCell<HashMap<StylesheetContentsCacheKey, ServoArc<StylesheetContents>>> =
|
||||||
|
RefCell::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct StylesheetContentsCache;
|
||||||
|
|
||||||
|
impl StylesheetContentsCache {
|
||||||
|
fn contents_can_be_cached(contents: &StylesheetContents, shared_lock: &SharedRwLock) -> bool {
|
||||||
|
let guard = shared_lock.read();
|
||||||
|
let rules = contents.rules(&guard);
|
||||||
|
// The copy-on-write can not be performed when the modification happens on the
|
||||||
|
// imported stylesheet, because it containing cssom has no owner dom node.
|
||||||
|
!(rules.is_empty() || rules.iter().any(|rule| matches!(rule, CssRule::Import(_))))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_or_insert_with(
|
||||||
|
stylesheet_text: &str,
|
||||||
|
shared_lock: &SharedRwLock,
|
||||||
|
url_data: UrlExtraData,
|
||||||
|
quirks_mode: QuirksMode,
|
||||||
|
stylesheetcontents_create_callback: impl FnOnce() -> ServoArc<StylesheetContents>,
|
||||||
|
) -> (
|
||||||
|
Option<StylesheetContentsCacheKey>,
|
||||||
|
ServoArc<StylesheetContents>,
|
||||||
|
) {
|
||||||
|
let cache_key =
|
||||||
|
StylesheetContentsCacheKey::new(stylesheet_text, url_data.as_str(), quirks_mode);
|
||||||
|
STYLESHEETCONTENTS_CACHE.with_borrow_mut(|stylesheetcontents_cache| {
|
||||||
|
let entry = stylesheetcontents_cache.entry(cache_key);
|
||||||
|
match entry {
|
||||||
|
Entry::Occupied(occupied_entry) => {
|
||||||
|
// Use a copy of the cache key from `Entry` instead of the newly created one above
|
||||||
|
// to correctly update and track to owner count of `StylesheetContents`.
|
||||||
|
(
|
||||||
|
Some(occupied_entry.key().clone()),
|
||||||
|
occupied_entry.get().clone(),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
Entry::Vacant(vacant_entry) => {
|
||||||
|
let contents = stylesheetcontents_create_callback();
|
||||||
|
if Self::contents_can_be_cached(&contents, shared_lock) {
|
||||||
|
let occupied_entry = vacant_entry.insert_entry(contents.clone());
|
||||||
|
// Use a copy of the cache key from `Entry` instead of the newly created one above
|
||||||
|
// to correctly update and track to owner count of `StylesheetContents`.
|
||||||
|
(Some(occupied_entry.key().clone()), contents)
|
||||||
|
} else {
|
||||||
|
(None, contents)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn remove(cache_key: StylesheetContentsCacheKey) {
|
||||||
|
STYLESHEETCONTENTS_CACHE.with_borrow_mut(|stylesheetcontents_cache| {
|
||||||
|
stylesheetcontents_cache.remove(&cache_key)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -214,6 +214,9 @@ impl FetchResponseListener for StylesheetContext {
|
||||||
.is_none_or(|generation| generation == link.get_request_generation_id());
|
.is_none_or(|generation| generation == link.get_request_generation_id());
|
||||||
if is_stylesheet_load_applicable {
|
if is_stylesheet_load_applicable {
|
||||||
let shared_lock = document.style_shared_lock().clone();
|
let shared_lock = document.style_shared_lock().clone();
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
let _span = tracing::trace_span!("ParseStylesheet", servo_profiling = true)
|
||||||
|
.entered();
|
||||||
let sheet = Arc::new(Stylesheet::from_bytes(
|
let sheet = Arc::new(Stylesheet::from_bytes(
|
||||||
&data,
|
&data,
|
||||||
UrlExtraData(final_url.get_arc()),
|
UrlExtraData(final_url.get_arc()),
|
||||||
|
@ -235,6 +238,9 @@ impl FetchResponseListener for StylesheetContext {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
StylesheetContextSource::Import(ref stylesheet) => {
|
StylesheetContextSource::Import(ref stylesheet) => {
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
let _span =
|
||||||
|
tracing::trace_span!("ParseStylesheet", servo_profiling = true).entered();
|
||||||
Stylesheet::update_from_bytes(
|
Stylesheet::update_from_bytes(
|
||||||
stylesheet,
|
stylesheet,
|
||||||
&data,
|
&data,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue