From e470b27b4159956cc82d55193256634e78ef1810 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Thu, 30 Jan 2020 18:41:39 +0200 Subject: [PATCH] FIX: Ensure 'unless' helper resolves variable name once (#8820) This fixes a bug which caused '{{#unless var}}' to act the same as '{{#if true}}' because 'unless' was transforming the conditional value to 'undefined'. --- .../lib/raw-handlebars-helpers.js.es6 | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/discourse-common/lib/raw-handlebars-helpers.js.es6 b/app/assets/javascripts/discourse-common/lib/raw-handlebars-helpers.js.es6 index ffaa721cf39..77923676a46 100644 --- a/app/assets/javascripts/discourse-common/lib/raw-handlebars-helpers.js.es6 +++ b/app/assets/javascripts/discourse-common/lib/raw-handlebars-helpers.js.es6 @@ -47,7 +47,32 @@ export function registerRawHelpers(hbs, handlebarsClass) { return old.apply(this, [hbs.helpers.get(context, options), options]); }; } + + // HACK: Ensure that the variable is resolved only once. + // The "get" function will be called twice because both `if` and `unless` + // helpers are patched to resolve the variable and `unless` is implemented + // as not `if`. For example, for {{#unless var}} will generate a stack + // trace like: + // + // - patched-unless("var") "var" is resolved to its value, val + // - unless(val) unless is implemented as !if + // - !patched-if(val) val is already resolved, but it is resolved again + // - !if(???) at this point, ??? usually stands for undefined + // + // The following code ensures that patched-unless will call `if` directly, + // `patched-unless("var")` will return `!if(val)`. + const oldIf = hbs.helpers["if"]; + hbs.helpers["unless"] = function(context, options) { + return oldIf.apply(this, [ + hbs.helpers.get(context, options), + { + fn: options.inverse, + inverse: options.fn, + hash: options.hash + } + ]); + }; + stringCompatHelper("if"); - stringCompatHelper("unless"); stringCompatHelper("with"); }