webglimpse
Version:
Webglimpse is a data visualization library for the web.
295 lines • 39.5 kB
JavaScript
/*
* Copyright (c) 2014, Metron, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { GL, getObjectId, hasval } from './util/util';
function compileShader(gl, shaderType, glsl) {
const shader = gl.createShader(shaderType);
gl.shaderSource(shader, glsl);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, GL.COMPILE_STATUS)) {
throw new Error(gl.getShaderInfoLog(shader));
}
return shader;
}
function linkProgram(gl, shaders) {
const program = gl.createProgram();
for (let i = 0; i < shaders.length; i++) {
gl.attachShader(program, shaders[i]);
}
try {
gl.linkProgram(program);
if (!gl.getProgramParameter(program, GL.LINK_STATUS)) {
throw new Error(gl.getProgramInfoLog(program));
}
return program;
}
finally {
// It's good GL practice to detach and delete shaders after they have been linked
// into a program, and are no longer needed. However, on some versions of Firefox,
// doing so causes getAttribLocation and getUniformLocation to fail.
//
// for ( var i = 0; i < shaders.length; i++ ) {
// gl.detachShader( program, shaders[ i ] );
// }
}
}
function createProgram(gl, vertShaderSource, fragShaderSource) {
const shaders = [];
try {
shaders.push(compileShader(gl, GL.VERTEX_SHADER, vertShaderSource));
shaders.push(compileShader(gl, GL.FRAGMENT_SHADER, fragShaderSource));
return linkProgram(gl, shaders);
}
finally {
// It's good GL practice to detach and delete shaders after they have been linked
// into a program, and are no longer needed. However, on some versions of Firefox,
// doing so causes getAttribLocation and getUniformLocation to fail.
//
// for ( var i = 0; i < shaders.length; i++ ) {
// gl.deleteShader( shaders[ i ] );
// }
}
}
class ProgramEntry {
constructor(gl, program) {
this.gl = gl;
this.program = program;
}
}
export class Program {
constructor(vertShaderSource, fragShaderSource) {
this.programs = {};
this.vertShaderSource = vertShaderSource;
this.fragShaderSource = fragShaderSource;
}
// XXX: Would be nice if this weren't public
_program(gl) {
const glId = getObjectId(gl);
if (this.programs[glId] === undefined) {
const program = createProgram(gl, this.vertShaderSource, this.fragShaderSource);
this.programs[glId] = new ProgramEntry(gl, program);
}
return this.programs[glId].program;
}
use(gl) {
gl.useProgram(this._program(gl));
}
endUse(gl) {
gl.useProgram(null);
}
dispose() {
// XXX: Not sure this actually works ... may have to make each gl current or something
for (const glid in this.programs) {
if (this.programs.hasOwnProperty(glid)) {
const en = this.programs[glid];
en.gl.deleteProgram(en.program);
}
}
this.programs = {};
}
}
export class Uniform {
constructor(program, name, optional) {
this.locations = {};
this.program = program;
this.name = name;
this.optional = optional;
}
// XXX: Would be nice if this weren't public
_location(gl) {
const glId = getObjectId(gl);
if (this.locations[glId] === undefined) {
const location = gl.getUniformLocation(this.program._program(gl), this.name);
if (!this.optional && !hasval(location)) {
throw new Error('Uniform \'' + this.name + '\' not found');
}
this.locations[glId] = location;
}
return this.locations[glId];
}
}
export class Uniform1f extends Uniform {
constructor(program, name, optional = false) {
super(program, name, optional);
}
setData(gl, x) {
const location = this._location(gl);
if (hasval(location)) {
gl.uniform1f(location, x);
}
}
}
export class Uniform2f extends Uniform {
constructor(program, name, optional = false) {
super(program, name, optional);
}
setData(gl, x, y) {
const location = this._location(gl);
if (hasval(location)) {
gl.uniform2f(location, x, y);
}
}
}
export class Uniform3f extends Uniform {
constructor(program, name, optional = false) {
super(program, name, optional);
}
setData(gl, x, y, z) {
const location = this._location(gl);
if (hasval(location)) {
gl.uniform3f(location, x, y, z);
}
}
}
export class Uniform4f extends Uniform {
constructor(program, name, optional = false) {
super(program, name, optional);
}
setData(gl, x, y, z, w) {
const location = this._location(gl);
if (hasval(location)) {
gl.uniform4f(location, x, y, z, w);
}
}
}
export class UniformMatrix4f extends Uniform {
constructor(program, name, optional = false) {
super(program, name, optional);
}
setData(gl, value, transpose = false) {
const location = this._location(gl);
if (hasval(location)) {
gl.uniformMatrix4fv(location, transpose, value);
}
}
}
export class Uniform1i extends Uniform {
constructor(program, name, optional = false) {
super(program, name, optional);
}
setData(gl, x) {
const location = this._location(gl);
if (hasval(location)) {
gl.uniform1i(location, x);
}
}
}
export class Uniform2i extends Uniform {
constructor(program, name, optional = false) {
super(program, name, optional);
}
setData(gl, x, y) {
const location = this._location(gl);
if (hasval(location)) {
gl.uniform2i(location, x, y);
}
}
}
export class Uniform3i extends Uniform {
constructor(program, name, optional = false) {
super(program, name, optional);
}
setData(gl, x, y, z) {
const location = this._location(gl);
if (hasval(location)) {
gl.uniform3i(location, x, y, z);
}
}
}
export class Uniform4i extends Uniform {
constructor(program, name, optional = false) {
super(program, name, optional);
}
setData(gl, x, y, z, w) {
const location = this._location(gl);
if (hasval(location)) {
gl.uniform4i(location, x, y, z, w);
}
}
}
export class UniformColor extends Uniform {
constructor(program, name, optional = false) {
super(program, name, optional);
}
setData(gl, color) {
const location = this._location(gl);
if (hasval(location)) {
gl.uniform4f(location, color.r, color.g, color.b, color.a);
}
}
}
export class UniformSampler2D extends Uniform {
constructor(program, name, optional = false) {
super(program, name, optional);
}
setDataAndBind(gl, textureUnit, texture) {
const location = this._location(gl);
if (hasval(location)) {
texture.bind(gl, textureUnit);
gl.uniform1i(location, textureUnit);
this.currentTexture = texture;
}
}
unbind(gl) {
if (hasval(this.currentTexture)) {
this.currentTexture.unbind(gl);
this.currentTexture = null;
}
}
}
export class Attribute {
constructor(program, name) {
this.locations = {};
this.program = program;
this.name = name;
}
// XXX: Would be nice if this weren't public
_location(gl) {
const glId = getObjectId(gl);
if (this.locations[glId] === undefined) {
const location = gl.getAttribLocation(this.program._program(gl), this.name);
if (location === -1) {
throw new Error('Attribute "' + this.name + '" not found');
}
this.locations[glId] = location;
}
return this.locations[glId];
}
setDataAndEnable(gl, buffer, size, type, normalized = false, stride = 0, offset = 0) {
const location = this._location(gl);
gl.enableVertexAttribArray(location);
buffer.bind(gl, GL.ARRAY_BUFFER);
gl.vertexAttribPointer(location, size, type, normalized, stride, offset);
buffer.unbind(gl, GL.ARRAY_BUFFER);
}
disable(gl) {
gl.disableVertexAttribArray(this._location(gl));
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3dlYmdsaW1wc2Uvc2hhZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNEJHO0FBQ0gsT0FBTyxFQUFFLEVBQUUsRUFBYSxXQUFXLEVBQUUsTUFBTSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBS2pFLFNBQVMsYUFBYSxDQUFDLEVBQXlCLEVBQUUsVUFBa0IsRUFBRSxJQUFZO0lBQzlFLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDM0MsRUFBRSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFFOUIsRUFBRSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN6QixJQUFJLENBQUMsRUFBRSxDQUFDLGtCQUFrQixDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsY0FBYyxDQUFDLEVBQUU7UUFDbkQsTUFBTSxJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztLQUNoRDtJQUVELE9BQU8sTUFBTSxDQUFDO0FBQ2xCLENBQUM7QUFFRCxTQUFTLFdBQVcsQ0FBQyxFQUF5QixFQUFFLE9BQXNCO0lBQ2xFLE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUNuQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUNyQyxFQUFFLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUN4QztJQUNELElBQUk7UUFDQSxFQUFFLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3hCLElBQUksQ0FBQyxFQUFFLENB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QUksUUFBUSxLQUFLLENBQUMsQ0FBQyxFQUFFO2dCQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsSUFBSSxHQUFHLGFBQWEsQ0FBQyxDQUFDO2FBQzlEO1lBQ0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsR0FBRyxRQUFRLENBQUM7U0FDbkM7UUFDRCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVELGdCQUFnQixDQUFDLEVBQXlCLEVBQUUsTUFBYyxFQUFFLElBQVksRUFBRSxJQUFZLEVBQUUsYUFBc0IsS0FBSyxFQUFFLFNBQWlCLENBQUMsRUFBRSxTQUFpQixDQUFDO1FBQ3ZKLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDcEMsRUFBRSxDQUFDLHVCQUF1QixDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNqQyxFQUFFLENBQUMsbUJBQW1CLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztRQUN6RSxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVELE9BQU8sQ0FBQyxFQUF5QjtRQUM3QixFQUFFLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3BELENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbIi8qXHJcbiAqIENvcHlyaWdodCAoYykgMjAxNCwgTWV0cm9uLCBJbmMuXHJcbiAqIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqXHJcbiAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXHJcbiAqIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcclxuICpcclxuICogMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXHJcbiAqICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxyXG4gKlxyXG4gKiAyLiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXHJcbiAqICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb25cclxuICogICAgYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXHJcbiAqXHJcbiAqIDMuIE5laXRoZXIgdGhlIG5hbWUgb2YgdGhlIGNvcHlyaWdodCBob2xkZXIgbm9yIHRoZSBuYW1lcyBvZiBpdHMgY29udHJpYnV0b3JzXHJcbiAqICAgIG1heSBiZSB1c2VkIHRvIGVuZG9yc2Ugb3IgcHJvbW90ZSBwcm9kdWN0cyBkZXJpdmVkIGZyb20gdGhpcyBzb2Z0d2FyZSB3aXRob3V0XHJcbiAqICAgIHNwZWNpZmljIHByaW9yIHdyaXR0ZW4gcGVybWlzc2lvbi5cclxuICpcclxuICogVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXHJcbiAqIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXHJcbiAqIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcclxuICogRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcclxuICogQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXHJcbiAqIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcclxuICogTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXHJcbiAqIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXHJcbiAqIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXHJcbiAqIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxyXG4gKi9cclxuaW1wb3J0IHsgR0wsIFN0cmluZ01hcCwgZ2V0T2JqZWN0SWQsIGhhc3ZhbCB9IGZyb20gJy4vdXRpbC91dGlsJztcclxuaW1wb3J0IHsgQ29sb3IgfSBmcm9tICcuL2NvbG9yJztcclxuaW1wb3J0IHsgVGV4dHVyZSB9IGZyb20gJy4vdGV4dHVyZSc7XHJcbmltcG9ydCB7IEJ1ZmZlciB9IGZyb20gJy4vYnVmZmVyJztcclxuXHJcbmZ1bmN0aW9uIGNvbXBpbGVTaGFkZXIoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgc2hhZGVyVHlwZTogbnVtYmVyLCBnbHNsOiBzdHJpbmcpOiBXZWJHTFNoYWRlciB7XHJcbiAgICBjb25zdCBzaGFkZXIgPSBnbC5jcmVhdGVTaGFkZXIoc2hhZGVyVHlwZSk7XHJcbiAgICBnbC5zaGFkZXJTb3VyY2Uoc2hhZGVyLCBnbHNsKTtcclxuXHJcbiAgICBnbC5jb21waWxlU2hhZGVyKHNoYWRlcik7XHJcbiAgICBpZiAoIWdsLmdldFNoYWRlclBhcmFtZXRlcihzaGFkZXIsIEdMLkNPTVBJTEVfU1RBVFVTKSkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihnbC5nZXRTaGFkZXJJbmZvTG9nKHNoYWRlcikpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBzaGFkZXI7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGxpbmtQcm9ncmFtKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIHNoYWRlcnM6IFdlYkdMU2hhZGVyW10pOiBXZWJHTFByb2dyYW0ge1xyXG4gICAgY29uc3QgcHJvZ3JhbSA9IGdsLmNyZWF0ZVByb2dyYW0oKTtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2hhZGVycy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIGdsLmF0dGFjaFNoYWRlcihwcm9ncmFtLCBzaGFkZXJzW2ldKTtcclxuICAgIH1cclxuICAgIHRyeSB7XHJcbiAgICAgICAgZ2wubGlua1Byb2dyYW0ocHJvZ3JhbSk7XHJcbiAgICAgICAgaWYgKCFnbC5nZXRQcm9ncmFtUGFyYW1ldGVyKHByb2dyYW0sIEdMLkxJTktfU1RBVFVTKSkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZ2wuZ2V0UHJvZ3JhbUluZm9Mb2cocHJvZ3JhbSkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gcHJvZ3JhbTtcclxuICAgIH1cclxuICAgIGZpbmFsbHkge1xyXG4gICAgICAgIC8vIEl0J3MgZ29vZCBHTCBwcmFjdGljZSB0byBkZXRhY2ggYW5kIGRlbGV0ZSBzaGFkZXJzIGFmdGVyIHRoZXkgaGF2ZSBiZWVuIGxpbmtlZFxyXG4gICAgICAgIC8vIGludG8gYSBwcm9ncmFtLCBhbmQgYXJlIG5vIGxvbmdlciBuZWVkZWQuIEhvd2V2ZXIsIG9uIHNvbWUgdmVyc2lvbnMgb2YgRmlyZWZveCxcclxuICAgICAgICAvLyBkb2luZyBzbyBjYXVzZXMgZ2V0QXR0cmliTG9jYXRpb24gYW5kIGdldFVuaWZvcm1Mb2NhdGlvbiB0byBmYWlsLlxyXG4gICAgICAgIC8vXHJcbiAgICAgICAgLy8gZm9yICggdmFyIGkgPSAwOyBpIDwgc2hhZGVycy5sZW5ndGg7IGkrKyApIHtcclxuICAgICAgICAvLyAgICBnbC5kZXRhY2hTaGFkZXIoIHByb2dyYW0sIHNoYWRlcnNbIGkgXSApO1xyXG4gICAgICAgIC8vIH1cclxuICAgIH1cclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlUHJvZ3JhbShnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCB2ZXJ0U2hhZGVyU291cmNlOiBzdHJpbmcsIGZyYWdTaGFkZXJTb3VyY2U6IHN0cmluZyk6IFdlYkdMUHJvZ3JhbSB7XHJcbiAgICBjb25zdCBzaGFkZXJzID0gW107XHJcbiAgICB0cnkge1xyXG4gICAgICAgIHNoYWRlcnMucHVzaChjb21waWxlU2hhZGVyKGdsLCBHTC5WRVJURVhfU0hBREVSLCB2ZXJ0U2hhZGVyU291cmNlKSk7XHJcbiAgICAgICAgc2hhZGVycy5wdXNoKGNvbXBpbGVTaGFkZXIoZ2wsIEdMLkZSQUdNRU5UX1NIQURFUiwgZnJhZ1NoYWRlclNvdXJjZSkpO1xyXG4gICAgICAgIHJldHVybiBsaW5rUHJvZ3JhbShnbCwgc2hhZGVycyk7XHJcbiAgICB9XHJcbiAgICBmaW5hbGx5IHtcclxuICAgICAgICAvLyBJdCdzIGdvb2QgR0wgcHJhY3RpY2UgdG8gZGV0YWNoIGFuZCBkZWxldGUgc2hhZGVycyBhZnRlciB0aGV5IGhhdmUgYmVlbiBsaW5rZWRcclxuICAgICAgICAvLyBpbnRvIGEgcHJvZ3JhbSwgYW5kIGFyZSBubyBsb25nZXIgbmVlZGVkLiBIb3dldmVyLCBvbiBzb21lIHZlcnNpb25zIG9mIEZpcmVmb3gsXHJcbiAgICAgICAgLy8gZG9pbmcgc28gY2F1c2VzIGdldEF0dHJpYkxvY2F0aW9uIGFuZCBnZXRVbmlmb3JtTG9jYXRpb24gdG8gZmFpbC5cclxuICAgICAgICAvL1xyXG4gICAgICAgIC8vIGZvciAoIHZhciBpID0gMDsgaSA8IHNoYWRlcnMubGVuZ3RoOyBpKysgKSB7XHJcbiAgICAgICAgLy8gICAgZ2wuZGVsZXRlU2hhZGVyKCBzaGFkZXJzWyBpIF0gKTtcclxuICAgICAgICAvLyB9XHJcbiAgICB9XHJcbn1cclxuXHJcblxyXG5jbGFzcyBQcm9ncmFtRW50cnkge1xyXG4gICAgZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dDtcclxuICAgIHByb2dyYW06IFdlYkdMUHJvZ3JhbTtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCBwcm9ncmFtOiBXZWJHTFByb2dyYW0pIHtcclxuICAgICAgICB0aGlzLmdsID0gZ2w7XHJcbiAgICAgICAgdGhpcy5wcm9ncmFtID0gcHJvZ3JhbTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIFByb2dyYW0ge1xyXG4gICAgcHJpdmF0ZSB2ZXJ0U2hhZGVyU291cmNlOiBzdHJpbmc7XHJcbiAgICBwcml2YXRlIGZyYWdTaGFkZXJTb3VyY2U6IHN0cmluZztcclxuICAgIHByaXZhdGUgcHJvZ3JhbXM6IFN0cmluZ01hcDxQcm9ncmFtRW50cnk+ID0ge307XHJcblxyXG4gICAgY29uc3RydWN0b3IodmVydFNoYWRlclNvdXJjZTogc3RyaW5nLCBmcmFnU2hhZGVyU291cmNlOiBzdHJpbmcpIHtcclxuICAgICAgICB0aGlzLnZlcnRTaGFkZXJTb3VyY2UgPSB2ZXJ0U2hhZGVyU291cmNlO1xyXG4gICAgICAgIHRoaXMuZnJhZ1NoYWRlclNvdXJjZSA9IGZyYWdTaGFkZXJTb3VyY2U7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gWFhYOiBXb3VsZCBiZSBuaWNlIGlmIHRoaXMgd2VyZW4ndCBwdWJsaWNcclxuICAgIF9wcm9ncmFtKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQpOiBXZWJHTFByb2dyYW0ge1xyXG4gICAgICAgIGNvbnN0IGdsSWQgPSBnZXRPYmplY3RJZChnbCk7XHJcbiAgICAgICAgaWYgKHRoaXMucHJvZ3JhbXNbZ2xJZF0gPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICBjb25zdCBwcm9ncmFtID0gY3JlYXRlUHJvZ3JhbShnbCwgdGhpcy52ZXJ0U2hhZGVyU291cmNlLCB0aGlzLmZyYWdTaGFkZXJTb3VyY2UpO1xyXG4gICAgICAgICAgICB0aGlzLnByb2dyYW1zW2dsSWRdID0gbmV3IFByb2dyYW1FbnRyeShnbCwgcHJvZ3JhbSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzLnByb2dyYW1zW2dsSWRdLnByb2dyYW07XHJcbiAgICB9XHJcblxyXG4gICAgdXNlKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQpIHtcclxuICAgICAgICBnbC51c2VQcm9ncmFtKHRoaXMuX3Byb2dyYW0oZ2wpKTtcclxuICAgIH1cclxuXHJcbiAgICBlbmRVc2UoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCkge1xyXG4gICAgICAgIGdsLnVzZVByb2dyYW0obnVsbCk7XHJcbiAgICB9XHJcblxyXG4gICAgZGlzcG9zZSgpIHtcclxuICAgICAgICAvLyBYWFg6IE5vdCBzdXJlIHRoaXMgYWN0dWFsbHkgd29ya3MgLi4uIG1heSBoYXZlIHRvIG1ha2UgZWFjaCBnbCBjdXJyZW50IG9yIHNvbWV0aGluZ1xyXG4gICAgICAgIGZvciAoY29uc3QgZ2xpZCBpbiB0aGlzLnByb2dyYW1zKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLnByb2dyYW1zLmhhc093blByb3BlcnR5KGdsaWQpKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBlbiA9IHRoaXMucHJvZ3JhbXNbZ2xpZF07XHJcbiAgICAgICAgICAgICAgICBlbi5nbC5kZWxldGVQcm9ncmFtKGVuLnByb2dyYW0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMucHJvZ3JhbXMgPSB7fTtcclxuICAgIH1cclxufVxyXG5cclxuXHJcbmV4cG9ydCBjbGFzcyBVbmlmb3JtIHtcclxuICAgIHByaXZhdGUgcHJvZ3JhbTogUHJvZ3JhbTtcclxuICAgIHByaXZhdGUgbmFtZTogc3RyaW5nO1xyXG4gICAgcHJpdmF0ZSBvcHRpb25hbDogYm9vbGVhbjtcclxuICAgIHByaXZhdGUgbG9jYXRpb25zOiBTdHJpbmdNYXA8V2ViR0xVbmlmb3JtTG9jYXRpb24+ID0ge307XHJcblxyXG4gICAgY29uc3RydWN0b3IocHJvZ3JhbTogUHJvZ3JhbSwgbmFtZTogc3RyaW5nLCBvcHRpb25hbDogYm9vbGVhbikge1xyXG4gICAgICAgIHRoaXMucHJvZ3JhbSA9IHByb2dyYW07XHJcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcclxuICAgICAgICB0aGlzLm9wdGlvbmFsID0gb3B0aW9uYWw7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gWFhYOiBXb3VsZCBiZSBuaWNlIGlmIHRoaXMgd2VyZW4ndCBwdWJsaWNcclxuICAgIF9sb2NhdGlvbihnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0KTogV2ViR0xVbmlmb3JtTG9jYXRpb24ge1xyXG4gICAgICAgIGNvbnN0IGdsSWQgPSBnZXRPYmplY3RJZChnbCk7XHJcbiAgICAgICAgaWYgKHRoaXMubG9jYXRpb25zW2dsSWRdID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgY29uc3QgbG9jYXRpb24gPSBnbC5nZXRVbmlmb3JtTG9jYXRpb24odGhpcy5wcm9ncmFtLl9wcm9ncmFtKGdsKSwgdGhpcy5uYW1lKTtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLm9wdGlvbmFsICYmICFoYXN2YWwobG9jYXRpb24pKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuaWZvcm0gXFwnJyArIHRoaXMubmFtZSArICdcXCcgbm90IGZvdW5kJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy5sb2NhdGlvbnNbZ2xJZF0gPSBsb2NhdGlvbjtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXMubG9jYXRpb25zW2dsSWRdO1xyXG4gICAgfVxyXG59XHJcblxyXG5cclxuZXhwb3J0IGNsYXNzIFVuaWZvcm0xZiBleHRlbmRzIFVuaWZvcm0ge1xyXG4gICAgY29uc3RydWN0b3IocHJvZ3JhbTogUHJvZ3JhbSwgbmFtZTogc3RyaW5nLCBvcHRpb25hbDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICAgICAgc3VwZXIocHJvZ3JhbSwgbmFtZSwgb3B0aW9uYWwpO1xyXG4gICAgfVxyXG5cclxuICAgIHNldERhdGEoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgeDogbnVtYmVyKSB7XHJcbiAgICAgICAgY29uc3QgbG9jYXRpb24gPSB0aGlzLl9sb2NhdGlvbihnbCk7XHJcbiAgICAgICAgaWYgKGhhc3ZhbChsb2NhdGlvbikpIHtcclxuICAgICAgICAgICAgZ2wudW5pZm9ybTFmKGxvY2F0aW9uLCB4KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCBjbGFzcyBVbmlmb3JtMmYgZXh0ZW5kcyBVbmlmb3JtIHtcclxuICAgIGNvbnN0cnVjdG9yKHByb2dyYW06IFByb2dyYW0sIG5hbWU6IHN0cmluZywgb3B0aW9uYWw6IGJvb2xlYW4gPSBmYWxzZSkge1xyXG4gICAgICAgIHN1cGVyKHByb2dyYW0sIG5hbWUsIG9wdGlvbmFsKTtcclxuICAgIH1cclxuXHJcbiAgICBzZXREYXRhKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIHg6IG51bWJlciwgeTogbnVtYmVyKSB7XHJcbiAgICAgICAgY29uc3QgbG9jYXRpb24gPSB0aGlzLl9sb2NhdGlvbihnbCk7XHJcbiAgICAgICAgaWYgKGhhc3ZhbChsb2NhdGlvbikpIHtcclxuICAgICAgICAgICAgZ2wudW5pZm9ybTJmKGxvY2F0aW9uLCB4LCB5KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCBjbGFzcyBVbmlmb3JtM2YgZXh0ZW5kcyBVbmlmb3JtIHtcclxuICAgIGNvbnN0cnVjdG9yKHByb2dyYW06IFByb2dyYW0sIG5hbWU6IHN0cmluZywgb3B0aW9uYWw6IGJvb2xlYW4gPSBmYWxzZSkge1xyXG4gICAgICAgIHN1cGVyKHByb2dyYW0sIG5hbWUsIG9wdGlvbmFsKTtcclxuICAgIH1cclxuXHJcbiAgICBzZXREYXRhKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIHg6IG51bWJlciwgeTogbnVtYmVyLCB6OiBudW1iZXIpIHtcclxuICAgICAgICBjb25zdCBsb2NhdGlvbiA9IHRoaXMuX2xvY2F0aW9uKGdsKTtcclxuICAgICAgICBpZiAoaGFzdmFsKGxvY2F0aW9uKSkge1xyXG4gICAgICAgICAgICBnbC51bmlmb3JtM2YobG9jYXRpb24sIHgsIHksIHopO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIFVuaWZvcm00ZiBleHRlbmRzIFVuaWZvcm0ge1xyXG4gICAgY29uc3RydWN0b3IocHJvZ3JhbTogUHJvZ3JhbSwgbmFtZTogc3RyaW5nLCBvcHRpb25hbDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICAgICAgc3VwZXIocHJvZ3JhbSwgbmFtZSwgb3B0aW9uYWwpO1xyXG4gICAgfVxyXG5cclxuICAgIHNldERhdGEoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgeDogbnVtYmVyLCB5OiBudW1iZXIsIHo6IG51bWJlciwgdzogbnVtYmVyKSB7XHJcbiAgICAgICAgY29uc3QgbG9jYXRpb24gPSB0aGlzLl9sb2NhdGlvbihnbCk7XHJcbiAgICAgICAgaWYgKGhhc3ZhbChsb2NhdGlvbikpIHtcclxuICAgICAgICAgICAgZ2wudW5pZm9ybTRmKGxvY2F0aW9uLCB4LCB5LCB6LCB3KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCBjbGFzcyBVbmlmb3JtTWF0cml4NGYgZXh0ZW5kcyBVbmlmb3JtIHtcclxuICAgIGNvbnN0cnVjdG9yKHByb2dyYW06IFByb2dyYW0sIG5hbWU6IHN0cmluZywgb3B0aW9uYWw6IGJvb2xlYW4gPSBmYWxzZSkge1xyXG4gICAgICAgIHN1cGVyKHByb2dyYW0sIG5hbWUsIG9wdGlvbmFsKTtcclxuICAgIH1cclxuXHJcbiAgICBzZXREYXRhKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIHZhbHVlOiBGbG9hdDMyQXJyYXksIHRyYW5zcG9zZTogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICAgICAgY29uc3QgbG9jYXRpb24gPSB0aGlzLl9sb2NhdGlvbihnbCk7XHJcbiAgICAgICAgaWYgKGhhc3ZhbChsb2NhdGlvbikpIHtcclxuICAgICAgICAgICAgZ2wudW5pZm9ybU1hdHJpeDRmdihsb2NhdGlvbiwgdHJhbnNwb3NlLCB2YWx1ZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgVW5pZm9ybTFpIGV4dGVuZHMgVW5pZm9ybSB7XHJcbiAgICBjb25zdHJ1Y3Rvcihwcm9ncmFtOiBQcm9ncmFtLCBuYW1lOiBzdHJpbmcsIG9wdGlvbmFsOiBib29sZWFuID0gZmFsc2UpIHtcclxuICAgICAgICBzdXBlcihwcm9ncmFtLCBuYW1lLCBvcHRpb25hbCk7XHJcbiAgICB9XHJcblxyXG4gICAgc2V0RGF0YShnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCB4OiBudW1iZXIpIHtcclxuICAgICAgICBjb25zdCBsb2NhdGlvbiA9IHRoaXMuX2xvY2F0aW9uKGdsKTtcclxuICAgICAgICBpZiAoaGFzdmFsKGxvY2F0aW9uKSkge1xyXG4gICAgICAgICAgICBnbC51bmlmb3JtMWkobG9jYXRpb24sIHgpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIFVuaWZvcm0yaSBleHRlbmRzIFVuaWZvcm0ge1xyXG4gICAgY29uc3RydWN0b3IocHJvZ3JhbTogUHJvZ3JhbSwgbmFtZTogc3RyaW5nLCBvcHRpb25hbDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICAgICAgc3VwZXIocHJvZ3JhbSwgbmFtZSwgb3B0aW9uYWwpO1xyXG4gICAgfVxyXG5cclxuICAgIHNldERhdGEoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgeDogbnVtYmVyLCB5OiBudW1iZXIpIHtcclxuICAgICAgICBjb25zdCBsb2NhdGlvbiA9IHRoaXMuX2xvY2F0aW9uKGdsKTtcclxuICAgICAgICBpZiAoaGFzdmFsKGxvY2F0aW9uKSkge1xyXG4gICAgICAgICAgICBnbC51bmlmb3JtMmkobG9jYXRpb24sIHgsIHkpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIFVuaWZvcm0zaSBleHRlbmRzIFVuaWZvcm0ge1xyXG4gICAgY29uc3RydWN0b3IocHJvZ3JhbTogUHJvZ3JhbSwgbmFtZTogc3RyaW5nLCBvcHRpb25hbDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICAgICAgc3VwZXIocHJvZ3JhbSwgbmFtZSwgb3B0aW9uYWwpO1xyXG4gICAgfVxyXG5cclxuICAgIHNldERhdGEoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgeDogbnVtYmVyLCB5OiBudW1iZXIsIHo6IG51bWJlcikge1xyXG4gICAgICAgIGNvbnN0IGxvY2F0aW9uID0gdGhpcy5fbG9jYXRpb24oZ2wpO1xyXG4gICAgICAgIGlmIChoYXN2YWwobG9jYXRpb24pKSB7XHJcbiAgICAgICAgICAgIGdsLnVuaWZvcm0zaShsb2NhdGlvbiwgeCwgeSwgeik7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgVW5pZm9ybTRpIGV4dGVuZHMgVW5pZm9ybSB7XHJcbiAgICBjb25zdHJ1Y3Rvcihwcm9ncmFtOiBQcm9ncmFtLCBuYW1lOiBzdHJpbmcsIG9wdGlvbmFsOiBib29sZWFuID0gZmFsc2UpIHtcclxuICAgICAgICBzdXBlcihwcm9ncmFtLCBuYW1lLCBvcHRpb25hbCk7XHJcbiAgICB9XHJcblxyXG4gICAgc2V0RGF0YShnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCB4OiBudW1iZXIsIHk6IG51bWJlciwgejogbnVtYmVyLCB3OiBudW1iZXIpIHtcclxuICAgICAgICBjb25zdCBsb2NhdGlvbiA9IHRoaXMuX2xvY2F0aW9uKGdsKTtcclxuICAgICAgICBpZiAoaGFzdmFsKGxvY2F0aW9uKSkge1xyXG4gICAgICAgICAgICBnbC51bmlmb3JtNGkobG9jYXRpb24sIHgsIHksIHosIHcpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIFVuaWZvcm1Db2xvciBleHRlbmRzIFVuaWZvcm0ge1xyXG4gICAgY29uc3RydWN0b3IocHJvZ3JhbTogUHJvZ3JhbSwgbmFtZTogc3RyaW5nLCBvcHRpb25hbDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICAgICAgc3VwZXIocHJvZ3JhbSwgbmFtZSwgb3B0aW9uYWwpO1xyXG4gICAgfVxyXG5cclxuICAgIHNldERhdGEoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgY29sb3I6IENvbG9yKSB7XHJcbiAgICAgICAgY29uc3QgbG9jYXRpb24gPSB0aGlzLl9sb2NhdGlvbihnbCk7XHJcbiAgICAgICAgaWYgKGhhc3ZhbChsb2NhdGlvbikpIHtcclxuICAgICAgICAgICAgZ2wudW5pZm9ybTRmKGxvY2F0aW9uLCBjb2xvci5yLCBjb2xvci5nLCBjb2xvci5iLCBjb2xvci5hKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcblxyXG5leHBvcnQgY2xhc3MgVW5pZm9ybVNhbXBsZXIyRCBleHRlbmRzIFVuaWZvcm0ge1xyXG4gICAgcHJpdmF0ZSBjdXJyZW50VGV4dHVyZTogVGV4dHVyZTtcclxuXHJcbiAgICBjb25zdHJ1Y3Rvcihwcm9ncmFtOiBQcm9ncmFtLCBuYW1lOiBzdHJpbmcsIG9wdGlvbmFsOiBib29sZWFuID0gZmFsc2UpIHtcclxuICAgICAgICBzdXBlcihwcm9ncmFtLCBuYW1lLCBvcHRpb25hbCk7XHJcbiAgICB9XHJcblxyXG4gICAgc2V0RGF0YUFuZEJpbmQoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgdGV4dHVyZVVuaXQ6IG51bWJlciwgdGV4dHVyZTogVGV4dHVyZSkge1xyXG4gICAgICAgIGNvbnN0IGxvY2F0aW9uID0gdGhpcy5fbG9jYXRpb24oZ2wpO1xyXG4gICAgICAgIGlmIChoYXN2YWwobG9jYXRpb24pKSB7XHJcbiAgICAgICAgICAgIHRleHR1cmUuYmluZChnbCwgdGV4dHVyZVVuaXQpO1xyXG4gICAgICAgICAgICBnbC51bmlmb3JtMWkobG9jYXRpb24sIHRleHR1cmVVbml0KTtcclxuICAgICAgICAgICAgdGhpcy5jdXJyZW50VGV4dHVyZSA9IHRleHR1cmU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHVuYmluZChnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0KSB7XHJcbiAgICAgICAgaWYgKGhhc3ZhbCh0aGlzLmN1cnJlbnRUZXh0dXJlKSkge1xyXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRUZXh0dXJlLnVuYmluZChnbCk7XHJcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFRleHR1cmUgPSBudWxsO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuXHJcbmV4cG9ydCBjbGFzcyBBdHRyaWJ1dGUge1xyXG4gICAgcHJpdmF0ZSBwcm9ncmFtOiBQcm9ncmFtO1xyXG4gICAgcHJpdmF0ZSBuYW1lOiBzdHJpbmc7XHJcbiAgICBwcml2YXRlIGxvY2F0aW9uczogU3RyaW5nTWFwPG51bWJlcj4gPSB7fTtcclxuXHJcbiAgICBjb25zdHJ1Y3Rvcihwcm9ncmFtOiBQcm9ncmFtLCBuYW1lOiBzdHJpbmcpIHtcclxuICAgICAgICB0aGlzLnByb2dyYW0gPSBwcm9ncmFtO1xyXG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gWFhYOiBXb3VsZCBiZSBuaWNlIGlmIHRoaXMgd2VyZW4ndCBwdWJsaWNcclxuICAgIF9sb2NhdGlvbihnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0KTogbnVtYmVyIHtcclxuICAgICAgICBjb25zdCBnbElkID0gZ2V0T2JqZWN0SWQoZ2wpO1xyXG4gICAgICAgIGlmICh0aGlzLmxvY2F0aW9uc1tnbElkXSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGxvY2F0aW9uID0gZ2wuZ2V0QXR0cmliTG9jYXRpb24odGhpcy5wcm9ncmFtLl9wcm9ncmFtKGdsKSwgdGhpcy5uYW1lKTtcclxuICAgICAgICAgICAgaWYgKGxvY2F0aW9uID09PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdBdHRyaWJ1dGUgXCInICsgdGhpcy5uYW1lICsgJ1wiIG5vdCBmb3VuZCcpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMubG9jYXRpb25zW2dsSWRdID0gbG9jYXRpb247XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzLmxvY2F0aW9uc1tnbElkXTtcclxuICAgIH1cclxuXHJcbiAgICBzZXREYXRhQW5kRW5hYmxlKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIGJ1ZmZlcjogQnVmZmVyLCBzaXplOiBudW1iZXIsIHR5cGU6IG51bWJlciwgbm9ybWFsaXplZDogYm9vbGVhbiA9IGZhbHNlLCBzdHJpZGU6IG51bWJlciA9IDAsIG9mZnNldDogbnVtYmVyID0gMCkge1xyXG4gICAgICAgIGNvbnN0IGxvY2F0aW9uID0gdGhpcy5fbG9jYXRpb24oZ2wpO1xyXG4gICAgICAgIGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGxvY2F0aW9uKTtcclxuICAgICAgICBidWZmZXIuYmluZChnbCwgR0wuQVJSQVlfQlVGRkVSKTtcclxuICAgICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKGxvY2F0aW9uLCBzaXplLCB0eXBlLCBub3JtYWxpemVkLCBzdHJpZGUsIG9mZnNldCk7XHJcbiAgICAgICAgYnVmZmVyLnVuYmluZChnbCwgR0wuQVJSQVlfQlVGRkVSKTtcclxuICAgIH1cclxuXHJcbiAgICBkaXNhYmxlKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQpIHtcclxuICAgICAgICBnbC5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkodGhpcy5fbG9jYXRpb24oZ2wpKTtcclxuICAgIH1cclxufVxyXG5cclxuXHJcbiJdfQ==