@playwright-repl/runner 0.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/README.md +116 -0
  2. package/dist/args.d.ts +16 -0
  3. package/dist/args.d.ts.map +1 -0
  4. package/dist/args.js +48 -0
  5. package/dist/args.js.map +1 -0
  6. package/dist/bridge-utils.cjs +197 -0
  7. package/dist/bridge-utils.cjs.map +1 -0
  8. package/dist/bridge-utils.d.cts +30 -0
  9. package/dist/bridge-utils.d.cts.map +1 -0
  10. package/dist/browser.d.ts +12 -0
  11. package/dist/browser.d.ts.map +1 -0
  12. package/dist/browser.js +40 -0
  13. package/dist/browser.js.map +1 -0
  14. package/dist/bundler.d.ts +6 -0
  15. package/dist/bundler.d.ts.map +1 -0
  16. package/dist/bundler.js +32 -0
  17. package/dist/bundler.js.map +1 -0
  18. package/dist/cdpPreload.cjs +44 -0
  19. package/dist/cdpPreload.cjs.map +1 -0
  20. package/dist/cdpPreload.d.cts +11 -0
  21. package/dist/cdpPreload.d.cts.map +1 -0
  22. package/dist/chrome-extension/background.js +233485 -0
  23. package/dist/chrome-extension/background.js.map +1 -0
  24. package/dist/chrome-extension/content/picker.js +279 -0
  25. package/dist/chrome-extension/content/recorder.js +475 -0
  26. package/dist/chrome-extension/devtools/console.html +17 -0
  27. package/dist/chrome-extension/devtools/console.js +28 -0
  28. package/dist/chrome-extension/devtools/console.js.map +1 -0
  29. package/dist/chrome-extension/devtools/devtools.html +8 -0
  30. package/dist/chrome-extension/devtools/devtools.js +7 -0
  31. package/dist/chrome-extension/devtools/devtools.js.map +1 -0
  32. package/dist/chrome-extension/icons/dramaturg_icon_128.png +0 -0
  33. package/dist/chrome-extension/icons/dramaturg_icon_16.png +0 -0
  34. package/dist/chrome-extension/icons/dramaturg_icon_32.png +0 -0
  35. package/dist/chrome-extension/icons/dramaturg_icon_48.png +0 -0
  36. package/dist/chrome-extension/index.css +1333 -0
  37. package/dist/chrome-extension/index.js +12462 -0
  38. package/dist/chrome-extension/index.js.map +1 -0
  39. package/dist/chrome-extension/index2.js +27327 -0
  40. package/dist/chrome-extension/index2.js.map +1 -0
  41. package/dist/chrome-extension/manifest.json +46 -0
  42. package/dist/chrome-extension/modulepreload-polyfill.js +30 -0
  43. package/dist/chrome-extension/modulepreload-polyfill.js.map +1 -0
  44. package/dist/chrome-extension/newtab/newtab.html +202 -0
  45. package/dist/chrome-extension/offscreen/offscreen.html +6 -0
  46. package/dist/chrome-extension/offscreen/offscreen.js +54 -0
  47. package/dist/chrome-extension/offscreen/offscreen.js.map +1 -0
  48. package/dist/chrome-extension/panel/panel.html +16 -0
  49. package/dist/chrome-extension/panel/panel.js +2210 -0
  50. package/dist/chrome-extension/panel/panel.js.map +1 -0
  51. package/dist/chrome-extension/preferences/preferences.html +14 -0
  52. package/dist/chrome-extension/preferences/preferences.js +102 -0
  53. package/dist/chrome-extension/preferences/preferences.js.map +1 -0
  54. package/dist/chrome-extension/settings.js +13 -0
  55. package/dist/chrome-extension/settings.js.map +1 -0
  56. package/dist/chrome-extension/sw-debugger-core.js +1127 -0
  57. package/dist/chrome-extension/sw-debugger-core.js.map +1 -0
  58. package/dist/cli.d.ts +14 -0
  59. package/dist/cli.d.ts.map +1 -0
  60. package/dist/cli.js +43 -0
  61. package/dist/cli.js.map +1 -0
  62. package/dist/compiler/classify.d.ts +13 -0
  63. package/dist/compiler/classify.d.ts.map +1 -0
  64. package/dist/compiler/classify.js +143 -0
  65. package/dist/compiler/classify.js.map +1 -0
  66. package/dist/compiler/index.d.ts +24 -0
  67. package/dist/compiler/index.d.ts.map +1 -0
  68. package/dist/compiler/index.js +41 -0
  69. package/dist/compiler/index.js.map +1 -0
  70. package/dist/compiler/parser.d.ts +24 -0
  71. package/dist/compiler/parser.d.ts.map +1 -0
  72. package/dist/compiler/parser.js +77 -0
  73. package/dist/compiler/parser.js.map +1 -0
  74. package/dist/compiler/transform.d.ts +20 -0
  75. package/dist/compiler/transform.d.ts.map +1 -0
  76. package/dist/compiler/transform.js +36 -0
  77. package/dist/compiler/transform.js.map +1 -0
  78. package/dist/compiler.d.ts +24 -0
  79. package/dist/compiler.d.ts.map +1 -0
  80. package/dist/compiler.js +129 -0
  81. package/dist/compiler.js.map +1 -0
  82. package/dist/config.d.ts +6 -0
  83. package/dist/config.d.ts.map +1 -0
  84. package/dist/config.js +16 -0
  85. package/dist/config.js.map +1 -0
  86. package/dist/discover.d.ts +5 -0
  87. package/dist/discover.d.ts.map +1 -0
  88. package/dist/discover.js +46 -0
  89. package/dist/discover.js.map +1 -0
  90. package/dist/execute.d.ts +13 -0
  91. package/dist/execute.d.ts.map +1 -0
  92. package/dist/execute.js +281 -0
  93. package/dist/execute.js.map +1 -0
  94. package/dist/index.d.ts +3 -0
  95. package/dist/index.d.ts.map +1 -0
  96. package/dist/index.js +2 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/mode-detect.d.ts +21 -0
  99. package/dist/mode-detect.d.ts.map +1 -0
  100. package/dist/mode-detect.js +67 -0
  101. package/dist/mode-detect.js.map +1 -0
  102. package/dist/proxy-page.d.ts +32 -0
  103. package/dist/proxy-page.d.ts.map +1 -0
  104. package/dist/proxy-page.js +192 -0
  105. package/dist/proxy-page.js.map +1 -0
  106. package/dist/pw-cli.d.ts +12 -0
  107. package/dist/pw-cli.d.ts.map +1 -0
  108. package/dist/pw-cli.js +73 -0
  109. package/dist/pw-cli.js.map +1 -0
  110. package/dist/pw-launch.d.ts +15 -0
  111. package/dist/pw-launch.d.ts.map +1 -0
  112. package/dist/pw-launch.js +97 -0
  113. package/dist/pw-launch.js.map +1 -0
  114. package/dist/pw-preload.cjs +164 -0
  115. package/dist/pw-preload.cjs.map +1 -0
  116. package/dist/pw-preload.d.cts +15 -0
  117. package/dist/pw-preload.d.cts.map +1 -0
  118. package/dist/pw-repl-extension.d.ts +12 -0
  119. package/dist/pw-repl-extension.d.ts.map +1 -0
  120. package/dist/pw-repl-extension.js +100 -0
  121. package/dist/pw-repl-extension.js.map +1 -0
  122. package/dist/pw-repl.d.ts +12 -0
  123. package/dist/pw-repl.d.ts.map +1 -0
  124. package/dist/pw-repl.js +111 -0
  125. package/dist/pw-repl.js.map +1 -0
  126. package/dist/pw-worker.cjs +216 -0
  127. package/dist/pw-worker.cjs.map +1 -0
  128. package/dist/pw-worker.d.cts +13 -0
  129. package/dist/pw-worker.d.cts.map +1 -0
  130. package/dist/pw-worker.d.ts +11 -0
  131. package/dist/pw-worker.d.ts.map +1 -0
  132. package/dist/pw-worker.js +51 -0
  133. package/dist/pw-worker.js.map +1 -0
  134. package/dist/run-test.d.ts +22 -0
  135. package/dist/run-test.d.ts.map +1 -0
  136. package/dist/run-test.js +358 -0
  137. package/dist/run-test.js.map +1 -0
  138. package/dist/runner.d.ts +10 -0
  139. package/dist/runner.d.ts.map +1 -0
  140. package/dist/runner.js +82 -0
  141. package/dist/runner.js.map +1 -0
  142. package/dist/shim/alias.d.ts +11 -0
  143. package/dist/shim/alias.d.ts.map +1 -0
  144. package/dist/shim/alias.js +24 -0
  145. package/dist/shim/alias.js.map +1 -0
  146. package/dist/shim/framework.d.ts +11 -0
  147. package/dist/shim/framework.d.ts.map +1 -0
  148. package/dist/shim/framework.js +11 -0
  149. package/dist/shim/framework.js.map +1 -0
  150. package/dist/shim/test-runner-node.d.ts +49 -0
  151. package/dist/shim/test-runner-node.d.ts.map +1 -0
  152. package/dist/shim/test-runner-node.js +191 -0
  153. package/dist/shim/test-runner-node.js.map +1 -0
  154. package/dist/shim/test-runner.d.ts +44 -0
  155. package/dist/shim/test-runner.d.ts.map +1 -0
  156. package/dist/shim/test-runner.js +181 -0
  157. package/dist/shim/test-runner.js.map +1 -0
  158. package/dist/types.d.ts +41 -0
  159. package/dist/types.d.ts.map +1 -0
  160. package/dist/types.js +2 -0
  161. package/dist/types.js.map +1 -0
  162. package/package.json +37 -0
@@ -0,0 +1,279 @@
1
+ "use strict";
2
+ (() => {
3
+ // src/content/locator.ts
4
+ var IMPLICIT_ROLES = {
5
+ A: (el) => el.hasAttribute("href") ? "link" : null,
6
+ BUTTON: "button",
7
+ H1: "heading",
8
+ H2: "heading",
9
+ H3: "heading",
10
+ H4: "heading",
11
+ H5: "heading",
12
+ H6: "heading",
13
+ INPUT: (el) => {
14
+ const type = el.type.toLowerCase();
15
+ if (type === "checkbox") return "checkbox";
16
+ if (type === "radio") return "radio";
17
+ if (type === "submit" || type === "reset" || type === "button") return "button";
18
+ if (type === "hidden") return null;
19
+ return "textbox";
20
+ },
21
+ TEXTAREA: "textbox",
22
+ SELECT: "combobox",
23
+ IMG: "img",
24
+ NAV: "navigation",
25
+ MAIN: "main",
26
+ HEADER: "banner",
27
+ FOOTER: "contentinfo",
28
+ UL: "list",
29
+ OL: "list",
30
+ LI: "listitem",
31
+ TABLE: "table",
32
+ TR: "row",
33
+ TH: "columnheader",
34
+ TD: "cell",
35
+ FORM: "form",
36
+ DIALOG: "dialog",
37
+ ARTICLE: "article"
38
+ };
39
+ function getImplicitRole(el) {
40
+ const explicit = el.getAttribute("role");
41
+ if (explicit && explicit !== "none" && explicit !== "presentation") return explicit;
42
+ const entry = IMPLICIT_ROLES[el.tagName];
43
+ if (!entry) return null;
44
+ return typeof entry === "function" ? entry(el) : entry;
45
+ }
46
+ function getAccessibleName(el) {
47
+ const ariaLabel = el.getAttribute("aria-label");
48
+ if (ariaLabel) return ariaLabel.trim();
49
+ const labelledBy = el.getAttribute("aria-labelledby");
50
+ if (labelledBy) {
51
+ const parts = labelledBy.split(/\s+/).map((id) => document.getElementById(id)?.textContent?.trim()).filter(Boolean);
52
+ if (parts.length) return parts.join(" ");
53
+ }
54
+ if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) {
55
+ const label = getLabel(el);
56
+ if (label) return label;
57
+ }
58
+ const role = getImplicitRole(el);
59
+ const NAME_FROM_CONTENT = /* @__PURE__ */ new Set([
60
+ "button",
61
+ "link",
62
+ "heading",
63
+ "tab",
64
+ "menuitem",
65
+ "menuitemcheckbox",
66
+ "menuitemradio",
67
+ "option",
68
+ "radio",
69
+ "checkbox",
70
+ "switch",
71
+ "cell",
72
+ "columnheader",
73
+ "rowheader",
74
+ "tooltip",
75
+ "treeitem"
76
+ ]);
77
+ if (role && NAME_FROM_CONTENT.has(role)) {
78
+ const text = (el.textContent || "").trim();
79
+ if (text && text.length <= 80) return text;
80
+ }
81
+ if (el.tagName === "IMG") {
82
+ const alt = el.getAttribute("alt");
83
+ if (alt) return alt.trim();
84
+ }
85
+ return "";
86
+ }
87
+ function getLabel(el) {
88
+ if (el.id) {
89
+ const label = document.querySelector(`label[for="${CSS.escape(el.id)}"]`);
90
+ if (label) return (label.textContent || "").trim();
91
+ }
92
+ const parentLabel = el.closest("label");
93
+ if (parentLabel) {
94
+ const clone = parentLabel.cloneNode(true);
95
+ clone.querySelectorAll("input,textarea,select").forEach((c) => c.remove());
96
+ const text = (clone.textContent || "").trim();
97
+ if (text) return text;
98
+ }
99
+ return "";
100
+ }
101
+ var CONTAINER_ROLES = /* @__PURE__ */ new Set(["listitem", "row", "article", "group"]);
102
+ function getContextText(ancestor, exclude) {
103
+ function findText(node) {
104
+ for (const child of node.childNodes) {
105
+ if (child === exclude) continue;
106
+ if (child.nodeType === Node.ELEMENT_NODE && child.contains(exclude)) {
107
+ const inner = findText(child);
108
+ if (inner) return inner;
109
+ continue;
110
+ }
111
+ const text = (child.textContent || "").trim();
112
+ if (text && text.length <= 50) return text;
113
+ }
114
+ return "";
115
+ }
116
+ return findText(ancestor);
117
+ }
118
+ function findContainerAncestor(el) {
119
+ let current = el.parentElement;
120
+ while (current && current !== document.body && current !== document.documentElement) {
121
+ const role = getImplicitRole(current);
122
+ if (role && CONTAINER_ROLES.has(role)) return { ancestor: current, role };
123
+ current = current.parentElement;
124
+ }
125
+ return null;
126
+ }
127
+ function tryAncestorContext(el, role, name, matches) {
128
+ const container = findContainerAncestor(el);
129
+ if (!container) return null;
130
+ const contextText = getContextText(container.ancestor, el);
131
+ if (!contextText || contextText.length > 50) return null;
132
+ let count = 0;
133
+ for (const match of matches) {
134
+ const mc = findContainerAncestor(match);
135
+ if (!mc || mc.role !== container.role) continue;
136
+ if ((mc.ancestor.textContent || "").includes(contextText)) {
137
+ count++;
138
+ if (count > 1) return null;
139
+ }
140
+ }
141
+ if (count !== 1) return null;
142
+ return `getByRole(${escapeString(container.role)}).filter({ hasText: ${escapeString(contextText)} }).getByRole(${escapeString(role)}, { name: ${escapeString(name)} })`;
143
+ }
144
+ function findByRoleAndName(role, name) {
145
+ const matches = [];
146
+ for (const el of document.querySelectorAll("*")) {
147
+ if (getImplicitRole(el) === role && getAccessibleName(el) === name && el.checkVisibility?.() !== false)
148
+ matches.push(el);
149
+ }
150
+ return matches;
151
+ }
152
+ function escapeString(s) {
153
+ if (!s.includes("'")) return `'${s}'`;
154
+ if (!s.includes('"')) return `"${s}"`;
155
+ return `'${s.replace(/'/g, "\\'")}'`;
156
+ }
157
+ function generateLocator(el) {
158
+ const testId = el.getAttribute("data-testid") || el.getAttribute("data-test-id");
159
+ if (testId) return `getByTestId(${escapeString(testId)})`;
160
+ const role = getImplicitRole(el);
161
+ const name = getAccessibleName(el);
162
+ if (role && name) {
163
+ const matches = findByRoleAndName(role, name);
164
+ if (matches.length > 1) {
165
+ const ancestorLocator = tryAncestorContext(el, role, name, matches);
166
+ if (ancestorLocator) return ancestorLocator;
167
+ const base = `getByRole(${escapeString(role)}, { name: ${escapeString(name)}, exact: true })`;
168
+ const idx = matches.indexOf(el);
169
+ return idx === 0 ? base + ".first()" : base + `.nth(${idx})`;
170
+ }
171
+ return `getByRole(${escapeString(role)}, { name: ${escapeString(name)} })`;
172
+ }
173
+ if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) {
174
+ const label = getLabel(el);
175
+ if (label) return `getByLabel(${escapeString(label)})`;
176
+ }
177
+ const placeholder = el.getAttribute("placeholder");
178
+ if (placeholder) return `getByPlaceholder(${escapeString(placeholder)})`;
179
+ const alt = el.getAttribute("alt");
180
+ if (alt && ["IMG", "APPLET", "AREA", "INPUT"].includes(el.tagName))
181
+ return `getByAltText(${escapeString(alt)})`;
182
+ const title = el.getAttribute("title");
183
+ if (title) return `getByTitle(${escapeString(title)})`;
184
+ const text = (el.textContent || "").trim();
185
+ if (text && text.length <= 80) return `getByText(${escapeString(text)})`;
186
+ if (role) return `getByRole(${escapeString(role)})`;
187
+ return `locator(${escapeString(buildCssSelector(el))})`;
188
+ }
189
+ function buildCssSelector(el) {
190
+ const tag = el.tagName.toLowerCase();
191
+ if (el.id) return `${tag}#${CSS.escape(el.id)}`;
192
+ const classes = [...el.classList].slice(0, 2).map((c) => "." + CSS.escape(c)).join("");
193
+ if (classes) return `${tag}${classes}`;
194
+ return tag;
195
+ }
196
+
197
+ // src/content/picker.ts
198
+ function getOuterHtml(el) {
199
+ const outer = el.outerHTML;
200
+ if (outer.length <= 200) return outer;
201
+ const tag = el.tagName.toLowerCase();
202
+ const open = outer.slice(0, outer.indexOf(">") + 1);
203
+ return `${open}...</${tag}>`;
204
+ }
205
+ function gatherInfo(el) {
206
+ const rect = el.getBoundingClientRect();
207
+ const attrs = {};
208
+ for (const a of el.attributes) attrs[a.name] = a.value;
209
+ return {
210
+ locator: generateLocator(el),
211
+ tag: el.tagName.toLowerCase(),
212
+ text: (el.textContent || "").trim().slice(0, 200),
213
+ html: getOuterHtml(el),
214
+ attributes: attrs,
215
+ visible: rect.width > 0 && rect.height > 0,
216
+ enabled: !el.disabled,
217
+ box: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },
218
+ value: el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement ? el.value : void 0,
219
+ checked: el instanceof HTMLInputElement && (el.type === "checkbox" || el.type === "radio") ? el.checked : void 0
220
+ };
221
+ }
222
+ var highlight = document.createElement("div");
223
+ highlight.style.cssText = "position:fixed;pointer-events:none;z-index:2147483646;border:2px solid #6fa8dc;background:rgba(111,168,220,0.2);display:none;box-sizing:border-box;";
224
+ var currentElement = null;
225
+ function onMouseMove(e) {
226
+ const target = document.elementFromPoint(e.clientX, e.clientY);
227
+ if (!target || target === highlight) return;
228
+ if (target === currentElement) return;
229
+ currentElement = target;
230
+ const rect = target.getBoundingClientRect();
231
+ highlight.style.display = "block";
232
+ highlight.style.left = rect.left + "px";
233
+ highlight.style.top = rect.top + "px";
234
+ highlight.style.width = rect.width + "px";
235
+ highlight.style.height = rect.height + "px";
236
+ }
237
+ function onClick(e) {
238
+ e.preventDefault();
239
+ e.stopPropagation();
240
+ e.stopImmediatePropagation();
241
+ if (!currentElement) return;
242
+ const info = gatherInfo(currentElement);
243
+ const pickId = Math.random().toString(36).slice(2);
244
+ currentElement.setAttribute("data-pw-pick-id", pickId);
245
+ cleanup();
246
+ chrome.runtime.sendMessage({ type: "element-picked-raw", pickId, info });
247
+ }
248
+ function onKeyDown(e) {
249
+ if (e.key === "Escape") {
250
+ e.preventDefault();
251
+ e.stopImmediatePropagation();
252
+ cleanup();
253
+ chrome.runtime.sendMessage({ type: "pick-cancelled" });
254
+ }
255
+ }
256
+ function cleanup() {
257
+ window.__pw_picker_active = false;
258
+ currentElement = null;
259
+ highlight.remove();
260
+ document.removeEventListener("mousemove", onMouseMove, true);
261
+ document.removeEventListener("click", onClick, true);
262
+ document.removeEventListener("keydown", onKeyDown, true);
263
+ chrome.runtime.onMessage.removeListener(onMessage);
264
+ }
265
+ function onMessage(msg) {
266
+ if (msg.type === "pick-stop") cleanup();
267
+ }
268
+ function init() {
269
+ if (window.__pw_picker_active) return;
270
+ window.__pw_picker_active = true;
271
+ document.documentElement.appendChild(highlight);
272
+ chrome.runtime.onMessage.addListener(onMessage);
273
+ document.addEventListener("mousemove", onMouseMove, true);
274
+ document.addEventListener("click", onClick, true);
275
+ document.addEventListener("keydown", onKeyDown, true);
276
+ }
277
+ init();
278
+ })();
279
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL2NvbnRlbnQvbG9jYXRvci50cyIsICJzcmMvY29udGVudC9waWNrZXIudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxyXG4gKiBTaGFyZWQgbG9jYXRvciBnZW5lcmF0aW9uIHV0aWxpdGllcy5cclxuICogVXNlZCBieSBib3RoIHBpY2tlci50cyBhbmQgcmVjb3JkZXIudHMgY29udGVudCBzY3JpcHRzLlxyXG4gKiBWaXRlIGlubGluZXMgdGhpcyBpbnRvIGVhY2ggY29udGVudCBzY3JpcHQgYnVuZGxlIFx1MjAxNCBubyBydW50aW1lIG1vZHVsZSBsb2FkaW5nLlxyXG4gKi9cclxuXHJcbi8vIFx1MjUwMFx1MjUwMFx1MjUwMCBJbXBsaWNpdCBBUklBIHJvbGVzIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxyXG5cclxuZXhwb3J0IGNvbnN0IElNUExJQ0lUX1JPTEVTOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCAoKGVsOiBFbGVtZW50KSA9PiBzdHJpbmcgfCBudWxsKT4gPSB7XHJcbiAgICBBOiAoZWwpID0+IGVsLmhhc0F0dHJpYnV0ZSgnaHJlZicpID8gJ2xpbmsnIDogbnVsbCxcclxuICAgIEJVVFRPTjogJ2J1dHRvbicsXHJcbiAgICBIMTogJ2hlYWRpbmcnLCBIMjogJ2hlYWRpbmcnLCBIMzogJ2hlYWRpbmcnLCBINDogJ2hlYWRpbmcnLCBINTogJ2hlYWRpbmcnLCBINjogJ2hlYWRpbmcnLFxyXG4gICAgSU5QVVQ6IChlbCkgPT4ge1xyXG4gICAgICAgIGNvbnN0IHR5cGUgPSAoZWwgYXMgSFRNTElucHV0RWxlbWVudCkudHlwZS50b0xvd2VyQ2FzZSgpO1xyXG4gICAgICAgIGlmICh0eXBlID09PSAnY2hlY2tib3gnKSByZXR1cm4gJ2NoZWNrYm94JztcclxuICAgICAgICBpZiAodHlwZSA9PT0gJ3JhZGlvJykgcmV0dXJuICdyYWRpbyc7XHJcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdWJtaXQnIHx8IHR5cGUgPT09ICdyZXNldCcgfHwgdHlwZSA9PT0gJ2J1dHRvbicpIHJldHVybiAnYnV0dG9uJztcclxuICAgICAgICBpZiAodHlwZSA9PT0gJ2hpZGRlbicpIHJldHVybiBudWxsO1xyXG4gICAgICAgIHJldHVybiAndGV4dGJveCc7XHJcbiAgICB9LFxyXG4gICAgVEVYVEFSRUE6ICd0ZXh0Ym94JyxcclxuICAgIFNFTEVDVDogJ2NvbWJvYm94JyxcclxuICAgIElNRzogJ2ltZycsXHJcbiAgICBOQVY6ICduYXZpZ2F0aW9uJyxcclxuICAgIE1BSU46ICdtYWluJyxcclxuICAgIEhFQURFUjogJ2Jhbm5lcicsXHJcbiAgICBGT09URVI6ICdjb250ZW50aW5mbycsXHJcbiAgICBVTDogJ2xpc3QnLCBPTDogJ2xpc3QnLFxyXG4gICAgTEk6ICdsaXN0aXRlbScsXHJcbiAgICBUQUJMRTogJ3RhYmxlJyxcclxuICAgIFRSOiAncm93JyxcclxuICAgIFRIOiAnY29sdW1uaGVhZGVyJyxcclxuICAgIFREOiAnY2VsbCcsXHJcbiAgICBGT1JNOiAnZm9ybScsXHJcbiAgICBESUFMT0c6ICdkaWFsb2cnLFxyXG4gICAgQVJUSUNMRTogJ2FydGljbGUnLFxyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGdldEltcGxpY2l0Um9sZShlbDogRWxlbWVudCk6IHN0cmluZyB8IG51bGwge1xyXG4gICAgY29uc3QgZXhwbGljaXQgPSBlbC5nZXRBdHRyaWJ1dGUoJ3JvbGUnKTtcclxuICAgIGlmIChleHBsaWNpdCAmJiBleHBsaWNpdCAhPT0gJ25vbmUnICYmIGV4cGxpY2l0ICE9PSAncHJlc2VudGF0aW9uJykgcmV0dXJuIGV4cGxpY2l0O1xyXG4gICAgY29uc3QgZW50cnkgPSBJTVBMSUNJVF9ST0xFU1tlbC50YWdOYW1lXTtcclxuICAgIGlmICghZW50cnkpIHJldHVybiBudWxsO1xyXG4gICAgcmV0dXJuIHR5cGVvZiBlbnRyeSA9PT0gJ2Z1bmN0aW9uJyA/IGVudHJ5KGVsKSA6IGVudHJ5O1xyXG59XHJcblxyXG4vLyBcdTI1MDBcdTI1MDBcdTI1MDAgQWNjZXNzaWJsZSBuYW1lIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGdldEFjY2Vzc2libGVOYW1lKGVsOiBFbGVtZW50KTogc3RyaW5nIHtcclxuICAgIC8vIGFyaWEtbGFiZWxcclxuICAgIGNvbnN0IGFyaWFMYWJlbCA9IGVsLmdldEF0dHJpYnV0ZSgnYXJpYS1sYWJlbCcpO1xyXG4gICAgaWYgKGFyaWFMYWJlbCkgcmV0dXJuIGFyaWFMYWJlbC50cmltKCk7XHJcblxyXG4gICAgLy8gYXJpYS1sYWJlbGxlZGJ5XHJcbiAgICBjb25zdCBsYWJlbGxlZEJ5ID0gZWwuZ2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsbGVkYnknKTtcclxuICAgIGlmIChsYWJlbGxlZEJ5KSB7XHJcbiAgICAgICAgY29uc3QgcGFydHMgPSBsYWJlbGxlZEJ5LnNwbGl0KC9cXHMrLykubWFwKGlkID0+IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKT8udGV4dENvbnRlbnQ/LnRyaW0oKSkuZmlsdGVyKEJvb2xlYW4pO1xyXG4gICAgICAgIGlmIChwYXJ0cy5sZW5ndGgpIHJldHVybiBwYXJ0cy5qb2luKCcgJyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRm9yIGlucHV0czogYXNzb2NpYXRlZCA8bGFiZWw+XHJcbiAgICBpZiAoZWwgaW5zdGFuY2VvZiBIVE1MSW5wdXRFbGVtZW50IHx8IGVsIGluc3RhbmNlb2YgSFRNTFRleHRBcmVhRWxlbWVudCB8fCBlbCBpbnN0YW5jZW9mIEhUTUxTZWxlY3RFbGVtZW50KSB7XHJcbiAgICAgICAgY29uc3QgbGFiZWwgPSBnZXRMYWJlbChlbCk7XHJcbiAgICAgICAgaWYgKGxhYmVsKSByZXR1cm4gbGFiZWw7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRm9yIHJvbGVzIHRoYXQgZ2V0IG5hbWUgZnJvbSBjb250ZW50IChBUklBIFwibmFtZSBmcm9tIGNvbnRlbnRcIiByb2xlcylcclxuICAgIGNvbnN0IHJvbGUgPSBnZXRJbXBsaWNpdFJvbGUoZWwpO1xyXG4gICAgY29uc3QgTkFNRV9GUk9NX0NPTlRFTlQgPSBuZXcgU2V0KFtcclxuICAgICAgICAnYnV0dG9uJywgJ2xpbmsnLCAnaGVhZGluZycsICd0YWInLCAnbWVudWl0ZW0nLCAnbWVudWl0ZW1jaGVja2JveCcsXHJcbiAgICAgICAgJ21lbnVpdGVtcmFkaW8nLCAnb3B0aW9uJywgJ3JhZGlvJywgJ2NoZWNrYm94JywgJ3N3aXRjaCcsICdjZWxsJyxcclxuICAgICAgICAnY29sdW1uaGVhZGVyJywgJ3Jvd2hlYWRlcicsICd0b29sdGlwJywgJ3RyZWVpdGVtJyxcclxuICAgIF0pO1xyXG4gICAgaWYgKHJvbGUgJiYgTkFNRV9GUk9NX0NPTlRFTlQuaGFzKHJvbGUpKSB7XHJcbiAgICAgICAgY29uc3QgdGV4dCA9IChlbC50ZXh0Q29udGVudCB8fCAnJykudHJpbSgpO1xyXG4gICAgICAgIGlmICh0ZXh0ICYmIHRleHQubGVuZ3RoIDw9IDgwKSByZXR1cm4gdGV4dDtcclxuICAgIH1cclxuXHJcbiAgICAvLyBhbHQgZm9yIGltYWdlc1xyXG4gICAgaWYgKGVsLnRhZ05hbWUgPT09ICdJTUcnKSB7XHJcbiAgICAgICAgY29uc3QgYWx0ID0gZWwuZ2V0QXR0cmlidXRlKCdhbHQnKTtcclxuICAgICAgICBpZiAoYWx0KSByZXR1cm4gYWx0LnRyaW0oKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gJyc7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRMYWJlbChlbDogSFRNTElucHV0RWxlbWVudCB8IEhUTUxUZXh0QXJlYUVsZW1lbnQgfCBIVE1MU2VsZWN0RWxlbWVudCk6IHN0cmluZyB7XHJcbiAgICAvLyBFeHBsaWNpdCBsYWJlbCB2aWEgZm9yIGF0dHJpYnV0ZVxyXG4gICAgaWYgKGVsLmlkKSB7XHJcbiAgICAgICAgY29uc3QgbGFiZWwgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGBsYWJlbFtmb3I9XCIke0NTUy5lc2NhcGUoZWwuaWQpfVwiXWApO1xyXG4gICAgICAgIGlmIChsYWJlbCkgcmV0dXJuIChsYWJlbC50ZXh0Q29udGVudCB8fCAnJykudHJpbSgpO1xyXG4gICAgfVxyXG4gICAgLy8gSW1wbGljaXQgbGFiZWwgKGFuY2VzdG9yKVxyXG4gICAgY29uc3QgcGFyZW50TGFiZWwgPSBlbC5jbG9zZXN0KCdsYWJlbCcpO1xyXG4gICAgaWYgKHBhcmVudExhYmVsKSB7XHJcbiAgICAgICAgLy8gR2V0IGxhYmVsIHRleHQgZXhjbHVkaW5nIHRoZSBpbnB1dCdzIG93biB0ZXh0XHJcbiAgICAgICAgY29uc3QgY2xvbmUgPSBwYXJlbnRMYWJlbC5jbG9uZU5vZGUodHJ1ZSkgYXMgSFRNTEVsZW1lbnQ7XHJcbiAgICAgICAgY2xvbmUucXVlcnlTZWxlY3RvckFsbCgnaW5wdXQsdGV4dGFyZWEsc2VsZWN0JykuZm9yRWFjaChjID0+IGMucmVtb3ZlKCkpO1xyXG4gICAgICAgIGNvbnN0IHRleHQgPSAoY2xvbmUudGV4dENvbnRlbnQgfHwgJycpLnRyaW0oKTtcclxuICAgICAgICBpZiAodGV4dCkgcmV0dXJuIHRleHQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gJyc7XHJcbn1cclxuXHJcbi8vIFx1MjUwMFx1MjUwMFx1MjUwMCBBbmNlc3RvciBjb250ZXh0IGRpc2FtYmlndWF0aW9uIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxyXG5cclxuLyoqIENvbnRhaW5lciByb2xlcyBzdWl0YWJsZSBmb3IgYW5jZXN0b3ItY29udGV4dCBkaXNhbWJpZ3VhdGlvbi4gKi9cclxuY29uc3QgQ09OVEFJTkVSX1JPTEVTID0gbmV3IFNldChbJ2xpc3RpdGVtJywgJ3JvdycsICdhcnRpY2xlJywgJ2dyb3VwJ10pO1xyXG5cclxuLyoqXHJcbiAqIEZpbmQgZGlzdGluY3RpdmUgdGV4dCBpbiBhbiBhbmNlc3RvciB0aGF0IGRvZXNuJ3QgY29tZSBmcm9tIHRoZSBleGNsdWRlZCBlbGVtZW50J3Mgc3VidHJlZS5cclxuICogUmV0dXJucyB0ZXh0IGZyb20gdGhlIGZpcnN0IGNoaWxkIHN1YnRyZWUgdGhhdCBkb2Vzbid0IGNvbnRhaW4gdGhlIGV4Y2x1ZGVkIGVsZW1lbnQsXHJcbiAqIHJlY3Vyc2luZyBpbnRvIHdyYXBwZXJzIHRoYXQgZG8gY29udGFpbiBpdC4gVGhpcyBlbnN1cmVzIHRoZSByZXR1cm5lZCB0ZXh0IGlzIGFcclxuICogY29udGlndW91cyBzdWJzdHJpbmcgb2YgdGhlIGFuY2VzdG9yJ3MgZnVsbCB0ZXh0Q29udGVudCAobmVlZGVkIGZvciBoYXNUZXh0IG1hdGNoaW5nKS5cclxuICovXHJcbmZ1bmN0aW9uIGdldENvbnRleHRUZXh0KGFuY2VzdG9yOiBFbGVtZW50LCBleGNsdWRlOiBFbGVtZW50KTogc3RyaW5nIHtcclxuICAgIGZ1bmN0aW9uIGZpbmRUZXh0KG5vZGU6IE5vZGUpOiBzdHJpbmcge1xyXG4gICAgICAgIGZvciAoY29uc3QgY2hpbGQgb2Ygbm9kZS5jaGlsZE5vZGVzKSB7XHJcbiAgICAgICAgICAgIGlmIChjaGlsZCA9PT0gZXhjbHVkZSkgY29udGludWU7XHJcbiAgICAgICAgICAgIGlmIChjaGlsZC5ub2RlVHlwZSA9PT0gTm9kZS5FTEVNRU5UX05PREUgJiYgKGNoaWxkIGFzIEVsZW1lbnQpLmNvbnRhaW5zKGV4Y2x1ZGUpKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBUaGlzIHN1YnRyZWUgY29udGFpbnMgdGhlIHRhcmdldCBcdTIwMTQgcmVjdXJzZSB0byBmaW5kIG5vbi10YXJnZXQgc2libGluZ3NcclxuICAgICAgICAgICAgICAgIGNvbnN0IGlubmVyID0gZmluZFRleHQoY2hpbGQpO1xyXG4gICAgICAgICAgICAgICAgaWYgKGlubmVyKSByZXR1cm4gaW5uZXI7XHJcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjb25zdCB0ZXh0ID0gKGNoaWxkLnRleHRDb250ZW50IHx8ICcnKS50cmltKCk7XHJcbiAgICAgICAgICAgIGlmICh0ZXh0ICYmIHRleHQubGVuZ3RoIDw9IDUwKSByZXR1cm4gdGV4dDtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuICcnO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGZpbmRUZXh0KGFuY2VzdG9yKTtcclxufVxyXG5cclxuLyoqIFdhbGsgdXAgZnJvbSBlbCB0byBmaW5kIG5lYXJlc3QgYW5jZXN0b3Igd2l0aCBhIGNvbnRhaW5lciByb2xlLiAqL1xyXG5mdW5jdGlvbiBmaW5kQ29udGFpbmVyQW5jZXN0b3IoZWw6IEVsZW1lbnQpOiB7IGFuY2VzdG9yOiBFbGVtZW50OyByb2xlOiBzdHJpbmcgfSB8IG51bGwge1xyXG4gICAgbGV0IGN1cnJlbnQgPSBlbC5wYXJlbnRFbGVtZW50O1xyXG4gICAgd2hpbGUgKGN1cnJlbnQgJiYgY3VycmVudCAhPT0gZG9jdW1lbnQuYm9keSAmJiBjdXJyZW50ICE9PSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpIHtcclxuICAgICAgICBjb25zdCByb2xlID0gZ2V0SW1wbGljaXRSb2xlKGN1cnJlbnQpO1xyXG4gICAgICAgIGlmIChyb2xlICYmIENPTlRBSU5FUl9ST0xFUy5oYXMocm9sZSkpIHJldHVybiB7IGFuY2VzdG9yOiBjdXJyZW50LCByb2xlIH07XHJcbiAgICAgICAgY3VycmVudCA9IGN1cnJlbnQucGFyZW50RWxlbWVudDtcclxuICAgIH1cclxuICAgIHJldHVybiBudWxsO1xyXG59XHJcblxyXG4vKipcclxuICogVHJ5IHRvIGRpc2FtYmlndWF0ZSB1c2luZyBhbmNlc3RvciBjb250ZXh0LlxyXG4gKiBSZXR1cm5zIGEgY2hhaW5lZCBsb2NhdG9yIGxpa2U6XHJcbiAqICAgZ2V0QnlSb2xlKCdsaXN0aXRlbScpLmZpbHRlcih7IGhhc1RleHQ6ICdyZWFkaW5nJyB9KS5nZXRCeVJvbGUoJ2J1dHRvbicsIHsgbmFtZTogJ0RlbGV0ZScgfSlcclxuICogb3IgbnVsbCBpZiBhbmNlc3RvciBjb250ZXh0IGRvZXNuJ3QgcHJvZHVjZSBhIHVuaXF1ZSByZXN1bHQuXHJcbiAqL1xyXG5mdW5jdGlvbiB0cnlBbmNlc3RvckNvbnRleHQoZWw6IEVsZW1lbnQsIHJvbGU6IHN0cmluZywgbmFtZTogc3RyaW5nLCBtYXRjaGVzOiBFbGVtZW50W10pOiBzdHJpbmcgfCBudWxsIHtcclxuICAgIGNvbnN0IGNvbnRhaW5lciA9IGZpbmRDb250YWluZXJBbmNlc3RvcihlbCk7XHJcbiAgICBpZiAoIWNvbnRhaW5lcikgcmV0dXJuIG51bGw7XHJcblxyXG4gICAgY29uc3QgY29udGV4dFRleHQgPSBnZXRDb250ZXh0VGV4dChjb250YWluZXIuYW5jZXN0b3IsIGVsKTtcclxuICAgIGlmICghY29udGV4dFRleHQgfHwgY29udGV4dFRleHQubGVuZ3RoID4gNTApIHJldHVybiBudWxsO1xyXG5cclxuICAgIC8vIFZlcmlmeSB1bmlxdWVuZXNzOiBvbmx5IG9uZSBtYXRjaCdzIGNvbnRhaW5lciBhbmNlc3RvciBzaG91bGQgY29udGFpbiB0aGlzIHRleHRcclxuICAgIGxldCBjb3VudCA9IDA7XHJcbiAgICBmb3IgKGNvbnN0IG1hdGNoIG9mIG1hdGNoZXMpIHtcclxuICAgICAgICBjb25zdCBtYyA9IGZpbmRDb250YWluZXJBbmNlc3RvcihtYXRjaCk7XHJcbiAgICAgICAgaWYgKCFtYyB8fCBtYy5yb2xlICE9PSBjb250YWluZXIucm9sZSkgY29udGludWU7XHJcbiAgICAgICAgaWYgKChtYy5hbmNlc3Rvci50ZXh0Q29udGVudCB8fCAnJykuaW5jbHVkZXMoY29udGV4dFRleHQpKSB7XHJcbiAgICAgICAgICAgIGNvdW50Kys7XHJcbiAgICAgICAgICAgIGlmIChjb3VudCA+IDEpIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGlmIChjb3VudCAhPT0gMSkgcmV0dXJuIG51bGw7XHJcblxyXG4gICAgcmV0dXJuIGBnZXRCeVJvbGUoJHtlc2NhcGVTdHJpbmcoY29udGFpbmVyLnJvbGUpfSkuZmlsdGVyKHsgaGFzVGV4dDogJHtlc2NhcGVTdHJpbmcoY29udGV4dFRleHQpfSB9KS5nZXRCeVJvbGUoJHtlc2NhcGVTdHJpbmcocm9sZSl9LCB7IG5hbWU6ICR7ZXNjYXBlU3RyaW5nKG5hbWUpfSB9KWA7XHJcbn1cclxuXHJcbi8vIFx1MjUwMFx1MjUwMFx1MjUwMCBMb2NhdG9yIGRpc2FtYmlndWF0aW9uIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRCeVJvbGVBbmROYW1lKHJvbGU6IHN0cmluZywgbmFtZTogc3RyaW5nKTogRWxlbWVudFtdIHtcclxuICAgIGNvbnN0IG1hdGNoZXM6IEVsZW1lbnRbXSA9IFtdO1xyXG4gICAgZm9yIChjb25zdCBlbCBvZiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcqJykpIHtcclxuICAgICAgICBpZiAoZ2V0SW1wbGljaXRSb2xlKGVsKSA9PT0gcm9sZSAmJiBnZXRBY2Nlc3NpYmxlTmFtZShlbCkgPT09IG5hbWVcclxuICAgICAgICAgICAgJiYgKGVsIGFzIEhUTUxFbGVtZW50KS5jaGVja1Zpc2liaWxpdHk/LigpICE9PSBmYWxzZSlcclxuICAgICAgICAgICAgbWF0Y2hlcy5wdXNoKGVsKTtcclxuICAgIH1cclxuICAgIHJldHVybiBtYXRjaGVzO1xyXG59XHJcblxyXG4vKiogTGlrZSBmaW5kQnlSb2xlQW5kTmFtZSBidXQgaW5jbHVkZXMgaGlkZGVuIGVsZW1lbnRzIChmb3IgaG92ZXIgZGV0ZWN0aW9uKS4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRBbGxCeVJvbGVBbmROYW1lKHJvbGU6IHN0cmluZywgbmFtZTogc3RyaW5nKTogRWxlbWVudFtdIHtcclxuICAgIGNvbnN0IG1hdGNoZXM6IEVsZW1lbnRbXSA9IFtdO1xyXG4gICAgZm9yIChjb25zdCBlbCBvZiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcqJykpIHtcclxuICAgICAgICBpZiAoZ2V0SW1wbGljaXRSb2xlKGVsKSA9PT0gcm9sZSAmJiBnZXRBY2Nlc3NpYmxlTmFtZShlbCkgPT09IG5hbWUpXHJcbiAgICAgICAgICAgIG1hdGNoZXMucHVzaChlbCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbWF0Y2hlcztcclxufVxyXG5cclxuLyoqIEZpbmQgdGhlIG5lYXJlc3QgOmhvdmVyIGFuY2VzdG9yIChmb3IgcmVjb3JkaW5nIGhvdmVyIGJlZm9yZSBjbGljaykuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBmaW5kSG92ZXJBbmNlc3RvcihlbDogRWxlbWVudCk6IEVsZW1lbnQgfCBudWxsIHtcclxuICAgIGxldCBhbmNlc3RvciA9IGVsLnBhcmVudEVsZW1lbnQ7XHJcbiAgICB3aGlsZSAoYW5jZXN0b3IgJiYgYW5jZXN0b3IgIT09IGRvY3VtZW50LmJvZHkgJiYgYW5jZXN0b3IgIT09IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkge1xyXG4gICAgICAgIGlmIChhbmNlc3Rvci5tYXRjaGVzKCc6aG92ZXInKSkgcmV0dXJuIGFuY2VzdG9yO1xyXG4gICAgICAgIGFuY2VzdG9yID0gYW5jZXN0b3IucGFyZW50RWxlbWVudDtcclxuICAgIH1cclxuICAgIHJldHVybiBudWxsO1xyXG59XHJcblxyXG4vKipcclxuICogQ2hlY2sgaWYgZWxlbWVudCBpcyByZXZlYWxlZCBieSBhIDpob3ZlciBDU1MgcnVsZS5cclxuICogU2NhbnMgc3R5bGVzaGVldHMgZm9yIHJ1bGVzIGxpa2UgYC5wYXJlbnQ6aG92ZXIgLmNoaWxkIHsgZGlzcGxheTogaW5saW5lLWJsb2NrIH1gLlxyXG4gKiBBdCBjbGljayB0aW1lIHRoZSBhbmNlc3RvciBJUyBob3ZlcmVkLCBzbyBlbC5tYXRjaGVzKCkgd29ya3MgYWdhaW5zdCA6aG92ZXIgc2VsZWN0b3JzLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGlzSG92ZXJSZXZlYWxlZChlbDogRWxlbWVudCk6IGJvb2xlYW4ge1xyXG4gICAgZm9yIChjb25zdCBzaGVldCBvZiBkb2N1bWVudC5zdHlsZVNoZWV0cykge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGZvciAoY29uc3QgcnVsZSBvZiBzaGVldC5jc3NSdWxlcykge1xyXG4gICAgICAgICAgICAgICAgaWYgKCEocnVsZSBpbnN0YW5jZW9mIENTU1N0eWxlUnVsZSkpIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgaWYgKCFydWxlLnNlbGVjdG9yVGV4dC5pbmNsdWRlcygnOmhvdmVyJykpIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgcyA9IHJ1bGUuc3R5bGU7XHJcbiAgICAgICAgICAgICAgICBjb25zdCByZXZlYWxzID0gKHMuZGlzcGxheSAmJiBzLmRpc3BsYXkgIT09ICdub25lJykgfHxcclxuICAgICAgICAgICAgICAgICAgICBzLnZpc2liaWxpdHkgPT09ICd2aXNpYmxlJyB8fFxyXG4gICAgICAgICAgICAgICAgICAgIChzLm9wYWNpdHkgJiYgcy5vcGFjaXR5ICE9PSAnMCcpO1xyXG4gICAgICAgICAgICAgICAgaWYgKCFyZXZlYWxzKSBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIHRyeSB7IGlmIChlbC5tYXRjaGVzKHJ1bGUuc2VsZWN0b3JUZXh0KSkgcmV0dXJuIHRydWU7IH0gY2F0Y2ggeyAvKiBpbnZhbGlkIHNlbGVjdG9yICovIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gY2F0Y2ggeyAvKiBjcm9zcy1vcmlnaW4gc3R5bGVzaGVldCAqLyB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbn1cclxuXHJcbi8vIFx1MjUwMFx1MjUwMFx1MjUwMCBMb2NhdG9yIHN0cmluZyBjb252ZXJzaW9uIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxyXG5cclxuLyoqXHJcbiAqIFBhcnNlIGEgSlMgbG9jYXRvciBzdHJpbmcgaW50byBQVyBrZXl3b3JkIGFyZ3MuXHJcbiAqIGUuZy4gYGdldEJ5Um9sZSgndGFiJywgeyBuYW1lOiAnbnBtJywgZXhhY3Q6IHRydWUgfSkubnRoKDEpYCBcdTIxOTIgYHRhYiBcIm5wbVwiIC0tbnRoIDFgXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gbG9jYXRvclRvUHdBcmdzKGxvY2F0b3I6IHN0cmluZywgcm9sZT86IHN0cmluZyB8IG51bGwpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgcSA9IChzOiBzdHJpbmcpID0+IGBcIiR7c31cImA7XHJcblxyXG4gICAgLy8gRXh0cmFjdCBudGggbW9kaWZpZXJcclxuICAgIGxldCBudGggPSAnJztcclxuICAgIGlmICgvXFwuZmlyc3RcXChcXCkvLnRlc3QobG9jYXRvcikpIG50aCA9ICcgLS1udGggMCc7XHJcbiAgICBlbHNlIGlmICgvXFwubGFzdFxcKFxcKS8udGVzdChsb2NhdG9yKSkgbnRoID0gJyAtLW50aCAtMSc7XHJcbiAgICBlbHNlIHtcclxuICAgICAgICBjb25zdCBudGhNYXRjaCA9IGxvY2F0b3IubWF0Y2goL1xcLm50aFxcKChcXGQrKVxcKS8pO1xyXG4gICAgICAgIGlmIChudGhNYXRjaCkgbnRoID0gYCAtLW50aCAke250aE1hdGNoWzFdfWA7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gZ2V0QnlSb2xlIHdpdGggbmFtZSBcdTIwMTQgYWxyZWFkeSBoYXMgcm9sZVxyXG4gICAgY29uc3Qgcm9sZU5hbWVNYXRjaCA9IGxvY2F0b3IubWF0Y2goL2dldEJ5Um9sZVxcKFsnXCJdKC4rPylbJ1wiXSxcXHMqXFx7W159XSpuYW1lOlxccypbJ1wiXSguKz8pWydcIl0vKTtcclxuICAgIGlmIChyb2xlTmFtZU1hdGNoKSByZXR1cm4gYCR7cm9sZU5hbWVNYXRjaFsxXX0gJHtxKHJvbGVOYW1lTWF0Y2hbMl0pfSR7bnRofWA7XHJcblxyXG4gICAgLy8gZ2V0QnlSb2xlIHdpdGhvdXQgbmFtZSBcdTIwMTQgYWxyZWFkeSBoYXMgcm9sZVxyXG4gICAgY29uc3Qgcm9sZU1hdGNoID0gbG9jYXRvci5tYXRjaCgvZ2V0QnlSb2xlXFwoWydcIl0oLis/KVsnXCJdXFwpLyk7XHJcbiAgICBpZiAocm9sZU1hdGNoKSByZXR1cm4gYCR7cm9sZU1hdGNoWzFdfSR7bnRofWA7XHJcblxyXG4gICAgLy8gZ2V0QnlUZXN0SWQgXHUyMDE0IHRlc3QgSUQgaXMgbm90IGFuIGFjY2Vzc2libGUgbmFtZSwgZG9uJ3QgYWRkIHJvbGVcclxuICAgIGNvbnN0IHRlc3RJZE1hdGNoID0gbG9jYXRvci5tYXRjaCgvZ2V0QnlUZXN0SWRcXChbJ1wiXSguKz8pWydcIl1cXCkvKTtcclxuICAgIGlmICh0ZXN0SWRNYXRjaCkgcmV0dXJuIGAke3EodGVzdElkTWF0Y2hbMV0pfSR7bnRofWA7XHJcblxyXG4gICAgLy8gZ2V0QnlMYWJlbCAvIGdldEJ5VGV4dCAvIGdldEJ5UGxhY2Vob2xkZXIgLyBnZXRCeVRpdGxlIC8gZ2V0QnlBbHRUZXh0IFx1MjAxNCBwcmVwZW5kIHJvbGUgaWYgYXZhaWxhYmxlXHJcbiAgICBjb25zdCBnZXRCeU1hdGNoID0gbG9jYXRvci5tYXRjaCgvZ2V0QnlcXHcrXFwoWydcIl0oLis/KVsnXCJdXFwpLyk7XHJcbiAgICBpZiAoZ2V0QnlNYXRjaCkge1xyXG4gICAgICAgIGNvbnN0IHByZWZpeCA9IHJvbGUgPyBgJHtyb2xlfSBgIDogJyc7XHJcbiAgICAgICAgcmV0dXJuIGAke3ByZWZpeH0ke3EoZ2V0QnlNYXRjaFsxXSl9JHtudGh9YDtcclxuICAgIH1cclxuXHJcbiAgICAvLyBsb2NhdG9yKCdjc3MnKSBmYWxsYmFja1xyXG4gICAgY29uc3QgbG9jYXRvck1hdGNoID0gbG9jYXRvci5tYXRjaCgvbG9jYXRvclxcKFsnXCJdKC4rPylbJ1wiXVxcKS8pO1xyXG4gICAgaWYgKGxvY2F0b3JNYXRjaCkgcmV0dXJuIGAke3EobG9jYXRvck1hdGNoWzFdKX0ke250aH1gO1xyXG5cclxuICAgIHJldHVybiBxKGxvY2F0b3IpO1xyXG59XHJcblxyXG4vLyBcdTI1MDBcdTI1MDBcdTI1MDAgTG9jYXRvciBnZW5lcmF0aW9uIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGVzY2FwZVN0cmluZyhzOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgaWYgKCFzLmluY2x1ZGVzKFwiJ1wiKSkgcmV0dXJuIGAnJHtzfSdgO1xyXG4gICAgaWYgKCFzLmluY2x1ZGVzKCdcIicpKSByZXR1cm4gYFwiJHtzfVwiYDtcclxuICAgIHJldHVybiBgJyR7cy5yZXBsYWNlKC8nL2csIFwiXFxcXCdcIil9J2A7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZUxvY2F0b3IoZWw6IEVsZW1lbnQpOiBzdHJpbmcge1xyXG4gICAgLy8gMS4gVGVzdCBJRFxyXG4gICAgY29uc3QgdGVzdElkID0gZWwuZ2V0QXR0cmlidXRlKCdkYXRhLXRlc3RpZCcpIHx8IGVsLmdldEF0dHJpYnV0ZSgnZGF0YS10ZXN0LWlkJyk7XHJcbiAgICBpZiAodGVzdElkKSByZXR1cm4gYGdldEJ5VGVzdElkKCR7ZXNjYXBlU3RyaW5nKHRlc3RJZCl9KWA7XHJcblxyXG4gICAgLy8gMi4gUm9sZSArIGFjY2Vzc2libGUgbmFtZVxyXG4gICAgY29uc3Qgcm9sZSA9IGdldEltcGxpY2l0Um9sZShlbCk7XHJcbiAgICBjb25zdCBuYW1lID0gZ2V0QWNjZXNzaWJsZU5hbWUoZWwpO1xyXG4gICAgaWYgKHJvbGUgJiYgbmFtZSkge1xyXG4gICAgICAgIC8vIERpc2FtYmlndWF0ZSB3aGVuIG11bHRpcGxlIGVsZW1lbnRzIHNoYXJlIHNhbWUgcm9sZSArIG5hbWVcclxuICAgICAgICBjb25zdCBtYXRjaGVzID0gZmluZEJ5Um9sZUFuZE5hbWUocm9sZSwgbmFtZSk7XHJcbiAgICAgICAgaWYgKG1hdGNoZXMubGVuZ3RoID4gMSkge1xyXG4gICAgICAgICAgICAvLyBUcnkgYW5jZXN0b3IgY29udGV4dCBmaXJzdCAocmVhZGFibGUgY2hhaW5lZCBsb2NhdG9ycylcclxuICAgICAgICAgICAgY29uc3QgYW5jZXN0b3JMb2NhdG9yID0gdHJ5QW5jZXN0b3JDb250ZXh0KGVsLCByb2xlLCBuYW1lLCBtYXRjaGVzKTtcclxuICAgICAgICAgICAgaWYgKGFuY2VzdG9yTG9jYXRvcikgcmV0dXJuIGFuY2VzdG9yTG9jYXRvcjtcclxuICAgICAgICAgICAgLy8gRmFsbGJhY2sgdG8gbnRoLWJhc2VkIGRpc2FtYmlndWF0aW9uXHJcbiAgICAgICAgICAgIGNvbnN0IGJhc2UgPSBgZ2V0QnlSb2xlKCR7ZXNjYXBlU3RyaW5nKHJvbGUpfSwgeyBuYW1lOiAke2VzY2FwZVN0cmluZyhuYW1lKX0sIGV4YWN0OiB0cnVlIH0pYDtcclxuICAgICAgICAgICAgY29uc3QgaWR4ID0gbWF0Y2hlcy5pbmRleE9mKGVsKTtcclxuICAgICAgICAgICAgcmV0dXJuIGlkeCA9PT0gMCA/IGJhc2UgKyAnLmZpcnN0KCknIDogYmFzZSArIGAubnRoKCR7aWR4fSlgO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gYGdldEJ5Um9sZSgke2VzY2FwZVN0cmluZyhyb2xlKX0sIHsgbmFtZTogJHtlc2NhcGVTdHJpbmcobmFtZSl9IH0pYDtcclxuICAgIH1cclxuXHJcbiAgICAvLyAzLiBMYWJlbCAoZm9yIGZvcm0gZWxlbWVudHMpXHJcbiAgICBpZiAoZWwgaW5zdGFuY2VvZiBIVE1MSW5wdXRFbGVtZW50IHx8IGVsIGluc3RhbmNlb2YgSFRNTFRleHRBcmVhRWxlbWVudCB8fCBlbCBpbnN0YW5jZW9mIEhUTUxTZWxlY3RFbGVtZW50KSB7XHJcbiAgICAgICAgY29uc3QgbGFiZWwgPSBnZXRMYWJlbChlbCk7XHJcbiAgICAgICAgaWYgKGxhYmVsKSByZXR1cm4gYGdldEJ5TGFiZWwoJHtlc2NhcGVTdHJpbmcobGFiZWwpfSlgO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIDQuIFBsYWNlaG9sZGVyXHJcbiAgICBjb25zdCBwbGFjZWhvbGRlciA9IGVsLmdldEF0dHJpYnV0ZSgncGxhY2Vob2xkZXInKTtcclxuICAgIGlmIChwbGFjZWhvbGRlcikgcmV0dXJuIGBnZXRCeVBsYWNlaG9sZGVyKCR7ZXNjYXBlU3RyaW5nKHBsYWNlaG9sZGVyKX0pYDtcclxuXHJcbiAgICAvLyA1LiBBbHQgdGV4dFxyXG4gICAgY29uc3QgYWx0ID0gZWwuZ2V0QXR0cmlidXRlKCdhbHQnKTtcclxuICAgIGlmIChhbHQgJiYgWydJTUcnLCAnQVBQTEVUJywgJ0FSRUEnLCAnSU5QVVQnXS5pbmNsdWRlcyhlbC50YWdOYW1lKSlcclxuICAgICAgICByZXR1cm4gYGdldEJ5QWx0VGV4dCgke2VzY2FwZVN0cmluZyhhbHQpfSlgO1xyXG5cclxuICAgIC8vIDYuIFRpdGxlXHJcbiAgICBjb25zdCB0aXRsZSA9IGVsLmdldEF0dHJpYnV0ZSgndGl0bGUnKTtcclxuICAgIGlmICh0aXRsZSkgcmV0dXJuIGBnZXRCeVRpdGxlKCR7ZXNjYXBlU3RyaW5nKHRpdGxlKX0pYDtcclxuXHJcbiAgICAvLyA3LiBUZXh0IGNvbnRlbnRcclxuICAgIGNvbnN0IHRleHQgPSAoZWwudGV4dENvbnRlbnQgfHwgJycpLnRyaW0oKTtcclxuICAgIGlmICh0ZXh0ICYmIHRleHQubGVuZ3RoIDw9IDgwKSByZXR1cm4gYGdldEJ5VGV4dCgke2VzY2FwZVN0cmluZyh0ZXh0KX0pYDtcclxuXHJcbiAgICAvLyA4LiBSb2xlIHdpdGhvdXQgbmFtZVxyXG4gICAgaWYgKHJvbGUpIHJldHVybiBgZ2V0QnlSb2xlKCR7ZXNjYXBlU3RyaW5nKHJvbGUpfSlgO1xyXG5cclxuICAgIC8vIDkuIENTUyBmYWxsYmFja1xyXG4gICAgcmV0dXJuIGBsb2NhdG9yKCR7ZXNjYXBlU3RyaW5nKGJ1aWxkQ3NzU2VsZWN0b3IoZWwpKX0pYDtcclxufVxyXG5cclxuLyoqIFNob3J0aGFuZCBtYXBwaW5nIGZvciBQVyAtLWluIGZsYWcgKGxpc3RpdGVtIFx1MjE5MiBsaXN0IGZvciByZWFkYWJpbGl0eSkuICovXHJcbmNvbnN0IFJPTEVfU0hPUlRIQU5EUzogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHsgbGlzdGl0ZW06ICdsaXN0JyB9O1xyXG5cclxuLyoqXHJcbiAqIEdlbmVyYXRlIHNlcGFyYXRlIEpTIGFuZCBQVyBsb2NhdG9ycy5cclxuICogSlMgdXNlcyBhbmNlc3RvciBjb250ZXh0ICguZmlsdGVyIGNoYWlucyk7IFBXIHVzZXMgLS1pbiBmbGFnLlxyXG4gKiBGYWxscyBiYWNrIHRvIC5udGgoKSB3aGVuIGFuY2VzdG9yIGNvbnRleHQgaXNuJ3QgYXZhaWxhYmxlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlTG9jYXRvclBhaXIoZWw6IEVsZW1lbnQpOiB7IGpzOiBzdHJpbmc7IHB3OiBzdHJpbmc7IGFuY2VzdG9yPzogeyByb2xlOiBzdHJpbmc7IHRleHQ6IHN0cmluZyB9IH0ge1xyXG4gICAgY29uc3QganNMb2NhdG9yID0gZ2VuZXJhdGVMb2NhdG9yKGVsKTtcclxuICAgIGlmICghanNMb2NhdG9yLmluY2x1ZGVzKCcuZmlsdGVyKCcpKSByZXR1cm4geyBqczoganNMb2NhdG9yLCBwdzoganNMb2NhdG9yIH07XHJcblxyXG4gICAgLy8gSlMgdXNlZCBhbmNlc3RvciBjb250ZXh0IFx1MjAxNCBleHRyYWN0IGFuY2VzdG9yIGluZm8gZm9yIFBXIC0taW4gZmxhZ1xyXG4gICAgY29uc3Qgcm9sZSA9IGdldEltcGxpY2l0Um9sZShlbCkhO1xyXG4gICAgY29uc3QgbmFtZSA9IGdldEFjY2Vzc2libGVOYW1lKGVsKTtcclxuICAgIGNvbnN0IGNvbnRhaW5lciA9IGZpbmRDb250YWluZXJBbmNlc3RvcihlbCk7XHJcbiAgICBjb25zdCBjb250ZXh0VGV4dCA9IGNvbnRhaW5lciA/IGdldENvbnRleHRUZXh0KGNvbnRhaW5lci5hbmNlc3RvciwgZWwpIDogJyc7XHJcblxyXG4gICAgaWYgKGNvbnRhaW5lciAmJiBjb250ZXh0VGV4dCkge1xyXG4gICAgICAgIGNvbnN0IHB3TG9jYXRvciA9IGBnZXRCeVJvbGUoJHtlc2NhcGVTdHJpbmcocm9sZSl9LCB7IG5hbWU6ICR7ZXNjYXBlU3RyaW5nKG5hbWUpfSB9KWA7XHJcbiAgICAgICAgY29uc3Qgc2hvcnRSb2xlID0gUk9MRV9TSE9SVEhBTkRTW2NvbnRhaW5lci5yb2xlXSA/PyBjb250YWluZXIucm9sZTtcclxuICAgICAgICByZXR1cm4geyBqczoganNMb2NhdG9yLCBwdzogcHdMb2NhdG9yLCBhbmNlc3RvcjogeyByb2xlOiBzaG9ydFJvbGUsIHRleHQ6IGNvbnRleHRUZXh0IH0gfTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBObyBhbmNlc3RvciBjb250ZXh0IFx1MjAxNCBmYWxsIGJhY2sgdG8gLm50aCgpXHJcbiAgICBjb25zdCBtYXRjaGVzID0gZmluZEJ5Um9sZUFuZE5hbWUocm9sZSwgbmFtZSk7XHJcbiAgICBjb25zdCBiYXNlID0gYGdldEJ5Um9sZSgke2VzY2FwZVN0cmluZyhyb2xlKX0sIHsgbmFtZTogJHtlc2NhcGVTdHJpbmcobmFtZSl9LCBleGFjdDogdHJ1ZSB9KWA7XHJcbiAgICBjb25zdCBpZHggPSBtYXRjaGVzLmluZGV4T2YoZWwpO1xyXG4gICAgY29uc3QgcHdMb2NhdG9yID0gaWR4ID09PSAwID8gYmFzZSArICcuZmlyc3QoKScgOiBiYXNlICsgYC5udGgoJHtpZHh9KWA7XHJcbiAgICByZXR1cm4geyBqczoganNMb2NhdG9yLCBwdzogcHdMb2NhdG9yIH07XHJcbn1cclxuXHJcbi8vIFx1MjUwMFx1MjUwMFx1MjUwMCBFbGVtZW50IGNsYXNzaWZpY2F0aW9uIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxyXG5cclxuLyoqIENoZWNrIGlmIGVsZW1lbnQgaXMgYSB0ZXh0LWVudHJ5IGZpZWxkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc1RleHRGaWVsZChlbDogRWxlbWVudCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKGVsIGluc3RhbmNlb2YgSFRNTFRleHRBcmVhRWxlbWVudCkgcmV0dXJuIHRydWU7XHJcbiAgICBpZiAoZWwgaW5zdGFuY2VvZiBIVE1MSW5wdXRFbGVtZW50KSB7XHJcbiAgICAgICAgY29uc3QgdHlwZSA9IGVsLnR5cGUudG9Mb3dlckNhc2UoKTtcclxuICAgICAgICByZXR1cm4gIVsnY2hlY2tib3gnLCAncmFkaW8nLCAnc3VibWl0JywgJ3Jlc2V0JywgJ2J1dHRvbicsICdoaWRkZW4nLCAnZmlsZScsICdpbWFnZScsICdyYW5nZScsICdjb2xvciddLmluY2x1ZGVzKHR5cGUpO1xyXG4gICAgfVxyXG4gICAgLy8gY29udGVudGVkaXRhYmxlXHJcbiAgICBpZiAoZWwuZ2V0QXR0cmlidXRlKCdjb250ZW50ZWRpdGFibGUnKSA9PT0gJ3RydWUnKSByZXR1cm4gdHJ1ZTtcclxuICAgIHJldHVybiBmYWxzZTtcclxufVxyXG5cclxuLyoqIENoZWNrIGlmIGVsZW1lbnQgaXMgYSBjaGVja2JveCBvciByYWRpbyAqL1xyXG5leHBvcnQgZnVuY3Rpb24gaXNDaGVja2FibGUoZWw6IEVsZW1lbnQpOiBib29sZWFuIHtcclxuICAgIHJldHVybiBlbCBpbnN0YW5jZW9mIEhUTUxJbnB1dEVsZW1lbnQgJiYgKGVsLnR5cGUgPT09ICdjaGVja2JveCcgfHwgZWwudHlwZSA9PT0gJ3JhZGlvJyk7XHJcbn1cclxuXHJcbi8vIFx1MjUwMFx1MjUwMFx1MjUwMCBDb21tYW5kIGJ1aWxkaW5nIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxyXG5cclxuLyoqIEJ1aWxkIGJvdGggUFcgYW5kIEpTIGNvbW1hbmQgc3RyaW5ncyBmb3IgYSByZWNvcmRlciBhY3Rpb24gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkQ29tbWFuZHMoYWN0aW9uOiBzdHJpbmcsIGVsOiBFbGVtZW50LCBvcHRzPzoge1xyXG4gICAgdmFsdWU/OiBzdHJpbmc7XHJcbiAgICBrZXk/OiBzdHJpbmc7XHJcbiAgICBjaGVja2VkPzogYm9vbGVhbjtcclxuICAgIG9wdGlvbj86IHN0cmluZztcclxufSk6IHsgcHc6IHN0cmluZzsganM6IHN0cmluZyB9IHwgbnVsbCB7XHJcbiAgICBjb25zdCB7IGpzOiBqc0xvY2F0b3IsIHB3OiBwd0xvY2F0b3IsIGFuY2VzdG9yIH0gPSBnZW5lcmF0ZUxvY2F0b3JQYWlyKGVsKTtcclxuICAgIGNvbnN0IGpzTG9jID0gYHBhZ2UuJHtqc0xvY2F0b3J9YDtcclxuICAgIGNvbnN0IHJvbGUgPSBnZXRJbXBsaWNpdFJvbGUoZWwpO1xyXG4gICAgY29uc3QgcHdBcmdzID0gbG9jYXRvclRvUHdBcmdzKHB3TG9jYXRvciwgcm9sZSk7XHJcbiAgICBjb25zdCBxID0gKHM6IHN0cmluZykgPT4gYFwiJHtzfVwiYDtcclxuICAgIGNvbnN0IGluRmxhZyA9IGFuY2VzdG9yID8gYCAtLWluICR7YW5jZXN0b3Iucm9sZX0gJHtxKGFuY2VzdG9yLnRleHQpfWAgOiAnJztcclxuXHJcbiAgICBzd2l0Y2ggKGFjdGlvbikge1xyXG4gICAgICAgIGNhc2UgJ2hvdmVyJzpcclxuICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgIHB3OiBgaG92ZXIgJHtwd0FyZ3N9JHtpbkZsYWd9YCxcclxuICAgICAgICAgICAgICAgIGpzOiBgYXdhaXQgJHtqc0xvY30uaG92ZXIoKTtgLFxyXG4gICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICBjYXNlICdjbGljayc6XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICBwdzogYGNsaWNrICR7cHdBcmdzfSR7aW5GbGFnfWAsXHJcbiAgICAgICAgICAgICAgICBqczogYGF3YWl0ICR7anNMb2N9LmNsaWNrKCk7YCxcclxuICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgY2FzZSAnZmlsbCc6IHtcclxuICAgICAgICAgICAgY29uc3QgdmFsID0gb3B0cz8udmFsdWUgPz8gJyc7XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICBwdzogYGZpbGwgJHtwd0FyZ3N9ICR7cSh2YWwpfSR7aW5GbGFnfWAsXHJcbiAgICAgICAgICAgICAgICBqczogYGF3YWl0ICR7anNMb2N9LmZpbGwoJHtlc2NhcGVTdHJpbmcodmFsKX0pO2AsXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjYXNlICdjaGVjayc6XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICBwdzogYGNoZWNrICR7cHdBcmdzfSR7aW5GbGFnfWAsXHJcbiAgICAgICAgICAgICAgICBqczogYGF3YWl0ICR7anNMb2N9LmNoZWNrKCk7YCxcclxuICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgY2FzZSAndW5jaGVjayc6XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICBwdzogYHVuY2hlY2sgJHtwd0FyZ3N9JHtpbkZsYWd9YCxcclxuICAgICAgICAgICAgICAgIGpzOiBgYXdhaXQgJHtqc0xvY30udW5jaGVjaygpO2AsXHJcbiAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgIGNhc2UgJ3NlbGVjdCc6IHtcclxuICAgICAgICAgICAgY29uc3Qgb3B0VmFsID0gb3B0cz8ub3B0aW9uID8/ICcnO1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcHc6IGBzZWxlY3QgJHtwd0FyZ3N9ICR7cShvcHRWYWwpfSR7aW5GbGFnfWAsXHJcbiAgICAgICAgICAgICAgICBqczogYGF3YWl0ICR7anNMb2N9LnNlbGVjdE9wdGlvbigke2VzY2FwZVN0cmluZyhvcHRWYWwpfSk7YCxcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNhc2UgJ3ByZXNzJzoge1xyXG4gICAgICAgICAgICBjb25zdCBrZXkgPSBvcHRzPy5rZXkgPz8gJyc7XHJcbiAgICAgICAgICAgIGlmIChwd0FyZ3MpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICAgICAgcHc6IGBwcmVzcyAke3B3QXJnc30gJHtrZXl9JHtpbkZsYWd9YCxcclxuICAgICAgICAgICAgICAgICAgICBqczogYGF3YWl0ICR7anNMb2N9LnByZXNzKCR7ZXNjYXBlU3RyaW5nKGtleSl9KTtgLFxyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAvLyBHbG9iYWwga2V5IHByZXNzIChubyBsb2NhdG9yIGNvbnRleHQpXHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICBwdzogYHByZXNzICR7a2V5fWAsXHJcbiAgICAgICAgICAgICAgICBqczogYGF3YWl0IHBhZ2Uua2V5Ym9hcmQucHJlc3MoJHtlc2NhcGVTdHJpbmcoa2V5KX0pO2AsXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxufVxyXG5cclxuLy8gXHUyNTAwXHUyNTAwXHUyNTAwIENTUyBzZWxlY3RvciBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBidWlsZENzc1NlbGVjdG9yKGVsOiBFbGVtZW50KTogc3RyaW5nIHtcclxuICAgIGNvbnN0IHRhZyA9IGVsLnRhZ05hbWUudG9Mb3dlckNhc2UoKTtcclxuICAgIGlmIChlbC5pZCkgcmV0dXJuIGAke3RhZ30jJHtDU1MuZXNjYXBlKGVsLmlkKX1gO1xyXG4gICAgY29uc3QgY2xhc3NlcyA9IFsuLi5lbC5jbGFzc0xpc3RdLnNsaWNlKDAsIDIpLm1hcChjID0+ICcuJyArIENTUy5lc2NhcGUoYykpLmpvaW4oJycpO1xyXG4gICAgaWYgKGNsYXNzZXMpIHJldHVybiBgJHt0YWd9JHtjbGFzc2VzfWA7XHJcbiAgICByZXR1cm4gdGFnO1xyXG59XHJcbiIsICIvKipcclxuICogRWxlbWVudCBwaWNrZXIgY29udGVudCBzY3JpcHQuXHJcbiAqIEluamVjdGVkIGludG8gdGhlIGFjdGl2ZSB0YWIgdmlhIGNocm9tZS5zY3JpcHRpbmcuZXhlY3V0ZVNjcmlwdC5cclxuICogSGlnaGxpZ2h0cyBlbGVtZW50cyBvbiBob3ZlciwgY2FwdHVyZXMgY2xpY2ssIGdlbmVyYXRlcyBsb2NhdG9yICsgZWxlbWVudCBpbmZvLlxyXG4gKi9cclxuaW1wb3J0IHsgZ2VuZXJhdGVMb2NhdG9yIH0gZnJvbSAnLi9sb2NhdG9yJztcclxuXHJcbi8vIFx1MjUwMFx1MjUwMFx1MjUwMCBFbGVtZW50IGluZm8gZ2F0aGVyaW5nIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGdldE91dGVySHRtbChlbDogRWxlbWVudCk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBvdXRlciA9IGVsLm91dGVySFRNTDtcclxuICAgIGlmIChvdXRlci5sZW5ndGggPD0gMjAwKSByZXR1cm4gb3V0ZXI7XHJcbiAgICBjb25zdCB0YWcgPSBlbC50YWdOYW1lLnRvTG93ZXJDYXNlKCk7XHJcbiAgICBjb25zdCBvcGVuID0gb3V0ZXIuc2xpY2UoMCwgb3V0ZXIuaW5kZXhPZignPicpICsgMSk7XHJcbiAgICByZXR1cm4gYCR7b3Blbn0uLi48LyR7dGFnfT5gO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gZ2F0aGVySW5mbyhlbDogRWxlbWVudCkge1xyXG4gICAgY29uc3QgcmVjdCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgY29uc3QgYXR0cnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcclxuICAgIGZvciAoY29uc3QgYSBvZiBlbC5hdHRyaWJ1dGVzKSBhdHRyc1thLm5hbWVdID0gYS52YWx1ZTtcclxuICAgIHJldHVybiB7XHJcbiAgICAgICAgbG9jYXRvcjogZ2VuZXJhdGVMb2NhdG9yKGVsKSxcclxuICAgICAgICB0YWc6IGVsLnRhZ05hbWUudG9Mb3dlckNhc2UoKSxcclxuICAgICAgICB0ZXh0OiAoZWwudGV4dENvbnRlbnQgfHwgJycpLnRyaW0oKS5zbGljZSgwLCAyMDApLFxyXG4gICAgICAgIGh0bWw6IGdldE91dGVySHRtbChlbCksXHJcbiAgICAgICAgYXR0cmlidXRlczogYXR0cnMsXHJcbiAgICAgICAgdmlzaWJsZTogcmVjdC53aWR0aCA+IDAgJiYgcmVjdC5oZWlnaHQgPiAwLFxyXG4gICAgICAgIGVuYWJsZWQ6ICEoZWwgYXMgSFRNTEJ1dHRvbkVsZW1lbnQpLmRpc2FibGVkLFxyXG4gICAgICAgIGJveDogeyB4OiByZWN0LngsIHk6IHJlY3QueSwgd2lkdGg6IHJlY3Qud2lkdGgsIGhlaWdodDogcmVjdC5oZWlnaHQgfSxcclxuICAgICAgICB2YWx1ZTogKGVsIGluc3RhbmNlb2YgSFRNTElucHV0RWxlbWVudCB8fCBlbCBpbnN0YW5jZW9mIEhUTUxUZXh0QXJlYUVsZW1lbnQgfHwgZWwgaW5zdGFuY2VvZiBIVE1MU2VsZWN0RWxlbWVudClcclxuICAgICAgICAgICAgPyBlbC52YWx1ZSA6IHVuZGVmaW5lZCxcclxuICAgICAgICBjaGVja2VkOiAoZWwgaW5zdGFuY2VvZiBIVE1MSW5wdXRFbGVtZW50ICYmIChlbC50eXBlID09PSAnY2hlY2tib3gnIHx8IGVsLnR5cGUgPT09ICdyYWRpbycpKVxyXG4gICAgICAgICAgICA/IGVsLmNoZWNrZWQgOiB1bmRlZmluZWQsXHJcbiAgICB9O1xyXG59XHJcblxyXG4vLyBcdTI1MDBcdTI1MDBcdTI1MDAgT3ZlcmxheSArIHN0YXRlIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxyXG5cclxuZXhwb3J0IGNvbnN0IGhpZ2hsaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xyXG5oaWdobGlnaHQuc3R5bGUuY3NzVGV4dCA9ICdwb3NpdGlvbjpmaXhlZDtwb2ludGVyLWV2ZW50czpub25lO3otaW5kZXg6MjE0NzQ4MzY0Njtib3JkZXI6MnB4IHNvbGlkICM2ZmE4ZGM7YmFja2dyb3VuZDpyZ2JhKDExMSwxNjgsMjIwLDAuMik7ZGlzcGxheTpub25lO2JveC1zaXppbmc6Ym9yZGVyLWJveDsnO1xyXG5cclxuZXhwb3J0IGxldCBjdXJyZW50RWxlbWVudDogRWxlbWVudCB8IG51bGwgPSBudWxsO1xyXG5cclxuLy8gXHUyNTAwXHUyNTAwXHUyNTAwIEV2ZW50IGhhbmRsZXJzIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIG9uTW91c2VNb3ZlKGU6IE1vdXNlRXZlbnQpIHtcclxuICAgIGNvbnN0IHRhcmdldCA9IGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQoZS5jbGllbnRYLCBlLmNsaWVudFkpO1xyXG4gICAgaWYgKCF0YXJnZXQgfHwgdGFyZ2V0ID09PSBoaWdobGlnaHQpIHJldHVybjtcclxuICAgIGlmICh0YXJnZXQgPT09IGN1cnJlbnRFbGVtZW50KSByZXR1cm47XHJcbiAgICBjdXJyZW50RWxlbWVudCA9IHRhcmdldDtcclxuXHJcbiAgICBjb25zdCByZWN0ID0gdGFyZ2V0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgaGlnaGxpZ2h0LnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xyXG4gICAgaGlnaGxpZ2h0LnN0eWxlLmxlZnQgPSByZWN0LmxlZnQgKyAncHgnO1xyXG4gICAgaGlnaGxpZ2h0LnN0eWxlLnRvcCA9IHJlY3QudG9wICsgJ3B4JztcclxuICAgIGhpZ2hsaWdodC5zdHlsZS53aWR0aCA9IHJlY3Qud2lkdGggKyAncHgnO1xyXG4gICAgaGlnaGxpZ2h0LnN0eWxlLmhlaWdodCA9IHJlY3QuaGVpZ2h0ICsgJ3B4JztcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIG9uQ2xpY2soZTogTW91c2VFdmVudCkge1xyXG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XHJcblxyXG4gICAgaWYgKCFjdXJyZW50RWxlbWVudCkgcmV0dXJuO1xyXG4gICAgY29uc3QgaW5mbyA9IGdhdGhlckluZm8oY3VycmVudEVsZW1lbnQpO1xyXG4gICAgLy8gTWFyayBlbGVtZW50IHNvIENEUCBjYW4gZmluZCBpdCBmb3IgX2dlbmVyYXRlTG9jYXRvclN0cmluZygpXHJcbiAgICBjb25zdCBwaWNrSWQgPSBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zbGljZSgyKTtcclxuICAgIGN1cnJlbnRFbGVtZW50LnNldEF0dHJpYnV0ZSgnZGF0YS1wdy1waWNrLWlkJywgcGlja0lkKTtcclxuICAgIGNsZWFudXAoKTtcclxuICAgIGNocm9tZS5ydW50aW1lLnNlbmRNZXNzYWdlKHsgdHlwZTogJ2VsZW1lbnQtcGlja2VkLXJhdycsIHBpY2tJZCwgaW5mbyB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIG9uS2V5RG93bihlOiBLZXlib2FyZEV2ZW50KSB7XHJcbiAgICBpZiAoZS5rZXkgPT09ICdFc2NhcGUnKSB7XHJcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XHJcbiAgICAgICAgY2xlYW51cCgpO1xyXG4gICAgICAgIGNocm9tZS5ydW50aW1lLnNlbmRNZXNzYWdlKHsgdHlwZTogJ3BpY2stY2FuY2VsbGVkJyB9KTtcclxuICAgIH1cclxufVxyXG5cclxuLy8gXHUyNTAwXHUyNTAwXHUyNTAwIExpZmVjeWNsZSBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBjbGVhbnVwKCkge1xyXG4gICAgKHdpbmRvdyBhcyBhbnkpLl9fcHdfcGlja2VyX2FjdGl2ZSA9IGZhbHNlO1xyXG4gICAgY3VycmVudEVsZW1lbnQgPSBudWxsO1xyXG4gICAgaGlnaGxpZ2h0LnJlbW92ZSgpO1xyXG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgb25Nb3VzZU1vdmUsIHRydWUpO1xyXG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCBvbkNsaWNrLCB0cnVlKTtcclxuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCBvbktleURvd24sIHRydWUpO1xyXG4gICAgY2hyb21lLnJ1bnRpbWUub25NZXNzYWdlLnJlbW92ZUxpc3RlbmVyKG9uTWVzc2FnZSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIG9uTWVzc2FnZShtc2c6IGFueSkge1xyXG4gICAgaWYgKG1zZy50eXBlID09PSAncGljay1zdG9wJykgY2xlYW51cCgpO1xyXG59XHJcblxyXG4vLyBcdTI1MDBcdTI1MDBcdTI1MDAgSW5pdCBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBpbml0KCkge1xyXG4gICAgLy8gR3VhcmQgYWdhaW5zdCBkb3VibGUtaW5qZWN0aW9uXHJcbiAgICBpZiAoKHdpbmRvdyBhcyBhbnkpLl9fcHdfcGlja2VyX2FjdGl2ZSkgcmV0dXJuO1xyXG4gICAgKHdpbmRvdyBhcyBhbnkpLl9fcHdfcGlja2VyX2FjdGl2ZSA9IHRydWU7XHJcblxyXG4gICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmFwcGVuZENoaWxkKGhpZ2hsaWdodCk7XHJcblxyXG4gICAgY2hyb21lLnJ1bnRpbWUub25NZXNzYWdlLmFkZExpc3RlbmVyKG9uTWVzc2FnZSk7XHJcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBvbk1vdXNlTW92ZSwgdHJ1ZSk7XHJcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIG9uQ2xpY2ssIHRydWUpO1xyXG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIG9uS2V5RG93biwg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