Bug #5656


XDM array is not converted to a true JS array?

Added by Martynas Jusevicius 3 months ago. Updated 2 months ago.

IXSL extensions
Start date:
Due date:
% Done:


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


According to XDM to JavaScript Conversion array(*) should be converted to a JS array.

However this code:

<xsl:variable name="array" select="[ 'a' ]" as="array(*)"/>
<xsl:sequence select="ixsl:call($array, 'push', [ 'b' ])"/>

gives error:

ixsl:call: object method 'push' not found

Same error for this code (note that @as is absent here):

<xsl:variable name="array" select="js:Array([ 'a' ])"/>
<xsl:sequence select="ixsl:call($array, 'push', [ 'b' ])"/>
Actions #1

Updated by Michael Kay 3 months ago

The specification of ixsl:call at!ixsl-extension/functions/call says

See Type Conversion for details on how the supplied parameters in $arguments are converted from XDM to JavaScript, and how any returned JavaScript objects are converted to XDM.

I believe that no conversion is applied to the $object and $method arguments of ixsl:call, only to the values supplied in $arguments.

Actions #2

Updated by Martynas Jusevicius 3 months ago

Hmm, okay. Any workarounds for this then?

Actions #3

Updated by Michael Kay 3 months ago

It rather depends on what you are trying to achieve, which isn't clear. What's wrong with array:append()?

I would discourage any attempt to modify an XDM array in-situ. Saxon is going to assume that the contents of a variable remain unchanged once bound, and any attempt to subvert that is going to have very unpredictable consequences. I think that the conversion rules mean you'll normally get a copy of the array anyway.

Actions #4

Updated by Martynas Jusevicius 3 months ago

There is still something weird going on, if not with array conversion then with ixsl:set-property in combination with arrays.

<xsl:variable name="js-array" select="ixsl:eval('Array(1, 2)')"/>
<xsl:value-of select="ixsl:call(ixsl:get(ixsl:window(), 'Array'), 'isArray', [ $js-array ])"/> <!-- true -->
<xsl:value-of select="ixsl:call(ixsl:get(ixsl:window(), 'JSON'), 'stringify', [ $js-array ])"/> <!-- [1, 2] -->

<ixsl:set-property name="prop" select="$js-array"/>
<xsl:value-of select="ixsl:call(ixsl:get(ixsl:window(), 'Array'), 'isArray', [ ixsl:get(ixsl:window(), 'prop') ])"/> <!-- false -->
<xsl:value-of select="ixsl:call(ixsl:get(ixsl:window(), 'JSON'), 'stringify', [ ixsl:get(ixsl:window(), 'prop') ])"/> <!-- 1 -->

This test case shows that $js-array is an array as expected, but after it's been set as the value of window.prop, it's not an array anymore.

Actions #5

Updated by Norm Tovey-Walsh 3 months ago

  • Sprint/Milestone set to SaxonJS 2.5
Actions #7

Updated by Norm Tovey-Walsh 3 months ago

I think Mike is right about the attempt to call push on an XDM array. The first argument to ixsl:call is expected to be a (native) JavaScript object.

The ixsl:set-property problem is trickier. It feels like that should work, and I have managed to make it work, but I'm not sure I like my workaround.

Actions #8

Updated by Norm Tovey-Walsh 2 months ago

  • Sprint/Milestone changed from SaxonJS 2.5 to SaxonJS 3.0
  • Applies to JS Branch deleted (2)

The "problem" here is that the type conversion rules apply to the return value of ixsl:get. So when you get the JavaScript array, it's converted into an XDM array, and then it isn't a JSON array anymore.

I don't think we can fix this in 2.x. What we need is a new function, ixsl:get-javascript or ixsl:get-raw or ixsl:get-unconverted or something (or an additional, optional argument on ixsl:get perhaps) that returns the value without type conversion. Then what you'd get back is a JavaScript object and it would still be an array.

Please register to edit this issue

Also available in: Atom PDF Tracking page