@browserstack/testcafe
Version:
Automated browser testing for the modern web development stack.
164 lines • 24.5 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const net_1 = require("net");
const promisify_event_1 = __importDefault(require("promisify-event"));
const events_1 = __importDefault(require("events"));
const delay_1 = __importDefault(require("../../../../../../utils/delay"));
const client_functions_1 = require("../../../../utils/client-functions");
const commands_1 = __importDefault(require("./commands"));
const CONNECTION_TIMEOUT = 30000;
const CONNECTION_RETRY_DELAY = 300;
const MAX_RESIZE_RETRY_COUNT = 2;
const HEADER_SEPARATOR = ':';
module.exports = class MarionetteClient {
constructor(port = 2828, host = '127.0.0.1') {
this.currentPacketNumber = 1;
this.events = new events_1.default();
this.port = port;
this.host = host;
this.socket = new net_1.Socket();
this.buffer = Buffer.alloc(0);
this.getPacketPromise = Promise.resolve();
this.sendPacketPromise = Promise.resolve();
this.protocolInfo = {
applicationType: '',
marionetteProtocol: '',
};
this.sessionInfo = null;
}
async _attemptToConnect(port, host) {
this.socket.connect(port, host);
const connectionPromise = Promise.race([
promisify_event_1.default(this.socket, 'connect'),
promisify_event_1.default(this.socket, 'error')
]);
return await connectionPromise
.then(() => true)
.catch(() => {
this.socket.removeAllListeners('connect');
return delay_1.default(CONNECTION_RETRY_DELAY);
});
}
async _connectSocket(port, host) {
const connectionStartTime = Date.now();
let connected = await this._attemptToConnect(port, host);
while (!connected && Date.now() - connectionStartTime < CONNECTION_TIMEOUT)
connected = await this._attemptToConnect(port, host);
if (!connected)
throw new Error('Unable to connect');
this.socket.on('data', data => this._handleNewData(data));
}
async _writeSocket(message) {
if (!this.socket.write(message))
await promisify_event_1.default(this.socket, 'drain');
}
_handleNewData(data) {
if (!data)
return;
this.buffer = Buffer.concat([this.buffer, data]);
this.events.emit('new-data');
}
_getPacket() {
this.getPacketPromise = this.getPacketPromise.then(async () => {
let headerEndIndex = this.buffer.indexOf(HEADER_SEPARATOR);
while (headerEndIndex < 0) {
await promisify_event_1.default(this.events, 'new-data');
headerEndIndex = this.buffer.indexOf(HEADER_SEPARATOR);
}
const packet = {
length: NaN,
body: null
};
packet.length = parseInt(this.buffer.toString('utf8', 0, headerEndIndex), 10) || 0;
const bodyStartIndex = headerEndIndex + HEADER_SEPARATOR.length;
const bodyEndIndex = bodyStartIndex + packet.length;
if (packet.length) {
while (this.buffer.length < bodyEndIndex)
await promisify_event_1.default(this.events, 'new-data');
packet.body = JSON.parse(this.buffer.toString('utf8', bodyStartIndex, bodyEndIndex));
}
this.buffer = this.buffer.slice(bodyEndIndex);
return packet;
});
return this.getPacketPromise;
}
_sendPacket(payload) {
this.sendPacketPromise = this.sendPacketPromise.then(async () => {
const body = [0, this.currentPacketNumber++, payload.command, payload.parameters];
const serialized = JSON.stringify(body);
const message = Buffer.byteLength(serialized, 'utf8') + HEADER_SEPARATOR + serialized;
this._writeSocket(message);
});
return this.sendPacketPromise;
}
_throwMarionetteError(error) {
throw new Error(`${error.error}${error.message ? ': ' + error.message : ''}`);
}
async _getResponse(packet) {
const packetNumber = this.currentPacketNumber;
await this._sendPacket(packet);
let responsePacket = await this._getPacket();
while (!responsePacket.body || responsePacket.body[1] !== packetNumber)
responsePacket = await this._getPacket();
if (responsePacket.body[2])
this._throwMarionetteError(responsePacket.body[2]);
return responsePacket.body[3];
}
async _getScreenshotRawData(fullPage = false) {
return await this._getResponse({
command: commands_1.default.takeScreenshot,
parameters: {
full: fullPage,
hash: false,
scroll: false
}
});
}
async connect() {
await this._connectSocket(this.port, this.host);
const infoPacket = await this._getPacket();
this.protocolInfo = {
applicationType: infoPacket.body.applicationType,
marionetteProtocol: infoPacket.body.marionetteProtocol
};
this.sessionInfo = await this._getResponse({ command: commands_1.default.newSession });
}
dispose() {
this.socket.end();
this.buffer = null;
}
async executeScript(code) {
return await this._getResponse({
command: commands_1.default.executeScript,
parameters: { script: `return (${code})()` }
});
}
async getScreenshotData(_, fullPage) {
const frameData = await this._getScreenshotRawData(fullPage);
return Buffer.from(frameData.value, 'base64');
}
async setWindowSize(width, height) {
let { value: pageRect } = await this.executeScript(client_functions_1.GET_WINDOW_DIMENSIONS_INFO_SCRIPT);
let attemptCounter = 0;
while (attemptCounter++ < MAX_RESIZE_RETRY_COUNT && (pageRect.width !== width || pageRect.height !== height)) {
const currentRect = await this._getResponse({ command: commands_1.default.getWindowRect });
await this._getResponse({
command: commands_1.default.setWindowRect,
parameters: {
x: currentRect.x,
y: currentRect.y,
width: width + (currentRect.width - pageRect.width),
height: height + (currentRect.height - pageRect.height)
}
});
({ value: pageRect } = await this.executeScript(client_functions_1.GET_WINDOW_DIMENSIONS_INFO_SCRIPT));
}
}
async quit() {
await this._getResponse({ command: commands_1.default.quit });
}
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYnJvd3Nlci9wcm92aWRlci9idWlsdC1pbi9kZWRpY2F0ZWQvZmlyZWZveC9tYXJpb25ldHRlLWNsaWVudC9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZCQUE2QjtBQUM3QixzRUFBNkM7QUFDN0Msb0RBQWtDO0FBQ2xDLDBFQUFrRDtBQUNsRCx5RUFBdUY7QUFDdkYsMERBQWtDO0FBR2xDLE1BQU0sa0JBQWtCLEdBQU8sS0FBSyxDQUFDO0FBQ3JDLE1BQU0sc0JBQXNCLEdBQUcsR0FBRyxDQUFDO0FBQ25DLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxDQUFDO0FBQ2pDLE1BQU0sZ0JBQWdCLEdBQVMsR0FBRyxDQUFDO0FBRW5DLE1BQU0sQ0FBQyxPQUFPLEdBQUcsTUFBTSxnQkFBZ0I7SUFDbkMsWUFBYSxJQUFJLEdBQUcsSUFBSSxFQUFFLElBQUksR0FBRyxXQUFXO1FBQ3hDLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxDQUFDLENBQUM7UUFDN0IsSUFBSSxDQUFDLE1BQU0sR0FBZ0IsSUFBSSxnQkFBWSxFQUFFLENBQUM7UUFDOUMsSUFBSSxDQUFDLElBQUksR0FBa0IsSUFBSSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxJQUFJLEdBQWtCLElBQUksQ0FBQztRQUNoQyxJQUFJLENBQUMsTUFBTSxHQUFnQixJQUFJLFlBQU0sRUFBRSxDQUFDO1FBQ3hDLElBQUksQ0FBQyxNQUFNLEdBQWdCLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0MsSUFBSSxDQUFDLGdCQUFnQixHQUFNLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUM3QyxJQUFJLENBQUMsaUJBQWlCLEdBQUssT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBRTdDLElBQUksQ0FBQyxZQUFZLEdBQUc7WUFDaEIsZUFBZSxFQUFLLEVBQUU7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Q0FBQztJQUN4RCxDQUFDO0NBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFNvY2tldCB9IGZyb20gJ25ldCc7XG5pbXBvcnQgcHJvbWlzaWZ5RXZlbnQgZnJvbSAncHJvbWlzaWZ5LWV2ZW50JztcbmltcG9ydCBFdmVudEVtaXR0ZXIgZnJvbSAnZXZlbnRzJztcbmltcG9ydCBkZWxheSBmcm9tICcuLi8uLi8uLi8uLi8uLi8uLi91dGlscy9kZWxheSc7XG5pbXBvcnQgeyBHRVRfV0lORE9XX0RJTUVOU0lPTlNfSU5GT19TQ1JJUFQgfSBmcm9tICcuLi8uLi8uLi8uLi91dGlscy9jbGllbnQtZnVuY3Rpb25zJztcbmltcG9ydCBDT01NQU5EUyBmcm9tICcuL2NvbW1hbmRzJztcblxuXG5jb25zdCBDT05ORUNUSU9OX1RJTUVPVVQgICAgID0gMzAwMDA7XG5jb25zdCBDT05ORUNUSU9OX1JFVFJZX0RFTEFZID0gMzAwO1xuY29uc3QgTUFYX1JFU0laRV9SRVRSWV9DT1VOVCA9IDI7XG5jb25zdCBIRUFERVJfU0VQQVJBVE9SICAgICAgID0gJzonO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsYXNzIE1hcmlvbmV0dGVDbGllbnQge1xuICAgIGNvbnN0cnVjdG9yIChwb3J0ID0gMjgyOCwgaG9zdCA9ICcxMjcuMC4wLjEnKSB7XG4gICAgICAgIHRoaXMuY3VycmVudFBhY2tldE51bWJlciA9IDE7XG4gICAgICAgIHRoaXMuZXZlbnRzICAgICAgICAgICAgICA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAgICAgdGhpcy5wb3J0ICAgICAgICAgICAgICAgID0gcG9ydDtcbiAgICAgICAgdGhpcy5ob3N0ICAgICAgICAgICAgICAgID0gaG9zdDtcbiAgICAgICAgdGhpcy5zb2NrZXQgICAgICAgICAgICAgID0gbmV3IFNvY2tldCgpO1xuICAgICAgICB0aGlzLmJ1ZmZlciAgICAgICAgICAgICAgPSBCdWZmZXIuYWxsb2MoMCk7XG4gICAgICAgIHRoaXMuZ2V0UGFja2V0UHJvbWlzZSAgICA9IFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB0aGlzLnNlbmRQYWNrZXRQcm9taXNlICAgPSBQcm9taXNlLnJlc29sdmUoKTtcblxuICAgICAgICB0aGlzLnByb3RvY29sSW5mbyA9IHtcbiAgICAgICAgICAgIGFwcGxpY2F0aW9uVHlwZTogICAgJycsXG4gICAgICAgICAgICBtYXJpb25ldHRlUHJvdG9jb2w6ICcnLFxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMuc2Vzc2lvbkluZm8gPSBudWxsO1xuICAgIH1cblxuICAgIGFzeW5jIF9hdHRlbXB0VG9Db25uZWN0IChwb3J0LCBob3N0KSB7XG4gICAgICAgIHRoaXMuc29ja2V0LmNvbm5lY3QocG9ydCwgaG9zdCk7XG5cbiAgICAgICAgY29uc3QgY29ubmVjdGlvblByb21pc2UgPSBQcm9taXNlLnJhY2UoW1xuICAgICAgICAgICAgcHJvbWlzaWZ5RXZlbnQodGhpcy5zb2NrZXQsICdjb25uZWN0JyksXG4gICAgICAgICAgICBwcm9taXNpZnlFdmVudCh0aGlzLnNvY2tldCwgJ2Vycm9yJylcbiAgICAgICAgXSk7XG5cbiAgICAgICAgcmV0dXJuIGF3YWl0IGNvbm5lY3Rpb25Qcm9taXNlXG4gICAgICAgICAgICAudGhlbigoKSA9PiB0cnVlKVxuICAgICAgICAgICAgLmNhdGNoKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNvY2tldC5yZW1vdmVBbGxMaXN0ZW5lcnMoJ2Nvbm5lY3QnKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGVsYXkoQ09OTkVDVElPTl9SRVRSWV9ERUxBWSk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhc3luYyBfY29ubmVjdFNvY2tldCAocG9ydCwgaG9zdCkge1xuICAgICAgICBjb25zdCBjb25uZWN0aW9uU3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcblxuICAgICAgICBsZXQgY29ubmVjdGVkID0gYXdhaXQgdGhpcy5fYXR0ZW1wdFRvQ29ubmVjdChwb3J0LCBob3N0KTtcblxuICAgICAgICB3aGlsZSAoIWNvbm5lY3RlZCAmJiBEYXRlLm5vdygpIC0gY29ubmVjdGlvblN0YXJ0VGltZSA8IENPTk5FQ1RJT05fVElNRU9VVClcbiAgICAgICAgICAgIGNvbm5lY3RlZCA9IGF3YWl0IHRoaXMuX2F0dGVtcHRUb0Nvbm5lY3QocG9ydCwgaG9zdCk7XG5cbiAgICAgICAgaWYgKCFjb25uZWN0ZWQpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBjb25uZWN0Jyk7XG5cbiAgICAgICAgdGhpcy5zb2NrZXQub24oJ2RhdGEnLCBkYXRhID0+IHRoaXMuX2hhbmRsZU5ld0RhdGEoZGF0YSkpO1xuICAgIH1cblxuICAgIGFzeW5jIF93cml0ZVNvY2tldCAobWVzc2FnZSkge1xuICAgICAgICBpZiAoIXRoaXMuc29ja2V0LndyaXRlKG1lc3NhZ2UpKVxuICAgICAgICAgICAgYXdhaXQgcHJvbWlzaWZ5RXZlbnQodGhpcy5zb2NrZXQsICdkcmFpbicpO1xuICAgIH1cblxuICAgIF9oYW5kbGVOZXdEYXRhIChkYXRhKSB7XG4gICAgICAgIGlmICghZGF0YSlcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICB0aGlzLmJ1ZmZlciA9IEJ1ZmZlci5jb25jYXQoW3RoaXMuYnVmZmVyLCBkYXRhXSk7XG5cbiAgICAgICAgdGhpcy5ldmVudHMuZW1pdCgnbmV3LWRhdGEnKTtcbiAgICB9XG5cbiAgICBfZ2V0UGFja2V0ICgpIHtcbiAgICAgICAgdGhpcy5nZXRQYWNrZXRQcm9taXNlID0gdGhpcy5nZXRQYWNrZXRQcm9taXNlLnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgbGV0IGhlYWRlckVuZEluZGV4ID0gdGhpcy5idWZmZXIuaW5kZXhPZihIRUFERVJfU0VQQVJBVE9SKTtcblxuICAgICAgICAgICAgd2hpbGUgKGhlYWRlckVuZEluZGV4IDwgMCkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHByb21pc2lmeUV2ZW50KHRoaXMuZXZlbnRzLCAnbmV3LWRhdGEnKTtcblxuICAgICAgICAgICAgICAgIGhlYWRlckVuZEluZGV4ID0gdGhpcy5idWZmZXIuaW5kZXhPZihIRUFERVJfU0VQQVJBVE9SKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgcGFja2V0ID0ge1xuICAgICAgICAgICAgICAgIGxlbmd0aDogTmFOLFxuICAgICAgICAgICAgICAgIGJvZHk6ICAgbnVsbFxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgcGFja2V0Lmxlbmd0aCA9IHBhcnNlSW50KHRoaXMuYnVmZmVyLnRvU3RyaW5nKCd1dGY4JywgMCwgaGVhZGVyRW5kSW5kZXgpLCAxMCkgfHwgMDtcblxuICAgICAgICAgICAgY29uc3QgYm9keVN0YXJ0SW5kZXggPSBoZWFkZXJFbmRJbmRleCArIEhFQURFUl9TRVBBUkFUT1IubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgYm9keUVuZEluZGV4ICAgPSBib2R5U3RhcnRJbmRleCArIHBhY2tldC5sZW5ndGg7XG5cbiAgICAgICAgICAgIGlmIChwYWNrZXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHRoaXMuYnVmZmVyLmxlbmd0aCA8IGJvZHlFbmRJbmRleClcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgcHJvbWlzaWZ5RXZlbnQodGhpcy5ldmVudHMsICduZXctZGF0YScpO1xuXG4gICAgICAgICAgICAgICAgcGFja2V0LmJvZHkgPSBKU09OLnBhcnNlKHRoaXMuYnVmZmVyLnRvU3RyaW5nKCd1dGY4JywgYm9keVN0YXJ0SW5kZXgsIGJvZHlFbmRJbmRleCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmJ1ZmZlciA9IHRoaXMuYnVmZmVyLnNsaWNlKGJvZHlFbmRJbmRleCk7XG5cbiAgICAgICAgICAgIHJldHVybiBwYWNrZXQ7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmdldFBhY2tldFByb21pc2U7XG4gICAgfVxuXG4gICAgX3NlbmRQYWNrZXQgKHBheWxvYWQpIHtcbiAgICAgICAgdGhpcy5zZW5kUGFja2V0UHJvbWlzZSA9IHRoaXMuc2VuZFBhY2tldFByb21pc2UudGhlbihhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBib2R5ICAgICAgID0gWzAsIHRoaXMuY3VycmVudFBhY2tldE51bWJlcisrLCBwYXlsb2FkLmNvbW1hbmQsIHBheWxvYWQucGFyYW1ldGVyc107XG4gICAgICAgICAgICBjb25zdCBzZXJpYWxpemVkID0gSlNPTi5zdHJpbmdpZnkoYm9keSk7XG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlICAgID0gQnVmZmVyLmJ5dGVMZW5ndGgoc2VyaWFsaXplZCwgJ3V0ZjgnKSArIEhFQURFUl9TRVBBUkFUT1IgKyBzZXJpYWxpemVkO1xuXG4gICAgICAgICAgICB0aGlzLl93cml0ZVNvY2tldChtZXNzYWdlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuc2VuZFBhY2tldFByb21pc2U7XG4gICAgfVxuXG4gICAgX3Rocm93TWFyaW9uZXR0ZUVycm9yIChlcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZXJyb3IuZXJyb3J9JHtlcnJvci5tZXNzYWdlID8gJzogJyArIGVycm9yLm1lc3NhZ2UgOiAnJ31gKTtcbiAgICB9XG5cbiAgICBhc3luYyBfZ2V0UmVzcG9uc2UgKHBhY2tldCkge1xuICAgICAgICBjb25zdCBwYWNrZXROdW1iZXIgPSB0aGlzLmN1cnJlbnRQYWNrZXROdW1iZXI7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5fc2VuZFBhY2tldChwYWNrZXQpO1xuXG4gICAgICAgIGxldCByZXNwb25zZVBhY2tldCA9IGF3YWl0IHRoaXMuX2dldFBhY2tldCgpO1xuXG4gICAgICAgIHdoaWxlICghcmVzcG9uc2VQYWNrZXQuYm9keSB8fCByZXNwb25zZVBhY2tldC5ib2R5WzFdICE9PSBwYWNrZXROdW1iZXIpXG4gICAgICAgICAgICByZXNwb25zZVBhY2tldCA9IGF3YWl0IHRoaXMuX2dldFBhY2tldCgpO1xuXG4gICAgICAgIGlmIChyZXNwb25zZVBhY2tldC5ib2R5WzJdKVxuICAgICAgICAgICAgdGhpcy5fdGhyb3dNYXJpb25ldHRlRXJyb3IocmVzcG9uc2VQYWNrZXQuYm9keVsyXSk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlUGFja2V0LmJvZHlbM107XG4gICAgfVxuXG4gICAgYXN5bmMgX2dldFNjcmVlbnNob3RSYXdEYXRhIChmdWxsUGFnZSA9IGZhbHNlKSB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLl9nZXRSZXNwb25zZSh7XG4gICAgICAgICAgICBjb21tYW5kOiAgICBDT01NQU5EUy50YWtlU2NyZWVuc2hvdCxcbiAgICAgICAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAgICAgICBmdWxsOiAgIGZ1bGxQYWdlLFxuICAgICAgICAgICAgICAgIGhhc2g6ICAgZmFsc2UsXG4gICAgICAgICAgICAgICAgc2Nyb2xsOiBmYWxzZVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhc3luYyBjb25uZWN0ICgpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5fY29ubmVjdFNvY2tldCh0aGlzLnBvcnQsIHRoaXMuaG9zdCk7XG5cbiAgICAgICAgY29uc3QgaW5mb1BhY2tldCA9IGF3YWl0IHRoaXMuX2dldFBhY2tldCgpO1xuXG4gICAgICAgIHRoaXMucHJvdG9jb2xJbmZvID0ge1xuICAgICAgICAgICAgYXBwbGljYXRpb25UeXBlOiAgICBpbmZvUGFja2V0LmJvZHkuYXBwbGljYXRpb25UeXBlLFxuICAgICAgICAgICAgbWFyaW9uZXR0ZVByb3RvY29sOiBpbmZvUGFja2V0LmJvZHkubWFyaW9uZXR0ZVByb3RvY29sXG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uSW5mbyA9IGF3YWl0IHRoaXMuX2dldFJlc3BvbnNlKHsgY29tbWFuZDogQ09NTUFORFMubmV3U2Vzc2lvbiB9KTtcbiAgICB9XG5cbiAgICBkaXNwb3NlICgpIHtcbiAgICAgICAgdGhpcy5zb2NrZXQuZW5kKCk7XG4gICAgICAgIHRoaXMuYnVmZmVyID0gbnVsbDtcbiAgICB9XG5cbiAgICBhc3luYyBleGVjdXRlU2NyaXB0IChjb2RlKSB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLl9nZXRSZXNwb25zZSh7XG4gICAgICAgICAgICBjb21tYW5kOiAgICBDT01NQU5EUy5leGVjdXRlU2NyaXB0LFxuICAgICAgICAgICAgcGFyYW1ldGVyczogeyBzY3JpcHQ6IGByZXR1cm4gKCR7Y29kZX0pKClgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgYXN5bmMgZ2V0U2NyZWVuc2hvdERhdGEgKF8sIGZ1bGxQYWdlKSB7XG4gICAgICAgIGNvbnN0IGZyYW1lRGF0YSA9IGF3YWl0IHRoaXMuX2dldFNjcmVlbnNob3RSYXdEYXRhKGZ1bGxQYWdlKTtcblxuICAgICAgICByZXR1cm4gQnVmZmVyLmZyb20oZnJhbWVEYXRhLnZhbHVlLCAnYmFzZTY0Jyk7XG4gICAgfVxuXG4gICAgYXN5bmMgc2V0V2luZG93U2l6ZSAod2lkdGgsIGhlaWdodCkge1xuICAgICAgICBsZXQgeyB2YWx1ZTogcGFnZVJlY3QgfSA9IGF3YWl0IHRoaXMuZXhlY3V0ZVNjcmlwdChHRVRfV0lORE9XX0RJTUVOU0lPTlNfSU5GT19TQ1JJUFQpO1xuICAgICAgICBsZXQgYXR0ZW1wdENvdW50ZXIgICAgICA9IDA7XG5cbiAgICAgICAgd2hpbGUgKGF0dGVtcHRDb3VudGVyKysgPCBNQVhfUkVTSVpFX1JFVFJZX0NPVU5UICYmIChwYWdlUmVjdC53aWR0aCAhPT0gd2lkdGggfHwgcGFnZVJlY3QuaGVpZ2h0ICE9PSBoZWlnaHQpKSB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW50UmVjdCA9IGF3YWl0IHRoaXMuX2dldFJlc3BvbnNlKHsgY29tbWFuZDogQ09NTUFORFMuZ2V0V2luZG93UmVjdCB9KTtcblxuICAgICAgICAgICAgYXdhaXQgdGhpcy5fZ2V0UmVzcG9uc2Uoe1xuICAgICAgICAgICAgICAgIGNvbW1hbmQ6IENPTU1BTkRTLnNldFdpbmRvd1JlY3QsXG5cbiAgICAgICAgICAgICAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICAgICAgICAgICAgICAgIHg6ICAgICAgY3VycmVudFJlY3QueCxcbiAgICAgICAgICAgICAgICAgICAgeTogICAgICBjdXJyZW50UmVjdC55LFxuICAgICAgICAgICAgICAgICAgICB3aWR0aDogIHdpZHRoICsgKGN1cnJlbnRSZWN0LndpZHRoIC0gcGFnZVJlY3Qud2lkdGgpLFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGhlaWdodCArIChjdXJyZW50UmVjdC5oZWlnaHQgLSBwYWdlUmVjdC5oZWlnaHQpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICh7IHZhbHVlOiBwYWdlUmVjdCB9ID0gYXdhaXQgdGhpcy5leGVjdXRlU2NyaXB0KEdFVF9XSU5ET1dfRElNRU5TSU9OU19JTkZPX1NDUklQVCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgcXVpdCAoKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuX2dldFJlc3BvbnNlKHsgY29tbWFuZDogQ09NTUFORFMucXVpdCB9KTtcbiAgICB9XG59O1xuXG4iXX0=