Skip to main content

boa_engine/
spanned_source_text.rs

1use std::rc::Rc;
2
3use boa_ast::LinearSpan;
4use boa_gc::{Finalize, Trace};
5
6struct Inner {
7    source_text: boa_ast::SourceText,
8}
9impl Inner {
10    fn new(source_text: boa_ast::SourceText) -> Self {
11        Self { source_text }
12    }
13}
14
15#[derive(Default, Trace, Finalize, Clone)]
16pub(crate) struct SourceText {
17    #[unsafe_ignore_trace]
18    source_text: Option<Rc<Inner>>,
19}
20
21impl SourceText {
22    #[must_use]
23    pub(crate) fn new(source_text: boa_ast::SourceText) -> Self {
24        Self {
25            source_text: Some(Rc::new(Inner::new(source_text))),
26        }
27    }
28
29    fn new_empty() -> Self {
30        Self { source_text: None }
31    }
32
33    #[inline]
34    fn inner(&self) -> Option<&boa_ast::SourceText> {
35        self.source_text.as_ref().map(|x| &x.source_text)
36    }
37
38    fn is_empty(&self) -> bool {
39        self.source_text.is_none()
40    }
41}
42
43/// Contains pointer to source code and span of the object.
44#[derive(Default, Clone)]
45pub struct SpannedSourceText {
46    source_text: SourceText,
47    span: Option<LinearSpan>,
48}
49
50impl SpannedSourceText {
51    pub(crate) fn new(source_text: SourceText, span: Option<LinearSpan>) -> Self {
52        Self { source_text, span }
53    }
54
55    pub(crate) fn new_source_only(source_text: SourceText) -> Self {
56        Self {
57            source_text,
58            span: None,
59        }
60    }
61
62    pub(crate) fn new_empty() -> Self {
63        Self {
64            source_text: SourceText::new_empty(),
65            span: None,
66        }
67    }
68
69    /// Creates new [`SpannedSourceText`] with the same [`SourceText`] but without its span.
70    pub(crate) fn clone_only_source(&self) -> Self {
71        Self {
72            source_text: self.source_text.clone(),
73            span: None,
74        }
75    }
76
77    /// Returns the [`SourceText`].
78    #[must_use]
79    pub(crate) fn source_text(&self) -> SourceText {
80        self.source_text.clone()
81    }
82
83    /// Test if the span is empty.
84    #[inline]
85    #[must_use]
86    pub fn is_empty(&self) -> bool {
87        let span_is_empty = if let Some(x) = self.span {
88            x.is_empty()
89        } else {
90            true
91        };
92        span_is_empty || self.source_text.is_empty()
93    }
94
95    /// Gets inner code points.
96    #[must_use]
97    pub fn to_code_points(&self) -> Option<&[u16]> {
98        if let (Some(source_text), Some(span)) = (self.source_text.inner(), self.span) {
99            Some(source_text.get_code_points_from_span(span))
100        } else {
101            None
102        }
103    }
104}
105
106impl std::fmt::Debug for SpannedSourceText {
107    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108        f.debug_struct("SourceTextSpanned").finish()
109    }
110}
111impl std::fmt::Debug for SourceText {
112    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113        f.debug_struct("SourceTextInner").finish()
114    }
115}