From ce2f8b31289164df21c3d24b86c3a007725e46c6 Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Tue, 2 Nov 2021 16:53:22 +0100 Subject: [PATCH] Revert "implement Context-local functions and ergonomic wrappers marking functions as safe (#666)" This reverts commit 34435db2ee91e64a0c1985b8567feef141522e9f. --- src/builtins/functions.rs | 57 -------------------------------------- src/context.rs | 40 ++------------------------ src/lib.rs | 5 +--- src/renderer/call_stack.rs | 7 +---- src/renderer/processor.rs | 13 +++------ 5 files changed, 9 insertions(+), 113 deletions(-) diff --git a/src/builtins/functions.rs b/src/builtins/functions.rs index 11291de8b..c3b9fefbf 100644 --- a/src/builtins/functions.rs +++ b/src/builtins/functions.rs @@ -8,26 +8,6 @@ use serde_json::value::{from_value, to_value, Value}; use crate::errors::{Error, Result}; -/// The context-local function type definition -pub trait FunctionRelaxed { - /// The context-local function type definition - fn call(&self, args: &HashMap) -> Result; - - /// Whether the current function's output should be treated as safe, defaults to `false` - fn is_safe(&self) -> bool { - false - } -} - -impl FunctionRelaxed for F -where - F: Fn(&HashMap) -> Result, -{ - fn call(&self, args: &HashMap) -> Result { - self(args) - } -} - /// The global function type definition pub trait Function: Sync + Send { /// The global function type definition @@ -48,43 +28,6 @@ where } } -macro_rules! safe_function { - ($function_trait:ident, $function_wrapper:ident) => { - /// Wrapper to make `is_safe` return `true` instead of `false` for a trait implementation. - pub struct $function_wrapper - where - F: $function_trait, - { - inner: F, - } - - impl $function_trait for $function_wrapper - where - F: $function_trait, - { - fn call(&self, args: &HashMap) -> Result { - self.inner.call(args) - } - - fn is_safe(&self) -> bool { - true - } - } - - impl From for $function_wrapper - where - F: $function_trait, - { - fn from(func: F) -> Self { - $function_wrapper { inner: func } - } - } - }; -} - -safe_function!(FunctionRelaxed, FunctionRelaxedSafe); -safe_function!(Function, FunctionSafe); - pub fn range(args: &HashMap) -> Result { let start = match args.get("start") { Some(val) => match from_value::(val.clone()) { diff --git a/src/context.rs b/src/context.rs index f3976fce2..8e8c8bee8 100644 --- a/src/context.rs +++ b/src/context.rs @@ -5,39 +5,20 @@ use serde::ser::Serialize; use serde_json::value::{to_value, Map, Value}; use crate::errors::{Error, Result as TeraResult}; -use crate::FunctionRelaxed; -use std::sync::Arc; /// The struct that holds the context of a template rendering. /// /// Light wrapper around a `BTreeMap` for easier insertions of Serializable /// values -#[derive(Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct Context { data: BTreeMap, - /// Ignored by PartialEq! - functions: BTreeMap>, -} - -impl std::fmt::Debug for Context { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Context") - .field("data", &self.data) - .field("functions", &self.functions.keys()) - .finish() - } -} - -impl PartialEq for Context { - fn eq(&self, other: &Self) -> bool { - self.data.eq(&other.data) - } } impl Context { /// Initializes an empty context pub fn new() -> Self { - Context { data: BTreeMap::new(), functions: Default::default() } + Context { data: BTreeMap::new() } } /// Converts the `val` parameter to `Value` and insert it into the context. @@ -82,15 +63,6 @@ impl Context { Ok(()) } - /// Registers Context-local function - pub fn register_function>( - &mut self, - key: S, - val: T, - ) { - self.functions.insert(key.into(), Arc::new(val)); - } - /// Appends the data of the `source` parameter to `self`, overwriting existing keys. /// The source context will be dropped. /// @@ -125,7 +97,7 @@ impl Context { for (key, value) in m { data.insert(key, value); } - Ok(Context { data, functions: Default::default() }) + Ok(Context { data }) } _ => Err(Error::msg( "Creating a Context from a Value/Serialize requires it being a JSON object", @@ -155,12 +127,6 @@ impl Context { pub fn contains_key(&self, index: &str) -> bool { self.data.contains_key(index) } - - /// Looks up Context-local registered function - #[inline] - pub fn get_function(&self, fn_name: &str) -> Option<&Arc> { - self.functions.get(fn_name) - } } impl Default for Context { diff --git a/src/lib.rs b/src/lib.rs index 25ea64d97..b46f19ebb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,6 @@ //! See the [site](https://tera.netlify.com) for features and to get started. #![deny(missing_docs)] -#![deny(warnings)] #[macro_use] mod macros; @@ -24,9 +23,7 @@ mod utils; // Library exports. pub use crate::builtins::filters::Filter; -pub use crate::builtins::functions::{ - Function, FunctionRelaxed, FunctionRelaxedSafe, FunctionSafe, -}; +pub use crate::builtins::functions::Function; pub use crate::builtins::testers::Test; pub use crate::context::Context; pub use crate::errors::{Error, ErrorKind, Result}; diff --git a/src/renderer/call_stack.rs b/src/renderer/call_stack.rs index 4cb9deb12..11253a9a7 100644 --- a/src/renderer/call_stack.rs +++ b/src/renderer/call_stack.rs @@ -8,8 +8,7 @@ use crate::errors::{Error, Result}; use crate::renderer::for_loop::{ForLoop, ForLoopState}; use crate::renderer::stack_frame::{FrameContext, FrameType, StackFrame, Val}; use crate::template::Template; -use crate::{Context, FunctionRelaxed}; -use std::sync::Arc; +use crate::Context; /// Contains the user data and allows no mutation #[derive(Debug)] @@ -132,10 +131,6 @@ impl<'a> CallStack<'a> { None } - pub fn lookup_function(&self, fn_name: &str) -> Option<&Arc> { - self.context.inner.get_function(fn_name) - } - /// Add an assignment value (via {% set ... %} and {% set_global ... %} ) pub fn add_assignment(&mut self, key: &'a str, global: bool, value: Val<'a>) { if global { diff --git a/src/renderer/processor.rs b/src/renderer/processor.rs index 9dcbe80e6..2c1f2dbb2 100644 --- a/src/renderer/processor.rs +++ b/src/renderer/processor.rs @@ -491,6 +491,9 @@ impl<'a> Processor<'a> { function_call: &'a FunctionCall, needs_escape: &mut bool, ) -> Result> { + let tera_fn = self.tera.get_function(&function_call.name)?; + *needs_escape = !tera_fn.is_safe(); + let err_wrap = |e| Error::call_function(&function_call.name, e); let mut args = HashMap::new(); @@ -501,15 +504,7 @@ impl<'a> Processor<'a> { ); } - if let Some(tera_fn) = self.call_stack.lookup_function(&function_call.name) { - *needs_escape = !tera_fn.is_safe(); - Ok(Cow::Owned(tera_fn.call(&args).map_err(err_wrap)?)) - } else { - let tera_fn = self.tera.get_function(&function_call.name)?; - *needs_escape = !tera_fn.is_safe(); - - Ok(Cow::Owned(tera_fn.call(&args).map_err(err_wrap)?)) - } + Ok(Cow::Owned(tera_fn.call(&args).map_err(err_wrap)?)) } fn eval_macro_call(&mut self, macro_call: &'a MacroCall, write: &mut impl Write) -> Result<()> {