UNPKG

19.6 kBJavaScriptView Raw
1import assert from "assert";
2import cri from "chrome-remote-interface";
3import { SourceType } from "istanbulize";
4import { InspectorServer } from "node-inspector-server";
5export async function spawnInspected(file, args, options) {
6 const processCovs = [];
7 const srv = await InspectorServer.open();
8 return new Promise((resolve, reject) => {
9 srv
10 .subscribe(async (ev) => {
11 try {
12 // if (ev.rootProcess !== undefined && options.onRootProcess !== undefined) {
13 // options.onRootProcess(ev.rootProcess);
14 // }
15 // const args: ReadonlyArray<string> = ["--inspect=0", ...ev.args];
16 // const proxy: ChildProcessProxy = ev.proxySpawn(args);
17 // const debuggerPort: number = await getDebuggerPort(proxy);
18 const processCov = await getCoverage(ev.url, options.filter, options.timeout);
19 processCovs.push(processCov);
20 }
21 catch (err) {
22 reject(err);
23 }
24 }, reject, () => resolve(processCovs));
25 const child = srv.spawn(file, args, options);
26 if (options.onRootProcess !== undefined) {
27 options.onRootProcess(child);
28 }
29 child.on("close", () => {
30 srv.closeSync();
31 });
32 });
33}
34async function getCoverage(url, filter, timeout) {
35 return new Promise(async (resolve, reject) => {
36 const timeoutId = timeout !== undefined ? setTimeout(onTimeout, timeout) : undefined;
37 let session;
38 let mainExecutionContextId;
39 const scriptIdToMeta = new Map();
40 let state = "WaitingForMainContext"; // TODO: enum
41 try {
42 session = await cri({ target: url });
43 session.once("Runtime.executionContextCreated", onMainContextCreation);
44 session.on("Runtime.executionContextDestroyed", onContextDestruction);
45 session.on("Debugger.scriptParsed", onScriptParsed);
46 await session.Profiler.enable();
47 await session.Profiler.startPreciseCoverage({ callCount: true, detailed: true });
48 await session.Debugger.enable();
49 await session.Runtime.enable();
50 await session.Runtime.runIfWaitingForDebugger();
51 }
52 catch (err) {
53 removeListeners();
54 reject(err);
55 }
56 function onMainContextCreation(ev) {
57 assert(state === "WaitingForMainContext");
58 mainExecutionContextId = ev.context.id;
59 state = "WaitingForMainContextDestruction";
60 }
61 function onScriptParsed(ev) {
62 const collect = filter !== undefined ? filter(ev) : true;
63 if (collect) {
64 let sourceType = SourceType.Script;
65 if (ev.isModule !== undefined) {
66 sourceType = ev.isModule ? SourceType.Module : SourceType.Script;
67 }
68 let sourceMapUrl;
69 if (ev.sourceMapURL !== undefined && ev.sourceMapURL !== "") {
70 sourceMapUrl = ev.sourceMapURL;
71 }
72 scriptIdToMeta.set(ev.scriptId, {
73 sourceType,
74 sourceMapUrl,
75 });
76 }
77 }
78 async function onContextDestruction(ev) {
79 assert(state === "WaitingForMainContextDestruction");
80 if (ev.executionContextId !== mainExecutionContextId) {
81 return;
82 }
83 state = "WaitingForCoverage";
84 try {
85 // await session.Profiler.stopPreciseCoverage();
86 await session.HeapProfiler.collectGarbage();
87 const { result: scriptCovs } = await session.Profiler.takePreciseCoverage();
88 const result = [];
89 for (const scriptCov of scriptCovs) {
90 const meta = scriptIdToMeta.get(scriptCov.scriptId);
91 if (meta === undefined) {
92 // `undefined` means that the script was filtered out.
93 continue;
94 }
95 const { scriptSource } = await session.Debugger.getScriptSource({ scriptId: scriptCov.scriptId });
96 result.push(Object.assign(Object.assign(Object.assign({}, scriptCov), { sourceText: scriptSource }), meta));
97 }
98 resolve({ result });
99 }
100 catch (err) {
101 reject(err);
102 }
103 finally {
104 removeListeners();
105 }
106 }
107 function onTimeout() {
108 removeListeners();
109 reject(new Error("Unable to get V8 coverage (timeout)"));
110 }
111 function removeListeners() {
112 if (session === undefined) {
113 // Failure before the session is created
114 return;
115 }
116 session.removeListener("Runtime.executionContextCreated", onMainContextCreation);
117 session.removeListener("Runtime.executionContextDestroyed", onContextDestruction);
118 session.removeListener("Runtime.scriptParsed", onScriptParsed);
119 if (timeoutId !== undefined) {
120 clearTimeout(timeoutId);
121 }
122 session.close();
123 }
124 });
125}
126
127//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIl9zcmMvc3Bhd24taW5zcGVjdGVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUU1QixPQUFPLEdBQUcsTUFBTSx5QkFBeUIsQ0FBQztBQUcxQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3pDLE9BQU8sRUFBbUIsZUFBZSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUF3QnpFLE1BQU0sQ0FBQyxLQUFLLFVBQVUsY0FBYyxDQUNsQyxJQUFZLEVBQ1osSUFBMkIsRUFDM0IsT0FBOEI7SUFFOUIsTUFBTSxXQUFXLEdBQXFCLEVBQUUsQ0FBQztJQUV6QyxNQUFNLEdBQUcsR0FBb0IsTUFBTSxlQUFlLENBQUMsSUFBSSxFQUFFLENBQUM7SUFFMUQsT0FBTyxJQUFJLE9BQU8sQ0FBbUIsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDdkQsR0FBRzthQUNBLFNBQVMsQ0FDUixLQUFLLEVBQUUsRUFBbUIsRUFBRSxFQUFFO1lBQzVCLElBQUk7Z0JBQ0YsNkVBQTZFO2dCQUM3RSwyQ0FBMkM7Z0JBQzNDLElBQUk7Z0JBQ0osbUVBQW1FO2dCQUNuRSx3REFBd0Q7Z0JBQ3hELDZEQUE2RDtnQkFDN0QsTUFBTSxVQUFVLEdBQW1CLE1BQU0sV0FBVyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQzlGLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7YUFDOUI7WUFBQyxPQUFPLEdBQUcsRUFBRTtnQkFDWixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7YUFDYjtRQUNILENBQUMsRUFDRCxNQUFNLEVBQ04sR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUMzQixDQUFDO1FBRUosTUFBTSxLQUFLLEdBQW9CLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFF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LE9BQU8sR0FBRyxFQUFFO2dCQUNaLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQzthQUNiO29CQUFTO2dCQUNSLGVBQWUsRUFBRSxDQUFDO2FBQ25CO1FBQ0gsQ0FBQztRQUVELFNBQVMsU0FBUztZQUNoQixlQUFlLEVBQUUsQ0FBQztZQUNsQixNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMscUNBQXFDLENBQUMsQ0FBQyxDQUFDO1FBQzNELENBQUM7UUFFRCxTQUFTLGVBQWU7WUFDdEIsSUFBSSxPQUFPLEtBQUssU0FBUyxFQUFFO2dCQUN6Qix3Q0FBd0M7Z0JBQ3hDLE9BQU87YUFDUjtZQUVBLE9BQXNDLENBQUMsY0FBYyxDQUFDLGlDQUFpQyxFQUFFLHFCQUFxQixDQUFDLENBQUM7WUFDaEgsT0FBc0MsQ0FBQyxjQUFjLENBQUMsbUNBQW1DLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztZQUNqSCxPQUFzQyxDQUFDLGNBQWMsQ0FBQyxzQkFBc0IsRUFBRSxjQUFjLENBQUMsQ0FBQztZQUMvRixJQUFJLFNBQVMsS0FBSyxTQUFTLEVBQUU7Z0JBQzNCLFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQzthQUN6QjtZQUNBLE9BQWUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUMzQixDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDIiwiZmlsZSI6InNwYXduLWluc3BlY3RlZC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFByb2Nlc3NDb3YsIFNjcmlwdENvdiB9IGZyb20gXCJAYzg4L3Y4LWNvdmVyYWdlXCI7XG5pbXBvcnQgYXNzZXJ0IGZyb20gXCJhc3NlcnRcIjtcbmltcG9ydCBjcCBmcm9tIFwiY2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IGNyaSBmcm9tIFwiY2hyb21lLXJlbW90ZS1pbnRlcmZhY2VcIjtcbmltcG9ydCBQcm90b2NvbCBmcm9tIFwiZGV2dG9vbHMtcHJvdG9jb2xcIjtcbmltcG9ydCBldmVudHMgZnJvbSBcImV2ZW50c1wiO1xuaW1wb3J0IHsgU291cmNlVHlwZSB9IGZyb20gXCJpc3RhbmJ1bGl6ZVwiO1xuaW1wb3J0IHsgSW5zcGVjdG9yQ2xpZW50LCBJbnNwZWN0b3JTZXJ2ZXIgfSBmcm9tIFwibm9kZS1pbnNwZWN0b3Itc2VydmVyXCI7XG5pbXBvcnQgeyBDb3ZlcmFnZUZpbHRlciB9IGZyb20gXCIuL2ZpbHRlclwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNjcmlwdE1ldGEge1xuICBzb3VyY2VUZXh0OiBzdHJpbmc7XG4gIHNvdXJjZVR5cGU6IFNvdXJjZVR5cGU7XG4gIHNvdXJjZU1hcFVybD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSaWNoU2NyaXB0Q292IGV4dGVuZHMgU2NyaXB0Q292LCBTY3JpcHRNZXRhIHtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSaWNoUHJvY2Vzc0NvdiBleHRlbmRzIFByb2Nlc3NDb3Yge1xuICByZXN1bHQ6IFJpY2hTY3JpcHRDb3ZbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTcGF3bkluc3BlY3RlZE9wdGlvbnMgZXh0ZW5kcyBjcC5TcGF3bk9wdGlvbnMge1xuICBmaWx0ZXI/OiBDb3ZlcmFnZUZpbHRlcjtcblxuICB0aW1lb3V0PzogbnVtYmVyO1xuXG4gIG9uUm9vdFByb2Nlc3M/KHByb2Nlc3M6IGNwLkNoaWxkUHJvY2Vzcyk6IGFueTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNwYXduSW5zcGVjdGVkKFxuICBmaWxlOiBzdHJpbmcsXG4gIGFyZ3M6IFJlYWRvbmx5QXJyYXk8c3RyaW5nPixcbiAgb3B0aW9uczogU3Bhd25JbnNwZWN0ZWRPcHRpb25zLFxuKTogUHJvbWlzZTxSaWNoUHJvY2Vzc0NvdltdPiB7XG4gIGNvbnN0IHByb2Nlc3NDb3ZzOiBSaWNoUHJvY2Vzc0NvdltdID0gW107XG5cbiAgY29uc3Qgc3J2OiBJbnNwZWN0b3JTZXJ2ZXIgPSBhd2FpdCBJbnNwZWN0b3JTZXJ2ZXIub3BlbigpO1xuXG4gIHJldHVybiBuZXcgUHJvbWlzZTxSaWNoUHJvY2Vzc0NvdltdPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgc3J2XG4gICAgICAuc3Vic2NyaWJlKFxuICAgICAgICBhc3luYyAoZXY6IEluc3BlY3RvckNsaWVudCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBpZiAoZXYucm9vdFByb2Nlc3MgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLm9uUm9vdFByb2Nlc3MgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gICBvcHRpb25zLm9uUm9vdFByb2Nlc3MoZXYucm9vdFByb2Nlc3MpO1xuICAgICAgICAgICAgLy8gfVxuICAgICAgICAgICAgLy8gY29uc3QgYXJnczogUmVhZG9ubHlBcnJheTxzdHJpbmc+ID0gW1wiLS1pbnNwZWN0PTBcIiwgLi4uZXYuYXJnc107XG4gICAgICAgICAgICAvLyBjb25zdCBwcm94eTogQ2hpbGRQcm9jZXNzUHJveHkgPSBldi5wcm94eVNwYXduKGFyZ3MpO1xuICAgICAgICAgICAgLy8gY29uc3QgZGVidWdnZXJQb3J0OiBudW1iZXIgPSBhd2FpdCBnZXREZWJ1Z2dlclBvcnQocHJveHkpO1xuICAgICAgICAgICAgY29uc3QgcHJvY2Vzc0NvdjogUmljaFByb2Nlc3NDb3YgPSBhd2FpdCBnZXRDb3ZlcmFnZShldi51cmwsIG9wdGlvbnMuZmlsdGVyLCBvcHRpb25zLnRpbWVvdXQpO1xuICAgICAgICAgICAgcHJvY2Vzc0NvdnMucHVzaChwcm9jZXNzQ292KTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgcmVqZWN0LFxuICAgICAgICAoKSA9PiByZXNvbHZlKHByb2Nlc3NDb3ZzKSxcbiAgICAgICk7XG5cbiAgICBjb25zdCBjaGlsZDogY3AuQ2hpbGRQcm9jZXNzID0gc3J2LnNwYXduKGZpbGUsIGFyZ3MsIG9wdGlvbnMpO1xuICAgIGlmIChvcHRpb25zLm9uUm9vdFByb2Nlc3MgIT09IHVuZGVmaW5lZCkge1xuICAgICAgb3B0aW9ucy5vblJvb3RQcm9jZXNzKGNoaWxkKTtcbiAgICB9XG5cbiAgICBjaGlsZC5vbihcImNsb3NlXCIsICgpID0+IHtcbiAgICAgIHNydi5jbG9zZVN5bmMoKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldENvdmVyYWdlKHVybDogc3RyaW5nLCBmaWx0ZXI/OiBDb3ZlcmFnZUZpbHRlciwgdGltZW91dD86IG51bWJlcik6IFByb21pc2U8UmljaFByb2Nlc3NDb3Y+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlPFJpY2hQcm9jZXNzQ292Pihhc3luYyAocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgdGltZW91dElkOiBOb2RlSlMuVGltZXIgfCB1bmRlZmluZWQgPSB0aW1lb3V0ICE9PSB1bmRlZmluZWQgPyBzZXRUaW1lb3V0KG9uVGltZW91dCwgdGltZW91dCkgOiB1bmRlZmluZWQ7XG4gICAgbGV0IHNlc3Npb246IGFueTtcbiAgICBsZXQgbWFpbkV4ZWN1dGlvbkNvbnRleHRJZDogUHJvdG9jb2wuUnVudGltZS5FeGVjdXRpb25Db250ZXh0SWQgfCB1bmRlZmluZWQ7XG4gICAgY29uc3Qgc2NyaXB0SWRUb01ldGE6IE1hcDxQcm90b2NvbC5SdW50aW1lLlNjcmlwdElkLCBQYXJ0aWFsPFNjcmlwdE1ldGE+PiA9IG5ldyBNYXAoKTtcbiAgICBsZXQgc3RhdGU6IHN0cmluZyA9IFwiV2FpdGluZ0Zvck1haW5Db250ZXh0XCI7IC8vIFRPRE86IGVudW1cbiAgICB0cnkge1xuICAgICAgc2Vzc2lvbiA9IGF3YWl0IGNyaSh7dGFyZ2V0OiB1cmx9KTtcbiAgICAgIChzZXNzaW9uIGFzIGFueSBhcyBldmVudHMuRXZlbnRFbWl0dGVyKS5vbmNlKFwiUnVudGltZS5leGVjdXRpb25Db250ZXh0Q3JlYXRlZFwiLCBvbk1haW5Db250ZXh0Q3JlYXRpb24pO1xuICAgICAgKHNlc3Npb24gYXMgYW55IGFzIGV2ZW50cy5FdmVudEVtaXR0ZXIpLm9uKFwiUnVudGltZS5leGVjdXRpb25Db250ZXh0RGVzdHJveWVkXCIsIG9uQ29udGV4dERlc3RydWN0aW9uKTtcbiAgICAgIChzZXNzaW9uIGFzIGFueSBhcyBldmVudHMuRXZlbnRFbWl0dGVyKS5vbihcIkRlYnVnZ2VyLnNjcmlwdFBhcnNlZFwiLCBvblNjcmlwdFBhcnNlZCk7XG5cbiAgICAgIGF3YWl0IHNlc3Npb24uUHJvZmlsZXIuZW5hYmxlKCk7XG4gICAgICBhd2FpdCBzZXNzaW9uLlByb2ZpbGVyLnN0YXJ0UHJlY2lzZUNvdmVyYWdlKHtjYWxsQ291bnQ6IHRydWUsIGRldGFpbGVkOiB0cnVlfSk7XG4gICAgICBhd2FpdCBzZXNzaW9uLkRlYnVnZ2VyLmVuYWJsZSgpO1xuICAgICAgYXdhaXQgc2Vzc2lvbi5SdW50aW1lLmVuYWJsZSgpO1xuICAgICAgYXdhaXQgc2Vzc2lvbi5SdW50aW1lLnJ1bklmV2FpdGluZ0ZvckRlYnVnZ2VyKCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICByZW1vdmVMaXN0ZW5lcnMoKTtcbiAgICAgIHJlamVjdChlcnIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uTWFpbkNvbnRleHRDcmVhdGlvbihldjogUHJvdG9jb2wuUnVudGltZS5FeGVjdXRpb25Db250ZXh0Q3JlYXRlZEV2ZW50KSB7XG4gICAgICBhc3NlcnQoc3RhdGUgPT09IFwiV2FpdGluZ0Zvck1haW5Db250ZXh0XCIpO1xuICAgICAgbWFpbkV4ZWN1dGlvbkNvbnRleHRJZCA9IGV2LmNvbnRleHQuaWQ7XG4gICAgICBzdGF0ZSA9IFwiV2FpdGluZ0Zvck1haW5Db250ZXh0RGVzdHJ1Y3Rpb25cIjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBvblNjcmlwdFBhcnNlZChldjogUHJvdG9jb2wuRGVidWdnZXIuU2NyaXB0UGFyc2VkRXZlbnQpIHtcbiAgICAgIGNvbnN0IGNvbGxlY3Q6IGJvb2xlYW4gPSBmaWx0ZXIgIT09IHVuZGVmaW5lZCA/IGZpbHRlcihldikgOiB0cnVlO1xuICAgICAgaWYgKGNvbGxlY3QpIHtcbiAgICAgICAgbGV0IHNvdXJjZVR5cGU6IFNvdXJjZVR5cGUgPSBTb3VyY2VUeXBlLlNjcmlwdDtcbiAgICAgICAgaWYgKGV2LmlzTW9kdWxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBzb3VyY2VUeXBlID0gZXYuaXNNb2R1bGUgPyBTb3VyY2VUeXBlLk1vZHVsZSA6IFNvdXJjZVR5cGUuU2NyaXB0O1xuICAgICAgICB9XG4gICAgICAgIGxldCBzb3VyY2VNYXBVcmw6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGV2LnNvdXJjZU1hcFVSTCAhPT0gdW5kZWZpbmVkICYmIGV2LnNvdXJjZU1hcFVSTCAhPT0gXCJcIikge1xuICAgICAgICAgIHNvdXJjZU1hcFVybCA9IGV2LnNvdXJjZU1hcFVSTDtcbiAgICAgICAgfVxuICAgICAgICBzY3JpcHRJZFRvTWV0YS5zZXQoXG4gICAgICAgICAgZXYuc2NyaXB0SWQsXG4gICAgICAgICAge1xuICAgICAgICAgICAgc291cmNlVHlwZSxcbiAgICAgICAgICAgIHNvdXJjZU1hcFVybCxcbiAgICAgICAgICB9LFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIG9uQ29udGV4dERlc3RydWN0aW9uKGV2OiBQcm90b2NvbC5SdW50aW1lLkV4ZWN1dGlvbkNvbnRleHREZXN0cm95ZWRFdmVudCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgYXNzZXJ0KHN0YXRlID09PSBcIldhaXRpbmdGb3JNYWluQ29udGV4dERlc3RydWN0aW9uXCIpO1xuICAgICAgaWYgKGV2LmV4ZWN1dGlvbkNvbnRleHRJZCAhPT0gbWFpbkV4ZWN1dGlvbkNvbnRleHRJZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBzdGF0ZSA9IFwiV2FpdGluZ0ZvckNvdmVyYWdlXCI7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIGF3YWl0IHNlc3Npb24uUHJvZmlsZXIuc3RvcFByZWNpc2VDb3ZlcmFnZSgpO1xuICAgICAgICBhd2FpdCBzZXNzaW9uLkhlYXBQcm9maWxlci5jb2xsZWN0R2FyYmFnZSgpO1xuICAgICAgICBjb25zdCB7cmVzdWx0OiBzY3JpcHRDb3ZzfSA9IGF3YWl0IHNlc3Npb24uUHJvZmlsZXIudGFrZVByZWNpc2VDb3ZlcmFnZSgpO1xuICAgICAgICBjb25zdCByZXN1bHQ6IFJpY2hTY3JpcHRDb3ZbXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IHNjcmlwdENvdiBvZiBzY3JpcHRDb3ZzKSB7XG4gICAgICAgICAgY29uc3QgbWV0YTogUGFydGlhbDxTY3JpcHRNZXRhPiB8IHVuZGVmaW5lZCA9IHNjcmlwdElkVG9NZXRhLmdldChzY3JpcHRDb3Yuc2NyaXB0SWQpO1xuICAgICAgICAgIGlmIChtZXRhID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIGB1bmRlZmluZWRgIG1lYW5zIHRoYXQgdGhlIHNjcmlwdCB3YXMgZmlsdGVyZWQgb3V0LlxuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHtzY3JpcHRTb3VyY2V9ID0gYXdhaXQgc2Vzc2lvbi5EZWJ1Z2dlci5nZXRTY3JpcHRTb3VyY2Uoe3NjcmlwdElkOiBzY3JpcHRDb3Yuc2NyaXB0SWR9KTtcbiAgICAgICAgICByZXN1bHQucHVzaCh7XG4gICAgICAgICAgICAuLi5zY3JpcHRDb3YsXG4gICAgICAgICAgICBzb3VyY2VUZXh0OiBzY3JpcHRTb3VyY2UsXG4gICAgICAgICAgICAuLi5tZXRhLFxuICAgICAgICAgIH0gYXMgUmljaFNjcmlwdENvdik7XG4gICAgICAgIH1cbiAgICAgICAgcmVzb2x2ZSh7cmVzdWx0fSk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICByZW1vdmVMaXN0ZW5lcnMoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBvblRpbWVvdXQoKTogdm9pZCB7XG4gICAgICByZW1vdmVMaXN0ZW5lcnMoKTtcbiAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJVbmFibGUgdG8gZ2V0IFY4IGNvdmVyYWdlICh0aW1lb3V0KVwiKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXJzKCk6IHZvaWQge1xuICAgICAgaWYgKHNlc3Npb24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAvLyBGYWlsdXJlIGJlZm9yZSB0aGUgc2Vzc2lvbiBpcyBjcmVhdGVkXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgKHNlc3Npb24gYXMgYW55IGFzIGV2ZW50cy5FdmVudEVtaXR0ZXIpLnJlbW92ZUxpc3RlbmVyKFwiUnVudGltZS5leGVjdXRpb25Db250ZXh0Q3JlYXRlZFwiLCBvbk1haW5Db250ZXh0Q3JlYXRpb24pO1xuICAgICAgKHNlc3Npb24gYXMgYW55IGFzIGV2ZW50cy5FdmVudEVtaXR0ZXIpLnJlbW92ZUxpc3RlbmVyKFwiUnVudGltZS5leGVjdXRpb25Db250ZXh0RGVzdHJveWVkXCIsIG9uQ29udGV4dERlc3RydWN0aW9uKTtcbiAgICAgIChzZXNzaW9uIGFzIGFueSBhcyBldmVudHMuRXZlbnRFbWl0dGVyKS5yZW1vdmVMaXN0ZW5lcihcIlJ1bnRpbWUuc2NyaXB0UGFyc2VkXCIsIG9uU2NyaXB0UGFyc2VkKTtcbiAgICAgIGlmICh0aW1lb3V0SWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTtcbiAgICAgIH1cbiAgICAgIChzZXNzaW9uIGFzIGFueSkuY2xvc2UoKTtcbiAgICB9XG4gIH0pO1xufVxuIl0sInNvdXJjZVJvb3QiOiIifQ==