Skip to content

Commit

Permalink
Fixed an issue with invoked service not being correctly started
Browse files Browse the repository at this point in the history
  • Loading branch information
Andarist committed May 13, 2020
1 parent b967db6 commit 326db72
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/great-toes-vanish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'xstate': patch
---

Fixed an issue with invoked service not being correctly started if other service got stopped in a subsequent microstep (in response to raised or null event).
9 changes: 4 additions & 5 deletions packages/core/src/StateNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1127,12 +1127,11 @@ class StateNode<
const activities = currentState ? { ...currentState.activities } : {};
for (const action of actions) {
if (action.type === actionTypes.start) {
activities[action.activity!.type] = action as ActivityDefinition<
TContext,
TEvent
>;
activities[
action.activity!.id || action.activity!.type
] = action as ActivityDefinition<TContext, TEvent>;
} else if (action.type === actionTypes.stop) {
activities[action.activity!.type] = false;
activities[action.activity!.id || action.activity!.type] = false;
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,7 @@ export class Interpreter<
// If the activity will be stopped right after it's started
// (such as in transient states)
// don't bother starting the activity.
if (!this.state.activities[activity.type]) {
if (!this.state.activities[activity.id || activity.type]) {
break;
}

Expand Down
67 changes: 64 additions & 3 deletions packages/core/test/invoke.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import {
sendParent,
send,
EventObject,
StateValue
StateValue,
createMachine
} from '../src';
import {
actionTypes,
done as _done,
doneInvoke,
escalate
escalate,
raise
} from '../src/actions';
import { interval } from 'rxjs';
import { map, take } from 'rxjs/operators';
Expand Down Expand Up @@ -2177,7 +2179,7 @@ describe('invoke', () => {
service.start();
});

it('should not invoke a service if transient', (done) => {
it('should not invoke a service if it gets stopped immediately by transitioning away in microstep', (done) => {
// Since an invocation will be canceled when the state machine leaves the
// invoking state, it does not make sense to start an invocation in a state
// that will be exited immediately
Expand Down Expand Up @@ -2215,6 +2217,65 @@ describe('invoke', () => {
})
.start();
});

it('should invoke a service if other service gets stopped in subsequent microstep (#1180)', (done) => {
const machine = createMachine({
initial: 'running',
states: {
running: {
type: 'parallel',
states: {
one: {
initial: 'active',
on: {
STOP_ONE: '.idle'
},
states: {
idle: {},
active: {
invoke: {
id: 'active',
src: () => () => {}
},
on: {
NEXT: {
actions: raise('STOP_ONE')
}
}
}
}
},
two: {
initial: 'idle',
on: {
NEXT: '.active'
},
states: {
idle: {},
active: {
invoke: {
id: 'post',
src: () => Promise.resolve(42),
onDone: '#done'
}
}
}
}
}
},
done: {
id: 'done',
type: 'final'
}
}
});

const service = interpret(machine)
.onDone(() => done())
.start();

service.send('NEXT');
});
});

describe('error handling', () => {
Expand Down

0 comments on commit 326db72

Please sign in to comment.