1use data::ElementId;
2use dom_executor::DomExecutor;
3pub use js_sys;
4use mutation::error::MutationError;
5use raw_operations::error::{DebugOf, RawOperationError};
6use thiserror::Error;
7pub use web_sys;
8use web_sys::{Document, Element};
9pub mod flavors;
10
11thread_local! {
12 pub static DOCUMENT: web_sys::Document = crate::get_document().expect("document not present");
13}
14
15pub mod data;
16pub mod document_model;
17pub mod dom_executor;
18pub mod element_builder;
19pub mod mutation;
20pub mod raw_operations;
21pub mod utils;
22
23#[derive(Error, Debug)]
24pub enum RuntimeError {
25 #[error("No window")]
26 NoWindow,
27 #[error("No document")]
28 NoDocument,
29 #[error("No root element (body)")]
30 NoRootElement,
31 #[error("Executing a mutation: {0}")]
32 Mutation(#[source] mutation::error::MutationError),
33 #[error("Nothing to revert, revert stack is empty")]
34 UndoStackEmpty,
35 #[error("Document model didn't clean up properly on previous draw.")]
36 ElementStackNonEmpty,
37 #[error("DocumentModel modification failed: {0}")]
38 DocumentModel(#[source] document_model::error::DocumentModelError),
39 #[error(
40 "Tried popping unexpected element: got root [{current_root:?}], exepected root: [{expected_root:?}]"
41 )]
42 InvalidElementPopped {
43 current_root: DebugOf,
44 expected_root: DebugOf,
45 },
46 #[error("Slicers went out of sync: {message}")]
47 SlicersWentOutOfSync { message: String },
48 #[error("Error occurred when reparenting: {source}")]
49 Reparenting { source: RawOperationError },
50 #[error("When reverting trailing mutations: {0}")]
51 UndoingTrailingMutations(#[source] MutationError),
52 #[error("When performing new mutations: {0}")]
53 PerformingNewMutations(#[source] MutationError),
54 #[error("This should never happen, but runtime crashed on previous redraw.")]
55 RuntimeCrashedOnPreviousRedraw,
56 #[error("Reinserting old child resulted in an error.")]
57 ReinsertingOldChild(#[source] RawOperationError),
58 #[error("Removing old child.")]
59 RemovingElement(#[source] RawOperationError),
60}
61
62type RuntimeResult<T> = std::result::Result<T, RuntimeError>;
63
64pub fn get_document() -> RuntimeResult<Document> {
65 web_sys::window()
66 .ok_or(RuntimeError::NoWindow)
67 .and_then(|window| window.document().ok_or(RuntimeError::NoDocument))
68}
69
70#[derive(Debug)]
71pub struct Runtime {
72 pub dom_executor: DomExecutor,
73}
74
75impl Runtime {
76 pub fn root_element(&self) -> &ElementId {
77 self.dom_executor
78 .executed
79 .as_ref()
80 .map(|executed| &executed.element.create.log.element_id)
81 .expect("runtime crashed")
82 }
83 pub fn new(root_element: impl Into<Element>) -> Self {
84 Self {
85 dom_executor: DomExecutor::new(ElementId::new(root_element.into())),
86 }
87 }
88}