@omostan/ngx-idle
Version:
A module for responding to idle users in Angular applications. this is a forked version of the original @ng-Idle
380 lines • 39.9 kB
JavaScript
import { EventEmitter, Inject, Injectable, Optional, PLATFORM_ID } from '@angular/core';
import { Interrupt } from './interrupt';
import { LocalStorageExpiry } from './localstorageexpiry';
import * as i0 from "@angular/core";
import * as i1 from "./idleexpiry";
import * as i2 from "./keepalivesvc";
/*
* Indicates the desired auto resume behavior.
*/
export var AutoResume;
(function (AutoResume) {
/*
* Auto resume functionality will be disabled.
*/
AutoResume[AutoResume["disabled"] = 0] = "disabled";
/*
* Can resume automatically even if they are idle.
*/
AutoResume[AutoResume["idle"] = 1] = "idle";
/*
* Can only resume automatically if they are not yet idle.
*/
AutoResume[AutoResume["notIdle"] = 2] = "notIdle";
})(AutoResume || (AutoResume = {}));
/**
* A service for detecting and responding to user idleness.
*/
export class Idle {
constructor(expiry, zone, keepaliveSvc,
// eslint-disable-next-line @typescript-eslint/ban-types
platformId) {
this.expiry = expiry;
this.zone = zone;
this.platformId = platformId;
this.idle = 20 * 60; // in seconds
this.timeoutVal = 30; // in seconds
this.autoResume = AutoResume.idle;
this.interrupts = new Array();
this.running = false;
this.keepaliveEnabled = false;
this.onIdleStart = new EventEmitter();
this.onIdleEnd = new EventEmitter();
this.onTimeoutWarning = new EventEmitter();
this.onTimeout = new EventEmitter();
this.onInterrupt = new EventEmitter();
if (keepaliveSvc) {
this.keepaliveSvc = keepaliveSvc;
this.keepaliveEnabled = true;
}
this.setIdling(false);
}
/*
* Sets the idle name for localStorage.
* Important to set if multiple instances of Idle with LocalStorageExpiry
* @param The name of the idle.
*/
setIdleName(key) {
if (this.expiry instanceof LocalStorageExpiry) {
this.expiry.setIdleName(key);
}
else {
throw new Error('Cannot set expiry key name because no LocalStorageExpiry has been provided.');
}
}
/*
* Returns whether or not keepalive integration is enabled.
* @return True if integration is enabled; otherwise, false.
*/
getKeepaliveEnabled() {
return this.keepaliveEnabled;
}
/*
* Sets and returns whether or not keepalive integration is enabled.
* @param True if the integration is enabled; otherwise, false.
* @return The current value.
*/
setKeepaliveEnabled(value) {
if (!this.keepaliveSvc) {
throw new Error('Cannot enable keepalive integration because no KeepaliveSvc has been provided.');
}
return (this.keepaliveEnabled = value);
}
/*
* Returns the current timeout value.
* @return The timeout value in seconds.
*/
getTimeout() {
return this.timeoutVal;
}
/*
* Sets the timeout value.
* @param seconds - The timeout value in seconds. 0 or false to disable timeout feature.
* @return The current value. If disabled, the value will be 0.
*/
setTimeout(seconds) {
if (seconds === false) {
this.timeoutVal = 0;
}
else if (typeof seconds === 'number' && seconds >= 0) {
this.timeoutVal = seconds;
}
else {
throw new Error("'seconds' can only be 'false' or a positive number.");
}
return this.timeoutVal;
}
/*
* Returns the current idle value.
* @return The idle value in seconds.
*/
getIdle() {
return this.idle;
}
/*
* Sets the idle value.
* @param seconds - The idle value in seconds.
* @return The idle value in seconds.
*/
setIdle(seconds) {
if (seconds <= 0) {
throw new Error("'seconds' must be greater zero");
}
return (this.idle = seconds);
}
/*
* Returns the current autoresume value.
* @return The current value.
*/
getAutoResume() {
return this.autoResume;
}
setAutoResume(value) {
return (this.autoResume = value);
}
/*
* Sets interrupts from the specified sources.
* @param sources - Interrupt sources.
* @return The resulting interrupts.
*/
setInterrupts(sources) {
this.clearInterrupts();
const self = this;
for (const source of sources) {
const options = { platformId: this.platformId };
const sub = new Interrupt(source, options);
sub.subscribe((args) => {
self.interrupt(args.force, args.innerArgs);
});
this.interrupts.push(sub);
}
return this.interrupts;
}
/*
* Returns the current interrupts.
* @return The current interrupts.
*/
getInterrupts() {
return this.interrupts;
}
/*
* Pauses, unsubscribes, and clears the current interrupt subscriptions.
*/
clearInterrupts() {
for (const sub of this.interrupts) {
sub.pause();
sub.unsubscribe();
}
this.interrupts.length = 0;
}
/*
* Returns whether or not the service is running i.e. watching for idleness.
* @return True if service is watching; otherwise, false.
*/
isRunning() {
return this.running;
}
/*
* Returns whether or not the user is considered idle.
* @return True if the user is in the idle state; otherwise, false.
*/
isIdling() {
return this.idling;
}
/*
* Starts watching for inactivity.
*/
watch(skipExpiry) {
this.safeClearInterval('idleHandle');
this.safeClearInterval('timeoutHandle');
const timeout = !this.timeoutVal ? 0 : this.timeoutVal;
if (!skipExpiry) {
const value = new Date(this.expiry.now().getTime() + (this.idle + timeout) * 1000);
this.expiry.last(value);
}
if (this.idling) {
this.toggleState();
}
if (!this.running) {
this.startKeepalive();
this.toggleInterrupts(true);
}
this.running = true;
const watchFn = () => {
this.zone.run(() => {
const diff = this.getExpiryDiff(timeout);
if (diff > 0) {
this.safeClearInterval('idleHandle');
this.setIdleIntervalOutsideOfZone(watchFn, diff);
}
else {
this.toggleState();
}
});
};
this.setIdleIntervalOutsideOfZone(watchFn, this.idle * 1000);
}
/*
* Allows protractor tests to call waitForAngular without hanging
*/
setIdleIntervalOutsideOfZone(watchFn, frequency) {
this.zone.runOutsideAngular(() => {
this.idleHandle = setInterval(watchFn, frequency);
});
}
/*
* Stops watching for inactivity.
*/
stop() {
this.stopKeepalive();
this.toggleInterrupts(false);
this.safeClearInterval('idleHandle');
this.safeClearInterval('timeoutHandle');
this.setIdling(false);
this.running = false;
this.expiry.last(null);
}
/*
* Forces a timeout event and state.
*/
timeout() {
this.stopKeepalive();
this.toggleInterrupts(false);
this.safeClearInterval('idleHandle');
this.safeClearInterval('timeoutHandle');
this.setIdling(true);
this.running = false;
this.countdown = 0;
this.onTimeout.emit(null);
}
/*
* Signals that user activity has occurred.
* @param force - Forces watch to be called, unless they are timed out.
* @param eventArgs - Optional source event arguments.
*/
interrupt(force, eventArgs) {
if (!this.running) {
return;
}
if (this.timeoutVal && this.expiry.isExpired()) {
this.timeout();
return;
}
this.onInterrupt.emit(eventArgs);
if (force === true ||
this.autoResume === AutoResume.idle ||
(this.autoResume === AutoResume.notIdle && !this.expiry.idling())) {
this.watch(force);
}
}
setIdling(value) {
this.idling = value;
this.expiry.idling(value);
}
toggleState() {
this.setIdling(!this.idling);
if (this.idling) {
this.onIdleStart.emit(null);
this.stopKeepalive();
if (this.timeoutVal > 0) {
this.countdown = this.timeoutVal;
this.doCountdown();
this.setTimoutIntervalOutsideZone(() => {
this.doCountdownInZone();
}, 1000);
}
}
else {
this.toggleInterrupts(true);
this.onIdleEnd.emit(null);
this.startKeepalive();
}
this.safeClearInterval('idleHandle');
}
setTimoutIntervalOutsideZone(intervalFn, frequency) {
this.zone.runOutsideAngular(() => {
this.timeoutHandle = setInterval(() => {
intervalFn();
}, frequency);
});
}
toggleInterrupts(resume) {
for (const interrupt of this.interrupts) {
if (resume) {
interrupt.resume();
}
else {
interrupt.pause();
}
}
}
getExpiryDiff(timeout) {
const now = this.expiry.now();
const last = this.expiry.last() || now;
return last.getTime() - now.getTime() - timeout * 1000;
}
doCountdownInZone() {
this.zone.run(() => {
this.doCountdown();
});
}
doCountdown() {
const diff = this.getExpiryDiff(this.timeoutVal);
if (diff > 0) {
this.safeClearInterval('timeoutHandle');
this.interrupt(true);
return;
}
if (!this.idling) {
return;
}
if (this.countdown <= 0) {
this.timeout();
return;
}
this.onTimeoutWarning.emit(this.countdown);
this.countdown--;
}
safeClearInterval(handleName) {
const handle = this[handleName];
if (handle !== null && typeof handle !== 'undefined') {
clearInterval(this[handleName]);
this[handleName] = null;
}
}
startKeepalive() {
if (!this.keepaliveSvc || !this.keepaliveEnabled) {
return;
}
if (this.running) {
this.keepaliveSvc.ping();
}
this.keepaliveSvc.start();
}
stopKeepalive() {
if (!this.keepaliveSvc || !this.keepaliveEnabled) {
return;
}
this.keepaliveSvc.stop();
}
/*
* Called by Angular when destroying the instance.
*/
ngOnDestroy() {
this.stop();
this.clearInterrupts();
}
}
Idle.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: Idle, deps: [{ token: i1.IdleExpiry }, { token: i0.NgZone }, { token: i2.KeepaliveSvc, optional: true }, { token: PLATFORM_ID, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
Idle.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: Idle });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: Idle, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i1.IdleExpiry }, { type: i0.NgZone }, { type: i2.KeepaliveSvc, decorators: [{
type: Optional
}] }, { type: Object, decorators: [{
type: Optional
}, {
type: Inject,
args: [PLATFORM_ID]
}] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWRsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2NvcmUvc3JjL2xpYi9pZGxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxZQUFZLEVBQ1osTUFBTSxFQUNOLFVBQVUsRUFHVixRQUFRLEVBQ1IsV0FBVyxFQUNaLE1BQU0sZUFBZSxDQUFDO0FBR3ZCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFJeEMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7Ozs7QUFFMUQ7O0dBRUc7QUFDSCxNQUFNLENBQU4sSUFBWSxVQWFYO0FBYkQsV0FBWSxVQUFVO0lBQ3BCOztPQUVHO0lBQ0gsbURBQVEsQ0FBQTtJQUNSOztPQUVHO0lBQ0gsMkNBQUksQ0FBQTtJQUNKOztPQUVHO0lBQ0gsaURBQU8sQ0FBQTtBQUNULENBQUMsRUFiVyxVQUFVLEtBQVYsVUFBVSxRQWFyQjtBQUVEOztHQUVHO0FBRUgsTUFBTSxPQUFPLElBQUk7SUFxQmYsWUFDVSxNQUFrQixFQUNsQixJQUFZLEVBQ1IsWUFBMkI7SUFDdkMsd0RBQXdEO0lBQ2YsVUFBbUI7UUFKcEQsV0FBTSxHQUFOLE1BQU0sQ0FBWTtRQUNsQixTQUFJLEdBQUosSUFBSSxDQUFRO1FBR3FCLGVBQVUsR0FBVixVQUFVLENBQVM7UUF6QnRELFNBQUksR0FBVyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsYUFBYTtRQUNyQyxlQUFVLEdBQUcsRUFBRSxDQUFDLENBQUMsYUFBYTtRQUM5QixlQUFVLEdBQWUsVUFBVSxDQUFDLElBQUksQ0FBQztRQUN6QyxlQUFVLEdBQXFCLElBQUksS0FBSyxFQUFFLENBQUM7UUFDM0MsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUtoQixxQkFBZ0IsR0FBRyxLQUFLLENBQUM7UUFHMUIsZ0JBQVcsR0FBc0IsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUNwRCxjQUFTLEdBQXNC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RTtZQUNoRCxPQUFPO1NBQ1I7UUFFRCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRDs7T0FFRztJQUNILFdBQVc7UUFDVCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDWixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDekIsQ0FBQzs7aUdBL1pVLElBQUksOEdBMEJPLFdBQVc7cUdBMUJ0QixJQUFJOzJGQUFKLElBQUk7a0JBRGhCLFVBQVU7OzBCQXlCTixRQUFROzhCQUU2QyxNQUFNOzBCQUEzRCxRQUFROzswQkFBSSxNQUFNOzJCQUFDLFdBQVciLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIEV2ZW50RW1pdHRlcixcclxuICBJbmplY3QsXHJcbiAgSW5qZWN0YWJsZSxcclxuICBOZ1pvbmUsXHJcbiAgT25EZXN0cm95LFxyXG4gIE9wdGlvbmFsLFxyXG4gIFBMQVRGT1JNX0lEXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcblxyXG5pbXBvcnQgeyBJZGxlRXhwaXJ5IH0gZnJvbSAnLi9pZGxlZXhwaXJ5JztcclxuaW1wb3J0IHsgSW50ZXJydXB0IH0gZnJvbSAnLi9pbnRlcnJ1cHQnO1xyXG5pbXBvcnQgeyBJbnRlcnJ1cHRBcmdzIH0gZnJvbSAnLi9pbnRlcnJ1cHRhcmdzJztcclxuaW1wb3J0IHsgSW50ZXJydXB0U291cmNlIH0gZnJvbSAnLi9pbnRlcnJ1cHRzb3VyY2UnO1xyXG5pbXBvcnQgeyBLZWVwYWxpdmVTdmMgfSBmcm9tICcuL2tlZXBhbGl2ZXN2Yyc7XHJcbmltcG9ydCB7IExvY2FsU3RvcmFnZUV4cGlyeSB9IGZyb20gJy4vbG9jYWxzdG9yYWdlZXhwaXJ5JztcclxuXHJcbi8qXHJcbiAqIEluZGljYXRlcyB0aGUgZGVzaXJlZCBhdXRvIHJlc3VtZSBiZWhhdmlvci5cclxuICovXHJcbmV4cG9ydCBlbnVtIEF1dG9SZXN1bWUge1xyXG4gIC8qXHJcbiAgICogQXV0byByZXN1bWUgZnVuY3Rpb25hbGl0eSB3aWxsIGJlIGRpc2FibGVkLlxyXG4gICAqL1xyXG4gIGRpc2FibGVkLFxyXG4gIC8qXHJcbiAgICogQ2FuIHJlc3VtZSBhdXRvbWF0aWNhbGx5IGV2ZW4gaWYgdGhleSBhcmUgaWRsZS5cclxuICAgKi9cclxuICBpZGxlLFxyXG4gIC8qXHJcbiAgICogQ2FuIG9ubHkgcmVzdW1lIGF1dG9tYXRpY2FsbHkgaWYgdGhleSBhcmUgbm90IHlldCBpZGxlLlxyXG4gICAqL1xyXG4gIG5vdElkbGVcclxufVxyXG5cclxuLyoqXHJcbiAqIEEgc2VydmljZSBmb3IgZGV0ZWN0aW5nIGFuZCByZXNwb25kaW5nIHRvIHVzZXIgaWRsZW5lc3MuXHJcbiAqL1xyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBJZGxlIGltcGxlbWVudHMgT25EZXN0cm95IHtcclxuICBwcml2YXRlIGlkbGU6IG51bWJlciA9IDIwICogNjA7IC8vIGluIHNlY29uZHNcclxuICBwcml2YXRlIHRpbWVvdXRWYWwgPSAzMDsgLy8gaW4gc2Vjb25kc1xyXG4gIHByaXZhdGUgYXV0b1Jlc3VtZTogQXV0b1Jlc3VtZSA9IEF1dG9SZXN1bWUuaWRsZTtcclxuICBwcml2YXRlIGludGVycnVwdHM6IEFycmF5PEludGVycnVwdD4gPSBuZXcgQXJyYXkoKTtcclxuICBwcml2YXRlIHJ1bm5pbmcgPSBmYWxzZTtcclxuICBwcml2YXRlIGlkbGluZzogYm9vbGVhbjtcclxuICBwcml2YXRlIGlkbGVIYW5kbGU6IGFueTtcclxuICBwcml2YXRlIHRpbWVvdXRIYW5kbGU6IGFueTtcclxuICBwcml2YXRlIGNvdW50ZG93bjogbnVtYmVyO1xyXG4gIHByaXZhdGUga2VlcGFsaXZlRW5hYmxlZCA9IGZhbHNlO1xyXG4gIHByaXZhdGUga2VlcGFsaXZlU3ZjOiBLZWVwYWxpdmVTdmM7XHJcblxyXG4gIHB1YmxpYyBvbklkbGVTdGFydDogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcbiAgcHVibGljIG9uSWRsZUVuZDogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcbiAgcHVibGljIG9uVGltZW91dFdhcm5pbmc6IEV2ZW50RW1pdHRlcjxudW1iZXI+ID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXI+KCk7XHJcbiAgcHVibGljIG9uVGltZW91dDogRXZlbnRFbWl0dGVyPG51bWJlcj4gPSBuZXcgRXZlbnRFbWl0dGVyPG51bWJlcj4oKTtcclxuICBwdWJsaWMgb25JbnRlcnJ1cHQ6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xyXG5cclxuICBba2V5OiBzdHJpbmddOiBhbnk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBleHBpcnk6IElkbGVFeHBpcnksXHJcbiAgICBwcml2YXRlIHpvbmU6IE5nWm9uZSxcclxuICAgIEBPcHRpb25hbCgpIGtlZXBhbGl2ZVN2Yz86IEtlZXBhbGl2ZVN2YyxcclxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXR5cGVzXHJcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KFBMQVRGT1JNX0lEKSBwcml2YXRlIHBsYXRmb3JtSWQ/OiBPYmplY3RcclxuICApIHtcclxuICAgIGlmIChrZWVwYWxpdmVTdmMpIHtcclxuICAgICAgdGhpcy5rZWVwYWxpdmVTdmMgPSBrZWVwYWxpdmVTdmM7XHJcbiAgICAgIHRoaXMua2VlcGFsaXZlRW5hYmxlZCA9IHRydWU7XHJcbiAgICB9XHJcbiAgICB0aGlzLnNldElkbGluZyhmYWxzZSk7XHJcbiAgfVxyXG5cclxuICAvKlxyXG4gICAqIFNldHMgdGhlIGlkbGUgbmFtZSBmb3IgbG9jYWxTdG9yYWdlLlxyXG4gICAqIEltcG9ydGFudCB0byBzZXQgaWYgbXVsdGlwbGUgaW5zdGFuY2VzIG9mIElkbGUgd2l0aCBMb2NhbFN0b3JhZ2VFeHBpcnlcclxuICAgKiBAcGFyYW0gVGhlIG5hbWUgb2YgdGhlIGlkbGUuXHJcbiAgICovXHJcbiAgc2V0SWRsZU5hbWUoa2V5OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmV4cGlyeSBpbnN0YW5jZW9mIExvY2FsU3RvcmFnZUV4cGlyeSkge1xyXG4gICAgICB0aGlzLmV4cGlyeS5zZXRJZGxlTmFtZShrZXkpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxyXG4gICAgICAgICdDYW5ub3Qgc2V0IGV4cGlyeSBrZXkgbmFtZSBiZWNhdXNlIG5vIExvY2FsU3RvcmFnZUV4cGlyeSBoYXMgYmVlbiBwcm92aWRlZC4nXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKlxyXG4gICAqIFJldHVybnMgd2hldGhlciBvciBub3Qga2VlcGFsaXZlIGludGVncmF0aW9uIGlzIGVuYWJsZWQuXHJcbiAgICogQHJldHVybiBUcnVlIGlmIGludGVncmF0aW9uIGlzIGVuYWJsZWQ7IG90aGVyd2lzZSwgZmFsc2UuXHJcbiAgICovXHJcbiAgZ2V0S2VlcGFsaXZlRW5hYmxlZCgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLmtlZXBhbGl2ZUVuYWJsZWQ7XHJcbiAgfVxyXG5cclxuICAvKlxyXG4gICAqIFNldHMgYW5kIHJldHVybnMgd2hldGhlciBvciBub3Qga2VlcGFsaXZlIGludGVncmF0aW9uIGlzIGVuYWJsZWQuXHJcbiAgICogQHBhcmFtIFRydWUgaWYgdGhlIGludGVncmF0aW9uIGlzIGVuYWJsZWQ7IG90aGVyd2lzZSwgZmFsc2UuXHJcbiAgICogQHJldHVybiBUaGUgY3VycmVudCB2YWx1ZS5cclxuICAgKi9cclxuICBzZXRLZWVwYWxpdmVFbmFibGVkKHZhbHVlOiBib29sZWFuKTogYm9vbGVhbiB7XHJcbiAgICBpZiAoIXRoaXMua2VlcGFsaXZlU3ZjKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcclxuICAgICAgICAnQ2Fubm90IGVuYWJsZSBrZWVwYWxpdmUgaW50ZWdyYXRpb24gYmVjYXVzZSBubyBLZWVwYWxpdmVTdmMgaGFzIGJlZW4gcHJvdmlkZWQuJ1xyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiAodGhpcy5rZWVwYWxpdmVFbmFibGVkID0gdmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgLypcclxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHRpbWVvdXQgdmFsdWUuXHJcbiAgICogQHJldHVybiBUaGUgdGltZW91dCB2YWx1ZSBpbiBzZWNvbmRzLlxyXG4gICAqL1xyXG4gIGdldFRpbWVvdXQoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLnRpbWVvdXRWYWw7XHJcbiAgfVxyXG5cclxuICAvKlxyXG4gICAqIFNldHMgdGhlIHRpbWVvdXQgdmFsdWUuXHJcbiAgICogQHBhcmFtIHNlY29uZHMgLSBUaGUgdGltZW91dCB2YWx1ZSBpbiBzZWNvbmRzLiAwIG9yIGZhbHNlIHRvIGRpc2FibGUgdGltZW91dCBmZWF0dXJlLlxyXG4gICAqIEByZXR1cm4gVGhlIGN1cnJlbnQgdmFsdWUuIElmIGRpc2FibGVkLCB0aGUgdmFsdWUgd2lsbCBiZSAwLlxyXG4gICAqL1xyXG4gIHNldFRpbWVvdXQoc2Vjb25kczogbnVtYmVyIHwgYm9vbGVhbik6IG51bWJlciB7XHJcbiAgICBpZiAoc2Vjb25kcyA9PT0gZmFsc2UpIHtcclxuICAgICAgdGhpcy50aW1lb3V0VmFsID0gMDtcclxuICAgIH0gZWxzZSBpZiAodHlwZW9mIHNlY29uZHMgPT09ICdudW1iZXInICYmIHNlY29uZHMgPj0gMCkge1xyXG4gICAgICB0aGlzLnRpbWVvdXRWYWwgPSBzZWNvbmRzO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiJ3NlY29uZHMnIGNhbiBvbmx5IGJlICdmYWxzZScgb3IgYSBwb3NpdGl2ZSBudW1iZXIuXCIpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0aGlzLnRpbWVvdXRWYWw7XHJcbiAgfVxyXG5cclxuICAvKlxyXG4gICAqIFJldHVybnMgdGhlIGN1cnJlbnQgaWRsZSB2YWx1ZS5cclxuICAgKiBAcmV0dXJuIFRoZSBpZGxlIHZhbHVlIGluIHNlY29uZHMuXHJcbiAgICovXHJcbiAgZ2V0SWRsZSgpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuaWRsZTtcclxuICB9XHJcblxyXG4gIC8qXHJcbiAgICogU2V0cyB0aGUgaWRsZSB2YWx1ZS5cclxuICAgKiBAcGFyYW0gc2Vjb25kcyAtIFRoZSBpZGxlIHZhbHVlIGluIHNlY29uZHMuXHJcbiAgICogQHJldHVybiBUaGUgaWRsZSB2YWx1ZSBpbiBzZWNvbmRzLlxyXG4gICAqL1xyXG4gIHNldElkbGUoc2Vjb25kczogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgIGlmIChzZWNvbmRzIDw9IDApIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiJ3NlY29uZHMnIG11c3QgYmUgZ3JlYXRlciB6ZXJvXCIpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiAodGhpcy5pZGxlID0gc2Vjb25kcyk7XHJcbiAgfVxyXG5cclxuICAvKlxyXG4gICAqIFJldHVybnMgdGhlIGN1cnJlbnQgYXV0b3Jlc3VtZSB2YWx1ZS5cclxuICAgKiBAcmV0dXJuIFRoZSBjdXJyZW50IHZhbHVlLlxyXG4gICAqL1xyXG4gIGdldEF1dG9SZXN1bWUoKTogQXV0b1Jlc3VtZSB7XHJcbiAgICByZXR1cm4gdGhpcy5hdXRvUmVzdW1lO1xyXG4gIH1cclxuXHJcbiAgc2V0QXV0b1Jlc3VtZSh2YWx1ZTogQXV0b1Jlc3VtZSk6IEF1dG9SZXN1bWUge1xyXG4gICAgcmV0dXJuICh0aGlzLmF1dG9SZXN1bWUgPSB2YWx1ZSk7XHJcbiAgfVxyXG5cclxuICAvKlxyXG4gICAqIFNldHMgaW50ZXJydXB0cyBmcm9tIHRoZSBzcGVjaWZpZWQgc291cmNlcy5cclxuICAgKiBAcGFyYW0gc291cmNlcyAtIEludGVycnVwdCBzb3VyY2VzLlxyXG4gICAqIEByZXR1cm4gVGhlIHJlc3VsdGluZyBpbnRlcnJ1cHRzLlxyXG4gICAqL1xyXG4gIHNldEludGVycnVwdHMoc291cmNlczogQXJyYXk8SW50ZXJydXB0U291cmNlPik6IEFycmF5PEludGVycnVwdD4ge1xyXG4gICAgdGhpcy5jbGVhckludGVycnVwdHMoKTtcclxuXHJcbiAgICBjb25zdCBzZWxmID0gdGhpcztcclxuXHJcbiAgICBmb3IgKGNvbnN0IHNvdXJjZSBvZiBzb3VyY2VzKSB7XHJcbiAgICAgIGNvbnN0IG9wdGlvbnMgPSB7IHBsYXRmb3JtSWQ6IHRoaXMucGxhdGZvcm1JZCB9O1xyXG4gICAgICBjb25zdCBzdWIgPSBuZXcgSW50ZXJydXB0KHNvdXJjZSwgb3B0aW9ucyk7XHJcbiAgICAgIHN1Yi5zdWJzY3JpYmUoKGFyZ3M6IEludGVycnVwdEFyZ3MpID0+IHtcclxuICAgICAgICBzZWxmLmludGVycnVwdChhcmdzLmZvcmNlLCBhcmdzLmlubmVyQXJncyk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy5pbnRlcnJ1cHRzLnB1c2goc3ViKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdGhpcy5pbnRlcnJ1cHRzO1xyXG4gIH1cclxuXHJcbiAgLypcclxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IGludGVycnVwdHMuXHJcbiAgICogQHJldHVybiBUaGUgY3VycmVudCBpbnRlcnJ1cHRzLlxyXG4gICAqL1xyXG4gIGdldEludGVycnVwdHMoKTogQXJyYXk8SW50ZXJydXB0PiB7XHJcbiAgICByZXR1cm4gdGhpcy5pbnRlcnJ1cHRzO1xyXG4gIH1cclxuXHJcbiAgLypcclxuICAgKiBQYXVzZXMsIHVuc3Vic2NyaWJlcywgYW5kIGNsZWFycyB0aGUgY3VycmVudCBpbnRlcnJ1cHQgc3Vic2NyaXB0aW9ucy5cclxuICAgKi9cclxuICBjbGVhckludGVycnVwdHMoKTogdm9pZCB7XHJcbiAgICBmb3IgKGNvbnN0IHN1YiBvZiB0aGlzLmludGVycnVwdHMpIHtcclxuICAgICAgc3ViLnBhdXNlKCk7XHJcbiAgICAgIHN1Yi51bnN1YnNjcmliZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuaW50ZXJydXB0cy5sZW5ndGggPSAwO1xyXG4gIH1cclxuXHJcbiAgLypcclxuICAgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBzZXJ2aWNlIGlzIHJ1bm5pbmcgaS5lLiB3YXRjaGluZyBmb3IgaWRsZW5lc3MuXHJcbiAgICogQHJldHVybiBUcnVlIGlmIHNlcnZpY2UgaXMgd2F0Y2hpbmc7IG90aGVyd2lzZSwgZmFsc2UuXHJcbiAgICovXHJcbiAgaXNSdW5uaW5nKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMucnVubmluZztcclxuICB9XHJcblxyXG4gIC8qXHJcbiAgICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgdXNlciBpcyBjb25zaWRlcmVkIGlkbGUuXHJcbiAgICogQHJldHVybiBUcnVlIGlmIHRoZSB1c2VyIGlzIGluIHRoZSBpZGxlIHN0YXRlOyBvdGhlcndpc2UsIGZhbHNlLlxyXG4gICAqL1xyXG4gIGlzSWRsaW5nKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuaWRsaW5nO1xyXG4gIH1cclxuXHJcbiAgLypcclxuICAgKiBTdGFydHMgd2F0Y2hpbmcgZm9yIGluYWN0aXZpdHkuXHJcbiAgICovXHJcbiAgd2F0Y2goc2tpcEV4cGlyeT86IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgIHRoaXMuc2FmZUNsZWFySW50ZXJ2YWwoJ2lkbGVIYW5kbGUnKTtcclxuICAgIHRoaXMuc2FmZUNsZWFySW50ZXJ2YWwoJ3RpbWVvdXRIYW5kbGUnKTtcclxuXHJcbiAgICBjb25zdCB0aW1lb3V0ID0gIXRoaXMudGltZW91dFZhbCA/IDAgOiB0aGlzLnRpbWVvdXRWYWw7XHJcbiAgICBpZiAoIXNraXBFeHBpcnkpIHtcclxuICAgICAgY29uc3QgdmFsdWUgPSBuZXcgRGF0ZShcclxuICAgICAgICB0aGlzLmV4cGlyeS5ub3coKS5nZXRUaW1lKCkgKyAodGhpcy5pZGxlICsgdGltZW91dCkgKiAxMDAwXHJcbiAgICAgICk7XHJcbiAgICAgIHRoaXMuZXhwaXJ5Lmxhc3QodmFsdWUpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmlkbGluZykge1xyXG4gICAgICB0aGlzLnRvZ2dsZVN0YXRlKCk7XHJcbiAgICB9XHJcbiAgICBpZiAoIXRoaXMucnVubmluZykge1xyXG4gICAgICB0aGlzLnN0YXJ0S2VlcGFsaXZlKCk7XHJcbiAgICAgIHRoaXMudG9nZ2xlSW50ZXJydXB0cyh0cnVlKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnJ1bm5pbmcgPSB0cnVlO1xyXG5cclxuICAgIGNvbnN0IHdhdGNoRm4gPSAoKSA9PiB7XHJcbiAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT4ge1xyXG4gICAgICAgIGNvbnN0IGRpZmYgPSB0aGlzLmdldEV4cGlyeURpZmYodGltZW91dCk7XHJcbiAgICAgICAgaWYgKGRpZmYgPiAwKSB7XHJcbiAgICAgICAgICB0aGlzLnNhZmVDbGVhckludGVydmFsKCdpZGxlSGFuZGxlJyk7XHJcbiAgICAgICAgICB0aGlzLnNldElkbGVJbnRlcnZhbE91dHNpZGVPZlpvbmUod2F0Y2hGbiwgZGlmZik7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoaXMudG9nZ2xlU3RhdGUoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfTtcclxuXHJcbiAgICB0aGlzLnNldElkbGVJbnRlcnZhbE91dHNpZGVPZlpvbmUod2F0Y2hGbiwgdGhpcy5pZGxlICogMTAwMCk7XHJcbiAgfVxyXG5cclxuICAvKlxyXG4gICAqIEFsbG93cyBwcm90cmFjdG9yIHRlc3RzIHRvIGNhbGwgd2FpdEZvckFuZ3VsYXIgd2l0aG91dCBoYW5naW5nXHJcbiAgICovXHJcbiAgc2V0SWRsZUludGVydmFsT3V0c2lkZU9mWm9uZSh3YXRjaEZuOiAoKSA9PiB2b2lkLCBmcmVxdWVuY3k6IG51bWJlcik6IHZvaWQge1xyXG4gICAgdGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcclxuICAgICAgdGhpcy5pZGxlSGFuZGxlID0gc2V0SW50ZXJ2YWwod2F0Y2hGbiwgZnJlcXVlbmN5KTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLypcclxuICAgKiBTdG9wcyB3YXRjaGluZyBmb3IgaW5hY3Rpdml0eS5cclxuICAgKi9cclxuICBzdG9wKCk6IHZvaWQge1xyXG4gICAgdGhpcy5zdG9wS2VlcGFsaXZlKCk7XHJcblxyXG4gICAgdGhpcy50b2dnbGVJbnRlcnJ1cHRzKGZhbHNlKTtcclxuXHJcbiAgICB0aGlzLnNhZmVDbGVhckludGVydmFsKCdpZGxlSGFuZGxlJyk7XHJcbiAgICB0aGlzLnNhZmVDbGVhckludGVydmFsKCd0aW1lb3V0SGFuZGxlJyk7XHJcblxyXG4gICAgdGhpcy5zZXRJZGxpbmcoZmFsc2UpO1xyXG4gICAgdGhpcy5ydW5uaW5nID0gZmFsc2U7XHJcblxyXG4gICAgdGhpcy5leHBpcnkubGFzdChudWxsKTtcclxuICB9XHJcblxyXG4gIC8qXHJcbiAgICogRm9yY2VzIGEgdGltZW91dCBldmVudCBhbmQgc3RhdGUuXHJcbiAgICovXHJcbiAgdGltZW91dCgpOiB2b2lkIHtcclxuICAgIHRoaXMuc3RvcEtlZXBhbGl2ZSgpO1xyXG5cclxuICAgIHRoaXMudG9nZ2xlSW50ZXJydXB0cyhmYWxzZSk7XHJcblxyXG4gICAgdGhpcy5zYWZlQ2xlYXJJbnRlcnZhbCgnaWRsZUhhbmRsZScpO1xyXG4gICAgdGhpcy5zYWZlQ2xlYXJJbnRlcnZhbCgndGltZW91dEhhbmRsZScpO1xyXG5cclxuICAgIHRoaXMuc2V0SWRsaW5nKHRydWUpO1xyXG4gICAgdGhpcy5ydW5uaW5nID0gZmFsc2U7XHJcbiAgICB0aGlzLmNvdW50ZG93biA9IDA7XHJcblxyXG4gICAgdGhpcy5vblRpbWVvdXQuZW1pdChudWxsKTtcclxuICB9XHJcblxyXG4gIC8qXHJcbiAgICogU2lnbmFscyB0aGF0IHVzZXIgYWN0aXZpdHkgaGFzIG9jY3VycmVkLlxyXG4gICAqIEBwYXJhbSBmb3JjZSAtIEZvcmNlcyB3YXRjaCB0byBiZSBjYWxsZWQsIHVubGVzcyB0aGV5IGFyZSB0aW1lZCBvdXQuXHJcbiAgICogQHBhcmFtIGV2ZW50QXJncyAtIE9wdGlvbmFsIHNvdXJjZSBldmVudCBhcmd1bWVudHMuXHJcbiAgICovXHJcbiAgaW50ZXJydXB0KGZvcmNlPzogYm9vbGVhbiwgZXZlbnRBcmdzPzogYW55KTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMucnVubmluZykge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMudGltZW91dFZhbCAmJiB0aGlzLmV4cGlyeS5pc0V4cGlyZWQoKSkge1xyXG4gICAgICB0aGlzLnRpbWVvdXQoKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdGhpcy5vbkludGVycnVwdC5lbWl0KGV2ZW50QXJncyk7XHJcblxyXG4gICAgaWYgKFxyXG4gICAgICBmb3JjZSA9PT0gdHJ1ZSB8fFxyXG4gICAgICB0aGlzLmF1dG9SZXN1bWUgPT09IEF1dG9SZXN1bWUuaWRsZSB8fFxyXG4gICAgICAodGhpcy5hdXRvUmVzdW1lID09PSBBdXRvUmVzdW1lLm5vdElkbGUgJiYgIXRoaXMuZXhwaXJ5LmlkbGluZygpKVxyXG4gICAgKSB7XHJcbiAgICAgIHRoaXMud2F0Y2goZm9yY2UpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzZXRJZGxpbmcodmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgIHRoaXMuaWRsaW5nID0gdmFsdWU7XHJcbiAgICB0aGlzLmV4cGlyeS5pZGxpbmcodmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB0b2dnbGVTdGF0ZSgpOiB2b2lkIHtcclxuICAgIHRoaXMuc2V0SWRsaW5nKCF0aGlzLmlkbGluZyk7XHJcblxyXG4gICAgaWYgKHRoaXMuaWRsaW5nKSB7XHJcbiAgICAgIHRoaXMub25JZGxlU3RhcnQuZW1pdChudWxsKTtcclxuICAgICAgdGhpcy5zdG9wS2VlcGFsaXZlKCk7XHJcblxyXG4gICAgICBpZiAodGhpcy50aW1lb3V0VmFsID4gMCkge1xyXG4gICAgICAgIHRoaXMuY291bnRkb3duID0gdGhpcy50aW1lb3V0VmFsO1xyXG4gICAgICAgIHRoaXMuZG9Db3VudGRvd24oKTtcclxuICAgICAgICB0aGlzLnNldFRpbW91dEludGVydmFsT3V0c2lkZVpvbmUoKCkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5kb0NvdW50ZG93bkluWm9uZSgpO1xyXG4gICAgICAgIH0sIDEwMDApO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnRvZ2dsZUludGVycnVwdHModHJ1ZSk7XHJcbiAgICAgIHRoaXMub25JZGxlRW5kLmVtaXQobnVsbCk7XHJcbiAgICAgIHRoaXMuc3RhcnRLZWVwYWxpdmUoKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnNhZmVDbGVhckludGVydmFsKCdpZGxlSGFuZGxlJyk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldFRpbW91dEludGVydmFsT3V0c2lkZVpvbmUoXHJcbiAgICBpbnRlcnZhbEZuOiAoKSA9PiB2b2lkLFxyXG4gICAgZnJlcXVlbmN5OiBudW1iZXJcclxuICApIHtcclxuICAgIHRoaXMuem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XHJcbiAgICAgIHRoaXMudGltZW91dEhhbmRsZSA9IHNldEludGVydmFsKCgpID0+IHtcclxuICAgICAgICBpbnRlcnZhbEZuKCk7XHJcbiAgICAgIH0sIGZyZXF1ZW5jeSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdG9nZ2xlSW50ZXJydXB0cyhyZXN1bWU6IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgIGZvciAoY29uc3QgaW50ZXJydXB0IG9mIHRoaXMuaW50ZXJydXB0cykge1xyXG4gICAgICBpZiAocmVzdW1lKSB7XHJcbiAgICAgICAgaW50ZXJydXB0LnJlc3VtZSgpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGludGVycnVwdC5wYXVzZSgpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldEV4cGlyeURpZmYodGltZW91dDogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgIGNvbnN0IG5vdzogRGF0ZSA9IHRoaXMuZXhwaXJ5Lm5vdygpO1xyXG4gICAgY29uc3QgbGFzdDogRGF0ZSA9IHRoaXMuZXhwaXJ5Lmxhc3QoKSB8fCBub3c7XHJcbiAgICByZXR1cm4gbGFzdC5nZXRUaW1lKCkgLSBub3cuZ2V0VGltZSgpIC0gdGltZW91dCAqIDEwMDA7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGRvQ291bnRkb3duSW5ab25lKCk6IHZvaWQge1xyXG4gICAgdGhpcy56b25lLnJ1bigoKSA9PiB7XHJcbiAgICAgIHRoaXMuZG9Db3VudGRvd24oKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBkb0NvdW50ZG93bigpOiB2b2lkIHtcclxuICAgIGNvbnN0IGRpZmYgPSB0aGlzLmdldEV4cGlyeURpZmYodGhpcy50aW1lb3V0VmFsKTtcclxuICAgIGlmIChkaWZmID4gMCkge1xyXG4gICAgICB0aGlzLnNhZmVDbGVhckludGVydmFsKCd0aW1lb3V0SGFuZGxlJyk7XHJcbiAgICAgIHRoaXMuaW50ZXJydXB0KHRydWUpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCF0aGlzLmlkbGluZykge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuY291bnRkb3duIDw9IDApIHtcclxuICAgICAgdGhpcy50aW1lb3V0KCk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLm9uVGltZW91dFdhcm5pbmcuZW1pdCh0aGlzLmNvdW50ZG93bik7XHJcbiAgICB0aGlzLmNvdW50ZG93bi0tO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzYWZlQ2xlYXJJbnRlcnZhbChoYW5kbGVOYW1lOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGNvbnN0IGhhbmRsZSA9IHRoaXNbaGFuZGxlTmFtZV07XHJcbiAgICBpZiAoaGFuZGxlICE9PSBudWxsICYmIHR5cGVvZiBoYW5kbGUgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgIGNsZWFySW50ZXJ2YWwodGhpc1toYW5kbGVOYW1lXSk7XHJcbiAgICAgIHRoaXNbaGFuZGxlTmFtZV0gPSBudWxsO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzdGFydEtlZXBhbGl2ZSgpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5rZWVwYWxpdmVTdmMgfHwgIXRoaXMua2VlcGFsaXZlRW5hYmxlZCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMucnVubmluZykge1xyXG4gICAgICB0aGlzLmtlZXBhbGl2ZVN2Yy5waW5nKCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5rZWVwYWxpdmVTdmMuc3RhcnQoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc3RvcEtlZXBhbGl2ZSgpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5rZWVwYWxpdmVTdmMgfHwgIXRoaXMua2VlcGFsaXZlRW5hYmxlZCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5rZWVwYWxpdmVTdmMuc3RvcCgpO1xyXG4gIH1cclxuXHJcbiAgLypcclxuICAgKiBDYWxsZWQgYnkgQW5ndWxhciB3aGVuIGRlc3Ryb3lpbmcgdGhlIGluc3RhbmNlLlxyXG4gICAqL1xyXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xyXG4gICAgdGhpcy5zdG9wKCk7XHJcbiAgICB0aGlzLmNsZWFySW50ZXJydXB0cygpO1xyXG4gIH1cclxufVxyXG4iXX0=