Skip to content

Commit

Permalink
Expose the name of the currently called item
Browse files Browse the repository at this point in the history
  • Loading branch information
SergioBenitez committed Nov 18, 2022
1 parent 90bdb45 commit baa407c
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 7 deletions.
26 changes: 19 additions & 7 deletions minijinja/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ impl<'env> Vm<'env> {
env: self.env,
ctx: Context::new(Frame::new(root)),
current_block: None,
instructions,
current_call: None,
auto_escape,
instructions,
blocks: prepare_blocks(blocks),
loaded_templates: BTreeSet::new(),
#[cfg(feature = "macros")]
Expand Down Expand Up @@ -115,8 +116,9 @@ impl<'env> Vm<'env> {
env: self.env,
ctx,
current_block: None,
instructions,
current_call: None,
auto_escape: state.auto_escape(),
instructions,
blocks: BTreeMap::default(),
loaded_templates: BTreeSet::new(),
#[cfg(feature = "macros")]
Expand Down Expand Up @@ -421,6 +423,7 @@ impl<'env> Vm<'env> {
stack.push(out.end_capture(state.auto_escape));
}
Instruction::ApplyFilter(name, arg_count, local_id) => {
state.current_call = Some(name);
let filter =
ctx_ok!(get_or_lookup_local(&mut loaded_filters, *local_id, || {
state.env.get_filter(name)
Expand All @@ -435,8 +438,10 @@ impl<'env> Vm<'env> {
a = ctx_ok!(filter.apply_to(state, args));
stack.drop_top(*arg_count);
stack.push(a);
state.current_call = Some(name);
}
Instruction::PerformTest(name, arg_count, local_id) => {
state.current_call = Some(name);
let test = ctx_ok!(get_or_lookup_local(&mut loaded_tests, *local_id, || {
state.env.get_test(name)
})
Expand All @@ -447,10 +452,13 @@ impl<'env> Vm<'env> {
let rv = ctx_ok!(test.perform(state, args));
stack.drop_top(*arg_count);
stack.push(Value::from(rv));
state.current_call = None;
}
Instruction::CallFunction(function_name, arg_count) => {
Instruction::CallFunction(name, arg_count) => {
state.current_call = Some(name);

// super is a special function reserved for super-ing into blocks.
if *function_name == "super" {
if *name == "super" {
if *arg_count != 0 {
bail!(Error::new(
ErrorKind::InvalidOperation,
Expand All @@ -459,7 +467,7 @@ impl<'env> Vm<'env> {
}
stack.push(ctx_ok!(self.perform_super(state, out, true)));
// loop is a special name which when called recurses the current loop.
} else if *function_name == "loop" {
} else if *name == "loop" {
if *arg_count != 1 {
bail!(Error::new(
ErrorKind::InvalidOperation,
Expand All @@ -468,23 +476,27 @@ impl<'env> Vm<'env> {
}
// leave the one argument on the stack for the recursion
recurse_loop!(true);
} else if let Some(func) = state.ctx.load(self.env, function_name) {
} else if let Some(func) = state.ctx.load(self.env, name) {
let args = stack.slice_top(*arg_count);
a = ctx_ok!(func.call(state, args));
stack.drop_top(*arg_count);
stack.push(a);
} else {
bail!(Error::new(
ErrorKind::UnknownFunction,
format!("{} is unknown", function_name),
format!("{} is unknown", name),
));
}

state.current_call = None;
}
Instruction::CallMethod(name, arg_count) => {
state.current_call = Some(name);
let args = stack.slice_top(*arg_count);
a = ctx_ok!(args[0].call_method(state, name, &args[1..]));
stack.drop_top(*arg_count);
stack.push(a);
state.current_call = None;
}
Instruction::CallObject(arg_count) => {
let args = stack.slice_top(*arg_count);
Expand Down
9 changes: 9 additions & 0 deletions minijinja/src/vm/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub struct State<'vm, 'env> {
pub(crate) env: &'env Environment<'env>,
pub(crate) ctx: Context<'env>,
pub(crate) current_block: Option<&'env str>,
pub(crate) current_call: Option<&'env str>,
pub(crate) auto_escape: AutoEscape,
pub(crate) instructions: &'vm Instructions<'env>,
pub(crate) blocks: BTreeMap<&'env str, BlockStack<'vm, 'env>>,
Expand All @@ -38,6 +39,7 @@ impl<'vm, 'env> fmt::Debug for State<'vm, 'env> {
let mut ds = f.debug_struct("State");
ds.field("name", &self.instructions.name());
ds.field("current_block", &self.current_block);
ds.field("current_call", &self.current_call);
ds.field("auto_escape", &self.auto_escape);
ds.field("ctx", &self.ctx);
ds.field("env", &self.env);
Expand Down Expand Up @@ -66,6 +68,12 @@ impl<'vm, 'env> State<'vm, 'env> {
self.current_block
}

/// Returns the name of the item (filter, function, test, method) currently
/// being called.
pub fn current_call(&self) -> Option<&str> {
self.current_call
}

/// Looks up a variable by name in the context.
pub fn lookup(&self, name: &str) -> Option<Value> {
self.ctx.load(self.env(), name)
Expand All @@ -82,6 +90,7 @@ impl<'vm, 'env> State<'vm, 'env> {
blocks: BTreeMap::new(),
loaded_templates: BTreeSet::new(),
macros: Default::default(),
current_call: None,
})
}

Expand Down
3 changes: 3 additions & 0 deletions minijinja/tests/snapshots/test_templates__vm@debug.txt.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ input_file: minijinja/tests/inputs/debug.txt
State {
name: "debug.txt",
current_block: None,
current_call: Some(
"debug",
),
auto_escape: None,
ctx: {
"x": 0,
Expand Down

0 comments on commit baa407c

Please sign in to comment.