@esotericsoftware/spine-webgl
Version:
The official Spine Runtimes for the web.
203 lines • 27.9 kB
JavaScript
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
import { Shader } from "./Shader.js";
import { ManagedWebGLRenderingContext } from "./WebGL.js";
export class Mesh {
attributes;
context;
vertices;
verticesBuffer = null;
verticesLength = 0;
dirtyVertices = false;
indices;
indicesBuffer = null;
indicesLength = 0;
dirtyIndices = false;
elementsPerVertex = 0;
getAttributes() { return this.attributes; }
maxVertices() { return this.vertices.length / this.elementsPerVertex; }
numVertices() { return this.verticesLength / this.elementsPerVertex; }
setVerticesLength(length) {
this.dirtyVertices = true;
this.verticesLength = length;
}
getVertices() { return this.vertices; }
maxIndices() { return this.indices.length; }
numIndices() { return this.indicesLength; }
setIndicesLength(length) {
this.dirtyIndices = true;
this.indicesLength = length;
}
getIndices() { return this.indices; }
;
getVertexSizeInFloats() {
let size = 0;
for (var i = 0; i < this.attributes.length; i++) {
let attribute = this.attributes[i];
size += attribute.numElements;
}
return size;
}
constructor(context, attributes, maxVertices, maxIndices) {
this.attributes = attributes;
this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);
this.elementsPerVertex = 0;
for (let i = 0; i < attributes.length; i++) {
this.elementsPerVertex += attributes[i].numElements;
}
this.vertices = new Float32Array(maxVertices * this.elementsPerVertex);
this.indices = new Uint16Array(maxIndices);
this.context.addRestorable(this);
}
setVertices(vertices) {
this.dirtyVertices = true;
if (vertices.length > this.vertices.length)
throw Error("Mesh can't store more than " + this.maxVertices() + " vertices");
this.vertices.set(vertices, 0);
this.verticesLength = vertices.length;
}
setIndices(indices) {
this.dirtyIndices = true;
if (indices.length > this.indices.length)
throw Error("Mesh can't store more than " + this.maxIndices() + " indices");
this.indices.set(indices, 0);
this.indicesLength = indices.length;
}
draw(shader, primitiveType) {
this.drawWithOffset(shader, primitiveType, 0, this.indicesLength > 0 ? this.indicesLength : this.verticesLength / this.elementsPerVertex);
}
drawWithOffset(shader, primitiveType, offset, count) {
let gl = this.context.gl;
if (this.dirtyVertices || this.dirtyIndices)
this.update();
this.bind(shader);
if (this.indicesLength > 0) {
gl.drawElements(primitiveType, count, gl.UNSIGNED_SHORT, offset * 2);
}
else {
gl.drawArrays(primitiveType, offset, count);
}
this.unbind(shader);
}
bind(shader) {
let gl = this.context.gl;
gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer);
let offset = 0;
for (let i = 0; i < this.attributes.length; i++) {
let attrib = this.attributes[i];
let location = shader.getAttributeLocation(attrib.name);
gl.enableVertexAttribArray(location);
gl.vertexAttribPointer(location, attrib.numElements, gl.FLOAT, false, this.elementsPerVertex * 4, offset * 4);
offset += attrib.numElements;
}
if (this.indicesLength > 0)
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
}
unbind(shader) {
let gl = this.context.gl;
for (let i = 0; i < this.attributes.length; i++) {
let attrib = this.attributes[i];
let location = shader.getAttributeLocation(attrib.name);
gl.disableVertexAttribArray(location);
}
gl.bindBuffer(gl.ARRAY_BUFFER, null);
if (this.indicesLength > 0)
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
}
update() {
let gl = this.context.gl;
if (this.dirtyVertices) {
if (!this.verticesBuffer) {
this.verticesBuffer = gl.createBuffer();
}
gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW);
this.dirtyVertices = false;
}
if (this.dirtyIndices) {
if (!this.indicesBuffer) {
this.indicesBuffer = gl.createBuffer();
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW);
this.dirtyIndices = false;
}
}
restore() {
this.verticesBuffer = null;
this.indicesBuffer = null;
this.update();
}
dispose() {
this.context.removeRestorable(this);
let gl = this.context.gl;
gl.deleteBuffer(this.verticesBuffer);
gl.deleteBuffer(this.indicesBuffer);
}
}
export class VertexAttribute {
name;
type;
numElements;
constructor(name, type, numElements) {
this.name = name;
this.type = type;
this.numElements = numElements;
}
}
export class Position2Attribute extends VertexAttribute {
constructor() {
super(Shader.POSITION, VertexAttributeType.Float, 2);
}
}
export class Position3Attribute extends VertexAttribute {
constructor() {
super(Shader.POSITION, VertexAttributeType.Float, 3);
}
}
export class TexCoordAttribute extends VertexAttribute {
constructor(unit = 0) {
super(Shader.TEXCOORDS + (unit == 0 ? "" : unit), VertexAttributeType.Float, 2);
}
}
export class ColorAttribute extends VertexAttribute {
constructor() {
super(Shader.COLOR, VertexAttributeType.Float, 4);
}
}
export class Color2Attribute extends VertexAttribute {
constructor() {
super(Shader.COLOR2, VertexAttributeType.Float, 4);
}
}
export var VertexAttributeType;
(function (VertexAttributeType) {
VertexAttributeType[VertexAttributeType["Float"] = 0] = "Float";
})(VertexAttributeType || (VertexAttributeType = {}));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWVzaC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9NZXNoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7K0VBMkIrRTtBQUcvRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3JDLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUcxRCxNQUFNLE9BQU8sSUFBSTtJQXVDb0U7SUF0QzVFLE9BQU8sQ0FBK0I7SUFDdEMsUUFBUSxDQUFlO0lBQ3ZCLGNBQWMsR0FBdUIsSUFBSSxDQUFDO0lBQzFDLGNBQWMsR0FBRyxDQUFDLENBQUM7SUFDbkIsYUFBYSxHQUFHLEtBQUssQ0FBQztJQUN0QixPQUFPLENBQWM7SUFDckIsYUFBYSxHQUF1QixJQUFJLENBQUM7SUFDekMsYUFBYSxHQUFHLENBQUMsQ0FBQztJQUNsQixZQUFZLEdBQUcsS0FBSyxDQUFDO0lBQ3JCLGlCQUFpQixHQUFHLENBQUMsQ0FBQztJQUU5QixhQUFhLEtBQXlCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFFL0QsV0FBVyxLQUFjLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQztJQUNoRixXQUFXLEtBQWMsT0FBTyxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7SUFDL0UsaUJBQWlCLENBQUUsTUFBYztRQUNoQyxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztRQUMxQixJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQztJQUM5QixDQUFDO0lBQ0QsV0FBVyxLQUFvQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBRXRELFVBQVUsS0FBYyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxVQUFVLEtBQWMsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztJQUNwRCxnQkFBZ0IsQ0FBRSxNQUFjO1FBQy9CLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDO0lBQzdCLENBQUM7SUFDRCxVQUFVLEtBQW1CLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQSxDQUFDLENBQUM7SUFBQSxDQUFDO0lBRW5ELHFCQUFxQjtRQUNwQixJQUFJLElBQUksR0FBRyxDQUFDLENBQUM7UUFDYixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNqRCxJQUFJLFNBQVMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ25DLElBQUksSUFBSSxTQUFTLENBQUMsV0FBVyxDQUFDO1FBQy9CLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNiLENBQUM7SUFFRCxZQUFhLE9BQTZELEVBQVUsVUFBNkIsRUFBRSxXQUFtQixFQUFFLFVBQWtCO1FBQXRFLGVBQVUsR0FBVixVQUFVLENBQW1CO1FBQ2hILElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxZQUFZLDRCQUE0QixDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksNEJBQTRCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDckgsSUFBSSxDQUFDLGlCQUFpQixHQUFHLENBQUMsQ0FBQztRQUMzQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQzVDLElBQUksQ0FBQyxpQkFBaUIsSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDO1FBQ3JELENBQUM7UUFDRCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksWUFBWSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUN2RSxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2xDLENBQUM7SUFFRCxXQUFXLENBQUUsUUFBdUI7UUFDbkMsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUM7UUFDMUIsSUFBSSxRQUFRLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTTtZQUFFLE1BQU0sS0FBSyxDQUFDLDZCQUE2QixHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsR0FBRyxXQUFXLENBQUMsQ0FBQztRQUMxSCxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLGNBQWMsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDO0lBQ3ZDLENBQUM7SUFFRCxVQUFVLENBQUUsT0FBc0I7UUFDakMsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7UUFDekIsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTTtZQUFFLE1BQU0sS0FBSyxDQUFDLDZCQUE2QixHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsR0FBRyxVQUFVLENBQUMsQ0FBQztRQUN0SCxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDN0IsSUFBSSxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDO0lBQ3JDLENBQUM7SUFFRCxJQUFJLENBQUUsTUFBYyxFQUFFLGFBQXFCO1FBQzFDLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLGFBQWEsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLGFBQWEsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDM0ksQ0FBQztJQUVELGNBQWMsQ0FBRSxNQUFjLEVBQUUsYUFBcUIsRUFBRSxNQUFjLEVBQUUsS0FBYTtRQUNuRixJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUN6QixJQUFJLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLFlBQVk7WUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDM0QsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNsQixJQUFJLElBQUksQ0FBQyxhQUFhLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDNUIsRUFBRSxDQUFDLFlBQVksQ0FBQyxhQUFhLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxjQUFjLEVBQUUsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3RFLENBQUM7YUFBTSxDQUFDO1lBQ1AsRUFBRSxDQUFDLFVBQVUsQ0FBQyxhQUFhLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzdDLENBQUM7UUFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3JCLENBQUM7SUFFRCxJQUFJLENBQUUsTUFBYztRQUNuQixJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUN6QixFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3BELElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztRQUNmLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ2pELElBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDaEMsSUFBSSxRQUFRLEdBQUcsTUFBTSxDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN4RCxFQUFFLENBQUMsdUJBQXVCLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDckMsRUFBRSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLEVBQUUsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQzlHLE1BQU0sSUFBSSxNQUFNLENBQUMsV0FBVyxDQUFDO1FBQzlCLENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyxhQUFhLEdBQUcsQ0FBQztZQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLG9CQUFvQixFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUN4RixDQUFDO0lBRUQsTUFBTSxDQUFFLE1BQWM7UUFDckIsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDekIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDakQsSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNoQyxJQUFJLFFBQVEsR0FBRyxNQUFNLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3hELEVBQUUsQ0FBQyx3QkFBd0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN2QyxDQUFDO1FBQ0QsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3JDLElBQUksSUFBSSxDQUFDLGFBQWEsR0FBRyxDQUFDO1lBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDMUUsQ0FBQztJQUVPLE1BQU07UUFDYixJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUN6QixJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUMxQixJQUFJLENBQUMsY0FBYyxHQUFHLEVBQUUsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN6QyxDQUFDO1lBQ0QsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUNwRCxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDaEcsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7UUFDNUIsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7Z0JBQ3pCLElBQUksQ0FBQyxhQUFhLEdBQUcsRUFBRSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3hDLENBQUM7WUFDRCxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxvQkFBb0IsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDM0QsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDdEcsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDM0IsQ0FBQztJQUNGLENBQUM7SUFFRCxPQUFPO1FBQ04sSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUM7UUFDM0IsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUM7UUFDMUIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ2YsQ0FBQztJQUVELE9BQU87UUFDTixJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BDLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ3pCLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3JDLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7Q0FDRDtBQUVELE1BQU0sT0FBTyxlQUFlO0lBQ1A7SUFBcUI7SUFBa0M7SUFBM0UsWUFBb0IsSUFBWSxFQUFTLElBQXlCLEVBQVMsV0FBbUI7UUFBMUUsU0FBSSxHQUFKLElBQUksQ0FBUTtRQUFTLFNBQUksR0FBSixJQUFJLENBQXFCO1FBQVMsZ0JBQVcsR0FBWCxXQUFXLENBQVE7SUFBSSxDQUFDO0NBQ25HO0FBRUQsTUFBTSxPQUFPLGtCQUFtQixTQUFRLGVBQWU7SUFDdEQ7UUFDQyxLQUFLLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEQsQ0FBQztDQUNEO0FBRUQsTUFBTSxPQUFPLGtCQUFtQixTQUFRLGVBQWU7SUFDdEQ7UUFDQyxLQUFLLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEQsQ0FBQztDQUNEO0FBRUQsTUFBTSxPQUFPLGlCQUFrQixTQUFRLGVBQWU7SUFDckQsWUFBYSxPQUFlLENBQUM7UUFDNUIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLG1CQUFtQixDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqRixDQUFDO0NBQ0Q7QUFFRCxNQUFNLE9BQU8sY0FBZSxTQUFRLGVBQWU7SUFDbEQ7UUFDQyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkQsQ0FBQztDQUNEO0FBRUQsTUFBTSxPQUFPLGVBQWdCLFNBQVEsZUFBZTtJQUNuRDtRQUNDLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLG1CQUFtQixDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNwRCxDQUFDO0NBQ0Q7QUFFRCxNQUFNLENBQU4sSUFBWSxtQkFFWDtBQUZELFdBQVksbUJBQW1CO0lBQzlCLCtEQUFLLENBQUE7QUFDTixDQUFDLEVBRlcsbUJBQW1CLEtBQW5CLG1CQUFtQixRQUU5QiIsInNvdXJjZXNDb250ZW50IjpbIi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAqIFNwaW5lIFJ1bnRpbWVzIExpY2Vuc2UgQWdyZWVtZW50XG4gKiBMYXN0IHVwZGF0ZWQgQXByaWwgNSwgMjAyNS4gUmVwbGFjZXMgYWxsIHByaW9yIHZlcnNpb25zLlxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDI1LCBFc290ZXJpYyBTb2Z0d2FyZSBMTENcbiAqXG4gKiBJbnRlZ3JhdGlvbiBvZiB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZSBvciBvdGhlcndpc2UgY3JlYXRpbmdcbiAqIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIGlzIHBlcm1pdHRlZCB1bmRlciB0aGUgdGVybXMgYW5kXG4gKiBjb25kaXRpb25zIG9mIFNlY3Rpb24gMiBvZiB0aGUgU3BpbmUgRWRpdG9yIExpY2Vuc2UgQWdyZWVtZW50OlxuICogaHR0cDovL2Vzb3Rlcmljc29mdHdhcmUuY29tL3NwaW5lLWVkaXRvci1saWNlbnNlXG4gKlxuICogT3RoZXJ3aXNlLCBpdCBpcyBwZXJtaXR0ZWQgdG8gaW50ZWdyYXRlIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlXG4gKiBvciBvdGhlcndpc2UgY3JlYXRlIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIChjb2xsZWN0aXZlbHksXG4gKiBcIlByb2R1Y3RzXCIpLCBwcm92aWRlZCB0aGF0IGVhY2ggdXNlciBvZiB0aGUgUHJvZHVjdHMgbXVzdCBvYnRhaW4gdGhlaXIgb3duXG4gKiBTcGluZSBFZGl0b3IgbGljZW5zZSBhbmQgcmVkaXN0cmlidXRpb24gb2YgdGhlIFByb2R1Y3RzIGluIGFueSBmb3JtIG11c3RcbiAqIGluY2x1ZGUgdGhpcyBsaWNlbnNlIGFuZCBjb3B5cmlnaHQgbm90aWNlLlxuICpcbiAqIFRIRSBTUElORSBSVU5USU1FUyBBUkUgUFJPVklERUQgQlkgRVNPVEVSSUMgU09GVFdBUkUgTExDIFwiQVMgSVNcIiBBTkQgQU5ZXG4gKiBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG4gKiBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXG4gKiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBFU09URVJJQyBTT0ZUV0FSRSBMTEMgQkUgTElBQkxFIEZPUiBBTllcbiAqIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4gKiAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVMsXG4gKiBCVVNJTkVTUyBJTlRFUlJVUFRJT04sIE9SIExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTKSBIT1dFVkVSIENBVVNFRCBBTkRcbiAqIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4gKiAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0ZcbiAqIFRIRSBTUElORSBSVU5USU1FUywgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cbiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuaW1wb3J0IHsgRGlzcG9zYWJsZSwgUmVzdG9yYWJsZSB9IGZyb20gXCJAZXNvdGVyaWNzb2Z0d2FyZS9zcGluZS1jb3JlXCI7XG5pbXBvcnQgeyBTaGFkZXIgfSBmcm9tIFwiLi9TaGFkZXIuanNcIjtcbmltcG9ydCB7IE1hbmFnZWRXZWJHTFJlbmRlcmluZ0NvbnRleHQgfSBmcm9tIFwiLi9XZWJHTC5qc1wiO1xuXG5cbmV4cG9ydCBjbGFzcyBNZXNoIGltcGxlbWVudHMgRGlzcG9zYWJsZSwgUmVzdG9yYWJsZSB7XG5cdHByaXZhdGUgY29udGV4dDogTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dDtcblx0cHJpdmF0ZSB2ZXJ0aWNlczogRmxvYXQzMkFycmF5O1xuXHRwcml2YXRlIHZlcnRpY2VzQnVmZmVyOiBXZWJHTEJ1ZmZlciB8IG51bGwgPSBudWxsO1xuXHRwcml2YXRlIHZlcnRpY2VzTGVuZ3RoID0gMDtcblx0cHJpdmF0ZSBkaXJ0eVZlcnRpY2VzID0gZmFsc2U7XG5cdHByaXZhdGUgaW5kaWNlczogVWludDE2QXJyYXk7XG5cdHByaXZhdGUgaW5kaWNlc0J1ZmZlcjogV2ViR0xCdWZmZXIgfCBudWxsID0gbnVsbDtcblx0cHJpdmF0ZSBpbmRpY2VzTGVuZ3RoID0gMDtcblx0cHJpdmF0ZSBkaXJ0eUluZGljZXMgPSBmYWxzZTtcblx0cHJpdmF0ZSBlbGVtZW50c1BlclZlcnRleCA9IDA7XG5cblx0Z2V0QXR0cmlidXRlcyAoKTogVmVydGV4QXR0cmlidXRlW10geyByZXR1cm4gdGhpcy5hdHRyaWJ1dGVzOyB9XG5cblx0bWF4VmVydGljZXMgKCk6IG51bWJlciB7IHJldHVybiB0aGlzLnZlcnRpY2VzLmxlbmd0aCAvIHRoaXMuZWxlbWVudHNQZXJWZXJ0ZXg7IH1cblx0bnVtVmVydGljZXMgKCk6IG51bWJlciB7IHJldHVybiB0aGlzLnZlcnRpY2VzTGVuZ3RoIC8gdGhpcy5lbGVtZW50c1BlclZlcnRleDsgfVxuXHRzZXRWZXJ0aWNlc0xlbmd0aCAobGVuZ3RoOiBudW1iZXIpIHtcblx0XHR0aGlzLmRpcnR5VmVydGljZXMgPSB0cnVlO1xuXHRcdHRoaXMudmVydGljZXNMZW5ndGggPSBsZW5ndGg7XG5cdH1cblx0Z2V0VmVydGljZXMgKCk6IEZsb2F0MzJBcnJheSB7IHJldHVybiB0aGlzLnZlcnRpY2VzOyB9XG5cblx0bWF4SW5kaWNlcyAoKTogbnVtYmVyIHsgcmV0dXJuIHRoaXMuaW5kaWNlcy5sZW5ndGg7IH1cblx0bnVtSW5kaWNlcyAoKTogbnVtYmVyIHsgcmV0dXJuIHRoaXMuaW5kaWNlc0xlbmd0aDsgfVxuXHRzZXRJbmRpY2VzTGVuZ3RoIChsZW5ndGg6IG51bWJlcikge1xuXHRcdHRoaXMuZGlydHlJbmRpY2VzID0gdHJ1ZTtcblx0XHR0aGlzLmluZGljZXNMZW5ndGggPSBsZW5ndGg7XG5cdH1cblx0Z2V0SW5kaWNlcyAoKTogVWludDE2QXJyYXkgeyByZXR1cm4gdGhpcy5pbmRpY2VzIH07XG5cblx0Z2V0VmVydGV4U2l6ZUluRmxvYXRzICgpOiBudW1iZXIge1xuXHRcdGxldCBzaXplID0gMDtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuYXR0cmlidXRlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0bGV0IGF0dHJpYnV0ZSA9IHRoaXMuYXR0cmlidXRlc1tpXTtcblx0XHRcdHNpemUgKz0gYXR0cmlidXRlLm51bUVsZW1lbnRzO1xuXHRcdH1cblx0XHRyZXR1cm4gc2l6ZTtcblx0fVxuXG5cdGNvbnN0cnVjdG9yIChjb250ZXh0OiBNYW5hZ2VkV2ViR0xSZW5kZXJpbmdDb250ZXh0IHwgV2ViR0xSZW5kZXJpbmdDb250ZXh0LCBwcml2YXRlIGF0dHJpYnV0ZXM6IFZlcnRleEF0dHJpYnV0ZVtdLCBtYXhWZXJ0aWNlczogbnVtYmVyLCBtYXhJbmRpY2VzOiBudW1iZXIpIHtcblx0XHR0aGlzLmNvbnRleHQgPSBjb250ZXh0IGluc3RhbmNlb2YgTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dCA/IGNvbnRleHQgOiBuZXcgTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dChjb250ZXh0KTtcblx0XHR0aGlzLmVsZW1lbnRzUGVyVmVydGV4ID0gMDtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGF0dHJpYnV0ZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMuZWxlbWVudHNQZXJWZXJ0ZXggKz0gYXR0cmlidXRlc1tpXS5udW1FbGVtZW50cztcblx0XHR9XG5cdFx0dGhpcy52ZXJ0aWNlcyA9IG5ldyBGbG9hdDMyQXJyYXkobWF4VmVydGljZXMgKiB0aGlzLmVsZW1lbnRzUGVyVmVydGV4KTtcblx0XHR0aGlzLmluZGljZXMgPSBuZXcgVWludDE2QXJyYXkobWF4SW5kaWNlcyk7XG5cdFx0dGhpcy5jb250ZXh0LmFkZFJlc3RvcmFibGUodGhpcyk7XG5cdH1cblxuXHRzZXRWZXJ0aWNlcyAodmVydGljZXM6IEFycmF5PG51bWJlcj4pIHtcblx0XHR0aGlzLmRpcnR5VmVydGljZXMgPSB0cnVlO1xuXHRcdGlmICh2ZXJ0aWNlcy5sZW5ndGggPiB0aGlzLnZlcnRpY2VzLmxlbmd0aCkgdGhyb3cgRXJyb3IoXCJNZXNoIGNhbid0IHN0b3JlIG1vcmUgdGhhbiBcIiArIHRoaXMubWF4VmVydGljZXMoKSArIFwiIHZlcnRpY2VzXCIpO1xuXHRcdHRoaXMudmVydGljZXMuc2V0KHZlcnRpY2VzLCAwKTtcblx0XHR0aGlzLnZlcnRpY2VzTGVuZ3RoID0gdmVydGljZXMubGVuZ3RoO1xuXHR9XG5cblx0c2V0SW5kaWNlcyAoaW5kaWNlczogQXJyYXk8bnVtYmVyPikge1xuXHRcdHRoaXMuZGlydHlJbmRpY2VzID0gdHJ1ZTtcblx0XHRpZiAoaW5kaWNlcy5sZW5ndGggPiB0aGlzLmluZGljZXMubGVuZ3RoKSB0aHJvdyBFcnJvcihcIk1lc2ggY2FuJ3Qgc3RvcmUgbW9yZSB0aGFuIFwiICsgdGhpcy5tYXhJbmRpY2VzKCkgKyBcIiBpbmRpY2VzXCIpO1xuXHRcdHRoaXMuaW5kaWNlcy5zZXQoaW5kaWNlcywgMCk7XG5cdFx0dGhpcy5pbmRpY2VzTGVuZ3RoID0gaW5kaWNlcy5sZW5ndGg7XG5cdH1cblxuXHRkcmF3IChzaGFkZXI6IFNoYWRlciwgcHJpbWl0aXZlVHlwZTogbnVtYmVyKSB7XG5cdFx0dGhpcy5kcmF3V2l0aE9mZnNldChzaGFkZXIsIHByaW1pdGl2ZVR5cGUsIDAsIHRoaXMuaW5kaWNlc0xlbmd0aCA+IDAgPyB0aGlzLmluZGljZXNMZW5ndGggOiB0aGlzLnZlcnRpY2VzTGVuZ3RoIC8gdGhpcy5lbGVtZW50c1BlclZlcnRleCk7XG5cdH1cblxuXHRkcmF3V2l0aE9mZnNldCAoc2hhZGVyOiBTaGFkZXIsIHByaW1pdGl2ZVR5cGU6IG51bWJlciwgb2Zmc2V0OiBudW1iZXIsIGNvdW50OiBudW1iZXIpIHtcblx0XHRsZXQgZ2wgPSB0aGlzLmNvbnRleHQuZ2w7XG5cdFx0aWYgKHRoaXMuZGlydHlWZXJ0aWNlcyB8fCB0aGlzLmRpcnR5SW5kaWNlcykgdGhpcy51cGRhdGUoKTtcblx0XHR0aGlzLmJpbmQoc2hhZGVyKTtcblx0XHRpZiAodGhpcy5pbmRpY2VzTGVuZ3RoID4gMCkge1xuXHRcdFx0Z2wuZHJhd0VsZW1lbnRzKHByaW1pdGl2ZVR5cGUsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgb2Zmc2V0ICogMik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGdsLmRyYXdBcnJheXMocHJpbWl0aXZlVHlwZSwgb2Zmc2V0LCBjb3VudCk7XG5cdFx0fVxuXHRcdHRoaXMudW5iaW5kKHNoYWRlcik7XG5cdH1cblxuXHRiaW5kIChzaGFkZXI6IFNoYWRlcikge1xuXHRcdGxldCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHRnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgdGhpcy52ZXJ0aWNlc0J1ZmZlcik7XG5cdFx0bGV0IG9mZnNldCA9IDA7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmF0dHJpYnV0ZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGxldCBhdHRyaWIgPSB0aGlzLmF0dHJpYnV0ZXNbaV07XG5cdFx0XHRsZXQgbG9jYXRpb24gPSBzaGFkZXIuZ2V0QXR0cmlidXRlTG9jYXRpb24oYXR0cmliLm5hbWUpO1xuXHRcdFx0Z2wuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkobG9jYXRpb24pO1xuXHRcdFx0Z2wudmVydGV4QXR0cmliUG9pbnRlcihsb2NhdGlvbiwgYXR0cmliLm51bUVsZW1lbnRzLCBnbC5GTE9BVCwgZmFsc2UsIHRoaXMuZWxlbWVudHNQZXJWZXJ0ZXggKiA0LCBvZmZzZXQgKiA0KTtcblx0XHRcdG9mZnNldCArPSBhdHRyaWIubnVtRWxlbWVudHM7XG5cdFx0fVxuXHRcdGlmICh0aGlzLmluZGljZXNMZW5ndGggPiAwKSBnbC5iaW5kQnVmZmVyKGdsLkVMRU1FTlRfQVJSQVlfQlVGRkVSLCB0aGlzLmluZGljZXNCdWZmZXIpO1xuXHR9XG5cblx0dW5iaW5kIChzaGFkZXI6IFNoYWRlcikge1xuXHRcdGxldCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuYXR0cmlidXRlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0bGV0IGF0dHJpYiA9IHRoaXMuYXR0cmlidXRlc1tpXTtcblx0XHRcdGxldCBsb2NhdGlvbiA9IHNoYWRlci5nZXRBdHRyaWJ1dGVMb2NhdGlvbihhdHRyaWIubmFtZSk7XG5cdFx0XHRnbC5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkobG9jYXRpb24pO1xuXHRcdH1cblx0XHRnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgbnVsbCk7XG5cdFx0aWYgKHRoaXMuaW5kaWNlc0xlbmd0aCA+IDApIGdsLmJpbmRCdWZmZXIoZ2wuRUxFTUVOVF9BUlJBWV9CVUZGRVIsIG51bGwpO1xuXHR9XG5cblx0cHJpdmF0ZSB1cGRhdGUgKCkge1xuXHRcdGxldCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHRpZiAodGhpcy5kaXJ0eVZlcnRpY2VzKSB7XG5cdFx0XHRpZiAoIXRoaXMudmVydGljZXNCdWZmZXIpIHtcblx0XHRcdFx0dGhpcy52ZXJ0aWNlc0J1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuXHRcdFx0fVxuXHRcdFx0Z2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMudmVydGljZXNCdWZmZXIpO1xuXHRcdFx0Z2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIHRoaXMudmVydGljZXMuc3ViYXJyYXkoMCwgdGhpcy52ZXJ0aWNlc0xlbmd0aCksIGdsLkRZTkFNSUNfRFJBVyk7XG5cdFx0XHR0aGlzLmRpcnR5VmVydGljZXMgPSBmYWxzZTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5kaXJ0eUluZGljZXMpIHtcblx0XHRcdGlmICghdGhpcy5pbmRpY2VzQnVmZmVyKSB7XG5cdFx0XHRcdHRoaXMuaW5kaWNlc0J1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuXHRcdFx0fVxuXHRcdFx0Z2wuYmluZEJ1ZmZlcihnbC5FTEVNRU5UX0FSUkFZX0JVRkZFUiwgdGhpcy5pbmRpY2VzQnVmZmVyKTtcblx0XHRcdGdsLmJ1ZmZlckRhdGEoZ2wuRUxFTUVOVF9BUlJBWV9CVUZGRVIsIHRoaXMuaW5kaWNlcy5zdWJhcnJheSgwLCB0aGlzLmluZGljZXNMZW5ndGgpLCBnbC5EWU5BTUlDX0RSQVcpO1xuXHRcdFx0dGhpcy5kaXJ0eUluZGljZXMgPSBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHRyZXN0b3JlICgpIHtcblx0XHR0aGlzLnZlcnRpY2VzQnVmZmVyID0gbnVsbDtcblx0XHR0aGlzLmluZGljZXNCdWZmZXIgPSBudWxsO1xuXHRcdHRoaXMudXBkYXRlKCk7XG5cdH1cblxuXHRkaXNwb3NlICgpIHtcblx0XHR0aGlzLmNvbnRleHQucmVtb3ZlUmVzdG9yYWJsZSh0aGlzKTtcblx0XHRsZXQgZ2wgPSB0aGlzLmNvbnRleHQuZ2w7XG5cdFx0Z2wuZGVsZXRlQnVmZmVyKHRoaXMudmVydGljZXNCdWZmZXIpO1xuXHRcdGdsLmRlbGV0ZUJ1ZmZlcih0aGlzLmluZGljZXNCdWZmZXIpO1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBWZXJ0ZXhBdHRyaWJ1dGUge1xuXHRjb25zdHJ1Y3RvciAocHVibGljIG5hbWU6IHN0cmluZywgcHVibGljIHR5cGU6IFZlcnRleEF0dHJpYnV0ZVR5cGUsIHB1YmxpYyBudW1FbGVtZW50czogbnVtYmVyKSB7IH1cbn1cblxuZXhwb3J0IGNsYXNzIFBvc2l0aW9uMkF0dHJpYnV0ZSBleHRlbmRzIFZlcnRleEF0dHJpYnV0ZSB7XG5cdGNvbnN0cnVjdG9yICgpIHtcblx0XHRzdXBlcihTaGFkZXIuUE9TSVRJT04sIFZlcnRleEF0dHJpYnV0ZVR5cGUuRmxvYXQsIDIpO1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBQb3NpdGlvbjNBdHRyaWJ1dGUgZXh0ZW5kcyBWZXJ0ZXhBdHRyaWJ1dGUge1xuXHRjb25zdHJ1Y3RvciAoKSB7XG5cdFx0c3VwZXIoU2hhZGVyLlBPU0lUSU9OLCBWZXJ0ZXhBdHRyaWJ1dGVUeXBlLkZsb2F0LCAzKTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgVGV4Q29vcmRBdHRyaWJ1dGUgZXh0ZW5kcyBWZXJ0ZXhBdHRyaWJ1dGUge1xuXHRjb25zdHJ1Y3RvciAodW5pdDogbnVtYmVyID0gMCkge1xuXHRcdHN1cGVyKFNoYWRlci5URVhDT09SRFMgKyAodW5pdCA9PSAwID8gXCJcIiA6IHVuaXQpLCBWZXJ0ZXhBdHRyaWJ1dGVUeXBlLkZsb2F0LCAyKTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgQ29sb3JBdHRyaWJ1dGUgZXh0ZW5kcyBWZXJ0ZXhBdHRyaWJ1dGUge1xuXHRjb25zdHJ1Y3RvciAoKSB7XG5cdFx0c3VwZXIoU2hhZGVyLkNPTE9SLCBWZXJ0ZXhBdHRyaWJ1dGVUeXBlLkZsb2F0LCA0KTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgQ29sb3IyQXR0cmlidXRlIGV4dGVuZHMgVmVydGV4QXR0cmlidXRlIHtcblx0Y29uc3RydWN0b3IgKCkge1xuXHRcdHN1cGVyKFNoYWRlci5DT0xPUjIsIFZlcnRleEF0dHJpYnV0ZVR5cGUuRmxvYXQsIDQpO1xuXHR9XG59XG5cbmV4cG9ydCBlbnVtIFZlcnRleEF0dHJpYnV0ZVR5cGUge1xuXHRGbG9hdFxufVxuIl19