fix: cleanup

This commit is contained in:
Ivan Miletic
2026-10-01 23:56:31 +02:00
parent d076cab213
commit 191c17fe98
4 changed files with 69 additions and 7 deletions
Generated
+1
View File
@@ -6010,6 +6010,7 @@ dependencies = [
"arc-swap",
"async-trait",
"base64",
"bumpalo",
"criterion",
"downcast-rs",
"fixedbitset",
+1
View File
@@ -15,6 +15,7 @@ doctest = false
ahash = { workspace = true }
anyhow = { workspace = true }
base64 = "0.22"
bumpalo = { workspace = true }
thiserror = { workspace = true }
petgraph = { workspace = true }
serde_json = { workspace = true, features = [] }
+66 -6
View File
@@ -1,12 +1,15 @@
use crate::model::ExpressionNodeContent;
use crate::nodes::result::NodeResult;
use ahash::HashMap;
use bumpalo::Bump;
use std::rc::Rc;
use crate::nodes::context::{NodeContext, NodeContextExt};
use crate::nodes::definition::NodeHandler;
use zen_expression::lexer::{Identifier, Lexer, TokenKind};
use zen_expression::variable::{ToVariable, Variable};
use zen_types::decision::TransformAttributes;
use zen_types::symbol::Symbol;
#[derive(Debug, Clone)]
pub struct ExpressionNodeHandler;
@@ -28,6 +31,7 @@ impl NodeHandler for ExpressionNodeHandler {
async fn handle(&self, ctx: NodeContext<Self::NodeData, Self::TraceData>) -> NodeResult {
let result = Variable::empty_object();
let mut isolate = ctx.isolate();
let mut dollar_bound = false;
for expression in ctx.node.expressions.iter() {
if expression.key.is_empty() || expression.value.is_empty() {
@@ -39,9 +43,11 @@ impl NodeHandler for ExpressionNodeHandler {
.with_node_context(&ctx, |_| {
format!(r#"Failed to evaluate expression: "{}""#, &expression.value)
})?;
let value = match expression.value.contains('$') {
true => value.deep_clone(),
false => value,
let value = match &value {
Variable::Object(_) | Variable::Array(_) if reads_context(&expression.value) => {
value.deep_clone()
}
_ => value,
};
ctx.trace(|trace| {
trace.insert(
@@ -52,15 +58,69 @@ impl NodeHandler for ExpressionNodeHandler {
);
});
isolate.insert_dollar(&expression.key, value.clone());
result.dot_insert(&expression.key, value);
insert_at_path(&result, &expression.key, value);
if !dollar_bound {
isolate.set_local(Variable::dollar_key(), result.shallow_clone());
dollar_bound = true;
}
}
ctx.success(result)
}
}
fn reads_context(source: &str) -> bool {
let bump = Bump::new();
Lexer::new()
.tokenize(&bump, source)
.map(|tokens| {
tokens.iter().any(|token| {
matches!(
token.kind,
TokenKind::Identifier(Identifier::ContextReference | Identifier::RootReference)
)
})
})
.unwrap_or(true)
}
fn insert_at_path(root: &Variable, key: &str, value: Variable) {
let mut parts = key.split('.');
let Some(last) = parts.next_back() else {
return;
};
let mut current = root.shallow_clone();
for part in parts {
let Variable::Object(object) = &current else {
return;
};
let next = {
let mut map = object.borrow_mut();
match map.get_str(part).map(Variable::shallow_clone) {
Some(Variable::Object(child)) if Rc::strong_count(&child) > 2 => {
let copy = Variable::Object(child).depth_clone(1);
map.insert(Symbol::from(part), copy.shallow_clone());
copy
}
Some(child @ Variable::Object(_)) => child,
Some(_) => return,
None => {
let created = Variable::empty_object();
map.insert(Symbol::from(part), created.shallow_clone());
created
}
}
};
current = next;
}
if let Variable::Object(object) = &current {
object.borrow_mut().insert(Symbol::from(last), value);
}
}
#[derive(Debug, Clone, ToVariable)]
pub struct ExpressionNodeTraceItem {
result: Variable,
+1 -1
View File
@@ -795,7 +795,7 @@ impl<'a> GraphAnalyzer<'a> {
let row_scope = Self::scope_with(
scope,
&[
("$", dollar.depth_clone(usize::MAX)),
("$", dollar.shallow_clone()),
(NODES_KEY, self.nodes_scope.shallow_clone()),
],
);