blitz_dom_api/error.rs
1//! The error type every operation returns.
2
3use blitz_dom::NodeId;
4
5use crate::atom::AtomId;
6
7/// Why a DOM operation could not be performed.
8///
9/// Deliberately narrow. Most of `blitz-script`'s operations are *tolerant*
10/// where the DOM specification is strict: reading an attribute off a node that
11/// is not an element yields "absent" rather than throwing, and removing a
12/// child that is not a child removes it from wherever it actually is. Those
13/// behaviours are copied rather than corrected, so they do not appear here.
14/// What does appear is every case where `blitz-script` itself raises, plus the
15/// tree invariants it asserts with `expect`.
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub enum DomError {
18 /// The node id does not name a node in this document.
19 ///
20 /// Only produced where `blitz-script` would panic rather than return.
21 NodeNotFound(NodeId),
22 /// The document has no root element, so there is nothing to answer with.
23 NoRootElement,
24 /// A selector string could not be parsed.
25 ///
26 /// `blitz-script` swallows this: `querySelector` returns `null`, `matches`
27 /// returns `false`, `closest` searches an empty match set. This crate
28 /// surfaces it instead, and the reparenting diff for each of those call
29 /// sites is a trailing `.ok().flatten()` or `.unwrap_or_default()`.
30 InvalidSelector(String),
31 /// A `classList` token was empty or contained ASCII whitespace.
32 ///
33 /// `blitz-script` raises a `SyntaxError` here; this is the same case.
34 InvalidClassToken(String),
35 /// An [`AtomId`] was resolved against an interner that did not mint it.
36 UnknownAtom(AtomId),
37 /// A structural invariant the operation relies on did not hold.
38 ///
39 /// `compare_document_position` is the only current source: it walks to a
40 /// common ancestor and then indexes into it, and `blitz-script` asserts
41 /// both steps with `expect`. A facade must not take the process down over
42 /// a malformed tree, so the assertion becomes this.
43 TreeInvariant(&'static str),
44}
45
46impl std::fmt::Display for DomError {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 match self {
49 Self::NodeNotFound(id) => write!(f, "no node with id {id:?} in this document"),
50 Self::NoRootElement => write!(f, "document has no root element"),
51 Self::InvalidSelector(selector) => write!(f, "could not parse selector `{selector}`"),
52 Self::InvalidClassToken(token) => write!(
53 f,
54 "classList token `{token}` must be non-empty and contain no ASCII whitespace"
55 ),
56 Self::UnknownAtom(atom) => write!(f, "{atom:?} was not produced by this interner"),
57 Self::TreeInvariant(what) => write!(f, "document tree invariant violated: {what}"),
58 }
59 }
60}
61
62impl std::error::Error for DomError {}