From f5a65ead7aea9fe97f05d9e5f919a32cd32a8526 Mon Sep 17 00:00:00 2001 From: koko Date: Sat, 7 Sep 2024 16:45:52 +0200 Subject: [PATCH] Workaround for css loading --- packages/dom/src/document.rs | 1 - packages/dom/src/htmlsink.rs | 9 +++++- packages/dom/src/util.rs | 6 +++- packages/net/src/lib.rs | 9 ++++++ packages/net/src/provider/blocking.rs | 16 ++++++++-- packages/net/src/provider/dummy.rs | 4 +++ packages/net/src/provider/non_blocking.rs | 39 ++++++++++++++++++++--- 7 files changed, 74 insertions(+), 10 deletions(-) diff --git a/packages/dom/src/document.rs b/packages/dom/src/document.rs index f586b837..5cdfd321 100644 --- a/packages/dom/src/document.rs +++ b/packages/dom/src/document.rs @@ -498,7 +498,6 @@ impl Document { match resource { Resource::Css(node_id, css) => { self.append_or_insert_stylesheet(css, node_id); - self.resolve() } Resource::Image(node_id, image) => { let node = self.get_node_mut(node_id).unwrap(); diff --git a/packages/dom/src/htmlsink.rs b/packages/dom/src/htmlsink.rs index 78f56820..d13f5d03 100644 --- a/packages/dom/src/htmlsink.rs +++ b/packages/dom/src/htmlsink.rs @@ -1,5 +1,5 @@ use crate::node::{Attribute, ElementNodeData, Node, NodeData}; -use crate::util::{CssHandler, ImageHandler, Resource}; +use crate::util::{CssHandler, CssMarker, ImageHandler, Resource}; use crate::Document; use blitz_net::NetProvider; use html5ever::local_name; @@ -151,6 +151,13 @@ impl<'b, N: NetProvider> TreeSink for DocumentHtmlParser<'b, N> { self.doc.process_style_element(*id); } + let st = self.net_provider.resolve_all(CssMarker); + if let Some(st) = st { + for res in st { + self.doc.load_resource(res); + } + } + // Compute child_idx fields. self.doc.flush_child_indexes(0, 0, 0); diff --git a/packages/dom/src/util.rs b/packages/dom/src/util.rs index c3973677..c55917fd 100644 --- a/packages/dom/src/util.rs +++ b/packages/dom/src/util.rs @@ -2,6 +2,7 @@ use crate::node::{Node, NodeData}; use blitz_net::RequestHandler; use image::DynamicImage; use selectors::context::QuirksMode; +use std::any::{Any, TypeId}; use std::{ io::Cursor, sync::{Arc, OnceLock}, @@ -24,7 +25,7 @@ pub enum Resource { Svg(usize, Tree), Css(usize, DocumentStyleSheet), } - +pub(crate) struct CssMarker; pub(crate) struct CssHandler { pub node: usize, pub source_url: Url, @@ -47,6 +48,9 @@ impl RequestHandler for CssHandler { ); Resource::Css(self.node, DocumentStyleSheet(ServoArc::new(sheet))) } + fn special(&self) -> Option { + Some(CssMarker.type_id()) + } } pub(crate) struct ImageHandler(usize); impl ImageHandler { diff --git a/packages/net/src/lib.rs b/packages/net/src/lib.rs index 42a69d1f..38998d38 100644 --- a/packages/net/src/lib.rs +++ b/packages/net/src/lib.rs @@ -1,5 +1,6 @@ mod provider; +use std::any::{Any, TypeId}; use std::ops::Deref; use url::Url; @@ -7,12 +8,14 @@ pub use http::Method; pub use provider::*; +#[cfg(any(feature = "blocking", feature = "non_blocking"))] const USER_AGENT: &str = "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/81.0"; pub trait NetProvider { fn fetch(&self, url: Url, handler: H) where H: RequestHandler; + fn resolve_all(&self, marker: M) -> Option>; } impl NetProvider for D @@ -26,6 +29,9 @@ where { self.deref().fetch(url, handler) } + fn resolve_all(&self, marker: M) -> Option> { + self.deref().resolve_all(marker) + } } pub trait RequestHandler: Send + Sync + 'static { @@ -33,6 +39,9 @@ pub trait RequestHandler: Send + Sync + 'static { fn method(&self) -> Method { Method::GET } + fn special(&self) -> Option { + None + } } impl T + Sync + Send + 'static, T> RequestHandler for F { fn bytes(self, bytes: &[u8]) -> T { diff --git a/packages/net/src/provider/blocking.rs b/packages/net/src/provider/blocking.rs index ac4094dd..e9fa7167 100644 --- a/packages/net/src/provider/blocking.rs +++ b/packages/net/src/provider/blocking.rs @@ -1,15 +1,17 @@ use crate::{NetProvider, RequestHandler, USER_AGENT}; +use std::any::{Any, TypeId}; use std::cell::RefCell; +use std::collections::HashMap; use std::io::Read; use thiserror::Error; use url::Url; const FILE_SIZE_LIMIT: u64 = 1_000_000_000; // 1GB -pub struct SyncProvider(pub RefCell>); +pub struct SyncProvider(pub RefCell>, pub RefCell>>); impl SyncProvider { pub fn new() -> Self { - Self(RefCell::new(Vec::new())) + Self(RefCell::new(Vec::new()), RefCell::default()) } fn fetch_inner>( &self, @@ -57,7 +59,15 @@ impl NetProvider for SyncProvider { return; } }; - self.0.borrow_mut().push(handler.bytes(&res)); + if let Some(t) = handler.special() { + let mut entry = self.1.borrow_mut(); + entry.entry(t).or_default().push(handler.bytes(&res)); + } else { + self.0.borrow_mut().push(handler.bytes(&res)); + } + } + fn resolve_all(&self, marker: M) -> Option> { + self.1.borrow_mut().remove(&marker.type_id()) } } diff --git a/packages/net/src/provider/dummy.rs b/packages/net/src/provider/dummy.rs index 335609d0..dcef86fe 100644 --- a/packages/net/src/provider/dummy.rs +++ b/packages/net/src/provider/dummy.rs @@ -1,4 +1,5 @@ use crate::{NetProvider, RequestHandler}; +use std::any::Any; use url::Url; pub struct DummyProvider; @@ -8,4 +9,7 @@ impl NetProvider for DummyProvider { H: RequestHandler, { } + fn resolve_all(&self, _marker: M) -> Option> { + None + } } diff --git a/packages/net/src/provider/non_blocking.rs b/packages/net/src/provider/non_blocking.rs index f38a2a59..8d6f49f4 100644 --- a/packages/net/src/provider/non_blocking.rs +++ b/packages/net/src/provider/non_blocking.rs @@ -2,6 +2,8 @@ use crate::{NetProvider, RequestHandler, USER_AGENT}; use data_url::DataUrl; use futures_util::{stream::FuturesUnordered, StreamExt}; use reqwest::Client; +use std::any::{Any, TypeId}; +use std::collections::HashMap; use std::{sync::Arc, time::Duration}; use thiserror::Error; use tokio::{ @@ -18,6 +20,7 @@ pub struct AsyncProvider { rt: Handle, client: Client, futures: Mutex>>, + special: Mutex>>>, } impl AsyncProvider { pub fn new(rt: &Runtime) -> Self { @@ -25,6 +28,7 @@ impl AsyncProvider { rt: rt.handle().clone(), client: Client::new(), futures: Mutex::new(FuturesUnordered::new()), + special: Mutex::default(), } } pub fn resolve + Send>( @@ -99,10 +103,37 @@ impl NetProvider for AsyncProvider { H: RequestHandler, { let client = self.client.clone(); - - let join = self.rt.spawn(Self::fetch_inner(client, url, handler)); - - self.futures.blocking_lock().push(join); + if let Some(t) = handler.special() { + let join = self.rt.spawn(Self::fetch_inner(client, url, handler)); + self.special + .blocking_lock() + .entry(t) + .or_default() + .push(join); + } else { + let join = self.rt.spawn(Self::fetch_inner(client, url, handler)); + self.futures.blocking_lock().push(join); + } + } + fn resolve_all(&self, marker: M) -> Option> { + self.rt.block_on(async { + let mut futures = self.special.lock().await.remove(&marker.type_id())?; + let mut out = vec![]; + while let Some(ir) = futures.next().await { + match ir { + Ok(Ok(t)) => { + out.push(t); + } + Ok(Err(e)) => { + tracing::error!("Fetch failed with {e:?}") + } + Err(e) => { + tracing::error!("Fetch thread failed with {e}") + } + } + } + Some(out) + }) } }