/** * @license * Copyright 2021 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================================= */ import { backend_util, buffer, DataStorage, engine, env, kernel_impls, KernelBackend, util } from '@tensorflow/tfjs-core'; const whereImpl = kernel_impls.whereImpl; import { assertNotComplex } from './cpu_util'; class MathBackendCPU extends KernelBackend { nextDataId() { return MathBackendCPU.nextDataId++; } constructor() { super(); this.blockSize = 48; this.firstUse = true; this.data = new DataStorage(this, engine()); } write(values, shape, dtype) { if (this.firstUse) { this.firstUse = false; if (env().get('IS_NODE')) { backend_util.warn('\n============================\n' + 'Hi, looks like you are running TensorFlow.js in ' + 'Node.js. To speed things up dramatically, install our node ' + 'backend, visit https://github.com/tensorflow/tfjs-node for more details. ' + '\n============================'); } } const dataId = { id: this.nextDataId() }; this.data.set(dataId, { values, dtype, refCount: 1 }); return dataId; } /** * Create a data bucket in cpu backend. * @param shape Shape of the `TensorInfo`. * @param dtype DType of the `TensorInfo`. * @param values The value of the `TensorInfo` stored as a flattened array. */ makeTensorInfo(shape, dtype, values) { let outId; if (dtype === 'string' && values != null && values.length > 0 && util.isString(values[0])) { const encodedValues = values.map(d => util.encodeString(d)); outId = this.write(encodedValues, shape, dtype); } else { outId = this.write(values, shape, dtype); } return { dataId: outId, shape, dtype }; } /** Return refCount of a `TensorData`. */ refCount(dataId) { if (this.data.has(dataId)) { const tensorData = this.data.get(dataId); return tensorData.refCount; } return 0; } /** Increase refCount of a `TensorData`. */ incRef(dataId) { const tensorData = this.data.get(dataId); tensorData.refCount++; } /** Decrease refCount of a `TensorData`. */ decRef(dataId) { if (this.data.has(dataId)) { const tensorData = this.data.get(dataId); tensorData.refCount--; } } move(dataId, values, shape, dtype, refCount) { this.data.set(dataId, { values, dtype, refCount }); } numDataIds() { return this.data.numDataIds(); } async read(dataId) { return this.readSync(dataId); } readSync(dataId) { const { dtype, complexTensorInfos } = this.data.get(dataId); if (dtype === 'complex64') { const realValues = this.readSync(complexTensorInfos.real.dataId); const imagValues = this.readSync(complexTensorInfos.imag.dataId); return backend_util.mergeRealAndImagArrays(realValues, imagValues); } return util.convertBackendValuesAndArrayBuffer(this.data.get(dataId).values, dtype); } bufferSync(t) { const data = this.readSync(t.dataId); if (t.dtype === 'string') { try { // Decode the bytes into string. const strings = data.map(d => util.decodeString(d)); return buffer(t.shape, t.dtype, strings); } catch (_a) { throw new Error('Failed to decode encoded string bytes into utf-8'); } } return buffer(t.shape, t.dtype, data); } makeOutput(values, shape, dtype) { return engine().makeTensorFromTensorInfo(this.makeTensorInfo(shape, dtype, values), this); } /** * Dispose the memory if the dataId has 0 refCount. Return true if the memory * is released or memory is not managed in this backend, false if memory is * not cleared. * @param dataId * @oaram force Optional, remove the data regardless of refCount */ disposeData(dataId, force = false) { if (this.data.has(dataId)) { this.data.get(dataId).refCount--; if (!force && this.data.get(dataId).refCount > 0) { return false; } const { complexTensorInfos } = this.data.get(dataId); if (complexTensorInfos != null) { this.disposeData(complexTensorInfos.real.dataId, true); this.disposeData(complexTensorInfos.imag.dataId, true); } this.data.delete(dataId); } return true; } disposeIntermediateTensorInfo(tensorInfo) { this.disposeData(tensorInfo.dataId); } async time(f) { const start = util.now(); f(); const kernelMs = util.now() - start; return { kernelMs }; } memory() { return { // Unreliable due to automatic gc. The numbers above are cumulative. unreliable: true, reasons: ['The reported memory is an upper bound. Due to automatic garbage ' + 'collection, the true allocated memory may be less.'] }; } where(condition) { assertNotComplex([condition], 'where'); const condVals = this.readSync(condition.dataId); return whereImpl(condition.shape, condVals); } dispose() { } floatPrecision() { return 32; } /** Returns the smallest representable number. */ epsilon() { return super.epsilon(); } } MathBackendCPU.nextDataId = 0; export { MathBackendCPU }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFja2VuZF9jcHUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi90ZmpzLWJhY2tlbmQtY3B1L3NyYy9iYWNrZW5kX2NwdS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFFSCxPQUFPLEVBQUMsWUFBWSxFQUFxQixNQUFNLEVBQUUsV0FBVyxFQUFZLE1BQU0sRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLGFBQWEsRUFBMEUsSUFBSSxFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFFN04sTUFBTSxTQUFTLEdBQUcsWUFBWSxDQUFDLFNBQVMsQ0FBQztBQUN6QyxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSxZQUFZLENBQUM7QUFnQjVDLE1BQWEsY0FBZSxTQUFRLGFBQWE7SUFNdkMsVUFBVTtRQUNoQixPQUFPLGNBQWMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUNyQyxDQUFDO0lBRUQ7UUFDRSxLQUFLLEVBQUUsQ0FBQztRQVZILGNBQVMsR0FBRyxFQUFFLENBQUM7UUFHZCxhQUFRLEdBQUcsSUFBSSxDQUFDO1FBUXRCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxXQUFXLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDOUMsQ0FBQztJQUVRLEtBQUssQ0FDVixNQUFrQyxFQUFFLEtBQWUsRUFDbkQsS0FBZTtRQUNqQixJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDakIsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7WUFDdEIsSUFBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLEVBQUU7Z0JBQ3hCLFlBQVksQ0FBQyxJQUFJLENBQ2Isa0NBQWtDO29CQUNsQyxrREFBa0Q7b0JBQ2xELDZEQUE2RDtvQkFDN0QsMkVBQTJFO29CQUMzRSxnQ0FBZ0MsQ0FBQyxDQUFDO2FBQ3ZDO1NBQ0Y7UUFDRCxNQUFNLE1BQU0sR0FBRyxFQUFD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QUFLLENBQUM7UUFDcEMsT0FBTyxFQUFDLFFBQVEsRUFBQyxDQUFDO0lBQ3BCLENBQUM7SUFFUSxNQUFNO1FBQ2IsT0FBTztZQUNMLG9FQUFvRTtZQUNwRSxVQUFVLEVBQUUsSUFBSTtZQUNoQixPQUFPLEVBQ0gsQ0FBQyxrRUFBa0U7b0JBQ2xFLG9EQUFvRCxDQUFDO1NBQzNELENBQUM7SUFDSixDQUFDO0lBRUQsS0FBSyxDQUFDLFNBQWlCO1FBQ3JCLGdCQUFnQixDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFdkMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFlLENBQUM7UUFDL0QsT0FBTyxTQUFTLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBRVEsT0FBTyxLQUFJLENBQUM7SUFFWixjQUFjO1FBQ3JCLE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztJQUVELGtEQUFrRDtJQUN6QyxPQUFPO1FBQ2QsT0FBTyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDekIsQ0FBQzs7QUE5TGMseUJBQVUsR0FBRyxDQUFDLEFBQUosQ0FBSztTQUxuQixjQUFjIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjEgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG5pbXBvcnQge2JhY2tlbmRfdXRpbCwgQmFja2VuZFRpbWluZ0luZm8sIGJ1ZmZlciwgRGF0YVN0b3JhZ2UsIERhdGFUeXBlLCBlbmdpbmUsIGVudiwga2VybmVsX2ltcGxzLCBLZXJuZWxCYWNrZW5kLCBSYW5rLCBTaGFwZU1hcCwgVGVuc29yLCBUZW5zb3IyRCwgVGVuc29yQnVmZmVyLCBUZW5zb3JJbmZvLCBUeXBlZEFycmF5LCB1dGlsfSBmcm9tICdAdGVuc29yZmxvdy90ZmpzLWNvcmUnO1xuXG5jb25zdCB3aGVyZUltcGwgPSBrZXJuZWxfaW1wbHMud2hlcmVJbXBsO1xuaW1wb3J0IHthc3NlcnROb3RDb21wbGV4fSBmcm9tICcuL2NwdV91dGlsJztcblxuaW50ZXJmYWNlIERhdGFJZCB7fVxuXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvckRhdGE8RCBleHRlbmRzIERhdGFUeXBlPiB7XG4gIHZhbHVlcz86IGJhY2tlbmRfdXRpbC5CYWNrZW5kVmFsdWVzO1xuICBkdHlwZTogRDtcbiAgLy8gRm9yIGNvbXBsZXggbnVtYmVycywgdGhlIHJlYWwgYW5kIGltYWdpbmFyeSBwYXJ0cyBhcmUgc3RvcmVkIGFzIHRoZWlyIG93blxuICAvLyBpbmRpdmlkdWFsIHRlbnNvcnMsIHdpdGggYSBwYXJlbnQgam9pbmluZyB0aGUgdHdvIHdpdGggdGhlXG4gIC8vIGNvbXBsZXhUZW5zb3JJbmZvcyBmaWVsZC5cbiAgY29tcGxleFRlbnNvckluZm9zPzoge3JlYWw6IFRlbnNvckluZm8sIGltYWc6IFRlbnNvckluZm99O1xuICAvLyByZWZDb3VudCBrZWVwcyB0cmFjayBvZiBob3cgbWFueSB0ZW5zb3JzIHJlZmVyZW5jZSBpdC4gVXNlZCBmb3IgbWVtb3J5XG4gIC8vIG1hbmFnZW1lbnQuXG4gIHJlZkNvdW50OiBudW1iZXI7XG59XG5cbmV4cG9ydCBjbGFzcyBNYXRoQmFja2VuZENQVSBleHRlbmRzIEtlcm5lbEJhY2tlbmQge1xuICBwdWJsaWMgYmxvY2tTaXplID0gNDg7XG5cbiAgZGF0YTogRGF0YVN0b3JhZ2U8VGVuc29yRGF0YTxEYXRhVHlwZT4+O1xuICBwcml2YXRlIGZpcnN0VXNlID0gdHJ1ZTtcbiAgcHJpdmF0ZSBzdGF0aWMgbmV4dERhdGFJZCA9IDA7XG4gIHByaXZhdGUgbmV4dERhdGFJZCgpOiBudW1iZXIge1xuICAgIHJldHVybiBNYXRoQmFja2VuZENQVS5uZXh0RGF0YUlkKys7XG4gIH1cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMuZGF0YSA9IG5ldyBEYXRhU3RvcmFnZSh0aGlzLCBlbmdpbmUoKSk7XG4gIH1cblxuICBvdmVycmlkZSB3cml0ZShcbiAgICAgIHZhbHVlczogYmFja2VuZF91dGlsLkJhY2tlbmRWYWx1ZXMsIHNoYXBlOiBudW1iZXJbXSxcbiAgICAgIGR0eXBlOiBEYXRhVHlwZSk6IERhdGFJZCB7XG4gICAgaWYgKHRoaXMuZmlyc3RVc2UpIHtcbiAgICAgIHRoaXMuZmlyc3RVc2UgPSBmYWxzZTtcbiAgICAgIGlmIChlbnYoKS5nZXQoJ0lTX05PREUnKSkge1xuICAgICAgICBiYWNrZW5kX3V0aWwud2FybihcbiAgICAgICAgICAgICdcXG49PT09PT09PT09PT09PT09PT09PT09PT09PT09XFxuJyArXG4gICAgICAgICAgICAnSGksIGxvb2tzIGxpa2UgeW91IGFyZSBydW5uaW5nIFRlbnNvckZsb3cuanMgaW4gJyArXG4gICAgICAgICAgICAnTm9kZS5qcy4gVG8gc3BlZWQgdGhpbmdzIHVwIGRyYW1hdGljYWxseSwgaW5zdGFsbCBvdXIgbm9kZSAnICtcbiAgICAgICAgICAgICdiYWNrZW5kLCB2aXNpdCBodHRwczovL2dpdGh1Yi5jb20vdGVuc29yZmxvdy90ZmpzLW5vZGUgZm9yIG1vcmUgZGV0YWlscy4gJyArXG4gICAgICAgICAgICAnXFxuPT09PT09PT09PT09PT09PT09PT09PT09PT09PScpO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBkYXRhSWQgPSB7aWQ6IHRoaXMubmV4dERhdGFJZCgpfTtcblxuICAgIHRoaXMuZGF0YS5zZXQoZGF0YUlkLCB7dmFsdWVzLCBkdHlwZSwgcmVmQ291bnQ6IDF9KTtcblxuICAgIHJldHVybiBkYXRhSWQ7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgZGF0YSBidWNrZXQgaW4gY3B1IGJhY2tlbmQuXG4gICAqIEBwYXJhbSBzaGFwZSBTaGFwZSBvZiB0aGUgYFRlbnNvckluZm9gLlxuICAgKiBAcGFyYW0gZHR5cGUgRFR5cGUgb2YgdGhlIGBUZW5zb3JJbmZvYC5cbiAgICogQHBhcmFtIHZhbHVlcyBUaGUgdmFsdWUgb2YgdGhlIGBUZW5zb3JJbmZvYCBzdG9yZWQgYXMgYSBmbGF0dGVuZWQgYXJyYXkuXG4gICAqL1xuICBtYWtlVGVuc29ySW5mbyhcbiAgICAgIHNoYXBlOiBudW1iZXJbXSwgZHR5cGU6IERhdGFUeXBlLFxuICAgICAgdmFsdWVzPzogYmFja2VuZF91dGlsLkJhY2tlbmRWYWx1ZXN8c3RyaW5nW10pOiBUZW5zb3JJbmZvIHtcbiAgICBsZXQgb3V0SWQ7XG4gICAgaWYgKGR0eXBlID09PSAnc3RyaW5nJyAmJiB2YWx1ZXMgIT0gbnVsbCAmJiB2YWx1ZXMubGVuZ3RoID4gMCAmJlxuICAgICAgICB1dGlsLmlzU3RyaW5nKHZhbHVlc1swXSkpIHtcbiAgICAgIGNvbnN0IGVuY29kZWRWYWx1ZXMgPVxuICAgICAgICAgICh2YWx1ZXMgYXMgdW5rbm93biBhcyBzdHJpbmdbXSkubWFwKGQgPT4gdXRpbC5lbmNvZGVTdHJpbmcoZCkpO1xuXG4gICAgICBvdXRJZCA9IHRoaXMud3JpdGUoZW5jb2RlZFZhbHVlcywgc2hhcGUsIGR0eXBlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0SWQgPSB0aGlzLndyaXRlKHZhbHVlcyBhcyBUeXBlZEFycmF5LCBzaGFwZSwgZHR5cGUpO1xuICAgIH1cblxuICAgIHJldHVybiB7ZGF0YUlkOiBvdXRJZCwgc2hhcGUsIGR0eXBlfTtcbiAgfVxuXG4gIC8qKiBSZXR1cm4gcmVmQ291bnQgb2YgYSBgVGVuc29yRGF0YWAuICovXG4gIG92ZXJyaWRlIHJlZkNvdW50KGRhdGFJZDogRGF0YUlkKTogbnVtYmVyIHtcbiAgICBpZiAodGhpcy5kYXRhLmhhcyhkYXRhSWQpKSB7XG4gICAgICBjb25zdCB0ZW5zb3JEYXRhID0gdGhpcy5kYXRhLmdldChkYXRhSWQpO1xuICAgICAgcmV0dXJuIHRlbnNvckRhdGEucmVmQ291bnQ7XG4gICAgfVxuICAgIHJldHVybiAwO1xuICB9XG5cbiAgLyoqIEluY3JlYXNlIHJlZkNvdW50IG9mIGEgYFRlbnNvckRhdGFgLiAqL1xuICBvdmVycmlkZSBpbmNSZWYoZGF0YUlkOiBEYXRhSWQpOiB2b2lkIHtcbiAgICBjb25zdCB0ZW5zb3JEYXRhID0gdGhpcy5kYXRhLmdldChkYXRhSWQpO1xuICAgIHRlbnNvckRhdGEucmVmQ291bnQrKztcbiAgfVxuXG4gIC8qKiBEZWNyZWFzZSByZWZDb3VudCBvZiBhIGBUZW5zb3JEYXRhYC4gKi9cbiAgZGVjUmVmKGRhdGFJZDogRGF0YUlkKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGF0YS5oYXMoZGF0YUlkKSkge1xuICAgICAgY29uc3QgdGVuc29yRGF0YSA9IHRoaXMuZGF0YS5nZXQoZGF0YUlkKTtcbiAgICAgIHRlbnNvckRhdGEucmVmQ291bnQtLTtcbiAgICB9XG4gIH1cblxuICBvdmVycmlkZSBtb3ZlKFxuICAgICAgZGF0YUlkOiBEYXRhSWQsIHZhbHVlczogYmFja2VuZF91dGlsLkJhY2tlbmRWYWx1ZXMsIHNoYXBlOiBudW1iZXJbXSxcbiAgICAgIGR0eXBlOiBEYXRhVHlwZSwgcmVmQ291bnQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZGF0YS5zZXQoZGF0YUlkLCB7dmFsdWVzLCBkdHlwZSwgcmVmQ291bnR9KTtcbiAgfVxuXG4gIG92ZXJyaWRlIG51bURhdGFJZHMoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5kYXRhLm51bURhdGFJZHMoKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIHJlYWQoZGF0YUlkOiBEYXRhSWQpOiBQcm9taXNlPGJhY2tlbmRfdXRpbC5CYWNrZW5kVmFsdWVzPiB7XG4gICAgcmV0dXJuIHRoaXMucmVhZFN5bmMoZGF0YUlkKTtcbiAgfVxuICBvdmVycmlkZSByZWFkU3luYyhkYXRhSWQ6IERhdGFJZCk6IGJhY2tlbmRfdXRpbC5CYWNrZW5kVmFsdWVzIHtcbiAgICBjb25zdCB7ZHR5cGUsIGNvbXBsZXhUZW5zb3JJbmZvc30gPSB0aGlzLmRhdGEuZ2V0KGRhdGFJZCk7XG5cbiAgICBpZiAoZHR5cGUgPT09ICdjb21wbGV4NjQnKSB7XG4gICAgICBjb25zdCByZWFsVmFsdWVzID1cbiAgICAgICAgICB0aGlzLnJlYWRTeW5jKGNvbXBsZXhUZW5zb3JJbmZvcy5yZWFsLmRhdGFJZCkgYXMgRmxvYXQzMkFycmF5O1xuICAgICAgY29uc3QgaW1hZ1ZhbHVlcyA9XG4gICAgICAgICAgdGhpcy5yZWFkU3luYyhjb21wbGV4VGVuc29ySW5mb3MuaW1hZy5kYXRhSWQpIGFzIEZsb2F0MzJBcnJheTtcbiAgICAgIHJldHVybiBiYWNrZW5kX3V0aWwubWVyZ2VSZWFsQW5kSW1hZ0FycmF5cyhyZWFsVmFsdWVzLCBpbWFnVmFsdWVzKTtcbiAgICB9XG4gICAgcmV0dXJuIHV0aWwuY29udmVydEJhY2tlbmRWYWx1ZXNBbmRBcnJheUJ1ZmZlcihcbiAgICAgICAgdGhpcy5kYXRhLmdldChkYXRhSWQpLnZhbHVlcywgZHR5cGUpO1xuICB9XG5cbiAgYnVmZmVyU3luYzxSIGV4dGVuZHMgUmFuaywgRCBleHRlbmRzIERhdGFUeXBlPih0OiBUZW5zb3JJbmZvKTpcbiAgICAgIFRlbnNvckJ1ZmZlcjxSLCBEPiB7XG4gICAgY29uc3QgZGF0YSA9IHRoaXMucmVhZFN5bmModC5kYXRhSWQpO1xuICAgIGlmICh0LmR0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gRGVjb2RlIHRoZSBieXRlcyBpbnRvIHN0cmluZy5cbiAgICAgICAgY29uc3Qgc3RyaW5ncyA9IChkYXRhIGFzIFVpbnQ4QXJyYXlbXSkubWFwKGQgPT4gdXRpbC5kZWNvZGVTdHJpbmcoZCkpO1xuICAgICAgICByZXR1cm4gYnVmZmVyKHQuc2hhcGUgYXMgU2hhcGVNYXBbUl0sIHQuZHR5cGUsIHN0cmluZ3MpIGFzXG4gICAgICAgICAgICBUZW5zb3JCdWZmZXI8UiwgRD47XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gZGVjb2RlIGVuY29kZWQgc3RyaW5nIGJ5dGVzIGludG8gdXRmLTgnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGJ1ZmZlcih0LnNoYXBlIGFzIFNoYXBlTWFwW1JdLCB0LmR0eXBlLCBkYXRhIGFzIFR5cGVkQXJyYXkpIGFzXG4gICAgICAgIFRlbnNvckJ1ZmZlcjxSLCBEPjtcbiAgfVxuXG4gIG1ha2VPdXRwdXQ8VCBleHRlbmRzIFRlbnNvcj4oXG4gICAgICB2YWx1ZXM6IGJhY2tlbmRfdXRpbC5CYWNrZW5kVmFsdWVzLCBzaGFwZTogbnVtYmVyW10sIGR0eXBlOiBEYXRhVHlwZSk6IFQge1xuICAgIHJldHVybiBlbmdpbmUoKS5tYWtlVGVuc29yRnJvbVRlbnNvckluZm8oXG4gICAgICAgICAgICAgICB0aGlzLm1ha2VUZW5zb3JJbmZvKHNoYXBlLCBkdHlwZSwgdmFsdWVzKSwgdGhpcykgYXMgVDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNwb3NlIHRoZSBtZW1vcnkgaWYgdGhlIGRhdGFJZCBoYXMgMCByZWZDb3VudC4gUmV0dXJuIHRydWUgaWYgdGhlIG1lbW9yeVxuICAgKiBpcyByZWxlYXNlZCBvciBtZW1vcnkgaXMgbm90IG1hbmFnZWQgaW4gdGhpcyBiYWNrZW5kLCBmYWxzZSBpZiBtZW1vcnkgaXNcbiAgICogbm90IGNsZWFyZWQuXG4gICAqIEBwYXJhbSBkYXRhSWRcbiAgICogQG9hcmFtIGZvcmNlIE9wdGlvbmFsLCByZW1vdmUgdGhlIGRhdGEgcmVnYXJkbGVzcyBvZiByZWZDb3VudFxuICAgKi9cbiAgb3ZlcnJpZGUgZGlzcG9zZURhdGEoZGF0YUlkOiBEYXRhSWQsIGZvcmNlID0gZmFsc2UpOiBib29sZWFuIHtcbiAgICBpZiAodGhpcy5kYXRhLmhhcyhkYXRhSWQpKSB7XG4gICAgICB0aGlzLmRhdGEuZ2V0KGRhdGFJZCkucmVmQ291bnQtLTtcbiAgICAgIGlmICghZm9yY2UgJiYgdGhpcy5kYXRhLmdldChkYXRhSWQpLnJlZkNvdW50ID4gMCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHtjb21wbGV4VGVuc29ySW5mb3N9ID0gdGhpcy5kYXRhLmdldChkYXRhSWQpO1xuXG4gICAgICBpZiAoY29tcGxleFRlbnNvckluZm9zICE9IG51bGwpIHtcbiAgICAgICAgdGhpcy5kaXNwb3NlRGF0YShjb21wbGV4VGVuc29ySW5mb3MucmVhbC5kYXRhSWQsIHRydWUpO1xuICAgICAgICB0aGlzLmRpc3Bvc2VEYXRhKGNvbXBsZXhUZW5zb3JJbmZvcy5pbWFnLmRhdGFJZCwgdHJ1ZSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZGF0YS5kZWxldGUoZGF0YUlkKTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBkaXNwb3NlSW50ZXJtZWRpYXRlVGVuc29ySW5mbyh0ZW5zb3JJbmZvOiBUZW5zb3JJbmZvKTogdm9pZCB7XG4gICAgdGhpcy5kaXNwb3NlRGF0YSh0ZW5zb3JJbmZvLmRhdGFJZCk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyB0aW1lKGY6ICgpID0+IHZvaWQpOiBQcm9taXNlPEJhY2tlbmRUaW1pbmdJbmZvPiB7XG4gICAgY29uc3Qgc3RhcnQgPSB1dGlsLm5vdygpO1xuICAgIGYoKTtcbiAgICBjb25zdCBrZXJuZWxNcyA9IHV0aWwubm93KCkgLSBzdGFydDtcbiAgICByZXR1cm4ge2tlcm5lbE1zfTtcbiAgfVxuXG4gIG92ZXJyaWRlIG1lbW9yeSgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLy8gVW5yZWxpYWJsZSBkdWUgdG8gYXV0b21hdGljIGdjLiBUaGUgbnVtYmVycyBhYm92ZSBhcmUgY3VtdWxhdGl2ZS5cbiAgICAgIHVucmVsaWFibGU6IHRydWUsXG4gICAgICByZWFzb25zOlxuICAgICAgICAgIFsnVGhlIHJlcG9ydGVkIG1lbW9yeSBpcyBhbiB1cHBlciBib3VuZC4gRHVlIHRvIGF1dG9tYXRpYyBnYXJiYWdlICcgK1xuICAgICAgICAgICAnY29sbGVjdGlvbiwgdGhlIHRydWUgYWxsb2NhdGVkIG1lbW9yeSBtYXkgYmUgbGVzcy4nXVxuICAgIH07XG4gIH1cblxuICB3aGVyZShjb25kaXRpb246IFRlbnNvcik6IFRlbnNvcjJEIHtcbiAgICBhc3NlcnROb3RDb21wbGV4KFtjb25kaXRpb25dLCAnd2hlcmUnKTtcblxuICAgIGNvbnN0IGNvbmRWYWxzID0gdGhpcy5yZWFkU3luYyhjb25kaXRpb24uZGF0YUlkKSBhcyBUeXBlZEFycmF5O1xuICAgIHJldHVybiB3aGVyZUltcGwoY29uZGl0aW9uLnNoYXBlLCBjb25kVmFscyk7XG4gIH1cblxuICBvdmVycmlkZSBkaXNwb3NlKCkge31cblxuICBvdmVycmlkZSBmbG9hdFByZWNpc2lvbigpOiAxNnwzMiB7XG4gICAgcmV0dXJuIDMyO1xuICB9XG5cbiAgLyoqIFJldHVybnMgdGhlIHNtYWxsZXN0IHJlcHJlc2VudGFibGUgbnVtYmVyLiAgKi9cbiAgb3ZlcnJpZGUgZXBzaWxvbigpOiBudW1iZXIge1xuICAgIHJldHVybiBzdXBlci5lcHNpbG9uKCk7XG4gIH1cbn1cbiJdfQ==