Project

Profile

Help

Bug #4767

closed

xsl:with-param value evaluation in xsl:call-template in ixsl:schedule-action

Added by Martynas Jusevicius about 4 years ago. Updated almost 4 years ago.

Status:
Closed
Priority:
Normal
Category:
IXSL extensions
Sprint/Milestone:
-
Start date:
2020-09-29
Due date:
% Done:

100%

Estimated time:
Applies to JS Branch:
2
Fix Committed on JS Branch:
2
Fixed in JS Release:
SEF Generated with:
Platforms:
Company:
-
Contact person:
-
Additional contact persons:
-

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/

Actions #1

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.

Actions #2

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.

Actions #3

Updated by Martynas Jusevicius about 4 years ago

Thank you Michael, I can confirm the workaround works.

Actions #4

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.

Actions #5

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.

Actions #6

Updated by Community Admin almost 4 years ago

  • Applies to JS Branch 2 added
  • Applies to JS Branch deleted (2.0)
Actions #7

Updated by Debbie Lockett almost 4 years ago

  • Fix Committed on JS Branch 2 added
Actions #8

Updated by Debbie Lockett almost 4 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