@esotericsoftware/spine-pixi-v8
Version:
The official Spine Runtimes for PixiJS v8.
189 lines • 29.7 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 { SkeletonRenderer as CanvasSkeletonRenderer, MeshAttachment, RegionAttachment } from '@esotericsoftware/spine-canvas';
import { ExtensionType, extensions, RendererType, } from 'pixi.js';
import { BatchableSpineSlot } from './BatchableSpineSlot.js';
const spineBlendModeMap = {
0: 'normal',
1: 'add',
2: 'multiply',
3: 'screen'
};
// eslint-disable-next-line max-len
export class SpinePipe {
/** @ignore */
static extension = {
type: [
ExtensionType.WebGLPipes,
ExtensionType.WebGPUPipes,
ExtensionType.CanvasPipes,
],
name: 'spine',
};
renderer;
canvasSkeletonRenderer;
gpuSpineData = {};
_destroyRenderableBound = this.destroyRenderable.bind(this);
constructor(renderer) {
this.renderer = renderer;
}
validateRenderable(spine) {
if (this.renderer.type === RendererType.CANVAS) {
return true;
}
spine._validateAndTransformAttachments();
// if spine attachments have changed or destroyed, we need to rebuild the batch!
if (spine.spineAttachmentsDirty) {
return true;
}
// if the textures have changed, we need to rebuild the batch, but only if the texture is not already in the batch
else if (spine.spineTexturesDirty) {
// loop through and see if the textures have changed..
const drawOrder = spine.skeleton.drawOrder.appliedPose;
const gpuSpine = this.gpuSpineData[spine.uid];
if (!gpuSpine)
return false;
for (let i = 0, n = drawOrder.length; i < n; i++) {
const slot = drawOrder[i];
const attachment = slot.appliedPose.attachment;
if (attachment instanceof RegionAttachment || attachment instanceof MeshAttachment) {
const cacheData = spine._getCachedData(slot, attachment);
const batchableSpineSlot = gpuSpine.slotBatches[cacheData.id];
const texture = cacheData.texture;
if (texture !== batchableSpineSlot?.texture) {
if (!batchableSpineSlot?._batcher.checkAndUpdateTexture(batchableSpineSlot, texture)) {
return true;
}
}
}
}
}
return false;
}
execute(spine) {
if (this.renderer.type === RendererType.CANVAS) {
const renderer = this.renderer;
const groupAlpha = ((spine.groupColorAlpha >>> 24) & 0xFF) / 255;
const contextSystem = renderer.canvasContext;
const context = contextSystem.activeContext;
context.save();
if (!this.canvasSkeletonRenderer) {
this.canvasSkeletonRenderer = new CanvasSkeletonRenderer(context);
this.canvasSkeletonRenderer.triangleRendering = true;
}
contextSystem.setContextTransform(spine.groupTransform, (renderer._roundPixels | spine._roundPixels) === 1);
const oldAlpha = spine.skeleton.color.a;
spine.skeleton.color.a *= groupAlpha;
this.canvasSkeletonRenderer.draw(spine.skeleton);
spine.skeleton.color.a = oldAlpha;
context.restore();
}
}
addRenderable(spine, instructionSet) {
if (this.renderer.type === RendererType.CANVAS) {
this.renderer.renderPipes.batch.break(instructionSet);
instructionSet.add(spine);
return;
}
const gpuSpine = this._getSpineData(spine);
const batcher = this.renderer.renderPipes.batch;
const drawOrder = spine.skeleton.drawOrder.appliedPose;
const roundPixels = (this.renderer._roundPixels | spine._roundPixels);
spine._validateAndTransformAttachments();
spine.spineAttachmentsDirty = false;
spine.spineTexturesDirty = false;
for (let i = 0, n = drawOrder.length; i < n; i++) {
const slot = drawOrder[i];
const attachment = slot.appliedPose.attachment;
const blendMode = spineBlendModeMap[slot.data.blendMode];
let skipRender = false;
if (attachment instanceof RegionAttachment || attachment instanceof MeshAttachment) {
const cacheData = spine._getCachedData(slot, attachment);
const batchableSpineSlot = gpuSpine.slotBatches[cacheData.id] ||= new BatchableSpineSlot();
batchableSpineSlot.setData(spine, cacheData, blendMode, roundPixels);
skipRender = cacheData.skipRender;
if (!skipRender) {
batcher.addToBatch(batchableSpineSlot, instructionSet);
}
}
const containerAttachment = spine._slotsObject[slot.data.name];
if (containerAttachment) {
const container = containerAttachment.container;
container.includeInBuild = true;
// See https://github.com/pixijs/pixijs/blob/b4c050a791fe65e979e467c9cba2bda0c01a1c35/src/scene/container/utils/collectAllRenderables.ts#L28
// biome-ignore lint/style/noNonNullAssertion: it was in pixi code
container.collectRenderables(instructionSet, this.renderer, null);
container.includeInBuild = false;
}
}
}
updateRenderable(spine) {
const gpuSpine = this.gpuSpineData[spine.uid];
if (!gpuSpine)
return;
spine._validateAndTransformAttachments();
spine.spineAttachmentsDirty = false;
spine.spineTexturesDirty = false;
const drawOrder = spine.skeleton.drawOrder.appliedPose;
for (let i = 0, n = drawOrder.length; i < n; i++) {
const slot = drawOrder[i];
const attachment = slot.appliedPose.attachment;
if (attachment instanceof RegionAttachment || attachment instanceof MeshAttachment) {
const cacheData = spine._getCachedData(slot, attachment);
if (!cacheData.skipRender) {
const batchableSpineSlot = gpuSpine.slotBatches[cacheData.id];
if (batchableSpineSlot) {
// biome-ignore lint/style/noNonNullAssertion: if clipped is true, clippedData exists
batchableSpineSlot.uvs = cacheData.clipped ? cacheData.clippedData.uvs : cacheData.uvs;
batchableSpineSlot._batcher?.updateElement(batchableSpineSlot);
}
}
}
}
}
destroyRenderable(spine) {
this.gpuSpineData[spine.uid] = null;
spine.off('destroyed', this._destroyRenderableBound);
}
destroy() {
this.gpuSpineData = null;
this.renderer = null;
this.canvasSkeletonRenderer = null;
}
_getSpineData(spine) {
return this.gpuSpineData[spine.uid] || this._initMeshData(spine);
}
_initMeshData(spine) {
this.gpuSpineData[spine.uid] = { slotBatches: {} };
spine.on('destroyed', this._destroyRenderableBound);
return this.gpuSpineData[spine.uid];
}
}
extensions.add(SpinePipe);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3BpbmVQaXBlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1NwaW5lUGlwZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OytFQTJCK0U7QUFFL0UsT0FBTyxFQUFFLGdCQUFnQixJQUFJLHNCQUFzQixFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzlILE9BQU8sRUFHVSxhQUFhLEVBQzdCLFVBQVUsRUFHVixZQUFZLEdBRVosTUFBTSxTQUFTLENBQUM7QUFDakIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHN0QsTUFBTSxpQkFBaUIsR0FBZ0M7SUFDdEQsQ0FBQyxFQUFFLFFBQVE7SUFDWCxDQUFDLEVBQUUsS0FBSztJQUNSLENBQUMsRUFBRSxVQUFVO0lBQ2IsQ0FBQyxFQUFFLFFBQVE7Q0FDWCxDQUFDO0FBSUYsbUNBQW1DO0FBQ25DLE1BQU0sT0FBTyxTQUFTO0lBQ3JCLGNBQWM7SUFDZCxNQUFNLENBQUMsU0FBUyxHQUFHO1FBQ2xCLElBQUksRUFBRTtZQUNMLGFBQWEsQ0FBQyxVQUFVO1lBQ3hCLGFBQWEsQ0FBQyxXQUFXO1lBQ3pCLGFBQWEsQ0FBQyxXQUFXO1NBQ3pCO1FBQ0QsSUFBSSxFQUFFLE9BQU87S0FDSixDQUFDO0lBRVgsUUFBUSxDQUFXO0lBQ1gsc0JBQXNCLENBQTBCO0lBRWhELFlBQVksR0FBd0MsRUFBRSxDQUFDO0lBQzlDLHVCQUF1QixHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFvQyxDQUFDO0lBRWhILFlBQWEsUUFBa0I7UUFDOUIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7SUFDMUIsQ0FBQztJQUVELGtCQUFrQixDQUFFLEtBQVk7UUFDL0IsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksS0FBSyxZQUFZLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDaEQsT0FBTyxJQUFJLENBQUM7UUFDYixDQUFDO1FBRUQsS0FBSyxDQUFDLGdDQUFnQyxFQUFFLENBQUM7UUFFekMsZ0ZBQWdGO1FBQ2hGLElBQUksS0FBSyxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDakMsT0FBTyxJQUFJLENBQUM7UUFDYixDQUFDO1FBRUQsa0hBQWtIO2FBQzdHLElBQUksS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDbkMsc0RBQXNEO1lBQ3RELE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQztZQUN2RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUU5QyxJQUFJLENBQUMsUUFBUTtnQkFBRSxPQUFPLEtBQUssQ0FBQztZQUU1QixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQ2xELE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDMUIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUM7Z0JBRS9DLElBQUksVUFBVSxZQUFZLGdCQUFnQixJQUFJLFVBQVUsWUFBWSxjQUFjLEVBQUUsQ0FBQztvQkFDcEYsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7b0JBQ3pELE1BQU0sa0JBQWtCLEdBQUcsUUFBUSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7b0JBRTlELE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUM7b0JBRWxDLElBQUksT0FBTyxLQUFLLGtCQUFrQixFQUFFLE9BQU8sRUFBRSxDQUFDO3dCQUM3QyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsUUFBUSxDQUFDLHFCQUFxQixDQUFDLGtCQUFrQixFQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUM7NEJBQ3RGLE9BQU8sSUFBSSxDQUFDO3dCQUNiLENBQUM7b0JBQ0YsQ0FBQztnQkFDRixDQUFDO1lBQ0YsQ0FBQztRQUNGLENBQUM7UUFFRCxPQUFPLEtBQUssQ0FBQztJQUNkLENBQUM7SUFFRCxPQUFPLENBQUUsS0FBWTtRQUNwQixJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxLQUFLLFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNoRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBMEIsQ0FBQztZQUNqRCxNQUFNLFVBQVUsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLGVBQWUsS0FBSyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUM7WUFDakUsTUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQztZQUM3QyxNQUFNLE9BQU8sR0FBRyxhQUFhLENBQUMsYUFBYSxDQUFDO1lBRTVDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUVmLElBQUksQ0FBQyxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztnQkFDbEMsSUFBSSxDQUFDLHNCQUFzQixHQUFHLElBQUksc0JBQXNCLENBQUMsT0FBOEMsQ0FBQyxDQUFDO2dCQUN6RyxJQUFJLENBQUMsc0JBQXNCLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDO1lBQ3RELENBQUM7WUFFRCxhQUFhLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBRTVHLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztZQUN4QyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksVUFBVSxDQUFDO1lBQ3JDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2pELEtBQUssQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUM7WUFFbEMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ25CLENBQUM7SUFDRixDQUFDO0lBRUQsYUFBYSxDQUFFLEtBQVksRUFBRSxjQUE4QjtRQUMxRCxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxLQUFLLFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNoRCxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQ3RELGNBQWMsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDMUIsT0FBTztRQUNSLENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRTNDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQztRQUVoRCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUM7UUFFdkQsTUFBTSxXQUFXLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUMsWUFBWSxDQUFVLENBQUM7UUFFL0UsS0FBSyxDQUFDLGdDQUFnQyxFQUFFLENBQUM7UUFFekMsS0FBSyxDQUFDLHFCQUFxQixHQUFHLEtBQUssQ0FBQztRQUNwQyxLQUFLLENBQUMsa0JBQWtCLEdBQUcsS0FBSyxDQUFDO1FBRWpDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNsRCxNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDMUIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUM7WUFDL0MsTUFBTSxTQUFTLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUN6RCxJQUFJLFVBQVUsR0FBRyxLQUFLLENBQUM7WUFFdkIsSUFBSSxVQUFVLFlBQVksZ0JBQWdCLElBQUksVUFBVSxZQUFZLGNBQWMsRUFBRSxDQUFDO2dCQUNwRixNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQztnQkFDekQsTUFBTSxrQkFBa0IsR0FBRyxRQUFRLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsS0FBSyxJQUFJLGtCQUFrQixFQUFFLENBQUM7Z0JBRTNGLGtCQUFrQixDQUFDLE9BQU8sQ0FDekIsS0FBSyxFQUNMLFNBQVMsRUFDVCxTQUFTLEVBQ1QsV0FBVyxDQUNYLENBQUM7Z0JBRUYsVUFBVSxHQUFHLFNBQVMsQ0FBQyxVQUFVLENBQUM7Z0JBQ2xDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztvQkFDakIsT0FBTyxDQUFDLFVBQVUsQ0FBQyxrQkFBa0IsRUFBRSxjQUFjLENBQUMsQ0FBQztnQkFDeEQsQ0FBQztZQUNGLENBQUM7WUFFRCxNQUFNLG1CQUFtQixHQUFHLEtBQUssQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUUvRCxJQUFJLG1CQUFtQixFQUFFLENBQUM7Z0JBQ3pCLE1BQU0sU0FBUyxHQUFHLG1CQUFtQixDQUFDLFNBQVMsQ0FBQztnQkFFaEQsU0FBUyxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUM7Z0JBQ2hDLDRJQUE0STtnQkFDNUksa0VBQWtFO2dCQUNsRSxTQUFTLENBQUMsa0JBQWtCLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQyxRQUFRLEVBQUUsSUFBSyxDQUFDLENBQUM7Z0JBRW5FLFNBQVMsQ0FBQyxjQUFjLEdBQUcsS0FBSyxDQUFDO1lBQ2xDLENBQUM7UUFDRixDQUFDO0lBQ0YsQ0FBQztJQUVELGdCQUFnQixDQUFFLEtBQVk7UUFDN0IsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFOUMsSUFBSSxDQUFDLFFBQVE7WUFBRSxPQUFPO1FBRXRCLEtBQUssQ0FBQyxnQ0FBZ0MsRUFBRSxDQUFDO1FBRXpDLEtBQUssQ0FBQyxxQkFBcUIsR0FBRyxLQUFLLENBQUM7UUFDcEMsS0FBSyxDQUFDLGtCQUFrQixHQUFHLEtBQUssQ0FBQztRQUVqQyxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUM7UUFFdkQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ2xELE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMxQixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQztZQUUvQyxJQUFJLFVBQVUsWUFBWSxnQkFBZ0IsSUFBSSxVQUFVLFlBQVksY0FBYyxFQUFFLENBQUM7Z0JBQ3BGLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDO2dCQUV6RCxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsRUFBRSxDQUFDO29CQUMzQixNQUFNLGtCQUFrQixHQUFHLFFBQVEsQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDO29CQUM5RCxJQUFJLGtCQUFrQixFQUFFLENBQUM7d0JBQ3hCLHFGQUFxRjt3QkFDckYsa0JBQWtCLENBQUMsR0FBRyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxXQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDO3dCQUN4RixrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsYUFBYSxDQUFDLGtCQUFrQixDQUFDLENBQUM7b0JBQ2hFLENBQUM7Z0JBQ0YsQ0FBQztZQUNGLENBQUM7UUFDRixDQUFDO0lBQ0YsQ0FBQztJQUVELGlCQUFpQixDQUFFLEtBQVk7UUFDN0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFhLEdBQUcsSUFBSSxDQUFDO1FBQ2pELEtBQUssQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO0lBQ3RELENBQUM7SUFFRCxPQUFPO1FBQ0wsSUFBSSxDQUFDLFlBQXdCLEdBQUcsSUFBSSxDQUFDO1FBQ3JDLElBQUksQ0FBQyxRQUFvQixHQUFHLElBQUksQ0FBQztRQUNqQyxJQUFJLENBQUMsc0JBQWtDLEdBQUcsSUFBSSxDQUFDO0lBQ2pELENBQUM7SUFFTyxhQUFhLENBQUUsS0FBWTtRQUNsQyxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUVPLGFBQWEsQ0FBRSxLQUFZO1FBQ2xDLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsV0FBVyxFQUFFLEVBQUUsRUFBRSxDQUFDO1FBQ25ELEtBQUssQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBQ3BELE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDckMsQ0FBQzs7QUFHRixVQUFVLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICogU3BpbmUgUnVudGltZXMgTGljZW5zZSBBZ3JlZW1lbnRcbiAqIExhc3QgdXBkYXRlZCBBcHJpbCA1LCAyMDI1LiBSZXBsYWNlcyBhbGwgcHJpb3IgdmVyc2lvbnMuXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMjUsIEVzb3RlcmljIFNvZnR3YXJlIExMQ1xuICpcbiAqIEludGVncmF0aW9uIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlIG9yIG90aGVyd2lzZSBjcmVhdGluZ1xuICogZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgaXMgcGVybWl0dGVkIHVuZGVyIHRoZSB0ZXJtcyBhbmRcbiAqIGNvbmRpdGlvbnMgb2YgU2VjdGlvbiAyIG9mIHRoZSBTcGluZSBFZGl0b3IgTGljZW5zZSBBZ3JlZW1lbnQ6XG4gKiBodHRwOi8vZXNvdGVyaWNzb2Z0d2FyZS5jb20vc3BpbmUtZWRpdG9yLWxpY2Vuc2VcbiAqXG4gKiBPdGhlcndpc2UsIGl0IGlzIHBlcm1pdHRlZCB0byBpbnRlZ3JhdGUgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmVcbiAqIG9yIG90aGVyd2lzZSBjcmVhdGUgZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgKGNvbGxlY3RpdmVseSxcbiAqIFwiUHJvZHVjdHNcIiksIHByb3ZpZGVkIHRoYXQgZWFjaCB1c2VyIG9mIHRoZSBQcm9kdWN0cyBtdXN0IG9idGFpbiB0aGVpciBvd25cbiAqIFNwaW5lIEVkaXRvciBsaWNlbnNlIGFuZCByZWRpc3RyaWJ1dGlvbiBvZiB0aGUgUHJvZHVjdHMgaW4gYW55IGZvcm0gbXVzdFxuICogaW5jbHVkZSB0aGlzIGxpY2Vuc2UgYW5kIGNvcHlyaWdodCBub3RpY2UuXG4gKlxuICogVEhFIFNQSU5FIFJVTlRJTUVTIEFSRSBQUk9WSURFRCBCWSBFU09URVJJQyBTT0ZUV0FSRSBMTEMgXCJBUyBJU1wiIEFORCBBTllcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbiAqIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcbiAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIEVTT1RFUklDIFNPRlRXQVJFIExMQyBCRSBMSUFCTEUgRk9SIEFOWVxuICogRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbiAqIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUyxcbiAqIEJVU0lORVNTIElOVEVSUlVQVElPTiwgT1IgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFMpIEhPV0VWRVIgQ0FVU0VEIEFORFxuICogT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbiAqIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRlxuICogVEhFIFNQSU5FIFJVTlRJTUVTLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG5pbXBvcnQgeyBTa2VsZXRvblJlbmRlcmVyIGFzIENhbnZhc1NrZWxldG9uUmVuZGVyZXIsIE1lc2hBdHRhY2htZW50LCBSZWdpb25BdHRhY2htZW50IH0gZnJvbSAnQGVzb3Rlcmljc29mdHdhcmUvc3BpbmUtY2FudmFzJztcbmltcG9ydCB7XG5cdHR5cGUgQkxFTkRfTU9ERVMsXG5cdHR5cGUgQ2FudmFzUmVuZGVyZXIsXG5cdHR5cGUgQ29udGFpbmVyLCBFeHRlbnNpb25UeXBlLFxuXHRleHRlbnNpb25zLFxuXHR0eXBlIEluc3RydWN0aW9uU2V0LFxuXHR0eXBlIFJlbmRlcmVyLFxuXHRSZW5kZXJlclR5cGUsXG5cdHR5cGUgUmVuZGVyUGlwZSxcbn0gZnJvbSAncGl4aS5qcyc7XG5pbXBvcnQgeyBCYXRjaGFibGVTcGluZVNsb3QgfSBmcm9tICcuL0JhdGNoYWJsZVNwaW5lU2xvdC5qcyc7XG5pbXBvcnQgdHlwZSB7IFNwaW5lIH0gZnJvbSAnLi9TcGluZS5qcyc7XG5cbmNvbnN0IHNwaW5lQmxlbmRNb2RlTWFwOiBSZWNvcmQ8bnVtYmVyLCBCTEVORF9NT0RFUz4gPSB7XG5cdDA6ICdub3JtYWwnLFxuXHQxOiAnYWRkJyxcblx0MjogJ211bHRpcGx5Jyxcblx0MzogJ3NjcmVlbidcbn07XG5cbnR5cGUgR3B1U3BpbmVEYXRhRWxlbWVudCA9IHsgc2xvdEJhdGNoZXM6IFJlY29yZDxzdHJpbmcsIEJhdGNoYWJsZVNwaW5lU2xvdCB8IHVuZGVmaW5lZD4gfTtcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbmV4cG9ydCBjbGFzcyBTcGluZVBpcGUgaW1wbGVtZW50cyBSZW5kZXJQaXBlPFNwaW5lPiB7XG5cdC8qKiBAaWdub3JlICovXG5cdHN0YXRpYyBleHRlbnNpb24gPSB7XG5cdFx0dHlwZTogW1xuXHRcdFx0RXh0ZW5zaW9uVHlwZS5XZWJHTFBpcGVzLFxuXHRcdFx0RXh0ZW5zaW9uVHlwZS5XZWJHUFVQaXBlcyxcblx0XHRcdEV4dGVuc2lvblR5cGUuQ2FudmFzUGlwZXMsXG5cdFx0XSxcblx0XHRuYW1lOiAnc3BpbmUnLFxuXHR9IGFzIGNvbnN0O1xuXG5cdHJlbmRlcmVyOiBSZW5kZXJlcjtcblx0cHJpdmF0ZSBjYW52YXNTa2VsZXRvblJlbmRlcmVyITogQ2FudmFzU2tlbGV0b25SZW5kZXJlcjtcblxuXHRwcml2YXRlIGdwdVNwaW5lRGF0YTogUmVjb3JkPHN0cmluZywgR3B1U3BpbmVEYXRhRWxlbWVudD4gPSB7fTtcblx0cHJpdmF0ZSByZWFkb25seSBfZGVzdHJveVJlbmRlcmFibGVCb3VuZCA9IHRoaXMuZGVzdHJveVJlbmRlcmFibGUuYmluZCh0aGlzKSBhcyAocmVuZGVyYWJsZTogQ29udGFpbmVyKSA9PiB2b2lkO1xuXG5cdGNvbnN0cnVjdG9yIChyZW5kZXJlcjogUmVuZGVyZXIpIHtcblx0XHR0aGlzLnJlbmRlcmVyID0gcmVuZGVyZXI7XG5cdH1cblxuXHR2YWxpZGF0ZVJlbmRlcmFibGUgKHNwaW5lOiBTcGluZSk6IGJvb2xlYW4ge1xuXHRcdGlmICh0aGlzLnJlbmRlcmVyLnR5cGUgPT09IFJlbmRlcmVyVHlwZS5DQU5WQVMpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdHNwaW5lLl92YWxpZGF0ZUFuZFRyYW5zZm9ybUF0dGFjaG1lbnRzKCk7XG5cblx0XHQvLyBpZiBzcGluZSBhdHRhY2htZW50cyBoYXZlIGNoYW5nZWQgb3IgZGVzdHJveWVkLCB3ZSBuZWVkIHRvIHJlYnVpbGQgdGhlIGJhdGNoIVxuXHRcdGlmIChzcGluZS5zcGluZUF0dGFjaG1lbnRzRGlydHkpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIGlmIHRoZSB0ZXh0dXJlcyBoYXZlIGNoYW5nZWQsIHdlIG5lZWQgdG8gcmVidWlsZCB0aGUgYmF0Y2gsIGJ1dCBvbmx5IGlmIHRoZSB0ZXh0dXJlIGlzIG5vdCBhbHJlYWR5IGluIHRoZSBiYXRjaFxuXHRcdGVsc2UgaWYgKHNwaW5lLnNwaW5lVGV4dHVyZXNEaXJ0eSkge1xuXHRcdFx0Ly8gbG9vcCB0aHJvdWdoIGFuZCBzZWUgaWYgdGhlIHRleHR1cmVzIGhhdmUgY2hhbmdlZC4uXG5cdFx0XHRjb25zdCBkcmF3T3JkZXIgPSBzcGluZS5za2VsZXRvbi5kcmF3T3JkZXIuYXBwbGllZFBvc2U7XG5cdFx0XHRjb25zdCBncHVTcGluZSA9IHRoaXMuZ3B1U3BpbmVEYXRhW3NwaW5lLnVpZF07XG5cblx0XHRcdGlmICghZ3B1U3BpbmUpIHJldHVybiBmYWxzZTtcblxuXHRcdFx0Zm9yIChsZXQgaSA9IDAsIG4gPSBkcmF3T3JkZXIubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG5cdFx0XHRcdGNvbnN0IHNsb3QgPSBkcmF3T3JkZXJbaV07XG5cdFx0XHRcdGNvbnN0IGF0dGFjaG1lbnQgPSBzbG90LmFwcGxpZWRQb3NlLmF0dGFjaG1lbnQ7XG5cblx0XHRcdFx0aWYgKGF0dGFjaG1lbnQgaW5zdGFuY2VvZiBSZWdpb25BdHRhY2htZW50IHx8IGF0dGFjaG1lbnQgaW5zdGFuY2VvZiBNZXNoQXR0YWNobWVudCkge1xuXHRcdFx0XHRcdGNvbnN0IGNhY2hlRGF0YSA9IHNwaW5lLl9nZXRDYWNoZWREYXRhKHNsb3QsIGF0dGFjaG1lbnQpO1xuXHRcdFx0XHRcdGNvbnN0IGJhdGNoYWJsZVNwaW5lU2xvdCA9IGdwdVNwaW5lLnNsb3RCYXRjaGVzW2NhY2hlRGF0YS5pZF07XG5cblx0XHRcdFx0XHRjb25zdCB0ZXh0dXJlID0gY2FjaGVEYXRhLnRleHR1cmU7XG5cblx0XHRcdFx0XHRpZiAodGV4dHVyZSAhPT0gYmF0Y2hhYmxlU3BpbmVTbG90Py50ZXh0dXJlKSB7XG5cdFx0XHRcdFx0XHRpZiAoIWJhdGNoYWJsZVNwaW5lU2xvdD8uX2JhdGNoZXIuY2hlY2tBbmRVcGRhdGVUZXh0dXJlKGJhdGNoYWJsZVNwaW5lU2xvdCwgdGV4dHVyZSkpIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0ZXhlY3V0ZSAoc3BpbmU6IFNwaW5lKSB7XG5cdFx0aWYgKHRoaXMucmVuZGVyZXIudHlwZSA9PT0gUmVuZGVyZXJUeXBlLkNBTlZBUykge1xuXHRcdFx0Y29uc3QgcmVuZGVyZXIgPSB0aGlzLnJlbmRlcmVyIGFzIENhbnZhc1JlbmRlcmVyO1xuXHRcdFx0Y29uc3QgZ3JvdXBBbHBoYSA9ICgoc3BpbmUuZ3JvdXBDb2xvckFscGhhID4+PiAyNCkgJiAweEZGKSAvIDI1NTtcblx0XHRcdGNvbnN0IGNvbnRleHRTeXN0ZW0gPSByZW5kZXJlci5jYW52YXNDb250ZXh0O1xuXHRcdFx0Y29uc3QgY29udGV4dCA9IGNvbnRleHRTeXN0ZW0uYWN0aXZlQ29udGV4dDtcblxuXHRcdFx0Y29udGV4dC5zYXZlKCk7XG5cblx0XHRcdGlmICghdGhpcy5jYW52YXNTa2VsZXRvblJlbmRlcmVyKSB7XG5cdFx0XHRcdHRoaXMuY2FudmFzU2tlbGV0b25SZW5kZXJlciA9IG5ldyBDYW52YXNTa2VsZXRvblJlbmRlcmVyKGNvbnRleHQgYXMgdW5rbm93biBhcyBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQpO1xuXHRcdFx0XHR0aGlzLmNhbnZhc1NrZWxldG9uUmVuZGVyZXIudHJpYW5nbGVSZW5kZXJpbmcgPSB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRjb250ZXh0U3lzdGVtLnNldENvbnRleHRUcmFuc2Zvcm0oc3BpbmUuZ3JvdXBUcmFuc2Zvcm0sIChyZW5kZXJlci5fcm91bmRQaXhlbHMgfCBzcGluZS5fcm91bmRQaXhlbHMpID09PSAxKTtcblxuXHRcdFx0Y29uc3Qgb2xkQWxwaGEgPSBzcGluZS5za2VsZXRvbi5jb2xvci5hO1xuXHRcdFx0c3BpbmUuc2tlbGV0b24uY29sb3IuYSAqPSBncm91cEFscGhhO1xuXHRcdFx0dGhpcy5jYW52YXNTa2VsZXRvblJlbmRlcmVyLmRyYXcoc3BpbmUuc2tlbGV0b24pO1xuXHRcdFx0c3BpbmUuc2tlbGV0b24uY29sb3IuYSA9IG9sZEFscGhhO1xuXG5cdFx0XHRjb250ZXh0LnJlc3RvcmUoKTtcblx0XHR9XG5cdH1cblxuXHRhZGRSZW5kZXJhYmxlIChzcGluZTogU3BpbmUsIGluc3RydWN0aW9uU2V0OiBJbnN0cnVjdGlvblNldCkge1xuXHRcdGlmICh0aGlzLnJlbmRlcmVyLnR5cGUgPT09IFJlbmRlcmVyVHlwZS5DQU5WQVMpIHtcblx0XHRcdHRoaXMucmVuZGVyZXIucmVuZGVyUGlwZXMuYmF0Y2guYnJlYWsoaW5zdHJ1Y3Rpb25TZXQpO1xuXHRcdFx0aW5zdHJ1Y3Rpb25TZXQuYWRkKHNwaW5lKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRjb25zdCBncHVTcGluZSA9IHRoaXMuX2dldFNwaW5lRGF0YShzcGluZSk7XG5cblx0XHRjb25zdCBiYXRjaGVyID0gdGhpcy5yZW5kZXJlci5yZW5kZXJQaXBlcy5iYXRjaDtcblxuXHRcdGNvbnN0IGRyYXdPcmRlciA9IHNwaW5lLnNrZWxldG9uLmRyYXdPcmRlci5hcHBsaWVkUG9zZTtcblxuXHRcdGNvbnN0IHJvdW5kUGl4ZWxzID0gKHRoaXMucmVuZGVyZXIuX3JvdW5kUGl4ZWxzIHwgc3BpbmUuX3JvdW5kUGl4ZWxzKSBhcyAwIHwgMTtcblxuXHRcdHNwaW5lLl92YWxpZGF0ZUFuZFRyYW5zZm9ybUF0dGFjaG1lbnRzKCk7XG5cblx0XHRzcGluZS5zcGluZUF0dGFjaG1lbnRzRGlydHkgPSBmYWxzZTtcblx0XHRzcGluZS5zcGluZVRleHR1cmVzRGlydHkgPSBmYWxzZTtcblxuXHRcdGZvciAobGV0IGkgPSAwLCBuID0gZHJhd09yZGVyLmxlbmd0aDsgaSA8IG47IGkrKykge1xuXHRcdFx0Y29uc3Qgc2xvdCA9IGRyYXdPcmRlcltpXTtcblx0XHRcdGNvbnN0IGF0dGFjaG1lbnQgPSBzbG90LmFwcGxpZWRQb3NlLmF0dGFjaG1lbnQ7XG5cdFx0XHRjb25zdCBibGVuZE1vZGUgPSBzcGluZUJsZW5kTW9kZU1hcFtzbG90LmRhdGEuYmxlbmRNb2RlXTtcblx0XHRcdGxldCBza2lwUmVuZGVyID0gZmFsc2U7XG5cblx0XHRcdGlmIChhdHRhY2htZW50IGluc3RhbmNlb2YgUmVnaW9uQXR0YWNobWVudCB8fCBhdHRhY2htZW50IGluc3RhbmNlb2YgTWVzaEF0dGFjaG1lbnQpIHtcblx0XHRcdFx0Y29uc3QgY2FjaGVEYXRhID0gc3BpbmUuX2dldENhY2hlZERhdGEoc2xvdCwgYXR0YWNobWVudCk7XG5cdFx0XHRcdGNvbnN0IGJhdGNoYWJsZVNwaW5lU2xvdCA9IGdwdVNwaW5lLnNsb3RCYXRjaGVzW2NhY2hlRGF0YS5pZF0gfHw9IG5ldyBCYXRjaGFibGVTcGluZVNsb3QoKTtcblxuXHRcdFx0XHRiYXRjaGFibGVTcGluZVNsb3Quc2V0RGF0YShcblx0XHRcdFx0XHRzcGluZSxcblx0XHRcdFx0XHRjYWNoZURhdGEsXG5cdFx0XHRcdFx0YmxlbmRNb2RlLFxuXHRcdFx0XHRcdHJvdW5kUGl4ZWxzXG5cdFx0XHRcdCk7XG5cblx0XHRcdFx0c2tpcFJlbmRlciA9IGNhY2hlRGF0YS5za2lwUmVuZGVyO1xuXHRcdFx0XHRpZiAoIXNraXBSZW5kZXIpIHtcblx0XHRcdFx0XHRiYXRjaGVyLmFkZFRvQmF0Y2goYmF0Y2hhYmxlU3BpbmVTbG90LCBpbnN0cnVjdGlvblNldCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgY29udGFpbmVyQXR0YWNobWVudCA9IHNwaW5lLl9zbG90c09iamVjdFtzbG90LmRhdGEubmFtZV07XG5cblx0XHRcdGlmIChjb250YWluZXJBdHRhY2htZW50KSB7XG5cdFx0XHRcdGNvbnN0IGNvbnRhaW5lciA9IGNvbnRhaW5lckF0dGFjaG1lbnQuY29udGFpbmVyO1xuXG5cdFx0XHRcdGNvbnRhaW5lci5pbmNsdWRlSW5CdWlsZCA9IHRydWU7XG5cdFx0XHRcdC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vcGl4aWpzL3BpeGlqcy9ibG9iL2I0YzA1MGE3OTFmZTY1ZTk3OWU0NjdjOWNiYTJiZGEwYzAxYTFjMzUvc3JjL3NjZW5lL2NvbnRhaW5lci91dGlscy9jb2xsZWN0QWxsUmVuZGVyYWJsZXMudHMjTDI4XG5cdFx0XHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N0eWxlL25vTm9uTnVsbEFzc2VydGlvbjogaXQgd2FzIGluIHBpeGkgY29kZVxuXHRcdFx0XHRjb250YWluZXIuY29sbGVjdFJlbmRlcmFibGVzKGluc3RydWN0aW9uU2V0LCB0aGlzLnJlbmRlcmVyLCBudWxsISk7XG5cblx0XHRcdFx0Y29udGFpbmVyLmluY2x1ZGVJbkJ1aWxkID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0dXBkYXRlUmVuZGVyYWJsZSAoc3BpbmU6IFNwaW5lKSB7XG5cdFx0Y29uc3QgZ3B1U3BpbmUgPSB0aGlzLmdwdVNwaW5lRGF0YVtzcGluZS51aWRdO1xuXG5cdFx0aWYgKCFncHVTcGluZSkgcmV0dXJuO1xuXG5cdFx0c3BpbmUuX3ZhbGlkYXRlQW5kVHJhbnNmb3JtQXR0YWNobWVudHMoKTtcblxuXHRcdHNwaW5lLnNwaW5lQXR0YWNobWVudHNEaXJ0eSA9IGZhbHNlO1xuXHRcdHNwaW5lLnNwaW5lVGV4dHVyZXNEaXJ0eSA9IGZhbHNlO1xuXG5cdFx0Y29uc3QgZHJhd09yZGVyID0gc3BpbmUuc2tlbGV0b24uZHJhd09yZGVyLmFwcGxpZWRQb3NlO1xuXG5cdFx0Zm9yIChsZXQgaSA9IDAsIG4gPSBkcmF3T3JkZXIubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG5cdFx0XHRjb25zdCBzbG90ID0gZHJhd09yZGVyW2ldO1xuXHRcdFx0Y29uc3QgYXR0YWNobWVudCA9IHNsb3QuYXBwbGllZFBvc2UuYXR0YWNobWVudDtcblxuXHRcdFx0aWYgKGF0dGFjaG1lbnQgaW5zdGFuY2VvZiBSZWdpb25BdHRhY2htZW50IHx8IGF0dGFjaG1lbnQgaW5zdGFuY2VvZiBNZXNoQXR0YWNobWVudCkge1xuXHRcdFx0XHRjb25zdCBjYWNoZURhdGEgPSBzcGluZS5fZ2V0Q2FjaGVkRGF0YShzbG90LCBhdHRhY2htZW50KTtcblxuXHRcdFx0XHRpZiAoIWNhY2hlRGF0YS5za2lwUmVuZGVyKSB7XG5cdFx0XHRcdFx0Y29uc3QgYmF0Y2hhYmxlU3BpbmVTbG90ID0gZ3B1U3BpbmUuc2xvdEJhdGNoZXNbY2FjaGVEYXRhLmlkXTtcblx0XHRcdFx0XHRpZiAoYmF0Y2hhYmxlU3BpbmVTbG90KSB7XG5cdFx0XHRcdFx0XHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdHlsZS9ub05vbk51bGxBc3NlcnRpb246IGlmIGNsaXBwZWQgaXMgdHJ1ZSwgY2xpcHBlZERhdGEgZXhpc3RzXG5cdFx0XHRcdFx0XHRiYXRjaGFibGVTcGluZVNsb3QudXZzID0gY2FjaGVEYXRhLmNsaXBwZWQgPyBjYWNoZURhdGEuY2xpcHBlZERhdGEhLnV2cyA6IGNhY2hlRGF0YS51dnM7XG5cdFx0XHRcdFx0XHRiYXRjaGFibGVTcGluZVNsb3QuX2JhdGNoZXI/LnVwZGF0ZUVsZW1lbnQoYmF0Y2hhYmxlU3BpbmVTbG90KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRkZXN0cm95UmVuZGVyYWJsZSAoc3BpbmU6IFNwaW5lKSB7XG5cdFx0KHRoaXMuZ3B1U3BpbmVEYXRhW3NwaW5lLnVpZF0gYXMgdW5rbm93bikgPSBudWxsO1xuXHRcdHNwaW5lLm9mZignZGVzdHJveWVkJywgdGhpcy5fZGVzdHJveVJlbmRlcmFibGVCb3VuZCk7XG5cdH1cblxuXHRkZXN0cm95ICgpIHtcblx0XHQodGhpcy5ncHVTcGluZURhdGEgYXMgdW5rbm93bikgPSBudWxsO1xuXHRcdCh0aGlzLnJlbmRlcmVyIGFzIHVua25vd24pID0gbnVsbDtcblx0XHQodGhpcy5jYW52YXNTa2VsZXRvblJlbmRlcmVyIGFzIHVua25vd24pID0gbnVsbDtcblx0fVxuXG5cdHByaXZhdGUgX2dldFNwaW5lRGF0YSAoc3BpbmU6IFNwaW5lKTogR3B1U3BpbmVEYXRhRWxlbWVudCB7XG5cdFx0cmV0dXJuIHRoaXMuZ3B1U3BpbmVEYXRhW3NwaW5lLnVpZF0gfHwgdGhpcy5faW5pdE1lc2hEYXRhKHNwaW5lKTtcblx0fVxuXG5cdHByaXZhdGUgX2luaXRNZXNoRGF0YSAoc3BpbmU6IFNwaW5lKTogR3B1U3BpbmVEYXRhRWxlbWVudCB7XG5cdFx0dGhpcy5ncHVTcGluZURhdGFbc3BpbmUudWlkXSA9IHsgc2xvdEJhdGNoZXM6IHt9IH07XG5cdFx0c3BpbmUub24oJ2Rlc3Ryb3llZCcsIHRoaXMuX2Rlc3Ryb3lSZW5kZXJhYmxlQm91bmQpO1xuXHRcdHJldHVybiB0aGlzLmdwdVNwaW5lRGF0YVtzcGluZS51aWRdO1xuXHR9XG59XG5cbmV4dGVuc2lvbnMuYWRkKFNwaW5lUGlwZSk7XG4iXX0=