This is an automated email from the ASF dual-hosted git repository.
stevedlawrence pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil.git
The following commit(s) were added to refs/heads/main by this push:
new edee1e2e1 Convert NodeInfo.Nothing from a lazy val to an object
edee1e2e1 is described below
commit edee1e2e1a609194110f0e6f87e91decd6f0cbab
Author: Steve Lawrence <[email protected]>
AuthorDate: Fri Apr 17 12:34:58 2026 -0400
Convert NodeInfo.Nothing from a lazy val to an object
The NodeInfo.Nothing instance has a `children` Delay member that never
actually gets evaluated. This is fine and not unexpected since Nothing
doesn't really have children and so nothing ever attempts to access or
need the member.
However, in some cases it is possible for the Nothing val to be
referenced in a serialized class (e.g. in a DPath expression object that
stores argument types such as fn:round-half-to-even) when creating a
saved parser. And because this Nothing has a Delay that is never
evaluated, it leads to an "object not initialized" exception, preventing
creating a saved parser.
To fix this issue, this changes NodeInfo.Nothing from a lazy val to an
object. Whether we use a lazy val or an object here really does not make
a difference with how we use it, but in Scala lazy vals are serialized
while objects are not--Scala only serializes object names which are used
to look up and return the singleton instance during deserialization.
This allows us to avoid all possible serialization issues, and also
changes Nothing to match the same pattern as all the other TypeNodes.
DAFFODIL-3079
---
.../apache/daffodil/runtime1/dpath/NodeInfo.scala | 49 ++++++++++++----------
.../calc_value_properties/outputValueCalc.tdml | 29 +++++++++++++
.../TestOutputValueCalc.scala | 1 +
3 files changed, 57 insertions(+), 22 deletions(-)
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/dpath/NodeInfo.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/dpath/NodeInfo.scala
index fef41e7a6..d49e416cd 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/dpath/NodeInfo.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/dpath/NodeInfo.scala
@@ -297,29 +297,32 @@ object NodeInfo extends Enum {
/**
* Nothing is the bottom of the type lattice.
*
- * It is the return type of the dfdlx:error() function. It's a subtype of
+ * It is the return type of the fn:error() function. It's a subtype of
* every type (except some special singletons like ArrayType).
*/
- lazy val Nothing = new TypeNode(
- Seq(
- Boolean,
- Complex,
- Array,
- ArrayIndex,
- Double,
- Float,
- Date,
- Time,
- DateTime,
- UnsignedByte,
- Byte,
- HexBinary,
- AnyURI,
- String,
- NonEmptyString
- ),
- Nil
- ) with Boolean.Kind
+ protected sealed trait NothingKind extends NodeInfo.Kind
+ case object Nothing
+ extends TypeNode(
+ Seq(
+ Boolean,
+ Complex,
+ Array,
+ ArrayIndex,
+ Double,
+ Float,
+ Date,
+ Time,
+ DateTime,
+ UnsignedByte,
+ Byte,
+ HexBinary,
+ AnyURI,
+ String,
+ NonEmptyString
+ ),
+ Nil
+ )
+ with Boolean.Kind
with Complex.Kind
with Array.Kind
with ArrayIndex.Kind
@@ -332,7 +335,9 @@ object NodeInfo extends Enum {
with Byte.Kind
with HexBinary.Kind
with NonEmptyString.Kind
- with AnyURI.Kind
+ with AnyURI.Kind {
+ sealed trait Kind extends NothingKind
+ }
/**
* All complex types are represented by this one type object.
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section17/calc_value_properties/outputValueCalc.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section17/calc_value_properties/outputValueCalc.tdml
index a379d3a3c..c15cb3118 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/section17/calc_value_properties/outputValueCalc.tdml
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section17/calc_value_properties/outputValueCalc.tdml
@@ -315,6 +315,15 @@
</xs:complexType>
</xs:element>
+ <xs:element name="err_05">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="err1" type="xs:string"
+
dfdl:outputValueCalc="{fn:round-half-to-even(fn:error('This is the error
string'))}" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
<xs:element name="refSimpleElementWithOvc">
<xs:complexType>
<xs:sequence>
@@ -766,6 +775,26 @@
</tdml:unparserTestCase>
+ <tdml:unparserTestCase name="errorInRoundHalfToEven"
+ root="err_05" model="outputValueCalc-Embedded.dfdl.xsd"
+ description="Calling fn:error() inside fn:round-half-to-even()">
+ <tdml:infoset>
+ <tdml:dfdlInfoset
xmlns:xs="http://www.w3.org/2001/XMLSchema"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <ex:err_05>
+ <err1>a</err1>
+ </ex:err_05>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document />
+
+ <tdml:errors>
+ <tdml:error>Unparse Error</tdml:error>
+ <tdml:error>This is the error string</tdml:error>
+ </tdml:errors>
+
+ </tdml:unparserTestCase>
+
<tdml:unparserTestCase name="refSimpleTypeElemWithOvc"
root="refSimpleElementWithOvc" model="outputValueCalc-Embedded.dfdl.xsd"
description="An element referencing a simpleType Elem with an OVC"
roundTrip="false">
diff --git
a/daffodil-test/src/test/scala/org/apache/daffodil/section17/calc_value_properties/TestOutputValueCalc.scala
b/daffodil-test/src/test/scala/org/apache/daffodil/section17/calc_value_properties/TestOutputValueCalc.scala
index d6387d96b..a0ec423f7 100644
---
a/daffodil-test/src/test/scala/org/apache/daffodil/section17/calc_value_properties/TestOutputValueCalc.scala
+++
b/daffodil-test/src/test/scala/org/apache/daffodil/section17/calc_value_properties/TestOutputValueCalc.scala
@@ -58,6 +58,7 @@ class TestOutputValueCalc1 extends TdmlTests {
@Test def errorOneArg = test
@Test def errorTwoArg = test
@Test def errorThreeArg = test
+ @Test def errorInRoundHalfToEven = test
// DAFFODIL-1701
@Test def refSimpleTypeElemWithOvc = test