-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[core] Event emitter #4746
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
[core] Event emitter #4746
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
bd67a8d
Add basic event emitter
davidkpiano 0bfb107
Merge branch 'main' into davidkpiano/event-emitter
davidkpiano 177b5af
Remove id and delay
davidkpiano eb6219d
Fix types
davidkpiano f3b4420
Rename
davidkpiano cb3d527
Add machine types
davidkpiano 488e5f6
Add TEmitted type... everywhere
davidkpiano 10e379b
Avoid upsetting devs who rely on order of ActorLogic<…> generics
davidkpiano 1776853
Same for ActorScope<…>
davidkpiano e53bc8e
Update packages/core/src/actions/emit.ts
davidkpiano 906ecea
Update packages/core/src/actions/emit.ts
davidkpiano 631531c
Update packages/core/src/State.ts
davidkpiano e21516f
Update packages/core/src/actions/emit.ts
davidkpiano b921e0c
Update packages/core/src/actions/emit.ts
davidkpiano a6f25c2
Update packages/core/src/actions/emit.ts
davidkpiano 4ea771a
Update packages/core/test/types.test.ts
davidkpiano d9f2adf
Update packages/core/src/createMachine.ts
davidkpiano b371646
Update packages/core/src/actions/emit.ts
davidkpiano 438aa35
Fix TS error
davidkpiano 486bb19
Add emit to enqueueActions
davidkpiano 6c450c2
Add default
davidkpiano 6744bd7
Wrap handler
davidkpiano de00cb0
Check for errors
davidkpiano 9d3cc49
Add changeset
davidkpiano caeec03
Types
davidkpiano 035c78d
Merge branch 'main' into davidkpiano/event-emitter
davidkpiano f7326fb
small tweaks
Andarist af70340
fix types
Andarist 50bbddf
tweak things
Andarist 82fa0bd
fix small issues around listeners management
Andarist 911def1
rename stuff
Andarist 193f513
tighten up one default
Andarist 8a3cb25
remove unused type
Andarist 343c852
fixed `MachineImplementationsActions`
Andarist 497d25f
No need for defer
davidkpiano dbc672b
Add test
davidkpiano 9976ae4
rewrite test to make it fail correctly
Andarist 98ada6f
defer again
Andarist 91de30c
Add jsdocs
davidkpiano 10f8dca
Update packages/core/src/actions/emit.ts
Andarist File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| import isDevelopment from '#is-development'; | ||
| import { | ||
| ActionArgs, | ||
| AnyActorScope, | ||
| AnyActor, | ||
| AnyMachineSnapshot, | ||
| DelayExpr, | ||
| EventObject, | ||
| MachineContext, | ||
| NoInfer, | ||
| RaiseActionOptions, | ||
| SendExpr, | ||
| ParameterizedObject, | ||
| AnyEventObject | ||
| } from '../types.ts'; | ||
|
|
||
| function resolveEmit( | ||
| _: AnyActorScope, | ||
| snapshot: AnyMachineSnapshot, | ||
| args: ActionArgs<any, any, any>, | ||
| actionParams: ParameterizedObject['params'] | undefined, | ||
| { | ||
| event: eventOrExpr, | ||
| id, | ||
| delay | ||
| }: { | ||
| event: | ||
| | EventObject | ||
| | SendExpr< | ||
| MachineContext, | ||
| EventObject, | ||
| ParameterizedObject['params'] | undefined, | ||
| EventObject, | ||
| EventObject | ||
| >; | ||
| id: string | undefined; | ||
| delay: | ||
| | string | ||
| | number | ||
| | DelayExpr< | ||
| MachineContext, | ||
| EventObject, | ||
| ParameterizedObject['params'] | undefined, | ||
| EventObject | ||
| > | ||
| | undefined; | ||
| }, | ||
| { internalQueue }: { internalQueue: AnyEventObject[] } | ||
| ) { | ||
| const delaysMap = snapshot.machine.implementations.delays; | ||
|
|
||
| if (typeof eventOrExpr === 'string') { | ||
davidkpiano marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| throw new Error( | ||
| `Only event objects may be used with emit; use emit({ type: "${eventOrExpr}" }) instead` | ||
| ); | ||
| } | ||
| const resolvedEvent = | ||
| typeof eventOrExpr === 'function' | ||
| ? eventOrExpr(args, actionParams) | ||
| : eventOrExpr; | ||
|
|
||
| let resolvedDelay: number | undefined; | ||
| if (typeof delay === 'string') { | ||
| const configDelay = delaysMap && delaysMap[delay]; | ||
| resolvedDelay = | ||
| typeof configDelay === 'function' | ||
| ? configDelay(args, actionParams) | ||
| : configDelay; | ||
| } else { | ||
| resolvedDelay = | ||
| typeof delay === 'function' ? delay(args, actionParams) : delay; | ||
| } | ||
| if (typeof resolvedDelay !== 'number') { | ||
| internalQueue.push(resolvedEvent); | ||
| } | ||
davidkpiano marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return [snapshot, { event: resolvedEvent, id, delay: resolvedDelay }]; | ||
| } | ||
|
|
||
| function executeEmit( | ||
| actorScope: AnyActorScope, | ||
| params: { | ||
| event: EventObject; | ||
| id: string | undefined; | ||
| delay: number | undefined; | ||
davidkpiano marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| ) { | ||
| const { event, delay, id } = params; | ||
davidkpiano marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // if (typeof delay === 'number') { | ||
davidkpiano marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| actorScope.defer(() => { | ||
davidkpiano marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| actorScope.emit(event); | ||
| }); | ||
| return; | ||
Andarist marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // } | ||
davidkpiano marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| export interface RaiseAction< | ||
davidkpiano marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| TContext extends MachineContext, | ||
| TExpressionEvent extends EventObject, | ||
| TParams extends ParameterizedObject['params'] | undefined, | ||
| TEvent extends EventObject, | ||
| TDelay extends string | ||
| > { | ||
| (args: ActionArgs<TContext, TExpressionEvent, TEvent>, params: TParams): void; | ||
| _out_TEvent?: TEvent; | ||
Andarist marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| _out_TDelay?: TDelay; | ||
| } | ||
|
|
||
| /** | ||
| * Raises an event. This places the event in the internal event queue, so that | ||
| * the event is immediately consumed by the machine in the current step. | ||
| * | ||
| * @param eventType The event to raise. | ||
| */ | ||
| export function emit< | ||
| TContext extends MachineContext, | ||
| TExpressionEvent extends EventObject, | ||
| TEvent extends EventObject = TExpressionEvent, | ||
| TParams extends ParameterizedObject['params'] | undefined = | ||
| | ParameterizedObject['params'] | ||
| | undefined, | ||
| TDelay extends string = string | ||
| >( | ||
| eventOrExpr: | ||
| | AnyEventObject | ||
| | SendExpr<TContext, TExpressionEvent, TParams, AnyEventObject, TEvent>, | ||
| options?: RaiseActionOptions< | ||
| TContext, | ||
| TExpressionEvent, | ||
| TParams, | ||
| NoInfer<TEvent>, | ||
| NoInfer<TDelay> | ||
| > | ||
| ): RaiseAction<TContext, TExpressionEvent, TParams, TEvent, TDelay> { | ||
| function emit( | ||
| args: ActionArgs<TContext, TExpressionEvent, TEvent>, | ||
| params: TParams | ||
| ) { | ||
| if (isDevelopment) { | ||
| throw new Error(`This isn't supposed to be called`); | ||
| } | ||
| } | ||
|
|
||
| emit.type = 'xstate.emit'; | ||
| emit.event = eventOrExpr; | ||
davidkpiano marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| emit.id = options?.id; | ||
| emit.delay = options?.delay; | ||
|
|
||
| emit.resolve = resolveEmit; | ||
| emit.execute = executeEmit; | ||
|
|
||
| return emit; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import { AnyEventObject, createActor, createMachine } from '../src'; | ||
| import { emit } from '../src/actions/emit'; | ||
|
|
||
| describe('event emitter', () => { | ||
| it('emits events that can be listened to on actorRef.on(…)', async () => { | ||
| const machine = createMachine({ | ||
| on: { | ||
| someEvent: { | ||
| actions: emit({ type: 'emitted', foo: 'bar' }) | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| const actor = createActor(machine).start(); | ||
| setTimeout(() => { | ||
| actor.send({ | ||
| type: 'someEvent' | ||
| }); | ||
| }); | ||
| const event = await new Promise<AnyEventObject>((res) => { | ||
| actor.on('emitted', res); | ||
| }); | ||
|
|
||
| expect(event.foo).toBe('bar'); | ||
| }); | ||
| }); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.