UNPKG

@jokio/ts-events

Version:

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

214 lines 22 kB
// Copyright © 2015 Rogier Schouten<github@workingcode.ninja> // License: ISC 'use strict'; var __extends = (this && this.__extends) || (function () { var 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 function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t; return { next: verb(0), "throw": verb(1), "return": verb(2) }; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [0, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); var base_event_1 = require("./base-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 = (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) { var _this = _super.call(this) || this; _this._queued = false; _this.options = opts; var options = opts || {}; if (typeof options.condensed === 'boolean') { _this._condensed = options.condensed; } else { _this._condensed = false; } return _this; } /** * 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 { 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) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { // 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); } return [2 /*return*/]; }); }); }; /** * 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); } }; return AsyncEvent; }(base_event_1.BaseEvent)); /** * The current scheduler */ AsyncEvent._scheduler = AsyncEvent.defaultScheduler; exports.AsyncEvent = AsyncEvent; /** * Convenience class for AsyncEvents without data */ var VoidAsyncEvent = (function (_super) { __extends(VoidAsyncEvent, _super); function VoidAsyncEvent() { return _super !== null && _super.apply(this, arguments) || this; } /** * Send the AsyncEvent. */ VoidAsyncEvent.prototype.post = function () { return _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 = (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); } return _super.prototype.post.call(this, data); }; return ErrorAsyncEvent; }(AsyncEvent)); exports.ErrorAsyncEvent = ErrorAsyncEvent; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN5bmMtZXZlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL2FzeW5jLWV2ZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDZEQUE2RDtBQUM3RCxlQUFlO0FBRWYsWUFBWSxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUViLDJDQUE2RDtBQWE3RDs7Ozs7R0FLRztBQUNIO0lBQW1DLDhCQUFZO0lBd0MzQzs7OztPQUlHO0lBQ0gsb0JBQVksSUFBcUI7UUFBakMsWUFDSSxpQkFBTyxTQVFWO1FBOUNPLGFBQU8sR0FBWSxLQUFLLENBQUM7UUF1QzdCLEtBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO1FBQ3BCLElBQU0sT0FBTyxHQUFtQixJQUFJLElBQUksRUFBRSxDQUFDO1FBQzNDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sT0FBTyxDQUFDLFNBQVMsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDO1lBQ3pDLEtBQUksQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQztRQUN4QyxDQUFDO1FBQUMsSUFBSSxDQUFDLENBQUM7WUFDSixLQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztRQUM1QixDQUFDOztJQUNMLENBQUM7SUExQ0Q7O09BRUc7SUFDVywyQkFBZ0IsR0FBOUIsVUFBK0IsUUFBb0I7UUFDL0MsMkJBQTJCO1FBQzNCLEVBQUUsQ0FBQyxDQUFDLE9BQU8sTUFBTSxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUM7WUFDaEMsK0NBQStDO1lBQy9DLFVBQVUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDNUIsQ0FBQztRQUFDLElBQUksQ0FBQyxDQUFDO1lBQ0osVUFBVTtZQUNWLFlBQVksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMzQixDQUFDO0lBQ0wsQ0FBQztJQU9EOzs7O09BSUc7SUFDVyx1QkFBWSxHQUExQixVQUEyQixT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MjAxNSBSb2dpZXIgU2Nob3V0ZW48Z2l0aHViQHdvcmtpbmdjb2RlLm5pbmphPlxuLy8gTGljZW5zZTogSVNDXG5cbid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgQmFzZUV2ZW50LCBQb3N0YWJsZSwgTGlzdGVuZXIgfSBmcm9tICcuL2Jhc2UtZXZlbnQnO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIHRoZSBBc3luY0V2ZW50IGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXN5bmNFdmVudE9wdHMge1xuICAgIC8qKlxuICAgICAqIENvbmRlbnNlIG11bHRpcGxlIGNhbGxzIHRvIHBvc3QoKSBpbnRvIG9uZSB3aGlsZSB0aGUgcHJldmlvdXMgb25lXG4gICAgICogaGFzIG5vdCBiZWVuIGhhbmRsZWQgeWV0LlxuICAgICAqL1xuICAgIGNvbmRlbnNlZD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogQS1zeW5jaHJvbm91cyBldmVudC4gSGFuZGxlcnMgYXJlIGNhbGxlZCBpbiB0aGUgbmV4dCBOb2RlLkpTIGN5Y2xlLlxuICogLSBPcHRpb25hbGx5IGNvbmRlbnNlcyBtdWx0aXBsZSBwb3N0KCkgY2FsbHMgaW50byBvbmUgKHRoZSBsYXN0IHBvc3QoKSBnZXRzIHRocm91Z2gpXG4gKiAtIEhhbmRsZXJzIGFyZSBjYWxsZWQgb25seSBmb3IgZXZlbnRzIHBvc3RlZCBhZnRlciB0aGV5IHdlcmUgYXR0YWNoZWQuXG4gKiAtIEhhbmRsZXJzIGFyZSBub3QgY2FsbGVkIGFueW1vcmUgd2hlbiB0aGV5IGFyZSBkZXRhY2hlZCwgZXZlbiBpZiBhIHBvc3QoKSBpcyBpbiBwcm9ncmVzc1xuICovXG5leHBvcnQgY2xhc3MgQXN5bmNFdmVudDxUPiBleHRlbmRzIEJhc2VFdmVudDxUPiBpbXBsZW1lbnRzIFBvc3RhYmxlPFQ+IHtcblxuICAgIC8qKlxuICAgICAqIFVzZWQgaW50ZXJuYWxseSAtIHRoZSBleGFjdCBvcHRpb25zIG9iamVjdCBnaXZlbiB0byBjb25zdHJ1Y3RvclxuICAgICAqL1xuICAgIHB1YmxpYyBvcHRpb25zOiBBc3luY0V2ZW50T3B0cztcblxuICAgIHByaXZhdGUgX2NvbmRlbnNlZDogYm9vbGVhbjtcbiAgICBwcml2YXRlIF9xdWV1ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBwcml2YXRlIF9xdWV1ZWRMaXN0ZW5lcnM6IExpc3RlbmVyPFQ+W107XG4gICAgcHJpdmF0ZSBfcXVldWVkRGF0YTogYW55W107XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZGVmYXVsdCBzY2hlZHVsZXIgdXNlcyBzZXRJbW1lZGlhdGUoKSBvciBzZXRUaW1lb3V0KC4uLiwgMCkgaWYgc2V0SW1tZWRpYXRlIGlzIG5vdCBhdmFpbGFibGUuXG4gICAgICovXG4gICAgcHVibGljIHN0YXRpYyBkZWZhdWx0U2NoZWR1bGVyKGNhbGxiYWNrOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICAqL1xuICAgICAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIC8vIGJyb3dzZXJzIGRvbid0IGFsd2F5cyBzdXBwb3J0IHNldEltbWVkaWF0ZSgpXG4gICAgICAgICAgICBzZXRUaW1lb3V0KGNhbGxiYWNrLCAwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIG5vZGUuanNcbiAgICAgICAgICAgIHNldEltbWVkaWF0ZShjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgY3VycmVudCBzY2hlZHVsZXJcbiAgICAgKi9cbiAgICBwcml2YXRlIHN0YXRpYyBfc2NoZWR1bGVyOiAoY2FsbGJhY2s6ICgpID0+IHZvaWQpID0+IHZvaWQgPSBBc3luY0V2ZW50LmRlZmF1bHRTY2hlZHVsZXI7XG5cbiAgICAvKipcbiAgICAgKiBCeSBkZWZhdWx0LCBBc3luY0V2ZW50IHVzZXMgc2V0SW1tZWRpYXRlKCkgdG8gc2NoZWR1bGUgZXZlbnQgaGFuZGxlciBpbnZvY2F0aW9uLlxuICAgICAqIFlvdSBjYW4gY2hhbmdlIHRoaXMgZm9yIGUuZy4gc2V0VGltZW91dCguLi4sIDApIGJ5IGNhbGxpbmcgdGhpcyBzdGF0aWMgbWV0aG9kIG9uY2UuXG4gICAgICogQHBhcmFtIHNjaGVkdWxlciBBIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYSBjYWxsYmFjayBhbmQgZXhlY3V0ZXMgaXQgaW4gdGhlIG5leHQgTm9kZS5KUyBjeWNsZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIHNldFNjaGVkdWxlcihzY2hlZHVsZXI6IChjYWxsYmFjazogKCkgPT4gdm9pZCkgPT4gdm9pZCk6IHZvaWQge1xuICAgICAgICBBc3luY0V2ZW50Ll9zY2hlZHVsZXIgPSBzY2hlZHVsZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0gb3B0cyBPcHRpb25hbC4gVmFyaW91cyBzZXR0aW5nczpcbiAgICAgKiAgICAgICAgICAgICAtIGNvbmRlbnNlZDogYSBCb29sZWFuIGluZGljYXRpbmcgd2hldGhlciB0byBjb25kZW5zZSBtdWx0aXBsZSBwb3N0KCkgY2FsbHMgd2l0aGluIHRoZSBzYW1lIGN5Y2xlLlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG9wdHM/OiBBc3luY0V2ZW50T3B0cykge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSBvcHRzO1xuICAgICAgICBjb25zdCBvcHRpb25zOiBBc3luY0V2ZW50T3B0cyA9IG9wdHMgfHwge307XG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5jb25kZW5zZWQgPT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgdGhpcy5fY29uZGVuc2VkID0gb3B0aW9ucy5jb25kZW5zZWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9jb25kZW5zZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmQgdGhlIEFzeW5jRXZlbnQuIEhhbmRsZXJzIGFyZSBjYWxsZWQgaW4gdGhlIG5leHQgTm9kZS5KUyBjeWNsZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgcG9zdChkYXRhOiBUKTogUHJvbWlzZTx2b2lkPjtcbiAgICBwdWJsaWMgcG9zdCguLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAoIXRoaXMuX2xpc3RlbmVycyB8fCB0aGlzLl9saXN0ZW5lcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX2NvbmRlbnNlZCkge1xuICAgICAgICAgICAgdGhpcy5fcXVldWVkRGF0YSA9IGFyZ3M7XG4gICAgICAgICAgICB0aGlzLl9xdWV1ZWRMaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnM7XG4gICAgICAgICAgICBpZiAodGhpcy5fcXVldWVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9xdWV1ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIEFzeW5jRXZlbnQuX3NjaGVkdWxlcigoKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGltbWVkaWF0ZWx5IG1hcmsgbm9uLXF1ZXVlZCB0byBhbGxvdyBuZXcgQXN5bmNFdmVudCB0byBoYXBwZW4gYXMgcmVzdWx0XG4gICAgICAgICAgICAgICAgICAgIC8vIG9mIGNhbGxpbmcgaGFuZGxlcnNcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcXVldWVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIC8vIGNhY2hlIGxpc3RlbmVycyBhbmQgZGF0YSBiZWNhdXNlIHRoZXkgbWlnaHQgY2hhbmdlIHdoaWxlIGNhbGxpbmcgZXZlbnQgaGFuZGxlcnNcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IHRoaXMuX3F1ZXVlZERhdGE7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpc3RlbmVycyA9IHRoaXMuX3F1ZXVlZExpc3RlbmVycztcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpc3RlbmVyID0gbGlzdGVuZXJzW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY2FsbChsaXN0ZW5lciwgZGF0YSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHsgLy8gbm90IGNvbmRlbnNlZFxuICAgICAgICAgICAgY29uc3QgbGlzdGVuZXJzID0gdGhpcy5fbGlzdGVuZXJzO1xuICAgICAgICAgICAgQXN5bmNFdmVudC5fc2NoZWR1bGVyKCgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fY2FsbChsaXN0ZW5lciwgYXJncyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBpbmhlcml0ZWRcbiAgICBwcm90ZWN0ZWQgYXN5bmMgX2NhbGwobGlzdGVuZXI6IExpc3RlbmVyPFQ+LCBhcmdzOiBhbnlbXSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICAvLyBwZXJmb3JtYW5jZSBvcHRpbWl6YXRpb246IGRvbid0IHVzZSBjb25zZWN1dGl2ZSBub2RlanMgY3ljbGVzXG4gICAgICAgIC8vIGZvciBhc3luY2V2ZW50cyBhdHRhY2hlZCB0byBhc3luY2V2ZW50c1xuICAgICAgICBpZiAobGlzdGVuZXIuZXZlbnQgJiYgbGlzdGVuZXIuZXZlbnQgaW5zdGFuY2VvZiBBc3luY0V2ZW50KSB7XG4gICAgICAgICAgICAoPEFzeW5jRXZlbnQ8VD4+bGlzdGVuZXIuZXZlbnQpLl9wb3N0RGlyZWN0KGFyZ3MpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3VwZXIuX2NhbGwobGlzdGVuZXIsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGVyZm9ybWFuY2Ugb3B0aW1pemF0aW9uOiBpZiB0aGlzIGFzeW5jIHNpZ25hbCBpcyBhdHRhY2hlZCB0byBhbm90aGVyXG4gICAgICogYXN5bmMgc2lnbmFsLCB3ZSdyZSBhbHJlYWR5IGEgdGhlIG5leHQgY3ljbGUgYW5kIHdlIGNhbiBjYWxsIGxpc3RlbmVyc1xuICAgICAqIGRpcmVjdGx5XG4gICAgICovXG4gICAgcHJvdGVjdGVkIF9wb3N0RGlyZWN0KGFyZ3M6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5fbGlzdGVuZXJzIHx8IHRoaXMuX2xpc3RlbmVycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBjb3B5IGEgcmVmZXJlbmNlIHRvIHRoZSBhcnJheSBiZWNhdXNlIHRoaXMuX2xpc3RlbmVycyBtaWdodCBiZSByZXBsYWNlZCBkdXJpbmdcbiAgICAgICAgLy8gdGhlIGhhbmRsZXIgY2FsbHNcbiAgICAgICAgY29uc3QgbGlzdGVuZXJzID0gdGhpcy5fbGlzdGVuZXJzO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgY29uc3QgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG4gICAgICAgICAgICB0aGlzLl9jYWxsKGxpc3RlbmVyLCBhcmdzKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBDb252ZW5pZW5jZSBjbGFzcyBmb3IgQXN5bmNFdmVudHMgd2l0aG91dCBkYXRhXG4gKi9cbmV4cG9ydCBjbGFzcyBWb2lkQXN5bmNFdmVudCBleHRlbmRzIEFzeW5jRXZlbnQ8dm9pZD4ge1xuXG4gICAgLyoqXG4gICAgICogU2VuZCB0aGUgQXN5bmNFdmVudC5cbiAgICAgKi9cbiAgICBwdWJsaWMgcG9zdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHN1cGVyLnBvc3QodW5kZWZpbmVkKTtcbiAgICB9XG59XG5cbi8qKlxuICogU2ltaWxhciB0byAnZXJyb3InIGV2ZW50IG9uIEV2ZW50RW1pdHRlcjogdGhyb3dzIHdoZW4gYSBwb3N0KCkgb2NjdXJzIHdoaWxlIG5vIGhhbmRsZXJzIHNldC5cbiAqL1xuZXhwb3J0IGNsYXNzIEVycm9yQXN5bmNFdmVudCBleHRlbmRzIEFzeW5jRXZlbnQ8RXJyb3I+IHtcblxuICAgIHB1YmxpYyBwb3N0KGRhdGE6IEVycm9yKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICh0aGlzLmxpc3RlbmVyQ291bnQoKSA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBlcnJvciBldmVudCBwb3N0ZWQgd2hpbGUgbm8gbGlzdGVuZXJzIGF0dGFjaGVkLiBFcnJvcjogJHtkYXRhLm1lc3NhZ2V9YCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN1cGVyLnBvc3QoZGF0YSk7XG4gICAgfVxufVxuIl19