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