Bug #5046
closedHandling null and undefined objects in ixsl:get() and ixsl:set-property
100%
Description
(Having already spent lots of time working on this, it's time to try to get the issues in writing.)
We need to clarify how null
and undefined
JavaScript objects are handled within ixsl:get()
and ixsl:set-property
. Both the code and documentation need work.
Currently the documentation for ixsl:get()
says:
If the specified object or property does not exist, then the function returns the empty sequence (with a console log warning in the latter case). (Note the difference to the similar function
ixsl:call()
, for which a run-time error is raised in this case.)
While for ixsl:set-property
:
An error will be raised at run-time if the specified object does not exist or is not unique. If the specified property does not exist, then there is no error, but a warning is output in the console log.
Note that the property name string supplied to ixsl:get()
and ixsl:set-property
can be a dot separated list of names to access a nested property; but we are not clear about what happens when we encounter null or undefined objects in such a nested chain of objects.
For instance consider ixsl:get($object, 'a.b.c')
and <ixsl:set-property object="$object" name="a.b.c" select="'value'"/>
. What happens if in JavaScript $object.a
or $object.a.b
returns null or undefined? Currently if either of these is null, Saxon-JS 2.2 crashes with an uncaught TypeError, so there is definitely a bug here.
Updated by Debbie Lockett over 3 years ago
The proposed solution is that we should throw an error if we ever attempt to get a property of null or undefined. This is indeed what happens in JavaScript. So if at any point prior to the last step, while stepping down a chain of nested properties, we encounter null or undefined as the property value, then we should in fact throw an error.
However it would then be inconsistent not to throw an error if the initial object is null or undefined; i.e. ixsl:get($object, 'prop')
should throw an error if $object
is null or undefined. This would be a change in behaviour for Saxon-JS, which could potentially cause problems from unexpected errors in existing applications.
Note that we did previously look into what to do in this case (see Bug #3501: Error when object supplied to ixsl:get() is null), but it now seems that that solution was not fully thought through. At that time we decided that it would make sense for ixsl:get($object, 'prop')
to return the empty sequence when $object
is null; so that we get the same result as when using the lookup operator: $object?prop
. Note that by the XPath specification, ()?prop
always returns the empty sequence.
However, we subsequently clarified that ixsl:get($object, 'prop')
and $object?prop
are not always equivalent; see
https://www.saxonica.com/saxon-js/documentation/index.html#!development/properties:
In order to use this
$object?propName
shorthand, the JavaScript object must be converted using "weak" conversion (as described in JavaScript to XDM Conversion), and must not be of a more specific type which is recognised (i.e. the object is not any of the following: null, undefined, String, Number, Boolean, Date, Node, Array, or Function). So that$object
is treated as a JSValue wrapped external object.
And this specifically points out that you may not get the same result for null or undefined objects!
Updated by Debbie Lockett over 3 years ago
If we amend the definition of ixsl:get()
to say that the supplied object must exist (i.e. not be null or undefined in JavaScript), then this brings the function better in line with ixsl:call
, ixsl:contains()
and ixsl:set-property
, for which we already specify that the supplied object must exist. We should update the function signature to reflect this to provide the correct cardinality check - which means a change in IXSLFunctionSet.java
for Saxon on Java, and in lib/xpath/xsltData.js
for the XX compiler.
Updated by Debbie Lockett over 3 years ago
Committed:
- Saxon-JS code changes (in ExtraFn.js and lib/xpath/xsltData.js)
- New selenium browser tests: ixsl/get20; ixsl2/getlookup20, getlookup20b
- Updated results for tests ixsl/getEmpty01, getEmpty02, getEmpty04
These now all align with the proposed solution above.
I have not yet done the following:
- Commit update to IXSLFunctionSet.java for Saxon on Java
- Documentation updates
Updated by Debbie Lockett over 3 years ago
- Status changed from New to Resolved
- Fix Committed on JS Branch 2 added
Documentation updates committed.
Update to IXSLFunctionSet.java for Saxon on Java committed on saxon10 and saxondev branches.
Updated by Debbie Lockett over 3 years ago
- Status changed from Resolved to In Progress
Reopened because the new logic (that we should always throw an error if we ever attempt to get a property of null or undefined; in particular when accessing nested properties) is also relevant to ixsl:contains()
, ixsl:call()
and ixsl:remove-property
.
Updated by Debbie Lockett over 3 years ago
- Status changed from In Progress to Resolved
New logic also applied for ixsl:call()
, ixsl:contains()
, and ixsl:remove-property
; so marking resolved again.
Committed:
- New selenium browser tests: ixsl/call20, ixsl/contains20, ixsl/removeProperty20
- Saxon-JS code changes (in ExtraFn.js)
- Further documentation updates
Updated by Debbie Lockett over 3 years ago
- % Done changed from 0 to 100
- Fixed in JS Release set to Saxon-JS 2.3
Bug fix applied in the Saxon-JS 2.3 maintenance release.
Updated by Debbie Lockett over 3 years ago
- Status changed from Resolved to Closed
Please register to edit this issue
Also available in: Atom PDF Tracking page