Skip to content

Commit

Permalink
Workaround for css loading
Browse files Browse the repository at this point in the history
  • Loading branch information
kokoISnoTarget committed Sep 7, 2024
1 parent 407942e commit f5a65ea
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 10 deletions.
1 change: 0 additions & 1 deletion packages/dom/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
9 changes: 8 additions & 1 deletion packages/dom/src/htmlsink.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -151,6 +151,13 @@ impl<'b, N: NetProvider<Resource>> 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);

Expand Down
6 changes: 5 additions & 1 deletion packages/dom/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand All @@ -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,
Expand All @@ -47,6 +48,9 @@ impl RequestHandler<Resource> for CssHandler {
);
Resource::Css(self.node, DocumentStyleSheet(ServoArc::new(sheet)))
}
fn special(&self) -> Option<TypeId> {
Some(CssMarker.type_id())
}
}
pub(crate) struct ImageHandler(usize);
impl ImageHandler {
Expand Down
9 changes: 9 additions & 0 deletions packages/net/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
mod provider;

use std::any::{Any, TypeId};
use std::ops::Deref;
use url::Url;

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<T> {
fn fetch<H>(&self, url: Url, handler: H)
where
H: RequestHandler<T>;
fn resolve_all<M: Any>(&self, marker: M) -> Option<Vec<T>>;
}

impl<T, P, D> NetProvider<T> for D
Expand All @@ -26,13 +29,19 @@ where
{
self.deref().fetch(url, handler)
}
fn resolve_all<M: Any>(&self, marker: M) -> Option<Vec<T>> {
self.deref().resolve_all(marker)
}
}

pub trait RequestHandler<T>: Send + Sync + 'static {
fn bytes(self, bytes: &[u8]) -> T;
fn method(&self) -> Method {
Method::GET
}
fn special(&self) -> Option<TypeId> {
None
}
}
impl<F: Fn(&[u8]) -> T + Sync + Send + 'static, T> RequestHandler<T> for F {
fn bytes(self, bytes: &[u8]) -> T {
Expand Down
16 changes: 13 additions & 3 deletions packages/net/src/provider/blocking.rs
Original file line number Diff line number Diff line change
@@ -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<T>(pub RefCell<Vec<T>>);
pub struct SyncProvider<T>(pub RefCell<Vec<T>>, pub RefCell<HashMap<TypeId, Vec<T>>>);
impl<T> SyncProvider<T> {
pub fn new() -> Self {
Self(RefCell::new(Vec::new()))
Self(RefCell::new(Vec::new()), RefCell::default())
}
fn fetch_inner<H: RequestHandler<T>>(
&self,
Expand Down Expand Up @@ -57,7 +59,15 @@ impl<T> NetProvider<T> for SyncProvider<T> {
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<M: Any>(&self, marker: M) -> Option<Vec<T>> {
self.1.borrow_mut().remove(&marker.type_id())
}
}

Expand Down
4 changes: 4 additions & 0 deletions packages/net/src/provider/dummy.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{NetProvider, RequestHandler};
use std::any::Any;
use url::Url;

pub struct DummyProvider;
Expand All @@ -8,4 +9,7 @@ impl<T> NetProvider<T> for DummyProvider {
H: RequestHandler<T>,
{
}
fn resolve_all<M: Any>(&self, _marker: M) -> Option<Vec<T>> {
None
}
}
39 changes: 35 additions & 4 deletions packages/net/src/provider/non_blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -18,13 +20,15 @@ pub struct AsyncProvider<T> {
rt: Handle,
client: Client,
futures: Mutex<FuturesUnordered<TaskHandle<T>>>,
special: Mutex<HashMap<TypeId, FuturesUnordered<TaskHandle<T>>>>,
}
impl<T: Send + Sync + 'static> AsyncProvider<T> {
pub fn new(rt: &Runtime) -> Self {
Self {
rt: rt.handle().clone(),
client: Client::new(),
futures: Mutex::new(FuturesUnordered::new()),
special: Mutex::default(),
}
}
pub fn resolve<P: From<(WindowId, T)> + Send>(
Expand Down Expand Up @@ -99,10 +103,37 @@ impl<T: Send + 'static> NetProvider<T> for AsyncProvider<T> {
H: RequestHandler<T>,
{
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<M: Any>(&self, marker: M) -> Option<Vec<T>> {
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)
})
}
}

Expand Down

0 comments on commit f5a65ea

Please sign in to comment.