Skip to content

Commit 8686ed6

Browse files
committed
Create DocumentUrl abstraction
Signed-off-by: Nico Burns <[email protected]>
1 parent dbf070f commit 8686ed6

File tree

9 files changed

+83
-49
lines changed

9 files changed

+83
-49
lines changed

packages/blitz-dom/src/document.rs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use crate::net::{Resource, StylesheetLoader};
55
use crate::node::{ImageData, NodeFlags, RasterImageData, SpecialElementData, Status, TextBrush};
66
use crate::stylo_to_cursor_icon::stylo_to_cursor_icon;
77
use crate::traversal::TreeTraverser;
8-
use crate::util::{ImageType, resolve_url};
8+
use crate::url::DocumentUrl;
9+
use crate::util::ImageType;
910
use crate::{
1011
DEFAULT_CSS, DocumentConfig, DocumentMutator, ElementData, Node, NodeData, TextNodeData,
1112
};
@@ -24,6 +25,7 @@ use slab::Slab;
2425
use std::any::Any;
2526
use std::collections::{BTreeMap, Bound, HashMap, HashSet};
2627
use std::ops::{Deref, DerefMut};
28+
use std::str::FromStr;
2729
use std::sync::Arc;
2830
use std::sync::atomic::{AtomicUsize, Ordering};
2931
use style::Atom;
@@ -43,7 +45,7 @@ use style::{
4345
media_queries::{Device, MediaList},
4446
selector_parser::SnapshotMap,
4547
shared_lock::{SharedRwLock, StylesheetGuards},
46-
stylesheets::{AllowImportRules, DocumentStyleSheet, Origin, Stylesheet, UrlExtraData},
48+
stylesheets::{AllowImportRules, DocumentStyleSheet, Origin, Stylesheet},
4749
stylist::Stylist,
4850
};
4951
use taffy::AvailableSpace;
@@ -98,7 +100,7 @@ pub struct BaseDocument {
98100

99101
// Config
100102
/// Base url for resolving linked resources (stylesheets, images, fonts, etc)
101-
pub(crate) base_url: Option<url::Url>,
103+
pub(crate) url: DocumentUrl,
102104
// Devtool settings. Currently used to render debug overlays
103105
pub(crate) devtool_settings: DevtoolSettings,
104106
// Viewport details such as the dimensions, HiDPI scale, and zoom factor,
@@ -208,6 +210,11 @@ impl BaseDocument {
208210
style_config::set_bool("layout.unimplemented", true);
209211
style_config::set_bool("layout.columns.enabled", true);
210212

213+
let base_url = config
214+
.base_url
215+
.and_then(|url| DocumentUrl::from_str(&url).ok())
216+
.unwrap_or_default();
217+
211218
let font_ctx = config.font_ctx.unwrap_or_else(|| {
212219
let mut font_ctx = FontContext::default();
213220
font_ctx
@@ -236,7 +243,7 @@ impl BaseDocument {
236243
viewport,
237244
devtool_settings: DevtoolSettings::default(),
238245
viewport_scroll: kurbo::Point::ZERO,
239-
base_url: None,
246+
url: base_url,
240247
ua_stylesheets: HashMap::new(),
241248
nodes_to_stylesheet: BTreeMap::new(),
242249
font_ctx,
@@ -300,7 +307,7 @@ impl BaseDocument {
300307

301308
/// Set base url for resolving linked resources (stylesheets, images, fonts, etc)
302309
pub fn set_base_url(&mut self, url: &str) {
303-
self.base_url = Some(Url::parse(url).unwrap());
310+
self.url = DocumentUrl::from(Url::parse(url).unwrap());
304311
}
305312

306313
pub fn guard(&self) -> &SharedRwLock {
@@ -483,11 +490,11 @@ impl BaseDocument {
483490
node
484491
}
485492

486-
pub fn resolve_url(&self, raw: &str) -> url::Url {
487-
resolve_url(&self.base_url, raw).unwrap_or_else(|| {
493+
pub(crate) fn resolve_url(&self, raw: &str) -> url::Url {
494+
self.url.resolve_relative(raw).unwrap_or_else(|| {
488495
panic!(
489-
"to be able to resolve {raw} with the base_url: {base_url:?}",
490-
base_url = self.base_url
496+
"to be able to resolve {raw} with the base_url: {:?}",
497+
*self.url
491498
)
492499
})
493500
}
@@ -522,11 +529,7 @@ impl BaseDocument {
522529
pub fn make_stylesheet(&self, css: impl AsRef<str>, origin: Origin) -> DocumentStyleSheet {
523530
let data = Stylesheet::from_str(
524531
css.as_ref(),
525-
UrlExtraData::from(self.base_url.clone().unwrap_or_else(|| {
526-
"data:text/css;charset=utf-8;base64,"
527-
.parse::<Url>()
528-
.unwrap()
529-
})),
532+
self.url.url_extra_data(),
530533
origin,
531534
ServoArc::new(self.guard.wrap(MediaList::empty())),
532535
self.guard.clone(),

packages/blitz-dom/src/events/mouse.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use blitz_traits::{
77
};
88
use markup5ever::local_name;
99

10-
use crate::{BaseDocument, node::SpecialElementData, util::resolve_url};
10+
use crate::{BaseDocument, node::SpecialElementData};
1111

1212
pub(crate) fn handle_mousemove(
1313
doc: &mut BaseDocument,
@@ -192,17 +192,14 @@ pub(crate) fn handle_click<F: FnMut(DomEvent)>(
192192
}
193193
} else if el.name.local == local_name!("a") {
194194
if let Some(href) = el.attr(local_name!("href")) {
195-
if let Some(url) = resolve_url(&doc.base_url, href) {
195+
if let Some(url) = doc.url.resolve_relative(href) {
196196
doc.navigation_provider.navigate_to(NavigationOptions::new(
197197
url,
198198
String::from("text/plain"),
199199
doc.id(),
200200
));
201201
} else {
202-
println!(
203-
"{href} is not parseable as a url. : {base_url:?}",
204-
base_url = doc.base_url
205-
)
202+
println!("{href} is not parseable as a url. : {:?}", *doc.url)
206203
}
207204
return;
208205
} else {

packages/blitz-dom/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ mod stylo;
4747
mod stylo_to_cursor_icon;
4848
mod stylo_to_parley;
4949
mod traversal;
50+
mod url;
5051

5152
pub mod net;
5253
pub mod util;

packages/blitz-dom/src/mutator.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ impl DocumentMutator<'_> {
121121

122122
pub fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>) -> usize {
123123
let mut data = ElementData::new(name, attrs);
124-
data.flush_style_attribute(self.doc.guard(), self.doc.base_url.clone());
124+
data.flush_style_attribute(self.doc.guard(), &self.doc.url.url_extra_data());
125125

126126
let id = self.doc.create_node(NodeData::Element(data));
127127
let node = self.doc.get_node(id).unwrap();
@@ -216,7 +216,7 @@ impl DocumentMutator<'_> {
216216
}
217217

218218
if *attr == local_name!("style") {
219-
element.flush_style_attribute(&self.doc.guard, self.doc.base_url.clone());
219+
element.flush_style_attribute(&self.doc.guard, &self.doc.url.url_extra_data());
220220
} else if (tag, attr) == tag_and_attr!("input", "checked") {
221221
set_input_checked_state(element, value.to_string());
222222
} else if (tag, attr) == tag_and_attr!("img", "src") {
@@ -257,7 +257,7 @@ impl DocumentMutator<'_> {
257257
let tag = &element.name.local;
258258
let attr = &name.local;
259259
if *attr == local_name!("style") {
260-
element.flush_style_attribute(&self.doc.guard, self.doc.base_url.clone());
260+
element.flush_style_attribute(&self.doc.guard, &self.doc.url.url_extra_data());
261261
} else if (tag, attr) == tag_and_attr!("canvas", "src") {
262262
self.recompute_is_animating = true;
263263
} else if (tag, attr) == tag_and_attr!("link", "href") {

packages/blitz-dom/src/node/element.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -246,17 +246,11 @@ impl ElementData {
246246
}
247247
}
248248

249-
pub fn flush_style_attribute(&mut self, guard: &SharedRwLock, base_url: Option<Url>) {
249+
pub fn flush_style_attribute(&mut self, guard: &SharedRwLock, url_extra_data: &UrlExtraData) {
250250
self.style_attribute = self.attr(local_name!("style")).map(|style_str| {
251-
let url = UrlExtraData::from(base_url.clone().unwrap_or_else(|| {
252-
"data:text/css;charset=utf-8;base64,"
253-
.parse::<Url>()
254-
.unwrap()
255-
}));
256-
257251
ServoArc::new(guard.wrap(parse_style_attribute(
258252
style_str,
259-
&url,
253+
url_extra_data,
260254
None,
261255
QuirksMode::NoQuirks,
262256
CssRuleType::Style,

packages/blitz-dom/src/node/node.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use style::invalidation::element::restyle_hints::RestyleHint;
1414
use style::properties::ComputedValues;
1515
use style::properties::generated::longhands::position::computed_value::T as Position;
1616
use style::selector_parser::PseudoElement;
17+
use style::stylesheets::UrlExtraData;
1718
use style::values::computed::Display;
1819
use style::values::specified::box_::{DisplayInside, DisplayOutside};
1920
use style::{data::ElementData as StyloElementData, shared_lock::SharedRwLock};
@@ -23,7 +24,6 @@ use taffy::{
2324
Cache,
2425
prelude::{Layout, Style},
2526
};
26-
use url::Url;
2727

2828
use super::{Attribute, ElementData};
2929

@@ -632,9 +632,9 @@ impl Node {
632632
}
633633
}
634634

635-
pub fn flush_style_attribute(&mut self, base_url: Option<Url>) {
635+
pub fn flush_style_attribute(&mut self, url_extra_data: &UrlExtraData) {
636636
if let NodeData::Element(ref mut elem_data) = self.data {
637-
elem_data.flush_style_attribute(&self.guard, base_url);
637+
elem_data.flush_style_attribute(&self.guard, url_extra_data);
638638
}
639639
}
640640

packages/blitz-dom/src/query_selector.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ use selectors::SelectorList;
22
use smallvec::SmallVec;
33
use style::dom_apis::{MayUseInvalidation, QueryAll, QueryFirst, query_selector};
44
use style::selector_parser::{SelectorImpl, SelectorParser};
5-
use style::stylesheets::UrlExtraData;
65
use style_traits::ParseError;
7-
use url::Url;
86

97
use crate::{BaseDocument, Node};
108

@@ -69,11 +67,7 @@ impl BaseDocument {
6967
&self,
7068
input: &'input str,
7169
) -> Result<SelectorList<SelectorImpl>, ParseError<'input>> {
72-
let url_extra_data = UrlExtraData::from(self.base_url.clone().unwrap_or_else(|| {
73-
"data:text/css;charset=utf-8;base64,"
74-
.parse::<Url>()
75-
.unwrap()
76-
}));
70+
let url_extra_data = self.url.url_extra_data();
7771
SelectorParser::parse_author_origin_no_namespace(input, &url_extra_data)
7872
}
7973
}

packages/blitz-dom/src/url.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use std::ops::Deref;
2+
use std::str::FromStr;
3+
4+
use style::servo_arc::Arc as ServoArc;
5+
use style::stylesheets::UrlExtraData;
6+
use url::Url;
7+
8+
#[derive(Clone)]
9+
pub(crate) struct DocumentUrl {
10+
base_url: ServoArc<Url>,
11+
}
12+
13+
impl DocumentUrl {
14+
/// Create a stylo `UrlExtraData` from the URL
15+
pub(crate) fn url_extra_data(&self) -> UrlExtraData {
16+
UrlExtraData(ServoArc::clone(&self.base_url))
17+
}
18+
19+
pub(crate) fn resolve_relative(&self, raw: &str) -> Option<url::Url> {
20+
self.base_url.join(raw).ok()
21+
}
22+
}
23+
24+
impl Default for DocumentUrl {
25+
fn default() -> Self {
26+
Self::from_str("data:text/css;charset=utf-8;base64,").unwrap()
27+
}
28+
}
29+
impl FromStr for DocumentUrl {
30+
type Err = <Url as FromStr>::Err;
31+
fn from_str(s: &str) -> Result<Self, Self::Err> {
32+
let base_url = ServoArc::new(Url::parse(s)?);
33+
Ok(Self { base_url })
34+
}
35+
}
36+
impl From<Url> for DocumentUrl {
37+
fn from(base_url: Url) -> Self {
38+
Self {
39+
base_url: ServoArc::new(base_url),
40+
}
41+
}
42+
}
43+
impl From<ServoArc<Url>> for DocumentUrl {
44+
fn from(base_url: ServoArc<Url>) -> Self {
45+
Self { base_url }
46+
}
47+
}
48+
impl Deref for DocumentUrl {
49+
type Target = Url;
50+
fn deref(&self) -> &Self::Target {
51+
&self.base_url
52+
}
53+
}

packages/blitz-dom/src/util.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,6 @@ pub enum ImageType {
2121
Background(usize),
2222
}
2323

24-
pub(crate) fn resolve_url(base_url: &Option<url::Url>, raw: &str) -> Option<url::Url> {
25-
match base_url {
26-
Some(base_url) => base_url.join(raw),
27-
None => url::Url::parse(raw),
28-
}
29-
.ok()
30-
}
31-
3224
// Debug print an RcDom
3325
pub fn walk_tree(indent: usize, node: &Node) {
3426
// Skip all-whitespace text nodes entirely

0 commit comments

Comments
 (0)