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