diff options
author | Martin Robinson <mrobinson@igalia.com> | 2024-05-23 08:49:31 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-23 06:49:31 +0000 |
commit | 14286d913d5a88647fad2255f06bec0763914e55 (patch) | |
tree | bb54e1ce8b3b2c4f328d68cfc99bd4a300a64df8 | |
parent | a772ecf786bda74cd5202b9ca6fb2d487cc61b94 (diff) | |
download | servo-14286d913d5a88647fad2255f06bec0763914e55.tar.gz servo-14286d913d5a88647fad2255f06bec0763914e55.zip |
fonts: Remove web fonts when their stylsheet is removed (#32346)
This is the first part of ensuring that unused fonts do not leak. This
change makes it so that when a stylesheet is removed, the corresponding
web fonts are removed from the `FontContext`.
Note: WebRender assets are still leaked, which was the situation before
for all fonts. A followup change will fix this issue.
Fixes #15139.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
-rw-r--r-- | components/gfx/font_cache_thread.rs | 1 | ||||
-rw-r--r-- | components/gfx/font_context.rs | 95 | ||||
-rw-r--r-- | components/gfx/font_store.rs | 84 | ||||
-rw-r--r-- | components/gfx/font_template.rs | 12 | ||||
-rw-r--r-- | components/gfx/tests/font_context.rs | 2 | ||||
-rw-r--r-- | components/layout_thread/lib.rs | 27 | ||||
-rw-r--r-- | components/layout_thread_2020/lib.rs | 28 | ||||
-rw-r--r-- | tests/wpt/meta/MANIFEST.json | 21 | ||||
-rw-r--r-- | tests/wpt/tests/css/css-fonts/web-font-no-longer-accessible-when-stylesheet-removed-ref.html | 16 | ||||
-rw-r--r-- | tests/wpt/tests/css/css-fonts/web-font-no-longer-accessible-when-stylesheet-removed.html | 29 |
10 files changed, 258 insertions, 57 deletions
diff --git a/components/gfx/font_cache_thread.rs b/components/gfx/font_cache_thread.rs index 5be2ed7d492..bde22d4b515 100644 --- a/components/gfx/font_cache_thread.rs +++ b/components/gfx/font_cache_thread.rs @@ -484,6 +484,7 @@ impl FontSource for FontCacheThread { identifier: serialized_font_template.identifier, descriptor: serialized_font_template.descriptor.clone(), data: font_data.map(Arc::new), + stylesheet: None, })) }) .collect() diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs index ef83d3e9de2..e27c4d0bef4 100644 --- a/components/gfx/font_context.rs +++ b/components/gfx/font_context.rs @@ -5,7 +5,6 @@ use std::collections::HashMap; use std::default::Default; use std::hash::{BuildHasherDefault, Hash, Hasher}; -use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use app_units::Au; @@ -24,7 +23,7 @@ use style::font_face::{FontFaceSourceFormat, FontFaceSourceFormatKeyword, Source use style::media_queries::Device; use style::properties::style_structs::Font as FontStyleStruct; use style::shared_lock::SharedRwLockReadGuard; -use style::stylesheets::{Stylesheet, StylesheetInDocument}; +use style::stylesheets::{DocumentStyleSheet, StylesheetInDocument}; use style::Atom; use url::Url; @@ -51,7 +50,6 @@ pub struct FontContext<S: FontSource> { cache: CachingFontSource<S>, web_fonts: CrossThreadFontStore, webrender_font_store: CrossThreadWebRenderFontStore, - web_fonts_still_loading: AtomicUsize, } impl<S: FontSource> MallocSizeOf for FontContext<S> { @@ -69,12 +67,11 @@ impl<S: FontSource> FontContext<S> { cache: CachingFontSource::new(font_source), web_fonts: Arc::new(RwLock::default()), webrender_font_store: Arc::new(RwLock::default()), - web_fonts_still_loading: Default::default(), } } pub fn web_fonts_still_loading(&self) -> usize { - self.web_fonts_still_loading.load(Ordering::SeqCst) + self.web_fonts.read().number_of_fonts_still_loading() } /// Handle the situation where a web font finishes loading, specifying if the load suceeded or failed. @@ -83,7 +80,6 @@ impl<S: FontSource> FontContext<S> { finished_callback: &WebFontLoadFinishedCallback, succeeded: bool, ) { - self.web_fonts_still_loading.fetch_sub(1, Ordering::SeqCst); if succeeded { self.cache.invalidate_after_web_font_load(); } @@ -159,6 +155,8 @@ impl<S: FontSource> FontContext<S> { font_template, font_descriptor ); + // TODO: Inserting `None` into the cache here is a bit bogus. Instead we should somehow + // mark this template as invalid so it isn't tried again. let font = self .create_font( font_template, @@ -229,29 +227,31 @@ impl<S: FontSource> FontContext<S> { #[derive(Clone)] pub struct WebFontDownloadState { - css_font_face_descriptors: Arc<CSSFontFaceDescriptors>, + pub css_font_face_descriptors: Arc<CSSFontFaceDescriptors>, remaining_sources: Vec<Source>, finished_callback: WebFontLoadFinishedCallback, core_resource_thread: CoreResourceThread, local_fonts: Arc<HashMap<Atom, Option<FontTemplateRef>>>, + pub stylesheet: DocumentStyleSheet, } pub trait FontContextWebFontMethods { fn add_all_web_fonts_from_stylesheet( &self, - stylesheet: &Stylesheet, + stylesheet: &DocumentStyleSheet, guard: &SharedRwLockReadGuard, device: &Device, finished_callback: WebFontLoadFinishedCallback, synchronous: bool, ) -> usize; fn process_next_web_font_source(&self, web_font_download_state: WebFontDownloadState); + fn remove_all_web_fonts_from_stylesheet(&self, stylesheet: &DocumentStyleSheet); } impl<S: FontSource + Send + 'static> FontContextWebFontMethods for Arc<FontContext<S>> { fn add_all_web_fonts_from_stylesheet( &self, - stylesheet: &Stylesheet, + stylesheet: &DocumentStyleSheet, guard: &SharedRwLockReadGuard, device: &Device, finished_callback: WebFontLoadFinishedCallback, @@ -312,17 +312,20 @@ impl<S: FontSource + Send + 'static> FontContextWebFontMethods for Arc<FontConte } } + number_loading += 1; + self.web_fonts + .write() + .handle_web_font_load_started_for_stylesheet(stylesheet); + self.process_next_web_font_source(WebFontDownloadState { css_font_face_descriptors: Arc::new(rule.into()), remaining_sources: sources, finished_callback: finished_callback.clone(), core_resource_thread: self.resource_threads.lock().clone(), local_fonts: Arc::new(local_fonts), + stylesheet: stylesheet.clone(), }); - number_loading += 1; - self.web_fonts_still_loading.fetch_add(1, Ordering::SeqCst); - // If the load is synchronous wait for it to be signalled. if let Some(ref synchronous_receiver) = synchronous_receiver { synchronous_receiver.recv().unwrap(); @@ -334,6 +337,9 @@ impl<S: FontSource + Send + 'static> FontContextWebFontMethods for Arc<FontConte fn process_next_web_font_source(&self, mut state: WebFontDownloadState) { let Some(source) = state.remaining_sources.pop() else { + self.web_fonts + .write() + .handle_web_font_failed_to_load(&state); self.handle_web_font_load_finished(&state.finished_callback, false); return; }; @@ -354,23 +360,48 @@ impl<S: FontSource + Send + 'static> FontContextWebFontMethods for Arc<FontConte FontTemplate::new_for_local_web_font( local_template, &state.css_font_face_descriptors, + state.stylesheet.clone(), ) .ok() }) { - this.web_fonts + let not_cancelled = self + .web_fonts .write() - .families - .entry(web_font_family_name.clone()) - .or_default() - .add_template(new_template); - self.handle_web_font_load_finished(&state.finished_callback, true); + .handle_web_font_loaded(&state, new_template); + self.handle_web_font_load_finished(&state.finished_callback, not_cancelled); } else { this.process_next_web_font_source(state); } }, } } + + fn remove_all_web_fonts_from_stylesheet(&self, stylesheet: &DocumentStyleSheet) { + let mut web_fonts = self.web_fonts.write(); + let mut fonts = self.cache.fonts.write(); + let mut font_groups = self.cache.resolved_font_groups.write(); + + // Cancel any currently in-progress web font loads. + web_fonts.handle_stylesheet_removed(stylesheet); + + let mut removed_any = false; + for family in web_fonts.families.values_mut() { + removed_any |= family.remove_templates_for_stylesheet(stylesheet); + } + if !removed_any { + return; + }; + + fonts.retain(|_, font| match font { + Some(font) => font.template.borrow().stylesheet.as_ref() != Some(stylesheet), + _ => true, + }); + + // Removing this stylesheet modified the available fonts, so invalidate the cache + // of resolved font groups. + font_groups.clear(); + } } struct RemoteWebFontDownloader<FCT: FontSource> { @@ -437,6 +468,18 @@ impl<FCT: FontSource + Send + 'static> RemoteWebFontDownloader<FCT> { /// After a download finishes, try to process the downloaded data, returning true if /// the font is added successfully to the [`FontContext`] or false if it isn't. fn process_downloaded_font_and_signal_completion(&self, state: &WebFontDownloadState) -> bool { + if self + .font_context + .web_fonts + .read() + .font_load_cancelled_for_stylesheet(&state.stylesheet) + { + self.font_context + .handle_web_font_load_finished(&state.finished_callback, false); + // Returning true here prevents trying to load the next font on the source list. + return true; + } + let font_data = std::mem::take(&mut *self.response_data.lock()); trace!( "@font-face {} data={:?}", @@ -459,21 +502,21 @@ impl<FCT: FontSource + Send + 'static> RemoteWebFontDownloader<FCT> { self.url.clone().into(), Arc::new(font_data), &state.css_font_face_descriptors, + Some(state.stylesheet.clone()), ) else { return false; }; - let family_name = state.css_font_face_descriptors.family_name.clone(); - self.font_context + let not_cancelled = self + .font_context .web_fonts .write() - .families - .entry(family_name.clone()) - .or_default() - .add_template(new_template); - + .handle_web_font_loaded(state, new_template); self.font_context - .handle_web_font_load_finished(&state.finished_callback, true); + .handle_web_font_load_finished(&state.finished_callback, not_cancelled); + + // If the load was canceled above, then we still want to return true from this function in + // order to halt any attempt to load sources that come later on the source list. true } diff --git a/components/gfx/font_store.rs b/components/gfx/font_store.rs index 888a0ae0a1e..8abb74fc188 100644 --- a/components/gfx/font_store.rs +++ b/components/gfx/font_store.rs @@ -8,15 +8,18 @@ use std::sync::Arc; use app_units::Au; use atomic_refcell::AtomicRefCell; use parking_lot::RwLock; +use style::stylesheets::DocumentStyleSheet; use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey}; use crate::font::FontDescriptor; use crate::font_cache_thread::{FontIdentifier, FontSource, LowercaseString}; +use crate::font_context::WebFontDownloadState; use crate::font_template::{FontTemplate, FontTemplateRef, FontTemplateRefMethods}; #[derive(Default)] pub struct FontStore { pub(crate) families: HashMap<LowercaseString, FontTemplates>, + web_fonts_loading: Vec<(DocumentStyleSheet, usize)>, } pub(crate) type CrossThreadFontStore = Arc<RwLock<FontStore>>; @@ -24,6 +27,77 @@ impl FontStore { pub(crate) fn clear(&mut self) { self.families.clear(); } + + pub(crate) fn font_load_cancelled_for_stylesheet( + &self, + stylesheet: &DocumentStyleSheet, + ) -> bool { + !self + .web_fonts_loading + .iter() + .any(|(loading_stylesheet, _)| loading_stylesheet == stylesheet) + } + + pub(crate) fn handle_stylesheet_removed(&mut self, stylesheet: &DocumentStyleSheet) { + self.web_fonts_loading + .retain(|(loading_stylesheet, _)| loading_stylesheet != stylesheet); + } + + pub(crate) fn handle_web_font_load_started_for_stylesheet( + &mut self, + stylesheet: &DocumentStyleSheet, + ) { + if let Some((_, count)) = self + .web_fonts_loading + .iter_mut() + .find(|(loading_stylesheet, _)| loading_stylesheet == stylesheet) + { + *count += 1; + } else { + self.web_fonts_loading.push((stylesheet.clone(), 1)) + } + } + + fn remove_one_web_font_loading_for_stylesheet(&mut self, stylesheet: &DocumentStyleSheet) { + if let Some((_, count)) = self + .web_fonts_loading + .iter_mut() + .find(|(loading_stylesheet, _)| loading_stylesheet == stylesheet) + { + *count -= 1; + } + self.web_fonts_loading.retain(|(_, count)| *count != 0); + } + + pub(crate) fn handle_web_font_failed_to_load(&mut self, state: &WebFontDownloadState) { + self.remove_one_web_font_loading_for_stylesheet(&state.stylesheet); + } + + /// Handle a web font load finishing, adding the new font to the [`FontStore`]. If the web font + /// load was canceled (for instance, if the stylesheet was removed), then do nothing and return + /// false. + pub(crate) fn handle_web_font_loaded( + &mut self, + state: &WebFontDownloadState, + new_template: FontTemplate, + ) -> bool { + // Abort processing this web font if the originating stylesheet was removed. + if self.font_load_cancelled_for_stylesheet(&state.stylesheet) { + return false; + } + + let family_name = state.css_font_face_descriptors.family_name.clone(); + self.families + .entry(family_name) + .or_default() + .add_template(new_template); + self.remove_one_web_font_loading_for_stylesheet(&state.stylesheet); + true + } + + pub(crate) fn number_of_fonts_still_loading(&self) -> usize { + self.web_fonts_loading.iter().map(|(_, count)| count).sum() + } } #[derive(Default)] @@ -127,4 +201,14 @@ impl FontTemplates { self.templates .push(Arc::new(AtomicRefCell::new(new_template))); } + + pub(crate) fn remove_templates_for_stylesheet( + &mut self, + stylesheet: &DocumentStyleSheet, + ) -> bool { + let length_before = self.templates.len(); + self.templates + .retain(|template| template.borrow().stylesheet.as_ref() != Some(stylesheet)); + length_before != self.templates.len() + } } diff --git a/components/gfx/font_template.rs b/components/gfx/font_template.rs index 3bc9f21acf0..bfa8bb49fb4 100644 --- a/components/gfx/font_template.rs +++ b/components/gfx/font_template.rs @@ -12,6 +12,7 @@ use serde::{Deserialize, Serialize}; use servo_url::ServoUrl; use style::computed_values::font_stretch::T as FontStretch; use style::computed_values::font_style::T as FontStyle; +use style::stylesheets::DocumentStyleSheet; use style::values::computed::font::FontWeight; use crate::font::{FontDescriptor, PlatformFontMethods}; @@ -132,9 +133,11 @@ pub struct FontTemplate { pub descriptor: FontTemplateDescriptor, /// The data to use for this [`FontTemplate`]. For web fonts, this is always filled, but /// for local fonts, this is loaded only lazily in layout. - /// - /// TODO: There is no mechanism for web fonts to unset their data! pub data: Option<Arc<Vec<u8>>>, + /// If this font is a web font, this is a reference to the stylesheet that + /// created it. This will be used to remove this font from caches, when the + /// stylesheet is removed. + pub stylesheet: Option<DocumentStyleSheet>, } impl malloc_size_of::MallocSizeOf for FontTemplate { @@ -164,6 +167,7 @@ impl FontTemplate { identifier: FontIdentifier::Local(identifier), descriptor, data: None, + stylesheet: None, } } @@ -172,6 +176,7 @@ impl FontTemplate { url: ServoUrl, data: Arc<Vec<u8>>, css_font_template_descriptors: &CSSFontFaceDescriptors, + stylesheet: Option<DocumentStyleSheet>, ) -> Result<FontTemplate, &'static str> { let identifier = FontIdentifier::Web(url.clone()); let Ok(handle) = PlatformFont::new_from_data(identifier, data.clone(), 0, None) else { @@ -185,6 +190,7 @@ impl FontTemplate { identifier: FontIdentifier::Web(url), descriptor, data: Some(data), + stylesheet, }) } @@ -194,11 +200,13 @@ impl FontTemplate { pub fn new_for_local_web_font( local_template: FontTemplateRef, css_font_template_descriptors: &CSSFontFaceDescriptors, + stylesheet: DocumentStyleSheet, ) -> Result<FontTemplate, &'static str> { let mut alias_template = local_template.borrow().clone(); alias_template .descriptor .override_values_with_css_font_template_descriptors(css_font_template_descriptors); + alias_template.stylesheet = Some(stylesheet); Ok(alias_template) } diff --git a/components/gfx/tests/font_context.rs b/components/gfx/tests/font_context.rs index 06870f6f88c..dc61775db18 100644 --- a/components/gfx/tests/font_context.rs +++ b/components/gfx/tests/font_context.rs @@ -24,6 +24,7 @@ use servo_atoms::Atom; use servo_url::ServoUrl; use style::properties::longhands::font_variant_caps::computed_value::T as FontVariantCaps; use style::properties::style_structs::Font as FontStyleStruct; +use style::stylesheets::Stylesheet; use style::values::computed::font::{ FamilyName, FontFamily, FontFamilyList, FontFamilyNameSyntax, FontSize, FontStretch, FontStyle, FontWeight, SingleFontFamily, @@ -85,6 +86,7 @@ impl MockFontCacheThread { Self::url_for_font_name(name), std::sync::Arc::new(data), &CSSFontFaceDescriptors::new(name), + None, ) .unwrap(), ); diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index f4efdc17c41..0192f58a4f4 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -273,7 +273,10 @@ impl Layout for LayoutThread { fn load_web_fonts_from_stylesheet(&self, stylesheet: ServoArc<Stylesheet>) { let guard = stylesheet.shared_lock.read(); - self.load_all_web_fonts_from_stylesheet_with_guard(&stylesheet, &guard); + self.load_all_web_fonts_from_stylesheet_with_guard( + &DocumentStyleSheet(stylesheet.clone()), + &guard, + ); } fn add_stylesheet( @@ -282,24 +285,25 @@ impl Layout for LayoutThread { before_stylesheet: Option<ServoArc<Stylesheet>>, ) { let guard = stylesheet.shared_lock.read(); + let stylesheet = DocumentStyleSheet(stylesheet.clone()); self.load_all_web_fonts_from_stylesheet_with_guard(&stylesheet, &guard); match before_stylesheet { Some(insertion_point) => self.stylist.insert_stylesheet_before( - DocumentStyleSheet(stylesheet.clone()), + stylesheet, DocumentStyleSheet(insertion_point), &guard, ), - None => self - .stylist - .append_stylesheet(DocumentStyleSheet(stylesheet.clone()), &guard), + None => self.stylist.append_stylesheet(stylesheet, &guard), } } fn remove_stylesheet(&mut self, stylesheet: ServoArc<Stylesheet>) { let guard = stylesheet.shared_lock.read(); - self.stylist - .remove_stylesheet(DocumentStyleSheet(stylesheet.clone()), &guard); + let stylesheet = DocumentStyleSheet(stylesheet.clone()); + self.stylist.remove_stylesheet(stylesheet.clone(), &guard); + self.font_context + .remove_all_web_fonts_from_stylesheet(&stylesheet); } fn query_content_box(&self, node: OpaqueNode) -> Option<UntypedRect<Au>> { @@ -668,7 +672,7 @@ impl LayoutThread { fn load_all_web_fonts_from_stylesheet_with_guard( &self, - stylesheet: &Stylesheet, + stylesheet: &DocumentStyleSheet, guard: &SharedRwLockReadGuard, ) { if !stylesheet.is_effective_for_device(self.stylist.device(), guard) { @@ -982,10 +986,7 @@ impl LayoutThread { for stylesheet in &ua_stylesheets.user_or_user_agent_stylesheets { self.stylist .append_stylesheet(stylesheet.clone(), &ua_or_user_guard); - self.load_all_web_fonts_from_stylesheet_with_guard( - &stylesheet.0, - &ua_or_user_guard, - ); + self.load_all_web_fonts_from_stylesheet_with_guard(&stylesheet, &ua_or_user_guard); } if self.stylist.quirks_mode() != QuirksMode::NoQuirks { @@ -994,7 +995,7 @@ impl LayoutThread { &ua_or_user_guard, ); self.load_all_web_fonts_from_stylesheet_with_guard( - &ua_stylesheets.quirks_mode_stylesheet.0, + &ua_stylesheets.quirks_mode_stylesheet, &ua_or_user_guard, ); } diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs index b9cc25fbc7d..63af1c98349 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -249,7 +249,10 @@ impl Layout for LayoutThread { fn load_web_fonts_from_stylesheet(&self, stylesheet: ServoArc<Stylesheet>) { let guard = stylesheet.shared_lock.read(); - self.load_all_web_fonts_from_stylesheet_with_guard(&stylesheet, &guard); + self.load_all_web_fonts_from_stylesheet_with_guard( + &DocumentStyleSheet(stylesheet.clone()), + &guard, + ); } fn add_stylesheet( @@ -258,25 +261,25 @@ impl Layout for LayoutThread { before_stylesheet: Option<ServoArc<Stylesheet>>, ) { let guard = stylesheet.shared_lock.read(); + let stylesheet = DocumentStyleSheet(stylesheet.clone()); self.load_all_web_fonts_from_stylesheet_with_guard(&stylesheet, &guard); match before_stylesheet { Some(insertion_point) => self.stylist.insert_stylesheet_before( - DocumentStyleSheet(stylesheet.clone()), + stylesheet, DocumentStyleSheet(insertion_point), &guard, ), - None => self - .stylist - .append_stylesheet(DocumentStyleSheet(stylesheet.clone()), &guard), + None => self.stylist.append_stylesheet(stylesheet, &guard), } } fn remove_stylesheet(&mut self, stylesheet: ServoArc<Stylesheet>) { - // TODO(mrobinson): This should also unload web fonts from the FontCacheThread. let guard = stylesheet.shared_lock.read(); - self.stylist - .remove_stylesheet(DocumentStyleSheet(stylesheet.clone()), &guard); + let stylesheet = DocumentStyleSheet(stylesheet.clone()); + self.stylist.remove_stylesheet(stylesheet.clone(), &guard); + self.font_context + .remove_all_web_fonts_from_stylesheet(&stylesheet); } fn query_content_box(&self, node: OpaqueNode) -> Option<UntypedRect<Au>> { @@ -584,7 +587,7 @@ impl LayoutThread { fn load_all_web_fonts_from_stylesheet_with_guard( &self, - stylesheet: &Stylesheet, + stylesheet: &DocumentStyleSheet, guard: &SharedRwLockReadGuard, ) { if !stylesheet.is_effective_for_device(self.stylist.device(), guard) { @@ -651,10 +654,7 @@ impl LayoutThread { for stylesheet in &ua_stylesheets.user_or_user_agent_stylesheets { self.stylist .append_stylesheet(stylesheet.clone(), &ua_or_user_guard); - self.load_all_web_fonts_from_stylesheet_with_guard( - &stylesheet.0, - &ua_or_user_guard, - ); + self.load_all_web_fonts_from_stylesheet_with_guard(stylesheet, &ua_or_user_guard); } if self.stylist.quirks_mode() != QuirksMode::NoQuirks { @@ -663,7 +663,7 @@ impl LayoutThread { &ua_or_user_guard, ); self.load_all_web_fonts_from_stylesheet_with_guard( - &ua_stylesheets.quirks_mode_stylesheet.0, + &ua_stylesheets.quirks_mode_stylesheet, &ua_or_user_guard, ); } diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index 3fc382143d9..66ce446fe98 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -179113,7 +179113,20 @@ {} ] ] - } + }, + "web-font-no-longer-accessible-when-stylesheet-removed.html": [ + "aac3e77a819019d349123fac2265531f3746f826", + [ + null, + [ + [ + "/css/css-fonts/web-font-no-longer-accessible-when-stylesheet-removed-ref.html", + "==" + ] + ], + {} + ] + ] }, "css-grid": { "abspos": { @@ -403830,7 +403843,11 @@ "4e88cace350e32711fc06220c2d14dcbd3ab3339", [] ] - } + }, + "web-font-no-longer-accessible-when-stylesheet-removed-ref.html": [ + "363b88d7180a9471c647cd69b9c69678e2f88da6", + [] + ] }, "css-gcpm": { "META.yml": [ diff --git a/tests/wpt/tests/css/css-fonts/web-font-no-longer-accessible-when-stylesheet-removed-ref.html b/tests/wpt/tests/css/css-fonts/web-font-no-longer-accessible-when-stylesheet-removed-ref.html new file mode 100644 index 00000000000..363b88d7180 --- /dev/null +++ b/tests/wpt/tests/css/css-fonts/web-font-no-longer-accessible-when-stylesheet-removed-ref.html @@ -0,0 +1,16 @@ + <!DOCTYPE html> + +<html> + <head> + <title>CSS fonts: Web fonts from removed stylsheets should not be accessible</title> + <link rel="author" title="Martin Robinson" href="mrobinson@igalia.com"> + <link rel="help" href="https://drafts.csswg.org/css-fonts/#font-face-rule"> + </head> + + <body> + <p>Test passes if the text below is not rendered with Ahem.</p> + <p>TEXT</p> + </body> + +</html> + diff --git a/tests/wpt/tests/css/css-fonts/web-font-no-longer-accessible-when-stylesheet-removed.html b/tests/wpt/tests/css/css-fonts/web-font-no-longer-accessible-when-stylesheet-removed.html new file mode 100644 index 00000000000..aac3e77a819 --- /dev/null +++ b/tests/wpt/tests/css/css-fonts/web-font-no-longer-accessible-when-stylesheet-removed.html @@ -0,0 +1,29 @@ + <!DOCTYPE html> + +<html> + <head> + <title>CSS fonts: Web fonts from removed stylsheets should not be accessible</title> + <link rel="author" title="Martin Robinson" href="mrobinson@igalia.com"> + <link rel="match" href="web-font-no-longer-accessible-when-stylesheet-removed-ref.html"> + <link rel="help" href="https://drafts.csswg.org/css-fonts/#font-face-rule"> + </head> + + <body> + <style id="web-font-stylesheet"> + @font-face { + font-family: CustomFontFamily; + src: url(/fonts/Ahem.ttf); + } + </style> + + <p>Test passes if the text below is not rendered with Ahem.</p> + <p style="font-family: CustomFontFamily;">TEXT</p> + + <script> + let styleTag = document.getElementById("web-font-stylesheet"); + styleTag.parentNode.removeChild(styleTag); + </script> + </body> + +</html> + |