diff --git a/packages/node_modules/overmind/src/statemachine.test.ts b/packages/node_modules/overmind/src/statemachine.test.ts index de9f40e3..4b8e1623 100644 --- a/packages/node_modules/overmind/src/statemachine.test.ts +++ b/packages/node_modules/overmind/src/statemachine.test.ts @@ -456,25 +456,40 @@ describe('Statemachine', () => { expect(() => overmind.actions.transition()).not.toThrow() }) - test('should deal with transition effects', async () => { + test('should dispose nested machines', async () => { type States = { current: 'FOO' } | { current: 'BAR', - number: number } - const state = statemachine({ + type ParentStates = { + current: 'FOO' + nested: typeof nested + } | { + current: 'BAR' + } + + const nested = statemachine({ + FOO: ['BAR'], + BAR: ['FOO'] + }, { + current: 'FOO' + }) + + const state = statemachine({ FOO: ['BAR'], BAR: ['FOO'] }, { current: 'FOO', + nested }) const transition: Action = ({ state }) => { - return state.transition('BAR', { number: 123 }, () => { - return Promise.resolve(4321) - }, (barState, value) => { - barState.number = value + state.matches('FOO', (fooState) => { + const ref = fooState.nested + state.transition('BAR', {}) + expect(fooState.nested).toBe(undefined) + expect(ref.current).toBe('FOO') }) } @@ -485,13 +500,12 @@ describe('Statemachine', () => { } } - interface Action extends IAction> {} + interface Action extends IAction {} const overmind = createOvermindMock(config) // @ts-ignore overmind.isStrict = true - await overmind.actions.transition() - expect(overmind.state.current === 'BAR' && overmind.state.number === 4321).toBe(true) + overmind.actions.transition() }) }) diff --git a/packages/node_modules/overmind/src/statemachine.ts b/packages/node_modules/overmind/src/statemachine.ts index 918837e2..f5d1fc5f 100644 --- a/packages/node_modules/overmind/src/statemachine.ts +++ b/packages/node_modules/overmind/src/statemachine.ts @@ -1,4 +1,4 @@ -import { PROXY_TREE, VALUE } from 'proxy-state-tree' +import { PROXY_TREE, VALUE, PATH } from 'proxy-state-tree' import { deepCopy } from './utils' import { IState } from '.' @@ -34,18 +34,15 @@ export interface MachineMethods(state: T | T[], cb: (current: Statemachine) => O): O; - transition( + transition( state: T, newState: States extends { current: T } ? Exact, {}> extends never ? Omit & Partial : Exact, {}> extends never ? Partial : { [NO_PROP]?: true} : never, effectsCallback?: ((current: Statemachine) => O), - stateCallback?: ((current: Statemachine, value: O extends Promise ? V : O) => O2) - ): O extends Promise ? Promise : O2; + } ? States : never>) => O) + ): O; } export type Statemachine = Base extends never ? State & MachineMethods : Base & State & MachineMethods @@ -56,15 +53,20 @@ const BASE = Symbol('BASE') const STATE = Symbol('STATE') const CURRENT_KEYS = Symbol('CURRENT_KEYS') const NO_PROP = Symbol('NO_PROP') +const IS_DISPOSED = Symbol('IS_DISPOSED') export class StateMachine { current: State["current"] private [INITIAL_STATE]: State["current"] private [STATE]: any private [BASE]: any + private [IS_DISPOSED] = false private clone() { return new StateMachine(this[TRANSITIONS], deepCopy(this[STATE]), deepCopy(this[BASE])) } + private dispose() { + this + } constructor(transitions: StatemachineTransitions, state: States, base: Base) { this[STATE] = state this[INITIAL_STATE] = state.current @@ -74,6 +76,13 @@ export class StateMachine { if (!baseKeys.includes(key)) { + if (this[key] instanceof StateMachine) { + this[key].dispose() + } delete this[key] } }) @@ -115,18 +134,6 @@ export class StateMachine { - if (this.current !== state) { - return value - } - tree.enableMutations() - const result = stateCallback(this, value) - tree.blockMutations() - return result - }) - } - return result } else if (process.env.NODE_ENV === 'development' && state !== this.current) { console.warn(`Overmind Statemachine - You tried to transition into "${state}", but it is not a valid transition. The valid transitions are ${JSON.stringify(transitions[this.current])}`)