Bug #4293

Streamability of accumulator-after in select expression of accumulator-rule with phase=end

Added by Michael Kay 6 months ago. Updated 6 months ago.

Start date:
Due date:
% Done:


Legacy ID:
Applies to branch:
9.9, trunk
Fix Committed on Branch:
9.9, trunk
Fixed in Maintenance Release:


#1 Updated by Michael Kay 6 months ago

  • Status changed from New to In Progress

Added to XSLT3 test suite as accumulator-077s.

#2 Updated by Michael Kay 6 months ago

We need to implement the rule

If the function call [on fn:accumulator-after()] is contained in the select expression or contained sequence constructor of an xsl:accumulator-rule specifying phase="end", then it is motionless.

The challenge is: at the point we assess the streamability of the call on accumulator-after(), how do we know this condition is true?

Searching up the expression tree doesn't work, because this only takes us up to the outermost containing expression or instruction, it doesn't tell us where in the stylesheet that expression or instruction occurs.

We could perhaps wrap the select expression or sequence constructor of an accumulator rule in a new kind of PseudoExpression at the root of the expression tree, existing purely for this purpose.

Alternatively we could add information to the ContextItemStaticInfoEE that we pass down the tree as we evaluate streamability. This seems a cleaner solution.

#3 Updated by Michael Kay 6 months ago

  • Applies to branch 9.9, trunk added
  • Fix Committed on Branch 9.9, trunk added

Added information to ContextItemStaticInfoEE to indicate whether we are evaluating the streamability of an accumulator rule, and if so whether the phase is START or END; this information is set during XSLAccumulator.checkRuleStreamability(), and is read during Streamability.computeAccumulatorAfterSweep().

Test now passing.

#4 Updated by Michael Kay 6 months ago

I also took the opportunity to review various TODO messages pointing out that the spec no longer defines an error XTDE3420, though there are various places in the code that throw this error.

The first of these is in AccumulatorRegistryEE.getStreamingAccumulatorValue(), which calls AccumulatorWatch.isDonePostDescent(). I think this check never fires simply because we now have static rules that ensure that the situation cannot arise.

The other two are within Inversion.invertChildExpression() and Inversion.processChildExpression(), both called during static streamability analysis. These both look for calls on accumulator-after() within a motionless expression; but under the revised design, a call on accumulator-after() that is not preceded by a consuming expression is itself deemed consuming, so the containing expressions are by definition not motionless; therefore we can never go down this path.

I will leave well alone on the 9.9 branch, but on the development branch I will remove the tests for conditions that can never be satisfied.

#5 Updated by Michael Kay 6 months ago

  • Status changed from In Progress to Resolved

#6 Updated by O'Neil Delpratt 6 months ago

  • Status changed from Resolved to Closed
  • % Done changed from 0 to 100
  • Fixed in Maintenance Release added

Bug fix applied in the Saxon maintenance release.

Please register to edit this issue

Also available in: Atom PDF