UNPKG

@esotericsoftware/spine-core

Version:
434 lines 62.1 kB
/****************************************************************************** * 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 { TextureAtlas } from "./TextureAtlas.js"; export class AssetManagerBase { pathPrefix = ""; textureLoader; downloader; assets = {}; assetsRefCount = {}; assetsLoaded = {}; errors = {}; toLoad = 0; loaded = 0; constructor(textureLoader, pathPrefix = "", downloader = new Downloader()) { this.textureLoader = textureLoader; this.pathPrefix = pathPrefix; this.downloader = downloader; } start(path) { this.toLoad++; return this.pathPrefix + path; } success(callback, path, asset) { this.toLoad--; this.loaded++; this.assets[path] = asset; this.assetsRefCount[path] = (this.assetsRefCount[path] || 0) + 1; if (callback) callback(path, asset); } error(callback, path, message) { this.toLoad--; this.loaded++; this.errors[path] = message; if (callback) callback(path, message); } loadAll() { let promise = new Promise((resolve, reject) => { let check = () => { if (this.isLoadingComplete()) { if (this.hasErrors()) reject(this.errors); else resolve(this); return; } requestAnimationFrame(check); }; requestAnimationFrame(check); }); return promise; } setRawDataURI(path, data) { this.downloader.rawDataUris[this.pathPrefix + path] = data; } loadBinary(path, success = () => { }, error = () => { }) { path = this.start(path); if (this.reuseAssets(path, success, error)) return; this.assetsLoaded[path] = new Promise((resolve, reject) => { this.downloader.downloadBinary(path, (data) => { this.success(success, path, data); resolve(data); }, (status, responseText) => { const errorMsg = `Couldn't load binary ${path}: status ${status}, ${responseText}`; this.error(error, path, errorMsg); reject(errorMsg); }); }); } loadText(path, success = () => { }, error = () => { }) { path = this.start(path); this.downloader.downloadText(path, (data) => { this.success(success, path, data); }, (status, responseText) => { this.error(error, path, `Couldn't load text ${path}: status ${status}, ${responseText}`); }); } loadJson(path, success = () => { }, error = () => { }) { path = this.start(path); if (this.reuseAssets(path, success, error)) return; this.assetsLoaded[path] = new Promise((resolve, reject) => { this.downloader.downloadJson(path, (data) => { this.success(success, path, data); resolve(data); }, (status, responseText) => { const errorMsg = `Couldn't load JSON ${path}: status ${status}, ${responseText}`; this.error(error, path, errorMsg); reject(errorMsg); }); }); } reuseAssets(path, success = () => { }, error = () => { }) { const loadedStatus = this.assetsLoaded[path]; const alreadyExistsOrLoading = loadedStatus !== undefined; if (alreadyExistsOrLoading) { loadedStatus .then(data => this.success(success, path, data)) .catch(errorMsg => this.error(error, path, errorMsg)); } return alreadyExistsOrLoading; } loadTexture(path, success = () => { }, error = () => { }) { path = this.start(path); if (this.reuseAssets(path, success, error)) return; this.assetsLoaded[path] = new Promise((resolve, reject) => { let isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document); let isWebWorker = !isBrowser; // && typeof importScripts !== 'undefined'; if (isWebWorker) { fetch(path, { mode: "cors" }).then((response) => { if (response.ok) return response.blob(); const errorMsg = `Couldn't load image: ${path}`; this.error(error, path, `Couldn't load image: ${path}`); reject(errorMsg); }).then((blob) => { return blob ? createImageBitmap(blob, { premultiplyAlpha: "none", colorSpaceConversion: "none" }) : null; }).then((bitmap) => { if (bitmap) { const texture = this.textureLoader(bitmap); this.success(success, path, texture); resolve(texture); } ; }); } else { let image = new Image(); image.crossOrigin = "anonymous"; image.onload = () => { const texture = this.textureLoader(image); this.success(success, path, texture); resolve(texture); }; image.onerror = () => { const errorMsg = `Couldn't load image: ${path}`; this.error(error, path, errorMsg); reject(errorMsg); }; if (this.downloader.rawDataUris[path]) path = this.downloader.rawDataUris[path]; image.src = path; } }); } loadTextureAtlas(path, success = () => { }, error = () => { }, fileAlias) { let index = path.lastIndexOf("/"); let parent = index >= 0 ? path.substring(0, index + 1) : ""; path = this.start(path); if (this.reuseAssets(path, success, error)) return; this.assetsLoaded[path] = new Promise((resolve, reject) => { this.downloader.downloadText(path, (atlasText) => { try { let atlas = new TextureAtlas(atlasText); let toLoad = atlas.pages.length, abort = false; for (let page of atlas.pages) { this.loadTexture(!fileAlias ? parent + page.name : fileAlias[page.name], (imagePath, texture) => { if (!abort) { page.setTexture(texture); if (--toLoad == 0) { this.success(success, path, atlas); resolve(atlas); } } }, (imagePath, message) => { if (!abort) { const errorMsg = `Couldn't load texture atlas ${path} page image: ${imagePath}`; this.error(error, path, errorMsg); reject(errorMsg); } abort = true; }); } } catch (e) { const errorMsg = `Couldn't parse texture atlas ${path}: ${e.message}`; this.error(error, path, errorMsg); reject(errorMsg); } }, (status, responseText) => { const errorMsg = `Couldn't load texture atlas ${path}: status ${status}, ${responseText}`; this.error(error, path, errorMsg); reject(errorMsg); }); }); } loadTextureAtlasButNoTextures(path, success = () => { }, error = () => { }, fileAlias) { path = this.start(path); if (this.reuseAssets(path, success, error)) return; this.assetsLoaded[path] = new Promise((resolve, reject) => { this.downloader.downloadText(path, (atlasText) => { try { const atlas = new TextureAtlas(atlasText); this.success(success, path, atlas); resolve(atlas); } catch (e) { const errorMsg = `Couldn't parse texture atlas ${path}: ${e.message}`; this.error(error, path, errorMsg); reject(errorMsg); } }, (status, responseText) => { const errorMsg = `Couldn't load texture atlas ${path}: status ${status}, ${responseText}`; this.error(error, path, errorMsg); reject(errorMsg); }); }); } // Promisified versions of load function async loadBinaryAsync(path) { return new Promise((resolve, reject) => { this.loadBinary(path, (_, binary) => resolve(binary), (_, message) => reject(message)); }); } async loadJsonAsync(path) { return new Promise((resolve, reject) => { this.loadJson(path, (_, object) => resolve(object), (_, message) => reject(message)); }); } async loadTextureAsync(path) { return new Promise((resolve, reject) => { this.loadTexture(path, (_, texture) => resolve(texture), (_, message) => reject(message)); }); } async loadTextureAtlasAsync(path) { return new Promise((resolve, reject) => { this.loadTextureAtlas(path, (_, atlas) => resolve(atlas), (_, message) => reject(message)); }); } async loadTextureAtlasButNoTexturesAsync(path) { return new Promise((resolve, reject) => { this.loadTextureAtlasButNoTextures(path, (_, atlas) => resolve(atlas), (_, message) => reject(message)); }); } get(path) { return this.assets[this.pathPrefix + path]; } require(path) { path = this.pathPrefix + path; let asset = this.assets[path]; if (asset) return asset; let error = this.errors[path]; throw Error("Asset not found: " + path + (error ? "\n" + error : "")); } remove(path) { path = this.pathPrefix + path; let asset = this.assets[path]; if (asset.dispose) asset.dispose(); delete this.assets[path]; delete this.assetsRefCount[path]; delete this.assetsLoaded[path]; return asset; } removeAll() { for (let path in this.assets) { let asset = this.assets[path]; if (asset.dispose) asset.dispose(); } this.assets = {}; this.assetsLoaded = {}; this.assetsRefCount = {}; } isLoadingComplete() { return this.toLoad == 0; } getToLoad() { return this.toLoad; } getLoaded() { return this.loaded; } dispose() { this.removeAll(); } // dispose asset only if it's not used by others disposeAsset(path) { if (--this.assetsRefCount[path] === 0) { this.remove(path); } } hasErrors() { return Object.keys(this.errors).length > 0; } getErrors() { return this.errors; } } export class Downloader { callbacks = {}; rawDataUris = {}; dataUriToString(dataUri) { if (!dataUri.startsWith("data:")) { throw new Error("Not a data URI."); } let base64Idx = dataUri.indexOf("base64,"); if (base64Idx != -1) { base64Idx += "base64,".length; return atob(dataUri.substr(base64Idx)); } else { return dataUri.substr(dataUri.indexOf(",") + 1); } } base64ToUint8Array(base64) { var binary_string = window.atob(base64); var len = binary_string.length; var bytes = new Uint8Array(len); for (var i = 0; i < len; i++) { bytes[i] = binary_string.charCodeAt(i); } return bytes; } dataUriToUint8Array(dataUri) { if (!dataUri.startsWith("data:")) { throw new Error("Not a data URI."); } let base64Idx = dataUri.indexOf("base64,"); if (base64Idx == -1) throw new Error("Not a binary data URI."); base64Idx += "base64,".length; return this.base64ToUint8Array(dataUri.substr(base64Idx)); } downloadText(url, success, error) { if (this.start(url, success, error)) return; const rawDataUri = this.rawDataUris[url]; // we assume if a "." is included in a raw data uri, it is used to rewrite an asset URL if (rawDataUri && !rawDataUri.includes(".")) { try { this.finish(url, 200, this.dataUriToString(rawDataUri)); } catch (e) { this.finish(url, 400, JSON.stringify(e)); } return; } let request = new XMLHttpRequest(); request.overrideMimeType("text/html"); request.open("GET", rawDataUri ? rawDataUri : url, true); let done = () => { this.finish(url, request.status, request.responseText); }; request.onload = done; request.onerror = done; request.send(); } downloadJson(url, success, error) { this.downloadText(url, (data) => { success(JSON.parse(data)); }, error); } downloadBinary(url, success, error) { if (this.start(url, success, error)) return; const rawDataUri = this.rawDataUris[url]; // we assume if a "." is included in a raw data uri, it is used to rewrite an asset URL if (rawDataUri && !rawDataUri.includes(".")) { try { this.finish(url, 200, this.dataUriToUint8Array(rawDataUri)); } catch (e) { this.finish(url, 400, JSON.stringify(e)); } return; } let request = new XMLHttpRequest(); request.open("GET", rawDataUri ? rawDataUri : url, true); request.responseType = "arraybuffer"; let onerror = () => { this.finish(url, request.status, request.response); }; request.onload = () => { if (request.status == 200 || request.status == 0) this.finish(url, 200, new Uint8Array(request.response)); else onerror(); }; request.onerror = onerror; request.send(); } start(url, success, error) { let callbacks = this.callbacks[url]; try { if (callbacks) return true; this.callbacks[url] = callbacks = []; } finally { callbacks.push(success, error); } } finish(url, status, data) { let callbacks = this.callbacks[url]; delete this.callbacks[url]; let args = status == 200 || status == 0 ? [data] : [status, data]; for (let i = args.length - 1, n = callbacks.length; i < n; i += 2) callbacks[i].apply(null, args); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQXNzZXRNYW5hZ2VyQmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9Bc3NldE1hbmFnZXJCYXNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7K0VBMkIrRTtBQUcvRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFHakQsTUFBTSxPQUFPLGdCQUFnQjtJQUNwQixVQUFVLEdBQVcsRUFBRSxDQUFDO0lBQ3hCLGFBQWEsQ0FBcUQ7SUFDbEUsVUFBVSxDQUFhO0lBQ3ZCLE1BQU0sR0FBbUIsRUFBRSxDQUFDO0lBQzVCLGNBQWMsR0FBc0IsRUFBRSxDQUFDO0lBQ3ZDLFlBQVksR0FBNEIsRUFBRSxDQUFDO0lBQzNDLE1BQU0sR0FBc0IsRUFBRSxDQUFDO0lBQy9CLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDWCxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBRW5CLFlBQWEsYUFBaUUsRUFBRSxhQUFxQixFQUFFLEVBQUUsYUFBeUIsSUFBSSxVQUFVLEVBQUU7UUFDakosSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUM7UUFDbkMsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFDN0IsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7SUFDOUIsQ0FBQztJQUVPLEtBQUssQ0FBRSxJQUFZO1FBQzFCLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNkLE9BQU8sSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7SUFDL0IsQ0FBQztJQUVPLE9BQU8sQ0FBRSxRQUEyQyxFQUFFLElBQVksRUFBRSxLQUFVO1FBQ3JGLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNkLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNkLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDO1FBQzFCLElBQUksQ0FBQyxjQUFjLENB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QUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDakMsQ0FBQztDQUNEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICogU3BpbmUgUnVudGltZXMgTGljZW5zZSBBZ3JlZW1lbnRcbiAqIExhc3QgdXBkYXRlZCBBcHJpbCA1LCAyMDI1LiBSZXBsYWNlcyBhbGwgcHJpb3IgdmVyc2lvbnMuXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMjUsIEVzb3RlcmljIFNvZnR3YXJlIExMQ1xuICpcbiAqIEludGVncmF0aW9uIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlIG9yIG90aGVyd2lzZSBjcmVhdGluZ1xuICogZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgaXMgcGVybWl0dGVkIHVuZGVyIHRoZSB0ZXJtcyBhbmRcbiAqIGNvbmRpdGlvbnMgb2YgU2VjdGlvbiAyIG9mIHRoZSBTcGluZSBFZGl0b3IgTGljZW5zZSBBZ3JlZW1lbnQ6XG4gKiBodHRwOi8vZXNvdGVyaWNzb2Z0d2FyZS5jb20vc3BpbmUtZWRpdG9yLWxpY2Vuc2VcbiAqXG4gKiBPdGhlcndpc2UsIGl0IGlzIHBlcm1pdHRlZCB0byBpbnRlZ3JhdGUgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmVcbiAqIG9yIG90aGVyd2lzZSBjcmVhdGUgZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgKGNvbGxlY3RpdmVseSxcbiAqIFwiUHJvZHVjdHNcIiksIHByb3ZpZGVkIHRoYXQgZWFjaCB1c2VyIG9mIHRoZSBQcm9kdWN0cyBtdXN0IG9idGFpbiB0aGVpciBvd25cbiAqIFNwaW5lIEVkaXRvciBsaWNlbnNlIGFuZCByZWRpc3RyaWJ1dGlvbiBvZiB0aGUgUHJvZHVjdHMgaW4gYW55IGZvcm0gbXVzdFxuICogaW5jbHVkZSB0aGlzIGxpY2Vuc2UgYW5kIGNvcHlyaWdodCBub3RpY2UuXG4gKlxuICogVEhFIFNQSU5FIFJVTlRJTUVTIEFSRSBQUk9WSURFRCBCWSBFU09URVJJQyBTT0ZUV0FSRSBMTEMgXCJBUyBJU1wiIEFORCBBTllcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbiAqIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcbiAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIEVTT1RFUklDIFNPRlRXQVJFIExMQyBCRSBMSUFCTEUgRk9SIEFOWVxuICogRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbiAqIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUyxcbiAqIEJVU0lORVNTIElOVEVSUlVQVElPTiwgT1IgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFMpIEhPV0VWRVIgQ0FVU0VEIEFORFxuICogT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbiAqIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRlxuICogVEhFIFNQSU5FIFJVTlRJTUVTLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG5pbXBvcnQgeyBUZXh0dXJlIH0gZnJvbSBcIi4vVGV4dHVyZS5qc1wiO1xuaW1wb3J0IHsgVGV4dHVyZUF0bGFzIH0gZnJvbSBcIi4vVGV4dHVyZUF0bGFzLmpzXCI7XG5pbXBvcnQgeyBEaXNwb3NhYmxlLCBTdHJpbmdNYXAgfSBmcm9tIFwiLi9VdGlscy5qc1wiO1xuXG5leHBvcnQgY2xhc3MgQXNzZXRNYW5hZ2VyQmFzZSBpbXBsZW1lbnRzIERpc3Bvc2FibGUge1xuXHRwcml2YXRlIHBhdGhQcmVmaXg6IHN0cmluZyA9IFwiXCI7XG5cdHByaXZhdGUgdGV4dHVyZUxvYWRlcjogKGltYWdlOiBIVE1MSW1hZ2VFbGVtZW50IHwgSW1hZ2VCaXRtYXApID0+IFRleHR1cmU7XG5cdHByaXZhdGUgZG93bmxvYWRlcjogRG93bmxvYWRlcjtcblx0cHJpdmF0ZSBhc3NldHM6IFN0cmluZ01hcDxhbnk+ID0ge307XG5cdHByaXZhdGUgYXNzZXRzUmVmQ291bnQ6IFN0cmluZ01hcDxudW1iZXI+ID0ge307XG5cdHByaXZhdGUgYXNzZXRzTG9hZGVkOiBTdHJpbmdNYXA8UHJvbWlzZTxhbnk+PiA9IHt9O1xuXHRwcml2YXRlIGVycm9yczogU3RyaW5nTWFwPHN0cmluZz4gPSB7fTtcblx0cHJpdmF0ZSB0b0xvYWQgPSAwO1xuXHRwcml2YXRlIGxvYWRlZCA9IDA7XG5cblx0Y29uc3RydWN0b3IgKHRleHR1cmVMb2FkZXI6IChpbWFnZTogSFRNTEltYWdlRWxlbWVudCB8IEltYWdlQml0bWFwKSA9PiBUZXh0dXJlLCBwYXRoUHJlZml4OiBzdHJpbmcgPSBcIlwiLCBkb3dubG9hZGVyOiBEb3dubG9hZGVyID0gbmV3IERvd25sb2FkZXIoKSkge1xuXHRcdHRoaXMudGV4dHVyZUxvYWRlciA9IHRleHR1cmVMb2FkZXI7XG5cdFx0dGhpcy5wYXRoUHJlZml4ID0gcGF0aFByZWZpeDtcblx0XHR0aGlzLmRvd25sb2FkZXIgPSBkb3dubG9hZGVyO1xuXHR9XG5cblx0cHJpdmF0ZSBzdGFydCAocGF0aDogc3RyaW5nKTogc3RyaW5nIHtcblx0XHR0aGlzLnRvTG9hZCsrO1xuXHRcdHJldHVybiB0aGlzLnBhdGhQcmVmaXggKyBwYXRoO1xuXHR9XG5cblx0cHJpdmF0ZSBzdWNjZXNzIChjYWxsYmFjazogKHBhdGg6IHN0cmluZywgZGF0YTogYW55KSA9PiB2b2lkLCBwYXRoOiBzdHJpbmcsIGFzc2V0OiBhbnkpIHtcblx0XHR0aGlzLnRvTG9hZC0tO1xuXHRcdHRoaXMubG9hZGVkKys7XG5cdFx0dGhpcy5hc3NldHNbcGF0aF0gPSBhc3NldDtcblx0XHR0aGlzLmFzc2V0c1JlZkNvdW50W3BhdGhdID0gKHRoaXMuYXNzZXRzUmVmQ291bnRbcGF0aF0gfHwgMCkgKyAxO1xuXHRcdGlmIChjYWxsYmFjaykgY2FsbGJhY2socGF0aCwgYXNzZXQpO1xuXHR9XG5cblx0cHJpdmF0ZSBlcnJvciAoY2FsbGJhY2s6IChwYXRoOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZykgPT4gdm9pZCwgcGF0aDogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpIHtcblx0XHR0aGlzLnRvTG9hZC0tO1xuXHRcdHRoaXMubG9hZGVkKys7XG5cdFx0dGhpcy5lcnJvcnNbcGF0aF0gPSBtZXNzYWdlO1xuXHRcdGlmIChjYWxsYmFjaykgY2FsbGJhY2socGF0aCwgbWVzc2FnZSk7XG5cdH1cblxuXHRsb2FkQWxsICgpIHtcblx0XHRsZXQgcHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlOiAoYXNzZXRNYW5hZ2VyOiBBc3NldE1hbmFnZXJCYXNlKSA9PiB2b2lkLCByZWplY3Q6IChlcnJvcnM6IFN0cmluZ01hcDxzdHJpbmc+KSA9PiB2b2lkKSA9PiB7XG5cdFx0XHRsZXQgY2hlY2sgPSAoKSA9PiB7XG5cdFx0XHRcdGlmICh0aGlzLmlzTG9hZGluZ0NvbXBsZXRlKCkpIHtcblx0XHRcdFx0XHRpZiAodGhpcy5oYXNFcnJvcnMoKSkgcmVqZWN0KHRoaXMuZXJyb3JzKTtcblx0XHRcdFx0XHRlbHNlIHJlc29sdmUodGhpcyk7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJlcXVlc3RBbmltYXRpb25GcmFtZShjaGVjayk7XG5cdFx0XHR9XG5cdFx0XHRyZXF1ZXN0QW5pbWF0aW9uRnJhbWUoY2hlY2spO1xuXHRcdH0pO1xuXHRcdHJldHVybiBwcm9taXNlO1xuXHR9XG5cblx0c2V0UmF3RGF0YVVSSSAocGF0aDogc3RyaW5nLCBkYXRhOiBzdHJpbmcpIHtcblx0XHR0aGlzLmRvd25sb2FkZXIucmF3RGF0YVVyaXNbdGhpcy5wYXRoUHJlZml4ICsgcGF0aF0gPSBkYXRhO1xuXHR9XG5cblx0bG9hZEJpbmFyeSAocGF0aDogc3RyaW5nLFxuXHRcdHN1Y2Nlc3M6IChwYXRoOiBzdHJpbmcsIGJpbmFyeTogVWludDhBcnJheSkgPT4gdm9pZCA9ICgpID0+IHsgfSxcblx0XHRlcnJvcjogKHBhdGg6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkID0gKCkgPT4geyB9KSB7XG5cdFx0cGF0aCA9IHRoaXMuc3RhcnQocGF0aCk7XG5cblx0XHRpZiAodGhpcy5yZXVzZUFzc2V0cyhwYXRoLCBzdWNjZXNzLCBlcnJvcikpIHJldHVybjtcblxuXHRcdHRoaXMuYXNzZXRzTG9hZGVkW3BhdGhdID0gbmV3IFByb21pc2U8YW55PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cdFx0XHR0aGlzLmRvd25sb2FkZXIuZG93bmxvYWRCaW5hcnkocGF0aCwgKGRhdGE6IFVpbnQ4QXJyYXkpOiB2b2lkID0+IHtcblx0XHRcdFx0dGhpcy5zdWNjZXNzKHN1Y2Nlc3MsIHBhdGgsIGRhdGEpO1xuXHRcdFx0XHRyZXNvbHZlKGRhdGEpO1xuXHRcdFx0fSwgKHN0YXR1czogbnVtYmVyLCByZXNwb25zZVRleHQ6IHN0cmluZyk6IHZvaWQgPT4ge1xuXHRcdFx0XHRjb25zdCBlcnJvck1zZyA9IGBDb3VsZG4ndCBsb2FkIGJpbmFyeSAke3BhdGh9OiBzdGF0dXMgJHtzdGF0dXN9LCAke3Jlc3BvbnNlVGV4dH1gO1xuXHRcdFx0XHR0aGlzLmVycm9yKGVycm9yLCBwYXRoLCBlcnJvck1zZyk7XG5cdFx0XHRcdHJlamVjdChlcnJvck1zZyk7XG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fVxuXG5cdGxvYWRUZXh0IChwYXRoOiBzdHJpbmcsXG5cdFx0c3VjY2VzczogKHBhdGg6IHN0cmluZywgdGV4dDogc3RyaW5nKSA9PiB2b2lkID0gKCkgPT4geyB9LFxuXHRcdGVycm9yOiAocGF0aDogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQgPSAoKSA9PiB7IH0pIHtcblx0XHRwYXRoID0gdGhpcy5zdGFydChwYXRoKTtcblxuXHRcdHRoaXMuZG93bmxvYWRlci5kb3dubG9hZFRleHQocGF0aCwgKGRhdGE6IHN0cmluZyk6IHZvaWQgPT4ge1xuXHRcdFx0dGhpcy5zdWNjZXNzKHN1Y2Nlc3MsIHBhdGgsIGRhdGEpO1xuXHRcdH0sIChzdGF0dXM6IG51bWJlciwgcmVzcG9uc2VUZXh0OiBzdHJpbmcpOiB2b2lkID0+IHtcblx0XHRcdHRoaXMuZXJyb3IoZXJyb3IsIHBhdGgsIGBDb3VsZG4ndCBsb2FkIHRleHQgJHtwYXRofTogc3RhdHVzICR7c3RhdHVzfSwgJHtyZXNwb25zZVRleHR9YCk7XG5cdFx0fSk7XG5cdH1cblxuXHRsb2FkSnNvbiAocGF0aDogc3RyaW5nLFxuXHRcdHN1Y2Nlc3M6IChwYXRoOiBzdHJpbmcsIG9iamVjdDogb2JqZWN0KSA9PiB2b2lkID0gKCkgPT4geyB9LFxuXHRcdGVycm9yOiAocGF0aDogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQgPSAoKSA9PiB7IH0pIHtcblx0XHRwYXRoID0gdGhpcy5zdGFydChwYXRoKTtcblxuXHRcdGlmICh0aGlzLnJldXNlQXNzZXRzKHBhdGgsIHN1Y2Nlc3MsIGVycm9yKSkgcmV0dXJuO1xuXG5cdFx0dGhpcy5hc3NldHNMb2FkZWRbcGF0aF0gPSBuZXcgUHJvbWlzZTxhbnk+KChyZXNvbHZlLCByZWplY3QpID0+IHtcblx0XHRcdHRoaXMuZG93bmxvYWRlci5kb3dubG9hZEpzb24ocGF0aCwgKGRhdGE6IG9iamVjdCk6IHZvaWQgPT4ge1xuXHRcdFx0XHR0aGlzLnN1Y2Nlc3Moc3VjY2VzcywgcGF0aCwgZGF0YSk7XG5cdFx0XHRcdHJlc29sdmUoZGF0YSk7XG5cdFx0XHR9LCAoc3RhdHVzOiBudW1iZXIsIHJlc3BvbnNlVGV4dDogc3RyaW5nKTogdm9pZCA9PiB7XG5cdFx0XHRcdGNvbnN0IGVycm9yTXNnID0gYENvdWxkbid0IGxvYWQgSlNPTiAke3BhdGh9OiBzdGF0dXMgJHtzdGF0dXN9LCAke3Jlc3BvbnNlVGV4dH1gO1xuXHRcdFx0XHR0aGlzLmVycm9yKGVycm9yLCBwYXRoLCBlcnJvck1zZyk7XG5cdFx0XHRcdHJlamVjdChlcnJvck1zZyk7XG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fVxuXG5cdHJldXNlQXNzZXRzIChwYXRoOiBzdHJpbmcsXG5cdFx0c3VjY2VzczogKHBhdGg6IHN0cmluZywgZGF0YTogYW55KSA9PiB2b2lkID0gKCkgPT4geyB9LFxuXHRcdGVycm9yOiAocGF0aDogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQgPSAoKSA9PiB7IH0pIHtcblx0XHRjb25zdCBsb2FkZWRTdGF0dXMgPSB0aGlzLmFzc2V0c0xvYWRlZFtwYXRoXTtcblx0XHRjb25zdCBhbHJlYWR5RXhpc3RzT3JMb2FkaW5nID0gbG9hZGVkU3RhdHVzICE9PSB1bmRlZmluZWQ7XG5cdFx0aWYgKGFscmVhZHlFeGlzdHNPckxvYWRpbmcpIHtcblx0XHRcdGxvYWRlZFN0YXR1c1xuXHRcdFx0XHQudGhlbihkYXRhID0+IHRoaXMuc3VjY2VzcyhzdWNjZXNzLCBwYXRoLCBkYXRhKSlcblx0XHRcdFx0LmNhdGNoKGVycm9yTXNnID0+IHRoaXMuZXJyb3IoZXJyb3IsIHBhdGgsIGVycm9yTXNnKSk7XG5cdFx0fVxuXHRcdHJldHVybiBhbHJlYWR5RXhpc3RzT3JMb2FkaW5nO1xuXHR9XG5cblx0bG9hZFRleHR1cmUgKHBhdGg6IHN0cmluZyxcblx0XHRzdWNjZXNzOiAocGF0aDogc3RyaW5nLCB0ZXh0dXJlOiBUZXh0dXJlKSA9PiB2b2lkID0gKCkgPT4geyB9LFxuXHRcdGVycm9yOiAocGF0aDogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQgPSAoKSA9PiB7IH0pIHtcblxuXHRcdHBhdGggPSB0aGlzLnN0YXJ0KHBhdGgpO1xuXG5cdFx0aWYgKHRoaXMucmV1c2VBc3NldHMocGF0aCwgc3VjY2VzcywgZXJyb3IpKSByZXR1cm47XG5cblx0XHR0aGlzLmFzc2V0c0xvYWRlZFtwYXRoXSA9IG5ldyBQcm9taXNlPGFueT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXHRcdFx0bGV0IGlzQnJvd3NlciA9ICEhKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5kb2N1bWVudCk7XG5cdFx0XHRsZXQgaXNXZWJXb3JrZXIgPSAhaXNCcm93c2VyOyAvLyAmJiB0eXBlb2YgaW1wb3J0U2NyaXB0cyAhPT0gJ3VuZGVmaW5lZCc7XG5cdFx0XHRpZiAoaXNXZWJXb3JrZXIpIHtcblx0XHRcdFx0ZmV0Y2gocGF0aCwgeyBtb2RlOiA8UmVxdWVzdE1vZGU+XCJjb3JzXCIgfSkudGhlbigocmVzcG9uc2UpID0+IHtcblx0XHRcdFx0XHRpZiAocmVzcG9uc2Uub2spIHJldHVybiByZXNwb25zZS5ibG9iKCk7XG5cdFx0XHRcdFx0Y29uc3QgZXJyb3JNc2cgPSBgQ291bGRuJ3QgbG9hZCBpbWFnZTogJHtwYXRofWA7XG5cdFx0XHRcdFx0dGhpcy5lcnJvcihlcnJvciwgcGF0aCwgYENvdWxkbid0IGxvYWQgaW1hZ2U6ICR7cGF0aH1gKTtcblx0XHRcdFx0XHRyZWplY3QoZXJyb3JNc2cpO1xuXHRcdFx0XHR9KS50aGVuKChibG9iKSA9PiB7XG5cdFx0XHRcdFx0cmV0dXJuIGJsb2IgPyBjcmVhdGVJbWFnZUJpdG1hcChibG9iLCB7IHByZW11bHRpcGx5QWxwaGE6IFwibm9uZVwiLCBjb2xvclNwYWNlQ29udmVyc2lvbjogXCJub25lXCIgfSkgOiBudWxsO1xuXHRcdFx0XHR9KS50aGVuKChiaXRtYXApID0+IHtcblx0XHRcdFx0XHRpZiAoYml0bWFwKSB7XG5cdFx0XHRcdFx0XHRjb25zdCB0ZXh0dXJlID0gdGhpcy50ZXh0dXJlTG9hZGVyKGJpdG1hcClcblx0XHRcdFx0XHRcdHRoaXMuc3VjY2VzcyhzdWNjZXNzLCBwYXRoLCB0ZXh0dXJlKTtcblx0XHRcdFx0XHRcdHJlc29sdmUodGV4dHVyZSk7XG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRsZXQgaW1hZ2UgPSBuZXcgSW1hZ2UoKTtcblx0XHRcdFx0aW1hZ2UuY3Jvc3NPcmlnaW4gPSBcImFub255bW91c1wiO1xuXHRcdFx0XHRpbWFnZS5vbmxvYWQgPSAoKSA9PiB7XG5cdFx0XHRcdFx0Y29uc3QgdGV4dHVyZSA9IHRoaXMudGV4dHVyZUxvYWRlcihpbWFnZSlcblx0XHRcdFx0XHR0aGlzLnN1Y2Nlc3Moc3VjY2VzcywgcGF0aCwgdGV4dHVyZSk7XG5cdFx0XHRcdFx0cmVzb2x2ZSh0ZXh0dXJlKTtcblx0XHRcdFx0fTtcblx0XHRcdFx0aW1hZ2Uub25lcnJvciA9ICgpID0+IHtcblx0XHRcdFx0XHRjb25zdCBlcnJvck1zZyA9IGBDb3VsZG4ndCBsb2FkIGltYWdlOiAke3BhdGh9YDtcblx0XHRcdFx0XHR0aGlzLmVycm9yKGVycm9yLCBwYXRoLCBlcnJvck1zZyk7XG5cdFx0XHRcdFx0cmVqZWN0KGVycm9yTXNnKTtcblx0XHRcdFx0fTtcblx0XHRcdFx0aWYgKHRoaXMuZG93bmxvYWRlci5yYXdEYXRhVXJpc1twYXRoXSkgcGF0aCA9IHRoaXMuZG93bmxvYWRlci5yYXdEYXRhVXJpc1twYXRoXTtcblx0XHRcdFx0aW1hZ2Uuc3JjID0gcGF0aDtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdGxvYWRUZXh0dXJlQXRsYXMgKHBhdGg6IHN0cmluZyxcblx0XHRzdWNjZXNzOiAocGF0aDogc3RyaW5nLCBhdGxhczogVGV4dHVyZUF0bGFzKSA9PiB2b2lkID0gKCkgPT4geyB9LFxuXHRcdGVycm9yOiAocGF0aDogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQgPSAoKSA9PiB7IH0sXG5cdFx0ZmlsZUFsaWFzPzogeyBba2V5d29yZDogc3RyaW5nXTogc3RyaW5nIH1cblx0KSB7XG5cdFx0bGV0IGluZGV4ID0gcGF0aC5sYXN0SW5kZXhPZihcIi9cIik7XG5cdFx0bGV0IHBhcmVudCA9IGluZGV4ID49IDAgPyBwYXRoLnN1YnN0cmluZygwLCBpbmRleCArIDEpIDogXCJcIjtcblx0XHRwYXRoID0gdGhpcy5zdGFydChwYXRoKTtcblxuXHRcdGlmICh0aGlzLnJldXNlQXNzZXRzKHBhdGgsIHN1Y2Nlc3MsIGVycm9yKSkgcmV0dXJuO1xuXG5cdFx0dGhpcy5hc3NldHNMb2FkZWRbcGF0aF0gPSBuZXcgUHJvbWlzZTxhbnk+KChyZXNvbHZlLCByZWplY3QpID0+IHtcblx0XHRcdHRoaXMuZG93bmxvYWRlci5kb3dubG9hZFRleHQocGF0aCwgKGF0bGFz