Bug #4767
closedxsl:with-param value evaluation in xsl:call-template in ixsl:schedule-action
100%
Description
In a situation like this
<xsl:for-each select="$sequence">
<xsl:variable name="item" select="." as="element()"/>
<ixsl:schedule-action http-request="map{ ... } }">
<xsl:call-template name="callback">
<xsl:with-param name="value" select="$item"/>
</xsl:call-template>
</ixsl:schedule-action>
</xsl:for-each>
all the callback
template invocations get the same (last?) $item
as the value
param. Expected: each $item
in the sequence is passed as the invocation param.
The reason is that with-param
values are evaluated at the time the action is scheduled, not at the time it completes.
From the mailing list: https://sourceforge.net/p/saxon/mailman/message/37118233/
Updated by Michael Kay about 4 years ago
I agree we should fix this by evaluating the xsl:with-param values earlier.
As a workaround, consider:
<xsl:for-each select="$sequence">
<xsl:call-template name="despatch"/>
</xsl:for-each>
<xsl:template name="despatch">
<xsl:variable name="item" select="." as="element()"/>
<ixsl:schedule-action http-request="map{ ... } }">
<xsl:call-template name="callback">
<xsl:with-param name="value" select="$item"/>
</xsl:call-template>
</ixsl:schedule-action>
</xsl:template>
I'm hoping this will work because each call of the despatch template creates a new stackframe for the called template, with its own variables, rather than reusiing the same stackframe. But I haven't tested it.
Updated by Michael Kay about 4 years ago
I suspect this can be fixed fairly easily. Where we create a new context for the template call (Expr.js#1150)
const c2 = context.newContext(true);
we should make a copy of the array holding local variables:
c2.localVars = c2.localVars.slice()
Testing it is more difficult... And I suspect we need to take a snapshot of the current focus as well as the local variables.
Updated by Martynas Jusevicius about 4 years ago
Thank you Michael, I can confirm the workaround works.
Updated by Debbie Lockett about 4 years ago
- Subject changed from xsl:with-param value evaluation in xsl:call-template in xsl:schedule-action to xsl:with-param value evaluation in xsl:call-template in ixsl:schedule-action
- Status changed from New to In Progress
- Assignee set to Debbie Lockett
- Priority changed from High to Normal
I've created some JS2 unit tests to reproduce the bug, and test the issue. I'm actually also seeing some difference in behaviour here between XX SEFs (generated by Saxon-JS 2 on Node.js) and XJ SEFs (generated with Saxon-EE 10).
Test ixsl2/schedule21
reproduces the bug, and I get the same wrong results as reported with an XX SEF. Test ixsl/schedule25
tests the work around, which gives the correct results with an XX SEF. However, for both of these tests, with XJ SEFs I get a different run time error:
"Focus for . (dot) is absent"
The stack frame is pointing to the elabChild1
call inside assembleParams
.
I have also confirmed that the bug only seems to arise when using @http-request
with ixsl:schedule-action
, not when only using @document
or @wait
.
Updated by Debbie Lockett about 4 years ago
- Status changed from In Progress to Resolved
Rather than needing to copy the localVars
, there is an assembleParams
method which is supposed to handle this ("Assemble parameters for a template call using call-template, apply-templates, apply-imports, or next-match"). The problem was that we were only calling this from within the callback when @http-request
was used, after the context item had already been changed. (Recall that when using @http-request
, the HTTP response is supplied as the context item to the called template, in the form of an XPath map. Meanwhile for @wait
and @document
the context item is not changed.)
For @wait
and @document
, we were already calling assembleParams
earlier (i.e. not in their callbacks).
I have committed changes to call assembleParams
(and do other new context processing) earlier for @http-request
too. Then the callback in this case just changes the context and does the checkTemplateFocus
check.
The differences in the way the XJ and XX SEFs failed is just due to their internal differences; causing run time failures at slightly different parts of the assembleParams
code.
JS2 unit tests ixsl2/schedule20-25
tests also committed. These now pass.
Updated by Community Admin almost 4 years ago
- Applies to JS Branch 2 added
- Applies to JS Branch deleted (
2.0)
Updated by Debbie Lockett over 3 years ago
- Status changed from Resolved to Closed
- % Done changed from 0 to 100
- Fixed in JS Release set to Saxon-JS 2.1
Bug fix applied in the Saxon-JS 2.1 maintenance release.
Please register to edit this issue
Also available in: Atom PDF Tracking page