@tensorflow/tfjs-backend-wasm
Version:
This package adds a WebAssembly backend to TensorFlow.js. It currently supports the following models from our [models](https://github.com/tensorflow/tfjs-models) repo: - BlazeFace - BodyPix - CocoSSD - Face landmarks detection - HandPose - KNN classifier
107 lines • 17 kB
JavaScript
/**
* @license
* Copyright 2019 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, FusedDepthwiseConv2D } from '@tensorflow/tfjs-core';
import { FusableActivation } from './types';
let wasmFusedDepthwiseConv2d;
function setup(backend) {
wasmFusedDepthwiseConv2d =
backend.wasm.cwrap(FusedDepthwiseConv2D, null /* void */, [
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number',
'number', // outId
]);
}
function fusedDepthwiseConv2d(args) {
const { inputs, attrs, backend } = args;
const { x, filter, bias, preluActivationWeights } = inputs;
const { strides, pad, dilations, dataFormat, dimRoundingMode, activation, leakyreluAlpha } = attrs;
const convInfo = backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, true /* depthwise */);
const fusedActivation = FusableActivation[activation];
if (fusedActivation == null) {
throw new Error(`${activation} activation not yet supported for FusedDepthwiseConv2D ` +
`in the wasm backend.`);
}
const xId = backend.dataIdMap.get(x.dataId).id;
const filterId = backend.dataIdMap.get(filter.dataId).id;
const outputChannels = convInfo.outChannels;
let biasId = 0;
if (bias != null) {
const biasData = backend.dataIdMap.get(bias.dataId);
if (biasData.shape.length !== 1) {
throw new Error(`FusedDepthwiseConv2D only supports rank-1 bias but got ` +
`rank ${biasData.shape.length}.`);
}
if (biasData.shape[0] !== outputChannels) {
throw new Error(`FusedDepthwiseConv2D bias shape (${biasData.shape}) does not ` +
`match the number of output channels (${outputChannels})`);
}
biasId = biasData.id;
}
const filterHeight = convInfo.filterHeight;
const filterWidth = convInfo.filterWidth;
const padTop = convInfo.padInfo.top;
const padRight = convInfo.padInfo.right;
const padBottom = convInfo.padInfo.bottom;
const padLeft = convInfo.padInfo.left;
const dilationHeight = convInfo.dilationHeight;
const dilationWidth = convInfo.dilationWidth;
const strideHeight = convInfo.strideHeight;
const strideWidth = convInfo.strideWidth;
const inputChannels = convInfo.inChannels;
const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0;
const batchSize = convInfo.batchSize;
const inHeight = convInfo.inHeight;
const inWidth = convInfo.inWidth;
if (dataFormat !== 'NHWC') {
throw new Error(`wasm backend FusedDepthwiseConv2D does not support dataFormat:'` +
`${dataFormat}'. Please use 'NHWC'.`);
}
const out = backend.makeOutput(convInfo.outShape, 'float32');
const outId = backend.dataIdMap.get(out.dataId).id;
const preluActivationWeightsId = preluActivationWeights == null ?
0 :
backend.dataIdMap.get(preluActivationWeights.dataId).id;
wasmFusedDepthwiseConv2d(xId, batchSize, inHeight, inWidth, filterId, filterHeight, filterWidth, biasId, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, fusedActivation, preluActivationWeightsId, leakyreluAlpha || 0, outId);
return out;
}
export const fusedDepthwiseConv2DConfig = {
kernelName: FusedDepthwiseConv2D,
backendName: 'wasm',
setupFunc: setup,
kernelFunc: fusedDepthwiseConv2d
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRnVzZWREZXB0aHdpc2VDb252MkQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi90ZmpzLWJhY2tlbmQtd2FzbS9zcmMva2VybmVscy9GdXNlZERlcHRod2lzZUNvbnYyRC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFFSCxPQUFPLEVBQUMsWUFBWSxFQUFFLG9CQUFvQixFQUE0RixNQUFNLHVCQUF1QixDQUFDO0FBSXBLLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUUxQyxJQUFJLHdCQVFRLENBQUM7QUFFYixTQUFTLEtBQUssQ0FBQyxPQUFvQjtJQUNqQyx3QkFBd0I7UUFDcEIsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUN4RCxRQUFRO1lBQ1IsUUFBUTtZQUNSLFFBQVE7WUFDUixRQUFRO1lBQ1IsUUFBUTtZQUNSLFFBQVE7WUFDUixRQUFRO1lBQ1IsUUFBUTtZQUNSLFFBQVE7WUFDUixRQUFRO1lBQ1IsUUFBUTtZQUNSLFFBQVE7WUFDUixRQUFRO1lBQ1IsUUFBUTtZQUNSLFFBQVE7WUFDUixRQUFRO1lBQ1IsUUFBUTtZQUNSLFFBQVE7WUFDUixRQUFRO1lBQ1IsUUFBUTtZQUNSLFFBQVE7WUFDUixRQUFRO1lBQ1IsUUFBUSxFQUFHLFFBQVE7U0FDcEIsQ0FBQyxDQUFDO0FBQ1QsQ0FBQztBQUVELFNBQVMsb0JBQW9CLENBQUMsSUFJN0I7SUFDQyxNQUFNLEVBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUMsR0FBRyxJQUFJLENBQUM7SUFDdEMsTUFBTSxFQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLHNCQUFzQixFQUFDLEdBQUcsTUFBTSxDQUFDO0lBQ3pELE1BQU0sRUFDSixPQUFPLEVBQ1AsR0FBRyxFQUNILFNBQVMsRUFDVCxVQUFVLEVBQ1YsZUFBZSxFQUNmLFVBQVUsRUFDVixjQUFjLEVBQ2YsR0FBRyxLQUFLLENBQUM7SUFFVixNQUFNLFFBQVEsR0FBRyxZQUFZLENBQUMsaUJBQWlCLENBQzFDLENBQWMsQ0FBQyxLQUFLLEVBQUcsTUFBbUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFDckUsR0FBRyxFQUFFLGVBQWUsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7SUFFaEQsTUFBTSxlQUFlLEdBQ2pCLGlCQUFpQixDQUFDLFVBQzhCLENBQUMsQ0FBQztJQUN0RCxJQUFJLGVBQWUsSUFBSSxJQUFJLEVBQUU7UUFDM0IsTUFBTSxJQUFJLEtBQUssQ0FDWCxHQUFHLFVBQVUseURBQXlEO1lBQ3RFLHNCQUFzQixDQUFDLENBQUM7S0FDN0I7SUFFRCxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQy9DLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFFekQsTUFBTSxjQUFjLEdBQUcsUUFBUSxDQUFDLFdBQVcsQ0FBQztJQUU1QyxJQUFJLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDZixJQUFJLElBQUksSUFBSSxJQUFJLEVBQUU7UUFDaEIsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3BELElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1lBQy9CLE1BQU0sSUFBSSxLQUFLLENBQ1gseURBQXlEO2dCQUN6RCxRQUFRLFFBQVEsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztTQUN2QztRQUNELElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxjQUFjLEVBQUU7WUFDeEMsTUFBTSxJQUFJLEtBQUssQ0FDWCxvQ0FBb0MsUUFBUSxDQUFDLEtBQUssYUFBYTtnQkFDL0Qsd0NBQXdDLGNBQWMsR0FBRyxDQUFDLENBQUM7U0FDaEU7UUFDRCxNQUFNLEdBQUcsUUFBUSxDQUFDLEVBQUUsQ0FBQztLQUN0QjtJQUVELE1BQU0sWUFBWSxHQUFHLFFBQVEsQ0FBQyxZQUFZLENBQUM7SUFDM0MsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLFdBQVcsQ0FBQztJQUN6QyxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQztJQUNwQyxNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztJQUN4QyxNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUMxQyxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztJQUN0QyxNQUFNLGNBQWMsR0FBRyxRQUFRLENBQUMsY0FBYyxDQUFDO0lBQy9DLE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUM7SUFDN0MsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLFlBQVksQ0FBQztJQUMzQyxNQUFNLFdBQVcsR0FBRyxRQUFRLENBQUMsV0FBVyxDQUFDO0lBQ3pDLE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxVQUFVLENBQUM7SUFDMUMsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRCxNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDO0lBQ3JDLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUM7SUFDbkMsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQztJQUVqQyxJQUFJLFVBQVUsS0FBSyxNQUFNLEVBQUU7UUFDekIsTUFBTSxJQUFJLEtBQUssQ0FDWCxpRUFBaUU7WUFDakUsR0FBRyxVQUFVLHVCQUF1QixDQUFDLENBQUM7S0FDM0M7SUFFRCxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDN0QsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNuRCxNQUFNLHdCQUF3QixHQUFHLHNCQUFzQixJQUFJLElBQUksQ0FBQyxDQUFDO1FBQzdELENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsc0JBQXNCLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDO0lBRTVELHdCQUF3QixDQUNwQixHQUFHLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQ3RFLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLGNBQWMsRUFDdkUsYUFBYSxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLGNBQWMsRUFDdkUsZUFBZSxFQUFFLHdCQUF3QixFQUFFLGNBQWMsSUFBSSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFFM0UsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBRUQsTUFBTSxDQUFDLE1BQU0sMEJBQTBCLEdBQWlCO0lBQ3RELFVBQVUsRUFBRSxvQkFBb0I7SUFDaEMsV0FBVyxFQUFFLE1BQU07SUFDbkIsU0FBUyxFQUFFLEtBQUs7SUFDaEIsVUFBVSxFQUFFLG9CQUE2QztDQUMxRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG5pbXBvcnQge2JhY2tlbmRfdXRpbCwgRnVzZWREZXB0aHdpc2VDb252MkQsIEZ1c2VkRGVwdGh3aXNlQ29udjJEQXR0cnMsIEZ1c2VkRGVwdGh3aXNlQ29udjJESW5wdXRzLCBLZXJuZWxDb25maWcsIEtlcm5lbEZ1bmMsIFRlbnNvcjREfSBmcm9tICdAdGVuc29yZmxvdy90ZmpzLWNvcmUnO1xuXG5pbXBvcnQge0JhY2tlbmRXYXNtfSBmcm9tICcuLi9iYWNrZW5kX3dhc20nO1xuXG5pbXBvcnQge0Z1c2FibGVBY3RpdmF0aW9ufSBmcm9tICcuL3R5cGVzJztcblxubGV0IHdhc21GdXNlZERlcHRod2lzZUNvbnYyZDpcbiAgICAoeElkOiBudW1iZXIsIGJhdGNoU2l6ZTogbnVtYmVyLCBpbnB1dEhlaWdodDogbnVtYmVyLCBpbnB1dFdpZHRoOiBudW1iZXIsXG4gICAgIGZpbHRlcklkOiBudW1iZXIsIGZpbHRlckhlaWdodDogbnVtYmVyLCBmaWx0ZXJXaWR0aDogbnVtYmVyLFxuICAgICBiaWFzSWQ6IG51bWJlciwgcGFkVG9wOiBudW1iZXIsIHBhZFJpZ2h0OiBudW1iZXIsIHBhZEJvdHRvbTogbnVtYmVyLFxuICAgICBwYWRMZWZ0OiBudW1iZXIsIGlzU2FtZVBhZDogbnVtYmVyLCBkaWxhdGlvbkhlaWdodDogbnVtYmVyLFxuICAgICBkaWxhdGlvbldpZHRoOiBudW1iZXIsIHN0cmlkZUhlaWdodDogbnVtYmVyLCBzdHJpZGVXaWR0aDogbnVtYmVyLFxuICAgICBpbnB1dENoYW5uZWxzOiBudW1iZXIsIG91dHB1dENoYW5uZWxzOiBudW1iZXIsIGFjdGl2YXRpb246IG51bWJlcixcbiAgICAgcHJlbHVBY3RpdmF0aW9uV2VpZ2h0c0lkOiBudW1iZXIsIGxlYWt5cmVsdUFscGhhOiBudW1iZXIsIG91dElkOiBudW1iZXIpID0+XG4gICAgICAgIHZvaWQ7XG5cbmZ1bmN0aW9uIHNldHVwKGJhY2tlbmQ6IEJhY2tlbmRXYXNtKSB7XG4gIHdhc21GdXNlZERlcHRod2lzZUNvbnYyZCA9XG4gICAgICBiYWNrZW5kLndhc20uY3dyYXAoRnVzZWREZXB0aHdpc2VDb252MkQsIG51bGwgLyogdm9pZCAqLywgW1xuICAgICAgICAnbnVtYmVyJywgIC8vIHhJZFxuICAgICAgICAnbnVtYmVyJywgIC8vIGJhdGNoU2l6ZVxuICAgICAgICAnbnVtYmVyJywgIC8vIGlucHV0SGVpZ2h0XG4gICAgICAgICdudW1iZXInLCAgLy8gaW5wdXRXaWR0aFxuICAgICAgICAnbnVtYmVyJywgIC8vIGZpbHRlcklkXG4gICAgICAgICdudW1iZXInLCAgLy8gZmlsdGVySGVpZ2h0XG4gICAgICAgICdudW1iZXInLCAgLy8gZmlsdGVyV2lkdGhcbiAgICAgICAgJ251bWJlcicsICAvLyBiaWFzSWRcbiAgICAgICAgJ251bWJlcicsICAvLyBwYWRUb3BcbiAgICAgICAgJ251bWJlcicsICAvLyBwYWRSaWdodFxuICAgICAgICAnbnVtYmVyJywgIC8vIHBhZEJvdHRvbVxuICAgICAgICAnbnVtYmVyJywgIC8vIHBhZExlZnRcbiAgICAgICAgJ251bWJlcicsICAvLyBpc1NhbWVQYWRcbiAgICAgICAgJ251bWJlcicsICAvLyBkaWxhdGlvbkhlaWdodFxuICAgICAgICAnbnVtYmVyJywgIC8vIGRpbGF0aW9uV2lkdGhcbiAgICAgICAgJ251bWJlcicsICAvLyBzdHJpZGVIZWlnaHRcbiAgICAgICAgJ251bWJlcicsICAvLyBzdHJpZGVXaWR0aFxuICAgICAgICAnbnVtYmVyJywgIC8vIGlucHV0Q2hhbm5lbHNcbiAgICAgICAgJ251bWJlcicsICAvLyBvdXRwdXRDaGFubmVsc1xuICAgICAgICAnbnVtYmVyJywgIC8vIGFjdGl2YXRpb25cbiAgICAgICAgJ251bWJlcicsICAvLyBwcmVsdUFjdGl2YXRpb25XZWlnaHRzSWRcbiAgICAgICAgJ251bWJlcicsICAvLyBsZWFreXJlbHVBbHBoYVxuICAgICAgICAnbnVtYmVyJywgIC8vIG91dElkXG4gICAgICBdKTtcbn1cblxuZnVuY3Rpb24gZnVzZWREZXB0aHdpc2VDb252MmQoYXJnczoge1xuICBpbnB1dHM6IEZ1c2VkRGVwdGh3aXNlQ29udjJESW5wdXRzLFxuICBiYWNrZW5kOiBCYWNrZW5kV2FzbSxcbiAgYXR0cnM6IEZ1c2VkRGVwdGh3aXNlQ29udjJEQXR0cnNcbn0pIHtcbiAgY29uc3Qge2lucHV0cywgYXR0cnMsIGJhY2tlbmR9ID0gYXJncztcbiAgY29uc3Qge3gsIGZpbHRlciwgYmlhcywgcHJlbHVBY3RpdmF0aW9uV2VpZ2h0c30gPSBpbnB1dHM7XG4gIGNvbnN0IHtcbiAgICBzdHJpZGVzLFxuICAgIHBhZCxcbiAgICBkaWxhdGlvbnMsXG4gICAgZGF0YUZvcm1hdCxcbiAgICBkaW1Sb3VuZGluZ01vZGUsXG4gICAgYWN0aXZhdGlvbixcbiAgICBsZWFreXJlbHVBbHBoYVxuICB9ID0gYXR0cnM7XG5cbiAgY29uc3QgY29udkluZm8gPSBiYWNrZW5kX3V0aWwuY29tcHV0ZUNvbnYyREluZm8oXG4gICAgICAoeCBhcyBUZW5zb3I0RCkuc2hhcGUsIChmaWx0ZXIgYXMgVGVuc29yNEQpLnNoYXBlLCBzdHJpZGVzLCBkaWxhdGlvbnMsXG4gICAgICBwYWQsIGRpbVJvdW5kaW5nTW9kZSwgdHJ1ZSAvKiBkZXB0aHdpc2UgKi8pO1xuXG4gIGNvbnN0IGZ1c2VkQWN0aXZhdGlvbiA9XG4gICAgICBGdXNhYmxlQWN0aXZhdGlvblthY3RpdmF0aW9uIGFzIHVua25vd24gYXNcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleW9mIHR5cGVvZiBGdXNhYmxlQWN0aXZhdGlvbl07XG4gIGlmIChmdXNlZEFjdGl2YXRpb24gPT0gbnVsbCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYCR7YWN0aXZhdGlvbn0gYWN0aXZhdGlvbiBub3QgeWV0IHN1cHBvcnRlZCBmb3IgRnVzZWREZXB0aHdpc2VDb252MkQgYCArXG4gICAgICAgIGBpbiB0aGUgd2FzbSBiYWNrZW5kLmApO1xuICB9XG5cbiAgY29uc3QgeElkID0gYmFja2VuZC5kYXRhSWRNYXAuZ2V0KHguZGF0YUlkKS5pZDtcbiAgY29uc3QgZmlsdGVySWQgPSBiYWNrZW5kLmRhdGFJZE1hcC5nZXQoZmlsdGVyLmRhdGFJZCkuaWQ7XG5cbiAgY29uc3Qgb3V0cHV0Q2hhbm5lbHMgPSBjb252SW5mby5vdXRDaGFubmVscztcblxuICBsZXQgYmlhc0lkID0gMDtcbiAgaWYgKGJpYXMgIT0gbnVsbCkge1xuICAgIGNvbnN0IGJpYXNEYXRhID0gYmFja2VuZC5kYXRhSWRNYXAuZ2V0KGJpYXMuZGF0YUlkKTtcbiAgICBpZiAoYmlhc0RhdGEuc2hhcGUubGVuZ3RoICE9PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEZ1c2VkRGVwdGh3aXNlQ29udjJEIG9ubHkgc3VwcG9ydHMgcmFuay0xIGJpYXMgYnV0IGdvdCBgICtcbiAgICAgICAgICBgcmFuayAke2JpYXNEYXRhLnNoYXBlLmxlbmd0aH0uYCk7XG4gICAgfVxuICAgIGlmIChiaWFzRGF0YS5zaGFwZVswXSAhPT0gb3V0cHV0Q2hhbm5lbHMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgRnVzZWREZXB0aHdpc2VDb252MkQgYmlhcyBzaGFwZSAoJHtiaWFzRGF0YS5zaGFwZX0pIGRvZXMgbm90IGAgK1xuICAgICAgICAgIGBtYXRjaCB0aGUgbnVtYmVyIG9mIG91dHB1dCBjaGFubmVscyAoJHtvdXRwdXRDaGFubmVsc30pYCk7XG4gICAgfVxuICAgIGJpYXNJZCA9IGJpYXNEYXRhLmlkO1xuICB9XG5cbiAgY29uc3QgZmlsdGVySGVpZ2h0ID0gY29udkluZm8uZmlsdGVySGVpZ2h0O1xuICBjb25zdCBmaWx0ZXJXaWR0aCA9IGNvbnZJbmZvLmZpbHRlcldpZHRoO1xuICBjb25zdCBwYWRUb3AgPSBjb252SW5mby5wYWRJbmZvLnRvcDtcbiAgY29uc3QgcGFkUmlnaHQgPSBjb252SW5mby5wYWRJbmZvLnJpZ2h0O1xuICBjb25zdCBwYWRCb3R0b20gPSBjb252SW5mby5wYWRJbmZvLmJvdHRvbTtcbiAgY29uc3QgcGFkTGVmdCA9IGNvbnZJbmZvLnBhZEluZm8ubGVmdDtcbiAgY29uc3QgZGlsYXRpb25IZWlnaHQgPSBjb252SW5mby5kaWxhdGlvbkhlaWdodDtcbiAgY29uc3QgZGlsYXRpb25XaWR0aCA9IGNvbnZJbmZvLmRpbGF0aW9uV2lkdGg7XG4gIGNvbnN0IHN0cmlkZUhlaWdodCA9IGNvbnZJbmZvLnN0cmlkZUhlaWdodDtcbiAgY29uc3Qgc3RyaWRlV2lkdGggPSBjb252SW5mby5zdHJpZGVXaWR0aDtcbiAgY29uc3QgaW5wdXRDaGFubmVscyA9IGNvbnZJbmZvLmluQ2hhbm5lbHM7XG4gIGNvbnN0IGlzU2FtZVBhZCA9IGNvbnZJbmZvLnBhZEluZm8udHlwZSA9PT0gJ1NBTUUnID8gMSA6IDA7XG4gIGNvbnN0IGJhdGNoU2l6ZSA9IGNvbnZJbmZvLmJhdGNoU2l6ZTtcbiAgY29uc3QgaW5IZWlnaHQgPSBjb252SW5mby5pbkhlaWdodDtcbiAgY29uc3QgaW5XaWR0aCA9IGNvbnZJbmZvLmluV2lkdGg7XG5cbiAgaWYgKGRhdGFGb3JtYXQgIT09ICdOSFdDJykge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYHdhc20gYmFja2VuZCBGdXNlZERlcHRod2lzZUNvbnYyRCBkb2VzIG5vdCBzdXBwb3J0IGRhdGFGb3JtYXQ6J2AgK1xuICAgICAgICBgJHtkYXRhRm9ybWF0fScuIFBsZWFzZSB1c2UgJ05IV0MnLmApO1xuICB9XG5cbiAgY29uc3Qgb3V0ID0gYmFja2VuZC5tYWtlT3V0cHV0KGNvbnZJbmZvLm91dFNoYXBlLCAnZmxvYXQzMicpO1xuICBjb25zdCBvdXRJZCA9IGJhY2tlbmQuZGF0YUlkTWFwLmdldChvdXQuZGF0YUlkKS5pZDtcbiAgY29uc3QgcHJlbHVBY3RpdmF0aW9uV2VpZ2h0c0lkID0gcHJlbHVBY3RpdmF0aW9uV2VpZ2h0cyA9PSBudWxsID9cbiAgICAgIDAgOlxuICAgICAgYmFja2VuZC5kYXRhSWRNYXAuZ2V0KHByZWx1QWN0aXZhdGlvbldlaWdodHMuZGF0YUlkKS5pZDtcblxuICB3YXNtRnVzZWREZXB0aHdpc2VDb252MmQoXG4gICAgICB4SWQsIGJhdGNoU2l6ZSwgaW5IZWlnaHQsIGluV2lkdGgsIGZpbHRlcklkLCBmaWx0ZXJIZWlnaHQsIGZpbHRlcldpZHRoLFxuICAgICAgYmlhc0lkLCBwYWRUb3AsIHBhZFJpZ2h0LCBwYWRCb3R0b20sIHBhZExlZnQsIGlzU2FtZVBhZCwgZGlsYXRpb25IZWlnaHQsXG4gICAgICBkaWxhdGlvbldpZHRoLCBzdHJpZGVIZWlnaHQsIHN0cmlkZVdpZHRoLCBpbnB1dENoYW5uZWxzLCBvdXRwdXRDaGFubmVscyxcbiAgICAgIGZ1c2VkQWN0aXZhdGlvbiwgcHJlbHVBY3RpdmF0aW9uV2VpZ2h0c0lkLCBsZWFreXJlbHVBbHBoYSB8fCAwLCBvdXRJZCk7XG5cbiAgcmV0dXJuIG91dDtcbn1cblxuZXhwb3J0IGNvbnN0IGZ1c2VkRGVwdGh3aXNlQ29udjJEQ29uZmlnOiBLZXJuZWxDb25maWcgPSB7XG4gIGtlcm5lbE5hbWU6IEZ1c2VkRGVwdGh3aXNlQ29udjJELFxuICBiYWNrZW5kTmFtZTogJ3dhc20nLFxuICBzZXR1cEZ1bmM6IHNldHVwLFxuICBrZXJuZWxGdW5jOiBmdXNlZERlcHRod2lzZUNvbnYyZCBhcyB1bmtub3duIGFzIEtlcm5lbEZ1bmNcbn07XG4iXX0=