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.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.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
|
*
|
|
@@ -305,7 +300,7 @@ const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observabl
|
|
|
305
300
|
* @returns Actor logic
|
|
306
301
|
*/
|
|
307
302
|
function fromTransition(transition, initialState) {
|
|
308
|
-
|
|
303
|
+
return {
|
|
309
304
|
config: transition,
|
|
310
305
|
transition: (state, event, actorContext) => {
|
|
311
306
|
return transition(state, event, actorContext);
|
|
@@ -319,95 +314,260 @@ function fromTransition(transition, initialState) {
|
|
|
319
314
|
getPersistedState: state => state,
|
|
320
315
|
restoreState: state => state
|
|
321
316
|
};
|
|
322
|
-
return logic;
|
|
323
317
|
}
|
|
324
318
|
|
|
325
|
-
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
319
|
+
function matchesState(parentStateId, childStateId) {
|
|
320
|
+
const parentStateValue = toStateValue(parentStateId);
|
|
321
|
+
const childStateValue = toStateValue(childStateId);
|
|
322
|
+
if (typeof childStateValue === 'string') {
|
|
323
|
+
if (typeof parentStateValue === 'string') {
|
|
324
|
+
return childStateValue === parentStateValue;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Parent more specific than child
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
if (typeof parentStateValue === 'string') {
|
|
331
|
+
return parentStateValue in childStateValue;
|
|
332
|
+
}
|
|
333
|
+
return Object.keys(parentStateValue).every(key => {
|
|
334
|
+
if (!(key in childStateValue)) {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
return matchesState(parentStateValue[key], childStateValue[key]);
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
function toStatePath(stateId) {
|
|
341
|
+
try {
|
|
342
|
+
if (isArray(stateId)) {
|
|
343
|
+
return stateId;
|
|
344
|
+
}
|
|
345
|
+
return stateId.toString().split(STATE_DELIMITER);
|
|
346
|
+
} catch (e) {
|
|
347
|
+
throw new Error(`'${stateId}' is not a valid state path.`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
function isStateLike(state) {
|
|
351
|
+
return typeof state === 'object' && 'value' in state && 'context' in state && 'event' in state;
|
|
352
|
+
}
|
|
353
|
+
function toStateValue(stateValue) {
|
|
354
|
+
if (isStateLike(stateValue)) {
|
|
355
|
+
return stateValue.value;
|
|
356
|
+
}
|
|
357
|
+
if (isArray(stateValue)) {
|
|
358
|
+
return pathToStateValue(stateValue);
|
|
359
|
+
}
|
|
360
|
+
if (typeof stateValue !== 'string') {
|
|
361
|
+
return stateValue;
|
|
362
|
+
}
|
|
363
|
+
const statePath = toStatePath(stateValue);
|
|
364
|
+
return pathToStateValue(statePath);
|
|
365
|
+
}
|
|
366
|
+
function pathToStateValue(statePath) {
|
|
367
|
+
if (statePath.length === 1) {
|
|
368
|
+
return statePath[0];
|
|
369
|
+
}
|
|
370
|
+
const value = {};
|
|
371
|
+
let marker = value;
|
|
372
|
+
for (let i = 0; i < statePath.length - 1; i++) {
|
|
373
|
+
if (i === statePath.length - 2) {
|
|
374
|
+
marker[statePath[i]] = statePath[i + 1];
|
|
375
|
+
} else {
|
|
376
|
+
const previous = marker;
|
|
377
|
+
marker = {};
|
|
378
|
+
previous[statePath[i]] = marker;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return value;
|
|
382
|
+
}
|
|
383
|
+
function mapValues(collection, iteratee) {
|
|
384
|
+
const result = {};
|
|
385
|
+
const collectionKeys = Object.keys(collection);
|
|
386
|
+
for (let i = 0; i < collectionKeys.length; i++) {
|
|
387
|
+
const key = collectionKeys[i];
|
|
388
|
+
result[key] = iteratee(collection[key], key, collection, i);
|
|
389
|
+
}
|
|
390
|
+
return result;
|
|
391
|
+
}
|
|
392
|
+
function flatten(array) {
|
|
393
|
+
return [].concat(...array);
|
|
394
|
+
}
|
|
395
|
+
function toArrayStrict(value) {
|
|
396
|
+
if (isArray(value)) {
|
|
397
|
+
return value;
|
|
398
|
+
}
|
|
399
|
+
return [value];
|
|
400
|
+
}
|
|
401
|
+
function toArray(value) {
|
|
402
|
+
if (value === undefined) {
|
|
403
|
+
return [];
|
|
404
|
+
}
|
|
405
|
+
return toArrayStrict(value);
|
|
406
|
+
}
|
|
407
|
+
function mapContext(mapper, context, event) {
|
|
408
|
+
if (typeof mapper === 'function') {
|
|
409
|
+
return mapper({
|
|
410
|
+
context,
|
|
411
|
+
event
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
const result = {};
|
|
415
|
+
const args = {
|
|
416
|
+
context,
|
|
417
|
+
event
|
|
418
|
+
};
|
|
419
|
+
for (const key of Object.keys(mapper)) {
|
|
420
|
+
const subMapper = mapper[key];
|
|
421
|
+
if (typeof subMapper === 'function') {
|
|
422
|
+
result[key] = subMapper(args);
|
|
423
|
+
} else {
|
|
424
|
+
result[key] = subMapper;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return result;
|
|
428
|
+
}
|
|
429
|
+
function isPromiseLike(value) {
|
|
430
|
+
if (value instanceof Promise) {
|
|
431
|
+
return true;
|
|
432
|
+
}
|
|
433
|
+
// Check if shape matches the Promise/A+ specification for a "thenable".
|
|
434
|
+
if (value !== null && (typeof value === 'function' || typeof value === 'object') && typeof value.then === 'function') {
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
437
|
+
return false;
|
|
438
|
+
}
|
|
439
|
+
function isArray(value) {
|
|
440
|
+
return Array.isArray(value);
|
|
441
|
+
}
|
|
442
|
+
function isErrorEvent(event) {
|
|
443
|
+
return typeof event.type === 'string' && (event.type === errorExecution || event.type.startsWith(errorPlatform));
|
|
444
|
+
}
|
|
445
|
+
function toTransitionConfigArray(configLike) {
|
|
446
|
+
return toArrayStrict(configLike).map(transitionLike => {
|
|
447
|
+
if (typeof transitionLike === 'undefined' || typeof transitionLike === 'string') {
|
|
448
|
+
return {
|
|
449
|
+
target: transitionLike
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
return transitionLike;
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
function normalizeTarget(target) {
|
|
456
|
+
if (target === undefined || target === TARGETLESS_KEY) {
|
|
457
|
+
return undefined;
|
|
458
|
+
}
|
|
459
|
+
return toArray(target);
|
|
460
|
+
}
|
|
461
|
+
function toInvokeConfig(invocable, id) {
|
|
462
|
+
if (typeof invocable === 'object') {
|
|
463
|
+
if ('src' in invocable) {
|
|
464
|
+
return invocable;
|
|
465
|
+
}
|
|
466
|
+
if ('transition' in invocable) {
|
|
467
|
+
return {
|
|
468
|
+
id,
|
|
469
|
+
src: invocable
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
return {
|
|
474
|
+
id,
|
|
475
|
+
src: invocable
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
function toObserver(nextHandler, errorHandler, completionHandler) {
|
|
479
|
+
const noop = () => {};
|
|
480
|
+
const isObserver = typeof nextHandler === 'object';
|
|
481
|
+
const self = isObserver ? nextHandler : null;
|
|
482
|
+
return {
|
|
483
|
+
next: ((isObserver ? nextHandler.next : nextHandler) || noop).bind(self),
|
|
484
|
+
error: ((isObserver ? nextHandler.error : errorHandler) || noop).bind(self),
|
|
485
|
+
complete: ((isObserver ? nextHandler.complete : completionHandler) || noop).bind(self)
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
function createInvokeId(stateNodeId, index) {
|
|
489
|
+
return `${stateNodeId}:invocation[${index}]`;
|
|
490
|
+
}
|
|
491
|
+
function resolveReferencedActor(referenced) {
|
|
492
|
+
return referenced ? 'transition' in referenced ? {
|
|
493
|
+
src: referenced,
|
|
494
|
+
input: undefined
|
|
495
|
+
} : referenced : undefined;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
function fromCallback(invokeCallback) {
|
|
331
499
|
const logic = {
|
|
332
|
-
config:
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
return {
|
|
340
|
-
...state,
|
|
341
|
-
status: 'done',
|
|
342
|
-
data: event.data,
|
|
343
|
-
input: undefined
|
|
344
|
-
};
|
|
345
|
-
case rejectEventType:
|
|
346
|
-
return {
|
|
347
|
-
...state,
|
|
348
|
-
status: 'error',
|
|
349
|
-
data: event.data,
|
|
350
|
-
input: undefined
|
|
351
|
-
};
|
|
352
|
-
case stopSignalType:
|
|
353
|
-
return {
|
|
354
|
-
...state,
|
|
355
|
-
status: 'canceled',
|
|
356
|
-
input: undefined
|
|
357
|
-
};
|
|
358
|
-
default:
|
|
359
|
-
return state;
|
|
360
|
-
}
|
|
500
|
+
config: invokeCallback,
|
|
501
|
+
start: (_state, {
|
|
502
|
+
self
|
|
503
|
+
}) => {
|
|
504
|
+
self.send({
|
|
505
|
+
type: startSignalType
|
|
506
|
+
});
|
|
361
507
|
},
|
|
362
|
-
|
|
508
|
+
transition: (state, event, {
|
|
363
509
|
self,
|
|
510
|
+
id,
|
|
364
511
|
system
|
|
365
512
|
}) => {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
data: response
|
|
513
|
+
if (event.type === startSignalType) {
|
|
514
|
+
const sendBack = eventForParent => {
|
|
515
|
+
if (state.canceled) {
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
self._parent?.send(eventForParent);
|
|
519
|
+
};
|
|
520
|
+
const receive = newListener => {
|
|
521
|
+
state.receivers.add(newListener);
|
|
522
|
+
};
|
|
523
|
+
state.dispose = invokeCallback({
|
|
524
|
+
input: state.input,
|
|
525
|
+
system,
|
|
526
|
+
self: self,
|
|
527
|
+
sendBack,
|
|
528
|
+
receive
|
|
383
529
|
});
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
530
|
+
if (isPromiseLike(state.dispose)) {
|
|
531
|
+
state.dispose.then(resolved => {
|
|
532
|
+
self._parent?.send(doneInvoke(id, resolved));
|
|
533
|
+
state.canceled = true;
|
|
534
|
+
}, errorData => {
|
|
535
|
+
state.canceled = true;
|
|
536
|
+
self._parent?.send(error(id, errorData));
|
|
537
|
+
});
|
|
388
538
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
539
|
+
return state;
|
|
540
|
+
}
|
|
541
|
+
if (event.type === stopSignalType) {
|
|
542
|
+
state.canceled = true;
|
|
543
|
+
if (typeof state.dispose === 'function') {
|
|
544
|
+
state.dispose();
|
|
545
|
+
}
|
|
546
|
+
return state;
|
|
547
|
+
}
|
|
548
|
+
if (isSignal(event)) {
|
|
549
|
+
// TODO: unrecognized signal
|
|
550
|
+
return state;
|
|
551
|
+
}
|
|
552
|
+
state.receivers.forEach(receiver => receiver(event));
|
|
553
|
+
return state;
|
|
394
554
|
},
|
|
395
555
|
getInitialState: (_, input) => {
|
|
396
556
|
return {
|
|
397
|
-
|
|
398
|
-
|
|
557
|
+
canceled: false,
|
|
558
|
+
receivers: new Set(),
|
|
559
|
+
dispose: undefined,
|
|
399
560
|
input
|
|
400
561
|
};
|
|
401
562
|
},
|
|
402
|
-
getSnapshot:
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
563
|
+
getSnapshot: () => undefined,
|
|
564
|
+
getPersistedState: ({
|
|
565
|
+
input
|
|
566
|
+
}) => input
|
|
406
567
|
};
|
|
407
568
|
return logic;
|
|
408
569
|
}
|
|
409
570
|
|
|
410
|
-
// TODO: this likely shouldn't accept TEvent, observable actor doesn't accept external events
|
|
411
571
|
function fromObservable(observableCreator) {
|
|
412
572
|
const nextEventType = '$$xstate.next';
|
|
413
573
|
const errorEventType = '$$xstate.error';
|
|
@@ -483,7 +643,8 @@ function fromObservable(observableCreator) {
|
|
|
483
643
|
}
|
|
484
644
|
state.subscription = observableCreator({
|
|
485
645
|
input: state.input,
|
|
486
|
-
system
|
|
646
|
+
system,
|
|
647
|
+
self
|
|
487
648
|
}).subscribe({
|
|
488
649
|
next: value => {
|
|
489
650
|
self.send({
|
|
@@ -589,7 +750,8 @@ function fromEventObservable(lazyObservable) {
|
|
|
589
750
|
}
|
|
590
751
|
state.subscription = lazyObservable({
|
|
591
752
|
input: state.input,
|
|
592
|
-
system
|
|
753
|
+
system,
|
|
754
|
+
self
|
|
593
755
|
}).subscribe({
|
|
594
756
|
next: value => {
|
|
595
757
|
self._parent?.send(value);
|
|
@@ -626,251 +788,88 @@ function fromEventObservable(lazyObservable) {
|
|
|
626
788
|
return logic;
|
|
627
789
|
}
|
|
628
790
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
// Parent more specific than child
|
|
638
|
-
return false;
|
|
639
|
-
}
|
|
640
|
-
if (typeof parentStateValue === 'string') {
|
|
641
|
-
return parentStateValue in childStateValue;
|
|
642
|
-
}
|
|
643
|
-
return Object.keys(parentStateValue).every(key => {
|
|
644
|
-
if (!(key in childStateValue)) {
|
|
645
|
-
return false;
|
|
646
|
-
}
|
|
647
|
-
return matchesState(parentStateValue[key], childStateValue[key]);
|
|
648
|
-
});
|
|
649
|
-
}
|
|
650
|
-
function toStatePath(stateId) {
|
|
651
|
-
try {
|
|
652
|
-
if (isArray(stateId)) {
|
|
653
|
-
return stateId;
|
|
654
|
-
}
|
|
655
|
-
return stateId.toString().split(STATE_DELIMITER);
|
|
656
|
-
} catch (e) {
|
|
657
|
-
throw new Error(`'${stateId}' is not a valid state path.`);
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
function isStateLike(state) {
|
|
661
|
-
return typeof state === 'object' && 'value' in state && 'context' in state && 'event' in state;
|
|
662
|
-
}
|
|
663
|
-
function toStateValue(stateValue) {
|
|
664
|
-
if (isStateLike(stateValue)) {
|
|
665
|
-
return stateValue.value;
|
|
666
|
-
}
|
|
667
|
-
if (isArray(stateValue)) {
|
|
668
|
-
return pathToStateValue(stateValue);
|
|
669
|
-
}
|
|
670
|
-
if (typeof stateValue !== 'string') {
|
|
671
|
-
return stateValue;
|
|
672
|
-
}
|
|
673
|
-
const statePath = toStatePath(stateValue);
|
|
674
|
-
return pathToStateValue(statePath);
|
|
675
|
-
}
|
|
676
|
-
function pathToStateValue(statePath) {
|
|
677
|
-
if (statePath.length === 1) {
|
|
678
|
-
return statePath[0];
|
|
679
|
-
}
|
|
680
|
-
const value = {};
|
|
681
|
-
let marker = value;
|
|
682
|
-
for (let i = 0; i < statePath.length - 1; i++) {
|
|
683
|
-
if (i === statePath.length - 2) {
|
|
684
|
-
marker[statePath[i]] = statePath[i + 1];
|
|
685
|
-
} else {
|
|
686
|
-
const previous = marker;
|
|
687
|
-
marker = {};
|
|
688
|
-
previous[statePath[i]] = marker;
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
return value;
|
|
692
|
-
}
|
|
693
|
-
function mapValues(collection, iteratee) {
|
|
694
|
-
const result = {};
|
|
695
|
-
const collectionKeys = Object.keys(collection);
|
|
696
|
-
for (let i = 0; i < collectionKeys.length; i++) {
|
|
697
|
-
const key = collectionKeys[i];
|
|
698
|
-
result[key] = iteratee(collection[key], key, collection, i);
|
|
699
|
-
}
|
|
700
|
-
return result;
|
|
701
|
-
}
|
|
702
|
-
function flatten(array) {
|
|
703
|
-
return [].concat(...array);
|
|
704
|
-
}
|
|
705
|
-
function toArrayStrict(value) {
|
|
706
|
-
if (isArray(value)) {
|
|
707
|
-
return value;
|
|
708
|
-
}
|
|
709
|
-
return [value];
|
|
710
|
-
}
|
|
711
|
-
function toArray(value) {
|
|
712
|
-
if (value === undefined) {
|
|
713
|
-
return [];
|
|
714
|
-
}
|
|
715
|
-
return toArrayStrict(value);
|
|
716
|
-
}
|
|
717
|
-
function mapContext(mapper, context, event) {
|
|
718
|
-
if (typeof mapper === 'function') {
|
|
719
|
-
return mapper({
|
|
720
|
-
context,
|
|
721
|
-
event
|
|
722
|
-
});
|
|
723
|
-
}
|
|
724
|
-
const result = {};
|
|
725
|
-
const args = {
|
|
726
|
-
context,
|
|
727
|
-
event
|
|
728
|
-
};
|
|
729
|
-
for (const key of Object.keys(mapper)) {
|
|
730
|
-
const subMapper = mapper[key];
|
|
731
|
-
if (typeof subMapper === 'function') {
|
|
732
|
-
result[key] = subMapper(args);
|
|
733
|
-
} else {
|
|
734
|
-
result[key] = subMapper;
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
return result;
|
|
738
|
-
}
|
|
739
|
-
function isPromiseLike(value) {
|
|
740
|
-
if (value instanceof Promise) {
|
|
741
|
-
return true;
|
|
742
|
-
}
|
|
743
|
-
// Check if shape matches the Promise/A+ specification for a "thenable".
|
|
744
|
-
if (value !== null && (typeof value === 'function' || typeof value === 'object') && typeof value.then === 'function') {
|
|
745
|
-
return true;
|
|
746
|
-
}
|
|
747
|
-
return false;
|
|
748
|
-
}
|
|
749
|
-
function isArray(value) {
|
|
750
|
-
return Array.isArray(value);
|
|
751
|
-
}
|
|
752
|
-
function isErrorEvent(event) {
|
|
753
|
-
return typeof event.type === 'string' && (event.type === errorExecution || event.type.startsWith(errorPlatform));
|
|
754
|
-
}
|
|
755
|
-
function toTransitionConfigArray(configLike) {
|
|
756
|
-
return toArrayStrict(configLike).map(transitionLike => {
|
|
757
|
-
if (typeof transitionLike === 'undefined' || typeof transitionLike === 'string') {
|
|
758
|
-
return {
|
|
759
|
-
target: transitionLike
|
|
760
|
-
};
|
|
761
|
-
}
|
|
762
|
-
return transitionLike;
|
|
763
|
-
});
|
|
764
|
-
}
|
|
765
|
-
function normalizeTarget(target) {
|
|
766
|
-
if (target === undefined || target === TARGETLESS_KEY) {
|
|
767
|
-
return undefined;
|
|
768
|
-
}
|
|
769
|
-
return toArray(target);
|
|
770
|
-
}
|
|
771
|
-
function toInvokeConfig(invocable, id) {
|
|
772
|
-
if (typeof invocable === 'object') {
|
|
773
|
-
if ('src' in invocable) {
|
|
774
|
-
return invocable;
|
|
775
|
-
}
|
|
776
|
-
if ('transition' in invocable) {
|
|
777
|
-
return {
|
|
778
|
-
id,
|
|
779
|
-
src: invocable
|
|
780
|
-
};
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
return {
|
|
784
|
-
id,
|
|
785
|
-
src: invocable
|
|
786
|
-
};
|
|
787
|
-
}
|
|
788
|
-
function toObserver(nextHandler, errorHandler, completionHandler) {
|
|
789
|
-
const noop = () => {};
|
|
790
|
-
const isObserver = typeof nextHandler === 'object';
|
|
791
|
-
const self = isObserver ? nextHandler : null;
|
|
792
|
-
return {
|
|
793
|
-
next: ((isObserver ? nextHandler.next : nextHandler) || noop).bind(self),
|
|
794
|
-
error: ((isObserver ? nextHandler.error : errorHandler) || noop).bind(self),
|
|
795
|
-
complete: ((isObserver ? nextHandler.complete : completionHandler) || noop).bind(self)
|
|
796
|
-
};
|
|
797
|
-
}
|
|
798
|
-
function createInvokeId(stateNodeId, index) {
|
|
799
|
-
return `${stateNodeId}:invocation[${index}]`;
|
|
800
|
-
}
|
|
801
|
-
function resolveReferencedActor(referenced) {
|
|
802
|
-
return referenced ? 'transition' in referenced ? {
|
|
803
|
-
src: referenced,
|
|
804
|
-
input: undefined
|
|
805
|
-
} : referenced : undefined;
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
function fromCallback(invokeCallback) {
|
|
791
|
+
const resolveEventType = '$$xstate.resolve';
|
|
792
|
+
const rejectEventType = '$$xstate.reject';
|
|
793
|
+
function fromPromise(
|
|
794
|
+
// TODO: add types
|
|
795
|
+
promiseCreator) {
|
|
796
|
+
// TODO: add event types
|
|
809
797
|
const logic = {
|
|
810
|
-
config:
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
798
|
+
config: promiseCreator,
|
|
799
|
+
transition: (state, event) => {
|
|
800
|
+
if (state.status !== 'active') {
|
|
801
|
+
return state;
|
|
802
|
+
}
|
|
803
|
+
switch (event.type) {
|
|
804
|
+
case resolveEventType:
|
|
805
|
+
return {
|
|
806
|
+
...state,
|
|
807
|
+
status: 'done',
|
|
808
|
+
data: event.data,
|
|
809
|
+
input: undefined
|
|
810
|
+
};
|
|
811
|
+
case rejectEventType:
|
|
812
|
+
return {
|
|
813
|
+
...state,
|
|
814
|
+
status: 'error',
|
|
815
|
+
data: event.data,
|
|
816
|
+
input: undefined
|
|
817
|
+
};
|
|
818
|
+
case stopSignalType:
|
|
819
|
+
return {
|
|
820
|
+
...state,
|
|
821
|
+
status: 'canceled',
|
|
822
|
+
input: undefined
|
|
823
|
+
};
|
|
824
|
+
default:
|
|
825
|
+
return state;
|
|
826
|
+
}
|
|
817
827
|
},
|
|
818
|
-
|
|
828
|
+
start: (state, {
|
|
819
829
|
self,
|
|
820
|
-
id,
|
|
821
830
|
system
|
|
822
831
|
}) => {
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
}
|
|
828
|
-
self._parent?.send(eventForParent);
|
|
829
|
-
};
|
|
830
|
-
const receiver = newListener => {
|
|
831
|
-
state.receivers.add(newListener);
|
|
832
|
-
};
|
|
833
|
-
state.dispose = invokeCallback(sender, receiver, {
|
|
834
|
-
input: state.input,
|
|
835
|
-
system
|
|
836
|
-
});
|
|
837
|
-
if (isPromiseLike(state.dispose)) {
|
|
838
|
-
state.dispose.then(resolved => {
|
|
839
|
-
self._parent?.send(doneInvoke(id, resolved));
|
|
840
|
-
state.canceled = true;
|
|
841
|
-
}, errorData => {
|
|
842
|
-
state.canceled = true;
|
|
843
|
-
self._parent?.send(error(id, errorData));
|
|
844
|
-
});
|
|
845
|
-
}
|
|
846
|
-
return state;
|
|
832
|
+
// TODO: determine how to allow customizing this so that promises
|
|
833
|
+
// can be restarted if necessary
|
|
834
|
+
if (state.status !== 'active') {
|
|
835
|
+
return;
|
|
847
836
|
}
|
|
848
|
-
|
|
849
|
-
state.
|
|
850
|
-
|
|
851
|
-
|
|
837
|
+
const resolvedPromise = Promise.resolve(promiseCreator({
|
|
838
|
+
input: state.input,
|
|
839
|
+
system,
|
|
840
|
+
self
|
|
841
|
+
}));
|
|
842
|
+
resolvedPromise.then(response => {
|
|
843
|
+
// TODO: remove this condition once dead letter queue lands
|
|
844
|
+
if (self._state.status !== 'active') {
|
|
845
|
+
return;
|
|
852
846
|
}
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
847
|
+
self.send({
|
|
848
|
+
type: resolveEventType,
|
|
849
|
+
data: response
|
|
850
|
+
});
|
|
851
|
+
}, errorData => {
|
|
852
|
+
// TODO: remove this condition once dead letter queue lands
|
|
853
|
+
if (self._state.status !== 'active') {
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
856
|
+
self.send({
|
|
857
|
+
type: rejectEventType,
|
|
858
|
+
data: errorData
|
|
859
|
+
});
|
|
860
|
+
});
|
|
861
861
|
},
|
|
862
862
|
getInitialState: (_, input) => {
|
|
863
863
|
return {
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
dispose: undefined,
|
|
864
|
+
status: 'active',
|
|
865
|
+
data: undefined,
|
|
867
866
|
input
|
|
868
867
|
};
|
|
869
868
|
},
|
|
870
|
-
getSnapshot:
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
869
|
+
getSnapshot: state => state.data,
|
|
870
|
+
getStatus: state => state,
|
|
871
|
+
getPersistedState: state => state,
|
|
872
|
+
restoreState: state => state
|
|
874
873
|
};
|
|
875
874
|
return logic;
|
|
876
875
|
}
|
|
@@ -909,6 +908,7 @@ function toActorRef(actorRefLike) {
|
|
|
909
908
|
id: 'anonymous',
|
|
910
909
|
sessionId: '',
|
|
911
910
|
getSnapshot: () => undefined,
|
|
911
|
+
// TODO: this isn't safe
|
|
912
912
|
[symbolObservable]: function () {
|
|
913
913
|
return this;
|
|
914
914
|
},
|
|
@@ -2768,7 +2768,7 @@ function createSpawner(actorContext, {
|
|
|
2768
2768
|
}
|
|
2769
2769
|
};
|
|
2770
2770
|
return (src, options) => {
|
|
2771
|
-
const actorRef = spawn(src, options);
|
|
2771
|
+
const actorRef = spawn(src, options); // TODO: fix types
|
|
2772
2772
|
spawnedChildren[actorRef.id] = actorRef;
|
|
2773
2773
|
actorContext.defer(() => {
|
|
2774
2774
|
if (actorRef.status === ActorStatus.Stopped) {
|