931 lines
142 KiB
Plaintext
931 lines
142 KiB
Plaintext
import { __assign, __extends } from "/_nuxt/node_modules/tslib/tslib.es6.js?v=e4f18c29";
|
||
import { invariant } from "/_nuxt/node_modules/@apollo/client/utilities/globals/index.js?v=e4f18c29";
|
||
import { equal } from "/_nuxt/node_modules/@wry/equality/lib/index.js?v=e4f18c29";
|
||
import { NetworkStatus, isNetworkRequestInFlight } from "/_nuxt/node_modules/@apollo/client/core/networkStatus.js?v=e4f18c29";
|
||
import { cloneDeep, compact, getOperationDefinition, Observable, iterateObserversSafely, fixObservableSubclass, getQueryDefinition, preventUnhandledRejection, } from "/_nuxt/node_modules/@apollo/client/utilities/index.js?v=e4f18c29";
|
||
import { ApolloError, isApolloError } from "/_nuxt/node_modules/@apollo/client/errors/index.js?v=e4f18c29";
|
||
import { equalByQuery } from "/_nuxt/node_modules/@apollo/client/core/equalByQuery.js?v=e4f18c29";
|
||
import { Slot } from "/_nuxt/node_modules/optimism/lib/index.js?v=e4f18c29";
|
||
var assign = Object.assign, hasOwnProperty = Object.hasOwnProperty;
|
||
var ObservableQuery = /** @class */ (function (_super) {
|
||
__extends(ObservableQuery, _super);
|
||
function ObservableQuery(_a) {
|
||
var queryManager = _a.queryManager, queryInfo = _a.queryInfo, options = _a.options;
|
||
var _this = this;
|
||
var startedInactive = ObservableQuery.inactiveOnCreation.getValue();
|
||
_this = _super.call(this, function (observer) {
|
||
if (startedInactive) {
|
||
queryManager["queries"].set(_this.queryId, queryInfo);
|
||
startedInactive = false;
|
||
}
|
||
// Zen Observable has its own error function, so in order to log correctly
|
||
// we need to provide a custom error callback.
|
||
try {
|
||
var subObserver = observer._subscription._observer;
|
||
if (subObserver && !subObserver.error) {
|
||
subObserver.error = defaultSubscriptionObserverErrorCallback;
|
||
}
|
||
}
|
||
catch (_a) { }
|
||
var first = !_this.observers.size;
|
||
_this.observers.add(observer);
|
||
// Deliver most recent error or result.
|
||
var last = _this.last;
|
||
if (last && last.error) {
|
||
observer.error && observer.error(last.error);
|
||
}
|
||
else if (last && last.result) {
|
||
observer.next && observer.next(_this.maskResult(last.result));
|
||
}
|
||
// Initiate observation of this query if it hasn't been reported to
|
||
// the QueryManager yet.
|
||
if (first) {
|
||
// Blindly catching here prevents unhandled promise rejections,
|
||
// and is safe because the ObservableQuery handles this error with
|
||
// this.observer.error, so we're not just swallowing the error by
|
||
// ignoring it here.
|
||
_this.reobserve().catch(function () { });
|
||
}
|
||
return function () {
|
||
if (_this.observers.delete(observer) && !_this.observers.size) {
|
||
_this.tearDownQuery();
|
||
}
|
||
};
|
||
}) || this;
|
||
_this.observers = new Set();
|
||
_this.subscriptions = new Set();
|
||
_this.dirty = false;
|
||
// related classes
|
||
_this.queryInfo = queryInfo;
|
||
_this.queryManager = queryManager;
|
||
// active state
|
||
_this.waitForOwnResult = skipCacheDataFor(options.fetchPolicy);
|
||
_this.isTornDown = false;
|
||
_this.subscribeToMore = _this.subscribeToMore.bind(_this);
|
||
_this.maskResult = _this.maskResult.bind(_this);
|
||
var _b = queryManager.defaultOptions.watchQuery, _c = _b === void 0 ? {} : _b, _d = _c.fetchPolicy, defaultFetchPolicy = _d === void 0 ? "cache-first" : _d;
|
||
var _e = options.fetchPolicy, fetchPolicy = _e === void 0 ? defaultFetchPolicy : _e,
|
||
// Make sure we don't store "standby" as the initialFetchPolicy.
|
||
_f = options.initialFetchPolicy,
|
||
// Make sure we don't store "standby" as the initialFetchPolicy.
|
||
initialFetchPolicy = _f === void 0 ? fetchPolicy === "standby" ? defaultFetchPolicy : (fetchPolicy) : _f;
|
||
_this.options = __assign(__assign({}, options), {
|
||
// Remember the initial options.fetchPolicy so we can revert back to this
|
||
// policy when variables change. This information can also be specified
|
||
// (or overridden) by providing options.initialFetchPolicy explicitly.
|
||
initialFetchPolicy: initialFetchPolicy,
|
||
// This ensures this.options.fetchPolicy always has a string value, in
|
||
// case options.fetchPolicy was not provided.
|
||
fetchPolicy: fetchPolicy });
|
||
_this.queryId = queryInfo.queryId || queryManager.generateQueryId();
|
||
var opDef = getOperationDefinition(_this.query);
|
||
_this.queryName = opDef && opDef.name && opDef.name.value;
|
||
return _this;
|
||
}
|
||
Object.defineProperty(ObservableQuery.prototype, "query", {
|
||
// The `query` computed property will always reflect the document transformed
|
||
// by the last run query. `this.options.query` will always reflect the raw
|
||
// untransformed query to ensure document transforms with runtime conditionals
|
||
// are run on the original document.
|
||
get: function () {
|
||
return this.lastQuery || this.options.query;
|
||
},
|
||
enumerable: false,
|
||
configurable: true
|
||
});
|
||
Object.defineProperty(ObservableQuery.prototype, "variables", {
|
||
// Computed shorthand for this.options.variables, preserved for
|
||
// backwards compatibility.
|
||
/**
|
||
* An object containing the variables that were provided for the query.
|
||
*/
|
||
get: function () {
|
||
return this.options.variables;
|
||
},
|
||
enumerable: false,
|
||
configurable: true
|
||
});
|
||
ObservableQuery.prototype.result = function () {
|
||
var _this = this;
|
||
return new Promise(function (resolve, reject) {
|
||
// TODO: this code doesn’t actually make sense insofar as the observer
|
||
// will never exist in this.observers due how zen-observable wraps observables.
|
||
// https://github.com/zenparsing/zen-observable/blob/master/src/Observable.js#L169
|
||
var observer = {
|
||
next: function (result) {
|
||
resolve(result);
|
||
// Stop the query within the QueryManager if we can before
|
||
// this function returns.
|
||
//
|
||
// We do this in order to prevent observers piling up within
|
||
// the QueryManager. Notice that we only fully unsubscribe
|
||
// from the subscription in a setTimeout(..., 0) call. This call can
|
||
// actually be handled by the browser at a much later time. If queries
|
||
// are fired in the meantime, observers that should have been removed
|
||
// from the QueryManager will continue to fire, causing an unnecessary
|
||
// performance hit.
|
||
_this.observers.delete(observer);
|
||
if (!_this.observers.size) {
|
||
_this.queryManager.removeQuery(_this.queryId);
|
||
}
|
||
setTimeout(function () {
|
||
subscription.unsubscribe();
|
||
}, 0);
|
||
},
|
||
error: reject,
|
||
};
|
||
var subscription = _this.subscribe(observer);
|
||
});
|
||
};
|
||
/** @internal */
|
||
ObservableQuery.prototype.resetDiff = function () {
|
||
this.queryInfo.resetDiff();
|
||
};
|
||
ObservableQuery.prototype.getCurrentFullResult = function (saveAsLastResult) {
|
||
if (saveAsLastResult === void 0) { saveAsLastResult = true; }
|
||
// Use the last result as long as the variables match this.variables.
|
||
var lastResult = this.getLastResult(true);
|
||
var networkStatus = this.queryInfo.networkStatus ||
|
||
(lastResult && lastResult.networkStatus) ||
|
||
NetworkStatus.ready;
|
||
var result = __assign(__assign({}, lastResult), { loading: isNetworkRequestInFlight(networkStatus), networkStatus: networkStatus });
|
||
var _a = this.options.fetchPolicy, fetchPolicy = _a === void 0 ? "cache-first" : _a;
|
||
if (
|
||
// These fetch policies should never deliver data from the cache, unless
|
||
// redelivering a previously delivered result.
|
||
skipCacheDataFor(fetchPolicy) ||
|
||
// If this.options.query has @client(always: true) fields, we cannot
|
||
// trust diff.result, since it was read from the cache without running
|
||
// local resolvers (and it's too late to run resolvers now, since we must
|
||
// return a result synchronously).
|
||
this.queryManager.getDocumentInfo(this.query).hasForcedResolvers) {
|
||
// Fall through.
|
||
}
|
||
else if (this.waitForOwnResult) {
|
||
// This would usually be a part of `QueryInfo.getDiff()`.
|
||
// which we skip in the waitForOwnResult case since we are not
|
||
// interested in the diff.
|
||
this.queryInfo["updateWatch"]();
|
||
}
|
||
else {
|
||
var diff = this.queryInfo.getDiff();
|
||
if (diff.complete || this.options.returnPartialData) {
|
||
result.data = diff.result;
|
||
}
|
||
if (equal(result.data, {})) {
|
||
result.data = void 0;
|
||
}
|
||
if (diff.complete) {
|
||
// Similar to setting result.partial to false, but taking advantage of the
|
||
// falsiness of missing fields.
|
||
delete result.partial;
|
||
// If the diff is complete, and we're using a FetchPolicy that
|
||
// terminates after a complete cache read, we can assume the next result
|
||
// we receive will have NetworkStatus.ready and !loading.
|
||
if (diff.complete &&
|
||
result.networkStatus === NetworkStatus.loading &&
|
||
(fetchPolicy === "cache-first" || fetchPolicy === "cache-only")) {
|
||
result.networkStatus = NetworkStatus.ready;
|
||
result.loading = false;
|
||
}
|
||
}
|
||
else {
|
||
result.partial = true;
|
||
}
|
||
// We need to check for both both `error` and `errors` field because there
|
||
// are cases where sometimes `error` is set, but not `errors` and
|
||
// vice-versa. This will be updated in the next major version when
|
||
// `errors` is deprecated in favor of `error`.
|
||
if (result.networkStatus === NetworkStatus.ready &&
|
||
(result.error || result.errors)) {
|
||
result.networkStatus = NetworkStatus.error;
|
||
}
|
||
if (globalThis.__DEV__ !== false &&
|
||
!diff.complete &&
|
||
!this.options.partialRefetch &&
|
||
!result.loading &&
|
||
!result.data &&
|
||
!result.error) {
|
||
logMissingFieldErrors(diff.missing);
|
||
}
|
||
}
|
||
if (saveAsLastResult) {
|
||
this.updateLastResult(result);
|
||
}
|
||
return result;
|
||
};
|
||
ObservableQuery.prototype.getCurrentResult = function (saveAsLastResult) {
|
||
if (saveAsLastResult === void 0) { saveAsLastResult = true; }
|
||
return this.maskResult(this.getCurrentFullResult(saveAsLastResult));
|
||
};
|
||
// Compares newResult to the snapshot we took of this.lastResult when it was
|
||
// first received.
|
||
ObservableQuery.prototype.isDifferentFromLastResult = function (newResult, variables) {
|
||
if (!this.last) {
|
||
return true;
|
||
}
|
||
var documentInfo = this.queryManager.getDocumentInfo(this.query);
|
||
var dataMasking = this.queryManager.dataMasking;
|
||
var query = dataMasking ? documentInfo.nonReactiveQuery : this.query;
|
||
var resultIsDifferent = dataMasking || documentInfo.hasNonreactiveDirective ?
|
||
!equalByQuery(query, this.last.result, newResult, this.variables)
|
||
: !equal(this.last.result, newResult);
|
||
return (resultIsDifferent || (variables && !equal(this.last.variables, variables)));
|
||
};
|
||
ObservableQuery.prototype.getLast = function (key, variablesMustMatch) {
|
||
var last = this.last;
|
||
if (last &&
|
||
last[key] &&
|
||
(!variablesMustMatch || equal(last.variables, this.variables))) {
|
||
return last[key];
|
||
}
|
||
};
|
||
ObservableQuery.prototype.getLastResult = function (variablesMustMatch) {
|
||
return this.getLast("result", variablesMustMatch);
|
||
};
|
||
ObservableQuery.prototype.getLastError = function (variablesMustMatch) {
|
||
return this.getLast("error", variablesMustMatch);
|
||
};
|
||
ObservableQuery.prototype.resetLastResults = function () {
|
||
delete this.last;
|
||
this.isTornDown = false;
|
||
};
|
||
ObservableQuery.prototype.resetQueryStoreErrors = function () {
|
||
this.queryManager.resetErrors(this.queryId);
|
||
};
|
||
/**
|
||
* Update the variables of this observable query, and fetch the new results.
|
||
* This method should be preferred over `setVariables` in most use cases.
|
||
*
|
||
* @param variables - The new set of variables. If there are missing variables,
|
||
* the previous values of those variables will be used.
|
||
*/
|
||
ObservableQuery.prototype.refetch = function (variables) {
|
||
var _a;
|
||
var reobserveOptions = {
|
||
// Always disable polling for refetches.
|
||
pollInterval: 0,
|
||
};
|
||
// Unless the provided fetchPolicy always consults the network
|
||
// (no-cache, network-only, or cache-and-network), override it with
|
||
// network-only to force the refetch for this fetchQuery call.
|
||
var fetchPolicy = this.options.fetchPolicy;
|
||
if (fetchPolicy === "no-cache") {
|
||
reobserveOptions.fetchPolicy = "no-cache";
|
||
}
|
||
else {
|
||
reobserveOptions.fetchPolicy = "network-only";
|
||
}
|
||
if (globalThis.__DEV__ !== false && variables && hasOwnProperty.call(variables, "variables")) {
|
||
var queryDef = getQueryDefinition(this.query);
|
||
var vars = queryDef.variableDefinitions;
|
||
if (!vars || !vars.some(function (v) { return v.variable.name.value === "variables"; })) {
|
||
globalThis.__DEV__ !== false && invariant.warn(
|
||
21,
|
||
variables,
|
||
((_a = queryDef.name) === null || _a === void 0 ? void 0 : _a.value) || queryDef
|
||
);
|
||
}
|
||
}
|
||
if (variables && !equal(this.options.variables, variables)) {
|
||
// Update the existing options with new variables
|
||
reobserveOptions.variables = this.options.variables = __assign(__assign({}, this.options.variables), variables);
|
||
}
|
||
this.queryInfo.resetLastWrite();
|
||
return this.reobserve(reobserveOptions, NetworkStatus.refetch);
|
||
};
|
||
/**
|
||
* A function that helps you fetch the next set of results for a [paginated list field](https://www.apollographql.com/docs/react/pagination/core-api/).
|
||
*/
|
||
ObservableQuery.prototype.fetchMore = function (fetchMoreOptions) {
|
||
var _this = this;
|
||
var combinedOptions = __assign(__assign({}, (fetchMoreOptions.query ? fetchMoreOptions : (__assign(__assign(__assign(__assign({}, this.options), { query: this.options.query }), fetchMoreOptions), { variables: __assign(__assign({}, this.options.variables), fetchMoreOptions.variables) })))), {
|
||
// The fetchMore request goes immediately to the network and does
|
||
// not automatically write its result to the cache (hence no-cache
|
||
// instead of network-only), because we allow the caller of
|
||
// fetchMore to provide an updateQuery callback that determines how
|
||
// the data gets written to the cache.
|
||
fetchPolicy: "no-cache" });
|
||
combinedOptions.query = this.transformDocument(combinedOptions.query);
|
||
var qid = this.queryManager.generateQueryId();
|
||
// If a temporary query is passed to `fetchMore`, we don't want to store
|
||
// it as the last query result since it may be an optimized query for
|
||
// pagination. We will however run the transforms on the original document
|
||
// as well as the document passed in `fetchMoreOptions` to ensure the cache
|
||
// uses the most up-to-date document which may rely on runtime conditionals.
|
||
this.lastQuery =
|
||
fetchMoreOptions.query ?
|
||
this.transformDocument(this.options.query)
|
||
: combinedOptions.query;
|
||
// Simulate a loading result for the original query with
|
||
// result.networkStatus === NetworkStatus.fetchMore.
|
||
var queryInfo = this.queryInfo;
|
||
var originalNetworkStatus = queryInfo.networkStatus;
|
||
queryInfo.networkStatus = NetworkStatus.fetchMore;
|
||
if (combinedOptions.notifyOnNetworkStatusChange) {
|
||
this.observe();
|
||
}
|
||
var updatedQuerySet = new Set();
|
||
var updateQuery = fetchMoreOptions === null || fetchMoreOptions === void 0 ? void 0 : fetchMoreOptions.updateQuery;
|
||
var isCached = this.options.fetchPolicy !== "no-cache";
|
||
if (!isCached) {
|
||
invariant(updateQuery, 22);
|
||
}
|
||
return this.queryManager
|
||
.fetchQuery(qid, combinedOptions, NetworkStatus.fetchMore)
|
||
.then(function (fetchMoreResult) {
|
||
_this.queryManager.removeQuery(qid);
|
||
if (queryInfo.networkStatus === NetworkStatus.fetchMore) {
|
||
queryInfo.networkStatus = originalNetworkStatus;
|
||
}
|
||
if (isCached) {
|
||
// Performing this cache update inside a cache.batch transaction ensures
|
||
// any affected cache.watch watchers are notified at most once about any
|
||
// updates. Most watchers will be using the QueryInfo class, which
|
||
// responds to notifications by calling reobserveCacheFirst to deliver
|
||
// fetchMore cache results back to this ObservableQuery.
|
||
_this.queryManager.cache.batch({
|
||
update: function (cache) {
|
||
var updateQuery = fetchMoreOptions.updateQuery;
|
||
if (updateQuery) {
|
||
cache.updateQuery({
|
||
query: _this.query,
|
||
variables: _this.variables,
|
||
returnPartialData: true,
|
||
optimistic: false,
|
||
}, function (previous) {
|
||
return updateQuery(previous, {
|
||
fetchMoreResult: fetchMoreResult.data,
|
||
variables: combinedOptions.variables,
|
||
});
|
||
});
|
||
}
|
||
else {
|
||
// If we're using a field policy instead of updateQuery, the only
|
||
// thing we need to do is write the new data to the cache using
|
||
// combinedOptions.variables (instead of this.variables, which is
|
||
// what this.updateQuery uses, because it works by abusing the
|
||
// original field value, keyed by the original variables).
|
||
cache.writeQuery({
|
||
query: combinedOptions.query,
|
||
variables: combinedOptions.variables,
|
||
data: fetchMoreResult.data,
|
||
});
|
||
}
|
||
},
|
||
onWatchUpdated: function (watch) {
|
||
// Record the DocumentNode associated with any watched query whose
|
||
// data were updated by the cache writes above.
|
||
updatedQuerySet.add(watch.query);
|
||
},
|
||
});
|
||
}
|
||
else {
|
||
// There is a possibility `lastResult` may not be set when
|
||
// `fetchMore` is called which would cause this to crash. This should
|
||
// only happen if we haven't previously reported a result. We don't
|
||
// quite know what the right behavior should be here since this block
|
||
// of code runs after the fetch result has executed on the network.
|
||
// We plan to let it crash in the meantime.
|
||
//
|
||
// If we get bug reports due to the `data` property access on
|
||
// undefined, this should give us a real-world scenario that we can
|
||
// use to test against and determine the right behavior. If we do end
|
||
// up changing this behavior, this may require, for example, an
|
||
// adjustment to the types on `updateQuery` since that function
|
||
// expects that the first argument always contains previous result
|
||
// data, but not `undefined`.
|
||
var lastResult = _this.getLast("result");
|
||
var data = updateQuery(lastResult.data, {
|
||
fetchMoreResult: fetchMoreResult.data,
|
||
variables: combinedOptions.variables,
|
||
});
|
||
_this.reportResult(__assign(__assign({}, lastResult), { networkStatus: originalNetworkStatus, loading: isNetworkRequestInFlight(originalNetworkStatus), data: data }), _this.variables);
|
||
}
|
||
return _this.maskResult(fetchMoreResult);
|
||
})
|
||
.finally(function () {
|
||
// In case the cache writes above did not generate a broadcast
|
||
// notification (which would have been intercepted by onWatchUpdated),
|
||
// likely because the written data were the same as what was already in
|
||
// the cache, we still want fetchMore to deliver its final loading:false
|
||
// result with the unchanged data.
|
||
if (isCached && !updatedQuerySet.has(_this.query)) {
|
||
_this.reobserveCacheFirst();
|
||
}
|
||
});
|
||
};
|
||
// XXX the subscription variables are separate from the query variables.
|
||
// if you want to update subscription variables, right now you have to do that separately,
|
||
// and you can only do it by stopping the subscription and then subscribing again with new variables.
|
||
/**
|
||
* A function that enables you to execute a [subscription](https://www.apollographql.com/docs/react/data/subscriptions/), usually to subscribe to specific fields that were included in the query.
|
||
*
|
||
* This function returns _another_ function that you can call to terminate the subscription.
|
||
*/
|
||
ObservableQuery.prototype.subscribeToMore = function (options) {
|
||
var _this = this;
|
||
var subscription = this.queryManager
|
||
.startGraphQLSubscription({
|
||
query: options.document,
|
||
variables: options.variables,
|
||
context: options.context,
|
||
})
|
||
.subscribe({
|
||
next: function (subscriptionData) {
|
||
var updateQuery = options.updateQuery;
|
||
if (updateQuery) {
|
||
_this.updateQuery(function (previous, updateOptions) {
|
||
return updateQuery(previous, __assign({ subscriptionData: subscriptionData }, updateOptions));
|
||
});
|
||
}
|
||
},
|
||
error: function (err) {
|
||
if (options.onError) {
|
||
options.onError(err);
|
||
return;
|
||
}
|
||
globalThis.__DEV__ !== false && invariant.error(23, err);
|
||
},
|
||
});
|
||
this.subscriptions.add(subscription);
|
||
return function () {
|
||
if (_this.subscriptions.delete(subscription)) {
|
||
subscription.unsubscribe();
|
||
}
|
||
};
|
||
};
|
||
ObservableQuery.prototype.setOptions = function (newOptions) {
|
||
return this.reobserve(newOptions);
|
||
};
|
||
ObservableQuery.prototype.silentSetOptions = function (newOptions) {
|
||
var mergedOptions = compact(this.options, newOptions || {});
|
||
assign(this.options, mergedOptions);
|
||
};
|
||
/**
|
||
* Update the variables of this observable query, and fetch the new results
|
||
* if they've changed. Most users should prefer `refetch` instead of
|
||
* `setVariables` in order to to be properly notified of results even when
|
||
* they come from the cache.
|
||
*
|
||
* Note: the `next` callback will *not* fire if the variables have not changed
|
||
* or if the result is coming from cache.
|
||
*
|
||
* Note: the promise will return the old results immediately if the variables
|
||
* have not changed.
|
||
*
|
||
* Note: the promise will return null immediately if the query is not active
|
||
* (there are no subscribers).
|
||
*
|
||
* @param variables - The new set of variables. If there are missing variables,
|
||
* the previous values of those variables will be used.
|
||
*/
|
||
ObservableQuery.prototype.setVariables = function (variables) {
|
||
if (equal(this.variables, variables)) {
|
||
// If we have no observers, then we don't actually want to make a network
|
||
// request. As soon as someone observes the query, the request will kick
|
||
// off. For now, we just store any changes. (See #1077)
|
||
return this.observers.size ? this.result() : Promise.resolve();
|
||
}
|
||
this.options.variables = variables;
|
||
// See comment above
|
||
if (!this.observers.size) {
|
||
return Promise.resolve();
|
||
}
|
||
return this.reobserve({
|
||
// Reset options.fetchPolicy to its original value.
|
||
fetchPolicy: this.options.initialFetchPolicy,
|
||
variables: variables,
|
||
}, NetworkStatus.setVariables);
|
||
};
|
||
/**
|
||
* A function that enables you to update the query's cached result without executing a followup GraphQL operation.
|
||
*
|
||
* See [using updateQuery and updateFragment](https://www.apollographql.com/docs/react/caching/cache-interaction/#using-updatequery-and-updatefragment) for additional information.
|
||
*/
|
||
ObservableQuery.prototype.updateQuery = function (mapFn) {
|
||
var queryManager = this.queryManager;
|
||
var _a = queryManager.cache.diff({
|
||
query: this.options.query,
|
||
variables: this.variables,
|
||
returnPartialData: true,
|
||
optimistic: false,
|
||
}), result = _a.result, complete = _a.complete;
|
||
var newResult = mapFn(result, {
|
||
variables: this.variables,
|
||
complete: !!complete,
|
||
previousData: result,
|
||
});
|
||
if (newResult) {
|
||
queryManager.cache.writeQuery({
|
||
query: this.options.query,
|
||
data: newResult,
|
||
variables: this.variables,
|
||
});
|
||
queryManager.broadcastQueries();
|
||
}
|
||
};
|
||
/**
|
||
* A function that instructs the query to begin re-executing at a specified interval (in milliseconds).
|
||
*/
|
||
ObservableQuery.prototype.startPolling = function (pollInterval) {
|
||
this.options.pollInterval = pollInterval;
|
||
this.updatePolling();
|
||
};
|
||
/**
|
||
* A function that instructs the query to stop polling after a previous call to `startPolling`.
|
||
*/
|
||
ObservableQuery.prototype.stopPolling = function () {
|
||
this.options.pollInterval = 0;
|
||
this.updatePolling();
|
||
};
|
||
// Update options.fetchPolicy according to options.nextFetchPolicy.
|
||
ObservableQuery.prototype.applyNextFetchPolicy = function (reason,
|
||
// It's possible to use this method to apply options.nextFetchPolicy to
|
||
// options.fetchPolicy even if options !== this.options, though that happens
|
||
// most often when the options are temporary, used for only one request and
|
||
// then thrown away, so nextFetchPolicy may not end up mattering.
|
||
options) {
|
||
if (options.nextFetchPolicy) {
|
||
var _a = options.fetchPolicy, fetchPolicy = _a === void 0 ? "cache-first" : _a, _b = options.initialFetchPolicy, initialFetchPolicy = _b === void 0 ? fetchPolicy : _b;
|
||
if (fetchPolicy === "standby") {
|
||
// Do nothing, leaving options.fetchPolicy unchanged.
|
||
}
|
||
else if (typeof options.nextFetchPolicy === "function") {
|
||
// When someone chooses "cache-and-network" or "network-only" as their
|
||
// initial FetchPolicy, they often do not want future cache updates to
|
||
// trigger unconditional network requests, which is what repeatedly
|
||
// applying the "cache-and-network" or "network-only" policies would
|
||
// seem to imply. Instead, when the cache reports an update after the
|
||
// initial network request, it may be desirable for subsequent network
|
||
// requests to be triggered only if the cache result is incomplete. To
|
||
// that end, the options.nextFetchPolicy option provides an easy way to
|
||
// update options.fetchPolicy after the initial network request, without
|
||
// having to call observableQuery.setOptions.
|
||
options.fetchPolicy = options.nextFetchPolicy(fetchPolicy, {
|
||
reason: reason,
|
||
options: options,
|
||
observable: this,
|
||
initialFetchPolicy: initialFetchPolicy,
|
||
});
|
||
}
|
||
else if (reason === "variables-changed") {
|
||
options.fetchPolicy = initialFetchPolicy;
|
||
}
|
||
else {
|
||
options.fetchPolicy = options.nextFetchPolicy;
|
||
}
|
||
}
|
||
return options.fetchPolicy;
|
||
};
|
||
ObservableQuery.prototype.fetch = function (options, newNetworkStatus, query) {
|
||
// TODO Make sure we update the networkStatus (and infer fetchVariables)
|
||
// before actually committing to the fetch.
|
||
var queryInfo = this.queryManager.getOrCreateQuery(this.queryId);
|
||
queryInfo.setObservableQuery(this);
|
||
return this.queryManager["fetchConcastWithInfo"](queryInfo, options, newNetworkStatus, query);
|
||
};
|
||
// Turns polling on or off based on this.options.pollInterval.
|
||
ObservableQuery.prototype.updatePolling = function () {
|
||
var _this = this;
|
||
// Avoid polling in SSR mode
|
||
if (this.queryManager.ssrMode) {
|
||
return;
|
||
}
|
||
var _a = this, pollingInfo = _a.pollingInfo, pollInterval = _a.options.pollInterval;
|
||
if (!pollInterval || !this.hasObservers()) {
|
||
if (pollingInfo) {
|
||
clearTimeout(pollingInfo.timeout);
|
||
delete this.pollingInfo;
|
||
}
|
||
return;
|
||
}
|
||
if (pollingInfo && pollingInfo.interval === pollInterval) {
|
||
return;
|
||
}
|
||
invariant(pollInterval, 24);
|
||
var info = pollingInfo || (this.pollingInfo = {});
|
||
info.interval = pollInterval;
|
||
var maybeFetch = function () {
|
||
var _a, _b;
|
||
if (_this.pollingInfo) {
|
||
if (!isNetworkRequestInFlight(_this.queryInfo.networkStatus) &&
|
||
!((_b = (_a = _this.options).skipPollAttempt) === null || _b === void 0 ? void 0 : _b.call(_a))) {
|
||
_this.reobserve({
|
||
// Most fetchPolicy options don't make sense to use in a polling context, as
|
||
// users wouldn't want to be polling the cache directly. However, network-only and
|
||
// no-cache are both useful for when the user wants to control whether or not the
|
||
// polled results are written to the cache.
|
||
fetchPolicy: _this.options.initialFetchPolicy === "no-cache" ?
|
||
"no-cache"
|
||
: "network-only",
|
||
}, NetworkStatus.poll).then(poll, poll);
|
||
}
|
||
else {
|
||
poll();
|
||
}
|
||
}
|
||
};
|
||
var poll = function () {
|
||
var info = _this.pollingInfo;
|
||
if (info) {
|
||
clearTimeout(info.timeout);
|
||
info.timeout = setTimeout(maybeFetch, info.interval);
|
||
}
|
||
};
|
||
poll();
|
||
};
|
||
ObservableQuery.prototype.updateLastResult = function (newResult, variables) {
|
||
if (variables === void 0) { variables = this.variables; }
|
||
var error = this.getLastError();
|
||
// Preserve this.last.error unless the variables have changed.
|
||
if (error && this.last && !equal(variables, this.last.variables)) {
|
||
error = void 0;
|
||
}
|
||
return (this.last = __assign({ result: this.queryManager.assumeImmutableResults ?
|
||
newResult
|
||
: cloneDeep(newResult), variables: variables }, (error ? { error: error } : null)));
|
||
};
|
||
ObservableQuery.prototype.reobserveAsConcast = function (newOptions, newNetworkStatus) {
|
||
var _this = this;
|
||
this.isTornDown = false;
|
||
var useDisposableConcast =
|
||
// Refetching uses a disposable Concast to allow refetches using different
|
||
// options/variables, without permanently altering the options of the
|
||
// original ObservableQuery.
|
||
newNetworkStatus === NetworkStatus.refetch ||
|
||
// The fetchMore method does not actually call the reobserve method, but,
|
||
// if it did, it would definitely use a disposable Concast.
|
||
newNetworkStatus === NetworkStatus.fetchMore ||
|
||
// Polling uses a disposable Concast so the polling options (which force
|
||
// fetchPolicy to be "network-only" or "no-cache") won't override the original options.
|
||
newNetworkStatus === NetworkStatus.poll;
|
||
// Save the old variables, since Object.assign may modify them below.
|
||
var oldVariables = this.options.variables;
|
||
var oldFetchPolicy = this.options.fetchPolicy;
|
||
var mergedOptions = compact(this.options, newOptions || {});
|
||
var options = useDisposableConcast ?
|
||
// Disposable Concast fetches receive a shallow copy of this.options
|
||
// (merged with newOptions), leaving this.options unmodified.
|
||
mergedOptions
|
||
: assign(this.options, mergedOptions);
|
||
// Don't update options.query with the transformed query to avoid
|
||
// overwriting this.options.query when we aren't using a disposable concast.
|
||
// We want to ensure we can re-run the custom document transforms the next
|
||
// time a request is made against the original query.
|
||
var query = this.transformDocument(options.query);
|
||
this.lastQuery = query;
|
||
if (!useDisposableConcast) {
|
||
// We can skip calling updatePolling if we're not changing this.options.
|
||
this.updatePolling();
|
||
// Reset options.fetchPolicy to its original value when variables change,
|
||
// unless a new fetchPolicy was provided by newOptions.
|
||
if (newOptions &&
|
||
newOptions.variables &&
|
||
!equal(newOptions.variables, oldVariables) &&
|
||
// Don't mess with the fetchPolicy if it's currently "standby".
|
||
options.fetchPolicy !== "standby" &&
|
||
// If we're changing the fetchPolicy anyway, don't try to change it here
|
||
// using applyNextFetchPolicy. The explicit options.fetchPolicy wins.
|
||
(options.fetchPolicy === oldFetchPolicy ||
|
||
// A `nextFetchPolicy` function has even higher priority, though,
|
||
// so in that case `applyNextFetchPolicy` must be called.
|
||
typeof options.nextFetchPolicy === "function")) {
|
||
this.applyNextFetchPolicy("variables-changed", options);
|
||
if (newNetworkStatus === void 0) {
|
||
newNetworkStatus = NetworkStatus.setVariables;
|
||
}
|
||
}
|
||
}
|
||
this.waitForOwnResult && (this.waitForOwnResult = skipCacheDataFor(options.fetchPolicy));
|
||
var finishWaitingForOwnResult = function () {
|
||
if (_this.concast === concast) {
|
||
_this.waitForOwnResult = false;
|
||
}
|
||
};
|
||
var variables = options.variables && __assign({}, options.variables);
|
||
var _a = this.fetch(options, newNetworkStatus, query), concast = _a.concast, fromLink = _a.fromLink;
|
||
var observer = {
|
||
next: function (result) {
|
||
if (equal(_this.variables, variables)) {
|
||
finishWaitingForOwnResult();
|
||
_this.reportResult(result, variables);
|
||
}
|
||
},
|
||
error: function (error) {
|
||
if (equal(_this.variables, variables)) {
|
||
// Coming from `getResultsFromLink`, `error` here should always be an `ApolloError`.
|
||
// However, calling `concast.cancel` can inject another type of error, so we have to
|
||
// wrap it again here.
|
||
if (!isApolloError(error)) {
|
||
error = new ApolloError({ networkError: error });
|
||
}
|
||
finishWaitingForOwnResult();
|
||
_this.reportError(error, variables);
|
||
}
|
||
},
|
||
};
|
||
if (!useDisposableConcast && (fromLink || !this.concast)) {
|
||
// We use the {add,remove}Observer methods directly to avoid wrapping
|
||
// observer with an unnecessary SubscriptionObserver object.
|
||
if (this.concast && this.observer) {
|
||
this.concast.removeObserver(this.observer);
|
||
}
|
||
this.concast = concast;
|
||
this.observer = observer;
|
||
}
|
||
concast.addObserver(observer);
|
||
return concast;
|
||
};
|
||
ObservableQuery.prototype.reobserve = function (newOptions, newNetworkStatus) {
|
||
return preventUnhandledRejection(this.reobserveAsConcast(newOptions, newNetworkStatus).promise.then(this.maskResult));
|
||
};
|
||
ObservableQuery.prototype.resubscribeAfterError = function () {
|
||
var args = [];
|
||
for (var _i = 0; _i < arguments.length; _i++) {
|
||
args[_i] = arguments[_i];
|
||
}
|
||
// If `lastError` is set in the current when the subscription is re-created,
|
||
// the subscription will immediately receive the error, which will
|
||
// cause it to terminate again. To avoid this, we first clear
|
||
// the last error/result from the `observableQuery` before re-starting
|
||
// the subscription, and restore the last value afterwards so that the
|
||
// subscription has a chance to stay open.
|
||
var last = this.last;
|
||
this.resetLastResults();
|
||
var subscription = this.subscribe.apply(this, args);
|
||
this.last = last;
|
||
return subscription;
|
||
};
|
||
// (Re)deliver the current result to this.observers without applying fetch
|
||
// policies or making network requests.
|
||
ObservableQuery.prototype.observe = function () {
|
||
this.reportResult(
|
||
// Passing false is important so that this.getCurrentResult doesn't
|
||
// save the fetchMore result as this.lastResult, causing it to be
|
||
// ignored due to the this.isDifferentFromLastResult check in
|
||
// this.reportResult.
|
||
this.getCurrentFullResult(false), this.variables);
|
||
};
|
||
ObservableQuery.prototype.reportResult = function (result, variables) {
|
||
var lastError = this.getLastError();
|
||
var isDifferent = this.isDifferentFromLastResult(result, variables);
|
||
// Update the last result even when isDifferentFromLastResult returns false,
|
||
// because the query may be using the @nonreactive directive, and we want to
|
||
// save the the latest version of any nonreactive subtrees (in case
|
||
// getCurrentResult is called), even though we skip broadcasting changes.
|
||
if (lastError || !result.partial || this.options.returnPartialData) {
|
||
this.updateLastResult(result, variables);
|
||
}
|
||
if (lastError || isDifferent) {
|
||
iterateObserversSafely(this.observers, "next", this.maskResult(result));
|
||
}
|
||
};
|
||
ObservableQuery.prototype.reportError = function (error, variables) {
|
||
// Since we don't get the current result on errors, only the error, we
|
||
// must mirror the updates that occur in QueryStore.markQueryError here
|
||
var errorResult = __assign(__assign({}, this.getLastResult()), { error: error, errors: error.graphQLErrors, networkStatus: NetworkStatus.error, loading: false });
|
||
this.updateLastResult(errorResult, variables);
|
||
iterateObserversSafely(this.observers, "error", (this.last.error = error));
|
||
};
|
||
ObservableQuery.prototype.hasObservers = function () {
|
||
return this.observers.size > 0;
|
||
};
|
||
ObservableQuery.prototype.tearDownQuery = function () {
|
||
if (this.isTornDown)
|
||
return;
|
||
if (this.concast && this.observer) {
|
||
this.concast.removeObserver(this.observer);
|
||
delete this.concast;
|
||
delete this.observer;
|
||
}
|
||
this.stopPolling();
|
||
// stop all active GraphQL subscriptions
|
||
this.subscriptions.forEach(function (sub) { return sub.unsubscribe(); });
|
||
this.subscriptions.clear();
|
||
this.queryManager.stopQuery(this.queryId);
|
||
this.observers.clear();
|
||
this.isTornDown = true;
|
||
};
|
||
ObservableQuery.prototype.transformDocument = function (document) {
|
||
return this.queryManager.transform(document);
|
||
};
|
||
ObservableQuery.prototype.maskResult = function (result) {
|
||
return result && "data" in result ? __assign(__assign({}, result), { data: this.queryManager.maskOperation({
|
||
document: this.query,
|
||
data: result.data,
|
||
fetchPolicy: this.options.fetchPolicy,
|
||
id: this.queryId,
|
||
}) }) : result;
|
||
};
|
||
/** @internal */
|
||
ObservableQuery.prototype.resetNotifications = function () {
|
||
this.cancelNotifyTimeout();
|
||
this.dirty = false;
|
||
};
|
||
ObservableQuery.prototype.cancelNotifyTimeout = function () {
|
||
if (this.notifyTimeout) {
|
||
clearTimeout(this.notifyTimeout);
|
||
this.notifyTimeout = void 0;
|
||
}
|
||
};
|
||
/** @internal */
|
||
ObservableQuery.prototype.scheduleNotify = function () {
|
||
var _this = this;
|
||
if (this.dirty)
|
||
return;
|
||
this.dirty = true;
|
||
if (!this.notifyTimeout) {
|
||
this.notifyTimeout = setTimeout(function () { return _this.notify(); }, 0);
|
||
}
|
||
};
|
||
/** @internal */
|
||
ObservableQuery.prototype.notify = function () {
|
||
this.cancelNotifyTimeout();
|
||
if (this.dirty) {
|
||
if (this.options.fetchPolicy == "cache-only" ||
|
||
this.options.fetchPolicy == "cache-and-network" ||
|
||
!isNetworkRequestInFlight(this.queryInfo.networkStatus)) {
|
||
var diff = this.queryInfo.getDiff();
|
||
if (diff.fromOptimisticTransaction) {
|
||
// If this diff came from an optimistic transaction, deliver the
|
||
// current cache data to the ObservableQuery, but don't perform a
|
||
// reobservation, since oq.reobserveCacheFirst might make a network
|
||
// request, and we never want to trigger network requests in the
|
||
// middle of optimistic updates.
|
||
this.observe();
|
||
}
|
||
else {
|
||
// Otherwise, make the ObservableQuery "reobserve" the latest data
|
||
// using a temporary fetch policy of "cache-first", so complete cache
|
||
// results have a chance to be delivered without triggering additional
|
||
// network requests, even when options.fetchPolicy is "network-only"
|
||
// or "cache-and-network". All other fetch policies are preserved by
|
||
// this method, and are handled by calling oq.reobserve(). If this
|
||
// reobservation is spurious, isDifferentFromLastResult still has a
|
||
// chance to catch it before delivery to ObservableQuery subscribers.
|
||
this.reobserveCacheFirst();
|
||
}
|
||
}
|
||
}
|
||
this.dirty = false;
|
||
};
|
||
// Reobserve with fetchPolicy effectively set to "cache-first", triggering
|
||
// delivery of any new data from the cache, possibly falling back to the network
|
||
// if any cache data are missing. This allows _complete_ cache results to be
|
||
// delivered without also kicking off unnecessary network requests when
|
||
// this.options.fetchPolicy is "cache-and-network" or "network-only". When
|
||
// this.options.fetchPolicy is any other policy ("cache-first", "cache-only",
|
||
// "standby", or "no-cache"), we call this.reobserve() as usual.
|
||
ObservableQuery.prototype.reobserveCacheFirst = function () {
|
||
var _a = this.options, fetchPolicy = _a.fetchPolicy, nextFetchPolicy = _a.nextFetchPolicy;
|
||
if (fetchPolicy === "cache-and-network" || fetchPolicy === "network-only") {
|
||
return this.reobserve({
|
||
fetchPolicy: "cache-first",
|
||
// Use a temporary nextFetchPolicy function that replaces itself with the
|
||
// previous nextFetchPolicy value and returns the original fetchPolicy.
|
||
nextFetchPolicy: function (currentFetchPolicy, context) {
|
||
// Replace this nextFetchPolicy function in the options object with the
|
||
// original this.options.nextFetchPolicy value.
|
||
this.nextFetchPolicy = nextFetchPolicy;
|
||
// If the original nextFetchPolicy value was a function, give it a
|
||
// chance to decide what happens here.
|
||
if (typeof this.nextFetchPolicy === "function") {
|
||
return this.nextFetchPolicy(currentFetchPolicy, context);
|
||
}
|
||
// Otherwise go back to the original this.options.fetchPolicy.
|
||
return fetchPolicy;
|
||
},
|
||
});
|
||
}
|
||
return this.reobserve();
|
||
};
|
||
/**
|
||
* @internal
|
||
* A slot used by the `useQuery` hook to indicate that `client.watchQuery`
|
||
* should not register the query immediately, but instead wait for the query to
|
||
* be started registered with the `QueryManager` when `useSyncExternalStore`
|
||
* actively subscribes to it.
|
||
*/
|
||
ObservableQuery.inactiveOnCreation = new Slot();
|
||
return ObservableQuery;
|
||
}(Observable));
|
||
export { ObservableQuery };
|
||
// Necessary because the ObservableQuery constructor has a different
|
||
// signature than the Observable constructor.
|
||
fixObservableSubclass(ObservableQuery);
|
||
function defaultSubscriptionObserverErrorCallback(error) {
|
||
globalThis.__DEV__ !== false && invariant.error(25, error.message, error.stack);
|
||
}
|
||
export function logMissingFieldErrors(missing) {
|
||
if (globalThis.__DEV__ !== false && missing) {
|
||
globalThis.__DEV__ !== false && invariant.debug(26, missing);
|
||
}
|
||
}
|
||
function skipCacheDataFor(fetchPolicy /* `undefined` would mean `"cache-first"` */) {
|
||
return (fetchPolicy === "network-only" ||
|
||
fetchPolicy === "no-cache" ||
|
||
fetchPolicy === "standby");
|
||
}
|
||
|
||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT2JzZXJ2YWJsZVF1ZXJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvcmUvT2JzZXJ2YWJsZVF1ZXJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFMUQsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUV0QyxPQUFPLEVBQUUsYUFBYSxFQUFFLHdCQUF3QixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFNN0UsT0FBTyxFQUNMLFNBQVMsRUFDVCxPQUFPLEVBQ1Asc0JBQXNCLEVBQ3RCLFVBQVUsRUFDVixzQkFBc0IsRUFDdEIscUJBQXFCLEVBQ3JCLGtCQUFrQixFQUNsQix5QkFBeUIsR0FDMUIsTUFBTSx1QkFBdUIsQ0FBQztBQUMvQixPQUFPLEVBQUUsV0FBVyxFQUFFLGFBQWEsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBbUJoRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFHakQsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUV4QixJQUFBLE1BQU0sR0FBcUIsTUFBTSxPQUEzQixFQUFFLGNBQWMsR0FBSyxNQUFNLGVBQVgsQ0FBWTtBQXFCMUM7SUFHVSxtQ0FBaUQ7SUFzRHpELHlCQUFZLEVBUVg7WUFQQyxZQUFZLGtCQUFBLEVBQ1osU0FBUyxlQUFBLEVBQ1QsT0FBTyxhQUFBO1FBSFQsaUJBNkZDO1FBcEZDLElBQUksZUFBZSxHQUFHLGVBQWUsQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNwRSxRQUFBLE1BQUssWUFBQyxVQUFDLFFBQXlEO1lBQzlELElBQUksZUFBZSxFQUFFLENBQUM7Z0JBQ3BCLFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQyxHQUFHLENBQUMsS0FBSSxDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQztnQkFDckQsZUFBZSxHQUFH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QztBQUM3QyxxQkFBcUIsQ0FBQyxlQUFlLENBQUMsQ0FBQztBQUV2QyxTQUFTLHdDQUF3QyxDQUFDLEtBQWtCO0lBQ2xFLFNBQVMsQ0FBQyxLQUFLLENBQUMsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDakUsQ0FBQztBQUVELE1BQU0sVUFBVSxxQkFBcUIsQ0FDbkMsT0FBc0Q7SUFFdEQsSUFBSSxPQUFPLElBQUksT0FBTyxFQUFFLENBQUM7UUFDdkIsU0FBUyxDQUFDLEtBQUssQ0FBQyxpQ0FBaUMsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUM5RCxDQUFDO0FBQ0gsQ0FBQztBQUVELFNBQVMsZ0JBQWdCLENBQ3ZCLFdBQW1DLENBQUMsNENBQTRDO0lBRWhGLE9BQU8sQ0FDTCxXQUFXLEtBQUssY0FBYztRQUM5QixXQUFXLEtBQUssVUFBVTtRQUMxQixXQUFXLEtBQUssU0FBUyxDQUMxQixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGludmFyaWFudCB9IGZyb20gXCIuLi91dGlsaXRpZXMvZ2xvYmFscy9pbmRleC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBEb2N1bWVudE5vZGUgfSBmcm9tIFwiZ3JhcGhxbFwiO1xuaW1wb3J0IHsgZXF1YWwgfSBmcm9tIFwiQHdyeS9lcXVhbGl0eVwiO1xuXG5pbXBvcnQgeyBOZXR3b3JrU3RhdHVzLCBpc05ldHdvcmtSZXF1ZXN0SW5GbGlnaHQgfSBmcm9tIFwiLi9uZXR3b3JrU3RhdHVzLmpzXCI7XG5pbXBvcnQgdHlwZSB7XG4gIENvbmNhc3QsXG4gIE9ic2VydmVyLFxuICBPYnNlcnZhYmxlU3Vic2NyaXB0aW9uLFxufSBmcm9tIFwiLi4vdXRpbGl0aWVzL2luZGV4LmpzXCI7XG5pbXBvcnQge1xuICBjbG9uZURlZXAsXG4gIGNvbXBhY3QsXG4gIGdldE9wZXJhdGlvbkRlZmluaXRpb24sXG4gIE9ic2VydmFibGUsXG4gIGl0ZXJhdGVPYnNlcnZlcnNTYWZlbHksXG4gIGZpeE9ic2VydmFibGVTdWJjbGFzcyxcbiAgZ2V0UXVlcnlEZWZpbml0aW9uLFxuICBwcmV2ZW50VW5oYW5kbGVkUmVqZWN0aW9uLFxufSBmcm9tIFwiLi4vdXRpbGl0aWVzL2luZGV4LmpzXCI7XG5pbXBvcnQgeyBBcG9sbG9FcnJvciwgaXNBcG9sbG9FcnJvciB9IGZyb20gXCIuLi9lcnJvcnMvaW5kZXguanNcIjtcbmltcG9ydCB0eXBlIHsgUXVlcnlNYW5hZ2VyIH0gZnJvbSBcIi4vUXVlcnlNYW5hZ2VyLmpzXCI7XG5pbXBvcnQgdHlwZSB7XG4gIEFwb2xsb1F1ZXJ5UmVzdWx0LFxuICBPcGVyYXRpb25WYXJpYWJsZXMsXG4gIFR5cGVkRG9jdW1lbnROb2RlLFxufSBmcm9tIFwiLi90eXBlcy5qc1wiO1xuaW1wb3J0IHR5cGUge1xuICBXYXRjaFF1ZXJ5T3B0aW9ucyxcbiAgRmV0Y2hNb3JlUXVlcnlPcHRpb25zLFxuICBTdWJzY3JpYmVUb01vcmVPcHRpb25zLFxuICBOZXh0RmV0Y2hQb2xpY3lDb250ZXh0LFxuICBXYXRjaFF1ZXJ5RmV0Y2hQb2xpY3ksXG4gIFVwZGF0ZVF1ZXJ5TWFwRm4sXG4gIFVwZGF0ZVF1ZXJ5T3B0aW9ucyxcbn0gZnJvbSBcIi4vd2F0Y2hRdWVyeU9wdGlvbnMuanNcIjtcbmltcG9ydCB0eXBlIHsgUXVlcnlJbmZvIH0gZnJvbSBcIi4vUXVlcnlJbmZvLmpzXCI7XG5pbXBvcnQgdHlwZSB7IE1pc3NpbmdGaWVsZEVycm9yIH0gZnJvbSBcIi4uL2NhY2hlL2luZGV4LmpzXCI7XG5pbXBvcnQgdHlwZSB7IE1pc3NpbmdUcmVlIH0gZnJvbSBcIi4uL2NhY2hlL2NvcmUvdHlwZXMvY29tbW9uLmpzXCI7XG5pbXBvcnQgeyBlcXVhbEJ5UXVlcnkgfSBmcm9tIFwiLi9lcXVhbEJ5UXVlcnkuanNcIjtcbmltcG9ydCB0eXBlIHsgVE9ETyB9IGZyb20gXCIuLi91dGlsaXRpZXMvdHlwZXMvVE9ETy5qc1wiO1xuaW1wb3J0IHR5cGUgeyBNYXliZU1hc2tlZCwgVW5tYXNrZWQgfSBmcm9tIFwiLi4vbWFza2luZy9pbmRleC5qc1wiO1xuaW1wb3J0IHsgU2xvdCB9IGZyb20gXCJvcHRpbWlzbVwiO1xuXG5jb25zdCB7IGFzc2lnbiwgaGFzT3duUHJvcGVydHkgfSA9IE9iamVjdDtcblxuZXhwb3J0IGludGVyZmFjZSBGZXRjaE1vcmVPcHRpb25zPFxuICBURGF0YSA9IGFueSxcbiAgVFZhcmlhYmxlcyA9IE9wZXJhdGlvblZhcmlhYmxlcyxcbj4ge1xuICB1cGRhdGVRdWVyeT86IChcbiAgICBwcmV2aW91c1F1ZXJ5UmVzdWx0OiBURGF0YSxcbiAgICBvcHRpb25zOiB7XG4gICAgICBmZXRjaE1vcmVSZXN1bHQ/OiBURGF0YTtcbiAgICAgIHZhcmlhYmxlcz86IFRWYXJpYWJsZXM7XG4gICAgfVxuICApID0+IFREYXRhO1xufVxuXG5pbnRlcmZhY2UgTGFzdDxURGF0YSwgVFZhcmlhYmxlcz4ge1xuICByZXN1bHQ6IEFwb2xsb1F1ZXJ5UmVzdWx0PFREYXRhPjtcbiAgdmFyaWFibGVzPzogVFZhcmlhYmxlcztcbiAgZXJyb3I/OiBBcG9sbG9FcnJvcjtcbn1cblxuZXhwb3J0IGNsYXNzIE9ic2VydmFibGVRdWVyeTxcbiAgVERhdGEgPSBhbnksXG4gIFRWYXJpYWJsZXMgZXh0ZW5kcyBPcGVyYXRpb25WYXJpYWJsZXMgPSBPcGVyYXRpb25WYXJpYWJsZXMsXG4+IGV4dGVuZHMgT2JzZXJ2YWJsZTxBcG9sbG9RdWVyeVJlc3VsdDxNYXliZU1hc2tlZDxURGF0YT4+PiB7XG4gIC8qKlxuICAgKiBAaW50ZXJuYWxcbiAgICogQSBzbG90IHVzZWQgYnkgdGhlIGB1c2VRdWVyeWAgaG9vayB0byBpbmRpY2F0ZSB0aGF0IGBjbGllbnQud2F0Y2hRdWVyeWBcbiAgICogc2hvdWxkIG5vdCByZWdpc3RlciB0aGUgcXVlcnkgaW1tZWRpYXRlbHksIGJ1dCBpbnN0ZWFkIHdhaXQgZm9yIHRoZSBxdWVyeSB0b1xuICAgKiBiZSBzdGFydGVkIHJlZ2lzdGVyZWQgd2l0aCB0aGUgYFF1ZXJ5TWFuYWdlcmAgd2hlbiBgdXNlU3luY0V4dGVybmFsU3RvcmVgXG4gICAqIGFjdGl2ZWx5IHN1YnNjcmliZXMgdG8gaXQuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBpbmFjdGl2ZU9uQ3JlYXRpb24gPSBuZXcgU2xvdDxib29sZWFuPigpO1xuXG4gIHB1YmxpYyByZWFkb25seSBvcHRpb25zOiBXYXRjaFF1ZXJ5T3B0aW9uczxUVmFyaWFibGVzLCBURGF0YT47XG4gIHB1YmxpYyByZWFkb25seSBxdWVyeUlkOiBzdHJpbmc7XG4gIHB1YmxpYyByZWFkb25seSBxdWVyeU5hbWU/OiBzdHJpbmc7XG5cbiAgLy8gVGhlIGBxdWVyeWAgY29tcHV0ZWQgcHJvcGVydHkgd2lsbCBhbHdheXMgcmVmbGVjdCB0aGUgZG9jdW1lbnQgdHJhbnNmb3JtZWRcbiAgLy8gYnkgdGhlIGxhc3QgcnVuIHF1ZXJ5LiBgdGhpcy5vcHRpb25zLnF1ZXJ5YCB3aWxsIGFsd2F5cyByZWZsZWN0IHRoZSByYXdcbiAgLy8gdW50cmFuc2Zvcm1lZCBxdWVyeSB0byBlbnN1cmUgZG9jdW1lbnQgdHJhbnNmb3JtcyB3aXRoIHJ1bnRpbWUgY29uZGl0aW9uYWxzXG4gIC8vIGFyZSBydW4gb24gdGhlIG9yaWdpbmFsIGRvY3VtZW50LlxuICBwdWJsaWMgZ2V0IHF1ZXJ5KCk6IFR5cGVkRG9jdW1lbnROb2RlPFREYXRhLCBUVmFyaWFibGVzPiB7XG4gICAgcmV0dXJuIHRoaXMubGFzdFF1ZXJ5IHx8IHRoaXMub3B0aW9ucy5xdWVyeTtcbiAgfVxuXG4gIC8vIENvbXB1dGVkIHNob3J0aGFuZCBmb3IgdGhpcy5vcHRpb25zLnZhcmlhYmxlcywgcHJlc2VydmVkIGZvclxuICAvLyBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eS5cbiAgLyoqXG4gICAqIEFuIG9iamVjdCBjb250YWluaW5nIHRoZSB2YXJpYWJsZXMgdGhhdCB3ZXJlIHByb3ZpZGVkIGZvciB0aGUgcXVlcnkuXG4gICAqL1xuICBwdWJsaWMgZ2V0IHZhcmlhYmxlcygpOiBUVmFyaWFibGVzIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLnZhcmlhYmxlcztcbiAgfVxuXG4gIHByaXZhdGUgaXNUb3JuRG93bjogYm9vbGVhbjtcbiAgcHJpdmF0ZSBxdWVyeU1hbmFnZXI6IFF1ZXJ5TWFuYWdlcjxhbnk+O1xuICBwcml2YXRlIG9ic2VydmVycyA9IG5ldyBTZXQ8XG4gICAgT2JzZXJ2ZXI8QXBvbGxvUXVlcnlSZXN1bHQ8TWF5YmVNYXNrZWQ8VERhdGE+Pj5cbiAgPigpO1xuICBwcml2YXRlIHN1YnNjcmlwdGlvbnMgPSBuZXcgU2V0PE9ic2VydmFibGVTdWJzY3JpcHRpb24+KCk7XG5cbiAgcHJpdmF0ZSB3YWl0Rm9yT3duUmVzdWx0OiBib29sZWFuO1xuICBwcml2YXRlIGxhc3Q/OiBMYXN0PFREYXRhLCBUVmFyaWFibGVzPjtcbiAgcHJpdmF0ZSBsYXN0UXVlcnk/OiBEb2N1bWVudE5vZGU7XG5cbiAgcHJpdmF0ZSBxdWVyeUluZm86IFF1ZXJ5SW5mbztcblxuICAvLyBXaGVuIHRoaXMuY29uY2FzdCBpcyBkZWZpbmVkLCB0aGlzLm9ic2VydmVyIGlzIHRoZSBPYnNlcnZlciBjdXJyZW50bHlcbiAgLy8gc3Vic2NyaWJlZCB0byB0aGF0IENvbmNhc3QuXG4gIHByaXZhdGUgY29uY2FzdD86IENvbmNhc3Q8QXBvbGxvUXVlcnlSZXN1bHQ8VERhdGE+PjtcbiAgcHJpdmF0ZSBvYnNlcnZlcj86IE9ic2VydmVyPEFwb2xsb1F1ZXJ5UmVzdWx0PFREYXRhPj47XG5cbiAgcHJpdmF0ZSBwb2xsaW5nSW5mbz86IHtcbiAgICBpbnRlcnZhbDogbnVtYmVyO1xuICAgIHRpbWVvdXQ6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+O1xuICB9O1xuXG4gIGNvbnN0cnVjdG9yKHtcbiAgICBxdWVyeU1hbmFnZXIsXG4gICAgcXVlcnlJbmZvLFxuICAgIG9wdGlvbnMsXG4gIH06IHtcbiAgICBxdWVyeU1hbmFnZXI6IFF1ZXJ5TWFuYWdlcjxhbnk+O1xuICAgIHF1ZXJ5SW5mbzogUXVlcnlJbmZvO1xuICAgIG9wdGlvbnM6IFdhdGNoUXVlcnlPcHRpb25zPFRWYXJpYWJsZXMsIFREYXRhPjtcbiAgfSkge1xuICAgIGxldCBzdGFydGVkSW5hY3RpdmUgPSBPYnNlcnZhYmxlUXVlcnkuaW5hY3RpdmVPbkNyZWF0aW9uLmdldFZhbHVlKCk7XG4gICAgc3VwZXIoKG9ic2VydmVyOiBPYnNlcnZlcjxBcG9sbG9RdWVyeVJlc3VsdDxNYXliZU1hc2tlZDxURGF0YT4+PikgPT4ge1xuICAgICAgaWYgKHN0YXJ0ZWRJbmFjdGl2ZSkge1xuICAgICAgICBxdWVyeU1hbmFnZXJbXCJxdWVyaWVzXCJdLnNldCh0aGlzLnF1ZXJ5SWQsIHF1ZXJ5SW5mbyk7XG4gICAgICAgIHN0YXJ0ZWRJbmFjdGl2ZSA9IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICAvLyBaZW4gT2JzZXJ2YWJsZSBoYXMgaXRzIG93biBlcnJvciBmdW5jdGlvbiwgc28gaW4gb3JkZXIgdG8gbG9nIGNvcnJlY3RseVxuICAgICAgLy8gd2UgbmVlZCB0byBwcm92aWRlIGEgY3VzdG9tIGVycm9yIGNhbGxiYWNrLlxuICAgICAgdHJ5IHtcbiAgICAgICAgdmFyIHN1Yk9ic2VydmVyID0gKG9ic2VydmVyIGFzIGFueSkuX3N1YnNjcmlwdGlvbi5fb2JzZXJ2ZXI7XG4gICAgICAgIGlmIChzdWJPYnNlcnZlciAmJiAhc3ViT2JzZXJ2ZXIuZXJyb3IpIHtcbiAgICAgICAgICBzdWJPYnNlcnZlci5lcnJvciA9IGRlZmF1bHRTdWJzY3JpcHRpb25PYnNlcnZlckVycm9yQ2FsbGJhY2s7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge31cblxuICAgICAgY29uc3QgZmlyc3QgPSAhdGhpcy5vYnNlcnZlcnMuc2l6ZTtcbiAgICAgIHRoaXMub2JzZXJ2ZXJzLmFkZChvYnNlcnZlcik7XG5cbiAgICAgIC8vIERlbGl2ZXIgbW9zdCByZWNlbnQgZXJyb3Igb3IgcmVzdWx0LlxuICAgICAgY29uc3QgbGFzdCA9IHRoaXMubGFzdDtcbiAgICAgIGlmIChsYXN0ICYmIGxhc3QuZXJyb3IpIHtcbiAgICAgICAgb2JzZXJ2ZXIuZXJyb3IgJiYgb2JzZXJ2ZXIuZXJyb3IobGFzdC5lcnJvcik7XG4gICAgICB9IGVsc2UgaWYgKGxhc3QgJiYgbGFzdC5yZXN1bHQpIHtcbiAgICAgICAgb2JzZXJ2ZXIubmV4dCAmJiBvYnNlcnZlci5uZXh0KHRoaXMubWFza1Jlc3VsdChsYXN0LnJlc3VsdCkpO1xuICAgICAgfVxuXG4gICAgICAvLyBJbml0aWF0ZSBvYnNlcnZhdGlvbiBvZiB0aGlzIHF1ZXJ5IGlmIGl0IGhhc24ndCBiZWVuIHJlcG9ydGVkIHRvXG4gICAgICAvLyB0aGUgUXVlcnlNYW5hZ2VyIHlldC5cbiAgICAgIGlmIChmaXJzdCkge1xuICAgICAgICAvLyBCbGluZGx5IGNhdGNoaW5nIGhlcmUgcHJldmVudHMgdW5oYW5kbGVkIHByb21pc2UgcmVqZWN0aW9ucyxcbiAgICAgICAgLy8gYW5kIGlzIHNhZmUgYmVjYXVzZSB0aGUgT2JzZXJ2YWJsZVF1ZXJ5IGhhbmRsZXMgdGhpcyBlcnJvciB3aXRoXG4gICAgICAgIC8vIHRoaXMub2JzZXJ2ZXIuZXJyb3IsIHNvIHdlJ3JlIG5vdCBqdXN0IHN3YWxsb3dpbmcgdGhlIGVycm9yIGJ5XG4gICAgICAgIC8vIGlnbm9yaW5nIGl0IGhlcmUuXG4gICAgICAgIHRoaXMucmVvYnNlcnZlKCkuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5vYnNlcnZlcnMuZGVsZXRlKG9ic2VydmVyKSAmJiAhdGhpcy5vYnNlcnZlcnMuc2l6ZSkge1xuICAgICAgICAgIHRoaXMudGVhckRvd25RdWVyeSgpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgLy8gcmVsYXRlZCBjbGFzc2VzXG4gICAgdGhpcy5xdWVyeUluZm8gPSBxdWVyeUluZm87XG4gICAgdGhpcy5xdWVyeU1hbmFnZXIgPSBxdWVyeU1hbmFnZXI7XG5cbiAgICAvLyBhY3RpdmUgc3RhdGVcbiAgICB0aGlzLndhaXRGb3JPd25SZXN1bHQgPSBza2lwQ2FjaGVEYXRhRm9yKG9wdGlvbnMuZmV0Y2hQb2xpY3kpO1xuICAgIHRoaXMuaXNUb3JuRG93biA9IGZhbHNlO1xuXG4gICAgdGhpcy5zdWJzY3JpYmVUb01vcmUgPSB0aGlzLnN1YnNjcmliZVRvTW9yZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMubWFza1Jlc3VsdCA9IHRoaXMubWFza1Jlc3VsdC5iaW5kKHRoaXMpO1xuXG4gICAgY29uc3Qge1xuICAgICAgd2F0Y2hRdWVyeTogeyBmZXRjaFBvbGljeTogZGVmYXVsdEZldGNoUG9saWN5ID0gXCJjYWNoZS1maXJzdFwiIH0gPSB7fSxcbiAgICB9ID0gcXVlcnlNYW5hZ2VyLmRlZmF1bHRPcHRpb25zO1xuXG4gICAgY29uc3Qge1xuICAgICAgZmV0Y2hQb2xpY3kgPSBkZWZhdWx0RmV0Y2hQb2xpY3ksXG4gICAgICAvLyBNYWtlIHN1cmUgd2UgZG9uJ3Qgc3RvcmUgXCJzdGFuZGJ5XCIgYXMgdGhlIGluaXRpYWxGZXRjaFBvbGljeS5cbiAgICAgIGluaXRpYWxGZXRjaFBvbGljeSA9IGZldGNoUG9saWN5ID09PSBcInN0YW5kYnlcIiA/IGRlZmF1bHRGZXRjaFBvbGljeSA6IChcbiAgICAgICAgZmV0Y2hQb2xpY3lcbiAgICAgICksXG4gICAgfSA9IG9wdGlvbnM7XG5cbiAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICAuLi5vcHRpb25zLFxuXG4gICAgICAvLyBSZW1lbWJlciB0aGUgaW5pdGlhbCBvcHRpb25zLmZldGNoUG9saWN5IHNvIHdlIGNhbiByZXZlcnQgYmFjayB0byB0aGlzXG4gICAgICAvLyBwb2xpY3kgd2hlbiB2YXJpYWJsZXMgY2hhbmdlLiBUaGlzIGluZm9ybWF0aW9uIGNhbiBhbHNvIGJlIHNwZWNpZmllZFxuICAgICAgLy8gKG9yIG92ZXJyaWRkZW4pIGJ5IHByb3ZpZGluZyBvcHRpb25zLmluaXRpYWxGZXRjaFBvbGljeSBleHBsaWNpdGx5LlxuICAgICAgaW5pdGlhbEZldGNoUG9saWN5LFxuXG4gICAgICAvLyBUaGlzIGVuc3VyZXMgdGhpcy5vcHRpb25zLmZldGNoUG9saWN5IGFsd2F5cyBoYXMgYSBzdHJpbmcgdmFsdWUsIGluXG4gICAgICAvLyBjYXNlIG9wdGlvbnMuZmV0Y2hQb2xpY3kgd2FzIG5vdCBwcm92aWRlZC5cbiAgICAgIGZldGNoUG9saWN5LFxuICAgIH07XG5cbiAgICB0aGlzLnF1ZXJ5SWQgPSBxdWVyeUluZm8ucXVlcnlJZCB8fCBxdWVyeU1hbmFnZXIuZ2VuZXJhdGVRdWVyeUlkKCk7XG5cbiAgICBjb25zdCBvcERlZiA9IGdldE9wZXJhdGlvbkRlZmluaXRpb24odGhpcy5xdWVyeSk7XG4gICAgdGhpcy5xdWVyeU5hbWUgPSBvcERlZiAmJiBvcERlZi5uYW1lICYmIG9wRGVmLm5hbWUudmFsdWU7XG4gIH1cblxuICBwdWJsaWMgcmVzdWx0KCk6IFByb21pc2U8QXBvbGxvUXVlcnlSZXN1bHQ8TWF5YmVNYXNrZWQ8VERhdGE+Pj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAvLyBUT0RPOiB0aGlzIGNvZGUgZG9lc27igJl0IGFjdHVhbGx5IG1ha2Ugc2Vuc2UgaW5zb2ZhciBhcyB0aGUgb2JzZXJ2ZXJcbiAgICAgIC8vIHdpbGwgbmV2ZXIgZXhpc3QgaW4gdGhpcy5vYnNlcnZlcnMgZHVlIGhvdyB6ZW4tb2JzZXJ2YWJsZSB3cmFwcyBvYnNlcnZhYmxlcy5cbiAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS96ZW5wYXJzaW5nL3plbi1vYnNlcnZhYmxlL2Jsb2IvbWFzdGVyL3NyYy9PYnNlcnZhYmxlLmpzI0wxNjlcbiAgICAgIGNvbnN0IG9ic2VydmVyOiBPYnNlcnZlcjxBcG9sbG9RdWVyeVJlc3VsdDxNYXliZU1hc2tlZDxURGF0YT4+PiA9IHtcbiAgICAgICAgbmV4dDogKHJlc3VsdCkgPT4ge1xuICAgICAgICAgIHJlc29sdmUocmVzdWx0KTtcblxuICAgICAgICAgIC8vIFN0b3AgdGhlIHF1ZXJ5IHdpdGhpbiB0aGUgUXVlcnlNYW5hZ2VyIGlmIHdlIGNhbiBiZWZvcmVcbiAgICAgICAgICAvLyB0aGlzIGZ1bmN0aW9uIHJldHVybnMuXG4gICAgICAgICAgLy9cbiAgICAgICAgICAvLyBXZSBkbyB0aGlzIGluIG9yZGVyIHRvIHByZXZlbnQgb2JzZXJ2ZXJzIHBpbGluZyB1cCB3aXRoaW5cbiAgICAgICAgICAvLyB0aGUgUXVlcnlNYW5hZ2VyLiBOb3RpY2UgdGhhdCB3ZSBvbmx5IGZ1bGx5IHVuc3Vic2NyaWJlXG4gICAgICAgICAgLy8gZnJvbSB0aGUgc3Vic2NyaXB0aW9uIGluIGEgc2V0VGltZW91dCguLi4sIDApICBjYWxsLiBUaGlzIGNhbGwgY2FuXG4gICAgICAgICAgLy8gYWN0dWFsbHkgYmUgaGFuZGxlZCBieSB0aGUgYnJvd3NlciBhdCBhIG11Y2ggbGF0ZXIgdGltZS4gSWYgcXVlcmllc1xuICAgICAgICAgIC8vIGFyZSBmaXJlZCBpbiB0aGUgbWVhbnRpbWUsIG9ic2VydmVycyB0aGF0IHNob3VsZCBoYXZlIGJlZW4gcmVtb3ZlZFxuICAgICAgICAgIC8vIGZyb20gdGhlIFF1ZXJ5TWFuYWdlciB3aWxsIGNvbnRpbnVlIHRvIGZpcmUsIGNhdXNpbmcgYW4gdW5uZWNlc3NhcnlcbiAgICAgICAgICAvLyBwZXJmb3JtYW5jZSBoaXQuXG4gICAgICAgICAgdGhpcy5vYnNlcnZlcnMuZGVsZXRlKG9ic2VydmVyKTtcbiAgICAgICAgICBpZiAoIXRoaXMub2JzZXJ2ZXJzLnNpemUpIHtcbiAgICAgICAgICAgIHRoaXMucXVlcnlNYW5hZ2VyLnJlbW92ZVF1ZXJ5KHRoaXMucXVlcnlJZCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICB9LCAwKTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6IHJlamVjdCxcbiAgICAgIH07XG4gICAgICBjb25zdCBzdWJzY3JpcHRpb24gPSB0aGlzLnN1YnNjcmliZShvYnNlcnZlcik7XG4gICAgfSk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIHB1YmxpYyByZXNldERpZmYoKSB7XG4gICAgdGhpcy5xdWVyeUluZm8ucmVzZXREaWZmKCk7XG4gIH1cblxuICBwcml2YXRlIGdldEN1cnJlbnRGdWxsUmVzdWx0KFxuICAgIHNhdmVBc0xhc3RSZXN1bHQgPSB0cnVlXG4gICk6IEFwb2xsb1F1ZXJ5UmVzdWx0PFREYXRhPiB7XG4gICAgLy8gVXNlIHRoZSBsYXN0IHJlc3VsdCBhcyBsb25nIGFzIHRoZSB2YXJpYWJsZXMgbWF0Y2ggdGhpcy52YXJpYWJsZXMuXG4gICAgY29uc3QgbGFzdFJlc3VsdCA9IHRoaXMuZ2V0TGFzdFJlc3VsdCh0cnVlKTtcblxuICAgIGNvbnN0IG5ldHdvcmtTdGF0dXMgPVxuICAgICAgdGhpcy5xdWVyeUluZm8ubmV0d29ya1N0YXR1cyB8fFxuICAgICAgKGxhc3RSZXN1bHQgJiYgbGFzdFJlc3VsdC5uZXR3b3JrU3RhdHVzKSB8fFxuICAgICAgTmV0d29ya1N0YXR1cy5yZWFkeTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IHtcbiAgICAgIC4uLmxhc3RSZXN1bHQsXG4gICAgICBsb2FkaW5nOiBpc05ldHdvcmtSZXF1ZXN0SW5GbGlnaHQobmV0d29ya1N0YXR1cyksXG4gICAgICBuZXR3b3JrU3RhdHVzLFxuICAgIH0gYXMgQXBvbGxvUXVlcnlSZXN1bHQ8VERhdGE+O1xuXG4gICAgY29uc3QgeyBmZXRjaFBvbGljeSA9IFwiY2FjaGUtZmlyc3RcIiB9ID0gdGhpcy5vcHRpb25zO1xuICAgIGlmIChcbiAgICAgIC8vIFRoZXNlIGZldGNoIHBvbGljaWVzIHNob3VsZCBuZXZlciBkZWxpdmVyIGRhdGEgZnJvbSB0aGUgY2FjaGUsIHVubGVzc1xuICAgICAgLy8gcmVkZWxpdmVyaW5nIGEgcHJldmlvdXNseSBkZWxpdmVyZWQgcmVzdWx0LlxuICAgICAgc2tpcENhY2hlRGF0YUZvcihmZXRjaFBvbGljeSkgfHxcbiAgICAgIC8vIElmIHRoaXMub3B0aW9ucy5xdWVyeSBoYXMgQGNsaWVudChhbHdheXM6IHRydWUpIGZpZWxkcywgd2UgY2Fubm90XG4gICAgICAvLyB0cnVzdCBkaWZmLnJlc3VsdCwgc2luY2UgaXQgd2FzIHJlYWQgZnJvbSB0aGUgY2FjaGUgd2l0aG91dCBydW5uaW5nXG4gICAgICAvLyBsb2NhbCByZXNvbHZlcnMgKGFuZCBpdCdzIHRvbyBsYXRlIHRvIHJ1biByZXNvbHZlcnMgbm93LCBzaW5jZSB3ZSBtdXN0XG4gICAgICAvLyByZXR1cm4gYSByZXN1bHQgc3luY2hyb25vdXNseSkuXG4gICAgICB0aGlzLnF1ZXJ5TWFuYWdlci5nZXREb2N1bWVudEluZm8odGhpcy5xdWVyeSkuaGFzRm9yY2VkUmVzb2x2ZXJzXG4gICAgKSB7XG4gICAgICAvLyBGYWxsIHRocm91Z2guXG4gICAgfSBlbHNlIGlmICh0aGlzLndhaXRGb3JPd25SZXN1bHQpIHtcbiAgICAgIC8vIFRoaXMgd291bGQgdXN1YWxseSBiZSBhIHBhcnQgb2YgYFF1ZXJ5SW5mby5nZXREaWZmKClgLlxuICAgICAgLy8gd2hpY2ggd2Ugc2tpcCBpbiB0aGUgd2FpdEZvck93blJlc3VsdCBjYXNlIHNpbmNlIHdlIGFyZSBub3RcbiAgICAgIC8vIGludGVyZXN0ZWQgaW4gdGhlIGRpZmYuXG4gICAgICB0aGlzLnF1ZXJ5SW5mb1tcInVwZGF0ZVdhdGNoXCJdKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGRpZmYgPSB0aGlzLnF1ZXJ5SW5mby5nZXREaWZmKCk7XG5cbiAgICAgIGlmIChkaWZmLmNvbXBsZXRlIHx8IHRoaXMub3B0aW9ucy5yZXR1cm5QYXJ0aWFsRGF0YSkge1xuICAgICAgICByZXN1bHQuZGF0YSA9IGRpZmYucmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBpZiAoZXF1YWwocmVzdWx0LmRhdGEsIHt9KSkge1xuICAgICAgICByZXN1bHQuZGF0YSA9IHZvaWQgMCBhcyBhbnk7XG4gICAgICB9XG5cbiAgICAgIGlmIChkaWZmLmNvbXBsZXRlKSB7XG4gICAgICAgIC8vIFNpbWlsYXIgdG8gc2V0dGluZyByZXN1bHQucGFydGlhbCB0byBmYWxzZSwgYnV0IHRha2luZyBhZHZhbnRhZ2Ugb2YgdGhlXG4gICAgICAgIC8vIGZhbHNpbmVzcyBvZiBtaXNzaW5nIGZpZWxkcy5cbiAgICAgICAgZGVsZXRlIHJlc3VsdC5wYXJ0aWFsO1xuXG4gICAgICAgIC8vIElmIHRoZSBkaWZmIGlzIGNvbXBsZXRlLCBhbmQgd2UncmUgdXNpbmcgYSBGZXRjaFBvbGljeSB0aGF0XG4gICAgICAgIC8vIHRlcm1pbmF0ZXMgYWZ0ZXIgYSBjb21wbGV0ZSBjYWNoZSByZWFkLCB3ZSBjYW4gYXNzdW1lIHRoZSBuZXh0IHJlc3VsdFxuICAgICAgICAvLyB3ZSByZWNlaXZlIHdpbGwgaGF2ZSBOZXR3b3JrU3RhdHVzLnJlYWR5IGFuZCAhbG9hZGluZy5cbiAgICAgICAgaWYgKFxuICAgICAgICAgIGRpZmYuY29tcGxldGUgJiZcbiAgICAgICAgICByZXN1bHQubmV0d29ya1N0YXR1cyA9PT0gTmV0d29ya1N0YXR1cy5sb2FkaW5nICYmXG4gICAgICAgICAgKGZldGNoUG9saWN5ID09PSBcImNhY2hlLWZpcnN0XCIgfHwgZmV0Y2hQb2xpY3kgPT09IFwiY2FjaGUtb25seVwiKVxuICAgICAgICApIHtcbiAgICAgICAgICByZXN1bHQubmV0d29ya1N0YXR1cyA9IE5ldHdvcmtTdGF0dXMucmVhZHk7XG4gICAgICAgICAgcmVzdWx0LmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdWx0LnBhcnRpYWwgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBXZSBuZWVkIHRvIGNoZWNrIGZvciBib3RoIGJvdGggYGVycm9yYCBhbmQgYGVycm9yc2AgZmllbGQgYmVjYXVzZSB0aGVyZVxuICAgICAgLy8gYXJlIGNhc2VzIHdoZXJlIHNvbWV0aW1lcyBgZXJyb3JgIGlzIHNldCwgYnV0IG5vdCBgZXJyb3JzYCBhbmRcbiAgICAgIC8vIHZpY2UtdmVyc2EuIFRoaXMgd2lsbCBiZSB1cGRhdGVkIGluIHRoZSBuZXh0IG1ham9yIHZlcnNpb24gd2hlblxuICAgICAgLy8gYGVycm9yc2AgaXMgZGVwcmVjYXRlZCBpbiBmYXZvciBvZiBgZXJyb3JgLlxuICAgICAgaWYgKFxuICAgICAgICByZXN1bHQubmV0d29ya1N0YXR1cyA9PT0gTmV0d29ya1N0YXR1cy5yZWFkeSAmJlxuICAgICAgICAocmVzdWx0LmVycm9yIHx8IHJlc3VsdC5lcnJvcnMpXG4gICAgICApIHtcbiAgICAgICAgcmVzdWx0Lm5ldHdvcmtTdGF0dXMgPSBOZXR3b3JrU3RhdHVzLmVycm9yO1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgIF9fREVWX18gJiZcbiAgICAgICAgIWRpZmYuY29tcGxldGUgJiZcbiAgICAgICAgIXRoaXMub3B0aW9ucy5wYXJ0aWFsUmVmZXRjaCAmJlxuICAgICAgICAhcmVzdWx0LmxvYWRpbmcgJiZcbiAgICAgICAgIXJlc3VsdC5kYXRhICYmXG4gICAgICAgICFyZXN1bHQuZXJyb3JcbiAgICAgICkge1xuICAgICAgICBsb2dNaXNzaW5nRmllbGRFcnJvcnMoZGlmZi5taXNzaW5nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoc2F2ZUFzTGFzdFJlc3VsdCkge1xuICAgICAgdGhpcy51cGRhdGVMYXN0UmVzdWx0KHJlc3VsdCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHB1YmxpYyBnZXRDdXJyZW50UmVzdWx0KFxuICAgIHNhdmVBc0xhc3RSZXN1bHQgPSB0cnVlXG4gICk6IEFwb2xsb1F1ZXJ5UmVzdWx0PE1heWJlTWFza2VkPFREYXRhPj4ge1xuICAgIHJldHVybiB0aGlzLm1hc2tSZXN1bHQodGhpcy5nZXRDdXJyZW50RnVsbFJlc3VsdChzYXZlQXNMYXN0UmVzdWx0KSk7XG4gIH1cblxuICAvLyBDb21wYXJlcyBuZXdSZXN1bHQgdG8gdGhlIHNuYXBzaG90IHdlIHRvb2sgb2YgdGhpcy5sYXN0UmVzdWx0IHdoZW4gaXQgd2FzXG4gIC8vIGZpcnN0IHJlY2VpdmVkLlxuICBwdWJsaWMgaXNEaWZmZXJlbnRGcm9tTGFzdFJlc3VsdChcbiAgICBuZXdSZXN1bHQ6IEFwb2xsb1F1ZXJ5UmVzdWx0PFREYXRhPixcbiAgICB2YXJpYWJsZXM/OiBUVmFyaWFibGVzXG4gICkge1xuICAgIGlmICghdGhpcy5sYXN0KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBjb25zdCBkb2N1bWVudEluZm8gPSB0aGlzLnF1ZXJ5TWFuYWdlci5nZXREb2N1bWVudEluZm8odGhpcy5xdWVyeSk7XG4gICAgY29uc3QgZGF0YU1hc2tpbmcgPSB0aGlzLnF1ZXJ5TWFuYWdlci5kYXRhTWFza2luZztcbiAgICBjb25zdCBxdWVyeSA9IGRhdGFNYXNraW5nID8gZG9jdW1lbnRJbmZvLm5vblJlYWN0aXZlUXVlcnkgOiB0aGlzLnF1ZXJ5O1xuXG4gICAgY29uc3QgcmVzdWx0SXNEaWZmZXJlbnQgPVxuICAgICAgZGF0YU1hc2tpbmcgfHwgZG9jdW1lbnRJbmZvLmhhc05vbnJlYWN0aXZlRGlyZWN0aXZlID9cbiAgICAgICAgIWVxdWFsQnlRdWVyeShxdWVyeSwgdGhpcy5sYXN0LnJlc3VsdCwgbmV3UmVzdWx0LCB0aGlzLnZhcmlhYmxlcylcbiAgICAgIDogIWVxdWFsKHRoaXMubGFzdC5yZXN1bHQsIG5ld1Jlc3VsdCk7XG5cbiAgICByZXR1cm4gKFxuICAgICAgcmVzdWx0SXNEaWZmZXJlbnQgfHwgKHZhcmlhYmxlcyAmJiAhZXF1YWwodGhpcy5sYXN0LnZhcmlhYmxlcywgdmFyaWFibGVzKSlcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRMYXN0PEsgZXh0ZW5kcyBrZXlvZiBMYXN0PFREYXRhLCBUVmFyaWFibGVzPj4oXG4gICAga2V5OiBLLFxuICAgIHZhcmlhYmxlc011c3RNYXRjaD86IGJvb2xlYW5cbiAgKSB7XG4gICAgY29uc3QgbGFzdCA9IHRoaXMubGFzdDtcbiAgICBpZiAoXG4gICAgICBsYXN0ICYmXG4gICAgICBsYXN0W2tleV0gJiZcbiAgICAgICghdmFyaWFibGVzTXVzdE1hdGNoIHx8IGVxdWFsKGxhc3QudmFyaWFibGVzLCB0aGlzLnZhcmlhYmxlcykpXG4gICAgKSB7XG4gICAgICByZXR1cm4gbGFzdFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXRMYXN0UmVzdWx0KFxuICAgIHZhcmlhYmxlc011c3RNYXRjaD86IGJvb2xlYW5cbiAgKTogQXBvbGxvUXVlcnlSZXN1bHQ8VERhdGE+IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5nZXRMYXN0KFwicmVzdWx0XCIsIHZhcmlhYmxlc011c3RNYXRjaCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0TGFzdEVycm9yKHZhcmlhYmxlc011c3RNYXRjaD86IGJvb2xlYW4pOiBBcG9sbG9FcnJvciB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0TGFzdChcImVycm9yXCIsIHZhcmlhYmxlc011c3RNYXRjaCk7XG4gIH1cblxuICBwdWJsaWMgcmVzZXRMYXN0UmVzdWx0cygpOiB2b2lkIHtcbiAgICBkZWxldGUgdGhpcy5sYXN0O1xuICAgIHRoaXMuaXNUb3JuRG93biA9IGZhbHNlO1xuICB9XG5cbiAgcHVibGljIHJlc2V0UXVlcnlTdG9yZUVycm9ycygpIHtcbiAgICB0aGlzLnF1ZXJ5TWFuYWdlci5yZXNldEVycm9ycyh0aGlzLnF1ZXJ5SWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSB0aGUgdmFyaWFibGVzIG9mIHRoaXMgb2JzZXJ2YWJsZSBxdWVyeSwgYW5kIGZldGNoIHRoZSBuZXcgcmVzdWx0cy5cbiAgICogVGhpcyBtZXRob2Qgc2hvdWxkIGJlIHByZWZlcnJlZCBvdmVyIGBzZXRWYXJpYWJsZXNgIGluIG1vc3QgdXNlIGNhc2VzLlxuICAgKlxuICAgKiBAcGFyYW0gdmFyaWFibGVzIC0gVGhlIG5ldyBzZXQgb2YgdmFyaWFibGVzLiBJZiB0aGVyZSBhcmUgbWlzc2luZyB2YXJpYWJsZXMsXG4gICAqIHRoZSBwcmV2aW91cyB2YWx1ZXMgb2YgdGhvc2UgdmFyaWFibGVzIHdpbGwgYmUgdXNlZC5cbiAgICovXG4gIHB1YmxpYyByZWZldGNoKFxuICAgIHZhcmlhYmxlcz86IFBhcnRpYWw8VFZhcmlhYmxlcz5cbiAgKTogUHJvbWlzZTxBcG9sbG9RdWVyeVJlc3VsdDxNYXliZU1hc2tlZDxURGF0YT4+PiB7XG4gICAgY29uc3QgcmVvYnNlcnZlT3B0aW9uczogUGFydGlhbDxXYXRjaFF1ZXJ5T3B0aW9uczxUVmFyaWFibGVzLCBURGF0YT4+ID0ge1xuICAgICAgLy8gQWx3YXlzIGRpc2FibGUgcG9sbGluZyBmb3IgcmVmZXRjaGVzLlxuICAgICAgcG9sbEludGVydmFsOiAwLFxuICAgIH07XG5cbiAgICAvLyBVbmxlc3MgdGhlIHByb3ZpZGVkIGZldGNoUG9saWN5IGFsd2F5cyBjb25zdWx0cyB0aGUgbmV0d29ya1xuICAgIC8vIChuby1jYWNoZSwgbmV0d29yay1vbmx5LCBvciBjYWNoZS1hbmQtbmV0d29yayksIG92ZXJyaWRlIGl0IHdpdGhcbiAgICAvLyBuZXR3b3JrLW9ubHkgdG8gZm9yY2UgdGhlIHJlZmV0Y2ggZm9yIHRoaXMgZmV0Y2hRdWVyeSBjYWxsLlxuICAgIGNvbnN0IHsgZmV0Y2hQb2xpY3kgfSA9IHRoaXMub3B0aW9ucztcbiAgICBpZiAoZmV0Y2hQb2xpY3kgPT09IFwibm8tY2FjaGVcIikge1xuICAgICAgcmVvYnNlcnZlT3B0aW9ucy5mZXRjaFBvbGljeSA9IFwibm8tY2FjaGVcIjtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVvYnNlcnZlT3B0aW9ucy5mZXRjaFBvbGljeSA9IFwibmV0d29yay1vbmx5XCI7XG4gICAgfVxuXG4gICAgaWYgKF9fREVWX18gJiYgdmFyaWFibGVzICYmIGhhc093blByb3BlcnR5LmNhbGwodmFyaWFibGVzLCBcInZhcmlhYmxlc1wiKSkge1xuICAgICAgY29uc3QgcXVlcnlEZWYgPSBnZXRRdWVyeURlZmluaXRpb24odGhpcy5xdWVyeSk7XG4gICAgICBjb25zdCB2YXJzID0gcXVlcnlEZWYudmFyaWFibGVEZWZpbml0aW9ucztcbiAgICAgIGlmICghdmFycyB8fCAhdmFycy5zb21lKCh2KSA9PiB2LnZhcmlhYmxlLm5hbWUudmFsdWUgPT09IFwidmFyaWFibGVzXCIpKSB7XG4gICAgICAgIGludmFyaWFudC53YXJuKFxuICAgICAgICAgIGBDYWxsZWQgcmVmZXRjaCglbykgZm9yIHF1ZXJ5ICVvLCB3aGljaCBkb2VzIG5vdCBkZWNsYXJlIGEgJHZhcmlhYmxlcyB2YXJpYWJsZS5cbkRpZCB5b3UgbWVhbiB0byBjYWxsIHJlZmV0Y2godmFyaWFibGVzKSBpbnN0ZWFkIG9mIHJlZmV0Y2goeyB2YXJpYWJsZXMgfSk/YCxcbiAgICAgICAgICB2YXJpYWJsZXMsXG4gICAgICAgICAgcXVlcnlEZWYubmFtZT8udmFsdWUgfHwgcXVlcnlEZWZcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodmFyaWFibGVzICYmICFlcXVhbCh0aGlzLm9wdGlvbnMudmFyaWFibGVzLCB2YXJpYWJsZXMpKSB7XG4gICAgICAvLyBVcGRhdGUgdGhlIGV4aXN0aW5nIG9wdGlvbnMgd2l0aCBuZXcgdmFyaWFibGVzXG4gICAgICByZW9ic2VydmVPcHRpb25zLnZhcmlhYmxlcyA9IHRoaXMub3B0aW9ucy52YXJpYWJsZXMgPSB7XG4gICAgICAgIC4uLnRoaXMub3B0aW9ucy52YXJpYWJsZXMsXG4gICAgICAgIC4uLnZhcmlhYmxlcyxcbiAgICAgIH0gYXMgVFZhcmlhYmxlcztcbiAgICB9XG5cbiAgICB0aGlzLnF1ZXJ5SW5mby5yZXNldExhc3RXcml0ZSgpO1xuICAgIHJldHVybiB0aGlzLnJlb2JzZXJ2ZShyZW9ic2VydmVPcHRpb25zLCBOZXR3b3JrU3RhdHVzLnJlZmV0Y2gpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgZnVuY3Rpb24gdGhhdCBoZWxwcyB5b3UgZmV0Y2ggdGhlIG5leHQgc2V0IG9mIHJlc3VsdHMgZm9yIGEgW3BhZ2luYXRlZCBsaXN0IGZpZWxkXShodHRwczovL3d3dy5hcG9sbG9ncmFwaHFsLmNvbS9kb2NzL3JlYWN0L3BhZ2luYXRpb24vY29yZS1hcGkvKS5cbiAgICovXG4gIHB1YmxpYyBmZXRjaE1vcmU8XG4gICAgVEZldGNoRGF0YSA9IFREYXRhLFxuICAgIFRGZXRjaFZhcnMgZXh0ZW5kcyBPcGVyYXRpb25WYXJpYWJsZXMgPSBUVmFyaWFibGVzLFxuICA+KFxuICAgIGZldGNoTW9yZU9wdGlvbnM6IEZldGNoTW9yZVF1ZXJ5T3B0aW9uczxURmV0Y2hWYXJzLCBURmV0Y2hEYXRhPiAmIHtcbiAgICAgIHVwZGF0ZVF1ZXJ5PzogKFxuICAgICAgICBwcmV2aW91c1F1ZXJ5UmVzdWx0OiBVbm1hc2tlZDxURGF0YT4sXG4gICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICBmZXRjaE1vcmVSZXN1bHQ6IFVubWFza2VkPFRGZXRjaERhdGE+O1xuICAgICAgICAgIHZhcmlhYmxlczogVEZldGNoVmFycztcbiAgICAgICAgfVxuICAgICAgKSA9PiBVbm1hc2tlZDxURGF0YT47XG4gICAgfVxuICApOiBQcm9taXNlPEFwb2xsb1F1ZXJ5UmVzdWx0PE1heWJlTWFza2VkPFRGZXRjaERhdGE+Pj4ge1xuICAgIGNvbnN0IGNvbWJpbmVkT3B0aW9ucyA9IHtcbiAgICAgIC4uLihmZXRjaE1vcmVPcHRpb25zLnF1ZXJ5ID8gZmV0Y2hNb3JlT3B0aW9ucyA6IChcbiAgICAgICAge1xuICAgICAgICAgIC4uLnRoaXMub3B0aW9ucyxcbiAgICAgICAgICBxdWVyeTogdGhpcy5vcHRpb25zLnF1ZXJ5LFxuICAgICAgICAgIC4uLmZldGNoTW9yZU9wdGlvbnMsXG4gICAgICAgICAgdmFyaWFibGVzOiB7XG4gICAgICAgICAgICAuLi50aGlzLm9wdGlvbnMudmFyaWFibGVzLFxuICAgICAgICAgICAgLi4uZmV0Y2hNb3JlT3B0aW9ucy52YXJpYWJsZXMsXG4gICAgICAgICAgfSxcbiAgICAgICAgfVxuICAgICAgKSksXG4gICAgICAvLyBUaGUgZmV0Y2hNb3JlIHJlcXVlc3QgZ29lcyBpbW1lZGlhdGVseSB0byB0aGUgbmV0d29yayBhbmQgZG9lc1xuICAgICAgLy8gbm90IGF1dG9tYXRpY2FsbHkgd3JpdGUgaXRzIHJlc3VsdCB0byB0aGUgY2FjaGUgKGhlbmNlIG5vLWNhY2hlXG4gICAgICAvLyBpbnN0ZWFkIG9mIG5ldHdvcmstb25seSksIGJlY2F1c2Ugd2UgYWxsb3cgdGhlIGNhbGxlciBvZlxuICAgICAgLy8gZmV0Y2hNb3JlIHRvIHByb3ZpZGUgYW4gdXBkYXRlUXVlcnkgY2FsbGJhY2sgdGhhdCBkZXRlcm1pbmVzIGhvd1xuICAgICAgLy8gdGhlIGRhdGEgZ2V0cyB3cml0dGVuIHRvIHRoZSBjYWNoZS5cbiAgICAgIGZldGNoUG9saWN5OiBcIm5vLWNhY2hlXCIsXG4gICAgfSBhcyBXYXRjaFF1ZXJ5T3B0aW9uczxURmV0Y2hWYXJzLCBURmV0Y2hEYXRhPjtcblxuICAgIGNvbWJpbmVkT3B0aW9ucy5xdWVyeSA9IHRoaXMudHJhbnNmb3JtRG9jdW1lbnQoY29tYmluZWRPcHRpb25zLnF1ZXJ5KTtcblxuICAgIGNvbnN0IHFpZCA9IHRoaXMucXVlcnlNYW5hZ2VyLmdlbmVyYXRlUXVlcnlJZCgpO1xuXG4gICAgLy8gSWYgYSB0ZW1wb3JhcnkgcXVlcnkgaXMgcGFzc2VkIHRvIGBmZXRjaE1vcmVgLCB3ZSBkb24ndCB3YW50IHRvIHN0b3JlXG4gICAgLy8gaXQgYXMgdGhlIGxhc3QgcXVlcnkgcmVzdWx0IHNpbmNlIGl0IG1heSBiZSBhbiBvcHRpbWl6ZWQgcXVlcnkgZm9yXG4gICAgLy8gcGFnaW5hdGlvbi4gV2Ugd2lsbCBob3dldmVyIHJ1biB0aGUgdHJhbnNmb3JtcyBvbiB0aGUgb3JpZ2luYWwgZG9jdW1lbnRcbiAgICAvLyBhcyB3ZWxsIGFzIHRoZSBkb2N1bWVudCBwYXNzZWQgaW4gYGZldGNoTW9yZU9wdGlvbnNgIHRvIGVuc3VyZSB0aGUgY2FjaGVcbiAgICAvLyB1c2VzIHRoZSBtb3N0IHVwLXRvLWRhdGUgZG9jdW1lbnQgd2hpY2ggbWF5IHJlbHkgb24gcnVudGltZSBjb25kaXRpb25hbHMuXG4gICAgdGhpcy5sYXN0UXVlcnkgPVxuICAgICAgZmV0Y2hNb3JlT3B0aW9ucy5xdWVyeSA/XG4gICAgICAgIHRoaXMudHJhbnNmb3JtRG9jdW1lbnQodGhpcy5vcHRpb25zLnF1ZXJ5KVxuICAgICAgOiBjb21iaW5lZE9wdGlvbnMucXVlcnk7XG5cbiAgICAvLyBTaW11bGF0ZSBhIGxvYWRpbmcgcmVzdWx0IGZvciB0aGUgb3JpZ2luYWwgcXVlcnkgd2l0aFxuICAgIC8vIHJlc3VsdC5uZXR3b3JrU3RhdHVzID09PSBOZXR3b3JrU3RhdHVzLmZldGNoTW9yZS5cbiAgICBjb25zdCB7IHF1ZXJ5SW5mbyB9ID0gdGhpcztcbiAgICBjb25zdCBvcmlnaW5hbE5ldHdvcmtTdGF0dXMgPSBxdWVyeUluZm8ubmV0d29ya1N0YXR1cztcbiAgICBxdWVyeUluZm8ubmV0d29ya1N0YXR1cyA9IE5ldHdvcmtTdGF0dXMuZmV0Y2hNb3JlO1xuICAgIGlmIChjb21iaW5lZE9wdGlvbnMubm90aWZ5T25OZXR3b3JrU3RhdHVzQ2hhbmdlKSB7XG4gICAgICB0aGlzLm9ic2VydmUoKTtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVkUXVlcnlTZXQgPSBuZXcgU2V0PERvY3VtZW50Tm9kZT4oKTtcblxuICAgIGNvbnN0IHVwZGF0ZVF1ZXJ5ID0gZmV0Y2hNb3JlT3B0aW9ucz8udXBkYXRlUXVlcnk7XG4gICAgY29uc3QgaXNDYWNoZWQgPSB0aGlzLm9wdGlvbnMuZmV0Y2hQb2xpY3kgIT09IFwibm8tY2FjaGVcIjtcblxuICAgIGlmICghaXNDYWNoZWQpIHtcbiAgICAgIGludmFyaWFudChcbiAgICAgICAgdXBkYXRlUXVlcnksXG4gICAgICAgIFwiWW91IG11c3QgcHJvdmlkZSBhbiBgdXBkYXRlUXVlcnlgIGZ1bmN0aW9uIHdoZW4gdXNpbmcgYGZldGNoTW9yZWAgd2l0aCBhIGBuby1jYWNoZWAgZmV0Y2ggcG9saWN5LlwiXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnF1ZXJ5TWFuYWdlclxuICAgICAgLmZldGNoUXVlcnkocWlkLCBjb21iaW5lZE9wdGlvbnMsIE5ldHdvcmtTdGF0dXMuZmV0Y2hNb3JlKVxuICAgICAgLnRoZW4oKGZldGNoTW9yZVJlc3VsdCkgPT4ge1xuICAgICAgICB0aGlzLnF1ZXJ5TWFuYWdlci5yZW1vdmVRdWVyeShxaWQpO1xuXG4gICAgICAgIGlmIChxdWVyeUluZm8ubmV0d29ya1N0YXR1cyA9PT0gTmV0d29ya1N0YXR1cy5mZXRjaE1vcmUpIHtcbiAgICAgICAgICBxdWVyeUluZm8ubmV0d29ya1N0YXR1cyA9IG9yaWdpbmFsTmV0d29ya1N0YXR1cztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc0NhY2hlZCkge1xuICAgICAgICAgIC8vIFBlcmZvcm1pbmcgdGhpcyBjYWNoZSB1cGRhdGUgaW5zaWRlIGEgY2FjaGUuYmF0Y2ggdHJhbnNhY3Rpb24gZW5zdXJlc1xuICAgICAgICAgIC8vIGFueSBhZmZlY3RlZCBjYWNoZS53YXRjaCB3YXRjaGVycyBhcmUgbm90aWZpZWQgYXQgbW9zdCBvbmNlIGFib3V0IGFueVxuICAgICAgICAgIC8vIHVwZGF0ZXMuIE1vc3Qgd2F0Y2hlcnMgd2lsbCBiZSB1c2luZyB0aGUgUXVlcnlJbmZvIGNsYXNzLCB3aGljaFxuICAgICAgICAgIC8vIHJlc3BvbmRzIHRvIG5vdGlmaWNhdGlvbnMgYnkgY2FsbGluZyByZW9ic2VydmVDYWNoZUZpcnN0IHRvIGRlbGl2ZXJcbiAgICAgICAgICAvLyBmZXRjaE1vcmUgY2FjaGUgcmVzdWx0cyBiYWNrIHRvIHRoaXMgT2JzZXJ2YWJsZVF1ZXJ5LlxuICAgICAgICAgIHRoaXMucXVlcnlNYW5hZ2VyLmNhY2hlLmJhdGNoKHtcbiAgICAgICAgICAgIHVwZGF0ZTogKGNhY2hlKSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IHsgdXBkYXRlUXVlcnkgfSA9IGZldGNoTW9yZU9wdGlvbnM7XG4gICAgICAgICAgICAgIGlmICh1cGRhdGVRdWVyeSkge1xuICAgICAgICAgICAgICAgIGNhY2hlLnVwZGF0ZVF1ZXJ5KFxuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBxdWVyeTogdGhpcy5xdWVyeSxcbiAgICAgICAgICAgICAgICAgICAgdmFyaWFibGVzOiB0aGlzLnZhcmlhYmxlcyxcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuUGFydGlhbERhdGE6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIG9wdGltaXN0aWM6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIChwcmV2aW91cykgPT5cbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlUXVlcnkocHJldmlvdXMhIGFzIGFueSwge1xuICAgICAgICAgICAgICAgICAgICAgIGZldGNoTW9yZVJlc3VsdDogZmV0Y2hNb3JlUmVzdWx0LmRhdGEgYXMgYW55LFxuICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlczogY29tYmluZWRPcHRpb25zLnZhcmlhYmxlcyBhcyBURmV0Y2hWYXJzLFxuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgd2UncmUgdXNpbmcgYSBmaWVsZCBwb2xpY3kgaW5zdGVhZCBvZiB1cGRhdGVRdWVyeSwgdGhlIG9ubHlcbiAgICAgICAgICAgICAgICAvLyB0aGluZyB3ZSBuZWVkIHRvIGRvIGlzIHdyaXRlIHRoZSBuZXcgZGF0YSB0byB0aGUgY2FjaGUgdXNpbmdcbiAgICAgICAgICAgICAgICAvLyBjb21iaW5lZE9wdGlvbnMudmFyaWFibGVzIChpbnN0ZWFkIG9mIHRoaXMudmFyaWFibGVzLCB3aGljaCBpc1xuICAgICAgICAgICAgICAgIC8vIHdoYXQgdGhpcy51cGRhdGVRdWVyeSB1c2VzLCBiZWNhdXNlIGl0IHdvcmtzIGJ5IGFidXNpbmcgdGhlXG4gICAgICAgICAgICAgICAgLy8gb3JpZ2luYWwgZmllbGQgdmFsdWUsIGtleWVkIGJ5IHRoZSBvcmlnaW5hbCB2YXJpYWJsZXMpLlxuICAgICAgICAgICAgICAgIGNhY2hlLndyaXRlUXVlcnkoe1xuICAgICAgICAgICAgICAgICAgcXVlcnk6IGNvbWJpbmVkT3B0aW9ucy5xdWVyeSxcbiAgICAgICAgICAgICAgICAgIHZhcmlhYmxlczogY29tYmluZWRPcHRpb25zLnZhcmlhYmxlcyxcbiAgICAgICAgICAgICAgICAgIGRhdGE6IGZldGNoTW9yZVJlc3VsdC5kYXRhIGFzIFVubWFza2VkPFRGZXRjaERhdGE+LFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBvbldhdGNoVXBkYXRlZDogKHdhdGNoKSA9PiB7XG4gICAgICAgICAgICAgIC8vIFJlY29yZCB0aGUgRG9jdW1lbnROb2RlIGFzc29jaWF0ZWQgd2l0aCBhbnkgd2F0Y2hlZCBxdWVyeSB3aG9zZVxuICAgICAgICAgICAgICAvLyBkYXRhIHdlcmUgdXBkYXRlZCBieSB0aGUgY2FjaGUgd3JpdGVzIGFib3ZlLlxuICAgICAgICAgICAgICB1cGRhdGVkUXVlcnlTZXQuYWRkKHdhdGNoLnF1ZXJ5KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gVGhlcmUgaXMgYSBwb3NzaWJpbGl0eSBgbGFzdFJlc3VsdGAgbWF5IG5vdCBiZSBzZXQgd2hlblxuICAgICAgICAgIC8vIGBmZXRjaE1vcmVgIGlzIGNhbGxlZCB3aGljaCB3b3VsZCBjYXVzZSB0aGlzIHRvIGNyYXNoLiBUaGlzIHNob3VsZFxuICAgICAgICAgIC8vIG9ubHkgaGFwcGVuIGlmIHdlIGhhdmVuJ3QgcHJldmlvdXNseSByZXBvcnRlZCBhIHJlc3VsdC4gV2UgZG9uJ3RcbiAgICAgICAgICAvLyBxdWl0ZSBrbm93IHdoYXQgdGhlIHJpZ2h0IGJlaGF2aW9yIHNob3VsZCBiZSBoZXJlIHNpbmNlIHRoaXMgYmxvY2tcbiAgICAgICAgICAvLyBvZiBjb2RlIHJ1bnMgYWZ0ZXIgdGhlIGZldGNoIHJlc3VsdCBoYXMgZXhlY3V0ZWQgb24gdGhlIG5ldHdvcmsuXG4gICAgICAgICAgLy8gV2UgcGxhbiB0byBsZXQgaXQgY3Jhc2ggaW4gdGhlIG1lYW50aW1lLlxuICAgICAgICAgIC8vXG4gICAgICAgICAgLy8gSWYgd2UgZ2V0IGJ1ZyByZXBvcnRzIGR1ZSB0byB0aGUgYGRhdGFgIHByb3BlcnR5IGFjY2VzcyBvblxuICAgICAgICAgIC8vIHVuZGVmaW5lZCwgdGhpcyBzaG91bGQgZ2l2ZSB1cyBhIHJlYWwtd29ybGQgc2NlbmFyaW8gdGhhdCB3ZSBjYW5cbiAgICAgICAgICAvLyB1c2UgdG8gdGVzdCBhZ2FpbnN0IGFuZCBkZXRlcm1pbmUgdGhlIHJpZ2h0IGJlaGF2aW9yLiBJZiB3ZSBkbyBlbmRcbiAgICAgICAgICAvLyB1cCBjaGFuZ2luZyB0aGlzIGJlaGF2aW9yLCB0aGlzIG1heSByZXF1aXJlLCBmb3IgZXhhbXBsZSwgYW5cbiAgICAgICAgICAvLyBhZGp1c3RtZW50IHRvIHRoZSB0eXBlcyBvbiBgdXBkYXRlUXVlcnlgIHNpbmNlIHRoYXQgZnVuY3Rpb25cbiAgICAgICAgICAvLyBleHBlY3RzIHRoYXQgdGhlIGZpcnN0IGFyZ3VtZW50IGFsd2F5cyBjb250YWlucyBwcmV2aW91cyByZXN1bHRcbiAgICAgICAgICAvLyBkYXRhLCBidXQgbm90IGB1bmRlZmluZWRgLlxuICAgICAgICAgIGNvbnN0IGxhc3RSZXN1bHQgPSB0aGlzLmdldExhc3QoXCJyZXN1bHRcIikhO1xuICAgICAgICAgIGNvbnN0IGRhdGEgPSB1cGRhdGVRdWVyeSEobGFzdFJlc3VsdC5kYXRhIGFzIFVubWFza2VkPFREYXRhPiwge1xuICAgICAgICAgICAgZmV0Y2hNb3JlUmVzdWx0OiBmZXRjaE1vcmVSZXN1bHQuZGF0YSBhcyBVbm1hc2tlZDxURmV0Y2hEYXRhPixcbiAgICAgICAgICAgIHZhcmlhYmxlczogY29tYmluZWRPcHRpb25zLnZhcmlhYmxlcyBhcyBURmV0Y2hWYXJzLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgdGhpcy5yZXBvcnRSZXN1bHQoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIC4uLmxhc3RSZXN1bHQsXG4gICAgICAgICAgICAgIG5ldHdvcmtTdGF0dXM6IG9yaWdpbmFsTmV0d29ya1N0YXR1cyEsXG4gICAgICAgICAgICAgIGxvYWRpbmc6IGlzTmV0d29ya1JlcXVlc3RJbkZsaWdodChvcmlnaW5hbE5ldHdvcmtTdGF0dXMpLFxuICAgICAgICAgICAgICBkYXRhOiBkYXRhIGFzIFREYXRhLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRoaXMudmFyaWFibGVzXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLm1hc2tSZXN1bHQoZmV0Y2hNb3JlUmVzdWx0KTtcbiAgICAgIH0pXG4gICAgICAuZmluYWxseSgoKSA9PiB7XG4gICAgICAgIC8vIEluIGNhc2UgdGhlIGNhY2hlIHdyaXRlcyBhYm92ZSBkaWQgbm90IGdlbmVyYXRlIGEgYnJvYWRjYXN0XG4gICAgICAgIC8vIG5vdGlmaWNhdGlvbiAod2hpY2ggd291bGQgaGF2ZSBiZWVuIGludGVyY2VwdGVkIGJ5IG9uV2F0Y2hVcGRhdGVkKSxcbiAgICAgICAgLy8gbGlrZWx5IGJlY2F1c2UgdGhlIHdyaXR0ZW4gZGF0YSB3ZXJlIHRoZSBzYW1lIGFzIHdoYXQgd2FzIGFscmVhZHkgaW5cbiAgICAgICAgLy8gdGhlIGNhY2hlLCB3ZSBzdGlsbCB3YW50IGZldGNoTW9yZSB0byBkZWxpdmVyIGl0cyBmaW5hbCBsb2FkaW5nOmZhbHNlXG4gICAgICAgIC8vIHJlc3VsdCB3aXRoIHRoZSB1bmNoYW5nZWQgZGF0YS5cbiAgICAgICAgaWYgKGlzQ2FjaGVkICYmICF1cGRhdGVkUXVlcnlTZXQuaGFzKHRoaXMucXVlcnkpKSB7XG4gICAgICAgICAgdGhpcy5yZW9ic2VydmVDYWNoZUZpcnN0KCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgLy8gWFhYIHRoZSBzdWJzY3JpcHRpb24gdmFyaWFibGVzIGFyZSBzZXBhcmF0ZSBmcm9tIHRoZSBxdWVyeSB2YXJpYWJsZXMuXG4gIC8vIGlmIHlvdSB3YW50IHRvIHVwZGF0ZSBzdWJzY3JpcHRpb24gdmFyaWFibGVzLCByaWdodCBub3cgeW91IGhhdmUgdG8gZG8gdGhhdCBzZXBhcmF0ZWx5LFxuICAvLyBhbmQgeW91IGNhbiBvbmx5IGRvIGl0IGJ5IHN0b3BwaW5nIHRoZSBzdWJzY3JpcHRpb24gYW5kIHRoZW4gc3Vic2NyaWJpbmcgYWdhaW4gd2l0aCBuZXcgdmFyaWFibGVzLlxuICAvKipcbiAgICogQSBmdW5jdGlvbiB0aGF0IGVuYWJsZXMgeW91IHRvIGV4ZWN1dGUgYSBbc3Vic2NyaXB0aW9uXShodHRwczovL3d3dy5hcG9sbG9ncmFwaHFsLmNvbS9kb2NzL3JlYWN0L2RhdGEvc3Vic2NyaXB0aW9ucy8pLCB1c3VhbGx5IHRvIHN1YnNjcmliZSB0byBzcGVjaWZpYyBmaWVsZHMgdGhhdCB3ZXJlIGluY2x1ZGVkIGluIHRoZSBxdWVyeS5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiByZXR1cm5zIF9hbm90aGVyXyBmdW5jdGlvbiB0aGF0IHlvdSBjYW4gY2FsbCB0byB0ZXJtaW5hdGUgdGhlIHN1YnNjcmlwdGlvbi5cbiAgICovXG4gIHB1YmxpYyBzdWJzY3JpYmVUb01vcmU8XG4gICAgVFN1YnNjcmlwdGlvbkRhdGEgPSBURGF0YSxcbiAgICBUU3Vic2NyaXB0aW9uVmFyaWFibGVzIGV4dGVuZHMgT3BlcmF0aW9uVmFyaWFibGVzID0gVFZhcmlhYmxlcyxcbiAgPihcbiAgICBvcHRpb25zOiBTdWJzY3JpYmVUb01vcmVPcHRpb25zPFxuICAgICAgVERhdGEsXG4gICAgICBUU3Vic2NyaXB0aW9uVmFyaWFibGVzLFxuICAgICAgVFN1YnNjcmlwdGlvbkRhdGEsXG4gICAgICBUVmFyaWFibGVzXG4gICAgPlxuICApOiAoKSA9PiB2b2lkIHtcbiAgICBjb25zdCBzdWJzY3JpcHRpb24gPSB0aGlzLnF1ZXJ5TWFuYWdlclxuICAgICAgLnN0YXJ0R3JhcGhRTFN1YnNjcmlwdGlvbih7XG4gICAgICAgIHF1ZXJ5OiBvcHRpb25zLmRvY3VtZW50LFxuICAgICAgICB2YXJpYWJsZXM6IG9wdGlvbnMudmFyaWFibGVzLFxuICAgICAgICBjb250ZXh0OiBvcHRpb25zLmNvbnRleHQsXG4gICAgICB9KVxuICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgIG5leHQ6IChzdWJzY3JpcHRpb25EYXRhOiB7IGRhdGE6IFVubWFza2VkPFRTdWJzY3JpcHRpb25EYXRhPiB9KSA9PiB7XG4gICAgICAgICAgY29uc3QgeyB1cGRhdGVRdWVyeSB9ID0gb3B0aW9ucztcbiAgICAgICAgICBpZiAodXBkYXRlUXVlcnkpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlUXVlcnkoKHByZXZpb3VzLCB1cGRhdGVPcHRpb25zKSA9PlxuICAgICAgICAgICAgICB1cGRhdGVRdWVyeShwcmV2aW91cywge1xuICAgICAgICAgICAgICAgIHN1YnNjcmlwdGlvbkRhdGEsXG4gICAgICAgICAgICAgICAgLi4udXBkYXRlT3B0aW9ucyxcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogKGVycjogYW55KSA9PiB7XG4gICAgICAgICAgaWYgKG9wdGlvbnMub25FcnJvcikge1xuICAgICAgICAgICAgb3B0aW9ucy5vbkVycm9yKGVycik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIGludmFyaWFudC5lcnJvcihcIlVuaGFuZGxlZCBHcmFwaFFMIHN1YnNjcmlwdGlvbiBlcnJvclwiLCBlcnIpO1xuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMuYWRkKHN1YnNjcmlwdGlvbik7XG5cbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuc3Vic2NyaXB0aW9ucy5kZWxldGUoc3Vic2NyaXB0aW9uKSkge1xuICAgICAgICBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgcHVibGljIHNldE9wdGlvbnMoXG4gICAgbmV3T3B0aW9uczogUGFydGlhbDxXYXRjaFF1ZXJ5T3B0aW9uczxUVmFyaWFibGVzLCBURGF0YT4+XG4gICk6IFByb21pc2U8QXBvbGxvUXVlcnlSZXN1bHQ8TWF5YmVNYXNrZWQ8VERhdGE+Pj4ge1xuICAgIHJldHVybiB0aGlzLnJlb2JzZXJ2ZShuZXdPcHRpb25zKTtcbiAgfVxuXG4gIHB1YmxpYyBzaWxlbnRTZXRPcHRpb25zKFxuICAgIG5ld09wdGlvbnM6IFBhcnRpYWw8V2F0Y2hRdWVyeU9wdGlvbnM8VFZhcmlhYmxlcywgVERhdGE+PlxuICApIHtcbiAgICBjb25zdCBtZXJnZWRPcHRpb25zID0gY29tcGFjdCh0aGlzLm9wdGlvbnMsIG5ld09wdGlvbnMgfHwge30pO1xuICAgIGFzc2lnbih0aGlzLm9wdGlvbnMsIG1lcmdlZE9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSB0aGUgdmFyaWFibGVzIG9mIHRoaXMgb2JzZXJ2YWJsZSBxdWVyeSwgYW5kIGZldGNoIHRoZSBuZXcgcmVzdWx0c1xuICAgKiBpZiB0aGV5J3ZlIGNoYW5nZWQuIE1vc3QgdXNlcnMgc2hvdWxkIHByZWZlciBgcmVmZXRjaGAgaW5zdGVhZCBvZlxuICAgKiBgc2V0VmFyaWFibGVzYCBpbiBvcmRlciB0byB0byBiZSBwcm9wZXJseSBub3RpZmllZCBvZiByZXN1bHRzIGV2ZW4gd2hlblxuICAgKiB0aGV5IGNvbWUgZnJvbSB0aGUgY2FjaGUuXG4gICAqXG4gICAqIE5vdGU6IHRoZSBgbmV4dGAgY2FsbGJhY2sgd2lsbCAqbm90KiBmaXJlIGlmIHRoZSB2YXJpYWJsZXMgaGF2ZSBub3QgY2hhbmdlZFxuICAgKiBvciBpZiB0aGUgcmVzdWx0IGlzIGNvbWluZyBmcm9tIGNhY2hlLlxuICAgKlxuICAgKiBOb3RlOiB0aGUgcHJvbWlzZSB3aWxsIHJldHVybiB0aGUgb2xkIHJlc3VsdHMgaW1tZWRpYXRlbHkgaWYgdGhlIHZhcmlhYmxlc1xuICAgKiBoYXZlIG5vdCBjaGFuZ2VkLlxuICAgKlxuICAgKiBOb3RlOiB0aGUgcHJvbWlzZSB3aWxsIHJldHVybiBudWxsIGltbWVkaWF0ZWx5IGlmIHRoZSBxdWVyeSBpcyBub3QgYWN0aXZlXG4gICAqICh0aGVyZSBhcmUgbm8gc3Vic2NyaWJlcnMpLlxuICAgKlxuICAgKiBAcGFyYW0gdmFyaWFibGVzIC0gVGhlIG5ldyBzZXQgb2YgdmFyaWFibGVzLiBJZiB0aGVyZSBhcmUgbWlzc2luZyB2YXJpYWJsZXMsXG4gICAqIHRoZSBwcmV2aW91cyB2YWx1ZXMgb2YgdGhvc2UgdmFyaWFibGVzIHdpbGwgYmUgdXNlZC5cbiAgICovXG4gIHB1YmxpYyBzZXRWYXJpYWJsZXMoXG4gICAgdmFyaWFibGVzOiBUVmFyaWFibGVzXG4gICk6IFByb21pc2U8QXBvbGxvUXVlcnlSZXN1bHQ8TWF5YmVNYXNrZWQ8VERhdGE+PiB8IHZvaWQ+IHtcbiAgICBpZiAoZXF1YWwodGhpcy52YXJpYWJsZXMsIHZhcmlhYmxlcykpIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgbm8gb2JzZXJ2ZXJzLCB0aGVuIHdlIGRvbid0IGFjdHVhbGx5IHdhbnQgdG8gbWFrZSBhIG5ldHdvcmtcbiAgICAgIC8vIHJlcXVlc3QuIEFzIHNvb24gYXMgc29tZW9uZSBvYnNlcnZlcyB0aGUgcXVlcnksIHRoZSByZXF1ZXN0IHdpbGwga2lja1xuICAgICAgLy8gb2ZmLiBGb3Igbm93LCB3ZSBqdXN0IHN0b3JlIGFueSBjaGFuZ2VzLiAoU2VlICMxMDc3KVxuICAgICAgcmV0dXJuIHRoaXMub2JzZXJ2ZXJzLnNpemUgPyB0aGlzLnJlc3VsdCgpIDogUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgdGhpcy5vcHRpb25zLnZhcmlhYmxlcyA9IHZhcmlhYmxlcztcblxuICAgIC8vIFNlZSBjb21tZW50IGFib3ZlXG4gICAgaWYgKCF0aGlzLm9ic2VydmVycy5zaXplKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucmVvYnNlcnZlKFxuICAgICAge1xuICAgICAgICAvLyBSZXNldCBvcHRpb25zLmZldGNoUG9saWN5IHRvIGl0cyBvcmlnaW5hbCB2YWx1ZS5cbiAgICAgICAgZmV0Y2hQb2xpY3k6IHRoaXMub3B0aW9ucy5pbml0aWFsRmV0Y2hQb2xpY3ksXG4gICAgICAgIHZhcmlhYmxlcyxcbiAgICAgIH0sXG4gICAgICBOZXR3b3JrU3RhdHVzLnNldFZhcmlhYmxlc1xuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQSBmdW5jdGlvbiB0aGF0IGVuYWJsZXMgeW91IHRvIHVwZGF0ZSB0aGUgcXVlcnkncyBjYWNoZWQgcmVzdWx0IHdpdGhvdXQgZXhlY3V0aW5nIGEgZm9sbG93dXAgR3JhcGhRTCBvcGVyYXRpb24uXG4gICAqXG4gICAqIFNlZSBbdXNpbmcgdXBkYXRlUXVlcnkgYW5kIHVwZGF0ZUZyYWdtZW50XShodHRwczovL3d3dy5hcG9sbG9ncmFwaHFsLmNvbS9kb2NzL3JlYWN0L2NhY2hpbmcvY2FjaGUtaW50ZXJhY3Rpb24vI3VzaW5nLXVwZGF0ZXF1ZXJ5LWFuZC11cGRhdGVmcmFnbWVudCkgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24uXG4gICAqL1xuICBwdWJsaWMgdXBkYXRlUXVlcnkobWFwRm46IFVwZGF0ZVF1ZXJ5TWFwRm48VERhdGEsIFRWYXJpYWJsZXM+KTogdm9pZCB7XG4gICAgY29uc3QgeyBxdWVyeU1hbmFnZXIgfSA9IHRoaXM7XG4gICAgY29uc3QgeyByZXN1bHQsIGNvbXBsZXRlIH0gPSBxdWVyeU1hbmFnZXIuY2FjaGUuZGlmZjxURGF0YT4oe1xuICAgICAgcXVlcnk6IHRoaXMub3B0aW9ucy5xdWVyeSxcbiAgICAgIHZhcmlhYmxlczogdGhpcy52YXJpYWJsZXMsXG4gICAgICByZXR1cm5QYXJ0aWFsRGF0YTogdHJ1ZSxcbiAgICAgIG9wdGltaXN0aWM6IGZhbHNlLFxuICAgIH0pO1xuXG4gICAgY29uc3QgbmV3UmVzdWx0ID0gbWFwRm4oXG4gICAgICByZXN1bHQhIGFzIFVubWFza2VkPFREYXRhPixcbiAgICAgIHtcbiAgICAgICAgdmFyaWFibGVzOiB0aGlzLnZhcmlhYmxlcyxcbiAgICAgICAgY29tcGxldGU6ICEhY29tcGxldGUsXG4gICAgICAgIHByZXZpb3VzRGF0YTogcmVzdWx0LFxuICAgICAgfSBhcyBVcGRhdGVRdWVyeU9wdGlvbnM8VERhdGEsIFRWYXJpYWJsZXM+XG4gICAgKTtcblxuICAgIGlmIChuZXdSZXN1bHQpIHtcbiAgICAgIHF1ZXJ5TWFuYWdlci5jYWNoZS53cml0ZVF1ZXJ5KHtcbiAgICAgICAgcXVlcnk6IHRoaXMub3B0aW9ucy5xdWVyeSxcbiAgICAgICAgZGF0YTogbmV3UmVzdWx0LFxuICAgICAgICB2YXJpYWJsZXM6IHRoaXMudmFyaWFibGVzLFxuICAgICAgfSk7XG5cbiAgICAgIHF1ZXJ5TWFuYWdlci5icm9hZGNhc3RRdWVyaWVzKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEEgZnVuY3Rpb24gdGhhdCBpbnN0cnVjdHMgdGhlIHF1ZXJ5IHRvIGJlZ2luIHJlLWV4ZWN1dGluZyBhdCBhIHNwZWNpZmllZCBpbnRlcnZhbCAoaW4gbWlsbGlzZWNvbmRzKS5cbiAgICovXG4gIHB1YmxpYyBzdGFydFBvbGxpbmcocG9sbEludGVydmFsOiBudW1iZXIpIHtcbiAgICB0aGlzLm9wdGlvbnMucG9sbEludGVydmFsID0gcG9sbEludGVydmFsO1xuICAgIHRoaXMudXBkYXRlUG9sbGluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgZnVuY3Rpb24gdGhhdCBpbnN0cnVjdHMgdGhlIHF1ZXJ5IHRvIHN0b3AgcG9sbGluZyBhZnRlciBhIHByZXZpb3VzIGNhbGwgdG8gYHN0YXJ0UG9sbGluZ2AuXG4gICAqL1xuICBwdWJsaWMgc3RvcFBvbGxpbmcoKSB7XG4gICAgdGhpcy5vcHRpb25zLnBvbGxJbnRlcnZhbCA9IDA7XG4gICAgdGhpcy51cGRhdGVQb2xsaW5nKCk7XG4gIH1cblxuICAvLyBVcGRhdGUgb3B0aW9ucy5mZXRjaFBvbGljeSBhY2NvcmRpbmcgdG8gb3B0aW9ucy5uZXh0RmV0Y2hQb2xpY3kuXG4gIHByaXZhdGUgYXBwbHlOZXh0RmV0Y2hQb2xpY3koXG4gICAgcmVhc29uOiBOZXh0RmV0Y2hQb2xpY3lDb250ZXh0PFREYXRhLCBUVmFyaWFibGVzPltcInJlYXNvblwiXSxcbiAgICAvLyBJdCdzIHBvc3NpYmxlIHRvIHVzZSB0aGlzIG1ldGhvZCB0byBhcHBseSBvcHRpb25zLm5leHRGZXRjaFBvbGljeSB0b1xuICAgIC8vIG9wdGlvbnMuZmV0Y2hQb2xpY3kgZXZlbiBpZiBvcHRpb25zICE9PSB0aGlzLm9wdGlvbnMsIHRob3VnaCB0aGF0IGhhcHBlbnNcbiAgICAvLyBtb3N0IG9mdGVuIHdoZW4gdGhlIG9wdGlvbnMgYXJlIHRlbXBvcmFyeSwgdXNlZCBmb3Igb25seSBvbmUgcmVxdWVzdCBhbmRcbiAgICAvLyB0aGVuIHRocm93biBhd2F5LCBzbyBuZXh0RmV0Y2hQb2xpY3kgbWF5IG5vdCBlbmQgdXAgbWF0dGVyaW5nLlxuICAgIG9wdGlvbnM6IFdhdGNoUXVlcnlPcHRpb25zPFRWYXJpYWJsZXMsIFREYXRhPlxuICApIHtcbiAgICBpZiAob3B0aW9ucy5uZXh0RmV0Y2hQb2xpY3kpIHtcbiAgICAgIGNvbnN0IHsgZmV0Y2hQb2xpY3kgPSBcImNhY2hlLWZpcnN0XCIsIGluaXRpYWxGZXRjaFBvbGljeSA9IGZldGNoUG9saWN5IH0gPVxuICAgICAgICBvcHRpb25zO1xuXG4gICAgICBpZiAoZmV0Y2hQb2xpY3kgPT09IFwic3RhbmRieVwiKSB7XG4gICAgICAgIC8vIERvIG5vdGhpbmcsIGxlYXZpbmcgb3B0aW9ucy5mZXRjaFBvbGljeSB1bmNoYW5nZWQuXG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBvcHRpb25zLm5leHRGZXRjaFBvbGljeSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIC8vIFdoZW4gc29tZW9uZSBjaG9vc2VzIFwiY2FjaGUtYW5kLW5ldHdvcmtcIiBvciBcIm5ldHdvcmstb25seVwiIGFzIHRoZWlyXG4gICAgICAgIC8vIGluaXRpYWwgRmV0Y2hQb2xpY3ksIHRoZXkgb2Z0ZW4gZG8gbm90IHdhbnQgZnV0dXJlIGNhY2hlIHVwZGF0ZXMgdG9cbiAgICAgICAgLy8gdHJpZ2dlciB1bmNvbmRpdGlvbmFsIG5ldHdvcmsgcmVxdWVzdHMsIHdoaWNoIGlzIHdoYXQgcmVwZWF0ZWRseVxuICAgICAgICAvLyBhcHBseWluZyB0aGUgXCJjYWNoZS1hbmQtbmV0d29ya1wiIG9yIFwibmV0d29yay1vbmx5XCIgcG9saWNpZXMgd291bGRcbiAgICAgICAgLy8gc2VlbSB0byBpbXBseS4gSW5zdGVhZCwgd2hlbiB0aGUgY2FjaGUgcmVwb3J0cyBhbiB1cGRhdGUgYWZ0ZXIgdGhlXG4gICAgICAgIC8vIGluaXRpYWwgbmV0d29yayByZXF1ZXN0LCBpdCBtYXkgYmUgZGVzaXJhYmxlIGZvciBzdWJzZXF1ZW50IG5ldHdvcmtcbiAgICAgICAgLy8gcmVxdWVzdHMgdG8gYmUgdHJpZ2dlcmVkIG9ubHkgaWYgdGhlIGNhY2hlIHJlc3VsdCBpcyBpbmNvbXBsZXRlLiBUb1xuICAgICAgICAvLyB0aGF0IGVuZCwgdGhlIG9wdGlvbnMubmV4dEZldGNoUG9saWN5IG9wdGlvbiBwcm92aWRlcyBhbiBlYXN5IHdheSB0b1xuICAgICAgICAvLyB1cGRhdGUgb3B0aW9ucy5mZXRjaFBvbGljeSBhZnRlciB0aGUgaW5pdGlhbCBuZXR3b3JrIHJlcXVlc3QsIHdpdGhvdXRcbiAgICAgICAgLy8gaGF2aW5nIHRvIGNhbGwgb2JzZXJ2YWJsZVF1ZXJ5LnNldE9wdGlvbnMuXG4gICAgICAgIG9wdGlvbnMuZmV0Y2hQb2xpY3kgPSBvcHRpb25zLm5leHRGZXRjaFBvbGljeShmZXRjaFBvbGljeSwge1xuICAgICAgICAgIHJlYXNvbixcbiAgICAgICAgICBvcHRpb25zLFxuICAgICAgICAgIG9ic2VydmFibGU6IHRoaXMsXG4gICAgICAgICAgaW5pdGlhbEZldGNoUG9saWN5LFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAocmVhc29uID09PSBcInZhcmlhYmxlcy1jaGFuZ2VkXCIpIHtcbiAgICAgICAgb3B0aW9ucy5mZXRjaFBvbGljeSA9IGluaXRpYWxGZXRjaFBvbGljeTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9wdGlvbnMuZmV0Y2hQb2xpY3kgPSBvcHRpb25zLm5leHRGZXRjaFBvbGljeTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3B0aW9ucy5mZXRjaFBvbGljeTtcbiAgfVxuXG4gIHByaXZhdGUgZmV0Y2goXG4gICAgb3B0aW9uczogV2F0Y2hRdWVyeU9wdGlvbnM8VFZhcmlhYmxlcywgVERhdGE+LFxuICAgIG5ld05ldHdvcmtTdGF0dXM/OiBOZXR3b3JrU3RhdHVzLFxuICAgIHF1ZXJ5PzogRG9jdW1lbnROb2RlXG4gICkge1xuICAgIC8vIFRPRE8gTWFrZSBzdXJlIHdlIHVwZGF0ZSB0aGUgbmV0d29ya1N0YXR1cyAoYW5kIGluZmVyIGZldGNoVmFyaWFibGVzKVxuICAgIC8vIGJlZm9yZSBhY3R1YWxseSBjb21taXR0aW5nIHRvIHRoZSBmZXRjaC5cbiAgICBjb25zdCBxdWVyeUluZm8gPSB0aGlzLnF1ZXJ5TWFuYWdlci5nZXRPckNyZWF0ZVF1ZXJ5KHRoaXMucXVlcnlJZCk7XG4gICAgcXVlcnlJbmZvLnNldE9ic2VydmFibGVRdWVyeSh0aGlzKTtcbiAgICByZXR1cm4gdGhpcy5xdWVyeU1hbmFnZXJbXCJmZXRjaENvbmNhc3RXaXRoSW5mb1wiXShcbiAgICAgIHF1ZXJ5SW5mbyxcbiAgICAgIG9wdGlvbnMsXG4gICAgICBuZXdOZXR3b3JrU3RhdHVzLFxuICAgICAgcXVlcnlcbiAgICApO1xuICB9XG5cbiAgLy8gVHVybnMgcG9sbGluZyBvbiBvciBvZmYgYmFzZWQgb24gdGhpcy5vcHRpb25zLnBvbGxJbnRlcnZhbC5cbiAgcHJpdmF0ZSB1cGRhdGVQb2xsaW5nKCkge1xuICAgIC8vIEF2b2lkIHBvbGxpbmcgaW4gU1NSIG1vZGVcbiAgICBpZiAodGhpcy5xdWVyeU1hbmFnZXIuc3NyTW9kZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHtcbiAgICAgIHBvbGxpbmdJbmZvLFxuICAgICAgb3B0aW9uczogeyBwb2xsSW50ZXJ2YWwgfSxcbiAgICB9ID0gdGhpcztcblxuICAgIGlmICghcG9sbEludGVydmFsIHx8ICF0aGlzLmhhc09ic2VydmVycygpKSB7XG4gICAgICBpZiAocG9sbGluZ0luZm8pIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHBvbGxpbmdJbmZvLnRpbWVvdXQpO1xuICAgICAgICBkZWxldGUgdGhpcy5wb2xsaW5nSW5mbztcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAocG9sbGluZ0luZm8gJiYgcG9sbGluZ0luZm8uaW50ZXJ2YWwgPT09IHBvbGxJbnRlcnZhbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGludmFyaWFudChcbiAgICAgIHBvbGxJbnRlcnZhbCxcbiAgICAgIFwiQXR0ZW1wdGVkIHRvIHN0YXJ0IGEgcG9sbGluZyBxdWVyeSB3aXRob3V0IGEgcG9sbGluZyBpbnRlcnZhbC5cIlxuICAgICk7XG5cbiAgICBjb25zdCBpbmZvID0gcG9sbGluZ0luZm8gfHwgKHRoaXMucG9sbGluZ0luZm8gPSB7fSBhcyBhbnkpO1xuICAgIGluZm8uaW50ZXJ2YWwgPSBwb2xsSW50ZXJ2YWw7XG5cbiAgICBjb25zdCBtYXliZUZldGNoID0gKCkgPT4ge1xuICAgICAgaWYgKHRoaXMucG9sbGluZ0luZm8pIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICFpc05ldHdvcmtSZXF1ZXN0SW5GbGlnaHQodGhpcy5xdWVyeUluZm8ubmV0d29ya1N0YXR1cykgJiZcbiAgICAgICAgICAhdGhpcy5vcHRpb25zLnNraXBQb2xsQXR0ZW1wdD8uKClcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhpcy5yZW9ic2VydmUoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIC8vIE1vc3QgZmV0Y2hQb2xpY3kgb3B0aW9ucyBkb24ndCBtYWtlIHNlbnNlIHRvIHVzZSBpbiBhIHBvbGxpbmcgY29udGV4dCwgYXNcbiAgICAgICAgICAgICAgLy8gdXNlcnMgd291bGRuJ3Qgd2FudCB0byBiZSBwb2xsaW5nIHRoZSBjYWNoZSBkaXJlY3RseS4gSG93ZXZlciwgbmV0d29yay1vbmx5IGFuZFxuICAgICAgICAgICAgICAvLyBuby1jYWNoZSBhcmUgYm90aCB1c2VmdWwgZm9yIHdoZW4gdGhlIHVzZXIgd2FudHMgdG8gY29udHJvbCB3aGV0aGVyIG9yIG5vdCB0aGVcbiAgICAgICAgICAgICAgLy8gcG9sbGVkIHJlc3VsdHMgYXJlIHdyaXR0ZW4gdG8gdGhlIGNhY2hlLlxuICAgICAgICAgICAgICBmZXRjaFBvbGljeTpcbiAgICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMuaW5pdGlhbEZldGNoUG9saWN5ID09PSBcIm5vLWNhY2hlXCIgP1xuICAgICAgICAgICAgICAgICAgXCJuby1jYWNoZVwiXG4gICAgICAgICAgICAgICAgOiBcIm5ldHdvcmstb25seVwiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIE5ldHdvcmtTdGF0dXMucG9sbFxuICAgICAgICAgICkudGhlbihwb2xsLCBwb2xsKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwb2xsKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgcG9sbCA9ICgpID0+IHtcbiAgICAgIGNvbnN0IGluZm8gPSB0aGlzLnBvbGxpbmdJbmZvO1xuICAgICAgaWYgKGluZm8pIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KGluZm8udGltZW91dCk7XG4gICAgICAgIGluZm8udGltZW91dCA9IHNldFRpbWVvdXQobWF5YmVGZXRjaCwgaW5mby5pbnRlcnZhbCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHBvbGwoKTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlTGFzdFJlc3VsdChcbiAgICBuZXdSZXN1bHQ6IEFwb2xsb1F1ZXJ5UmVzdWx0PFREYXRhPixcbiAgICB2YXJpYWJsZXMgPSB0aGlzLnZhcmlhYmxlc1xuICApIHtcbiAgICBsZXQgZXJyb3I6IEFwb2xsb0Vycm9yIHwgdW5kZWZpbmVkID0gdGhpcy5nZXRMYXN0RXJyb3IoKTtcbiAgICAvLyBQcmVzZXJ2ZSB0aGlzLmxhc3QuZXJyb3IgdW5sZXNzIHRoZSB2YXJpYWJsZXMgaGF2ZSBjaGFuZ2VkLlxuICAgIGlmIChlcnJvciAmJiB0aGlzLmxhc3QgJiYgIWVxdWFsKHZhcmlhYmxlcywgdGhpcy5sYXN0LnZhcmlhYmxlcykpIHtcbiAgICAgIGVycm9yID0gdm9pZCAwO1xuICAgIH1cbiAgICByZXR1cm4gKHRoaXMubGFzdCA9IHtcbiAgICAgIHJlc3VsdDpcbiAgICAgICAgdGhpcy5xdWVyeU1hbmFnZXIuYXNzdW1lSW1tdXRhYmxlUmVzdWx0cyA/XG4gICAgICAgICAgbmV3UmVzdWx0XG4gICAgICAgIDogY2xvbmVEZWVwKG5ld1Jlc3VsdCksXG4gICAgICB2YXJpYWJsZXMsXG4gICAgICAuLi4oZXJyb3IgPyB7IGVycm9yIH0gOiBudWxsKSxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyByZW9ic2VydmVBc0NvbmNhc3QoXG4gICAgbmV3T3B0aW9ucz86IFBhcnRpYWw8V2F0Y2hRdWVyeU9wdGlvbnM8VFZhcmlhYmxlcywgVERhdGE+PixcbiAgICBuZXdOZXR3b3JrU3RhdHVzPzogTmV0d29ya1N0YXR1c1xuICApOiBDb25jYXN0PEFwb2xsb1F1ZXJ5UmVzdWx0PFREYXRhPj4ge1xuICAgIHRoaXMuaXNUb3JuRG93biA9IGZhbHNlO1xuXG4gICAgY29uc3QgdXNlRGlzcG9zYWJsZUNvbmNhc3QgPVxuICAgICAgLy8gUmVmZXRjaGluZyB1c2VzIGEgZGlzcG9zYWJsZSBDb25jYXN0IHRvIGFsbG93IHJlZmV0Y2hlcyB1c2luZyBkaWZmZXJlbnRcbiAgICAgIC8vIG9wdGlvbnMvdmFyaWFibGVzLCB3aXRob3V0IHBlcm1hbmVudGx5IGFsdGVyaW5nIHRoZSBvcHRpb25zIG9mIHRoZVxuICAgICAgLy8gb3JpZ2luYWwgT2JzZXJ2YWJsZVF1ZXJ5LlxuICAgICAgbmV3TmV0d29ya1N0YXR1cyA9PT0gTmV0d29ya1N0YXR1cy5yZWZldGNoIHx8XG4gICAgICAvLyBUaGUgZmV0Y2hNb3JlIG1ldGhvZCBkb2VzIG5vdCBhY3R1YWxseSBjYWxsIHRoZSByZW9ic2VydmUgbWV0aG9kLCBidXQsXG4gICAgICAvLyBpZiBpdCBkaWQsIGl0IHdvdWxkIGRlZmluaXRlbHkgdXNlIGEgZGlzcG9zYWJsZSBDb25jYXN0LlxuICAgICAgbmV3TmV0d29ya1N0YXR1cyA9PT0gTmV0d29ya1N0YXR1cy5mZXRjaE1vcmUgfHxcbiAgICAgIC8vIFBvbGxpbmcgdXNlcyBhIGRpc3Bvc2FibGUgQ29uY2FzdCBzbyB0aGUgcG9sbGluZyBvcHRpb25zICh3aGljaCBmb3JjZVxuICAgICAgLy8gZmV0Y2hQb2xpY3kgdG8gYmUgXCJuZXR3b3JrLW9ubHlcIiBvciBcIm5vLWNhY2hlXCIpIHdvbid0IG92ZXJyaWRlIHRoZSBvcmlnaW5hbCBvcHRpb25zLlxuICAgICAgbmV3TmV0d29ya1N0YXR1cyA9PT0gTmV0d29ya1N0YXR1cy5wb2xsO1xuXG4gICAgLy8gU2F2ZSB0aGUgb2xkIHZhcmlhYmxlcywgc2luY2UgT2JqZWN0LmFzc2lnbiBtYXkgbW9kaWZ5IHRoZW0gYmVsb3cuXG4gICAgY29uc3Qgb2xkVmFyaWFibGVzID0gdGhpcy5vcHRpb25zLnZhcmlhYmxlcztcbiAgICBjb25zdCBvbGRGZXRjaFBvbGljeSA9IHRoaXMub3B0aW9ucy5mZXRjaFBvbGljeTtcblxuICAgIGNvbnN0IG1lcmdlZE9wdGlvbnMgPSBjb21wYWN0KHRoaXMub3B0aW9ucywgbmV3T3B0aW9ucyB8fCB7fSk7XG4gICAgY29uc3Qgb3B0aW9ucyA9XG4gICAgICB1c2VEaXNwb3NhYmxlQ29uY2FzdCA/XG4gICAgICAgIC8vIERpc3Bvc2FibGUgQ29uY2FzdCBmZXRjaGVzIHJlY2VpdmUgYSBzaGFsbG93IGNvcHkgb2YgdGhpcy5vcHRpb25zXG4gICAgICAgIC8vIChtZXJnZWQgd2l0aCBuZXdPcHRpb25zKSwgbGVhdmluZyB0aGlzLm9wdGlvbnMgdW5tb2RpZmllZC5cbiAgICAgICAgbWVyZ2VkT3B0aW9uc1xuICAgICAgOiBhc3NpZ24odGhpcy5vcHRpb25zLCBtZXJnZWRPcHRpb25zKTtcblxuICAgIC8vIERvbid0IHVwZGF0ZSBvcHRpb25zLnF1ZXJ5IHdpdGggdGhlIHRyYW5zZm9ybWVkIHF1ZXJ5IHRvIGF2b2lkXG4gICAgLy8gb3ZlcndyaXRpbmcgdGhpcy5vcHRpb25zLnF1ZXJ5IHdoZW4gd2UgYXJlbid0IHVzaW5nIGEgZGlzcG9zYWJsZSBjb25jYXN0LlxuICAgIC8vIFdlIHdhbnQgdG8gZW5zdXJlIHdlIGNhbiByZS1ydW4gdGhlIGN1c3RvbSBkb2N1bWVudCB0cmFuc2Zvcm1zIHRoZSBuZXh0XG4gICAgLy8gdGltZSBhIHJlcXVlc3QgaXMgbWFkZSBhZ2FpbnN0IHRoZSBvcmlnaW5hbCBxdWVyeS5cbiAgICBjb25zdCBxdWVyeSA9IHRoaXMudHJhbnNmb3JtRG9jdW1lbnQob3B0aW9ucy5xdWVyeSk7XG5cbiAgICB0aGlzLmxhc3RRdWVyeSA9IHF1ZXJ5O1xuXG4gICAgaWYgKCF1c2VEaXNwb3NhYmxlQ29uY2FzdCkge1xuICAgICAgLy8gV2UgY2FuIHNraXAgY2FsbGluZyB1cGRhdGVQb2xsaW5nIGlmIHdlJ3JlIG5vdCBjaGFuZ2luZyB0aGlzLm9wdGlvbnMuXG4gICAgICB0aGlzLnVwZGF0ZVBvbGxpbmcoKTtcblxuICAgICAgLy8gUmVzZXQgb3B0aW9ucy5mZXRjaFBvbGljeSB0byBpdHMgb3JpZ2luYWwgdmFsdWUgd2hlbiB2YXJpYWJsZXMgY2hhbmdlLFxuICAgICAgLy8gdW5sZXNzIGEgbmV3IGZldGNoUG9saWN5IHdhcyBwcm92aWRlZCBieSBuZXdPcHRpb25zLlxuICAgICAgaWYgKFxuICAgICAgICBuZXdPcHRpb25zICYmXG4gICAgICAgIG5ld09wdGlvbnMudmFyaWFibGVzICYmXG4gICAgICAgICFlcXVhbChuZXdPcHRpb25zLnZhcmlhYmxlcywgb2xkVmFyaWFibGVzKSAmJlxuICAgICAgICAvLyBEb24ndCBtZXNzIHdpdGggdGhlIGZldGNoUG9saWN5IGlmIGl0J3MgY3VycmVudGx5IFwic3RhbmRieVwiLlxuICAgICAgICBvcHRpb25zLmZldGNoUG9saWN5ICE9PSBcInN0YW5kYnlcIiAmJlxuICAgICAgICAvLyBJZiB3ZSdyZSBjaGFuZ2luZyB0aGUgZmV0Y2hQb2xpY3kgYW55d2F5LCBkb24ndCB0cnkgdG8gY2hhbmdlIGl0IGhlcmVcbiAgICAgICAgLy8gdXNpbmcgYXBwbHlOZXh0RmV0Y2hQb2xpY3kuIFRoZSBleHBsaWNpdCBvcHRpb25zLmZldGNoUG9saWN5IHdpbnMuXG4gICAgICAgIChvcHRpb25zLmZldGNoUG9saWN5ID09PSBvbGRGZXRjaFBvbGljeSB8fFxuICAgICAgICAgIC8vIEEgYG5leHRGZXRjaFBvbGljeWAgZnVuY3Rpb24gaGFzIGV2ZW4gaGlnaGVyIHByaW9yaXR5LCB0aG91Z2gsXG4gICAgICAgICAgLy8gc28gaW4gdGhhdCBjYXNlIGBhcHBseU5leHRGZXRjaFBvbGljeWAgbXVzdCBiZSBjYWxsZWQuXG4gICAgICAgICAgdHlwZW9mIG9wdGlvbnMubmV4dEZldGNoUG9saWN5ID09PSBcImZ1bmN0aW9uXCIpXG4gICAgICApIHtcbiAgICAgICAgdGhpcy5hcHBseU5leHRGZXRjaFBvbGljeShcInZhcmlhYmxlcy1jaGFuZ2VkXCIsIG9wdGlvbnMpO1xuICAgICAgICBpZiAobmV3TmV0d29ya1N0YXR1cyA9PT0gdm9pZCAwKSB7XG4gICAgICAgICAgbmV3TmV0d29ya1N0YXR1cyA9IE5ldHdvcmtTdGF0dXMuc2V0VmFyaWFibGVzO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy53YWl0Rm9yT3duUmVzdWx0ICYmPSBza2lwQ2FjaGVEYXRhRm9yKG9wdGlvbnMuZmV0Y2hQb2xpY3kpO1xuICAgIGNvbnN0IGZpbmlzaFdhaXRpbmdGb3JPd25SZXN1bHQgPSAoKSA9PiB7XG4gICAgICBpZiAodGhpcy5jb25jYXN0ID09PSBjb25jYXN0KSB7XG4gICAgICAgIHRoaXMud2FpdEZvck93blJlc3VsdCA9IGZhbHNlO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdCB2YXJpYWJsZXMgPSBvcHRpb25zLnZhcmlhYmxlcyAmJiB7IC4uLm9wdGlvbnMudmFyaWFibGVzIH07XG4gICAgY29uc3QgeyBjb25jYXN0LCBmcm9tTGluayB9ID0gdGhpcy5mZXRjaChvcHRpb25zLCBuZXdOZXR3b3JrU3RhdHVzLCBxdWVyeSk7XG4gICAgY29uc3Qgb2JzZXJ2ZXI6IE9ic2VydmVyPEFwb2xsb1F1ZXJ5UmVzdWx0PFREYXRhPj4gPSB7XG4gICAgICBuZXh0OiAocmVzdWx0KSA9PiB7XG4gICAgICAgIGlmIChlcXVhbCh0aGlzLnZhcmlhYmxlcywgdmFyaWFibGVzKSkge1xuICAgICAgICAgIGZpbmlzaFdhaXRpbmdGb3JPd25SZXN1bHQoKTtcbiAgICAgICAgICB0aGlzLnJlcG9ydFJlc3VsdChyZXN1bHQsIHZhcmlhYmxlcyk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgIGlmIChlcXVhbCh0aGlzLnZhcmlhYmxlcywgdmFyaWFibGVzKSkge1xuICAgICAgICAgIC8vIENvbWluZyBmcm9tIGBnZXRSZXN1bHRzRnJvbUxpbmtgLCBgZXJyb3JgIGhlcmUgc2hvdWxkIGFsd2F5cyBiZSBhbiBgQXBvbGxvRXJyb3JgLlxuICAgICAgICAgIC8vIEhvd2V2ZXIsIGNhbGxpbmcgYGNvbmNhc3QuY2FuY2VsYCBjYW4gaW5qZWN0IGFub3RoZXIgdHlwZSBvZiBlcnJvciwgc28gd2UgaGF2ZSB0b1xuICAgICAgICAgIC8vIHdyYXAgaXQgYWdhaW4gaGVyZS5cbiAgICAgICAgICBpZiAoIWlzQXBvbGxvRXJyb3IoZXJyb3IpKSB7XG4gICAgICAgICAgICBlcnJvciA9IG5ldyBBcG9sbG9FcnJvcih7IG5ldHdvcmtFcnJvcjogZXJyb3IgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGZpbmlzaFdhaXRpbmdGb3JPd25SZXN1bHQoKTtcbiAgICAgICAgICB0aGlzLnJlcG9ydEVycm9yKGVycm9yLCB2YXJpYWJsZXMpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH07XG5cbiAgICBpZiAoIXVzZURpc3Bvc2FibGVDb25jYXN0ICYmIChmcm9tTGluayB8fCAhdGhpcy5jb25jYXN0KSkge1xuICAgICAgLy8gV2UgdXNlIHRoZSB7YWRkLHJlbW92ZX1PYnNlcnZlciBtZXRob2RzIGRpcmVjdGx5IHRvIGF2b2lkIHdyYXBwaW5nXG4gICAgICAvLyBvYnNlcnZlciB3aXRoIGFuIHVubmVjZXNzYXJ5IFN1YnNjcmlwdGlvbk9ic2VydmVyIG9iamVjdC5cbiAgICAgIGlmICh0aGlzLmNvbmNhc3QgJiYgdGhpcy5vYnNlcnZlcikge1xuICAgICAgICB0aGlzLmNvbmNhc3QucmVtb3ZlT2JzZXJ2ZXIodGhpcy5vYnNlcnZlcik7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuY29uY2FzdCA9IGNvbmNhc3Q7XG4gICAgICB0aGlzLm9ic2VydmVyID0gb2JzZXJ2ZXI7XG4gICAgfVxuXG4gICAgY29uY2FzdC5hZGRPYnNlcnZlcihvYnNlcnZlcik7XG5cbiAgICByZXR1cm4gY29uY2FzdDtcbiAgfVxuXG4gIHB1YmxpYyByZW9ic2VydmUoXG4gICAgbmV3T3B0aW9ucz86IFBhcnRpYWw8V2F0Y2hRdWVyeU9wdGlvbnM8VFZhcmlhYmxlcywgVERhdGE+PixcbiAgICBuZXdOZXR3b3JrU3RhdHVzPzogTmV0d29ya1N0YXR1c1xuICApOiBQcm9taXNlPEFwb2xsb1F1ZXJ5UmVzdWx0PE1heWJlTWFza2VkPFREYXRhPj4+IHtcbiAgICByZXR1cm4gcHJldmVudFVuaGFuZGxlZFJlamVjdGlvbihcbiAgICAgIHRoaXMucmVvYnNlcnZlQXNDb25jYXN0KG5ld09wdGlvbnMsIG5ld05ldHdvcmtTdGF0dXMpLnByb21pc2UudGhlbihcbiAgICAgICAgdGhpcy5tYXNrUmVzdWx0IGFzIFRPRE9cbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgcHVibGljIHJlc3Vic2NyaWJlQWZ0ZXJFcnJvcihcbiAgICBvbk5leHQ6ICh2YWx1ZTogQXBvbGxvUXVlcnlSZXN1bHQ8TWF5YmVNYXNrZWQ8VERhdGE+PikgPT4gdm9pZCxcbiAgICBvbkVycm9yPzogKGVycm9yOiBhbnkpID0+IHZvaWQsXG4gICAgb25Db21wbGV0ZT86ICgpID0+IHZvaWRcbiAgKTogT2JzZXJ2YWJsZVN1YnNjcmlwdGlvbjtcblxuICBwdWJsaWMgcmVzdWJzY3JpYmVBZnRlckVycm9yKFxuICAgIG9ic2VydmVyOiBPYnNlcnZlcjxBcG9sbG9RdWVyeVJlc3VsdDxURGF0YT4+XG4gICk6IE9ic2VydmFibGVTdWJzY3JpcHRpb247XG5cbiAgcHVibGljIHJlc3Vic2NyaWJlQWZ0ZXJFcnJvciguLi5hcmdzOiBbYW55LCBhbnk/LCBhbnk/XSkge1xuICAgIC8vIElmIGBsYXN0RXJyb3JgIGlzIHNldCBpbiB0aGUgY3VycmVudCB3aGVuIHRoZSBzdWJzY3JpcHRpb24gaXMgcmUtY3JlYXRlZCxcbiAgICAvLyB0aGUgc3Vic2NyaXB0aW9uIHdpbGwgaW1tZWRpYXRlbHkgcmVjZWl2ZSB0aGUgZXJyb3IsIHdoaWNoIHdpbGxcbiAgICAvLyBjYXVzZSBpdCB0byB0ZXJtaW5hdGUgYWdhaW4uIFRvIGF2b2lkIHRoaXMsIHdlIGZpcnN0IGNsZWFyXG4gICAgLy8gdGhlIGxhc3QgZXJyb3IvcmVzdWx0IGZyb20gdGhlIGBvYnNlcnZhYmxlUXVlcnlgIGJlZm9yZSByZS1zdGFydGluZ1xuICAgIC8vIHRoZSBzdWJzY3JpcHRpb24sIGFuZCByZXN0b3JlIHRoZSBsYXN0IHZhbHVlIGFmdGVyd2FyZHMgc28gdGhhdCB0aGVcbiAgICAvLyBzdWJzY3JpcHRpb24gaGFzIGEgY2hhbmNlIHRvIHN0YXkgb3Blbi5cbiAgICBjb25zdCBsYXN0ID0gdGhpcy5sYXN0O1xuICAgIHRoaXMucmVzZXRMYXN0UmVzdWx0cygpO1xuXG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gdGhpcy5zdWJzY3JpYmUoLi4uYXJncyk7XG4gICAgdGhpcy5sYXN0ID0gbGFzdDtcblxuICAgIHJldHVybiBzdWJzY3JpcHRpb247XG4gIH1cblxuICAvLyAoUmUpZGVsaXZlciB0aGUgY3VycmVudCByZXN1bHQgdG8gdGhpcy5vYnNlcnZlcnMgd2l0aG91dCBhcHBseWluZyBmZXRjaFxuICAvLyBwb2xpY2llcyBvciBtYWtpbmcgbmV0d29yayByZXF1ZXN0cy5cbiAgcHJpdmF0ZSBvYnNlcnZlKCkge1xuICAgIHRoaXMucmVwb3J0UmVzdWx0KFxuICAgICAgLy8gUGFzc2luZyBmYWxzZSBpcyBpbXBvcnRhbnQgc28gdGhhdCB0aGlzLmdldEN1cnJlbnRSZXN1bHQgZG9lc24ndFxuICAgICAgLy8gc2F2ZSB0aGUgZmV0Y2hNb3JlIHJlc3VsdCBhcyB0aGlzLmxhc3RSZXN1bHQsIGNhdXNpbmcgaXQgdG8gYmVcbiAgICAgIC8vIGlnbm9yZWQgZHVlIHRvIHRoZSB0aGlzLmlzRGlmZmVyZW50RnJvbUxhc3RSZXN1bHQgY2hlY2sgaW5cbiAgICAgIC8vIHRoaXMucmVwb3J0UmVzdWx0LlxuICAgICAgdGhpcy5nZXRDdXJyZW50RnVsbFJlc3VsdChmYWxzZSksXG4gICAgICB0aGlzLnZhcmlhYmxlc1xuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHJlcG9ydFJlc3VsdChcbiAgICByZXN1bHQ6IEFwb2xsb1F1ZXJ5UmVzdWx0PFREYXRhPixcbiAgICB2YXJpYWJsZXM6IFRWYXJpYWJsZXMgfCB1bmRlZmluZWRcbiAgKSB7XG4gICAgY29uc3QgbGFzdEVycm9yID0gdGhpcy5nZXRMYXN0RXJyb3IoKTtcbiAgICBjb25zdCBpc0RpZmZlcmVudCA9IHRoaXMuaXNEaWZmZXJlbnRGcm9tTGFzdFJlc3VsdChyZXN1bHQsIHZhcmlhYmxlcyk7XG4gICAgLy8gVXBkYXRlIHRoZSBsYXN0IHJlc3VsdCBldmVuIHdoZW4gaXNEaWZmZXJlbnRGcm9tTGFzdFJlc3VsdCByZXR1cm5zIGZhbHNlLFxuICAgIC8vIGJlY2F1c2UgdGhlIHF1ZXJ5IG1heSBiZSB1c2luZyB0aGUgQG5vbnJlYWN0aXZlIGRpcmVjdGl2ZSwgYW5kIHdlIHdhbnQgdG9cbiAgICAvLyBzYXZlIHRoZSB0aGUgbGF0ZXN0IHZlcnNpb24gb2YgYW55IG5vbnJlYWN0aXZlIHN1YnRyZWVzIChpbiBjYXNlXG4gICAgLy8gZ2V0Q3VycmVudFJlc3VsdCBpcyBjYWxsZWQpLCBldmVuIHRob3VnaCB3ZSBza2lwIGJyb2FkY2FzdGluZyBjaGFuZ2VzLlxuICAgIGlmIChsYXN0RXJyb3IgfHwgIXJlc3VsdC5wYXJ0aWFsIHx8IHRoaXMub3B0aW9ucy5yZXR1cm5QYXJ0aWFsRGF0YSkge1xuICAgICAgdGhpcy51cGRhdGVMYXN0UmVzdWx0KHJlc3VsdCwgdmFyaWFibGVzKTtcbiAgICB9XG4gICAgaWYgKGxhc3RFcnJvciB8fCBpc0RpZmZlcmVudCkge1xuICAgICAgaXRlcmF0ZU9ic2VydmVyc1NhZmVseSh0aGlzLm9ic2VydmVycywgXCJuZXh0XCIsIHRoaXMubWFza1Jlc3VsdChyZXN1bHQpKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlcG9ydEVycm9yKGVycm9yOiBBcG9sbG9FcnJvciwgdmFyaWFibGVzOiBUVmFyaWFibGVzIHwgdW5kZWZpbmVkKSB7XG4gICAgLy8gU2luY2Ugd2UgZG9uJ3QgZ2V0IHRoZSBjdXJyZW50IHJlc3VsdCBvbiBlcnJvcnMsIG9ubHkgdGhlIGVycm9yLCB3ZVxuICAgIC8vIG11c3QgbWlycm9yIHRoZSB1cGRhdGVzIHRoYXQgb2NjdXIgaW4gUXVlcnlTdG9yZS5tYXJrUXVlcnlFcnJvciBoZXJlXG4gICAgY29uc3QgZXJyb3JSZXN1bHQgPSB7XG4gICAgICAuLi50aGlzLmdldExhc3RSZXN1bHQoKSxcbiAgICAgIGVycm9yLFxuICAgICAgZXJyb3JzOiBlcnJvci5ncmFwaFFMRXJyb3JzLFxuICAgICAgbmV0d29ya1N0YXR1czogTmV0d29ya1N0YXR1cy5lcnJvcixcbiAgICAgIGxvYWRpbmc6IGZhbHNlLFxuICAgIH0gYXMgQXBvbGxvUXVlcnlSZXN1bHQ8VERhdGE+O1xuXG4gICAgdGhpcy51cGRhdGVMYXN0UmVzdWx0KGVycm9yUmVzdWx0LCB2YXJpYWJsZXMpO1xuXG4gICAgaXRlcmF0ZU9ic2VydmVyc1NhZmVseSh0aGlzLm9ic2VydmVycywgXCJlcnJvclwiLCAodGhpcy5sYXN0IS5lcnJvciA9IGVycm9yKSk7XG4gIH1cblxuICBwdWJsaWMgaGFzT2JzZXJ2ZXJzKCkge1xuICAgIHJldHVybiB0aGlzLm9ic2VydmVycy5zaXplID4gMDtcbiAgfVxuXG4gIHByaXZhdGUgdGVhckRvd25RdWVyeSgpIHtcbiAgICBpZiAodGhpcy5pc1Rvcm5Eb3duKSByZXR1cm47XG4gICAgaWYgKHRoaXMuY29uY2FzdCAmJiB0aGlzLm9ic2VydmVyKSB7XG4gICAgICB0aGlzLmNvbmNhc3QucmVtb3ZlT2JzZXJ2ZXIodGhpcy5vYnNlcnZlcik7XG4gICAgICBkZWxldGUgdGhpcy5jb25jYXN0O1xuICAgICAgZGVsZXRlIHRoaXMub2JzZXJ2ZXI7XG4gICAgfVxuXG4gICAgdGhpcy5zdG9wUG9sbGluZygpO1xuICAgIC8vIHN0b3AgYWxsIGFjdGl2ZSBHcmFwaFFMIHN1YnNjcmlwdGlvbnNcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMuZm9yRWFjaCgoc3ViKSA9PiBzdWIudW5zdWJzY3JpYmUoKSk7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLmNsZWFyKCk7XG4gICAgdGhpcy5xdWVyeU1hbmFnZXIuc3RvcFF1ZXJ5KHRoaXMucXVlcnlJZCk7XG4gICAgdGhpcy5vYnNlcnZlcnMuY2xlYXIoKTtcbiAgICB0aGlzLmlzVG9ybkRvd24gPSB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSB0cmFuc2Zvcm1Eb2N1bWVudChkb2N1bWVudDogRG9jdW1lbnROb2RlKSB7XG4gICAgcmV0dXJuIHRoaXMucXVlcnlNYW5hZ2VyLnRyYW5zZm9ybShkb2N1bWVudCk7XG4gIH1cblxuICBwcml2YXRlIG1hc2tSZXN1bHQ8VCA9IFREYXRhPihcbiAgICByZXN1bHQ6IEFwb2xsb1F1ZXJ5UmVzdWx0PFQ+XG4gICk6IEFwb2xsb1F1ZXJ5UmVzdWx0PE1heWJlTWFza2VkPFQ+PiB7XG4gICAgcmV0dXJuIHJlc3VsdCAmJiBcImRhdGFcIiBpbiByZXN1bHQgP1xuICAgICAgICB7XG4gICAgICAgICAgLi4ucmVzdWx0LFxuICAgICAgICAgIGRhdGE6IHRoaXMucXVlcnlNYW5hZ2VyLm1hc2tPcGVyYXRpb24oe1xuICAgICAgICAgICAgZG9jdW1lbnQ6IHRoaXMucXVlcnksXG4gICAgICAgICAgICBkYXRhOiByZXN1bHQuZGF0YSxcbiAgICAgICAgICAgIGZldGNoUG9saWN5OiB0aGlzLm9wdGlvbnMuZmV0Y2hQb2xpY3ksXG4gICAgICAgICAgICBpZDogdGhpcy5xdWVyeUlkLFxuICAgICAgICAgIH0pLFxuICAgICAgICB9XG4gICAgICA6IHJlc3VsdDtcbiAgfVxuXG4gIHByaXZhdGUgZGlydHk6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwcml2YXRlIG5vdGlmeVRpbWVvdXQ/OiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PjtcblxuICAvKiogQGludGVybmFsICovXG4gIHByb3RlY3RlZCByZXNldE5vdGlmaWNhdGlvbnMoKSB7XG4gICAgdGhpcy5jYW5jZWxOb3RpZnlUaW1lb3V0KCk7XG4gICAgdGhpcy5kaXJ0eSA9IGZhbHNlO1xuICB9XG5cbiAgcHJpdmF0ZSBjYW5jZWxOb3RpZnlUaW1lb3V0KCkge1xuICAgIGlmICh0aGlzLm5vdGlmeVRpbWVvdXQpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLm5vdGlmeVRpbWVvdXQpO1xuICAgICAgdGhpcy5ub3RpZnlUaW1lb3V0ID0gdm9pZCAwO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJvdGVjdGVkIHNjaGVkdWxlTm90aWZ5KCkge1xuICAgIGlmICh0aGlzLmRpcnR5KSByZXR1cm47XG4gICAgdGhpcy5kaXJ0eSA9IHRydWU7XG4gICAgaWYgKCF0aGlzLm5vdGlmeVRpbWVvdXQpIHtcbiAgICAgIHRoaXMubm90aWZ5VGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4gdGhpcy5ub3RpZnkoKSwgMCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBwcm90ZWN0ZWQgbm90aWZ5KCkge1xuICAgIHRoaXMuY2FuY2VsTm90aWZ5VGltZW91dCgpO1xuXG4gICAgaWYgKHRoaXMuZGlydHkpIHtcbiAgICAgIGlmIChcbiAgICAgICAgdGhpcy5vcHRpb25zLmZldGNoUG9saWN5ID09IFwiY2FjaGUtb25seVwiIHx8XG4gICAgICAgIHRoaXMub3B0aW9ucy5mZXRjaFBvbGljeSA9PSBcImNhY2hlLWFuZC1uZXR3b3JrXCIgfHxcbiAgICAgICAgIWlzTmV0d29ya1JlcXVlc3RJbkZsaWdodCh0aGlzLnF1ZXJ5SW5mby5uZXR3b3JrU3RhdHVzKVxuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IGRpZmYgPSB0aGlzLnF1ZXJ5SW5mby5nZXREaWZmKCk7XG4gICAgICAgIGlmIChkaWZmLmZyb21PcHRpbWlzdGljVHJhbnNhY3Rpb24pIHtcbiAgICAgICAgICAvLyBJZiB0aGlzIGRpZmYgY2FtZSBmcm9tIGFuIG9wdGltaXN0aWMgdHJhbnNhY3Rpb24sIGRlbGl2ZXIgdGhlXG4gICAgICAgICAgLy8gY3VycmVudCBjYWNoZSBkYXRhIHRvIHRoZSBPYnNlcnZhYmxlUXVlcnksIGJ1dCBkb24ndCBwZXJmb3JtIGFcbiAgICAgICAgICAvLyByZW9ic2VydmF0aW9uLCBzaW5jZSBvcS5yZW9ic2VydmVDYWNoZUZpcnN0IG1pZ2h0IG1ha2UgYSBuZXR3b3JrXG4gICAgICAgICAgLy8gcmVxdWVzdCwgYW5kIHdlIG5ldmVyIHdhbnQgdG8gdHJpZ2dlciBuZXR3b3JrIHJlcXVlc3RzIGluIHRoZVxuICAgICAgICAgIC8vIG1pZGRsZSBvZiBvcHRpbWlzdGljIHVwZGF0ZXMuXG4gICAgICAgICAgdGhpcy5vYnNlcnZlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gT3RoZXJ3aXNlLCBtYWtlIHRoZSBPYnNlcnZhYmxlUXVlcnkgXCJyZW9ic2VydmVcIiB0aGUgbGF0ZXN0IGRhdGFcbiAgICAgICAgICAvLyB1c2luZyBhIHRlbXBvcmFyeSBmZXRjaCBwb2xpY3kgb2YgXCJjYWNoZS1maXJzdFwiLCBzbyBjb21wbGV0ZSBjYWNoZVxuICAgICAgICAgIC8vIHJlc3VsdHMgaGF2ZSBhIGNoYW5jZSB0byBiZSBkZWxpdmVyZWQgd2l0aG91dCB0cmlnZ2VyaW5nIGFkZGl0aW9uYWxcbiAgICAgICAgICAvLyBuZXR3b3JrIHJlcXVlc3RzLCBldmVuIHdoZW4gb3B0aW9ucy5mZXRjaFBvbGljeSBpcyBcIm5ldHdvcmstb25seVwiXG4gICAgICAgICAgLy8gb3IgXCJjYWNoZS1hbmQtbmV0d29ya1wiLiBBbGwgb3RoZXIgZmV0Y2ggcG9saWNpZXMgYXJlIHByZXNlcnZlZCBieVxuICAgICAgICAgIC8vIHRoaXMgbWV0aG9kLCBhbmQgYXJlIGhhbmRsZWQgYnkgY2FsbGluZyBvcS5yZW9ic2VydmUoKS4gSWYgdGhpc1xuICAgICAgICAgIC8vIHJlb2JzZXJ2YXRpb24gaXMgc3B1cmlvdXMsIGlzRGlmZmVyZW50RnJvbUxhc3RSZXN1bHQgc3RpbGwgaGFzIGFcbiAgICAgICAgICAvLyBjaGFuY2UgdG8gY2F0Y2ggaXQgYmVmb3JlIGRlbGl2ZXJ5IHRvIE9ic2VydmFibGVRdWVyeSBzdWJzY3JpYmVycy5cbiAgICAgICAgICB0aGlzLnJlb2JzZXJ2ZUNhY2hlRmlyc3QoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuZGlydHkgPSBmYWxzZTtcbiAgfVxuXG4gIC8vIFJlb2JzZXJ2ZSB3aXRoIGZldGNoUG9saWN5IGVmZmVjdGl2ZWx5IHNldCB0byBcImNhY2hlLWZpcnN0XCIsIHRyaWdnZXJpbmdcbiAgLy8gZGVsaXZlcnkgb2YgYW55IG5ldyBkYXRhIGZyb20gdGhlIGNhY2hlLCBwb3NzaWJseSBmYWxsaW5nIGJhY2sgdG8gdGhlIG5ldHdvcmtcbiAgLy8gaWYgYW55IGNhY2hlIGRhdGEgYXJlIG1pc3NpbmcuIFRoaXMgYWxsb3dzIF9jb21wbGV0ZV8gY2FjaGUgcmVzdWx0cyB0byBiZVxuICAvLyBkZWxpdmVyZWQgd2l0aG91dCBhbHNvIGtpY2tpbmcgb2ZmIHVubmVjZXNzYXJ5IG5ldHdvcmsgcmVxdWVzdHMgd2hlblxuICAvLyB0aGlzLm9wdGlvbnMuZmV0Y2hQb2xpY3kgaXMgXCJjYWNoZS1hbmQtbmV0d29ya1wiIG9yIFwibmV0d29yay1vbmx5XCIuIFdoZW5cbiAgLy8gdGhpcy5vcHRpb25zLmZldGNoUG9saWN5IGlzIGFueSBvdGhlciBwb2xpY3kgKFwiY2FjaGUtZmlyc3RcIiwgXCJjYWNoZS1vbmx5XCIsXG4gIC8vIFwic3RhbmRieVwiLCBvciBcIm5vLWNhY2hlXCIpLCB3ZSBjYWxsIHRoaXMucmVvYnNlcnZlKCkgYXMgdXN1YWwuXG4gIHByaXZhdGUgcmVvYnNlcnZlQ2FjaGVGaXJzdCgpIHtcbiAgICBjb25zdCB7IGZldGNoUG9saWN5LCBuZXh0RmV0Y2hQb2xpY3kgfSA9IHRoaXMub3B0aW9ucztcblxuICAgIGlmIChmZXRjaFBvbGljeSA9PT0gXCJjYWNoZS1hbmQtbmV0d29ya1wiIHx8IGZldGNoUG9saWN5ID09PSBcIm5ldHdvcmstb25seVwiKSB7XG4gICAgICByZXR1cm4gdGhpcy5yZW9ic2VydmUoe1xuICAgICAgICBmZXRjaFBvbGljeTogXCJjYWNoZS1maXJzdFwiLFxuICAgICAgICAvLyBVc2UgYSB0ZW1wb3JhcnkgbmV4dEZldGNoUG9saWN5IGZ1bmN0aW9uIHRoYXQgcmVwbGFjZXMgaXRzZWxmIHdpdGggdGhlXG4gICAgICAgIC8vIHByZXZpb3VzIG5leHRGZXRjaFBvbGljeSB2YWx1ZSBhbmQgcmV0dXJucyB0aGUgb3JpZ2luYWwgZmV0Y2hQb2xpY3kuXG4gICAgICAgIG5leHRGZXRjaFBvbGljeShcbiAgICAgICAgICB0aGlzOiBXYXRjaFF1ZXJ5T3B0aW9uczxUVmFyaWFibGVzLCBURGF0YT4sXG4gICAgICAgICAgY3VycmVudEZldGNoUG9saWN5OiBXYXRjaFF1ZXJ5RmV0Y2hQb2xpY3ksXG4gICAgICAgICAgY29udGV4dDogTmV4dEZldGNoUG9saWN5Q29udGV4dDxURGF0YSwgVFZhcmlhYmxlcz5cbiAgICAgICAgKSB7XG4gICAgICAgICAgLy8gUmVwbGFjZSB0aGlzIG5leHRGZXRjaFBvbGljeSBmdW5jdGlvbiBpbiB0aGUgb3B0aW9ucyBvYmplY3Qgd2l0aCB0aGVcbiAgICAgICAgICAvLyBvcmlnaW5hbCB0aGlzLm9wdGlvbnMubmV4dEZldGNoUG9saWN5IHZhbHVlLlxuICAgICAgICAgIHRoaXMubmV4dEZldGNoUG9saWN5ID0gbmV4dEZldGNoUG9saWN5O1xuICAgICAgICAgIC8vIElmIHRoZSBvcmlnaW5hbCBuZXh0RmV0Y2hQb2xpY3kgdmFsdWUgd2FzIGEgZnVuY3Rpb24sIGdpdmUgaXQgYVxuICAgICAgICAgIC8vIGNoYW5jZSB0byBkZWNpZGUgd2hhdCBoYXBwZW5zIGhlcmUuXG4gICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLm5leHRGZXRjaFBvbGljeSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5uZXh0RmV0Y2hQb2xpY3koY3VycmVudEZldGNoUG9saWN5LCBjb250ZXh0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gT3RoZXJ3aXNlIGdvIGJhY2sgdG8gdGhlIG9yaWdpbmFsIHRoaXMub3B0aW9ucy5mZXRjaFBvbGljeS5cbiAgICAgICAgICByZXR1cm4gZmV0Y2hQb2xpY3khO1xuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucmVvYnNlcnZlKCk7XG4gIH1cbn1cblxuLy8gTmVjZXNzYXJ5IGJlY2F1c2UgdGhlIE9ic2VydmFibGVRdWVyeSBjb25zdHJ1Y3RvciBoYXMgYSBkaWZmZXJlbnRcbi8vIHNpZ25hdHVyZSB0aGFuIHRoZSBPYnNlcnZhYmxlIGNvbnN0cnVjdG9yLlxuZml4T2JzZXJ2YWJsZVN1YmNsYXNzKE9ic2VydmFibGVRdWVyeSk7XG5cbmZ1bmN0aW9uIGRlZmF1bHRTdWJzY3JpcHRpb25PYnNlcnZlckVycm9yQ2FsbGJhY2soZXJyb3I6IEFwb2xsb0Vycm9yKSB7XG4gIGludmFyaWFudC5lcnJvcihcIlVuaGFuZGxlZCBlcnJvclwiLCBlcnJvci5tZXNzYWdlLCBlcnJvci5zdGFjayk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBsb2dNaXNzaW5nRmllbGRFcnJvcnMoXG4gIG1pc3Npbmc6IE1pc3NpbmdGaWVsZEVycm9yW10gfCBNaXNzaW5nVHJlZSB8IHVuZGVmaW5lZFxuKSB7XG4gIGlmIChfX0RFVl9fICYmIG1pc3NpbmcpIHtcbiAgICBpbnZhcmlhbnQuZGVidWcoYE1pc3NpbmcgY2FjaGUgcmVzdWx0IGZpZWxkczogJW9gLCBtaXNzaW5nKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBza2lwQ2FjaGVEYXRhRm9yKFxuICBmZXRjaFBvbGljeT86IFdhdGNoUXVlcnlGZXRjaFBvbGljeSAvKiBgdW5kZWZpbmVkYCB3b3VsZCBtZWFuIGBcImNhY2hlLWZpcnN0XCJgICovXG4pIHtcbiAgcmV0dXJuIChcbiAgICBmZXRjaFBvbGljeSA9PT0gXCJuZXR3b3JrLW9ubHlcIiB8fFxuICAgIGZldGNoUG9saWN5ID09PSBcIm5vLWNhY2hlXCIgfHxcbiAgICBmZXRjaFBvbGljeSA9PT0gXCJzdGFuZGJ5XCJcbiAgKTtcbn1cbiJdLCJ4X2dvb2dsZV9pZ25vcmVMaXN0IjpbMF19 |