Bug #5656
closedXDM array is not converted to a true JS array?
100%
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' ])"/>
Related issues
Updated by Michael Kay over 2 years 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 over 2 years ago
Hmm, okay. Any workarounds for this then?
Updated by Michael Kay over 2 years 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 over 2 years 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 over 2 years ago
- Sprint/Milestone set to SaxonJS 2.5
Updated by Norm Tovey-Walsh over 2 years 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 2 years 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.
Updated by Debbie Lockett 5 months ago
- Related to Bug #4815: Conversion of XDM maps to JS objects added
Updated by Debbie Lockett 5 months ago
- Status changed from New to Resolved
- Assignee set to Debbie Lockett
- Applies to JS Branch 2, Trunk added
- Fix Committed on JS Branch Trunk added
For SaxonJS 3, a number of improvements have been made to make it easier for users to work directly with JavaScript objects inside XSLT, and avoid the usual SaxonJS type conversions between JavaScript and XDM.
The new IXSL functions ixsl:json-parse()
and ixsl:new()
are added to create JavaScript objects, where (by default) the result is not converted to XDM, it is just returned as a JSValue-wrapped object.
A new $options
argument is added for ixsl:apply()
, ixsl:call()
, ixsl:eval()
, and ixsl:get()
, which is an XDM map which can be used to control (enable or disable) XDM to JS conversion of the supplied arguments (as applicable), and JS to XDM conversion of the result. The new ixsl:json-parse()
and ixsl:new()
functions also have an $options
argument.
I believe these changes will make it possible to solve the coding problems raised in this issue.
Updated by Debbie Lockett 8 days ago
- Status changed from Resolved to Closed
- % Done changed from 0 to 100
- Fixed in JS Release set to SaxonJS 3.0
Bug fix applied in the SaxonJS 3.0.0-beta1 preview release.
Please register to edit this issue
Also available in: Atom PDF Tracking page