UNPKG

23.3 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6const assert_1 = __importDefault(require("assert"));
7const chrome_remote_interface_1 = __importDefault(require("chrome-remote-interface"));
8const demurgos_spawn_wrap_1 = require("demurgos-spawn-wrap");
9const istanbulize_1 = require("istanbulize");
10const DEBUGGER_URI_RE = /ws:\/\/.*?:(\d+)\//;
11// In milliseconds (1s)
12const GET_DEBUGGER_PORT_TIMEOUT = 1000;
13// In milliseconds (10s)
14const GET_COVERAGE_TIMEOUT = 10000;
15async function spawnInspected(file, args, options) {
16 const processCovs = [];
17 return new Promise((resolve, reject) => {
18 demurgos_spawn_wrap_1.observeSpawn(file, args, options)
19 .subscribe(async (ev) => {
20 try {
21 if (ev.rootProcess !== undefined && options.onRootProcess !== undefined) {
22 options.onRootProcess(ev.rootProcess);
23 }
24 const args = ["--inspect=0", ...ev.args];
25 const proxy = ev.proxySpawn(args);
26 const debuggerPort = await getDebuggerPort(proxy);
27 const processCov = await getCoverage(debuggerPort, options.filter);
28 processCovs.push(processCov);
29 }
30 catch (err) {
31 reject(err);
32 }
33 }, reject, () => resolve(processCovs));
34 });
35}
36exports.spawnInspected = spawnInspected;
37async function getDebuggerPort(proc) {
38 return new Promise((resolve, reject) => {
39 const timeoutId = setTimeout(onTimeout, GET_DEBUGGER_PORT_TIMEOUT * 100);
40 let stderrBuffer = Buffer.alloc(0);
41 proc.stderr.on("data", onStderrData);
42 proc.stderr.on("close", onClose);
43 function onStderrData(chunk) {
44 stderrBuffer = Buffer.concat([stderrBuffer, chunk]);
45 const stderrStr = stderrBuffer.toString("UTF-8");
46 const match = DEBUGGER_URI_RE.exec(stderrStr);
47 if (match === null) {
48 return;
49 }
50 const result = parseInt(match[1], 10);
51 removeListeners();
52 resolve(result);
53 }
54 function onClose(code, signal) {
55 removeListeners();
56 reject(new Error(`Unable to hook inspector (early exit, ${code}, ${signal})`));
57 }
58 function onTimeout() {
59 removeListeners();
60 reject(new Error("Unable to hook inspector (timeout)"));
61 // proc.kill();
62 }
63 function removeListeners() {
64 proc.stderr.removeListener("data", onStderrData);
65 proc.stderr.removeListener("close", onClose);
66 clearTimeout(timeoutId);
67 }
68 });
69}
70exports.getDebuggerPort = getDebuggerPort;
71async function getCoverage(port, filter) {
72 return new Promise(async (resolve, reject) => {
73 const timeoutId = setTimeout(onTimeout, GET_COVERAGE_TIMEOUT);
74 let client;
75 let mainExecutionContextId;
76 const scriptIdToMeta = new Map();
77 let state = "WaitingForMainContext"; // TODO: enum
78 try {
79 client = await chrome_remote_interface_1.default({ port });
80 await client.Profiler.enable();
81 await client.Profiler.startPreciseCoverage({ callCount: true, detailed: true });
82 await client.Debugger.enable();
83 client.once("Runtime.executionContextCreated", onMainContextCreation);
84 client.on("Runtime.executionContextDestroyed", onContextDestruction);
85 client.on("Debugger.scriptParsed", onScriptParsed);
86 await client.Runtime.enable();
87 }
88 catch (err) {
89 removeListeners();
90 reject(err);
91 }
92 function onMainContextCreation(ev) {
93 assert_1.default(state === "WaitingForMainContext");
94 mainExecutionContextId = ev.context.id;
95 state = "WaitingForMainContextDestruction";
96 }
97 function onScriptParsed(ev) {
98 const collect = filter !== undefined ? filter(ev) : true;
99 if (collect) {
100 let sourceType = istanbulize_1.SourceType.Script;
101 if (ev.isModule !== undefined) {
102 sourceType = ev.isModule ? istanbulize_1.SourceType.Module : istanbulize_1.SourceType.Script;
103 }
104 let sourceMapUrl;
105 if (ev.sourceMapURL !== undefined && ev.sourceMapURL !== "") {
106 sourceMapUrl = ev.sourceMapURL;
107 }
108 scriptIdToMeta.set(ev.scriptId, {
109 sourceType,
110 sourceMapUrl,
111 });
112 }
113 }
114 async function onContextDestruction(ev) {
115 assert_1.default(state === "WaitingForMainContextDestruction");
116 if (ev.executionContextId !== mainExecutionContextId) {
117 return;
118 }
119 state = "WaitingForCoverage";
120 try {
121 // await client.Profiler.stopPreciseCoverage();
122 await client.HeapProfiler.collectGarbage();
123 const { result: scriptCovs } = await client.Profiler.takePreciseCoverage();
124 const result = [];
125 for (const scriptCov of scriptCovs) {
126 const meta = scriptIdToMeta.get(scriptCov.scriptId);
127 if (meta === undefined) {
128 // `undefined` means that the script was filtered out.
129 continue;
130 }
131 const { scriptSource } = await client.Debugger.getScriptSource({ scriptId: scriptCov.scriptId });
132 result.push(Object.assign({}, scriptCov, { sourceText: scriptSource }, meta));
133 }
134 resolve({ result });
135 }
136 catch (err) {
137 reject(err);
138 }
139 finally {
140 removeListeners();
141 }
142 }
143 function onTimeout() {
144 removeListeners();
145 reject(new Error("Unable to get V8 coverage (timeout)"));
146 }
147 function removeListeners() {
148 client.removeListener("Runtime.executionContextCreated", onMainContextCreation);
149 client.removeListener("Runtime.executionContextDestroyed", onContextDestruction);
150 client.removeListener("Runtime.scriptParsed", onScriptParsed);
151 clearTimeout(timeoutId);
152 client.close();
153 }
154 });
155}
156
157//# sourceMappingURL=data:application/json;charset=utf8;base64,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QjtnQkFDRCxPQUFPLENBQUMsRUFBQyxNQUFNLEVBQUMsQ0FBQyxDQUFDO2FBQ25CO1lBQUMsT0FBTyxHQUFHLEVBQUU7Z0JBQ1osTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2FBQ2I7b0JBQVM7Z0JBQ1IsZUFBZSxFQUFFLENBQUM7YUFDbkI7UUFDSCxDQUFDO1FBRUQ7WUFDRSxlQUFlLEVBQUUsQ0FBQztZQUNsQixNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMscUNBQXFDLENBQUMsQ0FBQyxDQUFDO1FBQzNELENBQUM7UUFFRDtZQUNHLE1BQXFDLENBQUMsY0FBYyxDQUFDLGlDQUFpQyxFQUFFLHFCQUFxQixDQUFDLENBQUM7WUFDL0csTUFBcUMsQ0FBQyxjQUFjLENBQUMsbUNBQW1DLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztZQUNoSCxNQUFxQyxDQUFDLGNBQWMsQ0FBQyxzQkFBc0IsRUFBRSxjQUFjLENBQUMsQ0FBQztZQUM5RixZQUFZLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDdkIsTUFBYyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzFCLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMiLCJmaWxlIjoic3Bhd24taW5zcGVjdGVkLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUHJvY2Vzc0NvdiwgU2NyaXB0Q292IH0gZnJvbSBcIkBjODgvdjgtY292ZXJhZ2VcIjtcbmltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IGNwIGZyb20gXCJjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgY3JpIGZyb20gXCJjaHJvbWUtcmVtb3RlLWludGVyZmFjZVwiO1xuaW1wb3J0IHsgQ2hpbGRQcm9jZXNzUHJveHksIG9ic2VydmVTcGF3biwgT2JzZXJ2ZVNwYXduT3B0aW9ucywgU3Bhd25FdmVudCB9IGZyb20gXCJkZW11cmdvcy1zcGF3bi13cmFwXCI7XG5pbXBvcnQgUHJvdG9jb2wgZnJvbSBcImRldnRvb2xzLXByb3RvY29sXCI7XG5pbXBvcnQgZXZlbnRzIGZyb20gXCJldmVudHNcIjtcbmltcG9ydCB7IFNvdXJjZVR5cGUgfSBmcm9tIFwiaXN0YW5idWxpemVcIjtcbmltcG9ydCB7IENvdmVyYWdlRmlsdGVyIH0gZnJvbSBcIi4vZmlsdGVyXCI7XG5cbmNvbnN0IERFQlVHR0VSX1VSSV9SRTogUmVnRXhwID0gL3dzOlxcL1xcLy4qPzooXFxkKylcXC8vO1xuLy8gSW4gbWlsbGlzZWNvbmRzICgxcylcbmNvbnN0IEdFVF9ERUJVR0dFUl9QT1JUX1RJTUVPVVQ6IG51bWJlciA9IDEwMDA7XG4vLyBJbiBtaWxsaXNlY29uZHMgKDEwcylcbmNvbnN0IEdFVF9DT1ZFUkFHRV9USU1FT1VUOiBudW1iZXIgPSAxMDAwMDtcblxuZXhwb3J0IGludGVyZmFjZSBTY3JpcHRNZXRhIHtcbiAgc291cmNlVGV4dDogc3RyaW5nO1xuICBzb3VyY2VUeXBlOiBTb3VyY2VUeXBlO1xuICBzb3VyY2VNYXBVcmw/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmljaFNjcmlwdENvdiBleHRlbmRzIFNjcmlwdENvdiwgU2NyaXB0TWV0YSB7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmljaFByb2Nlc3NDb3YgZXh0ZW5kcyBQcm9jZXNzQ292IHtcbiAgcmVzdWx0OiBSaWNoU2NyaXB0Q292W107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3Bhd25JbnNwZWN0ZWRPcHRpb25zIGV4dGVuZHMgT2JzZXJ2ZVNwYXduT3B0aW9ucyB7XG4gIGZpbHRlcj86IENvdmVyYWdlRmlsdGVyO1xuXG4gIG9uUm9vdFByb2Nlc3M/KHByb2Nlc3M6IGNwLkNoaWxkUHJvY2Vzcyk6IGFueTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNwYXduSW5zcGVjdGVkKFxuICBmaWxlOiBzdHJpbmcsXG4gIGFyZ3M6IFJlYWRvbmx5QXJyYXk8c3RyaW5nPixcbiAgb3B0aW9uczogU3Bhd25JbnNwZWN0ZWRPcHRpb25zLFxuKTogUHJvbWlzZTxSaWNoUHJvY2Vzc0NvdltdPiB7XG4gIGNvbnN0IHByb2Nlc3NDb3ZzOiBSaWNoUHJvY2Vzc0NvdltdID0gW107XG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlPFJpY2hQcm9jZXNzQ292W10+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBvYnNlcnZlU3Bhd24oZmlsZSwgYXJncywgb3B0aW9ucylcbiAgICAgIC5zdWJzY3JpYmUoXG4gICAgICAgIGFzeW5jIChldjogU3Bhd25FdmVudCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAoZXYucm9vdFByb2Nlc3MgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLm9uUm9vdFByb2Nlc3MgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBvcHRpb25zLm9uUm9vdFByb2Nlc3MoZXYucm9vdFByb2Nlc3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYXJnczogUmVhZG9ubHlBcnJheTxzdHJpbmc+ID0gW1wiLS1pbnNwZWN0PTBcIiwgLi4uZXYuYXJnc107XG4gICAgICAgICAgICBjb25zdCBwcm94eTogQ2hpbGRQcm9jZXNzUHJveHkgPSBldi5wcm94eVNwYXduKGFyZ3MpO1xuICAgICAgICAgICAgY29uc3QgZGVidWdnZXJQb3J0OiBudW1iZXIgPSBhd2FpdCBnZXREZWJ1Z2dlclBvcnQocHJveHkpO1xuICAgICAgICAgICAgY29uc3QgcHJvY2Vzc0NvdjogUmljaFByb2Nlc3NDb3YgPSBhd2FpdCBnZXRDb3ZlcmFnZShkZWJ1Z2dlclBvcnQsIG9wdGlvbnMuZmlsdGVyKTtcbiAgICAgICAgICAgIHByb2Nlc3NDb3ZzLnB1c2gocHJvY2Vzc0Nvdik7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHJlamVjdCxcbiAgICAgICAgKCkgPT4gcmVzb2x2ZShwcm9jZXNzQ292cyksXG4gICAgICApO1xuICB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldERlYnVnZ2VyUG9ydChwcm9jOiBDaGlsZFByb2Nlc3NQcm94eSk6IFByb21pc2U8bnVtYmVyPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZTxudW1iZXI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjb25zdCB0aW1lb3V0SWQ6IE5vZGVKUy5UaW1lciA9IHNldFRpbWVvdXQob25UaW1lb3V0LCBHRVRfREVCVUdHRVJfUE9SVF9USU1FT1VUICogMTAwKTtcbiAgICBsZXQgc3RkZXJyQnVmZmVyOiBCdWZmZXIgPSBCdWZmZXIuYWxsb2MoMCk7XG4gICAgcHJvYy5zdGRlcnIub24oXCJkYXRhXCIsIG9uU3RkZXJyRGF0YSk7XG4gICAgcHJvYy5zdGRlcnIub24oXCJjbG9zZVwiLCBvbkNsb3NlKTtcblxuICAgIGZ1bmN0aW9uIG9uU3RkZXJyRGF0YShjaHVuazogQnVmZmVyKTogdm9pZCB7XG4gICAgICBzdGRlcnJCdWZmZXIgPSBCdWZmZXIuY29uY2F0KFtzdGRlcnJCdWZmZXIsIGNodW5rXSk7XG4gICAgICBjb25zdCBzdGRlcnJTdHI6IHN0cmluZyA9IHN0ZGVyckJ1ZmZlci50b1N0cmluZyhcIlVURi04XCIpO1xuICAgICAgY29uc3QgbWF0Y2g6IFJlZ0V4cEV4ZWNBcnJheSB8IG51bGwgPSBERUJVR0dFUl9VUklfUkUuZXhlYyhzdGRlcnJTdHIpO1xuICAgICAgaWYgKG1hdGNoID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJlc3VsdDogbnVtYmVyID0gcGFyc2VJbnQobWF0Y2hbMV0sIDEwKTtcbiAgICAgIHJlbW92ZUxpc3RlbmVycygpO1xuICAgICAgcmVzb2x2ZShyZXN1bHQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uQ2xvc2UoY29kZTogbnVtYmVyIHwgbnVsbCwgc2lnbmFsOiBzdHJpbmcgfCBudWxsKTogdm9pZCB7XG4gICAgICByZW1vdmVMaXN0ZW5lcnMoKTtcbiAgICAgIHJlamVjdChuZXcgRXJyb3IoYFVuYWJsZSB0byBob29rIGluc3BlY3RvciAoZWFybHkgZXhpdCwgJHtjb2RlfSwgJHtzaWduYWx9KWApKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBvblRpbWVvdXQoKTogdm9pZCB7XG4gICAgICByZW1vdmVMaXN0ZW5lcnMoKTtcbiAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJVbmFibGUgdG8gaG9vayBpbnNwZWN0b3IgKHRpbWVvdXQpXCIpKTtcbiAgICAgIC8vIHByb2Mua2lsbCgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVycygpOiB2b2lkIHtcbiAgICAgIHByb2Muc3RkZXJyLnJlbW92ZUxpc3RlbmVyKFwiZGF0YVwiLCBvblN0ZGVyckRhdGEpO1xuICAgICAgcHJvYy5zdGRlcnIucmVtb3ZlTGlzdGVuZXIoXCJjbG9zZVwiLCBvbkNsb3NlKTtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0SWQpO1xuICAgIH1cbiAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldENvdmVyYWdlKHBvcnQ6IG51bWJlciwgZmlsdGVyPzogQ292ZXJhZ2VGaWx0ZXIpOiBQcm9taXNlPFJpY2hQcm9jZXNzQ292PiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZTxSaWNoUHJvY2Vzc0Nvdj4oYXN5bmMgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGNvbnN0IHRpbWVvdXRJZDogTm9kZUpTLlRpbWVyID0gc2V0VGltZW91dChvblRpbWVvdXQsIEdFVF9DT1ZFUkFHRV9USU1FT1VUKTtcbiAgICBsZXQgY2xpZW50OiBhbnk7XG4gICAgbGV0IG1haW5FeGVjdXRpb25Db250ZXh0SWQ6IFByb3RvY29sLlJ1bnRpbWUuRXhlY3V0aW9uQ29udGV4dElkIHwgdW5kZWZpbmVkO1xuICAgIGNvbnN0IHNjcmlwdElkVG9NZXRhOiBNYXA8UHJvdG9jb2wuUnVudGltZS5TY3JpcHRJZCwgUGFydGlhbDxTY3JpcHRNZXRhPj4gPSBuZXcgTWFwKCk7XG4gICAgbGV0IHN0YXRlOiBzdHJpbmcgPSBcIldhaXRpbmdGb3JNYWluQ29udGV4dFwiOyAvLyBUT0RPOiBlbnVtXG4gICAgdHJ5IHtcbiAgICAgIGNsaWVudCA9IGF3YWl0IGNyaSh7cG9ydH0pO1xuXG4gICAgICBhd2FpdCBjbGllbnQuUHJvZmlsZXIuZW5hYmxlKCk7XG4gICAgICBhd2FpdCBjbGllbnQuUHJvZmlsZXIuc3RhcnRQcmVjaXNlQ292ZXJhZ2Uoe2NhbGxDb3VudDogdHJ1ZSwgZGV0YWlsZWQ6IHRydWV9KTtcbiAgICAgIGF3YWl0IGNsaWVudC5EZWJ1Z2dlci5lbmFibGUoKTtcblxuICAgICAgKGNsaWVudCBhcyBhbnkgYXMgZXZlbnRzLkV2ZW50RW1pdHRlcikub25jZShcIlJ1bnRpbWUuZXhlY3V0aW9uQ29udGV4dENyZWF0ZWRcIiwgb25NYWluQ29udGV4dENyZWF0aW9uKTtcbiAgICAgIChjbGllbnQgYXMgYW55IGFzIGV2ZW50cy5FdmVudEVtaXR0ZXIpLm9uKFwiUnVudGltZS5leGVjdXRpb25Db250ZXh0RGVzdHJveWVkXCIsIG9uQ29udGV4dERlc3RydWN0aW9uKTtcbiAgICAgIChjbGllbnQgYXMgYW55IGFzIGV2ZW50cy5FdmVudEVtaXR0ZXIpLm9uKFwiRGVidWdnZXIuc2NyaXB0UGFyc2VkXCIsIG9uU2NyaXB0UGFyc2VkKTtcblxuICAgICAgYXdhaXQgY2xpZW50LlJ1bnRpbWUuZW5hYmxlKCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICByZW1vdmVMaXN0ZW5lcnMoKTtcbiAgICAgIHJlamVjdChlcnIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uTWFpbkNvbnRleHRDcmVhdGlvbihldjogUHJvdG9jb2wuUnVudGltZS5FeGVjdXRpb25Db250ZXh0Q3JlYXRlZEV2ZW50KSB7XG4gICAgICBhc3NlcnQoc3RhdGUgPT09IFwiV2FpdGluZ0Zvck1haW5Db250ZXh0XCIpO1xuICAgICAgbWFpbkV4ZWN1dGlvbkNvbnRleHRJZCA9IGV2LmNvbnRleHQuaWQ7XG4gICAgICBzdGF0ZSA9IFwiV2FpdGluZ0Zvck1haW5Db250ZXh0RGVzdHJ1Y3Rpb25cIjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBvblNjcmlwdFBhcnNlZChldjogUHJvdG9jb2wuRGVidWdnZXIuU2NyaXB0UGFyc2VkRXZlbnQpIHtcbiAgICAgIGNvbnN0IGNvbGxlY3Q6IGJvb2xlYW4gPSBmaWx0ZXIgIT09IHVuZGVmaW5lZCA/IGZpbHRlcihldikgOiB0cnVlO1xuICAgICAgaWYgKGNvbGxlY3QpIHtcbiAgICAgICAgbGV0IHNvdXJjZVR5cGU6IFNvdXJjZVR5cGUgPSBTb3VyY2VUeXBlLlNjcmlwdDtcbiAgICAgICAgaWYgKGV2LmlzTW9kdWxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBzb3VyY2VUeXBlID0gZXYuaXNNb2R1bGUgPyBTb3VyY2VUeXBlLk1vZHVsZSA6IFNvdXJjZVR5cGUuU2NyaXB0O1xuICAgICAgICB9XG4gICAgICAgIGxldCBzb3VyY2VNYXBVcmw6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGV2LnNvdXJjZU1hcFVSTCAhPT0gdW5kZWZpbmVkICYmIGV2LnNvdXJjZU1hcFVSTCAhPT0gXCJcIikge1xuICAgICAgICAgIHNvdXJjZU1hcFVybCA9IGV2LnNvdXJjZU1hcFVSTDtcbiAgICAgICAgfVxuICAgICAgICBzY3JpcHRJZFRvTWV0YS5zZXQoXG4gICAgICAgICAgZXYuc2NyaXB0SWQsXG4gICAgICAgICAge1xuICAgICAgICAgICAgc291cmNlVHlwZSxcbiAgICAgICAgICAgIHNvdXJjZU1hcFVybCxcbiAgICAgICAgICB9LFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIG9uQ29udGV4dERlc3RydWN0aW9uKGV2OiBQcm90b2NvbC5SdW50aW1lLkV4ZWN1dGlvbkNvbnRleHREZXN0cm95ZWRFdmVudCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgYXNzZXJ0KHN0YXRlID09PSBcIldhaXRpbmdGb3JNYWluQ29udGV4dERlc3RydWN0aW9uXCIpO1xuICAgICAgaWYgKGV2LmV4ZWN1dGlvbkNvbnRleHRJZCAhPT0gbWFpbkV4ZWN1dGlvbkNvbnRleHRJZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBzdGF0ZSA9IFwiV2FpdGluZ0ZvckNvdmVyYWdlXCI7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIGF3YWl0IGNsaWVudC5Qcm9maWxlci5zdG9wUHJlY2lzZUNvdmVyYWdlKCk7XG4gICAgICAgIGF3YWl0IGNsaWVudC5IZWFwUHJvZmlsZXIuY29sbGVjdEdhcmJhZ2UoKTtcbiAgICAgICAgY29uc3Qge3Jlc3VsdDogc2NyaXB0Q292c30gPSBhd2FpdCBjbGllbnQuUHJvZmlsZXIudGFrZVByZWNpc2VDb3ZlcmFnZSgpO1xuICAgICAgICBjb25zdCByZXN1bHQ6IFJpY2hTY3JpcHRDb3ZbXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IHNjcmlwdENvdiBvZiBzY3JpcHRDb3ZzKSB7XG4gICAgICAgICAgY29uc3QgbWV0YTogUGFydGlhbDxTY3JpcHRNZXRhPiB8IHVuZGVmaW5lZCA9IHNjcmlwdElkVG9NZXRhLmdldChzY3JpcHRDb3Yuc2NyaXB0SWQpO1xuICAgICAgICAgIGlmIChtZXRhID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIGB1bmRlZmluZWRgIG1lYW5zIHRoYXQgdGhlIHNjcmlwdCB3YXMgZmlsdGVyZWQgb3V0LlxuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHtzY3JpcHRTb3VyY2V9ID0gYXdhaXQgY2xpZW50LkRlYnVnZ2VyLmdldFNjcmlwdFNvdXJjZSh7c2NyaXB0SWQ6IHNjcmlwdENvdi5zY3JpcHRJZH0pO1xuICAgICAgICAgIHJlc3VsdC5wdXNoKHtcbiAgICAgICAgICAgIC4uLnNjcmlwdENvdixcbiAgICAgICAgICAgIHNvdXJjZVRleHQ6IHNjcmlwdFNvdXJjZSxcbiAgICAgICAgICAgIC4uLm1ldGEsXG4gICAgICAgICAgfSBhcyBSaWNoU2NyaXB0Q292KTtcbiAgICAgICAgfVxuICAgICAgICByZXNvbHZlKHtyZXN1bHR9KTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIHJlbW92ZUxpc3RlbmVycygpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uVGltZW91dCgpOiB2b2lkIHtcbiAgICAgIHJlbW92ZUxpc3RlbmVycygpO1xuICAgICAgcmVqZWN0KG5ldyBFcnJvcihcIlVuYWJsZSB0byBnZXQgVjggY292ZXJhZ2UgKHRpbWVvdXQpXCIpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcnMoKTogdm9pZCB7XG4gICAgICAoY2xpZW50IGFzIGFueSBhcyBldmVudHMuRXZlbnRFbWl0dGVyKS5yZW1vdmVMaXN0ZW5lcihcIlJ1bnRpbWUuZXhlY3V0aW9uQ29udGV4dENyZWF0ZWRcIiwgb25NYWluQ29udGV4dENyZWF0aW9uKTtcbiAgICAgIChjbGllbnQgYXMgYW55IGFzIGV2ZW50cy5FdmVudEVtaXR0ZXIpLnJlbW92ZUxpc3RlbmVyKFwiUnVudGltZS5leGVjdXRpb25Db250ZXh0RGVzdHJveWVkXCIsIG9uQ29udGV4dERlc3RydWN0aW9uKTtcbiAgICAgIChjbGllbnQgYXMgYW55IGFzIGV2ZW50cy5FdmVudEVtaXR0ZXIpLnJlbW92ZUxpc3RlbmVyKFwiUnVudGltZS5zY3JpcHRQYXJzZWRcIiwgb25TY3JpcHRQYXJzZWQpO1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICAoY2xpZW50IGFzIGFueSkuY2xvc2UoKTtcbiAgICB9XG4gIH0pO1xufVxuIl0sInNvdXJjZVJvb3QiOiIifQ==