@storybook/instrumenter 7.0.0-alpha.21 → 7.0.0-alpha.25
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/dist/cjs/instrumenter.js +85 -66
- package/dist/esm/instrumenter.js +84 -65
- package/dist/types/instrumenter.d.ts +1 -1
- package/dist/types/types.d.ts +4 -4
- package/package.json +5 -12
package/dist/cjs/instrumenter.js
CHANGED
|
@@ -29,13 +29,13 @@ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typ
|
|
|
29
29
|
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
30
30
|
|
|
31
31
|
const EVENTS = {
|
|
32
|
-
CALL: 'instrumenter/call',
|
|
33
|
-
SYNC: 'instrumenter/sync',
|
|
34
|
-
START: 'instrumenter/start',
|
|
35
|
-
BACK: 'instrumenter/back',
|
|
36
|
-
GOTO: 'instrumenter/goto',
|
|
37
|
-
NEXT: 'instrumenter/next',
|
|
38
|
-
END: 'instrumenter/end'
|
|
32
|
+
CALL: 'storybook/instrumenter/call',
|
|
33
|
+
SYNC: 'storybook/instrumenter/sync',
|
|
34
|
+
START: 'storybook/instrumenter/start',
|
|
35
|
+
BACK: 'storybook/instrumenter/back',
|
|
36
|
+
GOTO: 'storybook/instrumenter/goto',
|
|
37
|
+
NEXT: 'storybook/instrumenter/next',
|
|
38
|
+
END: 'storybook/instrumenter/end'
|
|
39
39
|
};
|
|
40
40
|
exports.EVENTS = EVENTS;
|
|
41
41
|
const debuggerDisabled = ((_global$FEATURES = _global.default.FEATURES) === null || _global$FEATURES === void 0 ? void 0 : _global$FEATURES.interactionsDebugger) !== true;
|
|
@@ -80,7 +80,7 @@ const getInitialState = () => ({
|
|
|
80
80
|
shadowCalls: [],
|
|
81
81
|
callRefsByResult: new Map(),
|
|
82
82
|
chainedCallIds: new Set(),
|
|
83
|
-
|
|
83
|
+
ancestors: [],
|
|
84
84
|
playUntil: undefined,
|
|
85
85
|
resolvers: {},
|
|
86
86
|
syncTimeout: undefined
|
|
@@ -109,7 +109,7 @@ class Instrumenter {
|
|
|
109
109
|
this.state = void 0;
|
|
110
110
|
this.channel = _addons.addons.getChannel(); // Restore state from the parent window in case the iframe was reloaded.
|
|
111
111
|
|
|
112
|
-
this.state = _global.default.window.parent.__STORYBOOK_ADDON_INTERACTIONS_INSTRUMENTER_STATE__ || {}; // When called from `start`, isDebugging will be true
|
|
112
|
+
this.state = _global.default.window.parent.__STORYBOOK_ADDON_INTERACTIONS_INSTRUMENTER_STATE__ || {}; // When called from `start`, isDebugging will be true.
|
|
113
113
|
|
|
114
114
|
const resetState = ({
|
|
115
115
|
storyId,
|
|
@@ -123,9 +123,8 @@ class Instrumenter {
|
|
|
123
123
|
playUntil: isDebugging ? state.playUntil : undefined,
|
|
124
124
|
isPlaying,
|
|
125
125
|
isDebugging
|
|
126
|
-
}));
|
|
127
|
-
|
|
128
|
-
if (!isDebugging) this.sync(storyId);
|
|
126
|
+
}));
|
|
127
|
+
this.sync(storyId);
|
|
129
128
|
}; // A forceRemount might be triggered for debugging (on `start`), or elsewhere in Storybook.
|
|
130
129
|
|
|
131
130
|
|
|
@@ -180,6 +179,8 @@ class Instrumenter {
|
|
|
180
179
|
playUntil
|
|
181
180
|
}) => {
|
|
182
181
|
if (!this.getState(storyId).isDebugging) {
|
|
182
|
+
// Move everything into shadowCalls (a "carbon copy") and mark them as "waiting", so we keep
|
|
183
|
+
// a record of the original calls which haven't yet been executed while stepping through.
|
|
183
184
|
this.setState(storyId, ({
|
|
184
185
|
calls
|
|
185
186
|
}) => ({
|
|
@@ -197,9 +198,12 @@ class Instrumenter {
|
|
|
197
198
|
}) => {
|
|
198
199
|
var _shadowCalls$slice$fi;
|
|
199
200
|
|
|
201
|
+
if (playUntil || !log.length) return {
|
|
202
|
+
playUntil
|
|
203
|
+
};
|
|
200
204
|
const firstRowIndex = shadowCalls.findIndex(call => call.id === log[0].callId);
|
|
201
205
|
return {
|
|
202
|
-
playUntil:
|
|
206
|
+
playUntil: (_shadowCalls$slice$fi = shadowCalls.slice(0, firstRowIndex).filter(call => call.interceptable && !call.ancestors.length).slice(-1)[0]) === null || _shadowCalls$slice$fi === void 0 ? void 0 : _shadowCalls$slice$fi.id
|
|
203
207
|
};
|
|
204
208
|
}); // Force remount may trigger a page reload if the play function can't be aborted.
|
|
205
209
|
|
|
@@ -214,7 +218,7 @@ class Instrumenter {
|
|
|
214
218
|
}) => {
|
|
215
219
|
var _log;
|
|
216
220
|
|
|
217
|
-
const log = this.getLog(storyId).filter(call => !call.
|
|
221
|
+
const log = this.getLog(storyId).filter(call => !call.ancestors.length);
|
|
218
222
|
const last = log.reduceRight((res, item, index) => {
|
|
219
223
|
if (res >= 0 || item.status === _types.CallStates.WAITING) return res;
|
|
220
224
|
return index;
|
|
@@ -352,7 +356,7 @@ class Instrumenter {
|
|
|
352
356
|
acc.unshift({
|
|
353
357
|
callId: call.id,
|
|
354
358
|
status: call.status,
|
|
355
|
-
|
|
359
|
+
ancestors: call.ancestors
|
|
356
360
|
});
|
|
357
361
|
seen.add(call.id);
|
|
358
362
|
}
|
|
@@ -415,12 +419,12 @@ class Instrumenter {
|
|
|
415
419
|
const storyId = (args === null || args === void 0 ? void 0 : (_args$ = args[0]) === null || _args$ === void 0 ? void 0 : _args$.__storyId__) || ((_global$window$__STOR = _global.default.window.__STORYBOOK_PREVIEW__) === null || _global$window$__STOR === void 0 ? void 0 : (_global$window$__STOR2 = _global$window$__STOR.urlStore) === null || _global$window$__STOR2 === void 0 ? void 0 : (_global$window$__STOR3 = _global$window$__STOR2.selection) === null || _global$window$__STOR3 === void 0 ? void 0 : _global$window$__STOR3.storyId);
|
|
416
420
|
const {
|
|
417
421
|
cursor,
|
|
418
|
-
|
|
422
|
+
ancestors
|
|
419
423
|
} = this.getState(storyId);
|
|
420
424
|
this.setState(storyId, {
|
|
421
425
|
cursor: cursor + 1
|
|
422
426
|
});
|
|
423
|
-
const id = `${
|
|
427
|
+
const id = `${ancestors.slice(-1)[0] || storyId} [${cursor}] ${method}`;
|
|
424
428
|
const {
|
|
425
429
|
path = [],
|
|
426
430
|
intercept = false,
|
|
@@ -429,16 +433,16 @@ class Instrumenter {
|
|
|
429
433
|
const interceptable = typeof intercept === 'function' ? intercept(method, path) : intercept;
|
|
430
434
|
const call = {
|
|
431
435
|
id,
|
|
432
|
-
parentId,
|
|
433
|
-
storyId,
|
|
434
436
|
cursor,
|
|
437
|
+
storyId,
|
|
438
|
+
ancestors,
|
|
435
439
|
path,
|
|
436
440
|
method,
|
|
437
441
|
args,
|
|
438
442
|
interceptable,
|
|
439
443
|
retain
|
|
440
444
|
};
|
|
441
|
-
const interceptOrInvoke = interceptable && !
|
|
445
|
+
const interceptOrInvoke = interceptable && !ancestors.length ? this.intercept : this.invoke;
|
|
442
446
|
const result = interceptOrInvoke.call(this, fn, call, options);
|
|
443
447
|
return this.instrument(result, Object.assign({}, options, {
|
|
444
448
|
mutate: true,
|
|
@@ -640,10 +644,13 @@ class Instrumenter {
|
|
|
640
644
|
}]])
|
|
641
645
|
})); // Exceptions inside callbacks should bubble up to the parent call.
|
|
642
646
|
|
|
643
|
-
if (call.
|
|
644
|
-
Object.
|
|
645
|
-
|
|
646
|
-
|
|
647
|
+
if (call.ancestors.length) {
|
|
648
|
+
if (!Object.prototype.hasOwnProperty.call(e, 'callId')) {
|
|
649
|
+
Object.defineProperty(e, 'callId', {
|
|
650
|
+
value: call.id
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
|
|
647
654
|
throw e;
|
|
648
655
|
} // We need to throw to break out of the play function, but we don't want to trigger a redbox
|
|
649
656
|
// so we throw an ignoredException, which is caught and silently ignored by Storybook.
|
|
@@ -672,25 +679,26 @@ class Instrumenter {
|
|
|
672
679
|
// We only want to wrap plain functions, not objects.
|
|
673
680
|
if (typeof arg !== 'function' || Object.keys(arg).length) return arg;
|
|
674
681
|
return (...args) => {
|
|
675
|
-
// Set the cursor and
|
|
682
|
+
// Set the cursor and ancestors for calls that happen inside the callback.
|
|
676
683
|
const {
|
|
677
684
|
cursor,
|
|
678
|
-
|
|
685
|
+
ancestors
|
|
679
686
|
} = this.getState(call.storyId);
|
|
680
687
|
this.setState(call.storyId, {
|
|
681
688
|
cursor: 0,
|
|
682
|
-
|
|
689
|
+
ancestors: [...ancestors, call.id]
|
|
683
690
|
});
|
|
684
691
|
|
|
685
692
|
const restore = () => this.setState(call.storyId, {
|
|
686
693
|
cursor,
|
|
687
|
-
|
|
694
|
+
ancestors
|
|
688
695
|
}); // Invoke the actual callback function.
|
|
689
696
|
|
|
690
697
|
|
|
691
|
-
const res = arg(...args); // Reset cursor and
|
|
698
|
+
const res = arg(...args); // Reset cursor and ancestors to their original values before we entered the callback.
|
|
692
699
|
|
|
693
|
-
if (res instanceof Promise) res.then(restore, restore);
|
|
700
|
+
if (res instanceof Promise) return res.then(restore, restore);
|
|
701
|
+
restore();
|
|
694
702
|
return res;
|
|
695
703
|
};
|
|
696
704
|
});
|
|
@@ -723,12 +731,10 @@ class Instrumenter {
|
|
|
723
731
|
} catch (e) {
|
|
724
732
|
return handleException(e);
|
|
725
733
|
}
|
|
726
|
-
} // Sends the call info and
|
|
727
|
-
// Uses a 0ms debounce because this might get called many times in one tick.
|
|
734
|
+
} // Sends the call info to the manager and synchronizes the log.
|
|
728
735
|
|
|
729
736
|
|
|
730
737
|
update(call) {
|
|
731
|
-
clearTimeout(this.getState(call.storyId).syncTimeout);
|
|
732
738
|
this.channel.emit(EVENTS.CALL, call);
|
|
733
739
|
this.setState(call.storyId, ({
|
|
734
740
|
calls
|
|
@@ -742,49 +748,62 @@ class Instrumenter {
|
|
|
742
748
|
// Calls are sorted to ensure parent calls always come before calls in their callback.
|
|
743
749
|
calls: Object.values(callsById).sort((a, b) => a.id.localeCompare(b.id, undefined, {
|
|
744
750
|
numeric: true
|
|
745
|
-
}))
|
|
746
|
-
syncTimeout: setTimeout(() => this.sync(call.storyId), 0)
|
|
751
|
+
}))
|
|
747
752
|
};
|
|
748
753
|
});
|
|
749
|
-
|
|
754
|
+
this.sync(call.storyId);
|
|
755
|
+
} // Builds a log of interceptable calls and control states and sends it to the manager.
|
|
756
|
+
// Uses a 0ms debounce because this might get called many times in one tick.
|
|
757
|
+
|
|
750
758
|
|
|
751
759
|
sync(storyId) {
|
|
752
|
-
|
|
760
|
+
const synchronize = () => {
|
|
761
|
+
var _logItems$filter$find;
|
|
753
762
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
+
const {
|
|
764
|
+
isLocked,
|
|
765
|
+
isPlaying
|
|
766
|
+
} = this.getState(storyId);
|
|
767
|
+
const logItems = this.getLog(storyId);
|
|
768
|
+
const pausedAt = (_logItems$filter$find = logItems.filter(({
|
|
769
|
+
ancestors
|
|
770
|
+
}) => !ancestors.length).find(item => item.status === _types.CallStates.WAITING)) === null || _logItems$filter$find === void 0 ? void 0 : _logItems$filter$find.callId;
|
|
771
|
+
const hasActive = logItems.some(item => item.status === _types.CallStates.ACTIVE);
|
|
772
|
+
|
|
773
|
+
if (debuggerDisabled || isLocked || hasActive || logItems.length === 0) {
|
|
774
|
+
const payload = {
|
|
775
|
+
controlStates: controlsDisabled,
|
|
776
|
+
logItems
|
|
777
|
+
};
|
|
778
|
+
this.channel.emit(EVENTS.SYNC, payload);
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
763
781
|
|
|
764
|
-
|
|
782
|
+
const hasPrevious = logItems.some(item => [_types.CallStates.DONE, _types.CallStates.ERROR].includes(item.status));
|
|
783
|
+
const controlStates = {
|
|
784
|
+
debugger: true,
|
|
785
|
+
start: hasPrevious,
|
|
786
|
+
back: hasPrevious,
|
|
787
|
+
goto: true,
|
|
788
|
+
next: isPlaying,
|
|
789
|
+
end: isPlaying
|
|
790
|
+
};
|
|
765
791
|
const payload = {
|
|
766
|
-
controlStates
|
|
767
|
-
logItems
|
|
792
|
+
controlStates,
|
|
793
|
+
logItems,
|
|
794
|
+
pausedAt
|
|
768
795
|
};
|
|
769
796
|
this.channel.emit(EVENTS.SYNC, payload);
|
|
770
|
-
return;
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
const hasPrevious = logItems.some(item => [_types.CallStates.DONE, _types.CallStates.ERROR].includes(item.status));
|
|
774
|
-
const controlStates = {
|
|
775
|
-
debugger: true,
|
|
776
|
-
start: hasPrevious,
|
|
777
|
-
back: hasPrevious,
|
|
778
|
-
goto: true,
|
|
779
|
-
next: isPlaying,
|
|
780
|
-
end: isPlaying
|
|
781
|
-
};
|
|
782
|
-
const payload = {
|
|
783
|
-
controlStates,
|
|
784
|
-
logItems,
|
|
785
|
-
pausedAt
|
|
786
797
|
};
|
|
787
|
-
|
|
798
|
+
|
|
799
|
+
this.setState(storyId, ({
|
|
800
|
+
syncTimeout
|
|
801
|
+
}) => {
|
|
802
|
+
clearTimeout(syncTimeout);
|
|
803
|
+
return {
|
|
804
|
+
syncTimeout: setTimeout(synchronize, 0)
|
|
805
|
+
};
|
|
806
|
+
});
|
|
788
807
|
}
|
|
789
808
|
|
|
790
809
|
}
|
package/dist/esm/instrumenter.js
CHANGED
|
@@ -13,13 +13,13 @@ import { FORCE_REMOUNT, IGNORED_EXCEPTION, SET_CURRENT_STORY, STORY_RENDER_PHASE
|
|
|
13
13
|
import global from 'global';
|
|
14
14
|
import { CallStates } from './types';
|
|
15
15
|
export const EVENTS = {
|
|
16
|
-
CALL: 'instrumenter/call',
|
|
17
|
-
SYNC: 'instrumenter/sync',
|
|
18
|
-
START: 'instrumenter/start',
|
|
19
|
-
BACK: 'instrumenter/back',
|
|
20
|
-
GOTO: 'instrumenter/goto',
|
|
21
|
-
NEXT: 'instrumenter/next',
|
|
22
|
-
END: 'instrumenter/end'
|
|
16
|
+
CALL: 'storybook/instrumenter/call',
|
|
17
|
+
SYNC: 'storybook/instrumenter/sync',
|
|
18
|
+
START: 'storybook/instrumenter/start',
|
|
19
|
+
BACK: 'storybook/instrumenter/back',
|
|
20
|
+
GOTO: 'storybook/instrumenter/goto',
|
|
21
|
+
NEXT: 'storybook/instrumenter/next',
|
|
22
|
+
END: 'storybook/instrumenter/end'
|
|
23
23
|
};
|
|
24
24
|
const debuggerDisabled = global.FEATURES?.interactionsDebugger !== true;
|
|
25
25
|
const controlsDisabled = {
|
|
@@ -63,7 +63,7 @@ const getInitialState = () => ({
|
|
|
63
63
|
shadowCalls: [],
|
|
64
64
|
callRefsByResult: new Map(),
|
|
65
65
|
chainedCallIds: new Set(),
|
|
66
|
-
|
|
66
|
+
ancestors: [],
|
|
67
67
|
playUntil: undefined,
|
|
68
68
|
resolvers: {},
|
|
69
69
|
syncTimeout: undefined
|
|
@@ -92,7 +92,7 @@ export class Instrumenter {
|
|
|
92
92
|
this.state = void 0;
|
|
93
93
|
this.channel = addons.getChannel(); // Restore state from the parent window in case the iframe was reloaded.
|
|
94
94
|
|
|
95
|
-
this.state = global.window.parent.__STORYBOOK_ADDON_INTERACTIONS_INSTRUMENTER_STATE__ || {}; // When called from `start`, isDebugging will be true
|
|
95
|
+
this.state = global.window.parent.__STORYBOOK_ADDON_INTERACTIONS_INSTRUMENTER_STATE__ || {}; // When called from `start`, isDebugging will be true.
|
|
96
96
|
|
|
97
97
|
const resetState = ({
|
|
98
98
|
storyId,
|
|
@@ -106,9 +106,8 @@ export class Instrumenter {
|
|
|
106
106
|
playUntil: isDebugging ? state.playUntil : undefined,
|
|
107
107
|
isPlaying,
|
|
108
108
|
isDebugging
|
|
109
|
-
}));
|
|
110
|
-
|
|
111
|
-
if (!isDebugging) this.sync(storyId);
|
|
109
|
+
}));
|
|
110
|
+
this.sync(storyId);
|
|
112
111
|
}; // A forceRemount might be triggered for debugging (on `start`), or elsewhere in Storybook.
|
|
113
112
|
|
|
114
113
|
|
|
@@ -163,6 +162,8 @@ export class Instrumenter {
|
|
|
163
162
|
playUntil
|
|
164
163
|
}) => {
|
|
165
164
|
if (!this.getState(storyId).isDebugging) {
|
|
165
|
+
// Move everything into shadowCalls (a "carbon copy") and mark them as "waiting", so we keep
|
|
166
|
+
// a record of the original calls which haven't yet been executed while stepping through.
|
|
166
167
|
this.setState(storyId, ({
|
|
167
168
|
calls
|
|
168
169
|
}) => ({
|
|
@@ -178,9 +179,12 @@ export class Instrumenter {
|
|
|
178
179
|
this.setState(storyId, ({
|
|
179
180
|
shadowCalls
|
|
180
181
|
}) => {
|
|
182
|
+
if (playUntil || !log.length) return {
|
|
183
|
+
playUntil
|
|
184
|
+
};
|
|
181
185
|
const firstRowIndex = shadowCalls.findIndex(call => call.id === log[0].callId);
|
|
182
186
|
return {
|
|
183
|
-
playUntil:
|
|
187
|
+
playUntil: shadowCalls.slice(0, firstRowIndex).filter(call => call.interceptable && !call.ancestors.length).slice(-1)[0]?.id
|
|
184
188
|
};
|
|
185
189
|
}); // Force remount may trigger a page reload if the play function can't be aborted.
|
|
186
190
|
|
|
@@ -193,7 +197,7 @@ export class Instrumenter {
|
|
|
193
197
|
const back = ({
|
|
194
198
|
storyId
|
|
195
199
|
}) => {
|
|
196
|
-
const log = this.getLog(storyId).filter(call => !call.
|
|
200
|
+
const log = this.getLog(storyId).filter(call => !call.ancestors.length);
|
|
197
201
|
const last = log.reduceRight((res, item, index) => {
|
|
198
202
|
if (res >= 0 || item.status === CallStates.WAITING) return res;
|
|
199
203
|
return index;
|
|
@@ -327,7 +331,7 @@ export class Instrumenter {
|
|
|
327
331
|
acc.unshift({
|
|
328
332
|
callId: call.id,
|
|
329
333
|
status: call.status,
|
|
330
|
-
|
|
334
|
+
ancestors: call.ancestors
|
|
331
335
|
});
|
|
332
336
|
seen.add(call.id);
|
|
333
337
|
}
|
|
@@ -388,12 +392,12 @@ export class Instrumenter {
|
|
|
388
392
|
const storyId = args?.[0]?.__storyId__ || global.window.__STORYBOOK_PREVIEW__?.urlStore?.selection?.storyId;
|
|
389
393
|
const {
|
|
390
394
|
cursor,
|
|
391
|
-
|
|
395
|
+
ancestors
|
|
392
396
|
} = this.getState(storyId);
|
|
393
397
|
this.setState(storyId, {
|
|
394
398
|
cursor: cursor + 1
|
|
395
399
|
});
|
|
396
|
-
const id = `${
|
|
400
|
+
const id = `${ancestors.slice(-1)[0] || storyId} [${cursor}] ${method}`;
|
|
397
401
|
const {
|
|
398
402
|
path = [],
|
|
399
403
|
intercept = false,
|
|
@@ -402,16 +406,16 @@ export class Instrumenter {
|
|
|
402
406
|
const interceptable = typeof intercept === 'function' ? intercept(method, path) : intercept;
|
|
403
407
|
const call = {
|
|
404
408
|
id,
|
|
405
|
-
parentId,
|
|
406
|
-
storyId,
|
|
407
409
|
cursor,
|
|
410
|
+
storyId,
|
|
411
|
+
ancestors,
|
|
408
412
|
path,
|
|
409
413
|
method,
|
|
410
414
|
args,
|
|
411
415
|
interceptable,
|
|
412
416
|
retain
|
|
413
417
|
};
|
|
414
|
-
const interceptOrInvoke = interceptable && !
|
|
418
|
+
const interceptOrInvoke = interceptable && !ancestors.length ? this.intercept : this.invoke;
|
|
415
419
|
const result = interceptOrInvoke.call(this, fn, call, options);
|
|
416
420
|
return this.instrument(result, Object.assign({}, options, {
|
|
417
421
|
mutate: true,
|
|
@@ -611,10 +615,13 @@ export class Instrumenter {
|
|
|
611
615
|
}]])
|
|
612
616
|
})); // Exceptions inside callbacks should bubble up to the parent call.
|
|
613
617
|
|
|
614
|
-
if (call.
|
|
615
|
-
Object.
|
|
616
|
-
|
|
617
|
-
|
|
618
|
+
if (call.ancestors.length) {
|
|
619
|
+
if (!Object.prototype.hasOwnProperty.call(e, 'callId')) {
|
|
620
|
+
Object.defineProperty(e, 'callId', {
|
|
621
|
+
value: call.id
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
|
|
618
625
|
throw e;
|
|
619
626
|
} // We need to throw to break out of the play function, but we don't want to trigger a redbox
|
|
620
627
|
// so we throw an ignoredException, which is caught and silently ignored by Storybook.
|
|
@@ -642,25 +649,26 @@ export class Instrumenter {
|
|
|
642
649
|
// We only want to wrap plain functions, not objects.
|
|
643
650
|
if (typeof arg !== 'function' || Object.keys(arg).length) return arg;
|
|
644
651
|
return (...args) => {
|
|
645
|
-
// Set the cursor and
|
|
652
|
+
// Set the cursor and ancestors for calls that happen inside the callback.
|
|
646
653
|
const {
|
|
647
654
|
cursor,
|
|
648
|
-
|
|
655
|
+
ancestors
|
|
649
656
|
} = this.getState(call.storyId);
|
|
650
657
|
this.setState(call.storyId, {
|
|
651
658
|
cursor: 0,
|
|
652
|
-
|
|
659
|
+
ancestors: [...ancestors, call.id]
|
|
653
660
|
});
|
|
654
661
|
|
|
655
662
|
const restore = () => this.setState(call.storyId, {
|
|
656
663
|
cursor,
|
|
657
|
-
|
|
664
|
+
ancestors
|
|
658
665
|
}); // Invoke the actual callback function.
|
|
659
666
|
|
|
660
667
|
|
|
661
|
-
const res = arg(...args); // Reset cursor and
|
|
668
|
+
const res = arg(...args); // Reset cursor and ancestors to their original values before we entered the callback.
|
|
662
669
|
|
|
663
|
-
if (res instanceof Promise) res.then(restore, restore);
|
|
670
|
+
if (res instanceof Promise) return res.then(restore, restore);
|
|
671
|
+
restore();
|
|
664
672
|
return res;
|
|
665
673
|
};
|
|
666
674
|
});
|
|
@@ -693,12 +701,10 @@ export class Instrumenter {
|
|
|
693
701
|
} catch (e) {
|
|
694
702
|
return handleException(e);
|
|
695
703
|
}
|
|
696
|
-
} // Sends the call info and
|
|
697
|
-
// Uses a 0ms debounce because this might get called many times in one tick.
|
|
704
|
+
} // Sends the call info to the manager and synchronizes the log.
|
|
698
705
|
|
|
699
706
|
|
|
700
707
|
update(call) {
|
|
701
|
-
clearTimeout(this.getState(call.storyId).syncTimeout);
|
|
702
708
|
this.channel.emit(EVENTS.CALL, call);
|
|
703
709
|
this.setState(call.storyId, ({
|
|
704
710
|
calls
|
|
@@ -712,47 +718,60 @@ export class Instrumenter {
|
|
|
712
718
|
// Calls are sorted to ensure parent calls always come before calls in their callback.
|
|
713
719
|
calls: Object.values(callsById).sort((a, b) => a.id.localeCompare(b.id, undefined, {
|
|
714
720
|
numeric: true
|
|
715
|
-
}))
|
|
716
|
-
syncTimeout: setTimeout(() => this.sync(call.storyId), 0)
|
|
721
|
+
}))
|
|
717
722
|
};
|
|
718
723
|
});
|
|
719
|
-
|
|
724
|
+
this.sync(call.storyId);
|
|
725
|
+
} // Builds a log of interceptable calls and control states and sends it to the manager.
|
|
726
|
+
// Uses a 0ms debounce because this might get called many times in one tick.
|
|
727
|
+
|
|
720
728
|
|
|
721
729
|
sync(storyId) {
|
|
722
|
-
const {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
730
|
+
const synchronize = () => {
|
|
731
|
+
const {
|
|
732
|
+
isLocked,
|
|
733
|
+
isPlaying
|
|
734
|
+
} = this.getState(storyId);
|
|
735
|
+
const logItems = this.getLog(storyId);
|
|
736
|
+
const pausedAt = logItems.filter(({
|
|
737
|
+
ancestors
|
|
738
|
+
}) => !ancestors.length).find(item => item.status === CallStates.WAITING)?.callId;
|
|
739
|
+
const hasActive = logItems.some(item => item.status === CallStates.ACTIVE);
|
|
740
|
+
|
|
741
|
+
if (debuggerDisabled || isLocked || hasActive || logItems.length === 0) {
|
|
742
|
+
const payload = {
|
|
743
|
+
controlStates: controlsDisabled,
|
|
744
|
+
logItems
|
|
745
|
+
};
|
|
746
|
+
this.channel.emit(EVENTS.SYNC, payload);
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
731
749
|
|
|
732
|
-
|
|
750
|
+
const hasPrevious = logItems.some(item => [CallStates.DONE, CallStates.ERROR].includes(item.status));
|
|
751
|
+
const controlStates = {
|
|
752
|
+
debugger: true,
|
|
753
|
+
start: hasPrevious,
|
|
754
|
+
back: hasPrevious,
|
|
755
|
+
goto: true,
|
|
756
|
+
next: isPlaying,
|
|
757
|
+
end: isPlaying
|
|
758
|
+
};
|
|
733
759
|
const payload = {
|
|
734
|
-
controlStates
|
|
735
|
-
logItems
|
|
760
|
+
controlStates,
|
|
761
|
+
logItems,
|
|
762
|
+
pausedAt
|
|
736
763
|
};
|
|
737
764
|
this.channel.emit(EVENTS.SYNC, payload);
|
|
738
|
-
return;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
const hasPrevious = logItems.some(item => [CallStates.DONE, CallStates.ERROR].includes(item.status));
|
|
742
|
-
const controlStates = {
|
|
743
|
-
debugger: true,
|
|
744
|
-
start: hasPrevious,
|
|
745
|
-
back: hasPrevious,
|
|
746
|
-
goto: true,
|
|
747
|
-
next: isPlaying,
|
|
748
|
-
end: isPlaying
|
|
749
|
-
};
|
|
750
|
-
const payload = {
|
|
751
|
-
controlStates,
|
|
752
|
-
logItems,
|
|
753
|
-
pausedAt
|
|
754
765
|
};
|
|
755
|
-
|
|
766
|
+
|
|
767
|
+
this.setState(storyId, ({
|
|
768
|
+
syncTimeout
|
|
769
|
+
}) => {
|
|
770
|
+
clearTimeout(syncTimeout);
|
|
771
|
+
return {
|
|
772
|
+
syncTimeout: setTimeout(synchronize, 0)
|
|
773
|
+
};
|
|
774
|
+
});
|
|
756
775
|
}
|
|
757
776
|
|
|
758
777
|
}
|
|
@@ -34,7 +34,7 @@ export declare class Instrumenter {
|
|
|
34
34
|
intercept(fn: Function, call: Call, options: Options): any;
|
|
35
35
|
invoke(fn: Function, call: Call, options: Options): any;
|
|
36
36
|
update(call: Call): void;
|
|
37
|
-
sync(storyId:
|
|
37
|
+
sync(storyId: string): void;
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
40
|
* Instruments an object or module by traversing its properties, patching any functions (methods)
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { StoryId } from '@storybook/addons';
|
|
2
2
|
export interface Call {
|
|
3
3
|
id: string;
|
|
4
|
-
parentId?: Call['id'];
|
|
5
|
-
storyId: StoryId;
|
|
6
4
|
cursor: number;
|
|
5
|
+
storyId: StoryId;
|
|
6
|
+
ancestors: Call['id'][];
|
|
7
7
|
path: Array<string | CallRef>;
|
|
8
8
|
method: string;
|
|
9
9
|
args: any[];
|
|
@@ -46,7 +46,7 @@ export interface ControlStates {
|
|
|
46
46
|
export interface LogItem {
|
|
47
47
|
callId: Call['id'];
|
|
48
48
|
status: Call['status'];
|
|
49
|
-
|
|
49
|
+
ancestors: Call['id'][];
|
|
50
50
|
}
|
|
51
51
|
export interface SyncPayload {
|
|
52
52
|
controlStates: ControlStates;
|
|
@@ -65,7 +65,7 @@ export interface State {
|
|
|
65
65
|
retain: boolean;
|
|
66
66
|
}>;
|
|
67
67
|
chainedCallIds: Set<Call['id']>;
|
|
68
|
-
|
|
68
|
+
ancestors: Call['id'][];
|
|
69
69
|
playUntil?: Call['id'];
|
|
70
70
|
resolvers: Record<Call['id'], Function>;
|
|
71
71
|
syncTimeout: ReturnType<typeof setTimeout>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storybook/instrumenter",
|
|
3
|
-
"version": "7.0.0-alpha.
|
|
3
|
+
"version": "7.0.0-alpha.25",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"storybook"
|
|
@@ -23,13 +23,6 @@
|
|
|
23
23
|
"main": "dist/cjs/index.js",
|
|
24
24
|
"module": "dist/esm/index.js",
|
|
25
25
|
"types": "dist/types/index.d.ts",
|
|
26
|
-
"typesVersions": {
|
|
27
|
-
"<3.8": {
|
|
28
|
-
"*": [
|
|
29
|
-
"dist/ts3.4/*"
|
|
30
|
-
]
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
26
|
"files": [
|
|
34
27
|
"dist/**/*",
|
|
35
28
|
"README.md",
|
|
@@ -41,9 +34,9 @@
|
|
|
41
34
|
"prepare": "node ../../../scripts/prepare.js"
|
|
42
35
|
},
|
|
43
36
|
"dependencies": {
|
|
44
|
-
"@storybook/addons": "7.0.0-alpha.
|
|
45
|
-
"@storybook/client-logger": "7.0.0-alpha.
|
|
46
|
-
"@storybook/core-events": "7.0.0-alpha.
|
|
37
|
+
"@storybook/addons": "7.0.0-alpha.25",
|
|
38
|
+
"@storybook/client-logger": "7.0.0-alpha.25",
|
|
39
|
+
"@storybook/core-events": "7.0.0-alpha.25",
|
|
47
40
|
"core-js": "^3.8.2",
|
|
48
41
|
"global": "^4.4.0"
|
|
49
42
|
},
|
|
@@ -53,5 +46,5 @@
|
|
|
53
46
|
"publishConfig": {
|
|
54
47
|
"access": "public"
|
|
55
48
|
},
|
|
56
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "058af8bac4892d95fdfe755dedfd826cb4508fdc"
|
|
57
50
|
}
|