Skip to content

Commit eeb58bd

Browse files
committed
fix: improve mustache delimiter parsing
1 parent f25e121 commit eeb58bd

8 files changed

Lines changed: 352 additions & 95 deletions

File tree

Cargo.lock

Lines changed: 12 additions & 51 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@ categories = ["template-engine"]
1515
boa_ast = "0.21"
1616
boa_engine = { version = "0.21", features = ["deser"] }
1717
boa_parser = "0.21"
18-
html5ever = "0.38.0"
19-
markup5ever_rcdom = "0.38.0"
20-
regex = "1.12"
18+
html5ever = "0.39.0"
19+
markup5ever_rcdom = "0.39.0"
2120
serde = "1.0"
2221
serde_json = { version = "1.0", features = ["preserve_order"] }
23-
thiserror = "2"
22+
thiserror = "2.0"

src/engine.rs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::sync::atomic::AtomicUsize;
2-
31
use boa_ast::{
42
Statement, StatementListItem,
53
declaration::{Binding, Declaration},
@@ -26,17 +24,17 @@ pub(crate) struct ForBinding {
2624
pub(crate) struct Engine {
2725
pub context: Context,
2826
scope_keys: Vec<String>,
29-
scope_next: AtomicUsize,
30-
binding_next: AtomicUsize,
27+
scope_next: usize,
28+
binding_next: usize,
3129
}
3230

3331
impl Engine {
3432
pub fn new(data: impl Serialize) -> Result<Self> {
3533
let mut engine = Self {
3634
context: Context::default(),
3735
scope_keys: Default::default(),
38-
scope_next: AtomicUsize::new(0),
39-
binding_next: AtomicUsize::new(0),
36+
scope_next: 0,
37+
binding_next: 0,
4038
};
4139

4240
engine.enter_scope().map_err(|err| Error::Scope {
@@ -68,11 +66,8 @@ impl Engine {
6866
}
6967

7068
pub fn enter_scope(&mut self) -> JsResult<()> {
71-
let key = format!(
72-
"__scope_{}",
73-
self.scope_next
74-
.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
75-
);
69+
let key = format!("__scope_{}", self.scope_next);
70+
self.scope_next += 1;
7671
let scope = ObjectInitializer::new(&mut self.context).build();
7772
self.context.global_object().set(
7873
JsString::from(key.as_str()),
@@ -154,11 +149,8 @@ impl Engine {
154149
let Some(scope_key) = self.scope_keys.last().cloned() else {
155150
return false;
156151
};
157-
let temp_key = format!(
158-
"__temp_{}",
159-
self.binding_next
160-
.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
161-
);
152+
let temp_key = format!("__temp_{}", self.binding_next);
153+
self.binding_next += 1;
162154

163155
let slot_array = JsArray::from_iter(slots, &mut self.context);
164156

src/error.rs

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,28 @@ impl fmt::Display for DirectiveErrorKind {
4242
}
4343
}
4444

45+
fn format_field(field: &Option<String>) -> String {
46+
match field {
47+
Some(field) => format!(" field {field:?}"),
48+
None => String::new(),
49+
}
50+
}
51+
52+
fn format_expression(expression: &Option<String>) -> String {
53+
match expression {
54+
Some(expression) if !expression.is_empty() => format!(" {expression:?}"),
55+
_ => String::new(),
56+
}
57+
}
58+
59+
fn format_directives(directives: &[Directive]) -> String {
60+
directives
61+
.iter()
62+
.map(ToString::to_string)
63+
.collect::<Vec<_>>()
64+
.join(", ")
65+
}
66+
4567
#[derive(Debug, thiserror::Error)]
4668
pub enum Error {
4769
#[error("failed to parse template: {source}")]
@@ -68,13 +90,19 @@ pub enum Error {
6890
source: serde_json::Error,
6991
},
7092

71-
#[error("failed to convert render data to JavaScript: {message}")]
93+
#[error(
94+
"failed to convert render data{field} to JavaScript: {message}",
95+
field = format_field(field)
96+
)]
7297
DataToJs {
7398
field: Option<String>,
7499
message: String,
75100
},
76101

77-
#[error("failed to inject render data: {message}")]
102+
#[error(
103+
"failed to inject render data{field}: {message}",
104+
field = format_field(field)
105+
)]
78106
DataInject {
79107
field: Option<String>,
80108
message: String,
@@ -83,17 +111,23 @@ pub enum Error {
83111
#[error("failed to manage JavaScript scope: {message}")]
84112
Scope { message: String },
85113

86-
#[error("failed to execute prevue script: {message}")]
114+
#[error("failed to execute <script type=\"prevue\">: {message}")]
87115
SetupScript { message: String },
88116

89-
#[error("invalid {directive}: {kind}")]
117+
#[error(
118+
"invalid {directive}: {kind}{expression}",
119+
expression = format_expression(expression)
120+
)]
90121
InvalidDirective {
91122
directive: Directive,
92123
kind: DirectiveErrorKind,
93124
expression: Option<String>,
94125
},
95126

96-
#[error("conflicting directives: {directives:?}")]
127+
#[error(
128+
"conflicting directives: {directives}",
129+
directives = format_directives(directives)
130+
)]
97131
ConflictingDirectives { directives: Vec<Directive> },
98132
}
99133

0 commit comments

Comments
 (0)