machina 4.0.1 → 6.0.0

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/lib/machina.js DELETED
@@ -1,744 +0,0 @@
1
- /*!
2
- * * machina - A library for creating powerful and flexible finite state machines. Loosely inspired by Erlang/OTP's gen_fsm behavior.
3
- * * Author: Jim Cowart (http://ifandelse.com)
4
- * * Version: v4.0.1
5
- * * Url: http://machina-js.org/
6
- * * License(s):
7
- */
8
- (function webpackUniversalModuleDefinition(root, factory) {
9
- if(typeof exports === 'object' && typeof module === 'object')
10
- module.exports = factory(require("lodash"));
11
- else if(typeof define === 'function' && define.amd)
12
- define(["lodash"], factory);
13
- else if(typeof exports === 'object')
14
- exports["machina"] = factory(require("lodash"));
15
- else
16
- root["machina"] = factory(root["_"]);
17
- })(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {
18
- return /******/ (function(modules) { // webpackBootstrap
19
- /******/ // The module cache
20
- /******/ var installedModules = {};
21
- /******/
22
- /******/ // The require function
23
- /******/ function __webpack_require__(moduleId) {
24
- /******/
25
- /******/ // Check if module is in cache
26
- /******/ if(installedModules[moduleId])
27
- /******/ return installedModules[moduleId].exports;
28
- /******/
29
- /******/ // Create a new module (and put it into the cache)
30
- /******/ var module = installedModules[moduleId] = {
31
- /******/ exports: {},
32
- /******/ id: moduleId,
33
- /******/ loaded: false
34
- /******/ };
35
- /******/
36
- /******/ // Execute the module function
37
- /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
38
- /******/
39
- /******/ // Flag the module as loaded
40
- /******/ module.loaded = true;
41
- /******/
42
- /******/ // Return the exports of the module
43
- /******/ return module.exports;
44
- /******/ }
45
- /******/
46
- /******/
47
- /******/ // expose the modules object (__webpack_modules__)
48
- /******/ __webpack_require__.m = modules;
49
- /******/
50
- /******/ // expose the module cache
51
- /******/ __webpack_require__.c = installedModules;
52
- /******/
53
- /******/ // __webpack_public_path__
54
- /******/ __webpack_require__.p = "";
55
- /******/
56
- /******/ // Load entry module and return exports
57
- /******/ return __webpack_require__(0);
58
- /******/ })
59
- /************************************************************************/
60
- /******/ ([
61
- /* 0 */
62
- /***/ (function(module, exports, __webpack_require__) {
63
-
64
- var _ = __webpack_require__( 1 );
65
- var emitter = __webpack_require__( 2 );
66
-
67
- module.exports = _.merge( emitter.instance, {
68
- Fsm: __webpack_require__( 5 ),
69
- BehavioralFsm: __webpack_require__( 6 ),
70
- utils: __webpack_require__( 3 ),
71
- eventListeners: {
72
- newFsm: []
73
- }
74
- } );
75
-
76
-
77
- /***/ }),
78
- /* 1 */
79
- /***/ (function(module, exports) {
80
-
81
- module.exports = __WEBPACK_EXTERNAL_MODULE_1__;
82
-
83
- /***/ }),
84
- /* 2 */
85
- /***/ (function(module, exports, __webpack_require__) {
86
-
87
- var utils = __webpack_require__( 3 );
88
- var _ = __webpack_require__( 1 );
89
-
90
- function getInstance() {
91
- return {
92
- emit: function( eventName ) {
93
- var args = utils.getLeaklessArgs( arguments );
94
- if ( this.eventListeners[ "*" ] ) {
95
- _.each( this.eventListeners[ "*" ], function( callback ) {
96
- if ( !this.useSafeEmit ) {
97
- callback.apply( this, args );
98
- } else {
99
- try {
100
- callback.apply( this, args );
101
- } catch ( exception ) {
102
- /* istanbul ignore else */
103
- if ( console && typeof console.log !== "undefined" ) {
104
- console.log( exception.stack );
105
- }
106
- }
107
- }
108
- }.bind( this ) );
109
- }
110
- if ( this.eventListeners[ eventName ] ) {
111
- _.each( this.eventListeners[ eventName ], function( callback ) {
112
- if ( !this.useSafeEmit ) {
113
- callback.apply( this, args.slice( 1 ) );
114
- } else {
115
- try {
116
- callback.apply( this, args.slice( 1 ) );
117
- } catch ( exception ) {
118
- /* istanbul ignore else */
119
- if ( console && typeof console.log !== "undefined" ) {
120
- console.log( exception.stack );
121
- }
122
- }
123
- }
124
- }.bind( this ) );
125
- }
126
- },
127
-
128
- on: function( eventName, callback ) {
129
- var self = this;
130
- self.eventListeners = self.eventListeners || { "*": [] };
131
- if ( !self.eventListeners[ eventName ] ) {
132
- self.eventListeners[ eventName ] = [];
133
- }
134
- self.eventListeners[ eventName ].push( callback );
135
- return {
136
- eventName: eventName,
137
- callback: callback,
138
- off: function() {
139
- self.off( eventName, callback );
140
- }
141
- };
142
- },
143
-
144
- off: function( eventName, callback ) {
145
- this.eventListeners = this.eventListeners || { "*": [] };
146
- if ( !eventName ) {
147
- this.eventListeners = {};
148
- } else {
149
- if ( callback ) {
150
- this.eventListeners[ eventName ] = _.without( this.eventListeners[ eventName ], callback );
151
- } else {
152
- this.eventListeners[ eventName ] = [];
153
- }
154
- }
155
- }
156
- };
157
- }
158
-
159
- module.exports = {
160
- getInstance: getInstance,
161
- instance: getInstance()
162
- };
163
-
164
-
165
- /***/ }),
166
- /* 3 */
167
- /***/ (function(module, exports, __webpack_require__) {
168
-
169
- var slice = [].slice;
170
- var events = __webpack_require__( 4 );
171
- var _ = __webpack_require__( 1 );
172
-
173
- var makeFsmNamespace = ( function() {
174
- var machinaCount = 0;
175
- return function() {
176
- return "fsm." + machinaCount++;
177
- };
178
- } )();
179
-
180
- function getDefaultBehavioralOptions() {
181
- return {
182
- initialState: "uninitialized",
183
- eventListeners: {
184
- "*": []
185
- },
186
- states: {},
187
- namespace: makeFsmNamespace(),
188
- useSafeEmit: false,
189
- hierarchy: {},
190
- pendingDelegations: {}
191
- };
192
- }
193
-
194
- function getDefaultClientMeta() {
195
- return {
196
- inputQueue: [],
197
- targetReplayState: "",
198
- state: undefined,
199
- priorState: undefined,
200
- priorAction: "",
201
- currentAction: "",
202
- currentActionArgs: undefined,
203
- inExitHandler: false
204
- };
205
- }
206
-
207
- function getLeaklessArgs( args, startIdx ) {
208
- var result = [];
209
- for ( var i = ( startIdx || 0 ); i < args.length; i++ ) {
210
- result[ i ] = args[ i ];
211
- }
212
- return result;
213
- }
214
- /*
215
- handle ->
216
- child = stateObj._child && stateObj._child.instance;
217
-
218
- transition ->
219
- newStateObj._child = getChildFsmInstance( newStateObj._child );
220
- child = newStateObj._child && newStateObj._child.instance;
221
- */
222
- function getChildFsmInstance( config ) {
223
- if ( !config ) {
224
- return;
225
- }
226
- var childFsmDefinition = {};
227
- if ( typeof config === "object" ) {
228
- // is this a config object with a factory?
229
- if ( config.factory ) {
230
- childFsmDefinition = config;
231
- childFsmDefinition.instance = childFsmDefinition.factory();
232
- } else {
233
- // assuming this is a machina instance
234
- childFsmDefinition.factory = function() {
235
- return config;
236
- };
237
- }
238
- } else if ( typeof config === "function" ) {
239
- childFsmDefinition.factory = config;
240
- }
241
- childFsmDefinition.instance = childFsmDefinition.factory();
242
- return childFsmDefinition;
243
- }
244
-
245
- function listenToChild( fsm, child ) {
246
- // Need to investigate potential for discarded event
247
- // listener memory leak in long-running, deeply-nested hierarchies.
248
- return child.on( "*", function( eventName, data ) {
249
- switch ( eventName ) {
250
- case events.NO_HANDLER:
251
- if ( !data.ticket && !data.delegated && data.namespace !== fsm.namespace ) {
252
- // Ok - we're dealing w/ a child handling input that should bubble up
253
- data.args[ 1 ].bubbling = true;
254
- }
255
- // we do NOT bubble _reset inputs up to the parent
256
- if ( data.inputType !== "_reset" ) {
257
- fsm.handle.apply( fsm, data.args );
258
- }
259
- break;
260
- case events.HANDLING :
261
- var ticket = data.ticket;
262
- if ( ticket && fsm.pendingDelegations[ ticket ] ) {
263
- delete fsm.pendingDelegations[ ticket ];
264
- }
265
- fsm.emit( eventName, data ); // possibly transform payload?
266
- break;
267
- default:
268
- fsm.emit( eventName, data ); // possibly transform payload?
269
- break;
270
- }
271
- } );
272
- }
273
-
274
- // _machKeys are members we want to track across the prototype chain of an extended FSM constructor
275
- // Since we want to eventually merge the aggregate of those values onto the instance so that FSMs
276
- // that share the same extended prototype won't share state *on* those prototypes.
277
- var _machKeys = [ "states", "initialState" ];
278
- var extend = function( protoProps, staticProps ) {
279
- var parent = this;
280
- var fsm; // placeholder for instance constructor
281
- var machObj = {}; // object used to hold initialState & states from prototype for instance-level merging
282
- var Ctor = function() {}; // placeholder ctor function used to insert level in prototype chain
283
-
284
- // The constructor function for the new subclass is either defined by you
285
- // (the "constructor" property in your `extend` definition), or defaulted
286
- // by us to simply call the parent's constructor.
287
- if ( protoProps && protoProps.hasOwnProperty( "constructor" ) ) {
288
- fsm = protoProps.constructor;
289
- } else {
290
- // The default machina constructor (when using inheritance) creates a
291
- // deep copy of the states/initialState values from the prototype and
292
- // extends them over the instance so that they'll be instance-level.
293
- // If an options arg (args[0]) is passed in, a states or intialState
294
- // value will be preferred over any data pulled up from the prototype.
295
- fsm = function() {
296
- var args = slice.call( arguments, 0 );
297
- args[ 0 ] = args[ 0 ] || {};
298
- var blendedState;
299
- var instanceStates = args[ 0 ].states || {};
300
- blendedState = _.merge( _.cloneDeep( machObj ), { states: instanceStates } );
301
- blendedState.initialState = args[ 0 ].initialState || this.initialState;
302
- _.extend( args[ 0 ], blendedState );
303
- parent.apply( this, args );
304
- };
305
- }
306
-
307
- // Inherit class (static) properties from parent.
308
- _.merge( fsm, parent );
309
-
310
- // Set the prototype chain to inherit from `parent`, without calling
311
- // `parent`'s constructor function.
312
- Ctor.prototype = parent.prototype;
313
- fsm.prototype = new Ctor();
314
-
315
- // Add prototype properties (instance properties) to the subclass,
316
- // if supplied.
317
- if ( protoProps ) {
318
- _.extend( fsm.prototype, protoProps );
319
- _.merge( machObj, _.transform( protoProps, function( accum, val, key ) {
320
- if ( _machKeys.indexOf( key ) !== -1 ) {
321
- accum[ key ] = val;
322
- }
323
- } ) );
324
- }
325
-
326
- // Add static properties to the constructor function, if supplied.
327
- if ( staticProps ) {
328
- _.merge( fsm, staticProps );
329
- }
330
-
331
- // Correctly set child's `prototype.constructor`.
332
- fsm.prototype.constructor = fsm;
333
-
334
- // Set a convenience property in case the parent's prototype is needed later.
335
- fsm.__super__ = parent.prototype;
336
- return fsm;
337
- };
338
-
339
- function createUUID() {
340
- var s = [];
341
- var hexDigits = "0123456789abcdef";
342
- for ( var i = 0; i < 36; i++ ) {
343
- s[ i ] = hexDigits.substr( Math.floor( Math.random() * 0x10 ), 1 );
344
- }
345
- s[ 14 ] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
346
- /* jshint ignore:start */
347
- s[ 19 ] = hexDigits.substr( ( s[ 19 ] & 0x3 ) | 0x8, 1 ); // bits 6-7 of the clock_seq_hi_and_reserved to 01
348
- /* jshint ignore:end */
349
- s[ 8 ] = s[ 13 ] = s[ 18 ] = s[ 23 ] = "-";
350
- return s.join( "" );
351
- }
352
-
353
- module.exports = {
354
- createUUID: createUUID,
355
- extend: extend,
356
- getDefaultBehavioralOptions: getDefaultBehavioralOptions,
357
- getDefaultOptions: getDefaultBehavioralOptions,
358
- getDefaultClientMeta: getDefaultClientMeta,
359
- getChildFsmInstance: getChildFsmInstance,
360
- getLeaklessArgs: getLeaklessArgs,
361
- listenToChild: listenToChild,
362
- makeFsmNamespace: makeFsmNamespace
363
- };
364
-
365
-
366
- /***/ }),
367
- /* 4 */
368
- /***/ (function(module, exports) {
369
-
370
- module.exports = {
371
- NEXT_TRANSITION: "transition",
372
- HANDLING: "handling",
373
- HANDLED: "handled",
374
- NO_HANDLER: "nohandler",
375
- TRANSITION: "transition",
376
- TRANSITIONED: "transitioned",
377
- INVALID_STATE: "invalidstate",
378
- DEFERRED: "deferred",
379
- NEW_FSM: "newfsm"
380
- };
381
-
382
-
383
- /***/ }),
384
- /* 5 */
385
- /***/ (function(module, exports, __webpack_require__) {
386
-
387
- var BehavioralFsm = __webpack_require__( 6 );
388
- var utils = __webpack_require__( 3 );
389
- var _ = __webpack_require__( 1 );
390
-
391
- var Fsm = {
392
- constructor: function() {
393
- BehavioralFsm.apply( this, arguments );
394
- this.ensureClientMeta();
395
- },
396
- initClient: function initClient() {
397
- var initialState = this.initialState;
398
- if ( !initialState ) {
399
- throw new Error( "You must specify an initial state for this FSM" );
400
- }
401
- if ( !this.states[ initialState ] ) {
402
- throw new Error( "The initial state specified does not exist in the states object." );
403
- }
404
- this.transition( initialState );
405
- },
406
- ensureClientMeta: function ensureClientMeta() {
407
- if ( !this._stamped ) {
408
- this._stamped = true;
409
- _.defaults( this, _.cloneDeep( utils.getDefaultClientMeta() ) );
410
- this.initClient();
411
- }
412
- return this;
413
- },
414
-
415
- ensureClientArg: function( args ) {
416
- var _args = args;
417
- // we need to test the args and verify that if a client arg has
418
- // been passed, it must be this FSM instance (this isn't a behavioral FSM)
419
- if ( typeof _args[ 0 ] === "object" && !( "inputType" in _args[ 0 ] ) && _args[ 0 ] !== this ) {
420
- _args.splice( 0, 1, this );
421
- } else if ( typeof _args[ 0 ] !== "object" || ( typeof _args[ 0 ] === "object" && ( "inputType" in _args[ 0 ] ) ) ) {
422
- _args.unshift( this );
423
- }
424
- return _args;
425
- },
426
-
427
- getHandlerArgs: function( args, isCatchAll ) {
428
- // index 0 is the client, index 1 is inputType
429
- // if we're in a catch-all handler, input type needs to be included in the args
430
- // inputType might be an object, so we need to just get the inputType string if so
431
- var _args = args;
432
- var input = _args[ 1 ];
433
- if ( typeof inputType === "object" ) {
434
- _args.splice( 1, 1, input.inputType );
435
- }
436
- return isCatchAll ?
437
- _args.slice( 1 ) :
438
- _args.slice( 2 );
439
- },
440
-
441
- getSystemHandlerArgs: function( args, client ) {
442
- return args;
443
- },
444
-
445
- // "classic" machina FSM do not emit the client property on events (which would be the FSM itself)
446
- buildEventPayload: function() {
447
- var args = this.ensureClientArg( utils.getLeaklessArgs( arguments ) );
448
- var data = args[ 1 ];
449
- if ( _.isPlainObject( data ) ) {
450
- return _.extend( data, { namespace: this.namespace } );
451
- } else {
452
- return { data: data || null, namespace: this.namespace };
453
- }
454
- }
455
- };
456
-
457
- _.each( [
458
- "handle",
459
- "transition",
460
- "deferUntilTransition",
461
- "processQueue",
462
- "clearQueue"
463
- ], function( methodWithClientInjected ) {
464
- Fsm[ methodWithClientInjected ] = function() {
465
- var args = this.ensureClientArg( utils.getLeaklessArgs( arguments ) );
466
- return BehavioralFsm.prototype[ methodWithClientInjected ].apply( this, args );
467
- };
468
- } );
469
-
470
- Fsm = BehavioralFsm.extend( Fsm );
471
-
472
- module.exports = Fsm;
473
-
474
-
475
- /***/ }),
476
- /* 6 */
477
- /***/ (function(module, exports, __webpack_require__) {
478
-
479
- var _ = __webpack_require__( 1 );
480
- var utils = __webpack_require__( 3 );
481
- var emitter = __webpack_require__( 2 );
482
- var topLevelEmitter = emitter.instance;
483
- var events = __webpack_require__( 4 );
484
-
485
- var MACHINA_PROP = "__machina__";
486
-
487
- function BehavioralFsm( options ) {
488
- _.extend( this, options );
489
- _.defaults( this, utils.getDefaultBehavioralOptions() );
490
- this.initialize.apply( this, arguments );
491
- topLevelEmitter.emit( events.NEW_FSM, this );
492
- }
493
-
494
- _.extend( BehavioralFsm.prototype, {
495
- initialize: function() {},
496
-
497
- initClient: function initClient( client ) {
498
- var initialState = this.initialState;
499
- if ( !initialState ) {
500
- throw new Error( "You must specify an initial state for this FSM" );
501
- }
502
- if ( !this.states[ initialState ] ) {
503
- throw new Error( "The initial state specified does not exist in the states object." );
504
- }
505
- this.transition( client, initialState );
506
- },
507
-
508
- configForState: function configForState( newState ) {
509
- var newStateObj = this.states[ newState ];
510
- var child;
511
- _.each( this.hierarchy, function( childListener, key ) {
512
- if ( childListener && typeof childListener.off === "function" ) {
513
- childListener.off();
514
- }
515
- } );
516
-
517
- if ( newStateObj._child ) {
518
- newStateObj._child = utils.getChildFsmInstance( newStateObj._child );
519
- child = newStateObj._child && newStateObj._child.instance;
520
- this.hierarchy[ child.namespace ] = utils.listenToChild( this, child );
521
- }
522
-
523
- return child;
524
- },
525
-
526
- ensureClientMeta: function ensureClientMeta( client ) {
527
- if ( typeof client !== "object" ) {
528
- throw new Error( "An FSM client must be an object." );
529
- }
530
- client[ MACHINA_PROP ] = client[ MACHINA_PROP ] || {};
531
- if ( !client[ MACHINA_PROP ][ this.namespace ] ) {
532
- client[ MACHINA_PROP ][ this.namespace ] = _.cloneDeep( utils.getDefaultClientMeta() );
533
- this.initClient( client );
534
- }
535
- return client[ MACHINA_PROP ][ this.namespace ];
536
- },
537
-
538
- buildEventPayload: function( client, data ) {
539
- if ( _.isPlainObject( data ) ) {
540
- return _.extend( data, { client: client, namespace: this.namespace } );
541
- } else {
542
- return { client: client, data: data || null, namespace: this.namespace };
543
- }
544
- },
545
-
546
- getHandlerArgs: function( args, isCatchAll ) {
547
- // index 0 is the client, index 1 is inputType
548
- // if we're in a catch-all handler, input type needs to be included in the args
549
- // inputType might be an object, so we need to just get the inputType string if so
550
- var _args = args.slice( 0 );
551
- var input = _args[ 1 ];
552
- if ( typeof input === "object" ) {
553
- _args.splice( 1, 1, input.inputType );
554
- }
555
- return isCatchAll ?
556
- _args :
557
- [ _args[ 0 ] ].concat( _args.slice( 2 ) );
558
- },
559
-
560
- getSystemHandlerArgs: function( args, client ) {
561
- return [ client ].concat( args );
562
- },
563
-
564
- handle: function( client, input ) {
565
- var inputDef = input;
566
- if ( typeof input === "undefined" ) {
567
- throw new Error( "The input argument passed to the FSM's handle method is undefined. Did you forget to pass the input name?" );
568
- }
569
- if ( typeof input === "string" ) {
570
- inputDef = { inputType: input, delegated: false, ticket: undefined };
571
- }
572
- var clientMeta = this.ensureClientMeta( client );
573
- var args = utils.getLeaklessArgs( arguments );
574
- if ( typeof input !== "object" ) {
575
- args.splice( 1, 1, inputDef );
576
- }
577
- clientMeta.currentActionArgs = args.slice( 1 );
578
- var currentState = clientMeta.state;
579
- var stateObj = this.states[ currentState ];
580
- var handlerName;
581
- var handler;
582
- var isCatchAll = false;
583
- var child;
584
- var result;
585
- var action;
586
- if ( !clientMeta.inExitHandler ) {
587
- child = this.configForState( currentState );
588
- if ( child && !this.pendingDelegations[ inputDef.ticket ] && !inputDef.bubbling ) {
589
- inputDef.ticket = ( inputDef.ticket || utils.createUUID() );
590
- inputDef.delegated = true;
591
- this.pendingDelegations[ inputDef.ticket ] = { delegatedTo: child.namespace };
592
- // WARNING - returning a value from `handle` on child FSMs is not really supported.
593
- // If you need to return values from child FSM input handlers, use events instead.
594
- result = child.handle.apply( child, args );
595
- } else {
596
- if ( inputDef.ticket && this.pendingDelegations[ inputDef.ticket ] ) {
597
- delete this.pendingDelegations[ inputDef.ticket ];
598
- }
599
- handlerName = stateObj[ inputDef.inputType ] ? inputDef.inputType : "*";
600
- isCatchAll = ( handlerName === "*" );
601
- handler = ( stateObj[ handlerName ] || this[ handlerName ] ) || this[ "*" ];
602
- action = clientMeta.state + "." + handlerName;
603
- clientMeta.currentAction = action;
604
- var eventPayload = this.buildEventPayload(
605
- client,
606
- { inputType: inputDef.inputType, delegated: inputDef.delegated, ticket: inputDef.ticket }
607
- );
608
- if ( !handler ) {
609
- this.emit( events.NO_HANDLER, _.extend( { args: args }, eventPayload ) );
610
- } else {
611
- this.emit( events.HANDLING, eventPayload );
612
- if ( typeof handler === "function" ) {
613
- result = handler.apply( this, this.getHandlerArgs( args, isCatchAll ) );
614
- } else {
615
- result = handler;
616
- this.transition( client, handler );
617
- }
618
- this.emit( events.HANDLED, eventPayload );
619
- }
620
- clientMeta.priorAction = clientMeta.currentAction;
621
- clientMeta.currentAction = "";
622
- clientMeta.currentActionArgs = undefined;
623
- }
624
- }
625
- return result;
626
- },
627
-
628
- transition: function( client, newState ) {
629
- var clientMeta = this.ensureClientMeta( client );
630
- var curState = clientMeta.state;
631
- var curStateObj = this.states[ curState ];
632
- var newStateObj = this.states[ newState ];
633
- var child;
634
- var args = utils.getLeaklessArgs( arguments ).slice( 2 );
635
- if ( !clientMeta.inExitHandler && newState !== curState ) {
636
- if ( newStateObj ) {
637
- child = this.configForState( newState );
638
- if ( curStateObj && curStateObj._onExit ) {
639
- clientMeta.inExitHandler = true;
640
- curStateObj._onExit.call( this, client );
641
- clientMeta.inExitHandler = false;
642
- }
643
- clientMeta.targetReplayState = newState;
644
- clientMeta.priorState = curState;
645
- clientMeta.state = newState;
646
- var eventPayload = this.buildEventPayload( client, {
647
- fromState: clientMeta.priorState,
648
- action: clientMeta.currentAction,
649
- toState: newState
650
- } );
651
- this.emit( events.TRANSITION, eventPayload );
652
- if ( newStateObj._onEnter ) {
653
- newStateObj._onEnter.apply( this, this.getSystemHandlerArgs( args, client ) );
654
- }
655
- this.emit( events.TRANSITIONED, eventPayload );
656
- if ( child ) {
657
- child.handle( client, "_reset" );
658
- }
659
-
660
- if ( clientMeta.targetReplayState === newState ) {
661
- this.processQueue( client, events.NEXT_TRANSITION );
662
- }
663
- return;
664
- }
665
- this.emit( events.INVALID_STATE, this.buildEventPayload( client, {
666
- state: clientMeta.state,
667
- attemptedState: newState
668
- } ) );
669
- }
670
- },
671
-
672
- deferUntilTransition: function( client, stateName ) {
673
- var clientMeta = this.ensureClientMeta( client );
674
- var stateList = _.isArray( stateName ) ? stateName : ( stateName ? [ stateName ] : undefined );
675
- if ( clientMeta.currentActionArgs ) {
676
- var queued = {
677
- type: events.NEXT_TRANSITION,
678
- untilState: stateList,
679
- args: clientMeta.currentActionArgs
680
- };
681
- clientMeta.inputQueue.push( queued );
682
- var eventPayload = this.buildEventPayload( client, {
683
- state: clientMeta.state,
684
- queuedArgs: queued
685
- } );
686
- this.emit( events.DEFERRED, eventPayload );
687
- }
688
- },
689
-
690
- deferAndTransition: function( client, stateName ) {
691
- this.deferUntilTransition( client, stateName );
692
- this.transition( client, stateName );
693
- },
694
-
695
- processQueue: function( client ) {
696
- var clientMeta = this.ensureClientMeta( client );
697
- var filterFn = function( item ) {
698
- return ( ( !item.untilState ) || ( _.includes( item.untilState, clientMeta.state ) ) );
699
- };
700
- var toProcess = _.filter( clientMeta.inputQueue, filterFn );
701
- clientMeta.inputQueue = _.difference( clientMeta.inputQueue, toProcess );
702
- _.each( toProcess, function( item ) {
703
- this.handle.apply( this, [ client ].concat( item.args ) );
704
- }.bind( this ) );
705
- },
706
-
707
- clearQueue: function( client, name ) {
708
- var clientMeta = this.ensureClientMeta( client );
709
- if ( !name ) {
710
- clientMeta.inputQueue = [];
711
- } else {
712
- // first pass we remove the target state from any `untilState` array
713
- _.each( clientMeta.inputQueue, function( item ) {
714
- item.untilState = _.without( item.untilState, name );
715
- } );
716
- // second pass we clear out deferred events with empty untilState arrays
717
- var filter = function( evnt ) {
718
- return evnt.untilState.length !== 0;
719
- };
720
- clientMeta.inputQueue = _.filter( clientMeta.inputQueue, filter );
721
- }
722
- },
723
-
724
- compositeState: function( client ) {
725
- var clientMeta = this.ensureClientMeta( client );
726
- var state = clientMeta.state;
727
- var child = this.states[state]._child && this.states[state]._child.instance;
728
- if ( child ) {
729
- state += "." + child.compositeState( client );
730
- }
731
- return state;
732
- }
733
- }, emitter.getInstance() );
734
-
735
- BehavioralFsm.extend = utils.extend;
736
-
737
- module.exports = BehavioralFsm;
738
-
739
-
740
- /***/ })
741
- /******/ ])
742
- });
743
- ;
744
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay91bml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uIiwid2VicGFjazovLy93ZWJwYWNrL2Jvb3RzdHJhcCBkYmNmMjQ5MTk1NGQwMmNkNjAzNyIsIndlYnBhY2s6Ly8vLi9zcmMvbWFjaGluYS5qcyIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwge1wicm9vdFwiOlwiX1wiLFwiY29tbW9uanNcIjpcImxvZGFzaFwiLFwiY29tbW9uanMyXCI6XCJsb2Rhc2hcIixcImFtZFwiOlwibG9kYXNoXCJ9Iiwid2VicGFjazovLy8uL3NyYy9lbWl0dGVyLmpzIiwid2VicGFjazovLy8uL3NyYy91dGlscy5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvZXZlbnRzLmpzIiwid2VicGFjazovLy8uL3NyYy9Gc20uanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL0JlaGF2aW9yYWxGc20uanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRCxPO0FDVkE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsdUJBQWU7QUFDZjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7OztBQ3RDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBQzs7Ozs7OztBQ1ZELGdEOzs7Ozs7QUNBQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFNO0FBQ047QUFDQTtBQUNBLFFBQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU07QUFD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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSTtBQUNKO0FBQ0EsR0FBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUk7QUFDSjtBQUNBO0FBQ0EsR0FBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxHQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSCxHQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEtBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUM7O0FBRUQ7O0FBRUEiLCJmaWxlIjoibWFjaGluYS5qcyIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiB3ZWJwYWNrVW5pdmVyc2FsTW9kdWxlRGVmaW5pdGlvbihyb290LCBmYWN0b3J5KSB7XG5cdGlmKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0Jylcblx0XHRtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkocmVxdWlyZShcImxvZGFzaFwiKSk7XG5cdGVsc2UgaWYodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKVxuXHRcdGRlZmluZShbXCJsb2Rhc2hcIl0sIGZhY3RvcnkpO1xuXHRlbHNlIGlmKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0Jylcblx0XHRleHBvcnRzW1wibWFjaGluYVwiXSA9IGZhY3RvcnkocmVxdWlyZShcImxvZGFzaFwiKSk7XG5cdGVsc2Vcblx0XHRyb290W1wibWFjaGluYVwiXSA9IGZhY3Rvcnkocm9vdFtcIl9cIl0pO1xufSkodGhpcywgZnVuY3Rpb24oX19XRUJQQUNLX0VYVEVSTkFMX01PRFVMRV8xX18pIHtcbnJldHVybiBcblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gd2VicGFjay91bml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uIiwiIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbiBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblxuIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbiBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pXG4gXHRcdFx0cmV0dXJuIGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdLmV4cG9ydHM7XG5cbiBcdFx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcbiBcdFx0dmFyIG1vZHVsZSA9IGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdID0ge1xuIFx0XHRcdGV4cG9ydHM6IHt9LFxuIFx0XHRcdGlkOiBtb2R1bGVJZCxcbiBcdFx0XHRsb2FkZWQ6IGZhbHNlXG4gXHRcdH07XG5cbiBcdFx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG4gXHRcdG1vZHVsZXNbbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG4gXHRcdC8vIEZsYWcgdGhlIG1vZHVsZSBhcyBsb2FkZWRcbiBcdFx0bW9kdWxlLmxvYWRlZCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cbiBcdC8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oMCk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gd2VicGFjay9ib290c3RyYXAgZGJjZjI0OTE5NTRkMDJjZDYwMzciLCJ2YXIgXyA9IHJlcXVpcmUoIFwibG9kYXNoXCIgKTtcbnZhciBlbWl0dGVyID0gcmVxdWlyZSggXCIuL2VtaXR0ZXJcIiApO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF8ubWVyZ2UoIGVtaXR0ZXIuaW5zdGFuY2UsIHtcblx0RnNtOiByZXF1aXJlKCBcIi4vRnNtXCIgKSxcblx0QmVoYXZpb3JhbEZzbTogcmVxdWlyZSggXCIuL0JlaGF2aW9yYWxGc21cIiApLFxuXHR1dGlsczogcmVxdWlyZSggXCIuL3V0aWxzXCIgKSxcblx0ZXZlbnRMaXN0ZW5lcnM6IHtcblx0XHRuZXdGc206IFtdXG5cdH1cbn0gKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vc3JjL21hY2hpbmEuanNcbi8vIG1vZHVsZSBpZCA9IDBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSBfX1dFQlBBQ0tfRVhURVJOQUxfTU9EVUxFXzFfXztcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCB7XCJyb290XCI6XCJfXCIsXCJjb21tb25qc1wiOlwibG9kYXNoXCIsXCJjb21tb25qczJcIjpcImxvZGFzaFwiLFwiYW1kXCI6XCJsb2Rhc2hcIn1cbi8vIG1vZHVsZSBpZCA9IDFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwidmFyIHV0aWxzID0gcmVxdWlyZSggXCIuL3V0aWxzXCIgKTtcbnZhciBfID0gcmVxdWlyZSggXCJsb2Rhc2hcIiApO1xuXG5mdW5jdGlvbiBnZXRJbnN0YW5jZSgpIHtcblx0cmV0dXJuIHtcblx0XHRlbWl0OiBmdW5jdGlvbiggZXZlbnROYW1lICkge1xuXHRcdFx0dmFyIGFyZ3MgPSB1dGlscy5nZXRMZWFrbGVzc0FyZ3MoIGFyZ3VtZW50cyApO1xuXHRcdFx0aWYgKCB0aGlzLmV2ZW50TGlzdGVuZXJzWyBcIipcIiBdICkge1xuXHRcdFx0XHRfLmVhY2goIHRoaXMuZXZlbnRMaXN0ZW5lcnNbIFwiKlwiIF0sIGZ1bmN0aW9uKCBjYWxsYmFjayApIHtcblx0XHRcdFx0XHRpZiAoICF0aGlzLnVzZVNhZmVFbWl0ICkge1xuXHRcdFx0XHRcdFx0Y2FsbGJhY2suYXBwbHkoIHRoaXMsIGFyZ3MgKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdFx0Y2FsbGJhY2suYXBwbHkoIHRoaXMsIGFyZ3MgKTtcblx0XHRcdFx0XHRcdH0gY2F0Y2ggKCBleGNlcHRpb24gKSB7XG5cdFx0XHRcdFx0XHRcdC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICAqL1xuXHRcdFx0XHRcdFx0XHRpZiAoIGNvbnNvbGUgJiYgdHlwZW9mIGNvbnNvbGUubG9nICE9PSBcInVuZGVmaW5lZFwiICkge1xuXHRcdFx0XHRcdFx0XHRcdGNvbnNvbGUubG9nKCBleGNlcHRpb24uc3RhY2sgKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fS5iaW5kKCB0aGlzICkgKTtcblx0XHRcdH1cblx0XHRcdGlmICggdGhpcy5ldmVudExpc3RlbmVyc1sgZXZlbnROYW1lIF0gKSB7XG5cdFx0XHRcdF8uZWFjaCggdGhpcy5ldmVudExpc3RlbmVyc1sgZXZlbnROYW1lIF0sIGZ1bmN0aW9uKCBjYWxsYmFjayApIHtcblx0XHRcdFx0XHRpZiAoICF0aGlzLnVzZVNhZmVFbWl0ICkge1xuXHRcdFx0XHRcdFx0Y2FsbGJhY2suYXBwbHkoIHRoaXMsIGFyZ3Muc2xpY2UoIDEgKSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRjYWxsYmFjay5hcHBseSggdGhpcywgYXJncy5zbGljZSggMSApICk7XG5cdFx0XHRcdFx0XHR9IGNhdGNoICggZXhjZXB0aW9uICkge1xuXHRcdFx0XHRcdFx0XHQvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAgKi9cblx0XHRcdFx0XHRcdFx0aWYgKCBjb25zb2xlICYmIHR5cGVvZiBjb25zb2xlLmxvZyAhPT0gXCJ1bmRlZmluZWRcIiApIHtcblx0XHRcdFx0XHRcdFx0XHRjb25zb2xlLmxvZyggZXhjZXB0aW9uLnN0YWNrICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0uYmluZCggdGhpcyApICk7XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdG9uOiBmdW5jdGlvbiggZXZlbnROYW1lLCBjYWxsYmFjayApIHtcblx0XHRcdHZhciBzZWxmID0gdGhpcztcblx0XHRcdHNlbGYuZXZlbnRMaXN0ZW5lcnMgPSBzZWxmLmV2ZW50TGlzdGVuZXJzIHx8IHsgXCIqXCI6IFtdIH07XG5cdFx0XHRpZiAoICFzZWxmLmV2ZW50TGlzdGVuZXJzWyBldmVudE5hbWUgXSApIHtcblx0XHRcdFx0c2VsZi5ldmVudExpc3RlbmVyc1sgZXZlbnROYW1lIF0gPSBbXTtcblx0XHRcdH1cblx0XHRcdHNlbGYuZXZlbnRMaXN0ZW5lcnNbIGV2ZW50TmFtZSBdLnB1c2goIGNhbGxiYWNrICk7XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRldmVudE5hbWU6IGV2ZW50TmFtZSxcblx0XHRcdFx0Y2FsbGJhY2s6IGNhbGxiYWNrLFxuXHRcdFx0XHRvZmY6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHNlbGYub2ZmKCBldmVudE5hbWUsIGNhbGxiYWNrICk7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0fSxcblxuXHRcdG9mZjogZnVuY3Rpb24oIGV2ZW50TmFtZSwgY2FsbGJhY2sgKSB7XG5cdFx0XHR0aGlzLmV2ZW50TGlzdGVuZXJzID0gdGhpcy5ldmVudExpc3RlbmVycyB8fCB7IFwiKlwiOiBbXSB9O1xuXHRcdFx0aWYgKCAhZXZlbnROYW1lICkge1xuXHRcdFx0XHR0aGlzLmV2ZW50TGlzdGVuZXJzID0ge307XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdHRoaXMuZXZlbnRMaXN0ZW5lcnNbIGV2ZW50TmFtZSBdID0gXy53aXRob3V0KCB0aGlzLmV2ZW50TGlzdGVuZXJzWyBldmVudE5hbWUgXSwgY2FsbGJhY2sgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aGlzLmV2ZW50TGlzdGVuZXJzWyBldmVudE5hbWUgXSA9IFtdO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblx0Z2V0SW5zdGFuY2U6IGdldEluc3RhbmNlLFxuXHRpbnN0YW5jZTogZ2V0SW5zdGFuY2UoKVxufTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vc3JjL2VtaXR0ZXIuanNcbi8vIG1vZHVsZSBpZCA9IDJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwidmFyIHNsaWNlID0gW10uc2xpY2U7XG52YXIgZXZlbnRzID0gcmVxdWlyZSggXCIuL2V2ZW50cy5qc1wiICk7XG52YXIgXyA9IHJlcXVpcmUoIFwibG9kYXNoXCIgKTtcblxudmFyIG1ha2VGc21OYW1lc3BhY2UgPSAoIGZ1bmN0aW9uKCkge1xuXHR2YXIgbWFjaGluYUNvdW50ID0gMDtcblx0cmV0dXJuIGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiBcImZzbS5cIiArIG1hY2hpbmFDb3VudCsrO1xuXHR9O1xufSApKCk7XG5cbmZ1bmN0aW9uIGdldERlZmF1bHRCZWhhdmlvcmFsT3B0aW9ucygpIHtcblx0cmV0dXJuIHtcblx0XHRpbml0aWFsU3RhdGU6IFwidW5pbml0aWFsaXplZFwiLFxuXHRcdGV2ZW50TGlzdGVuZXJzOiB7XG5cdFx0XHRcIipcIjogW11cblx0XHR9LFxuXHRcdHN0YXRlczoge30sXG5cdFx0bmFtZXNwYWNlOiBtYWtlRnNtTmFtZXNwYWNlKCksXG5cdFx0dXNlU2FmZUVtaXQ6IGZhbHNlLFxuXHRcdGhpZXJhcmNoeToge30sXG5cdFx0cGVuZGluZ0RlbGVnYXRpb25zOiB7fVxuXHR9O1xufVxuXG5mdW5jdGlvbiBnZXREZWZhdWx0Q2xpZW50TWV0YSgpIHtcblx0cmV0dXJuIHtcblx0XHRpbnB1dFF1ZXVlOiBbXSxcblx0XHR0YXJnZXRSZXBsYXlTdGF0ZTogXCJcIixcblx0XHRzdGF0ZTogdW5kZWZpbmVkLFxuXHRcdHByaW9yU3RhdGU6IHVuZGVmaW5lZCxcblx0XHRwcmlvckFjdGlvbjogXCJcIixcblx0XHRjdXJyZW50QWN0aW9uOiBcIlwiLFxuXHRcdGN1cnJlbnRBY3Rpb25BcmdzOiB1bmRlZmluZWQsXG5cdFx0aW5FeGl0SGFuZGxlcjogZmFsc2Vcblx0fTtcbn1cblxuZnVuY3Rpb24gZ2V0TGVha2xlc3NBcmdzKCBhcmdzLCBzdGFydElkeCApIHtcblx0dmFyIHJlc3VsdCA9IFtdO1xuXHRmb3IgKCB2YXIgaSA9ICggc3RhcnRJZHggfHwgMCApOyBpIDwgYXJncy5sZW5ndGg7IGkrKyApIHtcblx0XHRyZXN1bHRbIGkgXSA9IGFyZ3NbIGkgXTtcblx0fVxuXHRyZXR1cm4gcmVzdWx0O1xufVxuLypcblx0aGFuZGxlIC0+XG5cdFx0Y2hpbGQgPSBzdGF0ZU9iai5fY2hpbGQgJiYgc3RhdGVPYmouX2NoaWxkLmluc3RhbmNlO1xuXG5cdHRyYW5zaXRpb24gLT5cblx0XHRuZXdTdGF0ZU9iai5fY2hpbGQgPSBnZXRDaGlsZEZzbUluc3RhbmNlKCBuZXdTdGF0ZU9iai5fY2hpbGQgKTtcblx0XHRjaGlsZCA9IG5ld1N0YXRlT2JqLl9jaGlsZCAmJiBuZXdTdGF0ZU9iai5fY2hpbGQuaW5zdGFuY2U7XG4qL1xuZnVuY3Rpb24gZ2V0Q2hpbGRGc21JbnN0YW5jZSggY29uZmlnICkge1xuXHRpZiAoICFjb25maWcgKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdHZhciBjaGlsZEZzbURlZmluaXRpb24gPSB7fTtcblx0aWYgKCB0eXBlb2YgY29uZmlnID09PSBcIm9iamVjdFwiICkge1xuXHRcdC8vIGlzIHRoaXMgYSBjb25maWcgb2JqZWN0IHdpdGggYSBmYWN0b3J5P1xuXHRcdGlmICggY29uZmlnLmZhY3RvcnkgKSB7XG5cdFx0XHRjaGlsZEZzbURlZmluaXRpb24gPSBjb25maWc7XG5cdFx0XHRjaGlsZEZzbURlZmluaXRpb24uaW5zdGFuY2UgPSBjaGlsZEZzbURlZmluaXRpb24uZmFjdG9yeSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBhc3N1bWluZyB0aGlzIGlzIGEgbWFjaGluYSBpbnN0YW5jZVxuXHRcdFx0Y2hpbGRGc21EZWZpbml0aW9uLmZhY3RvcnkgPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuIGNvbmZpZztcblx0XHRcdH07XG5cdFx0fVxuXHR9IGVsc2UgaWYgKCB0eXBlb2YgY29uZmlnID09PSBcImZ1bmN0aW9uXCIgKSB7XG5cdFx0Y2hpbGRGc21EZWZpbml0aW9uLmZhY3RvcnkgPSBjb25maWc7XG5cdH1cblx0Y2hpbGRGc21EZWZpbml0aW9uLmluc3RhbmNlID0gY2hpbGRGc21EZWZpbml0aW9uLmZhY3RvcnkoKTtcblx0cmV0dXJuIGNoaWxkRnNtRGVmaW5pdGlvbjtcbn1cblxuZnVuY3Rpb24gbGlzdGVuVG9DaGlsZCggZnNtLCBjaGlsZCApIHtcblx0Ly8gTmVlZCB0byBpbnZlc3RpZ2F0ZSBwb3RlbnRpYWwgZm9yIGRpc2NhcmRlZCBldmVudFxuXHQvLyBsaXN0ZW5lciBtZW1vcnkgbGVhayBpbiBsb25nLXJ1bm5pbmcsIGRlZXBseS1uZXN0ZWQgaGllcmFyY2hpZXMuXG5cdHJldHVybiBjaGlsZC5vbiggXCIqXCIsIGZ1bmN0aW9uKCBldmVudE5hbWUsIGRhdGEgKSB7XG5cdFx0c3dpdGNoICggZXZlbnROYW1lICkge1xuXHRcdFx0Y2FzZSBldmVudHMuTk9fSEFORExFUjpcblx0XHRcdFx0aWYgKCAhZGF0YS50aWNrZXQgJiYgIWRhdGEuZGVsZWdhdGVkICYmIGRhdGEubmFtZXNwYWNlICE9PSBmc20ubmFtZXNwYWNlICkge1xuXHRcdFx0XHRcdC8vIE9rIC0gd2UncmUgZGVhbGluZyB3LyBhIGNoaWxkIGhhbmRsaW5nIGlucHV0IHRoYXQgc2hvdWxkIGJ1YmJsZSB1cFxuXHRcdFx0XHRcdGRhdGEuYXJnc1sgMSBdLmJ1YmJsaW5nID0gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHQvLyB3ZSBkbyBOT1QgYnViYmxlIF9yZXNldCBpbnB1dHMgdXAgdG8gdGhlIHBhcmVudFxuXHRcdFx0XHRpZiAoIGRhdGEuaW5wdXRUeXBlICE9PSBcIl9yZXNldFwiICkge1xuXHRcdFx0XHRcdGZzbS5oYW5kbGUuYXBwbHkoIGZzbSwgZGF0YS5hcmdzICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIGV2ZW50cy5IQU5ETElORyA6XG5cdFx0XHRcdHZhciB0aWNrZXQgPSBkYXRhLnRpY2tldDtcblx0XHRcdFx0aWYgKCB0aWNrZXQgJiYgZnNtLnBlbmRpbmdEZWxlZ2F0aW9uc1sgdGlja2V0IF0gKSB7XG5cdFx0XHRcdFx0ZGVsZXRlIGZzbS5wZW5kaW5nRGVsZWdhdGlvbnNbIHRpY2tldCBdO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGZzbS5lbWl0KCBldmVudE5hbWUsIGRhdGEgKTsgLy8gcG9zc2libHkgdHJhbnNmb3JtIHBheWxvYWQ/XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0ZnNtLmVtaXQoIGV2ZW50TmFtZSwgZGF0YSApOyAvLyBwb3NzaWJseSB0cmFuc2Zvcm0gcGF5bG9hZD9cblx0XHRcdFx0YnJlYWs7XG5cdFx0fVxuXHR9ICk7XG59XG5cbi8vIF9tYWNoS2V5cyBhcmUgbWVtYmVycyB3ZSB3YW50IHRvIHRyYWNrIGFjcm9zcyB0aGUgcHJvdG90eXBlIGNoYWluIG9mIGFuIGV4dGVuZGVkIEZTTSBjb25zdHJ1Y3RvclxuLy8gU2luY2Ugd2Ugd2FudCB0byBldmVudHVhbGx5IG1lcmdlIHRoZSBhZ2dyZWdhdGUgb2YgdGhvc2UgdmFsdWVzIG9udG8gdGhlIGluc3RhbmNlIHNvIHRoYXQgRlNNc1xuLy8gdGhhdCBzaGFyZSB0aGUgc2FtZSBleHRlbmRlZCBwcm90b3R5cGUgd29uJ3Qgc2hhcmUgc3RhdGUgKm9uKiB0aG9zZSBwcm90b3R5cGVzLlxudmFyIF9tYWNoS2V5cyA9IFsgXCJzdGF0ZXNcIiwgXCJpbml0aWFsU3RhdGVcIiBdO1xudmFyIGV4dGVuZCA9IGZ1bmN0aW9uKCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcyApIHtcblx0dmFyIHBhcmVudCA9IHRoaXM7XG5cdHZhciBmc207IC8vIHBsYWNlaG9sZGVyIGZvciBpbnN0YW5jZSBjb25zdHJ1Y3RvclxuXHR2YXIgbWFjaE9iaiA9IHt9OyAvLyBvYmplY3QgdXNlZCB0byBob2xkIGluaXRpYWxTdGF0ZSAmIHN0YXRlcyBmcm9tIHByb3RvdHlwZSBmb3IgaW5zdGFuY2UtbGV2ZWwgbWVyZ2luZ1xuXHR2YXIgQ3RvciA9IGZ1bmN0aW9uKCkge307IC8vIHBsYWNlaG9sZGVyIGN0b3IgZnVuY3Rpb24gdXNlZCB0byBpbnNlcnQgbGV2ZWwgaW4gcHJvdG90eXBlIGNoYWluXG5cblx0Ly8gVGhlIGNvbnN0cnVjdG9yIGZ1bmN0aW9uIGZvciB0aGUgbmV3IHN1YmNsYXNzIGlzIGVpdGhlciBkZWZpbmVkIGJ5IHlvdVxuXHQvLyAodGhlIFwiY29uc3RydWN0b3JcIiBwcm9wZXJ0eSBpbiB5b3VyIGBleHRlbmRgIGRlZmluaXRpb24pLCBvciBkZWZhdWx0ZWRcblx0Ly8gYnkgdXMgdG8gc2ltcGx5IGNhbGwgdGhlIHBhcmVudCdzIGNvbnN0cnVjdG9yLlxuXHRpZiAoIHByb3RvUHJvcHMgJiYgcHJvdG9Qcm9wcy5oYXNPd25Qcm9wZXJ0eSggXCJjb25zdHJ1Y3RvclwiICkgKSB7XG5cdFx0ZnNtID0gcHJvdG9Qcm9wcy5jb25zdHJ1Y3Rvcjtcblx0fSBlbHNlIHtcblx0XHQvLyBUaGUgZGVmYXVsdCBtYWNoaW5hIGNvbnN0cnVjdG9yICh3aGVuIHVzaW5nIGluaGVyaXRhbmNlKSBjcmVhdGVzIGFcblx0XHQvLyBkZWVwIGNvcHkgb2YgdGhlIHN0YXRlcy9pbml0aWFsU3RhdGUgdmFsdWVzIGZyb20gdGhlIHByb3RvdHlwZSBhbmRcblx0XHQvLyBleHRlbmRzIHRoZW0gb3ZlciB0aGUgaW5zdGFuY2Ugc28gdGhhdCB0aGV5J2xsIGJlIGluc3RhbmNlLWxldmVsLlxuXHRcdC8vIElmIGFuIG9wdGlvbnMgYXJnIChhcmdzWzBdKSBpcyBwYXNzZWQgaW4sIGEgc3RhdGVzIG9yIGludGlhbFN0YXRlXG5cdFx0Ly8gdmFsdWUgd2lsbCBiZSBwcmVmZXJyZWQgb3ZlciBhbnkgZGF0YSBwdWxsZWQgdXAgZnJvbSB0aGUgcHJvdG90eXBlLlxuXHRcdGZzbSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIGFyZ3MgPSBzbGljZS5jYWxsKCBhcmd1bWVudHMsIDAgKTtcblx0XHRcdGFyZ3NbIDAgXSA9IGFyZ3NbIDAgXSB8fCB7fTtcblx0XHRcdHZhciBibGVuZGVkU3RhdGU7XG5cdFx0XHR2YXIgaW5zdGFuY2VTdGF0ZXMgPSBhcmdzWyAwIF0uc3RhdGVzIHx8IHt9O1xuXHRcdFx0YmxlbmRlZFN0YXRlID0gXy5tZXJnZSggXy5jbG9uZURlZXAoIG1hY2hPYmogKSwgeyBzdGF0ZXM6IGluc3RhbmNlU3RhdGVzIH0gKTtcblx0XHRcdGJsZW5kZWRTdGF0ZS5pbml0aWFsU3RhdGUgPSBhcmdzWyAwIF0uaW5pdGlhbFN0YXRlIHx8IHRoaXMuaW5pdGlhbFN0YXRlO1xuXHRcdFx0Xy5leHRlbmQoIGFyZ3NbIDAgXSwgYmxlbmRlZFN0YXRlICk7XG5cdFx0XHRwYXJlbnQuYXBwbHkoIHRoaXMsIGFyZ3MgKTtcblx0XHR9O1xuXHR9XG5cblx0Ly8gSW5oZXJpdCBjbGFzcyAoc3RhdGljKSBwcm9wZXJ0aWVzIGZyb20gcGFyZW50LlxuXHRfLm1lcmdlKCBmc20sIHBhcmVudCApO1xuXG5cdC8vIFNldCB0aGUgcHJvdG90eXBlIGNoYWluIHRvIGluaGVyaXQgZnJvbSBgcGFyZW50YCwgd2l0aG91dCBjYWxsaW5nXG5cdC8vIGBwYXJlbnRgJ3MgY29uc3RydWN0b3IgZnVuY3Rpb24uXG5cdEN0b3IucHJvdG90eXBlID0gcGFyZW50LnByb3RvdHlwZTtcblx0ZnNtLnByb3RvdHlwZSA9IG5ldyBDdG9yKCk7XG5cblx0Ly8gQWRkIHByb3RvdHlwZSBwcm9wZXJ0aWVzIChpbnN0YW5jZSBwcm9wZXJ0aWVzKSB0byB0aGUgc3ViY2xhc3MsXG5cdC8vIGlmIHN1cHBsaWVkLlxuXHRpZiAoIHByb3RvUHJvcHMgKSB7XG5cdFx0Xy5leHRlbmQoIGZzbS5wcm90b3R5cGUsIHByb3RvUHJvcHMgKTtcblx0XHRfLm1lcmdlKCBtYWNoT2JqLCBfLnRyYW5zZm9ybSggcHJvdG9Qcm9wcywgZnVuY3Rpb24oIGFjY3VtLCB2YWwsIGtleSApIHtcblx0XHRcdGlmICggX21hY2hLZXlzLmluZGV4T2YoIGtleSApICE9PSAtMSApIHtcblx0XHRcdFx0YWNjdW1bIGtleSBdID0gdmFsO1xuXHRcdFx0fVxuXHRcdH0gKSApO1xuXHR9XG5cblx0Ly8gQWRkIHN0YXRpYyBwcm9wZXJ0aWVzIHRvIHRoZSBjb25zdHJ1Y3RvciBmdW5jdGlvbiwgaWYgc3VwcGxpZWQuXG5cdGlmICggc3RhdGljUHJvcHMgKSB7XG5cdFx0Xy5tZXJnZSggZnNtLCBzdGF0aWNQcm9wcyApO1xuXHR9XG5cblx0Ly8gQ29ycmVjdGx5IHNldCBjaGlsZCdzIGBwcm90b3R5cGUuY29uc3RydWN0b3JgLlxuXHRmc20ucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gZnNtO1xuXG5cdC8vIFNldCBhIGNvbnZlbmllbmNlIHByb3BlcnR5IGluIGNhc2UgdGhlIHBhcmVudCdzIHByb3RvdHlwZSBpcyBuZWVkZWQgbGF0ZXIuXG5cdGZzbS5fX3N1cGVyX18gPSBwYXJlbnQucHJvdG90eXBlO1xuXHRyZXR1cm4gZnNtO1xufTtcblxuZnVuY3Rpb24gY3JlYXRlVVVJRCgpIHtcblx0dmFyIHMgPSBbXTtcblx0dmFyIGhleERpZ2l0cyA9IFwiMDEyMzQ1Njc4OWFiY2RlZlwiO1xuXHRmb3IgKCB2YXIgaSA9IDA7IGkgPCAzNjsgaSsrICkge1xuXHRcdHNbIGkgXSA9IGhleERpZ2l0cy5zdWJzdHIoIE1hdGguZmxvb3IoIE1hdGgucmFuZG9tKCkgKiAweDEwICksIDEgKTtcblx0fVxuXHRzWyAxNCBdID0gXCI0XCI7IC8vIGJpdHMgMTItMTUgb2YgdGhlIHRpbWVfaGlfYW5kX3ZlcnNpb24gZmllbGQgdG8gMDAxMFxuXHQvKiBqc2hpbnQgaWdub3JlOnN0YXJ0ICovXG5cdHNbIDE5IF0gPSBoZXhEaWdpdHMuc3Vic3RyKCAoIHNbIDE5IF0gJiAweDMgKSB8IDB4OCwgMSApOyAvLyBiaXRzIDYtNyBvZiB0aGUgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZCB0byAwMVxuXHQvKiBqc2hpbnQgaWdub3JlOmVuZCAqL1xuXHRzWyA4IF0gPSBzWyAxMyBdID0gc1sgMTggXSA9IHNbIDIzIF0gPSBcIi1cIjtcblx0cmV0dXJuIHMuam9pbiggXCJcIiApO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblx0Y3JlYXRlVVVJRDogY3JlYXRlVVVJRCxcblx0ZXh0ZW5kOiBleHRlbmQsXG5cdGdldERlZmF1bHRCZWhhdmlvcmFsT3B0aW9uczogZ2V0RGVmYXVsdEJlaGF2aW9yYWxPcHRpb25zLFxuXHRnZXREZWZhdWx0T3B0aW9uczogZ2V0RGVmYXVsdEJlaGF2aW9yYWxPcHRpb25zLFxuXHRnZXREZWZhdWx0Q2xpZW50TWV0YTogZ2V0RGVmYXVsdENsaWVudE1ldGEsXG5cdGdldENoaWxkRnNtSW5zdGFuY2U6IGdldENoaWxkRnNtSW5zdGFuY2UsXG5cdGdldExlYWtsZXNzQXJnczogZ2V0TGVha2xlc3NBcmdzLFxuXHRsaXN0ZW5Ub0NoaWxkOiBsaXN0ZW5Ub0NoaWxkLFxuXHRtYWtlRnNtTmFtZXNwYWNlOiBtYWtlRnNtTmFtZXNwYWNlXG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9zcmMvdXRpbHMuanNcbi8vIG1vZHVsZSBpZCA9IDNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSB7XG5cdE5FWFRfVFJBTlNJVElPTjogXCJ0cmFuc2l0aW9uXCIsXG5cdEhBTkRMSU5HOiBcImhhbmRsaW5nXCIsXG5cdEhBTkRMRUQ6IFwiaGFuZGxlZFwiLFxuXHROT19IQU5ETEVSOiBcIm5vaGFuZGxlclwiLFxuXHRUUkFOU0lUSU9OOiBcInRyYW5zaXRpb25cIixcblx0VFJBTlNJVElPTkVEOiBcInRyYW5zaXRpb25lZFwiLFxuXHRJTlZBTElEX1NUQVRFOiBcImludmFsaWRzdGF0ZVwiLFxuXHRERUZFUlJFRDogXCJkZWZlcnJlZFwiLFxuXHRORVdfRlNNOiBcIm5ld2ZzbVwiXG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9zcmMvZXZlbnRzLmpzXG4vLyBtb2R1bGUgaWQgPSA0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInZhciBCZWhhdmlvcmFsRnNtID0gcmVxdWlyZSggXCIuL0JlaGF2aW9yYWxGc21cIiApO1xudmFyIHV0aWxzID0gcmVxdWlyZSggXCIuL3V0aWxzXCIgKTtcbnZhciBfID0gcmVxdWlyZSggXCJsb2Rhc2hcIiApO1xuXG52YXIgRnNtID0ge1xuXHRjb25zdHJ1Y3RvcjogZnVuY3Rpb24oKSB7XG5cdFx0QmVoYXZpb3JhbEZzbS5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0dGhpcy5lbnN1cmVDbGllbnRNZXRhKCk7XG5cdH0sXG5cdGluaXRDbGllbnQ6IGZ1bmN0aW9uIGluaXRDbGllbnQoKSB7XG5cdFx0dmFyIGluaXRpYWxTdGF0ZSA9IHRoaXMuaW5pdGlhbFN0YXRlO1xuXHRcdGlmICggIWluaXRpYWxTdGF0ZSApIHtcblx0XHRcdHRocm93IG5ldyBFcnJvciggXCJZb3UgbXVzdCBzcGVjaWZ5IGFuIGluaXRpYWwgc3RhdGUgZm9yIHRoaXMgRlNNXCIgKTtcblx0XHR9XG5cdFx0aWYgKCAhdGhpcy5zdGF0ZXNbIGluaXRpYWxTdGF0ZSBdICkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCBcIlRoZSBpbml0aWFsIHN0YXRlIHNwZWNpZmllZCBkb2VzIG5vdCBleGlzdCBpbiB0aGUgc3RhdGVzIG9iamVjdC5cIiApO1xuXHRcdH1cblx0XHR0aGlzLnRyYW5zaXRpb24oIGluaXRpYWxTdGF0ZSApO1xuXHR9LFxuXHRlbnN1cmVDbGllbnRNZXRhOiBmdW5jdGlvbiBlbnN1cmVDbGllbnRNZXRhKCkge1xuXHRcdGlmICggIXRoaXMuX3N0YW1wZWQgKSB7XG5cdFx0XHR0aGlzLl9zdGFtcGVkID0gdHJ1ZTtcblx0XHRcdF8uZGVmYXVsdHMoIHRoaXMsIF8uY2xvbmVEZWVwKCB1dGlscy5nZXREZWZhdWx0Q2xpZW50TWV0YSgpICkgKTtcblx0XHRcdHRoaXMuaW5pdENsaWVudCgpO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHRlbnN1cmVDbGllbnRBcmc6IGZ1bmN0aW9uKCBhcmdzICkge1xuXHRcdHZhciBfYXJncyA9IGFyZ3M7XG5cdFx0Ly8gd2UgbmVlZCB0byB0ZXN0IHRoZSBhcmdzIGFuZCB2ZXJpZnkgdGhhdCBpZiBhIGNsaWVudCBhcmcgaGFzXG5cdFx0Ly8gYmVlbiBwYXNzZWQsIGl0IG11c3QgYmUgdGhpcyBGU00gaW5zdGFuY2UgKHRoaXMgaXNuJ3QgYSBiZWhhdmlvcmFsIEZTTSlcblx0XHRpZiAoIHR5cGVvZiBfYXJnc1sgMCBdID09PSBcIm9iamVjdFwiICYmICEoIFwiaW5wdXRUeXBlXCIgaW4gX2FyZ3NbIDAgXSApICYmIF9hcmdzWyAwIF0gIT09IHRoaXMgKSB7XG5cdFx0XHRfYXJncy5zcGxpY2UoIDAsIDEsIHRoaXMgKTtcblx0XHR9IGVsc2UgaWYgKCB0eXBlb2YgX2FyZ3NbIDAgXSAhPT0gXCJvYmplY3RcIiB8fCAoIHR5cGVvZiBfYXJnc1sgMCBdID09PSBcIm9iamVjdFwiICYmICggXCJpbnB1dFR5cGVcIiBpbiBfYXJnc1sgMCBdICkgKSApIHtcblx0XHRcdF9hcmdzLnVuc2hpZnQoIHRoaXMgKTtcblx0XHR9XG5cdFx0cmV0dXJuIF9hcmdzO1xuXHR9LFxuXG5cdGdldEhhbmRsZXJBcmdzOiBmdW5jdGlvbiggYXJncywgaXNDYXRjaEFsbCApIHtcblx0XHQvLyBpbmRleCAwIGlzIHRoZSBjbGllbnQsIGluZGV4IDEgaXMgaW5wdXRUeXBlXG5cdFx0Ly8gaWYgd2UncmUgaW4gYSBjYXRjaC1hbGwgaGFuZGxlciwgaW5wdXQgdHlwZSBuZWVkcyB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXJnc1xuXHRcdC8vIGlucHV0VHlwZSBtaWdodCBiZSBhbiBvYmplY3QsIHNvIHdlIG5lZWQgdG8ganVzdCBnZXQgdGhlIGlucHV0VHlwZSBzdHJpbmcgaWYgc29cblx0XHR2YXIgX2FyZ3MgPSBhcmdzO1xuXHRcdHZhciBpbnB1dCA9IF9hcmdzWyAxIF07XG5cdFx0aWYgKCB0eXBlb2YgaW5wdXRUeXBlID09PSBcIm9iamVjdFwiICkge1xuXHRcdFx0X2FyZ3Muc3BsaWNlKCAxLCAxLCBpbnB1dC5pbnB1dFR5cGUgKTtcblx0XHR9XG5cdFx0cmV0dXJuIGlzQ2F0Y2hBbGwgP1xuXHRcdFx0X2FyZ3Muc2xpY2UoIDEgKSA6XG5cdFx0XHRfYXJncy5zbGljZSggMiApO1xuXHR9LFxuXG5cdGdldFN5c3RlbUhhbmRsZXJBcmdzOiBmdW5jdGlvbiggYXJncywgY2xpZW50ICkge1xuXHRcdHJldHVybiBhcmdzO1xuXHR9LFxuXG5cdC8vIFwiY2xhc3NpY1wiIG1hY2hpbmEgRlNNIGRvIG5vdCBlbWl0IHRoZSBjbGllbnQgcHJvcGVydHkgb24gZXZlbnRzICh3aGljaCB3b3VsZCBiZSB0aGUgRlNNIGl0c2VsZilcblx0YnVpbGRFdmVudFBheWxvYWQ6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBhcmdzID0gdGhpcy5lbnN1cmVDbGllbnRBcmcoIHV0aWxzLmdldExlYWtsZXNzQXJncyggYXJndW1lbnRzICkgKTtcblx0XHR2YXIgZGF0YSA9IGFyZ3NbIDEgXTtcblx0XHRpZiAoIF8uaXNQbGFpbk9iamVjdCggZGF0YSApICkge1xuXHRcdFx0cmV0dXJuIF8uZXh0ZW5kKCBkYXRhLCB7IG5hbWVzcGFjZTogdGhpcy5uYW1lc3BhY2UgfSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4geyBkYXRhOiBkYXRhIHx8IG51bGwsIG5hbWVzcGFjZTogdGhpcy5uYW1lc3BhY2UgfTtcblx0XHR9XG5cdH1cbn07XG5cbl8uZWFjaCggW1xuXHRcImhhbmRsZVwiLFxuXHRcInRyYW5zaXRpb25cIixcblx0XCJkZWZlclVudGlsVHJhbnNpdGlvblwiLFxuXHRcInByb2Nlc3NRdWV1ZVwiLFxuXHRcImNsZWFyUXVldWVcIlxuXSwgZnVuY3Rpb24oIG1ldGhvZFdpdGhDbGllbnRJbmplY3RlZCApIHtcblx0RnNtWyBtZXRob2RXaXRoQ2xpZW50SW5qZWN0ZWQgXSA9IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBhcmdzID0gdGhpcy5lbnN1cmVDbGllbnRBcmcoIHV0aWxzLmdldExlYWtsZXNzQXJncyggYXJndW1lbnRzICkgKTtcblx0XHRyZXR1cm4gQmVoYXZpb3JhbEZzbS5wcm90b3R5cGVbIG1ldGhvZFdpdGhDbGllbnRJbmplY3RlZCBdLmFwcGx5KCB0aGlzLCBhcmdzICk7XG5cdH07XG59ICk7XG5cbkZzbSA9IEJlaGF2aW9yYWxGc20uZXh0ZW5kKCBGc20gKTtcblxubW9kdWxlLmV4cG9ydHMgPSBGc207XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL3NyYy9Gc20uanNcbi8vIG1vZHVsZSBpZCA9IDVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwidmFyIF8gPSByZXF1aXJlKCBcImxvZGFzaFwiICk7XG52YXIgdXRpbHMgPSByZXF1aXJlKCBcIi4vdXRpbHNcIiApO1xudmFyIGVtaXR0ZXIgPSByZXF1aXJlKCBcIi4vZW1pdHRlclwiICk7XG52YXIgdG9wTGV2ZWxFbWl0dGVyID0gZW1pdHRlci5pbnN0YW5jZTtcbnZhciBldmVudHMgPSByZXF1aXJlKCBcIi4vZXZlbnRzXCIgKTtcblxudmFyIE1BQ0hJTkFfUFJPUCA9IFwiX19tYWNoaW5hX19cIjtcblxuZnVuY3Rpb24gQmVoYXZpb3JhbEZzbSggb3B0aW9ucyApIHtcblx0Xy5leHRlbmQoIHRoaXMsIG9wdGlvbnMgKTtcblx0Xy5kZWZhdWx0cyggdGhpcywgdXRpbHMuZ2V0RGVmYXVsdEJlaGF2aW9yYWxPcHRpb25zKCkgKTtcblx0dGhpcy5pbml0aWFsaXplLmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0dG9wTGV2ZWxFbWl0dGVyLmVtaXQoIGV2ZW50cy5ORVdfRlNNLCB0aGlzICk7XG59XG5cbl8uZXh0ZW5kKCBCZWhhdmlvcmFsRnNtLnByb3RvdHlwZSwge1xuXHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHt9LFxuXG5cdGluaXRDbGllbnQ6IGZ1bmN0aW9uIGluaXRDbGllbnQoIGNsaWVudCApIHtcblx0XHR2YXIgaW5pdGlhbFN0YXRlID0gdGhpcy5pbml0aWFsU3RhdGU7XG5cdFx0aWYgKCAhaW5pdGlhbFN0YXRlICkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCBcIllvdSBtdXN0IHNwZWNpZnkgYW4gaW5pdGlhbCBzdGF0ZSBmb3IgdGhpcyBGU01cIiApO1xuXHRcdH1cblx0XHRpZiAoICF0aGlzLnN0YXRlc1sgaW5pdGlhbFN0YXRlIF0gKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoIFwiVGhlIGluaXRpYWwgc3RhdGUgc3BlY2lmaWVkIGRvZXMgbm90IGV4aXN0IGluIHRoZSBzdGF0ZXMgb2JqZWN0LlwiICk7XG5cdFx0fVxuXHRcdHRoaXMudHJhbnNpdGlvbiggY2xpZW50LCBpbml0aWFsU3RhdGUgKTtcblx0fSxcblxuXHRjb25maWdGb3JTdGF0ZTogZnVuY3Rpb24gY29uZmlnRm9yU3RhdGUoIG5ld1N0YXRlICkge1xuXHRcdHZhciBuZXdTdGF0ZU9iaiA9IHRoaXMuc3RhdGVzWyBuZXdTdGF0ZSBdO1xuXHRcdHZhciBjaGlsZDtcblx0XHRfLmVhY2goIHRoaXMuaGllcmFyY2h5LCBmdW5jdGlvbiggY2hpbGRMaXN0ZW5lciwga2V5ICkge1xuXHRcdFx0aWYgKCBjaGlsZExpc3RlbmVyICYmIHR5cGVvZiBjaGlsZExpc3RlbmVyLm9mZiA9PT0gXCJmdW5jdGlvblwiICkge1xuXHRcdFx0XHRjaGlsZExpc3RlbmVyLm9mZigpO1xuXHRcdFx0fVxuXHRcdH0gKTtcblxuXHRcdGlmICggbmV3U3RhdGVPYmouX2NoaWxkICkge1xuXHRcdFx0bmV3U3RhdGVPYmouX2NoaWxkID0gdXRpbHMuZ2V0Q2hpbGRGc21JbnN0YW5jZSggbmV3U3RhdGVPYmouX2NoaWxkICk7XG5cdFx0XHRjaGlsZCA9IG5ld1N0YXRlT2JqLl9jaGlsZCAmJiBuZXdTdGF0ZU9iai5fY2hpbGQuaW5zdGFuY2U7XG5cdFx0XHR0aGlzLmhpZXJhcmNoeVsgY2hpbGQubmFtZXNwYWNlIF0gPSB1dGlscy5saXN0ZW5Ub0NoaWxkKCB0aGlzLCBjaGlsZCApO1xuXHRcdH1cblxuXHRcdHJldHVybiBjaGlsZDtcblx0fSxcblxuXHRlbnN1cmVDbGllbnRNZXRhOiBmdW5jdGlvbiBlbnN1cmVDbGllbnRNZXRhKCBjbGllbnQgKSB7XG5cdFx0aWYgKCB0eXBlb2YgY2xpZW50ICE9PSBcIm9iamVjdFwiICkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCBcIkFuIEZTTSBjbGllbnQgbXVzdCBiZSBhbiBvYmplY3QuXCIgKTtcblx0XHR9XG5cdFx0Y2xpZW50WyBNQUNISU5BX1BST1AgXSA9IGNsaWVudFsgTUFDSElOQV9QUk9QIF0gfHwge307XG5cdFx0aWYgKCAhY2xpZW50WyBNQUNISU5BX1BST1AgXVsgdGhpcy5uYW1lc3BhY2UgXSApIHtcblx0XHRcdGNsaWVudFsgTUFDSElOQV9QUk9QIF1bIHRoaXMubmFtZXNwYWNlIF0gPSBfLmNsb25lRGVlcCggdXRpbHMuZ2V0RGVmYXVsdENsaWVudE1ldGEoKSApO1xuXHRcdFx0dGhpcy5pbml0Q2xpZW50KCBjbGllbnQgKTtcblx0XHR9XG5cdFx0cmV0dXJuIGNsaWVudFsgTUFDSElOQV9QUk9QIF1bIHRoaXMubmFtZXNwYWNlIF07XG5cdH0sXG5cblx0YnVpbGRFdmVudFBheWxvYWQ6IGZ1bmN0aW9uKCBjbGllbnQsIGRhdGEgKSB7XG5cdFx0aWYgKCBfLmlzUGxhaW5PYmplY3QoIGRhdGEgKSApIHtcblx0XHRcdHJldHVybiBfLmV4dGVuZCggZGF0YSwgeyBjbGllbnQ6IGNsaWVudCwgbmFtZXNwYWNlOiB0aGlzLm5hbWVzcGFjZSB9ICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiB7IGNsaWVudDogY2xpZW50LCBkYXRhOiBkYXRhIHx8IG51bGwsIG5hbWVzcGFjZTogdGhpcy5uYW1lc3BhY2UgfTtcblx0XHR9XG5cdH0sXG5cblx0Z2V0SGFuZGxlckFyZ3M6IGZ1bmN0aW9uKCBhcmdzLCBpc0NhdGNoQWxsICkge1xuXHRcdC8vIGluZGV4IDAgaXMgdGhlIGNsaWVudCwgaW5kZXggMSBpcyBpbnB1dFR5cGVcblx0XHQvLyBpZiB3ZSdyZSBpbiBhIGNhdGNoLWFsbCBoYW5kbGVyLCBpbnB1dCB0eXBlIG5lZWRzIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBhcmdzXG5cdFx0Ly8gaW5wdXRUeXBlIG1pZ2h0IGJlIGFuIG9iamVjdCwgc28gd2UgbmVlZCB0byBqdXN0IGdldCB0aGUgaW5wdXRUeXBlIHN0cmluZyBpZiBzb1xuXHRcdHZhciBfYXJncyA9IGFyZ3Muc2xpY2UoIDAgKTtcblx0XHR2YXIgaW5wdXQgPSBfYXJnc1sgMSBdO1xuXHRcdGlmICggdHlwZW9mIGlucHV0ID09PSBcIm9iamVjdFwiICkge1xuXHRcdFx0X2FyZ3Muc3BsaWNlKCAxLCAxLCBpbnB1dC5pbnB1dFR5cGUgKTtcblx0XHR9XG5cdFx0cmV0dXJuIGlzQ2F0Y2hBbGwgP1xuXHRcdFx0X2FyZ3MgOlxuXHRcdFx0WyBfYXJnc1sgMCBdIF0uY29uY2F0KCBfYXJncy5zbGljZSggMiApICk7XG5cdH0sXG5cblx0Z2V0U3lzdGVtSGFuZGxlckFyZ3M6IGZ1bmN0aW9uKCBhcmdzLCBjbGllbnQgKSB7XG5cdFx0cmV0dXJuIFsgY2xpZW50IF0uY29uY2F0KCBhcmdzICk7XG5cdH0sXG5cblx0aGFuZGxlOiBmdW5jdGlvbiggY2xpZW50LCBpbnB1dCApIHtcblx0XHR2YXIgaW5wdXREZWYgPSBpbnB1dDtcblx0XHRpZiAoIHR5cGVvZiBpbnB1dCA9PT0gXCJ1bmRlZmluZWRcIiApIHtcblx0XHRcdHRocm93IG5ldyBFcnJvciggXCJUaGUgaW5wdXQgYXJndW1lbnQgcGFzc2VkIHRvIHRoZSBGU00ncyBoYW5kbGUgbWV0aG9kIGlzIHVuZGVmaW5lZC4gRGlkIHlvdSBmb3JnZXQgdG8gcGFzcyB0aGUgaW5wdXQgbmFtZT9cIiApO1xuXHRcdH1cblx0XHRpZiAoIHR5cGVvZiBpbnB1dCA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdGlucHV0RGVmID0geyBpbnB1dFR5cGU6IGlucHV0LCBkZWxlZ2F0ZWQ6IGZhbHNlLCB0aWNrZXQ6IHVuZGVmaW5lZCB9O1xuXHRcdH1cblx0XHR2YXIgY2xpZW50TWV0YSA9IHRoaXMuZW5zdXJlQ2xpZW50TWV0YSggY2xpZW50ICk7XG5cdFx0dmFyIGFyZ3MgPSB1dGlscy5nZXRMZWFrbGVzc0FyZ3MoIGFyZ3VtZW50cyApO1xuXHRcdGlmICggdHlwZW9mIGlucHV0ICE9PSBcIm9iamVjdFwiICkge1xuXHRcdFx0YXJncy5zcGxpY2UoIDEsIDEsIGlucHV0RGVmICk7XG5cdFx0fVxuXHRcdGNsaWVudE1ldGEuY3VycmVudEFjdGlvbkFyZ3MgPSBhcmdzLnNsaWNlKCAxICk7XG5cdFx0dmFyIGN1cnJlbnRTdGF0ZSA9IGNsaWVudE1ldGEuc3RhdGU7XG5cdFx0dmFyIHN0YXRlT2JqID0gdGhpcy5zdGF0ZXNbIGN1cnJlbnRTdGF0ZSBdO1xuXHRcdHZhciBoYW5kbGVyTmFtZTtcblx0XHR2YXIgaGFuZGxlcjtcblx0XHR2YXIgaXNDYXRjaEFsbCA9IGZhbHNlO1xuXHRcdHZhciBjaGlsZDtcblx0XHR2YXIgcmVzdWx0O1xuXHRcdHZhciBhY3Rpb247XG5cdFx0aWYgKCAhY2xpZW50TWV0YS5pbkV4aXRIYW5kbGVyICkge1xuXHRcdFx0Y2hpbGQgPSB0aGlzLmNvbmZpZ0ZvclN0YXRlKCBjdXJyZW50U3RhdGUgKTtcblx0XHRcdGlmICggY2hpbGQgJiYgIXRoaXMucGVuZGluZ0RlbGVnYXRpb25zWyBpbnB1dERlZi50aWNrZXQgXSAmJiAhaW5wdXREZWYuYnViYmxpbmcgKSB7XG5cdFx0XHRcdGlucHV0RGVmLnRpY2tldCA9ICggaW5wdXREZWYudGlja2V0IHx8IHV0aWxzLmNyZWF0ZVVVSUQoKSApO1xuXHRcdFx0XHRpbnB1dERlZi5kZWxlZ2F0ZWQgPSB0cnVlO1xuXHRcdFx0XHR0aGlzLnBlbmRpbmdEZWxlZ2F0aW9uc1sgaW5wdXREZWYudGlja2V0IF0gPSB7IGRlbGVnYXRlZFRvOiBjaGlsZC5uYW1lc3BhY2UgfTtcblx0XHRcdFx0Ly8gV0FSTklORyAtIHJldHVybmluZyBhIHZhbHVlIGZyb20gYGhhbmRsZWAgb24gY2hpbGQgRlNNcyBpcyBub3QgcmVhbGx5IHN1cHBvcnRlZC5cblx0XHRcdFx0Ly8gSWYgeW91IG5lZWQgdG8gcmV0dXJuIHZhbHVlcyBmcm9tIGNoaWxkIEZTTSBpbnB1dCBoYW5kbGVycywgdXNlIGV2ZW50cyBpbnN0ZWFkLlxuXHRcdFx0XHRyZXN1bHQgPSBjaGlsZC5oYW5kbGUuYXBwbHkoIGNoaWxkLCBhcmdzICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoIGlucHV0RGVmLnRpY2tldCAmJiB0aGlzLnBlbmRpbmdEZWxlZ2F0aW9uc1sgaW5wdXREZWYudGlja2V0IF0gKSB7XG5cdFx0XHRcdFx0ZGVsZXRlIHRoaXMucGVuZGluZ0RlbGVnYXRpb25zWyBpbnB1dERlZi50aWNrZXQgXTtcblx0XHRcdFx0fVxuXHRcdFx0XHRoYW5kbGVyTmFtZSA9IHN0YXRlT2JqWyBpbnB1dERlZi5pbnB1dFR5cGUgXSA/IGlucHV0RGVmLmlucHV0VHlwZSA6IFwiKlwiO1xuXHRcdFx0XHRpc0NhdGNoQWxsID0gKCBoYW5kbGVyTmFtZSA9PT0gXCIqXCIgKTtcblx0XHRcdFx0aGFuZGxlciA9ICggc3RhdGVPYmpbIGhhbmRsZXJOYW1lIF0gfHwgdGhpc1sgaGFuZGxlck5hbWUgXSApIHx8IHRoaXNbIFwiKlwiIF07XG5cdFx0XHRcdGFjdGlvbiA9IGNsaWVudE1ldGEuc3RhdGUgKyBcIi5cIiArIGhhbmRsZXJOYW1lO1xuXHRcdFx0XHRjbGllbnRNZXRhLmN1cnJlbnRBY3Rpb24gPSBhY3Rpb247XG5cdFx0XHRcdHZhciBldmVudFBheWxvYWQgPSB0aGlzLmJ1aWxkRXZlbnRQYXlsb2FkKFxuXHRcdFx0XHRcdGNsaWVudCxcblx0XHRcdFx0XHR7IGlucHV0VHlwZTogaW5wdXREZWYuaW5wdXRUeXBlLCBkZWxlZ2F0ZWQ6IGlucHV0RGVmLmRlbGVnYXRlZCwgdGlja2V0OiBpbnB1dERlZi50aWNrZXQgfVxuXHRcdFx0XHQpO1xuXHRcdFx0XHRpZiAoICFoYW5kbGVyICkge1xuXHRcdFx0XHRcdHRoaXMuZW1pdCggZXZlbnRzLk5PX0hBTkRMRVIsIF8uZXh0ZW5kKCB7IGFyZ3M6IGFyZ3MgfSwgZXZlbnRQYXlsb2FkICkgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aGlzLmVtaXQoIGV2ZW50cy5IQU5ETElORywgZXZlbnRQYXlsb2FkICk7XG5cdFx0XHRcdFx0aWYgKCB0eXBlb2YgaGFuZGxlciA9PT0gXCJmdW5jdGlvblwiICkge1xuXHRcdFx0XHRcdFx0cmVzdWx0ID0gaGFuZGxlci5hcHBseSggdGhpcywgdGhpcy5nZXRIYW5kbGVyQXJncyggYXJncywgaXNDYXRjaEFsbCApICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHJlc3VsdCA9IGhhbmRsZXI7XG5cdFx0XHRcdFx0XHR0aGlzLnRyYW5zaXRpb24oIGNsaWVudCwgaGFuZGxlciApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR0aGlzLmVtaXQoIGV2ZW50cy5IQU5ETEVELCBldmVudFBheWxvYWQgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjbGllbnRNZXRhLnByaW9yQWN0aW9uID0gY2xpZW50TWV0YS5jdXJyZW50QWN0aW9uO1xuXHRcdFx0XHRjbGllbnRNZXRhLmN1cnJlbnRBY3Rpb24gPSBcIlwiO1xuXHRcdFx0XHRjbGllbnRNZXRhLmN1cnJlbnRBY3Rpb25BcmdzID0gdW5kZWZpbmVkO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gcmVzdWx0O1xuXHR9LFxuXG5cdHRyYW5zaXRpb246IGZ1bmN0aW9uKCBjbGllbnQsIG5ld1N0YXRlICkge1xuXHRcdHZhciBjbGllbnRNZXRhID0gdGhpcy5lbnN1cmVDbGllbnRNZXRhKCBjbGllbnQgKTtcblx0XHR2YXIgY3VyU3RhdGUgPSBjbGllbnRNZXRhLnN0YXRlO1xuXHRcdHZhciBjdXJTdGF0ZU9iaiA9IHRoaXMuc3RhdGVzWyBjdXJTdGF0ZSBdO1xuXHRcdHZhciBuZXdTdGF0ZU9iaiA9IHRoaXMuc3RhdGVzWyBuZXdTdGF0ZSBdO1xuXHRcdHZhciBjaGlsZDtcblx0XHR2YXIgYXJncyA9IHV0aWxzLmdldExlYWtsZXNzQXJncyggYXJndW1lbnRzICkuc2xpY2UoIDIgKTtcblx0XHRpZiAoICFjbGllbnRNZXRhLmluRXhpdEhhbmRsZXIgJiYgbmV3U3RhdGUgIT09IGN1clN0YXRlICkge1xuXHRcdFx0aWYgKCBuZXdTdGF0ZU9iaiApIHtcblx0XHRcdFx0Y2hpbGQgPSB0aGlzLmNvbmZpZ0ZvclN0YXRlKCBuZXdTdGF0ZSApO1xuXHRcdFx0XHRpZiAoIGN1clN0YXRlT2JqICYmIGN1clN0YXRlT2JqLl9vbkV4aXQgKSB7XG5cdFx0XHRcdFx0Y2xpZW50TWV0YS5pbkV4aXRIYW5kbGVyID0gdHJ1ZTtcblx0XHRcdFx0XHRjdXJTdGF0ZU9iai5fb25FeGl0LmNhbGwoIHRoaXMsIGNsaWVudCApO1xuXHRcdFx0XHRcdGNsaWVudE1ldGEuaW5FeGl0SGFuZGxlciA9IGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGNsaWVudE1ldGEudGFyZ2V0UmVwbGF5U3RhdGUgPSBuZXdTdGF0ZTtcblx0XHRcdFx0Y2xpZW50TWV0YS5wcmlvclN0YXRlID0gY3VyU3RhdGU7XG5cdFx0XHRcdGNsaWVudE1ldGEuc3RhdGUgPSBuZXdTdGF0ZTtcblx0XHRcdFx0dmFyIGV2ZW50UGF5bG9hZCA9IHRoaXMuYnVpbGRFdmVudFBheWxvYWQoIGNsaWVudCwge1xuXHRcdFx0XHRcdGZyb21TdGF0ZTogY2xpZW50TWV0YS5wcmlvclN0YXRlLFxuXHRcdFx0XHRcdGFjdGlvbjogY2xpZW50TWV0YS5jdXJyZW50QWN0aW9uLFxuXHRcdFx0XHRcdHRvU3RhdGU6IG5ld1N0YXRlXG5cdFx0XHRcdH0gKTtcblx0XHRcdFx0dGhpcy5lbWl0KCBldmVudHMuVFJBTlNJVElPTiwgZXZlbnRQYXlsb2FkICk7XG5cdFx0XHRcdGlmICggbmV3U3RhdGVPYmouX29uRW50ZXIgKSB7XG5cdFx0XHRcdFx0bmV3U3RhdGVPYmouX29uRW50ZXIuYXBwbHkoIHRoaXMsIHRoaXMuZ2V0U3lzdGVtSGFuZGxlckFyZ3MoIGFyZ3MsIGNsaWVudCApICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5lbWl0KCBldmVudHMuVFJBTlNJVElPTkVELCBldmVudFBheWxvYWQgKTtcblx0XHRcdFx0aWYgKCBjaGlsZCApIHtcblx0XHRcdFx0XHRjaGlsZC5oYW5kbGUoIGNsaWVudCwgXCJfcmVzZXRcIiApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCBjbGllbnRNZXRhLnRhcmdldFJlcGxheVN0YXRlID09PSBuZXdTdGF0ZSApIHtcblx0XHRcdFx0XHR0aGlzLnByb2Nlc3NRdWV1ZSggY2xpZW50LCBldmVudHMuTkVYVF9UUkFOU0lUSU9OICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5lbWl0KCBldmVudHMuSU5WQUxJRF9TVEFURSwgdGhpcy5idWlsZEV2ZW50UGF5bG9hZCggY2xpZW50LCB7XG5cdFx0XHRcdHN0YXRlOiBjbGllbnRNZXRhLnN0YXRlLFxuXHRcdFx0XHRhdHRlbXB0ZWRTdGF0ZTogbmV3U3RhdGVcblx0XHRcdH0gKSApO1xuXHRcdH1cblx0fSxcblxuXHRkZWZlclVudGlsVHJhbnNpdGlvbjogZnVuY3Rpb24oIGNsaWVudCwgc3RhdGVOYW1lICkge1xuXHRcdHZhciBjbGllbnRNZXRhID0gdGhpcy5lbnN1cmVDbGllbnRNZXRhKCBjbGllbnQgKTtcblx0XHR2YXIgc3RhdGVMaXN0ID0gXy5pc0FycmF5KCBzdGF0ZU5hbWUgKSA/IHN0YXRlTmFtZSA6ICggc3RhdGVOYW1lID8gWyBzdGF0ZU5hbWUgXSA6IHVuZGVmaW5lZCApO1xuXHRcdGlmICggY2xpZW50TWV0YS5jdXJyZW50QWN0aW9uQXJncyApIHtcblx0XHRcdHZhciBxdWV1ZWQgPSB7XG5cdFx0XHRcdHR5cGU6IGV2ZW50cy5ORVhUX1RSQU5TSVRJT04sXG5cdFx0XHRcdHVudGlsU3RhdGU6IHN0YXRlTGlzdCxcblx0XHRcdFx0YXJnczogY2xpZW50TWV0YS5jdXJyZW50QWN0aW9uQXJnc1xuXHRcdFx0fTtcblx0XHRcdGNsaWVudE1ldGEuaW5wdXRRdWV1ZS5wdXNoKCBxdWV1ZWQgKTtcblx0XHRcdHZhciBldmVudFBheWxvYWQgPSB0aGlzLmJ1aWxkRXZlbnRQYXlsb2FkKCBjbGllbnQsIHtcblx0XHRcdFx0c3RhdGU6IGNsaWVudE1ldGEuc3RhdGUsXG5cdFx0XHRcdHF1ZXVlZEFyZ3M6IHF1ZXVlZFxuXHRcdFx0fSApO1xuXHRcdFx0dGhpcy5lbWl0KCBldmVudHMuREVGRVJSRUQsIGV2ZW50UGF5bG9hZCApO1xuXHRcdH1cblx0fSxcblxuXHRkZWZlckFuZFRyYW5zaXRpb246IGZ1bmN0aW9uKCBjbGllbnQsIHN0YXRlTmFtZSApIHtcblx0XHR0aGlzLmRlZmVyVW50aWxUcmFuc2l0aW9uKCBjbGllbnQsIHN0YXRlTmFtZSApO1xuXHRcdHRoaXMudHJhbnNpdGlvbiggY2xpZW50LCBzdGF0ZU5hbWUgKTtcblx0fSxcblxuXHRwcm9jZXNzUXVldWU6IGZ1bmN0aW9uKCBjbGllbnQgKSB7XG5cdFx0dmFyIGNsaWVudE1ldGEgPSB0aGlzLmVuc3VyZUNsaWVudE1ldGEoIGNsaWVudCApO1xuXHRcdHZhciBmaWx0ZXJGbiA9IGZ1bmN0aW9uKCBpdGVtICkge1xuXHRcdFx0cmV0dXJuICggKCAhaXRlbS51bnRpbFN0YXRlICkgfHwgKCBfLmluY2x1ZGVzKCBpdGVtLnVudGlsU3RhdGUsIGNsaWVudE1ldGEuc3RhdGUgKSApICk7XG5cdFx0fTtcblx0XHR2YXIgdG9Qcm9jZXNzID0gXy5maWx0ZXIoIGNsaWVudE1ldGEuaW5wdXRRdWV1ZSwgZmlsdGVyRm4gKTtcblx0XHRjbGllbnRNZXRhLmlucHV0UXVldWUgPSBfLmRpZmZlcmVuY2UoIGNsaWVudE1ldGEuaW5wdXRRdWV1ZSwgdG9Qcm9jZXNzICk7XG5cdFx0Xy5lYWNoKCB0b1Byb2Nlc3MsIGZ1bmN0aW9uKCBpdGVtICkge1xuXHRcdFx0dGhpcy5oYW5kbGUuYXBwbHkoIHRoaXMsIFsgY2xpZW50IF0uY29uY2F0KCBpdGVtLmFyZ3MgKSApO1xuXHRcdH0uYmluZCggdGhpcyApICk7XG5cdH0sXG5cblx0Y2xlYXJRdWV1ZTogZnVuY3Rpb24oIGNsaWVudCwgbmFtZSApIHtcblx0XHR2YXIgY2xpZW50TWV0YSA9IHRoaXMuZW5zdXJlQ2xpZW50TWV0YSggY2xpZW50ICk7XG5cdFx0aWYgKCAhbmFtZSApIHtcblx0XHRcdGNsaWVudE1ldGEuaW5wdXRRdWV1ZSA9IFtdO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBmaXJzdCBwYXNzIHdlIHJlbW92ZSB0aGUgdGFyZ2V0IHN0YXRlIGZyb20gYW55IGB1bnRpbFN0YXRlYCBhcnJheVxuXHRcdFx0Xy5lYWNoKCBjbGllbnRNZXRhLmlucHV0UXVldWUsIGZ1bmN0aW9uKCBpdGVtICkge1xuXHRcdFx0XHRpdGVtLnVudGlsU3RhdGUgPSBfLndpdGhvdXQoIGl0ZW0udW50aWxTdGF0ZSwgbmFtZSApO1xuXHRcdFx0fSApO1xuXHRcdFx0Ly8gc2Vjb25kIHBhc3Mgd2UgY2xlYXIgb3V0IGRlZmVycmVkIGV2ZW50cyB3aXRoIGVtcHR5IHVudGlsU3RhdGUgYXJyYXlzXG5cdFx0XHR2YXIgZmlsdGVyID0gZnVuY3Rpb24oIGV2bnQgKSB7XG5cdFx0XHRcdHJldHVybiBldm50LnVudGlsU3RhdGUubGVuZ3RoICE9PSAwO1xuXHRcdFx0fTtcblx0XHRcdGNsaWVudE1ldGEuaW5wdXRRdWV1ZSA9IF8uZmlsdGVyKCBjbGllbnRNZXRhLmlucHV0UXVldWUsIGZpbHRlciApO1xuXHRcdH1cblx0fSxcblxuXHRjb21wb3NpdGVTdGF0ZTogZnVuY3Rpb24oIGNsaWVudCApIHtcblx0XHR2YXIgY2xpZW50TWV0YSA9IHRoaXMuZW5zdXJlQ2xpZW50TWV0YSggY2xpZW50ICk7XG5cdFx0dmFyIHN0YXRlID0gY2xpZW50TWV0YS5zdGF0ZTtcblx0XHR2YXIgY2hpbGQgPSB0aGlzLnN0YXRlc1tzdGF0ZV0uX2NoaWxkICYmIHRoaXMuc3RhdGVzW3N0YXRlXS5fY2hpbGQuaW5zdGFuY2U7XG5cdFx0aWYgKCBjaGlsZCApIHtcblx0XHRcdHN0YXRlICs9IFwiLlwiICsgY2hpbGQuY29tcG9zaXRlU3RhdGUoIGNsaWVudCApO1xuXHRcdH1cblx0XHRyZXR1cm4gc3RhdGU7XG5cdH1cbn0sIGVtaXR0ZXIuZ2V0SW5zdGFuY2UoKSApO1xuXG5CZWhhdmlvcmFsRnNtLmV4dGVuZCA9IHV0aWxzLmV4dGVuZDtcblxubW9kdWxlLmV4cG9ydHMgPSBCZWhhdmlvcmFsRnNtO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9zcmMvQmVoYXZpb3JhbEZzbS5qc1xuLy8gbW9kdWxlIGlkID0gNlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwic291cmNlUm9vdCI6IiJ9