Skip to content

Commit

Permalink
Error on incompatible state value when resolving state (#4290)
Browse files Browse the repository at this point in the history
* Handle incompatible state value

* Changeset

* Fix

* Update packages/core/test/rehydration.test.ts

Co-authored-by: Mateusz Burzyński <[email protected]>

* Update .changeset/olive-sheep-fetch.md

Co-authored-by: Mateusz Burzyński <[email protected]>

* Update packages/core/test/rehydration.test.ts

Co-authored-by: Mateusz Burzyński <[email protected]>

---------

Co-authored-by: Mateusz Burzyński <[email protected]>
  • Loading branch information
davidkpiano and Andarist authored Feb 14, 2024
1 parent b5d40d8 commit 7a8796f
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/olive-sheep-fetch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'xstate': minor
---

An error will now be thrown if an incompatible state value is passed to `machine.resolveState({ value })`.
4 changes: 2 additions & 2 deletions examples/todomvc-react/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ You may run the example locally with:
pnpm run dev
```

__OR__
**OR**

[Open in CodeSandbox](https://codesandbox.io/p/sandbox/github/statelyai/xstate/tree/main/examples/todomvc-react)

__OR__
**OR**

[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/statelyai/xstate/tree/main/examples/todomvc-react)
8 changes: 7 additions & 1 deletion packages/core/src/stateUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,13 @@ export function getStateNodes<
TEvent extends EventObject
>(stateNode: AnyStateNode, stateValue: StateValue): Array<AnyStateNode> {
if (typeof stateValue === 'string') {
return [stateNode, stateNode.states[stateValue]];
const childStateNode = stateNode.states[stateValue];
if (!childStateNode) {
throw new Error(
`State '${stateValue}' does not exist on '${stateNode.id}'`
);
}
return [stateNode, childStateNode];
}

const childStateKeys = Object.keys(stateValue);
Expand Down
31 changes: 31 additions & 0 deletions packages/core/test/rehydration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,37 @@ describe('rehydration', () => {

expect(actual).toEqual([]);
});

it('should error on incompatible state value (shallow)', () => {
const machine = createMachine({
initial: 'valid',
states: {
valid: {}
}
});

expect(() => {
machine.resolveState({ value: 'invalid' });
}).toThrowError(/invalid/);
});

it('should error on incompatible state value (deep)', () => {
const machine = createMachine({
initial: 'parent',
states: {
parent: {
initial: 'valid',
states: {
valid: {}
}
}
}
});

expect(() => {
machine.resolveState({ value: { parent: 'invalid' } });
}).toThrowError(/invalid/);
});
});

it('should not replay actions when starting from a persisted state', () => {
Expand Down

0 comments on commit 7a8796f

Please sign in to comment.