UNPKG

@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

106 lines 16.3 kB
/** * @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, FusedConv2D } from '@tensorflow/tfjs-core'; import { FusableActivation } from './types'; let wasmFusedConv2d; function setup(backend) { wasmFusedConv2d = backend.wasm.cwrap(FusedConv2D, 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 fusedConv2d(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); const fusedActivation = FusableActivation[activation]; if (fusedActivation == null) { throw new Error(`${activation} activation not yet supported for FusedConv2D ` + `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(`FusedConv2D only supports rank-1 bias but got ` + `rank ${biasData.shape.length}.`); } if (biasData.shape[0] !== outputChannels) { throw new Error(`FusedConv2D 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 FusedConv2D 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; wasmFusedConv2d(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 fusedConv2DConfig = { kernelName: FusedConv2D, backendName: 'wasm', setupFunc: setup, kernelFunc: fusedConv2d }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRnVzZWRDb252MkQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi90ZmpzLWJhY2tlbmQtd2FzbS9zcmMva2VybmVscy9GdXNlZENvbnYyRC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFFSCxPQUFPLEVBQUMsWUFBWSxFQUFFLFdBQVcsRUFBMEUsTUFBTSx1QkFBdUIsQ0FBQztBQUl6SSxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxTQUFTLENBQUM7QUFFMUMsSUFBSSxlQVFRLENBQUM7QUFFYixTQUFTLEtBQUssQ0FBQyxPQUFvQjtJQUNqQyxlQUFlLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUU7UUFDakUsUUFBUTtRQUNSLFFBQVE7UUFDUixRQUFRO1FBQ1IsUUFBUTtRQUNSLFFBQVE7UUFDUixRQUFRO1FBQ1IsUUFBUTtRQUNSLFFBQVE7UUFDUixRQUFRO1FBQ1IsUUFBUTtRQUNSLFFBQVE7UUFDUixRQUFRO1FBQ1IsUUFBUTtRQUNSLFFBQVE7UUFDUixRQUFRO1FBQ1IsUUFBUTtRQUNSLFFBQVE7UUFDUixRQUFRO1FBQ1IsUUFBUTtRQUNSLFFBQVE7UUFDUixRQUFRO1FBQ1IsUUFBUTtRQUNSLFFBQVEsRUFBRyxRQUFRO0tBQ3BCLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxTQUFTLFdBQVcsQ0FBQyxJQUlwQjtJQUNDLE1BQU0sRUFBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBQyxHQUFHLElBQUksQ0FBQztJQUN0QyxNQUFNLEVBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsc0JBQXNCLEVBQUMsR0FBRyxNQUFNLENBQUM7SUFDekQsTUFBTSxFQUNKLE9BQU8sRUFDUCxHQUFHLEVBQ0gsU0FBUyxFQUNULFVBQVUsRUFDVixlQUFlLEVBQ2YsVUFBVSxFQUNWLGNB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M0M7SUFFRCxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDN0QsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNuRCxNQUFNLHdCQUF3QixHQUFHLHNCQUFzQixJQUFJLElBQUksQ0FBQyxDQUFDO1FBQzdELENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsc0JBQXNCLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDO0lBRTVELGVBQWUsQ0FDWCxHQUFHLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQ3RFLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLGNBQWMsRUFDdkUsYUFBYSxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLGNBQWMsRUFDdkUsZUFBZSxFQUFFLHdCQUF3QixFQUFFLGNBQWMsSUFBSSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFFM0UsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBRUQsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQWlCO0lBQzdDLFVBQVUsRUFBRSxXQUFXO0lBQ3ZCLFdBQVcsRUFBRSxNQUFNO0lBQ25CLFNBQVMsRUFBRSxLQUFLO0lBQ2hCLFVBQVUsRUFBRSxXQUFvQztDQUNqRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG5pbXBvcnQge2JhY2tlbmRfdXRpbCwgRnVzZWRDb252MkQsIEZ1c2VkQ29udjJEQXR0cnMsIEZ1c2VkQ29udjJESW5wdXRzLCBLZXJuZWxDb25maWcsIEtlcm5lbEZ1bmMsIFRlbnNvcjREfSBmcm9tICdAdGVuc29yZmxvdy90ZmpzLWNvcmUnO1xuXG5pbXBvcnQge0JhY2tlbmRXYXNtfSBmcm9tICcuLi9iYWNrZW5kX3dhc20nO1xuXG5pbXBvcnQge0Z1c2FibGVBY3RpdmF0aW9ufSBmcm9tICcuL3R5cGVzJztcblxubGV0IHdhc21GdXNlZENvbnYyZDpcbiAgICAoeElkOiBudW1iZXIsIGJhdGNoU2l6ZTogbnVtYmVyLCBpbnB1dEhlaWdodDogbnVtYmVyLCBpbnB1dFdpZHRoOiBudW1iZXIsXG4gICAgIGZpbHRlcklkOiBudW1iZXIsIGZpbHRlckhlaWdodDogbnVtYmVyLCBmaWx0ZXJXaWR0aDogbnVtYmVyLFxuICAgICBiaWFzSWQ6IG51bWJlciwgcGFkVG9wOiBudW1iZXIsIHBhZFJpZ2h0OiBudW1iZXIsIHBhZEJvdHRvbTogbnVtYmVyLFxuICAgICBwYWRMZWZ0OiBudW1iZXIsIGlzU2FtZVBhZDogbnVtYmVyLCBkaWxhdGlvbkhlaWdodDogbnVtYmVyLFxuICAgICBkaWxhdGlvbldpZHRoOiBudW1iZXIsIHN0cmlkZUhlaWdodDogbnVtYmVyLCBzdHJpZGVXaWR0aDogbnVtYmVyLFxuICAgICBpbnB1dENoYW5uZWxzOiBudW1iZXIsIG91dHB1dENoYW5uZWxzOiBudW1iZXIsIGFjdGl2YXRpb246IG51bWJlcixcbiAgICAgcHJlbHVBY3RpdmF0aW9uV2VpZ2h0c0lkOiBudW1iZXIsIGxlYWt5cmVsdUFscGhhOiBudW1iZXIsIG91dElkOiBudW1iZXIpID0+XG4gICAgICAgIHZvaWQ7XG5cbmZ1bmN0aW9uIHNldHVwKGJhY2tlbmQ6IEJhY2tlbmRXYXNtKSB7XG4gIHdhc21GdXNlZENvbnYyZCA9IGJhY2tlbmQud2FzbS5jd3JhcChGdXNlZENvbnYyRCwgbnVsbCAvKiB2b2lkICovLCBbXG4gICAgJ251bWJlcicsICAvLyB4SWRcbiAgICAnbnVtYmVyJywgIC8vIGJhdGNoU2l6ZVxuICAgICdudW1iZXInLCAgLy8gaW5wdXRIZWlnaHRcbiAgICAnbnVtYmVyJywgIC8vIGlucHV0V2lkdGhcbiAgICAnbnVtYmVyJywgIC8vIGZpbHRlcklkXG4gICAgJ251bWJlcicsICAvLyBmaWx0ZXJIZWlnaHRcbiAgICAnbnVtYmVyJywgIC8vIGZpbHRlcldpZHRoXG4gICAgJ251bWJlcicsICAvLyBiaWFzSWRcbiAgICAnbnVtYmVyJywgIC8vIHBhZFRvcFxuICAgICdudW1iZXInLCAgLy8gcGFkUmlnaHRcbiAgICAnbnVtYmVyJywgIC8vIHBhZEJvdHRvbVxuICAgICdudW1iZXInLCAgLy8gcGFkTGVmdFxuICAgICdudW1iZXInLCAgLy8gaXNTYW1lUGFkXG4gICAgJ251bWJlcicsICAvLyBkaWxhdGlvbkhlaWdodFxuICAgICdudW1iZXInLCAgLy8gZGlsYXRpb25XaWR0aFxuICAgICdudW1iZXInLCAgLy8gc3RyaWRlSGVpZ2h0XG4gICAgJ251bWJlcicsICAvLyBzdHJpZGVXaWR0aFxuICAgICdudW1iZXInLCAgLy8gaW5wdXRDaGFubmVsc1xuICAgICdudW1iZXInLCAgLy8gb3V0cHV0Q2hhbm5lbHNcbiAgICAnbnVtYmVyJywgIC8vIGFjdGl2YXRpb25cbiAgICAnbnVtYmVyJywgIC8vIHByZWx1QWN0aXZhdGlvbldlaWdodHNJZFxuICAgICdudW1iZXInLCAgLy8gbGVha3lyZWx1QWxwaGFcbiAgICAnbnVtYmVyJywgIC8vIG91dElkXG4gIF0pO1xufVxuXG5mdW5jdGlvbiBmdXNlZENvbnYyZChhcmdzOiB7XG4gIGlucHV0czogRnVzZWRDb252MkRJbnB1dHMsXG4gIGJhY2tlbmQ6IEJhY2tlbmRXYXNtLFxuICBhdHRyczogRnVzZWRDb252MkRBdHRyc1xufSkge1xuICBjb25zdCB7aW5wdXRzLCBhdHRycywgYmFja2VuZH0gPSBhcmdzO1xuICBjb25zdCB7eCwgZmlsdGVyLCBiaWFzLCBwcmVsdUFjdGl2YXRpb25XZWlnaHRzfSA9IGlucHV0cztcbiAgY29uc3Qge1xuICAgIHN0cmlkZXMsXG4gICAgcGFkLFxuICAgIGRpbGF0aW9ucyxcbiAgICBkYXRhRm9ybWF0LFxuICAgIGRpbVJvdW5kaW5nTW9kZSxcbiAgICBhY3RpdmF0aW9uLFxuICAgIGxlYWt5cmVsdUFscGhhXG4gIH0gPSBhdHRycztcblxuICBjb25zdCBjb252SW5mbyA9IGJhY2tlbmRfdXRpbC5jb21wdXRlQ29udjJESW5mbyhcbiAgICAgICh4IGFzIFRlbnNvcjREKS5zaGFwZSwgKGZpbHRlciBhcyBUZW5zb3I0RCkuc2hhcGUsIHN0cmlkZXMsIGRpbGF0aW9ucyxcbiAgICAgIHBhZCwgZGltUm91bmRpbmdNb2RlKTtcblxuICBjb25zdCBmdXNlZEFjdGl2YXRpb24gPVxuICAgICAgRnVzYWJsZUFjdGl2YXRpb25bYWN0aXZhdGlvbiBhcyB1bmtub3duIGFzXG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlvZiB0eXBlb2YgRnVzYWJsZUFjdGl2YXRpb25dO1xuICBpZiAoZnVzZWRBY3RpdmF0aW9uID09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGAke2FjdGl2YXRpb259IGFjdGl2YXRpb24gbm90IHlldCBzdXBwb3J0ZWQgZm9yIEZ1c2VkQ29udjJEIGAgK1xuICAgICAgICBgaW4gdGhlIHdhc20gYmFja2VuZC5gKTtcbiAgfVxuXG4gIGNvbnN0IHhJZCA9IGJhY2tlbmQuZGF0YUlkTWFwLmdldCh4LmRhdGFJZCkuaWQ7XG4gIGNvbnN0IGZpbHRlcklkID0gYmFja2VuZC5kYXRhSWRNYXAuZ2V0KGZpbHRlci5kYXRhSWQpLmlkO1xuXG4gIGNvbnN0IG91dHB1dENoYW5uZWxzID0gY29udkluZm8ub3V0Q2hhbm5lbHM7XG5cbiAgbGV0IGJpYXNJZCA9IDA7XG4gIGlmIChiaWFzICE9IG51bGwpIHtcbiAgICBjb25zdCBiaWFzRGF0YSA9IGJhY2tlbmQuZGF0YUlkTWFwLmdldChiaWFzLmRhdGFJZCk7XG4gICAgaWYgKGJpYXNEYXRhLnNoYXBlLmxlbmd0aCAhPT0gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBGdXNlZENvbnYyRCBvbmx5IHN1cHBvcnRzIHJhbmstMSBiaWFzIGJ1dCBnb3QgYCArXG4gICAgICAgICAgYHJhbmsgJHtiaWFzRGF0YS5zaGFwZS5sZW5ndGh9LmApO1xuICAgIH1cbiAgICBpZiAoYmlhc0RhdGEuc2hhcGVbMF0gIT09IG91dHB1dENoYW5uZWxzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEZ1c2VkQ29udjJEIGJpYXMgc2hhcGUgKCR7Ymlhc0RhdGEuc2hhcGV9KSBkb2VzIG5vdCBgICtcbiAgICAgICAgICBgbWF0Y2ggdGhlIG51bWJlciBvZiBvdXRwdXQgY2hhbm5lbHMgKCR7b3V0cHV0Q2hhbm5lbHN9KWApO1xuICAgIH1cbiAgICBiaWFzSWQgPSBiaWFzRGF0YS5pZDtcbiAgfVxuXG4gIGNvbnN0IGZpbHRlckhlaWdodCA9IGNvbnZJbmZvLmZpbHRlckhlaWdodDtcbiAgY29uc3QgZmlsdGVyV2lkdGggPSBjb252SW5mby5maWx0ZXJXaWR0aDtcbiAgY29uc3QgcGFkVG9wID0gY29udkluZm8ucGFkSW5mby50b3A7XG4gIGNvbnN0IHBhZFJpZ2h0ID0gY29udkluZm8ucGFkSW5mby5yaWdodDtcbiAgY29uc3QgcGFkQm90dG9tID0gY29udkluZm8ucGFkSW5mby5ib3R0b207XG4gIGNvbnN0IHBhZExlZnQgPSBjb252SW5mby5wYWRJbmZvLmxlZnQ7XG4gIGNvbnN0IGRpbGF0aW9uSGVpZ2h0ID0gY29udkluZm8uZGlsYXRpb25IZWlnaHQ7XG4gIGNvbnN0IGRpbGF0aW9uV2lkdGggPSBjb252SW5mby5kaWxhdGlvbldpZHRoO1xuICBjb25zdCBzdHJpZGVIZWlnaHQgPSBjb252SW5mby5zdHJpZGVIZWlnaHQ7XG4gIGNvbnN0IHN0cmlkZVdpZHRoID0gY29udkluZm8uc3RyaWRlV2lkdGg7XG4gIGNvbnN0IGlucHV0Q2hhbm5lbHMgPSBjb252SW5mby5pbkNoYW5uZWxzO1xuICBjb25zdCBpc1NhbWVQYWQgPSBjb252SW5mby5wYWRJbmZvLnR5cGUgPT09ICdTQU1FJyA/IDEgOiAwO1xuICBjb25zdCBiYXRjaFNpemUgPSBjb252SW5mby5iYXRjaFNpemU7XG4gIGNvbnN0IGluSGVpZ2h0ID0gY29udkluZm8uaW5IZWlnaHQ7XG4gIGNvbnN0IGluV2lkdGggPSBjb252SW5mby5pbldpZHRoO1xuXG4gIGlmIChkYXRhRm9ybWF0ICE9PSAnTkhXQycpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGB3YXNtIGJhY2tlbmQgRnVzZWRDb252MkQgZG9lcyBub3Qgc3VwcG9ydCBkYXRhRm9ybWF0OidgICtcbiAgICAgICAgYCR7ZGF0YUZvcm1hdH0nLiBQbGVhc2UgdXNlICdOSFdDJy5gKTtcbiAgfVxuXG4gIGNvbnN0IG91dCA9IGJhY2tlbmQubWFrZU91dHB1dChjb252SW5mby5vdXRTaGFwZSwgJ2Zsb2F0MzInKTtcbiAgY29uc3Qgb3V0SWQgPSBiYWNrZW5kLmRhdGFJZE1hcC5nZXQob3V0LmRhdGFJZCkuaWQ7XG4gIGNvbnN0IHByZWx1QWN0aXZhdGlvbldlaWdodHNJZCA9IHByZWx1QWN0aXZhdGlvbldlaWdodHMgPT0gbnVsbCA/XG4gICAgICAwIDpcbiAgICAgIGJhY2tlbmQuZGF0YUlkTWFwLmdldChwcmVsdUFjdGl2YXRpb25XZWlnaHRzLmRhdGFJZCkuaWQ7XG5cbiAgd2FzbUZ1c2VkQ29udjJkKFxuICAgICAgeElkLCBiYXRjaFNpemUsIGluSGVpZ2h0LCBpbldpZHRoLCBmaWx0ZXJJZCwgZmlsdGVySGVpZ2h0LCBmaWx0ZXJXaWR0aCxcbiAgICAgIGJpYXNJZCwgcGFkVG9wLCBwYWRSaWdodCwgcGFkQm90dG9tLCBwYWRMZWZ0LCBpc1NhbWVQYWQsIGRpbGF0aW9uSGVpZ2h0LFxuICAgICAgZGlsYXRpb25XaWR0aCwgc3RyaWRlSGVpZ2h0LCBzdHJpZGVXaWR0aCwgaW5wdXRDaGFubmVscywgb3V0cHV0Q2hhbm5lbHMsXG4gICAgICBmdXNlZEFjdGl2YXRpb24sIHByZWx1QWN0aXZhdGlvbldlaWdodHNJZCwgbGVha3lyZWx1QWxwaGEgfHwgMCwgb3V0SWQpO1xuXG4gIHJldHVybiBvdXQ7XG59XG5cbmV4cG9ydCBjb25zdCBmdXNlZENvbnYyRENvbmZpZzogS2VybmVsQ29uZmlnID0ge1xuICBrZXJuZWxOYW1lOiBGdXNlZENvbnYyRCxcbiAgYmFja2VuZE5hbWU6ICd3YXNtJyxcbiAgc2V0dXBGdW5jOiBzZXR1cCxcbiAga2VybmVsRnVuYzogZnVzZWRDb252MmQgYXMgdW5rbm93biBhcyBLZXJuZWxGdW5jXG59O1xuIl19