@storybook/instrumenter 6.4.0-alpha.35

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.
@@ -0,0 +1,725 @@
1
+ "use strict";
2
+
3
+ require("core-js/modules/es.symbol.js");
4
+
5
+ require("core-js/modules/es.symbol.description.js");
6
+
7
+ require("core-js/modules/es.symbol.iterator.js");
8
+
9
+ require("core-js/modules/es.symbol.to-primitive.js");
10
+
11
+ require("core-js/modules/es.date.to-primitive.js");
12
+
13
+ require("core-js/modules/es.number.constructor.js");
14
+
15
+ Object.defineProperty(exports, "__esModule", {
16
+ value: true
17
+ });
18
+ exports.instrument = exports.Instrumenter = exports.EVENTS = void 0;
19
+
20
+ require("core-js/modules/es.object.to-string.js");
21
+
22
+ require("core-js/modules/es.map.js");
23
+
24
+ require("core-js/modules/es.string.iterator.js");
25
+
26
+ require("core-js/modules/es.array.iterator.js");
27
+
28
+ require("core-js/modules/web.dom-collections.iterator.js");
29
+
30
+ require("core-js/modules/es.set.js");
31
+
32
+ require("core-js/modules/es.array.filter.js");
33
+
34
+ require("core-js/modules/es.array.from.js");
35
+
36
+ require("core-js/modules/es.object.assign.js");
37
+
38
+ require("core-js/modules/es.array.map.js");
39
+
40
+ require("core-js/modules/es.array.find-index.js");
41
+
42
+ require("core-js/modules/es.array.slice.js");
43
+
44
+ require("core-js/modules/es.array.find.js");
45
+
46
+ require("core-js/modules/web.dom-collections.for-each.js");
47
+
48
+ require("core-js/modules/es.object.values.js");
49
+
50
+ require("core-js/modules/es.object.keys.js");
51
+
52
+ require("core-js/modules/es.array.concat.js");
53
+
54
+ require("core-js/modules/es.promise.js");
55
+
56
+ require("core-js/modules/es.function.name.js");
57
+
58
+ require("core-js/modules/es.array.includes.js");
59
+
60
+ var _addons = require("@storybook/addons");
61
+
62
+ var _coreEvents = require("@storybook/core-events");
63
+
64
+ var _global = _interopRequireDefault(require("global"));
65
+
66
+ var _types = require("./types");
67
+
68
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
69
+
70
+ function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
71
+
72
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
73
+
74
+ 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); }
75
+
76
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
77
+
78
+ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
79
+
80
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
81
+
82
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
83
+
84
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
85
+
86
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
87
+
88
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
89
+
90
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
91
+
92
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
93
+
94
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
95
+
96
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
97
+
98
+ function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
99
+
100
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
101
+
102
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
103
+
104
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
105
+
106
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
107
+
108
+ var EVENTS = {
109
+ CALL: 'instrumenter/call',
110
+ SYNC: 'instrumenter/sync',
111
+ START: 'instrumenter/start',
112
+ BACK: 'instrumenter/back',
113
+ GOTO: 'instrumenter/goto',
114
+ NEXT: 'instrumenter/next',
115
+ END: 'instrumenter/end'
116
+ };
117
+ exports.EVENTS = EVENTS;
118
+
119
+ var isObject = function isObject(o) {
120
+ return Object.prototype.toString.call(o) === '[object Object]';
121
+ };
122
+
123
+ var isModule = function isModule(o) {
124
+ return Object.prototype.toString.call(o) === '[object Module]';
125
+ };
126
+
127
+ var isInstrumentable = function isInstrumentable(o) {
128
+ if (!isObject(o) && !isModule(o)) return false;
129
+ if (o.constructor === undefined) return true;
130
+ var proto = o.constructor.prototype;
131
+ if (!isObject(proto)) return false;
132
+ if (Object.prototype.hasOwnProperty.call(proto, 'isPrototypeOf') === false) return false;
133
+ return true;
134
+ };
135
+
136
+ var construct = function construct(obj) {
137
+ try {
138
+ return new obj.constructor();
139
+ } catch (e) {
140
+ return {};
141
+ }
142
+ };
143
+
144
+ var getInitialState = function getInitialState() {
145
+ return {
146
+ isDebugging: false,
147
+ cursor: 0,
148
+ calls: [],
149
+ shadowCalls: [],
150
+ callRefsByResult: new Map(),
151
+ chainedCallIds: new Set(),
152
+ parentCallId: undefined,
153
+ playUntil: undefined,
154
+ resolvers: {},
155
+ syncTimeout: undefined,
156
+ forwardedException: undefined
157
+ };
158
+ };
159
+
160
+ var Instrumenter = /*#__PURE__*/function () {
161
+ function Instrumenter() {
162
+ var _this = this;
163
+
164
+ _classCallCheck(this, Instrumenter);
165
+
166
+ this.channel = void 0;
167
+ this.state = void 0;
168
+ this.channel = _addons.addons.getChannel();
169
+ this.state = // Restore state from the parent window in case the iframe was reloaded.
170
+ _global.default.window.parent.__STORYBOOK_ADDON_INTERACTIONS_INSTRUMENTER_STATE__ || getInitialState(); // When called from `start`, isDebugging will be true
171
+
172
+ var resetState = function resetState() {
173
+ var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
174
+ _ref$isDebugging = _ref.isDebugging,
175
+ isDebugging = _ref$isDebugging === void 0 ? false : _ref$isDebugging;
176
+
177
+ var _this$state = _this.state,
178
+ calls = _this$state.calls,
179
+ shadowCalls = _this$state.shadowCalls,
180
+ callRefsByResult = _this$state.callRefsByResult,
181
+ chainedCallIds = _this$state.chainedCallIds,
182
+ playUntil = _this$state.playUntil;
183
+ var retainedCalls = (isDebugging ? shadowCalls : calls).filter(function (call) {
184
+ return call.retain;
185
+ });
186
+ var retainedCallRefs = new Map(Array.from(callRefsByResult.entries()).filter(function (_ref2) {
187
+ var _ref3 = _slicedToArray(_ref2, 2),
188
+ ref = _ref3[1];
189
+
190
+ return ref.retain;
191
+ }));
192
+
193
+ _this.setState(Object.assign({}, getInitialState(), {
194
+ cursor: retainedCalls.length,
195
+ calls: retainedCalls,
196
+ callRefsByResult: retainedCallRefs,
197
+ shadowCalls: isDebugging ? shadowCalls : [],
198
+ chainedCallIds: isDebugging ? chainedCallIds : new Set(),
199
+ playUntil: isDebugging ? playUntil : undefined,
200
+ isDebugging: isDebugging
201
+ })); // Don't sync while debugging, as it'll cause flicker.
202
+
203
+
204
+ if (!isDebugging) _this.channel.emit(EVENTS.SYNC, _this.getLog());
205
+ }; // A forceRemount might be triggered for debugging (on `start`), or elsewhere in Storybook.
206
+
207
+
208
+ this.channel.on(_coreEvents.FORCE_REMOUNT, resetState); // Start with a clean slate before playing, but also clean up when switching to a story that
209
+ // doesn't have a play function (in which case there is no 'playing' phase).
210
+ // Invocation of the play function is guaranteed to always be preceded by the 'rendering' phase.
211
+
212
+ this.channel.on(_coreEvents.STORY_RENDER_PHASE_CHANGED, function (_ref4) {
213
+ var storyId = _ref4.storyId,
214
+ newPhase = _ref4.newPhase;
215
+
216
+ // TODO keep state per story
217
+ if (newPhase === 'loading') {
218
+ resetState({
219
+ isDebugging: _this.state.isDebugging
220
+ });
221
+ }
222
+
223
+ if (newPhase === 'completed') {
224
+ _this.setState({
225
+ isDebugging: false
226
+ }); // Rethrow any unhandled forwarded exception so it doesn't go unnoticed.
227
+
228
+
229
+ if (_this.state.forwardedException) throw _this.state.forwardedException;
230
+ }
231
+ });
232
+
233
+ var start = function start(_ref5) {
234
+ var storyId = _ref5.storyId,
235
+ playUntil = _ref5.playUntil;
236
+
237
+ if (!_this.state.isDebugging) {
238
+ _this.setState(function (_ref6) {
239
+ var calls = _ref6.calls;
240
+ return {
241
+ calls: [],
242
+ shadowCalls: calls.map(function (call) {
243
+ return Object.assign({}, call, {
244
+ state: _types.CallStates.WAITING
245
+ });
246
+ }),
247
+ isDebugging: true
248
+ };
249
+ });
250
+ }
251
+
252
+ var log = _this.getLog();
253
+
254
+ var firstRowIndex = _this.state.shadowCalls.findIndex(function (call) {
255
+ return call.id === log[0].callId;
256
+ });
257
+
258
+ _this.setState(function (_ref7) {
259
+ var _shadowCalls$slice$fi;
260
+
261
+ var shadowCalls = _ref7.shadowCalls;
262
+ return {
263
+ playUntil: playUntil || ((_shadowCalls$slice$fi = shadowCalls.slice(0, firstRowIndex).filter(function (call) {
264
+ return call.interceptable;
265
+ }).slice(-1)[0]) === null || _shadowCalls$slice$fi === void 0 ? void 0 : _shadowCalls$slice$fi.id)
266
+ };
267
+ }); // Force remount may trigger a page reload if the play function can't be aborted.
268
+ // global.window.location.reload();
269
+
270
+
271
+ _this.channel.emit(_coreEvents.FORCE_REMOUNT, {
272
+ storyId: storyId,
273
+ isDebugging: true
274
+ });
275
+ };
276
+
277
+ var back = function back(_ref8) {
278
+ var _log, _log$slice$;
279
+
280
+ var storyId = _ref8.storyId;
281
+ var isDebugging = _this.state.isDebugging;
282
+
283
+ var log = _this.getLog();
284
+
285
+ var next = log.findIndex(function (_ref9) {
286
+ var state = _ref9.state;
287
+ return state === _types.CallStates.WAITING;
288
+ });
289
+ var playUntil = ((_log = log[next - 2]) === null || _log === void 0 ? void 0 : _log.callId) || (isDebugging ? null : (_log$slice$ = log.slice(-2)[0]) === null || _log$slice$ === void 0 ? void 0 : _log$slice$.callId);
290
+ start({
291
+ storyId: storyId,
292
+ playUntil: playUntil
293
+ });
294
+ };
295
+
296
+ var goto = function goto(_ref10) {
297
+ var storyId = _ref10.storyId,
298
+ callId = _ref10.callId;
299
+ var _this$state2 = _this.state,
300
+ calls = _this$state2.calls,
301
+ shadowCalls = _this$state2.shadowCalls,
302
+ resolvers = _this$state2.resolvers;
303
+ var call = calls.find(function (_ref11) {
304
+ var id = _ref11.id;
305
+ return id === callId;
306
+ });
307
+ var shadowCall = shadowCalls.find(function (_ref12) {
308
+ var id = _ref12.id;
309
+ return id === callId;
310
+ });
311
+
312
+ if (!call && shadowCall) {
313
+ var _this$getLog$find;
314
+
315
+ var nextCallId = (_this$getLog$find = _this.getLog().find(function (_ref13) {
316
+ var state = _ref13.state;
317
+ return state === _types.CallStates.WAITING;
318
+ })) === null || _this$getLog$find === void 0 ? void 0 : _this$getLog$find.callId;
319
+ if (shadowCall.id !== nextCallId) _this.setState({
320
+ playUntil: shadowCall.id
321
+ });
322
+ Object.values(resolvers).forEach(function (resolve) {
323
+ return resolve();
324
+ });
325
+ } else {
326
+ start({
327
+ storyId: storyId,
328
+ playUntil: callId
329
+ });
330
+ }
331
+ };
332
+
333
+ var next = function next() {
334
+ Object.values(_this.state.resolvers).forEach(function (resolve) {
335
+ return resolve();
336
+ });
337
+ };
338
+
339
+ var end = function end() {
340
+ _this.setState({
341
+ playUntil: undefined,
342
+ isDebugging: false
343
+ });
344
+
345
+ Object.values(_this.state.resolvers).forEach(function (resolve) {
346
+ return resolve();
347
+ });
348
+ };
349
+
350
+ this.channel.on(EVENTS.START, start);
351
+ this.channel.on(EVENTS.BACK, back);
352
+ this.channel.on(EVENTS.GOTO, goto);
353
+ this.channel.on(EVENTS.NEXT, next);
354
+ this.channel.on(EVENTS.END, end);
355
+ }
356
+
357
+ _createClass(Instrumenter, [{
358
+ key: "setState",
359
+ value: function setState(update) {
360
+ this.state = Object.assign({}, this.state, typeof update === 'function' ? update(this.state) : update); // Track state on the parent window so we can reload the iframe without losing state.
361
+
362
+ _global.default.window.parent.__STORYBOOK_ADDON_INTERACTIONS_INSTRUMENTER_STATE__ = this.state;
363
+ }
364
+ }, {
365
+ key: "getLog",
366
+ value: function getLog() {
367
+ var merged = _toConsumableArray(this.state.shadowCalls);
368
+
369
+ this.state.calls.forEach(function (call, index) {
370
+ merged[index] = call;
371
+ });
372
+ var seen = new Set();
373
+ return merged.reduceRight(function (acc, call) {
374
+ call.args.forEach(function (arg) {
375
+ if (arg !== null && arg !== void 0 && arg.__callId__) {
376
+ seen.add(arg.__callId__);
377
+ }
378
+ });
379
+ call.path.forEach(function (node) {
380
+ if (node.__callId__) {
381
+ seen.add(node.__callId__);
382
+ }
383
+ });
384
+
385
+ if (call.interceptable && !seen.has(call.id) && !seen.has(call.parentId)) {
386
+ acc.unshift({
387
+ callId: call.id,
388
+ state: call.state
389
+ });
390
+ seen.add(call.id);
391
+
392
+ if (call.parentId) {
393
+ seen.add(call.parentId);
394
+ }
395
+ }
396
+
397
+ return acc;
398
+ }, []);
399
+ } // Traverses the object structure to recursively patch all function properties.
400
+ // Returns the original object, or a new object with the same constructor,
401
+ // depending on whether it should mutate.
402
+
403
+ }, {
404
+ key: "instrument",
405
+ value: function instrument(obj) {
406
+ var _this2 = this;
407
+
408
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
409
+ if (!isInstrumentable(obj)) return obj;
410
+ var _options$mutate = options.mutate,
411
+ mutate = _options$mutate === void 0 ? false : _options$mutate,
412
+ _options$path = options.path,
413
+ path = _options$path === void 0 ? [] : _options$path;
414
+ return Object.keys(obj).reduce(function (acc, key) {
415
+ var value = obj[key]; // Nothing to patch, but might be instrumentable, so we recurse
416
+
417
+ if (typeof value !== 'function') {
418
+ acc[key] = _this2.instrument(value, Object.assign({}, options, {
419
+ path: path.concat(key)
420
+ }));
421
+ return acc;
422
+ } // Already patched, so we pass through unchanged
423
+
424
+
425
+ if (typeof value._original === 'function') {
426
+ acc[key] = value;
427
+ return acc;
428
+ } // Patch the function and mark it "patched" by adding a reference to the original function
429
+
430
+
431
+ acc[key] = _this2.patch(key, value, options);
432
+ acc[key]._original = value; // Deal with functions that also act like an object
433
+
434
+ if (Object.keys(value).length > 0) {
435
+ Object.assign(acc[key], _this2.instrument(Object.assign({}, value), Object.assign({}, options, {
436
+ path: path.concat(key)
437
+ })));
438
+ }
439
+
440
+ return acc;
441
+ }, mutate ? obj : construct(obj));
442
+ }
443
+ }, {
444
+ key: "patch",
445
+ value: function patch(method, fn, options) {
446
+ var _this3 = this;
447
+
448
+ var patched = function patched() {
449
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
450
+ args[_key] = arguments[_key];
451
+ }
452
+
453
+ return _this3.track(method, fn, args, options);
454
+ };
455
+
456
+ Object.defineProperty(patched, 'name', {
457
+ value: method,
458
+ writable: false
459
+ });
460
+ return patched;
461
+ } // Monkey patch an object method to record calls.
462
+ // Returns a function that invokes the original function, records the invocation ("call") and
463
+ // returns the original result.
464
+
465
+ }, {
466
+ key: "track",
467
+ value: function track(method, fn, args, _ref14) {
468
+ var _ref14$path = _ref14.path,
469
+ path = _ref14$path === void 0 ? [] : _ref14$path,
470
+ options = _objectWithoutProperties(_ref14, ["path"]);
471
+
472
+ var index = this.state.cursor;
473
+ this.setState({
474
+ cursor: this.state.cursor + 1
475
+ });
476
+ var id = "".concat(index, "-").concat(method);
477
+ var _options$intercept = options.intercept,
478
+ intercept = _options$intercept === void 0 ? false : _options$intercept,
479
+ _options$retain = options.retain,
480
+ retain = _options$retain === void 0 ? false : _options$retain;
481
+ var interceptable = typeof intercept === 'function' ? intercept(method, path) : intercept;
482
+ var call = {
483
+ id: id,
484
+ path: path,
485
+ method: method,
486
+ args: args,
487
+ interceptable: interceptable,
488
+ retain: retain
489
+ };
490
+ var result = (interceptable ? this.intercept : this.invoke).call(this, fn, call);
491
+ return this.instrument(result, Object.assign({}, options, {
492
+ mutate: true,
493
+ path: [{
494
+ __callId__: call.id
495
+ }]
496
+ }));
497
+ }
498
+ }, {
499
+ key: "intercept",
500
+ value: function intercept(fn, call) {
501
+ var _this4 = this;
502
+
503
+ // For a "jump to step" action, continue playing until we hit a call by that ID.
504
+ // For chained calls, we can only return a Promise for the last call in the chain.
505
+ var isChainedUpon = this.state.chainedCallIds.has(call.id);
506
+
507
+ if (!this.state.isDebugging || isChainedUpon || this.state.playUntil) {
508
+ if (this.state.playUntil === call.id) {
509
+ this.setState({
510
+ playUntil: undefined
511
+ });
512
+ }
513
+
514
+ return this.invoke(fn, call);
515
+ } // Instead of invoking the function, defer the function call until we continue playing.
516
+
517
+
518
+ return new Promise(function (resolve) {
519
+ _this4.setState(function (_ref15) {
520
+ var resolvers = _ref15.resolvers;
521
+ return {
522
+ resolvers: Object.assign({}, resolvers, _defineProperty({}, call.id, resolve))
523
+ };
524
+ });
525
+ }).then(function () {
526
+ var _this4$state$resolver = _this4.state.resolvers,
527
+ _call$id = call.id,
528
+ _ = _this4$state$resolver[_call$id],
529
+ resolvers = _objectWithoutProperties(_this4$state$resolver, [_call$id].map(_toPropertyKey));
530
+
531
+ _this4.setState({
532
+ resolvers: resolvers
533
+ });
534
+
535
+ return _this4.invoke(fn, call);
536
+ });
537
+ }
538
+ }, {
539
+ key: "invoke",
540
+ value: function invoke(fn, call) {
541
+ var _this5 = this;
542
+
543
+ var _this$state3 = this.state,
544
+ parentCallId = _this$state3.parentCallId,
545
+ callRefsByResult = _this$state3.callRefsByResult,
546
+ forwardedException = _this$state3.forwardedException;
547
+ var info = Object.assign({}, call, {
548
+ parentId: parentCallId,
549
+ // Map args that originate from a tracked function call to a call reference to enable nesting.
550
+ // These values are often not fully serializable anyway (e.g. HTML elements).
551
+ args: call.args.map(function (arg) {
552
+ if (callRefsByResult.has(arg)) {
553
+ return callRefsByResult.get(arg);
554
+ }
555
+
556
+ if (arg instanceof _global.default.window.HTMLElement) {
557
+ var prefix = arg.prefix,
558
+ localName = arg.localName,
559
+ id = arg.id,
560
+ classList = arg.classList,
561
+ innerText = arg.innerText;
562
+ var classNames = Array.from(classList);
563
+ return {
564
+ __element__: {
565
+ prefix: prefix,
566
+ localName: localName,
567
+ id: id,
568
+ classNames: classNames,
569
+ innerText: innerText
570
+ }
571
+ };
572
+ }
573
+
574
+ return arg;
575
+ })
576
+ }); // Mark any ancestor calls as "chained upon" so we won't attempt to defer it later.
577
+
578
+ call.path.forEach(function (ref) {
579
+ if (ref !== null && ref !== void 0 && ref.__callId__) {
580
+ _this5.setState(function (_ref16) {
581
+ var chainedCallIds = _ref16.chainedCallIds;
582
+ return {
583
+ chainedCallIds: new Set(Array.from(chainedCallIds).concat(ref.__callId__))
584
+ };
585
+ });
586
+ }
587
+ });
588
+
589
+ var handleException = function handleException(e) {
590
+ if (e instanceof Error) {
591
+ var name = e.name,
592
+ message = e.message,
593
+ stack = e.stack;
594
+ var exception = {
595
+ name: name,
596
+ message: message,
597
+ stack: stack,
598
+ callId: call.id
599
+ };
600
+
601
+ _this5.sync(Object.assign({}, info, {
602
+ state: _types.CallStates.ERROR,
603
+ exception: exception
604
+ })); // Always track errors to their originating call.
605
+
606
+
607
+ _this5.setState(function (state) {
608
+ return {
609
+ callRefsByResult: new Map([].concat(_toConsumableArray(Array.from(state.callRefsByResult.entries())), [[e, {
610
+ __callId__: call.id,
611
+ retain: call.retain
612
+ }]]))
613
+ };
614
+ }); // We need to throw to break out of the play function, but we don't want to trigger a redbox
615
+ // so we throw an ignoredException, which is caught and silently ignored by Storybook.
616
+
617
+
618
+ if (call.interceptable) {
619
+ throw _coreEvents.IGNORED_EXCEPTION;
620
+ } // Non-interceptable calls need their exceptions forwarded to the next interceptable call.
621
+ // In case no interceptable call picks it up, it'll get rethrown in the "completed" phase.
622
+
623
+
624
+ _this5.setState({
625
+ forwardedException: e
626
+ });
627
+
628
+ return e;
629
+ }
630
+
631
+ throw e;
632
+ };
633
+
634
+ try {
635
+ // An earlier, non-interceptable call might have forwarded an exception.
636
+ if (forwardedException) {
637
+ this.setState({
638
+ forwardedException: undefined
639
+ });
640
+ throw forwardedException;
641
+ }
642
+
643
+ var result = fn.apply(void 0, _toConsumableArray(call.args.map(function (arg) {
644
+ if (typeof arg !== 'function' || Object.keys(arg).length) return arg;
645
+ return function () {
646
+ var prev = _this5.state.parentCallId;
647
+
648
+ _this5.setState({
649
+ parentCallId: call.id
650
+ });
651
+
652
+ var res = arg.apply(void 0, arguments);
653
+
654
+ _this5.setState({
655
+ parentCallId: prev
656
+ });
657
+
658
+ return res;
659
+ };
660
+ }))); // Track the result so we can trace later uses of it back to the originating call.
661
+ // Primitive results (undefined, null, boolean, string, number, BigInt) are ignored.
662
+
663
+ if (result && ['object', 'function', 'symbol'].includes(_typeof(result))) {
664
+ this.setState(function (state) {
665
+ return {
666
+ callRefsByResult: new Map([].concat(_toConsumableArray(Array.from(state.callRefsByResult.entries())), [[result, {
667
+ __callId__: call.id,
668
+ retain: call.retain
669
+ }]]))
670
+ };
671
+ });
672
+ }
673
+
674
+ this.sync(Object.assign({}, info, {
675
+ state: result instanceof Promise ? _types.CallStates.ACTIVE : _types.CallStates.DONE
676
+ }));
677
+
678
+ if (result instanceof Promise) {
679
+ return result.then(function (value) {
680
+ _this5.sync(Object.assign({}, info, {
681
+ state: _types.CallStates.DONE
682
+ }));
683
+
684
+ return value;
685
+ }, handleException);
686
+ }
687
+
688
+ return result;
689
+ } catch (e) {
690
+ return handleException(e);
691
+ }
692
+ }
693
+ }, {
694
+ key: "sync",
695
+ value: function sync(call) {
696
+ var _this6 = this;
697
+
698
+ clearTimeout(this.state.syncTimeout);
699
+ this.channel.emit(EVENTS.CALL, call);
700
+ this.setState(function (_ref17) {
701
+ var calls = _ref17.calls;
702
+ return {
703
+ calls: calls.concat(call),
704
+ syncTimeout: setTimeout(function () {
705
+ return _this6.channel.emit(EVENTS.SYNC, _this6.getLog());
706
+ }, 0)
707
+ };
708
+ });
709
+ }
710
+ }]);
711
+
712
+ return Instrumenter;
713
+ }();
714
+
715
+ exports.Instrumenter = Instrumenter;
716
+ var instrument = _global.default.window.parent === _global.default.window ? function (obj) {
717
+ return obj;
718
+ } // Don't do anything if not loaded in an iframe.
719
+ : function (obj) {
720
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
721
+ if (!_global.default.window.__STORYBOOK_ADDON_INTERACTIONS_INSTRUMENTER__) _global.default.window.__STORYBOOK_ADDON_INTERACTIONS_INSTRUMENTER__ = new Instrumenter();
722
+ var instrumenter = _global.default.window.__STORYBOOK_ADDON_INTERACTIONS_INSTRUMENTER__;
723
+ return instrumenter.instrument(obj, options);
724
+ };
725
+ exports.instrument = instrument;