You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by "Steve O'Hara (JIRA)" <de...@velocity.apache.org> on 2010/01/15 18:12:54 UTC

[jira] Created: (VELOCITY-752) Evaluation of macro arguments

Evaluation of macro arguments
-----------------------------

                 Key: VELOCITY-752
                 URL: https://issues.apache.org/jira/browse/VELOCITY-752
             Project: Velocity
          Issue Type: Bug
          Components: Engine
    Affects Versions: 1.6.2
         Environment: Windows XP SP2, Java 1.5
            Reporter: Steve O'Hara
            Priority: Minor


I've just come across a little gotcha that has taken a few hours to track down which might help other people.

An example;

#macro(myMacro $FieldName)
    #foreach ($Name in $FieldList)
        #if ($FieldName=="empty")
            #set ($tmp=$FieldsFound.put($FieldName,$velocityCount))
        #end
    #end
#end

#foreach ($X in $MyFields)
    #myMacro("Field$velocityCount")
#end

All looks OK doesn't it, but........

The problem is one of when arguments are evaluated or in fact to be more precise, are not evaluated at all.
Once you bear that in mind you can see the logical problem above - the use of $velocityCount (or indeed any variable) in the argument list of myMacro i.e. 

#myMacro("Field$velocityCount")

This sort of usage is dangerous because in effect, what is happening is that the macro argument literal is being placed within the macro body without being evaluated first.
So, the body of the macro becomes this;

    #foreach ($Name in $FieldList)
        #if ("Field$velocityCount"=="empty")
            #set ($tmp=$FieldsFound.put("Field$velocityCount",$velocityCount)
        #end
    #end

Not what you intended at all and depending on the names of your variables, could cause all kinds of mayhem with values coming into scope that you hadn't intended.

The workaround is to set a variable before the call to the macro and send that instead e.g.

#foreach ($X in $MyFields)
    #set ($tmp="Field$velocityCount")
    #myMacro($tmp)
#end



-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@velocity.apache.org
For additional commands, e-mail: dev-help@velocity.apache.org


[jira] Commented: (VELOCITY-752) Evaluation of macro arguments

Posted by "Jarkko Viinamäki (JIRA)" <de...@velocity.apache.org>.
    [ https://issues.apache.org/jira/browse/VELOCITY-752?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12801256#action_12801256 ] 

Jarkko Viinamäki commented on VELOCITY-752:
-------------------------------------------

I'm not 100% sure I understand the problem correctly but I also noticed that the test case provided here didn't yield expected results. I don't have time to confirm this but commenting one line in ProxyVMContext might fix the issue:

org.apache.velocity.context.ProxyVMContext

    private boolean isConstant(Node node)
    {
        switch (node.getType())
        {
            case ParserTreeConstants.JJTINTEGERRANGE:
            case ParserTreeConstants.JJTREFERENCE:
            case ParserTreeConstants.JJTOBJECTARRAY:
            case ParserTreeConstants.JJTMAP:
        //    case ParserTreeConstants.JJTSTRINGLITERAL:  // commenting this line should fix it?
            case ParserTreeConstants.JJTTEXT:
                return (false);
            default:
                return (true);
        }
    }

However, this causes at least test Velocity615TestCase.testForIrrationallyFearedRelatedPossibleProblem to fail since the behaviour is now different. Nathan, what do you think?

> Evaluation of macro arguments
> -----------------------------
>
>                 Key: VELOCITY-752
>                 URL: https://issues.apache.org/jira/browse/VELOCITY-752
>             Project: Velocity
>          Issue Type: Bug
>          Components: Engine
>    Affects Versions: 1.6.2
>         Environment: Windows XP SP2, Java 1.5
>            Reporter: Steve O'Hara
>            Priority: Minor
>
> I've just come across a little gotcha that has taken a few hours to track down which might help other people.
> An example;
> #macro(myMacro $FieldName)
>     #foreach ($Name in $FieldList)
>         #if ($FieldName=="empty")
>             #set ($tmp=$FieldsFound.put($FieldName,$velocityCount))
>         #end
>     #end
> #end
> #foreach ($X in $MyFields)
>     #myMacro("Field$velocityCount")
> #end
> All looks OK doesn't it, but........
> The problem is one of when arguments are evaluated or in fact to be more precise, are not evaluated at all.
> Once you bear that in mind you can see the logical problem above - the use of $velocityCount (or indeed any variable) in the argument list of myMacro i.e. 
> #myMacro("Field$velocityCount")
> This sort of usage is dangerous because in effect, what is happening is that the macro argument literal is being placed within the macro body without being evaluated first.
> So, the body of the macro becomes this;
>     #foreach ($Name in $FieldList)
>         #if ("Field$velocityCount"=="empty")
>             #set ($tmp=$FieldsFound.put("Field$velocityCount",$velocityCount)
>         #end
>     #end
> Not what you intended at all and depending on the names of your variables, could cause all kinds of mayhem with values coming into scope that you hadn't intended.
> The workaround is to set a variable before the call to the macro and send that instead e.g.
> #foreach ($X in $MyFields)
>     #set ($tmp="Field$velocityCount")
>     #myMacro($tmp)
> #end

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@velocity.apache.org
For additional commands, e-mail: dev-help@velocity.apache.org