Hi guys!
Probably, this issue is partially related to this one: #40
I am using macro like this in my project:
{% twig_js name="TwigRender.templates.template" %}
{% if doOrNot|default(false) %}
{{ 'do' }}
{% else %}
{{ 'not' }}
{% endif %}
twig.js compiles it in javascript code like this:
// line 2
TwigRender.templates.macros.prototype.gettest = function(opt_doOrNot) {
var context = twig.extend({}, this.env_.getGlobals());
var sb = new twig.StringBuffer;
// line 3
sb.append(" ");
if (((("doOrNot" in context)) ? (twig.filter.def(opt_doOrNot, true)) : (true))) {
// line 4
sb.append(" ");
sb.append("do");
sb.append("\n ");
} else {
// line 6
sb.append(" ");
sb.append("not");
sb.append("\n ");
}
return new twig.Markup(sb.toString());
};
Next, when i am trying to call this macro i always get do as result because context does not contain doOrNot variable (so we have in if condition always true value). More generaly, default filter for any variable always results to default value. That's the problem.
This issue appears only in macro compiling case. If we will try to execute simple template like this:
{% twig_js name="TwigRender.templates.template" %}
{% if doOrNot|default(true) %}
{{ 'do' }}
{% else %}
{{ 'not' }}
{% endif %}
the result will be correct (so it depends on doOrNot value).
Internally, this template is compiled into the function that uses context variable filled with scope variables:
/**
* @inheritDoc
*/
TwigRender.templates.template.prototype.render_ = function(sb, context, blocks) {
// line 2
if (((("doOrNot" in context)) ? (twig.filter.def("doOrNot" in context ? context["doOrNot"] : null, true)) : (true))) {
// line 3
sb.append(" ");
sb.append("do");
sb.append("\n");
} else {
// line 5
sb.append(" ");
sb.append("not");
sb.append("\n");
}
};
As i know, when twig compiles simple templates into php code, the resulting function (i.e doDisplay) has $context variable already filled with all template properties. But when twig renders macro, the result function php function has no $context variable filled with the scope variables - this function internally fills it itself with necessary variables and then uses $context.
@schmittjoh, as i can see, you are using in twig.js a little bit another approach when you are deal with macros - you do not fill context with scope variables (see #40 ), but hold special localVarMap in JsCompiler instead and than use it when compile Name expressions. Nevertheless, for example default filter constructions are compiled to conditional expressions with first term, that looks like this:
(varName in context)
thanks to NameCompiler.
May be it is pertinently to fill context with scope variables in macros?
Or we should use localVarMap in this case and become compiled
if (((opt_doOrNot) ? (twig.filter.def(opt_doOrNot, true)) : (true)))
instead of
if (((("doOrNot" in context)) ? (twig.filter.def(opt_doOrNot, true)) : (true)))
?