korvin_core/
lib.rs

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}