I've unconvered a subtle bug in the way TT evaluates (or rather, doesn't
evaluate) list vmethods when they appear in variables that are being 
assigned to (e.g. on the left side of a '=').  

Here's a test demonstrating the problem (added to t/vmeth.t)

  -- test --
  [% hash = { }
     list = [ hash ]
     list.last.message = 'Hello World';
     "message: $list.last.message\n"
  -%]

  -- expect --
  message: Hello World

The 'list.last' vmethod is not evaluated in the assignment and the test 
fails:

  MATCH FAILED
   input: [[% hash = { }\n   list = [ hash ]\n  ...etc...]
  expect: [message: Hello World]
  output: [message: ]

The problem is around line 621 of Template::Stash.pm, in the _dotop() 
method.  Fortunately the moron who wrote the code (me :-) left a comment
explaining his actions.

    elsif ($rootref eq 'ARRAY') {    
        # if root is an ARRAY then we check for a LIST_OPS pseudo-method 
        # (except for l-values for which it doesn't make any sense)
        # or return the numerical index into the array, or undef
        
        if (($value = $LIST_OPS->{ $item }) && ! $lvalue) {
            ...

Well it appears that it does make sense to evaluate LIST_OPS virtual
methods for l-values, so the fix is to remove the $lvalue test in that
last line:

        if ($value = $LIST_OPS->{ $item }) {

We also need the equivalent fix in the Template::Stash::XS module, around
line 451 of xs/Stash.xs

    /* try list pseudo-method, but not for lvalues */
    if ((flags & TT_LVALUE_FLAG) ||
        (list_op(aTHX_ root, item, args, &result) == TT_RET_UNDEF)) {

We can remove the (flags & TT_LVALUE_FLAG) test and it works as expected.
I've also added the same test from t/vmeth.t to t/stash-xs.t to make sure
it's fixed in the XS stash.  All others tests in the test suite continue 
to pass.

Changes are about to hit CVS.  New release expected soon.

Cheers
A



_______________________________________________
templates mailing list
[email protected]
http://lists.template-toolkit.org/mailman/listinfo/templates

Reply via email to