diff --git a/src/renderer/renderer.rs b/src/renderer/renderer.rs index b6cc041..6759c53 100644 --- a/src/renderer/renderer.rs +++ b/src/renderer/renderer.rs @@ -11,6 +11,7 @@ use crate::parser::Template; use crate::parser::TemplateElement; use crate::renderer::breadcrumb_tree::BreadcrumbTreeElement; use crate::renderer::context_element::ContextElement; +use crate::renderer::context_element::IceResult; use crate::renderer::context_element::IntoContextElement; use crate::renderer::context_element::Walkable; use crate::renderer::errors::CompileError; @@ -376,24 +377,6 @@ impl<'a> DustRenderer<'a> { let param_map = ParametersContext::new(self, breadcrumbs, ¶meterized_block.params); - // Special case: when comparing two RVPaths, if the - // path is equal then dust assumes the values are - // equal (otherwise, non-scalar values are - // automatically not equal) - if Self::are_paths_identical(¶m_map, "key", "value") { - return match ¶meterized_block.contents { - None => Ok("".to_owned()), - Some(body) => { - let rendered_content = self.render_body( - body, - new_breadcrumbs.as_ref().unwrap_or(breadcrumbs), - blocks, - )?; - Ok(rendered_content) - } - }; - } - if !param_map.contains_key("key") { return Ok("".to_owned()); } @@ -403,15 +386,22 @@ impl<'a> DustRenderer<'a> { let right_side = param_map .walk("value") .map(|ice| ice.into_context_element(self, breadcrumbs)); - if left_side.as_ref().map(|maybe_ice| { - maybe_ice - .as_ref() - .map(|ice| ice.get_context_element_reference()) - }) == right_side.as_ref().map(|maybe_ice| { - maybe_ice - .as_ref() - .map(|ice| ice.get_context_element_reference()) - }) { + // Special case: when comparing two RVPaths, if the + // path points to the same value then they are + // equal. This is particularly important for objects + // which compare memory locations rather than contents + // (javascript object equality). + if Self::new_are_paths_identical(&left_side, &right_side) + || left_side.as_ref().map(|maybe_ice| { + maybe_ice + .as_ref() + .map(|ice| ice.get_context_element_reference()) + }) == right_side.as_ref().map(|maybe_ice| { + maybe_ice + .as_ref() + .map(|ice| ice.get_context_element_reference()) + }) + { return self.render_maybe_body( ¶meterized_block.contents, new_breadcrumbs.as_ref().unwrap_or(breadcrumbs), @@ -436,24 +426,6 @@ impl<'a> DustRenderer<'a> { let param_map = ParametersContext::new(self, breadcrumbs, ¶meterized_block.params); - // Special case: when comparing two RVPaths, if the - // path is equal then dust assumes the values are - // equal (otherwise, non-scalar values are - // automatically not equal) - if Self::are_paths_identical(¶m_map, "key", "value") { - return match ¶meterized_block.else_contents { - None => Ok("".to_owned()), - Some(body) => { - let rendered_content = self.render_body( - body, - new_breadcrumbs.as_ref().unwrap_or(breadcrumbs), - blocks, - )?; - Ok(rendered_content) - } - }; - } - if !param_map.contains_key("key") { return Ok("".to_owned()); } @@ -463,23 +435,30 @@ impl<'a> DustRenderer<'a> { let right_side = param_map .walk("value") .map(|ice| ice.into_context_element(self, breadcrumbs)); - if left_side.as_ref().map(|maybe_ice| { - maybe_ice - .as_ref() - .map(|ice| ice.get_context_element_reference()) - }) != right_side.as_ref().map(|maybe_ice| { - maybe_ice - .as_ref() - .map(|ice| ice.get_context_element_reference()) - }) { + // Special case: when comparing two RVPaths, if the + // path points to the same value then they are + // equal. This is particularly important for objects + // which compare memory locations rather than contents + // (javascript object equality). + if Self::new_are_paths_identical(&left_side, &right_side) + || left_side.as_ref().map(|maybe_ice| { + maybe_ice + .as_ref() + .map(|ice| ice.get_context_element_reference()) + }) == right_side.as_ref().map(|maybe_ice| { + maybe_ice + .as_ref() + .map(|ice| ice.get_context_element_reference()) + }) + { return self.render_maybe_body( - ¶meterized_block.contents, + ¶meterized_block.else_contents, new_breadcrumbs.as_ref().unwrap_or(breadcrumbs), blocks, ); } else { return self.render_maybe_body( - ¶meterized_block.else_contents, + ¶meterized_block.contents, new_breadcrumbs.as_ref().unwrap_or(breadcrumbs), blocks, ); @@ -800,6 +779,26 @@ impl<'a> DustRenderer<'a> { } } + fn new_are_paths_identical<'b>( + left_side: &Result>, WalkError>, + right_side: &Result>, WalkError>, + ) -> bool { + let left_resolved = left_side.as_ref().map(|maybe_ice| { + maybe_ice + .as_ref() + .map(|ice| ice.get_context_element_reference()) + }); + let right_resolved = right_side.as_ref().map(|maybe_ice| { + maybe_ice + .as_ref() + .map(|ice| ice.get_context_element_reference()) + }); + match (left_resolved, right_resolved) { + (Ok(Some(lce)), Ok(Some(rce))) => lce as *const _ == rce as *const _, + _ => false, + } + } + fn preprocess_filters(filters: &Vec) -> Vec { let mut final_filters: Vec = filters .into_iter()