diff options
Diffstat (limited to 'components/script/dom/htmlstyleelement.rs')
-rw-r--r-- | components/script/dom/htmlstyleelement.rs | 208 |
1 files changed, 129 insertions, 79 deletions
diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index 0c026fcfe9a..83d35fc78c8 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -1,41 +1,41 @@ /* 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 http://mozilla.org/MPL/2.0/. */ - -use cssparser::Parser as CssParser; -use dom::bindings::cell::DOMRefCell; -use dom::bindings::codegen::Bindings::HTMLStyleElementBinding; -use dom::bindings::codegen::Bindings::HTMLStyleElementBinding::HTMLStyleElementMethods; -use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; -use dom::bindings::inheritance::Castable; -use dom::bindings::js::{MutNullableJS, Root}; -use dom::bindings::str::DOMString; -use dom::cssstylesheet::CSSStyleSheet; -use dom::document::Document; -use dom::element::{Element, ElementCreator}; -use dom::eventtarget::EventTarget; -use dom::htmlelement::HTMLElement; -use dom::node::{ChildrenMutation, Node, UnbindContext, document_from_node, window_from_node}; -use dom::stylesheet::StyleSheet as DOMStyleSheet; -use dom::virtualmethods::VirtualMethods; + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::HTMLStyleElementBinding::HTMLStyleElementMethods; +use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; +use crate::dom::bindings::inheritance::Castable; +use crate::dom::bindings::root::{DomRoot, MutNullableDom}; +use crate::dom::cssstylesheet::CSSStyleSheet; +use crate::dom::document::Document; +use crate::dom::element::{Element, ElementCreator}; +use crate::dom::htmlelement::HTMLElement; +use crate::dom::node::{ + document_from_node, stylesheets_owner_from_node, window_from_node, BindContext, + ChildrenMutation, Node, UnbindContext, +}; +use crate::dom::stylesheet::StyleSheet as DOMStyleSheet; +use crate::dom::virtualmethods::VirtualMethods; +use crate::stylesheet_loader::{StylesheetLoader, StylesheetOwner}; +use cssparser::{Parser as CssParser, ParserInput}; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::{LocalName, Prefix}; use net_traits::ReferrerPolicy; -use script_layout_interface::message::Msg; +use servo_arc::Arc; use std::cell::Cell; -use std::sync::Arc; -use style::media_queries::parse_media_query_list; -use style::parser::{LengthParsingMode, ParserContext as CssParserContext}; -use style::stylesheets::{CssRuleType, Stylesheet, Origin}; -use stylesheet_loader::{StylesheetLoader, StylesheetOwner}; +use style::media_queries::MediaList; +use style::parser::ParserContext as CssParserContext; +use style::stylesheets::{AllowImportRules, CssRuleType, Origin, Stylesheet}; +use style_traits::ParsingMode; #[dom_struct] pub struct HTMLStyleElement { htmlelement: HTMLElement, - #[ignore_heap_size_of = "Arc"] - stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>, - cssom_stylesheet: MutNullableJS<CSSStyleSheet>, - /// https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts + #[ignore_malloc_size_of = "Arc"] + stylesheet: DomRefCell<Option<Arc<Stylesheet>>>, + cssom_stylesheet: MutNullableDom<CSSStyleSheet>, + /// <https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts> parser_inserted: Cell<bool>, in_stack_of_open_elements: Cell<bool>, pending_loads: Cell<u32>, @@ -44,14 +44,16 @@ pub struct HTMLStyleElement { } impl HTMLStyleElement { - fn new_inherited(local_name: LocalName, - prefix: Option<DOMString>, - document: &Document, - creator: ElementCreator) -> HTMLStyleElement { + fn new_inherited( + local_name: LocalName, + prefix: Option<Prefix>, + document: &Document, + creator: ElementCreator, + ) -> HTMLStyleElement { HTMLStyleElement { htmlelement: HTMLElement::new_inherited(local_name, prefix, document), - stylesheet: DOMRefCell::new(None), - cssom_stylesheet: MutNullableJS::new(None), + stylesheet: DomRefCell::new(None), + cssom_stylesheet: MutNullableDom::new(None), parser_inserted: Cell::new(creator.is_parser_created()), in_stack_of_open_elements: Cell::new(creator.is_parser_created()), pending_loads: Cell::new(0), @@ -61,21 +63,27 @@ impl HTMLStyleElement { } #[allow(unrooted_must_root)] - pub fn new(local_name: LocalName, - prefix: Option<DOMString>, - document: &Document, - creator: ElementCreator) -> Root<HTMLStyleElement> { - Node::reflect_node(box HTMLStyleElement::new_inherited(local_name, prefix, document, creator), - document, - HTMLStyleElementBinding::Wrap) + pub fn new( + local_name: LocalName, + prefix: Option<Prefix>, + document: &Document, + creator: ElementCreator, + ) -> DomRoot<HTMLStyleElement> { + Node::reflect_node( + Box::new(HTMLStyleElement::new_inherited( + local_name, prefix, document, creator, + )), + document, + ) } pub fn parse_own_css(&self) { let node = self.upcast::<Node>(); let element = self.upcast::<Element>(); - assert!(node.is_in_doc()); + assert!(node.is_connected()); - let win = window_from_node(node); + let window = window_from_node(node); + let doc = document_from_node(self); let mq_attribute = element.get_attribute(&ns!(), &local_name!("media")); let mq_str = match mq_attribute { @@ -83,55 +91,94 @@ impl HTMLStyleElement { None => String::new(), }; - let data = node.GetTextContent().expect("Element.textContent must be a string"); - let url = win.get_url(); - let context = CssParserContext::new_for_cssom(&url, - win.css_error_reporter(), - Some(CssRuleType::Media), - LengthParsingMode::Default); + let data = node + .GetTextContent() + .expect("Element.textContent must be a string"); + let url = window.get_url(); + let css_error_reporter = window.css_error_reporter(); + let context = CssParserContext::new( + Origin::Author, + &url, + Some(CssRuleType::Media), + ParsingMode::DEFAULT, + doc.quirks_mode(), + css_error_reporter, + None, + ); let shared_lock = node.owner_doc().style_shared_lock().clone(); - let mq = Arc::new(shared_lock.wrap( - parse_media_query_list(&context, &mut CssParser::new(&mq_str)))); + let mut input = ParserInput::new(&mq_str); + let mq = + Arc::new(shared_lock.wrap(MediaList::parse(&context, &mut CssParser::new(&mut input)))); let loader = StylesheetLoader::for_element(self.upcast()); - let sheet = Stylesheet::from_str(&data, win.get_url(), Origin::Author, mq, - shared_lock, Some(&loader), - win.css_error_reporter(), - self.line_number); + let sheet = Stylesheet::from_str( + &data, + window.get_url(), + Origin::Author, + mq, + shared_lock, + Some(&loader), + css_error_reporter, + doc.quirks_mode(), + self.line_number as u32, + AllowImportRules::Yes, + ); let sheet = Arc::new(sheet); - // No subresource loads were triggered, just fire the load event now. + // No subresource loads were triggered, queue load event if self.pending_loads.get() == 0 { - self.upcast::<EventTarget>().fire_event(atom!("load")); + let window = window_from_node(self); + window + .task_manager() + .dom_manipulation_task_source() + .queue_simple_event(self.upcast(), atom!("load"), &window); } - win.layout_chan().send(Msg::AddStylesheet(sheet.clone())).unwrap(); - *self.stylesheet.borrow_mut() = Some(sheet); - let doc = document_from_node(self); - doc.invalidate_stylesheets(); + self.set_stylesheet(sheet); + } + + // FIXME(emilio): This is duplicated with HTMLLinkElement::set_stylesheet. + #[allow(unrooted_must_root)] + pub fn set_stylesheet(&self, s: Arc<Stylesheet>) { + let stylesheets_owner = stylesheets_owner_from_node(self); + if let Some(ref s) = *self.stylesheet.borrow() { + stylesheets_owner.remove_stylesheet(self.upcast(), s) + } + *self.stylesheet.borrow_mut() = Some(s.clone()); + self.clean_stylesheet_ownership(); + stylesheets_owner.add_stylesheet(self.upcast(), s); } pub fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> { self.stylesheet.borrow().clone() } - pub fn get_cssom_stylesheet(&self) -> Option<Root<CSSStyleSheet>> { + pub fn get_cssom_stylesheet(&self) -> Option<DomRoot<CSSStyleSheet>> { self.get_stylesheet().map(|sheet| { self.cssom_stylesheet.or_init(|| { - CSSStyleSheet::new(&window_from_node(self), - self.upcast::<Element>(), - "text/css".into(), - None, // todo handle location - None, // todo handle title - sheet) + CSSStyleSheet::new( + &window_from_node(self), + self.upcast::<Element>(), + "text/css".into(), + None, // todo handle location + None, // todo handle title + sheet, + ) }) }) } + + fn clean_stylesheet_ownership(&self) { + if let Some(cssom_stylesheet) = self.cssom_stylesheet.get() { + cssom_stylesheet.set_owner(None); + } + self.cssom_stylesheet.set(None); + } } impl VirtualMethods for HTMLStyleElement { - fn super_type(&self) -> Option<&VirtualMethods> { - Some(self.upcast::<HTMLElement>() as &VirtualMethods) + fn super_type(&self) -> Option<&dyn VirtualMethods> { + Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) } fn children_changed(&self, mutation: &ChildrenMutation) { @@ -147,14 +194,14 @@ impl VirtualMethods for HTMLStyleElement { } } - fn bind_to_tree(&self, tree_in_doc: bool) { - self.super_type().unwrap().bind_to_tree(tree_in_doc); + fn bind_to_tree(&self, context: &BindContext) { + self.super_type().unwrap().bind_to_tree(context); // https://html.spec.whatwg.org/multipage/#update-a-style-block // Handles the case when: // "The element is not on the stack of open elements of an HTML parser or XML parser, // and it becomes connected or disconnected." - if tree_in_doc && !self.in_stack_of_open_elements.get() { + if context.tree_connected && !self.in_stack_of_open_elements.get() { self.parse_own_css(); } } @@ -176,8 +223,12 @@ impl VirtualMethods for HTMLStyleElement { s.unbind_from_tree(context); } - let doc = document_from_node(self); - doc.invalidate_stylesheets(); + if context.tree_connected { + if let Some(s) = self.stylesheet.borrow_mut().take() { + self.clean_stylesheet_ownership(); + stylesheets_owner_from_node(self).remove_stylesheet(self.upcast(), &s) + } + } } } @@ -217,10 +268,9 @@ impl StylesheetOwner for HTMLStyleElement { } } - impl HTMLStyleElementMethods for HTMLStyleElement { // https://drafts.csswg.org/cssom/#dom-linkstyle-sheet - fn GetSheet(&self) -> Option<Root<DOMStyleSheet>> { - self.get_cssom_stylesheet().map(Root::upcast) + fn GetSheet(&self) -> Option<DomRoot<DOMStyleSheet>> { + self.get_cssom_stylesheet().map(DomRoot::upcast) } } |