fix: Prevent transitions from final states within parallel regions#5463
fix: Prevent transitions from final states within parallel regions#5463kaigritun wants to merge 1 commit intostatelyai:mainfrom
Conversation
Final states are terminal by definition and should not allow outgoing transitions. Previously, events sent to a final state within a parallel region could incorrectly trigger transitions. This fix ensures that StateNode.next() returns undefined for final states, preventing any transitions from occurring. Fixes statelyai#5460
🦋 Changeset detectedLatest commit: 2f65365 The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
@Andarist Should this be a minor or patch? |
|
Patch — this is a bugfix for incorrect behavior (transitions from final states in parallel regions shouldn't be allowed per the SCXML spec). No new features or breaking changes. |
| const actor = createActor(machine); | ||
| actor.start(); | ||
|
|
||
| // Move first region to final state | ||
| actor.send({ type: 'NEXT' }); | ||
| expect(actor.getSnapshot().value).toEqual({ | ||
| first: 'done', | ||
| second: 'a' | ||
| }); |
There was a problem hiding this comment.
What's the value of this assertion here? this surely has to be tested elsewhere already - this doesn't tell us anything about the behavior described in the test's title
|
You're right - that assertion doesn't demonstrate the blocked transition behavior. I'll update the test to:
Will push an update shortly. |
Are we sure about this?
|
|
Good point on the spec reference. Looking at it more carefully: The SCXML spec does define final states as atomic, but also says in 3.7
So the key distinction is:
The current xstate behavior in the issue (#5460) shows a final state transitioning to a sibling, which violates the "no outgoing transitions" rule. Happy to adjust the PR description/comments if this interpretation is correct, or close if you think the current behavior is actually spec-compliant. |
|
I agree with your interpretation. The spec has some inconsistencies, but the allowed children of I wonder though if we shouldnt handle this early, for example in |
|
Thanks for confirming! Good points on both:
I'll push an updated implementation. Should I keep this as a single PR or would you prefer the additional validation as a separate PR? |
Summary
This PR fixes #5460 where parallel states with
type: 'final'child states incorrectly allowed transitions from those final states.The Problem
According to SCXML semantics, final states are terminal and should not allow outgoing transitions. However, in xstate v5, when a child state under a parallel state has
type: 'final'set, it could still transition away to other sibling nodes.The Fix
Added a check in
StateNode.next()to immediately returnundefinedif the state node is of type'final'. This ensures that:Changes
next()method for final statesTesting
The fix has been tested with:
parallel.test.tstests passingfinal.test.tstests passing