@workflow/core 5.0.0-beta.40 → 5.0.0-beta.41
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/dist/events-consumer.d.ts +127 -6
- package/dist/events-consumer.d.ts.map +1 -1
- package/dist/events-consumer.js +364 -50
- package/dist/private.d.ts +87 -18
- package/dist/private.d.ts.map +1 -1
- package/dist/private.js +116 -44
- package/dist/runtime/constants.d.ts +15 -1
- package/dist/runtime/constants.d.ts.map +1 -1
- package/dist/runtime/constants.js +22 -3
- package/dist/runtime/helpers.d.ts +116 -8
- package/dist/runtime/helpers.d.ts.map +1 -1
- package/dist/runtime/helpers.js +174 -2
- package/dist/runtime/quickjs-assets.generated.d.ts.map +1 -1
- package/dist/runtime/quickjs-assets.generated.js +2 -2
- package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -1
- package/dist/runtime/quickjs-entrypoint.js +13 -5
- package/dist/runtime/quickjs-runtime.d.ts +36 -1
- package/dist/runtime/quickjs-runtime.d.ts.map +1 -1
- package/dist/runtime/quickjs-runtime.js +613 -185
- package/dist/runtime/quickjs-serde.d.ts +107 -0
- package/dist/runtime/quickjs-serde.d.ts.map +1 -0
- package/dist/runtime/quickjs-serde.js +2098 -0
- package/dist/runtime/replay-budget.d.ts +5 -14
- package/dist/runtime/replay-budget.d.ts.map +1 -1
- package/dist/runtime/replay-budget.js +19 -72
- package/dist/runtime/resume-hook.d.ts.map +1 -1
- package/dist/runtime/resume-hook.js +5 -1
- package/dist/runtime/runs.d.ts.map +1 -1
- package/dist/runtime/runs.js +3 -4
- package/dist/runtime/start.js +2 -7
- package/dist/runtime/step-executor.d.ts.map +1 -1
- package/dist/runtime/step-executor.js +1 -4
- package/dist/runtime/suspension-handler.d.ts +7 -0
- package/dist/runtime/suspension-handler.d.ts.map +1 -1
- package/dist/runtime/suspension-handler.js +58 -11
- package/dist/runtime/world-compatibility.d.ts +15 -0
- package/dist/runtime/world-compatibility.d.ts.map +1 -1
- package/dist/runtime/world-compatibility.js +25 -5
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +474 -418
- package/dist/serialization/codec-devalue-vm.d.ts +7 -0
- package/dist/serialization/codec-devalue-vm.d.ts.map +1 -1
- package/dist/serialization/codec-devalue-vm.js +12 -1
- package/dist/serialization/workflow-vm.d.ts +8 -3
- package/dist/serialization/workflow-vm.d.ts.map +1 -1
- package/dist/serialization/workflow-vm.js +9 -4
- package/dist/step.js +2 -2
- package/dist/telemetry/semantic-conventions.d.ts +23 -0
- package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
- package/dist/telemetry/semantic-conventions.js +18 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +2 -2
- package/dist/vm/index.d.ts.map +1 -1
- package/dist/vm/index.js +9 -6
- package/dist/workflow/abort-controller.d.ts.map +1 -1
- package/dist/workflow/abort-controller.js +4 -6
- package/dist/workflow/attribute-dispatcher.js +2 -2
- package/dist/workflow/hook.js +2 -2
- package/dist/workflow/sleep.js +2 -2
- package/dist/workflow.d.ts +10 -0
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +60 -19
- package/docs/how-it-works/event-sourcing.mdx +11 -3
- package/package.json +6 -6
- package/dist/correlation-id.d.ts +0 -109
- package/dist/correlation-id.d.ts.map +0 -1
- package/dist/correlation-id.js +0 -139
- package/dist/serialization/vm-bundle-entry.d.ts +0 -12
- package/dist/serialization/vm-bundle-entry.d.ts.map +0 -1
- package/dist/serialization/vm-bundle-entry.js +0 -58
package/dist/events-consumer.js
CHANGED
|
@@ -7,21 +7,103 @@ import { eventsLogger } from './logger.js';
|
|
|
7
7
|
* in host). Any subscribe() arriving during this window cancels the check.
|
|
8
8
|
*/
|
|
9
9
|
export const DEFERRED_CHECK_DELAY_MS = 100;
|
|
10
|
+
/**
|
|
11
|
+
* Floor for the deferred-check delay, so a too-low override can't manufacture
|
|
12
|
+
* spurious divergence (each false positive burns a divergence-recovery retry
|
|
13
|
+
* and can escalate to a terminal `CorruptedEventLogError`).
|
|
14
|
+
*
|
|
15
|
+
* Exported so tests needing the shortest legal delay can ask for it instead of
|
|
16
|
+
* hardcoding a number this floor would silently clamp up.
|
|
17
|
+
*/
|
|
18
|
+
export const MIN_DEFERRED_CHECK_DELAY_MS = 10;
|
|
10
19
|
/**
|
|
11
20
|
* Effective deferred-check delay. Override: `WORKFLOW_DEFERRED_CHECK_DELAY_MS`.
|
|
12
21
|
*
|
|
13
22
|
* Unlike the other timing knobs this is not a polling interval but a
|
|
14
23
|
* determinism safety margin: firing the unconsumed-event check before the
|
|
15
24
|
* cross-VM subscribe() chain has landed rejects a healthy run with
|
|
16
|
-
* `ReplayDivergenceError`.
|
|
17
|
-
* manufacture spurious divergence (each false positive burns a
|
|
18
|
-
* divergence-recovery retry and can escalate to a terminal
|
|
19
|
-
* `CorruptedEventLogError`).
|
|
25
|
+
* `ReplayDivergenceError`.
|
|
20
26
|
*/
|
|
21
27
|
const getDeferredCheckDelayMs = () => envNumber('WORKFLOW_DEFERRED_CHECK_DELAY_MS', DEFERRED_CHECK_DELAY_MS, {
|
|
22
28
|
integer: true,
|
|
23
|
-
min:
|
|
29
|
+
min: MIN_DEFERRED_CHECK_DELAY_MS,
|
|
24
30
|
});
|
|
31
|
+
/**
|
|
32
|
+
* Event types the ordered walk may step over and deliver later.
|
|
33
|
+
*
|
|
34
|
+
* Membership is not about who wrote the event. It is about whether the event
|
|
35
|
+
* can reach the head of the walk with nothing registered to consume it, which
|
|
36
|
+
* is the only situation parking exists for.
|
|
37
|
+
*
|
|
38
|
+
* Most types cannot. They are replay-origin: a replay emits them, in the order
|
|
39
|
+
* its code reaches them, so their position in the log is the record of what
|
|
40
|
+
* that replay decided. Reaching one of those out of order means this replay
|
|
41
|
+
* decided differently than the log holds, which is divergence and nothing else.
|
|
42
|
+
*
|
|
43
|
+
* Step lifecycle events are not replay-origin, and are still absent, because
|
|
44
|
+
* they always have a claimant. `step()` subscribes its consumer before the
|
|
45
|
+
* step's first event can exist; `step_created` is ordered, so the walk cannot
|
|
46
|
+
* pass it unless a consumer takes it; and that consumer stays subscribed until
|
|
47
|
+
* `step_completed` or `step_failed`, after which the World refuses any further
|
|
48
|
+
* write for that step. There is no window in which a replay knows about a step
|
|
49
|
+
* and has nothing registered to consume its events, so parking them would only
|
|
50
|
+
* defer reports of what is divergence either way. The same holds for
|
|
51
|
+
* `wait_created` and its consumer. `wait_completed` is listed anyway: a sleep
|
|
52
|
+
* can also be completed out of band, by the API that force-completes pending
|
|
53
|
+
* waits, and tolerating a stray one is the cheaper direction to be wrong in.
|
|
54
|
+
*
|
|
55
|
+
* An allowlist rather than the complement of the ordered set, so a type this
|
|
56
|
+
* file has not been taught about keeps the strict old behaviour.
|
|
57
|
+
*
|
|
58
|
+
* `hook_disposed` is deliberately absent despite being about a hook: it is
|
|
59
|
+
* written when the workflow's own `using` scope exits, so it is replay-origin.
|
|
60
|
+
*
|
|
61
|
+
* `attr_set` is listed by type even though a given instance of it may be
|
|
62
|
+
* replay-origin, since it is replay-origin when its writer is the workflow.
|
|
63
|
+
* Splitting that out per event was considered and rejected. A replay that
|
|
64
|
+
* reaches one of its own writes out of position has diverged, but a replay that
|
|
65
|
+
* reaches an event it did NOT write, sitting where its own write would go, has
|
|
66
|
+
* not: the writer field says who wrote the event, and not whether this replay
|
|
67
|
+
* is the same one. Guessing wrong in that direction fails healthy runs, which
|
|
68
|
+
* is the failure this file exists to stop, so the whole type is tolerated. The
|
|
69
|
+
* cost is that a divergence involving `attr_set` surfaces at the end of the
|
|
70
|
+
* replay, through `strandedEvent`, rather than at the offending event.
|
|
71
|
+
*/
|
|
72
|
+
const PARKABLE_EVENT_TYPES = new Set([
|
|
73
|
+
'hook_received',
|
|
74
|
+
'hook_conflict',
|
|
75
|
+
'wait_completed',
|
|
76
|
+
'attr_set',
|
|
77
|
+
'run_cancelled',
|
|
78
|
+
]);
|
|
79
|
+
/**
|
|
80
|
+
* Parkable types that can only ever resolve their correlation id once.
|
|
81
|
+
*
|
|
82
|
+
* A second one for the same id is not a delivery this replay has not reached
|
|
83
|
+
* yet: it is a resolution for something already resolved, which no consumer
|
|
84
|
+
* this replay or any later one registers can ever claim. `hook_received` is
|
|
85
|
+
* absent because a hook legitimately fires many times under one id.
|
|
86
|
+
*
|
|
87
|
+
* Must stay a subset of {@link PARKABLE_EVENT_TYPES}: {@link park} is the only
|
|
88
|
+
* reader of what this records, and it rejects a non-parkable type before it
|
|
89
|
+
* looks, so an entry outside that set is dead weight on a hot path.
|
|
90
|
+
*/
|
|
91
|
+
const ONE_SHOT_EVENT_TYPES = new Set([
|
|
92
|
+
'wait_completed',
|
|
93
|
+
]);
|
|
94
|
+
/** Identifies the thing a one-shot resolution event resolves. */
|
|
95
|
+
function resolutionKey(eventType, correlationId) {
|
|
96
|
+
return `${eventType}:${correlationId}`;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Types that end a run. Once one is in the log, no consumer will ever be
|
|
100
|
+
* registered again, so a parked event still parked here will never be claimed.
|
|
101
|
+
*/
|
|
102
|
+
const TERMINAL_EVENT_TYPES = new Set([
|
|
103
|
+
'run_completed',
|
|
104
|
+
'run_failed',
|
|
105
|
+
'run_cancelled',
|
|
106
|
+
]);
|
|
25
107
|
export var EventConsumerResult;
|
|
26
108
|
(function (EventConsumerResult) {
|
|
27
109
|
/**
|
|
@@ -41,9 +123,27 @@ export class EventsConsumer {
|
|
|
41
123
|
eventIndex;
|
|
42
124
|
events;
|
|
43
125
|
callbacks = [];
|
|
126
|
+
/**
|
|
127
|
+
* Events the ordered walk stepped over because nobody claimed them and their
|
|
128
|
+
* type carries no ordering claim. Each keeps the index it held in the log:
|
|
129
|
+
* consumers read {@link eventIndex} at consumption time to order their
|
|
130
|
+
* delivery against the rest of the log, and a late delivery must still make
|
|
131
|
+
* the claim its position gave it.
|
|
132
|
+
*
|
|
133
|
+
* Held in log order, drained in log order, and drained before every offer so
|
|
134
|
+
* a consumer registered after the walk passed the event still receives it.
|
|
135
|
+
*/
|
|
136
|
+
parked = [];
|
|
137
|
+
/**
|
|
138
|
+
* Correlation ids of the {@link ONE_SHOT_EVENT_TYPES} events consumed so
|
|
139
|
+
* far, so a second resolution for one of them is recognized as unclaimable
|
|
140
|
+
* rather than parked for a consumer that cannot exist.
|
|
141
|
+
*/
|
|
142
|
+
resolved = new Set();
|
|
44
143
|
onConsumedEvent;
|
|
45
144
|
onUnconsumedEvent;
|
|
46
145
|
getPromiseQueue;
|
|
146
|
+
isDeliveryIdle;
|
|
47
147
|
pendingUnconsumedCheck = null;
|
|
48
148
|
pendingUnconsumedTimeout = null;
|
|
49
149
|
unconsumedCheckVersion = 0;
|
|
@@ -56,6 +156,38 @@ export class EventsConsumer {
|
|
|
56
156
|
this.onConsumedEvent = options.onConsumedEvent;
|
|
57
157
|
this.onUnconsumedEvent = options.onUnconsumedEvent;
|
|
58
158
|
this.getPromiseQueue = options.getPromiseQueue;
|
|
159
|
+
this.isDeliveryIdle = options.isDeliveryIdle;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The oldest event the walk stepped over that no consumer has claimed yet,
|
|
163
|
+
* if any. Parking is a bet that a consumer will be registered later, so at
|
|
164
|
+
* any point where no consumer ever will be again — the replay finishing is
|
|
165
|
+
* the definitive one — this answers which event the bet lost on.
|
|
166
|
+
*/
|
|
167
|
+
get strandedEvent() {
|
|
168
|
+
return this.parked[0]?.event;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* What the walk is still holding, or `undefined` when it holds nothing.
|
|
172
|
+
*
|
|
173
|
+
* Read at every point a replay stops, including the suspensions that are not
|
|
174
|
+
* settling points, so the held state reaches telemetry. A replay cannot tell
|
|
175
|
+
* a delivery awaiting a later consumer from one no consumer will ever
|
|
176
|
+
* register, so it reports rather than decides: the same `eventId` reported on
|
|
177
|
+
* suspension after suspension of one run is the shape that says the bet
|
|
178
|
+
* parking made is not going to pay off, and that shape is only visible across
|
|
179
|
+
* replays.
|
|
180
|
+
*/
|
|
181
|
+
get parkedSummary() {
|
|
182
|
+
const oldest = this.parked[0]?.event;
|
|
183
|
+
if (!oldest) {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
count: this.parked.length,
|
|
188
|
+
eventId: oldest.eventId,
|
|
189
|
+
eventType: oldest.eventType,
|
|
190
|
+
};
|
|
59
191
|
}
|
|
60
192
|
append(events) {
|
|
61
193
|
for (const event of events)
|
|
@@ -115,25 +247,41 @@ export class EventsConsumer {
|
|
|
115
247
|
// case no callback consumes the event and we fall through to the
|
|
116
248
|
// cross-VM-safe deferred unconsumed-event check below, exactly as before.
|
|
117
249
|
while (true) {
|
|
250
|
+
// Before every offer, not just on subscribe: a callback registered by
|
|
251
|
+
// the work this same pass kicked off may be the owner of something
|
|
252
|
+
// parked, and the parked event's delivery is ordered ahead of the head
|
|
253
|
+
// event's by the index it holds.
|
|
254
|
+
this.drainParked();
|
|
118
255
|
const currentEvent = this.events[this.eventIndex] ?? null;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
this.
|
|
256
|
+
const consumed = this.offer(currentEvent);
|
|
257
|
+
if (consumed) {
|
|
258
|
+
this.eventIndex++;
|
|
259
|
+
}
|
|
260
|
+
if (currentEvent === null) {
|
|
261
|
+
// End of log. Consumers return NotConsumed for the `null` sentinel
|
|
262
|
+
// (the one that recognizes it as its own boundary schedules the
|
|
263
|
+
// suspension as a side effect and still declines it), so the drain
|
|
264
|
+
// stops here rather than spinning past the end. `consumed` is only
|
|
265
|
+
// true for a callback that claims the sentinel outright, which no
|
|
266
|
+
// production consumer does.
|
|
267
|
+
if (!consumed) {
|
|
268
|
+
this.handleEndOfLog();
|
|
269
|
+
}
|
|
122
270
|
return;
|
|
123
271
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
272
|
+
if (!consumed) {
|
|
273
|
+
this.scheduleUnconsumedCheck(currentEvent, true);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
// A real event was consumed — advance to the next in the same pass.
|
|
127
277
|
}
|
|
128
278
|
};
|
|
129
279
|
/**
|
|
130
280
|
* Offer `currentEvent` to each registered callback in turn. Returns true
|
|
131
|
-
* when a callback consumed
|
|
132
|
-
*
|
|
133
|
-
* (nothing consumed it, or the consumed event was the end-of-events
|
|
134
|
-
* sentinel).
|
|
281
|
+
* when a callback consumed it. Does not move {@link eventIndex}: the ordered
|
|
282
|
+
* walk and the parked drain advance differently, so each does its own.
|
|
135
283
|
*/
|
|
136
|
-
|
|
284
|
+
offer(currentEvent) {
|
|
137
285
|
for (let i = 0; i < this.callbacks.length; i++) {
|
|
138
286
|
const callback = this.callbacks[i];
|
|
139
287
|
let handled = EventConsumerResult.NotConsumed;
|
|
@@ -148,56 +296,222 @@ export class EventsConsumer {
|
|
|
148
296
|
continue;
|
|
149
297
|
}
|
|
150
298
|
if (currentEvent !== null) {
|
|
299
|
+
if (currentEvent.correlationId &&
|
|
300
|
+
ONE_SHOT_EVENT_TYPES.has(currentEvent.eventType)) {
|
|
301
|
+
this.resolved.add(resolutionKey(currentEvent.eventType, currentEvent.correlationId));
|
|
302
|
+
}
|
|
151
303
|
this.notifyConsumedEvent(currentEvent);
|
|
152
304
|
}
|
|
153
|
-
// consumer handled this event, so increase the event index
|
|
154
|
-
this.eventIndex++;
|
|
155
305
|
// remove the callback if it has finished
|
|
156
306
|
if (handled === EventConsumerResult.Finished) {
|
|
157
307
|
this.callbacks.splice(i, 1);
|
|
158
308
|
}
|
|
159
|
-
|
|
160
|
-
// NotConsumed for the `null` sentinel, but guard against a pathological
|
|
161
|
-
// callback consuming it so the drain never spins past end-of-log.
|
|
162
|
-
return currentEvent !== null;
|
|
309
|
+
return true;
|
|
163
310
|
}
|
|
164
311
|
return false;
|
|
165
312
|
}
|
|
166
|
-
|
|
313
|
+
/**
|
|
314
|
+
* Offer everything parked, oldest first, until a pass claims nothing.
|
|
315
|
+
*
|
|
316
|
+
* Each offer runs with {@link eventIndex} moved back to the position the
|
|
317
|
+
* parked event held in the log, because that is the position its consumer
|
|
318
|
+
* will register a delivery barrier under. Restoring the walk pointer
|
|
319
|
+
* afterwards is what keeps the two pointers from interfering.
|
|
320
|
+
*/
|
|
321
|
+
drainParked() {
|
|
322
|
+
let progressed = this.parked.length > 0;
|
|
323
|
+
while (progressed) {
|
|
324
|
+
progressed = false;
|
|
325
|
+
for (let i = 0; i < this.parked.length; i++) {
|
|
326
|
+
const entry = this.parked[i];
|
|
327
|
+
const walkIndex = this.eventIndex;
|
|
328
|
+
this.eventIndex = entry.index;
|
|
329
|
+
let consumed;
|
|
330
|
+
try {
|
|
331
|
+
consumed = this.offer(entry.event);
|
|
332
|
+
}
|
|
333
|
+
finally {
|
|
334
|
+
this.eventIndex = walkIndex;
|
|
335
|
+
}
|
|
336
|
+
if (consumed) {
|
|
337
|
+
this.parked.splice(i, 1);
|
|
338
|
+
// A `Finished` callback was spliced out of the list this pass, so
|
|
339
|
+
// restart rather than keep walking a mutated array.
|
|
340
|
+
progressed = this.parked.length > 0;
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Step the ordered walk over an event nobody claimed, holding on to it for a
|
|
348
|
+
* later consumer. Returns false when the event's type makes its position a
|
|
349
|
+
* decision record, which is the one case where nobody claiming it means the
|
|
350
|
+
* replay diverged.
|
|
351
|
+
*/
|
|
352
|
+
park(event) {
|
|
353
|
+
if (!PARKABLE_EVENT_TYPES.has(event.eventType)) {
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
if (event.correlationId &&
|
|
357
|
+
this.resolved.has(resolutionKey(event.eventType, event.correlationId))) {
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
this.parked.push({ event, index: this.eventIndex });
|
|
361
|
+
this.eventIndex++;
|
|
362
|
+
eventsLogger.debug('Parked an unclaimed event for later delivery', {
|
|
363
|
+
eventId: event.eventId,
|
|
364
|
+
eventType: event.eventType,
|
|
365
|
+
correlationId: event.correlationId,
|
|
366
|
+
parked: this.parked.length,
|
|
367
|
+
});
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
handleEndOfLog() {
|
|
371
|
+
// Everything still parked is waiting for a consumer some later replay will
|
|
372
|
+
// register, which is the whole point of parking — except once the log
|
|
373
|
+
// already holds the run's terminal event, because then there is no later
|
|
374
|
+
// replay and no consumer will ever come.
|
|
375
|
+
if (this.parked.length === 0) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const last = this.events.at(-1);
|
|
379
|
+
if (!last || !TERMINAL_EVENT_TYPES.has(last.eventType)) {
|
|
380
|
+
// A later replay is still expected, so nothing here is decidable and
|
|
381
|
+
// escalating would fail the healthy runs parking exists to keep alive.
|
|
382
|
+
// Reaching the end of the log holding something is not by itself a fault,
|
|
383
|
+
// so this stays at `debug`; {@link parkedSummary} is what carries the
|
|
384
|
+
// state to the span, where a run that keeps stopping on the same held
|
|
385
|
+
// event is visible and a single replay's view is not.
|
|
386
|
+
eventsLogger.debug('Reached the end of the log still holding events', {
|
|
387
|
+
eventId: this.parked[0].event.eventId,
|
|
388
|
+
eventType: this.parked[0].event.eventType,
|
|
389
|
+
correlationId: this.parked[0].event.correlationId,
|
|
390
|
+
parked: this.parked.length,
|
|
391
|
+
});
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
this.scheduleUnconsumedCheck(this.parked[0].event, false);
|
|
395
|
+
}
|
|
396
|
+
scheduleUnconsumedCheck(currentEvent, mayPark) {
|
|
167
397
|
// All callbacks returned NotConsumed for the current event.
|
|
168
|
-
//
|
|
169
|
-
// schedule a deferred check. We chain onto the promiseQueue so that any
|
|
398
|
+
// Schedule a deferred check. We chain onto the promiseQueue so that any
|
|
170
399
|
// pending async work (e.g., deserialization/decryption that triggers
|
|
171
400
|
// resolve() → user code → subscribe()) completes first. If the event
|
|
172
|
-
// is still unconsumed after the queue drains, it's truly orphaned
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
//
|
|
189
|
-
//
|
|
190
|
-
//
|
|
191
|
-
//
|
|
401
|
+
// is still unconsumed after the queue drains, it's truly orphaned — or,
|
|
402
|
+
// when its type carries no ordering claim, parked for a later consumer.
|
|
403
|
+
const checkVersion = ++this.unconsumedCheckVersion;
|
|
404
|
+
this.pendingUnconsumedCheck = this.getPromiseQueue()
|
|
405
|
+
.then(
|
|
406
|
+
// Yield once after the first queue drain so promise chains resumed by
|
|
407
|
+
// that drain can run across the VM boundary and append any follow-up
|
|
408
|
+
// async work (for example: step_completed resolves -> for-await loop
|
|
409
|
+
// resumes -> the next hook payload starts hydrating).
|
|
410
|
+
() => new Promise((resolve) => setTimeout(resolve, 0)))
|
|
411
|
+
.then(() => this.getPromiseQueue())
|
|
412
|
+
.then(() => {
|
|
413
|
+
// Wait out any delivery still in flight before starting the timer.
|
|
414
|
+
// The queue draining says the host has no hydration work left; it
|
|
415
|
+
// does not say the VM has finished reacting to what was hydrated.
|
|
416
|
+
this.whenDeliveryIdle(checkVersion, () => {
|
|
417
|
+
// Use a delayed setTimeout once deliveries are idle. The delay must
|
|
418
|
+
// be long enough for promise chains to propagate across the VM
|
|
419
|
+
// boundary (from resolve() in the host context through to the
|
|
420
|
+
// workflow code calling subscribe() in the VM context). Node.js does
|
|
421
|
+
// not guarantee that setTimeout(0) fires after all cross-context
|
|
422
|
+
// microtasks settle, so we use a small but non-zero delay. Any
|
|
423
|
+
// subscribe() call that arrives during this window will cancel the
|
|
424
|
+
// check via version invalidation + clearTimeout.
|
|
192
425
|
this.pendingUnconsumedTimeout = setTimeout(() => {
|
|
193
426
|
this.pendingUnconsumedTimeout = null;
|
|
194
|
-
if (this.unconsumedCheckVersion
|
|
195
|
-
|
|
196
|
-
this.onUnconsumedEvent(currentEvent);
|
|
427
|
+
if (this.unconsumedCheckVersion !== checkVersion) {
|
|
428
|
+
return;
|
|
197
429
|
}
|
|
430
|
+
this.pendingUnconsumedCheck = null;
|
|
431
|
+
if (mayPark) {
|
|
432
|
+
if (this.events[this.eventIndex] !== currentEvent) {
|
|
433
|
+
// An append() drain claimed it while the check was in flight.
|
|
434
|
+
// Only subscribe() cancels the check, so this is reachable.
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
if (this.park(currentEvent)) {
|
|
438
|
+
this.consume();
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
this.onUnconsumedEvent(currentEvent);
|
|
198
443
|
}, getDeferredCheckDelayMs());
|
|
199
444
|
});
|
|
200
|
-
}
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Run `fn` once no data delivery is in flight, polling the way
|
|
449
|
+
* `scheduleWhenIdle` does: let the promise queue drain, re-check a timer
|
|
450
|
+
* tick later, repeat.
|
|
451
|
+
*
|
|
452
|
+
* Without this the check is a bet that every delivery the walk is running
|
|
453
|
+
* ahead of lands inside a fixed window. Consumption is synchronous while the
|
|
454
|
+
* resolution it triggers is not: a step result hydrates in the host, resolves
|
|
455
|
+
* from a detached continuation behind `awaitEarlierDeliveries`, and only then
|
|
456
|
+
* does VM code run far enough to subscribe the next consumer. Replaying a
|
|
457
|
+
* batch of N parallel step results leaves N-1 of them on that detached path
|
|
458
|
+
* with the queue already drained, so the walk sits on the ordered event the
|
|
459
|
+
* VM is about to draw and the window is the only thing standing between a
|
|
460
|
+
* healthy run and `ReplayDivergenceError`.
|
|
461
|
+
*
|
|
462
|
+
* Shortening the window shows that mechanism directly: on identical event logs
|
|
463
|
+
* the local race repro corrupts 34 of 42 runs at a 10ms window and 0 of 114 at
|
|
464
|
+
* the 100ms default. That measures how the bet loses, not that the default
|
|
465
|
+
* loses it, and no measurement of a delivery outrunning 100ms exists either
|
|
466
|
+
* way. So read this as retiring the bet rather than as repairing an observed
|
|
467
|
+
* failure of that number: the delay is a user-settable env override, which
|
|
468
|
+
* leaves the old behaviour one configuration away from losing on any backend.
|
|
469
|
+
*
|
|
470
|
+
* Termination is `hasParkedCommittedDelivery`'s: it counts only deliveries
|
|
471
|
+
* that resolve on their own, so nothing here can gate its own retirement. A
|
|
472
|
+
* genuinely orphaned event has no delivery to wait on and reaches `fn` on the
|
|
473
|
+
* first poll.
|
|
474
|
+
*
|
|
475
|
+
* What the gate gives up: for the ordered events that still reach
|
|
476
|
+
* `onUnconsumedEvent` rather than {@link park}, this stops being the thing
|
|
477
|
+
* that catches a diverged log while a delivery is in flight. The suspension
|
|
478
|
+
* and this check now wake from the same `isDeliveryIdle` edge, and
|
|
479
|
+
* `scheduleWhenIdle` fires on the first timer tick after idle while this waits
|
|
480
|
+
* a further `getDeferredCheckDelayMs()`. So a run with a pending `sleep()`
|
|
481
|
+
* suspends first, and `onWorkflowError` drops the divergence arriving second
|
|
482
|
+
* (its `'suspended'` branch demotes to `'replay'` and surfaces nothing),
|
|
483
|
+
* leaving a later `resume()` to decline into a cold replay. Pre-gate the
|
|
484
|
+
* suspension already won that race whenever the delivery landed inside the
|
|
485
|
+
* fixed window, so what changed is that the outcome stopped depending on
|
|
486
|
+
* timing. Nothing should treat this check as the mechanism that reports
|
|
487
|
+
* divergence on a log the run is still delivering into.
|
|
488
|
+
*/
|
|
489
|
+
whenDeliveryIdle(checkVersion, fn) {
|
|
490
|
+
const poll = () => {
|
|
491
|
+
this.pendingUnconsumedTimeout = null;
|
|
492
|
+
if (this.unconsumedCheckVersion !== checkVersion) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
if (this.isDeliveryIdle()) {
|
|
496
|
+
fn();
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
this.getPromiseQueue().then(() => {
|
|
500
|
+
if (this.unconsumedCheckVersion !== checkVersion) {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
// Held in the same field the fired check uses so subscribe() cancels a
|
|
504
|
+
// poll in progress too. The two cancellations are not identical: for the
|
|
505
|
+
// poll it is the version bump that does the work and the clearTimeout is
|
|
506
|
+
// belt-and-braces. Two state machines write this one field, so a poll
|
|
507
|
+
// invalidated between scheduling and firing can null out a handle the
|
|
508
|
+
// live chain has since stored, which is why every path out of `poll` and
|
|
509
|
+
// out of the fired check re-checks the version rather than trusting the
|
|
510
|
+
// handle.
|
|
511
|
+
this.pendingUnconsumedTimeout = setTimeout(poll, 0);
|
|
512
|
+
});
|
|
513
|
+
};
|
|
514
|
+
poll();
|
|
201
515
|
}
|
|
202
516
|
}
|
|
203
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnRzLWNvbnN1bWVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2V2ZW50cy1jb25zdW1lci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWMsU0FBUyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDeEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUUzQzs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFHLEdBQUcsQ0FBQztBQUUzQzs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSx1QkFBdUIsR0FBRyxHQUFXLEVBQUUsQ0FDM0MsU0FBUyxDQUFDLGtDQUFrQyxFQUFFLHVCQUF1QixFQUFFO0lBQ3JFLE9BQU8sRUFBRSxJQUFJO0lBQ2IsR0FBRyxFQUFFLEVBQUU7Q0FDUixDQUFDLENBQUM7QUFFTCxNQUFNLENBQU4sSUFBWSxtQkFhWDtBQWJELFdBQVksbUJBQW1CO0lBQzdCOztPQUVHO0lBQ0gscUVBQVEsQ0FBQTtJQUNSOztPQUVHO0lBQ0gsMkVBQVcsQ0FBQTtJQUNYOztPQUVHO0lBQ0gscUVBQVEsQ0FBQTtBQUNWLENBQUMsRUFiVyxtQkFBbUIsS0FBbkIsbUJBQW1CLFFBYTlCO0FBNEJELE1BQU0sT0FBTyxjQUFjO0lBQ3pCLFVBQVUsQ0FBUztJQUNWLE1BQU0sQ0FBVTtJQUNoQixTQUFTLEdBQTRCLEVBQUUsQ0FBQztJQUN6QyxlQUFlLENBQTBCO0lBQ3pDLGlCQUFpQixDQUF5QjtJQUMxQyxlQUFlLENBQXNCO0lBQ3JDLHNCQUFzQixHQUF5QixJQUFJLENBQUM7SUFDcEQsd0JBQXdCLEdBQXlDLElBQUksQ0FBQztJQUN0RSxzQkFBc0IsR0FBRyxDQUFDLENBQUM7SUFFbkMsWUFBWSxNQUFlLEVBQUUsT0FBOEI7UUFDekQseUVBQXlFO1FBQ3pFLHNFQUFzRTtRQUN0RSwyQ0FBMkM7UUFDM0MsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLEdBQUcsTUFBTSxD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akQsSUFBSTtZQUNILHNFQUFzRTtZQUN0RSxxRUFBcUU7WUFDckUscUVBQXFFO1lBQ3JFLHNEQUFzRDtZQUN0RCxHQUFHLEVBQUUsQ0FBQyxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUM3RDtpQkFDQSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO2lCQUNsQyxJQUFJLENBQUMsR0FBRyxFQUFFO2dCQUNULHFFQUFxRTtnQkFDckUscUVBQXFFO2dCQUNyRSxtRUFBbUU7Z0JBQ25FLHFFQUFxRTtnQkFDckUsc0VBQXNFO2dCQUN0RSxrRUFBa0U7Z0JBQ2xFLCtEQUErRDtnQkFDL0QsK0JBQStCO2dCQUMvQixJQUFJLENBQUMsd0JBQXdCLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRTtvQkFDOUMsSUFBSSxDQUFDLHdCQUF3QixHQUFHLElBQUksQ0FBQztvQkFDckMsSUFBSSxJQUFJLENBQUMsc0JBQXNCLEtBQUssWUFBWSxFQUFFLENBQUM7d0JBQ2pELElBQUksQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLENBQUM7d0JBQ25DLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztvQkFDdkMsQ0FBQztnQkFDSCxDQUFDLEVBQUUsdUJBQXVCLEVBQUUsQ0FBQyxDQUFDO1lBQ2hDLENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQztJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHR5cGUgRXZlbnQsIGVudk51bWJlciB9IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBldmVudHNMb2dnZXIgfSBmcm9tICcuL2xvZ2dlci5qcyc7XG5cbi8qKlxuICogRGVsYXkgYmVmb3JlIGZpcmluZyB0aGUgZGVmZXJyZWQgdW5jb25zdW1lZC1ldmVudCBjaGVjayBhZnRlciB0aGUgcHJvbWlzZVxuICogcXVldWUgaGFzIGRyYWluZWQuIE11c3QgYmUgbG9uZyBlbm91Z2ggZm9yIGNyb3NzLVZNIG1pY3JvdGFzayBjaGFpbnMgdG9cbiAqIHByb3BhZ2F0ZSAocmVzb2x2ZSBpbiBob3N0IOKGkiB3b3JrZmxvdyBjb2RlIGluIFZNIOKGkiBzdWJzY3JpYmUgY2FsbCBiYWNrXG4gKiBpbiBob3N0KS4gQW55IHN1YnNjcmliZSgpIGFycml2aW5nIGR1cmluZyB0aGlzIHdpbmRvdyBjYW5jZWxzIHRoZSBjaGVjay5cbiAqL1xuZXhwb3J0IGNvbnN0IERFRkVSUkVEX0NIRUNLX0RFTEFZX01TID0gMTAwO1xuXG4vKipcbiAqIEVmZmVjdGl2ZSBkZWZlcnJlZC1jaGVjayBkZWxheS4gT3ZlcnJpZGU6IGBXT1JLRkxPV19ERUZFUlJFRF9DSEVDS19ERUxBWV9NU2AuXG4gKlxuICogVW5saWtlIHRoZSBvdGhlciB0aW1pbmcga25vYnMgdGhpcyBpcyBub3QgYSBwb2xsaW5nIGludGVydmFsIGJ1dCBhXG4gKiBkZXRlcm1pbmlzbSBzYWZldHkgbWFyZ2luOiBmaXJpbmcgdGhlIHVuY29uc3VtZWQtZXZlbnQgY2hlY2sgYmVmb3JlIHRoZVxuICogY3Jvc3MtVk0gc3Vic2NyaWJlKCkgY2hhaW4gaGFzIGxhbmRlZCByZWplY3RzIGEgaGVhbHRoeSBydW4gd2l0aFxuICogYFJlcGxheURpdmVyZ2VuY2VFcnJvcmAuIEZsb29yZWQgYXQgMTBtcyBzbyBhIHRvby1sb3cgb3ZlcnJpZGUgY2FuJ3RcbiAqIG1hbnVmYWN0dXJlIHNwdXJpb3VzIGRpdmVyZ2VuY2UgKGVhY2ggZmFsc2UgcG9zaXRpdmUgYnVybnMgYVxuICogZGl2ZXJnZW5jZS1yZWNvdmVyeSByZXRyeSBhbmQgY2FuIGVzY2FsYXRlIHRvIGEgdGVybWluYWxcbiAqIGBDb3JydXB0ZWRFdmVudExvZ0Vycm9yYCkuXG4gKi9cbmNvbnN0IGdldERlZmVycmVkQ2hlY2tEZWxheU1zID0gKCk6IG51bWJlciA9PlxuICBlbnZOdW1iZXIoJ1dPUktGTE9XX0RFRkVSUkVEX0NIRUNLX0RFTEFZX01TJywgREVGRVJSRURfQ0hFQ0tfREVMQVlfTVMsIHtcbiAgICBpbnRlZ2VyOiB0cnVlLFxuICAgIG1pbjogMTAsXG4gIH0pO1xuXG5leHBvcnQgZW51bSBFdmVudENvbnN1bWVyUmVzdWx0IHtcbiAgLyoqXG4gICAqIENhbGxiYWNrIGNvbnN1bWVkIHRoZSBldmVudCwgYnV0IHNob3VsZCBub3QgYmUgcmVtb3ZlZCBmcm9tIHRoZSBjYWxsYmFja3MgbGlzdFxuICAgKi9cbiAgQ29uc3VtZWQsXG4gIC8qKlxuICAgKiBDYWxsYmFjayBkaWQgbm90IGNvbnN1bWUgdGhlIGV2ZW50LCBzbyBpdCBzaG91bGQgYmUgcGFzc2VkIHRvIHRoZSBuZXh0IGNhbGxiYWNrXG4gICAqL1xuICBOb3RDb25zdW1lZCxcbiAgLyoqXG4gICAqIENhbGxiYWNrIGNvbnN1bWVkIHRoZSBldmVudCwgYW5kIHNob3VsZCBiZSByZW1vdmVkIGZyb20gdGhlIGNhbGxiYWNrcyBsaXN0XG4gICAqL1xuICBGaW5pc2hlZCxcbn1cblxudHlwZSBFdmVudENvbnN1bWVyQ2FsbGJhY2sgPSAoZXZlbnQ6IEV2ZW50IHwgbnVsbCkgPT4gRXZlbnRDb25zdW1lclJlc3VsdDtcblxuZXhwb3J0IGludGVyZmFjZSBFdmVudHNDb25zdW1lck9wdGlvbnMge1xuICAvKipcbiAgICogQ2FsbGJhY2sgaW52b2tlZCBhZnRlciBhbiBldmVudCBoYXMgYmVlbiBjb25zdW1lZC4gQ29uc3VtZXJzIHN1Y2ggYXMgdGhlXG4gICAqIGRldGVybWluaXN0aWMgd29ya2Zsb3cgY2xvY2sgbXVzdCBub3Qgb2JzZXJ2ZSBldmVudHMgdGhhdCBhcmUgbWVyZWx5XG4gICAqIGluc3BlY3RlZCB3aGlsZSB3YWl0aW5nIGZvciB1c2VyIGNvZGUgdG8gc3Vic2NyaWJlIHRvIHRoZSBuZXh0IG9wZXJhdGlvbi5cbiAgICovXG4gIG9uQ29uc3VtZWRFdmVudD86IChldmVudDogRXZlbnQpID0+IHZvaWQ7XG4gIC8qKlxuICAgKiBDYWxsYmFjayBpbnZva2VkIHdoZW4gYSBub24tbnVsbCBldmVudCBjYW5ub3QgYmUgY29uc3VtZWQgYnkgYW55IHJlZ2lzdGVyZWRcbiAgICogY2FsbGJhY2ssIGluZGljYXRpbmcgYW4gb3JwaGFuZWQgb3IgaW52YWxpZCBldmVudCBpbiB0aGUgZXZlbnQgbG9nLiBUaGVcbiAgICogY2hlY2sgaXMgZGVmZXJyZWQgdW50aWwgYWZ0ZXIgdGhlIHByb21pc2UgcXVldWUgaGFzIGRyYWluZWQsIGVuc3VyaW5nIHRoYXRcbiAgICogYW55IHBlbmRpbmcgYXN5bmMgd29yayAoZS5nLiwgZGVzZXJpYWxpemF0aW9uL2RlY3J5cHRpb24pIGNvbXBsZXRlcyBhbmRcbiAgICogZG93bnN0cmVhbSBzdWJzY3JpYmUoKSBjYWxscyBoYXZlIGEgY2hhbmNlIHRvIGNhbmNlbCB0aGUgY2hlY2sgZmlyc3QuXG4gICAqL1xuICBvblVuY29uc3VtZWRFdmVudDogKGV2ZW50OiBFdmVudCkgPT4gdm9pZDtcbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGN1cnJlbnQgcHJvbWlzZSBxdWV1ZS4gVGhlIHVuY29uc3VtZWQgZXZlbnQgY2hlY2sgaXMgY2hhaW5lZFxuICAgKiBvbnRvIHRoaXMgcXVldWUgc28gaXQgb25seSBmaXJlcyBhZnRlciBhbGwgcGVuZGluZyBhc3luYyB3b3JrIChlLmcuLFxuICAgKiBkZXNlcmlhbGl6YXRpb24pIGhhcyBjb21wbGV0ZWQuIFRoaXMgcHJldmVudHMgZmFsc2UgcG9zaXRpdmVzIHdoZW4gYXN5bmNcbiAgICogZGVzZXJpYWxpemF0aW9uIGRlbGF5cyB0aGUgcmVzb2x2ZSgpIHRoYXQgdHJpZ2dlcnMgdGhlIG5leHQgc3Vic2NyaWJlKCkuXG4gICAqL1xuICBnZXRQcm9taXNlUXVldWU6ICgpID0+IFByb21pc2U8dm9pZD47XG59XG5cbmV4cG9ydCBjbGFzcyBFdmVudHNDb25zdW1lciB7XG4gIGV2ZW50SW5kZXg6IG51bWJlcjtcbiAgcmVhZG9ubHkgZXZlbnRzOiBFdmVudFtdO1xuICByZWFkb25seSBjYWxsYmFja3M6IEV2ZW50Q29uc3VtZXJDYWxsYmFja1tdID0gW107XG4gIHByaXZhdGUgb25Db25zdW1lZEV2ZW50PzogKGV2ZW50OiBFdmVudCkgPT4gdm9pZDtcbiAgcHJpdmF0ZSBvblVuY29uc3VtZWRFdmVudDogKGV2ZW50OiBFdmVudCkgPT4gdm9pZDtcbiAgcHJpdmF0ZSBnZXRQcm9taXNlUXVldWU6ICgpID0+IFByb21pc2U8dm9pZD47XG4gIHByaXZhdGUgcGVuZGluZ1VuY29uc3VtZWRDaGVjazogUHJvbWlzZTx2b2lkPiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHBlbmRpbmdVbmNvbnN1bWVkVGltZW91dDogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSB1bmNvbnN1bWVkQ2hlY2tWZXJzaW9uID0gMDtcblxuICBjb25zdHJ1Y3RvcihldmVudHM6IEV2ZW50W10sIG9wdGlvbnM6IEV2ZW50c0NvbnN1bWVyT3B0aW9ucykge1xuICAgIC8vIE93biBjb3B5OiB0aGUgcnVudGltZSBtdXRhdGVzIGl0cyBldmVudCBhcnJheSBpbiBwbGFjZSwgYW5kIGEgcmV0YWluZWRcbiAgICAvLyBzZXNzaW9uIG11c3Qgb25seSBvYnNlcnZlIG5ldyBldmVudHMgdGhyb3VnaCBhcHBlbmQoKSBzbyByZXN1bWUoKSdzXG4gICAgLy8gc3RyaWN0LWV4dGVuc2lvbiBjaGVjayBzdGF5cyBtZWFuaW5nZnVsLlxuICAgIHRoaXMuZXZlbnRzID0gWy4uLmV2ZW50c107XG4gICAgdGhpcy5ldmVudEluZGV4ID0gMDtcbiAgICB0aGlzLm9uQ29uc3VtZWRFdmVudCA9IG9wdGlvbnMub25Db25zdW1lZEV2ZW50O1xuICAgIHRoaXMub25VbmNvbnN1bWVkRXZlbnQgPSBvcHRpb25zLm9uVW5jb25zdW1lZEV2ZW50O1xuICAgIHRoaXMuZ2V0UHJvbWlzZVF1ZXVlID0gb3B0aW9ucy5nZXRQcm9taXNlUXVldWU7XG4gIH1cblxuICBhcHBlbmQoZXZlbnRzOiBFdmVudFtdKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBldmVudCBvZiBldmVudHMpIHRoaXMuZXZlbnRzLnB1c2goZXZlbnQpO1xuICAgIHByb2Nlc3MubmV4dFRpY2sodGhpcy5jb25zdW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWQgYWZ0ZXIgYW4gZXZlbnQgaGFzIGJlZW4gY29uc3VtZWRcbiAgICogYnkgYSBkaWZmZXJlbnQgY2FsbGJhY2suIFRoZSBjYWxsYmFjayBjYW4gcmV0dXJuOlxuICAgKiAgLSBgRXZlbnRDb25zdW1lclJlc3VsdC5Db25zdW1lZGAgdGhlIGV2ZW50IGlzIGNvbnNpZGVyZWQgY29uc3VtZWQgYW5kIHdpbGwgbm90IGJlIHBhc3NlZCB0byBhbnkgb3RoZXIgY2FsbGJhY2ssIGJ1dCB0aGUgY2FsbGJhY2sgd2lsbCByZW1haW4gaW4gdGhlIGNhbGxiYWNrcyBsaXN0XG4gICAqICAtIGBFdmVudENvbnN1bWVyUmVzdWx0Lk5vdENvbnN1bWVkYCB0aGUgZXZlbnQgaXMgcGFzc2VkIHRvIHRoZSBuZXh0IGNhbGxiYWNrXG4gICAqICAtIGBFdmVudENvbnN1bWVyUmVzdWx0LkZpbmlzaGVkYCB0aGUgZXZlbnQgaXMgY29uc2lkZXJlZCBjb25zdW1lZCBhbmQgdGhlIGNhbGxiYWNrIGlzIHJlbW92ZWQgZnJvbSB0aGUgY2FsbGJhY2tzIGxpc3RcbiAgICpcbiAgICogQHBhcmFtIGZuIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIHJlZ2lzdGVyLlxuICAgKi9cbiAgc3Vic2NyaWJlKGZuOiBFdmVudENvbnN1bWVyQ2FsbGJhY2spIHtcbiAgICB0aGlzLmNhbGxiYWNrcy5wdXNoKGZuKTtcbiAgICAvLyBDYW5jZWwgYW55IHBlbmRpbmcgdW5jb25zdW1lZCBjaGVjayBzaW5jZSBhIG5ldyBjYWxsYmFjayBtYXkgY29uc3VtZSB0aGUgZXZlbnQuXG4gICAgLy8gSW5jcmVtZW50aW5nIHRoZSB2ZXJzaW9uIGNhdXNlcyBhbnkgaW4tZmxpZ2h0IHByb21pc2UgY2hhaW4gY2hlY2sgdG8gbm8tb3AuXG4gICAgLy8gQWxzbyBjbGVhciB0aGUgcGVuZGluZyBzZXRUaW1lb3V0IGlmIGl0IGhhc24ndCBmaXJlZCB5ZXQuXG4gICAgaWYgKHRoaXMucGVuZGluZ1VuY29uc3VtZWRDaGVjayAhPT0gbnVsbCkge1xuICAgICAgdGhpcy51bmNvbnN1bWVkQ2hlY2tWZXJzaW9uKys7XG4gICAgICB0aGlzLnBlbmRpbmdVbmNvbnN1bWVkQ2hlY2sgPSBudWxsO1xuICAgICAgaWYgKHRoaXMucGVuZGluZ1VuY29uc3VtZWRUaW1lb3V0ICE9PSBudWxsKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnBlbmRpbmdVbmNvbnN1bWVkVGltZW91dCk7XG4gICAgICAgIHRoaXMucGVuZGluZ1VuY29uc3VtZWRUaW1lb3V0ID0gbnVsbDtcbiAgICAgIH1cbiAgICB9XG4gICAgcHJvY2Vzcy5uZXh0VGljayh0aGlzLmNvbnN1bWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBub3RpZnlDb25zdW1lZEV2ZW50KGV2ZW50OiBFdmVudCkge1xuICAgIGlmICghdGhpcy5vbkNvbnN1bWVkRXZlbnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMub25Db25zdW1lZEV2ZW50KGV2ZW50KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgZXZlbnRzTG9nZ2VyLmVycm9yKCdvbkNvbnN1bWVkRXZlbnQgY2FsbGJhY2sgdGhyZXcgYW4gZXJyb3InLCB7XG4gICAgICAgIGVycm9yLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjb25zdW1lID0gKCkgPT4ge1xuICAgIC8vIERyYWluIGNvbnNlY3V0aXZlbHkgY29uc3VtYWJsZSBldmVudHMgc3luY2hyb25vdXNseSB3aXRoaW4gYSBzaW5nbGVcbiAgICAvLyBwYXNzIGluc3RlYWQgb2YgcGF5aW5nIG9uZSBgcHJvY2Vzcy5uZXh0VGlja2AgcGVyIGNvbnN1bWVkIGV2ZW50LlxuICAgIC8vXG4gICAgLy8gV2h5IHRoaXMgaXMgc2FmZTogYSBjYWxsYmFjayBvbmx5IGNvbnN1bWVzIGFuIGV2ZW50IHVzaW5nIGEgY29uc3VtZXJcbiAgICAvLyB0aGF0IGlzIEFMUkVBRFkgcmVnaXN0ZXJlZCAoZS5nLiBhIGxvbmctbGl2ZWQgc3RlcCBjb25zdW1lciB3YWxraW5nXG4gICAgLy8gYHN0ZXBfY3JlYXRlZGAg4oaSIGBzdGVwX3N0YXJ0ZWRgIOKGkiBgc3RlcF9jb21wbGV0ZWRgLCBvciB0aGUgc3RydWN0dXJhbFxuICAgIC8vIGxpZmVjeWNsZSBjb25zdW1lcikuIE5ldyBjb25zdW1lcnMgYXJlIG9ubHkgZXZlciByZWdpc3RlcmVkIGJ5IHdvcmtmbG93XG4gICAgLy8gVk0gYm9keSBjb2RlIHRoYXQgcnVucyBhc3luY2hyb25vdXNseSBvZmYgYGN0eC5wcm9taXNlUXVldWVgIGFmdGVyIGFcbiAgICAvLyBkZWxpdmVyeSBgcmVzb2x2ZSgpYDsgbm9uZSBvZiB0aGUgY2FsbGJhY2tzIGhlcmUgY2FsbCBgc3Vic2NyaWJlKClgXG4gICAgLy8gc3luY2hyb25vdXNseS4gU28gd2l0aGluIG9uZSBwYXNzIGB0aGlzLmNhbGxiYWNrc2AgaXMgbXV0YXRlZCBvbmx5IGJ5XG4gICAgLy8gdGhpcyBsb29wICh0aGUgYEZpbmlzaGVkYCBzcGxpY2UpLCBhbmQgdGhlIG5leHQgZXZlbnQncyBjb25zdW1lciBpc1xuICAgIC8vIGVpdGhlciBhbHJlYWR5IHByZXNlbnQgKGFkdmFuY2Ugbm93KSBvciBub3QgeWV0IHJlZ2lzdGVyZWQg4oCUIGluIHdoaWNoXG4gICAgLy8gY2FzZSBubyBjYWxsYmFjayBjb25zdW1lcyB0aGUgZXZlbnQgYW5kIHdlIGZhbGwgdGhyb3VnaCB0byB0aGVcbiAgICAvLyBjcm9zcy1WTS1zYWZlIGRlZmVycmVkIHVuY29uc3VtZWQtZXZlbnQgY2hlY2sgYmVsb3csIGV4YWN0bHkgYXMgYmVmb3JlLlxuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBjb25zdCBjdXJyZW50RXZlbnQgPSB0aGlzLmV2ZW50c1t0aGlzLmV2ZW50SW5kZXhdID8/IG51bGw7XG4gICAgICBpZiAoIXRoaXMuY29uc3VtZU9uZShjdXJyZW50RXZlbnQpKSB7XG4gICAgICAgIC8vIE5vIGNhbGxiYWNrIGNvbnN1bWVkIHRoZSBjdXJyZW50IGV2ZW50OyBoYW5kbGUgdGhlIHRlcm1pbmFsIGNhc2UuXG4gICAgICAgIHRoaXMuaGFuZGxlVW5jb25zdW1lZChjdXJyZW50RXZlbnQpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICAvLyBBIHJlYWwgZXZlbnQgd2FzIGNvbnN1bWVkIOKAlCBhZHZhbmNlIHRvIHRoZSBuZXh0IGluIHRoZSBzYW1lIHBhc3MuIEFcbiAgICAgIC8vIGNvbnN1bWVkIGBudWxsYCBzZW50aW5lbCBuZXZlciByZXR1cm5zIHRydWUgKHNlZSBjb25zdW1lT25lKSwgc28gdGhlXG4gICAgICAvLyBzeW5jaHJvbm91cyBkcmFpbiBjYW4ndCBzcGluIHBhc3QgdGhlIGVuZCBvZiB0aGUgbG9nLlxuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogT2ZmZXIgYGN1cnJlbnRFdmVudGAgdG8gZWFjaCByZWdpc3RlcmVkIGNhbGxiYWNrIGluIHR1cm4uIFJldHVybnMgdHJ1ZVxuICAgKiB3aGVuIGEgY2FsbGJhY2sgY29uc3VtZWQgYSByZWFsIChub24tbnVsbCkgZXZlbnQgYW5kIHRoZSBkcmFpbiBzaG91bGRcbiAgICogYWR2YW5jZSB0byB0aGUgbmV4dCBldmVudCBpbiB0aGUgc2FtZSBzeW5jaHJvbm91cyBwYXNzOyBmYWxzZSBvdGhlcndpc2VcbiAgICogKG5vdGhpbmcgY29uc3VtZWQgaXQsIG9yIHRoZSBjb25zdW1lZCBldmVudCB3YXMgdGhlIGVuZC1vZi1ldmVudHNcbiAgICogc2VudGluZWwpLlxuICAgKi9cbiAgcHJpdmF0ZSBjb25zdW1lT25lKGN1cnJlbnRFdmVudDogRXZlbnQgfCBudWxsKTogYm9vbGVhbiB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmNhbGxiYWNrcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgY2FsbGJhY2sgPSB0aGlzLmNhbGxiYWNrc1tpXTtcbiAgICAgIGxldCBoYW5kbGVkID0gRXZlbnRDb25zdW1lclJlc3VsdC5Ob3RDb25zdW1lZDtcbiAgICAgIHRyeSB7XG4gICAgICAgIGhhbmRsZWQgPSBjYWxsYmFjayhjdXJyZW50RXZlbnQpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgZXZlbnRzTG9nZ2VyLmVycm9yKCdFdmVudENvbnN1bWVyIGNhbGxiYWNrIHRocmV3IGFuIGVycm9yJywgeyBlcnJvciB9KTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgaGFuZGxlZCAhPT0gRXZlbnRDb25zdW1lclJlc3VsdC5Db25zdW1lZCAmJlxuICAgICAgICBoYW5kbGVkICE9PSBFdmVudENvbnN1bWVyUmVzdWx0LkZpbmlzaGVkXG4gICAgICApIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAoY3VycmVudEV2ZW50ICE9PSBudWxsKSB7XG4gICAgICAgIHRoaXMubm90aWZ5Q29uc3VtZWRFdmVudChjdXJyZW50RXZlbnQpO1xuICAgICAgfVxuICAgICAgLy8gY29uc3VtZXIgaGFuZGxlZCB0aGlzIGV2ZW50LCBzbyBpbmNyZWFzZSB0aGUgZXZlbnQgaW5kZXhcbiAgICAgIHRoaXMuZXZlbnRJbmRleCsrO1xuICAgICAgLy8gcmVtb3ZlIHRoZSBjYWxsYmFjayBpZiBpdCBoYXMgZmluaXNoZWRcbiAgICAgIGlmIChoYW5kbGVkID09PSBFdmVudENvbnN1bWVyUmVzdWx0LkZpbmlzaGVkKSB7XG4gICAgICAgIHRoaXMuY2FsbGJhY2tzLnNwbGljZShpLCAxKTtcbiAgICAgIH1cbiAgICAgIC8vIENvbnRpbnVlIGRyYWluaW5nIG9ubHkgZm9yIHJlYWwgZXZlbnRzLiBSZWFsIGNvbnN1bWVycyByZXR1cm5cbiAgICAgIC8vIE5vdENvbnN1bWVkIGZvciB0aGUgYG51bGxgIHNlbnRpbmVsLCBidXQgZ3VhcmQgYWdhaW5zdCBhIHBhdGhvbG9naWNhbFxuICAgICAgLy8gY2FsbGJhY2sgY29uc3VtaW5nIGl0IHNvIHRoZSBkcmFpbiBuZXZlciBzcGlucyBwYXN0IGVuZC1vZi1sb2cuXG4gICAgICByZXR1cm4gY3VycmVudEV2ZW50ICE9PSBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZVVuY29uc3VtZWQoY3VycmVudEV2ZW50OiBFdmVudCB8IG51bGwpIHtcbiAgICAvLyBBbGwgY2FsbGJhY2tzIHJldHVybmVkIE5vdENvbnN1bWVkIGZvciB0aGUgY3VycmVudCBldmVudC5cbiAgICAvLyBJZiB0aGUgY3VycmVudCBldmVudCBpcyBub24tbnVsbCAoYSByZWFsIGV2ZW50LCBub3QgZW5kLW9mLWV2ZW50cyksXG4gICAgLy8gc2NoZWR1bGUgYSBkZWZlcnJlZCBjaGVjay4gV2UgY2hhaW4gb250byB0aGUgcHJvbWlzZVF1ZXVlIHNvIHRoYXQgYW55XG4gICAgLy8gcGVuZGluZyBhc3luYyB3b3JrIChlLmcuLCBkZXNlcmlhbGl6YXRpb24vZGVjcnlwdGlvbiB0aGF0IHRyaWdnZXJzXG4gICAgLy8gcmVzb2x2ZSgpIOKGkiB1c2VyIGNvZGUg4oaSIHN1YnNjcmliZSgpKSBjb21wbGV0ZXMgZmlyc3QuIElmIHRoZSBldmVudFxuICAgIC8vIGlzIHN0aWxsIHVuY29uc3VtZWQgYWZ0ZXIgdGhlIHF1ZXVlIGRyYWlucywgaXQncyB0cnVseSBvcnBoYW5lZC5cbiAgICBpZiAoY3VycmVudEV2ZW50ICE9PSBudWxsKSB7XG4gICAgICBjb25zdCBjaGVja1ZlcnNpb24gPSArK3RoaXMudW5jb25zdW1lZENoZWNrVmVyc2lvbjtcbiAgICAgIHRoaXMucGVuZGluZ1VuY29uc3VtZWRDaGVjayA9IHRoaXMuZ2V0UHJvbWlzZVF1ZXVlKClcbiAgICAgICAgLnRoZW4oXG4gICAgICAgICAgLy8gWWllbGQgb25jZSBhZnRlciB0aGUgZmlyc3QgcXVldWUgZHJhaW4gc28gcHJvbWlzZSBjaGFpbnMgcmVzdW1lZCBieVxuICAgICAgICAgIC8vIHRoYXQgZHJhaW4gY2FuIHJ1biBhY3Jvc3MgdGhlIFZNIGJvdW5kYXJ5IGFuZCBhcHBlbmQgYW55IGZvbGxvdy11cFxuICAgICAgICAgIC8vIGFzeW5jIHdvcmsgKGZvciBleGFtcGxlOiBzdGVwX2NvbXBsZXRlZCByZXNvbHZlcyAtPiBmb3ItYXdhaXQgbG9vcFxuICAgICAgICAgIC8vIHJlc3VtZXMgLT4gdGhlIG5leHQgaG9vayBwYXlsb2FkIHN0YXJ0cyBoeWRyYXRpbmcpLlxuICAgICAgICAgICgpID0+IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDApKVxuICAgICAgICApXG4gICAgICAgIC50aGVuKCgpID0+IHRoaXMuZ2V0UHJvbWlzZVF1ZXVlKCkpXG4gICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAvLyBVc2UgYSBkZWxheWVkIHNldFRpbWVvdXQgYWZ0ZXIgdGhlIHF1ZXVlIGRyYWlucy4gVGhlIGRlbGF5IG11c3QgYmVcbiAgICAgICAgICAvLyBsb25nIGVub3VnaCBmb3IgcHJvbWlzZSBjaGFpbnMgdG8gcHJvcGFnYXRlIGFjcm9zcyB0aGUgVk0gYm91bmRhcnlcbiAgICAgICAgICAvLyAoZnJvbSByZXNvbHZlKCkgaW4gdGhlIGhvc3QgY29udGV4dCB0aHJvdWdoIHRvIHRoZSB3b3JrZmxvdyBjb2RlXG4gICAgICAgICAgLy8gY2FsbGluZyBzdWJzY3JpYmUoKSBpbiB0aGUgVk0gY29udGV4dCkuIE5vZGUuanMgZG9lcyBub3QgZ3VhcmFudGVlXG4gICAgICAgICAgLy8gdGhhdCBzZXRUaW1lb3V0KDApIGZpcmVzIGFmdGVyIGFsbCBjcm9zcy1jb250ZXh0IG1pY3JvdGFza3Mgc2V0dGxlLFxuICAgICAgICAgIC8vIHNvIHdlIHVzZSBhIHNtYWxsIGJ1dCBub24temVybyBkZWxheS4gQW55IHN1YnNjcmliZSgpIGNhbGwgdGhhdFxuICAgICAgICAgIC8vIGFycml2ZXMgZHVyaW5nIHRoaXMgd2luZG93IHdpbGwgY2FuY2VsIHRoZSBjaGVjayB2aWEgdmVyc2lvblxuICAgICAgICAgIC8vIGludmFsaWRhdGlvbiArIGNsZWFyVGltZW91dC5cbiAgICAgICAgICB0aGlzLnBlbmRpbmdVbmNvbnN1bWVkVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nVW5jb25zdW1lZFRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHRoaXMudW5jb25zdW1lZENoZWNrVmVyc2lvbiA9PT0gY2hlY2tWZXJzaW9uKSB7XG4gICAgICAgICAgICAgIHRoaXMucGVuZGluZ1VuY29uc3VtZWRDaGVjayA9IG51bGw7XG4gICAgICAgICAgICAgIHRoaXMub25VbmNvbnN1bWVkRXZlbnQoY3VycmVudEV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LCBnZXREZWZlcnJlZENoZWNrRGVsYXlNcygpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICB9XG59XG4iXX0=
|
|
517
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnRzLWNvbnN1bWVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2V2ZW50cy1jb25zdW1lci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWMsU0FBUyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDeEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUUzQzs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFHLEdBQUcsQ0FBQztBQUUzQzs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxDQUFDLE1BQU0sMkJBQTJCLEdBQUcsRUFBRSxDQUFDO0FBRTlDOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLHVCQUF1QixHQUFHLEdBQVcsRUFBRSxDQUMzQyxTQUFTLENBQUMsa0NBQWtDLEVBQUUsdUJBQXVCLEVBQUU7SUFDckUsT0FBTyxFQUFFLElBQUk7SUFDYixHQUFHLEVBQUUsMkJBQTJCO0NBQ2pDLENBQUMsQ0FBQztBQUVMOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0NHO0FBQ0gsTUFBTSxvQkFBb0IsR0FBb0MsSUFBSSxHQUFHLENBQUM7SUFDcEUsZUFBZTtJQUNmLGVBQWU7SUFDZixnQkFBZ0I7SUFDaEIsVUFBVTtJQUNWLGVBQWU7Q0FDaEIsQ0FBQyxDQUFDO0FBRUg7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxNQUFNLG9CQUFvQixHQUFvQyxJQUFJLEdBQUcsQ0FBQztJQUNwRSxnQkFBZ0I7Q0FDakIsQ0FBQyxDQUFDO0FBRUgsaUVBQWlFO0FBQ2pFLFNBQVMsYUFBYSxDQUFDLFNBQWlCLEVBQUUsYUFBcUI7SUFDN0QsT0FBTyxHQUFHLFNBQVMsSUFBSSxhQUFhLEVBQUUsQ0FBQztBQUN6QyxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxvQkFBb0IsR0FBb0MsSUFBSSxHQUFHLENBQUM7SUFDcEUsZUFBZTtJQUNmLFlBQVk7SUFDWixlQUFlO0NBQ2hC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dCI6WyJpbXBvcnQgeyB0eXBlIEV2ZW50LCBlbnZOdW1iZXIgfSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgZXZlbnRzTG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXIuanMnO1xuXG4vKipcbiAqIERlbGF5IGJlZm9yZSBmaXJpbmcgdGhlIGRlZmVycmVkIHVuY29uc3VtZWQtZXZlbnQgY2hlY2sgYWZ0ZXIgdGhlIHByb21pc2VcbiAqIHF1ZXVlIGhhcyBkcmFpbmVkLiBNdXN0IGJlIGxvbmcgZW5vdWdoIGZvciBjcm9zcy1WTSBtaWNyb3Rhc2sgY2hhaW5zIHRvXG4gKiBwcm9wYWdhdGUgKHJlc29sdmUgaW4gaG9zdCDihpIgd29ya2Zsb3cgY29kZSBpbiBWTSDihpIgc3Vic2NyaWJlIGNhbGwgYmFja1xuICogaW4gaG9zdCkuIEFueSBzdWJzY3JpYmUoKSBhcnJpdmluZyBkdXJpbmcgdGhpcyB3aW5kb3cgY2FuY2VscyB0aGUgY2hlY2suXG4gKi9cbmV4cG9ydCBjb25zdCBERUZFUlJFRF9DSEVDS19ERUxBWV9NUyA9IDEwMDtcblxuLyoqXG4gKiBGbG9vciBmb3IgdGhlIGRlZmVycmVkLWNoZWNrIGRlbGF5LCBzbyBhIHRvby1sb3cgb3ZlcnJpZGUgY2FuJ3QgbWFudWZhY3R1cmVcbiAqIHNwdXJpb3VzIGRpdmVyZ2VuY2UgKGVhY2ggZmFsc2UgcG9zaXRpdmUgYnVybnMgYSBkaXZlcmdlbmNlLXJlY292ZXJ5IHJldHJ5XG4gKiBhbmQgY2FuIGVzY2FsYXRlIHRvIGEgdGVybWluYWwgYENvcnJ1cHRlZEV2ZW50TG9nRXJyb3JgKS5cbiAqXG4gKiBFeHBvcnRlZCBzbyB0ZXN0cyBuZWVkaW5nIHRoZSBzaG9ydGVzdCBsZWdhbCBkZWxheSBjYW4gYXNrIGZvciBpdCBpbnN0ZWFkIG9mXG4gKiBoYXJkY29kaW5nIGEgbnVtYmVyIHRoaXMgZmxvb3Igd291bGQgc2lsZW50bHkgY2xhbXAgdXAuXG4gKi9cbmV4cG9ydCBjb25zdCBNSU5fREVGRVJSRURfQ0hFQ0tfREVMQVlfTVMgPSAxMDtcblxuLyoqXG4gKiBFZmZlY3RpdmUgZGVmZXJyZWQtY2hlY2sgZGVsYXkuIE92ZXJyaWRlOiBgV09SS0ZMT1dfREVGRVJSRURfQ0hFQ0tfREVMQVlfTVNgLlxuICpcbiAqIFVubGlrZSB0aGUgb3RoZXIgdGltaW5nIGtub2JzIHRoaXMgaXMgbm90IGEgcG9sbGluZyBpbnRlcnZhbCBidXQgYVxuICogZGV0ZXJtaW5pc20gc2FmZXR5IG1hcmdpbjogZmlyaW5nIHRoZSB1bmNvbnN1bWVkLWV2ZW50IGNoZWNrIGJlZm9yZSB0aGVcbiAqIGNyb3NzLVZNIHN1YnNjcmliZSgpIGNoYWluIGhhcyBsYW5kZWQgcmVqZWN0cyBhIGhlYWx0aHkgcnVuIHdpdGhcbiAqIGBSZXBsYXlEaXZlcmdlbmNlRXJyb3JgLlxuICovXG5jb25zdCBnZXREZWZlcnJlZENoZWNrRGVsYXlNcyA9ICgpOiBudW1iZXIgPT5cbiAgZW52TnVtYmVyKCdXT1JLRkxPV19ERUZFUlJFRF9DSEVDS19ERUxBWV9NUycsIERFRkVSUkVEX0NIRUNLX0RFTEFZX01TLCB7XG4gICAgaW50ZWdlcjogdHJ1ZSxcbiAgICBtaW46IE1JTl9ERUZFUlJFRF9DSEVDS19ERUxBWV9NUyxcbiAgfSk7XG5cbi8qKlxuICogRXZlbnQgdHlwZXMgdGhlIG9yZGVyZWQgd2FsayBtYXkgc3RlcCBvdmVyIGFuZCBkZWxpdmVyIGxhdGVyLlxuICpcbiAqIE1lbWJlcnNoaXAgaXMgbm90IGFib3V0IHdobyB3cm90ZSB0aGUgZXZlbnQuIEl0IGlzIGFib3V0IHdoZXRoZXIgdGhlIGV2ZW50XG4gKiBjYW4gcmVhY2ggdGhlIGhlYWQgb2YgdGhlIHdhbGsgd2l0aCBub3RoaW5nIHJlZ2lzdGVyZWQgdG8gY29uc3VtZSBpdCwgd2hpY2hcbiAqIGlzIHRoZSBvbmx5IHNpdHVhdGlvbiBwYXJraW5nIGV4aXN0cyBmb3IuXG4gKlxuICogTW9zdCB0eXBlcyBjYW5ub3QuIFRoZXkgYXJlIHJlcGxheS1vcmlnaW46IGEgcmVwbGF5IGVtaXRzIHRoZW0sIGluIHRoZSBvcmRlclxuICogaXRzIGNvZGUgcmVhY2hlcyB0aGVtLCBzbyB0aGVpciBwb3NpdGlvbiBpbiB0aGUgbG9nIGlzIHRoZSByZWNvcmQgb2Ygd2hhdFxuICogdGhhdCByZXBsYXkgZGVjaWRlZC4gUmVhY2hpbmcgb25lIG9mIHRob3NlIG91dCBvZiBvcmRlciBtZWFucyB0aGlzIHJlcGxheVxuICogZGVjaWRlZCBkaWZmZXJlbnRseSB0aGFuIHRoZSBsb2cgaG9sZHMsIHdoaWNoIGlzIGRpdmVyZ2VuY2UgYW5kIG5vdGhpbmcgZWxzZS5cbiAqXG4gKiBTdGVwIGxpZmVjeWNsZSBldmVudHMgYXJlIG5vdCByZXBsYXktb3JpZ2luLCBhbmQgYXJlIHN0aWxsIGFic2VudCwgYmVjYXVzZVxuICogdGhleSBhbHdheXMgaGF2ZSBhIGNsYWltYW50LiBgc3RlcCgpYCBzdWJzY3JpYmVzIGl0cyBjb25zdW1lciBiZWZvcmUgdGhlXG4gKiBzdGVwJ3MgZmlyc3QgZXZlbnQgY2FuIGV4aXN0OyBgc3RlcF9jcmVhdGVkYCBpcyBvcmRlcmVkLCBzbyB0aGUgd2FsayBjYW5ub3RcbiAqIHBhc3MgaXQgdW5sZXNzIGEgY29uc3VtZXIgdGFrZXMgaXQ7IGFuZCB0aGF0IGNvbnN1bWVyIHN0YXlzIHN1YnNjcmliZWQgdW50aWxcbiAqIGBzdGVwX2NvbXBsZXRlZGAgb3IgYHN0ZXBfZmFpbGVkYCwgYWZ0ZXIgd2hpY2ggdGhlIFdvcmxkIHJlZnVzZXMgYW55IGZ1cnRoZXJcbiAqIHdyaXRlIGZvciB0aGF0IHN0ZXAuIFRoZXJlIGlzIG5vIHdpbmRvdyBpbiB3aGljaCBhIHJlcGxheSBrbm93cyBhYm91dCBhIHN0ZXBcbiAqIGFuZCBoYXMgbm90aGluZyByZWdpc3RlcmVkIHRvIGNvbnN1bWUgaXRzIGV2ZW50cywgc28gcGFya2luZyB0aGVtIHdvdWxkIG9ubHlcbiAqIGRlZmVyIHJlcG9ydHMgb2Ygd2hhdCBpcyBkaXZlcmdlbmNlIGVpdGhlciB3YXkuIFRoZSBzYW1lIGhvbGRzIGZvclxuICogYHdhaXRfY3JlYXRlZGAgYW5kIGl0cyBjb25zdW1lci4gYHdhaXRfY29tcGxldGVkYCBpcyBsaXN0ZWQgYW55d2F5OiBhIHNsZWVwXG4gKiBjYW4gYWxzbyBiZSBjb21wbGV0ZWQgb3V0IG9mIGJhbmQsIGJ5IHRoZSBBUEkgdGhhdCBmb3JjZS1jb21wbGV0ZXMgcGVuZGluZ1xuICogd2FpdHMsIGFuZCB0b2xlcmF0aW5nIGEgc3RyYXkgb25lIGlzIHRoZSBjaGVhcGVyIGRpcmVjdGlvbiB0byBiZSB3cm9uZyBpbi5cbiAqXG4gKiBBbiBhbGxvd2xpc3QgcmF0aGVyIHRoYW4gdGhlIGNvbXBsZW1lbnQgb2YgdGhlIG9yZGVyZWQgc2V0LCBzbyBhIHR5cGUgdGhpc1xuICogZmlsZSBoYXMgbm90IGJlZW4gdGF1Z2h0IGFib3V0IGtlZXBzIHRoZSBzdHJpY3Qgb2xkIGJlaGF2aW91ci5cbiAqXG4gKiBgaG9va19kaXNwb3NlZGAgaXMgZGVsaWJlcmF0ZWx5IGFic2VudCBkZXNwaXRlIGJlaW5nIGFib3V0IGEgaG9vazogaXQgaXNcbiAqIHdyaXR0ZW4gd2hlbiB0aGUgd29ya2Zsb3cncyBvd24gYHVzaW5nYCBzY29wZSBleGl0cywgc28gaXQgaXMgcmVwbGF5LW9yaWdpbi5cbiAqXG4gKiBgYXR0cl9zZXRgIGlzIGxpc3RlZCBieSB0eXBlIGV2ZW4gdGhvdWdoIGEgZ2l2ZW4gaW5zdGFuY2Ugb2YgaXQgbWF5IGJlXG4gKiByZXBsYXktb3JpZ2luLCBzaW5jZSBpdCBpcyByZXBsYXktb3JpZ2luIHdoZW4gaXRzIHdyaXRlciBpcyB0aGUgd29ya2Zsb3cuXG4gKiBTcGxpdHRpbmcgdGhhdCBvdXQgcGVyIGV2ZW50IHdhcyBjb25zaWRlcmVkIGFuZCByZWplY3RlZC4gQSByZXBsYXkgdGhhdFxuICogcmVhY2hlcyBvbmUgb2YgaXRzIG93biB3cml0ZXMgb3V0IG9mIHBvc2l0aW9uIGhhcyBkaXZlcmdlZCwgYnV0IGEgcmVwbGF5IHRoYXRcbiAqIHJlYWNoZXMgYW4gZXZlbnQgaXQgZGlkIE5PVCB3cml0ZSwgc2l0dGluZyB3aGVyZSBpdHMgb3duIHdyaXRlIHdvdWxkIGdvLCBoYXNcbiAqIG5vdDogdGhlIHdyaXRlciBmaWVsZCBzYXlzIHdobyB3cm90ZSB0aGUgZXZlbnQsIGFuZCBub3Qgd2hldGhlciB0aGlzIHJlcGxheVxuICogaXMgdGhlIHNhbWUgb25lLiBHdWVzc2luZyB3cm9uZyBpbiB0aGF0IGRpcmVjdGlvbiBmYWlscyBoZWFsdGh5IHJ1bnMsIHdoaWNoXG4gKiBpcyB0aGUgZmFpbHVyZSB0aGlzIGZpbGUgZXhpc3RzIHRvIHN0b3AsIHNvIHRoZSB3aG9sZSB0eXBlIGlzIHRvbGVyYXRlZC4gVGhlXG4gKiBjb3N0IGlzIHRoYXQgYSBkaXZlcmdlbmNlIGludm9sdmluZyBgYXR0cl9zZXRgIHN1cmZhY2VzIGF0IHRoZSBlbmQgb2YgdGhlXG4gKiByZXBsYXksIHRocm91Z2ggYHN0cmFuZGVkRXZlbnRgLCByYXRoZXIgdGhhbiBhdCB0aGUgb2ZmZW5kaW5nIGV2ZW50LlxuICovXG5jb25zdCBQQVJLQUJMRV9FVkVOVF9UWVBFUzogUmVhZG9ubHlTZXQ8RXZlbnRbJ2V2ZW50VHlwZSddPiA9IG5ldyBTZXQoW1xuICAnaG9va19yZWNlaXZlZCcsXG4gICdob29rX2NvbmZsaWN0JyxcbiAgJ3dhaXRfY29tcGxldGVkJyxcbiAgJ2F0dHJfc2V0JyxcbiAgJ3J1bl9jYW5jZWxsZWQnLFxuXSk7XG5cbi8qKlxuICogUGFya2FibGUgdHlwZXMgdGhhdCBjYW4gb25seSBldmVyIHJlc29sdmUgdGhlaXIgY29ycmVsYXRpb24gaWQgb25jZS5cbiAqXG4gKiBBIHNlY29uZCBvbmUgZm9yIHRoZSBzYW1lIGlkIGlzIG5vdCBhIGRlbGl2ZXJ5IHRoaXMgcmVwbGF5IGhhcyBub3QgcmVhY2hlZFxuICogeWV0OiBpdCBpcyBhIHJlc29sdXRpb24gZm9yIHNvbWV0aGluZyBhbHJlYWR5IHJlc29sdmVkLCB3aGljaCBubyBjb25zdW1lclxuICogdGhpcyByZXBsYXkgb3IgYW55IGxhdGVyIG9uZSByZWdpc3RlcnMgY2FuIGV2ZXIgY2xhaW0uIGBob29rX3JlY2VpdmVkYCBpc1xuICogYWJzZW50IGJlY2F1c2UgYSBob29rIGxlZ2l0aW1hdGVseSBmaXJlcyBtYW55IHRpbWVzIHVuZGVyIG9uZSBpZC5cbiAqXG4gKiBNdXN0IHN0YXkgYSBzdWJzZXQgb2Yge0BsaW5rIFBBUktBQkxFX0VWRU5UX1RZUEVTfToge0BsaW5rIHBhcmt9IGlzIHRoZSBvbmx5XG4gKiByZWFkZXIgb2Ygd2hhdCB0aGlzIHJlY29yZHMsIGFuZCBpdCByZWplY3RzIGEgbm9uLXBhcmthYmxlIHR5cGUgYmVmb3JlIGl0XG4gKiBsb29rcywgc28gYW4gZW50cnkgb3V0c2lkZSB0aGF0IHNldCBpcyBkZWFkIHdlaWdodCBvbiBhIGhvdCBwYXRoLlxuICovXG5jb25zdCBPTkVfU0hPVF9FVkVOVF9UWVBFUzogUmVhZG9ubHlTZXQ8RXZlbnRbJ2V2ZW50VHlwZSddPiA9IG5ldyBTZXQoW1xuICAnd2FpdF9jb21wbGV0ZWQnLFxuXSk7XG5cbi8qKiBJZGVudGlmaWVzIHRoZSB0aGluZyBhIG9uZS1zaG90IHJlc29sdXRpb24gZXZlbnQgcmVzb2x2ZXMuICovXG5mdW5jdGlvbiByZXNvbHV0aW9uS2V5KGV2ZW50VHlwZTogc3RyaW5nLCBjb3JyZWxhdGlvbklkOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYCR7ZXZlbnRUeXBlfToke2NvcnJlbGF0aW9uSWR9YDtcbn1cblxuLyoqXG4gKiBUeXBlcyB0aGF0IGVuZCBhIHJ1bi4gT25jZSBvbmUgaXMgaW4gdGhlIGxvZywgbm8gY29uc3VtZXIgd2lsbCBldmVyIGJlXG4gKiByZWdpc3RlcmVkIGFnYWluLCBzbyBhIHBhcmtlZCBldmVudCBzdGlsbCBwYXJrZWQgaGVyZSB3aWxsIG5ldmVyIGJlIGNsYWltZWQuXG4gKi9cbmNvbnN0IFRFUk1JTkFMX0VWRU5UX1RZUEVTOiBSZWFkb25seVNldDxFdmVudFsnZXZlbnRUeXBlJ10+ID0gbmV3IFNldChbXG4gICdydW5fY29tcGxldGVkJyxcbiAgJ3J1bl9mYWlsZWQnLFxuICAncnVuX2NhbmNlbGxlZCcsXG5dKTtcblxuZXhwb3J0IGVudW0gRXZlbnRDb25zdW1lclJlc3VsdCB7XG4gIC8qKlxuICAgKiBDYWxsYmFjayBjb25zdW1lZCB0aGUgZXZlbnQsIGJ1dCBzaG91bGQgbm90IGJlIHJlbW92ZWQgZnJvbSB0aGUgY2FsbGJhY2tzIGxpc3RcbiAgICovXG4gIENvbnN1bWVkLFxuICAvKipcbiAgICogQ2FsbGJhY2sgZGlkIG5vdCBjb25zdW1lIHRoZSBldmVudCwgc28gaXQgc2hvdWxkIGJlIHBhc3NlZCB0byB0aGUgbmV4dCBjYWxsYmFja1xuICAgKi9cbiAgTm90Q29uc3VtZWQsXG4gIC8qKlxuICAgKiBDYWxsYmFjayBjb25zdW1lZCB0aGUgZXZlbnQsIGFuZCBzaG91bGQgYmUgcmVtb3ZlZCBmcm9tIHRoZSBjYWxsYmFja3MgbGlzdFxuICAgKi9cbiAgRmluaXNoZWQsXG59XG5cbnR5cGUgRXZlbnRDb25zdW1lckNhbGxiYWNrID0gKGV2ZW50OiBFdmVudCB8IG51bGwpID0+IEV2ZW50Q29uc3VtZXJSZXN1bHQ7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXZlbnRzQ29uc3VtZXJPcHRpb25zIHtcbiAgLyoqXG4gICAqIENhbGxiYWNrIGludm9rZWQgYWZ0ZXIgYW4gZXZlbnQgaGFzIGJlZW4gY29uc3VtZWQuIENvbnN1bWVycyBzdWNoIGFzIHRoZVxuICAgKiBkZXRlcm1pbmlzdGljIHdvcmtmbG93IGNsb2NrIG11c3Qgbm90IG9ic2VydmUgZXZlbnRzIHRoYXQgYXJlIG1lcmVseVxuICAgKiBpbnNwZWN0ZWQgd2hpbGUgd2FpdGluZyBmb3IgdXNlciBjb2RlIHRvIHN1YnNjcmliZSB0byB0aGUgbmV4dCBvcGVyYXRpb24uXG4gICAqL1xuICBvbkNvbnN1bWVkRXZlbnQ/OiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkO1xuICAvKipcbiAgICogQ2FsbGJhY2sgaW52b2tlZCB3aGVuIGEgbm9uLW51bGwgZXZlbnQgY2Fubm90IGJlIGNvbnN1bWVkIGJ5IGFueSByZWdpc3RlcmVkXG4gICAqIGNhbGxiYWNrLCBpbmRpY2F0aW5nIGFuIG9ycGhhbmVkIG9yIGludmFsaWQgZXZlbnQgaW4gdGhlIGV2ZW50IGxvZy4gVGhlXG4gICAqIGNoZWNrIGlzIGRlZmVycmVkIHVudGlsIGFmdGVyIHRoZSBwcm9taXNlIHF1ZXVlIGhhcyBkcmFpbmVkLCBlbnN1cmluZyB0aGF0XG4gICAqIGFueSBwZW5kaW5nIGFzeW5jIHdvcmsgKGUuZy4sIGRlc2VyaWFsaXphdGlvbi9kZWNyeXB0aW9uKSBjb21wbGV0ZXMgYW5kXG4gICAqIGRvd25zdHJlYW0gc3Vic2NyaWJlKCkgY2FsbHMgaGF2ZSBhIGNoYW5jZSB0byBjYW5jZWwgdGhlIGNoZWNrIGZpcnN0LlxuICAgKi9cbiAgb25VbmNvbnN1bWVkRXZlbnQ6IChldmVudDogRXZlbnQpID0+IHZvaWQ7XG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHByb21pc2UgcXVldWUuIFRoZSB1bmNvbnN1bWVkIGV2ZW50IGNoZWNrIGlzIGNoYWluZWRcbiAgICogb250byB0aGlzIHF1ZXVlIHNvIGl0IG9ubHkgZmlyZXMgYWZ0ZXIgYWxsIHBlbmRpbmcgYXN5bmMgd29yayAoZS5nLixcbiAgICogZGVzZXJpYWxpemF0aW9uKSBoYXMgY29tcGxldGVkLiBUaGlzIHByZXZlbnRzIGZhbHNlIHBvc2l0aXZlcyB3aGVuIGFzeW5jXG4gICAqIGRlc2VyaWFsaXphdGlvbiBkZWxheXMgdGhlIHJlc29sdmUoKSB0aGF0IHRyaWdnZXJzIHRoZSBuZXh0IHN1YnNjcmliZSgpLlxuICAgKi9cbiAgZ2V0UHJvbWlzZVF1ZXVlOiAoKSA9PiBQcm9taXNlPHZvaWQ+O1xuICAvKipcbiAgICogV2hldGhlciBubyBkYXRhIGRlbGl2ZXJ5IGlzIGluIGZsaWdodCAoYGlzRGVsaXZlcnlJZGxlYCBpbiBwcml2YXRlLnRzKS5cbiAgICogVGhlIHVuY29uc3VtZWQtZXZlbnQgY2hlY2sgd2FpdHMgZm9yIHRoaXMgYmVmb3JlIGl0IGZpcmVzOiBhIGRlbGl2ZXJ5IGluXG4gICAqIGZsaWdodCBtZWFucyB0aGUgd29ya2Zsb3cgVk0gaXMgbWlkLXJlYWN0aW9uLCBhbmQgYW4gZXZlbnQgaXQgaGFzIG5vdFxuICAgKiBjbGFpbWVkIHlldCBpcyBhbiBldmVudCBpdCBoYXMgbm90IHJlYWNoZWQgeWV0LlxuICAgKlxuICAgKiBSZXF1aXJlZCByYXRoZXIgdGhhbiBkZWZhdWx0aW5nIHRvIGFsd2F5cy1pZGxlOiBhbHdheXMtaWRsZSBpcyBleGFjdGx5IHRoZVxuICAgKiBwcmUtZ2F0ZSBiZWhhdmlvdXIsIHNvIGEgZGVmYXVsdGVkIG9wdGlvbiB3b3VsZCBsZXQgYSBjb25zdHJ1Y3Rpb24gc2l0ZSBvcHRcbiAgICogYSB3aG9sZSByZXBsYXkgcGF0aCBiYWNrIG91dCB3aXRob3V0IHNheWluZyBzby4gVGVzdHMgdGhhdCBkcml2ZSBhIGNvbnN1bWVyXG4gICAqIHdpdGggbm8gb3JjaGVzdHJhdG9yIGNvbnRleHQgcGFzcyBgKCkgPT4gdHJ1ZWAgdG8ga2VlcCB0aGUgcHJlLWV4aXN0aW5nXG4gICAqIHRpbWluZywgYW5kIHNheSBzbyBhdCB0aGUgY2FsbCBzaXRlLlxuICAgKi9cbiAgaXNEZWxpdmVyeUlkbGU6ICgpID0+IGJvb2xlYW47XG59XG5cbmV4cG9ydCBjbGFzcyBFdmVudHNDb25zdW1lciB7XG4gIGV2ZW50SW5kZXg6IG51bWJlcjtcbiAgcmVhZG9ubHkgZXZlbnRzOiBFdmVudFtdO1xuICByZWFkb25seSBjYWxsYmFja3M6IEV2ZW50Q29uc3VtZXJDYWxsYmFja1tdID0gW107XG4gIC8qKlxuICAgKiBFdmVudHMgdGhlIG9yZGVyZWQgd2FsayBzdGVwcGVkIG92ZXIgYmVjYXVzZSBub2JvZHkgY2xhaW1lZCB0aGVtIGFuZCB0aGVpclxuICAgKiB0eXBlIGNhcnJpZXMgbm8gb3JkZXJpbmcgY2xhaW0uIEVhY2gga2VlcHMgdGhlIGluZGV4IGl0IGhlbGQgaW4gdGhlIGxvZzpcbiAgICogY29uc3VtZXJzIHJlYWQge0BsaW5rIGV2ZW50SW5kZXh9IGF0IGNvbnN1bXB0aW9uIHRpbWUgdG8gb3JkZXIgdGhlaXJcbiAgICogZGVsaXZlcnkgYWdhaW5zdCB0aGUgcmVzdCBvZiB0aGUgbG9nLCBhbmQgYSBsYXRlIGRlbGl2ZXJ5IG11c3Qgc3RpbGwgbWFrZVxuICAgKiB0aGUgY2xhaW0gaXRzIHBvc2l0aW9uIGdhdmUgaXQuXG4gICAqXG4gICAqIEhlbGQgaW4gbG9nIG9yZGVyLCBkcmFpbmVkIGluIGxvZyBvcmRlciwgYW5kIGRyYWluZWQgYmVmb3JlIGV2ZXJ5IG9mZmVyIHNvXG4gICAqIGEgY29uc3VtZXIgcmVnaXN0ZXJlZCBhZnRlciB0aGUgd2FsayBwYXNzZWQgdGhlIGV2ZW50IHN0aWxsIHJlY2VpdmVzIGl0LlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBwYXJrZWQ6IHsgZXZlbnQ6IEV2ZW50OyBpbmRleDogbnVtYmVyIH1bXSA9IFtdO1xuICAvKipcbiAgICogQ29ycmVsYXRpb24gaWRzIG9mIHRoZSB7QGxpbmsgT05FX1NIT1RfRVZFTlRfVFlQRVN9IGV2ZW50cyBjb25zdW1lZCBzb1xuICAgKiBmYXIsIHNvIGEgc2Vjb25kIHJlc29sdXRpb24gZm9yIG9uZSBvZiB0aGVtIGlzIHJlY29nbml6ZWQgYXMgdW5jbGFpbWFibGVcbiAgICogcmF0aGVyIHRoYW4gcGFya2VkIGZvciBhIGNvbnN1bWVyIHRoYXQgY2Fubm90IGV4aXN0LlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSByZXNvbHZlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBwcml2YXRlIG9uQ29uc3VtZWRFdmVudD86IChldmVudDogRXZlbnQpID0+IHZvaWQ7XG4gIHByaXZhdGUgb25VbmNvbnN1bWVkRXZlbnQ6IChldmVudDogRXZlbnQpID0+IHZvaWQ7XG4gIHByaXZhdGUgZ2V0UHJvbWlzZVF1ZXVlOiAoKSA9PiBQcm9taXNlPHZvaWQ+O1xuICBwcml2YXRlIGlzRGVsaXZlcnlJZGxlOiAoKSA9PiBib29sZWFuO1xuICBwcml2YXRlIHBlbmRpbmdVbmNvbnN1bWVkQ2hlY2s6IFByb21pc2U8dm9pZD4gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBwZW5kaW5nVW5jb25zdW1lZFRpbWVvdXQ6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgdW5jb25zdW1lZENoZWNrVmVyc2lvbiA9IDA7XG5cbiAgY29uc3RydWN0b3IoZXZlbnRzOiBFdmVudFtdLCBvcHRpb25zOiBFdmVudHNDb25zdW1lck9wdGlvbnMpIHtcbiAgICAvLyBPd24gY29weTogdGhlIHJ1bnRpbWUgbXV0YXRlcyBpdHMgZXZlbnQgYXJyYXkgaW4gcGxhY2UsIGFuZCBhIHJldGFpbmVkXG4gICAgLy8gc2Vzc2lvbiBtdXN0IG9ubHkgb2JzZXJ2ZSBuZXcgZXZlbnRzIHRocm91Z2ggYXBwZW5kKCkgc28gcmVzdW1lKCknc1xuICAgIC8vIHN0cmljdC1leHRlbnNpb24gY2hlY2sgc3RheXMgbWVhbmluZ2Z1bC5cbiAgICB0aGlzLmV2ZW50cyA9IFsuLi5ldmVudHNdO1xuICAgIHRoaXMuZXZlbnRJbmRleCA9IDA7XG4gICAgdGhpcy5vbkNvbnN1bWVkRXZlbnQgPSBvcHRpb25zLm9uQ29uc3VtZWRFdmVudDtcbiAgICB0aGlzLm9uVW5jb25zdW1lZEV2ZW50ID0gb3B0aW9ucy5vblVuY29uc3VtZWRFdmVudDtcbiAgICB0aGlzLmdldFByb21pc2VRdWV1ZSA9IG9wdGlvbnMuZ2V0UHJvbWlzZVF1ZXVlO1xuICAgIHRoaXMuaXNEZWxpdmVyeUlkbGUgPSBvcHRpb25zLmlzRGVsaXZlcnlJZGxlO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBvbGRlc3QgZXZlbnQgdGhlIHdhbGsgc3RlcHBlZCBvdmVyIHRoYXQgbm8gY29uc3VtZXIgaGFzIGNsYWltZWQgeWV0LFxuICAgKiBpZiBhbnkuIFBhcmtpbmcgaXMgYSBiZXQgdGhhdCBhIGNvbnN1bWVyIHdpbGwgYmUgcmVnaXN0ZXJlZCBsYXRlciwgc28gYXRcbiAgICogYW55IHBvaW50IHdoZXJlIG5vIGNvbnN1bWVyIGV2ZXIgd2lsbCBiZSBhZ2FpbiDigJQgdGhlIHJlcGxheSBmaW5pc2hpbmcgaXNcbiAgICogdGhlIGRlZmluaXRpdmUgb25lIOKAlCB0aGlzIGFuc3dlcnMgd2hpY2ggZXZlbnQgdGhlIGJldCBsb3N0IG9uLlxuICAgKi9cbiAgZ2V0IHN0cmFuZGVkRXZlbnQoKTogRXZlbnQgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnBhcmtlZFswXT8uZXZlbnQ7XG4gIH1cblxuICAvKipcbiAgICogV2hhdCB0aGUgd2FsayBpcyBzdGlsbCBob2xkaW5nLCBvciBgdW5kZWZpbmVkYCB3aGVuIGl0IGhvbGRzIG5vdGhpbmcuXG4gICAqXG4gICAqIFJlYWQgYXQgZXZlcnkgcG9pbnQgYSByZXBsYXkgc3RvcHMsIGluY2x1ZGluZyB0aGUgc3VzcGVuc2lvbnMgdGhhdCBhcmUgbm90XG4gICAqIHNldHRsaW5nIHBvaW50cywgc28gdGhlIGhlbGQgc3RhdGUgcmVhY2hlcyB0ZWxlbWV0cnkuIEEgcmVwbGF5IGNhbm5vdCB0ZWxsXG4gICAqIGEgZGVsaXZlcnkgYXdhaXRpbmcgYSBsYXRlciBjb25zdW1lciBmcm9tIG9uZSBubyBjb25zdW1lciB3aWxsIGV2ZXJcbiAgICogcmVnaXN0ZXIsIHNvIGl0IHJlcG9ydHMgcmF0aGVyIHRoYW4gZGVjaWRlczogdGhlIHNhbWUgYGV2ZW50SWRgIHJlcG9ydGVkIG9uXG4gICAqIHN1c3BlbnNpb24gYWZ0ZXIgc3VzcGVuc2lvbiBvZiBvbmUgcnVuIGlzIHRoZSBzaGFwZSB0aGF0IHNheXMgdGhlIGJldFxuICAgKiBwYXJraW5nIG1hZGUgaXMgbm90IGdvaW5nIHRvIHBheSBvZmYsIGFuZCB0aGF0IHNoYXBlIGlzIG9ubHkgdmlzaWJsZSBhY3Jvc3NcbiAgICogcmVwbGF5cy5cbiAgICovXG4gIGdldCBwYXJrZWRTdW1tYXJ5KCk6XG4gICAgfCB7IGNvdW50OiBudW1iZXI7IGV2ZW50SWQ6IHN0cmluZzsgZXZlbnRUeXBlOiBFdmVudFsnZXZlbnRUeXBlJ10gfVxuICAgIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBvbGRlc3QgPSB0aGlzLnBhcmtlZFswXT8uZXZlbnQ7XG4gICAgaWYgKCFvbGRlc3QpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBjb3VudDogdGhpcy5wYXJrZWQubGVuZ3RoLFxuICAgICAgZXZlbnRJZDogb2xkZXN0LmV2ZW50SWQsXG4gICAgICBldmVudFR5cGU6IG9sZGVzdC5ldmVudFR5cGUsXG4gICAgfTtcbiAgfVxuXG4gIGFwcGVuZChldmVudHM6IEV2ZW50W10pOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIGV2ZW50cykgdGhpcy5ldmVudHMucHVzaChldmVudCk7XG4gICAgcHJvY2Vzcy5uZXh0VGljayh0aGlzLmNvbnN1bWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBhZnRlciBhbiBldmVudCBoYXMgYmVlbiBjb25zdW1lZFxuICAgKiBieSBhIGRpZmZlcmVudCBjYWxsYmFjay4gVGhlIGNhbGxiYWNrIGNhbiByZXR1cm46XG4gICAqICAtIGBFdmVudENvbnN1bWVyUmVzdWx0LkNvbnN1bWVkYCB0aGUgZXZlbnQgaXMgY29uc2lkZXJlZCBjb25zdW1lZCBhbmQgd2lsbCBub3QgYmUgcGFzc2VkIHRvIGFueSBvdGhlciBjYWxsYmFjaywgYnV0IHRoZSBjYWxsYmFjayB3aWxsIHJlbWFpbiBpbiB0aGUgY2FsbGJhY2tzIGxpc3RcbiAgICogIC0gYEV2ZW50Q29uc3VtZXJSZXN1bHQuTm90Q29uc3VtZWRgIHRoZSBldmVudCBpcyBwYXNzZWQgdG8gdGhlIG5leHQgY2FsbGJhY2tcbiAgICogIC0gYEV2ZW50Q29uc3VtZXJSZXN1bHQuRmluaXNoZWRgIHRoZSBldmVudCBpcyBjb25zaWRlcmVkIGNvbnN1bWVkIGFuZCB0aGUgY2FsbGJhY2sgaXMgcmVtb3ZlZCBmcm9tIHRoZSBjYWxsYmFja3MgbGlzdFxuICAgKlxuICAgKiBAcGFyYW0gZm4gLSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gdG8gcmVnaXN0ZXIuXG4gICAqL1xuICBzdWJzY3JpYmUoZm46IEV2ZW50Q29uc3VtZXJDYWxsYmFjaykge1xuICAgIHRoaXMuY2FsbGJhY2tzLnB1c2goZm4pO1xuICAgIC8vIENhbmNlbCBhbnkgcGVuZGluZyB1bmNvbnN1bWVkIGNoZWNrIHNpbmNlIGEgbmV3IGNhbGxiYWNrIG1heSBjb25zdW1lIHRoZSBldmVudC5cbiAgICAvLyBJbmNyZW1lbnRpbmcgdGhlIHZlcnNpb24gY2F1c2VzIGFueSBpbi1mbGlnaHQgcHJvbWlzZSBjaGFpbiBjaGVjayB0byBuby1vcC5cbiAgICAvLyBBbHNvIGNsZWFyIHRoZSBwZW5kaW5nIHNldFRpbWVvdXQgaWYgaXQgaGFzbid0IGZpcmVkIHlldC5cbiAgICBpZiAodGhpcy5wZW5kaW5nVW5jb25zdW1lZENoZWNrICE9PSBudWxsKSB7XG4gICAgICB0aGlzLnVuY29uc3VtZWRDaGVja1ZlcnNpb24rKztcbiAgICAgIHRoaXMucGVuZGluZ1VuY29uc3VtZWRDaGVjayA9IG51bGw7XG4gICAgICBpZiAodGhpcy5wZW5kaW5nVW5jb25zdW1lZFRpbWVvdXQgIT09IG51bGwpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucGVuZGluZ1VuY29uc3VtZWRUaW1lb3V0KTtcbiAgICAgICAgdGhpcy5wZW5kaW5nVW5jb25zdW1lZFRpbWVvdXQgPSBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgICBwcm9jZXNzLm5leHRUaWNrKHRoaXMuY29uc3VtZSk7XG4gIH1cblxuICBwcml2YXRlIG5vdGlmeUNvbnN1bWVkRXZlbnQoZXZlbnQ6IEV2ZW50KSB7XG4gICAgaWYgKCF0aGlzLm9uQ29uc3VtZWRFdmVudCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgdGhpcy5vbkNvbnN1bWVkRXZlbnQoZXZlbnQpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBldmVudHNMb2dnZXIuZXJyb3IoJ29uQ29uc3VtZWRFdmVudCBjYWxsYmFjayB0aHJldyBhbiBlcnJvcicsIHtcbiAgICAgICAgZXJyb3IsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNvbnN1bWUgPSAoKSA9PiB7XG4gICAgLy8gRHJhaW4gY29uc2VjdXRpdmVseSBjb25zdW1hYmxlIGV2ZW50cyBzeW5jaHJvbm91c2x5IHdpdGhpbiBhIHNpbmdsZVxuICAgIC8vIHBhc3MgaW5zdGVhZCBvZiBwYXlpbmcgb25lIGBwcm9jZXNzLm5leHRUaWNrYCBwZXIgY29uc3VtZWQgZXZlbnQuXG4gICAgLy9cbiAgICAvLyBXaHkgdGhpcyBpcyBzYWZlOiBhIGNhbGxiYWNrIG9ubHkgY29uc3VtZXMgYW4gZXZlbnQgdXNpbmcgYSBjb25zdW1lclxuICAgIC8vIHRoYXQgaXMgQUxSRUFEWSByZWdpc3RlcmVkIChlLmcuIGEgbG9uZy1saXZlZCBzdGVwIGNvbnN1bWVyIHdhbGtpbmdcbiAgICAvLyBgc3RlcF9jcmVhdGVkYCDihpIgYHN0ZXBfc3RhcnRlZGAg4oaSIGBzdGVwX2NvbXBsZXRlZGAsIG9yIHRoZSBzdHJ1Y3R1cmFsXG4gICAgLy8gbGlmZWN5Y2xlIGNvbnN1bWVyKS4gTmV3IGNvbnN1bWVycyBhcmUgb25seSBldmVyIHJlZ2lzdGVyZWQgYnkgd29ya2Zsb3dcbiAgICAvLyBWTSBib2R5IGNvZGUgdGhhdCBydW5zIGFzeW5jaHJvbm91c2x5IG9mZiBgY3R4LnByb21pc2VRdWV1ZWAgYWZ0ZXIgYVxuICAgIC8vIGRlbGl2ZXJ5IGByZXNvbHZlKClgOyBub25lIG9mIHRoZSBjYWxsYmFja3MgaGVyZSBjYWxsIGBzdWJzY3JpYmUoKWBcbiAgICAvLyBzeW5jaHJvbm91c2x5LiBTbyB3aXRoaW4gb25lIHBhc3MgYHRoaXMuY2FsbGJhY2tzYCBpcyBtdXRhdGVkIG9ubHkgYnlcbiAgICAvLyB0aGlzIGxvb3AgKHRoZSBgRmluaXNoZWRgIHNwbGljZSksIGFuZCB0aGUgbmV4dCBldmVudCdzIGNvbnN1bWVyIGlzXG4gICAgLy8gZWl0aGVyIGFscmVhZHkgcHJlc2VudCAoYWR2YW5jZSBub3cpIG9yIG5vdCB5ZXQgcmVnaXN0ZXJlZCDigJQgaW4gd2hpY2hcbiAgICAvLyBjYXNlIG5vIGNhbGxiYWNrIGNvbnN1bWVzIHRoZSBldmVudCBhbmQgd2UgZmFsbCB0aHJvdWdoIHRvIHRoZVxuICAgIC8vIGNyb3NzLVZNLXNhZmUgZGVmZXJyZWQgdW5jb25zdW1lZC1ldmVudCBjaGVjayBiZWxvdywgZXhhY3RseSBhcyBiZWZvcmUuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIC8vIEJlZm9yZSBldmVyeSBvZmZlciwgbm90IGp1c3Qgb24gc3Vic2NyaWJlOiBhIGNhbGxiYWNrIHJlZ2lzdGVyZWQgYnlcbiAgICAgIC8vIHRoZSB3b3JrIHRoaXMgc2FtZSBwYXNzIGtpY2tlZCBvZmYgbWF5IGJlIHRoZSBvd25lciBvZiBzb21ldGhpbmdcbiAgICAgIC8vIHBhcmtlZCwgYW5kIHRoZSBwYXJrZWQgZXZlbnQncyBkZWxpdmVyeSBpcyBvcmRlcmVkIGFoZWFkIG9mIHRoZSBoZWFkXG4gICAgICAvLyBldmVudCdzIGJ5IHRoZSBpbmRleCBpdCBob2xkcy5cbiAgICAgIHRoaXMuZHJhaW5QYXJrZWQoKTtcbiAgICAgIGNvbnN0IGN1cnJlbnRFdmVudCA9IHRoaXMuZXZlbnRzW3RoaXMuZXZlbnRJbmRleF0gPz8gbnVsbDtcbiAgICAgIGNvbnN0IGNvbnN1bWVkID0gdGhpcy5vZmZlcihjdXJyZW50RXZlbnQpO1xuICAgICAgaWYgKGNvbnN1bWVkKSB7XG4gICAgICAgIHRoaXMuZXZlbnRJbmRleCsrO1xuICAgICAgfVxuICAgICAgaWYgKGN1cnJlbnRFdmVudCA9PT0gbnVsbCkge1xuICAgICAgICAvLyBFbmQgb2YgbG9nLiBDb25zdW1lcnMgcmV0dXJuIE5vdENvbnN1bWVkIGZvciB0aGUgYG51bGxgIHNlbnRpbmVsXG4gICAgICAgIC8vICh0aGUgb25lIHRoYXQgcmVjb2duaXplcyBpdCBhcyBpdHMgb3duIGJvdW5kYXJ5IHNjaGVkdWxlcyB0aGVcbiAgICAgICAgLy8gc3VzcGVuc2lvbiBhcyBhIHNpZGUgZWZmZWN0IGFuZCBzdGlsbCBkZWNsaW5lcyBpdCksIHNvIHRoZSBkcmFpblxuICAgICAgICAvLyBzdG9wcyBoZXJlIHJhdGhlciB0aGFuIHNwaW5uaW5nIHBhc3QgdGhlIGVuZC4gYGNvbnN1bWVkYCBpcyBvbmx5XG4gICAgICAgIC8vIHRydWUgZm9yIGEgY2FsbGJhY2sgdGhhdCBjbGFpbXMgdGhlIHNlbnRpbmVsIG91dHJpZ2h0LCB3aGljaCBub1xuICAgICAgICAvLyBwcm9kdWN0aW9uIGNvbnN1bWVyIGRvZXMuXG4gICAgICAgIGlmICghY29uc3VtZWQpIHtcbiAgICAgICAgICB0aGlzLmhhbmRsZUVuZE9mTG9nKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKCFjb25zdW1lZCkge1xuICAgICAgICB0aGlzLnNjaGVkdWxlVW5jb25zdW1lZENoZWNrKGN1cnJlbnRFdmVudCwgdHJ1ZSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIC8vIEEgcmVhbCBldmVudCB3YXMgY29uc3VtZWQg4oCUIGFkdmFuY2UgdG8gdGhlIG5leHQgaW4gdGhlIHNhbWUgcGFzcy5cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIE9mZmVyIGBjdXJyZW50RXZlbnRgIHRvIGVhY2ggcmVnaXN0ZXJlZCBjYWxsYmFjayBpbiB0dXJuLiBSZXR1cm5zIHRydWVcbiAgICogd2hlbiBhIGNhbGxiYWNrIGNvbnN1bWVkIGl0LiBEb2VzIG5vdCBtb3ZlIHtAbGluayBldmVudEluZGV4fTogdGhlIG9yZGVyZWRcbiAgICogd2FsayBhbmQgdGhlIHBhcmtlZCBkcmFpbiBhZHZhbmNlIGRpZmZlcmVudGx5LCBzbyBlYWNoIGRvZXMgaXRzIG93bi5cbiAgICovXG4gIHByaXZhdGUgb2ZmZXIoY3VycmVudEV2ZW50OiBFdmVudCB8IG51bGwpOiBib29sZWFuIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuY2FsbGJhY2tzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBjYWxsYmFjayA9IHRoaXMuY2FsbGJhY2tzW2ldO1xuICAgICAgbGV0IGhhbmRsZWQgPSBFdmVudENvbnN1bWVyUmVzdWx0Lk5vdENvbnN1bWVkO1xuICAgICAgdHJ5IHtcbiAgICAgICAgaGFuZGxlZCA9IGNhbGxiYWNrKGN1cnJlbnRFdmVudCk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBldmVudHNMb2dnZXIuZXJyb3IoJ0V2ZW50Q29uc3VtZXIgY2FsbGJhY2sgdGhyZXcgYW4gZXJyb3InLCB7IGVycm9yIH0pO1xuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICBoYW5kbGVkICE9PSBFdmVudENvbnN1bWVyUmVzdWx0LkNvbnN1bWVkICYmXG4gICAgICAgIGhhbmRsZWQgIT09IEV2ZW50Q29uc3VtZXJSZXN1bHQuRmluaXNoZWRcbiAgICAgICkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmIChjdXJyZW50RXZlbnQgIT09IG51bGwpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGN1cnJlbnRFdmVudC5jb3JyZWxhdGlvbklkICYmXG4gICAgICAgICAgT05FX1NIT1RfRVZFTlRfVFlQRVMuaGFzKGN1cnJlbnRFdmVudC5ldmVudFR5cGUpXG4gICAgICAgICkge1xuICAgICAgICAgIHRoaXMucmVzb2x2ZWQuYWRkKFxuICAgICAgICAgICAgcmVzb2x1dGlvbktleShjdXJyZW50RXZlbnQuZXZlbnRUeXBlLCBjdXJyZW50RXZlbnQuY29ycmVsYXRpb25JZClcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubm90aWZ5Q29uc3VtZWRFdmVudChjdXJyZW50RXZlbnQpO1xuICAgICAgfVxuICAgICAgLy8gcmVtb3ZlIHRoZSBjYWxsYmFjayBpZiBpdCBoYXMgZmluaXNoZWRcbiAgICAgIGlmIChoYW5kbGVkID09PSBFdmVudENvbnN1bWVyUmVzdWx0LkZpbmlzaGVkKSB7XG4gICAgICAgIHRoaXMuY2FsbGJhY2tzLnNwbGljZShpLCAxKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogT2ZmZXIgZXZlcnl0aGluZyBwYXJrZWQsIG9sZGVzdCBmaXJzdCwgdW50aWwgYSBwYXNzIGNsYWltcyBub3RoaW5nLlxuICAgKlxuICAgKiBFYWNoIG9mZmVyIHJ1bnMgd2l0aCB7QGxpbmsgZXZlbnRJbmRleH0gbW92ZWQgYmFjayB0byB0aGUgcG9zaXRpb24gdGhlXG4gICAqIHBhcmtlZCBldmVudCBoZWxkIGluIHRoZSBsb2csIGJlY2F1c2UgdGhhdCBpcyB0aGUgcG9zaXRpb24gaXRzIGNvbnN1bWVyXG4gICAqIHdpbGwgcmVnaXN0ZXIgYSBkZWxpdmVyeSBiYXJyaWVyIHVuZGVyLiBSZXN0b3JpbmcgdGhlIHdhbGsgcG9pbnRlclxuICAgKiBhZnRlcndhcmRzIGlzIHdoYXQga2VlcHMgdGhlIHR3byBwb2ludGVycyBmcm9tIGludGVyZmVyaW5nLlxuICAgKi9cbiAgcHJpdmF0ZSBkcmFpblBhcmtlZCgpOiB2b2lkIHtcbiAgICBsZXQgcHJvZ3Jlc3NlZCA9IHRoaXMucGFya2VkLmxlbmd0aCA+IDA7XG4gICAgd2hpbGUgKHByb2dyZXNzZWQpIHtcbiAgICAgIHByb2dyZXNzZWQgPSBmYWxzZTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5wYXJrZWQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgZW50cnkgPSB0aGlzLnBhcmtlZFtpXTtcbiAgICAgICAgY29uc3Qgd2Fsa0luZGV4ID0gdGhpcy5ldmVudEluZGV4O1xuICAgICAgICB0aGlzLmV2ZW50SW5kZXggPSBlbnRyeS5pbmRleDtcbiAgICAgICAgbGV0IGNvbnN1bWVkOiBib29sZWFuO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN1bWVkID0gdGhpcy5vZmZlcihlbnRyeS5ldmVudCk7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgdGhpcy5ldmVudEluZGV4ID0gd2Fsa0luZGV4O1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb25zdW1lZCkge1xuICAgICAgICAgIHRoaXMucGFya2VkLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAvLyBBIGBGaW5pc2hlZGAgY2FsbGJhY2sgd2FzIHNwbGljZWQgb3V0IG9mIHRoZSBsaXN0IHRoaXMgcGFzcywgc29cbiAgICAgICAgICAvLyByZXN0YXJ0IHJhdGhlciB0aGFuIGtlZXAgd2Fsa2luZyBhIG11dGF0ZWQgYXJyYXkuXG4gICAgICAgICAgcHJvZ3Jlc3NlZCA9IHRoaXMucGFya2VkLmxlbmd0aCA+IDA7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3RlcCB0aGUgb3JkZXJlZCB3YWxrIG92ZXIgYW4gZXZlbnQgbm9ib2R5IGNsYWltZWQsIGhvbGRpbmcgb24gdG8gaXQgZm9yIGFcbiAgICogbGF0ZXIgY29uc3VtZXIuIFJldHVybnMgZmFsc2Ugd2hlbiB0aGUgZXZlbnQncyB0eXBlIG1ha2VzIGl0cyBwb3NpdGlvbiBhXG4gICAqIGRlY2lzaW9uIHJlY29yZCwgd2hpY2ggaXMgdGhlIG9uZSBjYXNlIHdoZXJlIG5vYm9keSBjbGFpbWluZyBpdCBtZWFucyB0aGVcbiAgICogcmVwbGF5IGRpdmVyZ2VkLlxuICAgKi9cbiAgcHJpdmF0ZSBwYXJrKGV2ZW50OiBFdmVudCk6IGJvb2xlYW4ge1xuICAgIGlmICghUEFSS0FCTEVfRVZFTlRfVFlQRVMuaGFzKGV2ZW50LmV2ZW50VHlwZSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgZXZlbnQuY29ycmVsYXRpb25JZCAmJlxuICAgICAgdGhpcy5yZXNvbHZlZC5oYXMocmVzb2x1dGlvbktleShldmVudC5ldmVudFR5cGUsIGV2ZW50LmNvcnJlbGF0aW9uSWQpKVxuICAgICkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICB0aGlzLnBhcmtlZC5wdXNoKHsgZXZlbnQsIGluZGV4OiB0aGlzLmV2ZW50SW5kZXggfSk7XG4gICAgdGhpcy5ldmVudEluZGV4Kys7XG4gICAgZXZlbnRzTG9nZ2VyLmRlYnVnKCdQYXJrZWQgYW4gdW5jbGFpbWVkIGV2ZW50IGZvciBsYXRlciBkZWxpdmVyeScsIHtcbiAgICAgIGV2ZW50SWQ6IGV2ZW50LmV2ZW50SWQsXG4gICAgICBldmVudFR5cGU6IGV2ZW50LmV2ZW50VHlwZSxcbiAgICAgIGNvcnJlbGF0aW9uSWQ6IGV2ZW50LmNvcnJlbGF0aW9uSWQsXG4gICAgICBwYXJrZWQ6IHRoaXMucGFya2VkLmxlbmd0aCxcbiAgICB9KTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlRW5kT2ZMb2coKSB7XG4gICAgLy8gRXZlcnl0aGluZyBzdGlsbCBwYXJrZWQgaXMgd2FpdGluZyBmb3IgYSBjb25zdW1lciBzb21lIGxhdGVyIHJlcGxheSB3aWxsXG4gICAgLy8gcmVnaXN0ZXIsIHdoaWNoIGlzIHRoZSB3aG9sZSBwb2ludCBvZiBwYXJraW5nIOKAlCBleGNlcHQgb25jZSB0aGUgbG9nXG4gICAgLy8gYWxyZWFkeSBob2xkcyB0aGUgcnVuJ3MgdGVybWluYWwgZXZlbnQsIGJlY2F1c2UgdGhlbiB0aGVyZSBpcyBubyBsYXRlclxuICAgIC8vIHJlcGxheSBhbmQgbm8gY29uc3VtZXIgd2lsbCBldmVyIGNvbWUuXG4gICAgaWYgKHRoaXMucGFya2VkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBsYXN0ID0gdGhpcy5ldmVudHMuYXQoLTEpO1xuICAgIGlmICghbGFzdCB8fCAhVEVSTUlOQUxfRVZFTlRfVFlQRVMuaGFzKGxhc3QuZXZlbnRUeXBlKSkge1xuICAgICAgLy8gQSBsYXRlciByZXBsYXkgaXMgc3RpbGwgZXhwZWN0ZWQsIHNvIG5vdGhpbmcgaGVyZSBpcyBkZWNpZGFibGUgYW5kXG4gICAgICAvLyBlc2NhbGF0aW5nIHdvdWxkIGZhaWwgdGhlIGhlYWx0aHkgcnVucyBwYXJraW5nIGV4aXN0cyB0byBrZWVwIGFsaXZlLlxuICAgICAgLy8gUmVhY2hpbmcgdGhlIGVuZCBvZiB0aGUgbG9nIGhvbGRpbmcgc29tZXRoaW5nIGlzIG5vdCBieSBpdHNlbGYgYSBmYXVsdCxcbiAgICAgIC8vIHNvIHRoaXMgc3RheXMgYXQgYGRlYnVnYDsge0BsaW5rIHBhcmtlZFN1bW1hcnl9IGlzIHdoYXQgY2FycmllcyB0aGVcbiAgICAgIC8vIHN0YXRlIHRvIHRoZSBzcGFuLCB3aGVyZSBhIHJ1biB0aGF0IGtlZXBzIHN0b3BwaW5nIG9uIHRoZSBzYW1lIGhlbGRcbiAgICAgIC8vIGV2ZW50IGlzIHZpc2libGUgYW5kIGEgc2luZ2xlIHJlcGxheSdzIHZpZXcgaXMgbm90LlxuICAgICAgZXZlbnRzTG9nZ2VyLmRlYnVnKCdSZWFjaGVkIHRoZSBlbmQgb2YgdGhlIGxvZyBzdGlsbCBob2xkaW5nIGV2ZW50cycsIHtcbiAgICAgICAgZXZlbnRJZDogdGhpcy5wYXJrZWRbMF0uZXZlbnQuZXZlbnRJZCxcbiAgICAgICAgZXZlbnRUeXBlOiB0aGlzLnBhcmtlZFswXS5ldmVudC5ldmVudFR5cGUsXG4gICAgICAgIGNvcnJlbGF0aW9uSWQ6IHRoaXMucGFya2VkWzBdLmV2ZW50LmNvcnJlbGF0aW9uSWQsXG4gICAgICAgIHBhcmtlZDogdGhpcy5wYXJrZWQubGVuZ3RoLFxuICAgICAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc2NoZWR1bGVVbmNvbnN1bWVkQ2hlY2sodGhpcy5wYXJrZWRbMF0uZXZlbnQsIGZhbHNlKTtcbiAgfVxuXG4gIHByaXZhdGUgc2NoZWR1bGVVbmNvbnN1bWVkQ2hlY2soY3VycmVudEV2ZW50OiBFdmVudCwgbWF5UGFyazogYm9vbGVhbikge1xuICAgIC8vIEFsbCBjYWxsYmFja3MgcmV0dXJuZWQgTm90Q29uc3VtZWQgZm9yIHRoZSBjdXJyZW50IGV2ZW50LlxuICAgIC8vIFNjaGVkdWxlIGEgZGVmZXJyZWQgY2hlY2suIFdlIGNoYWluIG9udG8gdGhlIHByb21pc2VRdWV1ZSBzbyB0aGF0IGFueVxuICAgIC8vIHBlbmRpbmcgYXN5bmMgd29yayAoZS5nLiwgZGVzZXJpYWxpemF0aW9uL2RlY3J5cHRpb24gdGhhdCB0cmlnZ2Vyc1xuICAgIC8vIHJlc29sdmUoKSDihpIgdXNlciBjb2RlIOKGkiBzdWJzY3JpYmUoKSkgY29tcGxldGVzIGZpcnN0LiBJZiB0aGUgZXZlbnRcbiAgICAvLyBpcyBzdGlsbCB1bmNvbnN1bWVkIGFmdGVyIHRoZSBxdWV1ZSBkcmFpbnMsIGl0J3MgdHJ1bHkgb3JwaGFuZWQg4oCUIG9yLFxuICAgIC8vIHdoZW4gaXRzIHR5cGUgY2FycmllcyBubyBvcmRlcmluZyBjbGFpbSwgcGFya2VkIGZvciBhIGxhdGVyIGNvbnN1bWVyLlxuICAgIGNvbnN0IGNoZWNrVmVyc2lvbiA9ICsrdGhpcy51bmNvbnN1bWVkQ2hlY2tWZXJzaW9uO1xuICAgIHRoaXMucGVuZGluZ1VuY29uc3VtZWRDaGVjayA9IHRoaXMuZ2V0UHJvbWlzZVF1ZXVlKClcbiAgICAgIC50aGVuKFxuICAgICAgICAvLyBZaWVsZCBvbmNlIGFmdGVyIHRoZSBmaXJzdCBxdWV1ZSBkcmFpbiBzbyBwcm9taXNlIGNoYWlucyByZXN1bWVkIGJ5XG4gICAgICAgIC8vIHRoYXQgZHJhaW4gY2FuIHJ1biBhY3Jvc3MgdGhlIFZNIGJvdW5kYXJ5IGFuZCBhcHBlbmQgYW55IGZvbGxvdy11cFxuICAgICAgICAvLyBhc3luYyB3b3JrIChmb3IgZXhhbXBsZTogc3RlcF9jb21wbGV0ZWQgcmVzb2x2ZXMgLT4gZm9yLWF3YWl0IGxvb3BcbiAgICAgICAgLy8gcmVzdW1lcyAtPiB0aGUgbmV4dCBob29rIHBheWxvYWQgc3RhcnRzIGh5ZHJhdGluZykuXG4gICAgICAgICgpID0+IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDApKVxuICAgICAgKVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5nZXRQcm9taXNlUXVldWUoKSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgLy8gV2FpdCBvdXQgYW55IGRlbGl2ZXJ5IHN0aWxsIGluIGZsaWdodCBiZWZvcmUgc3RhcnRpbmcgdGhlIHRpbWVyLlxuICAgICAgICAvLyBUaGUgcXVldWUgZHJhaW5pbmcgc2F5cyB0aGUgaG9zdCBoYXMgbm8gaHlkcmF0aW9uIHdvcmsgbGVmdDsgaXRcbiAgICAgICAgLy8gZG9lcyBub3Qgc2F5IHRoZSBWTSBoYXMgZmluaXNoZWQgcmVhY3RpbmcgdG8gd2hhdCB3YXMgaHlkcmF0ZWQuXG4gICAgICAgIHRoaXMud2hlbkRlbGl2ZXJ5SWRsZShjaGVja1ZlcnNpb24sICgpID0+IHtcbiAgICAgICAgICAvLyBVc2UgYSBkZWxheWVkIHNldFRpbWVvdXQgb25jZSBkZWxpdmVyaWVzIGFyZSBpZGxlLiBUaGUgZGVsYXkgbXVzdFxuICAgICAgICAgIC8vIGJlIGxvbmcgZW5vdWdoIGZvciBwcm9taXNlIGNoYWlucyB0byBwcm9wYWdhdGUgYWNyb3NzIHRoZSBWTVxuICAgICAgICAgIC8vIGJvdW5kYXJ5IChmcm9tIHJlc29sdmUoKSBpbiB0aGUgaG9zdCBjb250ZXh0IHRocm91Z2ggdG8gdGhlXG4gICAgICAgICAgLy8gd29ya2Zsb3cgY29kZSBjYWxsaW5nIHN1YnNjcmliZSgpIGluIHRoZSBWTSBjb250ZXh0KS4gTm9kZS5qcyBkb2VzXG4gICAgICAgICAgLy8gbm90IGd1YXJhbnRlZSB0aGF0IHNldFRpbWVvdXQoMCkgZmlyZXMgYWZ0ZXIgYWxsIGNyb3NzLWNvbnRleHRcbiAgICAgICAgICAvLyBtaWNyb3Rhc2tzIHNldHRsZSwgc28gd2UgdXNlIGEgc21hbGwgYnV0IG5vbi16ZXJvIGRlbGF5LiBBbnlcbiAgICAgICAgICAvLyBzdWJzY3JpYmUoKSBjYWxsIHRoYXQgYXJyaXZlcyBkdXJpbmcgdGhpcyB3aW5kb3cgd2lsbCBjYW5jZWwgdGhlXG4gICAgICAgICAgLy8gY2hlY2sgdmlhIHZlcnNpb24gaW52YWxpZGF0aW9uICsgY2xlYXJUaW1lb3V0LlxuICAgICAgICAgIHRoaXMucGVuZGluZ1VuY29uc3VtZWRUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnBlbmRpbmdVbmNvbnN1bWVkVGltZW91dCA9IG51bGw7XG4gICAgICAgICAgICBpZiAodGhpcy51bmNvbnN1bWVkQ2hlY2tWZXJzaW9uICE9PSBjaGVja1ZlcnNpb24pIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5wZW5kaW5nVW5jb25zdW1lZENoZWNrID0gbnVsbDtcbiAgICAgICAgICAgIGlmIChtYXlQYXJrKSB7XG4gICAgICAgICAgICAgIGlmICh0aGlzLmV2ZW50c1t0aGlzLmV2ZW50SW5kZXhdICE9PSBjdXJyZW50RXZlbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBBbiBhcHBlbmQoKSBkcmFpbiBjbGFpbWVkIGl0IHdoaWxlIHRoZSBjaGVjayB3YXMgaW4gZmxpZ2h0LlxuICAgICAgICAgICAgICAgIC8vIE9ubHkgc3Vic2NyaWJlKCkgY2FuY2VscyB0aGUgY2hlY2ssIHNvIHRoaXMgaXMgcmVhY2hhYmxlLlxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAodGhpcy5wYXJrKGN1cnJlbnRFdmVudCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnN1bWUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMub25VbmNvbnN1bWVkRXZlbnQoY3VycmVudEV2ZW50KTtcbiAgICAgICAgICB9LCBnZXREZWZlcnJlZENoZWNrRGVsYXlNcygpKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW4gYGZuYCBvbmNlIG5vIGRhdGEgZGVsaXZlcnkgaXMgaW4gZmxpZ2h0LCBwb2xsaW5nIHRoZSB3YXlcbiAgICogYHNjaGVkdWxlV2hlbklkbGVgIGRvZXM6IGxldCB0aGUgcHJvbWlzZSBxdWV1ZSBkcmFpbiwgcmUtY2hlY2sgYSB0aW1lclxuICAgKiB0aWNrIGxhdGVyLCByZXBlYXQuXG4gICAqXG4gICAqIFdpdGhvdXQgdGhpcyB0aGUgY2hlY2sgaXMgYSBiZXQgdGhhdCBldmVyeSBkZWxpdmVyeSB0aGUgd2FsayBpcyBydW5uaW5nXG4gICAqIGFoZWFkIG9mIGxhbmRzIGluc2lkZSBhIGZpeGVkIHdpbmRvdy4gQ29uc3VtcHRpb24gaXMgc3luY2hyb25vdXMgd2hpbGUgdGhlXG4gICAqIHJlc29sdXRpb24gaXQgdHJpZ2dlcnMgaXMgbm90OiBhIHN0ZXAgcmVzdWx0IGh5ZHJhdGVzIGluIHRoZSBob3N0LCByZXNvbHZlc1xuICAgKiBmcm9tIGEgZGV0YWNoZWQgY29udGludWF0aW9uIGJlaGluZCBgYXdhaXRFYXJsaWVyRGVsaXZlcmllc2AsIGFuZCBvbmx5IHRoZW5cbiAgICogZG9lcyBWTSBjb2RlIHJ1biBmYXIgZW5vdWdoIHRvIHN1YnNjcmliZSB0aGUgbmV4dCBjb25zdW1lci4gUmVwbGF5aW5nIGFcbiAgICogYmF0Y2ggb2YgTiBwYXJhbGxlbCBzdGVwIHJlc3VsdHMgbGVhdmVzIE4tMSBvZiB0aGVtIG9uIHRoYXQgZGV0YWNoZWQgcGF0aFxuICAgKiB3aXRoIHRoZSBxdWV1ZSBhbHJlYWR5IGRyYWluZWQsIHNvIHRoZSB3YWxrIHNpdHMgb24gdGhlIG9yZGVyZWQgZXZlbnQgdGhlXG4gICAqIFZNIGlzIGFib3V0IHRvIGRyYXcgYW5kIHRoZSB3aW5kb3cgaXMgdGhlIG9ubHkgdGhpbmcgc3RhbmRpbmcgYmV0d2VlbiBhXG4gICAqIGhlYWx0aHkgcnVuIGFuZCBgUmVwbGF5RGl2ZXJnZW5jZUVycm9yYC5cbiAgICpcbiAgICogU2hvcnRlbmluZyB0aGUgd2luZG93IHNob3dzIHRoYXQgbWVjaGFuaXNtIGRpcmVjdGx5OiBvbiBpZGVudGljYWwgZXZlbnQgbG9nc1xuICAgKiB0aGUgbG9jYWwgcmFjZSByZXBybyBjb3JydXB0cyAzNCBvZiA0MiBydW5zIGF0IGEgMTBtcyB3aW5kb3cgYW5kIDAgb2YgMTE0IGF0XG4gICAqIHRoZSAxMDBtcyBkZWZhdWx0LiBUaGF0IG1lYXN1cmVzIGhvdyB0aGUgYmV0IGxvc2VzLCBub3QgdGhhdCB0aGUgZGVmYXVsdFxuICAgKiBsb3NlcyBpdCwgYW5kIG5vIG1lYXN1cmVtZW50IG9mIGEgZGVsaXZlcnkgb3V0cnVubmluZyAxMDBtcyBleGlzdHMgZWl0aGVyXG4gICAqIHdheS4gU28gcmVhZCB0aGlzIGFzIHJldGlyaW5nIHRoZSBiZXQgcmF0aGVyIHRoYW4gYXMgcmVwYWlyaW5nIGFuIG9ic2VydmVkXG4gICAqIGZhaWx1cmUgb2YgdGhhdCBudW1iZXI6IHRoZSBkZWxheSBpcyBhIHVzZXItc2V0dGFibGUgZW52IG92ZXJyaWRlLCB3aGljaFxuICAgKiBsZWF2ZXMgdGhlIG9sZCBiZWhhdmlvdXIgb25lIGNvbmZpZ3VyYXRpb24gYXdheSBmcm9tIGxvc2luZyBvbiBhbnkgYmFja2VuZC5cbiAgICpcbiAgICogVGVybWluYXRpb24gaXMgYGhhc1BhcmtlZENvbW1pdHRlZERlbGl2ZXJ5YCdzOiBpdCBjb3VudHMgb25seSBkZWxpdmVyaWVzXG4gICAqIHRoYXQgcmVzb2x2ZSBvbiB0aGVpciBvd24sIHNvIG5vdGhpbmcgaGVyZSBjYW4gZ2F0ZSBpdHMgb3duIHJldGlyZW1lbnQuIEFcbiAgICogZ2VudWluZWx5IG9ycGhhbmVkIGV2ZW50IGhhcyBubyBkZWxpdmVyeSB0byB3YWl0IG9uIGFuZCByZWFjaGVzIGBmbmAgb24gdGhlXG4gICAqIGZpcnN0IHBvbGwuXG4gICAqXG4gICAqIFdoYXQgdGhlIGdhdGUgZ2l2ZXMgdXA6IGZvciB0aGUgb3JkZXJlZCBldmVudHMgdGhhdCBzdGlsbCByZWFjaFxuICAgKiBgb25VbmNvbnN1bWVkRXZlbnRgIHJhdGhlciB0aGFuIHtAbGluayBwYXJrfSwgdGhpcyBzdG9wcyBiZWluZyB0aGUgdGhpbmdcbiAgICogdGhhdCBjYXRjaGVzIGEgZGl2ZXJnZWQgbG9nIHdoaWxlIGEgZGVsaXZlcnkgaXMgaW4gZmxpZ2h0LiBUaGUgc3VzcGVuc2lvblxuICAgKiBhbmQgdGhpcyBjaGVjayBub3cgd2FrZSBmcm9tIHRoZSBzYW1lIGBpc0RlbGl2ZXJ5SWRsZWAgZWRnZSwgYW5kXG4gICAqIGBzY2hlZHVsZVdoZW5JZGxlYCBmaXJlcyBvbiB0aGUgZmlyc3QgdGltZXIgdGljayBhZnRlciBpZGxlIHdoaWxlIHRoaXMgd2FpdHNcbiAgICogYSBmdXJ0aGVyIGBnZXREZWZlcnJlZENoZWNrRGVsYXlNcygpYC4gU28gYSBydW4gd2l0aCBhIHBlbmRpbmcgYHNsZWVwKClgXG4gICAqIHN1c3BlbmRzIGZpcnN0LCBhbmQgYG9uV29ya2Zsb3dFcnJvcmAgZHJvcHMgdGhlIGRpdmVyZ2VuY2UgYXJyaXZpbmcgc2Vjb25kXG4gICAqIChpdHMgYCdzdXNwZW5kZWQnYCBicmFuY2ggZGVtb3RlcyB0byBgJ3JlcGxheSdgIGFuZCBzdXJmYWNlcyBub3RoaW5nKSxcbiAgICogbGVhdmluZyBhIGxhdGVyIGByZXN1bWUoKWAgdG8gZGVjbGluZSBpbnRvIGEgY29sZCByZXBsYXkuIFByZS1nYXRlIHRoZVxuICAgKiBzdXNwZW5zaW9uIGFscmVhZHkgd29uIHRoYXQgcmFjZSB3aGVuZXZlciB0aGUgZGVsaXZlcnkgbGFuZGVkIGluc2lkZSB0aGVcbiAgICogZml4ZWQgd2luZG93LCBzbyB3aGF0IGNoYW5nZWQgaXMgdGhhdCB0aGUgb3V0Y29tZSBzdG9wcGVkIGRlcGVuZGluZyBvblxuICAgKiB0aW1pbmcuIE5vdGhpbmcgc2hvdWxkIHRyZWF0IHRoaXMgY2hlY2sgYXMgdGhlIG1lY2hhbmlzbSB0aGF0IHJlcG9ydHNcbiAgICogZGl2ZXJnZW5jZSBvbiBhIGxvZyB0aGUgcnVuIGlzIHN0aWxsIGRlbGl2ZXJpbmcgaW50by5cbiAgICovXG4gIHByaXZhdGUgd2hlbkRlbGl2ZXJ5SWRsZShjaGVja1ZlcnNpb246IG51bWJlciwgZm46ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICBjb25zdCBwb2xsID0gKCkgPT4ge1xuICAgICAgdGhpcy5wZW5kaW5nVW5jb25zdW1lZFRpbWVvdXQgPSBudWxsO1xuICAgICAgaWYgKHRoaXMudW5jb25zdW1lZENoZWNrVmVyc2lvbiAhPT0gY2hlY2tWZXJzaW9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmlzRGVsaXZlcnlJZGxlKCkpIHtcbiAgICAgICAgZm4oKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhpcy5nZXRQcm9taXNlUXVldWUoKS50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMudW5jb25zdW1lZENoZWNrVmVyc2lvbiAhPT0gY2hlY2tWZXJzaW9uKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIEhlbGQgaW4gdGhlIHNhbWUgZmllbGQgdGhlIGZpcmVkIGNoZWNrIHVzZXMgc28gc3Vic2NyaWJlKCkgY2FuY2VscyBhXG4gICAgICAgIC8vIHBvbGwgaW4gcHJvZ3Jlc3MgdG9vLiBUaGUgdHdvIGNhbmNlbGxhdGlvbnMgYXJlIG5vdCBpZGVudGljYWw6IGZvciB0aGVcbiAgICAgICAgLy8gcG9sbCBpdCBpcyB0aGUgdmVyc2lvbiBidW1wIHRoYXQgZG9lcyB0aGUgd29yayBhbmQgdGhlIGNsZWFyVGltZW91dCBpc1xuICAgICAgICAvLyBiZWx0LWFuZC1icmFjZXMuIFR3byBzdGF0ZSBtYWNoaW5lcyB3cml0ZSB0aGlzIG9uZSBmaWVsZCwgc28gYSBwb2xsXG4gICAgICAgIC8vIGludmFsaWRhdGVkIGJldHdlZW4gc2NoZWR1bGluZyBhbmQgZmlyaW5nIGNhbiBudWxsIG91dCBhIGhhbmRsZSB0aGVcbiAgICAgICAgLy8gbGl2ZSBjaGFpbiBoYXMgc2luY2Ugc3RvcmVkLCB3aGljaCBpcyB3aHkgZXZlcnkgcGF0aCBvdXQgb2YgYHBvbGxgIGFuZFxuICAgICAgICAvLyBvdXQgb2YgdGhlIGZpcmVkIGNoZWNrIHJlLWNoZWNrcyB0aGUgdmVyc2lvbiByYXRoZXIgdGhhbiB0cnVzdGluZyB0aGVcbiAgICAgICAgLy8gaGFuZGxlLlxuICAgICAgICB0aGlzLnBlbmRpbmdVbmNvbnN1bWVkVGltZW91dCA9IHNldFRpbWVvdXQocG9sbCwgMCk7XG4gICAgICB9KTtcbiAgICB9O1xuICAgIHBvbGwoKTtcbiAgfVxufVxuIl19
|