all files / fc-er/ controller.js

45.08% Statements 165/366
31.69% Branches 90/284
52.46% Functions 32/61
42.99% Lines 144/335
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 75933×     869×   869×                                                                                                                                   869×   869×   869× 869× 869× 869× 869× 869×                                         871×                 860×                                       35×                                                                                           860×       860× 860×         14× 14×                                                     11× 11×   11×                 10×       10×                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; Eif ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { Eif (protoProps) defineProperties(Constructor.prototype, protoProps); Eif (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
 
function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }
 
function _classCallCheck(instance, Constructor) { Iif (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
 
function _possibleConstructorReturn(self, call) { Iif (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
 
function _inherits(subClass, superClass) { Iif (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); Eif (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : _defaults(subClass, superClass); }
 
Eif (typeof define !== 'function') {
    var define = require('amdefine')(module);
}
 
define(function (require) {
    'use strict';
 
    var URL = require('./URL');
    var config = require('./config');
    var util = require('./util');
    var assert = require('./assert');
    var EventTarget = require('fc-mini-event/EventTarget');
    var Permission = require('./permission').Permission;
    var router = require('./router');
    var canUseDOM = require('./ExecutionEnvironment').canUseDOM;
 
    var removeChildAction = function removeChildAction(controller, container, targetContext) {
        var info = controller.childActionMapping[container.id];
        if (!info) {
            return;
        }
 
        controller.childActionMapping[container.id] = undefined;
        if (info.hijack) {
            if (container.removeEventListener) {
                container.removeEventListener('click', info.hijack, false);
            } else {
                container.detachEvent('onclick', info.hijack);
            }
        }
 
        if (info.action) {
            targetContext = targetContext || {
                url: null,
                referrer: info.url,
                container: container.id,
                isChildAction: true
            };
            var eventBus = controller.getEventBus();
            eventBus && eventBus.fire('leaveaction', {
                controller: controller,
                action: info.action,
                to: targetContext
            });
        }
 
        if (typeof info.action.leave === 'function') {
            info.action.leave();
        }
    };
 
    var addChildAction = function addChildAction(controller, container, action, hijack, context) {
        removeChildAction(controller, container, context);
 
        if (container.addEventListener) {
            container.addEventListener('click', hijack, false);
        } else {
            container.attachEvent('onclick', hijack);
        }
 
        controller.childActionMapping[container.id] = {
            url: context.url,
            container: container.id,
            action: action,
            hijack: hijack
        };
 
        if (action instanceof EventTarget) {
            // 在Action销毁的时候要取消掉
            action.on('leave', function () {
                removeChildAction(controller, container);
            });
        }
    };
 
    var Controller = function (_EventTarget) {
        _inherits(Controller, _EventTarget);
 
        function Controller() {
            _classCallCheck(this, Controller);
 
            var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Controller).call(this));
 
            _this.childActionMapping = {};
            _this.currentURL = null;
            _this.currentAction = null;
            _this.globalActionLoader = null;
            _this.childActionLoaders = {};
            return _this;
        }
 
        _createClass(Controller, [{
            key: 'registerAction',
            value: function registerAction(actionConfigs) {
                var main = require('./main');
                main.registerAction(actionConfigs);
            }
        }, {
            key: 'getDefaultTitle',
            value: function getDefaultTitle() {
                return this.defaultTitle;
            }
        }, {
            key: 'setDefaultTitle',
            value: function setDefaultTitle(title) {
                this.defaultTitle = title;
            }
        }, {
            key: 'setErContext',
            value: function setErContext(erContext) {
                this.erContext = erContext;
            }
        }, {
            key: 'getErContext',
            value: function getErContext() {
                return this.erContext;
            }
        }, {
            key: 'getRouter',
            value: function getRouter() {
                return this.erContext && this.erContext.getRouter();
            }
        }, {
            key: 'setRouter',
            value: function setRouter(router) {
                this.erContext && this.erContext.setRouter(router);
            }
        }, {
            key: 'getLocator',
            value: function getLocator() {
                return this.erContext && this.erContext.getLocator();
            }
        }, {
            key: 'setLocator',
            value: function setLocator(locator) {
                this.erContext && this.erContext.setLocator(locator);
            }
        }, {
            key: 'getEventBus',
            value: function getEventBus() {
                return this.erContext && this.erContext.getEventBus();
            }
        }, {
            key: 'setEventBus',
            value: function setEventBus(eventBus) {
                this.erContext && this.erContext.setEventBus(eventBus);
            }
        }, {
            key: 'getPermissionProvider',
            value: function getPermissionProvider() {
                return this.erContext && this.erContext.getPermissionProvider();
            }
        }, {
            key: 'setPermissionProvider',
            value: function setPermissionProvider(permissionProvider) {
                this.erContext && this.erContext.setPermissionProvider(permissionProvider);
            }
        }, {
            key: 'getMainContainer',
            value: function getMainContainer() {
                return this.mainContainer || config.mainElement;
            }
        }, {
            key: 'setMainContainer',
            value: function setMainContainer(mainContainer) {
                this.mainContainer = mainContainer;
            }
        }, {
            key: 'getNoAuthorityLocation',
            value: function getNoAuthorityLocation() {
                return this.noAuthorityLocation || config.noAuthorityLocation;
            }
        }, {
            key: 'setNoAuthorityLocation',
            value: function setNoAuthorityLocation(noAuthorityLocation) {
                this.noAuthorityLocation = noAuthorityLocation;
            }
        }, {
            key: 'getNotFoundLocation',
            value: function getNotFoundLocation() {
                return this.notFoundLocation || config.notFoundLocation;
            }
        }, {
            key: 'setNotFoundLocation',
            value: function setNotFoundLocation(notFoundLocation) {
                this.notFoundLocation = notFoundLocation;
            }
        }, {
            key: 'start',
            value: function start() {
                Iif (canUseDOM && !this.getDefaultTitle()) {
                    this.setDefaultTitle(config.systemName || global.document.title);
                }
 
                var router = this.getRouter();
                router && router.setBackup(util.bind(this.renderAction, this));
            }
        }, {
            key: 'findActionConfig',
            value: function findActionConfig(actionContext) {
                var main = require('./main');
                return main.findActionConfig(actionContext);
            }
        }, {
            key: 'resolveActionConfig',
            value: function resolveActionConfig(actionConfig, actionContext) {
                return actionConfig;
            }
        }, {
            key: 'checkAuthority',
            value: function checkAuthority(actionConfig, actionContext) {
                var authority = actionConfig.authority;
                if (!authority) {
                    return true;
                }
 
                var permissionProvider = this.getPermissionProvider();
                Iif (!permissionProvider) {
                    return true;
                }
 
                Iif (typeof authority === 'function') {
                    return authority(actionContext, actionConfig, permissionProvider);
                }
 
                Eif (typeof authority === 'string') {
                    authority = authority.split('|');
                }
 
                for (var i = 0; i < authority.length; i++) {
                    Iif (permissionProvider.isAllow(util.trim(authority[i]))) {
                        return true;
                    }
                }
 
                return false;
            }
        }, {
            key: 'findEligibleActionConfig',
            value: function findEligibleActionConfig(actionContext) {
                var actionConfig = this.findActionConfig(actionContext);
                var eventBus = this.getEventBus();
 
                if (actionConfig && actionConfig.movedTo) {
                    eventBus && eventBus.fire('actionmoved', {
                        controller: this,
                        url: actionContext.url,
                        config: actionConfig,
                        movedTo: actionConfig.movedTo
                    });
                    actionContext.originalURL = actionContext.url;
                    actionContext.url = URL.parse(actionConfig.movedTo);
 
                    return this.findEligibleActionConfig(actionContext);
                }
 
                Iif (actionConfig && actionConfig.childActionOnly && !actionContext.isChildAction) {
                    actionConfig = null;
                }
 
                if (!actionConfig) {
                    eventBus && eventBus.fire('actionnotfound', util.mix({
                        controller: this,
                        failType: 'NotFound',
                        reason: 'Not found'
                    }, actionContext));
 
                    actionContext.originalURL = actionContext.url;
                    actionContext.url = URL.parse(this.getNotFoundLocation());
 
                    Iif (!this.findActionConfig(actionContext)) {
                        return null;
                    }
 
                    return this.findEligibleActionConfig(actionContext);
                }
 
                var hasAuthority = this.checkAuthority(actionConfig, actionContext);
                if (!hasAuthority) {
                    eventBus && eventBus.fire('permissiondenied', util.mix({
                        controller: this,
                        failType: 'PermissionDenied',
                        reason: 'Permission denied',
                        config: actionConfig
                    }, actionContext));
 
                    var location = actionConfig.noAuthorityLocation || this.getNoAuthorityLocation();
                    actionContext.originalURL = actionContext.url;
                    actionContext.url = URL.parse(location);
                    return this.findEligibleActionConfig(actionContext);
                }
 
                return actionConfig;
            }
        }, {
            key: 'loadAction',
            value: function loadAction(actionContext) {
                var _this2 = this;
 
                var actionConfig = this.findEligibleActionConfig(actionContext);
                actionConfig = this.resolveActionConfig(actionConfig, actionContext);
                var eventBus = this.getEventBus();
 
                Iif (!actionConfig) {
                    var failed = new Promise(function (resolve, reject) {
                        reject('no action configured for url ' + actionContext.url.getPath());
                    });
 
                    return failed;
                }
 
                Iif (actionConfig.title) {
                    actionContext.title = actionConfig.title;
                    actionContext.args.title = actionConfig.title;
                }
 
                Iif (actionConfig.documentTitle) {
                    actionContext.documentTitle = actionConfig.documentTitle;
                    actionContext.args.documentTitle = actionConfig.documentTitle;
                }
 
                Iif (actionConfig.args) {
                    for (var name in actionConfig.args) {
                        if (actionConfig.args.hasOwnProperty(name)) {
                            if (!actionContext.args.hasOwnProperty(name)) {
                                actionContext.args[name] = actionConfig.args[name];
                            }
                            if (!actionContext.hasOwnProperty(name)) {
                                actionContext[name] = actionConfig.args[name];
                            }
                        }
                    }
                }
 
                var loading = {};
                var loader = new Promise(function (resolve, reject) {
                    loading.resolve = resolve;
                    loading.reject = reject;
                });
 
                var aborted = false;
                loader.abort = function () {
                    if (!aborted) {
                        aborted = true;
                        eventBus && eventBus.fire('actionabort', util.mix({
                            controller: _this2
                        }, actionContext));
                    }
                };
 
                Eif (!actionContext.isChildAction) {
                    this.currentURL = actionContext.url;
                }
 
                var callback = function callback(SpecificAction) {
                    Iif (aborted) {
                        return;
                    }
 
                    Iif (!SpecificAction) {
                        var reason = 'No action implement for ' + actionConfig.type;
                        var error = util.mix({
                            controller: _this2,
                            failType: 'NoModule',
                            config: actionConfig,
                            reason: reason
                        }, actionContext);
 
                        eventBus && eventBus.fire('actionfail', error);
                        eventBus && eventBus.notifyError(error);
                        loading.reject(reason);
                        return;
                    }
 
                    eventBus && eventBus.fire('actionloaded', {
                        controller: _this2,
                        url: actionContext.url,
                        config: actionConfig,
                        action: SpecificAction
                    });
 
                    Eif (typeof SpecificAction === 'function') {
                        loading.resolve({
                            action: new SpecificAction(),
                            actionContext: actionContext
                        });
                    } else if (typeof SpecificAction.createRuntimeAction === 'function') {
                        var resolveActionInstance = function resolveActionInstance(action) {
                            if (!action) {
                                var _reason = 'Action factory returns non-action';
                                var _error = util.mix({
                                    controller: _this2,
                                    failType: 'InvalidFactory',
                                    config: actionConfig,
                                    reason: _reason,
                                    action: action
                                }, actionContext);
                                eventBus && eventBus.fire('actionfail', _error);
                                eventBus && eventBus.notifyError(_error);
 
                                loading.reject(_reason);
                            } else {
                                loading.resolve({ action: action, actionContext: actionContext });
                            }
                        };
                        var actionFactoryProduct = SpecificAction.createRuntimeAction(actionContext);
                        Promise.resolve(actionFactoryProduct).then(resolveActionInstance);
                    } else {
                        loading.resolve({
                            action: SpecificAction,
                            actionContext: actionContext
                        });
                    }
                };
 
                Eif (typeof actionConfig.type === 'string') {
                    Controller.getRequire()([actionConfig.type], callback);
                } else {
                    callback(actionConfig.type);
                }
 
                return loader;
            }
        }, {
            key: 'enterAction',
            value: function enterAction(action, actionContext) {
                var _this3 = this;
 
                var eventBus = this.getEventBus();
 
                Eif (!actionContext.isChildAction) {
                    Iif (actionContext.url !== this.currentURL) {
                        return;
                    }
 
                    Iif (this.currentAction) {
                        eventBus && eventBus.fire('leaveaction', {
                            controller: this,
                            action: this.currentAction,
                            to: util.mix({}, actionContext)
                        });
 
                        if (typeof this.currentAction.leave === 'function') {
                            this.currentAction.leave();
                        }
                    }
                    this.currentAction = action;
 
                    Iif (global.document) {
                        global.document.title = actionContext.title || actionContext.documentTitle || this.getDefaultTitle();
                    }
                }
 
                eventBus && eventBus.fire('enteraction', util.mix({
                    controller: this,
                    action: action
                }, actionContext));
 
                var notifyEnterComplete = function notifyEnterComplete() {
                    eventBus && eventBus.fire('enteractioncomplete', util.mix({
                        controller: _this3,
                        action: action
                    }, actionContext));
                };
 
                var notifyEnterFail = function notifyEnterFail(reason) {
                    var message = '';
                    if (!reason) {
                        message = 'Invoke action.enter() causes error';
                    } else if (reason.message) {
                        message = reason.message;
                        if (reason.stack) {
                            message += '\n' + reason.stack;
                        }
                    } else if (JSON && typeof JSON.stringify === 'function') {
                        try {
                            message = JSON.stringify(reason);
                        } catch (parseJSONError) {
                            message = reason;
                        }
                    } else {
                        message = reason;
                    }
 
                    var error = util.mix({
                        failType: 'EnterFail',
                        reason: message
                    }, actionContext);
 
                    eventBus && eventBus.fire('enteractionfail', error);
                    eventBus && eventBus.notifyError(error);
                };
 
                var entering = action.enter(actionContext);
                entering.then(notifyEnterComplete, notifyEnterFail);
 
                return entering;
            }
        }, {
            key: 'forward',
            value: function forward(url, container, options, isChildAction) {
                var actionContext = {
                    url: url,
                    container: container,
                    isChildAction: !!isChildAction
                };
                var eventBus = this.getEventBus();
 
                Iif (isChildAction) {
                    var referrerInfo = this.childActionMapping[container];
                    actionContext.referrer = referrerInfo ? referrerInfo.url : null;
                } else {
                    actionContext.referrer = this.currentURL;
                }
 
                util.mix(actionContext, options);
 
                actionContext.args = util.mix({}, actionContext);
                util.mix(actionContext.args, url.getQuery());
 
                Iif (!isChildAction && this.rehydratedCurrentURL && this.rehydratedCurrentURL.getPath() === url.getPath()) {
                    util.mix(actionContext.args, { DATA_REHYDRATED: true }, this.rehydratedModel);
                    this.rehydratedCurrentURL = null;
                    this.rehydratedModel = null;
                }
                actionContext.erContext = this.getErContext();
 
                eventBus && eventBus.fire('forwardaction', util.mix({ controller: this }, actionContext));
                var loader = this.loadAction(actionContext);
                assert.has(loader, 'loadAction should always return a Promise');
 
                return loader;
            }
        }, {
            key: 'renderAction',
            value: function renderAction(url) {
                var _this4 = this;
 
                if (typeof url === 'string') {
                    url = URL.parse(url);
                }
                Iif (this.globalActionLoader && typeof this.globalActionLoader.abort === 'function') {
                    this.globalActionLoader.abort();
                }
 
                Iif (this.currentAction && typeof this.currentAction.filterRedirect === 'function' && this.currentAction.filterRedirect(url) === false) {
                    return Promise.reject('Redirect aborted by previous action');
                }
 
                this.globalActionLoader = this.forward(url, this.getMainContainer(), null, false);
                var eventBus = this.getEventBus();
 
                return this.globalActionLoader.then(function (args) {
                    return _this4.enterAction.call(_this4, args.action, args.actionContext);
                }).then(null, function (error) {
                    eventBus && eventBus.notifyError(error);
                    throw error;
                });
            }
        }, {
            key: 'enterChildAction',
            value: function enterChildAction(action, actionContext) {
                this.childActionLoaders[actionContext.container] = null;
 
                var container = void 0;
                if (global.document && global.document.getElementById) {
                    container = global.document.getElementById(actionContext.container);
                }
                if (!container) {
                    return;
                }
 
                var locator = this.getLocator();
                var currentController = this;
 
                var redirect = function redirect(url, options, extra) {
                    options = options || {};
                    url = locator.resolveURL(url, options);
 
                    if (options.global) {
                        var globalRedirectPerformed = locator.redirect(url, options);
                        if (globalRedirectPerformed && container) {
                            removeChildAction(currentController, container);
                        }
                        return globalRedirectPerformed;
                    }
 
                    var childActionInfo = currentController.childActionMapping[actionContext.container];
                    var changed = url.toString() !== childActionInfo.url.toString();
                    var shouldPerformRedirect = changed || options.force;
                    if (shouldPerformRedirect) {
                        if (options.silent) {
                            childActionInfo.url = url;
                        } else {
                            currentController.renderChildAction(url, childActionInfo.container, extra);
                        }
                    }
 
                    return shouldPerformRedirect;
                };
 
                var isChildActionRedirected = function isChildActionRedirected(e) {
                    // 除低版本IE外,其它浏览器是可以在事件对象上加自定义属性的,IE每次都生成新的事件对象所以保留不了这些属性,
                    // 在这里优先用自定义属性控制,避免对DOM树无意义的遍历,只有在没有属性的时候,才向后兼容至DOM树的遍历
                    if (e.isChildActionRedirected) {
                        return true;
                    }
 
                    var innermostContainer = e.target || e.srcElement;
                    while (innermostContainer) {
                        // 是Action容器的元素肯定符合以下条件:
                        //
                        // - 有个`id`,因为没有`id`不能渲染子Action
                        // - 这个`id`在`childActionMapping`里是有对应的值的
                        if (innermostContainer.id && currentController.childActionMapping[innermostContainer.id]) {
                            break;
                        }
 
                        innermostContainer = innermostContainer.parentNode;
                    }
                    // 如果最接近被点击的链接的Action容器是不是当前的这个容器,就说明在当前容器和链接之间还有一层以上的子Action,
                    // 那么这个子Action肯定会处理掉这个链接的跳转,不需要这里处理了
                    if (innermostContainer.id !== actionContext.container) {
                        e.isChildActionRedirected = true;
                        return true;
                    }
 
                    return false;
                };
 
                // 需要把`container`上的链接点击全部拦截下来,如果是hash跳转,则转到controller上来
                var hijack = function hijack(e) {
                    // 下面两行是以主流浏览器为主,兼容IE的事件属性操作
                    e = e || global.window && global.window.event;
                    var target = e.target || e.srcElement;
 
                    // 担心有人在`<span>`之类的上面放`href`属性,还是判断一下标签
                    if (target.nodeName.toLowerCase() !== 'a') {
                        return;
                    }
 
                    // `<a>`元素也可能没有`href`属性
                    var href = target.getAttribute('href', 2) || '';
                    // 是hash跳转的链接就取消掉默认的跳转行为
                    if (href.charAt(0) !== '#') {
                        return;
                    }
                    // 如果有下面的子Action处理了跳转,那这里就啥也不干了
                    if (isChildActionRedirected(e)) {
                        return;
                    }
 
                    if (e.preventDefault) {
                        e.preventDefault();
                    } else {
                        e.returnValue = false;
                    }
 
                    // 转到`renderChildAction`上
                    var url = href.substring(1);
 
                    // 直接使用专供子Action上的`redirect`方法,
                    // 会自动处理`hijack`的解绑定、URL比对、进入子Action等事,
                    // 为免Action重写`redirect`方法,这里用闭包内的这个
                    var redirectAttributes = (target.getAttribute('data-redirect') || '').split(/[,\s]/);
                    var redirectOptions = {};
                    for (var i = 0; i < redirectAttributes.length; i++) {
                        var redirectAttributeName = util.trim(redirectAttributes[i]);
                        redirectOptions[redirectAttributeName] = true;
                    }
                    redirect(url, redirectOptions);
                };
 
                action.redirect = redirect;
 
                action.reload = function (extra) {
                    this.redirect(actionContext.url, { force: true }, extra);
                };
 
                action.back = function (defaultURL, extra) {
                    var referrer = this.context && this.context.referrer;
                    var url = referrer || defaultURL;
                    this.redirect(url, null, extra);
                };
                addChildAction(this, container, action, hijack, actionContext);
 
                return this.enterAction(action, actionContext);
            }
        }, {
            key: 'renderChildAction',
            value: function renderChildAction(url, container, options) {
                var _this5 = this;
 
                assert.has(container);
 
                if (typeof url === 'string') {
                    url = URL.parse(url);
                }
 
                var previousLoader = this.childActionLoaders[container];
                if (previousLoader && typeof previousLoader.abort === 'function') {
                    previousLoader.abort();
                }
 
                var actionInfo = this.childActionMapping[container];
                var previousAction = actionInfo && actionInfo.action;
                if (previousAction && typeof previousAction.filterRedirect === 'function' && previousAction.filterRedirect(url) === false) {
                    return Promise.reject('Redirect aborted by previous action');
                }
 
                var loader = this.forward(url, container, options, true);
                var events = this.getEventBus();
                var loadingChildAction = loader.then(function (args) {
                    return _this5.enterChildAction.call(_this5, args.action, args.actionContext);
                }).then(null, util.bind(events.notifyError, events));
                // `then`方法会返回一个新的`Promise`,但原来的`loader`上有个`abort`方法,要把这个方法留下来
                loadingChildAction.abort = loader.abort;
                this.childActionLoaders[container] = loadingChildAction;
                return loadingChildAction;
            }
        }, {
            key: 'rehydrate',
            value: function rehydrate(rehydratedState) {
                if (rehydratedState && rehydratedState.currentURL) {
                    this.rehydratedCurrentURL = URL.parse(rehydratedState.currentURL);
                    this.rehydratedModel = util.mix({}, rehydratedState.model, { url: this.rehydratedCurrentURL });
                }
            }
        }], [{
            key: 'getRequire',
            value: function getRequire() {
                return Controller.require || require;
            }
        }, {
            key: 'setRequire',
            value: function setRequire(require) {
                Controller.require = require;
            }
        }]);
 
        return Controller;
    }(EventTarget);
 
    var instance = new Controller();
    instance.Controller = Controller;
 
    return instance;
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9jb250cm9sbGVyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQSxJQUFJLE9BQU8sTUFBUCxLQUFrQixVQUFsQixFQUE4QjtBQUFDLFFBQUksU0FBUyxRQUFRLFVBQVIsRUFBb0IsTUFBcEIsQ0FBVCxDQUFMO0NBQWxDOztBQUVBLE9BQU8sVUFBVSxPQUFWLEVBQW1CO0FBQ3RCLGlCQURzQjs7QUFHdEIsUUFBTSxNQUFNLFFBQVEsT0FBUixDQUFOLENBSGdCO0FBSXRCLFFBQU0sU0FBUyxRQUFRLFVBQVIsQ0FBVCxDQUpnQjtBQUt0QixRQUFNLE9BQU8sUUFBUSxRQUFSLENBQVAsQ0FMZ0I7QUFNdEIsUUFBTSxTQUFTLFFBQVEsVUFBUixDQUFULENBTmdCO0FBT3RCLFFBQU0sY0FBYyxRQUFRLDJCQUFSLENBQWQsQ0FQZ0I7QUFRdEIsUUFBTSxhQUFhLFFBQVEsY0FBUixFQUF3QixVQUF4QixDQVJHO0FBU3RCLFFBQU0sU0FBUyxRQUFRLFVBQVIsQ0FBVCxDQVRnQjtBQVV0QixRQUFNLFlBQVksUUFBUSx3QkFBUixFQUFrQyxTQUFsQyxDQVZJOztBQVl0QixRQUFNLG9CQUFvQixTQUFwQixpQkFBb0IsQ0FBQyxVQUFELEVBQWEsU0FBYixFQUF3QixhQUF4QixFQUEwQztBQUNoRSxZQUFNLE9BQU8sV0FBVyxrQkFBWCxDQUE4QixVQUFVLEVBQVYsQ0FBckMsQ0FEMEQ7QUFFaEUsWUFBSSxDQUFDLElBQUQsRUFBTztBQUNQLG1CQURPO1NBQVg7O0FBSUEsbUJBQVcsa0JBQVgsQ0FBOEIsVUFBVSxFQUFWLENBQTlCLEdBQThDLFNBQTlDLENBTmdFO0FBT2hFLFlBQUksS0FBSyxNQUFMLEVBQWE7QUFDYixnQkFBSSxVQUFVLG1CQUFWLEVBQStCO0FBQy9CLDBCQUFVLG1CQUFWLENBQThCLE9BQTlCLEVBQXVDLEtBQUssTUFBTCxFQUFhLEtBQXBELEVBRCtCO2FBQW5DLE1BR0s7QUFDRCwwQkFBVSxXQUFWLENBQXNCLFNBQXRCLEVBQWlDLEtBQUssTUFBTCxDQUFqQyxDQURDO2FBSEw7U0FESjs7QUFTQSxZQUFJLEtBQUssTUFBTCxFQUFhO0FBQ2IsNEJBQWdCLGlCQUFpQjtBQUM3QixxQkFBSyxJQUFMO0FBQ0EsMEJBQVUsS0FBSyxHQUFMO0FBQ1YsMkJBQVcsVUFBVSxFQUFWO0FBQ1gsK0JBQWUsSUFBZjthQUpZLENBREg7QUFPYixnQkFBTSxXQUFXLFdBQVcsV0FBWCxFQUFYLENBUE87QUFRYix3QkFBWSxTQUFTLElBQVQsQ0FBYyxhQUFkLEVBQTZCO0FBQ3JDLHNDQURxQztBQUVyQyx3QkFBUSxLQUFLLE1BQUw7QUFDUixvQkFBSSxhQUFKO2FBSFEsQ0FBWixDQVJhO1NBQWpCOztBQWVBLFlBQUksT0FBTyxLQUFLLE1BQUwsQ0FBWSxLQUFaLEtBQXNCLFVBQTdCLEVBQXlDO0FBQ3pDLGlCQUFLLE1BQUwsQ0FBWSxLQUFaLEdBRHlDO1NBQTdDO0tBL0JzQixDQVpKOztBQWdEdEIsUUFBTSxpQkFBaUIsU0FBakIsY0FBaUIsQ0FBQyxVQUFELEVBQWEsU0FBYixFQUF3QixNQUF4QixFQUFnQyxNQUFoQyxFQUF3QyxPQUF4QyxFQUFvRDtBQUN2RSwwQkFBa0IsVUFBbEIsRUFBOEIsU0FBOUIsRUFBeUMsT0FBekMsRUFEdUU7O0FBR3ZFLFlBQUksVUFBVSxnQkFBVixFQUE0QjtBQUM1QixzQkFBVSxnQkFBVixDQUEyQixPQUEzQixFQUFvQyxNQUFwQyxFQUE0QyxLQUE1QyxFQUQ0QjtTQUFoQyxNQUdLO0FBQ0Qsc0JBQVUsV0FBVixDQUFzQixTQUF0QixFQUFpQyxNQUFqQyxFQURDO1NBSEw7O0FBT0EsbUJBQVcsa0JBQVgsQ0FBOEIsVUFBVSxFQUFWLENBQTlCLEdBQThDO0FBQzFDLGlCQUFLLFFBQVEsR0FBUjtBQUNMLHVCQUFXLFVBQVUsRUFBVjtBQUNYLG9CQUFRLE1BQVI7QUFDQSxvQkFBUSxNQUFSO1NBSkosQ0FWdUU7O0FBaUJ2RSxZQUFJLGtCQUFrQixXQUFsQixFQUErQjs7QUFFL0IsbUJBQU8sRUFBUCxDQUFVLE9BQVYsRUFBbUIsWUFBTTtBQUNyQixrQ0FBa0IsVUFBbEIsRUFBOEIsU0FBOUIsRUFEcUI7YUFBTixDQUFuQixDQUYrQjtTQUFuQztLQWpCbUIsQ0FoREQ7O1FBeUVoQjs7O0FBQ0YsOEJBQWM7Ozs7O0FBRVYsa0JBQUssa0JBQUwsR0FBMEIsRUFBMUIsQ0FGVTtBQUdWLGtCQUFLLFVBQUwsR0FBa0IsSUFBbEIsQ0FIVTtBQUlWLGtCQUFLLGFBQUwsR0FBcUIsSUFBckIsQ0FKVTtBQUtWLGtCQUFLLGtCQUFMLEdBQTBCLElBQTFCLENBTFU7QUFNVixrQkFBSyxrQkFBTCxHQUEwQixFQUExQixDQU5VOztTQUFkOzs7OzJDQVNnQixlQUFlO0FBQzNCLG9CQUFNLE9BQU8sUUFBUSxRQUFSLENBQVAsQ0FEcUI7QUFFM0IscUJBQUssY0FBTCxDQUFvQixhQUFwQixFQUYyQjs7Ozs4Q0FLYjtBQUNkLHVCQUFPLEtBQUssWUFBTCxDQURPOzs7OzRDQUlGLE9BQU87QUFDbkIscUJBQUssWUFBTCxHQUFvQixLQUFwQixDQURtQjs7Ozt5Q0FJVixXQUFXO0FBQ3BCLHFCQUFLLFNBQUwsR0FBaUIsU0FBakIsQ0FEb0I7Ozs7MkNBSVQ7QUFDWCx1QkFBTyxLQUFLLFNBQUwsQ0FESTs7Ozt3Q0FJSDtBQUNSLHVCQUFPLEtBQUssU0FBTCxJQUFrQixLQUFLLFNBQUwsQ0FBZSxTQUFmLEVBQWxCLENBREM7Ozs7c0NBSUYsUUFBUTtBQUNkLHFCQUFLLFNBQUwsSUFBa0IsS0FBSyxTQUFMLENBQWUsU0FBZixDQUF5QixNQUF6QixDQUFsQixDQURjOzs7O3lDQUlMO0FBQ1QsdUJBQU8sS0FBSyxTQUFMLElBQWtCLEtBQUssU0FBTCxDQUFlLFVBQWYsRUFBbEIsQ0FERTs7Ozt1Q0FJRixTQUFTO0FBQ2hCLHFCQUFLLFNBQUwsSUFBa0IsS0FBSyxTQUFMLENBQWUsVUFBZixDQUEwQixPQUExQixDQUFsQixDQURnQjs7OzswQ0FJTjtBQUNWLHVCQUFPLEtBQUssU0FBTCxJQUFrQixLQUFLLFNBQUwsQ0FBZSxXQUFmLEVBQWxCLENBREc7Ozs7d0NBSUYsVUFBVTtBQUNsQixxQkFBSyxTQUFMLElBQWtCLEtBQUssU0FBTCxDQUFlLFdBQWYsQ0FBMkIsUUFBM0IsQ0FBbEIsQ0FEa0I7Ozs7b0RBSUU7QUFDcEIsdUJBQU8sS0FBSyxTQUFMLElBQWtCLEtBQUssU0FBTCxDQUFlLHFCQUFmLEVBQWxCLENBRGE7Ozs7a0RBSUYsb0JBQW9CO0FBQ3RDLHFCQUFLLFNBQUwsSUFBa0IsS0FBSyxTQUFMLENBQWUscUJBQWYsQ0FBcUMsa0JBQXJDLENBQWxCLENBRHNDOzs7OytDQUl2QjtBQUNmLHVCQUFPLEtBQUssYUFBTCxJQUFzQixPQUFPLFdBQVAsQ0FEZDs7Ozs2Q0FJRixlQUFlO0FBQzVCLHFCQUFLLGFBQUwsR0FBcUIsYUFBckIsQ0FENEI7Ozs7cURBSVA7QUFDckIsdUJBQU8sS0FBSyxtQkFBTCxJQUE0QixPQUFPLG1CQUFQLENBRGQ7Ozs7bURBSUYscUJBQXFCO0FBQ3hDLHFCQUFLLG1CQUFMLEdBQTJCLG1CQUEzQixDQUR3Qzs7OztrREFJdEI7QUFDbEIsdUJBQU8sS0FBSyxnQkFBTCxJQUF5QixPQUFPLGdCQUFQLENBRGQ7Ozs7Z0RBSUYsa0JBQWtCO0FBQ2xDLHFCQUFLLGdCQUFMLEdBQXdCLGdCQUF4QixDQURrQzs7OztvQ0FJOUI7QUFDSixvQkFBSSxhQUFhLENBQUMsS0FBSyxlQUFMLEVBQUQsRUFBeUI7QUFDdEMseUJBQUssZUFBTCxDQUFxQixPQUFPLFVBQVAsSUFBcUIsT0FBTyxRQUFQLENBQWdCLEtBQWhCLENBQTFDLENBRHNDO2lCQUExQzs7QUFJQSxvQkFBTSxTQUFTLEtBQUssU0FBTCxFQUFULENBTEY7QUFNSiwwQkFBVSxPQUFPLFNBQVAsQ0FBaUIsS0FBSyxJQUFMLENBQVUsS0FBSyxZQUFMLEVBQW1CLElBQTdCLENBQWpCLENBQVYsQ0FOSTs7Ozs2Q0FTVSxlQUFlO0FBQzdCLG9CQUFNLE9BQU8sUUFBUSxRQUFSLENBQVAsQ0FEdUI7QUFFN0IsdUJBQU8sS0FBSyxnQkFBTCxDQUFzQixhQUF0QixDQUFQLENBRjZCOzs7O2dEQUtiLGNBQWMsZUFBZTtBQUM3Qyx1QkFBTyxZQUFQLENBRDZDOzs7OzJDQUlsQyxjQUFjLGVBQWU7QUFDeEMsb0JBQUksWUFBWSxhQUFhLFNBQWIsQ0FEd0I7QUFFeEMsb0JBQUksQ0FBQyxTQUFELEVBQVk7QUFDWiwyQkFBTyxJQUFQLENBRFk7aUJBQWhCOztBQUlBLG9CQUFNLHFCQUFxQixLQUFLLHFCQUFMLEVBQXJCLENBTmtDO0FBT3hDLG9CQUFJLENBQUMsa0JBQUQsRUFBcUI7QUFDckIsMkJBQU8sSUFBUCxDQURxQjtpQkFBekI7O0FBSUEsb0JBQUksT0FBTyxTQUFQLEtBQXFCLFVBQXJCLEVBQWlDO0FBQ2pDLDJCQUFPLFVBQVUsYUFBVixFQUF5QixZQUF6QixFQUF1QyxrQkFBdkMsQ0FBUCxDQURpQztpQkFBckM7O0FBSUEsb0JBQUksT0FBTyxTQUFQLEtBQXFCLFFBQXJCLEVBQStCO0FBQy9CLGdDQUFZLFVBQVUsS0FBVixDQUFnQixHQUFoQixDQUFaLENBRCtCO2lCQUFuQzs7QUFJQSxxQkFBSyxJQUFJLElBQUksQ0FBSixFQUFPLElBQUksVUFBVSxNQUFWLEVBQWtCLEdBQXRDLEVBQTJDO0FBQ3ZDLHdCQUFJLG1CQUFtQixPQUFuQixDQUEyQixLQUFLLElBQUwsQ0FBVSxVQUFVLENBQVYsQ0FBVixDQUEzQixDQUFKLEVBQXlEO0FBQ3JELCtCQUFPLElBQVAsQ0FEcUQ7cUJBQXpEO2lCQURKOztBQU1BLHVCQUFPLEtBQVAsQ0F6QndDOzs7O3FEQTRCbkIsZUFBZTtBQUNwQyxvQkFBSSxlQUFlLEtBQUssZ0JBQUwsQ0FBc0IsYUFBdEIsQ0FBZixDQURnQztBQUVwQyxvQkFBTSxXQUFXLEtBQUssV0FBTCxFQUFYLENBRjhCOztBQUlwQyxvQkFBSSxnQkFBZ0IsYUFBYSxPQUFiLEVBQXNCO0FBQ3RDLGdDQUFZLFNBQVMsSUFBVCxDQUFjLGFBQWQsRUFBNkI7QUFDckMsb0NBQVksSUFBWjtBQUNBLDZCQUFLLGNBQWMsR0FBZDtBQUNMLGdDQUFRLFlBQVI7QUFDQSxpQ0FBUyxhQUFhLE9BQWI7cUJBSkQsQ0FBWixDQURzQztBQU90QyxrQ0FBYyxXQUFkLEdBQTRCLGNBQWMsR0FBZCxDQVBVO0FBUXRDLGtDQUFjLEdBQWQsR0FBb0IsSUFBSSxLQUFKLENBQVUsYUFBYSxPQUFiLENBQTlCLENBUnNDOztBQVV0QywyQkFBTyxLQUFLLHdCQUFMLENBQThCLGFBQTlCLENBQVAsQ0FWc0M7aUJBQTFDOztBQWFBLG9CQUFJLGdCQUFpQixhQUFhLGVBQWIsSUFBZ0MsQ0FBQyxjQUFjLGFBQWQsRUFBOEI7QUFDaEYsbUNBQWUsSUFBZixDQURnRjtpQkFBcEY7O0FBSUEsb0JBQUksQ0FBQyxZQUFELEVBQWU7QUFDZixnQ0FBWSxTQUFTLElBQVQsQ0FBYyxnQkFBZCxFQUFnQyxLQUFLLEdBQUwsQ0FBUztBQUNqRCxvQ0FBWSxJQUFaO0FBQ0Esa0NBQVUsVUFBVjtBQUNBLGdDQUFRLFdBQVI7cUJBSHdDLEVBSXpDLGFBSnlDLENBQWhDLENBQVosQ0FEZTs7QUFPZixrQ0FBYyxXQUFkLEdBQTRCLGNBQWMsR0FBZCxDQVBiO0FBUWYsa0NBQWMsR0FBZCxHQUFvQixJQUFJLEtBQUosQ0FBVSxLQUFLLG1CQUFMLEVBQVYsQ0FBcEIsQ0FSZTs7QUFVZix3QkFBSSxDQUFDLEtBQUssZ0JBQUwsQ0FBc0IsYUFBdEIsQ0FBRCxFQUF1QztBQUN2QywrQkFBTyxJQUFQLENBRHVDO3FCQUEzQzs7QUFJQSwyQkFBTyxLQUFLLHdCQUFMLENBQThCLGFBQTlCLENBQVAsQ0FkZTtpQkFBbkI7O0FBaUJBLG9CQUFNLGVBQWUsS0FBSyxjQUFMLENBQW9CLFlBQXBCLEVBQWtDLGFBQWxDLENBQWYsQ0F0QzhCO0FBdUNwQyxvQkFBSSxDQUFDLFlBQUQsRUFBZTtBQUNmLGdDQUFZLFNBQVMsSUFBVCxDQUFjLGtCQUFkLEVBQWtDLEtBQUssR0FBTCxDQUFTO0FBQ25ELG9DQUFZLElBQVo7QUFDQSxrQ0FBVSxrQkFBVjtBQUNBLGdDQUFRLG1CQUFSO0FBQ0EsZ0NBQVEsWUFBUjtxQkFKMEMsRUFLM0MsYUFMMkMsQ0FBbEMsQ0FBWixDQURlOztBQVFmLHdCQUFNLFdBQVcsYUFBYSxtQkFBYixJQUFvQyxLQUFLLHNCQUFMLEVBQXBDLENBUkY7QUFTZixrQ0FBYyxXQUFkLEdBQTRCLGNBQWMsR0FBZCxDQVRiO0FBVWYsa0NBQWMsR0FBZCxHQUFvQixJQUFJLEtBQUosQ0FBVSxRQUFWLENBQXBCLENBVmU7QUFXZiwyQkFBTyxLQUFLLHdCQUFMLENBQThCLGFBQTlCLENBQVAsQ0FYZTtpQkFBbkI7O0FBY0EsdUJBQU8sWUFBUCxDQXJEb0M7Ozs7dUNBd0Q3QixlQUFlOzs7QUFDdEIsb0JBQUksZUFBZSxLQUFLLHdCQUFMLENBQThCLGFBQTlCLENBQWYsQ0FEa0I7QUFFdEIsK0JBQWUsS0FBSyxtQkFBTCxDQUF5QixZQUF6QixFQUF1QyxhQUF2QyxDQUFmLENBRnNCO0FBR3RCLG9CQUFNLFdBQVcsS0FBSyxXQUFMLEVBQVgsQ0FIZ0I7O0FBS3RCLG9CQUFJLENBQUMsWUFBRCxFQUFlO0FBQ2Ysd0JBQU0sU0FBUyxJQUFJLE9BQUosQ0FBWSxVQUFDLE9BQUQsRUFBVSxNQUFWLEVBQXFCO0FBQzVDLGlFQUF1QyxjQUFjLEdBQWQsQ0FBa0IsT0FBbEIsRUFBdkMsRUFENEM7cUJBQXJCLENBQXJCLENBRFM7O0FBS2YsMkJBQU8sTUFBUCxDQUxlO2lCQUFuQjs7QUFRQSxvQkFBSSxhQUFhLEtBQWIsRUFBb0I7QUFDcEIsa0NBQWMsS0FBZCxHQUFzQixhQUFhLEtBQWIsQ0FERjtBQUVwQixrQ0FBYyxJQUFkLENBQW1CLEtBQW5CLEdBQTJCLGFBQWEsS0FBYixDQUZQO2lCQUF4Qjs7QUFLQSxvQkFBSSxhQUFhLGFBQWIsRUFBNEI7QUFDNUIsa0NBQWMsYUFBZCxHQUE4QixhQUFhLGFBQWIsQ0FERjtBQUU1QixrQ0FBYyxJQUFkLENBQW1CLGFBQW5CLEdBQW1DLGFBQWEsYUFBYixDQUZQO2lCQUFoQzs7QUFLQSxvQkFBSSxhQUFhLElBQWIsRUFBbUI7QUFDbkIseUJBQUssSUFBTSxJQUFOLElBQWMsYUFBYSxJQUFiLEVBQW1CO0FBQ2xDLDRCQUFJLGFBQWEsSUFBYixDQUFrQixjQUFsQixDQUFpQyxJQUFqQyxDQUFKLEVBQTRDO0FBQ3hDLGdDQUFJLENBQUMsY0FBYyxJQUFkLENBQW1CLGNBQW5CLENBQWtDLElBQWxDLENBQUQsRUFBMEM7QUFDMUMsOENBQWMsSUFBZCxDQUFtQixJQUFuQixJQUEyQixhQUFhLElBQWIsQ0FBa0IsSUFBbEIsQ0FBM0IsQ0FEMEM7NkJBQTlDO0FBR0EsZ0NBQUksQ0FBQyxjQUFjLGNBQWQsQ0FBNkIsSUFBN0IsQ0FBRCxFQUFxQztBQUNyQyw4Q0FBYyxJQUFkLElBQXNCLGFBQWEsSUFBYixDQUFrQixJQUFsQixDQUF0QixDQURxQzs2QkFBekM7eUJBSko7cUJBREo7aUJBREo7O0FBYUEsb0JBQU0sVUFBVSxFQUFWLENBcENnQjtBQXFDdEIsb0JBQU0sU0FBUyxJQUFJLE9BQUosQ0FBWSxVQUFDLE9BQUQsRUFBVSxNQUFWLEVBQXFCO0FBQzVDLDRCQUFRLE9BQVIsR0FBa0IsT0FBbEIsQ0FENEM7QUFFNUMsNEJBQVEsTUFBUixHQUFpQixNQUFqQixDQUY0QztpQkFBckIsQ0FBckIsQ0FyQ2dCOztBQTBDdEIsb0JBQUksVUFBVSxLQUFWLENBMUNrQjtBQTJDdEIsdUJBQU8sS0FBUCxHQUFlLFlBQU07QUFDakIsd0JBQUksQ0FBQyxPQUFELEVBQVU7QUFDVixrQ0FBVSxJQUFWLENBRFU7QUFFVixvQ0FBWSxTQUFTLElBQVQsQ0FBYyxhQUFkLEVBQTZCLEtBQUssR0FBTCxDQUFTO0FBQzlDLDhDQUQ4Qzt5QkFBVCxFQUV0QyxhQUZzQyxDQUE3QixDQUFaLENBRlU7cUJBQWQ7aUJBRFcsQ0EzQ087O0FBb0R0QixvQkFBSSxDQUFDLGNBQWMsYUFBZCxFQUE2QjtBQUM5Qix5QkFBSyxVQUFMLEdBQWtCLGNBQWMsR0FBZCxDQURZO2lCQUFsQzs7QUFJQSxvQkFBTSxXQUFXLFNBQVgsUUFBVyxDQUFDLGNBQUQsRUFBb0I7QUFDakMsd0JBQUksT0FBSixFQUFhO0FBQ1QsK0JBRFM7cUJBQWI7O0FBSUEsd0JBQUksQ0FBQyxjQUFELEVBQWlCO0FBQ2pCLDRCQUFNLHNDQUFvQyxhQUFhLElBQWIsQ0FEekI7QUFFakIsNEJBQU0sUUFBUSxLQUFLLEdBQUwsQ0FBUztBQUNuQiw4Q0FEbUI7QUFFbkIsc0NBQVUsVUFBVjtBQUNBLG9DQUFRLFlBQVI7QUFDQSxvQ0FBUSxNQUFSO3lCQUpVLEVBS1gsYUFMVyxDQUFSLENBRlc7O0FBU2pCLG9DQUFZLFNBQVMsSUFBVCxDQUFjLFlBQWQsRUFBNEIsS0FBNUIsQ0FBWixDQVRpQjtBQVVqQixvQ0FBWSxTQUFTLFdBQVQsQ0FBcUIsS0FBckIsQ0FBWixDQVZpQjtBQVdqQixnQ0FBUSxNQUFSLENBQWUsTUFBZixFQVhpQjtBQVlqQiwrQkFaaUI7cUJBQXJCOztBQWVBLGdDQUFZLFNBQVMsSUFBVCxDQUFjLGNBQWQsRUFBOEI7QUFDdEMsMENBRHNDO0FBRXRDLDZCQUFLLGNBQWMsR0FBZDtBQUNMLGdDQUFRLFlBQVI7QUFDQSxnQ0FBUSxjQUFSO3FCQUpRLENBQVosQ0FwQmlDOztBQTJCakMsd0JBQUksT0FBTyxjQUFQLEtBQTBCLFVBQTFCLEVBQXNDO0FBQ3RDLGdDQUFRLE9BQVIsQ0FBZ0I7QUFDWixvQ0FBUSxJQUFJLGNBQUosRUFBUjtBQUNBLHdEQUZZO3lCQUFoQixFQURzQztxQkFBMUMsTUFNSyxJQUFJLE9BQU8sZUFBZSxtQkFBZixLQUF1QyxVQUE5QyxFQUEwRDtBQUMvRCw0QkFBTSx3QkFBd0IsU0FBeEIscUJBQXdCLENBQUMsTUFBRCxFQUFZO0FBQ3RDLGdDQUFJLENBQUMsTUFBRCxFQUFTO0FBQ1Qsb0NBQU0sVUFBUyxtQ0FBVCxDQURHO0FBRVQsb0NBQU0sU0FBUSxLQUFLLEdBQUwsQ0FBUztBQUNuQixzREFEbUI7QUFFbkIsOENBQVUsZ0JBQVY7QUFDQSw0Q0FBUSxZQUFSO0FBQ0EsbURBSm1CO0FBS25CLGtEQUxtQjtpQ0FBVCxFQU1YLGFBTlcsQ0FBUixDQUZHO0FBU1QsNENBQVksU0FBUyxJQUFULENBQWMsWUFBZCxFQUE0QixNQUE1QixDQUFaLENBVFM7QUFVVCw0Q0FBWSxTQUFTLFdBQVQsQ0FBcUIsTUFBckIsQ0FBWixDQVZTOztBQVlULHdDQUFRLE1BQVIsQ0FBZSxPQUFmLEVBWlM7NkJBQWIsTUFjSztBQUNELHdDQUFRLE9BQVIsQ0FBZ0IsRUFBQyxjQUFELEVBQVMsNEJBQVQsRUFBaEIsRUFEQzs2QkFkTDt5QkFEMEIsQ0FEaUM7QUFvQi9ELDRCQUFNLHVCQUF1QixlQUFlLG1CQUFmLENBQW1DLGFBQW5DLENBQXZCLENBcEJ5RDtBQXFCL0QsZ0NBQVEsT0FBUixDQUFnQixvQkFBaEIsRUFBc0MsSUFBdEMsQ0FBMkMscUJBQTNDLEVBckIrRDtxQkFBOUQsTUF1QkE7QUFDRCxnQ0FBUSxPQUFSLENBQWdCO0FBQ1osb0NBQVEsY0FBUjtBQUNBLHdEQUZZO3lCQUFoQixFQURDO3FCQXZCQTtpQkFqQ1EsQ0F4REs7O0FBd0h0QixvQkFBSSxPQUFPLGFBQWEsSUFBYixLQUFzQixRQUE3QixFQUF1QztBQUN2QywrQkFBVyxVQUFYLEdBQXdCLENBQUMsYUFBYSxJQUFiLENBQXpCLEVBQTZDLFFBQTdDLEVBRHVDO2lCQUEzQyxNQUdLO0FBQ0QsNkJBQVMsYUFBYSxJQUFiLENBQVQsQ0FEQztpQkFITDs7QUFPQSx1QkFBTyxNQUFQLENBL0hzQjs7Ozt3Q0FrSWQsUUFBUSxlQUFlOzs7QUFDL0Isb0JBQU0sV0FBVyxLQUFLLFdBQUwsRUFBWCxDQUR5Qjs7QUFHL0Isb0JBQUksQ0FBQyxjQUFjLGFBQWQsRUFBNkI7QUFDOUIsd0JBQUksY0FBYyxHQUFkLEtBQXNCLEtBQUssVUFBTCxFQUFpQjtBQUN2QywrQkFEdUM7cUJBQTNDOztBQUlBLHdCQUFJLEtBQUssYUFBTCxFQUFvQjtBQUNwQixvQ0FBWSxTQUFTLElBQVQsQ0FBYyxhQUFkLEVBQTZCO0FBQ3JDLHdDQUFZLElBQVo7QUFDQSxvQ0FBUSxLQUFLLGFBQUw7QUFDUixnQ0FBSSxLQUFLLEdBQUwsQ0FBUyxFQUFULEVBQWEsYUFBYixDQUFKO3lCQUhRLENBQVosQ0FEb0I7O0FBT3BCLDRCQUFJLE9BQU8sS0FBSyxhQUFMLENBQW1CLEtBQW5CLEtBQTZCLFVBQXBDLEVBQWdEO0FBQ2hELGlDQUFLLGFBQUwsQ0FBbUIsS0FBbkIsR0FEZ0Q7eUJBQXBEO3FCQVBKO0FBV0EseUJBQUssYUFBTCxHQUFxQixNQUFyQixDQWhCOEI7O0FBa0I5Qix3QkFBSSxPQUFPLFFBQVAsRUFBaUI7QUFDakIsK0JBQU8sUUFBUCxDQUFnQixLQUFoQixHQUF3QixjQUFjLEtBQWQsSUFBdUIsY0FBYyxhQUFkLElBQStCLEtBQUssZUFBTCxFQUF0RCxDQURQO3FCQUFyQjtpQkFsQko7O0FBdUJBLDRCQUFZLFNBQVMsSUFBVCxDQUFjLGFBQWQsRUFBNkIsS0FBSyxHQUFMLENBQVM7QUFDOUMsZ0NBQVksSUFBWjtBQUNBLGtDQUY4QztpQkFBVCxFQUd0QyxhQUhzQyxDQUE3QixDQUFaLENBMUIrQjs7QUErQi9CLG9CQUFNLHNCQUFzQixTQUF0QixtQkFBc0IsR0FBTTtBQUM5QixnQ0FBWSxTQUFTLElBQVQsQ0FBYyxxQkFBZCxFQUFxQyxLQUFLLEdBQUwsQ0FBUztBQUN0RCwwQ0FEc0Q7QUFFdEQsc0NBRnNEO3FCQUFULEVBRzlDLGFBSDhDLENBQXJDLENBQVosQ0FEOEI7aUJBQU4sQ0EvQkc7O0FBc0MvQixvQkFBTSxrQkFBa0IsU0FBbEIsZUFBa0IsQ0FBQyxNQUFELEVBQVk7QUFDaEMsd0JBQUksVUFBVSxFQUFWLENBRDRCO0FBRWhDLHdCQUFJLENBQUMsTUFBRCxFQUFTO0FBQ1Qsa0NBQVUsb0NBQVYsQ0FEUztxQkFBYixNQUdLLElBQUksT0FBTyxPQUFQLEVBQWdCO0FBQ3JCLGtDQUFVLE9BQU8sT0FBUCxDQURXO0FBRXJCLDRCQUFJLE9BQU8sS0FBUCxFQUFjO0FBQ2QsdUNBQVcsT0FBTyxPQUFPLEtBQVAsQ0FESjt5QkFBbEI7cUJBRkMsTUFNQSxJQUFJLFFBQVEsT0FBTyxLQUFLLFNBQUwsS0FBbUIsVUFBMUIsRUFBc0M7QUFDbkQsNEJBQUk7QUFDQSxzQ0FBVSxLQUFLLFNBQUwsQ0FBZSxNQUFmLENBQVYsQ0FEQTt5QkFBSixDQUdBLE9BQU8sY0FBUCxFQUF1QjtBQUNuQixzQ0FBVSxNQUFWLENBRG1CO3lCQUF2QjtxQkFKQyxNQVFBO0FBQ0Qsa0NBQVUsTUFBVixDQURDO3FCQVJBOztBQVlMLHdCQUFNLFFBQVEsS0FBSyxHQUFMLENBQVM7QUFDbkIsa0NBQVUsV0FBVjtBQUNBLGdDQUFRLE9BQVI7cUJBRlUsRUFHWCxhQUhXLENBQVIsQ0F2QjBCOztBQTRCaEMsZ0NBQVksU0FBUyxJQUFULENBQWMsaUJBQWQsRUFBaUMsS0FBakMsQ0FBWixDQTVCZ0M7QUE2QmhDLGdDQUFZLFNBQVMsV0FBVCxDQUFxQixLQUFyQixDQUFaLENBN0JnQztpQkFBWixDQXRDTzs7QUFzRS9CLG9CQUFNLFdBQVcsT0FBTyxLQUFQLENBQWEsYUFBYixDQUFYLENBdEV5QjtBQXVFL0IseUJBQVMsSUFBVCxDQUFjLG1CQUFkLEVBQW1DLGVBQW5DLEVBdkUrQjs7QUF5RS9CLHVCQUFPLFFBQVAsQ0F6RStCOzs7O29DQTRFM0IsS0FBSyxXQUFXLFNBQVMsZUFBZTtBQUM1QyxvQkFBTSxnQkFBZ0I7QUFDbEIsNEJBRGtCO0FBRWxCLHdDQUZrQjtBQUdsQixtQ0FBZSxDQUFDLENBQUMsYUFBRDtpQkFIZCxDQURzQztBQU01QyxvQkFBTSxXQUFXLEtBQUssV0FBTCxFQUFYLENBTnNDOztBQVE1QyxvQkFBSSxhQUFKLEVBQW1CO0FBQ2Ysd0JBQU0sZUFBZSxLQUFLLGtCQUFMLENBQXdCLFNBQXhCLENBQWYsQ0FEUztBQUVmLGtDQUFjLFFBQWQsR0FBeUIsZUFBZSxhQUFhLEdBQWIsR0FBbUIsSUFBbEMsQ0FGVjtpQkFBbkIsTUFJSztBQUNELGtDQUFjLFFBQWQsR0FBeUIsS0FBSyxVQUFMLENBRHhCO2lCQUpMOztBQVFBLHFCQUFLLEdBQUwsQ0FBUyxhQUFULEVBQXdCLE9BQXhCLEVBaEI0Qzs7QUFrQjVDLDhCQUFjLElBQWQsR0FBcUIsS0FBSyxHQUFMLENBQVMsRUFBVCxFQUFhLGFBQWIsQ0FBckIsQ0FsQjRDO0FBbUI1QyxxQkFBSyxHQUFMLENBQVMsY0FBYyxJQUFkLEVBQW9CLElBQUksUUFBSixFQUE3QixFQW5CNEM7O0FBcUI1QyxvQkFBSSxDQUFDLGFBQUQsSUFBa0IsS0FBSyxvQkFBTCxJQUNmLEtBQUssb0JBQUwsQ0FBMEIsT0FBMUIsT0FBd0MsSUFBSSxPQUFKLEVBQXhDLEVBQXVEO0FBQzFELHlCQUFLLEdBQUwsQ0FBUyxjQUFjLElBQWQsRUFBb0IsRUFBQyxpQkFBaUIsSUFBakIsRUFBOUIsRUFBc0QsS0FBSyxlQUFMLENBQXRELENBRDBEO0FBRTFELHlCQUFLLG9CQUFMLEdBQTRCLElBQTVCLENBRjBEO0FBRzFELHlCQUFLLGVBQUwsR0FBdUIsSUFBdkIsQ0FIMEQ7aUJBRDlEO0FBTUEsOEJBQWMsU0FBZCxHQUEwQixLQUFLLFlBQUwsRUFBMUIsQ0EzQjRDOztBQTZCNUMsNEJBQVksU0FBUyxJQUFULENBQWMsZUFBZCxFQUErQixLQUFLLEdBQUwsQ0FBUyxFQUFDLFlBQVksSUFBWixFQUFWLEVBQTZCLGFBQTdCLENBQS9CLENBQVosQ0E3QjRDO0FBOEI1QyxvQkFBTSxTQUFTLEtBQUssVUFBTCxDQUFnQixhQUFoQixDQUFULENBOUJzQztBQStCNUMsdUJBQU8sR0FBUCxDQUFXLE1BQVgsRUFBbUIsMkNBQW5CLEVBL0I0Qzs7QUFpQzVDLHVCQUFPLE1BQVAsQ0FqQzRDOzs7O3lDQW9DbkMsS0FBSzs7O0FBQ2Qsb0JBQUksT0FBTyxHQUFQLEtBQWUsUUFBZixFQUF5QjtBQUN6QiwwQkFBTSxJQUFJLEtBQUosQ0FBVSxHQUFWLENBQU4sQ0FEeUI7aUJBQTdCO0FBR0Esb0JBQUksS0FBSyxrQkFBTCxJQUEyQixPQUFPLEtBQUssa0JBQUwsQ0FBd0IsS0FBeEIsS0FBa0MsVUFBekMsRUFBcUQ7QUFDaEYseUJBQUssa0JBQUwsQ0FBd0IsS0FBeEIsR0FEZ0Y7aUJBQXBGOztBQUlBLG9CQUFJLEtBQUssYUFBTCxJQUNHLE9BQU8sS0FBSyxhQUFMLENBQW1CLGNBQW5CLEtBQXNDLFVBQTdDLElBQ0EsS0FBSyxhQUFMLENBQW1CLGNBQW5CLENBQWtDLEdBQWxDLE1BQTJDLEtBQTNDLEVBQWtEO0FBQ3JELDJCQUFPLFFBQVEsTUFBUixDQUFlLHFDQUFmLENBQVAsQ0FEcUQ7aUJBRnpEOztBQU1BLHFCQUFLLGtCQUFMLEdBQTBCLEtBQUssT0FBTCxDQUFhLEdBQWIsRUFBa0IsS0FBSyxnQkFBTCxFQUFsQixFQUEyQyxJQUEzQyxFQUFpRCxLQUFqRCxDQUExQixDQWRjO0FBZWQsb0JBQU0sV0FBVyxLQUFLLFdBQUwsRUFBWCxDQWZROztBQWlCZCx1QkFBTyxLQUFLLGtCQUFMLENBQ0YsSUFERSxDQUNHLGdCQUFRO0FBQ1YsMkJBQU8sT0FBSyxXQUFMLENBQWlCLElBQWpCLFNBQTRCLEtBQUssTUFBTCxFQUFhLEtBQUssYUFBTCxDQUFoRCxDQURVO2lCQUFSLENBREgsQ0FJRixJQUpFLENBSUcsSUFKSCxFQUlTLFVBQUMsS0FBRCxFQUFXO0FBQ25CLGdDQUFZLFNBQVMsV0FBVCxDQUFxQixLQUFyQixDQUFaLENBRG1CO0FBRW5CLDBCQUFNLEtBQU4sQ0FGbUI7aUJBQVgsQ0FKaEIsQ0FqQmM7Ozs7NkNBMkJELFFBQVEsZUFBZTtBQUNwQyxxQkFBSyxrQkFBTCxDQUF3QixjQUFjLFNBQWQsQ0FBeEIsR0FBbUQsSUFBbkQsQ0FEb0M7O0FBR3BDLG9CQUFJLGtCQUFKLENBSG9DO0FBSXBDLG9CQUFJLE9BQU8sUUFBUCxJQUFtQixPQUFPLFFBQVAsQ0FBZ0IsY0FBaEIsRUFBZ0M7QUFDbkQsZ0NBQVksT0FBTyxRQUFQLENBQWdCLGNBQWhCLENBQStCLGNBQWMsU0FBZCxDQUEzQyxDQURtRDtpQkFBdkQ7QUFHQSxvQkFBSSxDQUFDLFNBQUQsRUFBWTtBQUNaLDJCQURZO2lCQUFoQjs7QUFJQSxvQkFBTSxVQUFVLEtBQUssVUFBTCxFQUFWLENBWDhCO0FBWXBDLG9CQUFNLG9CQUFvQixJQUFwQixDQVo4Qjs7QUFjcEMsb0JBQU0sV0FBVyxTQUFYLFFBQVcsQ0FBQyxHQUFELEVBQU0sT0FBTixFQUFlLEtBQWYsRUFBeUI7QUFDdEMsOEJBQVUsV0FBVyxFQUFYLENBRDRCO0FBRXRDLDBCQUFNLFFBQVEsVUFBUixDQUFtQixHQUFuQixFQUF3QixPQUF4QixDQUFOLENBRnNDOztBQUl0Qyx3QkFBSSxRQUFRLE1BQVIsRUFBZ0I7QUFDaEIsNEJBQU0sMEJBQTBCLFFBQVEsUUFBUixDQUFpQixHQUFqQixFQUFzQixPQUF0QixDQUExQixDQURVO0FBRWhCLDRCQUFJLDJCQUEyQixTQUEzQixFQUFzQztBQUN0Qyw4Q0FBa0IsaUJBQWxCLEVBQXFDLFNBQXJDLEVBRHNDO3lCQUExQztBQUdBLCtCQUFPLHVCQUFQLENBTGdCO3FCQUFwQjs7QUFRQSx3QkFBTSxrQkFBa0Isa0JBQWtCLGtCQUFsQixDQUFxQyxjQUFjLFNBQWQsQ0FBdkQsQ0FaZ0M7QUFhdEMsd0JBQU0sVUFBVSxJQUFJLFFBQUosT0FBbUIsZ0JBQWdCLEdBQWhCLENBQW9CLFFBQXBCLEVBQW5CLENBYnNCO0FBY3RDLHdCQUFNLHdCQUF3QixXQUFXLFFBQVEsS0FBUixDQWRIO0FBZXRDLHdCQUFJLHFCQUFKLEVBQTJCO0FBQ3ZCLDRCQUFJLFFBQVEsTUFBUixFQUFnQjtBQUNoQiw0Q0FBZ0IsR0FBaEIsR0FBc0IsR0FBdEIsQ0FEZ0I7eUJBQXBCLE1BR0s7QUFDRCw4Q0FBa0IsaUJBQWxCLENBQW9DLEdBQXBDLEVBQXlDLGdCQUFnQixTQUFoQixFQUEyQixLQUFwRSxFQURDO3lCQUhMO3FCQURKOztBQVNBLDJCQUFPLHFCQUFQLENBeEJzQztpQkFBekIsQ0FkbUI7O0FBeUNwQyxvQkFBTSwwQkFBMEIsU0FBMUIsdUJBQTBCLENBQUMsQ0FBRCxFQUFPOzs7QUFHbkMsd0JBQUksRUFBRSx1QkFBRixFQUEyQjtBQUMzQiwrQkFBTyxJQUFQLENBRDJCO3FCQUEvQjs7QUFJQSx3QkFBSSxxQkFBcUIsRUFBRSxNQUFGLElBQVksRUFBRSxVQUFGLENBUEY7QUFRbkMsMkJBQU8sa0JBQVAsRUFBMkI7Ozs7O0FBS3ZCLDRCQUFJLG1CQUFtQixFQUFuQixJQUF5QixrQkFBa0Isa0JBQWxCLENBQXFDLG1CQUFtQixFQUFuQixDQUE5RCxFQUFzRjtBQUN0RixrQ0FEc0Y7eUJBQTFGOztBQUlBLDZDQUFxQixtQkFBbUIsVUFBbkIsQ0FURTtxQkFBM0I7OztBQVJtQyx3QkFxQi9CLG1CQUFtQixFQUFuQixLQUEwQixjQUFjLFNBQWQsRUFBeUI7QUFDbkQsMEJBQUUsdUJBQUYsR0FBNEIsSUFBNUIsQ0FEbUQ7QUFFbkQsK0JBQU8sSUFBUCxDQUZtRDtxQkFBdkQ7O0FBS0EsMkJBQU8sS0FBUCxDQTFCbUM7aUJBQVA7OztBQXpDSSxvQkF1RTlCLFNBQVMsU0FBVCxNQUFTLENBQUMsQ0FBRCxFQUFPOztBQUVsQix3QkFBSSxLQUFNLE9BQU8sTUFBUCxJQUFpQixPQUFPLE1BQVAsQ0FBYyxLQUFkLENBRlQ7QUFHbEIsd0JBQU0sU0FBUyxFQUFFLE1BQUYsSUFBWSxFQUFFLFVBQUY7OztBQUhULHdCQU1kLE9BQU8sUUFBUCxDQUFnQixXQUFoQixPQUFrQyxHQUFsQyxFQUF1QztBQUN2QywrQkFEdUM7cUJBQTNDOzs7QUFOa0Isd0JBV1osT0FBTyxPQUFPLFlBQVAsQ0FBb0IsTUFBcEIsRUFBNEIsQ0FBNUIsS0FBa0MsRUFBbEM7O0FBWEssd0JBYWQsS0FBSyxNQUFMLENBQVksQ0FBWixNQUFtQixHQUFuQixFQUF3QjtBQUN4QiwrQkFEd0I7cUJBQTVCOztBQWJrQix3QkFpQmQsd0JBQXdCLENBQXhCLENBQUosRUFBZ0M7QUFDNUIsK0JBRDRCO3FCQUFoQzs7QUFJQSx3QkFBSSxFQUFFLGNBQUYsRUFBa0I7QUFDbEIsMEJBQUUsY0FBRixHQURrQjtxQkFBdEIsTUFHSztBQUNELDBCQUFFLFdBQUYsR0FBZ0IsS0FBaEIsQ0FEQztxQkFITDs7O0FBckJrQix3QkE2QlosTUFBTSxLQUFLLFNBQUwsQ0FBZSxDQUFmLENBQU47Ozs7O0FBN0JZLHdCQWtDWixxQkFBcUIsQ0FBQyxPQUFPLFlBQVAsQ0FBb0IsZUFBcEIsS0FBd0MsRUFBeEMsQ0FBRCxDQUE2QyxLQUE3QyxDQUFtRCxPQUFuRCxDQUFyQixDQWxDWTtBQW1DbEIsd0JBQU0sa0JBQWtCLEVBQWxCLENBbkNZO0FBb0NsQix5QkFBSyxJQUFJLElBQUksQ0FBSixFQUFPLElBQUksbUJBQW1CLE1BQW5CLEVBQTJCLEdBQS9DLEVBQW9EO0FBQ2hELDRCQUFNLHdCQUF3QixLQUFLLElBQUwsQ0FBVSxtQkFBbUIsQ0FBbkIsQ0FBVixDQUF4QixDQUQwQztBQUVoRCx3Q0FBZ0IscUJBQWhCLElBQXlDLElBQXpDLENBRmdEO3FCQUFwRDtBQUlBLDZCQUFTLEdBQVQsRUFBYyxlQUFkLEVBeENrQjtpQkFBUCxDQXZFcUI7O0FBa0hwQyx1QkFBTyxRQUFQLEdBQWtCLFFBQWxCLENBbEhvQzs7QUFvSHBDLHVCQUFPLE1BQVAsR0FBZ0IsVUFBVSxLQUFWLEVBQWlCO0FBQzdCLHlCQUFLLFFBQUwsQ0FBYyxjQUFjLEdBQWQsRUFBbUIsRUFBQyxPQUFPLElBQVAsRUFBbEMsRUFBZ0QsS0FBaEQsRUFENkI7aUJBQWpCLENBcEhvQjs7QUF3SHBDLHVCQUFPLElBQVAsR0FBYyxVQUFVLFVBQVYsRUFBc0IsS0FBdEIsRUFBNkI7QUFDdkMsd0JBQU0sV0FBVyxLQUFLLE9BQUwsSUFBZ0IsS0FBSyxPQUFMLENBQWEsUUFBYixDQURNO0FBRXZDLHdCQUFNLE1BQU0sWUFBWSxVQUFaLENBRjJCO0FBR3ZDLHlCQUFLLFFBQUwsQ0FBYyxHQUFkLEVBQW1CLElBQW5CLEVBQXlCLEtBQXpCLEVBSHVDO2lCQUE3QixDQXhIc0I7QUE2SHBDLCtCQUFlLElBQWYsRUFBcUIsU0FBckIsRUFBZ0MsTUFBaEMsRUFBd0MsTUFBeEMsRUFBZ0QsYUFBaEQsRUE3SG9DOztBQStIcEMsdUJBQU8sS0FBSyxXQUFMLENBQWlCLE1BQWpCLEVBQXlCLGFBQXpCLENBQVAsQ0EvSG9DOzs7OzhDQWtJdEIsS0FBSyxXQUFXLFNBQVM7OztBQUN2Qyx1QkFBTyxHQUFQLENBQVcsU0FBWCxFQUR1Qzs7QUFHdkMsb0JBQUksT0FBTyxHQUFQLEtBQWUsUUFBZixFQUF5QjtBQUN6QiwwQkFBTSxJQUFJLEtBQUosQ0FBVSxHQUFWLENBQU4sQ0FEeUI7aUJBQTdCOztBQUlBLG9CQUFNLGlCQUFpQixLQUFLLGtCQUFMLENBQXdCLFNBQXhCLENBQWpCLENBUGlDO0FBUXZDLG9CQUFJLGtCQUFrQixPQUFPLGVBQWUsS0FBZixLQUF5QixVQUFoQyxFQUE0QztBQUM5RCxtQ0FBZSxLQUFmLEdBRDhEO2lCQUFsRTs7QUFJQSxvQkFBTSxhQUFhLEtBQUssa0JBQUwsQ0FBd0IsU0FBeEIsQ0FBYixDQVppQztBQWF2QyxvQkFBTSxpQkFBaUIsY0FBYyxXQUFXLE1BQVgsQ0FiRTtBQWN2QyxvQkFBSSxrQkFDRyxPQUFPLGVBQWUsY0FBZixLQUFrQyxVQUF6QyxJQUNBLGVBQWUsY0FBZixDQUE4QixHQUE5QixNQUF1QyxLQUF2QyxFQUNMO0FBQ0UsMkJBQU8sUUFBUSxNQUFSLENBQWUscUNBQWYsQ0FBUCxDQURGO2lCQUhGOztBQU9BLG9CQUFNLFNBQVMsS0FBSyxPQUFMLENBQWEsR0FBYixFQUFrQixTQUFsQixFQUE2QixPQUE3QixFQUFzQyxJQUF0QyxDQUFULENBckJpQztBQXNCdkMsb0JBQU0sU0FBUyxLQUFLLFdBQUwsRUFBVCxDQXRCaUM7QUF1QnZDLG9CQUFNLHFCQUFxQixPQUN0QixJQURzQixDQUNqQixnQkFBUTtBQUNWLDJCQUFPLE9BQUssZ0JBQUwsQ0FBc0IsSUFBdEIsU0FBaUMsS0FBSyxNQUFMLEVBQWEsS0FBSyxhQUFMLENBQXJELENBRFU7aUJBQVIsQ0FEaUIsQ0FJdEIsSUFKc0IsQ0FJakIsSUFKaUIsRUFJWCxLQUFLLElBQUwsQ0FBVSxPQUFPLFdBQVAsRUFBb0IsTUFBOUIsQ0FKVyxDQUFyQjs7QUF2QmlDLGtDQTZCdkMsQ0FBbUIsS0FBbkIsR0FBMkIsT0FBTyxLQUFQLENBN0JZO0FBOEJ2QyxxQkFBSyxrQkFBTCxDQUF3QixTQUF4QixJQUFxQyxrQkFBckMsQ0E5QnVDO0FBK0J2Qyx1QkFBTyxrQkFBUCxDQS9CdUM7Ozs7c0NBa0NqQyxpQkFBaUI7QUFDdkIsb0JBQUksbUJBQW1CLGdCQUFnQixVQUFoQixFQUE0QjtBQUMvQyx5QkFBSyxvQkFBTCxHQUE0QixJQUFJLEtBQUosQ0FBVSxnQkFBZ0IsVUFBaEIsQ0FBdEMsQ0FEK0M7QUFFL0MseUJBQUssZUFBTCxHQUF1QixLQUFLLEdBQUwsQ0FBUyxFQUFULEVBQWEsZ0JBQWdCLEtBQWhCLEVBQXVCLEVBQUMsS0FBSyxLQUFLLG9CQUFMLEVBQTFDLENBQXZCLENBRitDO2lCQUFuRDs7Ozt5Q0FNaUI7QUFDakIsdUJBQU8sV0FBVyxPQUFYLElBQXNCLE9BQXRCLENBRFU7Ozs7dUNBSUYsU0FBUztBQUN4QiwyQkFBVyxPQUFYLEdBQXFCLE9BQXJCLENBRHdCOzs7OztNQXpuQlAsYUF6RUg7O0FBdXNCdEIsUUFBSSxXQUFXLElBQUksVUFBSixFQUFYLENBdnNCa0I7QUF3c0J0QixhQUFTLFVBQVQsR0FBc0IsVUFBdEIsQ0F4c0JzQjs7QUEwc0J0QixXQUFPLFFBQVAsQ0Exc0JzQjtDQUFuQixDQUFQIiwiZmlsZSI6ImNvbnRyb2xsZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpZiAodHlwZW9mIGRlZmluZSAhPT0gJ2Z1bmN0aW9uJykge3ZhciBkZWZpbmUgPSByZXF1aXJlKCdhbWRlZmluZScpKG1vZHVsZSl9XG5cbmRlZmluZShmdW5jdGlvbiAocmVxdWlyZSkge1xuICAgICd1c2Ugc3RyaWN0JztcblxuICAgIGNvbnN0IFVSTCA9IHJlcXVpcmUoJy4vVVJMJyk7XG4gICAgY29uc3QgY29uZmlnID0gcmVxdWlyZSgnLi9jb25maWcnKTtcbiAgICBjb25zdCB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG4gICAgY29uc3QgYXNzZXJ0ID0gcmVxdWlyZSgnLi9hc3NlcnQnKTtcbiAgICBjb25zdCBFdmVudFRhcmdldCA9IHJlcXVpcmUoJ2ZjLW1pbmktZXZlbnQvRXZlbnRUYXJnZXQnKTtcbiAgICBjb25zdCBQZXJtaXNzaW9uID0gcmVxdWlyZSgnLi9wZXJtaXNzaW9uJykuUGVybWlzc2lvbjtcbiAgICBjb25zdCByb3V0ZXIgPSByZXF1aXJlKCcuL3JvdXRlcicpO1xuICAgIGNvbnN0IGNhblVzZURPTSA9IHJlcXVpcmUoJy4vRXhlY3V0aW9uRW52aXJvbm1lbnQnKS5jYW5Vc2VET007XG5cbiAgICBjb25zdCByZW1vdmVDaGlsZEFjdGlvbiA9IChjb250cm9sbGVyLCBjb250YWluZXIsIHRhcmdldENvbnRleHQpID0+IHtcbiAgICAgICAgY29uc3QgaW5mbyA9IGNvbnRyb2xsZXIuY2hpbGRBY3Rpb25NYXBwaW5nW2NvbnRhaW5lci5pZF07XG4gICAgICAgIGlmICghaW5mbykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29udHJvbGxlci5jaGlsZEFjdGlvbk1hcHBpbmdbY29udGFpbmVyLmlkXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGluZm8uaGlqYWNrKSB7XG4gICAgICAgICAgICBpZiAoY29udGFpbmVyLnJlbW92ZUV2ZW50TGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICBjb250YWluZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCBpbmZvLmhpamFjaywgZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyLmRldGFjaEV2ZW50KCdvbmNsaWNrJywgaW5mby5oaWphY2spO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGluZm8uYWN0aW9uKSB7XG4gICAgICAgICAgICB0YXJnZXRDb250ZXh0ID0gdGFyZ2V0Q29udGV4dCB8fCB7XG4gICAgICAgICAgICAgICAgdXJsOiBudWxsLFxuICAgICAgICAgICAgICAgIHJlZmVycmVyOiBpbmZvLnVybCxcbiAgICAgICAgICAgICAgICBjb250YWluZXI6IGNvbnRhaW5lci5pZCxcbiAgICAgICAgICAgICAgICBpc0NoaWxkQWN0aW9uOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3QgZXZlbnRCdXMgPSBjb250cm9sbGVyLmdldEV2ZW50QnVzKCk7XG4gICAgICAgICAgICBldmVudEJ1cyAmJiBldmVudEJ1cy5maXJlKCdsZWF2ZWFjdGlvbicsIHtcbiAgICAgICAgICAgICAgICBjb250cm9sbGVyLFxuICAgICAgICAgICAgICAgIGFjdGlvbjogaW5mby5hY3Rpb24sXG4gICAgICAgICAgICAgICAgdG86IHRhcmdldENvbnRleHRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBpbmZvLmFjdGlvbi5sZWF2ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgaW5mby5hY3Rpb24ubGVhdmUoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdCBhZGRDaGlsZEFjdGlvbiA9IChjb250cm9sbGVyLCBjb250YWluZXIsIGFjdGlvbiwgaGlqYWNrLCBjb250ZXh0KSA9PiB7XG4gICAgICAgIHJlbW92ZUNoaWxkQWN0aW9uKGNvbnRyb2xsZXIsIGNvbnRhaW5lciwgY29udGV4dCk7XG5cbiAgICAgICAgaWYgKGNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKSB7XG4gICAgICAgICAgICBjb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBoaWphY2ssIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnRhaW5lci5hdHRhY2hFdmVudCgnb25jbGljaycsIGhpamFjayk7XG4gICAgICAgIH1cblxuICAgICAgICBjb250cm9sbGVyLmNoaWxkQWN0aW9uTWFwcGluZ1tjb250YWluZXIuaWRdID0ge1xuICAgICAgICAgICAgdXJsOiBjb250ZXh0LnVybCxcbiAgICAgICAgICAgIGNvbnRhaW5lcjogY29udGFpbmVyLmlkLFxuICAgICAgICAgICAgYWN0aW9uOiBhY3Rpb24sXG4gICAgICAgICAgICBoaWphY2s6IGhpamFja1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChhY3Rpb24gaW5zdGFuY2VvZiBFdmVudFRhcmdldCkge1xuICAgICAgICAgICAgLy8g5ZyoQWN0aW9u6ZSA5q+B55qE5pe25YCZ6KaB5Y+W5raI5o6JXG4gICAgICAgICAgICBhY3Rpb24ub24oJ2xlYXZlJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlbW92ZUNoaWxkQWN0aW9uKGNvbnRyb2xsZXIsIGNvbnRhaW5lcik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjbGFzcyBDb250cm9sbGVyIGV4dGVuZHMgRXZlbnRUYXJnZXQge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIHN1cGVyKCk7XG4gICAgICAgICAgICB0aGlzLmNoaWxkQWN0aW9uTWFwcGluZyA9IHt9O1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50VVJMID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEFjdGlvbiA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmdsb2JhbEFjdGlvbkxvYWRlciA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmNoaWxkQWN0aW9uTG9hZGVycyA9IHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmVnaXN0ZXJBY3Rpb24gKGFjdGlvbkNvbmZpZ3MpIHtcbiAgICAgICAgICAgIGNvbnN0IG1haW4gPSByZXF1aXJlKCcuL21haW4nKTtcbiAgICAgICAgICAgIG1haW4ucmVnaXN0ZXJBY3Rpb24oYWN0aW9uQ29uZmlncyk7XG4gICAgICAgIH1cblxuICAgICAgICBnZXREZWZhdWx0VGl0bGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWZhdWx0VGl0bGU7XG4gICAgICAgIH1cblxuICAgICAgICBzZXREZWZhdWx0VGl0bGUodGl0bGUpIHtcbiAgICAgICAgICAgIHRoaXMuZGVmYXVsdFRpdGxlID0gdGl0bGU7XG4gICAgICAgIH1cblxuICAgICAgICBzZXRFckNvbnRleHQoZXJDb250ZXh0KSB7XG4gICAgICAgICAgICB0aGlzLmVyQ29udGV4dCA9IGVyQ29udGV4dDtcbiAgICAgICAgfVxuXG4gICAgICAgIGdldEVyQ29udGV4dCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVyQ29udGV4dDtcbiAgICAgICAgfVxuXG4gICAgICAgIGdldFJvdXRlcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVyQ29udGV4dCAmJiB0aGlzLmVyQ29udGV4dC5nZXRSb3V0ZXIoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNldFJvdXRlcihyb3V0ZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZXJDb250ZXh0ICYmIHRoaXMuZXJDb250ZXh0LnNldFJvdXRlcihyb3V0ZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2V0TG9jYXRvcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVyQ29udGV4dCAmJiB0aGlzLmVyQ29udGV4dC5nZXRMb2NhdG9yKCk7XG4gICAgICAgIH1cblxuICAgICAgICBzZXRMb2NhdG9yKGxvY2F0b3IpIHtcbiAgICAgICAgICAgIHRoaXMuZXJDb250ZXh0ICYmIHRoaXMuZXJDb250ZXh0LnNldExvY2F0b3IobG9jYXRvcik7XG4gICAgICAgIH1cblxuICAgICAgICBnZXRFdmVudEJ1cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVyQ29udGV4dCAmJiB0aGlzLmVyQ29udGV4dC5nZXRFdmVudEJ1cygpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2V0RXZlbnRCdXMoZXZlbnRCdXMpIHtcbiAgICAgICAgICAgIHRoaXMuZXJDb250ZXh0ICYmIHRoaXMuZXJDb250ZXh0LnNldEV2ZW50QnVzKGV2ZW50QnVzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGdldFBlcm1pc3Npb25Qcm92aWRlcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVyQ29udGV4dCAmJiB0aGlzLmVyQ29udGV4dC5nZXRQZXJtaXNzaW9uUHJvdmlkZXIoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNldFBlcm1pc3Npb25Qcm92aWRlcihwZXJtaXNzaW9uUHJvdmlkZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZXJDb250ZXh0ICYmIHRoaXMuZXJDb250ZXh0LnNldFBlcm1pc3Npb25Qcm92aWRlcihwZXJtaXNzaW9uUHJvdmlkZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2V0TWFpbkNvbnRhaW5lcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1haW5Db250YWluZXIgfHwgY29uZmlnLm1haW5FbGVtZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgc2V0TWFpbkNvbnRhaW5lcihtYWluQ29udGFpbmVyKSB7XG4gICAgICAgICAgICB0aGlzLm1haW5Db250YWluZXIgPSBtYWluQ29udGFpbmVyO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2V0Tm9BdXRob3JpdHlMb2NhdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm5vQXV0aG9yaXR5TG9jYXRpb24gfHwgY29uZmlnLm5vQXV0aG9yaXR5TG9jYXRpb247XG4gICAgICAgIH1cblxuICAgICAgICBzZXROb0F1dGhvcml0eUxvY2F0aW9uKG5vQXV0aG9yaXR5TG9jYXRpb24pIHtcbiAgICAgICAgICAgIHRoaXMubm9BdXRob3JpdHlMb2NhdGlvbiA9IG5vQXV0aG9yaXR5TG9jYXRpb247XG4gICAgICAgIH1cblxuICAgICAgICBnZXROb3RGb3VuZExvY2F0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubm90Rm91bmRMb2NhdGlvbiB8fCBjb25maWcubm90Rm91bmRMb2NhdGlvbjtcbiAgICAgICAgfVxuXG4gICAgICAgIHNldE5vdEZvdW5kTG9jYXRpb24obm90Rm91bmRMb2NhdGlvbikge1xuICAgICAgICAgICAgdGhpcy5ub3RGb3VuZExvY2F0aW9uID0gbm90Rm91bmRMb2NhdGlvbjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXJ0KCkge1xuICAgICAgICAgICAgaWYgKGNhblVzZURPTSAmJiAhdGhpcy5nZXREZWZhdWx0VGl0bGUoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0RGVmYXVsdFRpdGxlKGNvbmZpZy5zeXN0ZW1OYW1lIHx8IGdsb2JhbC5kb2N1bWVudC50aXRsZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHJvdXRlciA9IHRoaXMuZ2V0Um91dGVyKCk7XG4gICAgICAgICAgICByb3V0ZXIgJiYgcm91dGVyLnNldEJhY2t1cCh1dGlsLmJpbmQodGhpcy5yZW5kZXJBY3Rpb24sIHRoaXMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZpbmRBY3Rpb25Db25maWcgKGFjdGlvbkNvbnRleHQpIHtcbiAgICAgICAgICAgIGNvbnN0IG1haW4gPSByZXF1aXJlKCcuL21haW4nKTtcbiAgICAgICAgICAgIHJldHVybiBtYWluLmZpbmRBY3Rpb25Db25maWcoYWN0aW9uQ29udGV4dCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXNvbHZlQWN0aW9uQ29uZmlnKGFjdGlvbkNvbmZpZywgYWN0aW9uQ29udGV4dCkge1xuICAgICAgICAgICAgcmV0dXJuIGFjdGlvbkNvbmZpZztcbiAgICAgICAgfVxuXG4gICAgICAgIGNoZWNrQXV0aG9yaXR5KGFjdGlvbkNvbmZpZywgYWN0aW9uQ29udGV4dCkge1xuICAgICAgICAgICAgbGV0IGF1dGhvcml0eSA9IGFjdGlvbkNvbmZpZy5hdXRob3JpdHk7XG4gICAgICAgICAgICBpZiAoIWF1dGhvcml0eSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBwZXJtaXNzaW9uUHJvdmlkZXIgPSB0aGlzLmdldFBlcm1pc3Npb25Qcm92aWRlcigpO1xuICAgICAgICAgICAgaWYgKCFwZXJtaXNzaW9uUHJvdmlkZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBhdXRob3JpdHkgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXV0aG9yaXR5KGFjdGlvbkNvbnRleHQsIGFjdGlvbkNvbmZpZywgcGVybWlzc2lvblByb3ZpZGVyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBhdXRob3JpdHkgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgYXV0aG9yaXR5ID0gYXV0aG9yaXR5LnNwbGl0KCd8Jyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXV0aG9yaXR5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHBlcm1pc3Npb25Qcm92aWRlci5pc0FsbG93KHV0aWwudHJpbShhdXRob3JpdHlbaV0pKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZpbmRFbGlnaWJsZUFjdGlvbkNvbmZpZyhhY3Rpb25Db250ZXh0KSB7XG4gICAgICAgICAgICBsZXQgYWN0aW9uQ29uZmlnID0gdGhpcy5maW5kQWN0aW9uQ29uZmlnKGFjdGlvbkNvbnRleHQpO1xuICAgICAgICAgICAgY29uc3QgZXZlbnRCdXMgPSB0aGlzLmdldEV2ZW50QnVzKCk7XG5cbiAgICAgICAgICAgIGlmIChhY3Rpb25Db25maWcgJiYgYWN0aW9uQ29uZmlnLm1vdmVkVG8pIHtcbiAgICAgICAgICAgICAgICBldmVudEJ1cyAmJiBldmVudEJ1cy5maXJlKCdhY3Rpb25tb3ZlZCcsIHtcbiAgICAgICAgICAgICAgICAgICAgY29udHJvbGxlcjogdGhpcyxcbiAgICAgICAgICAgICAgICAgICAgdXJsOiBhY3Rpb25Db250ZXh0LnVybCxcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnOiBhY3Rpb25Db25maWcsXG4gICAgICAgICAgICAgICAgICAgIG1vdmVkVG86IGFjdGlvbkNvbmZpZy5tb3ZlZFRvXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgYWN0aW9uQ29udGV4dC5vcmlnaW5hbFVSTCA9IGFjdGlvbkNvbnRleHQudXJsO1xuICAgICAgICAgICAgICAgIGFjdGlvbkNvbnRleHQudXJsID0gVVJMLnBhcnNlKGFjdGlvbkNvbmZpZy5tb3ZlZFRvKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbmRFbGlnaWJsZUFjdGlvbkNvbmZpZyhhY3Rpb25Db250ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGFjdGlvbkNvbmZpZyAmJiAoYWN0aW9uQ29uZmlnLmNoaWxkQWN0aW9uT25seSAmJiAhYWN0aW9uQ29udGV4dC5pc0NoaWxkQWN0aW9uKSkge1xuICAgICAgICAgICAgICAgIGFjdGlvbkNvbmZpZyA9IG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghYWN0aW9uQ29uZmlnKSB7XG4gICAgICAgICAgICAgICAgZXZlbnRCdXMgJiYgZXZlbnRCdXMuZmlyZSgnYWN0aW9ubm90Zm91bmQnLCB1dGlsLm1peCh7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IHRoaXMsXG4gICAgICAgICAgICAgICAgICAgIGZhaWxUeXBlOiAnTm90Rm91bmQnLFxuICAgICAgICAgICAgICAgICAgICByZWFzb246ICdOb3QgZm91bmQnXG4gICAgICAgICAgICAgICAgfSwgYWN0aW9uQ29udGV4dCkpO1xuXG4gICAgICAgICAgICAgICAgYWN0aW9uQ29udGV4dC5vcmlnaW5hbFVSTCA9IGFjdGlvbkNvbnRleHQudXJsO1xuICAgICAgICAgICAgICAgIGFjdGlvbkNvbnRleHQudXJsID0gVVJMLnBhcnNlKHRoaXMuZ2V0Tm90Rm91bmRMb2NhdGlvbigpKTtcblxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5maW5kQWN0aW9uQ29uZmlnKGFjdGlvbkNvbnRleHQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbmRFbGlnaWJsZUFjdGlvbkNvbmZpZyhhY3Rpb25Db250ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgaGFzQXV0aG9yaXR5ID0gdGhpcy5jaGVja0F1dGhvcml0eShhY3Rpb25Db25maWcsIGFjdGlvbkNvbnRleHQpO1xuICAgICAgICAgICAgaWYgKCFoYXNBdXRob3JpdHkpIHtcbiAgICAgICAgICAgICAgICBldmVudEJ1cyAmJiBldmVudEJ1cy5maXJlKCdwZXJtaXNzaW9uZGVuaWVkJywgdXRpbC5taXgoe1xuICAgICAgICAgICAgICAgICAgICBjb250cm9sbGVyOiB0aGlzLFxuICAgICAgICAgICAgICAgICAgICBmYWlsVHlwZTogJ1Blcm1pc3Npb25EZW5pZWQnLFxuICAgICAgICAgICAgICAgICAgICByZWFzb246ICdQZXJtaXNzaW9uIGRlbmllZCcsXG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZzogYWN0aW9uQ29uZmlnXG4gICAgICAgICAgICAgICAgfSwgYWN0aW9uQ29udGV4dCkpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgbG9jYXRpb24gPSBhY3Rpb25Db25maWcubm9BdXRob3JpdHlMb2NhdGlvbiB8fCB0aGlzLmdldE5vQXV0aG9yaXR5TG9jYXRpb24oKTtcbiAgICAgICAgICAgICAgICBhY3Rpb25Db250ZXh0Lm9yaWdpbmFsVVJMID0gYWN0aW9uQ29udGV4dC51cmw7XG4gICAgICAgICAgICAgICAgYWN0aW9uQ29udGV4dC51cmwgPSBVUkwucGFyc2UobG9jYXRpb24pO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbmRFbGlnaWJsZUFjdGlvbkNvbmZpZyhhY3Rpb25Db250ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGFjdGlvbkNvbmZpZztcbiAgICAgICAgfVxuXG4gICAgICAgIGxvYWRBY3Rpb24oYWN0aW9uQ29udGV4dCkge1xuICAgICAgICAgICAgbGV0IGFjdGlvbkNvbmZpZyA9IHRoaXMuZmluZEVsaWdpYmxlQWN0aW9uQ29uZmlnKGFjdGlvbkNvbnRleHQpO1xuICAgICAgICAgICAgYWN0aW9uQ29uZmlnID0gdGhpcy5yZXNvbHZlQWN0aW9uQ29uZmlnKGFjdGlvbkNvbmZpZywgYWN0aW9uQ29udGV4dCk7XG4gICAgICAgICAgICBjb25zdCBldmVudEJ1cyA9IHRoaXMuZ2V0RXZlbnRCdXMoKTtcblxuICAgICAgICAgICAgaWYgKCFhY3Rpb25Db25maWcpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmYWlsZWQgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChgbm8gYWN0aW9uIGNvbmZpZ3VyZWQgZm9yIHVybCAke2FjdGlvbkNvbnRleHQudXJsLmdldFBhdGgoKX1gKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWlsZWQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChhY3Rpb25Db25maWcudGl0bGUpIHtcbiAgICAgICAgICAgICAgICBhY3Rpb25Db250ZXh0LnRpdGxlID0gYWN0aW9uQ29uZmlnLnRpdGxlO1xuICAgICAgICAgICAgICAgIGFjdGlvbkNvbnRleHQuYXJncy50aXRsZSA9IGFjdGlvbkNvbmZpZy50aXRsZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGFjdGlvbkNvbmZpZy5kb2N1bWVudFRpdGxlKSB7XG4gICAgICAgICAgICAgICAgYWN0aW9uQ29udGV4dC5kb2N1bWVudFRpdGxlID0gYWN0aW9uQ29uZmlnLmRvY3VtZW50VGl0bGU7XG4gICAgICAgICAgICAgICAgYWN0aW9uQ29udGV4dC5hcmdzLmRvY3VtZW50VGl0bGUgPSBhY3Rpb25Db25maWcuZG9jdW1lbnRUaXRsZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGFjdGlvbkNvbmZpZy5hcmdzKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBuYW1lIGluIGFjdGlvbkNvbmZpZy5hcmdzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhY3Rpb25Db25maWcuYXJncy5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhY3Rpb25Db250ZXh0LmFyZ3MuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb25Db250ZXh0LmFyZ3NbbmFtZV0gPSBhY3Rpb25Db25maWcuYXJnc1tuYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYWN0aW9uQ29udGV4dC5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbkNvbnRleHRbbmFtZV0gPSBhY3Rpb25Db25maWcuYXJnc1tuYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgbG9hZGluZyA9IHt9O1xuICAgICAgICAgICAgY29uc3QgbG9hZGVyID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIGxvYWRpbmcucmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgICAgICAgICAgICAgbG9hZGluZy5yZWplY3QgPSByZWplY3Q7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgbGV0IGFib3J0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGxvYWRlci5hYm9ydCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIWFib3J0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgYWJvcnRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50QnVzICYmIGV2ZW50QnVzLmZpcmUoJ2FjdGlvbmFib3J0JywgdXRpbC5taXgoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbGxlcjogdGhpc1xuICAgICAgICAgICAgICAgICAgICB9LCBhY3Rpb25Db250ZXh0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKCFhY3Rpb25Db250ZXh0LmlzQ2hpbGRBY3Rpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRVUkwgPSBhY3Rpb25Db250ZXh0LnVybDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgY2FsbGJhY2sgPSAoU3BlY2lmaWNBY3Rpb24pID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoYWJvcnRlZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFTcGVjaWZpY0FjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWFzb24gPSBgTm8gYWN0aW9uIGltcGxlbWVudCBmb3IgJHthY3Rpb25Db25maWcudHlwZX1gO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IHV0aWwubWl4KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IHRoaXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBmYWlsVHlwZTogJ05vTW9kdWxlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZzogYWN0aW9uQ29uZmlnLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uOiByZWFzb25cbiAgICAgICAgICAgICAgICAgICAgfSwgYWN0aW9uQ29udGV4dCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZXZlbnRCdXMgJiYgZXZlbnRCdXMuZmlyZSgnYWN0aW9uZmFpbCcsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRCdXMgJiYgZXZlbnRCdXMubm90aWZ5RXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICBsb2FkaW5nLnJlamVjdChyZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZXZlbnRCdXMgJiYgZXZlbnRCdXMuZmlyZSgnYWN0aW9ubG9hZGVkJywge1xuICAgICAgICAgICAgICAgICAgICBjb250cm9sbGVyOiB0aGlzLFxuICAgICAgICAgICAgICAgICAgICB1cmw6IGFjdGlvbkNvbnRleHQudXJsLFxuICAgICAgICAgICAgICAgICAgICBjb25maWc6IGFjdGlvbkNvbmZpZyxcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBTcGVjaWZpY0FjdGlvblxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBTcGVjaWZpY0FjdGlvbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICBsb2FkaW5nLnJlc29sdmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBuZXcgU3BlY2lmaWNBY3Rpb24oKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbkNvbnRleHRcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBTcGVjaWZpY0FjdGlvbi5jcmVhdGVSdW50aW1lQWN0aW9uID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc29sdmVBY3Rpb25JbnN0YW5jZSA9IChhY3Rpb24pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVhc29uID0gJ0FjdGlvbiBmYWN0b3J5IHJldHVybnMgbm9uLWFjdGlvbic7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB1dGlsLm1peCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IHRoaXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhaWxUeXBlOiAnSW52YWxpZEZhY3RvcnknLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maWc6IGFjdGlvbkNvbmZpZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCBhY3Rpb25Db250ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudEJ1cyAmJiBldmVudEJ1cy5maXJlKCdhY3Rpb25mYWlsJywgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50QnVzICYmIGV2ZW50QnVzLm5vdGlmeUVycm9yKGVycm9yKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvYWRpbmcucmVqZWN0KHJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2FkaW5nLnJlc29sdmUoe2FjdGlvbiwgYWN0aW9uQ29udGV4dH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBhY3Rpb25GYWN0b3J5UHJvZHVjdCA9IFNwZWNpZmljQWN0aW9uLmNyZWF0ZVJ1bnRpbWVBY3Rpb24oYWN0aW9uQ29udGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIFByb21pc2UucmVzb2x2ZShhY3Rpb25GYWN0b3J5UHJvZHVjdCkudGhlbihyZXNvbHZlQWN0aW9uSW5zdGFuY2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbG9hZGluZy5yZXNvbHZlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbjogU3BlY2lmaWNBY3Rpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb25Db250ZXh0XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgYWN0aW9uQ29uZmlnLnR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgQ29udHJvbGxlci5nZXRSZXF1aXJlKCkoW2FjdGlvbkNvbmZpZy50eXBlXSwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soYWN0aW9uQ29uZmlnLnR5cGUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gbG9hZGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgZW50ZXJBY3Rpb24oYWN0aW9uLCBhY3Rpb25Db250ZXh0KSB7XG4gICAgICAgICAgICBjb25zdCBldmVudEJ1cyA9IHRoaXMuZ2V0RXZlbnRCdXMoKTtcblxuICAgICAgICAgICAgaWYgKCFhY3Rpb25Db250ZXh0LmlzQ2hpbGRBY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBpZiAoYWN0aW9uQ29udGV4dC51cmwgIT09IHRoaXMuY3VycmVudFVSTCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudEFjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBldmVudEJ1cyAmJiBldmVudEJ1cy5maXJlKCdsZWF2ZWFjdGlvbicsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IHRoaXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb246IHRoaXMuY3VycmVudEFjdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvOiB1dGlsLm1peCh7fSwgYWN0aW9uQ29udGV4dClcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmN1cnJlbnRBY3Rpb24ubGVhdmUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudEFjdGlvbi5sZWF2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudEFjdGlvbiA9IGFjdGlvbjtcblxuICAgICAgICAgICAgICAgIGlmIChnbG9iYWwuZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2xvYmFsLmRvY3VtZW50LnRpdGxlID0gYWN0aW9uQ29udGV4dC50aXRsZSB8fCBhY3Rpb25Db250ZXh0LmRvY3VtZW50VGl0bGUgfHwgdGhpcy5nZXREZWZhdWx0VGl0bGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGV2ZW50QnVzICYmIGV2ZW50QnVzLmZpcmUoJ2VudGVyYWN0aW9uJywgdXRpbC5taXgoe1xuICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IHRoaXMsXG4gICAgICAgICAgICAgICAgYWN0aW9uXG4gICAgICAgICAgICB9LCBhY3Rpb25Db250ZXh0KSk7XG5cbiAgICAgICAgICAgIGNvbnN0IG5vdGlmeUVudGVyQ29tcGxldGUgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgZXZlbnRCdXMgJiYgZXZlbnRCdXMuZmlyZSgnZW50ZXJhY3Rpb25jb21wbGV0ZScsIHV0aWwubWl4KHtcbiAgICAgICAgICAgICAgICAgICAgY29udHJvbGxlcjogdGhpcyxcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uXG4gICAgICAgICAgICAgICAgfSwgYWN0aW9uQ29udGV4dCkpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgbm90aWZ5RW50ZXJGYWlsID0gKHJlYXNvbikgPT4ge1xuICAgICAgICAgICAgICAgIGxldCBtZXNzYWdlID0gJyc7XG4gICAgICAgICAgICAgICAgaWYgKCFyZWFzb24pIHtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9ICdJbnZva2UgYWN0aW9uLmVudGVyKCkgY2F1c2VzIGVycm9yJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAocmVhc29uLm1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IHJlYXNvbi5tZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVhc29uLnN0YWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlICs9ICdcXG4nICsgcmVhc29uLnN0YWNrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKEpTT04gJiYgdHlwZW9mIEpTT04uc3RyaW5naWZ5ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gSlNPTi5zdHJpbmdpZnkocmVhc29uKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjYXRjaCAocGFyc2VKU09ORXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSByZWFzb247XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSByZWFzb247XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB1dGlsLm1peCh7XG4gICAgICAgICAgICAgICAgICAgIGZhaWxUeXBlOiAnRW50ZXJGYWlsJyxcbiAgICAgICAgICAgICAgICAgICAgcmVhc29uOiBtZXNzYWdlXG4gICAgICAgICAgICAgICAgfSwgYWN0aW9uQ29udGV4dCk7XG5cbiAgICAgICAgICAgICAgICBldmVudEJ1cyAmJiBldmVudEJ1cy5maXJlKCdlbnRlcmFjdGlvbmZhaWwnLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgZXZlbnRCdXMgJiYgZXZlbnRCdXMubm90aWZ5RXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3QgZW50ZXJpbmcgPSBhY3Rpb24uZW50ZXIoYWN0aW9uQ29udGV4dCk7XG4gICAgICAgICAgICBlbnRlcmluZy50aGVuKG5vdGlmeUVudGVyQ29tcGxldGUsIG5vdGlmeUVudGVyRmFpbCk7XG5cbiAgICAgICAgICAgIHJldHVybiBlbnRlcmluZztcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcndhcmQodXJsLCBjb250YWluZXIsIG9wdGlvbnMsIGlzQ2hpbGRBY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbnN0IGFjdGlvbkNvbnRleHQgPSB7XG4gICAgICAgICAgICAgICAgdXJsLFxuICAgICAgICAgICAgICAgIGNvbnRhaW5lcixcbiAgICAgICAgICAgICAgICBpc0NoaWxkQWN0aW9uOiAhIWlzQ2hpbGRBY3Rpb25cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBldmVudEJ1cyA9IHRoaXMuZ2V0RXZlbnRCdXMoKTtcblxuICAgICAgICAgICAgaWYgKGlzQ2hpbGRBY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZWZlcnJlckluZm8gPSB0aGlzLmNoaWxkQWN0aW9uTWFwcGluZ1tjb250YWluZXJdO1xuICAgICAgICAgICAgICAgIGFjdGlvbkNvbnRleHQucmVmZXJyZXIgPSByZWZlcnJlckluZm8gPyByZWZlcnJlckluZm8udXJsIDogbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGFjdGlvbkNvbnRleHQucmVmZXJyZXIgPSB0aGlzLmN1cnJlbnRVUkw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHV0aWwubWl4KGFjdGlvbkNvbnRleHQsIG9wdGlvbnMpO1xuXG4gICAgICAgICAgICBhY3Rpb25Db250ZXh0LmFyZ3MgPSB1dGlsLm1peCh7fSwgYWN0aW9uQ29udGV4dCk7XG4gICAgICAgICAgICB1dGlsLm1peChhY3Rpb25Db250ZXh0LmFyZ3MsIHVybC5nZXRRdWVyeSgpKTtcblxuICAgICAgICAgICAgaWYgKCFpc0NoaWxkQWN0aW9uICYmIHRoaXMucmVoeWRyYXRlZEN1cnJlbnRVUkxcbiAgICAgICAgICAgICAgICAmJiB0aGlzLnJlaHlkcmF0ZWRDdXJyZW50VVJMLmdldFBhdGgoKSA9PT0gdXJsLmdldFBhdGgoKSkge1xuICAgICAgICAgICAgICAgIHV0aWwubWl4KGFjdGlvbkNvbnRleHQuYXJncywge0RBVEFfUkVIWURSQVRFRDogdHJ1ZX0sIHRoaXMucmVoeWRyYXRlZE1vZGVsKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlaHlkcmF0ZWRDdXJyZW50VVJMID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLnJlaHlkcmF0ZWRNb2RlbCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhY3Rpb25Db250ZXh0LmVyQ29udGV4dCA9IHRoaXMuZ2V0RXJDb250ZXh0KCk7XG5cbiAgICAgICAgICAgIGV2ZW50QnVzICYmIGV2ZW50QnVzLmZpcmUoJ2ZvcndhcmRhY3Rpb24nLCB1dGlsLm1peCh7Y29udHJvbGxlcjogdGhpc30sIGFjdGlvbkNvbnRleHQpKTtcbiAgICAgICAgICAgIGNvbnN0IGxvYWRlciA9IHRoaXMubG9hZEFjdGlvbihhY3Rpb25Db250ZXh0KTtcbiAgICAgICAgICAgIGFzc2VydC5oYXMobG9hZGVyLCAnbG9hZEFjdGlvbiBzaG91bGQgYWx3YXlzIHJldHVybiBhIFByb21pc2UnKTtcblxuICAgICAgICAgICAgcmV0dXJuIGxvYWRlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlbmRlckFjdGlvbih1cmwpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdXJsID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHVybCA9IFVSTC5wYXJzZSh1cmwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuZ2xvYmFsQWN0aW9uTG9hZGVyICYmIHR5cGVvZiB0aGlzLmdsb2JhbEFjdGlvbkxvYWRlci5hYm9ydCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHRoaXMuZ2xvYmFsQWN0aW9uTG9hZGVyLmFib3J0KCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnRBY3Rpb25cbiAgICAgICAgICAgICAgICAmJiB0eXBlb2YgdGhpcy5jdXJyZW50QWN0aW9uLmZpbHRlclJlZGlyZWN0ID09PSAnZnVuY3Rpb24nXG4gICAgICAgICAgICAgICAgJiYgdGhpcy5jdXJyZW50QWN0aW9uLmZpbHRlclJlZGlyZWN0KHVybCkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdSZWRpcmVjdCBhYm9ydGVkIGJ5IHByZXZpb3VzIGFjdGlvbicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmdsb2JhbEFjdGlvbkxvYWRlciA9IHRoaXMuZm9yd2FyZCh1cmwsIHRoaXMuZ2V0TWFpbkNvbnRhaW5lcigpLCBudWxsLCBmYWxzZSk7XG4gICAgICAgICAgICBjb25zdCBldmVudEJ1cyA9IHRoaXMuZ2V0RXZlbnRCdXMoKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2xvYmFsQWN0aW9uTG9hZGVyXG4gICAgICAgICAgICAgICAgLnRoZW4oYXJncyA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmVudGVyQWN0aW9uLmNhbGwodGhpcywgYXJncy5hY3Rpb24sIGFyZ3MuYWN0aW9uQ29udGV4dCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAudGhlbihudWxsLCAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRCdXMgJiYgZXZlbnRCdXMubm90aWZ5RXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGVudGVyQ2hpbGRBY3Rpb24oYWN0aW9uLCBhY3Rpb25Db250ZXh0KSB7XG4gICAgICAgICAgICB0aGlzLmNoaWxkQWN0aW9uTG9hZGVyc1thY3Rpb25Db250ZXh0LmNvbnRhaW5lcl0gPSBudWxsO1xuXG4gICAgICAgICAgICBsZXQgY29udGFpbmVyO1xuICAgICAgICAgICAgaWYgKGdsb2JhbC5kb2N1bWVudCAmJiBnbG9iYWwuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQpIHtcbiAgICAgICAgICAgICAgICBjb250YWluZXIgPSBnbG9iYWwuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoYWN0aW9uQ29udGV4dC5jb250YWluZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFjb250YWluZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGxvY2F0b3IgPSB0aGlzLmdldExvY2F0b3IoKTtcbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRDb250cm9sbGVyID0gdGhpcztcblxuICAgICAgICAgICAgY29uc3QgcmVkaXJlY3QgPSAodXJsLCBvcHRpb25zLCBleHRyYSkgPT4ge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHVybCA9IGxvY2F0b3IucmVzb2x2ZVVSTCh1cmwsIG9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGdsb2JhbFJlZGlyZWN0UGVyZm9ybWVkID0gbG9jYXRvci5yZWRpcmVjdCh1cmwsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZ2xvYmFsUmVkaXJlY3RQZXJmb3JtZWQgJiYgY29udGFpbmVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVDaGlsZEFjdGlvbihjdXJyZW50Q29udHJvbGxlciwgY29udGFpbmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZ2xvYmFsUmVkaXJlY3RQZXJmb3JtZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3QgY2hpbGRBY3Rpb25JbmZvID0gY3VycmVudENvbnRyb2xsZXIuY2hpbGRBY3Rpb25NYXBwaW5nW2FjdGlvbkNvbnRleHQuY29udGFpbmVyXTtcbiAgICAgICAgICAgICAgICBjb25zdCBjaGFuZ2VkID0gdXJsLnRvU3RyaW5nKCkgIT09IGNoaWxkQWN0aW9uSW5mby51cmwudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBzaG91bGRQZXJmb3JtUmVkaXJlY3QgPSBjaGFuZ2VkIHx8IG9wdGlvbnMuZm9yY2U7XG4gICAgICAgICAgICAgICAgaWYgKHNob3VsZFBlcmZvcm1SZWRpcmVjdCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5zaWxlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkQWN0aW9uSW5mby51cmwgPSB1cmw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Q29udHJvbGxlci5yZW5kZXJDaGlsZEFjdGlvbih1cmwsIGNoaWxkQWN0aW9uSW5mby5jb250YWluZXIsIGV4dHJhKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBzaG91bGRQZXJmb3JtUmVkaXJlY3Q7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBpc0NoaWxkQWN0aW9uUmVkaXJlY3RlZCA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8g6Zmk5L2O54mI5pysSUXlpJbvvIzlhbblroPmtY/op4jlmajmmK/lj6/ku6XlnKjkuovku7blr7nosaHkuIrliqDoh6rlrprkuYnlsZ7mgKfnmoTvvIxJReavj+asoemDveeUn+aIkOaWsOeahOS6i+S7tuWvueixoeaJgOS7peS/neeVmeS4jeS6hui/meS6m+WxnuaAp++8jFxuICAgICAgICAgICAgICAgIC8vIOWcqOi/memHjOS8mOWFiOeUqOiHquWumuS5ieWxnuaAp+aOp+WItu+8jOmBv+WFjeWvuURPTeagkeaXoOaEj+S5ieeahOmBjeWOhu+8jOWPquacieWcqOayoeacieWxnuaAp+eahOaXtuWAme+8jOaJjeWQkeWQjuWFvOWuueiHs0RPTeagkeeahOmBjeWOhlxuICAgICAgICAgICAgICAgIGlmIChlLmlzQ2hpbGRBY3Rpb25SZWRpcmVjdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxldCBpbm5lcm1vc3RDb250YWluZXIgPSBlLnRhcmdldCB8fCBlLnNyY0VsZW1lbnQ7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGlubmVybW9zdENvbnRhaW5lcikge1xuICAgICAgICAgICAgICAgICAgICAvLyDmmK9BY3Rpb27lrrnlmajnmoTlhYPntKDogq/lrprnrKblkIjku6XkuIvmnaHku7bvvJpcbiAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgLy8gLSDmnInkuKpgaWRg77yM5Zug5Li65rKh5pyJYGlkYOS4jeiDvea4suafk+WtkEFjdGlvblxuICAgICAgICAgICAgICAgICAgICAvLyAtIOi/meS4qmBpZGDlnKhgY2hpbGRBY3Rpb25NYXBwaW5nYOmHjOaYr+acieWvueW6lOeahOWAvOeahFxuICAgICAgICAgICAgICAgICAgICBpZiAoaW5uZXJtb3N0Q29udGFpbmVyLmlkICYmIGN1cnJlbnRDb250cm9sbGVyLmNoaWxkQWN0aW9uTWFwcGluZ1tpbm5lcm1vc3RDb250YWluZXIuaWRdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlubmVybW9zdENvbnRhaW5lciA9IGlubmVybW9zdENvbnRhaW5lci5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyDlpoLmnpzmnIDmjqXov5Hooqvngrnlh7vnmoTpk77mjqXnmoRBY3Rpb27lrrnlmajmmK/kuI3mmK/lvZPliY3nmoTov5nkuKrlrrnlmajvvIzlsLHor7TmmI7lnKjlvZPliY3lrrnlmajlkozpk77mjqXkuYvpl7Tov5jmnInkuIDlsYLku6XkuIrnmoTlrZBBY3Rpb27vvIxcbiAgICAgICAgICAgICAgICAvLyDpgqPkuYjov5nkuKrlrZBBY3Rpb27ogq/lrprkvJrlpITnkIbmjonov5nkuKrpk77mjqXnmoTot7PovazvvIzkuI3pnIDopoHov5nph4zlpITnkIbkuoZcbiAgICAgICAgICAgICAgICBpZiAoaW5uZXJtb3N0Q29udGFpbmVyLmlkICE9PSBhY3Rpb25Db250ZXh0LmNvbnRhaW5lcikge1xuICAgICAgICAgICAgICAgICAgICBlLmlzQ2hpbGRBY3Rpb25SZWRpcmVjdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8g6ZyA6KaB5oqKYGNvbnRhaW5lcmDkuIrnmoTpk77mjqXngrnlh7vlhajpg6jmi6bmiKrkuIvmnaXvvIzlpoLmnpzmmK9oYXNo6Lez6L2s77yM5YiZ6L2s5YiwY29udHJvbGxlcuS4iuadpVxuICAgICAgICAgICAgY29uc3QgaGlqYWNrID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICAvLyDkuIvpnaLkuKTooYzmmK/ku6XkuLvmtYHmtY/op4jlmajkuLrkuLvvvIzlhbzlrrlJReeahOS6i+S7tuWxnuaAp+aTjeS9nFxuICAgICAgICAgICAgICAgIGUgPSBlIHx8IChnbG9iYWwud2luZG93ICYmIGdsb2JhbC53aW5kb3cuZXZlbnQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldCA9IGUudGFyZ2V0IHx8IGUuc3JjRWxlbWVudDtcblxuICAgICAgICAgICAgICAgIC8vIOaLheW/g+acieS6uuWcqGA8c3Bhbj5g5LmL57G755qE5LiK6Z2i5pS+YGhyZWZg5bGe5oCn77yM6L+Y5piv5Yik5pat5LiA5LiL5qCH562+XG4gICAgICAgICAgICAgICAgaWYgKHRhcmdldC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpICE9PSAnYScpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGA8YT5g5YWD57Sg5Lmf5Y+v6IO95rKh5pyJYGhyZWZg5bGe5oCnXG4gICAgICAgICAgICAgICAgY29uc3QgaHJlZiA9IHRhcmdldC5nZXRBdHRyaWJ1dGUoJ2hyZWYnLCAyKSB8fCAnJztcbiAgICAgICAgICAgICAgICAvLyDmmK9oYXNo6Lez6L2s55qE6ZO+5o6l5bCx5Y+W5raI5o6J6buY6K6k55qE6Lez6L2s6KGM5Li6XG4gICAgICAgICAgICAgICAgaWYgKGhyZWYuY2hhckF0KDApICE9PSAnIycpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyDlpoLmnpzmnInkuIvpnaLnmoTlrZBBY3Rpb27lpITnkIbkuobot7PovazvvIzpgqPov5nph4zlsLHllaXkuZ/kuI3lubLkuoZcbiAgICAgICAgICAgICAgICBpZiAoaXNDaGlsZEFjdGlvblJlZGlyZWN0ZWQoZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChlLnByZXZlbnREZWZhdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGUucmV0dXJuVmFsdWUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyDovazliLBgcmVuZGVyQ2hpbGRBY3Rpb25g5LiKXG4gICAgICAgICAgICAgICAgY29uc3QgdXJsID0gaHJlZi5zdWJzdHJpbmcoMSk7XG5cbiAgICAgICAgICAgICAgICAvLyDnm7TmjqXkvb/nlKjkuJPkvpvlrZBBY3Rpb27kuIrnmoRgcmVkaXJlY3Rg5pa55rOV77yMXG4gICAgICAgICAgICAgICAgLy8g5Lya6Ieq5Yqo5aSE55CGYGhpamFja2DnmoTop6Pnu5HlrprjgIFVUkzmr5Tlr7njgIHov5vlhaXlrZBBY3Rpb27nrYnkuovvvIxcbiAgICAgICAgICAgICAgICAvLyDkuLrlhY1BY3Rpb27ph43lhplgcmVkaXJlY3Rg5pa55rOV77yM6L+Z6YeM55So6Zet5YyF5YaF55qE6L+Z5LiqXG4gICAgICAgICAgICAgICAgY29uc3QgcmVkaXJlY3RBdHRyaWJ1dGVzID0gKHRhcmdldC5nZXRBdHRyaWJ1dGUoJ2RhdGEtcmVkaXJlY3QnKSB8fCAnJykuc3BsaXQoL1ssXFxzXS8pO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlZGlyZWN0T3B0aW9ucyA9IHt9O1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVkaXJlY3RBdHRyaWJ1dGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlZGlyZWN0QXR0cmlidXRlTmFtZSA9IHV0aWwudHJpbShyZWRpcmVjdEF0dHJpYnV0ZXNbaV0pO1xuICAgICAgICAgICAgICAgICAgICByZWRpcmVjdE9wdGlvbnNbcmVkaXJlY3RBdHRyaWJ1dGVOYW1lXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlZGlyZWN0KHVybCwgcmVkaXJlY3RPcHRpb25zKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGFjdGlvbi5yZWRpcmVjdCA9IHJlZGlyZWN0O1xuXG4gICAgICAgICAgICBhY3Rpb24ucmVsb2FkID0gZnVuY3Rpb24gKGV4dHJhKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWRpcmVjdChhY3Rpb25Db250ZXh0LnVybCwge2ZvcmNlOiB0cnVlfSwgZXh0cmEpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgYWN0aW9uLmJhY2sgPSBmdW5jdGlvbiAoZGVmYXVsdFVSTCwgZXh0cmEpIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZWZlcnJlciA9IHRoaXMuY29udGV4dCAmJiB0aGlzLmNvbnRleHQucmVmZXJyZXI7XG4gICAgICAgICAgICAgICAgY29uc3QgdXJsID0gcmVmZXJyZXIgfHwgZGVmYXVsdFVSTDtcbiAgICAgICAgICAgICAgICB0aGlzLnJlZGlyZWN0KHVybCwgbnVsbCwgZXh0cmEpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGFkZENoaWxkQWN0aW9uKHRoaXMsIGNvbnRhaW5lciwgYWN0aW9uLCBoaWphY2ssIGFjdGlvbkNvbnRleHQpO1xuXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lbnRlckFjdGlvbihhY3Rpb24sIGFjdGlvbkNvbnRleHQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVuZGVyQ2hpbGRBY3Rpb24odXJsLCBjb250YWluZXIsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGFzc2VydC5oYXMoY29udGFpbmVyKTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB1cmwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdXJsID0gVVJMLnBhcnNlKHVybCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHByZXZpb3VzTG9hZGVyID0gdGhpcy5jaGlsZEFjdGlvbkxvYWRlcnNbY29udGFpbmVyXTtcbiAgICAgICAgICAgIGlmIChwcmV2aW91c0xvYWRlciAmJiB0eXBlb2YgcHJldmlvdXNMb2FkZXIuYWJvcnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICBwcmV2aW91c0xvYWRlci5hYm9ydCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBhY3Rpb25JbmZvID0gdGhpcy5jaGlsZEFjdGlvbk1hcHBpbmdbY29udGFpbmVyXTtcbiAgICAgICAgICAgIGNvbnN0IHByZXZpb3VzQWN0aW9uID0gYWN0aW9uSW5mbyAmJiBhY3Rpb25JbmZvLmFjdGlvbjtcbiAgICAgICAgICAgIGlmIChwcmV2aW91c0FjdGlvblxuICAgICAgICAgICAgICAgICYmIHR5cGVvZiBwcmV2aW91c0FjdGlvbi5maWx0ZXJSZWRpcmVjdCA9PT0gJ2Z1bmN0aW9uJ1xuICAgICAgICAgICAgICAgICYmIHByZXZpb3VzQWN0aW9uLmZpbHRlclJlZGlyZWN0KHVybCkgPT09IGZhbHNlXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ1JlZGlyZWN0IGFib3J0ZWQgYnkgcHJldmlvdXMgYWN0aW9uJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGxvYWRlciA9IHRoaXMuZm9yd2FyZCh1cmwsIGNvbnRhaW5lciwgb3B0aW9ucywgdHJ1ZSk7XG4gICAgICAgICAgICBjb25zdCBldmVudHMgPSB0aGlzLmdldEV2ZW50QnVzKCk7XG4gICAgICAgICAgICBjb25zdCBsb2FkaW5nQ2hpbGRBY3Rpb24gPSBsb2FkZXJcbiAgICAgICAgICAgICAgICAudGhlbihhcmdzID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW50ZXJDaGlsZEFjdGlvbi5jYWxsKHRoaXMsIGFyZ3MuYWN0aW9uLCBhcmdzLmFjdGlvbkNvbnRleHQpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLnRoZW4obnVsbCwgdXRpbC5iaW5kKGV2ZW50cy5ub3RpZnlFcnJvciwgZXZlbnRzKSk7XG4gICAgICAgICAgICAvLyBgdGhlbmDmlrnms5XkvJrov5Tlm57kuIDkuKrmlrDnmoRgUHJvbWlzZWDvvIzkvYbljp/mnaXnmoRgbG9hZGVyYOS4iuacieS4qmBhYm9ydGDmlrnms5XvvIzopoHmiorov5nkuKrmlrnms5XnlZnkuIvmnaVcbiAgICAgICAgICAgIGxvYWRpbmdDaGlsZEFjdGlvbi5hYm9ydCA9IGxvYWRlci5hYm9ydDtcbiAgICAgICAgICAgIHRoaXMuY2hpbGRBY3Rpb25Mb2FkZXJzW2NvbnRhaW5lcl0gPSBsb2FkaW5nQ2hpbGRBY3Rpb247XG4gICAgICAgICAgICByZXR1cm4gbG9hZGluZ0NoaWxkQWN0aW9uO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVoeWRyYXRlKHJlaHlkcmF0ZWRTdGF0ZSkge1xuICAgICAgICAgICAgaWYgKHJlaHlkcmF0ZWRTdGF0ZSAmJiByZWh5ZHJhdGVkU3RhdGUuY3VycmVudFVSTCkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVoeWRyYXRlZEN1cnJlbnRVUkwgPSBVUkwucGFyc2UocmVoeWRyYXRlZFN0YXRlLmN1cnJlbnRVUkwpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVoeWRyYXRlZE1vZGVsID0gdXRpbC5taXgoe30sIHJlaHlkcmF0ZWRTdGF0ZS5tb2RlbCwge3VybDogdGhpcy5yZWh5ZHJhdGVkQ3VycmVudFVSTH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc3RhdGljIGdldFJlcXVpcmUgKCkge1xuICAgICAgICAgICAgcmV0dXJuIENvbnRyb2xsZXIucmVxdWlyZSB8fCByZXF1aXJlO1xuICAgICAgICB9XG5cbiAgICAgICAgc3RhdGljIHNldFJlcXVpcmUgKHJlcXVpcmUpIHtcbiAgICAgICAgICAgIENvbnRyb2xsZXIucmVxdWlyZSA9IHJlcXVpcmU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgaW5zdGFuY2UgPSBuZXcgQ29udHJvbGxlcigpO1xuICAgIGluc3RhbmNlLkNvbnRyb2xsZXIgPSBDb250cm9sbGVyO1xuXG4gICAgcmV0dXJuIGluc3RhbmNlO1xufSk7XG4iXX0=