footprintjs 9.4.0 → 9.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/esm/lib/builder/FlowChartBuilder.js +15 -2
  2. package/dist/esm/lib/capture/envelope.js +187 -0
  3. package/dist/esm/lib/engine/handlers/ContinuationResolver.js +23 -4
  4. package/dist/esm/lib/engine/types.js +1 -1
  5. package/dist/esm/lib/observer-queue/deferredDispatcher.js +226 -0
  6. package/dist/esm/lib/observer-queue/flushDriver.js +163 -0
  7. package/dist/esm/lib/observer-queue/index.js +22 -0
  8. package/dist/esm/lib/observer-queue/mergedQueue.js +91 -0
  9. package/dist/esm/lib/observer-queue/ring.js +122 -0
  10. package/dist/lib/builder/FlowChartBuilder.js +15 -2
  11. package/dist/lib/capture/envelope.js +192 -0
  12. package/dist/lib/engine/handlers/ContinuationResolver.js +23 -4
  13. package/dist/lib/engine/types.js +1 -1
  14. package/dist/lib/observer-queue/deferredDispatcher.js +230 -0
  15. package/dist/lib/observer-queue/flushDriver.js +167 -0
  16. package/dist/lib/observer-queue/index.js +36 -0
  17. package/dist/lib/observer-queue/mergedQueue.js +95 -0
  18. package/dist/lib/observer-queue/ring.js +126 -0
  19. package/dist/types/lib/capture/envelope.d.ts +169 -0
  20. package/dist/types/lib/engine/handlers/ContinuationResolver.d.ts +15 -2
  21. package/dist/types/lib/engine/types.d.ts +3 -0
  22. package/dist/types/lib/observer-queue/deferredDispatcher.d.ts +169 -0
  23. package/dist/types/lib/observer-queue/flushDriver.d.ts +124 -0
  24. package/dist/types/lib/observer-queue/index.d.ts +25 -0
  25. package/dist/types/lib/observer-queue/mergedQueue.d.ts +85 -0
  26. package/dist/types/lib/observer-queue/ring.d.ts +99 -0
  27. package/package.json +1 -1
@@ -0,0 +1,230 @@
1
+ "use strict";
2
+ /**
3
+ * observer-queue/deferredDispatcher.ts — RFC-001 Block 5: deferred delivery façade.
4
+ *
5
+ * Pattern: capture → enqueue → (microtask) flush → invoke, with per-listener
6
+ * error isolation. Composes the whole pure pipeline: MergedQueue
7
+ * (Block 3, which captures via Block 1) + FlushDriver (Block 4) +
8
+ * a listener registry with timing/inflight accounting.
9
+ * Role: The object the engine wiring (Block 6) will hold. Producers call
10
+ * `capture()` (cheap, never throws, never blocks); listeners
11
+ * receive envelopes at the next checkpoint, "one beat behind".
12
+ * Pure module — zero engine imports.
13
+ *
14
+ * Delivery semantics (normative, RFC-001 §5 + amendments A2/A4):
15
+ * - Per-listener FIFO: every listener sees envelopes in seq order
16
+ * (invocation order; an async listener's COMPLETION order is its own
17
+ * concern) — EXCEPT under `'block'` overflow, where a refused enqueue
18
+ * is delivered inline and overtakes the queued backlog. `seq` always
19
+ * records true arrival order, so order-sensitive consumers re-sort;
20
+ * see the `'block'` caveat below.
21
+ * - Error isolation: a throwing listener (sync) or rejecting listener
22
+ * (async) never affects siblings or the producer. Both failure modes
23
+ * route to the injected `onError`; a throwing `onError` is itself
24
+ * swallowed.
25
+ * - The flush NEVER awaits a listener. Async continuations are tracked in
26
+ * an inflight set; `drain({ timeoutMs })` settles them
27
+ * (`Promise.allSettled` + deadline, shaped like `flushAllDetached`).
28
+ * - `'block'` overflow: a refused enqueue is delivered synchronously
29
+ * INLINE from `capture()` — re-introducing blocking delivery by the
30
+ * consumer's explicit choice. Ordering caveat (documented + tested): an
31
+ * inline event overtakes the queued backlog — `'block'` trades global
32
+ * ordering for zero loss and bounded memory. `seq` still tells the
33
+ * true arrival order.
34
+ * - Listener registry is idempotent by id (same id replaces, different
35
+ * ids coexist) — mirrors the repo-wide recorder ID contract. Stats
36
+ * accumulate per id across replacement; `removeListener` keeps the
37
+ * id's accumulated stats for post-run reports.
38
+ * - Events captured BEFORE any listener attaches stay queued — a listener
39
+ * attached before the next checkpoint still receives the backlog.
40
+ *
41
+ * Per-listener time accounting (amendment A2 — "name the hog"): cumulative
42
+ * `totalMs` and per-checkpoint `lastFlushMs` of SYNC time per listener id —
43
+ * the time that actually blocks the flush. An async listener's continuation
44
+ * time is intentionally not attributed (it does not block delivery).
45
+ */
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.DeferredDispatcher = void 0;
48
+ const flushDriver_js_1 = require("./flushDriver.js");
49
+ const mergedQueue_js_1 = require("./mergedQueue.js");
50
+ const defaultNow = () => (typeof performance !== 'undefined' ? performance.now() : Date.now());
51
+ function isThenable(value) {
52
+ return typeof value === 'object' && value !== null && typeof value.then === 'function';
53
+ }
54
+ class DeferredDispatcher {
55
+ queue;
56
+ driver;
57
+ listeners = new Map();
58
+ listenerStats = new Map();
59
+ /** Tracked async continuations — resolve `true` (ok) / `false` (failed). */
60
+ inflight = new Set();
61
+ onError;
62
+ now;
63
+ inlineDeliveries = 0;
64
+ constructor(opts) {
65
+ this.onError = opts?.onError;
66
+ this.now = opts?.now ?? defaultNow;
67
+ this.queue = new mergedQueue_js_1.MergedQueue({
68
+ maxQueue: opts?.maxQueue,
69
+ overflow: opts?.overflow,
70
+ sampleEvery: opts?.sampleEvery,
71
+ capturePolicy: opts?.capturePolicy,
72
+ hooks: opts?.hooks,
73
+ });
74
+ this.driver = new flushDriver_js_1.FlushDriver({
75
+ depth: () => this.queue.depth,
76
+ processNext: () => this.deliverNext(),
77
+ flushBudgetMs: opts?.flushBudgetMs,
78
+ now: opts?.now,
79
+ schedule: opts?.schedule,
80
+ onFlushStart: () => {
81
+ for (const stats of this.listenerStats.values())
82
+ stats.lastFlushMs = 0;
83
+ },
84
+ });
85
+ }
86
+ /** Idempotent by id — same id replaces (stats continue), ids coexist. */
87
+ addListener(id, listener) {
88
+ this.listeners.set(id, listener);
89
+ if (!this.listenerStats.has(id)) {
90
+ this.listenerStats.set(id, { events: 0, totalMs: 0, lastFlushMs: 0 });
91
+ }
92
+ }
93
+ /** Stop delivering to `id`. Accumulated stats are kept for reports. */
94
+ removeListener(id) {
95
+ this.listeners.delete(id);
96
+ }
97
+ /**
98
+ * Producer entry point: capture the event (seq-stamped, payload per
99
+ * policy) and stage it for the next checkpoint. Cheap; NEVER throws;
100
+ * never blocks — except under `'block'` overflow, where a refused
101
+ * enqueue is delivered synchronously inline (explicit consumer choice).
102
+ */
103
+ capture(input, policy) {
104
+ const result = this.queue.enqueue(input, policy);
105
+ if (result.outcome === 'queued') {
106
+ this.driver.arm();
107
+ return;
108
+ }
109
+ if (result.outcome === 'inline') {
110
+ this.inlineDeliveries += 1;
111
+ this.deliver(result.envelope);
112
+ }
113
+ // 'dropped': counted by the queue; loss surfaces in stats + seq gaps.
114
+ }
115
+ /**
116
+ * Terminal flush — synchronously deliver everything queued (end of run /
117
+ * shutdown). Async listener continuations are NOT awaited; follow with
118
+ * `drain()` for that.
119
+ */
120
+ flushNow(opts) {
121
+ return this.driver.flushSync(opts);
122
+ }
123
+ /**
124
+ * Flush the backlog, then settle all inflight async continuations —
125
+ * `Promise.allSettled` under a deadline, shaped like `flushAllDetached`.
126
+ * Loops while continuations spawn new captures, until quiescent or the
127
+ * deadline expires.
128
+ */
129
+ async drain(opts) {
130
+ const timeoutMs = opts?.timeoutMs ?? 30_000;
131
+ const startedAt = Date.now();
132
+ let done = 0;
133
+ let failed = 0;
134
+ this.flushNow();
135
+ while (this.inflight.size > 0) {
136
+ const remainingMs = timeoutMs - (Date.now() - startedAt);
137
+ if (remainingMs <= 0)
138
+ return { done, failed, pending: this.inflight.size + this.queue.depth };
139
+ const batch = [...this.inflight];
140
+ let timerId;
141
+ const timeoutPromise = new Promise((resolve) => {
142
+ timerId = setTimeout(() => resolve('__drain_timeout__'), remainingMs);
143
+ });
144
+ const settled = await Promise.race([Promise.allSettled(batch), timeoutPromise]);
145
+ if (timerId !== undefined)
146
+ clearTimeout(timerId);
147
+ if (settled === '__drain_timeout__') {
148
+ return { done, failed, pending: this.inflight.size + this.queue.depth };
149
+ }
150
+ for (const r of settled) {
151
+ // Tracked promises never reject — they resolve true (ok) / false.
152
+ if (r.status === 'fulfilled' && r.value === false)
153
+ failed += 1;
154
+ else
155
+ done += 1;
156
+ }
157
+ // Continuations may have captured more events — flush and re-check.
158
+ this.flushNow();
159
+ }
160
+ return { done, failed, pending: this.queue.depth };
161
+ }
162
+ /** A4 — the stats object Block 9 consumes. Pure getter, fresh snapshot. */
163
+ getStats() {
164
+ const counters = this.queue.getCounters();
165
+ const driverStats = this.driver.getStats();
166
+ const perListener = {};
167
+ for (const [id, stats] of this.listenerStats) {
168
+ perListener[id] = { events: stats.events, totalMs: stats.totalMs, lastFlushMs: stats.lastFlushMs };
169
+ }
170
+ return {
171
+ depth: this.queue.depth,
172
+ drops: counters.drops,
173
+ flushes: driverStats.flushes,
174
+ budgetExhausted: driverStats.budgetExhausted,
175
+ p95FlushMs: driverStats.p95FlushMs,
176
+ inlineDeliveries: this.inlineDeliveries,
177
+ inflight: this.inflight.size,
178
+ perListener,
179
+ };
180
+ }
181
+ deliverNext() {
182
+ const envelope = this.queue.shift();
183
+ if (envelope === undefined)
184
+ return;
185
+ this.deliver(envelope);
186
+ }
187
+ /** Invoke every listener with full error isolation + time accounting. */
188
+ deliver(envelope) {
189
+ for (const [id, listener] of this.listeners) {
190
+ const stats = this.listenerStats.get(id);
191
+ const start = this.now();
192
+ try {
193
+ const result = listener(envelope);
194
+ if (isThenable(result))
195
+ this.track(result, id, envelope);
196
+ }
197
+ catch (error) {
198
+ this.safeOnError(error, { listenerId: id, envelope, phase: 'sync' });
199
+ }
200
+ finally {
201
+ const elapsed = this.now() - start;
202
+ stats.events += 1;
203
+ stats.totalMs += elapsed;
204
+ stats.lastFlushMs += elapsed;
205
+ }
206
+ }
207
+ }
208
+ /** Track an async continuation; route its rejection; never reject. */
209
+ track(promise, listenerId, envelope) {
210
+ const tracked = promise.then(() => true, (error) => {
211
+ this.safeOnError(error, { listenerId, envelope, phase: 'async' });
212
+ return false;
213
+ });
214
+ this.inflight.add(tracked);
215
+ // Self-cleanup — `tracked` never rejects, so this chain cannot float an
216
+ // unhandled rejection.
217
+ tracked.then(() => this.inflight.delete(tracked));
218
+ }
219
+ /** The error sink must never become an error source. */
220
+ safeOnError(error, context) {
221
+ try {
222
+ this.onError?.(error, context);
223
+ }
224
+ catch {
225
+ // Swallow — isolation is absolute.
226
+ }
227
+ }
228
+ }
229
+ exports.DeferredDispatcher = DeferredDispatcher;
230
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVmZXJyZWREaXNwYXRjaGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi9vYnNlcnZlci1xdWV1ZS9kZWZlcnJlZERpc3BhdGNoZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMkNHOzs7QUFHSCxxREFBcUU7QUFDckUscURBQWtFO0FBd0ZsRSxNQUFNLFVBQVUsR0FBRyxHQUFXLEVBQUUsQ0FBQyxDQUFDLE9BQU8sV0FBVyxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztBQUV2RyxTQUFTLFVBQVUsQ0FBQyxLQUEyQjtJQUM3QyxPQUFPLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxLQUFLLEtBQUssSUFBSSxJQUFJLE9BQVEsS0FBdUIsQ0FBQyxJQUFJLEtBQUssVUFBVSxDQUFDO0FBQzVHLENBQUM7QUFFRCxNQUFhLGtCQUFrQjtJQUNaLEtBQUssQ0FBYztJQUNuQixNQUFNLENBQWM7SUFDcEIsU0FBUyxHQUFHLElBQUksR0FBRyxFQUE0QixDQUFDO0lBQ2hELGFBQWEsR0FBRyxJQUFJLEdBQUcsRUFBZ0MsQ0FBQztJQUN6RSw0RUFBNEU7SUFDM0QsUUFBUSxHQUFHLElBQUksR0FBRyxFQUFvQixDQUFDO0lBQ3ZDLE9BQU8sQ0FBd0I7SUFDL0IsR0FBRyxDQUFlO0lBQzNCLGdCQUFnQixHQUFHLENBQUMsQ0FBQztJQUU3QixZQUFZLElBQWdDO1FBQzFDLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxFQUFFLE9BQU8sQ0FBQztRQUM3QixJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksRUFBRSxHQUFHLElBQUksVUFBVSxDQUFDO1FBQ25DLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSw0QkFBVyxDQUFDO1lB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QUFJLENBQzVDLEdBQUcsRUFBRSxDQUFDLElBQUksRUFDVixDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ1IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ2xFLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQyxDQUNGLENBQUM7UUFDRixJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMzQix3RUFBd0U7UUFDeEUsdUJBQXVCO1FBQ3ZCLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQsd0RBQXdEO0lBQ2hELFdBQVcsQ0FBQyxLQUFjLEVBQUUsT0FBNkI7UUFDL0QsSUFBSSxDQUFDO1lBQ0gsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNqQyxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsbUNBQW1DO1FBQ3JDLENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUFwTEQsZ0RBb0xDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBvYnNlcnZlci1xdWV1ZS9kZWZlcnJlZERpc3BhdGNoZXIudHMg4oCUIFJGQy0wMDEgQmxvY2sgNTogZGVmZXJyZWQgZGVsaXZlcnkgZmHDp2FkZS5cbiAqXG4gKiBQYXR0ZXJuOiAgY2FwdHVyZSDihpIgZW5xdWV1ZSDihpIgKG1pY3JvdGFzaykgZmx1c2gg4oaSIGludm9rZSwgd2l0aCBwZXItbGlzdGVuZXJcbiAqICAgICAgICAgICBlcnJvciBpc29sYXRpb24uIENvbXBvc2VzIHRoZSB3aG9sZSBwdXJlIHBpcGVsaW5lOiBNZXJnZWRRdWV1ZVxuICogICAgICAgICAgIChCbG9jayAzLCB3aGljaCBjYXB0dXJlcyB2aWEgQmxvY2sgMSkgKyBGbHVzaERyaXZlciAoQmxvY2sgNCkgK1xuICogICAgICAgICAgIGEgbGlzdGVuZXIgcmVnaXN0cnkgd2l0aCB0aW1pbmcvaW5mbGlnaHQgYWNjb3VudGluZy5cbiAqIFJvbGU6ICAgICBUaGUgb2JqZWN0IHRoZSBlbmdpbmUgd2lyaW5nIChCbG9jayA2KSB3aWxsIGhvbGQuIFByb2R1Y2VycyBjYWxsXG4gKiAgICAgICAgICAgYGNhcHR1cmUoKWAgKGNoZWFwLCBuZXZlciB0aHJvd3MsIG5ldmVyIGJsb2Nrcyk7IGxpc3RlbmVyc1xuICogICAgICAgICAgIHJlY2VpdmUgZW52ZWxvcGVzIGF0IHRoZSBuZXh0IGNoZWNrcG9pbnQsIFwib25lIGJlYXQgYmVoaW5kXCIuXG4gKiAgICAgICAgICAgUHVyZSBtb2R1bGUg4oCUIHplcm8gZW5naW5lIGltcG9ydHMuXG4gKlxuICogRGVsaXZlcnkgc2VtYW50aWNzIChub3JtYXRpdmUsIFJGQy0wMDEgwqc1ICsgYW1lbmRtZW50cyBBMi9BNCk6XG4gKiAgIC0gUGVyLWxpc3RlbmVyIEZJRk86IGV2ZXJ5IGxpc3RlbmVyIHNlZXMgZW52ZWxvcGVzIGluIHNlcSBvcmRlclxuICogICAgIChpbnZvY2F0aW9uIG9yZGVyOyBhbiBhc3luYyBsaXN0ZW5lcidzIENPTVBMRVRJT04gb3JkZXIgaXMgaXRzIG93blxuICogICAgIGNvbmNlcm4pIOKAlCBFWENFUFQgdW5kZXIgYCdibG9jaydgIG92ZXJmbG93LCB3aGVyZSBhIHJlZnVzZWQgZW5xdWV1ZVxuICogICAgIGlzIGRlbGl2ZXJlZCBpbmxpbmUgYW5kIG92ZXJ0YWtlcyB0aGUgcXVldWVkIGJhY2tsb2cuIGBzZXFgIGFsd2F5c1xuICogICAgIHJlY29yZHMgdHJ1ZSBhcnJpdmFsIG9yZGVyLCBzbyBvcmRlci1zZW5zaXRpdmUgY29uc3VtZXJzIHJlLXNvcnQ7XG4gKiAgICAgc2VlIHRoZSBgJ2Jsb2NrJ2AgY2F2ZWF0IGJlbG93LlxuICogICAtIEVycm9yIGlzb2xhdGlvbjogYSB0aHJvd2luZyBsaXN0ZW5lciAoc3luYykgb3IgcmVqZWN0aW5nIGxpc3RlbmVyXG4gKiAgICAgKGFzeW5jKSBuZXZlciBhZmZlY3RzIHNpYmxpbmdzIG9yIHRoZSBwcm9kdWNlci4gQm90aCBmYWlsdXJlIG1vZGVzXG4gKiAgICAgcm91dGUgdG8gdGhlIGluamVjdGVkIGBvbkVycm9yYDsgYSB0aHJvd2luZyBgb25FcnJvcmAgaXMgaXRzZWxmXG4gKiAgICAgc3dhbGxvd2VkLlxuICogICAtIFRoZSBmbHVzaCBORVZFUiBhd2FpdHMgYSBsaXN0ZW5lci4gQXN5bmMgY29udGludWF0aW9ucyBhcmUgdHJhY2tlZCBpblxuICogICAgIGFuIGluZmxpZ2h0IHNldDsgYGRyYWluKHsgdGltZW91dE1zIH0pYCBzZXR0bGVzIHRoZW1cbiAqICAgICAoYFByb21pc2UuYWxsU2V0dGxlZGAgKyBkZWFkbGluZSwgc2hhcGVkIGxpa2UgYGZsdXNoQWxsRGV0YWNoZWRgKS5cbiAqICAgLSBgJ2Jsb2NrJ2Agb3ZlcmZsb3c6IGEgcmVmdXNlZCBlbnF1ZXVlIGlzIGRlbGl2ZXJlZCBzeW5jaHJvbm91c2x5XG4gKiAgICAgSU5MSU5FIGZyb20gYGNhcHR1cmUoKWAg4oCUIHJlLWludHJvZHVjaW5nIGJsb2NraW5nIGRlbGl2ZXJ5IGJ5IHRoZVxuICogICAgIGNvbnN1bWVyJ3MgZXhwbGljaXQgY2hvaWNlLiBPcmRlcmluZyBjYXZlYXQgKGRvY3VtZW50ZWQgKyB0ZXN0ZWQpOiBhblxuICogICAgIGlubGluZSBldmVudCBvdmVydGFrZXMgdGhlIHF1ZXVlZCBiYWNrbG9nIOKAlCBgJ2Jsb2NrJ2AgdHJhZGVzIGdsb2JhbFxuICogICAgIG9yZGVyaW5nIGZvciB6ZXJvIGxvc3MgYW5kIGJvdW5kZWQgbWVtb3J5LiBgc2VxYCBzdGlsbCB0ZWxscyB0aGVcbiAqICAgICB0cnVlIGFycml2YWwgb3JkZXIuXG4gKiAgIC0gTGlzdGVuZXIgcmVnaXN0cnkgaXMgaWRlbXBvdGVudCBieSBpZCAoc2FtZSBpZCByZXBsYWNlcywgZGlmZmVyZW50XG4gKiAgICAgaWRzIGNvZXhpc3QpIOKAlCBtaXJyb3JzIHRoZSByZXBvLXdpZGUgcmVjb3JkZXIgSUQgY29udHJhY3QuIFN0YXRzXG4gKiAgICAgYWNjdW11bGF0ZSBwZXIgaWQgYWNyb3NzIHJlcGxhY2VtZW50OyBgcmVtb3ZlTGlzdGVuZXJgIGtlZXBzIHRoZVxuICogICAgIGlkJ3MgYWNjdW11bGF0ZWQgc3RhdHMgZm9yIHBvc3QtcnVuIHJlcG9ydHMuXG4gKiAgIC0gRXZlbnRzIGNhcHR1cmVkIEJFRk9SRSBhbnkgbGlzdGVuZXIgYXR0YWNoZXMgc3RheSBxdWV1ZWQg4oCUIGEgbGlzdGVuZXJcbiAqICAgICBhdHRhY2hlZCBiZWZvcmUgdGhlIG5leHQgY2hlY2twb2ludCBzdGlsbCByZWNlaXZlcyB0aGUgYmFja2xvZy5cbiAqXG4gKiBQZXItbGlzdGVuZXIgdGltZSBhY2NvdW50aW5nIChhbWVuZG1lbnQgQTIg4oCUIFwibmFtZSB0aGUgaG9nXCIpOiBjdW11bGF0aXZlXG4gKiBgdG90YWxNc2AgYW5kIHBlci1jaGVja3BvaW50IGBsYXN0Rmx1c2hNc2Agb2YgU1lOQyB0aW1lIHBlciBsaXN0ZW5lciBpZCDigJRcbiAqIHRoZSB0aW1lIHRoYXQgYWN0dWFsbHkgYmxvY2tzIHRoZSBmbHVzaC4gQW4gYXN5bmMgbGlzdGVuZXIncyBjb250aW51YXRpb25cbiAqIHRpbWUgaXMgaW50ZW50aW9uYWxseSBub3QgYXR0cmlidXRlZCAoaXQgZG9lcyBub3QgYmxvY2sgZGVsaXZlcnkpLlxuICovXG5cbmltcG9ydCB7IHR5cGUgQ2FwdHVyZUVudmVsb3BlLCB0eXBlIENhcHR1cmVIb29rcywgdHlwZSBDYXB0dXJlUG9saWN5IH0gZnJvbSAnLi4vY2FwdHVyZS9lbnZlbG9wZS5qcyc7XG5pbXBvcnQgeyB0eXBlIEZsdXNoU3luY1Jlc3VsdCwgRmx1c2hEcml2ZXIgfSBmcm9tICcuL2ZsdXNoRHJpdmVyLmpzJztcbmltcG9ydCB7IHR5cGUgRW5xdWV1ZUlucHV0LCBNZXJnZWRRdWV1ZSB9IGZyb20gJy4vbWVyZ2VkUXVldWUuanMnO1xuaW1wb3J0IHsgdHlwZSBPdmVyZmxvd1BvbGljeSB9IGZyb20gJy4vcmluZy5qcyc7XG5cbi8qKlxuICogT25lIGRlZmVycmVkIG9ic2VydmVyLiBNYXkgcmV0dXJuIGEgUHJvbWlzZSDigJQgdGhlIGRpc3BhdGNoZXIgdHJhY2tzIGl0IGluXG4gKiB0aGUgaW5mbGlnaHQgc2V0IGJ1dCBORVZFUiBhd2FpdHMgaXQgZHVyaW5nIGEgZmx1c2guXG4gKi9cbmV4cG9ydCB0eXBlIERlZmVycmVkTGlzdGVuZXIgPSAoZW52ZWxvcGU6IENhcHR1cmVFbnZlbG9wZSkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD47XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGlzcGF0Y2hFcnJvckNvbnRleHQge1xuICByZWFkb25seSBsaXN0ZW5lcklkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGVudmVsb3BlOiBDYXB0dXJlRW52ZWxvcGU7XG4gIC8qKiBgJ3N5bmMnYCA9IGxpc3RlbmVyIHRocmV3OyBgJ2FzeW5jJ2AgPSByZXR1cm5lZCBwcm9taXNlIHJlamVjdGVkLiAqL1xuICByZWFkb25seSBwaGFzZTogJ3N5bmMnIHwgJ2FzeW5jJztcbn1cblxuLyoqIEluamVjdGVkIGVycm9yIHNpbmsg4oCUIHRoZSB3aXJpbmcgbGF5ZXIgcm91dGVzIHRoZXNlIChCbG9jayA2KS4gKi9cbmV4cG9ydCB0eXBlIERpc3BhdGNoRXJyb3JIYW5kbGVyID0gKGVycm9yOiB1bmtub3duLCBjb250ZXh0OiBEaXNwYXRjaEVycm9yQ29udGV4dCkgPT4gdm9pZDtcblxuZXhwb3J0IGludGVyZmFjZSBEZWZlcnJlZERpc3BhdGNoZXJPcHRpb25zIHtcbiAgLyoqIFF1ZXVlIGJvdW5kIOKAlCBkZWZhdWx0IDEwIDAwMCAoc2VlIGBNZXJnZWRRdWV1ZWApLiAqL1xuICByZWFkb25seSBtYXhRdWV1ZT86IG51bWJlcjtcbiAgLyoqIE92ZXJmbG93IHBvbGljeSDigJQgZGVmYXVsdCBgJ2Ryb3Atb2xkZXN0J2AuICovXG4gIHJlYWRvbmx5IG92ZXJmbG93PzogT3ZlcmZsb3dQb2xpY3k7XG4gIC8qKiBgJ3NhbXBsZSdgIG92ZXJmbG93IG9ubHkg4oCUIGFkbWl0IDEgaW4gdGhpcyBtYW55IHNhdHVyYXRlZCBhcnJpdmFscy4gKi9cbiAgcmVhZG9ubHkgc2FtcGxlRXZlcnk/OiBudW1iZXI7XG4gIC8qKiBEZWZhdWx0IGNhcHR1cmUgcG9saWN5IOKAlCBkZWZhdWx0IGAnc3VtbWFyeSdgLiAqL1xuICByZWFkb25seSBjYXB0dXJlUG9saWN5PzogQ2FwdHVyZVBvbGljeTtcbiAgLyoqIFBlci1mbHVzaCB0aW1lIGJ1ZGdldCwgbXMgKEExKSDigJQgZGVmYXVsdCAyOyBgSW5maW5pdHlgID0gZnVsbCBkcmFpbi4gKi9cbiAgcmVhZG9ubHkgZmx1c2hCdWRnZXRNcz86IG51bWJlcjtcbiAgLyoqIExpc3RlbmVyLWZhaWx1cmUgc2luay4gTm8gZGVmYXVsdCDigJQgd2l0aG91dCBpdCwgZmFpbHVyZXMgYXJlIHNpbGVudC4gKi9cbiAgcmVhZG9ubHkgb25FcnJvcj86IERpc3BhdGNoRXJyb3JIYW5kbGVyO1xuICAvKiogQ2FwdHVyZSBzZWFtcyAoZGV2LXdhcm4sIGNhcHR1cmVkQXQgY2xvY2spIOKAlCBzZWUgYENhcHR1cmVIb29rc2AuICovXG4gIHJlYWRvbmx5IGhvb2tzPzogQ2FwdHVyZUhvb2tzO1xuICAvKiogVGltaW5nIGNsb2NrIGZvciBidWRnZXQgKyBwZXItbGlzdGVuZXIgYWNjb3VudGluZy4gSW5qZWN0YWJsZS4gKi9cbiAgcmVhZG9ubHkgbm93PzogKCkgPT4gbnVtYmVyO1xuICAvKiogQ2hlY2twb2ludCBwcmltaXRpdmUg4oCUIGRlZmF1bHQgYHF1ZXVlTWljcm90YXNrYC4gSW5qZWN0YWJsZS4gKi9cbiAgcmVhZG9ubHkgc2NoZWR1bGU/OiAoY2I6ICgpID0+IHZvaWQpID0+IHZvaWQ7XG59XG5cbi8qKiBQZXItbGlzdGVuZXIgYWNjb3VudGluZyAoQTIvQTQpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBMaXN0ZW5lclN0YXRzIHtcbiAgLyoqIEVudmVsb3BlcyBkZWxpdmVyZWQgKGludm9jYXRpb25zLCBpbmNsdWRpbmcgb25lcyB0aGF0IHRocmV3KS4gKi9cbiAgcmVhZG9ubHkgZXZlbnRzOiBudW1iZXI7XG4gIC8qKiBDdW11bGF0aXZlIHN5bmMgZGVsaXZlcnkgdGltZSwgbXMuICovXG4gIHJlYWRvbmx5IHRvdGFsTXM6IG51bWJlcjtcbiAgLyoqIFN5bmMgZGVsaXZlcnkgdGltZSBzaW5jZSB0aGUgbGFzdCBmbHVzaCBzdGFydGVkLCBtcy4gKi9cbiAgcmVhZG9ubHkgbGFzdEZsdXNoTXM6IG51bWJlcjtcbn1cblxuLyoqIFRoZSBCbG9jayA5IG9ic2VydmFiaWxpdHkgc3VyZmFjZSAoYW1lbmRtZW50IEE0KSDigJQgcHVyZSBnZXR0ZXIuICovXG5leHBvcnQgaW50ZXJmYWNlIERpc3BhdGNoZXJTdGF0cyB7XG4gIC8qKiBDdXJyZW50IGJhY2tsb2cuICovXG4gIHJlYWRvbmx5IGRlcHRoOiBudW1iZXI7XG4gIC8qKiBFdmVudHMgTE9TVCAob3ZlcmZsb3cpIOKAlCBuZXZlciBzaWxlbnQ7IGFsc28gdmlzaWJsZSBhcyBzZXEgZ2Fwcy4gKi9cbiAgcmVhZG9ubHkgZHJvcHM6IG51bWJlcjtcbiAgLyoqIENvbXBsZXRlZCBjaGVja3BvaW50IGZsdXNoZXMuICovXG4gIHJlYWRvbmx5IGZsdXNoZXM6IG51bWJlcjtcbiAgLyoqIEZsdXNoZXMgY3V0IHNob3J0IGJ5IGBmbHVzaEJ1ZGdldE1zYCAoQTEpLiAqL1xuICByZWFkb25seSBidWRnZXRFeGhhdXN0ZWQ6IG51bWJlcjtcbiAgLyoqIHA5NSBmbHVzaCBkdXJhdGlvbiwgbXMgKHJvbGxpbmcgd2luZG93KS4gKi9cbiAgcmVhZG9ubHkgcDk1Rmx1c2hNczogbnVtYmVyO1xuICAvKiogYCdibG9jaydgLXBvbGljeSByZWZ1c2FscyBkZWxpdmVyZWQgc3luY2hyb25vdXNseSBpbmxpbmUuICovXG4gIHJlYWRvbmx5IGlubGluZURlbGl2ZXJpZXM6IG51bWJlcjtcbiAgLyoqIEFzeW5jIGxpc3RlbmVyIGNvbnRpbnVhdGlvbnMgbm90IHlldCBzZXR0bGVkLiAqL1xuICByZWFkb25seSBpbmZsaWdodDogbnVtYmVyO1xuICAvKiogUGVyLWxpc3RlbmVyIHRpbWUgYWNjb3VudGluZyDigJQgXCJuYW1lIHRoZSBob2dcIiAoQTIpLiAqL1xuICByZWFkb25seSBwZXJMaXN0ZW5lcjogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgTGlzdGVuZXJTdGF0cz4+O1xufVxuXG4vKiogUmVzdWx0IG9mIHtAbGluayBEZWZlcnJlZERpc3BhdGNoZXIuZHJhaW59IOKAlCBgZmx1c2hBbGxEZXRhY2hlZGAgc2hhcGUuICovXG5leHBvcnQgaW50ZXJmYWNlIERyYWluUmVzdWx0IHtcbiAgLyoqIEFzeW5jIGNvbnRpbnVhdGlvbnMgc2VlbiBzZXR0bGluZyBmdWxmaWxsZWQuIEJlc3QtZWZmb3J0IGNvdW50IOKAlCBhXG4gICAqICBjb250aW51YXRpb24gdGhhdCBzZXR0bGVzIGJldHdlZW4gY2hlY2tzIGlzIGRyYWluZWQgYnV0IG1heSBub3QgYmVcbiAgICogIGNvdW50ZWQgKHNhbWUgc2VtYW50aWNzIGFzIGBmbHVzaEFsbERldGFjaGVkYCkuICovXG4gIHJlYWRvbmx5IGRvbmU6IG51bWJlcjtcbiAgLyoqIENvbnRpbnVhdGlvbnMgd2hvc2UgbGlzdGVuZXIgcHJvbWlzZSByZWplY3RlZCAocm91dGVkIHRvIG9uRXJyb3IpLiAqL1xuICByZWFkb25seSBmYWlsZWQ6IG51bWJlcjtcbiAgLyoqIFN0aWxsIGluIGZsaWdodCAob3IgcXVldWVkKSB3aGVuIHRoZSBkZWFkbGluZSBleHBpcmVkLiBgMGAgPSBkcmFpbmVkLiAqL1xuICByZWFkb25seSBwZW5kaW5nOiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBNdXRhYmxlTGlzdGVuZXJTdGF0cyB7XG4gIGV2ZW50czogbnVtYmVyO1xuICB0b3RhbE1zOiBudW1iZXI7XG4gIGxhc3RGbHVzaE1zOiBudW1iZXI7XG59XG5cbmNvbnN0IGRlZmF1bHROb3cgPSAoKTogbnVtYmVyID0+ICh0eXBlb2YgcGVyZm9ybWFuY2UgIT09ICd1bmRlZmluZWQnID8gcGVyZm9ybWFuY2Uubm93KCkgOiBEYXRlLm5vdygpKTtcblxuZnVuY3Rpb24gaXNUaGVuYWJsZSh2YWx1ZTogdm9pZCB8IFByb21pc2U8dm9pZD4pOiB2YWx1ZSBpcyBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGwgJiYgdHlwZW9mICh2YWx1ZSBhcyBQcm9taXNlPHZvaWQ+KS50aGVuID09PSAnZnVuY3Rpb24nO1xufVxuXG5leHBvcnQgY2xhc3MgRGVmZXJyZWREaXNwYXRjaGVyIHtcbiAgcHJpdmF0ZSByZWFkb25seSBxdWV1ZTogTWVyZ2VkUXVldWU7XG4gIHByaXZhdGUgcmVhZG9ubHkgZHJpdmVyOiBGbHVzaERyaXZlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBsaXN0ZW5lcnMgPSBuZXcgTWFwPHN0cmluZywgRGVmZXJyZWRMaXN0ZW5lcj4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBsaXN0ZW5lclN0YXRzID0gbmV3IE1hcDxzdHJpbmcsIE11dGFibGVMaXN0ZW5lclN0YXRzPigpO1xuICAvKiogVHJhY2tlZCBhc3luYyBjb250aW51YXRpb25zIOKAlCByZXNvbHZlIGB0cnVlYCAob2spIC8gYGZhbHNlYCAoZmFpbGVkKS4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBpbmZsaWdodCA9IG5ldyBTZXQ8UHJvbWlzZTxib29sZWFuPj4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBvbkVycm9yPzogRGlzcGF0Y2hFcnJvckhhbmRsZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgbm93OiAoKSA9PiBudW1iZXI7XG4gIHByaXZhdGUgaW5saW5lRGVsaXZlcmllcyA9IDA7XG5cbiAgY29uc3RydWN0b3Iob3B0cz86IERlZmVycmVkRGlzcGF0Y2hlck9wdGlvbnMpIHtcbiAgICB0aGlzLm9uRXJyb3IgPSBvcHRzPy5vbkVycm9yO1xuICAgIHRoaXMubm93ID0gb3B0cz8ubm93ID8/IGRlZmF1bHROb3c7XG4gICAgdGhpcy5xdWV1ZSA9IG5ldyBNZXJnZWRRdWV1ZSh7XG4gICAgICBtYXhRdWV1ZTogb3B0cz8ubWF4UXVldWUsXG4gICAgICBvdmVyZmxvdzogb3B0cz8ub3ZlcmZsb3csXG4gICAgICBzYW1wbGVFdmVyeTogb3B0cz8uc2FtcGxlRXZlcnksXG4gICAgICBjYXB0dXJlUG9saWN5OiBvcHRzPy5jYXB0dXJlUG9saWN5LFxuICAgICAgaG9va3M6IG9wdHM/Lmhvb2tzLFxuICAgIH0pO1xuICAgIHRoaXMuZHJpdmVyID0gbmV3IEZsdXNoRHJpdmVyKHtcbiAgICAgIGRlcHRoOiAoKSA9PiB0aGlzLnF1ZXVlLmRlcHRoLFxuICAgICAgcHJvY2Vzc05leHQ6ICgpID0+IHRoaXMuZGVsaXZlck5leHQoKSxcbiAgICAgIGZsdXNoQnVkZ2V0TXM6IG9wdHM/LmZsdXNoQnVkZ2V0TXMsXG4gICAgICBub3c6IG9wdHM/Lm5vdyxcbiAgICAgIHNjaGVkdWxlOiBvcHRzPy5zY2hlZHVsZSxcbiAgICAgIG9uRmx1c2hTdGFydDogKCkgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IHN0YXRzIG9mIHRoaXMubGlzdGVuZXJTdGF0cy52YWx1ZXMoKSkgc3RhdHMubGFzdEZsdXNoTXMgPSAwO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBJZGVtcG90ZW50IGJ5IGlkIOKAlCBzYW1lIGlkIHJlcGxhY2VzIChzdGF0cyBjb250aW51ZSksIGlkcyBjb2V4aXN0LiAqL1xuICBhZGRMaXN0ZW5lcihpZDogc3RyaW5nLCBsaXN0ZW5lcjogRGVmZXJyZWRMaXN0ZW5lcik6IHZvaWQge1xuICAgIHRoaXMubGlzdGVuZXJzLnNldChpZCwgbGlzdGVuZXIpO1xuICAgIGlmICghdGhpcy5saXN0ZW5lclN0YXRzLmhhcyhpZCkpIHtcbiAgICAgIHRoaXMubGlzdGVuZXJTdGF0cy5zZXQoaWQsIHsgZXZlbnRzOiAwLCB0b3RhbE1zOiAwLCBsYXN0Rmx1c2hNczogMCB9KTtcbiAgICB9XG4gIH1cblxuICAvKiogU3RvcCBkZWxpdmVyaW5nIHRvIGBpZGAuIEFjY3VtdWxhdGVkIHN0YXRzIGFyZSBrZXB0IGZvciByZXBvcnRzLiAqL1xuICByZW1vdmVMaXN0ZW5lcihpZDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5saXN0ZW5lcnMuZGVsZXRlKGlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9kdWNlciBlbnRyeSBwb2ludDogY2FwdHVyZSB0aGUgZXZlbnQgKHNlcS1zdGFtcGVkLCBwYXlsb2FkIHBlclxuICAgKiBwb2xpY3kpIGFuZCBzdGFnZSBpdCBmb3IgdGhlIG5leHQgY2hlY2twb2ludC4gQ2hlYXA7IE5FVkVSIHRocm93cztcbiAgICogbmV2ZXIgYmxvY2tzIOKAlCBleGNlcHQgdW5kZXIgYCdibG9jaydgIG92ZXJmbG93LCB3aGVyZSBhIHJlZnVzZWRcbiAgICogZW5xdWV1ZSBpcyBkZWxpdmVyZWQgc3luY2hyb25vdXNseSBpbmxpbmUgKGV4cGxpY2l0IGNvbnN1bWVyIGNob2ljZSkuXG4gICAqL1xuICBjYXB0dXJlKGlucHV0OiBFbnF1ZXVlSW5wdXQsIHBvbGljeT86IENhcHR1cmVQb2xpY3kpOiB2b2lkIHtcbiAgICBjb25zdCByZXN1bHQgPSB0aGlzLnF1ZXVlLmVucXVldWUoaW5wdXQsIHBvbGljeSk7XG4gICAgaWYgKHJlc3VsdC5vdXRjb21lID09PSAncXVldWVkJykge1xuICAgICAgdGhpcy5kcml2ZXIuYXJtKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChyZXN1bHQub3V0Y29tZSA9PT0gJ2lubGluZScpIHtcbiAgICAgIHRoaXMuaW5saW5lRGVsaXZlcmllcyArPSAxO1xuICAgICAgdGhpcy5kZWxpdmVyKHJlc3VsdC5lbnZlbG9wZSk7XG4gICAgfVxuICAgIC8vICdkcm9wcGVkJzogY291bnRlZCBieSB0aGUgcXVldWU7IGxvc3Mgc3VyZmFjZXMgaW4gc3RhdHMgKyBzZXEgZ2Fwcy5cbiAgfVxuXG4gIC8qKlxuICAgKiBUZXJtaW5hbCBmbHVzaCDigJQgc3luY2hyb25vdXNseSBkZWxpdmVyIGV2ZXJ5dGhpbmcgcXVldWVkIChlbmQgb2YgcnVuIC9cbiAgICogc2h1dGRvd24pLiBBc3luYyBsaXN0ZW5lciBjb250aW51YXRpb25zIGFyZSBOT1QgYXdhaXRlZDsgZm9sbG93IHdpdGhcbiAgICogYGRyYWluKClgIGZvciB0aGF0LlxuICAgKi9cbiAgZmx1c2hOb3cob3B0cz86IHsgbWF4Um91bmRzPzogbnVtYmVyIH0pOiBGbHVzaFN5bmNSZXN1bHQge1xuICAgIHJldHVybiB0aGlzLmRyaXZlci5mbHVzaFN5bmMob3B0cyk7XG4gIH1cblxuICAvKipcbiAgICogRmx1c2ggdGhlIGJhY2tsb2csIHRoZW4gc2V0dGxlIGFsbCBpbmZsaWdodCBhc3luYyBjb250aW51YXRpb25zIOKAlFxuICAgKiBgUHJvbWlzZS5hbGxTZXR0bGVkYCB1bmRlciBhIGRlYWRsaW5lLCBzaGFwZWQgbGlrZSBgZmx1c2hBbGxEZXRhY2hlZGAuXG4gICAqIExvb3BzIHdoaWxlIGNvbnRpbnVhdGlvbnMgc3Bhd24gbmV3IGNhcHR1cmVzLCB1bnRpbCBxdWllc2NlbnQgb3IgdGhlXG4gICAqIGRlYWRsaW5lIGV4cGlyZXMuXG4gICAqL1xuICBhc3luYyBkcmFpbihvcHRzPzogeyB0aW1lb3V0TXM/OiBudW1iZXIgfSk6IFByb21pc2U8RHJhaW5SZXN1bHQ+IHtcbiAgICBjb25zdCB0aW1lb3V0TXMgPSBvcHRzPy50aW1lb3V0TXMgPz8gMzBfMDAwO1xuICAgIGNvbnN0IHN0YXJ0ZWRBdCA9IERhdGUubm93KCk7XG4gICAgbGV0IGRvbmUgPSAwO1xuICAgIGxldCBmYWlsZWQgPSAwO1xuXG4gICAgdGhpcy5mbHVzaE5vdygpO1xuICAgIHdoaWxlICh0aGlzLmluZmxpZ2h0LnNpemUgPiAwKSB7XG4gICAgICBjb25zdCByZW1haW5pbmdNcyA9IHRpbWVvdXRNcyAtIChEYXRlLm5vdygpIC0gc3RhcnRlZEF0KTtcbiAgICAgIGlmIChyZW1haW5pbmdNcyA8PSAwKSByZXR1cm4geyBkb25lLCBmYWlsZWQsIHBlbmRpbmc6IHRoaXMuaW5mbGlnaHQuc2l6ZSArIHRoaXMucXVldWUuZGVwdGggfTtcblxuICAgICAgY29uc3QgYmF0Y2ggPSBbLi4udGhpcy5pbmZsaWdodF07XG4gICAgICBsZXQgdGltZXJJZDogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCB1bmRlZmluZWQ7XG4gICAgICBjb25zdCB0aW1lb3V0UHJvbWlzZSA9IG5ldyBQcm9taXNlPCdfX2RyYWluX3RpbWVvdXRfXyc+KChyZXNvbHZlKSA9PiB7XG4gICAgICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KCgpID0+IHJlc29sdmUoJ19fZHJhaW5fdGltZW91dF9fJyksIHJlbWFpbmluZ01zKTtcbiAgICAgIH0pO1xuICAgICAgY29uc3Qgc2V0dGxlZCA9IGF3YWl0IFByb21pc2UucmFjZShbUHJvbWlzZS5hbGxTZXR0bGVkKGJhdGNoKSwgdGltZW91dFByb21pc2VdKTtcbiAgICAgIGlmICh0aW1lcklkICE9PSB1bmRlZmluZWQpIGNsZWFyVGltZW91dCh0aW1lcklkKTtcbiAgICAgIGlmIChzZXR0bGVkID09PSAnX19kcmFpbl90aW1lb3V0X18nKSB7XG4gICAgICAgIHJldHVybiB7IGRvbmUsIGZhaWxlZCwgcGVuZGluZzogdGhpcy5pbmZsaWdodC5zaXplICsgdGhpcy5xdWV1ZS5kZXB0aCB9O1xuICAgICAgfVxuICAgICAgZm9yIChjb25zdCByIG9mIHNldHRsZWQpIHtcbiAgICAgICAgLy8gVHJhY2tlZCBwcm9taXNlcyBuZXZlciByZWplY3Qg4oCUIHRoZXkgcmVzb2x2ZSB0cnVlIChvaykgLyBmYWxzZS5cbiAgICAgICAgaWYgKHIuc3RhdHVzID09PSAnZnVsZmlsbGVkJyAmJiByLnZhbHVlID09PSBmYWxzZSkgZmFpbGVkICs9IDE7XG4gICAgICAgIGVsc2UgZG9uZSArPSAxO1xuICAgICAgfVxuICAgICAgLy8gQ29udGludWF0aW9ucyBtYXkgaGF2ZSBjYXB0dXJlZCBtb3JlIGV2ZW50cyDigJQgZmx1c2ggYW5kIHJlLWNoZWNrLlxuICAgICAgdGhpcy5mbHVzaE5vdygpO1xuICAgIH1cbiAgICByZXR1cm4geyBkb25lLCBmYWlsZWQsIHBlbmRpbmc6IHRoaXMucXVldWUuZGVwdGggfTtcbiAgfVxuXG4gIC8qKiBBNCDigJQgdGhlIHN0YXRzIG9iamVjdCBCbG9jayA5IGNvbnN1bWVzLiBQdXJlIGdldHRlciwgZnJlc2ggc25hcHNob3QuICovXG4gIGdldFN0YXRzKCk6IERpc3BhdGNoZXJTdGF0cyB7XG4gICAgY29uc3QgY291bnRlcnMgPSB0aGlzLnF1ZXVlLmdldENvdW50ZXJzKCk7XG4gICAgY29uc3QgZHJpdmVyU3RhdHMgPSB0aGlzLmRyaXZlci5nZXRTdGF0cygpO1xuICAgIGNvbnN0IHBlckxpc3RlbmVyOiBSZWNvcmQ8c3RyaW5nLCBMaXN0ZW5lclN0YXRzPiA9IHt9O1xuICAgIGZvciAoY29uc3QgW2lkLCBzdGF0c10gb2YgdGhpcy5saXN0ZW5lclN0YXRzKSB7XG4gICAgICBwZXJMaXN0ZW5lcltpZF0gPSB7IGV2ZW50czogc3RhdHMuZXZlbnRzLCB0b3RhbE1zOiBzdGF0cy50b3RhbE1zLCBsYXN0Rmx1c2hNczogc3RhdHMubGFzdEZsdXNoTXMgfTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGRlcHRoOiB0aGlzLnF1ZXVlLmRlcHRoLFxuICAgICAgZHJvcHM6IGNvdW50ZXJzLmRyb3BzLFxuICAgICAgZmx1c2hlczogZHJpdmVyU3RhdHMuZmx1c2hlcyxcbiAgICAgIGJ1ZGdldEV4aGF1c3RlZDogZHJpdmVyU3RhdHMuYnVkZ2V0RXhoYXVzdGVkLFxuICAgICAgcDk1Rmx1c2hNczogZHJpdmVyU3RhdHMucDk1Rmx1c2hNcyxcbiAgICAgIGlubGluZURlbGl2ZXJpZXM6IHRoaXMuaW5saW5lRGVsaXZlcmllcyxcbiAgICAgIGluZmxpZ2h0OiB0aGlzLmluZmxpZ2h0LnNpemUsXG4gICAgICBwZXJMaXN0ZW5lcixcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBkZWxpdmVyTmV4dCgpOiB2b2lkIHtcbiAgICBjb25zdCBlbnZlbG9wZSA9IHRoaXMucXVldWUuc2hpZnQoKTtcbiAgICBpZiAoZW52ZWxvcGUgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICAgIHRoaXMuZGVsaXZlcihlbnZlbG9wZSk7XG4gIH1cblxuICAvKiogSW52b2tlIGV2ZXJ5IGxpc3RlbmVyIHdpdGggZnVsbCBlcnJvciBpc29sYXRpb24gKyB0aW1lIGFjY291bnRpbmcuICovXG4gIHByaXZhdGUgZGVsaXZlcihlbnZlbG9wZTogQ2FwdHVyZUVudmVsb3BlKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBbaWQsIGxpc3RlbmVyXSBvZiB0aGlzLmxpc3RlbmVycykge1xuICAgICAgY29uc3Qgc3RhdHMgPSB0aGlzLmxpc3RlbmVyU3RhdHMuZ2V0KGlkKSBhcyBNdXRhYmxlTGlzdGVuZXJTdGF0cztcbiAgICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5ub3coKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGxpc3RlbmVyKGVudmVsb3BlKTtcbiAgICAgICAgaWYgKGlzVGhlbmFibGUocmVzdWx0KSkgdGhpcy50cmFjayhyZXN1bHQsIGlkLCBlbnZlbG9wZSk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICB0aGlzLnNhZmVPbkVycm9yKGVycm9yLCB7IGxpc3RlbmVySWQ6IGlkLCBlbnZlbG9wZSwgcGhhc2U6ICdzeW5jJyB9KTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGNvbnN0IGVsYXBzZWQgPSB0aGlzLm5vdygpIC0gc3RhcnQ7XG4gICAgICAgIHN0YXRzLmV2ZW50cyArPSAxO1xuICAgICAgICBzdGF0cy50b3RhbE1zICs9IGVsYXBzZWQ7XG4gICAgICAgIHN0YXRzLmxhc3RGbHVzaE1zICs9IGVsYXBzZWQ7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqIFRyYWNrIGFuIGFzeW5jIGNvbnRpbnVhdGlvbjsgcm91dGUgaXRzIHJlamVjdGlvbjsgbmV2ZXIgcmVqZWN0LiAqL1xuICBwcml2YXRlIHRyYWNrKHByb21pc2U6IFByb21pc2U8dm9pZD4sIGxpc3RlbmVySWQ6IHN0cmluZywgZW52ZWxvcGU6IENhcHR1cmVFbnZlbG9wZSk6IHZvaWQge1xuICAgIGNvbnN0IHRyYWNrZWQ6IFByb21pc2U8Ym9vbGVhbj4gPSBwcm9taXNlLnRoZW4oXG4gICAgICAoKSA9PiB0cnVlLFxuICAgICAgKGVycm9yKSA9PiB7XG4gICAgICAgIHRoaXMuc2FmZU9uRXJyb3IoZXJyb3IsIHsgbGlzdGVuZXJJZCwgZW52ZWxvcGUsIHBoYXNlOiAnYXN5bmMnIH0pO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9LFxuICAgICk7XG4gICAgdGhpcy5pbmZsaWdodC5hZGQodHJhY2tlZCk7XG4gICAgLy8gU2VsZi1jbGVhbnVwIOKAlCBgdHJhY2tlZGAgbmV2ZXIgcmVqZWN0cywgc28gdGhpcyBjaGFpbiBjYW5ub3QgZmxvYXQgYW5cbiAgICAvLyB1bmhhbmRsZWQgcmVqZWN0aW9uLlxuICAgIHRyYWNrZWQudGhlbigoKSA9PiB0aGlzLmluZmxpZ2h0LmRlbGV0ZSh0cmFja2VkKSk7XG4gIH1cblxuICAvKiogVGhlIGVycm9yIHNpbmsgbXVzdCBuZXZlciBiZWNvbWUgYW4gZXJyb3Igc291cmNlLiAqL1xuICBwcml2YXRlIHNhZmVPbkVycm9yKGVycm9yOiB1bmtub3duLCBjb250ZXh0OiBEaXNwYXRjaEVycm9yQ29udGV4dCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLm9uRXJyb3I/LihlcnJvciwgY29udGV4dCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBTd2FsbG93IOKAlCBpc29sYXRpb24gaXMgYWJzb2x1dGUuXG4gICAgfVxuICB9XG59XG4iXX0=
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ /**
3
+ * observer-queue/flushDriver.ts — RFC-001 Block 4: armed-once microtask batcher.
4
+ *
5
+ * Pattern: Kernel-style bottom-half. Producers only set a flag ("work
6
+ * pending") and return; the actual work runs at the next
7
+ * scheduling checkpoint (a microtask), drains under a time
8
+ * budget, and re-arms itself if backlog remains. Same shape as
9
+ * the detach module's `microtaskBatchDriver` — accumulate during
10
+ * the current sync slice, drain at the boundary.
11
+ * Role: The scheduler of the deferred-observer pipeline. Owns WHEN
12
+ * delivery happens; knows nothing about envelopes or listeners
13
+ * (the dispatcher, Block 5, injects `depth`/`processNext`).
14
+ * Pure module — zero imports, zero engine knowledge.
15
+ *
16
+ * Scheduling semantics (normative, RFC-001 §5 + amendment A1):
17
+ * - `arm()` is idempotent: at most ONE pending flush exists (armed flag).
18
+ * N captures between checkpoints ⇒ exactly 1 flush.
19
+ * - A flush drains a SNAPSHOT: at most `depth()`-at-flush-start items.
20
+ * Events enqueued BY listeners during the flush exceed the snapshot and
21
+ * land at the NEXT checkpoint — listener-driven cascades cannot starve
22
+ * the event loop.
23
+ * - `flushBudgetMs` (default 2; `Infinity` = full snapshot drain): the
24
+ * flush stops once the budget is exhausted, counts `budgetExhausted`,
25
+ * and re-arms. At least ONE item is processed per flush regardless of
26
+ * budget — guaranteed progress under any clock.
27
+ * - If backlog remains after the flush (budget cut OR listener enqueues),
28
+ * the driver re-arms for the next checkpoint.
29
+ *
30
+ * Why stage boundaries make this safe: the engine `await`s every stage, so
31
+ * the microtask queue runs at EVERY stage boundary — flushes are at most
32
+ * "one beat behind" the producing stage. See
33
+ * `docs/guides/execution-model.md` ("Stage boundaries are scheduling
34
+ * points") and the FAQ in `docs/design/rfc-001-deferred-observers.md`.
35
+ *
36
+ * Testability: `now` (clock) and `schedule` (checkpoint primitive) are
37
+ * injectable — tests pump flushes deterministically with a fake clock and
38
+ * a captured-callback scheduler; production uses `performance.now` and
39
+ * `queueMicrotask`.
40
+ */
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.FlushDriver = exports.FLUSH_SAMPLE_WINDOW = void 0;
43
+ /** Rolling sample window for the p95 flush-duration stat (A4). */
44
+ exports.FLUSH_SAMPLE_WINDOW = 128;
45
+ /** Default cascade cap for {@link FlushDriver.flushSync}. */
46
+ const DEFAULT_MAX_SYNC_ROUNDS = 1_000;
47
+ const defaultNow = () => (typeof performance !== 'undefined' ? performance.now() : Date.now());
48
+ class FlushDriver {
49
+ depth;
50
+ processNext;
51
+ flushBudgetMs;
52
+ now;
53
+ schedule;
54
+ onFlushStart;
55
+ onFlushEnd;
56
+ armed = false;
57
+ flushes = 0;
58
+ budgetExhaustedCount = 0;
59
+ lastFlushMs = 0;
60
+ samples = [];
61
+ sampleWriteIdx = 0;
62
+ constructor(opts) {
63
+ const budget = opts.flushBudgetMs ?? 2;
64
+ if (Number.isNaN(budget) || budget <= 0) {
65
+ throw new RangeError(`flushBudgetMs must be > 0 (got ${budget}); use Infinity for full drains`);
66
+ }
67
+ this.depth = opts.depth;
68
+ this.processNext = opts.processNext;
69
+ this.flushBudgetMs = budget;
70
+ this.now = opts.now ?? defaultNow;
71
+ this.schedule = opts.schedule ?? ((cb) => queueMicrotask(cb));
72
+ this.onFlushStart = opts.onFlushStart;
73
+ this.onFlushEnd = opts.onFlushEnd;
74
+ }
75
+ /**
76
+ * Request a flush at the next checkpoint. Idempotent — while one flush
77
+ * is pending, further arms are free no-ops (the armed-once invariant).
78
+ */
79
+ arm() {
80
+ if (this.armed)
81
+ return;
82
+ this.armed = true;
83
+ this.schedule(() => this.flush());
84
+ }
85
+ /**
86
+ * Synchronous full drain — the terminal-flush primitive (end of run /
87
+ * shutdown). Repeats snapshot rounds until the queue is empty so
88
+ * listener-enqueued cascades drain too, capped at `maxRounds` so a
89
+ * listener that enqueues forever cannot hang the process (`remaining`
90
+ * reports what the cap left behind).
91
+ */
92
+ flushSync(opts) {
93
+ const maxRounds = opts?.maxRounds ?? DEFAULT_MAX_SYNC_ROUNDS;
94
+ if (this.depth() === 0)
95
+ return { drained: 0, remaining: 0 };
96
+ this.onFlushStart?.();
97
+ const start = this.now();
98
+ let drained = 0;
99
+ for (let round = 0; round < maxRounds && this.depth() > 0; round++) {
100
+ const snapshot = this.depth();
101
+ for (let i = 0; i < snapshot && this.depth() > 0; i++) {
102
+ this.processNext();
103
+ drained += 1;
104
+ }
105
+ }
106
+ this.recordFlush(this.now() - start, false);
107
+ const remaining = this.depth();
108
+ this.onFlushEnd?.({ processed: drained, budgetExhausted: false, rearmed: false });
109
+ return { drained, remaining };
110
+ }
111
+ getStats() {
112
+ return {
113
+ flushes: this.flushes,
114
+ budgetExhausted: this.budgetExhaustedCount,
115
+ lastFlushMs: this.lastFlushMs,
116
+ p95FlushMs: this.p95FlushMs(),
117
+ armed: this.armed,
118
+ };
119
+ }
120
+ /** The microtask body — see the module-header semantics. */
121
+ flush() {
122
+ this.armed = false;
123
+ const snapshot = this.depth();
124
+ if (snapshot === 0)
125
+ return; // raced with flushSync — zero-work wakeup
126
+ this.onFlushStart?.();
127
+ const start = this.now();
128
+ let processed = 0;
129
+ let exhausted = false;
130
+ while (processed < snapshot && this.depth() > 0) {
131
+ // Budget check AFTER the first item — guaranteed progress per flush.
132
+ if (processed > 0 && this.now() - start >= this.flushBudgetMs) {
133
+ exhausted = true;
134
+ break;
135
+ }
136
+ this.processNext();
137
+ processed += 1;
138
+ }
139
+ this.recordFlush(this.now() - start, exhausted);
140
+ // Backlog left (budget cut, or listeners enqueued past the snapshot):
141
+ // hand it to the NEXT checkpoint — never starve, never spin.
142
+ const rearmed = this.depth() > 0;
143
+ if (rearmed)
144
+ this.arm();
145
+ this.onFlushEnd?.({ processed, budgetExhausted: exhausted, rearmed });
146
+ }
147
+ recordFlush(elapsedMs, exhausted) {
148
+ this.flushes += 1;
149
+ this.lastFlushMs = elapsedMs;
150
+ if (exhausted)
151
+ this.budgetExhaustedCount += 1;
152
+ if (this.samples.length < exports.FLUSH_SAMPLE_WINDOW)
153
+ this.samples.push(elapsedMs);
154
+ else {
155
+ this.samples[this.sampleWriteIdx] = elapsedMs;
156
+ this.sampleWriteIdx = (this.sampleWriteIdx + 1) % exports.FLUSH_SAMPLE_WINDOW;
157
+ }
158
+ }
159
+ p95FlushMs() {
160
+ if (this.samples.length === 0)
161
+ return 0;
162
+ const sorted = [...this.samples].sort((a, b) => a - b);
163
+ return sorted[Math.min(sorted.length - 1, Math.floor(sorted.length * 0.95))];
164
+ }
165
+ }
166
+ exports.FlushDriver = FlushDriver;
167
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmx1c2hEcml2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL29ic2VydmVyLXF1ZXVlL2ZsdXNoRHJpdmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FzQ0c7OztBQXFESCxrRUFBa0U7QUFDckQsUUFBQSxtQkFBbUIsR0FBRyxHQUFHLENBQUM7QUFFdkMsNkRBQTZEO0FBQzdELE1BQU0sdUJBQXVCLEdBQUcsS0FBSyxDQUFDO0FBRXRDLE1BQU0sVUFBVSxHQUFHLEdBQVcsRUFBRSxDQUFDLENBQUMsT0FBTyxXQUFXLEtBQUssV0FBVyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO0FBRXZHLE1BQWEsV0FBVztJQUNMLEtBQUssQ0FBZTtJQUNwQixXQUFXLENBQWE7SUFDeEIsYUFBYSxDQUFTO0lBQ3RCLEdBQUcsQ0FBZTtJQUNsQixRQUFRLENBQTJCO0lBQ25DLFlBQVksQ0FBYztJQUMxQixVQUFVLENBQW1DO0lBRXRELEtBQUssR0FBRyxLQUFLLENBQUM7SUFDZCxPQUFPLEdBQUcsQ0FBQyxDQUFDO0lBQ1osb0JBQW9CLEdBQUcsQ0FBQyxDQUFDO0lBQ3pCLFdBQVcsR0FBRyxDQUFDLENBQUM7SUFDUCxPQUFPLEdBQWEsRUFBRSxDQUFDO0lBQ2hDLGNBQWMsR0FBRyxDQUFDLENBQUM7SUFFM0IsWUFBWSxJQUF3QjtRQUNsQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxJQUFJLENBQUMsQ0FBQztRQUN2QyxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ3hDLE1BQU0sSUFBSSxVQUFVLENBQUMsa0NBQWtDLE1BQU0saUNBQWlDLENBQUMsQ0FBQztR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QUM3QixJQUFJLFNBQVM7WUFBRSxJQUFJLENBQUMsb0JBQW9CLElBQUksQ0FBQyxDQUFDO1FBQzlDLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsMkJBQW1CO1lBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7YUFDdkUsQ0FBQztZQUNKLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLFNBQVMsQ0FBQztZQUM5QyxJQUFJLENBQUMsY0FBYyxHQUFHLENBQUMsSUFBSSxDQUFDLGNBQWMsR0FBRyxDQUFDLENBQUMsR0FBRywyQkFBbUIsQ0FBQztRQUN4RSxDQUFDO0lBQ0gsQ0FBQztJQUVPLFVBQVU7UUFDaEIsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDO1lBQUUsT0FBTyxDQUFDLENBQUM7UUFDeEMsTUFBTSxNQUFNLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDdkQsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9FLENBQUM7Q0FDRjtBQXpIRCxrQ0F5SEMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIG9ic2VydmVyLXF1ZXVlL2ZsdXNoRHJpdmVyLnRzIOKAlCBSRkMtMDAxIEJsb2NrIDQ6IGFybWVkLW9uY2UgbWljcm90YXNrIGJhdGNoZXIuXG4gKlxuICogUGF0dGVybjogIEtlcm5lbC1zdHlsZSBib3R0b20taGFsZi4gUHJvZHVjZXJzIG9ubHkgc2V0IGEgZmxhZyAoXCJ3b3JrXG4gKiAgICAgICAgICAgcGVuZGluZ1wiKSBhbmQgcmV0dXJuOyB0aGUgYWN0dWFsIHdvcmsgcnVucyBhdCB0aGUgbmV4dFxuICogICAgICAgICAgIHNjaGVkdWxpbmcgY2hlY2twb2ludCAoYSBtaWNyb3Rhc2spLCBkcmFpbnMgdW5kZXIgYSB0aW1lXG4gKiAgICAgICAgICAgYnVkZ2V0LCBhbmQgcmUtYXJtcyBpdHNlbGYgaWYgYmFja2xvZyByZW1haW5zLiBTYW1lIHNoYXBlIGFzXG4gKiAgICAgICAgICAgdGhlIGRldGFjaCBtb2R1bGUncyBgbWljcm90YXNrQmF0Y2hEcml2ZXJgIOKAlCBhY2N1bXVsYXRlIGR1cmluZ1xuICogICAgICAgICAgIHRoZSBjdXJyZW50IHN5bmMgc2xpY2UsIGRyYWluIGF0IHRoZSBib3VuZGFyeS5cbiAqIFJvbGU6ICAgICBUaGUgc2NoZWR1bGVyIG9mIHRoZSBkZWZlcnJlZC1vYnNlcnZlciBwaXBlbGluZS4gT3ducyBXSEVOXG4gKiAgICAgICAgICAgZGVsaXZlcnkgaGFwcGVuczsga25vd3Mgbm90aGluZyBhYm91dCBlbnZlbG9wZXMgb3IgbGlzdGVuZXJzXG4gKiAgICAgICAgICAgKHRoZSBkaXNwYXRjaGVyLCBCbG9jayA1LCBpbmplY3RzIGBkZXB0aGAvYHByb2Nlc3NOZXh0YCkuXG4gKiAgICAgICAgICAgUHVyZSBtb2R1bGUg4oCUIHplcm8gaW1wb3J0cywgemVybyBlbmdpbmUga25vd2xlZGdlLlxuICpcbiAqIFNjaGVkdWxpbmcgc2VtYW50aWNzIChub3JtYXRpdmUsIFJGQy0wMDEgwqc1ICsgYW1lbmRtZW50IEExKTpcbiAqICAgLSBgYXJtKClgIGlzIGlkZW1wb3RlbnQ6IGF0IG1vc3QgT05FIHBlbmRpbmcgZmx1c2ggZXhpc3RzIChhcm1lZCBmbGFnKS5cbiAqICAgICBOIGNhcHR1cmVzIGJldHdlZW4gY2hlY2twb2ludHMg4oeSIGV4YWN0bHkgMSBmbHVzaC5cbiAqICAgLSBBIGZsdXNoIGRyYWlucyBhIFNOQVBTSE9UOiBhdCBtb3N0IGBkZXB0aCgpYC1hdC1mbHVzaC1zdGFydCBpdGVtcy5cbiAqICAgICBFdmVudHMgZW5xdWV1ZWQgQlkgbGlzdGVuZXJzIGR1cmluZyB0aGUgZmx1c2ggZXhjZWVkIHRoZSBzbmFwc2hvdCBhbmRcbiAqICAgICBsYW5kIGF0IHRoZSBORVhUIGNoZWNrcG9pbnQg4oCUIGxpc3RlbmVyLWRyaXZlbiBjYXNjYWRlcyBjYW5ub3Qgc3RhcnZlXG4gKiAgICAgdGhlIGV2ZW50IGxvb3AuXG4gKiAgIC0gYGZsdXNoQnVkZ2V0TXNgIChkZWZhdWx0IDI7IGBJbmZpbml0eWAgPSBmdWxsIHNuYXBzaG90IGRyYWluKTogdGhlXG4gKiAgICAgZmx1c2ggc3RvcHMgb25jZSB0aGUgYnVkZ2V0IGlzIGV4aGF1c3RlZCwgY291bnRzIGBidWRnZXRFeGhhdXN0ZWRgLFxuICogICAgIGFuZCByZS1hcm1zLiBBdCBsZWFzdCBPTkUgaXRlbSBpcyBwcm9jZXNzZWQgcGVyIGZsdXNoIHJlZ2FyZGxlc3Mgb2ZcbiAqICAgICBidWRnZXQg4oCUIGd1YXJhbnRlZWQgcHJvZ3Jlc3MgdW5kZXIgYW55IGNsb2NrLlxuICogICAtIElmIGJhY2tsb2cgcmVtYWlucyBhZnRlciB0aGUgZmx1c2ggKGJ1ZGdldCBjdXQgT1IgbGlzdGVuZXIgZW5xdWV1ZXMpLFxuICogICAgIHRoZSBkcml2ZXIgcmUtYXJtcyBmb3IgdGhlIG5leHQgY2hlY2twb2ludC5cbiAqXG4gKiBXaHkgc3RhZ2UgYm91bmRhcmllcyBtYWtlIHRoaXMgc2FmZTogdGhlIGVuZ2luZSBgYXdhaXRgcyBldmVyeSBzdGFnZSwgc29cbiAqIHRoZSBtaWNyb3Rhc2sgcXVldWUgcnVucyBhdCBFVkVSWSBzdGFnZSBib3VuZGFyeSDigJQgZmx1c2hlcyBhcmUgYXQgbW9zdFxuICogXCJvbmUgYmVhdCBiZWhpbmRcIiB0aGUgcHJvZHVjaW5nIHN0YWdlLiBTZWVcbiAqIGBkb2NzL2d1aWRlcy9leGVjdXRpb24tbW9kZWwubWRgIChcIlN0YWdlIGJvdW5kYXJpZXMgYXJlIHNjaGVkdWxpbmdcbiAqIHBvaW50c1wiKSBhbmQgdGhlIEZBUSBpbiBgZG9jcy9kZXNpZ24vcmZjLTAwMS1kZWZlcnJlZC1vYnNlcnZlcnMubWRgLlxuICpcbiAqIFRlc3RhYmlsaXR5OiBgbm93YCAoY2xvY2spIGFuZCBgc2NoZWR1bGVgIChjaGVja3BvaW50IHByaW1pdGl2ZSkgYXJlXG4gKiBpbmplY3RhYmxlIOKAlCB0ZXN0cyBwdW1wIGZsdXNoZXMgZGV0ZXJtaW5pc3RpY2FsbHkgd2l0aCBhIGZha2UgY2xvY2sgYW5kXG4gKiBhIGNhcHR1cmVkLWNhbGxiYWNrIHNjaGVkdWxlcjsgcHJvZHVjdGlvbiB1c2VzIGBwZXJmb3JtYW5jZS5ub3dgIGFuZFxuICogYHF1ZXVlTWljcm90YXNrYC5cbiAqL1xuXG4vKiogUmVzdWx0IG9mIG9uZSBmbHVzaCAoYWxzbyBkZWxpdmVyZWQgdG8gYG9uRmx1c2hFbmRgKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRmx1c2hPdXRjb21lIHtcbiAgLyoqIEl0ZW1zIHByb2Nlc3NlZCBpbiB0aGlzIGZsdXNoLiAqL1xuICByZWFkb25seSBwcm9jZXNzZWQ6IG51bWJlcjtcbiAgLyoqIFRydWUgd2hlbiB0aGUgdGltZSBidWRnZXQgY3V0IHRoZSBmbHVzaCBiZWZvcmUgdGhlIHNuYXBzaG90IGRyYWluZWQuICovXG4gIHJlYWRvbmx5IGJ1ZGdldEV4aGF1c3RlZDogYm9vbGVhbjtcbiAgLyoqIFRydWUgd2hlbiBiYWNrbG9nIHJlbWFpbmVkIGFuZCB0aGUgZHJpdmVyIHJlLWFybWVkIGl0c2VsZi4gKi9cbiAgcmVhZG9ubHkgcmVhcm1lZDogYm9vbGVhbjtcbn1cblxuLyoqIFJlc3VsdCBvZiBhIHN5bmNocm9ub3VzIHtAbGluayBGbHVzaERyaXZlci5mbHVzaFN5bmN9IGRyYWluLiAqL1xuZXhwb3J0IGludGVyZmFjZSBGbHVzaFN5bmNSZXN1bHQge1xuICAvKiogSXRlbXMgcHJvY2Vzc2VkIGFjcm9zcyBhbGwgcm91bmRzLiAqL1xuICByZWFkb25seSBkcmFpbmVkOiBudW1iZXI7XG4gIC8qKiBJdGVtcyBzdGlsbCBxdWV1ZWQgd2hlbiBgbWF4Um91bmRzYCBzdG9wcGVkIGEgcnVuYXdheSBjYXNjYWRlLiAqL1xuICByZWFkb25seSByZW1haW5pbmc6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGbHVzaERyaXZlck9wdGlvbnMge1xuICAvKiogQ3VycmVudCBiYWNrbG9nIG9mIHRoZSBxdWV1ZSB0aGlzIGRyaXZlciBkcmFpbnMuICovXG4gIHJlYWRvbmx5IGRlcHRoOiAoKSA9PiBudW1iZXI7XG4gIC8qKiBQcm9jZXNzIGV4YWN0bHkgT05FIHF1ZXVlZCBpdGVtLiBQcmVjb25kaXRpb246IGBkZXB0aCgpID4gMGAuICovXG4gIHJlYWRvbmx5IHByb2Nlc3NOZXh0OiAoKSA9PiB2b2lkO1xuICAvKipcbiAgICogUGVyLWZsdXNoIHRpbWUgYnVkZ2V0IGluIG1zLiBEZWZhdWx0IDIuIGBJbmZpbml0eWAgZHJhaW5zIHRoZSBmdWxsXG4gICAqIHNuYXBzaG90IGV2ZXJ5IGNoZWNrcG9pbnQuIE11c3QgYmUgPiAwLlxuICAgKi9cbiAgcmVhZG9ubHkgZmx1c2hCdWRnZXRNcz86IG51bWJlcjtcbiAgLyoqIENsb2NrIOKAlCBkZWZhdWx0IGBwZXJmb3JtYW5jZS5ub3dgIChmYWxscyBiYWNrIHRvIGBEYXRlLm5vd2ApLiAqL1xuICByZWFkb25seSBub3c/OiAoKSA9PiBudW1iZXI7XG4gIC8qKiBDaGVja3BvaW50IHByaW1pdGl2ZSDigJQgZGVmYXVsdCBgcXVldWVNaWNyb3Rhc2tgLiAqL1xuICByZWFkb25seSBzY2hlZHVsZT86IChjYjogKCkgPT4gdm9pZCkgPT4gdm9pZDtcbiAgLyoqIEZpcmVzIGJlZm9yZSB0aGUgZmlyc3QgaXRlbSBvZiBldmVyeSBmbHVzaCAoaW5jbC4gYGZsdXNoU3luY2ApLiAqL1xuICByZWFkb25seSBvbkZsdXNoU3RhcnQ/OiAoKSA9PiB2b2lkO1xuICAvKiogRmlyZXMgYWZ0ZXIgZXZlcnkgZmx1c2ggd2l0aCBpdHMgb3V0Y29tZSAoaW5jbC4gYGZsdXNoU3luY2ApLiAqL1xuICByZWFkb25seSBvbkZsdXNoRW5kPzogKG91dGNvbWU6IEZsdXNoT3V0Y29tZSkgPT4gdm9pZDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGbHVzaERyaXZlclN0YXRzIHtcbiAgLyoqIENvbXBsZXRlZCBmbHVzaGVzICh6ZXJvLXdvcmsgd2FrZXVwcyBhcmUgbm90IGNvdW50ZWQpLiAqL1xuICByZWFkb25seSBmbHVzaGVzOiBudW1iZXI7XG4gIC8qKiBGbHVzaGVzIGN1dCBzaG9ydCBieSBgZmx1c2hCdWRnZXRNc2AgKEExIOKAlCBiYWNrbG9nIHZpc2liaWxpdHkpLiAqL1xuICByZWFkb25seSBidWRnZXRFeGhhdXN0ZWQ6IG51bWJlcjtcbiAgLyoqIER1cmF0aW9uIG9mIHRoZSBtb3N0IHJlY2VudCBmbHVzaCwgbXMuICovXG4gIHJlYWRvbmx5IGxhc3RGbHVzaE1zOiBudW1iZXI7XG4gIC8qKiBwOTUgb3ZlciB0aGUgbGFzdCB7QGxpbmsgRkxVU0hfU0FNUExFX1dJTkRPV30gZmx1c2ggZHVyYXRpb25zLCBtcy4gKi9cbiAgcmVhZG9ubHkgcDk1Rmx1c2hNczogbnVtYmVyO1xuICAvKiogVHJ1ZSB3aGlsZSBhIGZsdXNoIGlzIHNjaGVkdWxlZCBidXQgbm90IHlldCBydW4uICovXG4gIHJlYWRvbmx5IGFybWVkOiBib29sZWFuO1xufVxuXG4vKiogUm9sbGluZyBzYW1wbGUgd2luZG93IGZvciB0aGUgcDk1IGZsdXNoLWR1cmF0aW9uIHN0YXQgKEE0KS4gKi9cbmV4cG9ydCBjb25zdCBGTFVTSF9TQU1QTEVfV0lORE9XID0gMTI4O1xuXG4vKiogRGVmYXVsdCBjYXNjYWRlIGNhcCBmb3Ige0BsaW5rIEZsdXNoRHJpdmVyLmZsdXNoU3luY30uICovXG5jb25zdCBERUZBVUxUX01BWF9TWU5DX1JPVU5EUyA9IDFfMDAwO1xuXG5jb25zdCBkZWZhdWx0Tm93ID0gKCk6IG51bWJlciA9PiAodHlwZW9mIHBlcmZvcm1hbmNlICE9PSAndW5kZWZpbmVkJyA/IHBlcmZvcm1hbmNlLm5vdygpIDogRGF0ZS5ub3coKSk7XG5cbmV4cG9ydCBjbGFzcyBGbHVzaERyaXZlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVwdGg6ICgpID0+IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBwcm9jZXNzTmV4dDogKCkgPT4gdm9pZDtcbiAgcHJpdmF0ZSByZWFkb25seSBmbHVzaEJ1ZGdldE1zOiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgbm93OiAoKSA9PiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2NoZWR1bGU6IChjYjogKCkgPT4gdm9pZCkgPT4gdm9pZDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbkZsdXNoU3RhcnQ/OiAoKSA9PiB2b2lkO1xuICBwcml2YXRlIHJlYWRvbmx5IG9uRmx1c2hFbmQ/OiAob3V0Y29tZTogRmx1c2hPdXRjb21lKSA9PiB2b2lkO1xuXG4gIHByaXZhdGUgYXJtZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSBmbHVzaGVzID0gMDtcbiAgcHJpdmF0ZSBidWRnZXRFeGhhdXN0ZWRDb3VudCA9IDA7XG4gIHByaXZhdGUgbGFzdEZsdXNoTXMgPSAwO1xuICBwcml2YXRlIHJlYWRvbmx5IHNhbXBsZXM6IG51bWJlcltdID0gW107XG4gIHByaXZhdGUgc2FtcGxlV3JpdGVJZHggPSAwO1xuXG4gIGNvbnN0cnVjdG9yKG9wdHM6IEZsdXNoRHJpdmVyT3B0aW9ucykge1xuICAgIGNvbnN0IGJ1ZGdldCA9IG9wdHMuZmx1c2hCdWRnZXRNcyA/PyAyO1xuICAgIGlmIChOdW1iZXIuaXNOYU4oYnVkZ2V0KSB8fCBidWRnZXQgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoYGZsdXNoQnVkZ2V0TXMgbXVzdCBiZSA+IDAgKGdvdCAke2J1ZGdldH0pOyB1c2UgSW5maW5pdHkgZm9yIGZ1bGwgZHJhaW5zYCk7XG4gICAgfVxuICAgIHRoaXMuZGVwdGggPSBvcHRzLmRlcHRoO1xuICAgIHRoaXMucHJvY2Vzc05leHQgPSBvcHRzLnByb2Nlc3NOZXh0O1xuICAgIHRoaXMuZmx1c2hCdWRnZXRNcyA9IGJ1ZGdldDtcbiAgICB0aGlzLm5vdyA9IG9wdHMubm93ID8/IGRlZmF1bHROb3c7XG4gICAgdGhpcy5zY2hlZHVsZSA9IG9wdHMuc2NoZWR1bGUgPz8gKChjYikgPT4gcXVldWVNaWNyb3Rhc2soY2IpKTtcbiAgICB0aGlzLm9uRmx1c2hTdGFydCA9IG9wdHMub25GbHVzaFN0YXJ0O1xuICAgIHRoaXMub25GbHVzaEVuZCA9IG9wdHMub25GbHVzaEVuZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IGEgZmx1c2ggYXQgdGhlIG5leHQgY2hlY2twb2ludC4gSWRlbXBvdGVudCDigJQgd2hpbGUgb25lIGZsdXNoXG4gICAqIGlzIHBlbmRpbmcsIGZ1cnRoZXIgYXJtcyBhcmUgZnJlZSBuby1vcHMgKHRoZSBhcm1lZC1vbmNlIGludmFyaWFudCkuXG4gICAqL1xuICBhcm0oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuYXJtZWQpIHJldHVybjtcbiAgICB0aGlzLmFybWVkID0gdHJ1ZTtcbiAgICB0aGlzLnNjaGVkdWxlKCgpID0+IHRoaXMuZmx1c2goKSk7XG4gIH1cblxuICAvKipcbiAgICogU3luY2hyb25vdXMgZnVsbCBkcmFpbiDigJQgdGhlIHRlcm1pbmFsLWZsdXNoIHByaW1pdGl2ZSAoZW5kIG9mIHJ1biAvXG4gICAqIHNodXRkb3duKS4gUmVwZWF0cyBzbmFwc2hvdCByb3VuZHMgdW50aWwgdGhlIHF1ZXVlIGlzIGVtcHR5IHNvXG4gICAqIGxpc3RlbmVyLWVucXVldWVkIGNhc2NhZGVzIGRyYWluIHRvbywgY2FwcGVkIGF0IGBtYXhSb3VuZHNgIHNvIGFcbiAgICogbGlzdGVuZXIgdGhhdCBlbnF1ZXVlcyBmb3JldmVyIGNhbm5vdCBoYW5nIHRoZSBwcm9jZXNzIChgcmVtYWluaW5nYFxuICAgKiByZXBvcnRzIHdoYXQgdGhlIGNhcCBsZWZ0IGJlaGluZCkuXG4gICAqL1xuICBmbHVzaFN5bmMob3B0cz86IHsgbWF4Um91bmRzPzogbnVtYmVyIH0pOiBGbHVzaFN5bmNSZXN1bHQge1xuICAgIGNvbnN0IG1heFJvdW5kcyA9IG9wdHM/Lm1heFJvdW5kcyA/PyBERUZBVUxUX01BWF9TWU5DX1JPVU5EUztcbiAgICBpZiAodGhpcy5kZXB0aCgpID09PSAwKSByZXR1cm4geyBkcmFpbmVkOiAwLCByZW1haW5pbmc6IDAgfTtcblxuICAgIHRoaXMub25GbHVzaFN0YXJ0Py4oKTtcbiAgICBjb25zdCBzdGFydCA9IHRoaXMubm93KCk7XG4gICAgbGV0IGRyYWluZWQgPSAwO1xuICAgIGZvciAobGV0IHJvdW5kID0gMDsgcm91bmQgPCBtYXhSb3VuZHMgJiYgdGhpcy5kZXB0aCgpID4gMDsgcm91bmQrKykge1xuICAgICAgY29uc3Qgc25hcHNob3QgPSB0aGlzLmRlcHRoKCk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNuYXBzaG90ICYmIHRoaXMuZGVwdGgoKSA+IDA7IGkrKykge1xuICAgICAgICB0aGlzLnByb2Nlc3NOZXh0KCk7XG4gICAgICAgIGRyYWluZWQgKz0gMTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5yZWNvcmRGbHVzaCh0aGlzLm5vdygpIC0gc3RhcnQsIGZhbHNlKTtcbiAgICBjb25zdCByZW1haW5pbmcgPSB0aGlzLmRlcHRoKCk7XG4gICAgdGhpcy5vbkZsdXNoRW5kPy4oeyBwcm9jZXNzZWQ6IGRyYWluZWQsIGJ1ZGdldEV4aGF1c3RlZDogZmFsc2UsIHJlYXJtZWQ6IGZhbHNlIH0pO1xuICAgIHJldHVybiB7IGRyYWluZWQsIHJlbWFpbmluZyB9O1xuICB9XG5cbiAgZ2V0U3RhdHMoKTogRmx1c2hEcml2ZXJTdGF0cyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGZsdXNoZXM6IHRoaXMuZmx1c2hlcyxcbiAgICAgIGJ1ZGdldEV4aGF1c3RlZDogdGhpcy5idWRnZXRFeGhhdXN0ZWRDb3VudCxcbiAgICAgIGxhc3RGbHVzaE1zOiB0aGlzLmxhc3RGbHVzaE1zLFxuICAgICAgcDk1Rmx1c2hNczogdGhpcy5wOTVGbHVzaE1zKCksXG4gICAgICBhcm1lZDogdGhpcy5hcm1lZCxcbiAgICB9O1xuICB9XG5cbiAgLyoqIFRoZSBtaWNyb3Rhc2sgYm9keSDigJQgc2VlIHRoZSBtb2R1bGUtaGVhZGVyIHNlbWFudGljcy4gKi9cbiAgcHJpdmF0ZSBmbHVzaCgpOiB2b2lkIHtcbiAgICB0aGlzLmFybWVkID0gZmFsc2U7XG4gICAgY29uc3Qgc25hcHNob3QgPSB0aGlzLmRlcHRoKCk7XG4gICAgaWYgKHNuYXBzaG90ID09PSAwKSByZXR1cm47IC8vIHJhY2VkIHdpdGggZmx1c2hTeW5jIOKAlCB6ZXJvLXdvcmsgd2FrZXVwXG5cbiAgICB0aGlzLm9uRmx1c2hTdGFydD8uKCk7XG4gICAgY29uc3Qgc3RhcnQgPSB0aGlzLm5vdygpO1xuICAgIGxldCBwcm9jZXNzZWQgPSAwO1xuICAgIGxldCBleGhhdXN0ZWQgPSBmYWxzZTtcbiAgICB3aGlsZSAocHJvY2Vzc2VkIDwgc25hcHNob3QgJiYgdGhpcy5kZXB0aCgpID4gMCkge1xuICAgICAgLy8gQnVkZ2V0IGNoZWNrIEFGVEVSIHRoZSBmaXJzdCBpdGVtIOKAlCBndWFyYW50ZWVkIHByb2dyZXNzIHBlciBmbHVzaC5cbiAgICAgIGlmIChwcm9jZXNzZWQgPiAwICYmIHRoaXMubm93KCkgLSBzdGFydCA+PSB0aGlzLmZsdXNoQnVkZ2V0TXMpIHtcbiAgICAgICAgZXhoYXVzdGVkID0gdHJ1ZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICB0aGlzLnByb2Nlc3NOZXh0KCk7XG4gICAgICBwcm9jZXNzZWQgKz0gMTtcbiAgICB9XG4gICAgdGhpcy5yZWNvcmRGbHVzaCh0aGlzLm5vdygpIC0gc3RhcnQsIGV4aGF1c3RlZCk7XG5cbiAgICAvLyBCYWNrbG9nIGxlZnQgKGJ1ZGdldCBjdXQsIG9yIGxpc3RlbmVycyBlbnF1ZXVlZCBwYXN0IHRoZSBzbmFwc2hvdCk6XG4gICAgLy8gaGFuZCBpdCB0byB0aGUgTkVYVCBjaGVja3BvaW50IOKAlCBuZXZlciBzdGFydmUsIG5ldmVyIHNwaW4uXG4gICAgY29uc3QgcmVhcm1lZCA9IHRoaXMuZGVwdGgoKSA+IDA7XG4gICAgaWYgKHJlYXJtZWQpIHRoaXMuYXJtKCk7XG4gICAgdGhpcy5vbkZsdXNoRW5kPy4oeyBwcm9jZXNzZWQsIGJ1ZGdldEV4aGF1c3RlZDogZXhoYXVzdGVkLCByZWFybWVkIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSByZWNvcmRGbHVzaChlbGFwc2VkTXM6IG51bWJlciwgZXhoYXVzdGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5mbHVzaGVzICs9IDE7XG4gICAgdGhpcy5sYXN0Rmx1c2hNcyA9IGVsYXBzZWRNcztcbiAgICBpZiAoZXhoYXVzdGVkKSB0aGlzLmJ1ZGdldEV4aGF1c3RlZENvdW50ICs9IDE7XG4gICAgaWYgKHRoaXMuc2FtcGxlcy5sZW5ndGggPCBGTFVTSF9TQU1QTEVfV0lORE9XKSB0aGlzLnNhbXBsZXMucHVzaChlbGFwc2VkTXMpO1xuICAgIGVsc2Uge1xuICAgICAgdGhpcy5zYW1wbGVzW3RoaXMuc2FtcGxlV3JpdGVJZHhdID0gZWxhcHNlZE1zO1xuICAgICAgdGhpcy5zYW1wbGVXcml0ZUlkeCA9ICh0aGlzLnNhbXBsZVdyaXRlSWR4ICsgMSkgJSBGTFVTSF9TQU1QTEVfV0lORE9XO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcDk1Rmx1c2hNcygpOiBudW1iZXIge1xuICAgIGlmICh0aGlzLnNhbXBsZXMubGVuZ3RoID09PSAwKSByZXR1cm4gMDtcbiAgICBjb25zdCBzb3J0ZWQgPSBbLi4udGhpcy5zYW1wbGVzXS5zb3J0KChhLCBiKSA9PiBhIC0gYik7XG4gICAgcmV0dXJuIHNvcnRlZFtNYXRoLm1pbihzb3J0ZWQubGVuZ3RoIC0gMSwgTWF0aC5mbG9vcihzb3J0ZWQubGVuZ3RoICogMC45NSkpXTtcbiAgfVxufVxuIl19
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ /* istanbul ignore file */
3
+ /**
4
+ * observer-queue/ — RFC-001 deferred observer delivery, Blocks 2–5.
5
+ *
6
+ * The pure "one beat behind" pipeline:
7
+ *
8
+ * producer ─► capture (Block 1, `capture/envelope`) ─► MergedQueue
9
+ * (Block 3, seq-stamped over a BoundedRing, Block 2) ─► FlushDriver
10
+ * (Block 4, armed-once microtask checkpoints, flushBudgetMs) ─►
11
+ * DeferredDispatcher (Block 5, isolated listeners + inflight + stats)
12
+ *
13
+ * INTERNAL MODULE — deliberately NOT exported from the public footprintjs
14
+ * barrels yet. The engine wiring + public surface land with Blocks 6–10
15
+ * (see docs/design/rfc-001-deferred-observers.md). Zero engine imports:
16
+ * this directory may import only `../capture/` and its own files.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.BoundedRing = exports.MergedQueue = exports.DEFAULT_MAX_QUEUE = exports.FlushDriver = exports.FLUSH_SAMPLE_WINDOW = exports.DeferredDispatcher = exports.summarizePayload = exports.PAYLOAD_SUMMARY_MAX_NODES = exports.PAYLOAD_SUMMARY_MAX_ENTRIES = exports.PAYLOAD_SUMMARY_MAX_DEPTH = exports.capture = void 0;
20
+ var envelope_js_1 = require("../capture/envelope.js");
21
+ Object.defineProperty(exports, "capture", { enumerable: true, get: function () { return envelope_js_1.capture; } });
22
+ Object.defineProperty(exports, "PAYLOAD_SUMMARY_MAX_DEPTH", { enumerable: true, get: function () { return envelope_js_1.PAYLOAD_SUMMARY_MAX_DEPTH; } });
23
+ Object.defineProperty(exports, "PAYLOAD_SUMMARY_MAX_ENTRIES", { enumerable: true, get: function () { return envelope_js_1.PAYLOAD_SUMMARY_MAX_ENTRIES; } });
24
+ Object.defineProperty(exports, "PAYLOAD_SUMMARY_MAX_NODES", { enumerable: true, get: function () { return envelope_js_1.PAYLOAD_SUMMARY_MAX_NODES; } });
25
+ Object.defineProperty(exports, "summarizePayload", { enumerable: true, get: function () { return envelope_js_1.summarizePayload; } });
26
+ var deferredDispatcher_js_1 = require("./deferredDispatcher.js");
27
+ Object.defineProperty(exports, "DeferredDispatcher", { enumerable: true, get: function () { return deferredDispatcher_js_1.DeferredDispatcher; } });
28
+ var flushDriver_js_1 = require("./flushDriver.js");
29
+ Object.defineProperty(exports, "FLUSH_SAMPLE_WINDOW", { enumerable: true, get: function () { return flushDriver_js_1.FLUSH_SAMPLE_WINDOW; } });
30
+ Object.defineProperty(exports, "FlushDriver", { enumerable: true, get: function () { return flushDriver_js_1.FlushDriver; } });
31
+ var mergedQueue_js_1 = require("./mergedQueue.js");
32
+ Object.defineProperty(exports, "DEFAULT_MAX_QUEUE", { enumerable: true, get: function () { return mergedQueue_js_1.DEFAULT_MAX_QUEUE; } });
33
+ Object.defineProperty(exports, "MergedQueue", { enumerable: true, get: function () { return mergedQueue_js_1.MergedQueue; } });
34
+ var ring_js_1 = require("./ring.js");
35
+ Object.defineProperty(exports, "BoundedRing", { enumerable: true, get: function () { return ring_js_1.BoundedRing; } });
36
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL29ic2VydmVyLXF1ZXVlL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwwQkFBMEI7QUFDMUI7Ozs7Ozs7Ozs7Ozs7O0dBY0c7OztBQVlILHNEQU1nQztBQUw5QixzR0FBQSxPQUFPLE9BQUE7QUFDUCx3SEFBQSx5QkFBeUIsT0FBQTtBQUN6QiwwSEFBQSwyQkFBMkIsT0FBQTtBQUMzQix3SEFBQSx5QkFBeUIsT0FBQTtBQUN6QiwrR0FBQSxnQkFBZ0IsT0FBQTtBQVdsQixpRUFBNkQ7QUFBcEQsMkhBQUEsa0JBQWtCLE9BQUE7QUFFM0IsbURBQW9FO0FBQTNELHFIQUFBLG1CQUFtQixPQUFBO0FBQUUsNkdBQUEsV0FBVyxPQUFBO0FBRXpDLG1EQUFrRTtBQUF6RCxtSEFBQSxpQkFBaUIsT0FBQTtBQUFFLDZHQUFBLFdBQVcsT0FBQTtBQUV2QyxxQ0FBd0M7QUFBL0Isc0dBQUEsV0FBVyxPQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbi8qKlxuICogb2JzZXJ2ZXItcXVldWUvIOKAlCBSRkMtMDAxIGRlZmVycmVkIG9ic2VydmVyIGRlbGl2ZXJ5LCBCbG9ja3MgMuKAkzUuXG4gKlxuICogVGhlIHB1cmUgXCJvbmUgYmVhdCBiZWhpbmRcIiBwaXBlbGluZTpcbiAqXG4gKiAgIHByb2R1Y2VyIOKUgOKWuiBjYXB0dXJlIChCbG9jayAxLCBgY2FwdHVyZS9lbnZlbG9wZWApIOKUgOKWuiBNZXJnZWRRdWV1ZVxuICogICAoQmxvY2sgMywgc2VxLXN0YW1wZWQgb3ZlciBhIEJvdW5kZWRSaW5nLCBCbG9jayAyKSDilIDilrogRmx1c2hEcml2ZXJcbiAqICAgKEJsb2NrIDQsIGFybWVkLW9uY2UgbWljcm90YXNrIGNoZWNrcG9pbnRzLCBmbHVzaEJ1ZGdldE1zKSDilIDilrpcbiAqICAgRGVmZXJyZWREaXNwYXRjaGVyIChCbG9jayA1LCBpc29sYXRlZCBsaXN0ZW5lcnMgKyBpbmZsaWdodCArIHN0YXRzKVxuICpcbiAqIElOVEVSTkFMIE1PRFVMRSDigJQgZGVsaWJlcmF0ZWx5IE5PVCBleHBvcnRlZCBmcm9tIHRoZSBwdWJsaWMgZm9vdHByaW50anNcbiAqIGJhcnJlbHMgeWV0LiBUaGUgZW5naW5lIHdpcmluZyArIHB1YmxpYyBzdXJmYWNlIGxhbmQgd2l0aCBCbG9ja3MgNuKAkzEwXG4gKiAoc2VlIGRvY3MvZGVzaWduL3JmYy0wMDEtZGVmZXJyZWQtb2JzZXJ2ZXJzLm1kKS4gWmVybyBlbmdpbmUgaW1wb3J0czpcbiAqIHRoaXMgZGlyZWN0b3J5IG1heSBpbXBvcnQgb25seSBgLi4vY2FwdHVyZS9gIGFuZCBpdHMgb3duIGZpbGVzLlxuICovXG5cbmV4cG9ydCB0eXBlIHtcbiAgQ2FwdHVyZUNoYW5uZWwsXG4gIENhcHR1cmVFbnZlbG9wZSxcbiAgQ2FwdHVyZUhvb2tzLFxuICBDYXB0dXJlUG9saWN5LFxuICBDYXB0dXJlUmVxdWVzdCxcbiAgUGF5bG9hZFN1bW1hcnksXG4gIFBheWxvYWRTdW1tYXJ5Tm9kZSxcbiAgUGF5bG9hZFN1bW1hcnlUeXBlLFxufSBmcm9tICcuLi9jYXB0dXJlL2VudmVsb3BlLmpzJztcbmV4cG9ydCB7XG4gIGNhcHR1cmUsXG4gIFBBWUxPQURfU1VNTUFSWV9NQVhfREVQVEgsXG4gIFBBWUxPQURfU1VNTUFSWV9NQVhfRU5UUklFUyxcbiAgUEFZTE9BRF9TVU1NQVJZX01BWF9OT0RFUyxcbiAgc3VtbWFyaXplUGF5bG9hZCxcbn0gZnJvbSAnLi4vY2FwdHVyZS9lbnZlbG9wZS5qcyc7XG5leHBvcnQgdHlwZSB7XG4gIERlZmVycmVkRGlzcGF0Y2hlck9wdGlvbnMsXG4gIERlZmVycmVkTGlzdGVuZXIsXG4gIERpc3BhdGNoRXJyb3JDb250ZXh0LFxuICBEaXNwYXRjaEVycm9ySGFuZGxlcixcbiAgRGlzcGF0Y2hlclN0YXRzLFxuICBEcmFpblJlc3VsdCxcbiAgTGlzdGVuZXJTdGF0cyxcbn0gZnJvbSAnLi9kZWZlcnJlZERpc3BhdGNoZXIuanMnO1xuZXhwb3J0IHsgRGVmZXJyZWREaXNwYXRjaGVyIH0gZnJvbSAnLi9kZWZlcnJlZERpc3BhdGNoZXIuanMnO1xuZXhwb3J0IHR5cGUgeyBGbHVzaERyaXZlck9wdGlvbnMsIEZsdXNoRHJpdmVyU3RhdHMsIEZsdXNoT3V0Y29tZSwgRmx1c2hTeW5jUmVzdWx0IH0gZnJvbSAnLi9mbHVzaERyaXZlci5qcyc7XG5leHBvcnQgeyBGTFVTSF9TQU1QTEVfV0lORE9XLCBGbHVzaERyaXZlciB9IGZyb20gJy4vZmx1c2hEcml2ZXIuanMnO1xuZXhwb3J0IHR5cGUgeyBFbnF1ZXVlSW5wdXQsIEVucXVldWVPdXRjb21lLCBFbnF1ZXVlUmVzdWx0LCBNZXJnZWRRdWV1ZU9wdGlvbnMgfSBmcm9tICcuL21lcmdlZFF1ZXVlLmpzJztcbmV4cG9ydCB7IERFRkFVTFRfTUFYX1FVRVVFLCBNZXJnZWRRdWV1ZSB9IGZyb20gJy4vbWVyZ2VkUXVldWUuanMnO1xuZXhwb3J0IHR5cGUgeyBPdmVyZmxvd1BvbGljeSwgUmluZ0NvdW50ZXJzLCBSaW5nT3B0aW9ucywgUmluZ1B1c2hSZXN1bHQgfSBmcm9tICcuL3JpbmcuanMnO1xuZXhwb3J0IHsgQm91bmRlZFJpbmcgfSBmcm9tICcuL3JpbmcuanMnO1xuIl19
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ /**
3
+ * observer-queue/mergedQueue.ts — RFC-001 Block 3: seq stamping + multi-channel merge.
4
+ *
5
+ * Pattern: Single totally-ordered staging queue. All three observer
6
+ * channels (`scope` / `flow` / `emit`) funnel through ONE queue;
7
+ * the `seq` counter is assigned at capture under the single JS
8
+ * thread, so drain order == arrival order ACROSS channels with no
9
+ * cross-queue merge logic ever needed.
10
+ * Role: Glue between the capture tier (Block 1) and the flush driver
11
+ * (Block 4). Pure module — imports only `capture/envelope` and
12
+ * the ring (Block 2); zero engine knowledge.
13
+ *
14
+ * Seq semantics (normative, RFC-001 §5):
15
+ * - Stamped BEFORE admission — an event that is then dropped (overflow)
16
+ * or refused (`'block'`) still consumed its seq. Drops therefore leave
17
+ * VISIBLE gaps in the delivered stream (honest loss accounting), and
18
+ * `'block'`-refused events delivered inline keep their true arrival
19
+ * stamp even though they overtake the queued backlog.
20
+ * - Monotonic, starts at 0, never reused for the lifetime of the queue.
21
+ *
22
+ * Enqueue outcomes:
23
+ * - `'queued'` — staged for the next flush (drop-oldest may have evicted
24
+ * an older event to make room; that loss is counted, never silent).
25
+ * - `'dropped'` — the event was sampled out at saturation. Lost; counted.
26
+ * - `'inline'` — `'block'` policy refused the enqueue. NOT lost: the
27
+ * caller (the dispatcher, Block 5) must deliver the returned envelope
28
+ * synchronously inline — blocking delivery by explicit consumer choice.
29
+ */
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ exports.MergedQueue = exports.DEFAULT_MAX_QUEUE = void 0;
32
+ const envelope_js_1 = require("../capture/envelope.js");
33
+ const ring_js_1 = require("./ring.js");
34
+ /** RFC-001 §5 default queue bound. */
35
+ exports.DEFAULT_MAX_QUEUE = 10_000;
36
+ class MergedQueue {
37
+ ring;
38
+ overflow;
39
+ defaultPolicy;
40
+ hooks;
41
+ /** Arrival stamp — monotonic across ALL channels (see module header). */
42
+ seq = 0;
43
+ constructor(opts) {
44
+ this.overflow = opts?.overflow ?? 'drop-oldest';
45
+ this.ring = new ring_js_1.BoundedRing({
46
+ capacity: opts?.maxQueue ?? exports.DEFAULT_MAX_QUEUE,
47
+ policy: this.overflow,
48
+ sampleEvery: opts?.sampleEvery,
49
+ });
50
+ this.defaultPolicy = opts?.capturePolicy ?? 'summary';
51
+ this.hooks = opts?.hooks;
52
+ }
53
+ /**
54
+ * Capture one event (seq-stamped at arrival) and stage it for deferred
55
+ * delivery. `policy` overrides the queue default per call — e.g. `'ref'`
56
+ * for payloads the caller proved immutable. Never throws.
57
+ */
58
+ enqueue(input, policy) {
59
+ const envelope = (0, envelope_js_1.capture)({
60
+ seq: this.seq,
61
+ channel: input.channel,
62
+ method: input.method,
63
+ runtimeStageId: input.runtimeStageId,
64
+ runId: input.runId,
65
+ payload: input.payload,
66
+ }, policy ?? this.defaultPolicy, this.hooks);
67
+ this.seq += 1;
68
+ const pushed = this.ring.push(envelope);
69
+ if (pushed.accepted)
70
+ return { envelope, outcome: 'queued' };
71
+ return { envelope, outcome: this.overflow === 'block' ? 'inline' : 'dropped' };
72
+ }
73
+ /** Pop the oldest staged envelope (total arrival order across channels). */
74
+ shift() {
75
+ return this.ring.shift();
76
+ }
77
+ /** Current backlog. */
78
+ get depth() {
79
+ return this.ring.size;
80
+ }
81
+ /** Ring capacity (the `maxQueue` bound). */
82
+ get capacity() {
83
+ return this.ring.capacity;
84
+ }
85
+ /** The next seq to be assigned == total events captured so far. */
86
+ get nextSeq() {
87
+ return this.seq;
88
+ }
89
+ /** Lifetime loss/delivery accounting — delegated to the ring. */
90
+ getCounters() {
91
+ return this.ring.getCounters();
92
+ }
93
+ }
94
+ exports.MergedQueue = MergedQueue;
95
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVyZ2VkUXVldWUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL29ic2VydmVyLXF1ZXVlL21lcmdlZFF1ZXVlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMkJHOzs7QUFFSCx3REFNZ0M7QUFDaEMsdUNBQWdGO0FBRWhGLHNDQUFzQztBQUN6QixRQUFBLGlCQUFpQixHQUFHLE1BQU0sQ0FBQztBQWtDeEMsTUFBYSxXQUFXO0lBQ0wsSUFBSSxDQUErQjtJQUNuQyxRQUFRLENBQWlCO0lBQ3pCLGFBQWEsQ0FBZ0I7SUFDN0IsS0FBSyxDQUFnQjtJQUN0Qyx5RUFBeUU7SUFDakUsR0FBRyxHQUFHLENBQUMsQ0FBQztJQUVoQixZQUFZLElBQXlCO1FBQ25DLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxFQUFFLFFBQVEsSUFBSSxhQUFhLENBQUM7UUFDaEQsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLHFCQUFXLENBQWtCO1lBQzNDLFFBQVEsRUFBRSxJQUFJLEVBQUUsUUFBUSxJQUFJLHlCQUFpQjtZQUM3QyxNQUFNLEVBQUUsSUFBSSxDQUFDLFFBQVE7WUFDckIsV0FBVyxFQUFFLElBQUksRUFBRSxXQUFXO1NBQy9CLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxFQUFFLGFBQWEsSUFBSSxTQUFTLENBQUM7UUFDdEQsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLEVBQUUsS0FBSyxDQUFDO0lBQzNCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsT0FBTyxDQUFDLEtBQW1CLEVBQUUsTUFBc0I7UUFDakQsTUFBTSxRQUFRLEdBQUcsSUFBQSxxQkFBTyxFQUN0QjtZQUNFLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRztZQUNiLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTztZQUN0QixNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07WUFDcEIsY0FBYyxFQUFFLEtBQUssQ0FBQyxjQUFjO1lBQ3BDLEtBQUssRUFBRSxLQUFLLENBQUMsS0FBSztZQUNsQixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87U0FDdkIsRUFDRCxNQUFNLElBQUksSUFBSSxDQUFDLGFBQWEsRUFDNUIsSUFBSSxDQUFDLEtBQUssQ0FDWCxDQUFDO1FBQ0YsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFFZCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN4QyxJQUFJLE1BQU0sQ0FBQyxRQUFRO1lBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLENBQUM7UUFDNUQsT0FBTyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLFFBQVEsS0FBSyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDakYsQ0FBQztJQUVELDRFQUE0RTtJQUM1RSxLQUFLO1FBQ0gsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRCx1QkFBdUI7SUFDdkIsSUFBSSxLQUFLO1FBQ1AsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztJQUN4QixDQUFDO0lBRUQsNENBQTRDO0lBQzVDLElBQUksUUFBUTtRQUNWLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDNUIsQ0FBQztJQUVELG1FQUFtRTtJQUNuRSxJQUFJLE9BQU87UUFDVCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUM7SUFDbEIsQ0FBQztJQUVELGlFQUFpRTtJQUNqRSxXQUFXO1FBQ1QsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ2pDLENBQUM7Q0FDRjtBQXBFRCxrQ0FvRUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIG9ic2VydmVyLXF1ZXVlL21lcmdlZFF1ZXVlLnRzIOKAlCBSRkMtMDAxIEJsb2NrIDM6IHNlcSBzdGFtcGluZyArIG11bHRpLWNoYW5uZWwgbWVyZ2UuXG4gKlxuICogUGF0dGVybjogIFNpbmdsZSB0b3RhbGx5LW9yZGVyZWQgc3RhZ2luZyBxdWV1ZS4gQWxsIHRocmVlIG9ic2VydmVyXG4gKiAgICAgICAgICAgY2hhbm5lbHMgKGBzY29wZWAgLyBgZmxvd2AgLyBgZW1pdGApIGZ1bm5lbCB0aHJvdWdoIE9ORSBxdWV1ZTtcbiAqICAgICAgICAgICB0aGUgYHNlcWAgY291bnRlciBpcyBhc3NpZ25lZCBhdCBjYXB0dXJlIHVuZGVyIHRoZSBzaW5nbGUgSlNcbiAqICAgICAgICAgICB0aHJlYWQsIHNvIGRyYWluIG9yZGVyID09IGFycml2YWwgb3JkZXIgQUNST1NTIGNoYW5uZWxzIHdpdGggbm9cbiAqICAgICAgICAgICBjcm9zcy1xdWV1ZSBtZXJnZSBsb2dpYyBldmVyIG5lZWRlZC5cbiAqIFJvbGU6ICAgICBHbHVlIGJldHdlZW4gdGhlIGNhcHR1cmUgdGllciAoQmxvY2sgMSkgYW5kIHRoZSBmbHVzaCBkcml2ZXJcbiAqICAgICAgICAgICAoQmxvY2sgNCkuIFB1cmUgbW9kdWxlIOKAlCBpbXBvcnRzIG9ubHkgYGNhcHR1cmUvZW52ZWxvcGVgIGFuZFxuICogICAgICAgICAgIHRoZSByaW5nIChCbG9jayAyKTsgemVybyBlbmdpbmUga25vd2xlZGdlLlxuICpcbiAqIFNlcSBzZW1hbnRpY3MgKG5vcm1hdGl2ZSwgUkZDLTAwMSDCpzUpOlxuICogICAtIFN0YW1wZWQgQkVGT1JFIGFkbWlzc2lvbiDigJQgYW4gZXZlbnQgdGhhdCBpcyB0aGVuIGRyb3BwZWQgKG92ZXJmbG93KVxuICogICAgIG9yIHJlZnVzZWQgKGAnYmxvY2snYCkgc3RpbGwgY29uc3VtZWQgaXRzIHNlcS4gRHJvcHMgdGhlcmVmb3JlIGxlYXZlXG4gKiAgICAgVklTSUJMRSBnYXBzIGluIHRoZSBkZWxpdmVyZWQgc3RyZWFtIChob25lc3QgbG9zcyBhY2NvdW50aW5nKSwgYW5kXG4gKiAgICAgYCdibG9jaydgLXJlZnVzZWQgZXZlbnRzIGRlbGl2ZXJlZCBpbmxpbmUga2VlcCB0aGVpciB0cnVlIGFycml2YWxcbiAqICAgICBzdGFtcCBldmVuIHRob3VnaCB0aGV5IG92ZXJ0YWtlIHRoZSBxdWV1ZWQgYmFja2xvZy5cbiAqICAgLSBNb25vdG9uaWMsIHN0YXJ0cyBhdCAwLCBuZXZlciByZXVzZWQgZm9yIHRoZSBsaWZldGltZSBvZiB0aGUgcXVldWUuXG4gKlxuICogRW5xdWV1ZSBvdXRjb21lczpcbiAqICAgLSBgJ3F1ZXVlZCdgICDigJQgc3RhZ2VkIGZvciB0aGUgbmV4dCBmbHVzaCAoZHJvcC1vbGRlc3QgbWF5IGhhdmUgZXZpY3RlZFxuICogICAgIGFuIG9sZGVyIGV2ZW50IHRvIG1ha2Ugcm9vbTsgdGhhdCBsb3NzIGlzIGNvdW50ZWQsIG5ldmVyIHNpbGVudCkuXG4gKiAgIC0gYCdkcm9wcGVkJ2Ag4oCUIHRoZSBldmVudCB3YXMgc2FtcGxlZCBvdXQgYXQgc2F0dXJhdGlvbi4gTG9zdDsgY291bnRlZC5cbiAqICAgLSBgJ2lubGluZSdgICDigJQgYCdibG9jaydgIHBvbGljeSByZWZ1c2VkIHRoZSBlbnF1ZXVlLiBOT1QgbG9zdDogdGhlXG4gKiAgICAgY2FsbGVyICh0aGUgZGlzcGF0Y2hlciwgQmxvY2sgNSkgbXVzdCBkZWxpdmVyIHRoZSByZXR1cm5lZCBlbnZlbG9wZVxuICogICAgIHN5bmNocm9ub3VzbHkgaW5saW5lIOKAlCBibG9ja2luZyBkZWxpdmVyeSBieSBleHBsaWNpdCBjb25zdW1lciBjaG9pY2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgdHlwZSBDYXB0dXJlQ2hhbm5lbCxcbiAgdHlwZSBDYXB0dXJlRW52ZWxvcGUsXG4gIHR5cGUgQ2FwdHVyZUhvb2tzLFxuICB0eXBlIENhcHR1cmVQb2xpY3ksXG4gIGNhcHR1cmUsXG59IGZyb20gJy4uL2NhcHR1cmUvZW52ZWxvcGUuanMnO1xuaW1wb3J0IHsgdHlwZSBPdmVyZmxvd1BvbGljeSwgdHlwZSBSaW5nQ291bnRlcnMsIEJvdW5kZWRSaW5nIH0gZnJvbSAnLi9yaW5nLmpzJztcblxuLyoqIFJGQy0wMDEgwqc1IGRlZmF1bHQgcXVldWUgYm91bmQuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9NQVhfUVVFVUUgPSAxMF8wMDA7XG5cbi8qKiBPbmUgb2JzZXJ2ZXIgZXZlbnQgdG8gbWVyZ2Ug4oCUIHtAbGluayBjYXB0dXJlfSdzIHJlcXVlc3QgbWludXMgYHNlcWAuICovXG5leHBvcnQgaW50ZXJmYWNlIEVucXVldWVJbnB1dCB7XG4gIHJlYWRvbmx5IGNoYW5uZWw6IENhcHR1cmVDaGFubmVsO1xuICByZWFkb25seSBtZXRob2Q6IHN0cmluZztcbiAgcmVhZG9ubHkgcnVudGltZVN0YWdlSWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgcnVuSWQ6IHN0cmluZztcbiAgLyoqIExJVkUgcGF5bG9hZCDigJQgbWF0ZXJpYWxpemVkIHBlciBjYXB0dXJlIHBvbGljeSBhdCBlbnF1ZXVlIHRpbWUuICovXG4gIHJlYWRvbmx5IHBheWxvYWQ6IHVua25vd247XG59XG5cbi8qKiBGYXRlIG9mIG9uZSBlbnF1ZXVlZCBldmVudCDigJQgc2VlIHRoZSBtb2R1bGUgaGVhZGVyLiAqL1xuZXhwb3J0IHR5cGUgRW5xdWV1ZU91dGNvbWUgPSAncXVldWVkJyB8ICdkcm9wcGVkJyB8ICdpbmxpbmUnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEVucXVldWVSZXN1bHQge1xuICAvKiogVGhlIGNhcHR1cmVkLCBzZXEtc3RhbXBlZCBlbnZlbG9wZSAoYnVpbHQgZXZlbiB3aGVuIG5vdCBxdWV1ZWQpLiAqL1xuICByZWFkb25seSBlbnZlbG9wZTogQ2FwdHVyZUVudmVsb3BlO1xuICByZWFkb25seSBvdXRjb21lOiBFbnF1ZXVlT3V0Y29tZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNZXJnZWRRdWV1ZU9wdGlvbnMge1xuICAvKiogUmluZyBjYXBhY2l0eS4gRGVmYXVsdCB7QGxpbmsgREVGQVVMVF9NQVhfUVVFVUV9ICgxMCAwMDApLiAqL1xuICByZWFkb25seSBtYXhRdWV1ZT86IG51bWJlcjtcbiAgLyoqIE92ZXJmbG93IHBvbGljeSBhdCBjYXBhY2l0eS4gRGVmYXVsdCBgJ2Ryb3Atb2xkZXN0J2AuICovXG4gIHJlYWRvbmx5IG92ZXJmbG93PzogT3ZlcmZsb3dQb2xpY3k7XG4gIC8qKiBgJ3NhbXBsZSdgIG9ubHkg4oCUIGFkbWl0IDEgaW4gdGhpcyBtYW55IHNhdHVyYXRlZCBhcnJpdmFscy4gKi9cbiAgcmVhZG9ubHkgc2FtcGxlRXZlcnk/OiBudW1iZXI7XG4gIC8qKiBEZWZhdWx0IGNhcHR1cmUgcG9saWN5IHdoZW4gYGVucXVldWVgIGdldHMgbm9uZS4gRGVmYXVsdCBgJ3N1bW1hcnknYC4gKi9cbiAgcmVhZG9ubHkgY2FwdHVyZVBvbGljeT86IENhcHR1cmVQb2xpY3k7XG4gIC8qKiBFbmdpbmUtZnJlZSBzZWFtcyAoZGV2LXdhcm4sIGNsb2NrKSBwYXNzZWQgdGhyb3VnaCB0byB7QGxpbmsgY2FwdHVyZX0uICovXG4gIHJlYWRvbmx5IGhvb2tzPzogQ2FwdHVyZUhvb2tzO1xufVxuXG5leHBvcnQgY2xhc3MgTWVyZ2VkUXVldWUge1xuICBwcml2YXRlIHJlYWRvbmx5IHJpbmc6IEJvdW5kZWRSaW5nPENhcHR1cmVFbnZlbG9wZT47XG4gIHByaXZhdGUgcmVhZG9ubHkgb3ZlcmZsb3c6IE92ZXJmbG93UG9saWN5O1xuICBwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHRQb2xpY3k6IENhcHR1cmVQb2xpY3k7XG4gIHByaXZhdGUgcmVhZG9ubHkgaG9va3M/OiBDYXB0dXJlSG9va3M7XG4gIC8qKiBBcnJpdmFsIHN0YW1wIOKAlCBtb25vdG9uaWMgYWNyb3NzIEFMTCBjaGFubmVscyAoc2VlIG1vZHVsZSBoZWFkZXIpLiAqL1xuICBwcml2YXRlIHNlcSA9IDA7XG5cbiAgY29uc3RydWN0b3Iob3B0cz86IE1lcmdlZFF1ZXVlT3B0aW9ucykge1xuICAgIHRoaXMub3ZlcmZsb3cgPSBvcHRzPy5vdmVyZmxvdyA/PyAnZHJvcC1vbGRlc3QnO1xuICAgIHRoaXMucmluZyA9IG5ldyBCb3VuZGVkUmluZzxDYXB0dXJlRW52ZWxvcGU+KHtcbiAgICAgIGNhcGFjaXR5OiBvcHRzPy5tYXhRdWV1ZSA/PyBERUZBVUxUX01BWF9RVUVVRSxcbiAgICAgIHBvbGljeTogdGhpcy5vdmVyZmxvdyxcbiAgICAgIHNhbXBsZUV2ZXJ5OiBvcHRzPy5zYW1wbGVFdmVyeSxcbiAgICB9KTtcbiAgICB0aGlzLmRlZmF1bHRQb2xpY3kgPSBvcHRzPy5jYXB0dXJlUG9saWN5ID8/ICdzdW1tYXJ5JztcbiAgICB0aGlzLmhvb2tzID0gb3B0cz8uaG9va3M7XG4gIH1cblxuICAvKipcbiAgICogQ2FwdHVyZSBvbmUgZXZlbnQgKHNlcS1zdGFtcGVkIGF0IGFycml2YWwpIGFuZCBzdGFnZSBpdCBmb3IgZGVmZXJyZWRcbiAgICogZGVsaXZlcnkuIGBwb2xpY3lgIG92ZXJyaWRlcyB0aGUgcXVldWUgZGVmYXVsdCBwZXIgY2FsbCDigJQgZS5nLiBgJ3JlZidgXG4gICAqIGZvciBwYXlsb2FkcyB0aGUgY2FsbGVyIHByb3ZlZCBpbW11dGFibGUuIE5ldmVyIHRocm93cy5cbiAgICovXG4gIGVucXVldWUoaW5wdXQ6IEVucXVldWVJbnB1dCwgcG9saWN5PzogQ2FwdHVyZVBvbGljeSk6IEVucXVldWVSZXN1bHQge1xuICAgIGNvbnN0IGVudmVsb3BlID0gY2FwdHVyZShcbiAgICAgIHtcbiAgICAgICAgc2VxOiB0aGlzLnNlcSxcbiAgICAgICAgY2hhbm5lbDogaW5wdXQuY2hhbm5lbCxcbiAgICAgICAgbWV0aG9kOiBpbnB1dC5tZXRob2QsXG4gICAgICAgIHJ1bnRpbWVTdGFnZUlkOiBpbnB1dC5ydW50aW1lU3RhZ2VJZCxcbiAgICAgICAgcnVuSWQ6IGlucHV0LnJ1bklkLFxuICAgICAgICBwYXlsb2FkOiBpbnB1dC5wYXlsb2FkLFxuICAgICAgfSxcbiAgICAgIHBvbGljeSA/PyB0aGlzLmRlZmF1bHRQb2xpY3ksXG4gICAgICB0aGlzLmhvb2tzLFxuICAgICk7XG4gICAgdGhpcy5zZXEgKz0gMTtcblxuICAgIGNvbnN0IHB1c2hlZCA9IHRoaXMucmluZy5wdXNoKGVudmVsb3BlKTtcbiAgICBpZiAocHVzaGVkLmFjY2VwdGVkKSByZXR1cm4geyBlbnZlbG9wZSwgb3V0Y29tZTogJ3F1ZXVlZCcgfTtcbiAgICByZXR1cm4geyBlbnZlbG9wZSwgb3V0Y29tZTogdGhpcy5vdmVyZmxvdyA9PT0gJ2Jsb2NrJyA/ICdpbmxpbmUnIDogJ2Ryb3BwZWQnIH07XG4gIH1cblxuICAvKiogUG9wIHRoZSBvbGRlc3Qgc3RhZ2VkIGVudmVsb3BlICh0b3RhbCBhcnJpdmFsIG9yZGVyIGFjcm9zcyBjaGFubmVscykuICovXG4gIHNoaWZ0KCk6IENhcHR1cmVFbnZlbG9wZSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMucmluZy5zaGlmdCgpO1xuICB9XG5cbiAgLyoqIEN1cnJlbnQgYmFja2xvZy4gKi9cbiAgZ2V0IGRlcHRoKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucmluZy5zaXplO1xuICB9XG5cbiAgLyoqIFJpbmcgY2FwYWNpdHkgKHRoZSBgbWF4UXVldWVgIGJvdW5kKS4gKi9cbiAgZ2V0IGNhcGFjaXR5KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucmluZy5jYXBhY2l0eTtcbiAgfVxuXG4gIC8qKiBUaGUgbmV4dCBzZXEgdG8gYmUgYXNzaWduZWQgPT0gdG90YWwgZXZlbnRzIGNhcHR1cmVkIHNvIGZhci4gKi9cbiAgZ2V0IG5leHRTZXEoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5zZXE7XG4gIH1cblxuICAvKiogTGlmZXRpbWUgbG9zcy9kZWxpdmVyeSBhY2NvdW50aW5nIOKAlCBkZWxlZ2F0ZWQgdG8gdGhlIHJpbmcuICovXG4gIGdldENvdW50ZXJzKCk6IFJpbmdDb3VudGVycyB7XG4gICAgcmV0dXJuIHRoaXMucmluZy5nZXRDb3VudGVycygpO1xuICB9XG59XG4iXX0=