semantifold 0.8.0 → 0.10.0

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 (171) hide show
  1. package/README.md +11 -5
  2. package/bin/semantifold.js +6 -0
  3. package/build/bin/semantifold.d.ts +3 -0
  4. package/build/bin/semantifold.d.ts.map +1 -0
  5. package/build/bin/semantifold.js +5 -0
  6. package/build/index.d.ts +9 -0
  7. package/build/index.d.ts.map +1 -1
  8. package/build/index.js +10 -1
  9. package/build/src/artifact-path.d.ts +16 -0
  10. package/build/src/artifact-path.d.ts.map +1 -1
  11. package/build/src/artifact-path.js +29 -3
  12. package/build/src/backends/c-check.d.ts +7 -0
  13. package/build/src/backends/c-check.d.ts.map +1 -0
  14. package/build/src/backends/c-check.js +65 -0
  15. package/build/src/backends/check-plan.d.ts +96 -0
  16. package/build/src/backends/check-plan.d.ts.map +1 -0
  17. package/build/src/backends/check-plan.js +135 -0
  18. package/build/src/backends/cpp-check.d.ts +7 -0
  19. package/build/src/backends/cpp-check.d.ts.map +1 -0
  20. package/build/src/backends/cpp-check.js +59 -0
  21. package/build/src/backends/csharp-check.d.ts +7 -0
  22. package/build/src/backends/csharp-check.d.ts.map +1 -0
  23. package/build/src/backends/csharp-check.js +125 -0
  24. package/build/src/backends/csharp.d.ts +1 -0
  25. package/build/src/backends/csharp.d.ts.map +1 -1
  26. package/build/src/backends/csharp.js +5 -4
  27. package/build/src/backends/dart-check.d.ts +7 -0
  28. package/build/src/backends/dart-check.d.ts.map +1 -0
  29. package/build/src/backends/dart-check.js +103 -0
  30. package/build/src/backends/dart.d.ts +2 -0
  31. package/build/src/backends/dart.d.ts.map +1 -1
  32. package/build/src/backends/dart.js +5 -5
  33. package/build/src/backends/go-check.d.ts +7 -0
  34. package/build/src/backends/go-check.d.ts.map +1 -0
  35. package/build/src/backends/go-check.js +77 -0
  36. package/build/src/backends/go.d.ts +1 -0
  37. package/build/src/backends/go.d.ts.map +1 -1
  38. package/build/src/backends/go.js +3 -3
  39. package/build/src/backends/java-check.d.ts +21 -0
  40. package/build/src/backends/java-check.d.ts.map +1 -0
  41. package/build/src/backends/java-check.js +73 -0
  42. package/build/src/backends/javascript-check.d.ts +7 -0
  43. package/build/src/backends/javascript-check.d.ts.map +1 -0
  44. package/build/src/backends/javascript-check.js +29 -0
  45. package/build/src/backends/kotlin-check.d.ts +7 -0
  46. package/build/src/backends/kotlin-check.d.ts.map +1 -0
  47. package/build/src/backends/kotlin-check.js +31 -0
  48. package/build/src/backends/php-check.d.ts +7 -0
  49. package/build/src/backends/php-check.d.ts.map +1 -0
  50. package/build/src/backends/php-check.js +21 -0
  51. package/build/src/backends/program.d.ts +7 -0
  52. package/build/src/backends/program.d.ts.map +1 -1
  53. package/build/src/backends/program.js +16 -1
  54. package/build/src/backends/python-check.d.ts +7 -0
  55. package/build/src/backends/python-check.d.ts.map +1 -0
  56. package/build/src/backends/python-check.js +28 -0
  57. package/build/src/backends/ruby-check.d.ts +7 -0
  58. package/build/src/backends/ruby-check.d.ts.map +1 -0
  59. package/build/src/backends/ruby-check.js +21 -0
  60. package/build/src/backends/rust-check.d.ts +7 -0
  61. package/build/src/backends/rust-check.d.ts.map +1 -0
  62. package/build/src/backends/rust-check.js +65 -0
  63. package/build/src/backends/swift-check.d.ts +7 -0
  64. package/build/src/backends/swift-check.d.ts.map +1 -0
  65. package/build/src/backends/swift-check.js +77 -0
  66. package/build/src/backends/typescript-check.d.ts +7 -0
  67. package/build/src/backends/typescript-check.d.ts.map +1 -0
  68. package/build/src/backends/typescript-check.js +33 -0
  69. package/build/src/backends/zig-check.d.ts +7 -0
  70. package/build/src/backends/zig-check.d.ts.map +1 -0
  71. package/build/src/backends/zig-check.js +70 -0
  72. package/build/src/diagnostic.d.ts +13 -1
  73. package/build/src/diagnostic.d.ts.map +1 -1
  74. package/build/src/diagnostic.js +14 -2
  75. package/build/src/frontends/program.d.ts +6 -0
  76. package/build/src/frontends/program.d.ts.map +1 -1
  77. package/build/src/frontends/program.js +9 -1
  78. package/build/src/language-registry.d.ts +54 -0
  79. package/build/src/language-registry.d.ts.map +1 -1
  80. package/build/src/language-registry.js +107 -5
  81. package/build/src/project-build.d.ts +172 -0
  82. package/build/src/project-build.d.ts.map +1 -0
  83. package/build/src/project-build.js +320 -0
  84. package/build/src/project-cli.d.ts +40 -0
  85. package/build/src/project-cli.d.ts.map +1 -0
  86. package/build/src/project-cli.js +145 -0
  87. package/build/src/project-manifest.d.ts +148 -0
  88. package/build/src/project-manifest.d.ts.map +1 -0
  89. package/build/src/project-manifest.js +432 -0
  90. package/build/src/project-reporter.d.ts +81 -0
  91. package/build/src/project-reporter.d.ts.map +1 -0
  92. package/build/src/project-reporter.js +293 -0
  93. package/build/src/project-snapshot.d.ts +129 -0
  94. package/build/src/project-snapshot.d.ts.map +1 -0
  95. package/build/src/project-snapshot.js +362 -0
  96. package/build/src/project-watch-reporter.d.ts +125 -0
  97. package/build/src/project-watch-reporter.d.ts.map +1 -0
  98. package/build/src/project-watch-reporter.js +280 -0
  99. package/build/src/project-watch.d.ts +133 -0
  100. package/build/src/project-watch.d.ts.map +1 -0
  101. package/build/src/project-watch.js +839 -0
  102. package/build/src/publication.d.ts +218 -0
  103. package/build/src/publication.d.ts.map +1 -0
  104. package/build/src/publication.js +1832 -0
  105. package/build/src/semantic/types.d.ts +613 -0
  106. package/build/src/semantic/types.d.ts.map +1 -1
  107. package/build/src/semantic/types.js +163 -1
  108. package/build/src/subprocess.d.ts +8 -0
  109. package/build/src/subprocess.d.ts.map +1 -1
  110. package/build/src/subprocess.js +50 -9
  111. package/build/src/target-check.d.ts +52 -0
  112. package/build/src/target-check.d.ts.map +1 -0
  113. package/build/src/target-check.js +796 -0
  114. package/build/src/toolchains.d.ts.map +1 -1
  115. package/build/src/toolchains.js +3 -3
  116. package/docs/architecture.md +3 -1
  117. package/docs/c.md +4 -0
  118. package/docs/cpp.md +4 -0
  119. package/docs/dart.md +4 -0
  120. package/docs/generated-artifact-publication.md +98 -0
  121. package/docs/kotlin.md +2 -2
  122. package/docs/language-support.md +29 -3
  123. package/docs/project-build-cli.md +147 -0
  124. package/docs/project-watch.md +60 -0
  125. package/docs/rust.md +4 -0
  126. package/docs/swift.md +2 -0
  127. package/docs/testing.md +70 -3
  128. package/docs/watch-build-pipeline.md +42 -26
  129. package/docs/zig.md +2 -0
  130. package/examples/jsdoc-java-watch/expected-output.txt +3 -0
  131. package/examples/jsdoc-java-watch/semantifold.json +23 -0
  132. package/examples/jsdoc-java-watch/src/main.js +21 -0
  133. package/index.js +9 -0
  134. package/package.json +6 -1
  135. package/src/artifact-path.js +31 -2
  136. package/src/backends/c-check.js +80 -0
  137. package/src/backends/check-plan.js +147 -0
  138. package/src/backends/cpp-check.js +73 -0
  139. package/src/backends/csharp-check.js +139 -0
  140. package/src/backends/csharp.js +4 -3
  141. package/src/backends/dart-check.js +117 -0
  142. package/src/backends/dart.js +4 -4
  143. package/src/backends/go-check.js +89 -0
  144. package/src/backends/go.js +2 -2
  145. package/src/backends/java-check.js +77 -0
  146. package/src/backends/javascript-check.js +33 -0
  147. package/src/backends/kotlin-check.js +41 -0
  148. package/src/backends/php-check.js +23 -0
  149. package/src/backends/program.js +17 -0
  150. package/src/backends/python-check.js +30 -0
  151. package/src/backends/ruby-check.js +23 -0
  152. package/src/backends/rust-check.js +78 -0
  153. package/src/backends/swift-check.js +89 -0
  154. package/src/backends/typescript-check.js +37 -0
  155. package/src/backends/zig-check.js +81 -0
  156. package/src/diagnostic.js +9 -1
  157. package/src/frontends/program.js +9 -0
  158. package/src/language-registry.js +113 -4
  159. package/src/project-build.js +353 -0
  160. package/src/project-cli.js +155 -0
  161. package/src/project-manifest.js +479 -0
  162. package/src/project-reporter.js +320 -0
  163. package/src/project-snapshot.js +403 -0
  164. package/src/project-watch-reporter.js +303 -0
  165. package/src/project-watch.js +870 -0
  166. package/src/publication.js +2071 -0
  167. package/src/semantic/types.js +184 -0
  168. package/src/subprocess.js +49 -8
  169. package/src/target-check.js +844 -0
  170. package/src/toolchains.js +3 -2
  171. package/tsconfig.json +1 -1
@@ -0,0 +1,839 @@
1
+ // @ts-check
2
+ import { watch as watchFileSystem } from "node:fs";
3
+ import { lstat } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { SemantifoldDiagnostic } from "./diagnostic.js";
6
+ import { buildWatchedProject, ProjectBuilder } from "./project-build.js";
7
+ import { ProjectManifestLoader, SemantifoldProject } from "./project-manifest.js";
8
+ import { ProjectSnapshot, ProjectSnapshotBuilder } from "./project-snapshot.js";
9
+ import { ProjectWatchReporter } from "./project-watch-reporter.js";
10
+ const defaultQuietPeriodMs = 50;
11
+ const defaultPollIntervalMs = 1000;
12
+ const maximumQuietPeriodMs = 10_000;
13
+ const maximumPollIntervalMs = 60_000;
14
+ /** @type {WeakMap<ProjectWatchCoordinator, (event: ProjectWatchObservation) => void>} */
15
+ const projectWatchObservers = new WeakMap();
16
+ /** @type {WeakMap<ProjectWatchCoordinator, typeof watchFileSystem>} */
17
+ const projectWatchNativeBackends = new WeakMap();
18
+ /** @type {WeakMap<ProjectWatchCoordinator, ProjectWatchStateReader>} */
19
+ const projectWatchStateReaders = new WeakMap();
20
+ /**
21
+ * Installs a synchronous lifecycle observer for focused coordination specs.
22
+ * This helper is intentionally not part of the package root API.
23
+ * @param {ProjectWatchCoordinator} coordinator - Coordinator instance.
24
+ * @param {(event: ProjectWatchObservation) => void} observer - Marker observer.
25
+ * @returns {void}
26
+ */
27
+ export function observeProjectWatch(coordinator, observer) {
28
+ if (!(coordinator instanceof ProjectWatchCoordinator) || typeof observer != "function") {
29
+ throw new TypeError("Invalid project watch observer.");
30
+ }
31
+ projectWatchObservers.set(coordinator, observer);
32
+ }
33
+ /**
34
+ * Creates a coordinator with one instance-owned native event backend for focused fallback specs.
35
+ * This helper is intentionally not part of the package root API.
36
+ * @param {{builder?: ProjectBuilder, manifestLoader?: ProjectManifestLoader, nativeWatch: typeof watchFileSystem, pollIntervalMs?: number, quietPeriodMs?: number, snapshotBuilder?: ProjectSnapshotBuilder, watchStateReader?: ProjectWatchStateReader}} options - Coordinator options and backends.
37
+ * @returns {ProjectWatchCoordinator} Configured coordinator.
38
+ */
39
+ export function createProjectWatchCoordinator(options) {
40
+ if (!isPlainObject(options) || typeof options.nativeWatch != "function" ||
41
+ options.watchStateReader !== undefined && typeof options.watchStateReader != "function") {
42
+ throw new TypeError("Invalid project watch coordinator dependencies.");
43
+ }
44
+ const coordinator = new ProjectWatchCoordinator({
45
+ ...(options.builder === undefined ? {} : { builder: options.builder }),
46
+ ...(options.manifestLoader === undefined ? {} : { manifestLoader: options.manifestLoader }),
47
+ ...(options.pollIntervalMs === undefined ? {} : { pollIntervalMs: options.pollIntervalMs }),
48
+ ...(options.quietPeriodMs === undefined ? {} : { quietPeriodMs: options.quietPeriodMs }),
49
+ ...(options.snapshotBuilder === undefined ? {} : { snapshotBuilder: options.snapshotBuilder })
50
+ });
51
+ projectWatchNativeBackends.set(coordinator, options.nativeWatch);
52
+ if (options.watchStateReader !== undefined)
53
+ projectWatchStateReaders.set(coordinator, options.watchStateReader);
54
+ return coordinator;
55
+ }
56
+ /**
57
+ * Turns filesystem hints into serialized complete project build transactions.
58
+ */
59
+ export class ProjectWatchCoordinator {
60
+ /** @type {ProjectBuilder} */
61
+ #builder;
62
+ /** @type {ProjectManifestLoader} */
63
+ #manifestLoader;
64
+ /** @type {ProjectSnapshotBuilder} */
65
+ #snapshotBuilder;
66
+ #quietPeriodMs;
67
+ #pollIntervalMs;
68
+ /** @type {ProjectWatchReporter | undefined} */
69
+ #reporter;
70
+ /** @type {string | undefined} */
71
+ #manifestPath;
72
+ /** @type {SemantifoldProject | undefined} */
73
+ #project;
74
+ /** @type {string | undefined} */
75
+ #publicationRoot;
76
+ /** @type {ProjectSnapshot | undefined} */
77
+ #lastSnapshot;
78
+ /** @type {string | undefined} */
79
+ #suppressedHash;
80
+ /** @type {string | undefined} */
81
+ #suppressedInvalidState;
82
+ /** @type {Map<string, string>} */
83
+ #watchStates = new Map();
84
+ /** @type {Set<string>} */
85
+ #watchedPaths = new Set();
86
+ /** @type {Map<string, string>} */
87
+ #displayPaths = new Map();
88
+ /** @type {import("node:fs").FSWatcher[]} */
89
+ #subscriptions = [];
90
+ /** @type {ReturnType<typeof setTimeout> | undefined} */
91
+ #quietTimer;
92
+ /** @type {ReturnType<typeof setInterval> | undefined} */
93
+ #pollTimer;
94
+ #polling = false;
95
+ #pollActive = false;
96
+ #pollFailed = false;
97
+ #cycle = 0;
98
+ #hintVersion = 0;
99
+ #dirty = false;
100
+ #cycleDirtyReported = false;
101
+ #commitWindow = false;
102
+ #hadFailure = false;
103
+ #running = false;
104
+ #stopping = false;
105
+ #finished = false;
106
+ #initialCycle = true;
107
+ #stopReason = "watch stopped";
108
+ /** @type {Set<string>} */
109
+ #hintPaths = new Set();
110
+ /** @type {AbortController | undefined} */
111
+ #activeController;
112
+ /** @type {AbortController | undefined} */
113
+ #publicationController;
114
+ /** @type {Promise<void> | undefined} */
115
+ #activeCycle;
116
+ /** @type {Promise<void> | undefined} */
117
+ #startup;
118
+ /** @type {Promise<Readonly<ProjectWatchResult>> | undefined} */
119
+ #completion;
120
+ /**
121
+ * Resolves the sole run completion.
122
+ * @type {(result: Readonly<ProjectWatchResult>) => void}
123
+ */
124
+ #resolveCompletion = () => { };
125
+ /** @type {() => void} */
126
+ #signalHandler;
127
+ /**
128
+ * Creates one idle coordinator without touching the filesystem.
129
+ * @param {{builder?: ProjectBuilder, manifestLoader?: ProjectManifestLoader, pollIntervalMs?: number, quietPeriodMs?: number, snapshotBuilder?: ProjectSnapshotBuilder}} [options] - Collaborators and bounded timing policy.
130
+ */
131
+ constructor(options = {}) {
132
+ if (!isPlainObject(options) || Object.keys(options).some(key => !["builder", "manifestLoader", "pollIntervalMs", "quietPeriodMs", "snapshotBuilder"].includes(key)) ||
133
+ options.builder !== undefined && !(options.builder instanceof ProjectBuilder) ||
134
+ options.manifestLoader !== undefined && !(options.manifestLoader instanceof ProjectManifestLoader) ||
135
+ options.snapshotBuilder !== undefined && !(options.snapshotBuilder instanceof ProjectSnapshotBuilder)) {
136
+ throw new TypeError("Invalid project watch coordinator options.");
137
+ }
138
+ const quietPeriodMs = options.quietPeriodMs ?? defaultQuietPeriodMs;
139
+ const pollIntervalMs = options.pollIntervalMs ?? defaultPollIntervalMs;
140
+ if (!validMilliseconds(quietPeriodMs, maximumQuietPeriodMs) || !validMilliseconds(pollIntervalMs, maximumPollIntervalMs)) {
141
+ throw new TypeError("Project watch timing values must be bounded positive integer milliseconds.");
142
+ }
143
+ this.#builder = options.builder ?? new ProjectBuilder();
144
+ this.#manifestLoader = options.manifestLoader ?? new ProjectManifestLoader();
145
+ this.#snapshotBuilder = options.snapshotBuilder ?? new ProjectSnapshotBuilder();
146
+ this.#quietPeriodMs = quietPeriodMs;
147
+ this.#pollIntervalMs = pollIntervalMs;
148
+ this.#signalHandler = () => {
149
+ void this.stop("termination signal");
150
+ };
151
+ }
152
+ /**
153
+ * Starts the initial build and remains active until shutdown or startup failure.
154
+ * @param {string} [projectPath] - Project manifest path.
155
+ * @param {ProjectWatchReporter} [reporter] - Watch protocol reporter.
156
+ * @param {{check?: boolean}} [options] - Whether every cycle runs target-owned checks.
157
+ * @returns {Promise<Readonly<ProjectWatchResult>>} Terminal watcher result.
158
+ */
159
+ run(projectPath = "./semantifold.json", reporter = new ProjectWatchReporter(), options = {}) {
160
+ if (this.#running || this.#completion !== undefined || typeof projectPath != "string" || projectPath.length == 0 ||
161
+ !(reporter instanceof ProjectWatchReporter) || !isPlainObject(options) ||
162
+ Object.keys(options).some(key => key != "check") || options.check !== undefined && typeof options.check != "boolean") {
163
+ throw new TypeError("Invalid or repeated project watch run.");
164
+ }
165
+ this.#running = true;
166
+ this.#reporter = reporter;
167
+ this.#manifestPath = projectPath;
168
+ this.#check = options.check === true;
169
+ this.#completion = new Promise(resolve => {
170
+ this.#resolveCompletion = resolve;
171
+ });
172
+ process.once("SIGINT", this.#signalHandler);
173
+ process.once("SIGTERM", this.#signalHandler);
174
+ const startup = this.#start(this.#check);
175
+ this.#startup = startup;
176
+ const startupSettled = () => {
177
+ if (this.#startup === startup)
178
+ this.#startup = undefined;
179
+ this.#finishStoppedIfIdle();
180
+ };
181
+ void startup.then(startupSettled, startupSettled);
182
+ return this.#completion;
183
+ }
184
+ /**
185
+ * Stops admitting work, cancels the exact active operation, and waits through child close and staging cleanup.
186
+ * @param {string} [reason] - Stable shutdown reason.
187
+ * @returns {Promise<Readonly<ProjectWatchResult>>} Terminal watcher result.
188
+ */
189
+ async stop(reason = "shutdown requested") {
190
+ if (typeof reason != "string" || reason.length == 0)
191
+ throw new TypeError("Project watch stop reason must be non-empty.");
192
+ if (this.#completion === undefined)
193
+ throw new TypeError("Project watch coordinator has not started.");
194
+ if (!this.#stopping && !this.#finished) {
195
+ this.#stopping = true;
196
+ this.#stopReason = reason;
197
+ this.#closeEventBackends();
198
+ this.#activeController?.abort(reason);
199
+ this.#publicationController?.abort(reason);
200
+ this.#finishStoppedIfIdle();
201
+ }
202
+ return this.#completion;
203
+ }
204
+ /**
205
+ * Establishes the validated graph, event backend, and initial cycle.
206
+ * @param {boolean} check - Cycle check mode.
207
+ * @returns {Promise<void>} Startup completion.
208
+ */
209
+ async #start(check) {
210
+ try {
211
+ const project = await this.#manifestLoader.load(this.#manifestPath);
212
+ if (this.#stopping)
213
+ return;
214
+ const snapshot = await this.#snapshotBuilder.build(project);
215
+ if (this.#stopping)
216
+ return;
217
+ this.#project = project;
218
+ this.#lastSnapshot = snapshot;
219
+ this.#setWatchTopology(project);
220
+ this.#watchStates = await this.#readWatchStates();
221
+ if (this.#stopping)
222
+ return;
223
+ this.#reporter?.watchStarted(project.id);
224
+ if (this.#stopping)
225
+ return;
226
+ this.#startEventBackend();
227
+ if (this.#stopping)
228
+ return;
229
+ await this.#admitCycle({ changedPaths: [], check, project, snapshot });
230
+ }
231
+ catch (error) {
232
+ if (!this.#stopping)
233
+ this.#finishFailed(error);
234
+ }
235
+ }
236
+ /**
237
+ * Runs exactly one owned cycle.
238
+ * @param {WatchCycleInput} input - Admitted cycle.
239
+ * @returns {Promise<void>}
240
+ */
241
+ async #admitCycle({ changedPaths, check, failure, project, snapshot }) {
242
+ if (this.#activeCycle !== undefined || this.#stopping)
243
+ return;
244
+ this.#cycle += 1;
245
+ const cycle = this.#cycle;
246
+ const activeController = new AbortController();
247
+ const publicationController = new AbortController();
248
+ this.#activeController = activeController;
249
+ this.#publicationController = publicationController;
250
+ this.#dirty = false;
251
+ this.#cycleDirtyReported = false;
252
+ this.#commitWindow = false;
253
+ this.#hintPaths.clear();
254
+ this.#reporter?.cycleStarted({
255
+ changedPaths,
256
+ cycle,
257
+ projectId: project?.id ?? this.#project?.id ?? "project",
258
+ ...(snapshot === undefined ? {} : { snapshotHash: snapshot.hash })
259
+ });
260
+ this.#observe({ cycle, status: "started", type: "cycle-start" });
261
+ let terminalStatus = /** @type {"cancelled" | "failed" | "recovered" | "succeeded" | "superseded"} */ ("failed");
262
+ /** @type {unknown} */
263
+ let terminalFailure;
264
+ /** @type {SemantifoldProject | undefined} */
265
+ let currentProject;
266
+ /** @type {ProjectSnapshot | undefined} */
267
+ let currentSnapshot;
268
+ const manifestPath = /** @type {string} */ (this.#manifestPath);
269
+ const reporter = /** @type {ProjectWatchReporter} */ (this.#reporter);
270
+ const execute = async () => {
271
+ try {
272
+ if (snapshot === undefined) {
273
+ throw failure ?? new SemantifoldDiagnostic({
274
+ code: "WATCH_SNAPSHOT_UNAVAILABLE",
275
+ language: project?.id ?? this.#project?.id ?? "project",
276
+ message: "The complete watched project graph is unavailable."
277
+ });
278
+ }
279
+ const result = await buildWatchedProject(this.#builder, manifestPath, reporter, {
280
+ check,
281
+ expectedSnapshotHash: snapshot.hash,
282
+ publicationSignal: publicationController.signal,
283
+ signal: activeController.signal,
284
+ validateCurrentSnapshot: async () => {
285
+ const guardHintVersion = this.#hintVersion;
286
+ /** @type {SemantifoldProject} */
287
+ let reconciledProject;
288
+ /** @type {ProjectSnapshot} */
289
+ let reconciledSnapshot;
290
+ try {
291
+ reconciledProject = await this.#manifestLoader.load(manifestPath);
292
+ reconciledSnapshot = await this.#snapshotBuilder.build(reconciledProject);
293
+ }
294
+ catch (error) {
295
+ throw new SemantifoldDiagnostic({
296
+ cause: error instanceof Error ? error : new Error(String(error)),
297
+ code: "WATCH_CANDIDATE_SUPERSEDED",
298
+ language: this.#project?.id ?? "project",
299
+ message: "The watched project graph became unavailable before candidate publication."
300
+ });
301
+ }
302
+ if (snapshot === undefined || reconciledSnapshot.hash != snapshot.hash) {
303
+ throw new SemantifoldDiagnostic({
304
+ code: "WATCH_CANDIDATE_SUPERSEDED",
305
+ language: reconciledProject.id,
306
+ message: "A newer complete project snapshot superseded the completed watch candidate."
307
+ });
308
+ }
309
+ currentProject = reconciledProject;
310
+ currentSnapshot = reconciledSnapshot;
311
+ this.#commitWindow = true;
312
+ if (this.#hintVersion == guardHintVersion) {
313
+ this.#dirty = false;
314
+ this.#hintPaths.clear();
315
+ }
316
+ else {
317
+ this.#dirty = true;
318
+ publicationController.abort("A filesystem hint arrived during final snapshot reconciliation.");
319
+ }
320
+ }
321
+ });
322
+ this.#commitWindow = false;
323
+ terminalStatus = this.#hadFailure ? "recovered" : "succeeded";
324
+ this.#hadFailure = false;
325
+ this.#suppressedHash = result.snapshotHash;
326
+ if (currentProject !== undefined && currentSnapshot !== undefined) {
327
+ this.#project = currentProject;
328
+ this.#lastSnapshot = currentSnapshot;
329
+ this.#setWatchTopology(currentProject);
330
+ const watchStates = await this.#readWatchStates();
331
+ const changedWatchPaths = changedWatchStatePaths(this.#watchStates, watchStates, this.#displayPaths);
332
+ if (changedWatchPaths.length == 0)
333
+ this.#watchStates = watchStates;
334
+ else
335
+ for (const changedPath of changedWatchPaths)
336
+ this.#hint(changedPath, check);
337
+ }
338
+ this.#reporter?.cycleSucceeded(result, terminalStatus == "recovered");
339
+ }
340
+ catch (error) {
341
+ terminalFailure = error;
342
+ terminalStatus = this.#stopping ? "cancelled" : supersededFailure(error, this.#dirty) ? "superseded" : "failed";
343
+ if (terminalStatus == "failed") {
344
+ this.#hadFailure = true;
345
+ if (snapshot !== undefined)
346
+ this.#suppressedHash = snapshot.hash;
347
+ }
348
+ this.#reporter?.cycleFailed(error, terminalStatus);
349
+ }
350
+ finally {
351
+ this.#commitWindow = false;
352
+ }
353
+ };
354
+ this.#activeCycle = execute();
355
+ await this.#activeCycle;
356
+ this.#activeCycle = undefined;
357
+ this.#activeController = undefined;
358
+ this.#publicationController = undefined;
359
+ this.#observe({ cycle, status: terminalStatus, type: "cycle-terminal" });
360
+ if (this.#stopping) {
361
+ this.#finishStoppedIfIdle();
362
+ return;
363
+ }
364
+ if (this.#initialCycle && terminalStatus == "failed") {
365
+ this.#finishFailed(terminalFailure);
366
+ return;
367
+ }
368
+ if (terminalStatus == "succeeded" || terminalStatus == "recovered")
369
+ this.#initialCycle = false;
370
+ if (this.#dirty || terminalStatus == "superseded") {
371
+ queueMicrotask(() => void this.#reconcile(check));
372
+ }
373
+ else {
374
+ this.#observe({ cycle, status: "ready", type: "ready" });
375
+ }
376
+ }
377
+ /**
378
+ * Re-reads the complete graph after a quiet period or active-cycle dirty marker.
379
+ * @param {boolean} check - Cycle check mode.
380
+ * @returns {Promise<void>} Reconciliation completion.
381
+ */
382
+ async #reconcile(check) {
383
+ if (this.#stopping || this.#activeCycle !== undefined)
384
+ return;
385
+ if (this.#quietTimer !== undefined) {
386
+ clearTimeout(this.#quietTimer);
387
+ this.#quietTimer = undefined;
388
+ }
389
+ const hinted = [...this.#hintPaths].sort(compareStrings);
390
+ this.#hintPaths.clear();
391
+ this.#dirty = false;
392
+ let project;
393
+ let snapshot;
394
+ let snapshotFailure;
395
+ try {
396
+ project = await this.#manifestLoader.load(this.#manifestPath);
397
+ snapshot = await this.#snapshotBuilder.build(project);
398
+ this.#suppressedInvalidState = undefined;
399
+ this.#setWatchTopology(project);
400
+ this.#watchStates = await this.#readWatchStates();
401
+ }
402
+ catch (error) {
403
+ snapshotFailure = error;
404
+ try {
405
+ this.#watchStates = await this.#readWatchStates();
406
+ }
407
+ catch {
408
+ // The build cycle below owns and reports the original complete-graph failure.
409
+ }
410
+ const invalidState = watchStateKey(this.#watchStates);
411
+ if (invalidState == this.#suppressedInvalidState) {
412
+ this.#reporter?.unchanged(hinted);
413
+ this.#observe({ status: "unchanged", type: "reconciled" });
414
+ return;
415
+ }
416
+ this.#suppressedInvalidState = invalidState;
417
+ }
418
+ if (snapshot !== undefined && snapshot.hash == this.#suppressedHash && !this.#hadFailure) {
419
+ this.#reporter?.unchanged(hinted);
420
+ this.#observe({ status: "unchanged", type: "reconciled" });
421
+ return;
422
+ }
423
+ const changedPaths = snapshot === undefined
424
+ ? hinted
425
+ : changedSnapshotPaths(this.#lastSnapshot, snapshot, path.basename(project?.manifestPath ?? this.#manifestPath ?? "semantifold.json"));
426
+ if (snapshot !== undefined)
427
+ this.#lastSnapshot = snapshot;
428
+ await this.#admitCycle({ changedPaths, check, failure: snapshotFailure, project, snapshot });
429
+ }
430
+ /**
431
+ * Coalesces one event hint without treating its filename as the build input set.
432
+ * @param {string | undefined} changedPath - Project-relative changed-path hint.
433
+ * @param {boolean} check - Check mode.
434
+ * @returns {void}
435
+ */
436
+ #hint(changedPath, check) {
437
+ if (this.#stopping)
438
+ return;
439
+ this.#hintVersion += 1;
440
+ if (changedPath !== undefined)
441
+ this.#hintPaths.add(changedPath);
442
+ if (this.#activeCycle !== undefined) {
443
+ this.#dirty = true;
444
+ if (this.#commitWindow)
445
+ this.#publicationController?.abort("A filesystem hint reached the active-pointer commit window.");
446
+ if (!this.#cycleDirtyReported) {
447
+ this.#cycleDirtyReported = true;
448
+ this.#reporter?.cycleDirty();
449
+ this.#observe({ cycle: this.#cycle, status: "dirty", type: "dirty" });
450
+ }
451
+ return;
452
+ }
453
+ if (this.#quietTimer !== undefined)
454
+ clearTimeout(this.#quietTimer);
455
+ this.#quietTimer = setTimeout(() => {
456
+ this.#quietTimer = undefined;
457
+ void this.#reconcile(check);
458
+ }, this.#quietPeriodMs);
459
+ }
460
+ /**
461
+ * Updates the exact manifest/source watch topology.
462
+ * @param {SemantifoldProject} project - Current valid project.
463
+ * @returns {void}
464
+ */
465
+ #setWatchTopology(project) {
466
+ const watchedPaths = new Set([project.manifestPath, ...project.sources.map(({ absolutePath }) => absolutePath)]);
467
+ const displayPaths = new Map([[project.manifestPath, path.basename(project.manifestPath)]]);
468
+ for (const source of project.sources)
469
+ displayPaths.set(source.absolutePath, source.path);
470
+ const changed = [...watchedPaths].sort(compareStrings).join("\0") != [...this.#watchedPaths].sort(compareStrings).join("\0");
471
+ this.#watchedPaths = watchedPaths;
472
+ this.#displayPaths = displayPaths;
473
+ this.#publicationRoot = project.publicationRoot;
474
+ if (changed && this.#subscriptions.length > 0 && !this.#polling && !this.#openNativeSubscriptions()) {
475
+ this.#switchToPolling();
476
+ }
477
+ }
478
+ /**
479
+ * Starts native subscriptions or their polling fallback.
480
+ * @returns {void}
481
+ */
482
+ #startEventBackend() {
483
+ if (this.#openNativeSubscriptions()) {
484
+ this.#ensurePollingReconciliation();
485
+ this.#reporter?.watchBackend("native");
486
+ this.#observe({ status: "native", type: "watch-backend" });
487
+ }
488
+ else
489
+ this.#switchToPolling();
490
+ }
491
+ /**
492
+ * Opens exact file and parent-directory subscriptions.
493
+ * @returns {boolean} Whether native subscriptions opened completely.
494
+ */
495
+ #openNativeSubscriptions() {
496
+ this.#closeSubscriptions();
497
+ const nativeWatch = projectWatchNativeBackends.get(this) ?? watchFileSystem;
498
+ try {
499
+ for (const filename of this.#watchedPaths) {
500
+ const subscription = nativeWatch(filename, () => {
501
+ this.#hint(this.#displayPaths.get(filename), this.#currentCheckMode());
502
+ });
503
+ subscription.once("error", () => this.#switchToPolling());
504
+ this.#subscriptions.push(subscription);
505
+ }
506
+ const parents = new Set([...this.#watchedPaths].map(filename => path.dirname(filename)));
507
+ for (const directory of parents) {
508
+ const subscription = nativeWatch(directory, (_, filename) => {
509
+ if (filename == null) {
510
+ this.#hint(undefined, this.#currentCheckMode());
511
+ return;
512
+ }
513
+ const absolute = path.join(directory, filename.toString());
514
+ if (this.#publicationRoot !== undefined && pathsOverlap(this.#publicationRoot, absolute))
515
+ return;
516
+ this.#hint(this.#displayPaths.get(absolute), this.#currentCheckMode());
517
+ });
518
+ subscription.once("error", () => this.#switchToPolling());
519
+ this.#subscriptions.push(subscription);
520
+ }
521
+ return true;
522
+ }
523
+ catch {
524
+ this.#closeSubscriptions();
525
+ return false;
526
+ }
527
+ }
528
+ /**
529
+ * Permanently selects bounded polling after native backend failure.
530
+ * @returns {void}
531
+ */
532
+ #switchToPolling() {
533
+ if (this.#stopping || this.#polling)
534
+ return;
535
+ this.#polling = true;
536
+ this.#closeSubscriptions();
537
+ this.#ensurePollingReconciliation();
538
+ this.#reporter?.watchBackend("polling");
539
+ this.#observe({ status: "polling", type: "watch-backend" });
540
+ }
541
+ /**
542
+ * Compares one bounded polling state observation.
543
+ * @returns {Promise<void>} Poll completion.
544
+ */
545
+ async #poll() {
546
+ if (this.#pollActive || this.#stopping)
547
+ return;
548
+ this.#pollActive = true;
549
+ try {
550
+ if (this.#suppressedInvalidState !== undefined) {
551
+ try {
552
+ const project = await this.#manifestLoader.load(this.#manifestPath);
553
+ await this.#snapshotBuilder.build(project);
554
+ if (this.#quietTimer === undefined)
555
+ this.#hint(undefined, this.#currentCheckMode());
556
+ return;
557
+ }
558
+ catch {
559
+ // An unchanged invalid graph remains one failed cycle until it becomes readable and valid.
560
+ }
561
+ }
562
+ const current = await this.#readWatchStates();
563
+ const changed = changedWatchStatePaths(this.#watchStates, current, this.#displayPaths);
564
+ this.#pollFailed = false;
565
+ if (changed.length == 0)
566
+ return;
567
+ this.#watchStates = current;
568
+ for (const changedPath of changed)
569
+ this.#hint(changedPath, this.#currentCheckMode());
570
+ }
571
+ catch {
572
+ if (!this.#pollFailed) {
573
+ this.#pollFailed = true;
574
+ this.#hint(undefined, this.#currentCheckMode());
575
+ }
576
+ }
577
+ finally {
578
+ this.#pollActive = false;
579
+ }
580
+ }
581
+ /**
582
+ * Reads the immutable check mode captured by run.
583
+ * @returns {boolean} Active check mode.
584
+ */
585
+ #currentCheckMode() {
586
+ return this.#check;
587
+ }
588
+ /**
589
+ * Reads one detached mutation-sensitive state observation through the selected backend.
590
+ * @returns {Promise<Map<string, string>>} Stable ordered path states.
591
+ */
592
+ #readWatchStates() {
593
+ const reader = projectWatchStateReaders.get(this) ?? readWatchStates;
594
+ return reader(new Set(this.#watchedPaths));
595
+ }
596
+ #check = false;
597
+ /**
598
+ * Starts one bounded reconciliation interval shared by native and fallback modes.
599
+ * @returns {void}
600
+ */
601
+ #ensurePollingReconciliation() {
602
+ this.#pollTimer ??= setInterval(() => void this.#poll(), this.#pollIntervalMs);
603
+ }
604
+ /**
605
+ * Closes every native subscription.
606
+ * @returns {void}
607
+ */
608
+ #closeSubscriptions() {
609
+ for (const subscription of this.#subscriptions)
610
+ subscription.close();
611
+ this.#subscriptions = [];
612
+ }
613
+ /**
614
+ * Closes subscriptions and pending reconciliation timers.
615
+ * @returns {void}
616
+ */
617
+ #closeEventBackends() {
618
+ if (this.#quietTimer !== undefined)
619
+ clearTimeout(this.#quietTimer);
620
+ if (this.#pollTimer !== undefined)
621
+ clearInterval(this.#pollTimer);
622
+ this.#quietTimer = undefined;
623
+ this.#pollTimer = undefined;
624
+ this.#closeSubscriptions();
625
+ }
626
+ /**
627
+ * Resolves shutdown only after startup and the active cycle have both relinquished ownership.
628
+ * @returns {void}
629
+ */
630
+ #finishStoppedIfIdle() {
631
+ if (this.#stopping && this.#startup === undefined && this.#activeCycle === undefined)
632
+ this.#finishStopped();
633
+ }
634
+ /**
635
+ * Emits and resolves one clean watcher terminal.
636
+ * @returns {void}
637
+ */
638
+ #finishStopped() {
639
+ if (this.#finished)
640
+ return;
641
+ this.#finished = true;
642
+ this.#running = false;
643
+ this.#closeEventBackends();
644
+ this.#removeSignalHandlers();
645
+ this.#reporter?.watchStopped(this.#stopReason);
646
+ const result = Object.freeze({ cycles: this.#cycle, reason: this.#stopReason, status: /** @type {const} */ ("stopped") });
647
+ this.#observe({ status: "stopped", type: "stopped" });
648
+ this.#resolveCompletion(result);
649
+ }
650
+ /**
651
+ * Emits and resolves one startup-failure watcher terminal.
652
+ * @param {unknown} failure - Startup failure.
653
+ * @returns {void}
654
+ */
655
+ #finishFailed(failure) {
656
+ if (this.#finished)
657
+ return;
658
+ this.#finished = true;
659
+ this.#running = false;
660
+ this.#closeEventBackends();
661
+ this.#removeSignalHandlers();
662
+ this.#reporter?.watchFailed(failure);
663
+ const result = Object.freeze({ cycles: this.#cycle, reason: "startup failure", status: /** @type {const} */ ("failed") });
664
+ this.#observe({ status: "failed", type: "stopped" });
665
+ this.#resolveCompletion(result);
666
+ }
667
+ /**
668
+ * Removes process signal handlers owned by this coordinator.
669
+ * @returns {void}
670
+ */
671
+ #removeSignalHandlers() {
672
+ process.removeListener("SIGINT", this.#signalHandler);
673
+ process.removeListener("SIGTERM", this.#signalHandler);
674
+ }
675
+ /**
676
+ * Emits one internal deterministic lifecycle marker.
677
+ * @param {ProjectWatchObservation} event - Marker.
678
+ * @returns {void}
679
+ */
680
+ #observe(event) {
681
+ projectWatchObservers.get(this)?.(Object.freeze(event));
682
+ }
683
+ }
684
+ /**
685
+ * Reads mutation-sensitive states only as polling/event deduplication hints.
686
+ * Content hashes remain authoritative for cycle admission.
687
+ * @param {Readonly<Set<string>>} filenames - Exact watched graph paths.
688
+ * @returns {Promise<Map<string, string>>} Stable ordered path states.
689
+ */
690
+ async function readWatchStates(filenames) {
691
+ const result = new Map();
692
+ for (const filename of [...filenames].sort(compareStrings)) {
693
+ try {
694
+ const status = await lstat(filename, { bigint: true });
695
+ result.set(filename, [status.dev, status.ino, status.mode, status.size, status.mtimeNs, status.ctimeNs].map(String).join(":"));
696
+ }
697
+ catch (error) {
698
+ if (!isErrorCode(error, "ENOENT"))
699
+ throw error;
700
+ result.set(filename, "missing");
701
+ }
702
+ }
703
+ return result;
704
+ }
705
+ /**
706
+ * @typedef {(filenames: Readonly<Set<string>>) => Promise<Map<string, string>>} ProjectWatchStateReader
707
+ */
708
+ /**
709
+ * Locates polling changes without treating metadata as build identity.
710
+ * @param {Map<string, string>} previous - Previous states.
711
+ * @param {Map<string, string>} current - Current states.
712
+ * @param {Map<string, string>} displayPaths - Stable project-relative names.
713
+ * @returns {string[]} Changed project paths.
714
+ */
715
+ function changedWatchStatePaths(previous, current, displayPaths) {
716
+ const filenames = new Set([...previous.keys(), ...current.keys()]);
717
+ return [...filenames].filter(filename => previous.get(filename) != current.get(filename))
718
+ .map(filename => displayPaths.get(filename) ?? path.basename(filename)).sort(compareStrings);
719
+ }
720
+ /**
721
+ * Serializes one ordered polling state only for repeated-invalid reconciliation suppression.
722
+ * @param {Map<string, string>} states - Current watched path states.
723
+ * @returns {string} Stable state key.
724
+ */
725
+ function watchStateKey(states) {
726
+ return JSON.stringify([...states].sort(([left], [right]) => compareStrings(left, right)));
727
+ }
728
+ /**
729
+ * Checks whether either absolute path contains the other.
730
+ * @param {string} left - First absolute path.
731
+ * @param {string} right - Second absolute path.
732
+ * @returns {boolean} Whether the paths overlap.
733
+ */
734
+ function pathsOverlap(left, right) {
735
+ return pathWithin(left, right) || pathWithin(right, left);
736
+ }
737
+ /**
738
+ * Checks whether one absolute path is a root or descendant of another.
739
+ * @param {string} root - Absolute root.
740
+ * @param {string} candidate - Absolute candidate.
741
+ * @returns {boolean} Whether the candidate belongs to the root.
742
+ */
743
+ function pathWithin(root, candidate) {
744
+ const relative = path.relative(root, candidate);
745
+ return relative.length == 0 || relative != ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
746
+ }
747
+ /**
748
+ * Computes exact content/config changes between complete immutable snapshots.
749
+ * @param {ProjectSnapshot | undefined} previous - Previous admitted snapshot.
750
+ * @param {ProjectSnapshot} current - Current complete snapshot.
751
+ * @param {string} manifestPath - Project-root-relative manifest display path.
752
+ * @returns {string[]} Stable changed paths.
753
+ */
754
+ function changedSnapshotPaths(previous, current, manifestPath) {
755
+ if (previous === undefined)
756
+ return [manifestPath, ...current.sources.map(({ path: sourcePath }) => sourcePath)];
757
+ const changed = new Set();
758
+ if (previous.manifestText != current.manifestText)
759
+ changed.add(manifestPath);
760
+ const previousSources = new Map(previous.sources.map(source => [source.path, source.source]));
761
+ const currentSources = new Map(current.sources.map(source => [source.path, source.source]));
762
+ for (const sourcePath of new Set([...previousSources.keys(), ...currentSources.keys()])) {
763
+ if (previousSources.get(sourcePath) != currentSources.get(sourcePath))
764
+ changed.add(sourcePath);
765
+ }
766
+ return [...changed].sort(compareStrings);
767
+ }
768
+ /**
769
+ * Recognizes failures caused only by deterministic supersession.
770
+ * @param {unknown} failure - Candidate failure.
771
+ * @param {boolean} dirty - Whether a newer hint exists.
772
+ * @returns {boolean} Whether the cycle was superseded.
773
+ */
774
+ function supersededFailure(failure, dirty) {
775
+ let current = failure;
776
+ while (current instanceof Error) {
777
+ if ("code" in current && (current.code == "WATCH_CANDIDATE_SUPERSEDED" || current.code == "WATCH_SNAPSHOT_CHANGED" ||
778
+ dirty && current.code == "PUBLICATION_CANCELLED"))
779
+ return true;
780
+ current = current.cause;
781
+ }
782
+ return false;
783
+ }
784
+ /**
785
+ * Checks one ordinary object.
786
+ * @param {unknown} value - Candidate.
787
+ * @returns {value is Record<string, unknown>} Whether the value is a plain object.
788
+ */
789
+ function isPlainObject(value) {
790
+ return typeof value == "object" && value != null && !Array.isArray(value) && Object.getPrototypeOf(value) == Object.prototype;
791
+ }
792
+ /**
793
+ * Checks one bounded positive integer timing value.
794
+ * @param {number} value - Candidate milliseconds.
795
+ * @param {number} maximum - Inclusive maximum.
796
+ * @returns {boolean} Whether the value is valid.
797
+ */
798
+ function validMilliseconds(value, maximum) {
799
+ return typeof value == "number" && Number.isInteger(value) && value > 0 && value <= maximum;
800
+ }
801
+ /**
802
+ * Checks a narrowed filesystem error code.
803
+ * @param {unknown} error - Opaque error.
804
+ * @param {string} code - Expected code.
805
+ * @returns {boolean} Whether the code matches.
806
+ */
807
+ function isErrorCode(error, code) {
808
+ return error instanceof Error && "code" in error && error.code == code;
809
+ }
810
+ /**
811
+ * Compares stable protocol strings.
812
+ * @param {string} left - Left string.
813
+ * @param {string} right - Right string.
814
+ * @returns {number} Sort order.
815
+ */
816
+ function compareStrings(left, right) {
817
+ return left.localeCompare(right, "en");
818
+ }
819
+ /**
820
+ * @typedef ProjectWatchObservation
821
+ * @property {"cycle-start" | "cycle-terminal" | "dirty" | "ready" | "reconciled" | "stopped" | "watch-backend"} type - Marker type.
822
+ * @property {number} [cycle] - Related cycle number.
823
+ * @property {"cancelled" | "dirty" | "failed" | "native" | "polling" | "ready" | "recovered" | "started" | "stopped" | "succeeded" | "superseded" | "unchanged"} status - Marker status.
824
+ */
825
+ /**
826
+ * @typedef ProjectWatchResult
827
+ * @property {"failed" | "stopped"} status - Watcher terminal state.
828
+ * @property {number} cycles - Admitted cycle count.
829
+ * @property {string} reason - Stable terminal reason.
830
+ */
831
+ /**
832
+ * @typedef WatchCycleInput
833
+ * @property {readonly string[]} changedPaths - Stable changed paths.
834
+ * @property {boolean} check - Whether target checks are enabled.
835
+ * @property {unknown} [failure] - Preserved reconciliation failure.
836
+ * @property {SemantifoldProject | undefined} project - Reconciled project, when valid.
837
+ * @property {ProjectSnapshot | undefined} snapshot - Reconciled snapshot, when valid.
838
+ */
839
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvamVjdC13YXRjaC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcm9qZWN0LXdhdGNoLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEVBQUMsS0FBSyxJQUFJLGVBQWUsRUFBQyxNQUFNLFNBQVMsQ0FBQTtBQUNoRCxPQUFPLEVBQUMsS0FBSyxFQUFDLE1BQU0sa0JBQWtCLENBQUE7QUFDdEMsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFBO0FBQzVCLE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLGlCQUFpQixDQUFBO0FBQ3JELE9BQU8sRUFBQyxtQkFBbUIsRUFBRSxjQUFjLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQTtBQUN0RSxPQUFPLEVBQUMscUJBQXFCLEVBQUUsa0JBQWtCLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQTtBQUMvRSxPQUFPLEVBQUMsZUFBZSxFQUFFLHNCQUFzQixFQUFDLE1BQU0sdUJBQXVCLENBQUE7QUFDN0UsT0FBTyxFQUFDLG9CQUFvQixFQUFDLE1BQU0sNkJBQTZCLENBQUE7QUFFaEUsTUFBTSxvQkFBb0IsR0FBRyxFQUFFLENBQUE7QUFDL0IsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLENBQUE7QUFDbEMsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLENBQUE7QUFDbkMsTUFBTSxxQkFBcUIsR0FBRyxNQUFNLENBQUE7QUFDcEMseUZBQXlGO0FBQ3pGLE1BQU0scUJBQXFCLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQTtBQUMzQyx1RUFBdUU7QUFDdkUsTUFBTSwwQkFBMEIsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFBO0FBQ2hELHdFQUF3RTtBQUN4RSxNQUFNLHdCQUF3QixHQUFHLElBQUksT0FBTyxFQUFFLENBQUE7QUFFOUM7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUFDLFdBQVcsRUFBRSxRQUFRO0lBQ3ZELElBQUksQ0FBQyxDQUFDLFdBQVcsWUFBWSx1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QUFFLElBQUksQ0FBQyxDQUFBO0FBQ3hDLENBQUM7QUFFRDs7Ozs7R0FLRztBQUVIOzs7OztHQUtHO0FBRUg7Ozs7Ozs7R0FPRyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQge3dhdGNoIGFzIHdhdGNoRmlsZVN5c3RlbX0gZnJvbSBcIm5vZGU6ZnNcIlxuaW1wb3J0IHtsc3RhdH0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIlxuaW1wb3J0IHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiXG5pbXBvcnQge1NlbWFudGlmb2xkRGlhZ25vc3RpY30gZnJvbSBcIi4vZGlhZ25vc3RpYy5qc1wiXG5pbXBvcnQge2J1aWxkV2F0Y2hlZFByb2plY3QsIFByb2plY3RCdWlsZGVyfSBmcm9tIFwiLi9wcm9qZWN0LWJ1aWxkLmpzXCJcbmltcG9ydCB7UHJvamVjdE1hbmlmZXN0TG9hZGVyLCBTZW1hbnRpZm9sZFByb2plY3R9IGZyb20gXCIuL3Byb2plY3QtbWFuaWZlc3QuanNcIlxuaW1wb3J0IHtQcm9qZWN0U25hcHNob3QsIFByb2plY3RTbmFwc2hvdEJ1aWxkZXJ9IGZyb20gXCIuL3Byb2plY3Qtc25hcHNob3QuanNcIlxuaW1wb3J0IHtQcm9qZWN0V2F0Y2hSZXBvcnRlcn0gZnJvbSBcIi4vcHJvamVjdC13YXRjaC1yZXBvcnRlci5qc1wiXG5cbmNvbnN0IGRlZmF1bHRRdWlldFBlcmlvZE1zID0gNTBcbmNvbnN0IGRlZmF1bHRQb2xsSW50ZXJ2YWxNcyA9IDEwMDBcbmNvbnN0IG1heGltdW1RdWlldFBlcmlvZE1zID0gMTBfMDAwXG5jb25zdCBtYXhpbXVtUG9sbEludGVydmFsTXMgPSA2MF8wMDBcbi8qKiBAdHlwZSB7V2Vha01hcDxQcm9qZWN0V2F0Y2hDb29yZGluYXRvciwgKGV2ZW50OiBQcm9qZWN0V2F0Y2hPYnNlcnZhdGlvbikgPT4gdm9pZD59ICovXG5jb25zdCBwcm9qZWN0V2F0Y2hPYnNlcnZlcnMgPSBuZXcgV2Vha01hcCgpXG4vKiogQHR5cGUge1dlYWtNYXA8UHJvamVjdFdhdGNoQ29vcmRpbmF0b3IsIHR5cGVvZiB3YXRjaEZpbGVTeXN0ZW0+fSAqL1xuY29uc3QgcHJvamVjdFdhdGNoTmF0aXZlQmFja2VuZHMgPSBuZXcgV2Vha01hcCgpXG4vKiogQHR5cGUge1dlYWtNYXA8UHJvamVjdFdhdGNoQ29vcmRpbmF0b3IsIFByb2plY3RXYXRjaFN0YXRlUmVhZGVyPn0gKi9cbmNvbnN0IHByb2plY3RXYXRjaFN0YXRlUmVhZGVycyA9IG5ldyBXZWFrTWFwKClcblxuLyoqXG4gKiBJbnN0YWxscyBhIHN5bmNocm9ub3VzIGxpZmVjeWNsZSBvYnNlcnZlciBmb3IgZm9jdXNlZCBjb29yZGluYXRpb24gc3BlY3MuXG4gKiBUaGlzIGhlbHBlciBpcyBpbnRlbnRpb25hbGx5IG5vdCBwYXJ0IG9mIHRoZSBwYWNrYWdlIHJvb3QgQVBJLlxuICogQHBhcmFtIHtQcm9qZWN0V2F0Y2hDb29yZGluYXRvcn0gY29vcmRpbmF0b3IgLSBDb29yZGluYXRvciBpbnN0YW5jZS5cbiAqIEBwYXJhbSB7KGV2ZW50OiBQcm9qZWN0V2F0Y2hPYnNlcnZhdGlvbikgPT4gdm9pZH0gb2JzZXJ2ZXIgLSBNYXJrZXIgb2JzZXJ2ZXIuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9ic2VydmVQcm9qZWN0V2F0Y2goY29vcmRpbmF0b3IsIG9ic2VydmVyKSB7XG4gIGlmICghKGNvb3JkaW5hdG9yIGluc3RhbmNlb2YgUHJvamVjdFdhdGNoQ29vcmRpbmF0b3IpIHx8IHR5cGVvZiBvYnNlcnZlciAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiSW52YWxpZCBwcm9qZWN0IHdhdGNoIG9ic2VydmVyLlwiKVxuICB9XG4gIHByb2plY3RXYXRjaE9ic2VydmVycy5zZXQoY29vcmRpbmF0b3IsIG9ic2VydmVyKVxufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBjb29yZGluYXRvciB3aXRoIG9uZSBpbnN0YW5jZS1vd25lZCBuYXRpdmUgZXZlbnQgYmFja2VuZCBmb3IgZm9jdXNlZCBmYWxsYmFjayBzcGVjcy5cbiAqIFRoaXMgaGVscGVyIGlzIGludGVudGlvbmFsbHkgbm90IHBhcnQgb2YgdGhlIHBhY2thZ2Ugcm9vdCBBUEkuXG4gKiBAcGFyYW0ge3tidWlsZGVyPzogUHJvamVjdEJ1aWxkZXIsIG1hbmlmZXN0TG9hZGVyPzogUHJvamVjdE1hbmlmZXN0TG9hZGVyLCBuYXRpdmVXYXRjaDogdHlwZW9mIHdhdGNoRmlsZVN5c3RlbSwgcG9sbEludGVydmFsTXM/OiBudW1iZXIsIHF1aWV0UGVyaW9kTXM/OiBudW1iZXIsIHNuYXBzaG90QnVpbGRlcj86IFByb2plY3RTbmFwc2hvdEJ1aWxkZXIsIHdhdGNoU3RhdGVSZWFkZXI/OiBQcm9qZWN0V2F0Y2hTdGF0ZVJlYWRlcn19IG9wdGlvbnMgLSBDb29yZGluYXRvciBvcHRpb25zIGFuZCBiYWNrZW5kcy5cbiAqIEByZXR1cm5zIHtQcm9qZWN0V2F0Y2hDb29yZGluYXRvcn0gQ29uZmlndXJlZCBjb29yZGluYXRvci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVByb2plY3RXYXRjaENvb3JkaW5hdG9yKG9wdGlvbnMpIHtcbiAgaWYgKCFpc1BsYWluT2JqZWN0KG9wdGlvbnMpIHx8IHR5cGVvZiBvcHRpb25zLm5hdGl2ZVdhdGNoICE9IFwiZnVuY3Rpb25cIiB8fFxuICAgIG9wdGlvbnMud2F0Y2hTdGF0ZVJlYWRlciAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBvcHRpb25zLndhdGNoU3RhdGVSZWFkZXIgIT0gXCJmdW5jdGlvblwiKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgcHJvamVjdCB3YXRjaCBjb29yZGluYXRvciBkZXBlbmRlbmNpZXMuXCIpXG4gIH1cbiAgY29uc3QgY29vcmRpbmF0b3IgPSBuZXcgUHJvamVjdFdhdGNoQ29vcmRpbmF0b3Ioe1xuICAgIC4uLihvcHRpb25zLmJ1aWxkZXIgPT09IHVuZGVmaW5lZCA/IHt9IDoge2J1aWxkZXI6IG9wdGlvbnMuYnVpbGRlcn0pLFxuICAgIC4uLihvcHRpb25zLm1hbmlmZXN0TG9hZGVyID09PSB1bmRlZmluZWQgPyB7fSA6IHttYW5pZmVzdExvYWRlcjogb3B0aW9ucy5tYW5pZmVzdExvYWRlcn0pLFxuICAgIC4uLihvcHRpb25zLnBvbGxJbnRlcnZhbE1zID09PSB1bmRlZmluZWQgPyB7fSA6IHtwb2xsSW50ZXJ2YWxNczogb3B0aW9ucy5wb2xsSW50ZXJ2YWxNc30pLFxuICAgIC4uLihvcHRpb25zLnF1aWV0UGVyaW9kTXMgPT09IHVuZGVmaW5lZCA/IHt9IDoge3F1aWV0UGVyaW9kTXM6IG9wdGlvbnMucXVpZXRQZXJpb2RNc30pLFxuICAgIC4uLihvcHRpb25zLnNuYXBzaG90QnVpbGRlciA9PT0gdW5kZWZpbmVkID8ge30gOiB7c25hcHNob3RCdWlsZGVyOiBvcHRpb25zLnNuYXBzaG90QnVpbGRlcn0pXG4gIH0pXG5cbiAgcHJvamVjdFdhdGNoTmF0aXZlQmFja2VuZHMuc2V0KGNvb3JkaW5hdG9yLCBvcHRpb25zLm5hdGl2ZVdhdGNoKVxuICBpZiAob3B0aW9ucy53YXRjaFN0YXRlUmVhZGVyICE9PSB1bmRlZmluZWQpIHByb2plY3RXYXRjaFN0YXRlUmVhZGVycy5zZXQoY29vcmRpbmF0b3IsIG9wdGlvbnMud2F0Y2hTdGF0ZVJlYWRlcilcblxuICByZXR1cm4gY29vcmRpbmF0b3Jcbn1cblxuLyoqXG4gKiBUdXJucyBmaWxlc3lzdGVtIGhpbnRzIGludG8gc2VyaWFsaXplZCBjb21wbGV0ZSBwcm9qZWN0IGJ1aWxkIHRyYW5zYWN0aW9ucy5cbiAqL1xuZXhwb3J0IGNsYXNzIFByb2plY3RXYXRjaENvb3JkaW5hdG9yIHtcbiAgLyoqIEB0eXBlIHtQcm9qZWN0QnVpbGRlcn0gKi9cbiAgI2J1aWxkZXJcbiAgLyoqIEB0eXBlIHtQcm9qZWN0TWFuaWZlc3RMb2FkZXJ9ICovXG4gICNtYW5pZmVzdExvYWRlclxuICAvKiogQHR5cGUge1Byb2plY3RTbmFwc2hvdEJ1aWxkZXJ9ICovXG4gICNzbmFwc2hvdEJ1aWxkZXJcbiAgI3F1aWV0UGVyaW9kTXNcbiAgI3BvbGxJbnRlcnZhbE1zXG4gIC8qKiBAdHlwZSB7UHJvamVjdFdhdGNoUmVwb3J0ZXIgfCB1bmRlZmluZWR9ICovXG4gICNyZXBvcnRlclxuICAvKiogQHR5cGUge3N0cmluZyB8IHVuZGVmaW5lZH0gKi9cbiAgI21hbmlmZXN0UGF0aFxuICAvKiogQHR5cGUge1NlbWFudGlmb2xkUHJvamVjdCB8IHVuZGVmaW5lZH0gKi9cbiAgI3Byb2plY3RcbiAgLyoqIEB0eXBlIHtzdHJpbmcgfCB1bmRlZmluZWR9ICovXG4gICNwdWJsaWNhdGlvblJvb3RcbiAgLyoqIEB0eXBlIHtQcm9qZWN0U25hcHNob3QgfCB1bmRlZmluZWR9ICovXG4gICNsYXN0U25hcHNob3RcbiAgLyoqIEB0eXBlIHtzdHJpbmcgfCB1bmRlZmluZWR9ICovXG4gICNzdXBwcmVzc2VkSGFzaFxuICAvKiogQHR5cGUge3N0cmluZyB8IHVuZGVmaW5lZH0gKi9cbiAgI3N1cHByZXNzZWRJbnZhbGlkU3RhdGVcbiAgLyoqIEB0eXBlIHtNYXA8c3RyaW5nLCBzdHJpbmc+fSAqL1xuICAjd2F0Y2hTdGF0ZXMgPSBuZXcgTWFwKClcbiAgLyoqIEB0eXBlIHtTZXQ8c3RyaW5nPn0gKi9cbiAgI3dhdGNoZWRQYXRocyA9IG5ldyBTZXQoKVxuICAvKiogQHR5cGUge01hcDxzdHJpbmcsIHN0cmluZz59ICovXG4gICNkaXNwbGF5UGF0aHMgPSBuZXcgTWFwKClcbiAgLyoqIEB0eXBlIHtpbXBvcnQoXCJub2RlOmZzXCIpLkZTV2F0Y2hlcltdfSAqL1xuICAjc3Vic2NyaXB0aW9ucyA9IFtdXG4gIC8qKiBAdHlwZSB7UmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCB1bmRlZmluZWR9ICovXG4gICNxdWlldFRpbWVyXG4gIC8qKiBAdHlwZSB7UmV0dXJuVHlwZTx0eXBlb2Ygc2V0SW50ZXJ2YWw+IHwgdW5kZWZpbmVkfSAqL1xuICAjcG9sbFRpbWVyXG4gICNwb2xsaW5nID0gZmFsc2VcbiAgI3BvbGxBY3RpdmUgPSBmYWxzZVxuICAjcG9sbEZhaWxlZCA9IGZhbHNlXG4gICNjeWNsZSA9IDBcbiAgI2hpbnRWZXJzaW9uID0gMFxuICAjZGlydHkgPSBmYWxzZVxuICAjY3ljbGVEaXJ0eVJlcG9ydGVkID0gZmFsc2VcbiAgI2NvbW1pdFdpbmRvdyA9IGZhbHNlXG4gICNoYWRGYWlsdXJlID0gZmFsc2VcbiAgI3J1bm5pbmcgPSBmYWxzZVxuICAjc3RvcHBpbmcgPSBmYWxzZVxuICAjZmluaXNoZWQgPSBmYWxzZVxuICAjaW5pdGlhbEN5Y2xlID0gdHJ1ZVxuICAjc3RvcFJlYXNvbiA9IFwid2F0Y2ggc3RvcHBlZFwiXG4gIC8qKiBAdHlwZSB7U2V0PHN0cmluZz59ICovXG4gICNoaW50UGF0aHMgPSBuZXcgU2V0KClcbiAgLyoqIEB0eXBlIHtBYm9ydENvbnRyb2xsZXIgfCB1bmRlZmluZWR9ICovXG4gICNhY3RpdmVDb250cm9sbGVyXG4gIC8qKiBAdHlwZSB7QWJvcnRDb250cm9sbGVyIHwgdW5kZWZpbmVkfSAqL1xuICAjcHVibGljYXRpb25Db250cm9sbGVyXG4gIC8qKiBAdHlwZSB7UHJvbWlzZTx2b2lkPiB8IHVuZGVmaW5lZH0gKi9cbiAgI2FjdGl2ZUN5Y2xlXG4gIC8qKiBAdHlwZSB7UHJvbWlzZTx2b2lkPiB8IHVuZGVmaW5lZH0gKi9cbiAgI3N0YXJ0dXBcbiAgLyoqIEB0eXBlIHtQcm9taXNlPFJlYWRvbmx5PFByb2plY3RXYXRjaFJlc3VsdD4+IHwgdW5kZWZpbmVkfSAqL1xuICAjY29tcGxldGlvblxuICAvKipcbiAgICogUmVzb2x2ZXMgdGhlIHNvbGUgcnVuIGNvbXBsZXRpb24uXG4gICAqIEB0eXBlIHsocmVzdWx0OiBSZWFkb25seTxQcm9qZWN0V2F0Y2hSZXN1bHQ+KSA9PiB2b2lkfVxuICAgKi9cbiAgI3Jlc29sdmVDb21wbGV0aW9uID0gKCkgPT4ge31cbiAgLyoqIEB0eXBlIHsoKSA9PiB2b2lkfSAqL1xuICAjc2lnbmFsSGFuZGxlclxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIG9uZSBpZGxlIGNvb3JkaW5hdG9yIHdpdGhvdXQgdG91Y2hpbmcgdGhlIGZpbGVzeXN0ZW0uXG4gICAqIEBwYXJhbSB7e2J1aWxkZXI/OiBQcm9qZWN0QnVpbGRlciwgbWFuaWZlc3RMb2FkZXI/OiBQcm9qZWN0TWFuaWZlc3RMb2FkZXIsIHBvbGxJbnRlcnZhbE1zPzogbnVtYmVyLCBxdWlldFBlcmlvZE1zPzogbnVtYmVyLCBzbmFwc2hvdEJ1aWxkZXI/OiBQcm9qZWN0U25hcHNob3RCdWlsZGVyfX0gW29wdGlvbnNdIC0gQ29sbGFib3JhdG9ycyBhbmQgYm91bmRlZCB0aW1pbmcgcG9saWN5LlxuICAgKi9cbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKCFpc1BsYWluT2JqZWN0KG9wdGlvbnMpIHx8IE9iamVjdC5rZXlzKG9wdGlvbnMpLnNvbWUoa2V5ID0+XG4gICAgICAhW1wiYnVpbGRlclwiLCBcIm1hbmlmZXN0TG9hZGVyXCIsIFwicG9sbEludGVydmFsTXNcIiwgXCJxdWlldFBlcmlvZE1zXCIsIFwic25hcHNob3RCdWlsZGVyXCJdLmluY2x1ZGVzKGtleSkpIHx8XG4gICAgICBvcHRpb25zLmJ1aWxkZXIgIT09IHVuZGVmaW5lZCAmJiAhKG9wdGlvbnMuYnVpbGRlciBpbnN0YW5jZW9mIFByb2plY3RCdWlsZGVyKSB8fFxuICAgICAgb3B0aW9ucy5tYW5pZmVzdExvYWRlciAhPT0gdW5kZWZpbmVkICYmICEob3B0aW9ucy5tYW5pZmVzdExvYWRlciBpbnN0YW5jZW9mIFByb2plY3RNYW5pZmVzdExvYWRlcikgfHxcbiAgICAgIG9wdGlvbnMuc25hcHNob3RCdWlsZGVyICE9PSB1bmRlZmluZWQgJiYgIShvcHRpb25zLnNuYXBzaG90QnVpbGRlciBpbnN0YW5jZW9mIFByb2plY3RTbmFwc2hvdEJ1aWxkZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiSW52YWxpZCBwcm9qZWN0IHdhdGNoIGNvb3JkaW5hdG9yIG9wdGlvbnMuXCIpXG4gICAgfVxuICAgIGNvbnN0IHF1aWV0UGVyaW9kTXMgPSBvcHRpb25zLnF1aWV0UGVyaW9kTXMgPz8gZGVmYXVsdFF1aWV0UGVyaW9kTXNcbiAgICBjb25zdCBwb2xsSW50ZXJ2YWxNcyA9IG9wdGlvbnMucG9sbEludGVydmFsTXMgPz8gZGVmYXVsdFBvbGxJbnRlcnZhbE1zXG5cbiAgICBpZiAoIXZhbGlkTWlsbGlzZWNvbmRzKHF1aWV0UGVyaW9kTXMsIG1heGltdW1RdWlldFBlcmlvZE1zKSB8fCAhdmFsaWRNaWxsaXNlY29uZHMocG9sbEludGVydmFsTXMsIG1heGltdW1Qb2xsSW50ZXJ2YWxNcykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcm9qZWN0IHdhdGNoIHRpbWluZyB2YWx1ZXMgbXVzdCBiZSBib3VuZGVkIHBvc2l0aXZlIGludGVnZXIgbWlsbGlzZWNvbmRzLlwiKVxuICAgIH1cbiAgICB0aGlzLiNidWlsZGVyID0gb3B0aW9ucy5idWlsZGVyID8/IG5ldyBQcm9qZWN0QnVpbGRlcigpXG4gICAgdGhpcy4jbWFuaWZlc3RMb2FkZXIgPSBvcHRpb25zLm1hbmlmZXN0TG9hZGVyID8/IG5ldyBQcm9qZWN0TWFuaWZlc3RMb2FkZXIoKVxuICAgIHRoaXMuI3NuYXBzaG90QnVpbGRlciA9IG9wdGlvbnMuc25hcHNob3RCdWlsZGVyID8/IG5ldyBQcm9qZWN0U25hcHNob3RCdWlsZGVyKClcbiAgICB0aGlzLiNxdWlldFBlcmlvZE1zID0gcXVpZXRQZXJpb2RNc1xuICAgIHRoaXMuI3BvbGxJbnRlcnZhbE1zID0gcG9sbEludGVydmFsTXNcbiAgICB0aGlzLiNzaWduYWxIYW5kbGVyID0gKCkgPT4ge1xuICAgICAgdm9pZCB0aGlzLnN0b3AoXCJ0ZXJtaW5hdGlvbiBzaWduYWxcIilcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3RhcnRzIHRoZSBpbml0aWFsIGJ1aWxkIGFuZCByZW1haW5zIGFjdGl2ZSB1bnRpbCBzaHV0ZG93biBvciBzdGFydHVwIGZhaWx1cmUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcHJvamVjdFBhdGhdIC0gUHJvamVjdCBtYW5pZmVzdCBwYXRoLlxuICAgKiBAcGFyYW0ge1Byb2plY3RXYXRjaFJlcG9ydGVyfSBbcmVwb3J0ZXJdIC0gV2F0Y2ggcHJvdG9jb2wgcmVwb3J0ZXIuXG4gICAqIEBwYXJhbSB7e2NoZWNrPzogYm9vbGVhbn19IFtvcHRpb25zXSAtIFdoZXRoZXIgZXZlcnkgY3ljbGUgcnVucyB0YXJnZXQtb3duZWQgY2hlY2tzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZWFkb25seTxQcm9qZWN0V2F0Y2hSZXN1bHQ+Pn0gVGVybWluYWwgd2F0Y2hlciByZXN1bHQuXG4gICAqL1xuICBydW4ocHJvamVjdFBhdGggPSBcIi4vc2VtYW50aWZvbGQuanNvblwiLCByZXBvcnRlciA9IG5ldyBQcm9qZWN0V2F0Y2hSZXBvcnRlcigpLCBvcHRpb25zID0ge30pIHtcbiAgICBpZiAodGhpcy4jcnVubmluZyB8fCB0aGlzLiNjb21wbGV0aW9uICE9PSB1bmRlZmluZWQgfHwgdHlwZW9mIHByb2plY3RQYXRoICE9IFwic3RyaW5nXCIgfHwgcHJvamVjdFBhdGgubGVuZ3RoID09IDAgfHxcbiAgICAgICEocmVwb3J0ZXIgaW5zdGFuY2VvZiBQcm9qZWN0V2F0Y2hSZXBvcnRlcikgfHwgIWlzUGxhaW5PYmplY3Qob3B0aW9ucykgfHxcbiAgICAgIE9iamVjdC5rZXlzKG9wdGlvbnMpLnNvbWUoa2V5ID0+IGtleSAhPSBcImNoZWNrXCIpIHx8IG9wdGlvbnMuY2hlY2sgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2Ygb3B0aW9ucy5jaGVjayAhPSBcImJvb2xlYW5cIikge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgb3IgcmVwZWF0ZWQgcHJvamVjdCB3YXRjaCBydW4uXCIpXG4gICAgfVxuICAgIHRoaXMuI3J1bm5pbmcgPSB0cnVlXG4gICAgdGhpcy4jcmVwb3J0ZXIgPSByZXBvcnRlclxuICAgIHRoaXMuI21hbmlmZXN0UGF0aCA9IHByb2plY3RQYXRoXG4gICAgdGhpcy4jY2hlY2sgPSBvcHRpb25zLmNoZWNrID09PSB0cnVlXG4gICAgdGhpcy4jY29tcGxldGlvbiA9IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgdGhpcy4jcmVzb2x2ZUNvbXBsZXRpb24gPSByZXNvbHZlXG4gICAgfSlcbiAgICBwcm9jZXNzLm9uY2UoXCJTSUdJTlRcIiwgdGhpcy4jc2lnbmFsSGFuZGxlcilcbiAgICBwcm9jZXNzLm9uY2UoXCJTSUdURVJNXCIsIHRoaXMuI3NpZ25hbEhhbmRsZXIpXG4gICAgY29uc3Qgc3RhcnR1cCA9IHRoaXMuI3N0YXJ0KHRoaXMuI2NoZWNrKVxuXG4gICAgdGhpcy4jc3RhcnR1cCA9IHN0YXJ0dXBcbiAgICBjb25zdCBzdGFydHVwU2V0dGxlZCA9ICgpID0+IHtcbiAgICAgIGlmICh0aGlzLiNzdGFydHVwID09PSBzdGFydHVwKSB0aGlzLiNzdGFydHVwID0gdW5kZWZpbmVkXG4gICAgICB0aGlzLiNmaW5pc2hTdG9wcGVkSWZJZGxlKClcbiAgICB9XG5cbiAgICB2b2lkIHN0YXJ0dXAudGhlbihzdGFydHVwU2V0dGxlZCwgc3RhcnR1cFNldHRsZWQpXG5cbiAgICByZXR1cm4gdGhpcy4jY29tcGxldGlvblxuICB9XG5cbiAgLyoqXG4gICAqIFN0b3BzIGFkbWl0dGluZyB3b3JrLCBjYW5jZWxzIHRoZSBleGFjdCBhY3RpdmUgb3BlcmF0aW9uLCBhbmQgd2FpdHMgdGhyb3VnaCBjaGlsZCBjbG9zZSBhbmQgc3RhZ2luZyBjbGVhbnVwLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBTdGFibGUgc2h1dGRvd24gcmVhc29uLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZWFkb25seTxQcm9qZWN0V2F0Y2hSZXN1bHQ+Pn0gVGVybWluYWwgd2F0Y2hlciByZXN1bHQuXG4gICAqL1xuICBhc3luYyBzdG9wKHJlYXNvbiA9IFwic2h1dGRvd24gcmVxdWVzdGVkXCIpIHtcbiAgICBpZiAodHlwZW9mIHJlYXNvbiAhPSBcInN0cmluZ1wiIHx8IHJlYXNvbi5sZW5ndGggPT0gMCkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByb2plY3Qgd2F0Y2ggc3RvcCByZWFzb24gbXVzdCBiZSBub24tZW1wdHkuXCIpXG4gICAgaWYgKHRoaXMuI2NvbXBsZXRpb24gPT09IHVuZGVmaW5lZCkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByb2plY3Qgd2F0Y2ggY29vcmRpbmF0b3IgaGFzIG5vdCBzdGFydGVkLlwiKVxuICAgIGlmICghdGhpcy4jc3RvcHBpbmcgJiYgIXRoaXMuI2ZpbmlzaGVkKSB7XG4gICAgICB0aGlzLiNzdG9wcGluZyA9IHRydWVcbiAgICAgIHRoaXMuI3N0b3BSZWFzb24gPSByZWFzb25cbiAgICAgIHRoaXMuI2Nsb3NlRXZlbnRCYWNrZW5kcygpXG4gICAgICB0aGlzLiNhY3RpdmVDb250cm9sbGVyPy5hYm9ydChyZWFzb24pXG4gICAgICB0aGlzLiNwdWJsaWNhdGlvbkNvbnRyb2xsZXI/LmFib3J0KHJlYXNvbilcbiAgICAgIHRoaXMuI2ZpbmlzaFN0b3BwZWRJZklkbGUoKVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLiNjb21wbGV0aW9uXG4gIH1cblxuICAvKipcbiAgICogRXN0YWJsaXNoZXMgdGhlIHZhbGlkYXRlZCBncmFwaCwgZXZlbnQgYmFja2VuZCwgYW5kIGluaXRpYWwgY3ljbGUuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gY2hlY2sgLSBDeWNsZSBjaGVjayBtb2RlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gU3RhcnR1cCBjb21wbGV0aW9uLlxuICAgKi9cbiAgYXN5bmMgI3N0YXJ0KGNoZWNrKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHByb2plY3QgPSBhd2FpdCB0aGlzLiNtYW5pZmVzdExvYWRlci5sb2FkKHRoaXMuI21hbmlmZXN0UGF0aClcblxuICAgICAgaWYgKHRoaXMuI3N0b3BwaW5nKSByZXR1cm5cbiAgICAgIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgdGhpcy4jc25hcHNob3RCdWlsZGVyLmJ1aWxkKHByb2plY3QpXG5cbiAgICAgIGlmICh0aGlzLiNzdG9wcGluZykgcmV0dXJuXG4gICAgICB0aGlzLiNwcm9qZWN0ID0gcHJvamVjdFxuICAgICAgdGhpcy4jbGFzdFNuYXBzaG90ID0gc25hcHNob3RcbiAgICAgIHRoaXMuI3NldFdhdGNoVG9wb2xvZ3kocHJvamVjdClcbiAgICAgIHRoaXMuI3dhdGNoU3RhdGVzID0gYXdhaXQgdGhpcy4jcmVhZFdhdGNoU3RhdGVzKClcbiAgICAgIGlmICh0aGlzLiNzdG9wcGluZykgcmV0dXJuXG4gICAgICB0aGlzLiNyZXBvcnRlcj8ud2F0Y2hTdGFydGVkKHByb2plY3QuaWQpXG4gICAgICBpZiAodGhpcy4jc3RvcHBpbmcpIHJldHVyblxuICAgICAgdGhpcy4jc3RhcnRFdmVudEJhY2tlbmQoKVxuICAgICAgaWYgKHRoaXMuI3N0b3BwaW5nKSByZXR1cm5cbiAgICAgIGF3YWl0IHRoaXMuI2FkbWl0Q3ljbGUoe2NoYW5nZWRQYXRoczogW10sIGNoZWNrLCBwcm9qZWN0LCBzbmFwc2hvdH0pXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmICghdGhpcy4jc3RvcHBpbmcpIHRoaXMuI2ZpbmlzaEZhaWxlZChlcnJvcilcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBleGFjdGx5IG9uZSBvd25lZCBjeWNsZS5cbiAgICogQHBhcmFtIHtXYXRjaEN5Y2xlSW5wdXR9IGlucHV0IC0gQWRtaXR0ZWQgY3ljbGUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgI2FkbWl0Q3ljbGUoe2NoYW5nZWRQYXRocywgY2hlY2ssIGZhaWx1cmUsIHByb2plY3QsIHNuYXBzaG90fSkge1xuICAgIGlmICh0aGlzLiNhY3RpdmVDeWNsZSAhPT0gdW5kZWZpbmVkIHx8IHRoaXMuI3N0b3BwaW5nKSByZXR1cm5cbiAgICB0aGlzLiNjeWNsZSArPSAxXG4gICAgY29uc3QgY3ljbGUgPSB0aGlzLiNjeWNsZVxuICAgIGNvbnN0IGFjdGl2ZUNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKClcbiAgICBjb25zdCBwdWJsaWNhdGlvbkNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKClcblxuICAgIHRoaXMuI2FjdGl2ZUNvbnRyb2xsZXIgPSBhY3RpdmVDb250cm9sbGVyXG4gICAgdGhpcy4jcHVibGljYXRpb25Db250cm9sbGVyID0gcHVibGljYXRpb25Db250cm9sbGVyXG4gICAgdGhpcy4jZGlydHkgPSBmYWxzZVxuICAgIHRoaXMuI2N5Y2xlRGlydHlSZXBvcnRlZCA9IGZhbHNlXG4gICAgdGhpcy4jY29tbWl0V2luZG93ID0gZmFsc2VcbiAgICB0aGlzLiNoaW50UGF0aHMuY2xlYXIoKVxuICAgIHRoaXMuI3JlcG9ydGVyPy5jeWNsZVN0YXJ0ZWQoe1xuICAgICAgY2hhbmdlZFBhdGhzLFxuICAgICAgY3ljbGUsXG4gICAgICBwcm9qZWN0SWQ6IHByb2plY3Q/LmlkID8/IHRoaXMuI3Byb2plY3Q/LmlkID8/IFwicHJvamVjdFwiLFxuICAgICAgLi4uKHNuYXBzaG90ID09PSB1bmRlZmluZWQgPyB7fSA6IHtzbmFwc2hvdEhhc2g6IHNuYXBzaG90Lmhhc2h9KVxuICAgIH0pXG4gICAgdGhpcy4jb2JzZXJ2ZSh7Y3ljbGUsIHN0YXR1czogXCJzdGFydGVkXCIsIHR5cGU6IFwiY3ljbGUtc3RhcnRcIn0pXG4gICAgbGV0IHRlcm1pbmFsU3RhdHVzID0gLyoqIEB0eXBlIHtcImNhbmNlbGxlZFwiIHwgXCJmYWlsZWRcIiB8IFwicmVjb3ZlcmVkXCIgfCBcInN1Y2NlZWRlZFwiIHwgXCJzdXBlcnNlZGVkXCJ9ICovIChcImZhaWxlZFwiKVxuICAgIC8qKiBAdHlwZSB7dW5rbm93bn0gKi9cbiAgICBsZXQgdGVybWluYWxGYWlsdXJlXG4gICAgLyoqIEB0eXBlIHtTZW1hbnRpZm9sZFByb2plY3QgfCB1bmRlZmluZWR9ICovXG4gICAgbGV0IGN1cnJlbnRQcm9qZWN0XG4gICAgLyoqIEB0eXBlIHtQcm9qZWN0U25hcHNob3QgfCB1bmRlZmluZWR9ICovXG4gICAgbGV0IGN1cnJlbnRTbmFwc2hvdFxuICAgIGNvbnN0IG1hbmlmZXN0UGF0aCA9IC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAodGhpcy4jbWFuaWZlc3RQYXRoKVxuICAgIGNvbnN0IHJlcG9ydGVyID0gLyoqIEB0eXBlIHtQcm9qZWN0V2F0Y2hSZXBvcnRlcn0gKi8gKHRoaXMuI3JlcG9ydGVyKVxuICAgIGNvbnN0IGV4ZWN1dGUgPSBhc3luYyAoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoc25hcHNob3QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IGZhaWx1cmUgPz8gbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7XG4gICAgICAgICAgICBjb2RlOiBcIldBVENIX1NOQVBTSE9UX1VOQVZBSUxBQkxFXCIsXG4gICAgICAgICAgICBsYW5ndWFnZTogcHJvamVjdD8uaWQgPz8gdGhpcy4jcHJvamVjdD8uaWQgPz8gXCJwcm9qZWN0XCIsXG4gICAgICAgICAgICBtZXNzYWdlOiBcIlRoZSBjb21wbGV0ZSB3YXRjaGVkIHByb2plY3QgZ3JhcGggaXMgdW5hdmFpbGFibGUuXCJcbiAgICAgICAgICB9KVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJ1aWxkV2F0Y2hlZFByb2plY3QodGhpcy4jYnVpbGRlciwgbWFuaWZlc3RQYXRoLCByZXBvcnRlciwge1xuICAgICAgICAgIGNoZWNrLFxuICAgICAgICAgIGV4cGVjdGVkU25hcHNob3RIYXNoOiBzbmFwc2hvdC5oYXNoLFxuICAgICAgICAgIHB1YmxpY2F0aW9uU2lnbmFsOiBwdWJsaWNhdGlvbkNvbnRyb2xsZXIuc2lnbmFsLFxuICAgICAgICAgIHNpZ25hbDogYWN0aXZlQ29udHJvbGxlci5zaWduYWwsXG4gICAgICAgICAgdmFsaWRhdGVDdXJyZW50U25hcHNob3Q6IGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGd1YXJkSGludFZlcnNpb24gPSB0aGlzLiNoaW50VmVyc2lvblxuICAgICAgICAgICAgLyoqIEB0eXBlIHtTZW1hbnRpZm9sZFByb2plY3R9ICovXG4gICAgICAgICAgICBsZXQgcmVjb25jaWxlZFByb2plY3RcbiAgICAgICAgICAgIC8qKiBAdHlwZSB7UHJvamVjdFNuYXBzaG90fSAqL1xuICAgICAgICAgICAgbGV0IHJlY29uY2lsZWRTbmFwc2hvdFxuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICByZWNvbmNpbGVkUHJvamVjdCA9IGF3YWl0IHRoaXMuI21hbmlmZXN0TG9hZGVyLmxvYWQobWFuaWZlc3RQYXRoKVxuICAgICAgICAgICAgICByZWNvbmNpbGVkU25hcHNob3QgPSBhd2FpdCB0aGlzLiNzbmFwc2hvdEJ1aWxkZXIuYnVpbGQocmVjb25jaWxlZFByb2plY3QpXG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtcbiAgICAgICAgICAgICAgICBjYXVzZTogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yIDogbmV3IEVycm9yKFN0cmluZyhlcnJvcikpLFxuICAgICAgICAgICAgICAgIGNvZGU6IFwiV0FUQ0hfQ0FORElEQVRFX1NVUEVSU0VERURcIixcbiAgICAgICAgICAgICAgICBsYW5ndWFnZTogdGhpcy4jcHJvamVjdD8uaWQgPz8gXCJwcm9qZWN0XCIsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogXCJUaGUgd2F0Y2hlZCBwcm9qZWN0IGdyYXBoIGJlY2FtZSB1bmF2YWlsYWJsZSBiZWZvcmUgY2FuZGlkYXRlIHB1YmxpY2F0aW9uLlwiXG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChzbmFwc2hvdCA9PT0gdW5kZWZpbmVkIHx8IHJlY29uY2lsZWRTbmFwc2hvdC5oYXNoICE9IHNuYXBzaG90Lmhhc2gpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7XG4gICAgICAgICAgICAgICAgY29kZTogXCJXQVRDSF9DQU5ESURBVEVfU1VQRVJTRURFRFwiLFxuICAgICAgICAgICAgICAgIGxhbmd1YWdlOiByZWNvbmNpbGVkUHJvamVjdC5pZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBcIkEgbmV3ZXIgY29tcGxldGUgcHJvamVjdCBzbmFwc2hvdCBzdXBlcnNlZGVkIHRoZSBjb21wbGV0ZWQgd2F0Y2ggY2FuZGlkYXRlLlwiXG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50UHJvamVjdCA9IHJlY29uY2lsZWRQcm9qZWN0XG4gICAgICAgICAgICBjdXJyZW50U25hcHNob3QgPSByZWNvbmNpbGVkU25hcHNob3RcbiAgICAgICAgICAgIHRoaXMuI2NvbW1pdFdpbmRvdyA9IHRydWVcbiAgICAgICAgICAgIGlmICh0aGlzLiNoaW50VmVyc2lvbiA9PSBndWFyZEhpbnRWZXJzaW9uKSB7XG4gICAgICAgICAgICAgIHRoaXMuI2RpcnR5ID0gZmFsc2VcbiAgICAgICAgICAgICAgdGhpcy4jaGludFBhdGhzLmNsZWFyKClcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRoaXMuI2RpcnR5ID0gdHJ1ZVxuICAgICAgICAgICAgICBwdWJsaWNhdGlvbkNvbnRyb2xsZXIuYWJvcnQoXCJBIGZpbGVzeXN0ZW0gaGludCBhcnJpdmVkIGR1cmluZyBmaW5hbCBzbmFwc2hvdCByZWNvbmNpbGlhdGlvbi5cIilcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pXG5cbiAgICAgICAgdGhpcy4jY29tbWl0V2luZG93ID0gZmFsc2VcbiAgICAgICAgdGVybWluYWxTdGF0dXMgPSB0aGlzLiNoYWRGYWlsdXJlID8gXCJyZWNvdmVyZWRcIiA6IFwic3VjY2VlZGVkXCJcbiAgICAgICAgdGhpcy4jaGFkRmFpbHVyZSA9IGZhbHNlXG4gICAgICAgIHRoaXMuI3N1cHByZXNzZWRIYXNoID0gcmVzdWx0LnNuYXBzaG90SGFzaFxuICAgICAgICBpZiAoY3VycmVudFByb2plY3QgIT09IHVuZGVmaW5lZCAmJiBjdXJyZW50U25hcHNob3QgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRoaXMuI3Byb2plY3QgPSBjdXJyZW50UHJvamVjdFxuICAgICAgICAgIHRoaXMuI2xhc3RTbmFwc2hvdCA9IGN1cnJlbnRTbmFwc2hvdFxuICAgICAgICAgIHRoaXMuI3NldFdhdGNoVG9wb2xvZ3koY3VycmVudFByb2plY3QpXG4gICAgICAgICAgY29uc3Qgd2F0Y2hTdGF0ZXMgPSBhd2FpdCB0aGlzLiNyZWFkV2F0Y2hTdGF0ZXMoKVxuICAgICAgICAgIGNvbnN0IGNoYW5nZWRXYXRjaFBhdGhzID0gY2hhbmdlZFdhdGNoU3RhdGVQYXRocyh0aGlzLiN3YXRjaFN0YXRlcywgd2F0Y2hTdGF0ZXMsIHRoaXMuI2Rpc3BsYXlQYXRocylcblxuICAgICAgICAgIGlmIChjaGFuZ2VkV2F0Y2hQYXRocy5sZW5ndGggPT0gMCkgdGhpcy4jd2F0Y2hTdGF0ZXMgPSB3YXRjaFN0YXRlc1xuICAgICAgICAgIGVsc2UgZm9yIChjb25zdCBjaGFuZ2VkUGF0aCBvZiBjaGFuZ2VkV2F0Y2hQYXRocykgdGhpcy4jaGludChjaGFuZ2VkUGF0aCwgY2hlY2spXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy4jcmVwb3J0ZXI/LmN5Y2xlU3VjY2VlZGVkKHJlc3VsdCwgdGVybWluYWxTdGF0dXMgPT0gXCJyZWNvdmVyZWRcIilcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHRlcm1pbmFsRmFpbHVyZSA9IGVycm9yXG4gICAgICAgIHRlcm1pbmFsU3RhdHVzID0gdGhpcy4jc3RvcHBpbmcgPyBcImNhbmNlbGxlZFwiIDogc3VwZXJzZWRlZEZhaWx1cmUoZXJyb3IsIHRoaXMuI2RpcnR5KSA/IFwic3VwZXJzZWRlZFwiIDogXCJmYWlsZWRcIlxuICAgICAgICBpZiAodGVybWluYWxTdGF0dXMgPT0gXCJmYWlsZWRcIikge1xuICAgICAgICAgIHRoaXMuI2hhZEZhaWx1cmUgPSB0cnVlXG4gICAgICAgICAgaWYgKHNuYXBzaG90ICE9PSB1bmRlZmluZWQpIHRoaXMuI3N1cHByZXNzZWRIYXNoID0gc25hcHNob3QuaGFzaFxuICAgICAgICB9XG4gICAgICAgIHRoaXMuI3JlcG9ydGVyPy5jeWNsZUZhaWxlZChlcnJvciwgdGVybWluYWxTdGF0dXMpXG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB0aGlzLiNjb21taXRXaW5kb3cgPSBmYWxzZVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuI2FjdGl2ZUN5Y2xlID0gZXhlY3V0ZSgpXG4gICAgYXdhaXQgdGhpcy4jYWN0aXZlQ3ljbGVcbiAgICB0aGlzLiNhY3RpdmVDeWNsZSA9IHVuZGVmaW5lZFxuICAgIHRoaXMuI2FjdGl2ZUNvbnRyb2xsZXIgPSB1bmRlZmluZWRcbiAgICB0aGlzLiNwdWJsaWNhdGlvbkNvbnRyb2xsZXIgPSB1bmRlZmluZWRcbiAgICB0aGlzLiNvYnNlcnZlKHtjeWNsZSwgc3RhdHVzOiB0ZXJtaW5hbFN0YXR1cywgdHlwZTogXCJjeWNsZS10ZXJtaW5hbFwifSlcbiAgICBpZiAodGhpcy4jc3RvcHBpbmcpIHtcbiAgICAgIHRoaXMuI2ZpbmlzaFN0b3BwZWRJZklkbGUoKVxuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGlmICh0aGlzLiNpbml0aWFsQ3ljbGUgJiYgdGVybWluYWxTdGF0dXMgPT0gXCJmYWlsZWRcIikge1xuICAgICAgdGhpcy4jZmluaXNoRmFpbGVkKHRlcm1pbmFsRmFpbHVyZSlcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBpZiAodGVybWluYWxTdGF0dXMgPT0gXCJzdWNjZWVkZWRcIiB8fCB0ZXJtaW5hbFN0YXR1cyA9PSBcInJlY292ZXJlZFwiKSB0aGlzLiNpbml0aWFsQ3ljbGUgPSBmYWxzZVxuICAgIGlmICh0aGlzLiNkaXJ0eSB8fCB0ZXJtaW5hbFN0YXR1cyA9PSBcInN1cGVyc2VkZWRcIikge1xuICAgICAgcXVldWVNaWNyb3Rhc2soKCkgPT4gdm9pZCB0aGlzLiNyZWNvbmNpbGUoY2hlY2spKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLiNvYnNlcnZlKHtjeWNsZSwgc3RhdHVzOiBcInJlYWR5XCIsIHR5cGU6IFwicmVhZHlcIn0pXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlLXJlYWRzIHRoZSBjb21wbGV0ZSBncmFwaCBhZnRlciBhIHF1aWV0IHBlcmlvZCBvciBhY3RpdmUtY3ljbGUgZGlydHkgbWFya2VyLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGNoZWNrIC0gQ3ljbGUgY2hlY2sgbW9kZS5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IFJlY29uY2lsaWF0aW9uIGNvbXBsZXRpb24uXG4gICAqL1xuICBhc3luYyAjcmVjb25jaWxlKGNoZWNrKSB7XG4gICAgaWYgKHRoaXMuI3N0b3BwaW5nIHx8IHRoaXMuI2FjdGl2ZUN5Y2xlICE9PSB1bmRlZmluZWQpIHJldHVyblxuICAgIGlmICh0aGlzLiNxdWlldFRpbWVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLiNxdWlldFRpbWVyKVxuICAgICAgdGhpcy4jcXVpZXRUaW1lciA9IHVuZGVmaW5lZFxuICAgIH1cbiAgICBjb25zdCBoaW50ZWQgPSBbLi4udGhpcy4jaGludFBhdGhzXS5zb3J0KGNvbXBhcmVTdHJpbmdzKVxuXG4gICAgdGhpcy4jaGludFBhdGhzLmNsZWFyKClcbiAgICB0aGlzLiNkaXJ0eSA9IGZhbHNlXG4gICAgbGV0IHByb2plY3RcbiAgICBsZXQgc25hcHNob3RcbiAgICBsZXQgc25hcHNob3RGYWlsdXJlXG5cbiAgICB0cnkge1xuICAgICAgcHJvamVjdCA9IGF3YWl0IHRoaXMuI21hbmlmZXN0TG9hZGVyLmxvYWQodGhpcy4jbWFuaWZlc3RQYXRoKVxuICAgICAgc25hcHNob3QgPSBhd2FpdCB0aGlzLiNzbmFwc2hvdEJ1aWxkZXIuYnVpbGQocHJvamVjdClcbiAgICAgIHRoaXMuI3N1cHByZXNzZWRJbnZhbGlkU3RhdGUgPSB1bmRlZmluZWRcbiAgICAgIHRoaXMuI3NldFdhdGNoVG9wb2xvZ3kocHJvamVjdClcbiAgICAgIHRoaXMuI3dhdGNoU3RhdGVzID0gYXdhaXQgdGhpcy4jcmVhZFdhdGNoU3RhdGVzKClcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgc25hcHNob3RGYWlsdXJlID0gZXJyb3JcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMuI3dhdGNoU3RhdGVzID0gYXdhaXQgdGhpcy4jcmVhZFdhdGNoU3RhdGVzKClcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBUaGUgYnVpbGQgY3ljbGUgYmVsb3cgb3ducyBhbmQgcmVwb3J0cyB0aGUgb3JpZ2luYWwgY29tcGxldGUtZ3JhcGggZmFpbHVyZS5cbiAgICAgIH1cbiAgICAgIGNvbnN0IGludmFsaWRTdGF0ZSA9IHdhdGNoU3RhdGVLZXkodGhpcy4jd2F0Y2hTdGF0ZXMpXG5cbiAgICAgIGlmIChpbnZhbGlkU3RhdGUgPT0gdGhpcy4jc3VwcHJlc3NlZEludmFsaWRTdGF0ZSkge1xuICAgICAgICB0aGlzLiNyZXBvcnRlcj8udW5jaGFuZ2VkKGhpbnRlZClcbiAgICAgICAgdGhpcy4jb2JzZXJ2ZSh7c3RhdHVzOiBcInVuY2hhbmdlZFwiLCB0eXBlOiBcInJlY29uY2lsZWRcIn0pXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgdGhpcy4jc3VwcHJlc3NlZEludmFsaWRTdGF0ZSA9IGludmFsaWRTdGF0ZVxuICAgIH1cbiAgICBpZiAoc25hcHNob3QgIT09IHVuZGVmaW5lZCAmJiBzbmFwc2hvdC5oYXNoID09IHRoaXMuI3N1cHByZXNzZWRIYXNoICYmICF0aGlzLiNoYWRGYWlsdXJlKSB7XG4gICAgICB0aGlzLiNyZXBvcnRlcj8udW5jaGFuZ2VkKGhpbnRlZClcbiAgICAgIHRoaXMuI29ic2VydmUoe3N0YXR1czogXCJ1bmNoYW5nZWRcIiwgdHlwZTogXCJyZWNvbmNpbGVkXCJ9KVxuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGNvbnN0IGNoYW5nZWRQYXRocyA9IHNuYXBzaG90ID09PSB1bmRlZmluZWRcbiAgICAgID8gaGludGVkXG4gICAgICA6IGNoYW5nZWRTbmFwc2hvdFBhdGhzKHRoaXMuI2xhc3RTbmFwc2hvdCwgc25hcHNob3QsXG4gICAgICAgICAgcGF0aC5iYXNlbmFtZShwcm9qZWN0Py5tYW5pZmVzdFBhdGggPz8gdGhpcy4jbWFuaWZlc3RQYXRoID8/IFwic2VtYW50aWZvbGQuanNvblwiKSlcblxuICAgIGlmIChzbmFwc2hvdCAhPT0gdW5kZWZpbmVkKSB0aGlzLiNsYXN0U25hcHNob3QgPSBzbmFwc2hvdFxuICAgIGF3YWl0IHRoaXMuI2FkbWl0Q3ljbGUoe2NoYW5nZWRQYXRocywgY2hlY2ssIGZhaWx1cmU6IHNuYXBzaG90RmFpbHVyZSwgcHJvamVjdCwgc25hcHNob3R9KVxuICB9XG5cbiAgLyoqXG4gICAqIENvYWxlc2NlcyBvbmUgZXZlbnQgaGludCB3aXRob3V0IHRyZWF0aW5nIGl0cyBmaWxlbmFtZSBhcyB0aGUgYnVpbGQgaW5wdXQgc2V0LlxuICAgKiBAcGFyYW0ge3N0cmluZyB8IHVuZGVmaW5lZH0gY2hhbmdlZFBhdGggLSBQcm9qZWN0LXJlbGF0aXZlIGNoYW5nZWQtcGF0aCBoaW50LlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGNoZWNrIC0gQ2hlY2sgbW9kZS5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICAjaGludChjaGFuZ2VkUGF0aCwgY2hlY2spIHtcbiAgICBpZiAodGhpcy4jc3RvcHBpbmcpIHJldHVyblxuICAgIHRoaXMuI2hpbnRWZXJzaW9uICs9IDFcbiAgICBpZiAoY2hhbmdlZFBhdGggIT09IHVuZGVmaW5lZCkgdGhpcy4jaGludFBhdGhzLmFkZChjaGFuZ2VkUGF0aClcbiAgICBpZiAodGhpcy4jYWN0aXZlQ3ljbGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy4jZGlydHkgPSB0cnVlXG4gICAgICBpZiAodGhpcy4jY29tbWl0V2luZG93KSB0aGlzLiNwdWJsaWNhdGlvbkNvbnRyb2xsZXI/LmFib3J0KFwiQSBmaWxlc3lzdGVtIGhpbnQgcmVhY2hlZCB0aGUgYWN0aXZlLXBvaW50ZXIgY29tbWl0IHdpbmRvdy5cIilcbiAgICAgIGlmICghdGhpcy4jY3ljbGVEaXJ0eVJlcG9ydGVkKSB7XG4gICAgICAgIHRoaXMuI2N5Y2xlRGlydHlSZXBvcnRlZCA9IHRydWVcbiAgICAgICAgdGhpcy4jcmVwb3J0ZXI/LmN5Y2xlRGlydHkoKVxuICAgICAgICB0aGlzLiNvYnNlcnZlKHtjeWNsZTogdGhpcy4jY3ljbGUsIHN0YXR1czogXCJkaXJ0eVwiLCB0eXBlOiBcImRpcnR5XCJ9KVxuICAgICAgfVxuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGlmICh0aGlzLiNxdWlldFRpbWVyICE9PSB1bmRlZmluZWQpIGNsZWFyVGltZW91dCh0aGlzLiNxdWlldFRpbWVyKVxuICAgIHRoaXMuI3F1aWV0VGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMuI3F1aWV0VGltZXIgPSB1bmRlZmluZWRcbiAgICAgIHZvaWQgdGhpcy4jcmVjb25jaWxlKGNoZWNrKVxuICAgIH0sIHRoaXMuI3F1aWV0UGVyaW9kTXMpXG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlcyB0aGUgZXhhY3QgbWFuaWZlc3Qvc291cmNlIHdhdGNoIHRvcG9sb2d5LlxuICAgKiBAcGFyYW0ge1NlbWFudGlmb2xkUHJvamVjdH0gcHJvamVjdCAtIEN1cnJlbnQgdmFsaWQgcHJvamVjdC5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICAjc2V0V2F0Y2hUb3BvbG9neShwcm9qZWN0KSB7XG4gICAgY29uc3Qgd2F0Y2hlZFBhdGhzID0gbmV3IFNldChbcHJvamVjdC5tYW5pZmVzdFBhdGgsIC4uLnByb2plY3Quc291cmNlcy5tYXAoKHthYnNvbHV0ZVBhdGh9KSA9PiBhYnNvbHV0ZVBhdGgpXSlcbiAgICBjb25zdCBkaXNwbGF5UGF0aHMgPSBuZXcgTWFwKFtbcHJvamVjdC5tYW5pZmVzdFBhdGgsIHBhdGguYmFzZW5hbWUocHJvamVjdC5tYW5pZmVzdFBhdGgpXV0pXG5cbiAgICBmb3IgKGNvbnN0IHNvdXJjZSBvZiBwcm9qZWN0LnNvdXJjZXMpIGRpc3BsYXlQYXRocy5zZXQoc291cmNlLmFic29sdXRlUGF0aCwgc291cmNlLnBhdGgpXG4gICAgY29uc3QgY2hhbmdlZCA9IFsuLi53YXRjaGVkUGF0aHNdLnNvcnQoY29tcGFyZVN0cmluZ3MpLmpvaW4oXCJcXDBcIikgIT0gWy4uLnRoaXMuI3dhdGNoZWRQYXRoc10uc29ydChjb21wYXJlU3RyaW5ncykuam9pbihcIlxcMFwiKVxuXG4gICAgdGhpcy4jd2F0Y2hlZFBhdGhzID0gd2F0Y2hlZFBhdGhzXG4gICAgdGhpcy4jZGlzcGxheVBhdGhzID0gZGlzcGxheVBhdGhzXG4gICAgdGhpcy4jcHVibGljYXRpb25Sb290ID0gcHJvamVjdC5wdWJsaWNhdGlvblJvb3RcbiAgICBpZiAoY2hhbmdlZCAmJiB0aGlzLiNzdWJzY3JpcHRpb25zLmxlbmd0aCA+IDAgJiYgIXRoaXMuI3BvbGxpbmcgJiYgIXRoaXMuI29wZW5OYXRpdmVTdWJzY3JpcHRpb25zKCkpIHtcbiAgICAgIHRoaXMuI3N3aXRjaFRvUG9sbGluZygpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFN0YXJ0cyBuYXRpdmUgc3Vic2NyaXB0aW9ucyBvciB0aGVpciBwb2xsaW5nIGZhbGxiYWNrLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gICNzdGFydEV2ZW50QmFja2VuZCgpIHtcbiAgICBpZiAodGhpcy4jb3Blbk5hdGl2ZVN1YnNjcmlwdGlvbnMoKSkge1xuICAgICAgdGhpcy4jZW5zdXJlUG9sbGluZ1JlY29uY2lsaWF0aW9uKClcbiAgICAgIHRoaXMuI3JlcG9ydGVyPy53YXRjaEJhY2tlbmQoXCJuYXRpdmVcIilcbiAgICAgIHRoaXMuI29ic2VydmUoe3N0YXR1czogXCJuYXRpdmVcIiwgdHlwZTogXCJ3YXRjaC1iYWNrZW5kXCJ9KVxuICAgIH0gZWxzZSB0aGlzLiNzd2l0Y2hUb1BvbGxpbmcoKVxuICB9XG5cbiAgLyoqXG4gICAqIE9wZW5zIGV4YWN0IGZpbGUgYW5kIHBhcmVudC1kaXJlY3Rvcnkgc3Vic2NyaXB0aW9ucy5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgbmF0aXZlIHN1YnNjcmlwdGlvbnMgb3BlbmVkIGNvbXBsZXRlbHkuXG4gICAqL1xuICAjb3Blbk5hdGl2ZVN1YnNjcmlwdGlvbnMoKSB7XG4gICAgdGhpcy4jY2xvc2VTdWJzY3JpcHRpb25zKClcbiAgICBjb25zdCBuYXRpdmVXYXRjaCA9IHByb2plY3RXYXRjaE5hdGl2ZUJhY2tlbmRzLmdldCh0aGlzKSA/PyB3YXRjaEZpbGVTeXN0ZW1cblxuICAgIHRyeSB7XG4gICAgICBmb3IgKGNvbnN0IGZpbGVuYW1lIG9mIHRoaXMuI3dhdGNoZWRQYXRocykge1xuICAgICAgICBjb25zdCBzdWJzY3JpcHRpb24gPSBuYXRpdmVXYXRjaChmaWxlbmFtZSwgKCkgPT4ge1xuICAgICAgICAgIHRoaXMuI2hpbnQodGhpcy4jZGlzcGxheVBhdGhzLmdldChmaWxlbmFtZSksIHRoaXMuI2N1cnJlbnRDaGVja01vZGUoKSlcbiAgICAgICAgfSlcblxuICAgICAgICBzdWJzY3JpcHRpb24ub25jZShcImVycm9yXCIsICgpID0+IHRoaXMuI3N3aXRjaFRvUG9sbGluZygpKVxuICAgICAgICB0aGlzLiNzdWJzY3JpcHRpb25zLnB1c2goc3Vic2NyaXB0aW9uKVxuICAgICAgfVxuICAgICAgY29uc3QgcGFyZW50cyA9IG5ldyBTZXQoWy4uLnRoaXMuI3dhdGNoZWRQYXRoc10ubWFwKGZpbGVuYW1lID0+IHBhdGguZGlybmFtZShmaWxlbmFtZSkpKVxuXG4gICAgICBmb3IgKGNvbnN0IGRpcmVjdG9yeSBvZiBwYXJlbnRzKSB7XG4gICAgICAgIGNvbnN0IHN1YnNjcmlwdGlvbiA9IG5hdGl2ZVdhdGNoKGRpcmVjdG9yeSwgKF8sIGZpbGVuYW1lKSA9PiB7XG4gICAgICAgICAgaWYgKGZpbGVuYW1lID09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuI2hpbnQodW5kZWZpbmVkLCB0aGlzLiNjdXJyZW50Q2hlY2tNb2RlKCkpXG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgYWJzb2x1dGUgPSBwYXRoLmpvaW4oZGlyZWN0b3J5LCBmaWxlbmFtZS50b1N0cmluZygpKVxuXG4gICAgICAgICAgaWYgKHRoaXMuI3B1YmxpY2F0aW9uUm9vdCAhPT0gdW5kZWZpbmVkICYmIHBhdGhzT3ZlcmxhcCh0aGlzLiNwdWJsaWNhdGlvblJvb3QsIGFic29sdXRlKSkgcmV0dXJuXG4gICAgICAgICAgdGhpcy4jaGludCh0aGlzLiNkaXNwbGF5UGF0aHMuZ2V0KGFic29sdXRlKSwgdGhpcy4jY3VycmVudENoZWNrTW9kZSgpKVxuICAgICAgICB9KVxuXG4gICAgICAgIHN1YnNjcmlwdGlvbi5vbmNlKFwiZXJyb3JcIiwgKCkgPT4gdGhpcy4jc3dpdGNoVG9Qb2xsaW5nKCkpXG4gICAgICAgIHRoaXMuI3N1YnNjcmlwdGlvbnMucHVzaChzdWJzY3JpcHRpb24pXG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0cnVlXG4gICAgfSBjYXRjaCB7XG4gICAgICB0aGlzLiNjbG9zZVN1YnNjcmlwdGlvbnMoKVxuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcm1hbmVudGx5IHNlbGVjdHMgYm91bmRlZCBwb2xsaW5nIGFmdGVyIG5hdGl2ZSBiYWNrZW5kIGZhaWx1cmUuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgI3N3aXRjaFRvUG9sbGluZygpIHtcbiAgICBpZiAodGhpcy4jc3RvcHBpbmcgfHwgdGhpcy4jcG9sbGluZykgcmV0dXJuXG4gICAgdGhpcy4jcG9sbGluZyA9IHRydWVcbiAgICB0aGlzLiNjbG9zZVN1YnNjcmlwdGlvbnMoKVxuICAgIHRoaXMuI2Vuc3VyZVBvbGxpbmdSZWNvbmNpbGlhdGlvbigpXG4gICAgdGhpcy4jcmVwb3J0ZXI/LndhdGNoQmFja2VuZChcInBvbGxpbmdcIilcbiAgICB0aGlzLiNvYnNlcnZlKHtzdGF0dXM6IFwicG9sbGluZ1wiLCB0eXBlOiBcIndhdGNoLWJhY2tlbmRcIn0pXG4gIH1cblxuICAvKipcbiAgICogQ29tcGFyZXMgb25lIGJvdW5kZWQgcG9sbGluZyBzdGF0ZSBvYnNlcnZhdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IFBvbGwgY29tcGxldGlvbi5cbiAgICovXG4gIGFzeW5jICNwb2xsKCkge1xuICAgIGlmICh0aGlzLiNwb2xsQWN0aXZlIHx8IHRoaXMuI3N0b3BwaW5nKSByZXR1cm5cbiAgICB0aGlzLiNwb2xsQWN0aXZlID0gdHJ1ZVxuICAgIHRyeSB7XG4gICAgICBpZiAodGhpcy4jc3VwcHJlc3NlZEludmFsaWRTdGF0ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcHJvamVjdCA9IGF3YWl0IHRoaXMuI21hbmlmZXN0TG9hZGVyLmxvYWQodGhpcy4jbWFuaWZlc3RQYXRoKVxuXG4gICAgICAgICAgYXdhaXQgdGhpcy4jc25hcHNob3RCdWlsZGVyLmJ1aWxkKHByb2plY3QpXG4gICAgICAgICAgaWYgKHRoaXMuI3F1aWV0VGltZXIgPT09IHVuZGVmaW5lZCkgdGhpcy4jaGludCh1bmRlZmluZWQsIHRoaXMuI2N1cnJlbnRDaGVja01vZGUoKSlcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgLy8gQW4gdW5jaGFuZ2VkIGludmFsaWQgZ3JhcGggcmVtYWlucyBvbmUgZmFpbGVkIGN5Y2xlIHVudGlsIGl0IGJlY29tZXMgcmVhZGFibGUgYW5kIHZhbGlkLlxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjb25zdCBjdXJyZW50ID0gYXdhaXQgdGhpcy4jcmVhZFdhdGNoU3RhdGVzKClcbiAgICAgIGNvbnN0IGNoYW5nZWQgPSBjaGFuZ2VkV2F0Y2hTdGF0ZVBhdGhzKHRoaXMuI3dhdGNoU3RhdGVzLCBjdXJyZW50LCB0aGlzLiNkaXNwbGF5UGF0aHMpXG5cbiAgICAgIHRoaXMuI3BvbGxGYWlsZWQgPSBmYWxzZVxuICAgICAgaWYgKGNoYW5nZWQubGVuZ3RoID09IDApIHJldHVyblxuICAgICAgdGhpcy4jd2F0Y2hTdGF0ZXMgPSBjdXJyZW50XG4gICAgICBmb3IgKGNvbnN0IGNoYW5nZWRQYXRoIG9mIGNoYW5nZWQpIHRoaXMuI2hpbnQoY2hhbmdlZFBhdGgsIHRoaXMuI2N1cnJlbnRDaGVja01vZGUoKSlcbiAgICB9IGNhdGNoIHtcbiAgICAgIGlmICghdGhpcy4jcG9sbEZhaWxlZCkge1xuICAgICAgICB0aGlzLiNwb2xsRmFpbGVkID0gdHJ1ZVxuICAgICAgICB0aGlzLiNoaW50KHVuZGVmaW5lZCwgdGhpcy4jY3VycmVudENoZWNrTW9kZSgpKVxuICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLiNwb2xsQWN0aXZlID0gZmFsc2VcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVhZHMgdGhlIGltbXV0YWJsZSBjaGVjayBtb2RlIGNhcHR1cmVkIGJ5IHJ1bi5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IEFjdGl2ZSBjaGVjayBtb2RlLlxuICAgKi9cbiAgI2N1cnJlbnRDaGVja01vZGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuI2NoZWNrXG4gIH1cblxuICAvKipcbiAgICogUmVhZHMgb25lIGRldGFjaGVkIG11dGF0aW9uLXNlbnNpdGl2ZSBzdGF0ZSBvYnNlcnZhdGlvbiB0aHJvdWdoIHRoZSBzZWxlY3RlZCBiYWNrZW5kLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxNYXA8c3RyaW5nLCBzdHJpbmc+Pn0gU3RhYmxlIG9yZGVyZWQgcGF0aCBzdGF0ZXMuXG4gICAqL1xuICAjcmVhZFdhdGNoU3RhdGVzKCkge1xuICAgIGNvbnN0IHJlYWRlciA9IHByb2plY3RXYXRjaFN0YXRlUmVhZGVycy5nZXQodGhpcykgPz8gcmVhZFdhdGNoU3RhdGVzXG5cbiAgICByZXR1cm4gcmVhZGVyKG5ldyBTZXQodGhpcy4jd2F0Y2hlZFBhdGhzKSlcbiAgfVxuXG4gICNjaGVjayA9IGZhbHNlXG5cbiAgLyoqXG4gICAqIFN0YXJ0cyBvbmUgYm91bmRlZCByZWNvbmNpbGlhdGlvbiBpbnRlcnZhbCBzaGFyZWQgYnkgbmF0aXZlIGFuZCBmYWxsYmFjayBtb2Rlcy5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICAjZW5zdXJlUG9sbGluZ1JlY29uY2lsaWF0aW9uKCkge1xuICAgIHRoaXMuI3BvbGxUaW1lciA/Pz0gc2V0SW50ZXJ2YWwoKCkgPT4gdm9pZCB0aGlzLiNwb2xsKCksIHRoaXMuI3BvbGxJbnRlcnZhbE1zKVxuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlcyBldmVyeSBuYXRpdmUgc3Vic2NyaXB0aW9uLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gICNjbG9zZVN1YnNjcmlwdGlvbnMoKSB7XG4gICAgZm9yIChjb25zdCBzdWJzY3JpcHRpb24gb2YgdGhpcy4jc3Vic2NyaXB0aW9ucykgc3Vic2NyaXB0aW9uLmNsb3NlKClcbiAgICB0aGlzLiNzdWJzY3JpcHRpb25zID0gW11cbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgc3Vic2NyaXB0aW9ucyBhbmQgcGVuZGluZyByZWNvbmNpbGlhdGlvbiB0aW1lcnMuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgI2Nsb3NlRXZlbnRCYWNrZW5kcygpIHtcbiAgICBpZiAodGhpcy4jcXVpZXRUaW1lciAhPT0gdW5kZWZpbmVkKSBjbGVhclRpbWVvdXQodGhpcy4jcXVpZXRUaW1lcilcbiAgICBpZiAodGhpcy4jcG9sbFRpbWVyICE9PSB1bmRlZmluZWQpIGNsZWFySW50ZXJ2YWwodGhpcy4jcG9sbFRpbWVyKVxuICAgIHRoaXMuI3F1aWV0VGltZXIgPSB1bmRlZmluZWRcbiAgICB0aGlzLiNwb2xsVGltZXIgPSB1bmRlZmluZWRcbiAgICB0aGlzLiNjbG9zZVN1YnNjcmlwdGlvbnMoKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmVzIHNodXRkb3duIG9ubHkgYWZ0ZXIgc3RhcnR1cCBhbmQgdGhlIGFjdGl2ZSBjeWNsZSBoYXZlIGJvdGggcmVsaW5xdWlzaGVkIG93bmVyc2hpcC5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICAjZmluaXNoU3RvcHBlZElmSWRsZSgpIHtcbiAgICBpZiAodGhpcy4jc3RvcHBpbmcgJiYgdGhpcy4jc3RhcnR1cCA9PT0gdW5kZWZpbmVkICYmIHRoaXMuI2FjdGl2ZUN5Y2xlID09PSB1bmRlZmluZWQpIHRoaXMuI2ZpbmlzaFN0b3BwZWQoKVxuICB9XG5cbiAgLyoqXG4gICAqIEVtaXRzIGFuZCByZXNvbHZlcyBvbmUgY2xlYW4gd2F0Y2hlciB0ZXJtaW5hbC5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICAjZmluaXNoU3RvcHBlZCgpIHtcbiAgICBpZiAodGhpcy4jZmluaXNoZWQpIHJldHVyblxuICAgIHRoaXMuI2ZpbmlzaGVkID0gdHJ1ZVxuICAgIHRoaXMuI3J1bm5pbmcgPSBmYWxzZVxuICAgIHRoaXMuI2Nsb3NlRXZlbnRCYWNrZW5kcygpXG4gICAgdGhpcy4jcmVtb3ZlU2lnbmFsSGFuZGxlcnMoKVxuICAgIHRoaXMuI3JlcG9ydGVyPy53YXRjaFN0b3BwZWQodGhpcy4jc3RvcFJlYXNvbilcbiAgICBjb25zdCByZXN1bHQgPSBPYmplY3QuZnJlZXplKHtjeWNsZXM6IHRoaXMuI2N5Y2xlLCByZWFzb246IHRoaXMuI3N0b3BSZWFzb24sIHN0YXR1czogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwic3RvcHBlZFwiKX0pXG5cbiAgICB0aGlzLiNvYnNlcnZlKHtzdGF0dXM6IFwic3RvcHBlZFwiLCB0eXBlOiBcInN0b3BwZWRcIn0pXG4gICAgdGhpcy4jcmVzb2x2ZUNvbXBsZXRpb24ocmVzdWx0KVxuICB9XG5cbiAgLyoqXG4gICAqIEVtaXRzIGFuZCByZXNvbHZlcyBvbmUgc3RhcnR1cC1mYWlsdXJlIHdhdGNoZXIgdGVybWluYWwuXG4gICAqIEBwYXJhbSB7dW5rbm93bn0gZmFpbHVyZSAtIFN0YXJ0dXAgZmFpbHVyZS5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICAjZmluaXNoRmFpbGVkKGZhaWx1cmUpIHtcbiAgICBpZiAodGhpcy4jZmluaXNoZWQpIHJldHVyblxuICAgIHRoaXMuI2ZpbmlzaGVkID0gdHJ1ZVxuICAgIHRoaXMuI3J1bm5pbmcgPSBmYWxzZVxuICAgIHRoaXMuI2Nsb3NlRXZlbnRCYWNrZW5kcygpXG4gICAgdGhpcy4jcmVtb3ZlU2lnbmFsSGFuZGxlcnMoKVxuICAgIHRoaXMuI3JlcG9ydGVyPy53YXRjaEZhaWxlZChmYWlsdXJlKVxuICAgIGNvbnN0IHJlc3VsdCA9IE9iamVjdC5mcmVlemUoe2N5Y2xlczogdGhpcy4jY3ljbGUsIHJlYXNvbjogXCJzdGFydHVwIGZhaWx1cmVcIiwgc3RhdHVzOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJmYWlsZWRcIil9KVxuXG4gICAgdGhpcy4jb2JzZXJ2ZSh7c3RhdHVzOiBcImZhaWxlZFwiLCB0eXBlOiBcInN0b3BwZWRcIn0pXG4gICAgdGhpcy4jcmVzb2x2ZUNvbXBsZXRpb24ocmVzdWx0KVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgcHJvY2VzcyBzaWduYWwgaGFuZGxlcnMgb3duZWQgYnkgdGhpcyBjb29yZGluYXRvci5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICAjcmVtb3ZlU2lnbmFsSGFuZGxlcnMoKSB7XG4gICAgcHJvY2Vzcy5yZW1vdmVMaXN0ZW5lcihcIlNJR0lOVFwiLCB0aGlzLiNzaWduYWxIYW5kbGVyKVxuICAgIHByb2Nlc3MucmVtb3ZlTGlzdGVuZXIoXCJTSUdURVJNXCIsIHRoaXMuI3NpZ25hbEhhbmRsZXIpXG4gIH1cblxuICAvKipcbiAgICogRW1pdHMgb25lIGludGVybmFsIGRldGVybWluaXN0aWMgbGlmZWN5Y2xlIG1hcmtlci5cbiAgICogQHBhcmFtIHtQcm9qZWN0V2F0Y2hPYnNlcnZhdGlvbn0gZXZlbnQgLSBNYXJrZXIuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgI29ic2VydmUoZXZlbnQpIHtcbiAgICBwcm9qZWN0V2F0Y2hPYnNlcnZlcnMuZ2V0KHRoaXMpPy4oT2JqZWN0LmZyZWV6ZShldmVudCkpXG4gIH1cbn1cblxuLyoqXG4gKiBSZWFkcyBtdXRhdGlvbi1zZW5zaXRpdmUgc3RhdGVzIG9ubHkgYXMgcG9sbGluZy9ldmVudCBkZWR1cGxpY2F0aW9uIGhpbnRzLlxuICogQ29udGVudCBoYXNoZXMgcmVtYWluIGF1dGhvcml0YXRpdmUgZm9yIGN5Y2xlIGFkbWlzc2lvbi5cbiAqIEBwYXJhbSB7UmVhZG9ubHk8U2V0PHN0cmluZz4+fSBmaWxlbmFtZXMgLSBFeGFjdCB3YXRjaGVkIGdyYXBoIHBhdGhzLlxuICogQHJldHVybnMge1Byb21pc2U8TWFwPHN0cmluZywgc3RyaW5nPj59IFN0YWJsZSBvcmRlcmVkIHBhdGggc3RhdGVzLlxuICovXG5hc3luYyBmdW5jdGlvbiByZWFkV2F0Y2hTdGF0ZXMoZmlsZW5hbWVzKSB7XG4gIGNvbnN0IHJlc3VsdCA9IG5ldyBNYXAoKVxuXG4gIGZvciAoY29uc3QgZmlsZW5hbWUgb2YgWy4uLmZpbGVuYW1lc10uc29ydChjb21wYXJlU3RyaW5ncykpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3Qgc3RhdHVzID0gYXdhaXQgbHN0YXQoZmlsZW5hbWUsIHtiaWdpbnQ6IHRydWV9KVxuXG4gICAgICByZXN1bHQuc2V0KGZpbGVuYW1lLCBbc3RhdHVzLmRldiwgc3RhdHVzLmlubywgc3RhdHVzLm1vZGUsIHN0YXR1cy5zaXplLCBzdGF0dXMubXRpbWVOcywgc3RhdHVzLmN0aW1lTnNdLm1hcChTdHJpbmcpLmpvaW4oXCI6XCIpKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoIWlzRXJyb3JDb2RlKGVycm9yLCBcIkVOT0VOVFwiKSkgdGhyb3cgZXJyb3JcbiAgICAgIHJlc3VsdC5zZXQoZmlsZW5hbWUsIFwibWlzc2luZ1wiKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXN1bHRcbn1cblxuLyoqXG4gKiBAdHlwZWRlZiB7KGZpbGVuYW1lczogUmVhZG9ubHk8U2V0PHN0cmluZz4+KSA9PiBQcm9taXNlPE1hcDxzdHJpbmcsIHN0cmluZz4+fSBQcm9qZWN0V2F0Y2hTdGF0ZVJlYWRlclxuICovXG5cbi8qKlxuICogTG9jYXRlcyBwb2xsaW5nIGNoYW5nZXMgd2l0aG91dCB0cmVhdGluZyBtZXRhZGF0YSBhcyBidWlsZCBpZGVudGl0eS5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgc3RyaW5nPn0gcHJldmlvdXMgLSBQcmV2aW91cyBzdGF0ZXMuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIHN0cmluZz59IGN1cnJlbnQgLSBDdXJyZW50IHN0YXRlcy5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgc3RyaW5nPn0gZGlzcGxheVBhdGhzIC0gU3RhYmxlIHByb2plY3QtcmVsYXRpdmUgbmFtZXMuXG4gKiBAcmV0dXJucyB7c3RyaW5nW119IENoYW5nZWQgcHJvamVjdCBwYXRocy5cbiAqL1xuZnVuY3Rpb24gY2hhbmdlZFdhdGNoU3RhdGVQYXRocyhwcmV2aW91cywgY3VycmVudCwgZGlzcGxheVBhdGhzKSB7XG4gIGNvbnN0IGZpbGVuYW1lcyA9IG5ldyBTZXQoWy4uLnByZXZpb3VzLmtleXMoKSwgLi4uY3VycmVudC5rZXlzKCldKVxuXG4gIHJldHVybiBbLi4uZmlsZW5hbWVzXS5maWx0ZXIoZmlsZW5hbWUgPT4gcHJldmlvdXMuZ2V0KGZpbGVuYW1lKSAhPSBjdXJyZW50LmdldChmaWxlbmFtZSkpXG4gICAgLm1hcChmaWxlbmFtZSA9PiBkaXNwbGF5UGF0aHMuZ2V0KGZpbGVuYW1lKSA/PyBwYXRoLmJhc2VuYW1lKGZpbGVuYW1lKSkuc29ydChjb21wYXJlU3RyaW5ncylcbn1cblxuLyoqXG4gKiBTZXJpYWxpemVzIG9uZSBvcmRlcmVkIHBvbGxpbmcgc3RhdGUgb25seSBmb3IgcmVwZWF0ZWQtaW52YWxpZCByZWNvbmNpbGlhdGlvbiBzdXBwcmVzc2lvbi5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgc3RyaW5nPn0gc3RhdGVzIC0gQ3VycmVudCB3YXRjaGVkIHBhdGggc3RhdGVzLlxuICogQHJldHVybnMge3N0cmluZ30gU3RhYmxlIHN0YXRlIGtleS5cbiAqL1xuZnVuY3Rpb24gd2F0Y2hTdGF0ZUtleShzdGF0ZXMpIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KFsuLi5zdGF0ZXNdLnNvcnQoKFtsZWZ0XSwgW3JpZ2h0XSkgPT4gY29tcGFyZVN0cmluZ3MobGVmdCwgcmlnaHQpKSlcbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBlaXRoZXIgYWJzb2x1dGUgcGF0aCBjb250YWlucyB0aGUgb3RoZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gbGVmdCAtIEZpcnN0IGFic29sdXRlIHBhdGguXG4gKiBAcGFyYW0ge3N0cmluZ30gcmlnaHQgLSBTZWNvbmQgYWJzb2x1dGUgcGF0aC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIHRoZSBwYXRocyBvdmVybGFwLlxuICovXG5mdW5jdGlvbiBwYXRoc092ZXJsYXAobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIHBhdGhXaXRoaW4obGVmdCwgcmlnaHQpIHx8IHBhdGhXaXRoaW4ocmlnaHQsIGxlZnQpXG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgb25lIGFic29sdXRlIHBhdGggaXMgYSByb290IG9yIGRlc2NlbmRhbnQgb2YgYW5vdGhlci5cbiAqIEBwYXJhbSB7c3RyaW5nfSByb290IC0gQWJzb2x1dGUgcm9vdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjYW5kaWRhdGUgLSBBYnNvbHV0ZSBjYW5kaWRhdGUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgY2FuZGlkYXRlIGJlbG9uZ3MgdG8gdGhlIHJvb3QuXG4gKi9cbmZ1bmN0aW9uIHBhdGhXaXRoaW4ocm9vdCwgY2FuZGlkYXRlKSB7XG4gIGNvbnN0IHJlbGF0aXZlID0gcGF0aC5yZWxhdGl2ZShyb290LCBjYW5kaWRhdGUpXG5cbiAgcmV0dXJuIHJlbGF0aXZlLmxlbmd0aCA9PSAwIHx8IHJlbGF0aXZlICE9IFwiLi5cIiAmJiAhcmVsYXRpdmUuc3RhcnRzV2l0aChgLi4ke3BhdGguc2VwfWApICYmICFwYXRoLmlzQWJzb2x1dGUocmVsYXRpdmUpXG59XG5cbi8qKlxuICogQ29tcHV0ZXMgZXhhY3QgY29udGVudC9jb25maWcgY2hhbmdlcyBiZXR3ZWVuIGNvbXBsZXRlIGltbXV0YWJsZSBzbmFwc2hvdHMuXG4gKiBAcGFyYW0ge1Byb2plY3RTbmFwc2hvdCB8IHVuZGVmaW5lZH0gcHJldmlvdXMgLSBQcmV2aW91cyBhZG1pdHRlZCBzbmFwc2hvdC5cbiAqIEBwYXJhbSB7UHJvamVjdFNuYXBzaG90fSBjdXJyZW50IC0gQ3VycmVudCBjb21wbGV0ZSBzbmFwc2hvdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtYW5pZmVzdFBhdGggLSBQcm9qZWN0LXJvb3QtcmVsYXRpdmUgbWFuaWZlc3QgZGlzcGxheSBwYXRoLlxuICogQHJldHVybnMge3N0cmluZ1tdfSBTdGFibGUgY2hhbmdlZCBwYXRocy5cbiAqL1xuZnVuY3Rpb24gY2hhbmdlZFNuYXBzaG90UGF0aHMocHJldmlvdXMsIGN1cnJlbnQsIG1hbmlmZXN0UGF0aCkge1xuICBpZiAocHJldmlvdXMgPT09IHVuZGVmaW5lZCkgcmV0dXJuIFttYW5pZmVzdFBhdGgsIC4uLmN1cnJlbnQuc291cmNlcy5tYXAoKHtwYXRoOiBzb3VyY2VQYXRofSkgPT4gc291cmNlUGF0aCldXG4gIGNvbnN0IGNoYW5nZWQgPSBuZXcgU2V0KClcblxuICBpZiAocHJldmlvdXMubWFuaWZlc3RUZXh0ICE9IGN1cnJlbnQubWFuaWZlc3RUZXh0KSBjaGFuZ2VkLmFkZChtYW5pZmVzdFBhdGgpXG4gIGNvbnN0IHByZXZpb3VzU291cmNlcyA9IG5ldyBNYXAocHJldmlvdXMuc291cmNlcy5tYXAoc291cmNlID0+IFtzb3VyY2UucGF0aCwgc291cmNlLnNvdXJjZV0pKVxuICBjb25zdCBjdXJyZW50U291cmNlcyA9IG5ldyBNYXAoY3VycmVudC5zb3VyY2VzLm1hcChzb3VyY2UgPT4gW3NvdXJjZS5wYXRoLCBzb3VyY2Uuc291cmNlXSkpXG5cbiAgZm9yIChjb25zdCBzb3VyY2VQYXRoIG9mIG5ldyBTZXQoWy4uLnByZXZpb3VzU291cmNlcy5rZXlzKCksIC4uLmN1cnJlbnRTb3VyY2VzLmtleXMoKV0pKSB7XG4gICAgaWYgKHByZXZpb3VzU291cmNlcy5nZXQoc291cmNlUGF0aCkgIT0gY3VycmVudFNvdXJjZXMuZ2V0KHNvdXJjZVBhdGgpKSBjaGFuZ2VkLmFkZChzb3VyY2VQYXRoKVxuICB9XG5cbiAgcmV0dXJuIFsuLi5jaGFuZ2VkXS5zb3J0KGNvbXBhcmVTdHJpbmdzKVxufVxuXG4vKipcbiAqIFJlY29nbml6ZXMgZmFpbHVyZXMgY2F1c2VkIG9ubHkgYnkgZGV0ZXJtaW5pc3RpYyBzdXBlcnNlc3Npb24uXG4gKiBAcGFyYW0ge3Vua25vd259IGZhaWx1cmUgLSBDYW5kaWRhdGUgZmFpbHVyZS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gZGlydHkgLSBXaGV0aGVyIGEgbmV3ZXIgaGludCBleGlzdHMuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgY3ljbGUgd2FzIHN1cGVyc2VkZWQuXG4gKi9cbmZ1bmN0aW9uIHN1cGVyc2VkZWRGYWlsdXJlKGZhaWx1cmUsIGRpcnR5KSB7XG4gIGxldCBjdXJyZW50ID0gZmFpbHVyZVxuXG4gIHdoaWxlIChjdXJyZW50IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICBpZiAoXCJjb2RlXCIgaW4gY3VycmVudCAmJiAoY3VycmVudC5jb2RlID09IFwiV0FUQ0hfQ0FORElEQVRFX1NVUEVSU0VERURcIiB8fCBjdXJyZW50LmNvZGUgPT0gXCJXQVRDSF9TTkFQU0hPVF9DSEFOR0VEXCIgfHxcbiAgICAgIGRpcnR5ICYmIGN1cnJlbnQuY29kZSA9PSBcIlBVQkxJQ0FUSU9OX0NBTkNFTExFRFwiKSkgcmV0dXJuIHRydWVcbiAgICBjdXJyZW50ID0gY3VycmVudC5jYXVzZVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlXG59XG5cbi8qKlxuICogQ2hlY2tzIG9uZSBvcmRpbmFyeSBvYmplY3QuXG4gKiBAcGFyYW0ge3Vua25vd259IHZhbHVlIC0gQ2FuZGlkYXRlLlxuICogQHJldHVybnMge3ZhbHVlIGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+fSBXaGV0aGVyIHRoZSB2YWx1ZSBpcyBhIHBsYWluIG9iamVjdC5cbiAqL1xuZnVuY3Rpb24gaXNQbGFpbk9iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09IFwib2JqZWN0XCIgJiYgdmFsdWUgIT0gbnVsbCAmJiAhQXJyYXkuaXNBcnJheSh2YWx1ZSkgJiYgT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKSA9PSBPYmplY3QucHJvdG90eXBlXG59XG5cbi8qKlxuICogQ2hlY2tzIG9uZSBib3VuZGVkIHBvc2l0aXZlIGludGVnZXIgdGltaW5nIHZhbHVlLlxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIC0gQ2FuZGlkYXRlIG1pbGxpc2Vjb25kcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhpbXVtIC0gSW5jbHVzaXZlIG1heGltdW0uXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgdmFsdWUgaXMgdmFsaWQuXG4gKi9cbmZ1bmN0aW9uIHZhbGlkTWlsbGlzZWNvbmRzKHZhbHVlLCBtYXhpbXVtKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gXCJudW1iZXJcIiAmJiBOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKSAmJiB2YWx1ZSA+IDAgJiYgdmFsdWUgPD0gbWF4aW11bVxufVxuXG4vKipcbiAqIENoZWNrcyBhIG5hcnJvd2VkIGZpbGVzeXN0ZW0gZXJyb3IgY29kZS5cbiAqIEBwYXJhbSB7dW5rbm93bn0gZXJyb3IgLSBPcGFxdWUgZXJyb3IuXG4gKiBAcGFyYW0ge3N0cmluZ30gY29kZSAtIEV4cGVjdGVkIGNvZGUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgY29kZSBtYXRjaGVzLlxuICovXG5mdW5jdGlvbiBpc0Vycm9yQ29kZShlcnJvciwgY29kZSkge1xuICByZXR1cm4gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciAmJiBcImNvZGVcIiBpbiBlcnJvciAmJiBlcnJvci5jb2RlID09IGNvZGVcbn1cblxuLyoqXG4gKiBDb21wYXJlcyBzdGFibGUgcHJvdG9jb2wgc3RyaW5ncy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBsZWZ0IC0gTGVmdCBzdHJpbmcuXG4gKiBAcGFyYW0ge3N0cmluZ30gcmlnaHQgLSBSaWdodCBzdHJpbmcuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBTb3J0IG9yZGVyLlxuICovXG5mdW5jdGlvbiBjb21wYXJlU3RyaW5ncyhsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdC5sb2NhbGVDb21wYXJlKHJpZ2h0LCBcImVuXCIpXG59XG5cbi8qKlxuICogQHR5cGVkZWYgUHJvamVjdFdhdGNoT2JzZXJ2YXRpb25cbiAqIEBwcm9wZXJ0eSB7XCJjeWNsZS1zdGFydFwiIHwgXCJjeWNsZS10ZXJtaW5hbFwiIHwgXCJkaXJ0eVwiIHwgXCJyZWFkeVwiIHwgXCJyZWNvbmNpbGVkXCIgfCBcInN0b3BwZWRcIiB8IFwid2F0Y2gtYmFja2VuZFwifSB0eXBlIC0gTWFya2VyIHR5cGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2N5Y2xlXSAtIFJlbGF0ZWQgY3ljbGUgbnVtYmVyLlxuICogQHByb3BlcnR5IHtcImNhbmNlbGxlZFwiIHwgXCJkaXJ0eVwiIHwgXCJmYWlsZWRcIiB8IFwibmF0aXZlXCIgfCBcInBvbGxpbmdcIiB8IFwicmVhZHlcIiB8IFwicmVjb3ZlcmVkXCIgfCBcInN0YXJ0ZWRcIiB8IFwic3RvcHBlZFwiIHwgXCJzdWNjZWVkZWRcIiB8IFwic3VwZXJzZWRlZFwiIHwgXCJ1bmNoYW5nZWRcIn0gc3RhdHVzIC0gTWFya2VyIHN0YXR1cy5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIFByb2plY3RXYXRjaFJlc3VsdFxuICogQHByb3BlcnR5IHtcImZhaWxlZFwiIHwgXCJzdG9wcGVkXCJ9IHN0YXR1cyAtIFdhdGNoZXIgdGVybWluYWwgc3RhdGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gY3ljbGVzIC0gQWRtaXR0ZWQgY3ljbGUgY291bnQuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gcmVhc29uIC0gU3RhYmxlIHRlcm1pbmFsIHJlYXNvbi5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIFdhdGNoQ3ljbGVJbnB1dFxuICogQHByb3BlcnR5IHtyZWFkb25seSBzdHJpbmdbXX0gY2hhbmdlZFBhdGhzIC0gU3RhYmxlIGNoYW5nZWQgcGF0aHMuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGNoZWNrIC0gV2hldGhlciB0YXJnZXQgY2hlY2tzIGFyZSBlbmFibGVkLlxuICogQHByb3BlcnR5IHt1bmtub3dufSBbZmFpbHVyZV0gLSBQcmVzZXJ2ZWQgcmVjb25jaWxpYXRpb24gZmFpbHVyZS5cbiAqIEBwcm9wZXJ0eSB7U2VtYW50aWZvbGRQcm9qZWN0IHwgdW5kZWZpbmVkfSBwcm9qZWN0IC0gUmVjb25jaWxlZCBwcm9qZWN0LCB3aGVuIHZhbGlkLlxuICogQHByb3BlcnR5IHtQcm9qZWN0U25hcHNob3QgfCB1bmRlZmluZWR9IHNuYXBzaG90IC0gUmVjb25jaWxlZCBzbmFwc2hvdCwgd2hlbiB2YWxpZC5cbiAqL1xuIl19