Add support for HTMLStyleElement.media (#35148)

Signed-off-by: webbeef <me@webbeef.org>
This commit is contained in:
webbeef 2025-01-24 20:34:58 -08:00 committed by GitHub
parent fe5a075766
commit 8748071329
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 1389 additions and 1364 deletions

View file

@ -6,7 +6,7 @@ use std::cell::Cell;
use cssparser::{Parser as CssParser, ParserInput};
use dom_struct::dom_struct;
use html5ever::{local_name, namespace_url, ns, LocalName, Prefix};
use html5ever::{LocalName, Prefix};
use js::rust::HandleObject;
use net_traits::ReferrerPolicy;
use servo_arc::Arc;
@ -85,9 +85,30 @@ impl HTMLStyleElement {
)
}
fn create_media_list(&self, mq_str: &str) -> MediaList {
if mq_str.is_empty() {
return MediaList::empty();
}
let window = self.owner_window();
let doc = self.owner_document();
let url_data = UrlExtraData(window.get_url().get_arc());
let context = CssParserContext::new(
Origin::Author,
&url_data,
Some(CssRuleType::Media),
ParsingMode::DEFAULT,
doc.quirks_mode(),
/* namespaces = */ Default::default(),
window.css_error_reporter(),
None,
);
let mut input = ParserInput::new(mq_str);
MediaList::parse(&context, &mut CssParser::new(&mut input))
}
pub(crate) fn parse_own_css(&self) {
let node = self.upcast::<Node>();
let element = self.upcast::<Element>();
assert!(node.is_connected());
// Step 4. of <https://html.spec.whatwg.org/multipage/#the-style-element%3Aupdate-a-style-block>
@ -99,32 +120,11 @@ impl HTMLStyleElement {
let window = node.owner_window();
let doc = self.owner_document();
let mq_attribute = element.get_attribute(&ns!(), &local_name!("media"));
let mq_str = match mq_attribute {
Some(a) => String::from(&**a.value()),
None => String::new(),
};
let data = node
.GetTextContent()
.expect("Element.textContent must be a string");
let url_data = UrlExtraData(window.get_url().get_arc());
let css_error_reporter = window.css_error_reporter();
let context = CssParserContext::new(
Origin::Author,
&url_data,
Some(CssRuleType::Media),
ParsingMode::DEFAULT,
doc.quirks_mode(),
/* namespaces = */ Default::default(),
css_error_reporter,
None,
);
let shared_lock = node.owner_doc().style_shared_lock().clone();
let mut input = ParserInput::new(&mq_str);
let mq =
Arc::new(shared_lock.wrap(MediaList::parse(&context, &mut CssParser::new(&mut input))));
let mq = Arc::new(shared_lock.wrap(self.create_media_list(&self.Media())));
let loader = StylesheetLoader::for_element(self.upcast());
let sheet = Stylesheet::from_str(
&data,
@ -133,7 +133,7 @@ impl HTMLStyleElement {
mq,
shared_lock,
Some(&loader),
css_error_reporter,
window.css_error_reporter(),
doc.quirks_mode(),
AllowImportRules::Yes,
);
@ -259,10 +259,13 @@ impl VirtualMethods for HTMLStyleElement {
}
let node = self.upcast::<Node>();
if attr.name() == "type" &&
(node.is_in_a_document_tree() || node.is_in_a_shadow_tree()) &&
!self.in_stack_of_open_elements.get()
if !(node.is_in_a_document_tree() || node.is_in_a_shadow_tree()) ||
self.in_stack_of_open_elements.get()
{
return;
}
if attr.name() == "type" {
if let AttributeMutation::Set(Some(old_value)) = mutation {
if **old_value == **attr.value() {
return;
@ -270,6 +273,17 @@ impl VirtualMethods for HTMLStyleElement {
}
self.remove_stylesheet();
self.parse_own_css();
} else if attr.name() == "media" {
if let Some(ref stylesheet) = *self.stylesheet.borrow_mut() {
let shared_lock = node.owner_doc().style_shared_lock().clone();
let mut guard = shared_lock.write();
let media = stylesheet.media.write_with(&mut guard);
match mutation {
AttributeMutation::Set(_) => *media = self.create_media_list(&attr.value()),
AttributeMutation::Removed => *media = MediaList::empty(),
};
self.owner_document().invalidate_stylesheets();
}
}
}
}
@ -334,4 +348,10 @@ impl HTMLStyleElementMethods<crate::DomTypeHolder> for HTMLStyleElement {
// <https://html.spec.whatwg.org/multipage/#HTMLStyleElement-partial>
make_setter!(SetType, "type");
// <https://html.spec.whatwg.org/multipage/#attr-style-media>
make_getter!(Media, "media");
// <https://html.spec.whatwg.org/multipage/#attr-style-media>
make_setter!(SetMedia, "media");
}

View file

@ -8,12 +8,8 @@ interface HTMLStyleElement : HTMLElement {
[HTMLConstructor] constructor();
attribute boolean disabled;
// [CEReactions]
// attribute DOMString media;
[CEReactions] attribute DOMString media;
[CEReactions] attribute DOMString type;
// [CEReactions]
// attribute boolean scoped;
};
HTMLStyleElement includes LinkStyle;

View file

@ -1,2 +0,0 @@
[layer-media-toggle.html]
expected: FAIL

View file

@ -1,10 +0,0 @@
[medialist-interfaces-001.html]
[mediatest_medialist_serialize_order]
expected: FAIL
[mediatest_medialist_serialize_comma]
expected: FAIL
[mediatest_medialist_serialize_element]
expected: FAIL

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
[HTMLStyleElement.html]
[media on HTMLStyleElement must enqueue an attributeChanged reaction when adding a new attribute]
expected: FAIL
[media on HTMLStyleElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL

View file

@ -6202,15 +6202,9 @@
[HTMLMetaElement interface: document.createElement("meta") must inherit property "scheme" with the proper type]
expected: FAIL
[HTMLStyleElement interface: attribute media]
expected: FAIL
[HTMLStyleElement interface: attribute blocking]
expected: FAIL
[HTMLStyleElement interface: document.createElement("style") must inherit property "media" with the proper type]
expected: FAIL
[HTMLStyleElement interface: document.createElement("style") must inherit property "blocking" with the proper type]
expected: FAIL

View file

@ -2249,120 +2249,6 @@
[style.tabIndex: IDL set to -2147483648]
expected: FAIL
[style.media: typeof IDL attribute]
expected: FAIL
[style.media: IDL get with DOM attribute unset]
expected: FAIL
[style.media: setAttribute() to ""]
expected: FAIL
[style.media: setAttribute() to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo "]
expected: FAIL
[style.media: setAttribute() to undefined]
expected: FAIL
[style.media: setAttribute() to 7]
expected: FAIL
[style.media: setAttribute() to 1.5]
expected: FAIL
[style.media: setAttribute() to "5%"]
expected: FAIL
[style.media: setAttribute() to "+100"]
expected: FAIL
[style.media: setAttribute() to ".5"]
expected: FAIL
[style.media: setAttribute() to true]
expected: FAIL
[style.media: setAttribute() to false]
expected: FAIL
[style.media: setAttribute() to object "[object Object\]"]
expected: FAIL
[style.media: setAttribute() to NaN]
expected: FAIL
[style.media: setAttribute() to Infinity]
expected: FAIL
[style.media: setAttribute() to -Infinity]
expected: FAIL
[style.media: setAttribute() to "\\0"]
expected: FAIL
[style.media: setAttribute() to null]
expected: FAIL
[style.media: setAttribute() to object "test-toString"]
expected: FAIL
[style.media: setAttribute() to object "test-valueOf"]
expected: FAIL
[style.media: IDL set to ""]
expected: FAIL
[style.media: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo "]
expected: FAIL
[style.media: IDL set to undefined]
expected: FAIL
[style.media: IDL set to 7]
expected: FAIL
[style.media: IDL set to 1.5]
expected: FAIL
[style.media: IDL set to "5%"]
expected: FAIL
[style.media: IDL set to "+100"]
expected: FAIL
[style.media: IDL set to ".5"]
expected: FAIL
[style.media: IDL set to true]
expected: FAIL
[style.media: IDL set to false]
expected: FAIL
[style.media: IDL set to object "[object Object\]"]
expected: FAIL
[style.media: IDL set to NaN]
expected: FAIL
[style.media: IDL set to Infinity]
expected: FAIL
[style.media: IDL set to -Infinity]
expected: FAIL
[style.media: IDL set to "\\0"]
expected: FAIL
[style.media: IDL set to null]
expected: FAIL
[style.media: IDL set to object "test-toString"]
expected: FAIL
[style.media: IDL set to object "test-valueOf"]
expected: FAIL
[style.nonce: typeof IDL attribute]
expected: FAIL

View file

@ -4,6 +4,3 @@
[The LinkStyle interface's sheet attribute must return StyleSheet object; the disabled attribute must be same as the StyleSheet's disabled attribute]
expected: FAIL
[The media must be the same as the value of the element's media content attribute, or the empty string if it is omitted]
expected: FAIL

View file

@ -1,3 +0,0 @@
[style_media.html]
[The style information must be applied to the environment specified by the media attribute]
expected: FAIL

View file

@ -1,6 +0,0 @@
[style_media_change.html]
[change media value dynamically]
expected: FAIL
[removing media attribute]
expected: FAIL