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

98 lines 12.7 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 { Transpose } from '@tensorflow/tfjs-core'; import { identity } from './Identity'; import { CppDType } from './types'; let wasmTranspose; function setup(backend) { wasmTranspose = backend.wasm.cwrap(Transpose, null /* void */, [ 'number', 'array', 'number', 'number', 'number', 'array', 'number', // perm.length ]); } export function transpose(args) { const { inputs, backend, attrs } = args; // Reduce any dimensions with size one. Lower-rank transpose kernel performs // better due to simpler memory access pattern. const [reducedShape, perm] = removeOneSizeDims(inputs.x.shape, attrs.perm); let permIsNoOp = true; for (let i = 0; i < perm.length; i++) { if (perm[i] !== i) { permIsNoOp = false; } } const outShape = computeOutShape(inputs.x.shape, attrs.perm); const x = { dataId: inputs.x.dataId, shape: reducedShape, dtype: inputs.x.dtype }; if (permIsNoOp) { const cloned = identity({ inputs, backend }); cloned.shape = outShape; return cloned; } const out = backend.makeOutput(outShape, x.dtype); const xId = backend.dataIdMap.get(x.dataId).id; const outId = backend.dataIdMap.get(out.dataId).id; const permBytes = new Uint8Array(new Int32Array(perm).buffer); const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); wasmTranspose(xId, xShapeBytes, x.shape.length, CppDType[x.dtype], outId, permBytes, perm.length); return out; } function computeOutShape(inShape, perm) { const outShape = new Array(inShape.length); for (let i = 0; i < outShape.length; i++) { outShape[i] = inShape[perm[i]]; } return outShape; } function removeOneSizeDims(shape, perm) { const newShape = []; const newPerm = []; for (let i = 0; i < shape.length; ++i) { if (shape[i] !== 1) { newShape.push(shape[i]); } if (shape[perm[i]] !== 1) { newPerm.push(perm[i]); } } for (let i = 0; i < newPerm.length; ++i) { let minValIdx = -1; for (let j = 0; j < newPerm.length; ++j) { if (newPerm[j] >= i && (minValIdx === -1 || newPerm[minValIdx] > newPerm[j])) { minValIdx = j; } } newPerm[minValIdx] = i; } return [newShape, newPerm]; } export const transposeConfig = { kernelName: Transpose, backendName: 'wasm', kernelFunc: transpose, setupFunc: setup, }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHJhbnNwb3NlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGZqcy1iYWNrZW5kLXdhc20vc3JjL2tlcm5lbHMvVHJhbnNwb3NlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sRUFBdUMsU0FBUyxFQUFrQyxNQUFNLHVCQUF1QixDQUFDO0FBSXZILE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxZQUFZLENBQUM7QUFDcEMsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUVqQyxJQUFJLGFBRTRELENBQUM7QUFFakUsU0FBUyxLQUFLLENBQUMsT0FBb0I7SUFDakMsYUFBYSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFO1FBQzdELFFBQVE7UUFDUixPQUFPO1FBQ1AsUUFBUTtRQUNSLFFBQVE7UUFDUixRQUFRO1FBQ1IsT0FBTztRQUNQLFFBQVEsRUFBRyxjQUFjO0tBQzFCLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxNQUFNLFVBQVUsU0FBUyxDQUNyQixJQUMwRTtJQUU1RSxNQUFNLEVBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUMsR0FBRyxJQUFJLENBQUM7SUFDdEMsNEVBQTRFO0lBQzVFLCtDQUErQztJQUMvQyxNQUFNLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxHQUFHLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUUzRSxJQUFJLFVBQVUsR0FBRyxJQUFJLENBQUM7SUFDdEIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDcEMsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQ2pCLFVBQVUsR0FBRyxLQUFLLENBQUM7U0FDcEI7S0FDRjtJQUNELE1BQU0sUUFBUSxHQUFHLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDN0QsTUFBTSxDQUFDLEdBQUc7UUFDUixNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNO1FBQ3ZCLEtBQUssRUFBRSxZQUFZO1FBQ25CLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUs7S0FDdEIsQ0FBQztJQUVGLElBQUksVUFBVSxFQUFFO1FBQ2QsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLEVBQUMsTUFBTSxFQUFFLE9BQU8sRUFBQyxDQUFDLENBQUM7UUFDM0MsTUFBTSxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUM7UUFDeEIsT0FBTyxNQUFNLENBQUM7S0FDZjtJQUVELE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNsRCxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQy9DLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDbkQsTUFBTSxTQUFTLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDOUQsTUFBTSxXQUFXLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRW5FLGFBQWEsQ0FDVCxHQUFHLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFDckUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2pCLE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQUVELFNBQVMsZUFBZSxDQUFDLE9BQWlCLEVBQUUsSUFBYztJQUN4RCxNQUFNLFFBQVEsR0FBRyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDM0MsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDeEMsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUNoQztJQUNELE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUM7QUFFRCxTQUFTLGlCQUFpQixDQUN0QixLQUFlLEVBQUUsSUFBYztJQUNqQyxNQUFNLFFBQVEsR0FBYSxFQUFFLENBQUM7SUFDOUIsTUFBTSxPQUFPLEdBQWEsRUFBRSxDQUFDO0lBQzdCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxFQUFFO1FBQ3JDLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUNsQixRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ3pCO1FBQ0QsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQ3hCLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDdkI7S0FDRjtJQUNELEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxFQUFFO1FBQ3ZDLElBQUksU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ25CLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxFQUFFO1lBQ3ZDLElBQUksT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQ2YsQ0FBQyxTQUFTLEtBQUssQ0FBQyxDQUFDLElBQUksT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO2dCQUN6RCxTQUFTLEdBQUcsQ0FBQyxDQUFDO2FBQ2Y7U0FDRjtRQUNELE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDeEI7SUFDRCxPQUFPLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQzdCLENBQUM7QUFFRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQWlCO0lBQzNDLFVBQVUsRUFBRSxTQUFTO0lBQ3JCLFdBQVcsRUFBRSxNQUFNO0lBQ25CLFVBQVUsRUFBRSxTQUFrQztJQUM5QyxTQUFTLEVBQUUsS0FBSztDQUNqQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG5pbXBvcnQge0tlcm5lbENvbmZpZywgS2VybmVsRnVuYywgVGVuc29ySW5mbywgVHJhbnNwb3NlLCBUcmFuc3Bvc2VBdHRycywgVHJhbnNwb3NlSW5wdXRzfSBmcm9tICdAdGVuc29yZmxvdy90ZmpzLWNvcmUnO1xuXG5pbXBvcnQge0JhY2tlbmRXYXNtfSBmcm9tICcuLi9iYWNrZW5kX3dhc20nO1xuXG5pbXBvcnQge2lkZW50aXR5fSBmcm9tICcuL0lkZW50aXR5JztcbmltcG9ydCB7Q3BwRFR5cGV9IGZyb20gJy4vdHlwZXMnO1xuXG5sZXQgd2FzbVRyYW5zcG9zZTogKFxuICAgIHhJZDogbnVtYmVyLCB4U2hhcGU6IFVpbnQ4QXJyYXksIHhTaGFwZUxlbmd0aDogbnVtYmVyLCBkdHlwZTogQ3BwRFR5cGUsXG4gICAgb3V0SWQ6IG51bWJlciwgcGVybTogVWludDhBcnJheSwgcGVybUxlbmd0aDogbnVtYmVyKSA9PiB2b2lkO1xuXG5mdW5jdGlvbiBzZXR1cChiYWNrZW5kOiBCYWNrZW5kV2FzbSkge1xuICB3YXNtVHJhbnNwb3NlID0gYmFja2VuZC53YXNtLmN3cmFwKFRyYW5zcG9zZSwgbnVsbCAvKiB2b2lkICovLCBbXG4gICAgJ251bWJlcicsICAvLyB4SWRcbiAgICAnYXJyYXknLCAgIC8vIHguc2hhcGVcbiAgICAnbnVtYmVyJywgIC8vIHguc2hhcGUubGVuZ3RoXG4gICAgJ251bWJlcicsICAvLyBkdHlwZVxuICAgICdudW1iZXInLCAgLy8gb3V0SWRcbiAgICAnYXJyYXknLCAgIC8vIHBlcm1cbiAgICAnbnVtYmVyJywgIC8vIHBlcm0ubGVuZ3RoXG4gIF0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNwb3NlKFxuICAgIGFyZ3M6XG4gICAgICAgIHtpbnB1dHM6IFRyYW5zcG9zZUlucHV0cywgYmFja2VuZDogQmFja2VuZFdhc20sIGF0dHJzOiBUcmFuc3Bvc2VBdHRyc30pOlxuICAgIFRlbnNvckluZm8ge1xuICBjb25zdCB7aW5wdXRzLCBiYWNrZW5kLCBhdHRyc30gPSBhcmdzO1xuICAvLyBSZWR1Y2UgYW55IGRpbWVuc2lvbnMgd2l0aCBzaXplIG9uZS4gTG93ZXItcmFuayB0cmFuc3Bvc2Uga2VybmVsIHBlcmZvcm1zXG4gIC8vIGJldHRlciBkdWUgdG8gc2ltcGxlciBtZW1vcnkgYWNjZXNzIHBhdHRlcm4uXG4gIGNvbnN0IFtyZWR1Y2VkU2hhcGUsIHBlcm1dID0gcmVtb3ZlT25lU2l6ZURpbXMoaW5wdXRzLnguc2hhcGUsIGF0dHJzLnBlcm0pO1xuXG4gIGxldCBwZXJtSXNOb09wID0gdHJ1ZTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBwZXJtLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKHBlcm1baV0gIT09IGkpIHtcbiAgICAgIHBlcm1Jc05vT3AgPSBmYWxzZTtcbiAgICB9XG4gIH1cbiAgY29uc3Qgb3V0U2hhcGUgPSBjb21wdXRlT3V0U2hhcGUoaW5wdXRzLnguc2hhcGUsIGF0dHJzLnBlcm0pO1xuICBjb25zdCB4ID0ge1xuICAgIGRhdGFJZDogaW5wdXRzLnguZGF0YUlkLFxuICAgIHNoYXBlOiByZWR1Y2VkU2hhcGUsXG4gICAgZHR5cGU6IGlucHV0cy54LmR0eXBlXG4gIH07XG5cbiAgaWYgKHBlcm1Jc05vT3ApIHtcbiAgICBjb25zdCBjbG9uZWQgPSBpZGVudGl0eSh7aW5wdXRzLCBiYWNrZW5kfSk7XG4gICAgY2xvbmVkLnNoYXBlID0gb3V0U2hhcGU7XG4gICAgcmV0dXJuIGNsb25lZDtcbiAgfVxuXG4gIGNvbnN0IG91dCA9IGJhY2tlbmQubWFrZU91dHB1dChvdXRTaGFwZSwgeC5kdHlwZSk7XG4gIGNvbnN0IHhJZCA9IGJhY2tlbmQuZGF0YUlkTWFwLmdldCh4LmRhdGFJZCkuaWQ7XG4gIGNvbnN0IG91dElkID0gYmFja2VuZC5kYXRhSWRNYXAuZ2V0KG91dC5kYXRhSWQpLmlkO1xuICBjb25zdCBwZXJtQnl0ZXMgPSBuZXcgVWludDhBcnJheShuZXcgSW50MzJBcnJheShwZXJtKS5idWZmZXIpO1xuICBjb25zdCB4U2hhcGVCeXRlcyA9IG5ldyBVaW50OEFycmF5KG5ldyBJbnQzMkFycmF5KHguc2hhcGUpLmJ1ZmZlcik7XG5cbiAgd2FzbVRyYW5zcG9zZShcbiAgICAgIHhJZCwgeFNoYXBlQnl0ZXMsIHguc2hhcGUubGVuZ3RoLCBDcHBEVHlwZVt4LmR0eXBlXSwgb3V0SWQsIHBlcm1CeXRlcyxcbiAgICAgIHBlcm0ubGVuZ3RoKTtcbiAgcmV0dXJuIG91dDtcbn1cblxuZnVuY3Rpb24gY29tcHV0ZU91dFNoYXBlKGluU2hhcGU6IG51bWJlcltdLCBwZXJtOiBudW1iZXJbXSk6IG51bWJlcltdIHtcbiAgY29uc3Qgb3V0U2hhcGUgPSBuZXcgQXJyYXkoaW5TaGFwZS5sZW5ndGgpO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG91dFNoYXBlLmxlbmd0aDsgaSsrKSB7XG4gICAgb3V0U2hhcGVbaV0gPSBpblNoYXBlW3Blcm1baV1dO1xuICB9XG4gIHJldHVybiBvdXRTaGFwZTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlT25lU2l6ZURpbXMoXG4gICAgc2hhcGU6IG51bWJlcltdLCBwZXJtOiBudW1iZXJbXSk6IFtudW1iZXJbXSwgbnVtYmVyW11dIHtcbiAgY29uc3QgbmV3U2hhcGU6IG51bWJlcltdID0gW107XG4gIGNvbnN0IG5ld1Blcm06IG51bWJlcltdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc2hhcGUubGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoc2hhcGVbaV0gIT09IDEpIHtcbiAgICAgIG5ld1NoYXBlLnB1c2goc2hhcGVbaV0pO1xuICAgIH1cbiAgICBpZiAoc2hhcGVbcGVybVtpXV0gIT09IDEpIHtcbiAgICAgIG5ld1Blcm0ucHVzaChwZXJtW2ldKTtcbiAgICB9XG4gIH1cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZXdQZXJtLmxlbmd0aDsgKytpKSB7XG4gICAgbGV0IG1pblZhbElkeCA9IC0xO1xuICAgIGZvciAobGV0IGogPSAwOyBqIDwgbmV3UGVybS5sZW5ndGg7ICsraikge1xuICAgICAgaWYgKG5ld1Blcm1bal0gPj0gaSAmJlxuICAgICAgICAgIChtaW5WYWxJZHggPT09IC0xIHx8IG5ld1Blcm1bbWluVmFsSWR4XSA+IG5ld1Blcm1bal0pKSB7XG4gICAgICAgIG1pblZhbElkeCA9IGo7XG4gICAgICB9XG4gICAgfVxuICAgIG5ld1Blcm1bbWluVmFsSWR4XSA9IGk7XG4gIH1cbiAgcmV0dXJuIFtuZXdTaGFwZSwgbmV3UGVybV07XG59XG5cbmV4cG9ydCBjb25zdCB0cmFuc3Bvc2VDb25maWc6IEtlcm5lbENvbmZpZyA9IHtcbiAga2VybmVsTmFtZTogVHJhbnNwb3NlLFxuICBiYWNrZW5kTmFtZTogJ3dhc20nLFxuICBrZXJuZWxGdW5jOiB0cmFuc3Bvc2UgYXMgdW5rbm93biBhcyBLZXJuZWxGdW5jLFxuICBzZXR1cEZ1bmM6IHNldHVwLFxufTtcbiJdfQ==