commit a643ccf3b03b9c6925c17afcd601e85a07866d19
parent c226407064adf2a042558dde3333be5a6d5dbb80
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date: Fri, 24 Oct 2025 20:28:08 +0000
Bug 1994008 - Pass the right base URI to cached inline sheets. r=firefox-style-system-reviewers,layout-reviewers,dshin
With the dependent bugs closed, this fix is trivial.
Differential Revision: https://phabricator.services.mozilla.com/D269944
Diffstat:
6 files changed, 45 insertions(+), 12 deletions(-)
diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp
@@ -1822,14 +1822,18 @@ Result<Loader::LoadSheetResult, nsresult> Loader::LoadInlineStyle(
if (!isSheetFromCache) {
sheet = MakeRefPtr<StyleSheet>(eAuthorSheetFeatures, aInfo.mCORSMode,
SRIMetadata{});
- nsIReferrerInfo* referrerInfo =
- aInfo.mContent->OwnerDoc()->ReferrerInfoForInternalCSSAndSVGResources();
- sheet->SetURIs(nullptr, baseURI, referrerInfo, sheetPrincipal);
// If an extension creates an inline stylesheet, we don't want to consider
// it same-origin with the page.
// FIXME(emilio): That's rather odd.
sheet->SetOriginClean(LoaderPrincipal()->Subsumes(sheetPrincipal));
}
+ // We allow sharing inline sheets with e.g. different base URIs, iff there's
+ // no dependency on that base URI. However, we still need to keep track of the
+ // right URIs in case the sheet is then mutated. EnsureUniqueInner will make
+ // sure the StylesheetContents get fixed up.
+ nsIReferrerInfo* referrerInfo =
+ aInfo.mContent->OwnerDoc()->ReferrerInfoForInternalCSSAndSVGResources();
+ sheet->SetURIs(nullptr, baseURI, referrerInfo, sheetPrincipal);
auto matched = PrepareSheet(*sheet, aInfo.mTitle, aInfo.mMedia, nullptr,
isAlternate, aInfo.mIsExplicitlyEnabled);
diff --git a/layout/style/StyleSheet.cpp b/layout/style/StyleSheet.cpp
@@ -352,7 +352,9 @@ StyleSheetInfo::StyleSheetInfo(StyleSheetInfo& aCopy, StyleSheet* aPrimarySheet)
// We don't rebuild the child because we're making a copy without
// children.
mSourceMapURL(aCopy.mSourceMapURL),
- mContents(Servo_StyleSheet_Clone(aCopy.mContents.get()).Consume())
+ mContents(Servo_StyleSheet_Clone(aCopy.mContents.get(),
+ aPrimarySheet->URLData())
+ .Consume())
#ifdef DEBUG
,
mPrincipalSet(aCopy.mPrincipalSet)
diff --git a/servo/components/style/stylesheets/stylesheet.rs b/servo/components/style/stylesheets/stylesheet.rs
@@ -184,27 +184,33 @@ impl StylesheetContents {
) -> EffectiveRulesIterator<'a, 'b> {
self.iter_rules::<EffectiveRules>(device, guard)
}
-}
-impl DeepCloneWithLock for StylesheetContents {
- fn deep_clone_with_lock(&self, lock: &SharedRwLock, guard: &SharedRwLockReadGuard) -> Self {
+ /// Perform a deep clone, of this stylesheet, with an explicit URL data if needed.
+ pub fn deep_clone(
+ &self,
+ lock: &SharedRwLock,
+ url_data: Option<&UrlExtraData>,
+ guard: &SharedRwLockReadGuard,
+ ) -> Arc<Self> {
// Make a deep clone of the rules, using the new lock.
let rules = self
.rules
.read_with(guard)
.deep_clone_with_lock(lock, guard);
- Self {
+ let url_data = url_data.cloned().unwrap_or_else(|| self.url_data.clone());
+
+ Arc::new(Self {
rules: Arc::new(lock.wrap(rules)),
quirks_mode: self.quirks_mode,
origin: self.origin,
- url_data: self.url_data.clone(),
+ url_data,
namespaces: self.namespaces.clone(),
source_map_url: self.source_map_url.clone(),
source_url: self.source_url.clone(),
use_counters: self.use_counters.clone(),
_forbid_construction: (),
- }
+ })
}
}
diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs
@@ -2064,11 +2064,14 @@ pub extern "C" fn Servo_StyleSheet_GetRules(sheet: &StylesheetContents) -> Stron
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_Clone(
contents: &StylesheetContents,
+ data: *mut URLExtraData,
) -> Strong<StylesheetContents> {
- use style::shared_lock::DeepCloneWithLock;
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
- Arc::new(contents.deep_clone_with_lock(&global_style_data.shared_lock, &guard)).into()
+ let url_data = unsafe { UrlExtraData::from_ptr_ref(&data) };
+ contents
+ .deep_clone(&global_style_data.shared_lock, Some(url_data), &guard)
+ .into()
}
#[no_mangle]
diff --git a/testing/web-platform/tests/css/css-values/inline-cache-base-uri-cssom-ref.html b/testing/web-platform/tests/css/css-values/inline-cache-base-uri-cssom-ref.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<style>
+ :root { background-color: lime }
+</style>
diff --git a/testing/web-platform/tests/css/css-values/inline-cache-base-uri-cssom.html b/testing/web-platform/tests/css/css-values/inline-cache-base-uri-cssom.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>Relative URI in potentially-cached stylesheet</title>
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#relative-urls">
+<link rel="match" href="inline-cache-base-uri-cssom-ref.html">
+<style>
+ :root { background-color: red; }
+</style>
+<base href="/images/">
+<style>
+ :root { background-color: red; }
+</style>
+<script>
+document.styleSheets[1].insertRule(`:root { background-image: url(green.png) }`);
+</script>