Bug #5656
open
XDM array is not converted to a true JS array?
0%
Description
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' ])"/>
Updated by Michael Kay about 1 year ago
The specification of ixsl:call
at https://www.saxonica.com/saxon-js/documentation2/index.html#!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
.
Updated by Martynas Jusevicius about 1 year ago
Hmm, okay. Any workarounds for this then?
Updated by Michael Kay about 1 year 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.
Updated by Martynas Jusevicius about 1 year 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.
Updated by Norm Tovey-Walsh about 1 year ago
- Sprint/Milestone set to SaxonJS 2.5
Updated by Norm Tovey-Walsh about 1 year 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.
Updated by Norm Tovey-Walsh about 1 year 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