Bug #2770
closed
Internal error evaluating template rule (IndexOutOfBoundsException)
Fix Committed on Branch:
9.7, trunk
Fixed in Maintenance Release:
The function call that fails is in a template that has both a name and a match pattern. For component binding purposes, this is treated as two separate components, with different binding vectors. The expression trees for the two components should be disjoint, so that they can use different binding slot numbers. I suspect that the component hasn't been copied properly and that the two components are sharing some subtree of the expression tree, causing an incorrect slot number to be used.
- Description updated (diff)
I was right: the template body contains a LocalParamSetter which contains a reference to a LocalParam. The LocalParam object isn't being copied, which means that the initializer of the LocalParam (written as the content of the xsl:param element but represented on the tree as a select attribute) isn't being copied, so the slot number allocated in its role as a named template gets overwritten by the slot number allocated in its role as a template rule. See LocalParamSetter.copy(), which doesn't copy the "binding" (i.e. the LocalParam).
Copying the LocalParam is tricky because we need to rebind all local variable references to it, throughout the template body. We can only do this once the whole template body has been copied. It's also complicated by the fact that the LocalParamSetter is used not only for initialization of template parameters, but also for the initialization of xsl:iterate parameters.
- Fix Committed on Branch 9.7 added
After considering various alternatives, I have implemented a solution which works as follows: the Expression.copy() method has a new parameter "rebindings" which is a map of (oldBinding, newBinding) pairs. This list can be updated as the copy proceeds. LocalParam.copy() now creates a copy of itself, and adds the (old, new) pair to the binding list. When we reach a reference to the local parameter, if the binding is on the list then the copied local variable is bound to the new binding. (This mechanism can potentially be used to replace the current way in which let/for/some/every expressions rebind variable references, but I won't do that for 9.7 in the interests of stability.)
Currently applied to 9.7, tested against the supplied repro and regression tested against the XSLT3 test suite. Will now copy over to the 9.8 branch.
- Status changed from New to Resolved
- Applies to branch 9.8 added
- Fix Committed on Branch 9.8 added
- Fixed in Maintenance Release 9.6.0.2 added
A patch has been committed on the 9.7 and 9.8 branches. Because the patch adds an argument to Expression.copy(), it affects a large number of files, but in nearly all cases the change is trivial.
- Fixed in Maintenance Release 9.6.0.3 added
- Fixed in Maintenance Release deleted (
9.6.0.2)
The addition of "fixed in 9.6.0.2" seems to have been finger-trouble. I can't find a way to clear all entries from the field: raised a question on the Redmine forum here: http://www.redmine.org/boards/2/topics/50300.
The patch to LocalParam.copy() causes an NPE in test variable-0115. Committing a further (very simple) patch to fix this.
- % Done changed from 0 to 100
- Fixed in Maintenance Release deleted (
9.6.0.3)
- Status changed from Resolved to Closed
- Fixed in Maintenance Release 9.7.0.6 added
Bug fixed in maintenance release 9.7.0.6.
- Fix Committed on Branch trunk added
- Fix Committed on Branch deleted (
9.8)
- Applies to branch deleted (
9.8)
Please register to edit this issue
Also available in: Atom
PDF