(snapshot: SnapshotFrom<TLogic>, event: EventObject)
| 281 | private _deferred: Array<() => void> = []; |
| 282 | |
| 283 | private update(snapshot: SnapshotFrom<TLogic>, event: EventObject): void { |
| 284 | // Update state |
| 285 | this._snapshot = snapshot; |
| 286 | |
| 287 | // Execute deferred effects |
| 288 | let deferredFn: (typeof this._deferred)[number] | undefined; |
| 289 | |
| 290 | while ((deferredFn = this._deferred.shift())) { |
| 291 | try { |
| 292 | deferredFn(); |
| 293 | } catch (err) { |
| 294 | // this error can only be caught when executing *initial* actions |
| 295 | // it's the only time when we call actions provided by the user through those deferreds |
| 296 | // when the actor is already running we always execute them synchronously while transitioning |
| 297 | // no "builtin deferred" should actually throw an error since they are either safe |
| 298 | // or the control flow is passed through the mailbox and errors should be caught by the `_process` used by the mailbox |
| 299 | this._deferred.length = 0; |
| 300 | this._snapshot = { |
| 301 | ...(snapshot as any), |
| 302 | status: 'error', |
| 303 | error: err |
| 304 | }; |
| 305 | } |
| 306 | } |
| 307 | |
| 308 | switch ((this._snapshot as any).status) { |
| 309 | case 'active': |
| 310 | for (const observer of this.observers) { |
| 311 | try { |
| 312 | observer.next?.(snapshot); |
| 313 | } catch (err) { |
| 314 | reportUnhandledError(err); |
| 315 | } |
| 316 | } |
| 317 | break; |
| 318 | case 'done': |
| 319 | // next observers are meant to be notified about done snapshots |
| 320 | // this can be seen as something that is different from how observable work |
| 321 | // but with observables `complete` callback is called without any arguments |
| 322 | // it's more ergonomic for XState to treat a done snapshot as a "next" value |
| 323 | // and the completion event as something that is separate, |
| 324 | // something that merely follows emitting that done snapshot |
| 325 | for (const observer of this.observers) { |
| 326 | try { |
| 327 | observer.next?.(snapshot); |
| 328 | } catch (err) { |
| 329 | reportUnhandledError(err); |
| 330 | } |
| 331 | } |
| 332 | |
| 333 | this._stopProcedure(); |
| 334 | this._complete(); |
| 335 | this._doneEvent = createDoneActorEvent( |
| 336 | this.id, |
| 337 | (this._snapshot as any).output |
| 338 | ); |
| 339 | if (this._parent) { |
| 340 | this.system._relay(this, this._parent, this._doneEvent); |
no test coverage detected