mirror of
https://github.com/lexmount/moli.git
synced 2026-10-05 00:00:55 +00:00
perf(style): share inline source text backing
This commit is contained in:
@@ -544,6 +544,11 @@ impl DomHost {
|
||||
self.dom.text_content(handle)
|
||||
}
|
||||
|
||||
pub fn shared_text_content(&self, handle: DomHandle) -> Option<std::sync::Arc<str>> {
|
||||
self.node(handle)
|
||||
.map(|node| node.shared_text_content(&self.dom))
|
||||
}
|
||||
|
||||
pub fn inner_html(&self, handle: DomHandle) -> Option<String> {
|
||||
self.dom.inner_html(handle)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::collections::HashSet;
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
use super::{
|
||||
JsContextHost,
|
||||
@@ -873,13 +873,13 @@ impl JsContextHost {
|
||||
}
|
||||
|
||||
pub(crate) fn sync_owner_style_sheet_text(&mut self, owner: DomHandle) {
|
||||
let css_text = self.dom_host().text_content(owner).unwrap_or_default();
|
||||
let css_text = self
|
||||
.dom_host()
|
||||
.shared_text_content(owner)
|
||||
.unwrap_or_else(|| Arc::from(""));
|
||||
let dom_host = self.dom_host() as *const _;
|
||||
self.style_engine.sync_owner_style_sheet_text_with_host(
|
||||
unsafe { &*dom_host },
|
||||
owner,
|
||||
css_text,
|
||||
);
|
||||
self.style_engine
|
||||
.sync_owner_style_sheet_text_backing_with_host(unsafe { &*dom_host }, owner, css_text);
|
||||
self.install_owner_live_stylesheet(owner);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::collections::HashSet;
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
pub(super) mod adopted;
|
||||
pub(super) mod imports;
|
||||
@@ -160,21 +160,31 @@ impl MoliStyleEngine {
|
||||
.tracks_document(document)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn set_owner_style_sheet_text_with_host(
|
||||
&mut self,
|
||||
host: &DomHost,
|
||||
owner: DomHandle,
|
||||
css_text: String,
|
||||
) {
|
||||
self.set_owner_style_sheet_text_backing_with_host(host, owner, css_text.into());
|
||||
}
|
||||
|
||||
fn set_owner_style_sheet_text_backing_with_host(
|
||||
&mut self,
|
||||
host: &DomHost,
|
||||
owner: DomHandle,
|
||||
css_text: Arc<str>,
|
||||
) {
|
||||
let parser_base = stylesheet_source_base_url(host, owner);
|
||||
self.set_owner_style_sheet_source_with_parser_base(host, owner, css_text, parser_base);
|
||||
}
|
||||
|
||||
pub(crate) fn sync_owner_style_sheet_text_with_host(
|
||||
pub(crate) fn sync_owner_style_sheet_text_backing_with_host(
|
||||
&mut self,
|
||||
host: &DomHost,
|
||||
owner: DomHandle,
|
||||
css_text: String,
|
||||
css_text: Arc<str>,
|
||||
) {
|
||||
if self.owner_document_world(host, owner).is_some_and(|world| {
|
||||
world
|
||||
@@ -184,14 +194,14 @@ impl MoliStyleEngine {
|
||||
}) {
|
||||
return;
|
||||
}
|
||||
self.set_owner_style_sheet_text_with_host(host, owner, css_text);
|
||||
self.set_owner_style_sheet_text_backing_with_host(host, owner, css_text);
|
||||
}
|
||||
|
||||
fn process_owner_style_sheet_text_with_host(
|
||||
&mut self,
|
||||
host: &DomHost,
|
||||
owner: DomHandle,
|
||||
css_text: String,
|
||||
css_text: Arc<str>,
|
||||
) {
|
||||
let Some(document) = owner_document_for_source_owner(host, owner) else {
|
||||
return;
|
||||
@@ -214,7 +224,7 @@ impl MoliStyleEngine {
|
||||
&mut self,
|
||||
host: &DomHost,
|
||||
owner: DomHandle,
|
||||
css_text: String,
|
||||
css_text: Arc<str>,
|
||||
parser_base: url::Url,
|
||||
) {
|
||||
let Some(document) = owner_document_for_source_owner(host, owner) else {
|
||||
@@ -518,7 +528,8 @@ impl MoliStyleEngine {
|
||||
self.process_owner_style_sheet_text_with_host(
|
||||
host,
|
||||
owner,
|
||||
host.text_content(owner).unwrap_or_default(),
|
||||
host.shared_text_content(owner)
|
||||
.unwrap_or_else(|| Arc::from("")),
|
||||
);
|
||||
} else if matches!(
|
||||
change.kind(),
|
||||
|
||||
@@ -49,13 +49,19 @@ struct SharedStyleSourceCache {
|
||||
pub(super) fn shared_style_source_contents(
|
||||
css_text: String,
|
||||
base_url: url::Url,
|
||||
) -> Arc<SharedStyleSourceContents> {
|
||||
shared_style_source_contents_from_shared(css_text.into(), base_url)
|
||||
}
|
||||
|
||||
pub(super) fn shared_style_source_contents_from_shared(
|
||||
css_text: Arc<str>,
|
||||
base_url: url::Url,
|
||||
) -> Arc<SharedStyleSourceContents> {
|
||||
let key = SharedStyleSourceCacheKey::new(&css_text, &base_url);
|
||||
if let Some(cached) = CACHE.lock().lookup(&key, &css_text, &base_url) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
let css_text = Arc::<str>::from(css_text);
|
||||
let metadata = style_source_metadata_for_css_text(&css_text, &base_url);
|
||||
let source = Arc::new(SharedStyleSourceContents {
|
||||
source_metadata: SharedStyleSourceMetadata::from_metadata(
|
||||
@@ -288,6 +294,17 @@ mod tests {
|
||||
assert_eq!(cache.retained_bytes, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shared_input_becomes_the_retained_css_text_backing() {
|
||||
let css_text = Arc::<str>::from(".shared-input { color: green; }");
|
||||
let source = shared_style_source_contents_from_shared(
|
||||
Arc::clone(&css_text),
|
||||
url::Url::parse("https://shared-input.test/style.css").expect("valid base URL"),
|
||||
);
|
||||
|
||||
assert!(Arc::ptr_eq(&css_text, &source.css_text_handle()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn weak_cache_evicts_oldest_index_to_byte_budget() {
|
||||
let mut cache = SharedStyleSourceCache::with_retained_bytes_limit(2 * ENTRY_RETAINED_BYTES);
|
||||
|
||||
@@ -13,7 +13,10 @@ use super::super::{
|
||||
source_key::{StyleSourceKey, StyleSourceSetKey},
|
||||
};
|
||||
use super::imports::stylesheet_top_level_import_urls;
|
||||
use super::shared_cache::{SharedStyleSourceContents, shared_style_source_contents};
|
||||
use super::shared_cache::{
|
||||
SharedStyleSourceContents, shared_style_source_contents,
|
||||
shared_style_source_contents_from_shared,
|
||||
};
|
||||
use crate::{
|
||||
document_runtime::DomHandle, protocol_types::EmulatedMediaOverrides,
|
||||
style_engine::StyleViewport,
|
||||
@@ -92,6 +95,15 @@ pub(crate) struct OwnerStyleSheetSource {
|
||||
impl StyloStylesheetSource {
|
||||
pub(crate) fn new(css_text: String, base_url: url::Url) -> Self {
|
||||
let shared = shared_style_source_contents(css_text, base_url);
|
||||
Self::from_shared_contents(shared)
|
||||
}
|
||||
|
||||
fn from_shared_text(css_text: StdArc<str>, base_url: url::Url) -> Self {
|
||||
let shared = shared_style_source_contents_from_shared(css_text, base_url);
|
||||
Self::from_shared_contents(shared)
|
||||
}
|
||||
|
||||
fn from_shared_contents(shared: StdArc<SharedStyleSourceContents>) -> Self {
|
||||
let cache_key =
|
||||
StyleSourceKey::from_css_fingerprint(shared.css_fingerprint(), shared.base_url());
|
||||
let base_url = shared.base_url_handle();
|
||||
@@ -542,8 +554,22 @@ impl StylesheetFontFaceDescriptor {
|
||||
}
|
||||
|
||||
impl OwnerStyleSheetSource {
|
||||
#[cfg(test)]
|
||||
pub(crate) fn new(owner: DomHandle, css_text: String, parser_base: url::Url) -> Self {
|
||||
let source = StyloStylesheetSource::new(css_text, parser_base);
|
||||
Self::from_source(owner, source)
|
||||
}
|
||||
|
||||
pub(crate) fn from_shared_text(
|
||||
owner: DomHandle,
|
||||
css_text: StdArc<str>,
|
||||
parser_base: url::Url,
|
||||
) -> Self {
|
||||
let source = StyloStylesheetSource::from_shared_text(css_text, parser_base);
|
||||
Self::from_source(owner, source)
|
||||
}
|
||||
|
||||
fn from_source(owner: DomHandle, source: StyloStylesheetSource) -> Self {
|
||||
let processing_contents = source
|
||||
.processing_contents()
|
||||
.expect("owner processing source must remain text-backed");
|
||||
|
||||
@@ -94,7 +94,7 @@ impl OwnerStyleSheetSources {
|
||||
pub(super) fn set_source(
|
||||
&mut self,
|
||||
owner: DomHandle,
|
||||
css_text: String,
|
||||
css_text: Arc<str>,
|
||||
parser_base: url::Url,
|
||||
) -> bool {
|
||||
self.cssom_authoritative_owners.remove(&owner);
|
||||
@@ -105,7 +105,11 @@ impl OwnerStyleSheetSources {
|
||||
}) {
|
||||
return false;
|
||||
}
|
||||
let processing_source = Arc::new(OwnerStyleSheetSource::new(owner, css_text, parser_base));
|
||||
let processing_source = Arc::new(OwnerStyleSheetSource::from_shared_text(
|
||||
owner,
|
||||
css_text,
|
||||
parser_base,
|
||||
));
|
||||
self.sources_by_owner.insert(
|
||||
owner,
|
||||
InstalledOwnerStyleSheet::from_processing_source(processing_source),
|
||||
@@ -116,11 +120,15 @@ impl OwnerStyleSheetSources {
|
||||
pub(super) fn replace_processed_source(
|
||||
&mut self,
|
||||
owner: DomHandle,
|
||||
css_text: String,
|
||||
css_text: Arc<str>,
|
||||
parser_base: url::Url,
|
||||
) {
|
||||
self.cssom_authoritative_owners.remove(&owner);
|
||||
let processing_source = Arc::new(OwnerStyleSheetSource::new(owner, css_text, parser_base));
|
||||
let processing_source = Arc::new(OwnerStyleSheetSource::from_shared_text(
|
||||
owner,
|
||||
css_text,
|
||||
parser_base,
|
||||
));
|
||||
self.sources_by_owner.insert(
|
||||
owner,
|
||||
InstalledOwnerStyleSheet::from_processing_source(processing_source),
|
||||
|
||||
@@ -1770,8 +1770,8 @@ fn owner_style_sheet_sources_share_one_cached_text_allocation() {
|
||||
let mut owner_sources = super::source_owner_text::OwnerStyleSheetSources::default();
|
||||
let base_url = url::Url::parse("https://example.test/").expect("valid test url");
|
||||
let css_text = ".card:has(.item) { color: red; }";
|
||||
owner_sources.set_source(first_owner, css_text.to_owned(), base_url.clone());
|
||||
owner_sources.set_source(second_owner, css_text.to_owned(), base_url);
|
||||
owner_sources.set_source(first_owner, css_text.into(), base_url.clone());
|
||||
owner_sources.set_source(second_owner, css_text.into(), base_url);
|
||||
|
||||
let first = owner_sources
|
||||
.source(first_owner)
|
||||
@@ -1867,7 +1867,7 @@ fn linked_source_store_lifecycle_records_drive_retained_record_construction() {
|
||||
let mut owner_sources = super::source_owner_text::OwnerStyleSheetSources::default();
|
||||
owner_sources.set_source(
|
||||
style,
|
||||
".owner { color: green; }".to_owned(),
|
||||
".owner { color: green; }".into(),
|
||||
url::Url::parse("https://example.test/").unwrap(),
|
||||
);
|
||||
let linked_url = url::Url::parse("https://example.test/linked.css").unwrap();
|
||||
|
||||
Reference in New Issue
Block a user