semantifold 0.9.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.
- package/README.md +6 -3
- package/bin/semantifold.js +6 -0
- package/build/bin/semantifold.d.ts +3 -0
- package/build/bin/semantifold.d.ts.map +1 -0
- package/build/bin/semantifold.js +5 -0
- package/build/index.d.ts +8 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +9 -1
- package/build/src/artifact-path.d.ts +16 -0
- package/build/src/artifact-path.d.ts.map +1 -1
- package/build/src/artifact-path.js +29 -3
- package/build/src/backends/c-check.d.ts +7 -0
- package/build/src/backends/c-check.d.ts.map +1 -0
- package/build/src/backends/c-check.js +65 -0
- package/build/src/backends/check-plan.d.ts +96 -0
- package/build/src/backends/check-plan.d.ts.map +1 -0
- package/build/src/backends/check-plan.js +135 -0
- package/build/src/backends/cpp-check.d.ts +7 -0
- package/build/src/backends/cpp-check.d.ts.map +1 -0
- package/build/src/backends/cpp-check.js +59 -0
- package/build/src/backends/csharp-check.d.ts +7 -0
- package/build/src/backends/csharp-check.d.ts.map +1 -0
- package/build/src/backends/csharp-check.js +125 -0
- package/build/src/backends/csharp.d.ts +1 -0
- package/build/src/backends/csharp.d.ts.map +1 -1
- package/build/src/backends/csharp.js +5 -4
- package/build/src/backends/dart-check.d.ts +7 -0
- package/build/src/backends/dart-check.d.ts.map +1 -0
- package/build/src/backends/dart-check.js +103 -0
- package/build/src/backends/dart.d.ts +2 -0
- package/build/src/backends/dart.d.ts.map +1 -1
- package/build/src/backends/dart.js +5 -5
- package/build/src/backends/go-check.d.ts +7 -0
- package/build/src/backends/go-check.d.ts.map +1 -0
- package/build/src/backends/go-check.js +77 -0
- package/build/src/backends/go.d.ts +1 -0
- package/build/src/backends/go.d.ts.map +1 -1
- package/build/src/backends/go.js +3 -3
- package/build/src/backends/java-check.d.ts +21 -0
- package/build/src/backends/java-check.d.ts.map +1 -0
- package/build/src/backends/java-check.js +73 -0
- package/build/src/backends/javascript-check.d.ts +7 -0
- package/build/src/backends/javascript-check.d.ts.map +1 -0
- package/build/src/backends/javascript-check.js +29 -0
- package/build/src/backends/kotlin-check.d.ts +7 -0
- package/build/src/backends/kotlin-check.d.ts.map +1 -0
- package/build/src/backends/kotlin-check.js +31 -0
- package/build/src/backends/php-check.d.ts +7 -0
- package/build/src/backends/php-check.d.ts.map +1 -0
- package/build/src/backends/php-check.js +21 -0
- package/build/src/backends/program.d.ts +7 -0
- package/build/src/backends/program.d.ts.map +1 -1
- package/build/src/backends/program.js +16 -1
- package/build/src/backends/python-check.d.ts +7 -0
- package/build/src/backends/python-check.d.ts.map +1 -0
- package/build/src/backends/python-check.js +28 -0
- package/build/src/backends/ruby-check.d.ts +7 -0
- package/build/src/backends/ruby-check.d.ts.map +1 -0
- package/build/src/backends/ruby-check.js +21 -0
- package/build/src/backends/rust-check.d.ts +7 -0
- package/build/src/backends/rust-check.d.ts.map +1 -0
- package/build/src/backends/rust-check.js +65 -0
- package/build/src/backends/swift-check.d.ts +7 -0
- package/build/src/backends/swift-check.d.ts.map +1 -0
- package/build/src/backends/swift-check.js +77 -0
- package/build/src/backends/typescript-check.d.ts +7 -0
- package/build/src/backends/typescript-check.d.ts.map +1 -0
- package/build/src/backends/typescript-check.js +33 -0
- package/build/src/backends/zig-check.d.ts +7 -0
- package/build/src/backends/zig-check.d.ts.map +1 -0
- package/build/src/backends/zig-check.js +70 -0
- package/build/src/diagnostic.d.ts +13 -1
- package/build/src/diagnostic.d.ts.map +1 -1
- package/build/src/diagnostic.js +14 -2
- package/build/src/frontends/program.d.ts +6 -0
- package/build/src/frontends/program.d.ts.map +1 -1
- package/build/src/frontends/program.js +9 -1
- package/build/src/language-registry.d.ts +54 -0
- package/build/src/language-registry.d.ts.map +1 -1
- package/build/src/language-registry.js +107 -5
- package/build/src/project-build.d.ts +172 -0
- package/build/src/project-build.d.ts.map +1 -0
- package/build/src/project-build.js +320 -0
- package/build/src/project-cli.d.ts +40 -0
- package/build/src/project-cli.d.ts.map +1 -0
- package/build/src/project-cli.js +145 -0
- package/build/src/project-manifest.d.ts +148 -0
- package/build/src/project-manifest.d.ts.map +1 -0
- package/build/src/project-manifest.js +432 -0
- package/build/src/project-reporter.d.ts +81 -0
- package/build/src/project-reporter.d.ts.map +1 -0
- package/build/src/project-reporter.js +293 -0
- package/build/src/project-snapshot.d.ts +129 -0
- package/build/src/project-snapshot.d.ts.map +1 -0
- package/build/src/project-snapshot.js +362 -0
- package/build/src/project-watch-reporter.d.ts +125 -0
- package/build/src/project-watch-reporter.d.ts.map +1 -0
- package/build/src/project-watch-reporter.js +280 -0
- package/build/src/project-watch.d.ts +133 -0
- package/build/src/project-watch.d.ts.map +1 -0
- package/build/src/project-watch.js +839 -0
- package/build/src/publication.d.ts +69 -5
- package/build/src/publication.d.ts.map +1 -1
- package/build/src/publication.js +246 -57
- package/build/src/semantic/types.d.ts +303 -2
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +79 -2
- package/build/src/subprocess.d.ts +8 -0
- package/build/src/subprocess.d.ts.map +1 -1
- package/build/src/subprocess.js +50 -9
- package/build/src/target-check.d.ts +52 -0
- package/build/src/target-check.d.ts.map +1 -0
- package/build/src/target-check.js +796 -0
- package/build/src/toolchains.d.ts.map +1 -1
- package/build/src/toolchains.js +3 -3
- package/docs/architecture.md +3 -1
- package/docs/c.md +4 -0
- package/docs/cpp.md +4 -0
- package/docs/dart.md +4 -0
- package/docs/generated-artifact-publication.md +11 -8
- package/docs/kotlin.md +2 -2
- package/docs/language-support.md +29 -3
- package/docs/project-build-cli.md +147 -0
- package/docs/project-watch.md +60 -0
- package/docs/rust.md +4 -0
- package/docs/swift.md +2 -0
- package/docs/testing.md +70 -3
- package/docs/watch-build-pipeline.md +39 -23
- package/docs/zig.md +2 -0
- package/examples/jsdoc-java-watch/expected-output.txt +3 -0
- package/examples/jsdoc-java-watch/semantifold.json +23 -0
- package/examples/jsdoc-java-watch/src/main.js +21 -0
- package/index.js +8 -0
- package/package.json +6 -1
- package/src/artifact-path.js +31 -2
- package/src/backends/c-check.js +80 -0
- package/src/backends/check-plan.js +147 -0
- package/src/backends/cpp-check.js +73 -0
- package/src/backends/csharp-check.js +139 -0
- package/src/backends/csharp.js +4 -3
- package/src/backends/dart-check.js +117 -0
- package/src/backends/dart.js +4 -4
- package/src/backends/go-check.js +89 -0
- package/src/backends/go.js +2 -2
- package/src/backends/java-check.js +77 -0
- package/src/backends/javascript-check.js +33 -0
- package/src/backends/kotlin-check.js +41 -0
- package/src/backends/php-check.js +23 -0
- package/src/backends/program.js +17 -0
- package/src/backends/python-check.js +30 -0
- package/src/backends/ruby-check.js +23 -0
- package/src/backends/rust-check.js +78 -0
- package/src/backends/swift-check.js +89 -0
- package/src/backends/typescript-check.js +37 -0
- package/src/backends/zig-check.js +81 -0
- package/src/diagnostic.js +9 -1
- package/src/frontends/program.js +9 -0
- package/src/language-registry.js +113 -4
- package/src/project-build.js +353 -0
- package/src/project-cli.js +155 -0
- package/src/project-manifest.js +479 -0
- package/src/project-reporter.js +320 -0
- package/src/project-snapshot.js +403 -0
- package/src/project-watch-reporter.js +303 -0
- package/src/project-watch.js +870 -0
- package/src/publication.js +275 -58
- package/src/semantic/types.js +87 -1
- package/src/subprocess.js +49 -8
- package/src/target-check.js +844 -0
- package/src/toolchains.js +3 -2
- 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
|