testcafe
Version:
Automated browser testing for the modern web development stack.
158 lines • 24.2 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 pinkie_1 = __importDefault(require("pinkie"));
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 = pinkie_1.default.resolve();
this.sendPacketPromise = pinkie_1.default.resolve();
this.protocolInfo = {
applicationType: '',
marionetteProtocol: '',
};
this.sessionInfo = null;
}
async _attemptToConnect(port, host) {
this.socket.connect(port, host);
const connectionPromise = pinkie_1.default.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() {
return await this._getResponse({ command: commands_1.default.takeScreenshot });
}
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() {
const frameData = await this._getScreenshotRawData();
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYnJvd3Nlci9wcm92aWRlci9idWlsdC1pbi9kZWRpY2F0ZWQvZmlyZWZveC9tYXJpb25ldHRlLWNsaWVudC9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLG9EQUE2QjtBQUM3Qiw2QkFBNkI7QUFDN0Isc0VBQTZDO0FBQzdDLG9EQUFrQztBQUNsQywwRUFBa0Q7QUFDbEQseUVBQXVGO0FBQ3ZGLDBEQUFrQztBQUdsQyxNQUFNLGtCQUFrQixHQUFPLEtBQUssQ0FBQztBQUNyQyxNQUFNLHNCQUFzQixHQUFHLEdBQUcsQ0FBQztBQUNuQyxNQUFNLHNCQUFzQixHQUFHLENBQUMsQ0FBQztBQUNqQyxNQUFNLGdCQUFnQixHQUFTLEdBQUcsQ0FBQztBQUVuQyxNQUFNLENBQUMsT0FBTyxHQUFHLE1BQU0sZ0JBQWdCO0lBQ25DLFlBQWEsSUFBSSxHQUFHLElBQUksRUFBRSxJQUFJLEdBQUcsV0FBVztRQUN4QyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxNQUFNLEdBQWdCLElBQUksZ0JBQVksRUFBRSxDQUFDO1FBQzlDLElBQUksQ0FBQyxJQUFJLEdBQWtCLElBQUksQ0FBQztRQUNoQyxJQUFJLENBQUMsSUFBSSxHQUFrQixJQUFJLENBQUM7UUFDaEMsSUFBSSxDQUFDLE1BQU0sR0FBZ0IsSUFBSSxZQUFNLEVBQUUsQ0FBQztRQUN4QyxJQUFJLENBQUMsTUFBTSxHQUFnQixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxnQkFBZ0IsR0FBTSxnQkFBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQzdDLElBQUksQ0FBQyxpQkFBaUIsR0FBSyxnQkFBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBRTdDLElBQUksQ0FBQyxZQUFZLEdBQUc7WUFDaEIs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QUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLG9EQUFpQyxDQUFDLENBQUM7UUFDdEYsSUFBSSxjQUFjLEdBQVEsQ0FBQyxDQUFDO1FBRTVCLE9BQU8sY0FBYyxFQUFFLEdBQUcsc0JBQXNCLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxLQUFLLEtBQUssSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLE1BQU0sQ0FBQyxFQUFFO1lBQzFHLE1BQU0sV0FBVyxHQUFHLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLE9BQU8sRUFBRSxrQkFBUSxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUM7WUFFakYsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDO2dCQUNwQixPQUFPLEVBQUUsa0JBQVEsQ0FBQyxhQUFhO2dCQUUvQixVQUFVLEVBQUU7b0JBQ1IsQ0FBQyxFQUFPLFdBQVcsQ0FBQyxDQUFDO29CQUNyQixDQUFDLEVBQU8sV0FBVyxDQUFDLENBQUM7b0JBQ3JCLEtBQUssRUFBRyxLQUFLLEdBQUcsQ0FBQyxXQUFXLENBQUMsS0FBSyxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUM7b0JBQ3BELE1BQU0sRUFBRSxNQUFNLEdBQUcsQ0FBQyxXQUFXLENBQUMsTUFBTSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUM7aUJBQzFEO2FBQ0osQ0FBQyxDQUFDO1lBRUgsQ0FBQyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsR0FBRyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsb0RBQWlDLENBQUMsQ0FBQyxDQUFDO1NBQ3ZGO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyxJQUFJO1FBQ04sTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUUsT0FBTyxFQUFFLGtCQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN4RCxDQUFDO0NBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBQcm9taXNlIGZyb20gJ3BpbmtpZSc7XG5pbXBvcnQgeyBTb2NrZXQgfSBmcm9tICduZXQnO1xuaW1wb3J0IHByb21pc2lmeUV2ZW50IGZyb20gJ3Byb21pc2lmeS1ldmVudCc7XG5pbXBvcnQgRXZlbnRFbWl0dGVyIGZyb20gJ2V2ZW50cyc7XG5pbXBvcnQgZGVsYXkgZnJvbSAnLi4vLi4vLi4vLi4vLi4vLi4vdXRpbHMvZGVsYXknO1xuaW1wb3J0IHsgR0VUX1dJTkRPV19ESU1FTlNJT05TX0lORk9fU0NSSVBUIH0gZnJvbSAnLi4vLi4vLi4vLi4vdXRpbHMvY2xpZW50LWZ1bmN0aW9ucyc7XG5pbXBvcnQgQ09NTUFORFMgZnJvbSAnLi9jb21tYW5kcyc7XG5cblxuY29uc3QgQ09OTkVDVElPTl9USU1FT1VUICAgICA9IDMwMDAwO1xuY29uc3QgQ09OTkVDVElPTl9SRVRSWV9ERUxBWSA9IDMwMDtcbmNvbnN0IE1BWF9SRVNJWkVfUkVUUllfQ09VTlQgPSAyO1xuY29uc3QgSEVBREVSX1NFUEFSQVRPUiAgICAgICA9ICc6JztcblxubW9kdWxlLmV4cG9ydHMgPSBjbGFzcyBNYXJpb25ldHRlQ2xpZW50IHtcbiAgICBjb25zdHJ1Y3RvciAocG9ydCA9IDI4MjgsIGhvc3QgPSAnMTI3LjAuMC4xJykge1xuICAgICAgICB0aGlzLmN1cnJlbnRQYWNrZXROdW1iZXIgPSAxO1xuICAgICAgICB0aGlzLmV2ZW50cyAgICAgICAgICAgICAgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgICAgIHRoaXMucG9ydCAgICAgICAgICAgICAgICA9IHBvcnQ7XG4gICAgICAgIHRoaXMuaG9zdCAgICAgICAgICAgICAgICA9IGhvc3Q7XG4gICAgICAgIHRoaXMuc29ja2V0ICAgICAgICAgICAgICA9IG5ldyBTb2NrZXQoKTtcbiAgICAgICAgdGhpcy5idWZmZXIgICAgICAgICAgICAgID0gQnVmZmVyLmFsbG9jKDApO1xuICAgICAgICB0aGlzLmdldFBhY2tldFByb21pc2UgICAgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgdGhpcy5zZW5kUGFja2V0UHJvbWlzZSAgID0gUHJvbWlzZS5yZXNvbHZlKCk7XG5cbiAgICAgICAgdGhpcy5wcm90b2NvbEluZm8gPSB7XG4gICAgICAgICAgICBhcHBsaWNhdGlvblR5cGU6ICAgICcnLFxuICAgICAgICAgICAgbWFyaW9uZXR0ZVByb3RvY29sOiAnJyxcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnNlc3Npb25JbmZvID0gbnVsbDtcbiAgICB9XG5cbiAgICBhc3luYyBfYXR0ZW1wdFRvQ29ubmVjdCAocG9ydCwgaG9zdCkge1xuICAgICAgICB0aGlzLnNvY2tldC5jb25uZWN0KHBvcnQsIGhvc3QpO1xuXG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25Qcm9taXNlID0gUHJvbWlzZS5yYWNlKFtcbiAgICAgICAgICAgIHByb21pc2lmeUV2ZW50KHRoaXMuc29ja2V0LCAnY29ubmVjdCcpLFxuICAgICAgICAgICAgcHJvbWlzaWZ5RXZlbnQodGhpcy5zb2NrZXQsICdlcnJvcicpXG4gICAgICAgIF0pO1xuXG4gICAgICAgIHJldHVybiBhd2FpdCBjb25uZWN0aW9uUHJvbWlzZVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gdHJ1ZSlcbiAgICAgICAgICAgIC5jYXRjaCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zb2NrZXQucmVtb3ZlQWxsTGlzdGVuZXJzKCdjb25uZWN0Jyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRlbGF5KENPTk5FQ1RJT05fUkVUUllfREVMQVkpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgYXN5bmMgX2Nvbm5lY3RTb2NrZXQgKHBvcnQsIGhvc3QpIHtcbiAgICAgICAgY29uc3QgY29ubmVjdGlvblN0YXJ0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICAgICAgbGV0IGNvbm5lY3RlZCA9IGF3YWl0IHRoaXMuX2F0dGVtcHRUb0Nvbm5lY3QocG9ydCwgaG9zdCk7XG5cbiAgICAgICAgd2hpbGUgKCFjb25uZWN0ZWQgJiYgRGF0ZS5ub3coKSAtIGNvbm5lY3Rpb25TdGFydFRpbWUgPCBDT05ORUNUSU9OX1RJTUVPVVQpXG4gICAgICAgICAgICBjb25uZWN0ZWQgPSBhd2FpdCB0aGlzLl9hdHRlbXB0VG9Db25uZWN0KHBvcnQsIGhvc3QpO1xuXG4gICAgICAgIGlmICghY29ubmVjdGVkKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gY29ubmVjdCcpO1xuXG4gICAgICAgIHRoaXMuc29ja2V0Lm9uKCdkYXRhJywgZGF0YSA9PiB0aGlzLl9oYW5kbGVOZXdEYXRhKGRhdGEpKTtcbiAgICB9XG5cbiAgICBhc3luYyBfd3JpdGVTb2NrZXQgKG1lc3NhZ2UpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNvY2tldC53cml0ZShtZXNzYWdlKSlcbiAgICAgICAgICAgIGF3YWl0IHByb21pc2lmeUV2ZW50KHRoaXMuc29ja2V0LCAnZHJhaW4nKTtcbiAgICB9XG5cbiAgICBfaGFuZGxlTmV3RGF0YSAoZGF0YSkge1xuICAgICAgICBpZiAoIWRhdGEpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgdGhpcy5idWZmZXIgPSBCdWZmZXIuY29uY2F0KFt0aGlzLmJ1ZmZlciwgZGF0YV0pO1xuXG4gICAgICAgIHRoaXMuZXZlbnRzLmVtaXQoJ25ldy1kYXRhJyk7XG4gICAgfVxuXG4gICAgX2dldFBhY2tldCAoKSB7XG4gICAgICAgIHRoaXMuZ2V0UGFja2V0UHJvbWlzZSA9IHRoaXMuZ2V0UGFja2V0UHJvbWlzZS50aGVuKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGxldCBoZWFkZXJFbmRJbmRleCA9IHRoaXMuYnVmZmVyLmluZGV4T2YoSEVBREVSX1NFUEFSQVRPUik7XG5cbiAgICAgICAgICAgIHdoaWxlIChoZWFkZXJFbmRJbmRleCA8IDApIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBwcm9taXNpZnlFdmVudCh0aGlzLmV2ZW50cywgJ25ldy1kYXRhJyk7XG5cbiAgICAgICAgICAgICAgICBoZWFkZXJFbmRJbmRleCA9IHRoaXMuYnVmZmVyLmluZGV4T2YoSEVBREVSX1NFUEFSQVRPUik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHBhY2tldCA9IHtcbiAgICAgICAgICAgICAgICBsZW5ndGg6IE5hTixcbiAgICAgICAgICAgICAgICBib2R5OiAgIG51bGxcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHBhY2tldC5sZW5ndGggPSBwYXJzZUludCh0aGlzLmJ1ZmZlci50b1N0cmluZygndXRmOCcsIDAsIGhlYWRlckVuZEluZGV4KSwgMTApIHx8IDA7XG5cbiAgICAgICAgICAgIGNvbnN0IGJvZHlTdGFydEluZGV4ID0gaGVhZGVyRW5kSW5kZXggKyBIRUFERVJfU0VQQVJBVE9SLmxlbmd0aDtcbiAgICAgICAgICAgIGNvbnN0IGJvZHlFbmRJbmRleCAgID0gYm9keVN0YXJ0SW5kZXggKyBwYWNrZXQubGVuZ3RoO1xuXG4gICAgICAgICAgICBpZiAocGFja2V0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHdoaWxlICh0aGlzLmJ1ZmZlci5sZW5ndGggPCBib2R5RW5kSW5kZXgpXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHByb21pc2lmeUV2ZW50KHRoaXMuZXZlbnRzLCAnbmV3LWRhdGEnKTtcblxuICAgICAgICAgICAgICAgIHBhY2tldC5ib2R5ID0gSlNPTi5wYXJzZSh0aGlzLmJ1ZmZlci50b1N0cmluZygndXRmOCcsIGJvZHlTdGFydEluZGV4LCBib2R5RW5kSW5kZXgpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5idWZmZXIgPSB0aGlzLmJ1ZmZlci5zbGljZShib2R5RW5kSW5kZXgpO1xuXG4gICAgICAgICAgICByZXR1cm4gcGFja2V0O1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdGhpcy5nZXRQYWNrZXRQcm9taXNlO1xuICAgIH1cblxuICAgIF9zZW5kUGFja2V0IChwYXlsb2FkKSB7XG4gICAgICAgIHRoaXMuc2VuZFBhY2tldFByb21pc2UgPSB0aGlzLnNlbmRQYWNrZXRQcm9taXNlLnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgYm9keSAgICAgICA9IFswLCB0aGlzLmN1cnJlbnRQYWNrZXROdW1iZXIrKywgcGF5bG9hZC5jb21tYW5kLCBwYXlsb2FkLnBhcmFtZXRlcnNdO1xuICAgICAgICAgICAgY29uc3Qgc2VyaWFsaXplZCA9IEpTT04uc3RyaW5naWZ5KGJvZHkpO1xuICAgICAgICAgICAgY29uc3QgbWVzc2FnZSAgICA9IEJ1ZmZlci5ieXRlTGVuZ3RoKHNlcmlhbGl6ZWQsICd1dGY4JykgKyBIRUFERVJfU0VQQVJBVE9SICsgc2VyaWFsaXplZDtcblxuICAgICAgICAgICAgdGhpcy5fd3JpdGVTb2NrZXQobWVzc2FnZSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnNlbmRQYWNrZXRQcm9taXNlO1xuICAgIH1cblxuICAgIF90aHJvd01hcmlvbmV0dGVFcnJvciAoZXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2Vycm9yLmVycm9yfSR7ZXJyb3IubWVzc2FnZSA/ICc6ICcgKyBlcnJvci5tZXNzYWdlIDogJyd9YCk7XG4gICAgfVxuXG4gICAgYXN5bmMgX2dldFJlc3BvbnNlIChwYWNrZXQpIHtcbiAgICAgICAgY29uc3QgcGFja2V0TnVtYmVyID0gdGhpcy5jdXJyZW50UGFja2V0TnVtYmVyO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuX3NlbmRQYWNrZXQocGFja2V0KTtcblxuICAgICAgICBsZXQgcmVzcG9uc2VQYWNrZXQgPSBhd2FpdCB0aGlzLl9nZXRQYWNrZXQoKTtcblxuICAgICAgICB3aGlsZSAoIXJlc3BvbnNlUGFja2V0LmJvZHkgfHwgcmVzcG9uc2VQYWNrZXQuYm9keVsxXSAhPT0gcGFja2V0TnVtYmVyKVxuICAgICAgICAgICAgcmVzcG9uc2VQYWNrZXQgPSBhd2FpdCB0aGlzLl9nZXRQYWNrZXQoKTtcblxuICAgICAgICBpZiAocmVzcG9uc2VQYWNrZXQuYm9keVsyXSlcbiAgICAgICAgICAgIHRoaXMuX3Rocm93TWFyaW9uZXR0ZUVycm9yKHJlc3BvbnNlUGFja2V0LmJvZHlbMl0pO1xuXG4gICAgICAgIHJldHVybiByZXNwb25zZVBhY2tldC5ib2R5WzNdO1xuICAgIH1cblxuICAgIGFzeW5jIF9nZXRTY3JlZW5zaG90UmF3RGF0YSAoKSB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLl9nZXRSZXNwb25zZSh7IGNvbW1hbmQ6IENPTU1BTkRTLnRha2VTY3JlZW5zaG90IH0pO1xuICAgIH1cblxuICAgIGFzeW5jIGNvbm5lY3QgKCkge1xuICAgICAgICBhd2FpdCB0aGlzLl9jb25uZWN0U29ja2V0KHRoaXMucG9ydCwgdGhpcy5ob3N0KTtcblxuICAgICAgICBjb25zdCBpbmZvUGFja2V0ID0gYXdhaXQgdGhpcy5fZ2V0UGFja2V0KCk7XG5cbiAgICAgICAgdGhpcy5wcm90b2NvbEluZm8gPSB7XG4gICAgICAgICAgICBhcHBsaWNhdGlvblR5cGU6ICAgIGluZm9QYWNrZXQuYm9keS5hcHBsaWNhdGlvblR5cGUsXG4gICAgICAgICAgICBtYXJpb25ldHRlUHJvdG9jb2w6IGluZm9QYWNrZXQuYm9keS5tYXJpb25ldHRlUHJvdG9jb2xcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnNlc3Npb25JbmZvID0gYXdhaXQgdGhpcy5fZ2V0UmVzcG9uc2UoeyBjb21tYW5kOiBDT01NQU5EUy5uZXdTZXNzaW9uIH0pO1xuICAgIH1cblxuICAgIGRpc3Bvc2UgKCkge1xuICAgICAgICB0aGlzLnNvY2tldC5lbmQoKTtcbiAgICAgICAgdGhpcy5idWZmZXIgPSBudWxsO1xuICAgIH1cblxuICAgIGFzeW5jIGV4ZWN1dGVTY3JpcHQgKGNvZGUpIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX2dldFJlc3BvbnNlKHtcbiAgICAgICAgICAgIGNvbW1hbmQ6ICAgIENPTU1BTkRTLmV4ZWN1dGVTY3JpcHQsXG4gICAgICAgICAgICBwYXJhbWV0ZXJzOiB7IHNjcmlwdDogYHJldHVybiAoJHtjb2RlfSkoKWAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhc3luYyBnZXRTY3JlZW5zaG90RGF0YSAoKSB7XG4gICAgICAgIGNvbnN0IGZyYW1lRGF0YSA9IGF3YWl0IHRoaXMuX2dldFNjcmVlbnNob3RSYXdEYXRhKCk7XG5cbiAgICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGZyYW1lRGF0YS52YWx1ZSwgJ2Jhc2U2NCcpO1xuICAgIH1cblxuICAgIGFzeW5jIHNldFdpbmRvd1NpemUgKHdpZHRoLCBoZWlnaHQpIHtcbiAgICAgICAgbGV0IHsgdmFsdWU6IHBhZ2VSZWN0IH0gPSBhd2FpdCB0aGlzLmV4ZWN1dGVTY3JpcHQoR0VUX1dJTkRPV19ESU1FTlNJT05TX0lORk9fU0NSSVBUKTtcbiAgICAgICAgbGV0IGF0dGVtcHRDb3VudGVyICAgICAgPSAwO1xuXG4gICAgICAgIHdoaWxlIChhdHRlbXB0Q291bnRlcisrIDwgTUFYX1JFU0laRV9SRVRSWV9DT1VOVCAmJiAocGFnZVJlY3Qud2lkdGggIT09IHdpZHRoIHx8IHBhZ2VSZWN0LmhlaWdodCAhPT0gaGVpZ2h0KSkge1xuICAgICAgICAgICAgY29uc3QgY3VycmVudFJlY3QgPSBhd2FpdCB0aGlzLl9nZXRSZXNwb25zZSh7IGNvbW1hbmQ6IENPTU1BTkRTLmdldFdpbmRvd1JlY3QgfSk7XG5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX2dldFJlc3BvbnNlKHtcbiAgICAgICAgICAgICAgICBjb21tYW5kOiBDT01NQU5EUy5zZXRXaW5kb3dSZWN0LFxuXG4gICAgICAgICAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgICAgICAgICAgICB4OiAgICAgIGN1cnJlbnRSZWN0LngsXG4gICAgICAgICAgICAgICAgICAgIHk6ICAgICAgY3VycmVudFJlY3QueSxcbiAgICAgICAgICAgICAgICAgICAgd2lkdGg6ICB3aWR0aCArIChjdXJyZW50UmVjdC53aWR0aCAtIHBhZ2VSZWN0LndpZHRoKSxcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQgKyAoY3VycmVudFJlY3QuaGVpZ2h0IC0gcGFnZVJlY3QuaGVpZ2h0KVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAoeyB2YWx1ZTogcGFnZVJlY3QgfSA9IGF3YWl0IHRoaXMuZXhlY3V0ZVNjcmlwdChHRVRfV0lORE9XX0RJTUVOU0lPTlNfSU5GT19TQ1JJUFQpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIHF1aXQgKCkge1xuICAgICAgICBhd2FpdCB0aGlzLl9nZXRSZXNwb25zZSh7IGNvbW1hbmQ6IENPTU1BTkRTLnF1aXQgfSk7XG4gICAgfVxufTtcblxuIl19