diff --git a/Cargo.lock b/Cargo.lock index 287ebc9bf..eb8bb5ecf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1672,10 +1672,14 @@ dependencies = [ "encoding_rs", "futures", "getrandom", + "gosub_typeface", + "image", "js-sys", "lazy_static", "log", "rand 0.9.0-alpha.2", + "raw-window-handle", + "smallvec", "thiserror 2.0.3", "url", "uuid", diff --git a/benches/tree_iterator.rs b/benches/tree_iterator.rs index 639246007..3245eb71e 100644 --- a/benches/tree_iterator.rs +++ b/benches/tree_iterator.rs @@ -3,12 +3,30 @@ use std::fs::File; use criterion::{criterion_group, criterion_main, Criterion}; use gosub_css3::system::Css3System; use gosub_html5::document::builder::DocumentBuilderImpl; -use gosub_html5::document::document_impl::TreeIterator; +use gosub_html5::document::document_impl::{DocumentImpl, TreeIterator}; +use gosub_html5::document::fragment::DocumentFragmentImpl; use gosub_html5::parser::Html5Parser; use gosub_shared::byte_stream::{ByteStream, Encoding}; +use gosub_shared::document::DocumentHandle; use gosub_shared::node::NodeId; +use gosub_shared::traits::config::{HasCssSystem, HasDocument, HasHtmlParser}; use gosub_shared::traits::document::DocumentBuilder; +#[derive(Clone, Debug, PartialEq)] +struct Config; + +impl HasCssSystem for Config { + type CssSystem = Css3System; +} +impl HasDocument for Config { + type Document = DocumentImpl; + type DocumentFragment = DocumentFragmentImpl; + type DocumentBuilder = DocumentBuilderImpl; +} + +impl HasHtmlParser for Config { + type HtmlParser = Html5Parser<'static, Self>; +} fn wikipedia_main_page(c: &mut Criterion) { // Criterion can report inconsistent results from run to run in some cases. We attempt to // minimize that in this setup. @@ -20,7 +38,7 @@ fn wikipedia_main_page(c: &mut Criterion) { let mut stream = ByteStream::new(Encoding::UTF8, None); let _ = stream.read_from_file(html_file); - let doc_handle = >::new_document(None); + let doc_handle: DocumentHandle = DocumentBuilderImpl::new_document(None); let _ = Html5Parser::parse_document(&mut stream, doc_handle.clone(), None); group.bench_function("wikipedia main page", |b| { @@ -45,7 +63,7 @@ fn stackoverflow_home(c: &mut Criterion) { let mut bytestream = ByteStream::new(Encoding::UTF8, None); let _ = bytestream.read_from_file(html_file); - let doc_handle = >::new_document(None); + let doc_handle: DocumentHandle = DocumentBuilderImpl::new_document(None); let _ = Html5Parser::parse_document(&mut bytestream, doc_handle.clone(), None); group.bench_function("stackoverflow home", |b| { diff --git a/crates/gosub_css3/src/functions/attr.rs b/crates/gosub_css3/src/functions/attr.rs index 8de5951f8..956c080d5 100644 --- a/crates/gosub_css3/src/functions/attr.rs +++ b/crates/gosub_css3/src/functions/attr.rs @@ -1,10 +1,10 @@ use crate::stylesheet::CssValue; -use gosub_shared::traits::css3::CssSystem; +use gosub_shared::traits::config::HasDocument; use gosub_shared::traits::node::{ElementDataType, Node}; // Probably this shouldn't quite be in gosub_css3 #[allow(dead_code)] -pub fn resolve_attr, C: CssSystem>(values: &[CssValue], node: &N) -> Vec { +pub fn resolve_attr(values: &[CssValue], node: &C::Node) -> Vec { let Some(attr_name) = values.first().map(|v| v.to_string()) else { return vec![]; }; diff --git a/crates/gosub_css3/src/functions/calc.rs b/crates/gosub_css3/src/functions/calc.rs index c40bfcf56..e7f89ac90 100644 --- a/crates/gosub_css3/src/functions/calc.rs +++ b/crates/gosub_css3/src/functions/calc.rs @@ -1,6 +1,7 @@ use crate::stylesheet::CssValue; #[allow(dead_code)] -pub fn resolve_calc(_values: &[CssValue]) -> Vec { - todo!() +pub fn resolve_calc(values: &[CssValue]) -> Vec { + println!("Calc called with {values:?}"); + vec![CssValue::None] } diff --git a/crates/gosub_css3/src/functions/var.rs b/crates/gosub_css3/src/functions/var.rs index 1de85d88e..c06a39756 100644 --- a/crates/gosub_css3/src/functions/var.rs +++ b/crates/gosub_css3/src/functions/var.rs @@ -1,8 +1,6 @@ -use std::collections::HashMap; - use crate::stylesheet::CssValue; -use gosub_shared::traits::css3::CssSystem; -use gosub_shared::traits::document::Document; +use gosub_shared::traits::config::HasDocument; +use std::collections::HashMap; #[allow(dead_code)] #[derive(Clone, Debug, Default)] @@ -12,7 +10,7 @@ pub struct VariableEnvironment { #[allow(dead_code)] impl VariableEnvironment { - pub fn get, C: CssSystem>(&self, name: &str, _doc: &D, _node: &D::Node) -> Option { + pub fn get(&self, name: &str, _doc: &C::Document, _node: &C::Node) -> Option { let mut current = Some(self); while let Some(env) = current { @@ -32,7 +30,7 @@ impl VariableEnvironment { } #[allow(dead_code)] -pub fn resolve_var, C: CssSystem>(values: &[CssValue], doc: &D, node: &D::Node) -> Vec { +pub fn resolve_var(values: &[CssValue], doc: &C::Document, node: &C::Node) -> Vec { let Some(name) = values.first().map(|v| { let mut str = v.to_string(); @@ -50,7 +48,7 @@ pub fn resolve_var, C: CssSystem>(values: &[CssValue], doc: &D, n let environment = VariableEnvironment::default(); //TODO: get from node - let Some(value) = environment.get(&name, doc, node) else { + let Some(value) = environment.get::(&name, doc, node) else { let Some(default) = values.get(1).cloned() else { return vec![]; }; diff --git a/crates/gosub_css3/src/lib.rs b/crates/gosub_css3/src/lib.rs index ab70d8cbf..57d39d383 100644 --- a/crates/gosub_css3/src/lib.rs +++ b/crates/gosub_css3/src/lib.rs @@ -1,3 +1,5 @@ +extern crate core; + use crate::ast::convert_ast_to_stylesheet; use crate::stylesheet::CssStylesheet; use crate::tokenizer::Tokenizer; diff --git a/crates/gosub_css3/src/matcher/styling.rs b/crates/gosub_css3/src/matcher/styling.rs index 5cbd40488..b02ec3ae9 100644 --- a/crates/gosub_css3/src/matcher/styling.rs +++ b/crates/gosub_css3/src/matcher/styling.rs @@ -6,7 +6,9 @@ use std::fmt::Display; use gosub_shared::document::DocumentHandle; use gosub_shared::node::NodeId; -use gosub_shared::traits::css3::{CssOrigin, CssPropertyMap, CssSystem}; +use gosub_shared::traits::config::HasDocument; +use gosub_shared::traits::css3; +use gosub_shared::traits::css3::{CssOrigin, CssPropertyMap}; use gosub_shared::traits::document::Document; use gosub_shared::traits::node::ClassList; use gosub_shared::traits::node::ElementDataType; @@ -14,10 +16,11 @@ use gosub_shared::traits::node::Node; use crate::matcher::property_definitions::get_css_definitions; use crate::stylesheet::{Combinator, CssSelector, CssSelectorPart, CssValue, MatcherType, Specificity}; +use crate::system::Css3System; // Matches a complete selector (all parts) against the given node(id) -pub(crate) fn match_selector, C: CssSystem>( - document: DocumentHandle, +pub(crate) fn match_selector( + document: DocumentHandle, node_id: NodeId, selector: &CssSelector, ) -> (bool, Specificity) { @@ -41,8 +44,8 @@ fn consume<'a, T>(this: &mut &'a [T]) -> Option<&'a T> { } /// Returns true when the given node matches the part(s) -fn match_selector_parts, C: CssSystem>( - handle: DocumentHandle, +fn match_selector_parts( + handle: DocumentHandle, node_id: NodeId, mut parts: &[CssSelectorPart], ) -> bool { @@ -61,7 +64,7 @@ fn match_selector_parts, C: CssSystem>( return false; } - if !match_selector_part(part, current_node, &*binding, &mut next_current_node, &mut parts) { + if !match_selector_part::(part, current_node, &*binding, &mut next_current_node, &mut parts) { return false; } @@ -74,11 +77,11 @@ fn match_selector_parts, C: CssSystem>( true } -fn match_selector_part<'a, D: Document, C: CssSystem>( +fn match_selector_part<'a, C: HasDocument>( part: &CssSelectorPart, - current_node: &D::Node, - doc: &'a D, - next_node: &mut Option<&'a D::Node>, + current_node: &C::Node, + doc: &'a C::Document, + next_node: &mut Option<&'a C::Node>, parts: &mut &[CssSelectorPart], ) -> bool { match part { @@ -198,7 +201,7 @@ fn match_selector_part<'a, D: Document, C: CssSystem>( *next_node = Some(parent); - if match_selector_part(last, parent, doc, next_node, parts) { + if match_selector_part::(last, parent, doc, next_node, parts) { return true; } @@ -227,7 +230,7 @@ fn match_selector_part<'a, D: Document, C: CssSystem>( *next_node = Some(parent); - match_selector_part(last, parent, doc, next_node, parts) + match_selector_part::(last, parent, doc, next_node, parts) } Combinator::NextSibling => { let parent_node = doc.node_by_id(current_node.parent_id().unwrap()); @@ -261,7 +264,7 @@ fn match_selector_part<'a, D: Document, C: CssSystem>( *next_node = Some(prev); - match_selector_part(last, prev, doc, next_node, parts) + match_selector_part::(last, prev, doc, next_node, parts) } Combinator::SubsequentSibling => { let parent_node = doc.node_by_id(current_node.parent_id().unwrap()); @@ -282,7 +285,7 @@ fn match_selector_part<'a, D: Document, C: CssSystem>( continue; }; - if match_selector_part(last, child, doc, next_node, parts) { + if match_selector_part::(last, child, doc, next_node, parts) { return true; } } @@ -534,9 +537,7 @@ impl Display for CssProperty { } } -impl gosub_shared::traits::css3::CssProperty for CssProperty { - type Value = CssValue; - +impl css3::CssProperty for CssProperty { fn compute_value(&mut self) { self.compute_value(); } @@ -588,7 +589,7 @@ impl gosub_shared::traits::css3::CssProperty for CssProperty { } } - fn as_list(&self) -> Option<&[Self::Value]> { + fn as_list(&self) -> Option<&[CssValue]> { if let CssValue::List(list) = &self.actual { Some(list) } else { @@ -596,7 +597,7 @@ impl gosub_shared::traits::css3::CssProperty for CssProperty { } } - fn as_function(&self) -> Option<(&str, &[Self::Value])> { + fn as_function(&self) -> Option<(&str, &[CssValue])> { if let CssValue::Function(name, args) = &self.actual { Some((name.as_str(), args)) } else { @@ -636,22 +637,20 @@ impl CssProperties { } } -impl CssPropertyMap for CssProperties { - type Property = CssProperty; - - fn insert_inherited(&mut self, name: &str, value: Self::Property) { +impl CssPropertyMap for CssProperties { + fn insert_inherited(&mut self, name: &str, value: CssProperty) { self.properties.entry(name.to_string()).or_insert(value); } - fn insert(&mut self, name: &str, value: Self::Property) { + fn insert(&mut self, name: &str, value: CssProperty) { self.properties.insert(name.to_string(), value); } - fn get(&self, name: &str) -> Option<&Self::Property> { + fn get(&self, name: &str) -> Option<&CssProperty> { self.properties.get(name) } - fn get_mut(&mut self, name: &str) -> Option<&mut Self::Property> { + fn get_mut(&mut self, name: &str) -> Option<&mut CssProperty> { self.properties.get_mut(name) } @@ -659,11 +658,11 @@ impl CssPropertyMap for CssProperties { self.dirty = true; } - fn iter(&self) -> impl Iterator + '_ { + fn iter(&self) -> impl Iterator + '_ { self.properties.iter().map(|(k, v)| (k.as_str(), v)) } - fn iter_mut(&mut self) -> impl Iterator + '_ { + fn iter_mut(&mut self) -> impl Iterator + '_ { self.properties.iter_mut().map(|(k, v)| (k.as_str(), v)) } diff --git a/crates/gosub_css3/src/system.rs b/crates/gosub_css3/src/system.rs index 01e29ef53..2f2b54222 100644 --- a/crates/gosub_css3/src/system.rs +++ b/crates/gosub_css3/src/system.rs @@ -9,8 +9,8 @@ use crate::{load_default_useragent_stylesheet, Css3}; use gosub_shared::document::DocumentHandle; use gosub_shared::errors::CssResult; use gosub_shared::node::NodeId; +use gosub_shared::traits::config::{HasDocument, HasRenderTree}; use gosub_shared::traits::css3::{CssOrigin, CssPropertyMap, CssSystem}; -use gosub_shared::traits::document::Document; use gosub_shared::traits::node::{ElementDataType, Node, TextDataType}; use gosub_shared::traits::render_tree::{RenderTree, RenderTreeNode}; use gosub_shared::traits::ParserConfig; @@ -26,20 +26,21 @@ impl CssSystem for Css3System { type PropertyMap = CssProperties; type Property = CssProperty; + type Value = CssValue; fn parse_str(str: &str, config: ParserConfig, origin: CssOrigin, url: &str) -> CssResult { Css3::parse_str(str, config, origin, url) } - fn properties_from_node>( - node: &D::Node, + fn properties_from_node>( + node: &C::Node, sheets: &[Self::Stylesheet], - handle: DocumentHandle, + handle: DocumentHandle, id: NodeId, ) -> Option { let mut css_map_entry = CssProperties::new(); - if node_is_unrenderable::(node) { + if node_is_unrenderable::(node) { return None; } @@ -111,8 +112,8 @@ impl CssSystem for Css3System { Some(css_map_entry) } - fn inheritance>(tree: &mut T) { - Self::resolve_inheritance(tree, tree.root(), &Vec::new()); + fn inheritance>(tree: &mut C::RenderTree) { + Self::resolve_inheritance::(tree, tree.root(), &Vec::new()); } fn load_default_useragent_stylesheet() -> Self::Stylesheet { @@ -121,9 +122,9 @@ impl CssSystem for Css3System { } impl Css3System { - fn resolve_inheritance>( - tree: &mut T, - node_id: T::NodeId, + fn resolve_inheritance>( + tree: &mut C::RenderTree, + node_id: >::NodeId, inherit_props: &Vec<(String, CssValue)>, ) { let Some(current_node) = tree.get_node_mut(node_id) else { @@ -162,7 +163,7 @@ impl Css3System { }; for child in children { - Self::resolve_inheritance(tree, child, &inherit_props); + Self::resolve_inheritance::(tree, child, &inherit_props); } } } @@ -218,7 +219,7 @@ pub fn add_property_to_map( } } -pub fn node_is_unrenderable, C: CssSystem>(node: &D::Node) -> bool { +pub fn node_is_unrenderable(node: &C::Node) -> bool { // There are more elements that are not renderable, but for now we only remove the most common ones const REMOVABLE_ELEMENTS: [&str; 6] = ["head", "script", "style", "svg", "noscript", "title"]; @@ -238,18 +239,14 @@ pub fn node_is_unrenderable, C: CssSystem>(node: &D::Node) -> boo false } -pub fn resolve_functions, C: CssSystem>( - value: &CssValue, - node: &D::Node, - handle: DocumentHandle, -) -> CssValue { - fn resolve, C: CssSystem>(val: &CssValue, node: &D::Node, doc: &D) -> CssValue { +pub fn resolve_functions(value: &CssValue, node: &C::Node, handle: DocumentHandle) -> CssValue { + fn resolve(val: &CssValue, node: &C::Node, doc: &C::Document) -> CssValue { match val { CssValue::Function(func, values) => { let resolved = match func.as_str() { "calc" => resolve_calc(values), - "attr" => resolve_attr(values, node), - "var" => resolve_var(values, doc, node), + "attr" => resolve_attr::(values, node), + "var" => resolve_var::(values, doc, node), _ => vec![val.clone()], }; @@ -262,9 +259,9 @@ pub fn resolve_functions, C: CssSystem>( let doc = handle.get(); if let CssValue::List(list) = value { - let resolved = list.iter().map(|val| resolve(val, node, &*doc)).collect(); + let resolved = list.iter().map(|val| resolve::(val, node, &*doc)).collect(); CssValue::List(resolved) } else { - resolve(value, node, &*doc) + resolve::(value, node, &*doc) } } diff --git a/crates/gosub_html5/benches/tree_construction.rs b/crates/gosub_html5/benches/tree_construction.rs index b118414d1..e8a6aa13d 100644 --- a/crates/gosub_html5/benches/tree_construction.rs +++ b/crates/gosub_html5/benches/tree_construction.rs @@ -1,10 +1,29 @@ use criterion::{criterion_group, criterion_main, Criterion}; use gosub_css3::system::Css3System; +use gosub_html5::document::builder::DocumentBuilderImpl; use gosub_html5::document::document_impl::DocumentImpl; +use gosub_html5::document::fragment::DocumentFragmentImpl; use gosub_html5::parser::Html5Parser; +use gosub_shared::traits::config::{HasCssSystem, HasDocument, HasHtmlParser}; use gosub_testing::testing::tree_construction; use gosub_testing::testing::tree_construction::Harness; +#[derive(Clone, Debug, PartialEq)] +struct Config; + +impl HasCssSystem for Config { + type CssSystem = Css3System; +} +impl HasDocument for Config { + type Document = DocumentImpl; + type DocumentFragment = DocumentFragmentImpl; + type DocumentBuilder = DocumentBuilderImpl; +} + +impl HasHtmlParser for Config { + type HtmlParser = Html5Parser<'static, Self>; +} + fn criterion_benchmark(c: &mut Criterion) { let mut group = c.benchmark_group("Tree construction"); group.significance_level(0.1).sample_size(500); @@ -20,10 +39,7 @@ fn criterion_benchmark(c: &mut Criterion) { for root in &fixtures { for test in &root.tests { for &scripting_enabled in test.script_modes() { - let _ = harness.run_test::, Css3System>, Css3System>( - test.clone(), - scripting_enabled, - ); + let _ = harness.run_test::(test.clone(), scripting_enabled); } } } diff --git a/crates/gosub_html5/src/document/builder.rs b/crates/gosub_html5/src/document/builder.rs index 2cdd48dc3..26c490215 100644 --- a/crates/gosub_html5/src/document/builder.rs +++ b/crates/gosub_html5/src/document/builder.rs @@ -1,43 +1,34 @@ -use std::collections::HashMap; - -use gosub_shared::traits::css3::CssSystem; -use url::Url; - -use crate::document::document_impl::DocumentImpl; use crate::node::HTML_NAMESPACE; use crate::DocumentHandle; +use gosub_shared::traits::config::HasDocument; use gosub_shared::traits::document::DocumentBuilder; use gosub_shared::traits::document::{Document, DocumentType}; use gosub_shared::traits::node::{Node, QuirksMode}; +use std::collections::HashMap; +use url::Url; /// This struct will be used to create a fully initialized document or document fragment pub struct DocumentBuilderImpl {} -impl DocumentBuilder for DocumentBuilderImpl { - type Document = DocumentImpl; - +impl DocumentBuilder for DocumentBuilderImpl { /// Creates a new document with a document root node - fn new_document(url: Option) -> DocumentHandle { - >::new(DocumentType::HTML, url, None) + fn new_document(url: Option) -> DocumentHandle { + C::Document::new(DocumentType::HTML, url, None) } /// Creates a new document fragment with the context as the root node - fn new_document_fragment( - context_node: &>::Node, - quirks_mode: QuirksMode, - ) -> DocumentHandle { + fn new_document_fragment(context_node: &C::Node, quirks_mode: QuirksMode) -> DocumentHandle { let handle = context_node.handle(); // Create a new document with an HTML node as the root node - let fragment_root_node = >::new_element_node( + let fragment_root_node = C::Document::new_element_node( handle.clone(), "html", Some(HTML_NAMESPACE), HashMap::new(), context_node.location(), ); - let mut fragment_handle = - >::new(DocumentType::HTML, None, Some(fragment_root_node)); + let mut fragment_handle = C::Document::new(DocumentType::HTML, None, Some(fragment_root_node)); // let context_node = context_node.clone(); match quirks_mode { diff --git a/crates/gosub_html5/src/document/document_impl.rs b/crates/gosub_html5/src/document/document_impl.rs index 374677a9f..2ae84fc2a 100755 --- a/crates/gosub_html5/src/document/document_impl.rs +++ b/crates/gosub_html5/src/document/document_impl.rs @@ -1,16 +1,12 @@ use crate::DocumentHandle; use core::fmt::Debug; use gosub_shared::traits::document::{Document as OtherDocument, Document, DocumentType}; -use std::cell::RefCell; use std::collections::hash_map::Entry; use std::collections::HashMap; use std::fmt; use std::fmt::{Display, Formatter}; -use std::rc::Rc; use url::Url; -use crate::document::builder::DocumentBuilderImpl; -use crate::document::fragment::DocumentFragmentImpl; use crate::document::task_queue::is_valid_id_attribute_value; use crate::node::arena::NodeArena; use crate::node::data::comment::CommentData; @@ -22,18 +18,18 @@ use crate::node::node_impl::{NodeDataTypeInternal, NodeImpl}; use crate::node::visitor::Visitor; use gosub_shared::byte_stream::Location; use gosub_shared::node::NodeId; -use gosub_shared::traits::css3::CssSystem; +use gosub_shared::traits::config::HasDocument; use gosub_shared::traits::node::Node; use gosub_shared::traits::node::QuirksMode; /// Defines a document #[derive(Debug)] -pub struct DocumentImpl { +pub struct DocumentImpl { // pub handle: Weak>, /// URL of the given document (if any) pub url: Option, /// Holds and owns all nodes in the document - pub(crate) arena: NodeArena, C>, + pub(crate) arena: NodeArena, /// HTML elements with ID (e.g.,
) named_id_elements: HashMap, /// Document type of this document @@ -44,7 +40,7 @@ pub struct DocumentImpl { pub stylesheets: Vec, } -impl PartialEq for DocumentImpl { +impl PartialEq for DocumentImpl { fn eq(&self, other: &Self) -> bool { self.url == other.url && self.arena == other.arena @@ -55,15 +51,13 @@ impl PartialEq for DocumentImpl { } } -impl Document for DocumentImpl { +impl> Document for DocumentImpl { type Node = NodeImpl; - type Fragment = DocumentFragmentImpl; - type Builder = DocumentBuilderImpl; /// Creates a new document without a doc handle #[must_use] - fn new(document_type: DocumentType, url: Option, root_node: Option) -> DocumentHandle { - let doc = Self { + fn new(document_type: DocumentType, url: Option, root_node: Option) -> DocumentHandle { + let mut doc = Self { url, arena: NodeArena::new(), named_id_elements: HashMap::new(), @@ -72,16 +66,17 @@ impl Document for DocumentImpl { stylesheets: Vec::new(), }; - let mut doc_handle = DocumentHandle(Rc::new(RefCell::new(doc)), Default::default()); - if let Some(node) = root_node { - doc_handle.get_mut().register_node(node); + doc.register_node(node); + + DocumentHandle::create(doc) } else { + let mut doc_handle = DocumentHandle::create(doc); let node = Self::Node::new_document(doc_handle.clone(), Location::default(), QuirksMode::NoQuirks); doc_handle.get_mut().arena.register_node(node); - } - doc_handle + doc_handle + } } /// Returns the URL of the document, or "" when no location is set @@ -303,7 +298,7 @@ impl Document for DocumentImpl { } /// Creates a new document node - fn new_document_node(handle: DocumentHandle, quirks_mode: QuirksMode, location: Location) -> Self::Node { + fn new_document_node(handle: DocumentHandle, quirks_mode: QuirksMode, location: Location) -> Self::Node { NodeImpl::new( handle.clone(), location, @@ -312,7 +307,7 @@ impl Document for DocumentImpl { } fn new_doctype_node( - handle: DocumentHandle, + handle: DocumentHandle, name: &str, public_id: Option<&str>, system_id: Option<&str>, @@ -326,7 +321,7 @@ impl Document for DocumentImpl { } /// Creates a new comment node - fn new_comment_node(handle: DocumentHandle, comment: &str, location: Location) -> Self::Node { + fn new_comment_node(handle: DocumentHandle, comment: &str, location: Location) -> Self::Node { NodeImpl::new( handle.clone(), location, @@ -335,7 +330,7 @@ impl Document for DocumentImpl { } /// Creates a new text node - fn new_text_node(handle: DocumentHandle, value: &str, location: Location) -> Self::Node { + fn new_text_node(handle: DocumentHandle, value: &str, location: Location) -> Self::Node { NodeImpl::new( handle.clone(), location, @@ -345,7 +340,7 @@ impl Document for DocumentImpl { /// Creates a new element node fn new_element_node( - handle: DocumentHandle, + handle: DocumentHandle, name: &str, namespace: Option<&str>, attributes: HashMap, @@ -383,7 +378,7 @@ impl Document for DocumentImpl { } } -impl DocumentImpl { +impl> DocumentImpl { // Called whenever a node is being mutated in the document. fn on_document_node_mutation(&mut self, node: &NodeImpl) { // self.on_document_node_mutation_update_id_in_node(node); @@ -414,13 +409,7 @@ impl DocumentImpl { } /// Print a node and all its children in a tree-like structure - pub fn print_tree( - &self, - node: & as Document>::Node, - prefix: String, - last: bool, - f: &mut Formatter, - ) { + pub fn print_tree(&self, node: &C::Node, prefix: String, last: bool, f: &mut Formatter) { let mut buffer = prefix.clone(); if last { buffer.push_str("└─ "); @@ -480,7 +469,7 @@ impl DocumentImpl { } } -impl Display for DocumentImpl { +impl> Display for DocumentImpl { fn fmt(&self, f: &mut Formatter) -> fmt::Result { let root = self.get_root(); self.print_tree(root, "".to_string(), true, f); @@ -488,9 +477,9 @@ impl Display for DocumentImpl { } } -impl DocumentImpl { +impl> DocumentImpl { /// Fetches a node by named id (string) or returns None when no node with this ID is found - pub fn get_node_by_named_id(&self, named_id: &str) -> Option<& as Document>::Node> { + pub fn get_node_by_named_id(&self, named_id: &str) -> Option<&C::Node> { let node_id = self.named_id_elements.get(named_id)?; self.arena.node_ref(*node_id) } @@ -499,7 +488,7 @@ impl DocumentImpl { // pub fn get_node_by_named_id_mut( // &mut self, // named_id: &str, - // ) -> Option<&mut as Document>::Node> { + // ) -> Option<&mut C::Node> { // let node_id = self.named_id_elements.get(named_id)?; // self.arena.node_mut(*node_id) // } @@ -530,26 +519,19 @@ impl DocumentImpl { self.arena.peek_next_id() } - pub fn nodes(&self) -> &HashMap as Document>::Node> { + pub fn nodes(&self) -> &HashMap { self.arena.nodes() } } // Walk the document tree with the given visitor -pub fn walk_document_tree( - handle: DocumentHandle, C>, - visitor: &mut Box as Document>::Node, C>>, -) { +pub fn walk_document_tree(handle: DocumentHandle, visitor: &mut Box>) { let binding = handle.get(); let root = binding.get_root(); internal_visit(handle.clone(), root, visitor); } -fn internal_visit( - handle: DocumentHandle, C>, - node: & as Document>::Node, - visitor: &mut Box as Document>::Node, C>>, -) { +fn internal_visit(handle: DocumentHandle, node: &C::Node, visitor: &mut Box>) { visitor.document_enter(node); let binding = handle.get(); @@ -567,15 +549,15 @@ fn internal_visit( /// WARNING: mutations in the document would be reflected /// in the iterator. It's advised to consume the entire iterator /// before mutating the document again. -pub struct TreeIterator, C: CssSystem> { +pub struct TreeIterator { current_node_id: Option, node_stack: Vec, - document: DocumentHandle, + document: DocumentHandle, } -impl, C: CssSystem> TreeIterator { +impl TreeIterator { #[must_use] - pub fn new(doc: DocumentHandle) -> Self { + pub fn new(doc: DocumentHandle) -> Self { let node_stack = vec![doc.get().get_root().id()]; Self { @@ -586,7 +568,7 @@ impl, C: CssSystem> TreeIterator { } } -impl, C: CssSystem> Iterator for TreeIterator { +impl Iterator for TreeIterator { type Item = NodeId; fn next(&mut self) -> Option { @@ -614,6 +596,7 @@ impl, C: CssSystem> Iterator for TreeIterator { mod tests { use super::*; use crate::document::builder::DocumentBuilderImpl; + use crate::document::fragment::DocumentFragmentImpl; use crate::document::query::DocumentQuery; use crate::document::task_queue::DocumentTaskQueue; use crate::node::HTML_NAMESPACE; @@ -621,13 +604,26 @@ mod tests { use crate::parser::tree_builder::TreeBuilder; use gosub_css3::system::Css3System; use gosub_shared::byte_stream::Location; + use gosub_shared::traits::config::HasCssSystem; use gosub_shared::traits::document::DocumentBuilder; use gosub_shared::traits::node::ClassList; use gosub_shared::traits::node::ElementDataType; use gosub_shared::traits::node::NodeType; use std::collections::HashMap; - type Document = DocumentImpl; + #[derive(Clone, Debug, PartialEq)] + struct Config; + + impl HasCssSystem for Config { + type CssSystem = Css3System; + } + impl HasDocument for Config { + type Document = DocumentImpl; + type DocumentFragment = DocumentFragmentImpl; + type DocumentBuilder = DocumentBuilderImpl; + } + type Handle = DocumentHandle; + type Document = DocumentImpl; #[test] fn relocate() { @@ -713,16 +709,16 @@ mod tests { #[test] fn verify_node_ids_in_element_data() { - let mut doc_handle = DocumentBuilderImpl::new_document(None); + let mut doc_handle: DocumentHandle = DocumentBuilderImpl::new_document(None); - let node_1: NodeImpl = DocumentImpl::new_element_node( + let node_1: NodeImpl = DocumentImpl::new_element_node( doc_handle.clone(), "div", Some(HTML_NAMESPACE), HashMap::new(), Location::default(), ); - let node_2: NodeImpl = DocumentImpl::new_element_node( + let node_2: NodeImpl = DocumentImpl::new_element_node( doc_handle.clone(), "div", Some(HTML_NAMESPACE), @@ -750,7 +746,7 @@ mod tests { #[test] fn document_task_queue() { - let doc_handle: DocumentHandle, Css3System> = DocumentBuilderImpl::new_document(None); + let doc_handle: Handle = DocumentBuilderImpl::new_document(None); // Using task queue to create the following structure initially: //
@@ -859,8 +855,7 @@ mod tests { #[test] fn task_queue_insert_attribute_failues() { - let doc_handle: DocumentHandle, Css3System> = - >::new_document(None); + let doc_handle: Handle = DocumentBuilderImpl::new_document(None); let mut task_queue = DocumentTaskQueue::new(doc_handle.clone()); let div_id = task_queue.create_element("div", NodeId::root(), None, HTML_NAMESPACE, Location::default()); @@ -897,8 +892,7 @@ mod tests { // but using tree builder directly instead of the task queue #[test] fn document_tree_builder() { - let mut doc_handle: DocumentHandle, Css3System> = - >::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); // Using tree builder to create the following structure: //
@@ -1005,8 +999,7 @@ mod tests { #[test] fn insert_generic_attribute() { - let mut doc_handle: DocumentHandle, Css3System> = - >::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); let node = Document::new_element_node( doc_handle.clone(), @@ -1034,8 +1027,7 @@ mod tests { #[test] fn task_queue_insert_generic_attribute() { - let doc_handle: DocumentHandle, Css3System> = - >::new_document(None); + let doc_handle: Handle = DocumentBuilderImpl::new_document(None); let mut task_queue = DocumentTaskQueue::new(doc_handle.clone()); let div_id = task_queue.create_element("div", NodeId::root(), None, HTML_NAMESPACE, Location::default()); @@ -1051,8 +1043,7 @@ mod tests { #[test] fn insert_class_attribute() { - let mut doc_handle: DocumentHandle, Css3System> = - >::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); let div_node = Document::new_element_node( doc_handle.clone(), @@ -1082,7 +1073,7 @@ mod tests { #[test] fn task_queue_insert_class_attribute() { - let doc_handle: DocumentHandle, Css3System> = DocumentBuilderImpl::new_document(None); + let doc_handle: Handle = DocumentBuilderImpl::new_document(None); let mut task_queue = DocumentTaskQueue::new(doc_handle.clone()); let div_id = task_queue.create_element("div", NodeId::root(), None, HTML_NAMESPACE, Location::default()); @@ -1101,7 +1092,7 @@ mod tests { #[test] fn uninitialized_query() { - let doc_handle: DocumentHandle, Css3System> = DocumentBuilderImpl::new_document(None); + let doc_handle: Handle = DocumentBuilderImpl::new_document(None); let query = Query::new(); let found_ids = DocumentQuery::query(doc_handle.clone(), &query); @@ -1124,8 +1115,7 @@ mod tests { //
//

//

- let mut doc_handle: DocumentHandle, Css3System> = - DocumentBuilderImpl::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); let div_node = Document::new_element_node( doc_handle.clone(), @@ -1205,8 +1195,7 @@ mod tests { //

//

//

- let mut doc_handle: DocumentHandle, Css3System> = - DocumentBuilderImpl::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); let div_node = Document::new_element_node( doc_handle.clone(), @@ -1286,8 +1275,7 @@ mod tests { //

//

//

- let mut doc_handle: DocumentHandle, Css3System> = - DocumentBuilderImpl::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); let div_node = Document::new_element_node( doc_handle.clone(), @@ -1375,8 +1363,7 @@ mod tests { //

//

//

- let mut doc_handle: DocumentHandle, Css3System> = - DocumentBuilderImpl::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); let div_node = Document::new_element_node( doc_handle.clone(), @@ -1489,8 +1476,7 @@ mod tests { //

//

//

- let mut doc_handle: DocumentHandle, Css3System> = - DocumentBuilderImpl::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); let div_node = Document::new_element_node( doc_handle.clone(), @@ -1603,8 +1589,7 @@ mod tests { //

//

//

- let mut doc_handle: DocumentHandle, Css3System> = - DocumentBuilderImpl::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); let div_node = Document::new_element_node( doc_handle.clone(), @@ -1719,8 +1704,7 @@ mod tests { //

//

//

- let mut doc_handle: DocumentHandle, Css3System> = - DocumentBuilderImpl::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); let div_node = Document::new_element_node( doc_handle.clone(), @@ -1837,8 +1821,7 @@ mod tests { //

//

//

- let mut doc_handle: DocumentHandle, Css3System> = - DocumentBuilderImpl::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); let div_node = Document::new_element_node( doc_handle.clone(), @@ -1918,8 +1901,7 @@ mod tests { //

//

//

- let mut doc_handle: DocumentHandle, Css3System> = - DocumentBuilderImpl::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); let div_node = Document::new_element_node( doc_handle.clone(), @@ -1999,8 +1981,7 @@ mod tests { //

//

//

- let mut doc_handle: DocumentHandle, Css3System> = - DocumentBuilderImpl::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); let div_node = Document::new_element_node( doc_handle.clone(), @@ -2080,8 +2061,7 @@ mod tests { //

//

//

- let mut doc_handle: DocumentHandle, Css3System> = - DocumentBuilderImpl::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); let div_node = Document::new_element_node( doc_handle.clone(), @@ -2154,8 +2134,7 @@ mod tests { #[test] fn tree_iterator() { - let mut doc_handle: DocumentHandle, Css3System> = - DocumentBuilderImpl::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); //

//
@@ -2239,8 +2218,7 @@ mod tests { #[test] fn tree_iterator_mutation() { - let mut doc_handle: DocumentHandle, Css3System> = - DocumentBuilderImpl::new_document(None); + let mut doc_handle: Handle = DocumentBuilderImpl::new_document(None); let div_node = Document::new_element_node( doc_handle.clone(), diff --git a/crates/gosub_html5/src/document/fragment.rs b/crates/gosub_html5/src/document/fragment.rs index 4853a3803..fdf2d3361 100644 --- a/crates/gosub_html5/src/document/fragment.rs +++ b/crates/gosub_html5/src/document/fragment.rs @@ -2,25 +2,23 @@ use crate::DocumentHandle; use core::fmt; use core::fmt::Debug; -use crate::document::document_impl::DocumentImpl; use crate::node::arena::NodeArena; -use crate::node::node_impl::NodeImpl; use gosub_shared::node::NodeId; -use gosub_shared::traits::css3::CssSystem; +use gosub_shared::traits::config::HasDocument; use gosub_shared::traits::document::DocumentFragment; /// Defines a document fragment which can be attached to for instance a