@xstate-devtools/adapter 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/core.ts +28 -27
package/package.json
CHANGED
package/src/core.ts
CHANGED
|
@@ -569,44 +569,45 @@ export function createInspector(
|
|
|
569
569
|
if (inspectionEvent.type === '@xstate.actor') {
|
|
570
570
|
const actorRef: AnyActorRef = inspectionEvent.actorRef
|
|
571
571
|
const sessionId: string = actorRef.sessionId
|
|
572
|
+
|
|
573
|
+
// Serialize machine and populate both Maps BEFORE subscribing so that
|
|
574
|
+
// the Maps are fully consistent if complete()/error() ever fire
|
|
575
|
+
// synchronously during subscribe() (e.g. an actor that starts in a
|
|
576
|
+
// final state). Populating after subscribe introduced a race where
|
|
577
|
+
// actorMachines.delete() in the callback was a no-op and the subsequent
|
|
578
|
+
// actorMachines.set() would leak the entry permanently.
|
|
579
|
+
const actorLogic = (actorRef as { logic?: unknown }).logic as any
|
|
580
|
+
const machine = actorLogic?.root
|
|
581
|
+
? serializeMachine(
|
|
582
|
+
actorLogic,
|
|
583
|
+
actorLogic.config?.__xstateDevtoolsSource ?? getSourceLocation(source, options),
|
|
584
|
+
)
|
|
585
|
+
: null
|
|
572
586
|
actorRefs.set(sessionId, actorRef)
|
|
587
|
+
actorMachines.set(sessionId, machine)
|
|
573
588
|
|
|
574
589
|
// Eagerly remove the actor from both maps when it stops so we don't
|
|
575
590
|
// accumulate strong references to every short-lived actor indefinitely.
|
|
576
591
|
// Without this, actors that stop silently (no further snapshot/event) are
|
|
577
592
|
// only removed by checkAndNotifyStop — which never fires for them.
|
|
593
|
+
const notifyStop = () => {
|
|
594
|
+
if (actorRefs.has(sessionId)) {
|
|
595
|
+
actorRefs.delete(sessionId)
|
|
596
|
+
actorMachines.delete(sessionId)
|
|
597
|
+
const stopMsg: PageToExtensionMessage = {
|
|
598
|
+
type: 'XSTATE_ACTOR_STOPPED',
|
|
599
|
+
sessionId: tag(sessionId),
|
|
600
|
+
}
|
|
601
|
+
debugLog(source, 'actor stopped; notifying transport', summarizeMessage(stopMsg))
|
|
602
|
+
transport.send(stopMsg)
|
|
603
|
+
}
|
|
604
|
+
}
|
|
578
605
|
try {
|
|
579
|
-
actorRef.subscribe({
|
|
580
|
-
complete: () => {
|
|
581
|
-
if (actorRefs.has(sessionId)) {
|
|
582
|
-
actorRefs.delete(sessionId)
|
|
583
|
-
actorMachines.delete(sessionId)
|
|
584
|
-
const stopMsg: PageToExtensionMessage = {
|
|
585
|
-
type: 'XSTATE_ACTOR_STOPPED',
|
|
586
|
-
sessionId: tag(sessionId),
|
|
587
|
-
}
|
|
588
|
-
debugLog(source, 'actor completed; notifying transport', summarizeMessage(stopMsg))
|
|
589
|
-
transport.send(stopMsg)
|
|
590
|
-
}
|
|
591
|
-
},
|
|
592
|
-
error: () => {
|
|
593
|
-
actorRefs.delete(sessionId)
|
|
594
|
-
actorMachines.delete(sessionId)
|
|
595
|
-
},
|
|
596
|
-
})
|
|
606
|
+
actorRef.subscribe({ complete: notifyStop, error: notifyStop })
|
|
597
607
|
} catch {
|
|
598
608
|
// subscribe is best-effort; older actor implementations may not support it
|
|
599
609
|
}
|
|
600
610
|
|
|
601
|
-
const actorLogic = (actorRef as { logic?: unknown }).logic as any
|
|
602
|
-
const machine = actorLogic?.root
|
|
603
|
-
? serializeMachine(
|
|
604
|
-
actorLogic,
|
|
605
|
-
actorLogic.config?.__xstateDevtoolsSource ?? getSourceLocation(source, options),
|
|
606
|
-
)
|
|
607
|
-
: null
|
|
608
|
-
actorMachines.set(sessionId, machine)
|
|
609
|
-
|
|
610
611
|
const message: PageToExtensionMessage = {
|
|
611
612
|
type: 'XSTATE_ACTOR_REGISTERED',
|
|
612
613
|
sessionId: tag(sessionId),
|