UNPKG

angular-weblineindia-qrcode-scanner

Version:
594 lines 62 kB
import * as tslib_1 from "tslib"; import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output, ViewChild, } from '@angular/core'; import { ArgumentException, BarcodeFormat, DecodeHintType } from '@zxing/library'; import { BrowserMultiFormatContinuousReader } from './browser-multi-format-continuous-reader'; let ZXingScannerComponent = class ZXingScannerComponent { /** * Constructor to build the object and do some DI. */ constructor() { /** * How the preview element shoud be fit inside the :host container. */ this.previewFitMode = 'cover'; // instance based emitters this.autostarted = new EventEmitter(); this.autostarting = new EventEmitter(); this.torchCompatible = new EventEmitter(); this.scanSuccess = new EventEmitter(); this.scanFailure = new EventEmitter(); this.scanError = new EventEmitter(); this.scanComplete = new EventEmitter(); this.camerasFound = new EventEmitter(); this.camerasNotFound = new EventEmitter(); this.permissionResponse = new EventEmitter(true); this.hasDevices = new EventEmitter(); this.deviceChange = new EventEmitter(); this._device = null; this._enabled = true; this._hints = new Map(); this.autofocusEnabled = true; this.autostart = true; this.formats = [BarcodeFormat.QR_CODE]; // computed data this.hasNavigator = typeof navigator !== 'undefined'; this.isMediaDevicesSuported = this.hasNavigator && !!navigator.mediaDevices; } /** * Exposes the current code reader, so the user can use it's APIs. */ get codeReader() { return this._codeReader; } /** * User device input */ set device(device) { if (!device && device !== null) { throw new ArgumentException('The `device` must be a valid MediaDeviceInfo or null.'); } if (this.isCurrentDevice(device)) { console.warn('Setting the same device is not allowed.'); return; } if (this.isAutostarting) { // do not allow setting devices during auto-start, since it will set one and emit it. console.warn('Avoid setting a device during auto-start.'); return; } if (!this.hasPermission) { console.warn('Permissions not set yet, waiting for them to be set to apply device change.'); // this.permissionResponse // .pipe( // take(1), // tap(() => console.log(`Permissions set, applying device change${device ? ` (${device.deviceId})` : ''}.`)) // ) // .subscribe(() => this.device = device); // return; } // in order to change the device the codeReader gotta be reseted this._reset(); this._device = device; // if enabled, starts scanning if (this._enabled && device !== null) { this.scanFromDevice(device.deviceId); } } /** * User device acessor. */ get device() { return this._device; } /** * Returns all the registered formats. */ get formats() { return this.hints.get(DecodeHintType.POSSIBLE_FORMATS); } /** * Registers formats the scanner should support. * * @param input BarcodeFormat or case-insensitive string array. */ set formats(input) { if (typeof input === 'string') { throw new Error('Invalid formats, make sure the [formats] input is a binding.'); } // formats may be set from html template as BarcodeFormat or string array const formats = input.map(f => this.getBarcodeFormatOrFail(f)); const hints = this.hints; // updates the hints hints.set(DecodeHintType.POSSIBLE_FORMATS, formats); this.hints = hints; } /** * Returns all the registered hints. */ get hints() { return this._hints; } /** * Does what it takes to set the hints. */ set hints(hints) { this._hints = hints; // @note avoid restarting the code reader when possible // new instance with new hints. this.restart(); } /** * */ set isAutostarting(state) { this._isAutostarting = state; this.autostarting.next(state); } /** * */ get isAutstarting() { return this._isAutostarting; } /** * Allow start scan or not. */ set torch(on) { this.getCodeReader().setTorch(on); } /** * Allow start scan or not. */ set enable(enabled) { this._enabled = Boolean(enabled); if (!this._enabled) { this.reset(); } else if (this.device) { this.scanFromDevice(this.device.deviceId); } } /** * Tells if the scanner is enabled or not. */ get enabled() { return this._enabled; } /** * If is `tryHarder` enabled. */ get tryHarder() { return this.hints.get(DecodeHintType.TRY_HARDER); } /** * Enable/disable tryHarder hint. */ set tryHarder(enable) { const hints = this.hints; if (enable) { hints.set(DecodeHintType.TRY_HARDER, true); } else { hints.delete(DecodeHintType.TRY_HARDER); } this.hints = hints; } /** * Gets and registers all cammeras. */ askForPermission() { return tslib_1.__awaiter(this, void 0, void 0, function* () { if (!this.hasNavigator) { console.error('@zxing/ngx-scanner', 'Can\'t ask permission, navigator is not present.'); this.setPermission(null); return this.hasPermission; } if (!this.isMediaDevicesSuported) { console.error('@zxing/ngx-scanner', 'Can\'t get user media, this is not supported.'); this.setPermission(null); return this.hasPermission; } let stream; let permission; try { // Will try to ask for permission stream = yield this.getAnyVideoDevice(); permission = !!stream; } catch (err) { return this.handlePermissionException(err); } finally { this.terminateStream(stream); } this.setPermission(permission); // Returns the permission return permission; }); } /** * */ getAnyVideoDevice() { return navigator.mediaDevices.getUserMedia({ video: true }); } /** * Terminates a stream and it's tracks. */ terminateStream(stream) { if (stream) { stream.getTracks().forEach(t => t.stop()); } stream = undefined; } /** * Initializes the component without starting the scanner. */ initAutostartOff() { // do not ask for permission when autostart is off this.isAutostarting = null; // just update devices information this.updateVideoInputDevices(); } /** * Initializes the component and starts the scanner. * Permissions are asked to accomplish that. */ initAutostartOn() { return tslib_1.__awaiter(this, void 0, void 0, function* () { this.isAutostarting = true; let hasPermission; try { // Asks for permission before enumerating devices so it can get all the device's info hasPermission = yield this.askForPermission(); } catch (e) { console.error('Exception occurred while asking for permission:', e); return; } // from this point, things gonna need permissions if (hasPermission) { const devices = yield this.updateVideoInputDevices(); this.autostartScanner([...devices]); } }); } /** * Checks if the given device is the current defined one. */ isCurrentDevice(device) { return this.device && device && device.deviceId === this.device.deviceId; } /** * Executed after the view initialization. */ ngAfterViewInit() { // makes torch availability information available to user this.getCodeReader().isTorchAvailable.subscribe(x => this.torchCompatible.emit(x)); if (!this.autostart) { console.warn('New feature \'autostart\' disabled, be careful. Permissions and devices recovery has to be run manually.'); // does the necessary configuration without autostarting this.initAutostartOff(); return; } // configurates the component and starts the scanner this.initAutostartOn(); } /** * Executes some actions before destroy the component. */ ngOnDestroy() { this.reset(); } /** * Stops old `codeReader` and starts scanning in a new one. */ restart() { const prevDevice = this._reset(); if (!prevDevice) { return; } // @note apenas necessario por enquanto causa da Torch this._codeReader = undefined; this.device = prevDevice; } /** * Discovers and updates known video input devices. */ updateVideoInputDevices() { return tslib_1.__awaiter(this, void 0, void 0, function* () { // permissions aren't needed to get devices, but to access them and their info const devices = (yield this.getCodeReader().listVideoInputDevices()) || []; const hasDevices = devices && devices.length > 0; // stores discovered devices and updates information this.hasDevices.next(hasDevices); this.camerasFound.next([...devices]); if (!hasDevices) { this.camerasNotFound.next(); } return devices; }); } /** * Starts the scanner with the back camera otherwise take the last * available device. */ autostartScanner(devices) { const matcher = ({ label }) => /back|trás|rear|traseira|environment|ambiente/gi.test(label); // select the rear camera by default, otherwise take the last camera. const device = devices.find(matcher) || devices.pop(); if (!device) { throw new Error('Impossible to autostart, no input devices available.'); } this.device = device; // @note when listening to this change, callback code will sometimes run before the previous line. this.deviceChange.emit(device); this.isAutostarting = false; this.autostarted.next(); } /** * Dispatches the scan success event. * * @param result the scan result. */ dispatchScanSuccess(result) { this.scanSuccess.next(result.getText()); } /** * Dispatches the scan failure event. */ dispatchScanFailure(reason) { this.scanFailure.next(reason); } /** * Dispatches the scan error event. * * @param error the error thing. */ dispatchScanError(error) { this.scanError.next(error); } /** * Dispatches the scan event. * * @param result the scan result. */ dispatchScanComplete(result) { this.scanComplete.next(result); } /** * Returns the filtered permission. */ handlePermissionException(err) { // failed to grant permission to video input console.error('@zxing/ngx-scanner', 'Error when asking for permission.', err); let permission; switch (err.name) { // usually caused by not secure origins case 'NotSupportedError': console.warn('@zxing/ngx-scanner', err.message); // could not claim permission = null; // can't check devices this.hasDevices.next(null); break; // user denied permission case 'NotAllowedError': console.warn('@zxing/ngx-scanner', err.message); // claimed and denied permission permission = false; // this means that input devices exists this.hasDevices.next(true); break; // the device has no attached input devices case 'NotFoundError': console.warn('@zxing/ngx-scanner', err.message); // no permissions claimed permission = null; // because there was no devices this.hasDevices.next(false); // tells the listener about the error this.camerasNotFound.next(err); break; case 'NotReadableError': console.warn('@zxing/ngx-scanner', 'Couldn\'t read the device(s)\'s stream, it\'s probably in use by another app.'); // no permissions claimed permission = null; // there are devices, which I couldn't use this.hasDevices.next(false); // tells the listener about the error this.camerasNotFound.next(err); break; default: console.warn('@zxing/ngx-scanner', 'I was not able to define if I have permissions for camera or not.', err); // unknown permission = null; // this.hasDevices.next(undefined; break; } this.setPermission(permission); // tells the listener about the error this.permissionResponse.error(err); return permission; } /** * Returns a valid BarcodeFormat or fails. */ getBarcodeFormatOrFail(format) { return typeof format === 'string' ? BarcodeFormat[format.trim().toUpperCase()] : format; } /** * Retorna um code reader, cria um se nenhume existe. */ getCodeReader() { if (!this._codeReader) { this._codeReader = new BrowserMultiFormatContinuousReader(this.hints); } return this._codeReader; } /** * Starts the continuous scanning for the given device. * * @param deviceId The deviceId from the device. */ scanFromDevice(deviceId) { const videoElement = this.previewElemRef.nativeElement; const codeReader = this.getCodeReader(); const decodingStream = codeReader.continuousDecodeFromInputVideoDevice(deviceId, videoElement); if (!decodingStream) { throw new Error('Undefined decoding stream, aborting.'); } const next = (x) => this._onDecodeResult(x.result, x.error); const error = (err) => this._onDecodeError(err); const complete = () => { this.reset(); console.log('completed'); }; decodingStream.subscribe(next, error, complete); } /** * Handles decode errors. */ _onDecodeError(err) { this.dispatchScanError(err); this.reset(); } /** * Handles decode results. */ _onDecodeResult(result, error) { if (result) { this.dispatchScanSuccess(result); } else { this.dispatchScanFailure(error); } this.dispatchScanComplete(result); } /** * Stops the code reader and returns the previous selected device. */ _reset() { if (!this._codeReader) { return; } const device = this.device; // do not set this.device inside this method, it would create a recursive loop this._device = null; this._codeReader.reset(); return device; } /** * Resets the scanner and emits device change. */ reset() { this._reset(); this.deviceChange.emit(null); } /** * Sets the permission value and emmits the event. */ setPermission(hasPermission) { this.hasPermission = hasPermission; this.permissionResponse.next(hasPermission); } }; tslib_1.__decorate([ ViewChild('preview', { static: true }), tslib_1.__metadata("design:type", ElementRef) ], ZXingScannerComponent.prototype, "previewElemRef", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Boolean) ], ZXingScannerComponent.prototype, "autofocusEnabled", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "autostarted", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "autostarting", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Boolean) ], ZXingScannerComponent.prototype, "autostart", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", String) ], ZXingScannerComponent.prototype, "previewFitMode", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "torchCompatible", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "scanSuccess", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "scanFailure", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "scanError", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "scanComplete", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "camerasFound", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "camerasNotFound", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "permissionResponse", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "hasDevices", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", MediaDeviceInfo), tslib_1.__metadata("design:paramtypes", [MediaDeviceInfo]) ], ZXingScannerComponent.prototype, "device", null); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "deviceChange", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Array), tslib_1.__metadata("design:paramtypes", [Array]) ], ZXingScannerComponent.prototype, "formats", null); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Boolean), tslib_1.__metadata("design:paramtypes", [Boolean]) ], ZXingScannerComponent.prototype, "torch", null); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Boolean), tslib_1.__metadata("design:paramtypes", [Boolean]) ], ZXingScannerComponent.prototype, "enable", null); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Boolean), tslib_1.__metadata("design:paramtypes", [Boolean]) ], ZXingScannerComponent.prototype, "tryHarder", null); ZXingScannerComponent = tslib_1.__decorate([ Component({ selector: 'zxing-scanner', template: "<video #preview [style.object-fit]=\"previewFitMode\">\n <p>\n Your browser does not support this feature, please try to upgrade it.\n </p>\n <p>\n Seu navegador n\u00E3o suporta este recurso, por favor tente atualiz\u00E1-lo.\n </p>\n</video>\n", changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}video{width:100%;height:auto;-o-object-fit:contain;object-fit:contain}"] }), tslib_1.__metadata("design:paramtypes", []) ], ZXingScannerComponent); export { ZXingScannerComponent }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoienhpbmctc2Nhbm5lci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9Aenhpbmcvbmd4LXNjYW5uZXIvIiwic291cmNlcyI6WyJsaWIvenhpbmctc2Nhbm5lci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFFTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFDTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUNMLGlCQUFpQixFQUNqQixhQUFhLEVBQ2IsY0FBYyxFQUdmLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEIsT0FBTyxFQUFFLGtDQUFrQyxFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFTOUYsSUFBYSxxQkFBcUIsR0FBbEMsTUFBYSxxQkFBcUI7SUEwVGhDOztPQUVHO0lBQ0g7UUFyUEE7O1dBRUc7UUFFSCxtQkFBYyxHQUF5RCxPQUFPLENBQUM7UUFrUDdFLDBCQUEwQjtRQUMxQixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDdEMsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUMxQyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDdEMsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ3RDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUNwQyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDdkMsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUMxQyxJ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Q1QsUUFBUSxFQUFFLGVBQWU7UUFDekIsMlFBQTZDO1FBRTdDLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNOztLQUNoRCxDQUFDOztHQUNXLHFCQUFxQixDQTZ0QmpDO1NBN3RCWSxxQkFBcUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE91dHB1dCxcbiAgVmlld0NoaWxkLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHtcbiAgQXJndW1lbnRFeGNlcHRpb24sXG4gIEJhcmNvZGVGb3JtYXQsXG4gIERlY29kZUhpbnRUeXBlLFxuICBFeGNlcHRpb24sXG4gIFJlc3VsdFxufSBmcm9tICdAenhpbmcvbGlicmFyeSc7XG5cbmltcG9ydCB7IEJyb3dzZXJNdWx0aUZvcm1hdENvbnRpbnVvdXNSZWFkZXIgfSBmcm9tICcuL2Jyb3dzZXItbXVsdGktZm9ybWF0LWNvbnRpbnVvdXMtcmVhZGVyJztcbmltcG9ydCB7IFJlc3VsdEFuZEVycm9yIH0gZnJvbSAnLi9SZXN1bHRBbmRFcnJvcic7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3p4aW5nLXNjYW5uZXInLFxuICB0ZW1wbGF0ZVVybDogJy4venhpbmctc2Nhbm5lci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3p4aW5nLXNjYW5uZXIuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgWlhpbmdTY2FubmVyQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcblxuICAvKipcbiAgICogU3VwcG9ydGVkIEhpbnRzIG1hcC5cbiAgICovXG4gIHByaXZhdGUgX2hpbnRzOiBNYXA8RGVjb2RlSGludFR5cGUsIGFueT4gfCBudWxsO1xuXG4gIC8qKlxuICAgKiBUaGUgWlhpbmcgY29kZSByZWFkZXIuXG4gICAqL1xuICBwcml2YXRlIF9jb2RlUmVhZGVyOiBCcm93c2VyTXVsdGlGb3JtYXRDb250aW51b3VzUmVhZGVyO1xuXG4gIC8qKlxuICAgKiBUaGUgZGV2aWNlIHRoYXQgc2hvdWxkIGJlIHVzZWQgdG8gc2NhbiB0aGluZ3MuXG4gICAqL1xuICBwcml2YXRlIF9kZXZpY2U6IE1lZGlhRGV2aWNlSW5mbztcblxuICAvKipcbiAgICogVGhlIGRldmljZSB0aGF0IHNob3VsZCBiZSB1c2VkIHRvIHNjYW4gdGhpbmdzLlxuICAgKi9cbiAgcHJpdmF0ZSBfZW5hYmxlZDogYm9vbGVhbjtcblxuICAvKipcbiAgICpcbiAgICovXG4gIHByaXZhdGUgX2lzQXV0b3N0YXJ0aW5nOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBIYXMgYG5hdmlnYXRvcmAgYWNjZXNzLlxuICAgKi9cbiAgcHJpdmF0ZSBoYXNOYXZpZ2F0b3I6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFNheXMgaWYgc29tZSBuYXRpdmUgQVBJIGlzIHN1cHBvcnRlZC5cbiAgICovXG4gIHByaXZhdGUgaXNNZWRpYURldmljZXNTdXBvcnRlZDogYm9vbGVhbjtcblxuICAvKipcbiAgICogSWYgdGhlIHVzZXItYWdlbnQgYWxsb3dlZCB0aGUgdXNlIG9mIHRoZSBjYW1lcmEgb3Igbm90LlxuICAgKi9cbiAgcHJpdmF0ZSBoYXNQZXJtaXNzaW9uOiBib29sZWFuIHwgbnVsbDtcblxuICAvKipcbiAgICogUmVmZXJlbmNlIHRvIHRoZSBwcmV2aWV3IGVsZW1lbnQsIHNob3VsZCBiZSB0aGUgYHZpZGVvYCB0YWcuXG4gICAqL1xuICBAVmlld0NoaWxkKCdwcmV2aWV3JywgeyBzdGF0aWM6IHRydWUgfSlcbiAgcHJldmlld0VsZW1SZWY6IEVsZW1lbnRSZWY8SFRNTFZpZGVvRWxlbWVudD47XG5cbiAgLyoqXG4gICAqIEVuYWJsZSBvciBkaXNhYmxlIGF1dG9mb2N1cyBvZiB0aGUgY2FtZXJhIChtaWdodCBoYXZlIGFuIGltcGFjdCBvbiBwZXJmb3JtYW5jZSlcbiAgICovXG4gIEBJbnB1dCgpXG4gIGF1dG9mb2N1c0VuYWJsZWQ6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEVtaXRzIHdoZW4gYW5kIGlmIHRoZSBzY2FubmVyIGlzIGF1dG9zdGFydGVkLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIGF1dG9zdGFydGVkOiBFdmVudEVtaXR0ZXI8dm9pZD47XG5cbiAgLyoqXG4gICAqIFRydWUgZHVyaW5nIGF1dG9zdGFydCBhbmQgZmFsc2UgYWZ0ZXIuIEl0IHdpbGwgYmUgbnVsbCBpZiB3b24ndCBhdXRvc3RhcnQgYXQgYWxsLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIGF1dG9zdGFydGluZzogRXZlbnRFbWl0dGVyPGJvb2xlYW4gfCBudWxsPjtcblxuICAvKipcbiAgICogSWYgdGhlIHNjYW5uZXIgc2hvdWxkIGF1dG9zdGFydCB3aXRoIHRoZSBmaXJzdCBhdmFpbGFibGUgZGV2aWNlLlxuICAgKi9cbiAgQElucHV0KClcbiAgYXV0b3N0YXJ0OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBIb3cgdGhlIHByZXZpZXcgZWxlbWVudCBzaG91ZCBiZSBmaXQgaW5zaWRlIHRoZSA6aG9zdCBjb250YWluZXIuXG4gICAqL1xuICBASW5wdXQoKVxuICBwcmV2aWV3Rml0TW9kZTogJ2ZpbGwnIHwgJ2NvbnRhaW4nIHwgJ2NvdmVyJyB8ICdzY2FsZS1kb3duJyB8ICdub25lJyA9ICdjb3Zlcic7XG5cbiAgLyoqXG4gICAqIEVtaXR0cyBldmVudHMgd2hlbiB0aGUgdG9yY2ggY29tcGF0aWJpbGl0eSBpcyBjaGFuZ2VkLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIHRvcmNoQ29tcGF0aWJsZTogRXZlbnRFbWl0dGVyPGJvb2xlYW4+O1xuXG4gIC8qKlxuICAgKiBFbWl0dHMgZXZlbnRzIHdoZW4gYSBzY2FuIGlzIHN1Y2Nlc3NmdWwgcGVyZm9ybWVkLCB3aWxsIGluamVjdCB0aGUgc3RyaW5nIHZhbHVlIG9mIHRoZSBRUi1jb2RlIHRvIHRoZSBjYWxsYmFjay5cbiAgICovXG4gIEBPdXRwdXQoKVxuICBzY2FuU3VjY2VzczogRXZlbnRFbWl0dGVyPHN0cmluZz47XG5cbiAgLyoqXG4gICAqIEVtaXR0cyBldmVudHMgd2hlbiBhIHNjYW4gZmFpbHMgd2l0aG91dCBlcnJvcnMsIHVzZWZ1bGwgdG8ga25vdyBob3cgbXVjaCBzY2FuIHRyaWVzIHdoZXJlIG1hZGUuXG4gICAqL1xuICBAT3V0cHV0KClcbiAgc2NhbkZhaWx1cmU6IEV2ZW50RW1pdHRlcjxFeGNlcHRpb24gfCB1bmRlZmluZWQ+O1xuXG4gIC8qKlxuICAgKiBFbWl0dHMgZXZlbnRzIHdoZW4gYSBzY2FuIHRocm93cyBzb21lIGVycm9yLCB3aWxsIGluamVjdCB0aGUgZXJyb3IgdG8gdGhlIGNhbGxiYWNrLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIHNjYW5FcnJvcjogRXZlbnRFbWl0dGVyPEVycm9yPjtcblxuICAvKipcbiAgICogRW1pdHRzIGV2ZW50cyB3aGVuIGEgc2NhbiBpcyBwZXJmb3JtZWQsIHdpbGwgaW5qZWN0IHRoZSBSZXN1bHQgdmFsdWUgb2YgdGhlIFFSLWNvZGUgc2NhbiAoaWYgYXZhaWxhYmxlKSB0byB0aGUgY2FsbGJhY2suXG4gICAqL1xuICBAT3V0cHV0KClcbiAgc2NhbkNvbXBsZXRlOiBFdmVudEVtaXR0ZXI8UmVzdWx0PjtcblxuICAvKipcbiAgICogRW1pdHRzIGV2ZW50cyB3aGVuIG5vIGNhbWVyYXMgYXJlIGZvdW5kLCB3aWxsIGluamVjdCBhbiBleGNlcHRpb24gKGlmIGF2YWlsYWJsZSkgdG8gdGhlIGNhbGxiYWNrLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIGNhbWVyYXNGb3VuZDogRXZlbnRFbWl0dGVyPE1lZGlhRGV2aWNlSW5mb1tdPjtcblxuICAvKipcbiAgICogRW1pdHRzIGV2ZW50cyB3aGVuIG5vIGNhbWVyYXMgYXJlIGZvdW5kLCB3aWxsIGluamVjdCBhbiBleGNlcHRpb24gKGlmIGF2YWlsYWJsZSkgdG8gdGhlIGNhbGxiYWNrLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIGNhbWVyYXNOb3RGb3VuZDogRXZlbnRFbWl0dGVyPGFueT47XG5cbiAgLyoqXG4gICAqIEVtaXR0cyBldmVudHMgd2hlbiB0aGUgdXNlcnMgYW5zd2VycyBmb3IgcGVybWlzc2lvbi5cbiAgICovXG4gIEBPdXRwdXQoKVxuICBwZXJtaXNzaW9uUmVzcG9uc2U6IEV2ZW50RW1pdHRlcjxib29sZWFuPjtcblxuICAvKipcbiAgICogRW1pdHRzIGV2ZW50cyB3aGVuIGhhcyBkZXZpY2VzIHN0YXR1cyBpcyB1cGRhdGUuXG4gICAqL1xuICBAT3V0cHV0KClcbiAgaGFzRGV2aWNlczogRXZlbnRFbWl0dGVyPGJvb2xlYW4+O1xuXG4gIC8qKlxuICAgKiBFeHBvc2VzIHRoZSBjdXJyZW50IGNvZGUgcmVhZGVyLCBzbyB0aGUgdXNlciBjYW4gdXNlIGl0J3MgQVBJcy5cbiAgICovXG4gIGdldCBjb2RlUmVhZGVyKCk6IEJyb3dzZXJNdWx0aUZvcm1hdENvbnRpbnVvdXNSZWFkZXIge1xuICAgIHJldHVybiB0aGlzLl9jb2RlUmVhZGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZXIgZGV2aWNlIGlucHV0XG4gICAqL1xuICBASW5wdXQoKVxuICBzZXQgZGV2aWNlKGRldmljZTogTWVkaWFEZXZpY2VJbmZvIHwgbnVsbCkge1xuXG4gICAgaWYgKCFkZXZpY2UgJiYgZGV2aWNlICE9PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgQXJndW1lbnRFeGNlcHRpb24oJ1RoZSBgZGV2aWNlYCBtdXN0IGJlIGEgdmFsaWQgTWVkaWFEZXZpY2VJbmZvIG9yIG51bGwuJyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaXNDdXJyZW50RGV2aWNlKGRldmljZSkpIHtcbiAgICAgIGNvbnNvbGUud2FybignU2V0dGluZyB0aGUgc2FtZSBkZXZpY2UgaXMgbm90IGFsbG93ZWQuJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaXNBdXRvc3RhcnRpbmcpIHtcbiAgICAgIC8vIGRvIG5vdCBhbGxvdyBzZXR0aW5nIGRldmljZXMgZHVyaW5nIGF1dG8tc3RhcnQsIHNpbmNlIGl0IHdpbGwgc2V0IG9uZSBhbmQgZW1pdCBpdC5cbiAgICAgIGNvbnNvbGUud2FybignQXZvaWQgc2V0dGluZyBhIGRldmljZSBkdXJpbmcgYXV0by1zdGFydC4nKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaGFzUGVybWlzc2lvbikge1xuICAgICAgY29uc29sZS53YXJuKCdQZXJtaXNzaW9ucyBub3Qgc2V0IHlldCwgd2FpdGluZyBmb3IgdGhlbSB0byBiZSBzZXQgdG8gYXBwbHkgZGV2aWNlIGNoYW5nZS4nKTtcbiAgICAgIC8vIHRoaXMucGVybWlzc2lvblJlc3BvbnNlXG4gICAgICAvLyAgIC5waXBlKFxuICAgICAgLy8gICAgIHRha2UoMSksXG4gICAgICAvLyAgICAgdGFwKCgpID0+IGNvbnNvbGUubG9nKGBQZXJtaXNzaW9ucyBzZXQsIGFwcGx5aW5nIGRldmljZSBjaGFuZ2Uke2RldmljZSA/IGAgKCR7ZGV2aWNlLmRldmljZUlkfSlgIDogJyd9LmApKVxuICAgICAgLy8gICApXG4gICAgICAvLyAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5kZXZpY2UgPSBkZXZpY2UpO1xuICAgICAgLy8gcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGluIG9yZGVyIHRvIGNoYW5nZSB0aGUgZGV2aWNlIHRoZSBjb2RlUmVhZGVyIGdvdHRhIGJlIHJlc2V0ZWRcbiAgICB0aGlzLl9yZXNldCgpO1xuXG4gICAgdGhpcy5fZGV2aWNlID0gZGV2aWNlO1xuXG4gICAgLy8gaWYgZW5hYmxlZCwgc3RhcnRzIHNjYW5uaW5nXG4gICAgaWYgKHRoaXMuX2VuYWJsZWQgJiYgZGV2aWNlICE9PSBudWxsKSB7XG4gICAgICB0aGlzLnNjYW5Gcm9tRGV2aWNlKGRldmljZS5kZXZpY2VJZCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEVtaXRzIHdoZW4gdGhlIGN1cnJlbnQgZGV2aWNlIGlzIGNoYW5nZWQuXG4gICAqL1xuICBAT3V0cHV0KClcbiAgZGV2aWNlQ2hhbmdlOiBFdmVudEVtaXR0ZXI8TWVkaWFEZXZpY2VJbmZvPjtcblxuICAvKipcbiAgICogVXNlciBkZXZpY2UgYWNlc3Nvci5cbiAgICovXG4gIGdldCBkZXZpY2UoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2RldmljZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFsbCB0aGUgcmVnaXN0ZXJlZCBmb3JtYXRzLlxuICAgKi9cbiAgZ2V0IGZvcm1hdHMoKTogQmFyY29kZUZvcm1hdFtdIHtcbiAgICByZXR1cm4gdGhpcy5oaW50cy5nZXQoRGVjb2RlSGludFR5cGUuUE9TU0lCTEVfRk9STUFUUyk7XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXJzIGZvcm1hdHMgdGhlIHNjYW5uZXIgc2hvdWxkIHN1cHBvcnQuXG4gICAqXG4gICAqIEBwYXJhbSBpbnB1dCBCYXJjb2RlRm9ybWF0IG9yIGNhc2UtaW5zZW5zaXRpdmUgc3RyaW5nIGFycmF5LlxuICAgKi9cbiAgQElucHV0KClcbiAgc2V0IGZvcm1hdHMoaW5wdXQ6IEJhcmNvZGVGb3JtYXRbXSkge1xuXG4gICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBmb3JtYXRzLCBtYWtlIHN1cmUgdGhlIFtmb3JtYXRzXSBpbnB1dCBpcyBhIGJpbmRpbmcuJyk7XG4gICAgfVxuXG4gICAgLy8gZm9ybWF0cyBtYXkgYmUgc2V0IGZyb20gaHRtbCB0ZW1wbGF0ZSBhcyBCYXJjb2RlRm9ybWF0IG9yIHN0cmluZyBhcnJheVxuICAgIGNvbnN0IGZvcm1hdHMgPSBpbnB1dC5tYXAoZiA9PiB0aGlzLmdldEJhcmNvZGVGb3JtYXRPckZhaWwoZikpO1xuXG4gICAgY29uc3QgaGludHMgPSB0aGlzLmhpbnRzO1xuXG4gICAgLy8gdXBkYXRlcyB0aGUgaGludHNcbiAgICBoaW50cy5zZXQoRGVjb2RlSGludFR5cGUuUE9TU0lCTEVfRk9STUFUUywgZm9ybWF0cyk7XG5cbiAgICB0aGlzLmhpbnRzID0gaGludHM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbGwgdGhlIHJlZ2lzdGVyZWQgaGludHMuXG4gICAqL1xuICBnZXQgaGludHMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2hpbnRzO1xuICB9XG5cbiAgLyoqXG4gICAqIERvZXMgd2hhdCBpdCB0YWtlcyB0byBzZXQgdGhlIGhpbnRzLlxuICAgKi9cbiAgc2V0IGhpbnRzKGhpbnRzOiBNYXA8RGVjb2RlSGludFR5cGUsIGFueT4pIHtcblxuICAgIHRoaXMuX2hpbnRzID0gaGludHM7XG5cbiAgICAvLyBAbm90ZSBhdm9pZCByZXN0YXJ0aW5nIHRoZSBjb2RlIHJlYWRlciB3aGVuIHBvc3NpYmxlXG5cbiAgICAvLyBuZXcgaW5zdGFuY2Ugd2l0aCBuZXcgaGludHMuXG4gICAgdGhpcy5yZXN0YXJ0KCk7XG4gIH1cblxuICAvKipcbiAgICpcbiAgICovXG4gIHNldCBpc0F1dG9zdGFydGluZyhzdGF0ZTogYm9vbGVhbiB8IG51bGwpIHtcbiAgICB0aGlzLl9pc0F1dG9zdGFydGluZyA9IHN0YXRlO1xuICAgIHRoaXMuYXV0b3N0YXJ0aW5nLm5leHQoc3RhdGUpO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqL1xuICBnZXQgaXNBdXRzdGFydGluZygpOiBib29sZWFuIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuX2lzQXV0b3N0YXJ0aW5nO1xuICB9XG5cbiAgLyoqXG4gICAqIEFsbG93IHN0YXJ0IHNjYW4gb3Igbm90LlxuICAgKi9cbiAgQElucHV0KClcbiAgc2V0IHRvcmNoKG9uOiBib29sZWFuKSB7XG4gICAgdGhpcy5nZXRDb2RlUmVhZGVyKCkuc2V0VG9yY2gob24pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFsbG93IHN0YXJ0IHNjYW4gb3Igbm90LlxuICAgKi9cbiAgQElucHV0KClcbiAgc2V0IGVuYWJsZShlbmFibGVkOiBib29sZWFuKSB7XG5cbiAgICB0aGlzLl9lbmFibGVkID0gQm9vbGVhbihlbmFibGVkKTtcblxuICAgIGlmICghdGhpcy5fZW5hYmxlZCkge1xuICAgICAgdGhpcy5yZXNldCgpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5kZXZpY2UpIHtcbiAgICAgIHRoaXMuc2NhbkZyb21EZXZpY2UodGhpcy5kZXZpY2UuZGV2aWNlSWQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUZWxscyBpZiB0aGUgc2Nhbm5lciBpcyBlbmFibGVkIG9yIG5vdC5cbiAgICovXG4gIGdldCBlbmFibGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9lbmFibGVkO1xuICB9XG5cbiAgLyoqXG4gICAqIElmIGlzIGB0cnlIYXJkZXJgIGVuYWJsZWQuXG4gICAqL1xuICBnZXQgdHJ5SGFyZGVyKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmhpbnRzLmdldChEZWNvZGVIaW50VHlwZS5UUllfSEFSREVSKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGUvZGlzYWJsZSB0cnlIYXJkZXIgaGludC5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHNldCB0cnlIYXJkZXIoZW5hYmxlOiBib29sZWFuKSB7XG5cbiAgICBjb25zdCBoaW50cyA9IHRoaXMuaGludHM7XG5cbiAgICBpZiAoZW5hYmxlKSB7XG4gICAgICBoaW50cy5zZXQoRGVjb2RlSGludFR5cGUuVFJZX0hBUkRFUiwgdHJ1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGhpbnRzLmRlbGV0ZShEZWNvZGVIaW50VHlwZS5UUllfSEFSREVSKTtcbiAgICB9XG5cbiAgICB0aGlzLmhpbnRzID0gaGludHM7XG4gIH1cblxuICAvKipcbiAgICogQ29uc3RydWN0b3IgdG8gYnVpbGQgdGhlIG9iamVjdCBhbmQgZG8gc29tZSBESS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIC8vIGluc3RhbmNlIGJhc2VkIGVtaXR0ZXJzXG4gICAgdGhpcy5hdXRvc3RhcnRlZCA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICB0aGlzLmF1dG9zdGFydGluZyA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICB0aGlzLnRvcmNoQ29tcGF0aWJsZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICB0aGlzLnNjYW5TdWNjZXNzID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICAgIHRoaXMuc2NhbkZhaWx1cmUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgdGhpcy5zY2FuRXJyb3IgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgdGhpcy5zY2FuQ29tcGxldGUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgdGhpcy5jYW1lcmFzRm91bmQgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgdGhpcy5jYW1lcmFzTm90Rm91bmQgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgdGhpcy5wZXJtaXNzaW9uUmVzcG9uc2UgPSBuZXcgRXZlbnRFbWl0dGVyKHRydWUpO1xuICAgIHRoaXMuaGFzRGV2aWNlcyA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICB0aGlzLmRldmljZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIHRoaXMuX2RldmljZSA9IG51bGw7XG4gICAgdGhpcy5fZW5hYmxlZCA9IHRydWU7XG4gICAgdGhpcy5faGludHMgPSBuZXcgTWFwPERlY29kZUhpbnRUeXBlLCBhbnk+KCk7XG4gICAgdGhpcy5hdXRvZm9jdXNFbmFibGVkID0gdHJ1ZTtcbiAgICB0aGlzLmF1dG9zdGFydCA9IHRydWU7XG4gICAgdGhpcy5mb3JtYXRzID0gW0JhcmNvZGVGb3JtYXQuUVJfQ09ERV07XG5cbiAgICAvLyBjb21wdXRlZCBkYXRhXG4gICAgdGhpcy5oYXNOYXZpZ2F0b3IgPSB0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJztcbiAgICB0aGlzLmlzTWVkaWFEZXZpY2VzU3Vwb3J0ZWQgPSB0aGlzLmhhc05hdmlnYXRvciAmJiAhIW5hdmlnYXRvci5tZWRpYURldmljZXM7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBhbmQgcmVnaXN0ZXJzIGFsbCBjYW1tZXJhcy5cbiAgICovXG4gIGFzeW5jIGFza0ZvclBlcm1pc3Npb24oKTogUHJvbWlzZTxib29sZWFuPiB7XG5cbiAgICBpZiAoIXRoaXMuaGFzTmF2aWdhdG9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdAenhpbmcvbmd4LXNjYW5uZXInLCAnQ2FuXFwndCBhc2sgcGVybWlzc2lvbiwgbmF2aWdhdG9yIGlzIG5vdCBwcmVzZW50LicpO1xuICAgICAgdGhpcy5zZXRQZXJtaXNzaW9uKG51bGwpO1xuICAgICAgcmV0dXJuIHRoaXMuaGFzUGVybWlzc2lvbjtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaXNNZWRpYURldmljZXNTdXBvcnRlZCkge1xuICAgICAgY29uc29sZS5lcnJvcignQHp4aW5nL25neC1zY2FubmVyJywgJ0NhblxcJ3QgZ2V0IHVzZXIgbWVkaWEsIHRoaXMgaXMgbm90IHN1cHBvcnRlZC4nKTtcbiAgICAgIHRoaXMuc2V0UGVybWlzc2lvbihudWxsKTtcbiAgICAgIHJldHVybiB0aGlzLmhhc1Blcm1pc3Npb247XG4gICAgfVxuXG4gICAgbGV0IHN0cmVhbTogTWVkaWFTdHJlYW07XG4gICAgbGV0IHBlcm1pc3Npb246IGJvb2xlYW47XG5cbiAgICB0cnkge1xuICAgICAgLy8gV2lsbCB0cnkgdG8gYXNrIGZvciBwZXJtaXNzaW9uXG4gICAgICBzdHJlYW0gPSBhd2FpdCB0aGlzLmdldEFueVZpZGVvRGV2aWNlKCk7XG4gICAgICBwZXJtaXNzaW9uID0gISFzdHJlYW07XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVQZXJtaXNzaW9uRXhjZXB0aW9uKGVycik7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMudGVybWluYXRlU3RyZWFtKHN0cmVhbSk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXRQZXJtaXNzaW9uKHBlcm1pc3Npb24pO1xuXG4gICAgLy8gUmV0dXJucyB0aGUgcGVybWlzc2lvblxuICAgIHJldHVybiBwZXJtaXNzaW9uO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqL1xuICBnZXRBbnlWaWRlb0RldmljZSgpOiBQcm9taXNlPE1lZGlhU3RyZWFtPiB7XG4gICAgcmV0dXJuIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKHsgdmlkZW86IHRydWUgfSk7XG4gIH1cblxuICAvKipcbiAgICogVGVybWluYXRlcyBhIHN0cmVhbSBhbmQgaXQncyB0cmFja3MuXG4gICAqL1xuICBwcml2YXRlIHRlcm1pbmF0ZVN0cmVhbShzdHJlYW06IE1lZGlhU3RyZWFtKSB7XG5cbiAgICBpZiAoc3RyZWFtKSB7XG4gICAgICBzdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaCh0ID0+IHQuc3RvcCgpKTtcbiAgICB9XG5cbiAgICBzdHJlYW0gPSB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZXMgdGhlIGNvbXBvbmVudCB3aX