xstate 5.0.0-beta.18 → 5.0.0-beta.20
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/actions/dist/xstate-actions.cjs.js +1 -1
- package/actions/dist/xstate-actions.development.cjs.js +1 -1
- package/actions/dist/xstate-actions.development.esm.js +1 -1
- package/actions/dist/xstate-actions.esm.js +1 -1
- package/actions/dist/xstate-actions.umd.min.js.map +1 -1
- package/actors/dist/xstate-actors.cjs.js +1 -1
- package/actors/dist/xstate-actors.development.cjs.js +1 -1
- package/actors/dist/xstate-actors.development.esm.js +1 -1
- package/actors/dist/xstate-actors.esm.js +1 -1
- package/actors/dist/xstate-actors.umd.min.js +1 -1
- package/actors/dist/xstate-actors.umd.min.js.map +1 -1
- package/dist/{actions-5fb9f10d.cjs.js → actions-069d9805.cjs.js} +311 -311
- package/dist/{actions-4d6514d2.esm.js → actions-a8a9433c.esm.js} +311 -311
- package/dist/{actions-13190b25.development.esm.js → actions-b299d008.development.esm.js} +311 -311
- package/dist/{actions-40bd643f.development.cjs.js → actions-d1c41ed3.development.cjs.js} +311 -311
- package/dist/declarations/src/Machine.d.ts +2 -2
- package/dist/declarations/src/State.d.ts +15 -4
- package/dist/declarations/src/StateMachine.d.ts +16 -16
- package/dist/declarations/src/StateNode.d.ts +4 -4
- package/dist/declarations/src/actions/send.d.ts +1 -1
- package/dist/declarations/src/actions/stop.d.ts +1 -1
- package/dist/declarations/src/actors/callback.d.ts +14 -2
- package/dist/declarations/src/actors/index.d.ts +4 -4
- package/dist/declarations/src/actors/observable.d.ts +11 -7
- package/dist/declarations/src/actors/promise.d.ts +14 -5
- package/dist/declarations/src/actors/transition.d.ts +7 -4
- package/dist/declarations/src/guards.d.ts +2 -2
- package/dist/declarations/src/stateUtils.d.ts +8 -8
- package/dist/declarations/src/typegenTypes.d.ts +15 -17
- package/dist/declarations/src/types.d.ts +103 -58
- package/dist/declarations/src/utils.d.ts +2 -2
- package/dist/xstate.cjs.js +2 -3
- package/dist/xstate.development.cjs.js +2 -3
- package/dist/xstate.development.esm.js +3 -4
- package/dist/xstate.esm.js +3 -4
- package/dist/xstate.umd.min.js +1 -1
- package/dist/xstate.umd.min.js.map +1 -1
- package/guards/dist/xstate-guards.cjs.js +1 -1
- package/guards/dist/xstate-guards.development.cjs.js +1 -1
- package/guards/dist/xstate-guards.development.esm.js +1 -1
- package/guards/dist/xstate-guards.esm.js +1 -1
- package/guards/dist/xstate-guards.umd.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,9 +2,6 @@ import { devToolsAdapter } from '../dev/dist/xstate-dev.development.esm.js';
|
|
|
2
2
|
|
|
3
3
|
// https://github.com/microsoft/TypeScript/issues/23182#issuecomment-379091887
|
|
4
4
|
|
|
5
|
-
// TODO: replace in v5 with:
|
|
6
|
-
// export type IndexByType<T extends { type: string }> = { [E in T as E['type']]: E; };
|
|
7
|
-
|
|
8
5
|
/**
|
|
9
6
|
* The full definition of an event, with a string `type`.
|
|
10
7
|
*/
|
|
@@ -13,8 +10,6 @@ import { devToolsAdapter } from '../dev/dist/xstate-dev.development.esm.js';
|
|
|
13
10
|
// we should also accept a raw machine as actor logic here
|
|
14
11
|
// or just make machine actor logic
|
|
15
12
|
|
|
16
|
-
// TODO: narrow this to logic from machine
|
|
17
|
-
|
|
18
13
|
/**
|
|
19
14
|
* The string or object representing the state value relative to the parent state node.
|
|
20
15
|
*
|
|
@@ -321,7 +316,7 @@ const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observabl
|
|
|
321
316
|
* @returns Actor logic
|
|
322
317
|
*/
|
|
323
318
|
function fromTransition(transition, initialState) {
|
|
324
|
-
|
|
319
|
+
return {
|
|
325
320
|
config: transition,
|
|
326
321
|
transition: (state, event, actorContext) => {
|
|
327
322
|
return transition(state, event, actorContext);
|
|
@@ -335,95 +330,260 @@ function fromTransition(transition, initialState) {
|
|
|
335
330
|
getPersistedState: state => state,
|
|
336
331
|
restoreState: state => state
|
|
337
332
|
};
|
|
338
|
-
return logic;
|
|
339
333
|
}
|
|
340
334
|
|
|
341
|
-
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
335
|
+
function matchesState(parentStateId, childStateId) {
|
|
336
|
+
const parentStateValue = toStateValue(parentStateId);
|
|
337
|
+
const childStateValue = toStateValue(childStateId);
|
|
338
|
+
if (typeof childStateValue === 'string') {
|
|
339
|
+
if (typeof parentStateValue === 'string') {
|
|
340
|
+
return childStateValue === parentStateValue;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Parent more specific than child
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
if (typeof parentStateValue === 'string') {
|
|
347
|
+
return parentStateValue in childStateValue;
|
|
348
|
+
}
|
|
349
|
+
return Object.keys(parentStateValue).every(key => {
|
|
350
|
+
if (!(key in childStateValue)) {
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
return matchesState(parentStateValue[key], childStateValue[key]);
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
function toStatePath(stateId) {
|
|
357
|
+
try {
|
|
358
|
+
if (isArray(stateId)) {
|
|
359
|
+
return stateId;
|
|
360
|
+
}
|
|
361
|
+
return stateId.toString().split(STATE_DELIMITER);
|
|
362
|
+
} catch (e) {
|
|
363
|
+
throw new Error(`'${stateId}' is not a valid state path.`);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
function isStateLike(state) {
|
|
367
|
+
return typeof state === 'object' && 'value' in state && 'context' in state && 'event' in state;
|
|
368
|
+
}
|
|
369
|
+
function toStateValue(stateValue) {
|
|
370
|
+
if (isStateLike(stateValue)) {
|
|
371
|
+
return stateValue.value;
|
|
372
|
+
}
|
|
373
|
+
if (isArray(stateValue)) {
|
|
374
|
+
return pathToStateValue(stateValue);
|
|
375
|
+
}
|
|
376
|
+
if (typeof stateValue !== 'string') {
|
|
377
|
+
return stateValue;
|
|
378
|
+
}
|
|
379
|
+
const statePath = toStatePath(stateValue);
|
|
380
|
+
return pathToStateValue(statePath);
|
|
381
|
+
}
|
|
382
|
+
function pathToStateValue(statePath) {
|
|
383
|
+
if (statePath.length === 1) {
|
|
384
|
+
return statePath[0];
|
|
385
|
+
}
|
|
386
|
+
const value = {};
|
|
387
|
+
let marker = value;
|
|
388
|
+
for (let i = 0; i < statePath.length - 1; i++) {
|
|
389
|
+
if (i === statePath.length - 2) {
|
|
390
|
+
marker[statePath[i]] = statePath[i + 1];
|
|
391
|
+
} else {
|
|
392
|
+
const previous = marker;
|
|
393
|
+
marker = {};
|
|
394
|
+
previous[statePath[i]] = marker;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return value;
|
|
398
|
+
}
|
|
399
|
+
function mapValues(collection, iteratee) {
|
|
400
|
+
const result = {};
|
|
401
|
+
const collectionKeys = Object.keys(collection);
|
|
402
|
+
for (let i = 0; i < collectionKeys.length; i++) {
|
|
403
|
+
const key = collectionKeys[i];
|
|
404
|
+
result[key] = iteratee(collection[key], key, collection, i);
|
|
405
|
+
}
|
|
406
|
+
return result;
|
|
407
|
+
}
|
|
408
|
+
function flatten(array) {
|
|
409
|
+
return [].concat(...array);
|
|
410
|
+
}
|
|
411
|
+
function toArrayStrict(value) {
|
|
412
|
+
if (isArray(value)) {
|
|
413
|
+
return value;
|
|
414
|
+
}
|
|
415
|
+
return [value];
|
|
416
|
+
}
|
|
417
|
+
function toArray(value) {
|
|
418
|
+
if (value === undefined) {
|
|
419
|
+
return [];
|
|
420
|
+
}
|
|
421
|
+
return toArrayStrict(value);
|
|
422
|
+
}
|
|
423
|
+
function mapContext(mapper, context, event) {
|
|
424
|
+
if (typeof mapper === 'function') {
|
|
425
|
+
return mapper({
|
|
426
|
+
context,
|
|
427
|
+
event
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
const result = {};
|
|
431
|
+
const args = {
|
|
432
|
+
context,
|
|
433
|
+
event
|
|
434
|
+
};
|
|
435
|
+
for (const key of Object.keys(mapper)) {
|
|
436
|
+
const subMapper = mapper[key];
|
|
437
|
+
if (typeof subMapper === 'function') {
|
|
438
|
+
result[key] = subMapper(args);
|
|
439
|
+
} else {
|
|
440
|
+
result[key] = subMapper;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return result;
|
|
444
|
+
}
|
|
445
|
+
function isPromiseLike(value) {
|
|
446
|
+
if (value instanceof Promise) {
|
|
447
|
+
return true;
|
|
448
|
+
}
|
|
449
|
+
// Check if shape matches the Promise/A+ specification for a "thenable".
|
|
450
|
+
if (value !== null && (typeof value === 'function' || typeof value === 'object') && typeof value.then === 'function') {
|
|
451
|
+
return true;
|
|
452
|
+
}
|
|
453
|
+
return false;
|
|
454
|
+
}
|
|
455
|
+
function isArray(value) {
|
|
456
|
+
return Array.isArray(value);
|
|
457
|
+
}
|
|
458
|
+
function isErrorEvent(event) {
|
|
459
|
+
return typeof event.type === 'string' && (event.type === errorExecution || event.type.startsWith(errorPlatform));
|
|
460
|
+
}
|
|
461
|
+
function toTransitionConfigArray(configLike) {
|
|
462
|
+
return toArrayStrict(configLike).map(transitionLike => {
|
|
463
|
+
if (typeof transitionLike === 'undefined' || typeof transitionLike === 'string') {
|
|
464
|
+
return {
|
|
465
|
+
target: transitionLike
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
return transitionLike;
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
function normalizeTarget(target) {
|
|
472
|
+
if (target === undefined || target === TARGETLESS_KEY) {
|
|
473
|
+
return undefined;
|
|
474
|
+
}
|
|
475
|
+
return toArray(target);
|
|
476
|
+
}
|
|
477
|
+
function toInvokeConfig(invocable, id) {
|
|
478
|
+
if (typeof invocable === 'object') {
|
|
479
|
+
if ('src' in invocable) {
|
|
480
|
+
return invocable;
|
|
481
|
+
}
|
|
482
|
+
if ('transition' in invocable) {
|
|
483
|
+
return {
|
|
484
|
+
id,
|
|
485
|
+
src: invocable
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
return {
|
|
490
|
+
id,
|
|
491
|
+
src: invocable
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
function toObserver(nextHandler, errorHandler, completionHandler) {
|
|
495
|
+
const noop = () => {};
|
|
496
|
+
const isObserver = typeof nextHandler === 'object';
|
|
497
|
+
const self = isObserver ? nextHandler : null;
|
|
498
|
+
return {
|
|
499
|
+
next: ((isObserver ? nextHandler.next : nextHandler) || noop).bind(self),
|
|
500
|
+
error: ((isObserver ? nextHandler.error : errorHandler) || noop).bind(self),
|
|
501
|
+
complete: ((isObserver ? nextHandler.complete : completionHandler) || noop).bind(self)
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
function createInvokeId(stateNodeId, index) {
|
|
505
|
+
return `${stateNodeId}:invocation[${index}]`;
|
|
506
|
+
}
|
|
507
|
+
function resolveReferencedActor(referenced) {
|
|
508
|
+
return referenced ? 'transition' in referenced ? {
|
|
509
|
+
src: referenced,
|
|
510
|
+
input: undefined
|
|
511
|
+
} : referenced : undefined;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function fromCallback(invokeCallback) {
|
|
347
515
|
const logic = {
|
|
348
|
-
config:
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
return {
|
|
356
|
-
...state,
|
|
357
|
-
status: 'done',
|
|
358
|
-
data: event.data,
|
|
359
|
-
input: undefined
|
|
360
|
-
};
|
|
361
|
-
case rejectEventType:
|
|
362
|
-
return {
|
|
363
|
-
...state,
|
|
364
|
-
status: 'error',
|
|
365
|
-
data: event.data,
|
|
366
|
-
input: undefined
|
|
367
|
-
};
|
|
368
|
-
case stopSignalType:
|
|
369
|
-
return {
|
|
370
|
-
...state,
|
|
371
|
-
status: 'canceled',
|
|
372
|
-
input: undefined
|
|
373
|
-
};
|
|
374
|
-
default:
|
|
375
|
-
return state;
|
|
376
|
-
}
|
|
516
|
+
config: invokeCallback,
|
|
517
|
+
start: (_state, {
|
|
518
|
+
self
|
|
519
|
+
}) => {
|
|
520
|
+
self.send({
|
|
521
|
+
type: startSignalType
|
|
522
|
+
});
|
|
377
523
|
},
|
|
378
|
-
|
|
524
|
+
transition: (state, event, {
|
|
379
525
|
self,
|
|
526
|
+
id,
|
|
380
527
|
system
|
|
381
528
|
}) => {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
data: response
|
|
529
|
+
if (event.type === startSignalType) {
|
|
530
|
+
const sendBack = eventForParent => {
|
|
531
|
+
if (state.canceled) {
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
self._parent?.send(eventForParent);
|
|
535
|
+
};
|
|
536
|
+
const receive = newListener => {
|
|
537
|
+
state.receivers.add(newListener);
|
|
538
|
+
};
|
|
539
|
+
state.dispose = invokeCallback({
|
|
540
|
+
input: state.input,
|
|
541
|
+
system,
|
|
542
|
+
self: self,
|
|
543
|
+
sendBack,
|
|
544
|
+
receive
|
|
399
545
|
});
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
546
|
+
if (isPromiseLike(state.dispose)) {
|
|
547
|
+
state.dispose.then(resolved => {
|
|
548
|
+
self._parent?.send(doneInvoke(id, resolved));
|
|
549
|
+
state.canceled = true;
|
|
550
|
+
}, errorData => {
|
|
551
|
+
state.canceled = true;
|
|
552
|
+
self._parent?.send(error(id, errorData));
|
|
553
|
+
});
|
|
404
554
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
555
|
+
return state;
|
|
556
|
+
}
|
|
557
|
+
if (event.type === stopSignalType) {
|
|
558
|
+
state.canceled = true;
|
|
559
|
+
if (typeof state.dispose === 'function') {
|
|
560
|
+
state.dispose();
|
|
561
|
+
}
|
|
562
|
+
return state;
|
|
563
|
+
}
|
|
564
|
+
if (isSignal(event)) {
|
|
565
|
+
// TODO: unrecognized signal
|
|
566
|
+
return state;
|
|
567
|
+
}
|
|
568
|
+
state.receivers.forEach(receiver => receiver(event));
|
|
569
|
+
return state;
|
|
410
570
|
},
|
|
411
571
|
getInitialState: (_, input) => {
|
|
412
572
|
return {
|
|
413
|
-
|
|
414
|
-
|
|
573
|
+
canceled: false,
|
|
574
|
+
receivers: new Set(),
|
|
575
|
+
dispose: undefined,
|
|
415
576
|
input
|
|
416
577
|
};
|
|
417
578
|
},
|
|
418
|
-
getSnapshot:
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
579
|
+
getSnapshot: () => undefined,
|
|
580
|
+
getPersistedState: ({
|
|
581
|
+
input
|
|
582
|
+
}) => input
|
|
422
583
|
};
|
|
423
584
|
return logic;
|
|
424
585
|
}
|
|
425
586
|
|
|
426
|
-
// TODO: this likely shouldn't accept TEvent, observable actor doesn't accept external events
|
|
427
587
|
function fromObservable(observableCreator) {
|
|
428
588
|
const nextEventType = '$$xstate.next';
|
|
429
589
|
const errorEventType = '$$xstate.error';
|
|
@@ -499,7 +659,8 @@ function fromObservable(observableCreator) {
|
|
|
499
659
|
}
|
|
500
660
|
state.subscription = observableCreator({
|
|
501
661
|
input: state.input,
|
|
502
|
-
system
|
|
662
|
+
system,
|
|
663
|
+
self
|
|
503
664
|
}).subscribe({
|
|
504
665
|
next: value => {
|
|
505
666
|
self.send({
|
|
@@ -605,7 +766,8 @@ function fromEventObservable(lazyObservable) {
|
|
|
605
766
|
}
|
|
606
767
|
state.subscription = lazyObservable({
|
|
607
768
|
input: state.input,
|
|
608
|
-
system
|
|
769
|
+
system,
|
|
770
|
+
self
|
|
609
771
|
}).subscribe({
|
|
610
772
|
next: value => {
|
|
611
773
|
self._parent?.send(value);
|
|
@@ -642,251 +804,88 @@ function fromEventObservable(lazyObservable) {
|
|
|
642
804
|
return logic;
|
|
643
805
|
}
|
|
644
806
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
// Parent more specific than child
|
|
654
|
-
return false;
|
|
655
|
-
}
|
|
656
|
-
if (typeof parentStateValue === 'string') {
|
|
657
|
-
return parentStateValue in childStateValue;
|
|
658
|
-
}
|
|
659
|
-
return Object.keys(parentStateValue).every(key => {
|
|
660
|
-
if (!(key in childStateValue)) {
|
|
661
|
-
return false;
|
|
662
|
-
}
|
|
663
|
-
return matchesState(parentStateValue[key], childStateValue[key]);
|
|
664
|
-
});
|
|
665
|
-
}
|
|
666
|
-
function toStatePath(stateId) {
|
|
667
|
-
try {
|
|
668
|
-
if (isArray(stateId)) {
|
|
669
|
-
return stateId;
|
|
670
|
-
}
|
|
671
|
-
return stateId.toString().split(STATE_DELIMITER);
|
|
672
|
-
} catch (e) {
|
|
673
|
-
throw new Error(`'${stateId}' is not a valid state path.`);
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
function isStateLike(state) {
|
|
677
|
-
return typeof state === 'object' && 'value' in state && 'context' in state && 'event' in state;
|
|
678
|
-
}
|
|
679
|
-
function toStateValue(stateValue) {
|
|
680
|
-
if (isStateLike(stateValue)) {
|
|
681
|
-
return stateValue.value;
|
|
682
|
-
}
|
|
683
|
-
if (isArray(stateValue)) {
|
|
684
|
-
return pathToStateValue(stateValue);
|
|
685
|
-
}
|
|
686
|
-
if (typeof stateValue !== 'string') {
|
|
687
|
-
return stateValue;
|
|
688
|
-
}
|
|
689
|
-
const statePath = toStatePath(stateValue);
|
|
690
|
-
return pathToStateValue(statePath);
|
|
691
|
-
}
|
|
692
|
-
function pathToStateValue(statePath) {
|
|
693
|
-
if (statePath.length === 1) {
|
|
694
|
-
return statePath[0];
|
|
695
|
-
}
|
|
696
|
-
const value = {};
|
|
697
|
-
let marker = value;
|
|
698
|
-
for (let i = 0; i < statePath.length - 1; i++) {
|
|
699
|
-
if (i === statePath.length - 2) {
|
|
700
|
-
marker[statePath[i]] = statePath[i + 1];
|
|
701
|
-
} else {
|
|
702
|
-
const previous = marker;
|
|
703
|
-
marker = {};
|
|
704
|
-
previous[statePath[i]] = marker;
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
return value;
|
|
708
|
-
}
|
|
709
|
-
function mapValues(collection, iteratee) {
|
|
710
|
-
const result = {};
|
|
711
|
-
const collectionKeys = Object.keys(collection);
|
|
712
|
-
for (let i = 0; i < collectionKeys.length; i++) {
|
|
713
|
-
const key = collectionKeys[i];
|
|
714
|
-
result[key] = iteratee(collection[key], key, collection, i);
|
|
715
|
-
}
|
|
716
|
-
return result;
|
|
717
|
-
}
|
|
718
|
-
function flatten(array) {
|
|
719
|
-
return [].concat(...array);
|
|
720
|
-
}
|
|
721
|
-
function toArrayStrict(value) {
|
|
722
|
-
if (isArray(value)) {
|
|
723
|
-
return value;
|
|
724
|
-
}
|
|
725
|
-
return [value];
|
|
726
|
-
}
|
|
727
|
-
function toArray(value) {
|
|
728
|
-
if (value === undefined) {
|
|
729
|
-
return [];
|
|
730
|
-
}
|
|
731
|
-
return toArrayStrict(value);
|
|
732
|
-
}
|
|
733
|
-
function mapContext(mapper, context, event) {
|
|
734
|
-
if (typeof mapper === 'function') {
|
|
735
|
-
return mapper({
|
|
736
|
-
context,
|
|
737
|
-
event
|
|
738
|
-
});
|
|
739
|
-
}
|
|
740
|
-
const result = {};
|
|
741
|
-
const args = {
|
|
742
|
-
context,
|
|
743
|
-
event
|
|
744
|
-
};
|
|
745
|
-
for (const key of Object.keys(mapper)) {
|
|
746
|
-
const subMapper = mapper[key];
|
|
747
|
-
if (typeof subMapper === 'function') {
|
|
748
|
-
result[key] = subMapper(args);
|
|
749
|
-
} else {
|
|
750
|
-
result[key] = subMapper;
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
return result;
|
|
754
|
-
}
|
|
755
|
-
function isPromiseLike(value) {
|
|
756
|
-
if (value instanceof Promise) {
|
|
757
|
-
return true;
|
|
758
|
-
}
|
|
759
|
-
// Check if shape matches the Promise/A+ specification for a "thenable".
|
|
760
|
-
if (value !== null && (typeof value === 'function' || typeof value === 'object') && typeof value.then === 'function') {
|
|
761
|
-
return true;
|
|
762
|
-
}
|
|
763
|
-
return false;
|
|
764
|
-
}
|
|
765
|
-
function isArray(value) {
|
|
766
|
-
return Array.isArray(value);
|
|
767
|
-
}
|
|
768
|
-
function isErrorEvent(event) {
|
|
769
|
-
return typeof event.type === 'string' && (event.type === errorExecution || event.type.startsWith(errorPlatform));
|
|
770
|
-
}
|
|
771
|
-
function toTransitionConfigArray(configLike) {
|
|
772
|
-
return toArrayStrict(configLike).map(transitionLike => {
|
|
773
|
-
if (typeof transitionLike === 'undefined' || typeof transitionLike === 'string') {
|
|
774
|
-
return {
|
|
775
|
-
target: transitionLike
|
|
776
|
-
};
|
|
777
|
-
}
|
|
778
|
-
return transitionLike;
|
|
779
|
-
});
|
|
780
|
-
}
|
|
781
|
-
function normalizeTarget(target) {
|
|
782
|
-
if (target === undefined || target === TARGETLESS_KEY) {
|
|
783
|
-
return undefined;
|
|
784
|
-
}
|
|
785
|
-
return toArray(target);
|
|
786
|
-
}
|
|
787
|
-
function toInvokeConfig(invocable, id) {
|
|
788
|
-
if (typeof invocable === 'object') {
|
|
789
|
-
if ('src' in invocable) {
|
|
790
|
-
return invocable;
|
|
791
|
-
}
|
|
792
|
-
if ('transition' in invocable) {
|
|
793
|
-
return {
|
|
794
|
-
id,
|
|
795
|
-
src: invocable
|
|
796
|
-
};
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
return {
|
|
800
|
-
id,
|
|
801
|
-
src: invocable
|
|
802
|
-
};
|
|
803
|
-
}
|
|
804
|
-
function toObserver(nextHandler, errorHandler, completionHandler) {
|
|
805
|
-
const noop = () => {};
|
|
806
|
-
const isObserver = typeof nextHandler === 'object';
|
|
807
|
-
const self = isObserver ? nextHandler : null;
|
|
808
|
-
return {
|
|
809
|
-
next: ((isObserver ? nextHandler.next : nextHandler) || noop).bind(self),
|
|
810
|
-
error: ((isObserver ? nextHandler.error : errorHandler) || noop).bind(self),
|
|
811
|
-
complete: ((isObserver ? nextHandler.complete : completionHandler) || noop).bind(self)
|
|
812
|
-
};
|
|
813
|
-
}
|
|
814
|
-
function createInvokeId(stateNodeId, index) {
|
|
815
|
-
return `${stateNodeId}:invocation[${index}]`;
|
|
816
|
-
}
|
|
817
|
-
function resolveReferencedActor(referenced) {
|
|
818
|
-
return referenced ? 'transition' in referenced ? {
|
|
819
|
-
src: referenced,
|
|
820
|
-
input: undefined
|
|
821
|
-
} : referenced : undefined;
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
function fromCallback(invokeCallback) {
|
|
807
|
+
const resolveEventType = '$$xstate.resolve';
|
|
808
|
+
const rejectEventType = '$$xstate.reject';
|
|
809
|
+
function fromPromise(
|
|
810
|
+
// TODO: add types
|
|
811
|
+
promiseCreator) {
|
|
812
|
+
// TODO: add event types
|
|
825
813
|
const logic = {
|
|
826
|
-
config:
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
814
|
+
config: promiseCreator,
|
|
815
|
+
transition: (state, event) => {
|
|
816
|
+
if (state.status !== 'active') {
|
|
817
|
+
return state;
|
|
818
|
+
}
|
|
819
|
+
switch (event.type) {
|
|
820
|
+
case resolveEventType:
|
|
821
|
+
return {
|
|
822
|
+
...state,
|
|
823
|
+
status: 'done',
|
|
824
|
+
data: event.data,
|
|
825
|
+
input: undefined
|
|
826
|
+
};
|
|
827
|
+
case rejectEventType:
|
|
828
|
+
return {
|
|
829
|
+
...state,
|
|
830
|
+
status: 'error',
|
|
831
|
+
data: event.data,
|
|
832
|
+
input: undefined
|
|
833
|
+
};
|
|
834
|
+
case stopSignalType:
|
|
835
|
+
return {
|
|
836
|
+
...state,
|
|
837
|
+
status: 'canceled',
|
|
838
|
+
input: undefined
|
|
839
|
+
};
|
|
840
|
+
default:
|
|
841
|
+
return state;
|
|
842
|
+
}
|
|
833
843
|
},
|
|
834
|
-
|
|
844
|
+
start: (state, {
|
|
835
845
|
self,
|
|
836
|
-
id,
|
|
837
846
|
system
|
|
838
847
|
}) => {
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
}
|
|
844
|
-
self._parent?.send(eventForParent);
|
|
845
|
-
};
|
|
846
|
-
const receiver = newListener => {
|
|
847
|
-
state.receivers.add(newListener);
|
|
848
|
-
};
|
|
849
|
-
state.dispose = invokeCallback(sender, receiver, {
|
|
850
|
-
input: state.input,
|
|
851
|
-
system
|
|
852
|
-
});
|
|
853
|
-
if (isPromiseLike(state.dispose)) {
|
|
854
|
-
state.dispose.then(resolved => {
|
|
855
|
-
self._parent?.send(doneInvoke(id, resolved));
|
|
856
|
-
state.canceled = true;
|
|
857
|
-
}, errorData => {
|
|
858
|
-
state.canceled = true;
|
|
859
|
-
self._parent?.send(error(id, errorData));
|
|
860
|
-
});
|
|
861
|
-
}
|
|
862
|
-
return state;
|
|
848
|
+
// TODO: determine how to allow customizing this so that promises
|
|
849
|
+
// can be restarted if necessary
|
|
850
|
+
if (state.status !== 'active') {
|
|
851
|
+
return;
|
|
863
852
|
}
|
|
864
|
-
|
|
865
|
-
state.
|
|
866
|
-
|
|
867
|
-
|
|
853
|
+
const resolvedPromise = Promise.resolve(promiseCreator({
|
|
854
|
+
input: state.input,
|
|
855
|
+
system,
|
|
856
|
+
self
|
|
857
|
+
}));
|
|
858
|
+
resolvedPromise.then(response => {
|
|
859
|
+
// TODO: remove this condition once dead letter queue lands
|
|
860
|
+
if (self._state.status !== 'active') {
|
|
861
|
+
return;
|
|
868
862
|
}
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
863
|
+
self.send({
|
|
864
|
+
type: resolveEventType,
|
|
865
|
+
data: response
|
|
866
|
+
});
|
|
867
|
+
}, errorData => {
|
|
868
|
+
// TODO: remove this condition once dead letter queue lands
|
|
869
|
+
if (self._state.status !== 'active') {
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
self.send({
|
|
873
|
+
type: rejectEventType,
|
|
874
|
+
data: errorData
|
|
875
|
+
});
|
|
876
|
+
});
|
|
877
877
|
},
|
|
878
878
|
getInitialState: (_, input) => {
|
|
879
879
|
return {
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
dispose: undefined,
|
|
880
|
+
status: 'active',
|
|
881
|
+
data: undefined,
|
|
883
882
|
input
|
|
884
883
|
};
|
|
885
884
|
},
|
|
886
|
-
getSnapshot:
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
885
|
+
getSnapshot: state => state.data,
|
|
886
|
+
getStatus: state => state,
|
|
887
|
+
getPersistedState: state => state,
|
|
888
|
+
restoreState: state => state
|
|
890
889
|
};
|
|
891
890
|
return logic;
|
|
892
891
|
}
|
|
@@ -925,6 +924,7 @@ function toActorRef(actorRefLike) {
|
|
|
925
924
|
id: 'anonymous',
|
|
926
925
|
sessionId: '',
|
|
927
926
|
getSnapshot: () => undefined,
|
|
927
|
+
// TODO: this isn't safe
|
|
928
928
|
[symbolObservable]: function () {
|
|
929
929
|
return this;
|
|
930
930
|
},
|
|
@@ -2818,7 +2818,7 @@ function createSpawner(actorContext, {
|
|
|
2818
2818
|
}
|
|
2819
2819
|
};
|
|
2820
2820
|
return (src, options) => {
|
|
2821
|
-
const actorRef = spawn(src, options);
|
|
2821
|
+
const actorRef = spawn(src, options); // TODO: fix types
|
|
2822
2822
|
spawnedChildren[actorRef.id] = actorRef;
|
|
2823
2823
|
actorContext.defer(() => {
|
|
2824
2824
|
if (actorRef.status === ActorStatus.Stopped) {
|