UNPKG

ts-events

Version:

Various EventEmitter event replacements with synchronous, a-synchronous, and queued events. Made in TypeScript so usable with JavaScript and TypeScript.

217 lines 23.6 kB
// Copyright © 2015 Rogier Schouten<github@workingcode.ninja> // License: ISC 'use strict'; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.ErrorAsyncEvent = exports.VoidAsyncEvent = exports.AsyncEvent = void 0; var base_event_1 = require("./base-event"); var sync_event_1 = require("./sync-event"); /** * A-synchronous event. Handlers are called in the next Node.JS cycle. * - Optionally condenses multiple post() calls into one (the last post() gets through) * - Handlers are called only for events posted after they were attached. * - Handlers are not called anymore when they are detached, even if a post() is in progress */ var AsyncEvent = /** @class */ (function (_super) { __extends(AsyncEvent, _super); /** * Constructor * @param opts Optional. Various settings: * - condensed: a Boolean indicating whether to condense multiple post() calls within the same cycle. */ function AsyncEvent(opts) { if (opts === void 0) { opts = {}; } var _this = _super.call(this) || this; _this._queued = false; _this.options = opts; if (typeof opts.condensed === 'boolean') { _this._condensed = opts.condensed; } else { _this._condensed = false; } return _this; } Object.defineProperty(AsyncEvent.prototype, "evtListenersChanged", { /** * Sent when someone attaches or detaches */ get: function () { if (!this._listenersChanged) { // need to delay-load to avoid stack overflow in constructor this._listenersChanged = new sync_event_1.VoidSyncEvent(); } return this._listenersChanged; }, enumerable: false, configurable: true }); /** * The default scheduler uses setImmediate() or setTimeout(..., 0) if setImmediate is not available. */ AsyncEvent.defaultScheduler = function (callback) { /* istanbul ignore else */ if (typeof window !== 'undefined') { // browsers don't always support setImmediate() setTimeout(callback, 0); } else { // node.js setImmediate(callback); } }; /** * By default, AsyncEvent uses setImmediate() to schedule event handler invocation. * You can change this for e.g. setTimeout(..., 0) by calling this static method once. * @param scheduler A function that takes a callback and executes it in the next Node.JS cycle. */ AsyncEvent.setScheduler = function (scheduler) { AsyncEvent._scheduler = scheduler; }; AsyncEvent.prototype.post = function () { var _this = this; var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } if (!this._listeners || this._listeners.length === 0) { return; } if (this._condensed) { this._queuedData = args; this._queuedListeners = this._listeners; if (this._queued) { return; } else { this._queued = true; AsyncEvent._scheduler(function () { // immediately mark non-queued to allow new AsyncEvent to happen as result // of calling handlers _this._queued = false; // cache listeners and data because they might change while calling event handlers var data = _this._queuedData; var listeners = _this._queuedListeners; for (var i = 0; i < listeners.length; ++i) { var listener = listeners[i]; _this._call(listener, data); } }); } } else { // not condensed var listeners_1 = this._listeners; AsyncEvent._scheduler(function () { for (var i = 0; i < listeners_1.length; ++i) { var listener = listeners_1[i]; _this._call(listener, args); } }); } }; // inherited AsyncEvent.prototype._call = function (listener, args) { // performance optimization: don't use consecutive nodejs cycles // for asyncevents attached to asyncevents if (listener.event && listener.event instanceof AsyncEvent) { listener.event._postDirect(args); } else { _super.prototype._call.call(this, listener, args); } }; /** * Performance optimization: if this async signal is attached to another * async signal, we're already a the next cycle and we can call listeners * directly */ AsyncEvent.prototype._postDirect = function (args) { if (!this._listeners || this._listeners.length === 0) { return; } // copy a reference to the array because this._listeners might be replaced during // the handler calls var listeners = this._listeners; for (var i = 0; i < listeners.length; ++i) { var listener = listeners[i]; this._call(listener, args); } }; /** @inheritdoc */ AsyncEvent.prototype._attach = function (a, b, once) { var _a, _b, _c, _d; var count = (_b = (_a = this._listeners) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0; var result = _super.prototype._attach.call(this, a, b, once); if (this.evtListenersChanged && count !== ((_d = (_c = this._listeners) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0)) { this.evtListenersChanged.post(); } return result; }; /** @inheritdoc */ AsyncEvent.prototype._detach = function () { var _a, _b, _c, _d; var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var count = (_b = (_a = this._listeners) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0; var result = _super.prototype._detach.apply(this, args); if (this.evtListenersChanged && count !== ((_d = (_c = this._listeners) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0)) { this.evtListenersChanged.post(); } return result; }; /** * The current scheduler */ AsyncEvent._scheduler = AsyncEvent.defaultScheduler; return AsyncEvent; }(base_event_1.BaseEvent)); exports.AsyncEvent = AsyncEvent; /** * Convenience class for AsyncEvents without data */ var VoidAsyncEvent = /** @class */ (function (_super) { __extends(VoidAsyncEvent, _super); function VoidAsyncEvent() { return _super !== null && _super.apply(this, arguments) || this; } /** * Send the AsyncEvent. */ VoidAsyncEvent.prototype.post = function () { _super.prototype.post.call(this, undefined); }; return VoidAsyncEvent; }(AsyncEvent)); exports.VoidAsyncEvent = VoidAsyncEvent; /** * Similar to 'error' event on EventEmitter: throws when a post() occurs while no handlers set. */ var ErrorAsyncEvent = /** @class */ (function (_super) { __extends(ErrorAsyncEvent, _super); function ErrorAsyncEvent() { return _super !== null && _super.apply(this, arguments) || this; } ErrorAsyncEvent.prototype.post = function (data) { if (this.listenerCount() === 0) { throw new Error("error event posted while no listeners attached. Error: " + data.message); } _super.prototype.post.call(this, data); }; return ErrorAsyncEvent; }(AsyncEvent)); exports.ErrorAsyncEvent = ErrorAsyncEvent; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN5bmMtZXZlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL2FzeW5jLWV2ZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDZEQUE2RDtBQUM3RCxlQUFlO0FBRWYsWUFBWSxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7O0FBRWIsMkNBQTJEO0FBQzNELDJDQUEyQztBQWEzQzs7Ozs7R0FLRztBQUNIO0lBQW1DLDhCQUFZO0lBdUQzQzs7OztPQUlHO0lBQ0gsb0JBQVksSUFBeUI7UUFBekIscUJBQUEsRUFBQSxTQUF5QjtRQUFyQyxZQUNJLGlCQUFPLFNBT1Y7UUE3Q08sYUFBTyxHQUFZLEtBQUssQ0FBQztRQXVDN0IsS0FBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFDcEIsSUFBSSxPQUFPLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUyxFQUFFO1lBQ3JDLEtBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztTQUNwQzthQUFNO1lBQ0gsS0FBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7U0FDM0I7O0lBQ0wsQ0FBQztJQWhFRCxzQkFBVywyQ0FBbUI7UUFIOUI7O1dBRUc7YUFDSDtZQUNJLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUU7Z0JBQ3pCLDREQUE0RDtnQkFDNUQsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksMEJBQWEsRUFBRSxDQUFDO2FBQ2hEO1lBQ0QsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUM7UUFDbEMsQ0FBQzs7O09BQUE7SUFpQkQ7O09BRUc7SUFDVywyQkFBZ0IsR0FBOUIsVUFBK0IsUUFBb0I7UUFDL0MsMkJBQTJCO1FBQzNCLElBQUksT0FBTyxNQUFNLEtBQUssV0FBVyxFQUFFO1lBQy9CLCtDQUErQztZQUMvQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQzNCO2FBQU07WUFDSCxVQUFVO1lBQ1YsWUFBWSxDQUFDLFFB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R0E2SjNDO0FBN0pZLGdDQUFVO0FBK0p2Qjs7R0FFRztBQUNIO0lBQW9DLGtDQUFnQjtJQUFwRDs7SUFRQSxDQUFDO0lBTkc7O09BRUc7SUFDSSw2QkFBSSxHQUFYO1FBQ0ksaUJBQU0sSUFBSSxZQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzFCLENBQUM7SUFDTCxxQkFBQztBQUFELENBQUMsQUFSRCxDQUFvQyxVQUFVLEdBUTdDO0FBUlksd0NBQWM7QUFVM0I7O0dBRUc7QUFDSDtJQUFxQyxtQ0FBaUI7SUFBdEQ7O0lBUUEsQ0FBQztJQU5VLDhCQUFJLEdBQVgsVUFBWSxJQUFXO1FBQ25CLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRSxLQUFLLENBQUMsRUFBRTtZQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLDREQUEwRCxJQUFJLENBQUMsT0FBUyxDQUFDLENBQUM7U0FDN0Y7UUFDRCxpQkFBTSxJQUFJLFlBQUMsSUFBSSxDQUFDLENBQUM7SUFDckIsQ0FBQztJQUNMLHNCQUFDO0FBQUQsQ0FBQyxBQVJELENBQXFDLFVBQVUsR0FROUM7QUFSWSwwQ0FBZSIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCDCqSAyMDE1IFJvZ2llciBTY2hvdXRlbjxnaXRodWJAd29ya2luZ2NvZGUubmluamE+XG4vLyBMaWNlbnNlOiBJU0NcblxuJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQge0Jhc2VFdmVudCwgUG9zdGFibGUsIExpc3RlbmVyfSBmcm9tICcuL2Jhc2UtZXZlbnQnO1xuaW1wb3J0IHtWb2lkU3luY0V2ZW50fSBmcm9tICcuL3N5bmMtZXZlbnQnO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIHRoZSBBc3luY0V2ZW50IGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXN5bmNFdmVudE9wdHMge1xuICAgIC8qKlxuICAgICAqIENvbmRlbnNlIG11bHRpcGxlIGNhbGxzIHRvIHBvc3QoKSBpbnRvIG9uZSB3aGlsZSB0aGUgcHJldmlvdXMgb25lXG4gICAgICogaGFzIG5vdCBiZWVuIGhhbmRsZWQgeWV0LlxuICAgICAqL1xuICAgIGNvbmRlbnNlZD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogQS1zeW5jaHJvbm91cyBldmVudC4gSGFuZGxlcnMgYXJlIGNhbGxlZCBpbiB0aGUgbmV4dCBOb2RlLkpTIGN5Y2xlLlxuICogLSBPcHRpb25hbGx5IGNvbmRlbnNlcyBtdWx0aXBsZSBwb3N0KCkgY2FsbHMgaW50byBvbmUgKHRoZSBsYXN0IHBvc3QoKSBnZXRzIHRocm91Z2gpXG4gKiAtIEhhbmRsZXJzIGFyZSBjYWxsZWQgb25seSBmb3IgZXZlbnRzIHBvc3RlZCBhZnRlciB0aGV5IHdlcmUgYXR0YWNoZWQuXG4gKiAtIEhhbmRsZXJzIGFyZSBub3QgY2FsbGVkIGFueW1vcmUgd2hlbiB0aGV5IGFyZSBkZXRhY2hlZCwgZXZlbiBpZiBhIHBvc3QoKSBpcyBpbiBwcm9ncmVzc1xuICovXG5leHBvcnQgY2xhc3MgQXN5bmNFdmVudDxUPiBleHRlbmRzIEJhc2VFdmVudDxUPiBpbXBsZW1lbnRzIFBvc3RhYmxlPFQ+IHtcbiAgICAvKipcbiAgICAgKiBTZW50IHdoZW4gc29tZW9uZSBhdHRhY2hlcyBvciBkZXRhY2hlc1xuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgZXZ0TGlzdGVuZXJzQ2hhbmdlZCgpOiBWb2lkU3luY0V2ZW50IHtcbiAgICAgICAgaWYgKCF0aGlzLl9saXN0ZW5lcnNDaGFuZ2VkKSB7XG4gICAgICAgICAgICAvLyBuZWVkIHRvIGRlbGF5LWxvYWQgdG8gYXZvaWQgc3RhY2sgb3ZlcmZsb3cgaW4gY29uc3RydWN0b3JcbiAgICAgICAgICAgIHRoaXMuX2xpc3RlbmVyc0NoYW5nZWQgPSBuZXcgVm9pZFN5bmNFdmVudCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9saXN0ZW5lcnNDaGFuZ2VkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV2ZW50IGZvciBsaXN0ZW5pbmcgdG8gbGlzdGVuZXIgY291bnRcbiAgICAgKi9cbiAgICBwcml2YXRlIF9saXN0ZW5lcnNDaGFuZ2VkPzogVm9pZFN5bmNFdmVudDtcblxuICAgIC8qKlxuICAgICAqIFVzZWQgaW50ZXJuYWxseSAtIHRoZSBleGFjdCBvcHRpb25zIG9iamVjdCBnaXZlbiB0byBjb25zdHJ1Y3RvclxuICAgICAqL1xuICAgIHB1YmxpYyBvcHRpb25zOiBBc3luY0V2ZW50T3B0cztcblxuICAgIHByaXZhdGUgX2NvbmRlbnNlZDogYm9vbGVhbjtcbiAgICBwcml2YXRlIF9xdWV1ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBwcml2YXRlIF9xdWV1ZWRMaXN0ZW5lcnM6IExpc3RlbmVyPFQ+W107XG4gICAgcHJpdmF0ZSBfcXVldWVkRGF0YTogYW55W107XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZGVmYXVsdCBzY2hlZHVsZXIgdXNlcyBzZXRJbW1lZGlhdGUoKSBvciBzZXRUaW1lb3V0KC4uLiwgMCkgaWYgc2V0SW1tZWRpYXRlIGlzIG5vdCBhdmFpbGFibGUuXG4gICAgICovXG4gICAgcHVibGljIHN0YXRpYyBkZWZhdWx0U2NoZWR1bGVyKGNhbGxiYWNrOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICAqL1xuICAgICAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIC8vIGJyb3dzZXJzIGRvbid0IGFsd2F5cyBzdXBwb3J0IHNldEltbWVkaWF0ZSgpXG4gICAgICAgICAgICBzZXRUaW1lb3V0KGNhbGxiYWNrLCAwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIG5vZGUuanNcbiAgICAgICAgICAgIHNldEltbWVkaWF0ZShjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgY3VycmVudCBzY2hlZHVsZXJcbiAgICAgKi9cbiAgICBwcml2YXRlIHN0YXRpYyBfc2NoZWR1bGVyOiAoY2FsbGJhY2s6ICgpID0+IHZvaWQpID0+IHZvaWQgPSBBc3luY0V2ZW50LmRlZmF1bHRTY2hlZHVsZXI7XG5cbiAgICAvKipcbiAgICAgKiBCeSBkZWZhdWx0LCBBc3luY0V2ZW50IHVzZXMgc2V0SW1tZWRpYXRlKCkgdG8gc2NoZWR1bGUgZXZlbnQgaGFuZGxlciBpbnZvY2F0aW9uLlxuICAgICAqIFlvdSBjYW4gY2hhbmdlIHRoaXMgZm9yIGUuZy4gc2V0VGltZW91dCguLi4sIDApIGJ5IGNhbGxpbmcgdGhpcyBzdGF0aWMgbWV0aG9kIG9uY2UuXG4gICAgICogQHBhcmFtIHNjaGVkdWxlciBBIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYSBjYWxsYmFjayBhbmQgZXhlY3V0ZXMgaXQgaW4gdGhlIG5leHQgTm9kZS5KUyBjeWNsZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIHNldFNjaGVkdWxlcihzY2hlZHVsZXI6IChjYWxsYmFjazogKCkgPT4gdm9pZCkgPT4gdm9pZCk6IHZvaWQge1xuICAgICAgICBBc3luY0V2ZW50Ll9zY2hlZHVsZXIgPSBzY2hlZHVsZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0gb3B0cyBPcHRpb25hbC4gVmFyaW91cyBzZXR0aW5nczpcbiAgICAgKiAgICAgICAgICAgICAtIGNvbmRlbnNlZDogYSBCb29sZWFuIGluZGljYXRpbmcgd2hldGhlciB0byBjb25kZW5zZSBtdWx0aXBsZSBwb3N0KCkgY2FsbHMgd2l0aGluIHRoZSBzYW1lIGN5Y2xlLlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG9wdHM6IEFzeW5jRXZlbnRPcHRzID0ge30pIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cztcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRzLmNvbmRlbnNlZCA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICB0aGlzLl9jb25kZW5zZWQgPSBvcHRzLmNvbmRlbnNlZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2NvbmRlbnNlZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VuZCB0aGUgQXN5bmNFdmVudC4gSGFuZGxlcnMgYXJlIGNhbGxlZCBpbiB0aGUgbmV4dCBOb2RlLkpTIGN5Y2xlLlxuICAgICAqL1xuICAgIHB1YmxpYyBwb3N0KGRhdGE6IFQpOiB2b2lkO1xuICAgIHB1YmxpYyBwb3N0KC4uLmFyZ3M6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5fbGlzdGVuZXJzIHx8IHRoaXMuX2xpc3RlbmVycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5fY29uZGVuc2VkKSB7XG4gICAgICAgICAgICB0aGlzLl9xdWV1ZWREYXRhID0gYXJncztcbiAgICAgICAgICAgIHRoaXMuX3F1ZXVlZExpc3RlbmVycyA9IHRoaXMuX2xpc3RlbmVycztcbiAgICAgICAgICAgIGlmICh0aGlzLl9xdWV1ZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX3F1ZXVlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgQXN5bmNFdmVudC5fc2NoZWR1bGVyKCgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICAgICAgLy8gaW1tZWRpYXRlbHkgbWFyayBub24tcXVldWVkIHRvIGFsbG93IG5ldyBBc3luY0V2ZW50IHRvIGhhcHBlbiBhcyByZXN1bHRcbiAgICAgICAgICAgICAgICAgICAgLy8gb2YgY2FsbGluZyBoYW5kbGVyc1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9xdWV1ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgLy8gY2FjaGUgbGlzdGVuZXJzIGFuZCBkYXRhIGJlY2F1c2UgdGhleSBtaWdodCBjaGFuZ2Ugd2hpbGUgY2FsbGluZyBldmVudCBoYW5kbGVyc1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gdGhpcy5fcXVldWVkRGF0YTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGlzdGVuZXJzID0gdGhpcy5fcXVldWVkTGlzdGVuZXJzO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jYWxsKGxpc3RlbmVyLCBkYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgeyAvLyBub3QgY29uZGVuc2VkXG4gICAgICAgICAgICBjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnM7XG4gICAgICAgICAgICBBc3luY0V2ZW50Ll9zY2hlZHVsZXIoKCk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpc3RlbmVyID0gbGlzdGVuZXJzW2ldO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jYWxsKGxpc3RlbmVyLCBhcmdzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGluaGVyaXRlZFxuICAgIHByb3RlY3RlZCBfY2FsbChsaXN0ZW5lcjogTGlzdGVuZXI8VD4sIGFyZ3M6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIC8vIHBlcmZvcm1hbmNlIG9wdGltaXphdGlvbjogZG9uJ3QgdXNlIGNvbnNlY3V0aXZlIG5vZGVqcyBjeWNsZXNcbiAgICAgICAgLy8gZm9yIGFzeW5jZXZlbnRzIGF0dGFjaGVkIHRvIGFzeW5jZXZlbnRzXG4gICAgICAgIGlmIChsaXN0ZW5lci5ldmVudCAmJiBsaXN0ZW5lci5ldmVudCBpbnN0YW5jZW9mIEFzeW5jRXZlbnQpIHtcbiAgICAgICAgICAgICg8QXN5bmNFdmVudDxUPj5saXN0ZW5lci5ldmVudCkuX3Bvc3REaXJlY3QoYXJncyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdXBlci5fY2FsbChsaXN0ZW5lciwgYXJncyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtYW5jZSBvcHRpbWl6YXRpb246IGlmIHRoaXMgYXN5bmMgc2lnbmFsIGlzIGF0dGFjaGVkIHRvIGFub3RoZXJcbiAgICAgKiBhc3luYyBzaWduYWwsIHdlJ3JlIGFscmVhZHkgYSB0aGUgbmV4dCBjeWNsZSBhbmQgd2UgY2FuIGNhbGwgbGlzdGVuZXJzXG4gICAgICogZGlyZWN0bHlcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgX3Bvc3REaXJlY3QoYXJnczogYW55W10pOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLl9saXN0ZW5lcnMgfHwgdGhpcy5fbGlzdGVuZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNvcHkgYSByZWZlcmVuY2UgdG8gdGhlIGFycmF5IGJlY2F1c2UgdGhpcy5fbGlzdGVuZXJzIG1pZ2h0IGJlIHJlcGxhY2VkIGR1cmluZ1xuICAgICAgICAvLyB0aGUgaGFuZGxlciBjYWxsc1xuICAgICAgICBjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnM7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICBjb25zdCBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpXTtcbiAgICAgICAgICAgIHRoaXMuX2NhbGwobGlzdGVuZXIsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIEBpbmhlcml0ZG9jICovXG4gICAgcHJvdGVjdGVkIF9hdHRhY2goYTogKChkYXRhOiBUKSA9PiB2b2lkKSB8IE9iamVjdCB8IFBvc3RhYmxlPFQ+LCBiOiAoKGRhdGE6IFQpID0+IHZvaWQpIHwgdW5kZWZpbmVkLCBvbmNlOiBib29sZWFuKTogKCkgPT4gdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvdW50ID0gdGhpcy5fbGlzdGVuZXJzPy5sZW5ndGggPz8gMDtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gc3VwZXIuX2F0dGFjaChhLCBiLCBvbmNlKTtcbiAgICAgICAgaWYgKHRoaXMuZXZ0TGlzdGVuZXJzQ2hhbmdlZCAmJiBjb3VudCAhPT0gKHRoaXMuX2xpc3RlbmVycz8ubGVuZ3RoID8/IDApKSB7XG4gICAgICAgICAgICB0aGlzLmV2dExpc3RlbmVyc0NoYW5nZWQucG9zdCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqIEBpbmhlcml0ZG9jICovXG4gICAgcHJvdGVjdGVkIF9kZXRhY2goLi4uYXJnczogYW55W10pOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY291bnQgPSB0aGlzLl9saXN0ZW5lcnM/Lmxlbmd0aCA/PyAwO1xuICAgICAgICBjb25zdCByZXN1bHQgPSBzdXBlci5fZGV0YWNoKC4uLmFyZ3MpO1xuICAgICAgICBpZiAodGhpcy5ldnRMaXN0ZW5lcnNDaGFuZ2VkICYmIGNvdW50ICE9PSAodGhpcy5fbGlzdGVuZXJzPy5sZW5ndGggPz8gMCkpIHtcbiAgICAgICAgICAgIHRoaXMuZXZ0TGlzdGVuZXJzQ2hhbmdlZC5wb3N0KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG59XG5cbi8qKlxuICogQ29udmVuaWVuY2UgY2xhc3MgZm9yIEFzeW5jRXZlbnRzIHdpdGhvdXQgZGF0YVxuICovXG5leHBvcnQgY2xhc3MgVm9pZEFzeW5jRXZlbnQgZXh0ZW5kcyBBc3luY0V2ZW50PHZvaWQ+IHtcblxuICAgIC8qKlxuICAgICAqIFNlbmQgdGhlIEFzeW5jRXZlbnQuXG4gICAgICovXG4gICAgcHVibGljIHBvc3QoKTogdm9pZCB7XG4gICAgICAgIHN1cGVyLnBvc3QodW5kZWZpbmVkKTtcbiAgICB9XG59XG5cbi8qKlxuICogU2ltaWxhciB0byAnZXJyb3InIGV2ZW50IG9uIEV2ZW50RW1pdHRlcjogdGhyb3dzIHdoZW4gYSBwb3N0KCkgb2NjdXJzIHdoaWxlIG5vIGhhbmRsZXJzIHNldC5cbiAqL1xuZXhwb3J0IGNsYXNzIEVycm9yQXN5bmNFdmVudCBleHRlbmRzIEFzeW5jRXZlbnQ8RXJyb3I+IHtcblxuICAgIHB1YmxpYyBwb3N0KGRhdGE6IEVycm9yKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmxpc3RlbmVyQ291bnQoKSA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBlcnJvciBldmVudCBwb3N0ZWQgd2hpbGUgbm8gbGlzdGVuZXJzIGF0dGFjaGVkLiBFcnJvcjogJHtkYXRhLm1lc3NhZ2V9YCk7XG4gICAgICAgIH1cbiAgICAgICAgc3VwZXIucG9zdChkYXRhKTtcbiAgICB9XG59XG4iXX0=