Skip to content

Commit

Permalink
Call exit handlers when service gets stopped
Browse files Browse the repository at this point in the history
  • Loading branch information
Andarist committed Nov 25, 2020
1 parent 326b28d commit 02c7635
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/sour-carrots-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'xstate': patch
---

Exit actions will now be properly called when a service gets canceled by calling its `stop` method.
14 changes: 7 additions & 7 deletions packages/core/src/interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ export class Interpreter<
this.exec(action, state, actionsConfig);
}
}

private update(
state: State<TContext, TEvent, TStateSchema, TTypestate>,
_event: SCXML.Event<TEvent>
Expand Down Expand Up @@ -281,13 +282,6 @@ export class Interpreter<
const isDone = isInFinalState(state.configuration || [], this.machine);

if (this.state.configuration && isDone) {
// exit interpreter procedure: https://www.w3.org/TR/scxml/#exitInterpreter
this.state.configuration.forEach((stateNode) => {
for (const action of stateNode.definition.exit) {
this.exec(action, state);
}
});

// get final child state node
const finalChildStateNode = state.configuration.find(
(sn) => sn.type === 'final' && sn.parent === this.machine
Expand Down Expand Up @@ -502,6 +496,12 @@ export class Interpreter<
this.doneListeners.delete(listener);
}

this.state.configuration.forEach((stateNode) => {
for (const action of stateNode.definition.exit) {
this.exec(action, this.state);
}
});

// Stop all children
this.children.forEach((child) => {
if (isFunction(child.stop)) {
Expand Down
25 changes: 25 additions & 0 deletions packages/core/test/actions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1396,6 +1396,31 @@ describe('choose', () => {
})
.start();
});

it('exit actions should be called when stopping a machine', () => {
let exitCalled = false;
let childExitCalled = false;

const machine = Machine({
exit: () => {
exitCalled = true;
},
initial: 'a',
states: {
a: {
exit: () => {
childExitCalled = true;
}
}
}
});

const service = interpret(machine).start();
service.stop();

expect(exitCalled).toBeTruthy();
expect(childExitCalled).toBeTruthy();
});
});

describe('sendParent', () => {
Expand Down

0 comments on commit 02c7635

Please sign in to comment.