Project

Profile

Help

Bug #4686

closed

XSLT 3 using fold-left fails in Saxon-JS 2 with error Expected mode, found function

Added by Martin Honnen over 4 years ago. Updated almost 4 years ago.

Status:
Closed
Priority:
Low
Category:
XSLT Conformance
Sprint/Milestone:
-
Start date:
2020-08-15
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

An XSLT 3 stylesheet that works fine with Saxon HE 10.1 Java gives an error "Expected mode, found function" on execution with Saxon-JS 2 (run with xslt3 -s:sample1.xml -xsl:fold-left1.xsl):

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="3.0"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    xmlns:mf="http://example.com/mf"
    expand-text="yes">
    
    <xsl:function name="mf:wrap" as="node()*">
        <xsl:param name="nodes" as="node()*"/>
        <xsl:param name="tag" as="xs:string"/>
        <xsl:for-each-group select="$nodes" group-starting-with="e[@tag = $tag]">
            <xsl:choose>
                <xsl:when test="not(self::e[@tag = $tag])">
                    <xsl:apply-templates select="current-group()"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:for-each-group select="tail(current-group())" group-ending-with="e[@tag = '/' || $tag]">
                        <xsl:choose>
                            <xsl:when test="current-group()[last()][self::e][@tag = '/' || $tag]">
                                <xsl:element name="{$tag}">
                                    <xsl:apply-templates select="current-group()[position() lt last()]"/>
                                </xsl:element>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:apply-templates select="current-group()"/>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:for-each-group>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:function>
    
    <xsl:function name="mf:wrap" as="node()*">
        <xsl:param name="nodes" as="node()*"/>
        <xsl:sequence
            select="fold-left(distinct-values($nodes[self::e/@tag[not(starts-with(., '/'))]]/@tag), $nodes, mf:wrap#2)"/>
    </xsl:function>
    
    <xsl:mode on-no-match="shallow-copy"/>
    
    <xsl:template match="*[e[@tag]]">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:sequence select="mf:wrap(node())"/>
        </xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>

Example input sample:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas facilisis diam ac mi molestie faucibus. <e tag="b"/>Nulla facilisi<e tag="/b"/>. Ut molestie metus arcu, ut vestibulum dolor dignissim ut. <e tag="b"/>Cras tempor tortor libero, <e tag="i"/>non pretium ipsum efficitur vitae. Nulla facilisi. Sed maximus varius purus, in egestas justo<e tag="/i"/>. Nam eleifend metus vel odio rutrum auctor<e tag="/b"/>. Proin scelerisque purus pellentesque, congue quam quis, interdum lectus. Fusce accumsan sapien non turpis scelerisque, vel efficitur ligula rhoncus.</paragraph>
    <paragraph>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas facilisis diam ac mi molestie faucibus. <e tag="i"/>Nulla facilisi<e tag="/i"/>. Ut molestie metus arcu, ut vestibulum dolor dignissim ut. <e tag="b"/>Cras tempor tortor libero, <e tag="i"/>non pretium ipsum efficitur vitae. Nulla facilisi. Sed maximus varius purus, in egestas justo<e tag="/i"/>. Nam eleifend metus vel odio rutrum auctor<e tag="/b"/>. Proin scelerisque purus pellentesque, congue quam quis, interdum lectus. Fusce accumsan sapien non turpis scelerisque, vel efficitur ligula rhoncus.</paragraph>
</root>

Error:

<?xml version="1.0" encoding="UTF-8"?><root>
    Internal error: Expected mode, found function
Error
    at Object.a [as internalError] (C:\Users\marti\AppData\Roaming\npm\node_modules\xslt3\node_modules\saxon-js\SaxonJS2N.js:26:474)
    at Object.I [as getTargetComponent] (C:\Users\marti\AppData\Roaming\npm\node_modules\xslt3\node_modules\saxon-js\SaxonJS2N.js:686:120)
    at Array.<anonymous> (C:\Users\marti\AppData\Roaming\npm\node_modules\xslt3\node_modules\saxon-js\SaxonJS2N.js:386:157)
    at C:\Users\marti\AppData\Roaming\npm\node_modules\xslt3\node_modules\saxon-js\SaxonJS2N.js:389:125
    at C:\Users\marti\AppData\Roaming\npm\node_modules\xslt3\node_modules\saxon-js\SaxonJS2N.js:400:140
    at Object.push (C:\Users\marti\AppData\Roaming\npm\node_modules\xslt3\node_modules\saxon-js\SaxonJS2N.js:406:435)
    at C:\Users\marti\AppData\Roaming\npm\node_modules\xslt3\node_modules\saxon-js\SaxonJS2N.js:689:107
    at C:\Users\marti\AppData\Roaming\npm\node_modules\xslt3\node_modules\saxon-js\SaxonJS2N.js:787:421

[snip long stack trace]

Transformation failure: Error SXJS0004 at fold-left1.xsl#12
    Internal error: Expected mode, found function
Transformation failed: Error SXJS0004 at fold-left1.xsl#12
    Internal error: Expected mode, found function

Files

sample1.xml (1.22 KB) sample1.xml Martin Honnen, 2020-08-15 15:47
fold-left1.xsl (2.05 KB) fold-left1.xsl Martin Honnen, 2020-08-15 15:47
Actions #1

Updated by Debbie Lockett over 4 years ago

  • Assignee set to Debbie Lockett

Thanks for reporting the bug. I have run the supplied test, and can confirm the error. I've also run with a Saxon-EE compiled SEF, which produces the same error, so it does look like a run time (rather than compiler) error.

Actions #2

Updated by John Lumley about 4 years ago

It appears that the current component at the time of the apply-templates invocation in mf:wrap (i.e. the component holding mf:wrap) doesn't have the correct binding vector, which is correct in the compiler SEF. The binding vector should be [2] (pointing to the mode), but appears at execution to be [0], hence pointing to the function. Will investigate further.

Actions #3

Updated by John Lumley about 4 years ago

  • Status changed from New to Resolved

The issue involves the evaluation context for a NamedUserFunction (i.e. a reference, a subclass of XdmFunction), which was not setting the context.currentComponent to the component defining the function. In the test case it happened that the context.currentComponent for the evaluation of mf:wrap#2 contained a function (that holding mf:wrap#1), but wasn't the right one, and thus had the wrong binding vector. A simple addition of

c2.currentComponent = this.component;

in NamedUserFunction.evaluate() seems to work.

Actions #4

Updated by John Lumley about 4 years ago

  • Status changed from Resolved to In Progress
Actions #5

Updated by Michael Kay about 4 years ago

Test case higher-order-functions-076 added to XSLT3 test suite; confirmed that it passes under Saxon-J and crashes under Saxon-JS.

Actions #6

Updated by Debbie Lockett about 4 years ago

  • Status changed from In Progress to Resolved
  • Fix Committed on JS Branch 2.0 added

Committed suggested fix in evaluation context for NamedUserFunction. The new test higher-order-functions-076 now passes.

Actions #7

Updated by Community Admin almost 4 years ago

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

Updated by Community Admin almost 4 years ago

  • Fix Committed on JS Branch 2 added
  • Fix Committed on JS Branch deleted (2.0)
Actions #9

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